00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #if defined(LIBC_SCCS) && !defined(lint)
00021 static char rcsid[] =
00022 "$Id: inet_pton.c,v 1.19 2007/06/19 23:47:17 tbox Exp $";
00023 #endif
00024
00025 #include <config.h>
00026
00027 #include <errno.h>
00028 #include <string.h>
00029
00030 #include <isc/net.h>
00031
00032
00033 #define NS_INT16SZ 2
00034
00035 #define NS_INADDRSZ 4
00036
00037 #define NS_IN6ADDRSZ 16
00038
00039
00040
00041
00042
00043
00044 static int inet_pton4(const char *src, unsigned char *dst);
00045 static int inet_pton6(const char *src, unsigned char *dst);
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 int
00058 isc_net_pton(int af, const char *src, void *dst) {
00059 switch (af) {
00060 case AF_INET:
00061 return (inet_pton4(src, dst));
00062 case AF_INET6:
00063 return (inet_pton6(src, dst));
00064 default:
00065 errno = EAFNOSUPPORT;
00066 return (-1);
00067 }
00068
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 static int
00082 inet_pton4(const char *src, unsigned char *dst) {
00083 static const char digits[] = "0123456789";
00084 int saw_digit, octets, ch;
00085 unsigned char tmp[NS_INADDRSZ], *tp;
00086
00087 saw_digit = 0;
00088 octets = 0;
00089 *(tp = tmp) = 0;
00090 while ((ch = *src++) != '\0') {
00091 const char *pch;
00092
00093 if ((pch = strchr(digits, ch)) != NULL) {
00094 unsigned int new = *tp * 10;
00095
00096 new += (int)(pch - digits);
00097 if (saw_digit && *tp == 0)
00098 return (0);
00099 if (new > 255)
00100 return (0);
00101 *tp = new;
00102 if (!saw_digit) {
00103 if (++octets > 4)
00104 return (0);
00105 saw_digit = 1;
00106 }
00107 } else if (ch == '.' && saw_digit) {
00108 if (octets == 4)
00109 return (0);
00110 *++tp = 0;
00111 saw_digit = 0;
00112 } else
00113 return (0);
00114 }
00115 if (octets < 4)
00116 return (0);
00117 memmove(dst, tmp, NS_INADDRSZ);
00118 return (1);
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 static int
00135 inet_pton6(const char *src, unsigned char *dst) {
00136 static const char xdigits_l[] = "0123456789abcdef",
00137 xdigits_u[] = "0123456789ABCDEF";
00138 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
00139 const char *xdigits, *curtok;
00140 int ch, seen_xdigits;
00141 unsigned int val;
00142
00143 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
00144 endp = tp + NS_IN6ADDRSZ;
00145 colonp = NULL;
00146
00147 if (*src == ':')
00148 if (*++src != ':')
00149 return (0);
00150 curtok = src;
00151 seen_xdigits = 0;
00152 val = 0;
00153 while ((ch = *src++) != '\0') {
00154 const char *pch;
00155
00156 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
00157 pch = strchr((xdigits = xdigits_u), ch);
00158 if (pch != NULL) {
00159 val <<= 4;
00160 val |= (pch - xdigits);
00161 if (++seen_xdigits > 4)
00162 return (0);
00163 continue;
00164 }
00165 if (ch == ':') {
00166 curtok = src;
00167 if (!seen_xdigits) {
00168 if (colonp)
00169 return (0);
00170 colonp = tp;
00171 continue;
00172 }
00173 if (tp + NS_INT16SZ > endp)
00174 return (0);
00175 *tp++ = (unsigned char) (val >> 8) & 0xff;
00176 *tp++ = (unsigned char) val & 0xff;
00177 seen_xdigits = 0;
00178 val = 0;
00179 continue;
00180 }
00181 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
00182 inet_pton4(curtok, tp) > 0) {
00183 tp += NS_INADDRSZ;
00184 seen_xdigits = 0;
00185 break;
00186 }
00187 return (0);
00188 }
00189 if (seen_xdigits) {
00190 if (tp + NS_INT16SZ > endp)
00191 return (0);
00192 *tp++ = (unsigned char) (val >> 8) & 0xff;
00193 *tp++ = (unsigned char) val & 0xff;
00194 }
00195 if (colonp != NULL) {
00196
00197
00198
00199
00200 const int n = (int)(tp - colonp);
00201 int i;
00202
00203 if (tp == endp)
00204 return (0);
00205 for (i = 1; i <= n; i++) {
00206 endp[- i] = colonp[n - i];
00207 colonp[n - i] = 0;
00208 }
00209 tp = endp;
00210 }
00211 if (tp != endp)
00212 return (0);
00213 memmove(dst, tmp, NS_IN6ADDRSZ);
00214 return (1);
00215 }