library init: be recursive
[platform/upstream/c-ares.git] / inet_net_pton.c
index e028ec6..71c07c5 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996,1999 by Internet Software Consortium.
  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "setup.h"
-
-
-#include <sys/types.h>
+#include "ares_setup.h"
 
-#if defined(WIN32) && !defined(WATT32)
-#include "nameser.h"
-#else
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
 #ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
+#  include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#  include <arpa/inet.h>
 #endif
 #ifdef HAVE_ARPA_NAMESER_H
-#include <arpa/nameser.h>
+#  include <arpa/nameser.h>
+#else
+#  include "nameser.h"
 #endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#  include <arpa/nameser_compat.h>
 #endif
 
-#endif
+#include "ares.h"
+#include "ares_ipv6.h"
+#include "ares_nowarn.h"
+#include "ares_inet_net_pton.h"
 
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
 
-#include "ares_ipv6.h"
-#include "inet_net_pton.h"
+const struct ares_in6_addr ares_in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
+
 
-#if !defined(HAVE_INET_NET_PTON) || !defined(HAVE_INET_NET_PTON_IPV6) || \
-    !defined(HAVE_INET_PTON) || !defined(HAVE_INET_PTON_IPV6)
+#ifndef HAVE_INET_NET_PTON
 
 /*
  * static int
  * note:
  *      network byte order assumed.  this means 192.5.5.240/28 has
  *      0b11110000 in its fourth octet.
+ * note:
+ *      On Windows we store the error in the thread errno, not
+ *      in the winsock error code. This is to avoid loosing the
+ *      actual last winsock error. So use macro ERRNO to fetch the
+ *      errno this funtion sets when returning (-1), not SOCKERRNO.
  * author:
  *      Paul Vixie (ISC), June 1996
  */
@@ -77,46 +75,46 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
 
   ch = *src++;
   if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
-      && isascii((unsigned char)(src[1]))
-      && isxdigit((unsigned char)(src[1]))) {
+      && ISASCII(src[1])
+      && ISXDIGIT(src[1])) {
     /* Hexadecimal: Eat nybble string. */
-    if (size <= 0U)
+    if (!size)
       goto emsgsize;
     dirty = 0;
     src++;  /* skip x or X. */
-    while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) {
-      if (isupper(ch))
+    while ((ch = *src++) != '\0' && ISASCII(ch) && ISXDIGIT(ch)) {
+      if (ISUPPER(ch))
         ch = tolower(ch);
-      n = (int)(strchr(xdigits, ch) - xdigits);
+      n = aresx_sztosi(strchr(xdigits, ch) - xdigits);
       if (dirty == 0)
         tmp = n;
       else
         tmp = (tmp << 4) | n;
       if (++dirty == 2) {
-        if (size-- <= 0U)
+        if (!size--)
           goto emsgsize;
         *dst++ = (unsigned char) tmp;
         dirty = 0;
       }
     }
     if (dirty) {  /* Odd trailing nybble? */
-      if (size-- <= 0U)
+      if (!size--)
         goto emsgsize;
       *dst++ = (unsigned char) (tmp << 4);
     }
-  } else if (isascii(ch) && isdigit(ch)) {
+  } else if (ISASCII(ch) && ISDIGIT(ch)) {
     /* Decimal: eat dotted digit string. */
     for (;;) {
       tmp = 0;
       do {
-        n = (int)(strchr(digits, ch) - digits);
+        n = aresx_sztosi(strchr(digits, ch) - digits);
         tmp *= 10;
         tmp += n;
         if (tmp > 255)
           goto enoent;
       } while ((ch = *src++) != '\0' &&
-               isascii(ch) && isdigit(ch));
-      if (size-- <= 0U)
+               ISASCII(ch) && ISDIGIT(ch));
+      if (!size--)
         goto emsgsize;
       *dst++ = (unsigned char) tmp;
       if (ch == '\0' || ch == '/')
@@ -124,27 +122,27 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
       if (ch != '.')
         goto enoent;
       ch = *src++;
-      if (!isascii(ch) || !isdigit(ch))
+      if (!ISASCII(ch) || !ISDIGIT(ch))
         goto enoent;
     }
   } else
     goto enoent;
 
   bits = -1;
