Address.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "dht/Address.h"
  16. #include "crypto/AddressCalc.h"
  17. #include "crypto/Key.h"
  18. #include "util/AddrTools.h"
  19. #include "util/Assert.h"
  20. #include "util/Bits.h"
  21. #include "util/Endian.h"
  22. #include "util/Hex.h"
  23. #include "util/Defined.h"
  24. struct Address_List* Address_List_new(uint32_t length, struct Allocator* alloc)
  25. {
  26. struct Address_List* out = Allocator_malloc(alloc, sizeof(struct Address_List));
  27. out->length = length;
  28. out->elems = Allocator_calloc(alloc, Address_SIZE, length);
  29. return out;
  30. }
  31. uint32_t Address_prefixForIp6(uint8_t ip6[16])
  32. {
  33. uint32_t word = ((uint32_t*)ip6)[ Defined(Address_ROT64) ? 2 : 0 ];
  34. return Endian_bigEndianToHost32(word);
  35. }
  36. uint32_t Address_getPrefix(struct Address* addr)
  37. {
  38. if (addr->ip6.ints.one_be == 0
  39. && addr->ip6.ints.two_be == 0
  40. && addr->ip6.ints.three_be == 0
  41. && addr->ip6.ints.four_be == 0)
  42. {
  43. AddressCalc_addressForPublicKey(addr->ip6.bytes, addr->key);
  44. }
  45. return Endian_bigEndianToHost32(addr->ip6.ints.one_be);
  46. }
  47. uint32_t Address_prefixForSearchTarget(const uint8_t searchTarget[16])
  48. {
  49. uint32_t prefix_be;
  50. Bits_memcpy(&prefix_be, &searchTarget[8], 4);
  51. return Endian_bigEndianToHost32(prefix_be);
  52. }
  53. void Address_serialize(uint8_t output[Address_SERIALIZED_SIZE], const struct Address* addr)
  54. {
  55. Bits_memcpy(output, addr->key, Address_KEY_SIZE);
  56. Bits_memcpy(output+Address_KEY_SIZE, &addr->path, sizeof(addr->path));
  57. if (!Endian_isBigEndian()) {
  58. uint64_t path_be = Endian_hostToBigEndian64(addr->path);
  59. Bits_memcpy(output + Address_KEY_SIZE, &path_be, Address_NETWORK_ADDR_SIZE);
  60. }
  61. }
  62. void Address_parse(struct Address* addr, const uint8_t input[Address_SERIALIZED_SIZE])
  63. {
  64. Bits_memset(addr->ip6.bytes, 0, 16);
  65. Bits_memcpy(addr->key, input, Address_KEY_SIZE);
  66. Bits_memcpy(&addr->path, input+Address_KEY_SIZE, sizeof(addr->path));
  67. addr->path = Endian_bigEndianToHost64(addr->path);
  68. }
  69. bool Address_isSame(const struct Address* addr,
  70. const struct Address* addr2)
  71. {
  72. return (Bits_memcmp(addr->key, addr2->key, Address_KEY_SIZE) == 0
  73. && addr->path == addr2->path);
  74. }
  75. bool Address_isSameIp(const struct Address* addr,
  76. const struct Address* addr2)
  77. {
  78. return Bits_memcmp(addr->ip6.bytes, addr2->ip6.bytes, 16) == 0;
  79. }
  80. bool Address_equalsSearchTarget(struct Address* addr,
  81. const uint8_t searchTarget[Address_SEARCH_TARGET_SIZE])
  82. {
  83. Address_getPrefix(addr);
  84. return Bits_memcmp(addr->ip6.bytes, searchTarget, Address_SEARCH_TARGET_SIZE);
  85. }
  86. void Address_forKey(struct Address* out, const uint8_t key[Address_KEY_SIZE])
  87. {
  88. Bits_memcpy(out->key, key, Address_KEY_SIZE);
  89. AddressCalc_addressForPublicKey(out->ip6.bytes, key);
  90. }
  91. void Address_printIp(uint8_t output[40], struct Address* addr)
  92. {
  93. Address_getPrefix(addr);
  94. AddrTools_printIp(output, addr->ip6.bytes);
  95. }
  96. void Address_printShortIp(uint8_t output[40], struct Address* addr)
  97. {
  98. Address_getPrefix(addr);
  99. AddrTools_printShortIp(output, addr->ip6.bytes);
  100. }
  101. void Address_print(uint8_t output[60], struct Address* addr)
  102. {
  103. Address_printIp(output, addr);
  104. output[39] = '@';
  105. AddrTools_printPath(output + 40, addr->path);
  106. }
  107. int Address_xorcmp(uint32_t target,
  108. uint32_t negativeIfCloser,
  109. uint32_t positiveIfCloser)
  110. {
  111. if (negativeIfCloser == positiveIfCloser) {
  112. return 0;
  113. }
  114. uint32_t ref = Endian_bigEndianToHost32(target);
  115. return ((Endian_bigEndianToHost32(negativeIfCloser) ^ ref)
  116. < (Endian_bigEndianToHost32(positiveIfCloser) ^ ref)) ? -1 : 1;
  117. }
  118. /**
  119. * Return which node is closer to the target.
  120. *
  121. * @param target the address to test distance against.
  122. * @param negativeIfCloser one address to check distance.
  123. * @param positiveIfCloser another address to check distance.
  124. * @return -1 if negativeIfCloser is closer to target, 1 if positiveIfCloser is closer
  125. * 0 if they are both the same distance.
  126. */
  127. int Address_closest(struct Address* target,
  128. struct Address* negativeIfCloser,
  129. struct Address* positiveIfCloser)
  130. {
  131. Address_getPrefix(target);
  132. Address_getPrefix(negativeIfCloser);
  133. Address_getPrefix(positiveIfCloser);
  134. int ret = 0;
  135. #define Address_COMPARE(part) \
  136. if ((ret = Address_xorcmp(target->ip6.ints.part, \
  137. negativeIfCloser->ip6.ints.part, \
  138. positiveIfCloser->ip6.ints.part))) \
  139. { \
  140. return ret; \
  141. }
  142. Address_COMPARE(one_be)
  143. Address_COMPARE(two_be)
  144. Address_COMPARE(three_be)
  145. Address_COMPARE(four_be)
  146. return 0;
  147. #undef Address_COMPARE
  148. }
  149. String* Address_toString(struct Address* addr, struct Allocator* alloc)
  150. {
  151. struct Allocator* temp = Allocator_child(alloc);
  152. String* key = Key_stringify(addr->key, temp);
  153. String* path = String_newBinary(NULL, 19, temp);
  154. AddrTools_printPath(path->bytes, addr->path);
  155. String* out = String_printf(alloc, "v%u.%s.%s", addr->protocolVersion, path->bytes, key->bytes);
  156. Allocator_free(temp);
  157. return out;
  158. }
  159. struct Address* Address_fromString(String* str, struct Allocator* alloc)
  160. {
  161. // v6.0000.0000.0000.0001.yw4hn81kh3f9n39ff3qhnhdl8ngd662utbpgtjp5q4b0yxqv4by0.k
  162. if (str->len < 77) { return NULL; }
  163. if (str->bytes[0] != 'v') { return NULL; }
  164. struct Address addr = { .protocolVersion = 0 };
  165. int i = 1;
  166. for (; str->bytes[i] && str->bytes[i] != '.'; i++) {
  167. Assert_true(i < 77);
  168. if (str->bytes[i] > '9' || str->bytes[i] < '0') { return NULL; }
  169. addr.protocolVersion *= 10;
  170. addr.protocolVersion += (str->bytes[i] - '0');
  171. }
  172. if (str->bytes[i] != '.') { return NULL; }
  173. i++;
  174. // 0000.0000.0000.0001.yw4hn81kh3f9n39ff3qhnhdl8ngd662utbpgtjp5q4b0yxqv4by0.k
  175. if (str->len - i != 74) { return NULL; }
  176. if (str->bytes[i+19] != '.') { return NULL; }
  177. str->bytes[i+19] = '\0';
  178. int ret = AddrTools_parsePath(&addr.path, &str->bytes[i]);
  179. str->bytes[i+19] = '.';
  180. if (ret) { return NULL; }
  181. String keyPart = { .len = str->len - i - 20, .bytes = &str->bytes[i + 20] };
  182. Assert_true(keyPart.len == 54 && keyPart.bytes[53] == 'k');
  183. if (Key_parse(&keyPart, addr.key, addr.ip6.bytes)) { return NULL; }
  184. return Allocator_clone(alloc, &addr);
  185. }
  186. struct Address* Address_clone(struct Address* orig, struct Allocator* alloc)
  187. {
  188. return Allocator_clone(alloc, orig);
  189. }