Print this page
inet_pton


   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"

  28 
  29 #include <sys/types.h>
  30 #include <sys/cmn_err.h>
  31 #include <sys/systm.h>
  32 #include <sys/socket.h>
  33 #include <sys/sunddi.h>
  34 #include <netinet/in.h>
  35 #include <inet/led.h>
  36 
  37 static void     convert2ascii(char *, const in6_addr_t *);
  38 static char     *strchr_w(const char *, int);
  39 static int      str2inet_addr(char *, ipaddr_t *);
  40 
  41 /*
  42  * inet_ntop -- Convert an IPv4 or IPv6 address in binary form into
  43  * printable form, and return a pointer to that string. Caller should
  44  * provide a buffer of correct length to store string into.
  45  * Note: this routine is kernel version of inet_ntop. It has similar
  46  * format as inet_ntop() defined in rfc2553. But it does not do
  47  * error handling operations exactly as rfc2553 defines. This function


 216         /* skip leading white space */
 217         while (*sp && (*sp == ' ' || *sp == '\t')) {
 218                 sp++;
 219         }
 220 
 221         do {
 222                 if (*sp == (char)c)
 223                         return ((char *)sp);
 224                 if (*sp == ' ' || *sp == '\t')
 225                         return (NULL);
 226         } while (*sp++);
 227         return (NULL);
 228 }
 229 
 230 static int
 231 str2inet_addr(char *cp, ipaddr_t *addrp)
 232 {
 233         char *end;
 234         long byte;
 235         int i;
 236         ipaddr_t addr = 0;


 237 
 238         for (i = 0; i < 4; i++) {
 239                 if (ddi_strtol(cp, &end, 10, &byte) != 0 || byte < 0 ||
 240                     byte > 255) {
 241                         return (0);
 242                 }
 243                 addr = (addr << 8) | (uint8_t)byte;
 244                 if (i < 3) {
 245                         if (*end != '.') {
 246                                 return (0);
 247                         } else {
 248                                 cp = end + 1;
 249                         }
 250                 } else {
 251                         cp = end;
 252                 }
 253         }
 254         *addrp = addr;
 255         return (1);
 256 }
 257 
 258 /*
 259  * inet_pton: This function takes string format IPv4 or IPv6 address and
 260  * converts it to binary form. The format of this function corresponds to
 261  * inet_pton() in the socket library.
 262  * It returns 0 for invalid IPv4 and IPv6 address
 263  *            1 when successfully converts ascii to binary
 264  *            -1 when af is not AF_INET or AF_INET6
 265  */
 266 int
 267 inet_pton(int af, char *inp, void *outp)
 268 {
 269         int i;
 270         long byte;
 271         char *end;
 272 
 273         switch (af) {
 274         case AF_INET:
 275                 return (str2inet_addr(inp, (ipaddr_t *)outp));






 276         case AF_INET6: {
 277                 union v6buf_u {
 278                         uint16_t v6words_u[8];
 279                         in6_addr_t v6addr_u;
 280                 } v6buf, *v6outp;
 281                 uint16_t        *dbl_col = NULL;
 282                 char lastbyte = NULL;
 283 
 284                 v6outp = (union v6buf_u *)outp;
 285 
 286                 if (strchr_w(inp, '.') != NULL) {
 287                         /* v4 mapped or v4 compatable */
 288                         if (strncmp(inp, "::ffff:", 7) == 0) {
 289                                 ipaddr_t ipv4_all_zeroes = 0;
 290                                 /* mapped - first init prefix and then fill */
 291                                 IN6_IPADDR_TO_V4MAPPED(ipv4_all_zeroes,
 292                                     &v6outp->v6addr_u);
 293                                 return (str2inet_addr(inp + 7,
 294                                     &(v6outp->v6addr_u.s6_addr32[3])));
 295                         } else if (strncmp(inp, "::", 2) == 0) {


 299                                     &(v6outp->v6addr_u.s6_addr32[3])));
 300                         }
 301                         return (0);
 302                 }
 303                 for (i = 0; i < 8; i++) {
 304                         int error;
 305                         /*
 306                          * if ddi_strtol() fails it could be because
 307                          * the string is "::".  That is valid and
 308                          * checked for below so just set the value to
 309                          * 0 and continue.
 310                          */
 311                         if ((error = ddi_strtol(inp, &end, 16, &byte)) != 0) {
 312                                 if (error == ERANGE)
 313                                         return (0);
 314                                 byte = 0;
 315                         }
 316                         if (byte < 0 || byte > 0x0ffff) {
 317                                 return (0);
 318                         }



 319                         v6buf.v6words_u[i] = (uint16_t)byte;

 320                         if (*end == NULL || i == 7) {
 321                                 inp = end;
 322                                 break;
 323                         }
 324                         if (inp == end) {       /* not a number must be */
 325                                 if (*inp == ':' &&
 326                                     ((i == 0 && *(inp + 1) == ':') ||
 327                                     lastbyte == ':')) {
 328                                         if (dbl_col) {
 329                                                 return (0);
 330                                         }
 331                                         if (byte != 0)
 332                                                 i++;
 333                                         dbl_col = &v6buf.v6words_u[i];
 334                                         if (i == 0)
 335                                                 inp++;
 336                                 } else if (*inp == NULL || *inp == ' ' ||
 337                                     *inp == '\t') {
 338                                         break;
 339                                 } else {


 371                         bzero(&v6outp->v6addr_u, sizeof (in6_addr_t));
 372                         rem = dbl_col - &v6buf.v6words_u[0];
 373                         for (next = 0; next < rem; next++) {
 374                                 v6outp->v6words_u[next] = v6buf.v6words_u[next];
 375                         }
 376                         next++; /* skip dbl_col 0 */
 377                         rem = i - rem;
 378                         word = 8 - rem;
 379                         while (rem > 0) {
 380                                 v6outp->v6words_u[word] = v6buf.v6words_u[next];
 381                                 word++;
 382                                 rem--;
 383                                 next++;
 384                         }
 385                 }
 386                 return (1);     /* Success */
 387         }
 388         }       /* switch */
 389         return (-1);    /* return -1 for default case */
 390 }























   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 /*
  27  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <sys/cmn_err.h>
  32 #include <sys/systm.h>
  33 #include <sys/socket.h>
  34 #include <sys/sunddi.h>
  35 #include <netinet/in.h>
  36 #include <inet/led.h>
  37 
  38 static void     convert2ascii(char *, const in6_addr_t *);
  39 static char     *strchr_w(const char *, int);
  40 static int      str2inet_addr(char *, ipaddr_t *);
  41 
  42 /*
  43  * inet_ntop -- Convert an IPv4 or IPv6 address in binary form into
  44  * printable form, and return a pointer to that string. Caller should
  45  * provide a buffer of correct length to store string into.
  46  * Note: this routine is kernel version of inet_ntop. It has similar
  47  * format as inet_ntop() defined in rfc2553. But it does not do
  48  * error handling operations exactly as rfc2553 defines. This function


 217         /* skip leading white space */
 218         while (*sp && (*sp == ' ' || *sp == '\t')) {
 219                 sp++;
 220         }
 221 
 222         do {
 223                 if (*sp == (char)c)
 224                         return ((char *)sp);
 225                 if (*sp == ' ' || *sp == '\t')
 226                         return (NULL);
 227         } while (*sp++);
 228         return (NULL);
 229 }
 230 
 231 static int
 232 str2inet_addr(char *cp, ipaddr_t *addrp)
 233 {
 234         char *end;
 235         long byte;
 236         int i;
 237         uint8_t *addr = (uint8_t *)addrp;
 238 
 239         *addrp = 0;
 240 
 241         for (i = 0; i < 4; i++) {
 242                 if (ddi_strtol(cp, &end, 10, &byte) != 0 || byte < 0 ||
 243                     byte > 255) {
 244                         return (0);
 245                 }
 246                 addr[i] = (uint8_t)byte;
 247                 if (i < 3) {
 248                         if (*end != '.') {
 249                                 return (0);
 250                         } else {
 251                                 cp = end + 1;
 252                         }
 253                 } else {
 254                         cp = end;
 255                 }
 256         }
 257 
 258         return (1);
 259 }
 260 
 261 /*
 262  * inet_pton: This function takes string format IPv4 or IPv6 address and
 263  * converts it to binary form. The format of this function corresponds to
 264  * inet_pton() in the socket library.
 265  * It returns 0 for invalid IPv4 and IPv6 address
 266  *            1 when successfully converts ascii to binary
 267  *            -1 when af is not AF_INET or AF_INET6
 268  */
 269 int
 270 m_inet_pton(int af, char *inp, void *outp, int revert)
 271 {
 272         int i;
 273         long byte;
 274         char *end;
 275 
 276         switch (af) {
 277         case AF_INET:
 278                 if (str2inet_addr(inp, (ipaddr_t *)outp)) {
 279                         if (! revert)
 280                                 *(uint32_t *)outp = ntohl(*(uint32_t *)outp);
 281                         return (1);
 282                 } else {
 283                         return (0);
 284                 }
 285         case AF_INET6: {
 286                 union v6buf_u {
 287                         uint16_t v6words_u[8];
 288                         in6_addr_t v6addr_u;
 289                 } v6buf, *v6outp;
 290                 uint16_t        *dbl_col = NULL;
 291                 char lastbyte = NULL;
 292 
 293                 v6outp = (union v6buf_u *)outp;
 294 
 295                 if (strchr_w(inp, '.') != NULL) {
 296                         /* v4 mapped or v4 compatable */
 297                         if (strncmp(inp, "::ffff:", 7) == 0) {
 298                                 ipaddr_t ipv4_all_zeroes = 0;
 299                                 /* mapped - first init prefix and then fill */
 300                                 IN6_IPADDR_TO_V4MAPPED(ipv4_all_zeroes,
 301                                     &v6outp->v6addr_u);
 302                                 return (str2inet_addr(inp + 7,
 303                                     &(v6outp->v6addr_u.s6_addr32[3])));
 304                         } else if (strncmp(inp, "::", 2) == 0) {


 308                                     &(v6outp->v6addr_u.s6_addr32[3])));
 309                         }
 310                         return (0);
 311                 }
 312                 for (i = 0; i < 8; i++) {
 313                         int error;
 314                         /*
 315                          * if ddi_strtol() fails it could be because
 316                          * the string is "::".  That is valid and
 317                          * checked for below so just set the value to
 318                          * 0 and continue.
 319                          */
 320                         if ((error = ddi_strtol(inp, &end, 16, &byte)) != 0) {
 321                                 if (error == ERANGE)
 322                                         return (0);
 323                                 byte = 0;
 324                         }
 325                         if (byte < 0 || byte > 0x0ffff) {
 326                                 return (0);
 327                         }
 328                         if (revert) {
 329                                 v6buf.v6words_u[i] = htons((uint16_t)byte);
 330                         } else {
 331                                 v6buf.v6words_u[i] = (uint16_t)byte;
 332                         }
 333                         if (*end == NULL || i == 7) {
 334                                 inp = end;
 335                                 break;
 336                         }
 337                         if (inp == end) {       /* not a number must be */
 338                                 if (*inp == ':' &&
 339                                     ((i == 0 && *(inp + 1) == ':') ||
 340                                     lastbyte == ':')) {
 341                                         if (dbl_col) {
 342                                                 return (0);
 343                                         }
 344                                         if (byte != 0)
 345                                                 i++;
 346                                         dbl_col = &v6buf.v6words_u[i];
 347                                         if (i == 0)
 348                                                 inp++;
 349                                 } else if (*inp == NULL || *inp == ' ' ||
 350                                     *inp == '\t') {
 351                                         break;
 352                                 } else {


 384                         bzero(&v6outp->v6addr_u, sizeof (in6_addr_t));
 385                         rem = dbl_col - &v6buf.v6words_u[0];
 386                         for (next = 0; next < rem; next++) {
 387                                 v6outp->v6words_u[next] = v6buf.v6words_u[next];
 388                         }
 389                         next++; /* skip dbl_col 0 */
 390                         rem = i - rem;
 391                         word = 8 - rem;
 392                         while (rem > 0) {
 393                                 v6outp->v6words_u[word] = v6buf.v6words_u[next];
 394                                 word++;
 395                                 rem--;
 396                                 next++;
 397                         }
 398                 }
 399                 return (1);     /* Success */
 400         }
 401         }       /* switch */
 402         return (-1);    /* return -1 for default case */
 403 }
 404 
 405 
 406 int
 407 _inet_pton(int af, char *inp, void *outp)
 408 {
 409         return (m_inet_pton(af, inp, outp, 1));
 410 }
 411 
 412 /*
 413  * We need this inet_pton to preserve compatibility with old closed binaries.
 414  * Earlier, inet_pton returned address in hardware native order,
 415  * not in network one. (See http://www.illumos.org/issue/3105).
 416  * Having fixed that, we still need to support binaries, that use bad inet_pton
 417  * and reverse returned address manually. All new inet_pton calls will be
 418  * redirected to _inet_pton with #define in the header file.
 419  */
 420 int
 421 inet_pton(int af, char *inp, void *outp)
 422 {
 423         return (m_inet_pton(af, inp, outp, 0));
 424 }