inet_pton.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /* inet_pton.c -- convert IPv4 and IPv6 addresses from text to binary form
  2. Copyright (C) 2006, 2008-2022 Free Software Foundation, Inc.
  3. This file is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation; either version 2.1 of the
  6. License, or (at your option) any later version.
  7. This file is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. /*
  14. * Copyright (c) 1996,1999 by Internet Software Consortium.
  15. *
  16. * Permission to use, copy, modify, and distribute this software for any
  17. * purpose with or without fee is hereby granted, provided that the above
  18. * copyright notice and this permission notice appear in all copies.
  19. *
  20. * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
  21. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
  22. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
  23. * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  24. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  25. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  26. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  27. * SOFTWARE.
  28. */
  29. #include <config.h>
  30. /* Specification. */
  31. #include <arpa/inet.h>
  32. #if HAVE_DECL_INET_PTON
  33. # undef inet_pton
  34. int
  35. rpl_inet_pton (int af, const char *restrict src, void *restrict dst)
  36. {
  37. return inet_pton (af, src, dst);
  38. }
  39. #else
  40. # include <c-ctype.h>
  41. # include <string.h>
  42. # include <errno.h>
  43. # define NS_INADDRSZ 4
  44. # define NS_IN6ADDRSZ 16
  45. # define NS_INT16SZ 2
  46. /*
  47. * WARNING: Don't even consider trying to compile this on a system where
  48. * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
  49. */
  50. static int inet_pton4 (const char *src, unsigned char *dst);
  51. # if HAVE_IPV6
  52. static int inet_pton6 (const char *src, unsigned char *dst);
  53. # endif
  54. /* int
  55. * inet_pton(af, src, dst)
  56. * convert from presentation format (which usually means ASCII printable)
  57. * to network format (which is usually some kind of binary format).
  58. * return:
  59. * 1 if the address was valid for the specified address family
  60. * 0 if the address wasn't valid ('dst' is untouched in this case)
  61. * -1 if some other error occurred ('dst' is untouched in this case, too)
  62. * author:
  63. * Paul Vixie, 1996.
  64. */
  65. int
  66. inet_pton (int af, const char *restrict src, void *restrict dst)
  67. {
  68. switch (af)
  69. {
  70. case AF_INET:
  71. return (inet_pton4 (src, dst));
  72. # if HAVE_IPV6
  73. case AF_INET6:
  74. return (inet_pton6 (src, dst));
  75. # endif
  76. default:
  77. errno = EAFNOSUPPORT;
  78. return (-1);
  79. }
  80. /* NOTREACHED */
  81. }
  82. /* int
  83. * inet_pton4(src, dst)
  84. * like inet_aton() but without all the hexadecimal, octal (with the
  85. * exception of 0) and shorthand.
  86. * return:
  87. * 1 if 'src' is a valid dotted quad, else 0.
  88. * notice:
  89. * does not touch 'dst' unless it's returning 1.
  90. * author:
  91. * Paul Vixie, 1996.
  92. */
  93. static int
  94. inet_pton4 (const char *restrict src, unsigned char *restrict dst)
  95. {
  96. int saw_digit, octets, ch;
  97. unsigned char tmp[NS_INADDRSZ], *tp;
  98. saw_digit = 0;
  99. octets = 0;
  100. *(tp = tmp) = 0;
  101. while ((ch = *src++) != '\0')
  102. {
  103. if (ch >= '0' && ch <= '9')
  104. {
  105. unsigned new = *tp * 10 + (ch - '0');
  106. if (saw_digit && *tp == 0)
  107. return (0);
  108. if (new > 255)
  109. return (0);
  110. *tp = new;
  111. if (!saw_digit)
  112. {
  113. if (++octets > 4)
  114. return (0);
  115. saw_digit = 1;
  116. }
  117. }
  118. else if (ch == '.' && saw_digit)
  119. {
  120. if (octets == 4)
  121. return (0);
  122. *++tp = 0;
  123. saw_digit = 0;
  124. }
  125. else
  126. return (0);
  127. }
  128. if (octets < 4)
  129. return (0);
  130. memcpy (dst, tmp, NS_INADDRSZ);
  131. return (1);
  132. }
  133. # if HAVE_IPV6
  134. /* int
  135. * inet_pton6(src, dst)
  136. * convert presentation level address to network order binary form.
  137. * return:
  138. * 1 if 'src' is a valid [RFC1884 2.2] address, else 0.
  139. * notice:
  140. * (1) does not touch 'dst' unless it's returning 1.
  141. * (2) :: in a full address is silently ignored.
  142. * credit:
  143. * inspired by Mark Andrews.
  144. * author:
  145. * Paul Vixie, 1996.
  146. */
  147. static int
  148. inet_pton6 (const char *restrict src, unsigned char *restrict dst)
  149. {
  150. static const char xdigits[] = "0123456789abcdef";
  151. unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
  152. const char *curtok;
  153. int ch, saw_xdigit;
  154. unsigned val;
  155. tp = memset (tmp, '\0', NS_IN6ADDRSZ);
  156. endp = tp + NS_IN6ADDRSZ;
  157. colonp = NULL;
  158. /* Leading :: requires some special handling. */
  159. if (*src == ':')
  160. if (*++src != ':')
  161. return (0);
  162. curtok = src;
  163. saw_xdigit = 0;
  164. val = 0;
  165. while ((ch = c_tolower (*src++)) != '\0')
  166. {
  167. const char *pch;
  168. pch = strchr (xdigits, ch);
  169. if (pch != NULL)
  170. {
  171. val <<= 4;
  172. val |= (pch - xdigits);
  173. if (val > 0xffff)
  174. return (0);
  175. saw_xdigit = 1;
  176. continue;
  177. }
  178. if (ch == ':')
  179. {
  180. curtok = src;
  181. if (!saw_xdigit)
  182. {
  183. if (colonp)
  184. return (0);
  185. colonp = tp;
  186. continue;
  187. }
  188. else if (*src == '\0')
  189. {
  190. return (0);
  191. }
  192. if (tp + NS_INT16SZ > endp)
  193. return (0);
  194. *tp++ = (u_char) (val >> 8) & 0xff;
  195. *tp++ = (u_char) val & 0xff;
  196. saw_xdigit = 0;
  197. val = 0;
  198. continue;
  199. }
  200. if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
  201. inet_pton4 (curtok, tp) > 0)
  202. {
  203. tp += NS_INADDRSZ;
  204. saw_xdigit = 0;
  205. break; /* '\0' was seen by inet_pton4(). */
  206. }
  207. return (0);
  208. }
  209. if (saw_xdigit)
  210. {
  211. if (tp + NS_INT16SZ > endp)
  212. return (0);
  213. *tp++ = (u_char) (val >> 8) & 0xff;
  214. *tp++ = (u_char) val & 0xff;
  215. }
  216. if (colonp != NULL)
  217. {
  218. /*
  219. * Since some memmove()'s erroneously fail to handle
  220. * overlapping regions, we'll do the shift by hand.
  221. */
  222. const int n = tp - colonp;
  223. int i;
  224. if (tp == endp)
  225. return (0);
  226. for (i = 1; i <= n; i++)
  227. {
  228. endp[-i] = colonp[n - i];
  229. colonp[n - i] = 0;
  230. }
  231. tp = endp;
  232. }
  233. if (tp != endp)
  234. return (0);
  235. memcpy (dst, tmp, NS_IN6ADDRSZ);
  236. return (1);
  237. }
  238. # endif
  239. #endif