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
28 #include <netinet/in.h>
36 #include <sys/caprights.h>
37 #include <sys/capsicum.h>
38 #include <sys/event.h>
39 #include <sys/resource.h>
40 #include <sys/socket.h>
43 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
45 #define MAX_PKT_SIZE 1536
52 #define ANNOUNCE_PEER 5
57 static const unsigned char zeroes[20] = {0};
58 static const unsigned char v4prefix[16] =
59 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0};
61 static unsigned char myid[20];
62 static unsigned char my_v[9];
64 static int dht_socket = -1;
65 static int dht_socket6 = -1;
68 unsigned char id[160];
69 struct sockaddr_storage ss;
74 #define CIRCULAR_LIST_SIZE 256
76 struct circular_list {
79 struct node nodes[CIRCULAR_LIST_SIZE];
82 static struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
84 #define MAX_TOKEN_BUCKET_TOKENS 40
85 static time_t token_bucket_time;
86 static int token_bucket_tokens;
88 static bool verbose = true;
91 unsigned char buf[MAX_PKT_SIZE];
92 struct sockaddr_storage ss;
98 static struct Pkt pkt;
99 static int sockW = -1;
101 // ------------------------ >8 ------------------------
104 getAddr(const struct sockaddr *sa, const socklen_t saLen)
106 static char host[NI_MAXHOST];
107 static char port[NI_MAXSERV];
108 static char addr[64];
109 int rc = getnameinfo(
116 NI_NUMERICHOST | NI_NUMERICSERV);
118 fprintf(stderr, "getnameinfo: %s\n", gai_strerror(rc));
121 snprintf(addr, sizeof addr, "[%s]:%s", host, port);
126 stricttol(const char *p, unsigned long *l, char **q)
128 if ((isdigit((int)(p[0])) == 0) || (p[0] == '0'))
131 *l = strtoul(p, q, 10);
141 const unsigned char *buf,
143 unsigned char *tid_return,
145 unsigned char *id_return,
146 unsigned char *info_hash_return,
147 unsigned char *target_return,
148 unsigned short *port_return,
149 unsigned char *token_return,
151 unsigned char *nodes_return,
153 unsigned char *nodes6_return,
155 unsigned char *values_return,
157 unsigned char *values6_return,
160 const struct sockaddr *sa,
161 const socklen_t saLen)
163 /* This code will happily crash if the buffer is not NUL-terminated. */
164 if (buf[buflen] != '\0') {
166 printf("%s : parse_message with unterminated buffer\n", getAddr(sa, saLen));
170 #define CHECK(ptr, len) \
171 if (((const unsigned char *)ptr) + (len) > (buf) + (buflen)) \
178 p = memmem(buf, buflen, "1:t", 3);
180 if (stricttol((const char *)p + 3, &l, &q) && (q && *q == ':') &&
181 (l > 0 && l < *tid_len)) {
183 memcpy(tid_return, q + 1, l);
190 p = memmem(buf, buflen, "2:id20:", 7);
193 memcpy(id_return, p + 7, 20);
195 memset(id_return, 0, 20);
198 if (info_hash_return) {
199 p = memmem(buf, buflen, "9:info_hash20:", 14);
202 memcpy(info_hash_return, p + 14, 20);
204 memset(info_hash_return, 0, 20);
208 p = memmem(buf, buflen, "porti", 5);
210 if (stricttol((const char *)p + 5, &l, &q) && (q && *q == 'e') &&
211 (l > 0 && l < 0x10000))
212 *port_return = (unsigned short)l;
219 p = memmem(buf, buflen, "6:target20:", 11);
222 memcpy(target_return, p + 11, 20);
224 memset(target_return, 0, 20);
228 p = memmem(buf, buflen, "5:token", 7);
230 if (stricttol((const char *)p + 7, &l, &q) && (q && *q == ':') &&
231 (l > 0 && l < *token_len)) {
233 memcpy(token_return, q + 1, l);
242 p = memmem(buf, buflen, "5:nodes", 7);
244 if (stricttol((const char *)p + 7, &l, &q) && (q && *q == ':') &&
245 (l > 0 && l < *nodes_len)) {
247 memcpy(nodes_return, q + 1, l);
256 p = memmem(buf, buflen, "6:nodes6", 8);
258 if (stricttol((const char *)p + 8, &l, &q) && (q && *q == ':') &&
259 (l > 0 && l < *nodes6_len)) {
261 memcpy(nodes6_return, q + 1, l);
269 if (values_len || values6_len) {
270 p = memmem(buf, buflen, "6:valuesl", 9);
272 size_t i = p - buf + 9;
273 unsigned long j = 0, j6 = 0;
275 if (stricttol((const char *)buf + i, &l, &q) && (q && *q == ':') &&
279 if (j + l > *values_len)
281 i = q + 1 + l - (const char *)buf;
282 memcpy((char *)values_return + j, q + 1, l);
284 } else if (l == 18) {
285 if (j6 + l > *values6_len)
287 i = q + 1 + l - (const char *)buf;
288 memcpy((char *)values6_return + j6, q + 1, l);
293 "%s : received weird value: %d bytes\n",
296 i = q + 1 + l - (const char *)buf;
302 if (i >= buflen || buf[i] != 'e')
304 printf("%s : unexpected end for values\n", getAddr(sa, saLen));
316 p = memmem(buf, buflen, "4:wantl", 7);
318 size_t i = p - buf + 7;
320 while (buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
321 i + 2 + buf[i] - '0' < buflen) {
322 CHECK(buf + i + 2, buf[i] - '0');
323 if (buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
324 *want_return |= WANT4;
325 else if (buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
326 *want_return |= WANT6;
329 "%s : unexpected want flag: %c\n", getAddr(sa, saLen), buf[i]);
330 i += 2 + buf[i] - '0';
332 if (i >= buflen || buf[i] != 'e')
334 printf("%s : unexpected end for want\n", getAddr(sa, saLen));
342 if (memmem(buf, buflen, "1:y1:r", 6))
344 if (memmem(buf, buflen, "1:y1:e", 6))
346 if (!memmem(buf, buflen, "1:y1:q", 6))
348 if (memmem(buf, buflen, "1:q4:ping", 9))
350 if (memmem(buf, buflen, "1:q9:find_node", 14))
352 if (memmem(buf, buflen, "1:q9:get_peers", 14))
354 if (memmem(buf, buflen, "1:q13:announce_peer", 19))
355 return ANNOUNCE_PEER;
360 printf(": truncated message\n");
369 /* We could use a proper bencoding printer and parser, but the format of
370 DHT messages is fairly stylised, so this seemed simpler. */
372 #define CHECK(offset, delta, size) \
373 if (delta < 0 || offset + delta > size) \
376 #define INC(offset, delta, size) \
377 CHECK(offset, delta, size); \
380 #define COPY(buf, offset, src, delta, size) \
381 CHECK(offset, delta, size); \
382 memcpy(buf + offset, src, delta); \
385 #define ADD_V(buf, offset, size) COPY(buf, offset, my_v, (sizeof my_v), size)
388 is_martian(const struct sockaddr_storage *ss)
390 switch (((const struct sockaddr *)ss)->sa_family) {
392 const struct sockaddr_in *sin = (const struct sockaddr_in *)ss;
393 const unsigned char *address = (const unsigned char *)&sin->sin_addr;
394 return sin->sin_port == 0 || (address[0] == 0) || (address[0] == 127) ||
395 ((address[0] & 0xE0) == 0xE0);
398 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)ss;
399 const unsigned char *address = (const unsigned char *)&sin6->sin6_addr;
400 return sin6->sin6_port == 0 || (address[0] == 0xFF) ||
401 (address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
402 (memcmp(address, zeroes, 15) == 0 &&
403 (address[15] == 0 || address[15] == 1)) ||
404 (memcmp(address, v4prefix, 12) == 0);
410 /* Forget about the ``XOR-metric''. An id is just a path from the
411 root of the tree, so bits are numbered from the start. */
414 id_cmp(const unsigned char *restrict id1, const unsigned char *restrict id2)
416 /* Memcmp is guaranteed to perform an unsigned comparison. */
417 return memcmp(id1, id2, 20);
420 /* Our transaction-ids are 4-bytes long, with the first two bytes identi-
421 fying the kind of request, and the remaining two a sequence number in
425 make_tid(unsigned char *tid_return, const char *prefix, const unsigned short seqno)
427 tid_return[0] = prefix[0] & 0xFF;
428 tid_return[1] = prefix[1] & 0xFF;
429 memcpy(tid_return + 2, &seqno, 2);
433 tid_match(const unsigned char *tid, const char *prefix, unsigned short *seqno_return)
435 if (tid[0] == (prefix[0] & 0xFF) && tid[1] == (prefix[1] & 0xFF)) {
437 memcpy(seqno_return, tid + 2, 2);
444 circular(int from, int to)
448 return x + CIRCULAR_LIST_SIZE;
453 list_elements(struct circular_list *list)
455 return circular(list->head, list->tail);
459 list_empty(struct circular_list *list)
461 return list_elements(list) == 0;
465 list_free(struct circular_list *list)
467 return circular(list->tail + 1, list->head);
471 list_pop(struct circular_list *list, struct sockaddr_storage *ss, socklen_t *sslen)
473 if (list->head == list->tail)
476 memcpy(ss, &list->nodes[list->head].ss, list->nodes[list->head].sslen);
477 *sslen = list->nodes[list->head].sslen;
478 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
484 struct circular_list *list,
486 struct sockaddr_storage *ss,
489 if (list->head == list->tail)
492 int n = random() % (list->tail - list->head);
493 n = (list->head + n) % CIRCULAR_LIST_SIZE;
496 memcpy(id, &list->nodes[n].id, 20);
497 memcpy(ss, &list->nodes[n].ss, list->nodes[n].sslen);
498 *sslen = list->nodes[n].sslen;
502 /* We just learnt about a node, not necessarily a new one. Confirm is 1 if
503 the node sent a message, 2 if it sent us a reply. */
507 const unsigned char *id,
508 const struct sockaddr *sa,
509 const socklen_t salen,
512 struct circular_list *list;
513 if (sa->sa_family == AF_INET)
514 list = confirm >= 2 ? &v4_confirmed : &v4_new;
515 else if (sa->sa_family == AF_INET6)
516 list = confirm >= 2 ? &v6_confirmed : &v6_new;
520 /* A node that sends us a request is most probably bootstrapping.
521 We want to avoid getting our tables full of very young nodes -- only
522 include such a node if we have plenty of space. */
524 if (confirm == 1 && list_free(list) < 32)
527 for (int i = list->head; i != list->tail; i = (i + 1) % CIRCULAR_LIST_SIZE) {
528 struct node *n = &list->nodes[i];
529 if (n->sslen == salen && memcmp(&n->ss, sa, salen) == 0)
533 memcpy(&list->nodes[list->tail].id, id, 160);
534 memcpy(&list->nodes[list->tail].ss, sa, salen);
535 list->nodes[list->tail].sslen = salen;
536 list->tail = (list->tail + 1) % CIRCULAR_LIST_SIZE;
537 if (list->head == list->tail)
538 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
540 printf("%s : new node\n", getAddr(sa, salen));
548 time_t now = time(NULL);
549 if (token_bucket_tokens == 0) {
550 token_bucket_tokens =
551 MIN(MAX_TOKEN_BUCKET_TOKENS, 4 * (int)(now - token_bucket_time));
552 token_bucket_time = now;
554 if (token_bucket_tokens == 0)
556 token_bucket_tokens--;
561 pktSend(const struct Pkt *p)
564 const struct sockaddr *sa = (const struct sockaddr *)&(p->ss);
565 switch (sa->sa_family) {
575 return sendto(s, p->buf, p->len, 0, sa, p->salen);
582 const struct sockaddr *sa,
583 const socklen_t salen)
587 memcpy(&(pkt.ss), sa, sizeof(struct sockaddr_storage));
588 memcpy(pkt.buf, buf, len);
592 return pktSend(&pkt);
593 return write(sockW, &pkt, sizeof(struct Pkt));
598 const struct sockaddr *sa,
599 const socklen_t salen,
600 const unsigned char *tid,
601 const size_t tid_len)
605 int rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
607 COPY(buf, i, myid, 20, 512);
608 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%zu:", tid_len);
610 COPY(buf, i, tid, tid_len, 512);
612 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
615 printf("%s <- PING\n", getAddr(sa, salen));
616 return dht_send(buf, (size_t)i, sa, salen);
625 const struct sockaddr *sa,
626 const socklen_t salen,
627 const unsigned char *tid,
628 const size_t tid_len)
632 int rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:");
634 COPY(buf, i, myid, 20, 512);
635 rc = snprintf(buf + i, 512 - i, "e1:t%zu:", tid_len);
637 COPY(buf, i, tid, tid_len, 512);
639 rc = snprintf(buf + i, 512 - i, "1:y1:re");
642 printf("%s <- PONG\n", getAddr(sa, salen));
643 return dht_send(buf, (size_t)i, sa, salen);
652 const struct sockaddr *sa,
653 const socklen_t salen,
654 const unsigned char *tid,
655 const size_t tid_len,
656 const unsigned char *target,
661 int rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
663 COPY(buf, i, myid, 20, 512);
664 rc = snprintf(buf + i, 512 - i, "6:target20:");
666 COPY(buf, i, target, 20, 512);
672 (want & WANT4) ? "2:n4" : "",
673 (want & WANT6) ? "2:n6" : "");
676 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%zu:", tid_len);
678 COPY(buf, i, tid, tid_len, 512);
680 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
683 printf("%s <- FIND_NODE\n", getAddr(sa, salen));
684 return dht_send(buf, (size_t)i, sa, salen);
693 struct circular_list *list,
698 if (list_empty(list))
701 struct sockaddr_storage ss;
704 if (list_pop(list, &ss, &sslen) == 0)
707 if (list_random(list, NULL, &ss, &sslen) == 0)
711 unsigned char ttid[4];
713 make_tid(ttid, "pn", 0);
714 return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
716 unsigned char id[20];
717 arc4random_buf(id, sizeof id);
718 make_tid(ttid, "fn", 0);
719 return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want);
724 newSock(const char *host, const char *port)
726 struct addrinfo hints;
727 memset(&hints, 0, sizeof(hints));
728 hints.ai_family = AF_UNSPEC;
729 hints.ai_socktype = SOCK_DGRAM;
730 struct addrinfo *res = NULL;
731 int rc = getaddrinfo(host, port, &hints, &res);
733 err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
734 int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
736 err(EXIT_FAILURE, "socket()");
737 if (bind(sock, res->ai_addr, res->ai_addrlen) != 0)
738 err(EXIT_FAILURE, "bind()");
739 rc = fcntl(sock, F_GETFL, 0);
741 err(EXIT_FAILURE, "F_GETFL");
742 rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
744 err(EXIT_FAILURE, "F_SETFL");
755 if (setrlimit(res, &r) == -1) {
756 err(EXIT_FAILURE, "setrlimit()");
762 const struct sockaddr *sa,
763 const socklen_t salen,
764 const unsigned char *tid,
765 const size_t tid_len,
766 const unsigned char *nodes,
767 const size_t nodes_len,
768 const unsigned char *nodes6,
769 const size_t nodes6_len)
773 int rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:");
775 COPY(buf, i, myid, 20, 2048);
777 rc = snprintf(buf + i, 2048 - i, "5:nodes%zu:", nodes_len);
779 COPY(buf, i, nodes, nodes_len, 2048);
781 if (nodes6_len > 0) {
782 rc = snprintf(buf + i, 2048 - i, "6:nodes6%zu:", nodes6_len);
784 COPY(buf, i, nodes6, nodes6_len, 2048);
786 rc = snprintf(buf + i, 2048 - i, "e1:t%zu:", tid_len);
788 COPY(buf, i, tid, tid_len, 2048);
790 rc = snprintf(buf + i, 2048 - i, "1:y1:re");
792 return dht_send(buf, (size_t)i, sa, salen);
800 buffer_random_nodes(int af, unsigned char *nodes)
802 struct circular_list *list;
805 list = &v4_confirmed;
808 list = &v6_confirmed;
814 struct sockaddr_storage ss;
816 unsigned char id[20];
819 if (list_random(list, id, &ss, &sslen) < 1)
823 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
824 memcpy(nodes + n * 26, id, 20);
825 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
826 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
831 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
832 memcpy(nodes + n * 38, id, 20);
833 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
834 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
847 const struct sockaddr *sa,
848 const socklen_t salen,
849 const unsigned char *tid,
850 const size_t tid_len,
853 unsigned char nodes[8 * 26];
854 unsigned char nodes6[8 * 38];
858 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
860 numnodes = buffer_random_nodes(AF_INET, nodes);
862 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
864 printf("%s <- NODES (%d+%d)\n", getAddr(sa, salen), numnodes, numnodes6);
866 sa, salen, tid, tid_len, nodes, numnodes * 26, nodes6, numnodes6 * 38);
871 const struct sockaddr *sa,
872 const socklen_t salen,
873 const unsigned char *tid,
874 const size_t tid_len,
880 int rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, (int)strlen(message));
882 COPY(buf, i, message, (int)strlen(message), 512);
883 rc = snprintf(buf + i, 512 - i, "e1:t%zu:", tid_len);
885 COPY(buf, i, tid, tid_len, 512);
887 rc = snprintf(buf + i, 512 - i, "1:y1:ee");
889 return dht_send(buf, (size_t)i, sa, salen);
897 main(int argc, char **argv)
900 char *ipv4addr = NULL;
901 char *ipv6addr = NULL;
905 opt = getopt(argc, argv, "q4:6:");
914 ipv4addr = strdup(optarg);
917 ipv6addr = strdup(optarg);
929 const char *ourPort = strdup(argv[i++]);
930 if (ipv4addr != NULL) {
931 dht_socket = newSock(ipv4addr, ourPort);
933 if (ipv6addr != NULL) {
934 dht_socket6 = newSock(ipv6addr, ourPort);
937 arc4random_buf(myid, sizeof myid);
938 memcpy(my_v, "1:v4:JB\0\0", 9);
939 memset(&(pkt.ss), 0, sizeof(struct sockaddr_storage));
942 unsigned char ttid[4];
945 struct addrinfo hints, *info, *infop;
946 memset(&hints, 0, sizeof(hints));
947 hints.ai_socktype = SOCK_DGRAM;
950 hints.ai_family = AF_INET6;
951 else if (dht_socket6 < 0)
952 hints.ai_family |= AF_INET;
953 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
955 err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
963 make_tid(ttid, "pn", 0);
964 if (send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4) == -1)
965 err(EXIT_FAILURE, "sendto()");
966 infop = infop->ai_next;
974 close(STDOUT_FILENO);
977 if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, sockets) != 0)
978 err(EXIT_FAILURE, "socketpair()");
979 int sockR = sockets[0];
983 err(EXIT_FAILURE, "fork()");
987 rlimited(RLIMIT_NPROC);
988 rlimited(RLIMIT_FSIZE);
989 rlimited(RLIMIT_NOFILE);
991 unsigned char buf[sizeof(struct Pkt)];
993 n = read(sockR, buf, sizeof buf);
998 if (pktSend((struct Pkt *)buf) == -1)
1004 cap_rights_t caprights;
1005 cap_rights_init(&caprights, CAP_WRITE);
1006 if (cap_rights_limit(STDERR_FILENO, &caprights) != 0)
1007 err(EXIT_FAILURE, "cap_rights_limit(stderr)");
1009 if (cap_rights_limit(STDOUT_FILENO, &caprights) != 0)
1010 err(EXIT_FAILURE, "cap_rights_limit(stdout)");
1011 if (cap_rights_limit(sockW, &caprights) != 0)
1012 err(EXIT_FAILURE, "cap_rights_limit(sockW)");
1013 if (cap_enter() != 0)
1014 err(EXIT_FAILURE, "cap_enter()");
1016 token_bucket_time = time(NULL);
1017 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
1021 err(EXIT_FAILURE, "kqueue()");
1022 struct kevent chs[2];
1025 if (dht_socket != -1) {
1026 EV_SET(&(chs[chsLen]), dht_socket, EVFILT_READ, EV_ADD, 0, 0, NULL);
1029 if (dht_socket6 != -1) {
1030 EV_SET(&(chs[chsLen]), dht_socket6, EVFILT_READ, EV_ADD, 0, 0, NULL);
1034 rlimited(RLIMIT_NPROC);
1035 rlimited(RLIMIT_FSIZE);
1036 rlimited(RLIMIT_NOFILE);
1041 if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
1042 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
1045 tm.tv_sec = random() % 30;
1046 tm.tv_nsec = 1000000 * (random() % 1000);
1050 list_elements(&v4_confirmed),
1051 list_elements(&v6_confirmed),
1052 list_elements(&v4_new),
1053 list_elements(&v6_new));
1055 rc = kevent(kq, chs, chsLen, &ev, 1, &tm);
1057 err(EXIT_FAILURE, "kevent()");
1061 unsigned char buf[MAX_PKT_SIZE];
1062 struct sockaddr_storage source_storage;
1063 struct sockaddr *source = (struct sockaddr *)&source_storage;
1064 socklen_t sourcelen = sizeof(source_storage);
1065 if (ev.flags & EV_ERROR) {
1066 fprintf(stderr, "EV_ERROR: %s\n", strerror((int)(ev.data)));
1068 got = recvfrom((int)ev.ident, buf, MAX_PKT_SIZE, 0, source, &sourcelen);
1070 if (got < 0 || sourcelen > sizeof(struct sockaddr_storage))
1072 if (is_martian(&source_storage))
1074 if (got < MAX_PKT_SIZE) {
1078 printf("%s : overlong message\n", getAddr(source, sourcelen));
1083 unsigned char tid[16];
1084 unsigned char id[20];
1085 unsigned char info_hash[20];
1086 unsigned char target[20];
1087 unsigned char nodes[256];
1088 unsigned char nodes6[1024];
1089 unsigned char token[128];
1090 size_t tid_len = sizeof tid;
1091 size_t token_len = sizeof token;
1092 size_t nodes_len = sizeof nodes;
1093 size_t nodes6_len = sizeof nodes6;
1094 unsigned short port;
1095 unsigned char values[2048];
1096 unsigned char values6[2048];
1097 size_t values_len = sizeof values;
1098 size_t values6_len = sizeof values6;
1100 message = parse_message(
1123 if (id_cmp(id, myid) == 0) {
1126 "%s : received message from self\n",
1127 getAddr(source, sourcelen));
1131 if (message > REPLY) {
1132 /* Rate limit requests. */
1133 if (!token_bucket()) {
1136 "%s : dropping request due to rate limiting\n",
1137 getAddr(source, sourcelen));
1147 "%s : broken node truncates transaction ids\n",
1148 getAddr(source, sourcelen));
1151 if (tid_match(tid, "pn", NULL)) {
1153 printf("%s -> PONG\n", getAddr(source, sourcelen));
1154 new_node(id, source, sourcelen, 2);
1155 } else if (tid_match(tid, "fn", NULL)) {
1158 "%s -> NODES (%zu+%zu)\n",
1159 getAddr(source, sourcelen),
1162 if (nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
1165 "%s : unexpected length for node info\n",
1166 getAddr(source, sourcelen));
1168 new_node(id, source, sourcelen, 2);
1170 for (n = 0; n < nodes_len / 26; n++) {
1171 unsigned char *ni = nodes + n * 26;
1172 struct sockaddr_in sin;
1173 if (id_cmp(ni, myid) == 0)
1175 memset(&sin, 0, sizeof(sin));
1176 sin.sin_family = AF_INET;
1177 memcpy(&sin.sin_addr, ni + 20, 4);
1178 memcpy(&sin.sin_port, ni + 24, 2);
1179 new_node(ni, (struct sockaddr *)&sin, sizeof(sin), 0);
1181 for (n = 0; n < nodes6_len / 38; n++) {
1182 unsigned char *ni = nodes6 + n * 38;
1183 struct sockaddr_in6 sin6;
1184 if (id_cmp(ni, myid) == 0)
1186 memset(&sin6, 0, sizeof(sin6));
1187 sin6.sin6_family = AF_INET6;
1188 memcpy(&sin6.sin6_addr, ni + 20, 16);
1189 memcpy(&sin6.sin6_port, ni + 36, 2);
1190 new_node(ni, (struct sockaddr *)&sin6, sizeof(sin6), 0);
1195 printf("%s : unexpected reply\n", getAddr(source, sourcelen));
1201 printf("%s -> PING (%zu)\n", getAddr(source, sourcelen), tid_len);
1202 new_node(id, source, sourcelen, 1);
1203 send_pong(source, sourcelen, tid, tid_len);
1209 if (message == FIND_NODE)
1210 printf("%s -> FIND_NODE\n", getAddr(source, sourcelen));
1212 printf("%s -> GET_PEERS\n", getAddr(source, sourcelen));
1214 new_node(id, source, sourcelen, 1);
1215 send_random_nodes(source, sourcelen, tid, tid_len, want);
1219 printf("%s -> ANNOUNCE_PEER\n", getAddr(source, sourcelen));
1226 "This node doesn't accept announces");
1233 /* We need to be careful to avoid a positive feedback loop. Make
1234 sure we send at most one packet each time through the select
1237 if (dht_socket6 < 0)
1239 else if (dht_socket < 0)
1242 send4 = (random() % 2) == 1;
1245 int want = dht_socket6 >= 0 && list_free(&v6_new) > 8 ? (WANT4 | WANT6) : 0;
1246 if (!list_empty(&v4_new))
1247 send_request(&v4_new, true, list_free(&v4_new) < 8, want);
1248 else if (!list_empty(&v4_confirmed))
1249 send_request(&v4_confirmed, false, false, want);
1251 int want = dht_socket >= 0 && list_free(&v4_new) > 8 ? (WANT4 | WANT6) : 0;
1252 if (!list_empty(&v6_new))
1253 send_request(&v6_new, true, list_free(&v6_new) < 8, want);
1254 else if (!list_empty(&v6_confirmed))
1255 send_request(&v6_confirmed, false, false, want);
1260 fprintf(stderr, "dht-bootstrap [-q] [-4 ADDR4] [-6 ADDR6] port [node port...]\n");