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         uint32_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] */