stty: fix bug reported by Paul Albrecht <albrecht@rdi1.com> -
[oweals/busybox.git] / libbb / xconnect.c
index a5b16d982ae4a27b6c5ba733e20a3f34f95d000a..65554b24e177140e085f852c50d80123fb29229f 100644 (file)
@@ -32,13 +32,13 @@ void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen)
        }
 }
 
-/* Return network byte ordered port number for a service.
+/* Return port number for a service.
  * If "port" is a number use it as the port.
  * If "port" is a name it is looked up in /etc/services, if it isnt found return
  * default_port */
 unsigned bb_lookup_port(const char *port, const char *protocol, unsigned default_port)
 {
-       unsigned port_nr = htons(default_port);
+       unsigned port_nr = default_port;
        if (port) {
                int old_errno;
 
@@ -49,13 +49,11 @@ unsigned bb_lookup_port(const char *port, const char *protocol, unsigned default
                if (errno || port_nr > 65535) {
                        struct servent *tserv = getservbyname(port, protocol);
                        if (tserv)
-                               port_nr = tserv->s_port;
-               } else {
-                       port_nr = htons(port_nr);
+                               port_nr = ntohs(tserv->s_port);
                }
                errno = old_errno;
        }
-       return port_nr;
+       return (uint16_t)port_nr;
 }
 
 
@@ -83,7 +81,21 @@ int xconnect_tcp_v4(struct sockaddr_in *s_addr)
 /* "New" networking API */
 
 
-void set_port(len_and_sockaddr *lsa, unsigned port)
+int get_nport(len_and_sockaddr *lsa)
+{
+#if ENABLE_FEATURE_IPV6
+       if (lsa->sa.sa_family == AF_INET6) {
+               return lsa->sin6.sin6_port;
+       }
+#endif
+       if (lsa->sa.sa_family == AF_INET) {
+               return lsa->sin.sin_port;
+       }
+       return -1;
+       /* What? UNIX socket? IPX?? :) */
+}
+
+void set_nport(len_and_sockaddr *lsa, unsigned port)
 {
 #if ENABLE_FEATURE_IPV6
        if (lsa->sa.sa_family == AF_INET6) {
@@ -148,7 +160,7 @@ static len_and_sockaddr* str2sockaddr(const char *host, int port, int ai_flags)
        r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen);
        r->len = result->ai_addrlen;
        memcpy(&r->sa, result->ai_addr, result->ai_addrlen);
-       set_port(r, port);
+       set_nport(r, htons(port));
        freeaddrinfo(result);
        return r;
 }
@@ -163,19 +175,27 @@ static len_and_sockaddr* dotted2sockaddr(const char *host, int port)
        return str2sockaddr(host, port, NI_NUMERICHOST);
 }
 
-static int xsocket_stream(len_and_sockaddr *lsa)
+int xsocket_stream(len_and_sockaddr **lsap)
 {
+       len_and_sockaddr *lsa;
        int fd;
+       int len = sizeof(struct sockaddr_in);
+       int family = AF_INET;
+
 #if ENABLE_FEATURE_IPV6
        fd = socket(AF_INET6, SOCK_STREAM, 0);
-       lsa->sa.sa_family = AF_INET6;
-       lsa->len = sizeof(struct sockaddr_in6);
-       if (fd >= 0)
-               return fd;
+       if (fd >= 0) {
+               len = sizeof(struct sockaddr_in6);
+               family = AF_INET6;
+       } else
 #endif
-       fd = xsocket(AF_INET, SOCK_STREAM, 0);
-       lsa->sa.sa_family = AF_INET;
-       lsa->len = sizeof(struct sockaddr_in);
+       {
+               fd = xsocket(AF_INET, SOCK_STREAM, 0);
+       }
+       lsa = xzalloc(offsetof(len_and_sockaddr, sa) + len);
+       lsa->len = len;
+       lsa->sa.sa_family = family;
+       *lsap = lsa;
        return fd;
 }
 
@@ -192,11 +212,7 @@ int create_and_bind_stream_or_die(const char *bindaddr, int port)
                /* user specified bind addr dictates family */
                fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0);
        } else {
-               lsa = xzalloc(offsetof(len_and_sockaddr, sa) +
-                       USE_FEATURE_IPV6(sizeof(struct sockaddr_in6))
-                       SKIP_FEATURE_IPV6(sizeof(struct sockaddr_in))
-               );
-               fd = xsocket_stream(lsa);
+               fd = xsocket_stream(&lsa);
        }
        setsockopt_reuseaddr(fd);
        xbind(fd, &lsa->sa, lsa->len);
@@ -237,6 +253,7 @@ static char* sockaddr2str(const struct sockaddr *sa, socklen_t salen, int flags)
                        flags | NI_NUMERICSERV /* do not resolve port# */
        );
        if (rc) return NULL;
+// We probably need to use [%s]:%s for IPv6...
        return xasprintf("%s:%s", host, serv);
 }