* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
- * Preload-hacks distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * Preload-hacks are distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
* You should have received a copy of the GNU General Public License along
- * with mLib; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
+ * with preload-hacks; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define _GNU_SOURCE
_(sendto, ssize_t, (int, const void *buf, size_t, int, \
const struct sockaddr *to, socklen_t tolen)) \
_(recvfrom, ssize_t, (int, void *buf, size_t, int, \
- struct sockaddr *from, socklen_t *fromlen)) \
+ struct sockaddr *from, socklen_t *fromlen)) \
_(sendmsg, ssize_t, (int, const struct msghdr *, int)) \
- _(recvmsg, ssize_t, (int, struct msghdr *, int)) \
- _(close, int, (int))
+ _(recvmsg, ssize_t, (int, struct msghdr *, int))
/* Function pointers to set up. */
#define DECL(imp, ret, args) static ret (*real_##imp) args;
rc = USED;
if ((fp = fopen("/proc/net/unix", "r")) == 0)
goto done;
- fgets(buf, sizeof(buf), fp); /* skip header */
+ if (!fgets(buf, sizeof(buf), fp)) goto done; /* skip header */
len = strlen(sun->sun_path);
while (fgets(buf, sizeof(buf), fp)) {
n = strlen(buf);
return (0);
}
-/* Decode the Unix address SUN to an Internet address SIN. Returns zero on
- * success; -1 on failure (e.g., it wasn't one of our addresses). */
+/* Decode the Unix address SUN to an Internet address SIN. If
+ * DECODE_UNBOUND_P is nonzero, an empty address (indicative of an unbound
+ * Unix-domain socket) is translated to a wildcard Internet address. Returns
+ * zero on success; -1 on failure (e.g., it wasn't one of our addresses).
+ */
static int decode_inet_addr(struct sockaddr_in *sin,
const struct sockaddr_un *sun,
- socklen_t len)
+ socklen_t len,
+ int decode_unbound_p)
{
char buf[INET_ADDRSTRLEN + 16];
char *p;
- size_t n = strlen(sockdir), nn = strlen(sun->sun_path);
+ size_t n = strlen(sockdir), nn;
struct sockaddr_in sin_mine;
unsigned long port;
sin = &sin_mine;
if (sun->sun_family != AF_UNIX)
return (-1);
+ nn = strlen(sun->sun_path);
if (len < sizeof(sun)) ((char *)sun)[len] = 0;
D( fprintf(stderr, "noip: decode (%d) `%s'",
*sun->sun_path, sun->sun_path); )
- if (!sun->sun_path[0]) {
+ if (decode_unbound_p && !sun->sun_path[0]) {
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = INADDR_ANY;
sin->sin_port = 0;
len = sizeof(sun);
if (real_getsockname(sk, SA(&sun), &len))
return (-1);
- if (decode_inet_addr(&sin, &sun, len))
+ if (decode_inet_addr(&sin, &sun, len, 1))
return (0); /* Not one of ours */
len = sizeof(type);
if (real_getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0 ||
len = sizeof(ov_); \
if (real_getsockopt(sk, SOL_SOCKET, SO_##opt, &ov_, &len) < 0 || \
real_setsockopt(nsk, SOL_SOCKET, SO_##opt, &ov_, len)) { \
- real_close(nsk); \
+ close(nsk); \
return (-1); \
} \
} while (0);
(fd = fcntl(sk, F_GETFD)) < 0 ||
fcntl(nsk, F_SETFL, f) < 0 ||
dup2(nsk, sk) < 0) {
- real_close(nsk);
+ close(nsk);
return (-1);
}
unlink(sun.sun_path);
- real_close(nsk);
+ close(nsk);
if (fcntl(sk, F_SETFD, fd) < 0) {
perror("noip: fixup_real_ip_socket F_SETFD");
abort();
struct sockaddr_in sin;
socklen_t alen;
- if (sa->sa_family == AF_UNIX && !decode_inet_addr(&sin, SUN(sa), len)) {
+ if (sa->sa_family == AF_UNIX &&
+ !decode_inet_addr(&sin, SUN(sa), len, 0)) {
sa = SA(&sin);
len = sizeof(sin);
}
int socket(int pf, int ty, int proto)
{
- if (pf == PF_INET) {
- pf = PF_UNIX;
- proto = 0;
+ switch (pf) {
+ case PF_INET:
+ pf = PF_UNIX;
+ proto = 0;
+ case PF_UNIX:
+#ifdef PF_NETLINK
+ case PF_NETLINK:
+#endif
+ return real_socket(pf, ty, proto);
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
}
- return real_socket(pf, ty, proto);
}
int socketpair(int pf, int ty, int proto, int *sk)
int connect(int sk, const struct sockaddr *sa, socklen_t len)
{
struct sockaddr_un sun;
- int fixup_p = 0;
int rc;
switch (sa->sa_family) {
case AF_INET:
PRESERVING_ERRNO({
do_implicit_bind(sk, &sa, &len, &sun);
- fixup_p = 1;
});
rc = real_connect(sk, sa, len);
if (rc < 0) {
if (d->d_name[0] == '.') continue;
snprintf(sun.sun_path, sizeof(sun.sun_path),
"%s/%s", sockdir, d->d_name);
- if (decode_inet_addr(&sin, &sun, SUN_LEN(&sun)) ||
+ if (decode_inet_addr(&sin, &sun, SUN_LEN(&sun), 0) ||
stat(sun.sun_path, &st) ||
!S_ISSOCK(st.st_mode)) {
D( fprintf(stderr, "noip: ignoring unknown socketdir entry `%s'\n",
return;
for (i = n_local_ipaddrs = 0;
n_local_ipaddrs < MAX_LOCAL_IPADDRS &&
- ifn[i].if_name && *ifn[i].if_name;
+ ifn[i].if_name && *ifn[i].if_name;
i++) {
strcpy(ifr.ifr_name, ifn[i].if_name);
if (ioctl(sk, SIOCGIFADDR, &ifr) || ifr.ifr_addr.sa_family != AF_INET)
}
/* Print the given message to standard error. Avoids stdio. */
-static void printerr(const char *p) { write(STDERR_FILENO, p, strlen(p)); }
+static void printerr(const char *p)
+ { if (write(STDERR_FILENO, p, strlen(p))) ; }
/* Create the socket directory, being careful about permissions. */
static void create_sockdir(void)