2 Copyright (c) 2009-2011 by Juliusz Chroboczek
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 #include <netinet/in.h>
35 #include <sys/caprights.h>
36 #include <sys/capsicum.h>
37 #include <sys/event.h>
38 #include <sys/resource.h>
39 #include <sys/socket.h>
42 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
44 #define MAX_PKT_SIZE 1536
51 #define ANNOUNCE_PEER 5
56 static const unsigned char zeroes[20] = {0};
57 static const unsigned char v4prefix[16] =
58 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0};
60 static unsigned char myid[20];
61 static unsigned char my_v[9];
63 static int dht_socket = -1;
64 static int dht_socket6 = -1;
67 unsigned char id[160];
68 struct sockaddr_storage ss;
73 #define CIRCULAR_LIST_SIZE 256
75 struct circular_list {
78 struct node nodes[CIRCULAR_LIST_SIZE];
81 static struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
83 #define MAX_TOKEN_BUCKET_TOKENS 40
84 static time_t token_bucket_time;
85 static int token_bucket_tokens;
87 static bool verbose = true;
90 unsigned char buf[MAX_PKT_SIZE];
91 struct sockaddr_storage ss;
97 static struct Pkt pkt;
98 static int sockW = -1;
100 // ------------------------ >8 ------------------------
103 getAddr(const struct sockaddr *sa, const socklen_t saLen)
105 static char host[NI_MAXHOST];
106 static char port[NI_MAXSERV];
107 static char addr[64];
108 int rc = getnameinfo(
115 NI_NUMERICHOST | NI_NUMERICSERV);
117 fprintf(stderr, "getnameinfo: %s\n", gai_strerror(rc));
120 snprintf(addr, sizeof addr, "[%s]:%s", host, port);
126 const unsigned char *buf,
128 unsigned char *tid_return,
130 unsigned char *id_return,
131 unsigned char *info_hash_return,
132 unsigned char *target_return,
133 unsigned short *port_return,
134 unsigned char *token_return,
136 unsigned char *nodes_return,
138 unsigned char *nodes6_return,
140 unsigned char *values_return,
142 unsigned char *values6_return,
145 const struct sockaddr *sa,
146 const socklen_t saLen)
148 /* This code will happily crash if the buffer is not NUL-terminated. */
149 if (buf[buflen] != '\0') {
151 printf("%s : parse_message with unterminated buffer\n", getAddr(sa, saLen));
155 #define CHECK(ptr, len) \
156 if (((const unsigned char *)ptr) + (len) > (buf) + (buflen)) \
163 p = memmem(buf, buflen, "1:t", 3);
165 l = strtoul((const char *)p + 3, &q, 10);
166 if (q && *q == ':' && l > 0 && l < *tid_len) {
168 memcpy(tid_return, q + 1, l);
175 p = memmem(buf, buflen, "2:id20:", 7);
178 memcpy(id_return, p + 7, 20);
180 memset(id_return, 0, 20);
183 if (info_hash_return) {
184 p = memmem(buf, buflen, "9:info_hash20:", 14);
187 memcpy(info_hash_return, p + 14, 20);
189 memset(info_hash_return, 0, 20);
193 p = memmem(buf, buflen, "porti", 5);
195 l = strtoul((const char *)p + 5, &q, 10);
196 if (q && *q == 'e' && l > 0 && l < 0x10000)
197 *port_return = (unsigned short)l;
204 p = memmem(buf, buflen, "6:target20:", 11);
207 memcpy(target_return, p + 11, 20);
209 memset(target_return, 0, 20);
213 p = memmem(buf, buflen, "5:token", 7);
215 l = strtoul((const char *)p + 7, &q, 10);
216 if (q && *q == ':' && l > 0 && l < *token_len) {
218 memcpy(token_return, q + 1, l);
227 p = memmem(buf, buflen, "5:nodes", 7);
229 l = strtoul((const char *)p + 7, &q, 10);
230 if (q && *q == ':' && l > 0 && l < *nodes_len) {
232 memcpy(nodes_return, q + 1, l);
241 p = memmem(buf, buflen, "6:nodes6", 8);
243 l = strtoul((const char *)p + 8, &q, 10);
244 if (q && *q == ':' && l > 0 && l < *nodes6_len) {
246 memcpy(nodes6_return, q + 1, l);
254 if (values_len || values6_len) {
255 p = memmem(buf, buflen, "6:valuesl", 9);
257 size_t i = p - buf + 9;
258 unsigned long j = 0, j6 = 0;
260 l = strtoul((const char *)buf + i, &q, 10);
261 if (q && *q == ':' && l > 0) {
264 if (j + l > *values_len)
266 i = q + 1 + l - (const char *)buf;
267 memcpy((char *)values_return + j, q + 1, l);
269 } else if (l == 18) {
270 if (j6 + l > *values6_len)
272 i = q + 1 + l - (const char *)buf;
273 memcpy((char *)values6_return + j6, q + 1, l);
278 "%s : received weird value: %d bytes\n",
281 i = q + 1 + l - (const char *)buf;
287 if (i >= buflen || buf[i] != 'e')
289 printf("%s : unexpected end for values\n", getAddr(sa, saLen));
301 p = memmem(buf, buflen, "4:wantl", 7);
303 size_t i = p - buf + 7;
305 while (buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
306 i + 2 + buf[i] - '0' < buflen) {
307 CHECK(buf + i + 2, buf[i] - '0');
308 if (buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
309 *want_return |= WANT4;
310 else if (buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
311 *want_return |= WANT6;
314 "%s : unexpected want flag: %c\n", getAddr(sa, saLen), buf[i]);
315 i += 2 + buf[i] - '0';
317 if (i >= buflen || buf[i] != 'e')
319 printf("%s : unexpected end for want\n", getAddr(sa, saLen));
327 if (memmem(buf, buflen, "1:y1:r", 6))
329 if (memmem(buf, buflen, "1:y1:e", 6))
331 if (!memmem(buf, buflen, "1:y1:q", 6))
333 if (memmem(buf, buflen, "1:q4:ping", 9))
335 if (memmem(buf, buflen, "1:q9:find_node", 14))
337 if (memmem(buf, buflen, "1:q9:get_peers", 14))
339 if (memmem(buf, buflen, "1:q13:announce_peer", 19))
340 return ANNOUNCE_PEER;
345 printf(": truncated message\n");
354 /* We could use a proper bencoding printer and parser, but the format of
355 DHT messages is fairly stylised, so this seemed simpler. */
357 #define CHECK(offset, delta, size) \
358 if (delta < 0 || offset + delta > size) \
361 #define INC(offset, delta, size) \
362 CHECK(offset, delta, size); \
365 #define COPY(buf, offset, src, delta, size) \
366 CHECK(offset, delta, size); \
367 memcpy(buf + offset, src, delta); \
370 #define ADD_V(buf, offset, size) COPY(buf, offset, my_v, (sizeof my_v), size)
373 is_martian(const struct sockaddr_storage *ss)
375 switch (((const struct sockaddr *)ss)->sa_family) {
377 const struct sockaddr_in *sin = (const struct sockaddr_in *)ss;
378 const unsigned char *address = (const unsigned char *)&sin->sin_addr;
379 return sin->sin_port == 0 || (address[0] == 0) || (address[0] == 127) ||
380 ((address[0] & 0xE0) == 0xE0);
383 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)ss;
384 const unsigned char *address = (const unsigned char *)&sin6->sin6_addr;
385 return sin6->sin6_port == 0 || (address[0] == 0xFF) ||
386 (address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
387 (memcmp(address, zeroes, 15) == 0 &&
388 (address[15] == 0 || address[15] == 1)) ||
389 (memcmp(address, v4prefix, 12) == 0);
395 /* Forget about the ``XOR-metric''. An id is just a path from the
396 root of the tree, so bits are numbered from the start. */
399 id_cmp(const unsigned char *restrict id1, const unsigned char *restrict id2)
401 /* Memcmp is guaranteed to perform an unsigned comparison. */
402 return memcmp(id1, id2, 20);
405 /* Our transaction-ids are 4-bytes long, with the first two bytes identi-
406 fying the kind of request, and the remaining two a sequence number in
410 make_tid(unsigned char *tid_return, const char *prefix, const unsigned short seqno)
412 tid_return[0] = prefix[0] & 0xFF;
413 tid_return[1] = prefix[1] & 0xFF;
414 memcpy(tid_return + 2, &seqno, 2);
418 tid_match(const unsigned char *tid, const char *prefix, unsigned short *seqno_return)
420 if (tid[0] == (prefix[0] & 0xFF) && tid[1] == (prefix[1] & 0xFF)) {
422 memcpy(seqno_return, tid + 2, 2);
429 circular(int from, int to)
433 return x + CIRCULAR_LIST_SIZE;
438 list_elements(struct circular_list *list)
440 return circular(list->head, list->tail);
444 list_empty(struct circular_list *list)
446 return list_elements(list) == 0;
450 list_free(struct circular_list *list)
452 return circular(list->tail + 1, list->head);
456 list_pop(struct circular_list *list, struct sockaddr_storage *ss, socklen_t *sslen)
458 if (list->head == list->tail)
461 memcpy(ss, &list->nodes[list->head].ss, list->nodes[list->head].sslen);
462 *sslen = list->nodes[list->head].sslen;
463 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
469 struct circular_list *list,
471 struct sockaddr_storage *ss,
474 if (list->head == list->tail)
477 int n = random() % (list->tail - list->head);
478 n = (list->head + n) % CIRCULAR_LIST_SIZE;
481 memcpy(id, &list->nodes[n].id, 20);
482 memcpy(ss, &list->nodes[n].ss, list->nodes[n].sslen);
483 *sslen = list->nodes[n].sslen;
487 /* We just learnt about a node, not necessarily a new one. Confirm is 1 if
488 the node sent a message, 2 if it sent us a reply. */
492 const unsigned char *id,
493 const struct sockaddr *sa,
494 const socklen_t salen,
497 struct circular_list *list;
498 if (sa->sa_family == AF_INET)
499 list = confirm >= 2 ? &v4_confirmed : &v4_new;
500 else if (sa->sa_family == AF_INET6)
501 list = confirm >= 2 ? &v6_confirmed : &v6_new;
505 /* A node that sends us a request is most probably bootstrapping.
506 We want to avoid getting our tables full of very young nodes -- only
507 include such a node if we have plenty of space. */
509 if (confirm == 1 && list_free(list) < 32)
512 for (int i = list->head; i != list->tail; i = (i + 1) % CIRCULAR_LIST_SIZE) {
513 struct node *n = &list->nodes[i];
514 if (n->sslen == salen && memcmp(&n->ss, sa, salen) == 0)
518 memcpy(&list->nodes[list->tail].id, id, 160);
519 memcpy(&list->nodes[list->tail].ss, sa, salen);
520 list->nodes[list->tail].sslen = salen;
521 list->tail = (list->tail + 1) % CIRCULAR_LIST_SIZE;
522 if (list->head == list->tail)
523 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
525 printf("%s : new node\n", getAddr(sa, salen));
533 time_t now = time(NULL);
534 if (token_bucket_tokens == 0) {
535 token_bucket_tokens =
536 MIN(MAX_TOKEN_BUCKET_TOKENS, 4 * (int)(now - token_bucket_time));
537 token_bucket_time = now;
539 if (token_bucket_tokens == 0)
541 token_bucket_tokens--;
546 pktSend(const struct Pkt *p)
549 const struct sockaddr *sa = (const struct sockaddr *)&(p->ss);
550 switch (sa->sa_family) {
560 return sendto(s, p->buf, p->len, 0, sa, p->salen);
567 const struct sockaddr *sa,
568 const socklen_t salen)
572 memcpy(&(pkt.ss), sa, sizeof(struct sockaddr_storage));
573 memcpy(pkt.buf, buf, len);
577 return pktSend(&pkt);
578 return write(sockW, &pkt, sizeof(struct Pkt));
583 const struct sockaddr *sa,
584 const socklen_t salen,
585 const unsigned char *tid,
586 const size_t tid_len)
590 int rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
592 COPY(buf, i, myid, 20, 512);
593 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%zu:", tid_len);
595 COPY(buf, i, tid, tid_len, 512);
597 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
600 printf("%s <- PING\n", getAddr(sa, salen));
601 return dht_send(buf, (size_t)i, sa, salen);
610 const struct sockaddr *sa,
611 const socklen_t salen,
612 const unsigned char *tid,
613 const size_t tid_len)
617 int rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:");
619 COPY(buf, i, myid, 20, 512);
620 rc = snprintf(buf + i, 512 - i, "e1:t%zu:", tid_len);
622 COPY(buf, i, tid, tid_len, 512);
624 rc = snprintf(buf + i, 512 - i, "1:y1:re");
627 printf("%s <- PONG\n", getAddr(sa, salen));
628 return dht_send(buf, (size_t)i, sa, salen);
637 const struct sockaddr *sa,
638 const socklen_t salen,
639 const unsigned char *tid,
640 const size_t tid_len,
641 const unsigned char *target,
646 int rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
648 COPY(buf, i, myid, 20, 512);
649 rc = snprintf(buf + i, 512 - i, "6:target20:");
651 COPY(buf, i, target, 20, 512);
657 (want & WANT4) ? "2:n4" : "",
658 (want & WANT6) ? "2:n6" : "");
661 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%zu:", tid_len);
663 COPY(buf, i, tid, tid_len, 512);
665 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
668 printf("%s <- FIND_NODE\n", getAddr(sa, salen));
669 return dht_send(buf, (size_t)i, sa, salen);
678 struct circular_list *list,
683 if (list_empty(list))
686 struct sockaddr_storage ss;
689 if (list_pop(list, &ss, &sslen) == 0)
692 if (list_random(list, NULL, &ss, &sslen) == 0)
696 unsigned char ttid[4];
698 make_tid(ttid, "pn", 0);
699 return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
701 unsigned char id[20];
702 arc4random_buf(id, sizeof id);
703 make_tid(ttid, "fn", 0);
704 return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want);
709 newSock(const char *host, const char *port)
711 struct addrinfo hints;
712 memset(&hints, 0, sizeof(hints));
713 hints.ai_family = AF_UNSPEC;
714 hints.ai_socktype = SOCK_DGRAM;
715 struct addrinfo *res = NULL;
716 int rc = getaddrinfo(host, port, &hints, &res);
718 err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
719 int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
721 err(EXIT_FAILURE, "socket()");
722 if (bind(sock, res->ai_addr, res->ai_addrlen) != 0)
723 err(EXIT_FAILURE, "bind()");
724 rc = fcntl(sock, F_GETFL, 0);
726 err(EXIT_FAILURE, "F_GETFL");
727 rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
729 err(EXIT_FAILURE, "F_SETFL");
740 if (setrlimit(res, &r) == -1) {
741 err(EXIT_FAILURE, "setrlimit()");
747 const struct sockaddr *sa,
748 const socklen_t salen,
749 const unsigned char *tid,
750 const size_t tid_len,
751 const unsigned char *nodes,
752 const size_t nodes_len,
753 const unsigned char *nodes6,
754 const size_t nodes6_len)
758 int rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:");
760 COPY(buf, i, myid, 20, 2048);
762 rc = snprintf(buf + i, 2048 - i, "5:nodes%zu:", nodes_len);
764 COPY(buf, i, nodes, nodes_len, 2048);
766 if (nodes6_len > 0) {
767 rc = snprintf(buf + i, 2048 - i, "6:nodes6%zu:", nodes6_len);
769 COPY(buf, i, nodes6, nodes6_len, 2048);
771 rc = snprintf(buf + i, 2048 - i, "e1:t%zu:", tid_len);
773 COPY(buf, i, tid, tid_len, 2048);
775 rc = snprintf(buf + i, 2048 - i, "1:y1:re");
777 return dht_send(buf, (size_t)i, sa, salen);
785 buffer_random_nodes(int af, unsigned char *nodes)
787 struct circular_list *list;
790 list = &v4_confirmed;
793 list = &v6_confirmed;
799 struct sockaddr_storage ss;
801 unsigned char id[20];
804 if (list_random(list, id, &ss, &sslen) < 1)
808 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
809 memcpy(nodes + n * 26, id, 20);
810 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
811 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
816 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
817 memcpy(nodes + n * 38, id, 20);
818 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
819 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
832 const struct sockaddr *sa,
833 const socklen_t salen,
834 const unsigned char *tid,
835 const size_t tid_len,
838 unsigned char nodes[8 * 26];
839 unsigned char nodes6[8 * 38];
843 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
845 numnodes = buffer_random_nodes(AF_INET, nodes);
847 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
849 printf("%s <- NODES (%d+%d)\n", getAddr(sa, salen), numnodes, numnodes6);
851 sa, salen, tid, tid_len, nodes, numnodes * 26, nodes6, numnodes6 * 38);
856 const struct sockaddr *sa,
857 const socklen_t salen,
858 const unsigned char *tid,
859 const size_t tid_len,
865 int rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, (int)strlen(message));
867 COPY(buf, i, message, (int)strlen(message), 512);
868 rc = snprintf(buf + i, 512 - i, "e1:t%zu:", tid_len);
870 COPY(buf, i, tid, tid_len, 512);
872 rc = snprintf(buf + i, 512 - i, "1:y1:ee");
874 return dht_send(buf, (size_t)i, sa, salen);
882 main(int argc, char **argv)
885 char *ipv4addr = NULL;
886 char *ipv6addr = NULL;
890 opt = getopt(argc, argv, "q4:6:");
899 ipv4addr = strdup(optarg);
902 ipv6addr = strdup(optarg);
914 const char *ourPort = strdup(argv[i++]);
915 if (ipv4addr != NULL) {
916 dht_socket = newSock(ipv4addr, ourPort);
918 if (ipv6addr != NULL) {
919 dht_socket6 = newSock(ipv6addr, ourPort);
922 arc4random_buf(myid, sizeof myid);
923 memcpy(my_v, "1:v4:JB\0\0", 9);
924 memset(&(pkt.ss), 0, sizeof(struct sockaddr_storage));
927 unsigned char ttid[4];
930 struct addrinfo hints, *info, *infop;
931 memset(&hints, 0, sizeof(hints));
932 hints.ai_socktype = SOCK_DGRAM;
935 hints.ai_family = AF_INET6;
936 else if (dht_socket6 < 0)
937 hints.ai_family |= AF_INET;
938 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
940 err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
948 make_tid(ttid, "pn", 0);
949 if (send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4) == -1)
950 err(EXIT_FAILURE, "sendto()");
951 infop = infop->ai_next;
959 close(STDOUT_FILENO);
962 if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, sockets) != 0)
963 err(EXIT_FAILURE, "socketpair()");
964 int sockR = sockets[0];
968 err(EXIT_FAILURE, "fork()");
972 rlimited(RLIMIT_NPROC);
973 rlimited(RLIMIT_FSIZE);
974 rlimited(RLIMIT_NOFILE);
976 unsigned char buf[sizeof(struct Pkt)];
978 n = read(sockR, buf, sizeof buf);
983 if (pktSend((struct Pkt *)buf) == -1)
989 cap_rights_t caprights;
990 cap_rights_init(&caprights, CAP_WRITE);
991 if (cap_rights_limit(STDERR_FILENO, &caprights) != 0)
992 err(EXIT_FAILURE, "cap_rights_limit(stderr)");
994 if (cap_rights_limit(STDOUT_FILENO, &caprights) != 0)
995 err(EXIT_FAILURE, "cap_rights_limit(stdout)");
996 if (cap_rights_limit(sockW, &caprights) != 0)
997 err(EXIT_FAILURE, "cap_rights_limit(sockW)");
998 if (cap_enter() != 0)
999 err(EXIT_FAILURE, "cap_enter()");
1001 token_bucket_time = time(NULL);
1002 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
1006 err(EXIT_FAILURE, "kqueue()");
1007 struct kevent chs[2];
1010 if (dht_socket != -1) {
1011 EV_SET(&(chs[chsLen]), dht_socket, EVFILT_READ, EV_ADD, 0, 0, NULL);
1014 if (dht_socket6 != -1) {
1015 EV_SET(&(chs[chsLen]), dht_socket6, EVFILT_READ, EV_ADD, 0, 0, NULL);
1019 rlimited(RLIMIT_NPROC);
1020 rlimited(RLIMIT_FSIZE);
1021 rlimited(RLIMIT_NOFILE);
1026 if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
1027 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
1030 tm.tv_sec = random() % 30;
1031 tm.tv_nsec = 1000000 * (random() % 1000);
1035 list_elements(&v4_confirmed),
1036 list_elements(&v6_confirmed),
1037 list_elements(&v4_new),
1038 list_elements(&v6_new));
1040 rc = kevent(kq, chs, chsLen, &ev, 1, &tm);
1042 err(EXIT_FAILURE, "kevent()");
1046 unsigned char buf[MAX_PKT_SIZE];
1047 struct sockaddr_storage source_storage;
1048 struct sockaddr *source = (struct sockaddr *)&source_storage;
1049 socklen_t sourcelen = sizeof(source_storage);
1050 if (ev.flags & EV_ERROR) {
1051 fprintf(stderr, "EV_ERROR: %s\n", strerror((int)(ev.data)));
1053 got = recvfrom((int)ev.ident, buf, MAX_PKT_SIZE, 0, source, &sourcelen);
1055 if (got < 0 || sourcelen > sizeof(struct sockaddr_storage))
1057 if (is_martian(&source_storage))
1059 if (got < MAX_PKT_SIZE) {
1063 printf("%s : overlong message\n", getAddr(source, sourcelen));
1068 unsigned char tid[16];
1069 unsigned char id[20];
1070 unsigned char info_hash[20];
1071 unsigned char target[20];
1072 unsigned char nodes[256];
1073 unsigned char nodes6[1024];
1074 unsigned char token[128];
1075 size_t tid_len = sizeof tid;
1076 size_t token_len = sizeof token;
1077 size_t nodes_len = sizeof nodes;
1078 size_t nodes6_len = sizeof nodes6;
1079 unsigned short port;
1080 unsigned char values[2048];
1081 unsigned char values6[2048];
1082 size_t values_len = sizeof values;
1083 size_t values6_len = sizeof values6;
1085 message = parse_message(
1108 if (id_cmp(id, myid) == 0) {
1111 "%s : received message from self\n",
1112 getAddr(source, sourcelen));
1116 if (message > REPLY) {
1117 /* Rate limit requests. */
1118 if (!token_bucket()) {
1121 "%s : dropping request due to rate limiting\n",
1122 getAddr(source, sourcelen));
1132 "%s : broken node truncates transaction ids\n",
1133 getAddr(source, sourcelen));
1136 if (tid_match(tid, "pn", NULL)) {
1138 printf("%s -> PONG\n", getAddr(source, sourcelen));
1139 new_node(id, source, sourcelen, 2);
1140 } else if (tid_match(tid, "fn", NULL)) {
1143 "%s -> NODES (%zu+%zu)\n",
1144 getAddr(source, sourcelen),
1147 if (nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
1150 "%s : unexpected length for node info\n",
1151 getAddr(source, sourcelen));
1153 new_node(id, source, sourcelen, 2);
1155 for (n = 0; n < nodes_len / 26; n++) {
1156 unsigned char *ni = nodes + n * 26;
1157 struct sockaddr_in sin;
1158 if (id_cmp(ni, myid) == 0)
1160 memset(&sin, 0, sizeof(sin));
1161 sin.sin_family = AF_INET;
1162 memcpy(&sin.sin_addr, ni + 20, 4);
1163 memcpy(&sin.sin_port, ni + 24, 2);
1164 new_node(ni, (struct sockaddr *)&sin, sizeof(sin), 0);
1166 for (n = 0; n < nodes6_len / 38; n++) {
1167 unsigned char *ni = nodes6 + n * 38;
1168 struct sockaddr_in6 sin6;
1169 if (id_cmp(ni, myid) == 0)
1171 memset(&sin6, 0, sizeof(sin6));
1172 sin6.sin6_family = AF_INET6;
1173 memcpy(&sin6.sin6_addr, ni + 20, 16);
1174 memcpy(&sin6.sin6_port, ni + 36, 2);
1175 new_node(ni, (struct sockaddr *)&sin6, sizeof(sin6), 0);
1180 printf("%s : unexpected reply\n", getAddr(source, sourcelen));
1186 printf("%s -> PING (%zu)\n", getAddr(source, sourcelen), tid_len);
1187 new_node(id, source, sourcelen, 1);
1188 send_pong(source, sourcelen, tid, tid_len);
1194 if (message == FIND_NODE)
1195 printf("%s -> FIND_NODE\n", getAddr(source, sourcelen));
1197 printf("%s -> GET_PEERS\n", getAddr(source, sourcelen));
1199 new_node(id, source, sourcelen, 1);
1200 send_random_nodes(source, sourcelen, tid, tid_len, want);
1204 printf("%s -> ANNOUNCE_PEER\n", getAddr(source, sourcelen));
1211 "This node doesn't accept announces");
1218 /* We need to be careful to avoid a positive feedback loop. Make
1219 sure we send at most one packet each time through the select
1222 if (dht_socket6 < 0)
1224 else if (dht_socket < 0)
1227 send4 = (random() % 2) == 1;
1230 int want = dht_socket6 >= 0 && list_free(&v6_new) > 8 ? (WANT4 | WANT6) : 0;
1231 if (!list_empty(&v4_new))
1232 send_request(&v4_new, true, list_free(&v4_new) < 8, want);
1233 else if (!list_empty(&v4_confirmed))
1234 send_request(&v4_confirmed, false, false, want);
1236 int want = dht_socket >= 0 && list_free(&v4_new) > 8 ? (WANT4 | WANT6) : 0;
1237 if (!list_empty(&v6_new))
1238 send_request(&v6_new, true, list_free(&v6_new) < 8, want);
1239 else if (!list_empty(&v6_confirmed))
1240 send_request(&v6_confirmed, false, false, want);
1245 fprintf(stderr, "dht-bootstrap [-q] [-4 ADDR4] [-6 ADDR6] port [node port...]\n");