inet_pton.c

00001 /*      Id: inet_pton.c,v 1.5 2001/04/13 15:24:35 lukem Exp     */
00002 /*      $NetBSD: inet_pton.c,v 1.16 2000/02/07 18:51:02 itojun Exp $    */
00003 
00004 /* Copyright (c) 1996 by Internet Software Consortium.
00005  *
00006  * Permission to use, copy, modify, and distribute this software for any
00007  * purpose with or without fee is hereby granted, provided that the above
00008  * copyright notice and this permission notice appear in all copies.
00009  *
00010  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
00011  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00012  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
00013  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00014  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00015  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00016  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00017  * SOFTWARE.
00018  */
00019 
00020 #include <net-snmp/net-snmp-config.h>
00021 
00022 #ifndef HAVE_INET_PTON
00023 
00024 #if HAVE_ARPA_NAMESER_H
00025 #include <arpa/nameser.h>
00026 #endif
00027 
00028   /*
00029    * Net-SNMP Win32 additions
00030    */
00031 #if defined(HAVE_WINSOCK_H) || defined(cygwin)
00032 #include <winsock2.h>
00033 #include <ws2tcpip.h>
00034 #include <errno.h>
00035 #include <stdio.h>
00036 #endif
00037 
00038 #ifndef EAFNOSUPPORT
00039 #define EAFNOSUPPORT            WSAEAFNOSUPPORT
00040 #endif
00041 
00042 #ifndef IN6ADDRSZ
00043 #define IN6ADDRSZ       16
00044 #endif
00045 
00046 #ifndef INT16SZ
00047 #define INT16SZ         2
00048 #endif
00049   /*
00050    * End of Net-SNMP Win32 additions
00051    */
00052 
00053 #ifndef INADDRSZ
00054 #define INADDRSZ        4
00055 #endif
00056 
00057 /*
00058  * WARNING: Don't even consider trying to compile this on a system where
00059  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
00060  */
00061 
00062 static int      inet_pton4(const char *src, u_char *dst, int pton);
00063 #ifdef INET6
00064 static int      inet_pton6(const char *src, u_char *dst);
00065 #endif
00066 
00067 /* int
00068  * inet_pton(af, src, dst)
00069  *      convert from presentation format (which usually means ASCII printable)
00070  *      to network format (which is usually some kind of binary format).
00071  * return:
00072  *      1 if the address was valid for the specified address family
00073  *      0 if the address wasn't valid (`dst' is untouched in this case)
00074  *      -1 if some other error occurred (`dst' is untouched in this case, too)
00075  * author:
00076  *      Paul Vixie, 1996.
00077  */
00078 int
00079 inet_pton(af, src, dst)
00080         int af;
00081         const char *src;
00082         void *dst;
00083 {
00084 
00085         switch (af) {
00086         case AF_INET:
00087                 return (inet_pton4(src, dst, 1));
00088 #ifdef INET6
00089         case AF_INET6:
00090                 return (inet_pton6(src, dst));
00091 #endif
00092         default:
00093                 errno = EAFNOSUPPORT;
00094                 return (-1);
00095         }
00096         /* NOTREACHED */
00097 }
00098 
00099 /* int
00100  * inet_pton4(src, dst, pton)
00101  *      when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
00102  *      when last arg is 1: inet_pton(). decimal dotted-quad only.
00103  * return:
00104  *      1 if `src' is a valid input, else 0.
00105  * notice:
00106  *      does not touch `dst' unless it's returning 1.
00107  * author:
00108  *      Paul Vixie, 1996.
00109  */
00110 static int
00111 inet_pton4(src, dst, pton)
00112         const char *src;
00113         u_char *dst;
00114         int pton;
00115 {
00116         u_int val;
00117         u_int digit;
00118         int base, n;
00119         unsigned char c;
00120         u_int parts[4];
00121         register u_int *pp = parts;
00122 
00123         c = *src;
00124         for (;;) {
00125                 /*
00126                  * Collect number up to ``.''.
00127                  * Values are specified as for C:
00128                  * 0x=hex, 0=octal, isdigit=decimal.
00129                  */
00130                 if (!isdigit(c))
00131                         return (0);
00132                 val = 0; base = 10;
00133                 if (c == '0') {
00134                         c = *++src;
00135                         if (c == 'x' || c == 'X')
00136                                 base = 16, c = *++src;
00137                         else if (isdigit(c) && c != '9')
00138                                 base = 8;
00139                 }
00140                 /* inet_pton() takes decimal only */
00141                 if (pton && base != 10)
00142                         return (0);
00143                 for (;;) {
00144                         if (isdigit(c)) {
00145                                 digit = c - '0';
00146                                 if ((int)digit >= base)
00147                                         break;
00148                                 val = (val * base) + digit;
00149                                 c = *++src;
00150                         } else if (base == 16 && isxdigit(c)) {
00151                                 digit = c + 10 - (islower(c) ? 'a' : 'A');
00152                                 if (digit >= 16)
00153                                         break;
00154                                 val = (val << 4) | digit;
00155                                 c = *++src;
00156                         } else
00157                                 break;
00158                 }
00159                 if (c == '.') {
00160                         /*
00161                          * Internet format:
00162                          *      a.b.c.d
00163                          *      a.b.c   (with c treated as 16 bits)
00164                          *      a.b     (with b treated as 24 bits)
00165                          *      a       (with a treated as 32 bits)
00166                          */
00167                         if (pp >= parts + 3)
00168                                 return (0);
00169                         *pp++ = val;
00170                         c = *++src;
00171                 } else
00172                         break;
00173         }
00174         /*
00175          * Check for trailing characters.
00176          */
00177         if (c != '\0' && !isspace(c))
00178                 return (0);
00179         /*
00180          * Concoct the address according to
00181          * the number of parts specified.
00182          */
00183         n = pp - parts + 1;
00184         /* inet_pton() takes dotted-quad only.  it does not take shorthand. */
00185         if (pton && n != 4)
00186                 return (0);
00187         switch (n) {
00188 
00189         case 0:
00190                 return (0);             /* initial nondigit */
00191 
00192         case 1:                         /* a -- 32 bits */
00193                 break;
00194 
00195         case 2:                         /* a.b -- 8.24 bits */
00196                 if (parts[0] > 0xff || val > 0xffffff)
00197                         return (0);
00198                 val |= parts[0] << 24;
00199                 break;
00200 
00201         case 3:                         /* a.b.c -- 8.8.16 bits */
00202                 if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
00203                         return (0);
00204                 val |= (parts[0] << 24) | (parts[1] << 16);
00205                 break;
00206 
00207         case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
00208                 if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
00209                         return (0);
00210                 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
00211                 break;
00212         }
00213         if (dst) {
00214                 val = htonl(val);
00215                 memcpy(dst, &val, INADDRSZ);
00216         }
00217         return (1);
00218 }
00219 
00220 #ifdef INET6
00221 /* int
00222  * inet_pton6(src, dst)
00223  *      convert presentation level address to network order binary form.
00224  * return:
00225  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
00226  * notice:
00227  *      (1) does not touch `dst' unless it's returning 1.
00228  *      (2) :: in a full address is silently ignored.
00229  * credit:
00230  *      inspired by Mark Andrews.
00231  * author:
00232  *      Paul Vixie, 1996.
00233  */
00234 static int
00235 inet_pton6(src, dst)
00236         const char *src;
00237         u_char *dst;
00238 {
00239         static const char xdigits_l[] = "0123456789abcdef",
00240                           xdigits_u[] = "0123456789ABCDEF";
00241         u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
00242         const char *xdigits, *curtok;
00243         int ch, saw_xdigit;
00244         u_int val;
00245 
00246         memset((tp = tmp), '\0', IN6ADDRSZ);
00247         endp = tp + IN6ADDRSZ;
00248         colonp = NULL;
00249         /* Leading :: requires some special handling. */
00250         if (*src == ':')
00251                 if (*++src != ':')
00252                         return (0);
00253         curtok = src;
00254         saw_xdigit = 0;
00255         val = 0;
00256         while ((ch = *src++) != '\0') {
00257                 const char *pch;
00258 
00259                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
00260                         pch = strchr((xdigits = xdigits_u), ch);
00261                 if (pch != NULL) {
00262                         val <<= 4;
00263                         val |= (pch - xdigits);
00264                         if (val > 0xffff)
00265                                 return (0);
00266                         saw_xdigit = 1;
00267                         continue;
00268                 }
00269                 if (ch == ':') {
00270                         curtok = src;
00271                         if (!saw_xdigit) {
00272                                 if (colonp)
00273                                         return (0);
00274                                 colonp = tp;
00275                                 continue;
00276                         } else if (*src == '\0')
00277                                 return (0);
00278                         if (tp + INT16SZ > endp)
00279                                 return (0);
00280                         *tp++ = (u_char) (val >> 8) & 0xff;
00281                         *tp++ = (u_char) val & 0xff;
00282                         saw_xdigit = 0;
00283                         val = 0;
00284                         continue;
00285                 }
00286                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
00287                     inet_pton4(curtok, tp, 1) > 0) {
00288                         tp += INADDRSZ;
00289                         saw_xdigit = 0;
00290                         break;  /* '\0' was seen by inet_pton4(). */
00291                 }
00292                 return (0);
00293         }
00294         if (saw_xdigit) {
00295                 if (tp + INT16SZ > endp)
00296                         return (0);
00297                 *tp++ = (u_char) (val >> 8) & 0xff;
00298                 *tp++ = (u_char) val & 0xff;
00299         }
00300         if (colonp != NULL) {
00301                 /*
00302                  * Since some memmove()'s erroneously fail to handle
00303                  * overlapping regions, we'll do the shift by hand.
00304                  */
00305                 const int n = tp - colonp;
00306                 int i;
00307 
00308                 if (tp == endp)
00309                         return (0);
00310                 for (i = 1; i <= n; i++) {
00311                         endp[- i] = colonp[n - i];
00312                         colonp[n - i] = 0;
00313                 }
00314                 tp = endp;
00315         }
00316         if (tp != endp)
00317                 return (0);
00318         memcpy(dst, tmp, IN6ADDRSZ);
00319         return (1);
00320 }
00321 #endif
00322 
00323 #endif /* HAVE_INET_PTON */

net-snmpに対してSat Sep 5 13:14:21 2009に生成されました。  doxygen 1.4.7