ipv6.c 6.4 KB

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