00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "setup.h"
00020
00021 #ifndef HAVE_INET_PTON
00022
00023 #ifdef HAVE_SYS_PARAM_H
00024 #include <sys/param.h>
00025 #endif
00026 #ifdef HAVE_SYS_SOCKET_H
00027 #include <sys/socket.h>
00028 #endif
00029 #ifdef HAVE_NETINET_IN_H
00030 #include <netinet/in.h>
00031 #endif
00032 #ifdef HAVE_ARPA_INET_H
00033 #include <arpa/inet.h>
00034 #endif
00035 #include <string.h>
00036 #include <errno.h>
00037
00038 #include "inet_pton.h"
00039
00040 #define IN6ADDRSZ 16
00041 #define INADDRSZ 4
00042 #define INT16SZ 2
00043
00044
00045
00046
00047
00048
00049 static int inet_pton4(const char *src, unsigned char *dst);
00050 #ifdef ENABLE_IPV6
00051 static int inet_pton6(const char *src, unsigned char *dst);
00052 #endif
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 int
00071 Curl_inet_pton(int af, const char *src, void *dst)
00072 {
00073 switch (af) {
00074 case AF_INET:
00075 return (inet_pton4(src, (unsigned char *)dst));
00076 #ifdef ENABLE_IPV6
00077 #ifndef AF_INET6
00078 #define AF_INET6 (AF_MAX+1)
00079 #endif
00080 case AF_INET6:
00081 return (inet_pton6(src, (unsigned char *)dst));
00082 #endif
00083 default:
00084 SET_ERRNO(EAFNOSUPPORT);
00085 return (-1);
00086 }
00087
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 static int
00101 inet_pton4(const char *src, unsigned char *dst)
00102 {
00103 static const char digits[] = "0123456789";
00104 int saw_digit, octets, ch;
00105 unsigned char tmp[INADDRSZ], *tp;
00106
00107 saw_digit = 0;
00108 octets = 0;
00109 tp = tmp;
00110 *tp = 0;
00111 while ((ch = *src++) != '\0') {
00112 const char *pch;
00113
00114 if ((pch = strchr(digits, ch)) != NULL) {
00115 unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
00116
00117 if (val > 255)
00118 return (0);
00119 *tp = (unsigned char)val;
00120 if (! saw_digit) {
00121 if (++octets > 4)
00122 return (0);
00123 saw_digit = 1;
00124 }
00125 } else if (ch == '.' && saw_digit) {
00126 if (octets == 4)
00127 return (0);
00128 *++tp = 0;
00129 saw_digit = 0;
00130 } else
00131 return (0);
00132 }
00133 if (octets < 4)
00134 return (0);
00135
00136 memcpy(dst, tmp, INADDRSZ);
00137 return (1);
00138 }
00139
00140 #ifdef ENABLE_IPV6
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static int
00155 inet_pton6(const char *src, unsigned char *dst)
00156 {
00157 static const char xdigits_l[] = "0123456789abcdef",
00158 xdigits_u[] = "0123456789ABCDEF";
00159 unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
00160 const char *xdigits, *curtok;
00161 int ch, saw_xdigit;
00162 unsigned int val;
00163
00164 memset((tp = tmp), 0, IN6ADDRSZ);
00165 endp = tp + IN6ADDRSZ;
00166 colonp = NULL;
00167
00168 if (*src == ':')
00169 if (*++src != ':')
00170 return (0);
00171 curtok = src;
00172 saw_xdigit = 0;
00173 val = 0;
00174 while ((ch = *src++) != '\0') {
00175 const char *pch;
00176
00177 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
00178 pch = strchr((xdigits = xdigits_u), ch);
00179 if (pch != NULL) {
00180 val <<= 4;
00181 val |= (pch - xdigits);
00182 if (val > 0xffff)
00183 return (0);
00184 saw_xdigit = 1;
00185 continue;
00186 }
00187 if (ch == ':') {
00188 curtok = src;
00189 if (!saw_xdigit) {
00190 if (colonp)
00191 return (0);
00192 colonp = tp;
00193 continue;
00194 }
00195 if (tp + INT16SZ > endp)
00196 return (0);
00197 *tp++ = (unsigned char) (val >> 8) & 0xff;
00198 *tp++ = (unsigned char) val & 0xff;
00199 saw_xdigit = 0;
00200 val = 0;
00201 continue;
00202 }
00203 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
00204 inet_pton4(curtok, tp) > 0) {
00205 tp += INADDRSZ;
00206 saw_xdigit = 0;
00207 break;
00208 }
00209 return (0);
00210 }
00211 if (saw_xdigit) {
00212 if (tp + INT16SZ > endp)
00213 return (0);
00214 *tp++ = (unsigned char) (val >> 8) & 0xff;
00215 *tp++ = (unsigned char) val & 0xff;
00216 }
00217 if (colonp != NULL) {
00218
00219
00220
00221
00222 const int n = tp - colonp;
00223 int i;
00224
00225 for (i = 1; i <= n; i++) {
00226 endp[- i] = colonp[n - i];
00227 colonp[n - i] = 0;
00228 }
00229 tp = endp;
00230 }
00231 if (tp != endp)
00232 return (0);
00233
00234 memcpy(dst, tmp, IN6ADDRSZ);
00235 return (1);
00236 }
00237 #endif
00238
00239 #endif