noip.c: Add commentary to some hairier functions.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 6 Jun 2018 19:04:16 +0000 (20:04 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 6 Jun 2018 19:13:05 +0000 (20:13 +0100)
No code change.

noip.c

diff --git a/noip.c b/noip.c
index e3da246..8806d02 100644 (file)
--- a/noip.c
+++ b/noip.c
@@ -641,10 +641,23 @@ static int unix_socket_status(struct sockaddr_un *sun, int quickp)
   int rc;
   char buf[256];
 
+  /* If we can't find the socket node, then it's definitely not in use.  If
+   * we get some other error, then this socket is weird.
+   */
   if (stat(sun->sun_path, &st))
     return (errno == ENOENT ? UNUSED : USED);
+
+  /* If it's not a socket, then something weird is going on.  If we're just
+   * probing quickly to find a spare port, then existence is sufficient to
+   * discourage us now.
+   */
   if (!S_ISSOCK(st.st_mode) || quickp)
     return (USED);
+
+  /* The socket's definitely there, but is anyone actually still holding it
+   * open?  The only way I know to discover this is to trundle through
+   * `/proc/net/unix'.  If there's no entry, then the socket must be stale.
+   */
   rc = USED;
   if ((fp = fopen("/proc/net/unix", "r")) == 0)
     goto done;
@@ -661,6 +674,8 @@ static int unix_socket_status(struct sockaddr_un *sun, int quickp)
   rc = STALE;
 done:
   if (fp) fclose(fp);
+
+  /* All done. */
   return (rc);
 }
 
@@ -678,11 +693,18 @@ static int encode_unused_inet_addr(struct sockaddr *sa,
   char buf[ADDRBUFSZ];
   int port = port_from_sockaddr(sa);
 
+  /* First, look for an exact match.  Only look quickly unless we're
+   * desperate.  If the socket is in use, we fail here.  (This could get
+   * racy.  Let's not worry about that for now.)
+   */
   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);
 
+  /* Next, check the corresponding wildcard address, so as to avoid
+   * inadvertant collisions with listeners.  Do this in the same way.
+   */
   wildcard_address(sa->sa_family, &waddr.sa);
   port_to_sockaddr(&waddr.sa, port);
   snprintf(wsun.sun_path, sizeof(wsun.sun_path), "%s/%s", sockdir,
@@ -690,6 +712,7 @@ static int encode_unused_inet_addr(struct sockaddr *sa,
   if ((rc = unix_socket_status(&wsun, !desperatep)) == USED) return (-1);
   else if (rc == STALE) unlink(wsun.sun_path);
 
+  /* All is well. */
   return (0);
 }
 
@@ -714,34 +737,60 @@ static int encode_inet_addr(struct sockaddr_un *sun,
   D( fprintf(stderr, "noip(%d): encode %s (%s)", getpid(),
             present_sockaddr(sa, 0, buf, sizeof(buf)),
             (f&ENCF_FRESH) ? "FRESH" : "EXISTING"); )
+
+  /* Start making the Unix-domain address. */
   sun->sun_family = AF_UNIX;
+
   if (port || !(f&ENCF_FRESH)) {
+
+    /* Try the address as given.  If it's in use, or we don't necessarily
+     * want an existing socket, then we're done.
+     */
     snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
             present_sockaddr(sa, 0, buf, sizeof(buf)));
     rc = unix_socket_status(sun, 0);
     if (rc == STALE) unlink(sun->sun_path);
     if (rc == USED || (f&ENCF_FRESH)) goto found;
+
+    /* We're looking for a socket which already exists.  Try the
+     * corresponding wildcard address.
+     */
     wildcard_address(sa->sa_family, &addr.sa);
     port_to_sockaddr(&addr.sa, port);
     snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s", sockdir,
             present_sockaddr(&addr.sa, 0, buf, sizeof(buf)));
     if (unix_socket_status(sun, 0) == STALE) unlink(sun->sun_path);
+
   } else {
+    /* We want a fresh new socket. */
+
+    /* Make a copy of the given address, because we're going to mangle it. */
     copy_sockaddr(&addr.sa, sa);
+
+    /* Try a few random-ish port numbers to see if any of them is spare. */
     for (i = 0; i < 10; i++) {
       port_to_sockaddr(&addr.sa, randrange(minautoport, maxautoport));
       if (!encode_unused_inet_addr(&addr.sa, sun, 0)) goto found;
     }
+
+    /* Things must be getting tight.  Work through all of the autoport range
+     * to see if we can find a spare one.  The first time, just do it the
+     * quick way; if that doesn't work, then check harder for stale sockets.
+     */
     for (desperatep = 0; desperatep < 2; desperatep++) {
       for (i = minautoport; i <= maxautoport; i++) {
        port_to_sockaddr(&addr.sa, i);
        if (!encode_unused_inet_addr(&addr.sa, sun, 0)) goto found;
       }
     }
+
+    /* We failed to find any free ports. */
     errno = EADDRINUSE;
     D( fprintf(stderr, " -- can't resolve\n"); )
     return (-1);
   }
+
+  /* Success. */
 found:
   D( fprintf(stderr, " -> `%s'\n", sun->sun_path); )
   return (0);