inet_net_pton.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
4  * Copyright (c) 1996,1999 by Internet Software Consortium.
5  *
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.
9  *
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.
17  */
18 
19 #include "ares_setup.h"
20 
21 #ifdef HAVE_NETINET_IN_H
22 # include <netinet/in.h>
23 #endif
24 #ifdef HAVE_ARPA_INET_H
25 # include <arpa/inet.h>
26 #endif
27 
28 #include "ares_nameser.h"
29 
30 #include "ares.h"
31 #include "ares_ipv6.h"
32 #include "ares_nowarn.h"
33 #include "ares_inet_net_pton.h"
34 
35 
36 const struct ares_in6_addr ares_in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
37 
38 
39 #ifndef HAVE_INET_NET_PTON
40 
41 /*
42  * static int
43  * inet_net_pton_ipv4(src, dst, size)
44  * convert IPv4 network number from presentation to network format.
45  * accepts hex octets, hex strings, decimal octets, and /CIDR.
46  * "size" is in bytes and describes "dst".
47  * return:
48  * number of bits, either imputed classfully or specified with /CIDR,
49  * or -1 if some failure occurred (check errno). ENOENT means it was
50  * not an IPv4 network specification.
51  * note:
52  * network byte order assumed. this means 192.5.5.240/28 has
53  * 0b11110000 in its fourth octet.
54  * note:
55  * On Windows we store the error in the thread errno, not
56  * in the winsock error code. This is to avoid loosing the
57  * actual last winsock error. So use macro ERRNO to fetch the
58  * errno this funtion sets when returning (-1), not SOCKERRNO.
59  * author:
60  * Paul Vixie (ISC), June 1996
61  */
62 static int
63 inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
64 {
65  static const char xdigits[] = "0123456789abcdef";
66  static const char digits[] = "0123456789";
67  int n, ch, tmp = 0, dirty, bits;
68  const unsigned char *odst = dst;
69 
70  ch = *src++;
71  if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
72  && ISASCII(src[1])
73  && ISXDIGIT(src[1])) {
74  /* Hexadecimal: Eat nybble string. */
75  if (!size)
76  goto emsgsize;
77  dirty = 0;
78  src++; /* skip x or X. */
79  while ((ch = *src++) != '\0' && ISASCII(ch) && ISXDIGIT(ch)) {
80  if (ISUPPER(ch))
81  ch = tolower(ch);
82  n = aresx_sztosi(strchr(xdigits, ch) - xdigits);
83  if (dirty == 0)
84  tmp = n;
85  else
86  tmp = (tmp << 4) | n;
87  if (++dirty == 2) {
88  if (!size--)
89  goto emsgsize;
90  *dst++ = (unsigned char) tmp;
91  dirty = 0;
92  }
93  }
94  if (dirty) { /* Odd trailing nybble? */
95  if (!size--)
96  goto emsgsize;
97  *dst++ = (unsigned char) (tmp << 4);
98  }
99  } else if (ISASCII(ch) && ISDIGIT(ch)) {
100  /* Decimal: eat dotted digit string. */
101  for (;;) {
102  tmp = 0;
103  do {
104  n = aresx_sztosi(strchr(digits, ch) - digits);
105  tmp *= 10;
106  tmp += n;
107  if (tmp > 255)
108  goto enoent;
109  } while ((ch = *src++) != '\0' &&
110  ISASCII(ch) && ISDIGIT(ch));
111  if (!size--)
112  goto emsgsize;
113  *dst++ = (unsigned char) tmp;
114  if (ch == '\0' || ch == '/')
115  break;
116  if (ch != '.')
117  goto enoent;
118  ch = *src++;
119  if (!ISASCII(ch) || !ISDIGIT(ch))
120  goto enoent;
121  }
122  } else
123  goto enoent;
124 
125  bits = -1;
126  if (ch == '/' && ISASCII(src[0]) &&
127  ISDIGIT(src[0]) && dst > odst) {
128  /* CIDR width specifier. Nothing can follow it. */
129  ch = *src++; /* Skip over the /. */
130  bits = 0;
131  do {
132  n = aresx_sztosi(strchr(digits, ch) - digits);
133  bits *= 10;
134  bits += n;
135  if (bits > 32)
136  goto enoent;
137  } while ((ch = *src++) != '\0' && ISASCII(ch) && ISDIGIT(ch));
138  if (ch != '\0')
139  goto enoent;
140  }
141 
142  /* Firey death and destruction unless we prefetched EOS. */
143  if (ch != '\0')
144  goto enoent;
145 
146  /* If nothing was written to the destination, we found no address. */
147  if (dst == odst)
148  goto enoent; /* LCOV_EXCL_LINE: all valid paths above increment dst */
149  /* If no CIDR spec was given, infer width from net class. */
150  if (bits == -1) {
151  if (*odst >= 240) /* Class E */
152  bits = 32;
153  else if (*odst >= 224) /* Class D */
154  bits = 8;
155  else if (*odst >= 192) /* Class C */
156  bits = 24;
157  else if (*odst >= 128) /* Class B */
158  bits = 16;
159  else /* Class A */
160  bits = 8;
161  /* If imputed mask is narrower than specified octets, widen. */
162  if (bits < ((dst - odst) * 8))
163  bits = aresx_sztosi(dst - odst) * 8;
164  /*
165  * If there are no additional bits specified for a class D
166  * address adjust bits to 4.
167  */
168  if (bits == 8 && *odst == 224)
169  bits = 4;
170  }
171  /* Extend network to cover the actual mask. */
172  while (bits > ((dst - odst) * 8)) {
173  if (!size--)
174  goto emsgsize;
175  *dst++ = '\0';
176  }
177  return (bits);
178 
179  enoent:
180  SET_ERRNO(ENOENT);
181  return (-1);
182 
183  emsgsize:
184  SET_ERRNO(EMSGSIZE);
185  return (-1);
186 }
187 
188 static int
189 getbits(const char *src, int *bitsp)
190 {
191  static const char digits[] = "0123456789";
192  int n;
193  int val;
194  char ch;
195 
196  val = 0;
197  n = 0;
198  while ((ch = *src++) != '\0') {
199  const char *pch;
200 
201  pch = strchr(digits, ch);
202  if (pch != NULL) {
203  if (n++ != 0 && val == 0) /* no leading zeros */
204  return (0);
205  val *= 10;
206  val += aresx_sztosi(pch - digits);
207  if (val > 128) /* range */
208  return (0);
209  continue;
210  }
211  return (0);
212  }
213  if (n == 0)
214  return (0);
215  *bitsp = val;
216  return (1);
217 }
218 
219 static int
220 getv4(const char *src, unsigned char *dst, int *bitsp)
221 {
222  static const char digits[] = "0123456789";
223  unsigned char *odst = dst;
224  int n;
225  unsigned int val;
226  char ch;
227 
228  val = 0;
229  n = 0;
230  while ((ch = *src++) != '\0') {
231  const char *pch;
232 
233  pch = strchr(digits, ch);
234  if (pch != NULL) {
235  if (n++ != 0 && val == 0) /* no leading zeros */
236  return (0);
237  val *= 10;
238  val += aresx_sztoui(pch - digits);
239  if (val > 255) /* range */
240  return (0);
241  continue;
242  }
243  if (ch == '.' || ch == '/') {
244  if (dst - odst > 3) /* too many octets? */
245  return (0);
246  *dst++ = (unsigned char)val;
247  if (ch == '/')
248  return (getbits(src, bitsp));
249  val = 0;
250  n = 0;
251  continue;
252  }
253  return (0);
254  }
255  if (n == 0)
256  return (0);
257  if (dst - odst > 3) /* too many octets? */
258  return (0);
259  *dst = (unsigned char)val;
260  return 1;
261 }
262 
263 static int
264 inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
265 {
266  static const char xdigits_l[] = "0123456789abcdef",
267  xdigits_u[] = "0123456789ABCDEF";
268  unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
269  const char *xdigits, *curtok;
270  int ch, saw_xdigit;
271  unsigned int val;
272  int digits;
273  int bits;
274  size_t bytes;
275  int words;
276  int ipv4;
277 
278  memset((tp = tmp), '\0', NS_IN6ADDRSZ);
279  endp = tp + NS_IN6ADDRSZ;
280  colonp = NULL;
281  /* Leading :: requires some special handling. */
282  if (*src == ':')
283  if (*++src != ':')
284  goto enoent;
285  curtok = src;
286  saw_xdigit = 0;
287  val = 0;
288  digits = 0;
289  bits = -1;
290  ipv4 = 0;
291  while ((ch = *src++) != '\0') {
292  const char *pch;
293 
294  if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
295  pch = strchr((xdigits = xdigits_u), ch);
296  if (pch != NULL) {
297  val <<= 4;
298  val |= aresx_sztoui(pch - xdigits);
299  if (++digits > 4)
300  goto enoent;
301  saw_xdigit = 1;
302  continue;
303  }
304  if (ch == ':') {
305  curtok = src;
306  if (!saw_xdigit) {
307  if (colonp)
308  goto enoent;
309  colonp = tp;
310  continue;
311  } else if (*src == '\0')
312  goto enoent;
313  if (tp + NS_INT16SZ > endp)
314  return (0);
315  *tp++ = (unsigned char)((val >> 8) & 0xff);
316  *tp++ = (unsigned char)(val & 0xff);
317  saw_xdigit = 0;
318  digits = 0;
319  val = 0;
320  continue;
321  }
322  if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
323  getv4(curtok, tp, &bits) > 0) {
324  tp += NS_INADDRSZ;
325  saw_xdigit = 0;
326  ipv4 = 1;
327  break; /* '\0' was seen by inet_pton4(). */
328  }
329  if (ch == '/' && getbits(src, &bits) > 0)
330  break;
331  goto enoent;
332  }
333  if (saw_xdigit) {
334  if (tp + NS_INT16SZ > endp)
335  goto enoent;
336  *tp++ = (unsigned char)((val >> 8) & 0xff);
337  *tp++ = (unsigned char)(val & 0xff);
338  }
339  if (bits == -1)
340  bits = 128;
341 
342  words = (bits + 15) / 16;
343  if (words < 2)
344  words = 2;
345  if (ipv4)
346  words = 8;
347  endp = tmp + 2 * words;
348 
349  if (colonp != NULL) {
350  /*
351  * Since some memmove()'s erroneously fail to handle
352  * overlapping regions, we'll do the shift by hand.
353  */
354  const ares_ssize_t n = tp - colonp;
355  ares_ssize_t i;
356 
357  if (tp == endp)
358  goto enoent;
359  for (i = 1; i <= n; i++) {
360  *(endp - i) = *(colonp + n - i);
361  *(colonp + n - i) = 0;
362  }
363  tp = endp;
364  }
365  if (tp != endp)
366  goto enoent;
367 
368  bytes = (bits + 7) / 8;
369  if (bytes > size)
370  goto emsgsize;
371  memcpy(dst, tmp, bytes);
372  return (bits);
373 
374  enoent:
375  SET_ERRNO(ENOENT);
376  return (-1);
377 
378  emsgsize:
379  SET_ERRNO(EMSGSIZE);
380  return (-1);
381 }
382 
383 /*
384  * int
385  * inet_net_pton(af, src, dst, size)
386  * convert network number from presentation to network format.
387  * accepts hex octets, hex strings, decimal octets, and /CIDR.
388  * "size" is in bytes and describes "dst".
389  * return:
390  * number of bits, either imputed classfully or specified with /CIDR,
391  * or -1 if some failure occurred (check errno). ENOENT means it was
392  * not a valid network specification.
393  * note:
394  * On Windows we store the error in the thread errno, not
395  * in the winsock error code. This is to avoid loosing the
396  * actual last winsock error. So use macro ERRNO to fetch the
397  * errno this funtion sets when returning (-1), not SOCKERRNO.
398  * author:
399  * Paul Vixie (ISC), June 1996
400  */
401 int
402 ares_inet_net_pton(int af, const char *src, void *dst, size_t size)
403 {
404  switch (af) {
405  case AF_INET:
406  return (inet_net_pton_ipv4(src, dst, size));
407  case AF_INET6:
408  return (inet_net_pton_ipv6(src, dst, size));
409  default:
410  SET_ERRNO(EAFNOSUPPORT);
411  return (-1);
412  }
413 }
414 
415 #endif /* HAVE_INET_NET_PTON */
416 
417 #ifndef HAVE_INET_PTON
418 int ares_inet_pton(int af, const char *src, void *dst)
419 {
420  int result;
421  size_t size;
422 
423  if (af == AF_INET)
424  size = sizeof(struct in_addr);
425  else if (af == AF_INET6)
426  size = sizeof(struct ares_in6_addr);
427  else
428  {
429  SET_ERRNO(EAFNOSUPPORT);
430  return -1;
431  }
432  result = ares_inet_net_pton(af, src, dst, size);
433  if (result == -1 && ERRNO == ENOENT)
434  return 0;
435  return (result > -1 ? 1 : -1);
436 }
437 #else /* HAVE_INET_PTON */
438 int ares_inet_pton(int af, const char *src, void *dst)
439 {
440  /* just relay this to the underlying function */
441  return inet_pton(af, src, dst);
442 }
443 
444 #endif
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
ISXDIGIT
#define ISXDIGIT(x)
Definition: setup_once.h:278
dst
static const char dst[]
Definition: test-fs-copyfile.c:37
AF_INET6
#define AF_INET6
Definition: ares_setup.h:208
memset
return memset(p, 0, total)
ares.h
ISDIGIT
#define ISDIGIT(x)
Definition: setup_once.h:276
ares_inet_net_pton.h
inet_net_pton_ipv4
static int inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
Definition: inet_net_pton.c:63
words
std::vector< std::string > words
Definition: bloaty/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc:1787
ares_in6addr_any
const struct ares_in6_addr ares_in6addr_any
Definition: inet_net_pton.c:36
getv4
static int getv4(const char *src, unsigned char *dst, int *bitsp)
Definition: inet_net_pton.c:220
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
getbits
static int getbits(const char *src, int *bitsp)
Definition: inet_net_pton.c:189
ISASCII
#define ISASCII(x)
Definition: setup_once.h:284
ISUPPER
#define ISUPPER(x)
Definition: setup_once.h:282
bits
OPENSSL_EXPORT ASN1_BIT_STRING * bits
Definition: x509v3.h:482
ERRNO
#define ERRNO
Definition: fake_udp_and_tcp_server.cc:40
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
ares_setup.h
NS_INADDRSZ
#define NS_INADDRSZ
Definition: ares_ipv6.h:66
ares_inet_net_pton
int ares_inet_net_pton(int af, const char *src, void *dst, size_t size)
Definition: inet_net_pton.c:402
ares_ipv6.h
bytes
uint8 bytes[10]
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc:153
NS_IN6ADDRSZ
#define NS_IN6ADDRSZ
Definition: ares_ipv6.h:59
ares_in6_addr
Definition: ares.h:514
aresx_sztosi
int aresx_sztosi(ares_ssize_t sznum)
Definition: ares_nowarn.c:157
inet_net_pton_ipv6
static int inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
Definition: inet_net_pton.c:264
ares_inet_pton
int ares_inet_pton(int af, const char *src, void *dst)
Definition: inet_net_pton.c:418
SET_ERRNO
#define SET_ERRNO(x)
Definition: setup_once.h:441
ch
char ch
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3621
autogen_x86imm.tmp
tmp
Definition: autogen_x86imm.py:12
ares_nameser.h
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
ares_ssize_t
CARES_TYPEOF_ARES_SSIZE_T ares_ssize_t
Definition: ares_build.h:210
ares_nowarn.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
aresx_sztoui
unsigned int aresx_sztoui(ares_ssize_t sznum)
Definition: ares_nowarn.c:176
NS_INT16SZ
#define NS_INT16SZ
Definition: ares_ipv6.h:70


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:02