inaddr.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file inaddr.c
  7. * \brief Convert in_addr and in6_addr to and from strings.
  8. **/
  9. #include "lib/net/inaddr.h"
  10. #include "lib/cc/torint.h"
  11. #include "lib/log/util_bug.h"
  12. #include "lib/net/inaddr_st.h"
  13. #include "lib/string/compat_ctype.h"
  14. #include "lib/string/compat_string.h"
  15. #include "lib/string/printf.h"
  16. #include "lib/string/scanf.h"
  17. #include "lib/string/util_string.h"
  18. #ifdef HAVE_ARPA_INET_H
  19. #include <arpa/inet.h>
  20. #endif
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #ifdef _WIN32
  24. #include <winsock2.h>
  25. #endif
  26. /** Set *addr to the IP address (in dotted-quad notation) stored in *str.
  27. * Return 1 on success, 0 if *str is badly formatted.
  28. * (Like inet_aton(str,addr), but works on Windows and Solaris.)
  29. */
  30. int
  31. tor_inet_aton(const char *str, struct in_addr* addr)
  32. {
  33. unsigned a,b,c,d;
  34. char more;
  35. if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
  36. return 0;
  37. if (a > 255) return 0;
  38. if (b > 255) return 0;
  39. if (c > 255) return 0;
  40. if (d > 255) return 0;
  41. addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
  42. return 1;
  43. }
  44. /** Given an IPv4 in_addr struct *<b>in</b> (in network order, as usual),
  45. * write it as a string into the <b>buf_len</b>-byte buffer in
  46. * <b>buf</b>. Returns a non-negative integer on success.
  47. * Returns -1 on failure.
  48. */
  49. int
  50. tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len)
  51. {
  52. uint32_t a = ntohl(in->s_addr);
  53. return tor_snprintf(buf, buf_len, "%d.%d.%d.%d",
  54. (int)(uint8_t)((a>>24)&0xff),
  55. (int)(uint8_t)((a>>16)&0xff),
  56. (int)(uint8_t)((a>>8 )&0xff),
  57. (int)(uint8_t)((a )&0xff));
  58. }
  59. /** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or
  60. * <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the
  61. * address and store it in the <b>len</b>-byte buffer <b>dst</b>. Returns
  62. * <b>dst</b> on success, NULL on failure.
  63. *
  64. * (Like inet_ntop(af,src,dst,len), but works on platforms that don't have it:
  65. * Tor sometimes needs to format ipv6 addresses even on platforms without ipv6
  66. * support.) */
  67. const char *
  68. tor_inet_ntop(int af, const void *src, char *dst, size_t len)
  69. {
  70. if (af == AF_INET) {
  71. if (tor_inet_ntoa(src, dst, len) < 0)
  72. return NULL;
  73. else
  74. return dst;
  75. } else if (af == AF_INET6) {
  76. const struct in6_addr *addr = src;
  77. char buf[64], *cp;
  78. int longestGapLen = 0, longestGapPos = -1, i,
  79. curGapPos = -1, curGapLen = 0;
  80. uint16_t words[8];
  81. for (i = 0; i < 8; ++i) {
  82. words[i] = (((uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
  83. }
  84. if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
  85. words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) ||
  86. (words[5] == 0xffff))) {
  87. /* This is an IPv4 address. */
  88. if (words[5] == 0) {
  89. tor_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
  90. addr->s6_addr[12], addr->s6_addr[13],
  91. addr->s6_addr[14], addr->s6_addr[15]);
  92. } else {
  93. tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
  94. addr->s6_addr[12], addr->s6_addr[13],
  95. addr->s6_addr[14], addr->s6_addr[15]);
  96. }
  97. if ((strlen(buf) + 1) > len) /* +1 for \0 */
  98. return NULL;
  99. strlcpy(dst, buf, len);
  100. return dst;
  101. }
  102. i = 0;
  103. while (i < 8) {
  104. if (words[i] == 0) {
  105. curGapPos = i++;
  106. curGapLen = 1;
  107. while (i<8 && words[i] == 0) {
  108. ++i; ++curGapLen;
  109. }
  110. if (curGapLen > longestGapLen) {
  111. longestGapPos = curGapPos;
  112. longestGapLen = curGapLen;
  113. }
  114. } else {
  115. ++i;
  116. }
  117. }
  118. if (longestGapLen<=1)
  119. longestGapPos = -1;
  120. cp = buf;
  121. for (i = 0; i < 8; ++i) {
  122. if (words[i] == 0 && longestGapPos == i) {
  123. if (i == 0)
  124. *cp++ = ':';
  125. *cp++ = ':';
  126. while (i < 8 && words[i] == 0)
  127. ++i;
  128. --i; /* to compensate for loop increment. */
  129. } else {
  130. tor_snprintf(cp, sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
  131. cp += strlen(cp);
  132. if (i != 7)
  133. *cp++ = ':';
  134. }
  135. }
  136. *cp = '\0';
  137. if ((strlen(buf) + 1) > len) /* +1 for \0 */
  138. return NULL;
  139. strlcpy(dst, buf, len);
  140. return dst;
  141. } else {
  142. return NULL;
  143. }
  144. }
  145. /** Given <b>af</b>==AF_INET or <b>af</b>==AF_INET6, and a string <b>src</b>
  146. * encoding an IPv4 address or IPv6 address correspondingly, try to parse the
  147. * address and store the result in <b>dst</b> (which must have space for a
  148. * struct in_addr or a struct in6_addr, as appropriate). Return 1 on success,
  149. * 0 on a bad parse, and -1 on a bad <b>af</b>.
  150. *
  151. * (Like inet_pton(af,src,dst) but works on platforms that don't have it: Tor
  152. * sometimes needs to format ipv6 addresses even on platforms without ipv6
  153. * support.) */
  154. int
  155. tor_inet_pton(int af, const char *src, void *dst)
  156. {
  157. if (af == AF_INET) {
  158. return tor_inet_aton(src, dst);
  159. } else if (af == AF_INET6) {
  160. ssize_t len = strlen(src);
  161. /* Reject if src has needless trailing ':'. */
  162. if (len > 2 && src[len - 1] == ':' && src[len - 2] != ':') {
  163. return 0;
  164. }
  165. struct in6_addr *out = dst;
  166. uint16_t words[8];
  167. int gapPos = -1, i, setWords=0;
  168. const char *dot = strchr(src, '.');
  169. const char *eow; /* end of words. */
  170. memset(words, 0xf8, sizeof(words));
  171. if (dot == src)
  172. return 0;
  173. else if (!dot)
  174. eow = src+strlen(src);
  175. else {
  176. unsigned byte1,byte2,byte3,byte4;
  177. char more;
  178. for (eow = dot-1; eow > src && TOR_ISDIGIT(*eow); --eow)
  179. ;
  180. if (*eow != ':')
  181. return 0;
  182. ++eow;
  183. /* We use "scanf" because some platform inet_aton()s are too lax
  184. * about IPv4 addresses of the form "1.2.3" */
  185. if (tor_sscanf(eow, "%3u.%3u.%3u.%3u%c",
  186. &byte1,&byte2,&byte3,&byte4,&more) != 4)
  187. return 0;
  188. if (byte1 > 255 || byte2 > 255 || byte3 > 255 || byte4 > 255)
  189. return 0;
  190. words[6] = (byte1<<8) | byte2;
  191. words[7] = (byte3<<8) | byte4;
  192. setWords += 2;
  193. }
  194. i = 0;
  195. while (src < eow) {
  196. if (i > 7)
  197. return 0;
  198. if (TOR_ISXDIGIT(*src)) {
  199. char *next;
  200. long r = strtol(src, &next, 16);
  201. if (next == NULL || next == src) {
  202. /* The 'next == src' error case can happen on versions of openbsd
  203. * which treat "0xfoo" as an error, rather than as "0" followed by
  204. * "xfoo". */
  205. return 0;
  206. }
  207. len = *next == '\0' ? eow - src : next - src;
  208. if (len > 4)
  209. return 0;
  210. if (len > 1 && !TOR_ISXDIGIT(src[1]))
  211. return 0; /* 0x is not valid */
  212. tor_assert(r >= 0);
  213. tor_assert(r < 65536);
  214. words[i++] = (uint16_t)r;
  215. setWords++;
  216. src = next;
  217. if (*src != ':' && src != eow)
  218. return 0;
  219. ++src;
  220. } else if (*src == ':' && i > 0 && gapPos == -1) {
  221. gapPos = i;
  222. ++src;
  223. } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' &&
  224. gapPos == -1) {
  225. gapPos = i;
  226. src += 2;
  227. } else {
  228. return 0;
  229. }
  230. }
  231. if (setWords > 8 ||
  232. (setWords == 8 && gapPos != -1) ||
  233. (setWords < 8 && gapPos == -1))
  234. return 0;
  235. if (gapPos >= 0) {
  236. int nToMove = setWords - (dot ? 2 : 0) - gapPos;
  237. int gapLen = 8 - setWords;
  238. tor_assert(nToMove >= 0);
  239. memmove(&words[gapPos+gapLen], &words[gapPos],
  240. sizeof(uint16_t)*nToMove);
  241. memset(&words[gapPos], 0, sizeof(uint16_t)*gapLen);
  242. }
  243. for (i = 0; i < 8; ++i) {
  244. out->s6_addr[2*i ] = words[i] >> 8;
  245. out->s6_addr[2*i+1] = words[i] & 0xff;
  246. }
  247. return 1;
  248. } else {
  249. return -1;
  250. }
  251. }