inet_pton.c 5.4 KB

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