inet_pton.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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. #if defined(LIBC_SCCS) && !defined(lint)
  18. static const char rcsid[] = "$Id: inet_pton.c,v 1.3.18.2 2005/07/28 07:38:07 marka Exp $";
  19. #endif /* LIBC_SCCS and not lint */
  20. #ifdef __FreeBSD__
  21. #include <sys/cdefs.h>
  22. __FBSDID("$FreeBSD: stable/9/sys/libkern/inet_pton.c 213103 2010-09-24 15:01:45Z attilio $");
  23. #endif
  24. #if !defined(_WIN32)
  25. #include <sys/param.h>
  26. #include <sys/socket.h>
  27. #include <netinet/in.h>
  28. #else
  29. #include <ws2tcpip.h>
  30. #endif
  31. #include <stdio.h>
  32. #include <string.h>
  33. #if !defined(_WIN32) && __FreeBSD_version < 700000
  34. #define strchr index
  35. #endif
  36. /*%
  37. * WARNING: Don't even consider trying to compile this on a system where
  38. * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
  39. */
  40. static int inet_pton4(const char *src, u_char * dst);
  41. static int inet_pton6(const char *src, u_char * dst);
  42. /* int
  43. * inet_pton(af, src, dst)
  44. * convert from presentation format (which usually means ASCII printable)
  45. * to network format (which is usually some kind of binary format).
  46. * return:
  47. * 1 if the address was valid for the specified address family
  48. * 0 if the address wasn't valid (`dst' is untouched in this case)
  49. * -1 if some other error occurred (`dst' is untouched in this case, too)
  50. * author:
  51. * Paul Vixie, 1996.
  52. */
  53. int inet_pton(int af, const char *src, void *dst)
  54. {
  55. switch (af) {
  56. case AF_INET:
  57. return (inet_pton4(src, dst));
  58. case AF_INET6:
  59. return (inet_pton6(src, dst));
  60. default:
  61. return (-1);
  62. }
  63. /* NOTREACHED */
  64. }
  65. /* int
  66. * inet_pton4(src, dst)
  67. * like inet_aton() but without all the hexadecimal and shorthand.
  68. * return:
  69. * 1 if `src' is a valid dotted quad, else 0.
  70. * notice:
  71. * does not touch `dst' unless it's returning 1.
  72. * author:
  73. * Paul Vixie, 1996.
  74. */
  75. static int inet_pton4(const char *src, u_char * dst)
  76. {
  77. static const char digits[] = "0123456789";
  78. int saw_digit, octets, ch;
  79. #define NS_INADDRSZ 4
  80. u_char tmp[NS_INADDRSZ], *tp;
  81. saw_digit = 0;
  82. octets = 0;
  83. *(tp = tmp) = 0;
  84. while ((ch = *src++) != '\0') {
  85. const char *pch;
  86. if ((pch = strchr(digits, ch)) != NULL) {
  87. u_int new = *tp * 10 + (pch - digits);
  88. if (saw_digit && *tp == 0)
  89. return (0);
  90. if (new > 255)
  91. return (0);
  92. *tp = new;
  93. if (!saw_digit) {
  94. if (++octets > 4)
  95. return (0);
  96. saw_digit = 1;
  97. }
  98. } else if (ch == '.' && saw_digit) {
  99. if (octets == 4)
  100. return (0);
  101. *++tp = 0;
  102. saw_digit = 0;
  103. } else
  104. return (0);
  105. }
  106. if (octets < 4)
  107. return (0);
  108. memcpy(dst, tmp, NS_INADDRSZ);
  109. return (1);
  110. }
  111. /* int
  112. * inet_pton6(src, dst)
  113. * convert presentation level address to network order binary form.
  114. * return:
  115. * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
  116. * notice:
  117. * (1) does not touch `dst' unless it's returning 1.
  118. * (2) :: in a full address is silently ignored.
  119. * credit:
  120. * inspired by Mark Andrews.
  121. * author:
  122. * Paul Vixie, 1996.
  123. */
  124. static int inet_pton6(const char *src, u_char * dst)
  125. {
  126. static const char xdigits_l[] = "0123456789abcdef", xdigits_u[] = "0123456789ABCDEF";
  127. #define NS_IN6ADDRSZ 16
  128. #define NS_INT16SZ 2
  129. u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
  130. const char *xdigits, *curtok;
  131. int ch, seen_xdigits;
  132. u_int val;
  133. memset((tp = tmp), '\0', NS_IN6ADDRSZ);
  134. endp = tp + NS_IN6ADDRSZ;
  135. colonp = NULL;
  136. /* Leading :: requires some special handling. */
  137. if (*src == ':')
  138. if (*++src != ':')
  139. return (0);
  140. curtok = src;
  141. seen_xdigits = 0;
  142. val = 0;
  143. while ((ch = *src++) != '\0') {
  144. const char *pch;
  145. if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
  146. pch = strchr((xdigits = xdigits_u), ch);
  147. if (pch != NULL) {
  148. val <<= 4;
  149. val |= (pch - xdigits);
  150. if (++seen_xdigits > 4)
  151. return (0);
  152. continue;
  153. }
  154. if (ch == ':') {
  155. curtok = src;
  156. if (!seen_xdigits) {
  157. if (colonp)
  158. return (0);
  159. colonp = tp;
  160. continue;
  161. } else if (*src == '\0') {
  162. return (0);
  163. }
  164. if (tp + NS_INT16SZ > endp)
  165. return (0);
  166. *tp++ = (u_char) (val >> 8) & 0xff;
  167. *tp++ = (u_char) val & 0xff;
  168. seen_xdigits = 0;
  169. val = 0;
  170. continue;
  171. }
  172. if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) {
  173. tp += NS_INADDRSZ;
  174. seen_xdigits = 0;
  175. break; /*%< '\\0' was seen by inet_pton4(). */
  176. }
  177. return (0);
  178. }
  179. if (seen_xdigits) {
  180. if (tp + NS_INT16SZ > endp)
  181. return (0);
  182. *tp++ = (u_char) (val >> 8) & 0xff;
  183. *tp++ = (u_char) val & 0xff;
  184. }
  185. if (colonp != NULL) {
  186. /*
  187. * Since some memmove()'s erroneously fail to handle
  188. * overlapping regions, we'll do the shift by hand.
  189. */
  190. const int n = tp - colonp;
  191. int i;
  192. if (tp == endp)
  193. return (0);
  194. for (i = 1; i <= n; i++) {
  195. endp[-i] = colonp[n - i];
  196. colonp[n - i] = 0;
  197. }
  198. tp = endp;
  199. }
  200. if (tp != endp)
  201. return (0);
  202. memcpy(dst, tmp, NS_IN6ADDRSZ);
  203. return (1);
  204. }
  205. /*! \file */