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
35 #include <arpa/inet.h>
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
53 /* We set sin_family to 0 to mark unused slots. */
54 #if AF_INET == 0 || AF_INET6 == 0
58 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
60 #elif defined(__GNUC__)
61 #define inline __inline
63 #define restrict __restrict
72 #define MAX(x, y) ((x) >= (y) ? (x) : (y))
73 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
75 static int send_ping(struct sockaddr *sa, int salen,
76 const unsigned char *tid, int tid_len);
77 static int send_pong(struct sockaddr *sa, int salen,
78 const unsigned char *tid, int tid_len);
79 static int send_find_node(struct sockaddr *sa, int salen,
80 const unsigned char *tid, int tid_len,
81 const unsigned char *target, int want, int confirm);
82 static int send_nodes(struct sockaddr *sa, int salen,
83 const unsigned char *tid, int tid_len,
84 const unsigned char *nodes, int nodes_len,
85 const unsigned char *nodes6, int nodes6_len);
86 static int send_random_nodes(struct sockaddr *sa, int salen,
87 const unsigned char *tid, int tid_len,
88 const unsigned char *id, int want);
89 static int send_error(struct sockaddr *sa, int salen,
90 unsigned char *tid, int tid_len,
91 int code, const char *message);
98 #define ANNOUNCE_PEER 5
103 static int parse_message(const unsigned char *buf, int buflen,
104 unsigned char *tid_return, int *tid_len,
105 unsigned char *id_return,
106 unsigned char *info_hash_return,
107 unsigned char *target_return,
108 unsigned short *port_return,
109 unsigned char *token_return, int *token_len,
110 unsigned char *nodes_return, int *nodes_len,
111 unsigned char *nodes6_return, int *nodes6_len,
112 unsigned char *values_return, int *values_len,
113 unsigned char *values6_return, int *values6_len,
116 static const unsigned char zeroes[20] = {0};
117 static const unsigned char ones[20] = {
118 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
119 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
120 0xFF, 0xFF, 0xFF, 0xFF
122 static const unsigned char v4prefix[16] = {
123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0
126 static unsigned char myid[20];
127 static int have_v = 0;
128 static unsigned char my_v[9];
130 static int dht_socket = -1;
131 static int dht_socket6 = -1;
134 unsigned char id[160];
135 struct sockaddr_storage ss;
139 #define CIRCULAR_LIST_SIZE 256
141 struct circular_list {
144 struct node nodes[CIRCULAR_LIST_SIZE];
147 struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
149 #define MAX_TOKEN_BUCKET_TOKENS 40
150 static time_t token_bucket_time;
151 static int token_bucket_tokens;
153 FILE *dht_debug = NULL;
156 __attribute__ ((format (printf, 1, 2)))
159 debugf(const char *format, ...)
162 va_start(args, format);
164 vfprintf(dht_debug, format, args);
170 is_martian(struct sockaddr *sa)
172 switch(sa->sa_family) {
174 struct sockaddr_in *sin = (struct sockaddr_in*)sa;
175 const unsigned char *address = (const unsigned char*)&sin->sin_addr;
176 return sin->sin_port == 0 ||
178 (address[0] == 127) ||
179 ((address[0] & 0xE0) == 0xE0);
182 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa;
183 const unsigned char *address = (const unsigned char*)&sin6->sin6_addr;
184 return sin6->sin6_port == 0 ||
185 (address[0] == 0xFF) ||
186 (address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
187 (memcmp(address, zeroes, 15) == 0 &&
188 (address[15] == 0 || address[15] == 1)) ||
189 (memcmp(address, v4prefix, 12) == 0);
197 /* Forget about the ``XOR-metric''. An id is just a path from the
198 root of the tree, so bits are numbered from the start. */
201 id_cmp(const unsigned char *restrict id1, const unsigned char *restrict id2)
203 /* Memcmp is guaranteed to perform an unsigned comparison. */
204 return memcmp(id1, id2, 20);
207 /* Our transaction-ids are 4-bytes long, with the first two bytes identi-
208 fying the kind of request, and the remaining two a sequence number in
212 make_tid(unsigned char *tid_return, const char *prefix, unsigned short seqno)
214 tid_return[0] = prefix[0] & 0xFF;
215 tid_return[1] = prefix[1] & 0xFF;
216 memcpy(tid_return + 2, &seqno, 2);
220 tid_match(const unsigned char *tid, const char *prefix,
221 unsigned short *seqno_return)
223 if(tid[0] == (prefix[0] & 0xFF) && tid[1] == (prefix[1] & 0xFF)) {
225 memcpy(seqno_return, tid + 2, 2);
232 circular(int from, int to)
236 return x + CIRCULAR_LIST_SIZE;
241 list_elements(struct circular_list *list)
243 return circular(list->head, list->tail);
247 list_empty(struct circular_list *list)
249 return list_elements(list) == 0;
253 list_free(struct circular_list *list)
255 return circular(list->tail + 1, list->head);
259 list_pop(struct circular_list *list,
260 struct sockaddr_storage *ss, socklen_t *sslen)
262 if(list->head == list->tail)
265 memcpy(ss, &list->nodes[list->head].ss, list->nodes[list->head].sslen);
266 *sslen = list->nodes[list->head].sslen;
267 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
272 list_random(struct circular_list *list, unsigned char *id,
273 struct sockaddr_storage *ss, socklen_t *sslen)
276 if(list->head == list->tail)
279 n = random() % (list->tail - list->head);
280 n = (list->head + n) % CIRCULAR_LIST_SIZE;
283 memcpy(id, &list->nodes[n].id, 20);
284 memcpy(ss, &list->nodes[n].ss, list->nodes[n].sslen);
285 *sslen = list->nodes[n].sslen;
289 /* We just learnt about a node, not necessarily a new one. Confirm is 1 if
290 the node sent a message, 2 if it sent us a reply. */
293 new_node(unsigned char *id, struct sockaddr *sa, socklen_t salen, int confirm)
295 struct circular_list *list;
298 if(sa->sa_family == AF_INET)
299 list = confirm >= 2 ? &v4_confirmed : &v4_new;
300 else if(sa->sa_family == AF_INET6)
301 list = confirm >= 2 ? &v6_confirmed : &v6_new;
305 /* A node that sends us a request is most probably bootstrapping.
306 We want to avoid getting our tables full of very young nodes -- only
307 include such a node if we have plenty of space. */
309 if(confirm == 1 && list_free(list) < 32)
312 for(i = list->head; i != list->tail; i = (i + 1) % CIRCULAR_LIST_SIZE) {
313 struct node *n = &list->nodes[i];
314 if(n->sslen == salen && memcmp(&n->ss, sa, salen) == 0)
318 memcpy(&list->nodes[list->tail].id, id, 160);
319 memcpy(&list->nodes[list->tail].ss, sa, salen);
320 list->nodes[list->tail].sslen = salen;
321 list->tail = (list->tail + 1) % CIRCULAR_LIST_SIZE;
322 if(list->head == list->tail)
323 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
331 time_t now = time(NULL);
332 if(token_bucket_tokens == 0) {
333 token_bucket_tokens = MIN(MAX_TOKEN_BUCKET_TOKENS,
334 4 * (now - token_bucket_time));
335 token_bucket_time = now;
338 if(token_bucket_tokens == 0)
341 token_bucket_tokens--;
346 send_request(struct circular_list *list, int dopop, int doping, int want)
348 unsigned char ttid[4];
349 struct sockaddr_storage ss;
357 rc = list_pop(list, &ss, &sslen);
361 rc = list_random(list, NULL, &ss, &sslen);
367 make_tid(ttid, "pn", 0);
368 debugf("Sending ping.\n");
369 return send_ping((struct sockaddr*)&ss, sslen, ttid, 4);
371 unsigned char id[20];
373 for(i = 0; i < 20; i++)
374 id[i] = random() & 0xFF;
375 make_tid(ttid, "fn", 0);
376 debugf("Sending find_node.\n");
377 return send_find_node((struct sockaddr*)&ss, sslen, ttid, 4,
383 main(int argc, char **argv)
385 int port = 6881, quiet = 0, ipv4 = 1, ipv6 = 1;
386 int opt, rc, i, send4;
387 unsigned char ttid[4];
390 opt = getopt(argc, argv, "q46");
414 port = atoi(argv[i++]);
415 if(port <= 0 || port >= 0x10000)
419 dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
421 perror("socket(IPv4)");
425 dht_socket6 = socket(PF_INET6, SOCK_DGRAM, 0);
427 perror("socket(IPv6)");
430 if(dht_socket < 0 && dht_socket6 < 0) {
431 fprintf(stderr, "Eek!\n");
435 if(dht_socket >= 0) {
436 struct sockaddr_in sin;
438 memset(&sin, 0, sizeof(sin));
439 sin.sin_family = AF_INET;
440 sin.sin_port = htons(port);
441 rc = bind(dht_socket, (struct sockaddr*)&sin, sizeof(sin));
443 perror("bind(IPv4)");
447 rc = fcntl(dht_socket, F_GETFL, 0);
453 rc = fcntl(dht_socket, F_SETFL, (rc | O_NONBLOCK));
460 if(dht_socket6 >= 0) {
461 struct sockaddr_in6 sin6;
465 rc = setsockopt(dht_socket6, IPPROTO_IPV6, IPV6_V6ONLY,
466 (char *)&val, sizeof(val));
468 perror("setsockopt(IPV6_V6ONLY)");
472 /* BEP-32 mandates that we should bind this socket to one of our
473 global IPv6 addresses. In this program, this only happens if
474 the user used the -b flag. */
476 memset(&sin6, 0, sizeof(sin6));
477 sin6.sin6_family = AF_INET6;
478 sin6.sin6_port = htons(port);
479 rc = bind(dht_socket6, (struct sockaddr*)&sin6, sizeof(sin6));
481 perror("bind(IPv6)");
485 rc = fcntl(dht_socket6, F_GETFL, 0);
491 rc = fcntl(dht_socket6, F_SETFL, (rc | O_NONBLOCK));
502 fd = open("/dev/urandom", O_RDONLY);
504 perror("open(random)");
508 rc = read(fd, myid, 20);
510 perror("open(random)");
514 rc = read(fd, &seed, sizeof(seed));
520 memcpy(my_v, "1:v4:JB\0\0", 9);
527 struct addrinfo hints, *info, *infop;
528 memset(&hints, 0, sizeof(hints));
529 hints.ai_socktype = SOCK_DGRAM;
532 hints.ai_family = AF_INET6;
533 else if(dht_socket6 < 0)
534 hints.ai_family |= AF_INET;
535 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
537 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
547 make_tid(ttid, "pn", 0);
548 debugf("Sending ping.\n");
549 send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4);
550 infop = infop->ai_next;
557 token_bucket_time = time(NULL);
558 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
565 if((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
566 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
569 tv.tv_sec = random() % 30;
570 tv.tv_usec = random() % 1000000;
574 FD_SET(dht_socket, &readfds);
576 FD_SET(dht_socket6, &readfds);
579 debugf("%d+%d %d+%d\n",
580 list_elements(&v4_confirmed), list_elements(&v6_confirmed),
581 list_elements(&v4_new), list_elements(&v6_new));
583 rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL,
595 unsigned char tid[16], id[20], info_hash[20], target[20];
596 unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
597 int tid_len = 16, token_len = 128;
598 int nodes_len = 256, nodes6_len = 1024;
600 unsigned char values[2048], values6[2048];
601 int values_len = 2048, values6_len = 2048;
603 struct sockaddr_storage source_storage;
604 struct sockaddr *source = (struct sockaddr*)&source_storage;
605 socklen_t sourcelen = sizeof(source_storage);
606 if(dht_socket >= 0 && FD_ISSET(dht_socket, &readfds)) {
607 rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
608 } else if(dht_socket6 >= 0 && FD_ISSET(dht_socket6, &readfds)) {
609 rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
612 if(rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
615 if(is_martian(source))
618 /* There's a bug in parse_message -- it will happily overflow the
619 buffer if it's not NUL-terminated. For now, put a NUL at the
625 debugf("Overlong message.\n");
629 message = parse_message(buf, rc, tid, &tid_len, id, info_hash,
630 target, &port, token, &token_len,
631 nodes, &nodes_len, nodes6, &nodes6_len,
632 values, &values_len, values6, &values6_len,
635 if(id_cmp(id, myid) == 0) {
636 debugf("Received message from self.\n");
640 if(message > REPLY) {
641 /* Rate limit requests. */
642 if(!token_bucket()) {
643 debugf("Dropping request due to rate limiting.\n");
651 debugf("Broken node truncates transaction ids.\n");
654 if(tid_match(tid, "pn", NULL)) {
656 new_node(id, source, sourcelen, 2);
657 } else if(tid_match(tid, "fn", NULL)) {
658 debugf("Nodes found!\n");
659 if(nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
660 debugf("Unexpected length for node info!\n");
662 new_node(id, source, sourcelen, 2);
663 for(i = 0; i < nodes_len / 26; i++) {
664 unsigned char *ni = nodes + i * 26;
665 struct sockaddr_in sin;
666 if(id_cmp(ni, myid) == 0)
668 memset(&sin, 0, sizeof(sin));
669 sin.sin_family = AF_INET;
670 memcpy(&sin.sin_addr, ni + 20, 4);
671 memcpy(&sin.sin_port, ni + 24, 2);
672 new_node(ni, (struct sockaddr*)&sin, sizeof(sin),
675 for(i = 0; i < nodes6_len / 38; i++) {
676 unsigned char *ni = nodes6 + i * 38;
677 struct sockaddr_in6 sin6;
678 if(id_cmp(ni, myid) == 0)
680 memset(&sin6, 0, sizeof(sin6));
681 sin6.sin6_family = AF_INET6;
682 memcpy(&sin6.sin6_addr, ni + 20, 16);
683 memcpy(&sin6.sin6_port, ni + 36, 2);
684 new_node(ni, (struct sockaddr*)&sin6, sizeof(sin6),
689 debugf("Unexpected reply!\n");
694 debugf("Ping (%d)!\n", tid_len);
695 new_node(id, source, sourcelen, 1);
696 debugf("Sending pong.\n");
697 send_pong(source, sourcelen, tid, tid_len);
702 if(message == FIND_NODE)
703 debugf("Find node!\n");
705 debugf("Get peers!\n");
706 new_node(id, source, sourcelen, 1);
707 debugf("Sending nodes (%d).\n", want);
708 send_random_nodes(source, sourcelen,
709 tid, tid_len, target, want);
712 debugf("Announce peer!\n");
713 send_error(source, sourcelen, tid, tid_len,
714 203, "This node doesn't accept announces");
721 /* We need to be careful to avoid a positive feedback loop. Make
722 sure we send at most one packet each time through the select
727 else if(dht_socket < 0)
730 send4 = random() % 2;
734 dht_socket6 >= 0 && list_free(&v6_new) > 8 ?
736 if(!list_empty(&v4_new))
737 send_request(&v4_new, 1, list_free(&v4_new) < 8, want);
738 else if(!list_empty(&v4_confirmed))
739 send_request(&v4_confirmed, 0, 0, want);
742 dht_socket >= 0 && list_free(&v4_new) > 8 ?
744 if(!list_empty(&v6_new))
745 send_request(&v6_new, 1, list_free(&v6_new) < 8, want);
746 else if(!list_empty(&v6_confirmed))
747 send_request(&v6_confirmed, 0, 0, want);
754 fprintf(stderr, "dht-bootstrap [-q] [-4] [-6] port [node port...]\n");
758 /* We could use a proper bencoding printer and parser, but the format of
759 DHT messages is fairly stylised, so this seemed simpler. */
761 #define CHECK(offset, delta, size) \
762 if(delta < 0 || offset + delta > size) goto fail
764 #define INC(offset, delta, size) \
765 CHECK(offset, delta, size); \
768 #define COPY(buf, offset, src, delta, size) \
769 CHECK(offset, delta, size); \
770 memcpy(buf + offset, src, delta); \
773 #define ADD_V(buf, offset, size) \
775 COPY(buf, offset, my_v, sizeof(my_v), size); \
779 dht_send(const void *buf, size_t len, int flags,
780 const struct sockaddr *sa, int salen)
787 if(sa->sa_family == AF_INET)
789 else if(sa->sa_family == AF_INET6)
795 errno = EAFNOSUPPORT;
799 return sendto(s, buf, len, flags, sa, salen);
803 send_ping(struct sockaddr *sa, int salen,
804 const unsigned char *tid, int tid_len)
808 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
809 COPY(buf, i, myid, 20, 512);
810 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
812 COPY(buf, i, tid, tid_len, 512);
814 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
815 return dht_send(buf, i, 0, sa, salen);
823 send_pong(struct sockaddr *sa, int salen,
824 const unsigned char *tid, int tid_len)
828 rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:"); INC(i, rc, 512);
829 COPY(buf, i, myid, 20, 512);
830 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512);
831 COPY(buf, i, tid, tid_len, 512);
833 rc = snprintf(buf + i, 512 - i, "1:y1:re"); INC(i, rc, 512);
834 return dht_send(buf, i, 0, sa, salen);
842 send_find_node(struct sockaddr *sa, int salen,
843 const unsigned char *tid, int tid_len,
844 const unsigned char *target, int want, int confirm)
848 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
849 COPY(buf, i, myid, 20, 512);
850 rc = snprintf(buf + i, 512 - i, "6:target20:"); INC(i, rc, 512);
851 COPY(buf, i, target, 20, 512);
853 rc = snprintf(buf + i, 512 - i, "4:wantl%s%se",
854 (want & WANT4) ? "2:n4" : "",
855 (want & WANT6) ? "2:n6" : "");
858 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
860 COPY(buf, i, tid, tid_len, 512);
862 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
863 return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
871 send_nodes(struct sockaddr *sa, int salen,
872 const unsigned char *tid, int tid_len,
873 const unsigned char *nodes, int nodes_len,
874 const unsigned char *nodes6, int nodes6_len)
879 rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:"); INC(i, rc, 2048);
880 COPY(buf, i, myid, 20, 2048);
882 rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
884 COPY(buf, i, nodes, nodes_len, 2048);
887 rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
889 COPY(buf, i, nodes6, nodes6_len, 2048);
892 rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len); INC(i, rc, 2048);
893 COPY(buf, i, tid, tid_len, 2048);
895 rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048);
897 return dht_send(buf, i, 0, sa, salen);
905 buffer_random_nodes(int af, unsigned char *nodes)
907 struct circular_list *list;
908 struct sockaddr_storage ss;
910 unsigned char id[20];
915 case AF_INET: list = &v4_confirmed; break;
916 case AF_INET6: list = &v6_confirmed; break;
922 rc = list_random(list, id, &ss, &sslen);
927 struct sockaddr_in *sin = (struct sockaddr_in*)&ss;
928 memcpy(nodes + n * 26, id, 20);
929 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
930 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
935 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&ss;
936 memcpy(nodes + n * 38, id, 20);
937 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
938 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
950 send_random_nodes(struct sockaddr *sa, int salen,
951 const unsigned char *tid, int tid_len,
952 const unsigned char *id, int want)
954 unsigned char nodes[8 * 26];
955 unsigned char nodes6[8 * 38];
956 int numnodes = 0, numnodes6 = 0;
959 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
962 numnodes = buffer_random_nodes(AF_INET, nodes);
965 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
967 return send_nodes(sa, salen, tid, tid_len,
968 nodes, numnodes * 26,
969 nodes6, numnodes6 * 38);
973 send_error(struct sockaddr *sa, int salen,
974 unsigned char *tid, int tid_len,
975 int code, const char *message)
980 rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:",
981 code, (int)strlen(message));
983 COPY(buf, i, message, (int)strlen(message), 512);
984 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512);
985 COPY(buf, i, tid, tid_len, 512);
987 rc = snprintf(buf + i, 512 - i, "1:y1:ee"); INC(i, rc, 512);
988 return dht_send(buf, i, 0, sa, salen);
1002 memmem(const void *haystack, size_t haystacklen,
1003 const void *needle, size_t needlelen)
1005 const char *h = haystack;
1006 const char *n = needle;
1009 /* size_t is unsigned */
1010 if(needlelen > haystacklen)
1013 for(i = 0; i <= haystacklen - needlelen; i++) {
1014 if(memcmp(h + i, n, needlelen) == 0)
1015 return (void*)(h + i);
1022 parse_message(const unsigned char *buf, int buflen,
1023 unsigned char *tid_return, int *tid_len,
1024 unsigned char *id_return, unsigned char *info_hash_return,
1025 unsigned char *target_return, unsigned short *port_return,
1026 unsigned char *token_return, int *token_len,
1027 unsigned char *nodes_return, int *nodes_len,
1028 unsigned char *nodes6_return, int *nodes6_len,
1029 unsigned char *values_return, int *values_len,
1030 unsigned char *values6_return, int *values6_len,
1033 const unsigned char *p;
1035 /* This code will happily crash if the buffer is not NUL-terminated. */
1036 if(buf[buflen] != '\0') {
1037 debugf("Eek! parse_message with unterminated buffer.\n");
1041 #define CHECK(ptr, len) \
1042 if(((unsigned char*)ptr) + (len) > (buf) + (buflen)) goto overflow;
1045 p = memmem(buf, buflen, "1:t", 3);
1049 l = strtol((char*)p + 3, &q, 10);
1050 if(q && *q == ':' && l > 0 && l < *tid_len) {
1052 memcpy(tid_return, q + 1, l);
1059 p = memmem(buf, buflen, "2:id20:", 7);
1062 memcpy(id_return, p + 7, 20);
1064 memset(id_return, 0, 20);
1067 if(info_hash_return) {
1068 p = memmem(buf, buflen, "9:info_hash20:", 14);
1071 memcpy(info_hash_return, p + 14, 20);
1073 memset(info_hash_return, 0, 20);
1077 p = memmem(buf, buflen, "porti", 5);
1081 l = strtol((char*)p + 5, &q, 10);
1082 if(q && *q == 'e' && l > 0 && l < 0x10000)
1090 p = memmem(buf, buflen, "6:target20:", 11);
1093 memcpy(target_return, p + 11, 20);
1095 memset(target_return, 0, 20);
1099 p = memmem(buf, buflen, "5:token", 7);
1103 l = strtol((char*)p + 7, &q, 10);
1104 if(q && *q == ':' && l > 0 && l < *token_len) {
1106 memcpy(token_return, q + 1, l);
1115 p = memmem(buf, buflen, "5:nodes", 7);
1119 l = strtol((char*)p + 7, &q, 10);
1120 if(q && *q == ':' && l > 0 && l < *nodes_len) {
1122 memcpy(nodes_return, q + 1, l);
1131 p = memmem(buf, buflen, "6:nodes6", 8);
1135 l = strtol((char*)p + 8, &q, 10);
1136 if(q && *q == ':' && l > 0 && l < *nodes6_len) {
1138 memcpy(nodes6_return, q + 1, l);
1146 if(values_len || values6_len) {
1147 p = memmem(buf, buflen, "6:valuesl", 9);
1149 int i = p - buf + 9;
1154 l = strtol((char*)buf + i, &q, 10);
1155 if(q && *q == ':' && l > 0) {
1158 if(j + l > *values_len)
1160 i = q + 1 + l - (char*)buf;
1161 memcpy((char*)values_return + j, q + 1, l);
1163 } else if(l == 18) {
1164 if(j6 + l > *values6_len)
1166 i = q + 1 + l - (char*)buf;
1167 memcpy((char*)values6_return + j6, q + 1, l);
1170 debugf("Received weird value -- %d bytes.\n", (int)l);
1171 i = q + 1 + l - (char*)buf;
1177 if(i >= buflen || buf[i] != 'e')
1178 debugf("eek... unexpected end for values.\n");
1190 p = memmem(buf, buflen, "4:wantl", 7);
1192 int i = p - buf + 7;
1194 while(buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
1195 i + 2 + buf[i] - '0' < buflen) {
1196 CHECK(buf + i + 2, buf[i] - '0');
1197 if(buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
1198 *want_return |= WANT4;
1199 else if(buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
1200 *want_return |= WANT6;
1202 debugf("eek... unexpected want flag (%c)\n", buf[i]);
1203 i += 2 + buf[i] - '0';
1205 if(i >= buflen || buf[i] != 'e')
1206 debugf("eek... unexpected end for want.\n");
1214 if(memmem(buf, buflen, "1:y1:r", 6))
1216 if(memmem(buf, buflen, "1:y1:e", 6))
1218 if(!memmem(buf, buflen, "1:y1:q", 6))
1220 if(memmem(buf, buflen, "1:q4:ping", 9))
1222 if(memmem(buf, buflen, "1:q9:find_node", 14))
1224 if(memmem(buf, buflen, "1:q9:get_peers", 14))
1226 if(memmem(buf, buflen, "1:q13:announce_peer", 19))
1227 return ANNOUNCE_PEER;
1231 debugf("Truncated message.\n");