4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1996,1999 by Internet Software Consortium.
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include "ares_setup.h"
22 #ifdef HAVE_SYS_SOCKET_H
23 # include <sys/socket.h>
25 #ifdef HAVE_NETINET_IN_H
26 # include <netinet/in.h>
28 #ifdef HAVE_ARPA_INET_H
29 # include <arpa/inet.h>
31 #ifdef HAVE_ARPA_NAMESER_H
32 # include <arpa/nameser.h>
36 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
37 # include <arpa/nameser_compat.h>
47 #include "ares_ipv6.h"
48 #include "inet_net_pton.h"
50 #if !defined(HAVE_INET_NET_PTON) || !defined(HAVE_INET_NET_PTON_IPV6)
54 * inet_net_pton_ipv4(src, dst, size)
55 * convert IPv4 network number from presentation to network format.
56 * accepts hex octets, hex strings, decimal octets, and /CIDR.
57 * "size" is in bytes and describes "dst".
59 * number of bits, either imputed classfully or specified with /CIDR,
60 * or -1 if some failure occurred (check errno). ENOENT means it was
61 * not an IPv4 network specification.
63 * network byte order assumed. this means 192.5.5.240/28 has
64 * 0b11110000 in its fourth octet.
66 * On Windows we store the error in the thread errno, not
67 * in the winsock error code. This is to avoid loosing the
68 * actual last winsock error. So use macro ERRNO to fetch the
69 * errno this funtion sets when returning (-1), not SOCKERRNO.
71 * Paul Vixie (ISC), June 1996
74 inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
76 static const char xdigits[] = "0123456789abcdef";
77 static const char digits[] = "0123456789";
78 int n, ch, tmp = 0, dirty, bits;
79 const unsigned char *odst = dst;
82 if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
83 && ISXDIGIT(src[1])) {
84 /* Hexadecimal: Eat nybble string. */
88 src++; /* skip x or X. */
89 while ((ch = *src++) != '\0' && ISXDIGIT(ch)) {
92 n = (int)(strchr(xdigits, ch) - xdigits);
100 *dst++ = (unsigned char) tmp;
104 if (dirty) { /* Odd trailing nybble? */
107 *dst++ = (unsigned char) (tmp << 4);
109 } else if (ISDIGIT(ch)) {
110 /* Decimal: eat dotted digit string. */
114 n = (int)(strchr(digits, ch) - digits);
119 } while ((ch = *src++) != '\0' &&
123 *dst++ = (unsigned char) tmp;
124 if (ch == '\0' || ch == '/')
137 ISDIGIT(src[0]) && dst > odst) {
138 /* CIDR width specifier. Nothing can follow it. */
139 ch = *src++; /* Skip over the /. */
142 n = (int)(strchr(digits, ch) - digits);
145 } while ((ch = *src++) != '\0' && ISDIGIT(ch));
152 /* Firey death and destruction unless we prefetched EOS. */
156 /* If nothing was written to the destination, we found no address. */
159 /* If no CIDR spec was given, infer width from net class. */
161 if (*odst >= 240) /* Class E */
163 else if (*odst >= 224) /* Class D */
165 else if (*odst >= 192) /* Class C */
167 else if (*odst >= 128) /* Class B */
171 /* If imputed mask is narrower than specified octets, widen. */
172 if (bits < ((dst - odst) * 8))
173 bits = (int)(dst - odst) * 8;
175 * If there are no additional bits specified for a class D
176 * address adjust bits to 4.
178 if (bits == 8 && *odst == 224)
181 /* Extend network to cover the actual mask. */
182 while (bits > ((dst - odst) * 8)) {
199 getbits(const char *src, int *bitsp)
201 static const char digits[] = "0123456789";
208 while ((ch = *src++) != '\0') {
211 pch = strchr(digits, ch);
213 if (n++ != 0 && val == 0) /* no leading zeros */
216 val += (pch - digits);
217 if (val > 128) /* range */
230 getv4(const char *src, unsigned char *dst, int *bitsp)
232 static const char digits[] = "0123456789";
233 unsigned char *odst = dst;
240 while ((ch = *src++) != '\0') {
243 pch = strchr(digits, ch);
245 if (n++ != 0 && val == 0) /* no leading zeros */
248 val += (pch - digits);
249 if (val > 255) /* range */
253 if (ch == '.' || ch == '/') {
254 if (dst - odst > 3) /* too many octets? */
256 *dst++ = (unsigned char)val;
258 return (getbits(src, bitsp));
267 if (dst - odst > 3) /* too many octets? */
269 *dst++ = (unsigned char)val;
274 inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
276 static const char xdigits_l[] = "0123456789abcdef",
277 xdigits_u[] = "0123456789ABCDEF";
278 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
279 const char *xdigits, *curtok;
288 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
289 endp = tp + NS_IN6ADDRSZ;
291 /* Leading :: requires some special handling. */
301 while ((ch = *src++) != '\0') {
304 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
305 pch = strchr((xdigits = xdigits_u), ch);
308 val |= (pch - xdigits);
321 } else if (*src == '\0')
323 if (tp + NS_INT16SZ > endp)
325 *tp++ = (unsigned char)((val >> 8) & 0xff);
326 *tp++ = (unsigned char)(val & 0xff);
332 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
333 getv4(curtok, tp, &bits) > 0) {
337 break; /* '\0' was seen by inet_pton4(). */
339 if (ch == '/' && getbits(src, &bits) > 0)
344 if (tp + NS_INT16SZ > endp)
346 *tp++ = (unsigned char)((val >> 8) & 0xff);
347 *tp++ = (unsigned char)(val & 0xff);
352 words = (bits + 15) / 16;
357 endp = tmp + 2 * words;
359 if (colonp != NULL) {
361 * Since some memmove()'s erroneously fail to handle
362 * overlapping regions, we'll do the shift by hand.
364 const int n = (int)(tp - colonp);
369 for (i = 1; i <= n; i++) {
370 endp[- i] = colonp[n - i];
378 bytes = (bits + 7) / 8;
381 memcpy(dst, tmp, bytes);
395 * inet_net_pton(af, src, dst, size)
396 * convert network number from presentation to network format.
397 * accepts hex octets, hex strings, decimal octets, and /CIDR.
398 * "size" is in bytes and describes "dst".
400 * number of bits, either imputed classfully or specified with /CIDR,
401 * or -1 if some failure occurred (check errno). ENOENT means it was
402 * not a valid network specification.
404 * On Windows we store the error in the thread errno, not
405 * in the winsock error code. This is to avoid loosing the
406 * actual last winsock error. So use macro ERRNO to fetch the
407 * errno this funtion sets when returning (-1), not SOCKERRNO.
409 * Paul Vixie (ISC), June 1996
412 ares_inet_net_pton(int af, const char *src, void *dst, size_t size)
416 return (inet_net_pton_ipv4(src, dst, size));
418 return (inet_net_pton_ipv6(src, dst, size));
420 SET_ERRNO(EAFNOSUPPORT);
427 #ifndef HAVE_INET_PTON
428 int ares_inet_pton(int af, const char *src, void *dst)
434 size = sizeof(struct in_addr);
435 else if (af == AF_INET6)
436 size = sizeof(struct ares_in6_addr);
439 SET_ERRNO(EAFNOSUPPORT);
442 result = ares_inet_net_pton(af, src, dst, size);
443 if (result == -1 && ERRNO == ENOENT)
445 return (result > -1 ? 1 : -1);