]> sjero.net Git - wget/commitdiff
[svn] Simplify the ip_address data union. Always use inet_ntop for printing
authorhniksic <devnull@localhost>
Wed, 10 Aug 2005 13:50:08 +0000 (06:50 -0700)
committerhniksic <devnull@localhost>
Wed, 10 Aug 2005 13:50:08 +0000 (06:50 -0700)
IP addresses when IPv6 is enabled.

src/ChangeLog
src/connect.c
src/ftp-basic.c
src/ftp.c
src/host.c
src/host.h

index 6b9f90ca5c7aceccb769e99a24fb4a0e4c3694be..6575c255562cfd92a0d21a4509d94fdcecc704f9 100644 (file)
@@ -1,3 +1,10 @@
+2005-08-10  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * host.c (print_address): Always use inet_ntop when IPv6 is
+       enabled.
+
+       * host.h (ip_address): Simplify the data union.
+
 2005-08-09  Hrvoje Niksic  <hniksic@xemacs.org>
 
        * mswindows.c (inet_ntop): Also handle IPv4 addresses for
index dc7145f20a94686d72b55c0fb228ce445dcf7b95..9cf84f22c6e41721c08222a646a305971f49aea2 100644 (file)
@@ -73,27 +73,27 @@ so, delete this exception statement from your version.  */
 static void
 sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port)
 {
-  switch (ip->type)
+  switch (ip->family)
     {
-    case IPV4_ADDRESS:
+    case AF_INET:
       {
        struct sockaddr_in *sin = (struct sockaddr_in *)sa;
        xzero (*sin);
        sin->sin_family = AF_INET;
        sin->sin_port = htons (port);
-       sin->sin_addr = ADDRESS_IPV4_IN_ADDR (ip);
+       sin->sin_addr = ip->data.d4;
        break;
       }
 #ifdef ENABLE_IPV6
-    case IPV6_ADDRESS:
+    case AF_INET6:
       {
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
        xzero (*sin6);
        sin6->sin6_family = AF_INET6;
        sin6->sin6_port = htons (port);
-       sin6->sin6_addr = ADDRESS_IPV6_IN6_ADDR (ip);
+       sin6->sin6_addr = ip->data.d6;
 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
-       sin6->sin6_scope_id = ADDRESS_IPV6_SCOPE (ip);
+       sin6->sin6_scope_id = ip->ipv6_scope;
 #endif
        break;
       }
@@ -117,8 +117,8 @@ sockaddr_get_data (const struct sockaddr *sa, ip_address *ip, int *port)
        struct sockaddr_in *sin = (struct sockaddr_in *)sa;
        if (ip)
          {
-           ip->type = IPV4_ADDRESS;
-           ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
+           ip->family = AF_INET;
+           ip->data.d4 = sin->sin_addr;
          }
        if (port)
          *port = ntohs (sin->sin_port);
@@ -130,10 +130,10 @@ sockaddr_get_data (const struct sockaddr *sa, ip_address *ip, int *port)
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
        if (ip)
          {
-           ip->type = IPV6_ADDRESS;
-           ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
+           ip->family = AF_INET6;
+           ip->data.d6 = sin6->sin6_addr;
 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
-           ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
+           ip->ipv6_scope = sin6->sin6_scope_id;
 #endif
          }
        if (port)
@@ -415,7 +415,6 @@ int
 bind_local (const ip_address *bind_address, int *port)
 {
   int sock;
-  int family = AF_INET;
   struct sockaddr_storage ss;
   struct sockaddr *sa = (struct sockaddr *)&ss;
 
@@ -424,12 +423,7 @@ bind_local (const ip_address *bind_address, int *port)
   void *setopt_ptr = (void *)&setopt_val;
   socklen_t setopt_size = sizeof (setopt_val);
 
-#ifdef ENABLE_IPV6
-  if (bind_address->type == IPV6_ADDRESS) 
-    family = AF_INET6;
-#endif
-
-  sock = socket (family, SOCK_STREAM, 0);
+  sock = socket (bind_address->family, SOCK_STREAM, 0);
   if (sock < 0)
     return -1;
 
@@ -529,16 +523,16 @@ socket_ip_address (int sock, ip_address *ip, int endpoint)
   if (ret < 0)
     return false;
 
+  ip->family = sockaddr->sa_family;
   switch (sockaddr->sa_family)
     {
 #ifdef ENABLE_IPV6
     case AF_INET6:
       {
        struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
-       ip->type = IPV6_ADDRESS;
-       ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
+       ip->data.d6 = sa6->sin6_addr;
 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
-       ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
+       ip->ipv6_scope = sa6->sin6_scope_id;
 #endif
        DEBUGP (("conaddr is: %s\n", print_address (ip)));
        return true;
@@ -547,8 +541,7 @@ socket_ip_address (int sock, ip_address *ip, int endpoint)
     case AF_INET:
       {
        struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
-       ip->type = IPV4_ADDRESS;
-       ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
+       ip->data.d4 = sa->sin_addr;
        DEBUGP (("conaddr is: %s\n", print_address (ip)));
        return true;
       }
index 753566aeb862d5c3b4d6ecb3d18ebbfdb8060746..dd7d7b7addec75f8fe2da76b9a5b2caa9a661ea9 100644 (file)
@@ -250,13 +250,11 @@ ip_address_to_port_repr (const ip_address *addr, int port, char *buf,
 {
   unsigned char *ptr;
 
-  assert (addr != NULL);
-  assert (addr->type == IPV4_ADDRESS);
-  assert (buf != NULL);
+  assert (addr->family == AF_INET);
   /* buf must contain the argument of PORT (of the form a,b,c,d,e,f). */
   assert (buflen >= 6 * 4);
 
-  ptr = ADDRESS_IPV4_DATA (addr);
+  ptr = IP_INADDR_DATA (addr);
   snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d", ptr[0], ptr[1],
             ptr[2], ptr[3], (port & 0xff00) >> 8, port & 0xff);
   buf[buflen - 1] = '\0';
@@ -280,7 +278,7 @@ ftp_port (int csock, int *local_sock)
   if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
     return FTPSYSERR;
 
-  assert (addr.type == IPV4_ADDRESS);
+  assert (addr.family == AF_INET);
 
   /* Setting port to 0 lets the system choose a free port.  */
   port = 0;
@@ -326,32 +324,29 @@ static void
 ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf, 
                          size_t buflen)
 {
-  unsigned char *ptr;
+  unsigned char *ptr = IP_INADDR_DATA (addr);
 
-  assert (addr != NULL);
-  assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS);
-  assert (buf != NULL);
   /* buf must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
   assert (buflen >= 21 * 4);
 
   /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
-  switch (addr->type
-    {
-      case IPV4_ADDRESS
-       ptr = ADDRESS_IPV4_DATA (addr);
-        snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4, 
-                  ptr[0], ptr[1], ptr[2], ptr[3], 2,
-                  (port & 0xff00) >> 8, port & 0xff);
-        buf[buflen - 1] = '\0';
-        break;
-      case IPV6_ADDRESS: 
-       ptr = ADDRESS_IPV6_DATA (addr);
-       snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
-                 6, 16, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], 
-                 ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], 2,
-                 (port & 0xff00) >> 8, port & 0xff);
-       buf[buflen - 1] = '\0';
-       break;
+  switch (addr->family
+    {
+    case AF_INET
+      snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4, 
+               ptr[0], ptr[1], ptr[2], ptr[3], 2,
+               (port & 0xff00) >> 8, port & 0xff);
+      break;
+    case AF_INET6: 
+      snprintf (buf, buflen,
+               "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
+               6, 16,
+               ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], 
+               ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15],
+               2, (port & 0xff00) >> 8, port & 0xff);
+      break;
+    default:
+      abort ();
     }
 }
 
@@ -373,7 +368,7 @@ ftp_lprt (int csock, int *local_sock)
   if (!socket_ip_address (csock, &addr, ENDPOINT_LOCAL))
     return FTPSYSERR;
 
-  assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
+  assert (addr.family == AF_INET || addr.family == AF_INET6);
 
   /* Setting port to 0 lets the system choose a free port.  */
   port = 0;
@@ -425,7 +420,7 @@ ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf,
   assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5); 
 
   /* Construct the argument of EPRT (of the form |af|addr|port|). */
-  afnum = (addr->type == IPV4_ADDRESS ? 1 : 2);
+  afnum = (addr->family == AF_INET ? 1 : 2);
   snprintf (buf, buflen, "|%d|%s|%d|", afnum, print_address (addr), port);
   buf[buflen - 1] = '\0';
 }
@@ -546,8 +541,8 @@ ftp_pasv (int csock, ip_address *addr, int *port)
     }
   xfree (respline);
 
-  addr->type = IPV4_ADDRESS;
-  memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
+  addr->family = AF_INET;
+  memcpy (IP_INADDR_DATA (addr), tmp, 4);
   *port = ((tmp[4] << 8) & 0xff00) + tmp[5];
 
   return FTPOK;
@@ -692,8 +687,8 @@ ftp_lpsv (int csock, ip_address *addr, int *port)
 
   if (af == 4)
     {
-      addr->type = IPV4_ADDRESS;
-      memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
+      addr->family = AF_INET;
+      memcpy (IP_INADDR_DATA (addr), tmp, 4);
       *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
       DEBUGP (("lpsv addr is: %s\n", print_address(addr)));
       DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
@@ -703,8 +698,8 @@ ftp_lpsv (int csock, ip_address *addr, int *port)
   else
     {
       assert (af == 6);
-      addr->type = IPV6_ADDRESS;
-      memcpy (ADDRESS_IPV6_DATA (addr), tmp, 16);
+      addr->family = AF_INET6;
+      memcpy (IP_INADDR_DATA (addr), tmp, 16);
       *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
       DEBUGP (("lpsv addr is: %s\n", print_address(addr)));
       DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
@@ -735,7 +730,7 @@ ftp_epsv (int csock, ip_address *ip, int *port)
 
   /* Form the request.  */
   /* EPSV 1 means that we ask for IPv4 and EPSV 2 means that we ask for IPv6. */
-  request = ftp_request ("EPSV", (ip->type == IPV4_ADDRESS ? "1" : "2"));
+  request = ftp_request ("EPSV", (ip->family == AF_INET ? "1" : "2"));
 
   /* And send it.  */
   nwritten = fd_write (csock, request, strlen (request), -1);
index 7b79b8e2100ff25a8c946f3172d25855a4282e61..9b6fc8710efc13face668fbbb64686c801ed0fee 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -116,14 +116,14 @@ ftp_do_pasv (int csock, ip_address *addr, int *port)
   /* If our control connection is over IPv6, then we first try EPSV and then 
    * LPSV if the former is not supported. If the control connection is over 
    * IPv4, we simply issue the good old PASV request. */
-  switch (addr->type)
+  switch (addr->family)
     {
-    case IPV4_ADDRESS:
+    case AF_INET:
       if (!opt.server_response)
         logputs (LOG_VERBOSE, "==> PASV ... ");
       err = ftp_pasv (csock, addr, port);
       break;
-    case IPV6_ADDRESS:
+    case AF_INET6:
       if (!opt.server_response)
         logputs (LOG_VERBOSE, "==> EPSV ... ");
       err = ftp_epsv (csock, addr, port);
@@ -159,14 +159,14 @@ ftp_do_port (int csock, int *local_sock)
   /* If our control connection is over IPv6, then we first try EPRT and then 
    * LPRT if the former is not supported. If the control connection is over 
    * IPv4, we simply issue the good old PORT request. */
-  switch (cip.type)
+  switch (cip.family)
     {
-    case IPV4_ADDRESS:
+    case AF_INET:
       if (!opt.server_response)
         logputs (LOG_VERBOSE, "==> PORT ... ");
       err = ftp_port (csock, local_sock);
       break;
-    case IPV6_ADDRESS:
+    case AF_INET6:
       if (!opt.server_response)
         logputs (LOG_VERBOSE, "==> EPRT ... ");
       err = ftp_eprt (csock, local_sock);
index 745868c8842054b0d1ff091880c8e810ab6b8490..a13953b0ca30702f0f20d54777c4a36fadc61af5 100644 (file)
@@ -98,30 +98,27 @@ bool
 address_list_contains (const struct address_list *al, const ip_address *ip)
 {
   int i;
-  switch (ip->type)
+  switch (ip->family)
     {
-    case IPV4_ADDRESS:
+    case AF_INET:
       for (i = 0; i < al->count; i++)
        {
          ip_address *cur = al->addresses + i;
-         if (cur->type == IPV4_ADDRESS
-             && (ADDRESS_IPV4_IN_ADDR (cur).s_addr
-                 ==
-                 ADDRESS_IPV4_IN_ADDR (ip).s_addr))
+         if (cur->family == AF_INET
+             && (cur->data.d4.s_addr == ip->data.d4.s_addr))
            return true;
        }
       return false;
 #ifdef ENABLE_IPV6
-    case IPV6_ADDRESS:
+    case AF_INET6:
       for (i = 0; i < al->count; i++)
        {
          ip_address *cur = al->addresses + i;
-         if (cur->type == IPV6_ADDRESS
+         if (cur->family == AF_INET6
 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
-             && ADDRESS_IPV6_SCOPE (cur) == ADDRESS_IPV6_SCOPE (ip)
+             && cur->ipv6_scope == ip->ipv6_scope
 #endif
-             && IN6_ARE_ADDR_EQUAL (&ADDRESS_IPV6_IN6_ADDR (cur),
-                                    &ADDRESS_IPV6_IN6_ADDR (ip)))
+             && IN6_ARE_ADDR_EQUAL (&cur->data.d6, &ip->data.d6))
            return true;
        }
       return false;
@@ -199,10 +196,10 @@ address_list_from_addrinfo (const struct addrinfo *ai)
       {
        const struct sockaddr_in6 *sin6 =
          (const struct sockaddr_in6 *)ptr->ai_addr;
-       ip->type = IPV6_ADDRESS;
-       ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
+       ip->family = AF_INET6;
+       ip->data.d6 = sin6->sin6_addr;
 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
-       ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
+       ip->ipv6_scope = sin6->sin6_scope_id;
 #endif
        ++ip;
       } 
@@ -210,17 +207,17 @@ address_list_from_addrinfo (const struct addrinfo *ai)
       {
        const struct sockaddr_in *sin =
          (const struct sockaddr_in *)ptr->ai_addr;
-       ip->type = IPV4_ADDRESS;
-       ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
+       ip->family = AF_INET;
+       ip->data.d4 = sin->sin_addr;
        ++ip;
       }
   assert (ip - al->addresses == cnt);
   return al;
 }
 
-#define IS_IPV4(addr) (((const ip_address *) addr)->type == IPV4_ADDRESS)
+#define IS_IPV4(addr) (((const ip_address *) addr)->family == AF_INET)
 
-/* Compare two IP addresses by type, giving preference to the IPv4
+/* Compare two IP addresses by family, giving preference to the IPv4
    address (sorting it first).  In other words, return -1 if ADDR1 is
    IPv4 and ADDR2 is IPv6, +1 if ADDR1 is IPv6 and ADDR2 is IPv4, and
    0 otherwise.
@@ -234,7 +231,7 @@ cmp_prefer_ipv4 (const void *addr1, const void *addr2)
   return !IS_IPV4 (addr1) - !IS_IPV4 (addr2);
 }
 
-#define IS_IPV6(addr) (((const ip_address *) addr)->type == IPV6_ADDRESS)
+#define IS_IPV6(addr) (((const ip_address *) addr)->family == AF_INET6)
 
 /* Like the above, but give preference to the IPv6 address.  */
 
@@ -267,7 +264,7 @@ address_list_from_ipv4_addresses (char **vec)
   for (i = 0; i < count; i++)
     {
       ip_address *ip = &al->addresses[i];
-      ip->type = IPV4_ADDRESS;
+      ip->family = AF_INET;
       memcpy (ADDRESS_IPV4_DATA (ip), vec[i], 4);
     }
 
@@ -406,26 +403,18 @@ getaddrinfo_with_timeout (const char *node, const char *service,
 const char *
 print_address (const ip_address *addr)
 {
-  switch (addr->type) 
-    {
-    case IPV4_ADDRESS:
-      return inet_ntoa (ADDRESS_IPV4_IN_ADDR (addr));
 #ifdef ENABLE_IPV6
-    case IPV6_ADDRESS:
-      {
-        static char buf[64];
-       if (!inet_ntop (AF_INET6, &ADDRESS_IPV6_IN6_ADDR (addr),
-                       buf, sizeof (buf)))
-         snprintf (buf, sizeof buf, "<error: %s>", strerror (errno));
-        buf[sizeof (buf) - 1] = '\0';
-        return buf;
-      }
+  static char buf[64];
+  if (!inet_ntop (addr->family, IP_INADDR_DATA (addr), buf, sizeof buf))
+    snprintf (buf, sizeof buf, "<error: %s>", strerror (errno));
+  return buf;
+#else
+  return inet_ntoa (addr->data.d4);
 #endif
-    }
-  abort ();
 }
 
-/* The following two functions were adapted from glibc. */
+/* The following two functions were adapted from glibc's
+   implementation of inet_pton, written by Paul Vixie. */
 
 static bool
 is_valid_ipv4_address (const char *str, const char *end)
index 6d0c553f83fb391066a920df406415a8bde07854..de71a406d41ef2a35c1196984e979d7b47e8de24 100644 (file)
@@ -47,48 +47,30 @@ struct address_list;
 /* This struct defines an IP address, tagged with family type.  */
 
 typedef struct {
-  /* Address type. */
-  enum { 
-    IPV4_ADDRESS
-#ifdef ENABLE_IPV6
-    , IPV6_ADDRESS 
-#endif /* ENABLE_IPV6 */
-  } type;
+  /* Address family, one of AF_INET or AF_INET6. */
+  int family;
 
-  /* Address data union: ipv6 contains IPv6-related data (address and
-     scope), and ipv4 contains the IPv4 address.  */
+  /* The actual data, in the form of struct in_addr or in6_addr: */
   union {
+    struct in_addr d4;         /* IPv4 address */
 #ifdef ENABLE_IPV6
-    struct {
-      struct in6_addr addr;
-# ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
-      unsigned int scope_id;
-# endif
-    } ipv6;
-#endif /* ENABLE_IPV6 */
-    struct {
-      struct in_addr addr;
-    } ipv4;
-  } u;
-} ip_address;
-
-/* Because C doesn't support anonymous unions, access to ip_address
-   elements is unwieldy.  Hence the accessors.
-
-   The _ADDR accessors return the address as the struct in_addr or
-   in6_addr.  The _DATA accessor returns a pointer to the address data
-   -- pretty much the same as the above, but cast to void*.  The
-   _SCOPE accessor returns the address's scope_id, and makes sense
-   only when IPv6 and HAVE_SOCKADDR_IN6_SCOPE_ID are both defined.  */
+    struct in6_addr d6;                /* IPv6 address */
+#endif
+  } data;
 
-#define ADDRESS_IPV4_IN_ADDR(x) ((x)->u.ipv4.addr)
-/* Don't use &x->u.ipv4.addr.s_addr because it can be #defined to a
-   bitfield, which you can't take an address of.  */
-#define ADDRESS_IPV4_DATA(x) ((void *)&(x)->u.ipv4.addr)
+  /* Under IPv6 getaddrinfo also returns scope_id.  Since it's
+     IPv6-specific it strictly belongs in the above union, but we put
+     it here for simplicity.  */
+#if defined ENABLE_IPV6 && defined HAVE_SOCKADDR_IN6_SCOPE_ID
+  int ipv6_scope;
+#endif
+} ip_address;
 
-#define ADDRESS_IPV6_IN6_ADDR(x) ((x)->u.ipv6.addr)
-#define ADDRESS_IPV6_DATA(x) ((void *)&(x)->u.ipv6.addr)
-#define ADDRESS_IPV6_SCOPE(x) ((x)->u.ipv6.scope_id)
+/* IP_INADDR_DATA macro returns a void pointer that can be interpreted
+   as a pointer to struct in_addr in IPv4 context or a pointer to
+   struct in6_addr in IPv4 context.  This pointer can be passed to
+   functions that work on either, such as inet_ntop.  */
+#define IP_INADDR_DATA(x) ((void *) &(x)->data)
 
 enum {
   LH_SILENT  = 1,