noip.c (encode_inet_addr): Avoid collisions with wildcard addresses.
[preload-hacks] / noip.c
diff --git a/noip.c b/noip.c
index ee86680..de7cf89 100644 (file)
--- a/noip.c
+++ b/noip.c
@@ -624,6 +624,34 @@ done:
   return (rc);
 }
 
+/* Convert the IP address SA to a Unix-domain address SUN.  Fail if the
+ * address seems already taken.  If DESPARATEP then try cleaning up stale old
+ * sockets.
+ */
+static int encode_unused_inet_addr(struct sockaddr *sa,
+                                  struct sockaddr_un *sun,
+                                  int desperatep)
+{
+  address waddr;
+  struct sockaddr_un wsun;
+  int rc;
+  char buf[ADDRBUFSZ];
+
+  snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
+          present_sockaddr(sa, 0, buf, sizeof(buf)));
+  if ((rc = unix_socket_status(sun, !desperatep)) == USED) return (-1);
+  else if (rc == STALE) unlink(sun->sun_path);
+
+  wildcard_address(sa->sa_family, &waddr.sa);
+  port_to_sockaddr(&waddr.sa, port_from_sockaddr(sa));
+  snprintf(wsun.sun_path, sizeof(wsun.sun_path), "%s/%s", sockdir,
+          present_sockaddr(&waddr.sa, 0, buf, sizeof(buf)));
+  if ((rc = unix_socket_status(&wsun, !desperatep)) == USED) return (-1);
+  else if (rc == STALE) unlink(wsun.sun_path);
+
+  return (0);
+}
+
 /* Encode the Internet address SA as a Unix-domain address SUN.  If WANT is
  * WANT_FRESH, and SA's port number is zero, then we pick an arbitrary local
  * port.  Otherwise we pick the port given.  There's an unpleasant hack to
@@ -660,20 +688,12 @@ static int encode_inet_addr(struct sockaddr_un *sun,
     copy_sockaddr(&addr.sa, sa);
     for (i = 0; i < 10; i++) {
       port_to_sockaddr(&addr.sa, randrange(minautoport, maxautoport));
-      snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
-              present_sockaddr(&addr.sa, 0, buf, sizeof(buf)));
-      if (unix_socket_status(sun, 1) == UNUSED) goto found;
+      if (!encode_unused_inet_addr(&addr.sa, sun, 0)) goto found;
     }
     for (desperatep = 0; desperatep < 2; desperatep++) {
       for (i = minautoport; i <= maxautoport; i++) {
        port_to_sockaddr(&addr.sa, i);
-       snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
-                present_sockaddr(&addr.sa, 0, buf, sizeof(buf)));
-       rc = unix_socket_status(sun, !desperatep);
-       switch (rc) {
-         case STALE: unlink(sun->sun_path);
-         case UNUSED: goto found;
-       }
+       if (!encode_unused_inet_addr(&addr.sa, sun, 0)) goto found;
       }
     }
     errno = EADDRINUSE;