inet_pton.c

説明を見る。
00001 /*
00002  * Copyright (C) 1996-2001  Internet Software Consortium.
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
00009  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
00010  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
00011  * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
00013  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
00014  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
00015  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 #include "rsync.h"
00019 
00020 #define NS_INT16SZ       2
00021 #define NS_INADDRSZ      4
00022 #define NS_IN6ADDRSZ    16
00023 
00024 /*
00025  * WARNING: Don't even consider trying to compile this on a system where
00026  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
00027  */
00028 
00029 static int inet_pton4(const char *src, unsigned char *dst);
00030 #ifdef INET6
00031 static int inet_pton6(const char *src, unsigned char *dst);
00032 #endif
00033 
00034 /* int
00035  * inet_pton(af, src, dst)
00036  *      convert from presentation format (which usually means ASCII printable)
00037  *      to network format (which is usually some kind of binary format).
00038  * return:
00039  *      1 if the address was valid for the specified address family
00040  *      0 if the address wasn't valid (`dst' is untouched in this case)
00041  *      -1 if some other error occurred (`dst' is untouched in this case, too)
00042  * author:
00043  *      Paul Vixie, 1996.
00044  */
00045 int
00046 inet_pton(int af,
00047           const char *src,
00048           void *dst)
00049 {
00050         switch (af) {
00051         case AF_INET:
00052                 return (inet_pton4(src, dst));
00053 #ifdef INET6
00054         case AF_INET6:
00055                 return (inet_pton6(src, dst));
00056 #endif
00057         default:
00058                 errno = EAFNOSUPPORT;
00059                 return (-1);
00060         }
00061         /* NOTREACHED */
00062 }
00063 
00064 /* int
00065  * inet_pton4(src, dst)
00066  *      like inet_aton() but without all the hexadecimal and shorthand.
00067  * return:
00068  *      1 if `src' is a valid dotted quad, else 0.
00069  * notice:
00070  *      does not touch `dst' unless it's returning 1.
00071  * author:
00072  *      Paul Vixie, 1996.
00073  */
00074 static int
00075 inet_pton4(src, dst)
00076         const char *src;
00077         unsigned char *dst;
00078 {
00079         static const char digits[] = "0123456789";
00080         int saw_digit, octets, ch;
00081         unsigned char tmp[NS_INADDRSZ], *tp;
00082 
00083         saw_digit = 0;
00084         octets = 0;
00085         *(tp = tmp) = 0;
00086         while ((ch = *src++) != '\0') {
00087                 const char *pch;
00088 
00089                 if ((pch = strchr(digits, ch)) != NULL) {
00090                         unsigned int new = *tp * 10 + (pch - digits);
00091 
00092                         if (new > 255)
00093                                 return (0);
00094                         *tp = new;
00095                         if (! saw_digit) {
00096                                 if (++octets > 4)
00097                                         return (0);
00098                                 saw_digit = 1;
00099                         }
00100                 } else if (ch == '.' && saw_digit) {
00101                         if (octets == 4)
00102                                 return (0);
00103                         *++tp = 0;
00104                         saw_digit = 0;
00105                 } else
00106                         return (0);
00107         }
00108         if (octets < 4)
00109                 return (0);
00110         memcpy(dst, tmp, NS_INADDRSZ);
00111         return (1);
00112 }
00113 
00114 /* int
00115  * inet_pton6(src, dst)
00116  *      convert presentation level address to network order binary form.
00117  * return:
00118  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
00119  * notice:
00120  *      (1) does not touch `dst' unless it's returning 1.
00121  *      (2) :: in a full address is silently ignored.
00122  * credit:
00123  *      inspired by Mark Andrews.
00124  * author:
00125  *      Paul Vixie, 1996.
00126  */
00127 #ifdef INET6
00128 static int
00129 inet_pton6(src, dst)
00130         const char *src;
00131         unsigned char *dst;
00132 {
00133         static const char xdigits_l[] = "0123456789abcdef",
00134                           xdigits_u[] = "0123456789ABCDEF";
00135         unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
00136         const char *xdigits, *curtok;
00137         int ch, saw_xdigit;
00138         unsigned int val;
00139 
00140         memset((tp = tmp), '\0', NS_IN6ADDRSZ);
00141         endp = tp + NS_IN6ADDRSZ;
00142         colonp = NULL;
00143         /* Leading :: requires some special handling. */
00144         if (*src == ':')
00145                 if (*++src != ':')
00146                         return (0);
00147         curtok = src;
00148         saw_xdigit = 0;
00149         val = 0;
00150         while ((ch = *src++) != '\0') {
00151                 const char *pch;
00152 
00153                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
00154                         pch = strchr((xdigits = xdigits_u), ch);
00155                 if (pch != NULL) {
00156                         val <<= 4;
00157                         val |= (pch - xdigits);
00158                         if (val > 0xffff)
00159                                 return (0);
00160                         saw_xdigit = 1;
00161                         continue;
00162                 }
00163                 if (ch == ':') {
00164                         curtok = src;
00165                         if (!saw_xdigit) {
00166                                 if (colonp)
00167                                         return (0);
00168                                 colonp = tp;
00169                                 continue;
00170                         }
00171                         if (tp + NS_INT16SZ > endp)
00172                                 return (0);
00173                         *tp++ = (unsigned char) (val >> 8) & 0xff;
00174                         *tp++ = (unsigned char) val & 0xff;
00175                         saw_xdigit = 0;
00176                         val = 0;
00177                         continue;
00178                 }
00179                 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
00180                     inet_pton4(curtok, tp) > 0) {
00181                         tp += NS_INADDRSZ;
00182                         saw_xdigit = 0;
00183                         break;  /* '\0' was seen by inet_pton4(). */
00184                 }
00185                 return (0);
00186         }
00187         if (saw_xdigit) {
00188                 if (tp + NS_INT16SZ > endp)
00189                         return (0);
00190                 *tp++ = (unsigned char) (val >> 8) & 0xff;
00191                 *tp++ = (unsigned char) val & 0xff;
00192         }
00193         if (colonp != NULL) {
00194                 /*
00195                  * Since some memmove()'s erroneously fail to handle
00196                  * overlapping regions, we'll do the shift by hand.
00197                  */
00198                 const int n = tp - colonp;
00199                 int i;
00200 
00201                 for (i = 1; i <= n; i++) {
00202                         endp[- i] = colonp[n - i];
00203                         colonp[n - i] = 0;
00204                 }
00205                 tp = endp;
00206         }
00207         if (tp != endp)
00208                 return (0);
00209         memcpy(dst, tmp, NS_IN6ADDRSZ);
00210         return (1);
00211 }
00212 #endif

rsyncに対してSat Dec 5 19:45:41 2009に生成されました。  doxygen 1.4.7