2
0

udht.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <errno.h>
  4. #include <arpa/inet.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netdb.h>
  8. #include <libubox/usock.h>
  9. #include <libubox/uloop.h>
  10. #include <libubox/blob.h>
  11. #include "curve25519.h"
  12. #include "siphash.h"
  13. #include "sha512.h"
  14. #include "dht.h"
  15. #include "udht.h"
  16. #include "pex-msg.h"
  17. static struct uloop_timeout periodic_timer, peer_timer, status_timer, disconnect_timer;
  18. static struct uloop_fd dht_fd;
  19. static int dht_unix_fd;
  20. static LIST_HEAD(bootstrap_peers);
  21. static LIST_HEAD(networks);
  22. static struct blob_buf b;
  23. static uint8_t local_id[20];
  24. static const char *node_file;
  25. static const char *unix_path;
  26. static bool udht_connected;
  27. static struct {
  28. unsigned int tick;
  29. unsigned int peer_count;
  30. bool bootstrap_added;
  31. bool dht_ready;
  32. } state;
  33. struct network_entry {
  34. struct list_head list;
  35. uint8_t auth_key[CURVE25519_KEY_SIZE];
  36. uint8_t id[20];
  37. struct uloop_timeout search_timer;
  38. int search_count;
  39. int seq;
  40. };
  41. struct peer_entry {
  42. struct list_head list;
  43. struct sockaddr_storage sa;
  44. int sa_len;
  45. };
  46. void dht_hash(void *hash_return, int hash_size,
  47. const void *v1, int len1,
  48. const void *v2, int len2,
  49. const void *v3, int len3)
  50. {
  51. siphash_key_t key = {};
  52. if (hash_size != 8)
  53. abort();
  54. key.key[0] = siphash(v1, len1, &key);
  55. key.key[1] = siphash(v2, len2, &key);
  56. siphash_to_le64(hash_return, v3, len3, &key);
  57. }
  58. int dht_sendto(int sockfd, const void *buf, int len, int flags,
  59. const struct sockaddr *to, int tolen)
  60. {
  61. struct iovec iov[2] = {
  62. { .iov_base = (void *)to },
  63. { .iov_base = (void *)buf, .iov_len = len },
  64. };
  65. struct msghdr msg = {
  66. .msg_iov = iov,
  67. .msg_iovlen = ARRAY_SIZE(iov),
  68. };
  69. int ret;
  70. if (to->sa_family == AF_INET)
  71. iov[0].iov_len = sizeof(struct sockaddr_in);
  72. else if (to->sa_family == AF_INET6)
  73. iov[0].iov_len = sizeof(struct sockaddr_in6);
  74. else
  75. return -1;
  76. ret = sendmsg(sockfd, &msg, flags);
  77. if (ret < 0) {
  78. perror("send");
  79. if (errno == ECONNRESET || errno == EDESTADDRREQ ||
  80. errno == ENOTCONN || errno == ECONNREFUSED)
  81. uloop_timeout_set(&disconnect_timer, 1);
  82. }
  83. return ret;
  84. }
  85. int dht_blacklisted(const struct sockaddr *sa, int salen)
  86. {
  87. return 0;
  88. }
  89. int dht_random_bytes(void *buf, size_t size)
  90. {
  91. int fd, rc, save;
  92. fd = open("/dev/urandom", O_RDONLY);
  93. if(fd < 0)
  94. return -1;
  95. rc = read(fd, buf, size);
  96. save = errno;
  97. close(fd);
  98. errno = save;
  99. return rc;
  100. }
  101. static void
  102. udht_start_search(void)
  103. {
  104. struct network_entry *n;
  105. if (!state.dht_ready)
  106. return;
  107. list_for_each_entry(n, &networks, list) {
  108. if (n->search_timer.pending)
  109. continue;
  110. uloop_timeout_set(&n->search_timer, 1);
  111. }
  112. }
  113. static void
  114. udht_send_v4_node(const void *id, const void *data)
  115. {
  116. struct network_entry *n;
  117. struct {
  118. struct sockaddr sa;
  119. struct pex_msg_local_control local;
  120. } msg = {
  121. .sa = {
  122. .sa_family = AF_LOCAL
  123. },
  124. .local = {
  125. .ep.in = {
  126. .sin_family = AF_INET,
  127. .sin_addr = *(const struct in_addr *)data,
  128. .sin_port = *(const uint16_t *)(data + 4),
  129. },
  130. .timeout = 15 * 60,
  131. }
  132. };
  133. list_for_each_entry(n, &networks, list) {
  134. if (memcmp(n->id, id, sizeof(n->id)) != 0)
  135. continue;
  136. memcpy(&msg.local.auth_id, n->auth_key, sizeof(msg.local.auth_id));
  137. goto found;
  138. }
  139. found:
  140. send(dht_unix_fd, &msg, sizeof(msg), 0);
  141. }
  142. static void
  143. udht_cb(void *closure, int event, const unsigned char *info_hash,
  144. const void *data, size_t data_len)
  145. {
  146. char addrbuf[INET6_ADDRSTRLEN];
  147. int i;
  148. if (!udht_connected)
  149. return;
  150. if (event == DHT_EVENT_SEARCH_DONE) {
  151. printf("Search done.\n");
  152. udht_start_search();
  153. } else if (event == DHT_EVENT_SEARCH_DONE6) {
  154. printf("IPv6 search done.\n");
  155. } else if (event == DHT_EVENT_VALUES) {
  156. printf("Received %d values.\n", (int)(data_len / 6));
  157. for (i = 0; i < data_len / 6; i++) {
  158. fprintf(stderr, "Node: %s:%d\n", inet_ntop(AF_INET, data, addrbuf, sizeof(addrbuf)), ntohs(*(uint16_t *)(data + 4)));
  159. udht_send_v4_node(info_hash, data);
  160. data += 6;
  161. }
  162. }
  163. else if (event == DHT_EVENT_VALUES6)
  164. printf("Received %d IPv6 values.\n", (int)(data_len / 18));
  165. else
  166. printf("Unknown DHT event %d.\n", event);
  167. }
  168. static void
  169. udht_search_timer_cb(struct uloop_timeout *t)
  170. {
  171. struct network_entry *n = container_of(t, struct network_entry, search_timer);
  172. char id_str[42];
  173. int i;
  174. for (i = 0; i < sizeof(n->id); i++)
  175. snprintf(&id_str[i * 2], sizeof(id_str) - i * 2, "%02x", n->id[i]);
  176. fprintf(stderr, "Start search for network, id=%s\n", id_str);
  177. dht_search(n->id, UNETD_GLOBAL_PEX_PORT, AF_INET, udht_cb, NULL);
  178. if (++n->search_count > 2)
  179. uloop_timeout_set(&n->search_timer, 30 * 1000);
  180. }
  181. static void
  182. udht_timer_cb(struct uloop_timeout *t)
  183. {
  184. time_t tosleep = 1;
  185. dht_periodic(NULL, 0, NULL, 0, &tosleep, udht_cb, NULL);
  186. if (!tosleep)
  187. tosleep = 1;
  188. uloop_timeout_set(t, tosleep * 1000);
  189. }
  190. static void
  191. udht_fd_cb(struct uloop_fd *fd, unsigned int events)
  192. {
  193. static char buf[4096];
  194. struct sockaddr *sa = (struct sockaddr *)buf;
  195. time_t tosleep = 1;
  196. int len;
  197. while (1) {
  198. socklen_t fromlen;
  199. len = recv(fd->fd, buf, sizeof(buf) - 1, 0);
  200. if (len < 0) {
  201. if (errno == EINTR)
  202. continue;
  203. if (errno == EAGAIN)
  204. break;
  205. perror("recvfrom");
  206. uloop_timeout_set(&disconnect_timer, 1);
  207. return;
  208. }
  209. if (len <= sizeof(struct sockaddr))
  210. continue;
  211. if (sa->sa_family == AF_INET)
  212. fromlen = sizeof(struct sockaddr_in);
  213. else if (sa->sa_family == AF_INET6)
  214. fromlen = sizeof(struct sockaddr_in6);
  215. else
  216. continue;
  217. if (len <= fromlen)
  218. continue;
  219. buf[len] = 0;
  220. dht_periodic(buf + fromlen, len - fromlen, sa, fromlen,
  221. &tosleep, udht_cb, NULL);
  222. if (!tosleep)
  223. tosleep = 1;
  224. uloop_timeout_set(&periodic_timer, tosleep * 1000);
  225. }
  226. }
  227. static int
  228. udht_open_socket(const char *unix_path)
  229. {
  230. uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 };
  231. static struct sockaddr sa = {
  232. .sa_family = AF_LOCAL,
  233. };
  234. static struct iovec iov = {
  235. .iov_base = &sa,
  236. .iov_len = sizeof(sa),
  237. };
  238. struct msghdr msg = {
  239. .msg_iov = &iov,
  240. .msg_iovlen = 1,
  241. .msg_control = fd_buf,
  242. .msg_controllen = CMSG_LEN(sizeof(int)),
  243. };
  244. struct cmsghdr *cmsg;
  245. int sfd[2];
  246. int fd;
  247. fd = usock(USOCK_UNIX | USOCK_UDP, unix_path, NULL);
  248. if (fd < 0)
  249. return -1;
  250. if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sfd) < 0)
  251. close(fd);
  252. dht_unix_fd = fd;
  253. dht_fd.fd = sfd[1];
  254. dht_fd.cb = udht_fd_cb;
  255. uloop_fd_add(&dht_fd, ULOOP_READ);
  256. cmsg = CMSG_FIRSTHDR(&msg);
  257. cmsg->cmsg_type = SCM_RIGHTS;
  258. cmsg->cmsg_level = SOL_SOCKET;
  259. cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  260. *(int *)CMSG_DATA(cmsg) = sfd[0];
  261. sendmsg(dht_unix_fd, &msg, 0);
  262. close(sfd[0]);
  263. return 0;
  264. }
  265. static void
  266. udht_close_socket(void)
  267. {
  268. uloop_fd_delete(&dht_fd);
  269. close(dht_fd.fd);
  270. close(dht_unix_fd);
  271. }
  272. static void udht_id_hash(uint8_t *dest, const void *data, int len)
  273. {
  274. struct sha512_state s;
  275. uint8_t hash[SHA512_HASH_SIZE];
  276. sha512_init(&s);
  277. sha512_add(&s, data, len);
  278. sha512_final(&s, hash);
  279. memcpy(dest, hash, 20);
  280. }
  281. static void udht_add_peer(const void *data, int len)
  282. {
  283. const struct sockaddr *sa = data;
  284. struct peer_entry *p;
  285. p = calloc(1, sizeof(*p));
  286. memcpy(&p->sa, sa, len);
  287. p->sa_len = len;
  288. list_add_tail(&p->list, &bootstrap_peers);
  289. if (!peer_timer.pending)
  290. uloop_timeout_set(&peer_timer, 1);
  291. }
  292. static void udht_add_bootstrap_peer(void)
  293. {
  294. const struct addrinfo hints = {
  295. .ai_family = AF_INET,
  296. .ai_socktype = SOCK_DGRAM,
  297. .ai_flags = AI_ADDRCONFIG,
  298. };
  299. struct addrinfo *res, *cur;
  300. static const char * const bootstrap_hosts[] = {
  301. "router.bittorrent.com",
  302. "router.utorrent.com",
  303. };
  304. int i;
  305. for (i = 0; i < ARRAY_SIZE(bootstrap_hosts); i++) {
  306. if (getaddrinfo(bootstrap_hosts[i], "6881", &hints, &res) < 0)
  307. continue;
  308. for (cur = res; cur; cur = cur->ai_next)
  309. udht_add_peer(cur->ai_addr, cur->ai_addrlen);
  310. freeaddrinfo(res);
  311. }
  312. state.bootstrap_added = true;
  313. }
  314. static void udht_peer_timer_cb(struct uloop_timeout *t)
  315. {
  316. struct peer_entry *p;
  317. struct sockaddr_in *sin;
  318. char buf[INET6_ADDRSTRLEN];
  319. if (list_empty(&bootstrap_peers)) {
  320. if (!state.peer_count && !state.bootstrap_added)
  321. udht_add_bootstrap_peer();
  322. return;
  323. }
  324. p = list_first_entry(&bootstrap_peers, struct peer_entry, list);
  325. list_del(&p->list);
  326. sin = (struct sockaddr_in *)&p->sa;
  327. fprintf(stderr, "Ping node %s\n", inet_ntop(sin->sin_family, &sin->sin_addr, buf, sizeof(buf)));
  328. dht_ping_node((struct sockaddr *)&p->sa, p->sa_len);
  329. free(p);
  330. if (state.peer_count++ < 8)
  331. uloop_timeout_set(t, 2000);
  332. else
  333. uloop_timeout_set(t, 15000);
  334. }
  335. void udht_network_add(const uint8_t *auth_key, int seq)
  336. {
  337. struct network_entry *n;
  338. list_for_each_entry(n, &networks, list) {
  339. if (memcmp(n->auth_key, auth_key, sizeof(n->auth_key)) != 0)
  340. continue;
  341. goto out;
  342. }
  343. n = calloc(1, sizeof(*n));
  344. n->search_timer.cb = udht_search_timer_cb;
  345. memcpy(n->auth_key, auth_key, sizeof(n->auth_key));
  346. udht_id_hash(n->id, n->auth_key, sizeof(n->auth_key));
  347. list_add_tail(&n->list, &networks);
  348. if (state.dht_ready)
  349. uloop_timeout_set(&n->search_timer, 1);
  350. out:
  351. n->seq = seq;
  352. }
  353. void udht_network_flush(int seq)
  354. {
  355. struct network_entry *n, *tmp;
  356. list_for_each_entry_safe(n, tmp, &networks, list) {
  357. if (seq >= 0 && (n->seq < 0 || n->seq == seq))
  358. continue;
  359. list_del(&n->list);
  360. uloop_timeout_cancel(&n->search_timer);
  361. free(n);
  362. }
  363. }
  364. static void
  365. udht_status_check(struct uloop_timeout *t)
  366. {
  367. int good = 0, dubious = 0, incoming = 0;
  368. static int prev_good, prev_dubious, prev_incoming;
  369. state.tick++;
  370. uloop_timeout_set(t, 1000);
  371. dht_nodes(AF_INET, &good, &dubious, NULL, &incoming);
  372. if (good != prev_good || dubious != prev_dubious || incoming != prev_incoming)
  373. fprintf(stderr, "DHT status: good=%d, dubious=%d, incoming=%d\n", good, dubious, incoming);
  374. prev_good = good;
  375. prev_dubious = dubious;
  376. prev_incoming = incoming;
  377. if (state.dht_ready)
  378. return;
  379. if (good < 4 || good + dubious < 8) {
  380. if (state.tick > 45 && !state.bootstrap_added)
  381. udht_add_bootstrap_peer();
  382. return;
  383. }
  384. state.dht_ready = true;
  385. fprintf(stderr, "DHT is ready\n");
  386. udht_start_search();
  387. }
  388. static void
  389. udht_load_nodes(const char *filename)
  390. {
  391. struct blob_attr *data, *cur;
  392. size_t len;
  393. FILE *f;
  394. int rem;
  395. f = fopen(filename, "r");
  396. if (!f)
  397. return;
  398. data = malloc(sizeof(struct blob_attr));
  399. if (fread(data, sizeof(struct blob_attr), 1, f) != 1)
  400. goto out;
  401. len = blob_pad_len(data);
  402. if (len <= sizeof(struct blob_attr))
  403. goto out;
  404. if (len >= 256 * 1024)
  405. goto out;
  406. data = realloc(data, len);
  407. if (fread(data + 1, len - sizeof(struct blob_attr), 1, f) != 1)
  408. goto out;
  409. blob_for_each_attr(cur, data, rem) {
  410. void *entry = blob_data(cur);
  411. if (blob_len(cur) == 6) {
  412. struct sockaddr_in sin = {
  413. .sin_family = AF_INET,
  414. .sin_addr = *(struct in_addr *)entry,
  415. .sin_port = *(uint16_t *)(entry + 4),
  416. };
  417. udht_add_peer(&sin, sizeof(sin));
  418. } else {
  419. continue;
  420. }
  421. }
  422. out:
  423. free(data);
  424. }
  425. static void
  426. udht_save_nodes(const char *filename)
  427. {
  428. struct sockaddr_in sin[128];
  429. struct sockaddr_in6 sin6[128];
  430. int n_sin = ARRAY_SIZE(sin);
  431. int n_sin6 = ARRAY_SIZE(sin6);
  432. FILE *f;
  433. int i;
  434. if (!filename)
  435. return;
  436. if (dht_get_nodes(sin, &n_sin, sin6, &n_sin6) <= 0)
  437. return;
  438. if (n_sin < 8)
  439. return;
  440. blob_buf_init(&b, 0);
  441. for (i = 0; i < n_sin; i++) {
  442. struct {
  443. struct in_addr addr;
  444. uint16_t port;
  445. } __attribute__((packed)) data = {
  446. .addr = sin[i].sin_addr,
  447. .port = sin[i].sin_port,
  448. };
  449. blob_put(&b, 4, &data, sizeof(data));
  450. }
  451. f = fopen(filename, "w");
  452. if (!f)
  453. return;
  454. fwrite(b.head, blob_pad_len(b.head), 1, f);
  455. fclose(f);
  456. }
  457. static int usage(const char *progname)
  458. {
  459. fprintf(stderr, "Usage: %s [<options>] <id string>\n"
  460. "Options:\n"
  461. " -d Enable debug mode\n"
  462. " -n <file> Set node filename\n"
  463. " -N <key> Add network key\n"
  464. "\n",
  465. progname);
  466. return 1;
  467. }
  468. static void udht_disconnect(struct uloop_timeout *t)
  469. {
  470. struct peer_entry *p, *tmp;
  471. if (!udht_connected)
  472. return;
  473. list_for_each_entry_safe(p, tmp, &bootstrap_peers, list) {
  474. list_del(&p->list);
  475. free(p);
  476. }
  477. uloop_timeout_cancel(&disconnect_timer);
  478. udht_connected = false;
  479. udht_network_flush(-1);
  480. uloop_timeout_cancel(&peer_timer);
  481. uloop_timeout_cancel(&status_timer);
  482. uloop_timeout_cancel(&periodic_timer);
  483. udht_save_nodes(node_file);
  484. dht_uninit();
  485. memset(&state, 0, sizeof(state));
  486. udht_close_socket();
  487. #ifndef UBUS_SUPPORT
  488. uloop_end();
  489. #endif
  490. }
  491. int udht_reconnect(void)
  492. {
  493. udht_disconnect(&disconnect_timer);
  494. if (udht_open_socket(unix_path) < 0)
  495. return -1;
  496. if (dht_init(dht_unix_fd, -1, local_id, NULL) < 0) {
  497. udht_close_socket();
  498. return -1;
  499. }
  500. udht_connected = true;
  501. fprintf(stderr, "DHT connected\n");
  502. udht_load_nodes(node_file);
  503. uloop_timeout_set(&peer_timer, 1);
  504. uloop_timeout_set(&status_timer, 1000);
  505. return 0;
  506. }
  507. int main(int argc, char **argv)
  508. {
  509. const char *progname = argv[0];
  510. uint8_t auth_key[CURVE25519_KEY_SIZE];
  511. int ch;
  512. while ((ch = getopt(argc, argv, "dN:n:u:")) != -1) {
  513. switch (ch) {
  514. case 'N':
  515. if (b64_decode(optarg, auth_key, CURVE25519_KEY_SIZE) != CURVE25519_KEY_SIZE) {
  516. fprintf(stderr, "Invalid network key\n");
  517. return 1;
  518. }
  519. udht_network_add(auth_key, -1);
  520. break;
  521. case 'n':
  522. node_file = optarg;
  523. break;
  524. case 'd':
  525. dht_debug = stderr;
  526. break;
  527. case 'u':
  528. unix_path = optarg;
  529. break;
  530. default:
  531. return usage(progname);
  532. }
  533. }
  534. argv += optind;
  535. argc -= optind;
  536. if (argc != 1)
  537. return usage(progname);
  538. udht_id_hash(local_id, argv[0], strlen(argv[0]));
  539. status_timer.cb = udht_status_check;
  540. periodic_timer.cb = udht_timer_cb;
  541. peer_timer.cb = udht_peer_timer_cb;
  542. disconnect_timer.cb = udht_disconnect;
  543. uloop_init();
  544. #ifdef UBUS_SUPPORT
  545. udht_ubus_init();
  546. #else
  547. if (udht_reconnect() < 0) {
  548. fprintf(stderr, "Failed to connect to unetd\n");
  549. return 1;
  550. }
  551. #endif
  552. uloop_run();
  553. uloop_done();
  554. udht_disconnect(&disconnect_timer);
  555. blob_buf_free(&b);
  556. return 0;
  557. }