## modules/ip/inet_pton.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. inet_pton
2. inet_pton4
3. inet_pton6

       1 /*      $NetBSD: inet_pton.c,v 1.16 2000/02/07 18:51:02 itojun Exp $    */
       2
       3 /* Copyright (c) 1996 by Internet Software Consortium.
       4  *
       5  * Permission to use, copy, modify, and distribute this software for any
       6  * purpose with or without fee is hereby granted, provided that the above
       7  * copyright notice and this permission notice appear in all copies.
       8  *
       9  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
      10  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
      11  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
      12  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
      13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
      14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
      15  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
      16  * SOFTWARE.
      17  */
      18
      19 /*#include <sys/cdefs.h>*/
      20 #define __P(a) a
      21
      22 #if defined(LIBC_SCCS) && !defined(lint)
      23 #if 0
      24 static char rcsid[] = "Id: inet_pton.c,v 8.7 1996/08/05 08:31:35 vixie Exp ";
      25 #else
      26 __RCSID("$NetBSD: inet_pton.c,v 1.16 2000/02/07 18:51:02 itojun Exp $");
      27 #endif
      28 #endif /* LIBC_SCCS and not lint */
      29
      30 /*#include "namespace.h"*/
      31 #include <sys/param.h>
      32 #include <sys/types.h>
      33 #include <sys/socket.h>
      34 #include <netinet/in.h>
      35 #include <arpa/inet.h>
      36 #include <arpa/nameser.h>
      37
      38 #include <assert.h>
      39 #include <ctype.h>
      40 #include <errno.h>
      41 #include <stdlib.h>
      42 #include <string.h>
      43
      44 #include "inet6def.h"
      45
      46 /*
      47  * WARNING: Don't even consider trying to compile this on a system where
      48  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
      49  */
      50
      51 static int      inet_pton4 __P((const char *src, u_char *dst, int pton));
      52 static int      inet_pton6 __P((const char *src, u_char *dst));
      53
      54 /* int
      55  * inet_pton(af, src, dst)
      56  *      convert from presentation format (which usually means ASCII printable)
      57  *      to network format (which is usually some kind of binary format).
      58  * return:
      59  *      1 if the address was valid for the specified address family
      60  *      0 if the address wasn't valid (`dst' is untouched in this case)
      61  *      -1 if some other error occurred (`dst' is untouched in this case, too)
      62  * author:
      63  *      Paul Vixie, 1996.
      64  */
      65 int
      66 inet_pton(af, src, dst)
         /* [<][>][^][v][top][bottom][index][help] */
      67         int af;
      68         const char *src;
      69         void *dst;
      70 {
      71
      72         if(src == NULL || dst == NULL) {
      73                 return 0;
      74         }
      75
      76         switch (af) {
      77         case AF_INET:
      78                 return (inet_pton4(src, dst, 1));
      79         case AF_INET6:
      80                 return (inet_pton6(src, dst));
      81         default:
      82                 errno = EAFNOSUPPORT;
      83                 return (-1);
      84         }
      85         /* NOTREACHED */
      86 }
      87
      88 /* int
      89  * inet_pton4(src, dst, pton)
      90  *      when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
      91  *      when last arg is 1: inet_pton(). decimal dotted-quad only.
      92  * return:
      93  *      1 if `src' is a valid input, else 0.
      94  * notice:
      95  *      does not touch `dst' unless it's returning 1.
      96  * author:
      97  *      Paul Vixie, 1996.
      98  */
      99 static int
     100 inet_pton4(src, dst, pton)
         /* [<][>][^][v][top][bottom][index][help] */
     101         const char *src;
     102         u_char *dst;
     103         int pton;
     104 {
     105         u_int32_t val;
     106         u_int digit;
     107         int base, n;
     108         unsigned char c;
     109         u_int parts[4];
     110         register u_int *pp = parts;
     111
     112         if(src == NULL || dst == NULL) {
     113                 return 0;
     114         }
     115
     116         c = *src;
     117         for (;;) {
     118                 /*
     119                  * Collect number up to ``.''.
     120                  * Values are specified as for C:
     121                  * 0x=hex, 0=octal, isdigit=decimal.
     122                  */
     123                 if (!isdigit(c))
     124                         return (0);
     125                 val = 0; base = 10;
     126                 if (c == '0') {
     127                         c = *++src;
     128                         if (c == 'x' || c == 'X')
     129                                 base = 16, c = *++src;
     130                         else if (isdigit(c) && c != '9')
     131                                 base = 8;
     132                 }
     133                 /* inet_pton() takes decimal only */
     134                 if (pton && base != 10)
     135                         return (0);
     136                 for (;;) {
     137                         if (isdigit(c)) {
     138                                 digit = c - '0';
     139                                 if (digit >= base)
     140                                         break;
     141                                 val = (val * base) + digit;
     142                                 c = *++src;
     143                         } else if (base == 16 && isxdigit(c)) {
     144                                 digit = c + 10 - (islower(c) ? 'a' : 'A');
     145                                 if (digit >= 16)
     146                                         break;
     147                                 val = (val << 4) | digit;
     148                                 c = *++src;
     149                         } else
     150                                 break;
     151                 }
     152                 if (c == '.') {
     153                         /*
     154                          * Internet format:
     155                          *      a.b.c.d
     156                          *      a.b.c   (with c treated as 16 bits)
     157                          *      a.b     (with b treated as 24 bits)
     158                          *      a       (with a treated as 32 bits)
     159                          */
     160                         if (pp >= parts + 3)
     161                                 return (0);
     162                         *pp++ = val;
     163                         c = *++src;
     164                 } else
     165                         break;
     166         }
     167         /*
     168          * Check for trailing characters.
     169          */
     170         if (c != '\0' && !isspace(c))
     171                 return (0);
     172         /*
     173          * Concoct the address according to
     174          * the number of parts specified.
     175          */
     176         n = pp - parts + 1;
     177         /* inet_pton() takes dotted-quad only.  it does not take shorthand. */
     178         if (pton && n != 4)
     179                 return (0);
     180         switch (n) {
     181
     182         case 0:
     183                 return (0);             /* initial nondigit */
     184
     185         case 1:                         /* a -- 32 bits */
     186                 break;
     187
     188         case 2:                         /* a.b -- 8.24 bits */
     189                 if (parts[0] > 0xff || val > 0xffffff)
     190                         return (0);
     191                 val |= parts[0] << 24;
     192                 break;
     193
     194         case 3:                         /* a.b.c -- 8.8.16 bits */
     195                 if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
     196                         return (0);
     197                 val |= (parts[0] << 24) | (parts[1] << 16);
     198                 break;
     199
     200         case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
     201                 if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
     202                         return (0);
     203                 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
     204                 break;
     205         }
     206         if (dst) {
     207                 val = htonl(val);
     208                 memcpy(dst, &val, INADDRSZ);
     209         }
     210         return (1);
     211 }
     212
     213 /* int
     214  * inet_pton6(src, dst)
     215  *      convert presentation level address to network order binary form.
     216  * return:
     217  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
     218  * notice:
     219  *      (1) does not touch `dst' unless it's returning 1.
     220  *      (2) :: in a full address is silently ignored.
     221  * credit:
     222  *      inspired by Mark Andrews.
     223  * author:
     224  *      Paul Vixie, 1996.
     225  */
     226 static int
     227 inet_pton6(src, dst)
         /* [<][>][^][v][top][bottom][index][help] */
     228         const char *src;
     229         u_char *dst;
     230 {
     231         static const char xdigits_l[] = "0123456789abcdef",
     232                           xdigits_u[] = "0123456789ABCDEF";
     233         u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
     234         const char *xdigits, *curtok;
     235         int ch, saw_xdigit;
     236         u_int val;
     237
     238         if(src == NULL || dst == NULL) {
     239                 return 0;
     240         }
     241
     242         memset((tp = tmp), '\0', IN6ADDRSZ);
     243         endp = tp + IN6ADDRSZ;
     244         colonp = NULL;
     245         /* Leading :: requires some special handling. */
     246         if (*src == ':')
     247                 if (*++src != ':')
     248                         return (0);
     249         curtok = src;
     250         saw_xdigit = 0;
     251         val = 0;
     252         while ((ch = *src++) != '\0') {
     253                 const char *pch;
     254
     255                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
     256                         pch = strchr((xdigits = xdigits_u), ch);
     257                 if (pch != NULL) {
     258                         val <<= 4;
     259                         val |= (pch - xdigits);
     260                         if (val > 0xffff)
     261                                 return (0);
     262                         saw_xdigit = 1;
     263                         continue;
     264                 }
     265                 if (ch == ':') {
     266                         curtok = src;
     267                         if (!saw_xdigit) {
     268                                 if (colonp)
     269                                         return (0);
     270                                 colonp = tp;
     271                                 continue;
     272                         } else if (*src == '\0')
     273                                 return (0);
     274                         if (tp + INT16SZ > endp)
     275                                 return (0);
     276                         *tp++ = (u_char) (val >> 8) & 0xff;
     277                         *tp++ = (u_char) val & 0xff;
     278                         saw_xdigit = 0;
     279                         val = 0;
     280                         continue;
     281                 }
     282                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
     283                     inet_pton4(curtok, tp, 1) > 0) {
     284                         tp += INADDRSZ;
     285                         saw_xdigit = 0;
     286                         break;  /* '\0' was seen by inet_pton4(). */
     287                 }
     288                 return (0);
     289         }
     290         if (saw_xdigit) {
     291                 if (tp + INT16SZ > endp)
     292                         return (0);
     293                 *tp++ = (u_char) (val >> 8) & 0xff;
     294                 *tp++ = (u_char) val & 0xff;
     295         }
     296         if (colonp != NULL) {
     297                 /*
     298                  * Since some memmove()'s erroneously fail to handle
     299                  * overlapping regions, we'll do the shift by hand.
     300                  */
     301                 const int n = tp - colonp;
     302                 int i;
     303
     304                 if (tp == endp)
     305                         return (0);
     306                 for (i = 1; i <= n; i++) {
     307                         endp[- i] = colonp[n - i];
     308                         colonp[n - i] = 0;
     309                 }
     310                 tp = endp;
     311         }
     312         if (tp != endp)
     313                 return (0);
     314         memcpy(dst, tmp, IN6ADDRSZ);
     315         return (1);
     316 }
     317

/* [<][>][^][v][top][bottom][index][help] */