2 Copyright (c) 2009-2011 by Juliusz Chroboczek
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 #include <netinet/in.h>
37 #include <sys/caprights.h>
38 #include <sys/capsicum.h>
39 #include <sys/event.h>
40 #include <sys/resource.h>
41 #include <sys/socket.h>
44 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
46 #define MAX_PKT_SIZE 1536
53 #define ANNOUNCE_PEER 5
58 static const unsigned char zeroes[20] = {0};
59 static const unsigned char v4prefix[16] =
60 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0};
62 static unsigned char myid[20];
63 static unsigned char my_v[9];
65 static int dht_socket = -1;
66 static int dht_socket6 = -1;
69 unsigned char id[160];
70 struct sockaddr_storage ss;
75 #define CIRCULAR_LIST_SIZE 256
77 struct circular_list {
80 struct node nodes[CIRCULAR_LIST_SIZE];
83 static struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
85 #define MAX_TOKEN_BUCKET_TOKENS 40
86 static time_t token_bucket_time;
87 static int token_bucket_tokens;
89 static bool verbose = true;
92 unsigned char buf[MAX_PKT_SIZE];
93 struct sockaddr_storage ss;
99 static struct Pkt pkt;
100 static int sockW = -1;
102 // ------------------------ >8 ------------------------
105 getAddr(const struct sockaddr *sa, const socklen_t saLen)
107 static char host[NI_MAXHOST];
108 static char port[NI_MAXSERV];
109 static char addr[64];
110 int rc = getnameinfo(
117 NI_NUMERICHOST | NI_NUMERICSERV);
119 fprintf(stderr, "getnameinfo: %s\n", gai_strerror(rc));
122 snprintf(addr, sizeof addr, "[%s]:%s", host, port);
127 stricttol(const char *p, unsigned long *l, char **q)
129 if ((isdigit((int)(p[0])) == 0) || (p[0] == '0'))
132 *l = strtoul(p, q, 10);
142 const unsigned char *buf,
144 unsigned char *tid_return,
146 unsigned char *id_return,
147 unsigned char *info_hash_return,
148 unsigned char *target_return,
149 unsigned short *port_return,
150 unsigned char *token_return,
152 unsigned char *nodes_return,
154 unsigned char *nodes6_return,
156 unsigned char *values_return,
158 unsigned char *values6_return,
161 const struct sockaddr *sa,
162 const socklen_t saLen)
164 /* This code will happily crash if the buffer is not NUL-terminated. */
165 if (buf[buflen] != '\0') {
167 printf("%s : parse_message with unterminated buffer\n", getAddr(sa, saLen));
171 #define CHECK(ptr, len) \
172 if (((const unsigned char *)ptr) + (len) > (buf) + (buflen)) \
179 p = memmem(buf, buflen, "1:t", 3);
181 if (stricttol((const char *)p + 3, &l, &q) && (q && *q == ':') &&
182 (l > 0 && l < *tid_len)) {
184 memcpy(tid_return, q + 1, l);
191 p = memmem(buf, buflen, "2:id20:", 7);
194 memcpy(id_return, p + 7, 20);
196 memset(id_return, 0, 20);
199 if (info_hash_return) {
200 p = memmem(buf, buflen, "9:info_hash20:", 14);
203 memcpy(info_hash_return, p + 14, 20);
205 memset(info_hash_return, 0, 20);
209 p = memmem(buf, buflen, "porti", 5);
211 if (stricttol((const char *)p + 5, &l, &q) && (q && *q == 'e') &&
212 (l > 0 && l < 0x10000))
213 *port_return = (unsigned short)l;
220 p = memmem(buf, buflen, "6:target20:", 11);
223 memcpy(target_return, p + 11, 20);
225 memset(target_return, 0, 20);
229 p = memmem(buf, buflen, "5:token", 7);
231 if (stricttol((const char *)p + 7, &l, &q) && (q && *q == ':') &&
232 (l > 0 && l < *token_len)) {
234 memcpy(token_return, q + 1, l);
243 p = memmem(buf, buflen, "5:nodes", 7);
245 if (stricttol((const char *)p + 7, &l, &q) && (q && *q == ':') &&
246 (l > 0 && l < *nodes_len)) {
248 memcpy(nodes_return, q + 1, l);
257 p = memmem(buf, buflen, "6:nodes6", 8);
259 if (stricttol((const char *)p + 8, &l, &q) && (q && *q == ':') &&
260 (l > 0 && l < *nodes6_len)) {
262 memcpy(nodes6_return, q + 1, l);
270 if (values_len || values6_len) {
271 p = memmem(buf, buflen, "6:valuesl", 9);
273 size_t i = p - buf + 9;
274 unsigned long j = 0, j6 = 0;
276 if (stricttol((const char *)buf + i, &l, &q) && (q && *q == ':') &&
280 if (j + l > *values_len)
282 i = q + 1 + l - (const char *)buf;
283 memcpy((char *)values_return + j, q + 1, l);
285 } else if (l == 18) {
286 if (j6 + l > *values6_len)
288 i = q + 1 + l - (const char *)buf;
289 memcpy((char *)values6_return + j6, q + 1, l);
294 "%s : received weird value: %d bytes\n",
297 i = q + 1 + l - (const char *)buf;
303 if (i >= buflen || buf[i] != 'e')
305 printf("%s : unexpected end for values\n", getAddr(sa, saLen));
317 p = memmem(buf, buflen, "4:wantl", 7);
319 size_t i = p - buf + 7;
321 while (buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
322 i + 2 + buf[i] - '0' < buflen) {
323 CHECK(buf + i + 2, buf[i] - '0');
324 if (buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
325 *want_return |= WANT4;
326 else if (buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
327 *want_return |= WANT6;
330 "%s : unexpected want flag: %c\n", getAddr(sa, saLen), buf[i]);
331 i += 2 + buf[i] - '0';
333 if (i >= buflen || buf[i] != 'e')
335 printf("%s : unexpected end for want\n", getAddr(sa, saLen));
343 if (memmem(buf, buflen, "1:y1:r", 6))
345 if (memmem(buf, buflen, "1:y1:e", 6))
347 if (!memmem(buf, buflen, "1:y1:q", 6))
349 if (memmem(buf, buflen, "1:q4:ping", 9))
351 if (memmem(buf, buflen, "1:q9:find_node", 14))
353 if (memmem(buf, buflen, "1:q9:get_peers", 14))
355 if (memmem(buf, buflen, "1:q13:announce_peer", 19))
356 return ANNOUNCE_PEER;
361 printf(": truncated message\n");
370 /* We could use a proper bencoding printer and parser, but the format of
371 DHT messages is fairly stylised, so this seemed simpler. */
373 #define CHECK(offset, delta, size) \
374 if (delta < 0 || offset + delta > size) \
377 #define INC(offset, delta, size) \
378 CHECK(offset, delta, size); \
381 #define COPY(buf, offset, src, delta, size) \
382 CHECK(offset, delta, size); \
383 memcpy(buf + offset, src, delta); \
386 #define ADD_V(buf, offset, size) COPY(buf, offset, my_v, (sizeof my_v), size)
389 is_martian(const struct sockaddr_storage *ss)
391 switch (((const struct sockaddr *)ss)->sa_family) {
393 const struct sockaddr_in *sin = (const struct sockaddr_in *)ss;
394 const unsigned char *address = (const unsigned char *)&sin->sin_addr;
395 return sin->sin_port == 0 || (address[0] == 0) || (address[0] == 127) ||
396 ((address[0] & 0xE0) == 0xE0);
399 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)ss;
400 const unsigned char *address = (const unsigned char *)&sin6->sin6_addr;
401 return sin6->sin6_port == 0 || (address[0] == 0xFF) ||
402 (address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
403 (memcmp(address, zeroes, 15) == 0 &&
404 (address[15] == 0 || address[15] == 1)) ||
405 (memcmp(address, v4prefix, 12) == 0);
411 /* Forget about the ``XOR-metric''. An id is just a path from the
412 root of the tree, so bits are numbered from the start. */
415 id_cmp(const unsigned char *restrict id1, const unsigned char *restrict id2)
417 /* Memcmp is guaranteed to perform an unsigned comparison. */
418 return memcmp(id1, id2, 20);
421 /* Our transaction-ids are 4-bytes long, with the first two bytes identi-
422 fying the kind of request, and the remaining two a sequence number in
426 make_tid(unsigned char *tid_return, const char *prefix, const unsigned short seqno)
428 tid_return[0] = prefix[0] & 0xFF;
429 tid_return[1] = prefix[1] & 0xFF;
430 memcpy(tid_return + 2, &seqno, 2);
434 tid_match(const unsigned char *tid, const char *prefix, unsigned short *seqno_return)
436 if (tid[0] == (prefix[0] & 0xFF) && tid[1] == (prefix[1] & 0xFF)) {
438 memcpy(seqno_return, tid + 2, 2);
445 circular(int from, int to)
449 return x + CIRCULAR_LIST_SIZE;
454 list_elements(struct circular_list *list)
456 return circular(list->head, list->tail);
460 list_empty(struct circular_list *list)
462 return list_elements(list) == 0;
466 list_free(struct circular_list *list)
468 return circular(list->tail + 1, list->head);
472 list_pop(struct circular_list *list, struct sockaddr_storage *ss, socklen_t *sslen)
474 if (list->head == list->tail)
477 memcpy(ss, &list->nodes[list->head].ss, list->nodes[list->head].sslen);
478 *sslen = list->nodes[list->head].sslen;
479 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
485 struct circular_list *list,
487 struct sockaddr_storage *ss,
490 if (list->head == list->tail)
493 int n = random() % (list->tail - list->head);
494 n = (list->head + n) % CIRCULAR_LIST_SIZE;
497 memcpy(id, &list->nodes[n].id, 20);
498 memcpy(ss, &list->nodes[n].ss, list->nodes[n].sslen);
499 *sslen = list->nodes[n].sslen;
503 /* We just learnt about a node, not necessarily a new one. Confirm is 1 if
504 the node sent a message, 2 if it sent us a reply. */
508 const unsigned char *id,
509 const struct sockaddr *sa,
510 const socklen_t salen,
513 struct circular_list *list;
514 if (sa->sa_family == AF_INET)
515 list = confirm >= 2 ? &v4_confirmed : &v4_new;
516 else if (sa->sa_family == AF_INET6)
517 list = confirm >= 2 ? &v6_confirmed : &v6_new;
521 /* A node that sends us a request is most probably bootstrapping.
522 We want to avoid getting our tables full of very young nodes -- only
523 include such a node if we have plenty of space. */
525 if (confirm == 1 && list_free(list) < 32)
528 for (int i = list->head; i != list->tail; i = (i + 1) % CIRCULAR_LIST_SIZE) {
529 struct node *n = &list->nodes[i];
530 if (n->sslen == salen && memcmp(&n->ss, sa, salen) == 0)
534 memcpy(&list->nodes[list->tail].id, id, 160);
535 memcpy(&list->nodes[list->tail].ss, sa, salen);
536 list->nodes[list->tail].sslen = salen;
537 list->tail = (list->tail + 1) % CIRCULAR_LIST_SIZE;
538 if (list->head == list->tail)
539 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
541 printf("%s : new node\n", getAddr(sa, salen));
549 time_t now = time(NULL);
550 if (token_bucket_tokens == 0) {
551 token_bucket_tokens =
552 MIN(MAX_TOKEN_BUCKET_TOKENS, 4 * (int)(now - token_bucket_time));
553 token_bucket_time = now;
555 if (token_bucket_tokens == 0)
557 token_bucket_tokens--;
562 pktSend(const struct Pkt *p)
565 const struct sockaddr *sa = (const struct sockaddr *)&(p->ss);
566 switch (sa->sa_family) {
576 return sendto(s, p->buf, p->len, 0, sa, p->salen);
583 const struct sockaddr *sa,
584 const socklen_t salen)
588 memcpy(&(pkt.ss), sa, sizeof(struct sockaddr_storage));
589 memcpy(pkt.buf, buf, len);
593 return pktSend(&pkt);
594 return write(sockW, &pkt, sizeof(struct Pkt));
599 const struct sockaddr *sa,
600 const socklen_t salen,
601 const unsigned char *tid,
602 const size_t tid_len)
606 int rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
608 COPY(buf, i, myid, 20, 512);
609 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%zu:", tid_len);
611 COPY(buf, i, tid, tid_len, 512);
613 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
616 printf("%s <- PING\n", getAddr(sa, salen));
617 return dht_send(buf, (size_t)i, sa, salen);
626 const struct sockaddr *sa,
627 const socklen_t salen,
628 const unsigned char *tid,
629 const size_t tid_len)
633 int rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:");
635 COPY(buf, i, myid, 20, 512);
636 rc = snprintf(buf + i, 512 - i, "e1:t%zu:", tid_len);
638 COPY(buf, i, tid, tid_len, 512);
640 rc = snprintf(buf + i, 512 - i, "1:y1:re");
643 printf("%s <- PONG\n", getAddr(sa, salen));
644 return dht_send(buf, (size_t)i, sa, salen);
653 const struct sockaddr *sa,
654 const socklen_t salen,
655 const unsigned char *tid,
656 const size_t tid_len,
657 const unsigned char *target,
662 int rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
664 COPY(buf, i, myid, 20, 512);
665 rc = snprintf(buf + i, 512 - i, "6:target20:");
667 COPY(buf, i, target, 20, 512);
673 (want & WANT4) ? "2:n4" : "",
674 (want & WANT6) ? "2:n6" : "");
677 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%zu:", tid_len);
679 COPY(buf, i, tid, tid_len, 512);
681 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
684 printf("%s <- FIND_NODE\n", getAddr(sa, salen));
685 return dht_send(buf, (size_t)i, sa, salen);
694 struct circular_list *list,
699 if (list_empty(list))
702 struct sockaddr_storage ss;
705 if (list_pop(list, &ss, &sslen) == 0)
708 if (list_random(list, NULL, &ss, &sslen) == 0)
712 unsigned char ttid[4];
714 make_tid(ttid, "pn", 0);
715 return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
717 unsigned char id[20];
718 arc4random_buf(id, sizeof id);
719 make_tid(ttid, "fn", 0);
720 return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want);
725 newSock(const char *host, const char *port)
727 struct addrinfo hints;
728 memset(&hints, 0, sizeof(hints));
729 hints.ai_family = AF_UNSPEC;
730 hints.ai_socktype = SOCK_DGRAM;
731 struct addrinfo *res = NULL;
732 int rc = getaddrinfo(host, port, &hints, &res);
734 err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
735 int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
737 err(EXIT_FAILURE, "socket()");
738 if (bind(sock, res->ai_addr, res->ai_addrlen) != 0)
739 err(EXIT_FAILURE, "bind()");
740 rc = fcntl(sock, F_GETFL, 0);
742 err(EXIT_FAILURE, "F_GETFL");
743 rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
745 err(EXIT_FAILURE, "F_SETFL");
756 if (setrlimit(res, &r) == -1) {
757 err(EXIT_FAILURE, "setrlimit()");
763 const struct sockaddr *sa,
764 const socklen_t salen,
765 const unsigned char *tid,
766 const size_t tid_len,
767 const unsigned char *nodes,
768 const size_t nodes_len,
769 const unsigned char *nodes6,
770 const size_t nodes6_len)
774 int rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:");
776 COPY(buf, i, myid, 20, 2048);
778 rc = snprintf(buf + i, 2048 - i, "5:nodes%zu:", nodes_len);
780 COPY(buf, i, nodes, nodes_len, 2048);
782 if (nodes6_len > 0) {
783 rc = snprintf(buf + i, 2048 - i, "6:nodes6%zu:", nodes6_len);
785 COPY(buf, i, nodes6, nodes6_len, 2048);
787 rc = snprintf(buf + i, 2048 - i, "e1:t%zu:", tid_len);
789 COPY(buf, i, tid, tid_len, 2048);
791 rc = snprintf(buf + i, 2048 - i, "1:y1:re");
793 return dht_send(buf, (size_t)i, sa, salen);
801 buffer_random_nodes(int af, unsigned char *nodes)
803 struct circular_list *list;
806 list = &v4_confirmed;
809 list = &v6_confirmed;
815 struct sockaddr_storage ss;
817 unsigned char id[20];
820 if (list_random(list, id, &ss, &sslen) < 1)
824 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
825 memcpy(nodes + n * 26, id, 20);
826 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
827 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
832 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
833 memcpy(nodes + n * 38, id, 20);
834 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
835 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
848 const struct sockaddr *sa,
849 const socklen_t salen,
850 const unsigned char *tid,
851 const size_t tid_len,
854 unsigned char nodes[8 * 26];
855 unsigned char nodes6[8 * 38];
859 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
861 numnodes = buffer_random_nodes(AF_INET, nodes);
863 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
865 printf("%s <- NODES (%d+%d)\n", getAddr(sa, salen), numnodes, numnodes6);
867 sa, salen, tid, tid_len, nodes, numnodes * 26, nodes6, numnodes6 * 38);
872 const struct sockaddr *sa,
873 const socklen_t salen,
874 const unsigned char *tid,
875 const size_t tid_len,
881 int rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, (int)strlen(message));
883 COPY(buf, i, message, (int)strlen(message), 512);
884 rc = snprintf(buf + i, 512 - i, "e1:t%zu:", tid_len);
886 COPY(buf, i, tid, tid_len, 512);
888 rc = snprintf(buf + i, 512 - i, "1:y1:ee");
890 return dht_send(buf, (size_t)i, sa, salen);
898 main(int argc, char **argv)
901 char *ipv4addr = NULL;
902 char *ipv6addr = NULL;
906 opt = getopt(argc, argv, "q4:6:");
915 ipv4addr = strdup(optarg);
918 ipv6addr = strdup(optarg);
930 const char *ourPort = strdup(argv[i++]);
931 if (ipv4addr != NULL) {
932 dht_socket = newSock(ipv4addr, ourPort);
934 if (ipv6addr != NULL) {
935 dht_socket6 = newSock(ipv6addr, ourPort);
938 arc4random_buf(myid, sizeof myid);
939 memcpy(my_v, "1:v4:JB\0\0", 9);
940 memset(&(pkt.ss), 0, sizeof(struct sockaddr_storage));
943 unsigned char ttid[4];
946 struct addrinfo hints, *info, *infop;
947 memset(&hints, 0, sizeof(hints));
948 hints.ai_socktype = SOCK_DGRAM;
951 hints.ai_family = AF_INET6;
952 else if (dht_socket6 < 0)
953 hints.ai_family |= AF_INET;
954 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
956 err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
964 make_tid(ttid, "pn", 0);
965 if (send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4) == -1)
966 err(EXIT_FAILURE, "sendto()");
967 infop = infop->ai_next;
975 close(STDOUT_FILENO);
978 if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, sockets) != 0)
979 err(EXIT_FAILURE, "socketpair()");
980 int sockR = sockets[0];
984 err(EXIT_FAILURE, "fork()");
988 rlimited(RLIMIT_NPROC);
989 rlimited(RLIMIT_FSIZE);
990 rlimited(RLIMIT_NOFILE);
992 unsigned char buf[sizeof(struct Pkt)];
994 n = read(sockR, buf, sizeof buf);
999 if (pktSend((struct Pkt *)buf) == -1)
1005 cap_rights_t caprights;
1006 cap_rights_init(&caprights, CAP_WRITE);
1007 if (cap_rights_limit(STDERR_FILENO, &caprights) != 0)
1008 err(EXIT_FAILURE, "cap_rights_limit(stderr)");
1010 if (cap_rights_limit(STDOUT_FILENO, &caprights) != 0)
1011 err(EXIT_FAILURE, "cap_rights_limit(stdout)");
1012 if (cap_rights_limit(sockW, &caprights) != 0)
1013 err(EXIT_FAILURE, "cap_rights_limit(sockW)");
1014 if (cap_enter() != 0)
1015 err(EXIT_FAILURE, "cap_enter()");
1017 token_bucket_time = time(NULL);
1018 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
1022 err(EXIT_FAILURE, "kqueue()");
1023 struct kevent chs[2];
1026 if (dht_socket != -1) {
1027 EV_SET(&(chs[chsLen]), dht_socket, EVFILT_READ, EV_ADD, 0, 0, NULL);
1030 if (dht_socket6 != -1) {
1031 EV_SET(&(chs[chsLen]), dht_socket6, EVFILT_READ, EV_ADD, 0, 0, NULL);
1035 rlimited(RLIMIT_NPROC);
1036 rlimited(RLIMIT_FSIZE);
1037 rlimited(RLIMIT_NOFILE);
1042 if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
1043 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
1046 tm.tv_sec = random() % 30;
1047 tm.tv_nsec = 1000000 * (random() % 1000);
1051 list_elements(&v4_confirmed),
1052 list_elements(&v6_confirmed),
1053 list_elements(&v4_new),
1054 list_elements(&v6_new));
1056 rc = kevent(kq, chs, chsLen, &ev, 1, &tm);
1058 err(EXIT_FAILURE, "kevent()");
1062 unsigned char buf[MAX_PKT_SIZE];
1063 struct sockaddr_storage source_storage;
1064 struct sockaddr *source = (struct sockaddr *)&source_storage;
1065 socklen_t sourcelen = sizeof(source_storage);
1066 if (ev.flags & EV_ERROR) {
1067 fprintf(stderr, "EV_ERROR: %s\n", strerror((int)(ev.data)));
1069 got = recvfrom((int)ev.ident, buf, MAX_PKT_SIZE, 0, source, &sourcelen);
1071 if (got < 0 || sourcelen > sizeof(struct sockaddr_storage))
1073 if (is_martian(&source_storage))
1075 if (got < MAX_PKT_SIZE) {
1079 printf("%s : overlong message\n", getAddr(source, sourcelen));
1084 unsigned char tid[16];
1085 unsigned char id[20];
1086 unsigned char info_hash[20];
1087 unsigned char target[20];
1088 unsigned char nodes[256];
1089 unsigned char nodes6[1024];
1090 unsigned char token[128];
1091 size_t tid_len = sizeof tid;
1092 size_t token_len = sizeof token;
1093 size_t nodes_len = sizeof nodes;
1094 size_t nodes6_len = sizeof nodes6;
1095 unsigned short port;
1096 unsigned char values[2048];
1097 unsigned char values6[2048];
1098 size_t values_len = sizeof values;
1099 size_t values6_len = sizeof values6;
1101 message = parse_message(
1124 if (id_cmp(id, myid) == 0) {
1127 "%s : received message from self\n",
1128 getAddr(source, sourcelen));
1132 if (message > REPLY) {
1133 /* Rate limit requests. */
1134 if (!token_bucket()) {
1137 "%s : dropping request due to rate limiting\n",
1138 getAddr(source, sourcelen));
1148 "%s : broken node truncates transaction ids\n",
1149 getAddr(source, sourcelen));
1152 if (tid_match(tid, "pn", NULL)) {
1154 printf("%s -> PONG\n", getAddr(source, sourcelen));
1155 new_node(id, source, sourcelen, 2);
1156 } else if (tid_match(tid, "fn", NULL)) {
1159 "%s -> NODES (%zu+%zu)\n",
1160 getAddr(source, sourcelen),
1163 if (nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
1166 "%s : unexpected length for node info\n",
1167 getAddr(source, sourcelen));
1169 new_node(id, source, sourcelen, 2);
1171 for (n = 0; n < nodes_len / 26; n++) {
1172 unsigned char *ni = nodes + n * 26;
1173 struct sockaddr_in sin;
1174 if (id_cmp(ni, myid) == 0)
1176 memset(&sin, 0, sizeof(sin));
1177 sin.sin_family = AF_INET;
1178 memcpy(&sin.sin_addr, ni + 20, 4);
1179 memcpy(&sin.sin_port, ni + 24, 2);
1180 new_node(ni, (struct sockaddr *)&sin, sizeof(sin), 0);
1182 for (n = 0; n < nodes6_len / 38; n++) {
1183 unsigned char *ni = nodes6 + n * 38;
1184 struct sockaddr_in6 sin6;
1185 if (id_cmp(ni, myid) == 0)
1187 memset(&sin6, 0, sizeof(sin6));
1188 sin6.sin6_family = AF_INET6;
1189 memcpy(&sin6.sin6_addr, ni + 20, 16);
1190 memcpy(&sin6.sin6_port, ni + 36, 2);
1191 new_node(ni, (struct sockaddr *)&sin6, sizeof(sin6), 0);
1196 printf("%s : unexpected reply\n", getAddr(source, sourcelen));
1202 printf("%s -> PING (%zu)\n", getAddr(source, sourcelen), tid_len);
1203 new_node(id, source, sourcelen, 1);
1204 send_pong(source, sourcelen, tid, tid_len);
1210 if (message == FIND_NODE)
1211 printf("%s -> FIND_NODE\n", getAddr(source, sourcelen));
1213 printf("%s -> GET_PEERS\n", getAddr(source, sourcelen));
1215 new_node(id, source, sourcelen, 1);
1216 send_random_nodes(source, sourcelen, tid, tid_len, want);
1220 printf("%s -> ANNOUNCE_PEER\n", getAddr(source, sourcelen));
1227 "This node doesn't accept announces");
1234 /* We need to be careful to avoid a positive feedback loop. Make
1235 sure we send at most one packet each time through the select
1238 if (dht_socket6 < 0)
1240 else if (dht_socket < 0)
1243 send4 = (random() % 2) == 1;
1246 int want = dht_socket6 >= 0 && list_free(&v6_new) > 8 ? (WANT4 | WANT6) : 0;
1247 if (!list_empty(&v4_new))
1248 send_request(&v4_new, true, list_free(&v4_new) < 8, want);
1249 else if (!list_empty(&v4_confirmed))
1250 send_request(&v4_confirmed, false, false, want);
1252 int want = dht_socket >= 0 && list_free(&v4_new) > 8 ? (WANT4 | WANT6) : 0;
1253 if (!list_empty(&v6_new))
1254 send_request(&v6_new, true, list_free(&v6_new) < 8, want);
1255 else if (!list_empty(&v6_confirmed))
1256 send_request(&v6_confirmed, false, false, want);
1261 fprintf(stderr, "dht-bootstrap [-q] [-4 ADDR4] [-6 ADDR6] port [node port...]\n");