inet_pton.c 5.2 KB

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