3 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
4 * Copyright (c) 1996,1999 by Internet Software Consortium.
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include "ares_setup.h"
21 #ifdef HAVE_SYS_SOCKET_H
22 # include <sys/socket.h>
24 #ifdef HAVE_NETINET_IN_H
25 # include <netinet/in.h>
27 #ifdef HAVE_ARPA_INET_H
28 # include <arpa/inet.h>
30 #ifdef HAVE_ARPA_NAMESER_H
31 # include <arpa/nameser.h>
35 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
36 # include <arpa/nameser_compat.h>
45 #include "ares_ipv6.h"
46 #include "ares_nowarn.h"
47 #include "inet_net_pton.h"
50 const struct ares_in6_addr ares_in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
53 #ifndef HAVE_INET_NET_PTON
57 * inet_net_pton_ipv4(src, dst, size)
58 * convert IPv4 network number from presentation to network format.
59 * accepts hex octets, hex strings, decimal octets, and /CIDR.
60 * "size" is in bytes and describes "dst".
62 * number of bits, either imputed classfully or specified with /CIDR,
63 * or -1 if some failure occurred (check errno). ENOENT means it was
64 * not an IPv4 network specification.
66 * network byte order assumed. this means 192.5.5.240/28 has
67 * 0b11110000 in its fourth octet.
69 * On Windows we store the error in the thread errno, not
70 * in the winsock error code. This is to avoid loosing the
71 * actual last winsock error. So use macro ERRNO to fetch the
72 * errno this funtion sets when returning (-1), not SOCKERRNO.
74 * Paul Vixie (ISC), June 1996
77 inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
79 static const char xdigits[] = "0123456789abcdef";
80 static const char digits[] = "0123456789";
81 int n, ch, tmp = 0, dirty, bits;
82 const unsigned char *odst = dst;
85 if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
87 && ISXDIGIT(src[1])) {
88 /* Hexadecimal: Eat nybble string. */
92 src++; /* skip x or X. */
93 while ((ch = *src++) != '\0' && ISASCII(ch) && ISXDIGIT(ch)) {
96 n = aresx_sztosi(strchr(xdigits, ch) - xdigits);
100 tmp = (tmp << 4) | n;
104 *dst++ = (unsigned char) tmp;
108 if (dirty) { /* Odd trailing nybble? */
111 *dst++ = (unsigned char) (tmp << 4);
113 } else if (ISASCII(ch) && ISDIGIT(ch)) {
114 /* Decimal: eat dotted digit string. */
118 n = aresx_sztosi(strchr(digits, ch) - digits);
123 } while ((ch = *src++) != '\0' &&
124 ISASCII(ch) && ISDIGIT(ch));
127 *dst++ = (unsigned char) tmp;
128 if (ch == '\0' || ch == '/')
133 if (!ISASCII(ch) || !ISDIGIT(ch))
140 if (ch == '/' && ISASCII(src[0]) &&
141 ISDIGIT(src[0]) && dst > odst) {
142 /* CIDR width specifier. Nothing can follow it. */
143 ch = *src++; /* Skip over the /. */
146 n = aresx_sztosi(strchr(digits, ch) - digits);
151 } while ((ch = *src++) != '\0' && ISASCII(ch) && ISDIGIT(ch));
156 /* Firey death and destruction unless we prefetched EOS. */
160 /* If nothing was written to the destination, we found no address. */
163 /* If no CIDR spec was given, infer width from net class. */
165 if (*odst >= 240) /* Class E */
167 else if (*odst >= 224) /* Class D */
169 else if (*odst >= 192) /* Class C */
171 else if (*odst >= 128) /* Class B */
175 /* If imputed mask is narrower than specified octets, widen. */
176 if (bits < ((dst - odst) * 8))
177 bits = aresx_sztosi(dst - odst) * 8;
179 * If there are no additional bits specified for a class D
180 * address adjust bits to 4.
182 if (bits == 8 && *odst == 224)
185 /* Extend network to cover the actual mask. */
186 while (bits > ((dst - odst) * 8)) {
203 getbits(const char *src, int *bitsp)
205 static const char digits[] = "0123456789";
212 while ((ch = *src++) != '\0') {
215 pch = strchr(digits, ch);
217 if (n++ != 0 && val == 0) /* no leading zeros */
220 val += aresx_sztosi(pch - digits);
221 if (val > 128) /* range */
234 getv4(const char *src, unsigned char *dst, int *bitsp)
236 static const char digits[] = "0123456789";
237 unsigned char *odst = dst;
244 while ((ch = *src++) != '\0') {
247 pch = strchr(digits, ch);
249 if (n++ != 0 && val == 0) /* no leading zeros */
252 val += aresx_sztoui(pch - digits);
253 if (val > 255) /* range */
257 if (ch == '.' || ch == '/') {
258 if (dst - odst > 3) /* too many octets? */
260 *dst++ = (unsigned char)val;
262 return (getbits(src, bitsp));
271 if (dst - odst > 3) /* too many octets? */
273 *dst = (unsigned char)val;
278 inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
280 static const char xdigits_l[] = "0123456789abcdef",
281 xdigits_u[] = "0123456789ABCDEF";
282 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
283 const char *xdigits, *curtok;
292 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
293 endp = tp + NS_IN6ADDRSZ;
295 /* Leading :: requires some special handling. */
305 while ((ch = *src++) != '\0') {
308 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
309 pch = strchr((xdigits = xdigits_u), ch);
312 val |= aresx_sztoui(pch - xdigits);
325 } else if (*src == '\0')
327 if (tp + NS_INT16SZ > endp)
329 *tp++ = (unsigned char)((val >> 8) & 0xff);
330 *tp++ = (unsigned char)(val & 0xff);
336 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
337 getv4(curtok, tp, &bits) > 0) {
341 break; /* '\0' was seen by inet_pton4(). */
343 if (ch == '/' && getbits(src, &bits) > 0)
348 if (tp + NS_INT16SZ > endp)
350 *tp++ = (unsigned char)((val >> 8) & 0xff);
351 *tp++ = (unsigned char)(val & 0xff);
356 words = (bits + 15) / 16;
361 endp = tmp + 2 * words;
363 if (colonp != NULL) {
365 * Since some memmove()'s erroneously fail to handle
366 * overlapping regions, we'll do the shift by hand.
368 const ssize_t n = tp - colonp;
373 for (i = 1; i <= n; i++) {
374 *(endp - i) = *(colonp + n - i);
375 *(colonp + n - i) = 0;
382 bytes = (bits + 7) / 8;
385 memcpy(dst, tmp, bytes);
399 * inet_net_pton(af, src, dst, size)
400 * convert network number from presentation to network format.
401 * accepts hex octets, hex strings, decimal octets, and /CIDR.
402 * "size" is in bytes and describes "dst".
404 * number of bits, either imputed classfully or specified with /CIDR,
405 * or -1 if some failure occurred (check errno). ENOENT means it was
406 * not a valid network specification.
408 * On Windows we store the error in the thread errno, not
409 * in the winsock error code. This is to avoid loosing the
410 * actual last winsock error. So use macro ERRNO to fetch the
411 * errno this funtion sets when returning (-1), not SOCKERRNO.
413 * Paul Vixie (ISC), June 1996
416 ares_inet_net_pton(int af, const char *src, void *dst, size_t size)
420 return (inet_net_pton_ipv4(src, dst, size));
422 return (inet_net_pton_ipv6(src, dst, size));
424 SET_ERRNO(EAFNOSUPPORT);
429 #endif /* HAVE_INET_NET_PTON */
431 #ifndef HAVE_INET_PTON
432 int ares_inet_pton(int af, const char *src, void *dst)
438 size = sizeof(struct in_addr);
439 else if (af == AF_INET6)
440 size = sizeof(struct ares_in6_addr);
443 SET_ERRNO(EAFNOSUPPORT);
446 result = ares_inet_net_pton(af, src, dst, size);
447 if (result == -1 && ERRNO == ENOENT)
449 return (result > -1 ? 1 : -1);