-  if (ch == '/' && isascii((unsigned char)(src[0])) &&
-      isdigit((unsigned char)(src[0])) && dst > odst) {
+  if (ch == '/' && ISASCII(src[0]) &&
+      ISDIGIT(src[0]) && dst > odst) {
     /* CIDR width specifier.  Nothing can follow it. */
     ch = *src++;    /* Skip over the /. */
     bits = 0;
     do {
-      n = (int)(strchr(digits, ch) - digits);
+      n = aresx_sztosi(strchr(digits, ch) - digits);
       bits *= 10;
       bits += n;
-    } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+      if (bits > 32)
+        goto enoent;
+    } while ((ch = *src++) != '\0' && ISASCII(ch) && ISDIGIT(ch));
     if (ch != '\0')
       goto enoent;
-    if (bits > 32)
-      goto emsgsize;
   }
 
   /* Firey death and destruction unless we prefetched EOS. */
@@ -168,7 +166,7 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
       bits = 8;
     /* If imputed mask is narrower than specified octets, widen. */
     if (bits < ((dst - odst) * 8))
-      bits = (int)(dst - odst) * 8;
+      bits = aresx_sztosi(dst - odst) * 8;
     /*
      * If there are no additional bits specified for a class D
      * address adjust bits to 4.
@@ -178,18 +176,18 @@ inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
   }
   /* Extend network to cover the actual mask. */
   while (bits > ((dst - odst) * 8)) {
-    if (size-- <= 0U)
+    if (!size--)
       goto emsgsize;
     *dst++ = '\0';
   }
   return (bits);
 
   enoent:
-  errno = ENOENT;
+  SET_ERRNO(ENOENT);
   return (-1);
 
   emsgsize:
-  errno = EMSGSIZE;
+  SET_ERRNO(EMSGSIZE);
   return (-1);
 }
 
@@ -211,7 +209,7 @@ getbits(const char *src, int *bitsp)
       if (n++ != 0 && val == 0)       /* no leading zeros */
         return (0);
       val *= 10;
-      val += (pch - digits);
+      val += aresx_sztosi(pch - digits);
       if (val > 128)                  /* range */
         return (0);
       continue;
@@ -243,7 +241,7 @@ getv4(const char *src, unsigned char *dst, int *bitsp)
       if (n++ != 0 && val == 0)       /* no leading zeros */
         return (0);
       val *= 10;
-      val += (pch - digits);
+      val += aresx_sztoui(pch - digits);
       if (val > 255)                  /* range */
         return (0);
       continue;
@@ -251,7 +249,7 @@ getv4(const char *src, unsigned char *dst, int *bitsp)
     if (ch == '.' || ch == '/') {
       if (dst - odst > 3)             /* too many octets? */
         return (0);
-      *dst++ = val;
+      *dst++ = (unsigned char)val;
       if (ch == '/')
         return (getbits(src, bitsp));
       val = 0;
@@ -264,8 +262,8 @@ getv4(const char *src, unsigned char *dst, int *bitsp)
     return (0);
   if (dst - odst > 3)             /* too many octets? */
     return (0);
-  *dst++ = val;
-  return (1);
+  *dst = (unsigned char)val;
+  return 1;
 }
 
 static int
