Print this page
inet_pton

@@ -21,12 +21,13 @@
  */
 /*
  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident   "%Z%%M% %I%     %E% SMI"
+/*
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/cmn_err.h>
 #include <sys/systm.h>
 #include <sys/socket.h>

@@ -231,29 +232,31 @@
 str2inet_addr(char *cp, ipaddr_t *addrp)
 {
         char *end;
         long byte;
         int i;
-        ipaddr_t addr = 0;
+        uint8_t *addr = (uint8_t *)addrp;
+
+        *addrp = 0;
 
         for (i = 0; i < 4; i++) {
                 if (ddi_strtol(cp, &end, 10, &byte) != 0 || byte < 0 ||
                     byte > 255) {
                         return (0);
                 }
-                addr = (addr << 8) | (uint8_t)byte;
+                addr[i] = (uint8_t)byte;
                 if (i < 3) {
                         if (*end != '.') {
                                 return (0);
                         } else {
                                 cp = end + 1;
                         }
                 } else {
                         cp = end;
                 }
         }
-        *addrp = addr;
+
         return (1);
 }
 
 /*
  * inet_pton: This function takes string format IPv4 or IPv6 address and

@@ -262,19 +265,25 @@
  * It returns 0 for invalid IPv4 and IPv6 address
  *            1 when successfully converts ascii to binary
  *            -1 when af is not AF_INET or AF_INET6
  */
 int
-inet_pton(int af, char *inp, void *outp)
+m_inet_pton(int af, char *inp, void *outp, int revert)
 {
         int i;
         long byte;
         char *end;
 
         switch (af) {
         case AF_INET:
-                return (str2inet_addr(inp, (ipaddr_t *)outp));
+                if (str2inet_addr(inp, (ipaddr_t *)outp)) {
+                        if (! revert)
+                                *(uint32_t *)outp = ntohl(*(uint32_t *)outp);
+                        return (1);
+                } else {
+                        return (0);
+                }
         case AF_INET6: {
                 union v6buf_u {
                         uint16_t v6words_u[8];
                         in6_addr_t v6addr_u;
                 } v6buf, *v6outp;

@@ -314,11 +323,15 @@
                                 byte = 0;
                         }
                         if (byte < 0 || byte > 0x0ffff) {
                                 return (0);
                         }
+                        if (revert) {
+                                v6buf.v6words_u[i] = htons((uint16_t)byte);
+                        } else {
                         v6buf.v6words_u[i] = (uint16_t)byte;
+                        }
                         if (*end == NULL || i == 7) {
                                 inp = end;
                                 break;
                         }
                         if (inp == end) {       /* not a number must be */

@@ -386,5 +399,26 @@
                 return (1);     /* Success */
         }
         }       /* switch */
         return (-1);    /* return -1 for default case */
 }
+
+
+int
+_inet_pton(int af, char *inp, void *outp)
+{
+        return (m_inet_pton(af, inp, outp, 1));
+}
+
+/*
+ * We need this inet_pton to preserve compatibility with old closed binaries.
+ * Earlier, inet_pton returned address in hardware native order,
+ * not in network one. (See http://www.illumos.org/issue/3105).
+ * Having fixed that, we still need to support binaries, that use bad inet_pton
+ * and reverse returned address manually. All new inet_pton calls will be
+ * redirected to _inet_pton with #define in the header file.
+ */
+int
+inet_pton(int af, char *inp, void *outp)
+{
+        return (m_inet_pton(af, inp, outp, 0));
+}