Duplicate r7795 in uxnet.c.
[u/mdw/putty] / unix / uxnet.c
index 5d4ace4..bfc4a8e 100644 (file)
@@ -23,7 +23,7 @@
 #include "tree234.h"
 
 /* Solaris needs <sys/sockio.h> for SIOCATMARK. */
-#ifdef HAVE_SYS_SOCKIO_H
+#ifndef SIOCATMARK
 #include <sys/sockio.h>
 #endif
 
@@ -97,6 +97,10 @@ static int cmpfortree(void *av, void *bv)
        return -1;
     if (as > bs)
        return +1;
+    if (a < b)
+       return -1;
+    if (a > b)
+       return +1;
     return 0;
 }
 
@@ -236,7 +240,7 @@ SockAddr sk_nonamelookup(const char *host)
 static int sk_nextaddr(SockAddr addr)
 {
 #ifndef NO_IPV6
-    if (addr->ai->ai_next) {
+    if (addr->ai && addr->ai->ai_next) {
        addr->ai = addr->ai->ai_next;
        addr->family = addr->ai->ai_family;
        return TRUE;
@@ -453,6 +457,14 @@ static int try_connect(Actual_Socket sock)
     short localport;
     int fl, salen;
 
+    /*
+     * Remove the socket from the tree before we overwrite its
+     * internal socket id, because that forms part of the tree's
+     * sorting criterion. We'll add it back before exiting this
+     * function, whether we changed anything or not.
+     */
+    del234(sktree, sock);
+
     if (sock->s >= 0)
         close(sock->s);
 
@@ -470,6 +482,8 @@ static int try_connect(Actual_Socket sock)
        goto ret;
     }
 
+    cloexec(s);
+
     if (sock->oobinline) {
        int b = TRUE;
        setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b));
@@ -603,9 +617,14 @@ static int try_connect(Actual_Socket sock)
     }
 
     uxsel_tell(sock);
-    add234(sktree, sock);
 
     ret:
+
+    /*
+     * No matter what happened, put the socket back in the tree.
+     */
+    add234(sktree, sock);
+
     if (err)
        plug_log(sock->plug, 1, sock->addr, sock->port, strerror(err), err);
     return err;
@@ -691,7 +710,10 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, i
      * into local reality.
      */
     address_family = (address_family == ADDRTYPE_IPV4 ? AF_INET :
-                     address_family == ADDRTYPE_IPV6 ? AF_INET6 : AF_UNSPEC);
+#ifndef NO_IPV6
+                     address_family == ADDRTYPE_IPV6 ? AF_INET6 :
+#endif
+                     AF_UNSPEC);
 
 #ifndef NO_IPV6
     /* Let's default to IPv6.
@@ -707,17 +729,21 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, i
      */
     s = socket(address_family, SOCK_STREAM, 0);
 
+#ifndef NO_IPV6
     /* If the host doesn't support IPv6 try fallback to IPv4. */
     if (s < 0 && address_family == AF_INET6) {
        address_family = AF_INET;
        s = socket(address_family, SOCK_STREAM, 0);
     }
+#endif
 
     if (s < 0) {
        ret->error = strerror(errno);
        return (Socket) ret;
     }
 
+    cloexec(s);
+
     ret->oobinline = 0;
 
     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
@@ -1277,9 +1303,10 @@ SockAddr platform_get_x11_unix_address(int displaynum, char **canonicalname)
     else
        *canonicalname = dupstr(ret->hostname);
 #ifndef NO_IPV6
-    ret->ais = NULL;
+    ret->ai = ret->ais = NULL;
 #else
     ret->addresses = NULL;
+    ret->curraddr = ret->naddresses = 0;
 #endif
     return ret;
 }