inet_net_pton.c 11 KB

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