inet_pton.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /* Copyright (C) 1996-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library 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 GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. /*
  15. * Copyright (c) 1996,1999 by Internet Software Consortium.
  16. *
  17. * Permission to use, copy, modify, and distribute this software for any
  18. * purpose with or without fee is hereby granted, provided that the above
  19. * copyright notice and this permission notice appear in all copies.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
  22. * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
  23. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
  24. * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  25. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  26. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  27. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  28. * SOFTWARE.
  29. */
  30. #include <arpa/inet.h>
  31. #include <arpa/nameser.h>
  32. #include <ctype.h>
  33. #include <errno.h>
  34. #include <netinet/in.h>
  35. #include <resolv/resolv-internal.h>
  36. #include <string.h>
  37. #include <sys/socket.h>
  38. #include <sys/types.h>
  39. static int inet_pton4 (const char *src, const char *src_end, u_char *dst);
  40. static int inet_pton6 (const char *src, const char *src_end, u_char *dst);
  41. int
  42. __inet_pton_length (int af, const char *src, size_t srclen, void *dst)
  43. {
  44. switch (af)
  45. {
  46. case AF_INET:
  47. return inet_pton4 (src, src + srclen, dst);
  48. case AF_INET6:
  49. return inet_pton6 (src, src + srclen, dst);
  50. default:
  51. __set_errno (EAFNOSUPPORT);
  52. return -1;
  53. }
  54. }
  55. libc_hidden_def (__inet_pton_length)
  56. /* Like __inet_pton_length, but use strlen (SRC) as the length of
  57. SRC. */
  58. int
  59. __inet_pton (int af, const char *src, void *dst)
  60. {
  61. return __inet_pton_length (af, src, strlen (src), dst);
  62. }
  63. libc_hidden_def (__inet_pton)
  64. weak_alias (__inet_pton, inet_pton)
  65. libc_hidden_weak (inet_pton)
  66. /* Like inet_aton but without all the hexadecimal, octal and shorthand
  67. (and trailing garbage is not ignored). Return 1 if SRC is a valid
  68. dotted quad, else 0. This function does not touch DST unless it's
  69. returning 1.
  70. Author: Paul Vixie, 1996. */
  71. static int
  72. inet_pton4 (const char *src, const char *end, unsigned char *dst)
  73. {
  74. int saw_digit, octets, ch;
  75. unsigned char tmp[NS_INADDRSZ], *tp;
  76. saw_digit = 0;
  77. octets = 0;
  78. *(tp = tmp) = 0;
  79. while (src < end)
  80. {
  81. ch = *src++;
  82. if (ch >= '0' && ch <= '9')
  83. {
  84. unsigned int new = *tp * 10 + (ch - '0');
  85. if (saw_digit && *tp == 0)
  86. return 0;
  87. if (new > 255)
  88. return 0;
  89. *tp = new;
  90. if (! saw_digit)
  91. {
  92. if (++octets > 4)
  93. return 0;
  94. saw_digit = 1;
  95. }
  96. }
  97. else if (ch == '.' && saw_digit)
  98. {
  99. if (octets == 4)
  100. return 0;
  101. *++tp = 0;
  102. saw_digit = 0;
  103. }
  104. else
  105. return 0;
  106. }
  107. if (octets < 4)
  108. return 0;
  109. memcpy (dst, tmp, NS_INADDRSZ);
  110. return 1;
  111. }
  112. /* Return the value of CH as a hexademical digit, or -1 if it is a
  113. different type of character. */
  114. static int
  115. hex_digit_value (char ch)
  116. {
  117. if ('0' <= ch && ch <= '9')
  118. return ch - '0';
  119. if ('a' <= ch && ch <= 'f')
  120. return ch - 'a' + 10;
  121. if ('A' <= ch && ch <= 'F')
  122. return ch - 'A' + 10;
  123. return -1;
  124. }
  125. /* Convert presentation-level IPv6 address to network order binary
  126. form. Return 1 if SRC is a valid [RFC1884 2.2] address, else 0.
  127. This function does not touch DST unless it's returning 1.
  128. Author: Paul Vixie, 1996. Inspired by Mark Andrews. */
  129. static int
  130. inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
  131. {
  132. unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
  133. const char *curtok;
  134. int ch;
  135. size_t xdigits_seen; /* Number of hex digits since colon. */
  136. unsigned int val;
  137. tp = memset (tmp, '\0', NS_IN6ADDRSZ);
  138. endp = tp + NS_IN6ADDRSZ;
  139. colonp = NULL;
  140. /* Leading :: requires some special handling. */
  141. if (src == src_endp)
  142. return 0;
  143. if (*src == ':')
  144. {
  145. ++src;
  146. if (src == src_endp || *src != ':')
  147. return 0;
  148. }
  149. curtok = src;
  150. xdigits_seen = 0;
  151. val = 0;
  152. while (src < src_endp)
  153. {
  154. ch = *src++;
  155. int digit = hex_digit_value (ch);
  156. if (digit >= 0)
  157. {
  158. if (xdigits_seen == 4)
  159. return 0;
  160. val <<= 4;
  161. val |= digit;
  162. if (val > 0xffff)
  163. return 0;
  164. ++xdigits_seen;
  165. continue;
  166. }
  167. if (ch == ':')
  168. {
  169. curtok = src;
  170. if (xdigits_seen == 0)
  171. {
  172. if (colonp)
  173. return 0;
  174. colonp = tp;
  175. continue;
  176. }
  177. else if (src == src_endp)
  178. return 0;
  179. if (tp + NS_INT16SZ > endp)
  180. return 0;
  181. *tp++ = (unsigned char) (val >> 8) & 0xff;
  182. *tp++ = (unsigned char) val & 0xff;
  183. xdigits_seen = 0;
  184. val = 0;
  185. continue;
  186. }
  187. if (ch == '.' && ((tp + NS_INADDRSZ) <= endp)
  188. && inet_pton4 (curtok, src_endp, tp) > 0)
  189. {
  190. tp += NS_INADDRSZ;
  191. xdigits_seen = 0;
  192. break; /* '\0' was seen by inet_pton4. */
  193. }
  194. return 0;
  195. }
  196. if (xdigits_seen > 0)
  197. {
  198. if (tp + NS_INT16SZ > endp)
  199. return 0;
  200. *tp++ = (unsigned char) (val >> 8) & 0xff;
  201. *tp++ = (unsigned char) val & 0xff;
  202. }
  203. if (colonp != NULL)
  204. {
  205. /* Replace :: with zeros. */
  206. if (tp == endp)
  207. /* :: would expand to a zero-width field. */
  208. return 0;
  209. size_t n = tp - colonp;
  210. memmove (endp - n, colonp, n);
  211. memset (colonp, 0, endp - n - colonp);
  212. tp = endp;
  213. }
  214. if (tp != endp)
  215. return 0;
  216. memcpy (dst, tmp, NS_IN6ADDRSZ);
  217. return 1;
  218. }