@@ -303,7 +301,7 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
       pch = strchr((xdigits = xdigits_u), ch);
     if (pch != NULL) {
       val <<= 4;
-      val |= (pch - xdigits);
+      val |= aresx_sztoui(pch - xdigits);
       if (++digits > 4)
         goto enoent;
       saw_xdigit = 1;
@@ -320,8 +318,8 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
         goto enoent;
       if (tp + NS_INT16SZ > endp)
         return (0);
-      *tp++ = (unsigned char) (val >> 8) & 0xff;
-      *tp++ = (unsigned char) val & 0xff;
+      *tp++ = (unsigned char)((val >> 8) & 0xff);
+      *tp++ = (unsigned char)(val & 0xff);
       saw_xdigit = 0;
       digits = 0;
       val = 0;
@@ -341,8 +339,8 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
   if (saw_xdigit) {
     if (tp + NS_INT16SZ > endp)
       goto enoent;
-    *tp++ = (unsigned char) (val >> 8) & 0xff;
-    *tp++ = (unsigned char) val & 0xff;
+    *tp++ = (unsigned char)((val >> 8) & 0xff);
+    *tp++ = (unsigned char)(val & 0xff);
   }
   if (bits == -1)
     bits = 128;
@@ -359,14 +357,14 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
      * Since some memmove()'s erroneously fail to handle
      * overlapping regions, we'll do the shift by hand.
      */
-    const int n = (int)(tp - colonp);
-    int i;
+    const ssize_t n = tp - colonp;
+    ssize_t i;
 
     if (tp == endp)
       goto enoent;
     for (i = 1; i <= n; i++) {
-      endp[- i] = colonp[n - i];
-      colonp[n - i] = 0;
+      *(endp - i) = *(colonp + n - i);
+      *(colonp + n - i) = 0;
     }
     tp = endp;
   }
@@ -380,11 +378,11 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
   return (bits);
 
   enoent:
-  errno = ENOENT;
+  SET_ERRNO(ENOENT);
   return (-1);
 
   emsgsize:
-  errno = EMSGSIZE;
+  SET_ERRNO(EMSGSIZE);
   return (-1);
 }
 
@@ -398,6 +396,11 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
  *      number of bits, either imputed classfully or specified with /CIDR,
  *      or -1 if some failure occurred (check errno).  ENOENT means it was
  *      not a valid network specification.
+ * note:
+ *      On Windows we store the error in the thread errno, not
+ *      in the winsock error code. This is to avoid loosing the
+ *      actual last winsock error. So use macro ERRNO to fetch the
+ *      errno this funtion sets when returning (-1), not SOCKERRNO.
  * author:
  *      Paul Vixie (ISC), June 1996
  */
@@ -410,30 +413,38 @@ ares_inet_net_pton(int af, const char *src, void *dst, size_t size)
   case AF_INET6:
     return (inet_net_pton_ipv6(src, dst, size));
   default:
-    errno = EAFNOSUPPORT;
+    SET_ERRNO(EAFNOSUPPORT);
     return (-1);
   }
 }
 
-#endif
+#endif /* HAVE_INET_NET_PTON */
 
-#if !defined(HAVE_INET_PTON) || !defined(HAVE_INET_PTON_IPV6)
+#ifndef HAVE_INET_PTON
 int ares_inet_pton(int af, const char *src, void *dst)
 {
-  int size, result;
+  int result;
+  size_t size;
 
   if (af == AF_INET)
     size = sizeof(struct in_addr);
   else if (af == AF_INET6)
-    size = sizeof(struct in6_addr);
+    size = sizeof(struct ares_in6_addr);
   else
   {
-    errno = EAFNOSUPPORT;
+    SET_ERRNO(EAFNOSUPPORT);
     return -1;
   }
   result = ares_inet_net_pton(af, src, dst, size);
-  if (result == -1 && errno == ENOENT)
+  if (result == -1 && ERRNO == ENOENT)
     return 0;
   return (result > -1 ? 1 : -1);
 }
+#else /* HAVE_INET_PTON */
+int ares_inet_pton(int af, const char *src, void *dst)
+{
+  /* just relay this to the underlying function */
+  return inet_pton(af, src, dst);
+}
+
 #endif