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-2017 Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program 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 <http://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