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 simple example, this only
474 happens if 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;
602 int want, want4, want6;
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");
649 want4 = (want & WANT4);
650 want6 = (want & WANT6);
652 want4 = source->sa_family == AF_INET;
653 want6 = source->sa_family == AF_INET6;
659 debugf("Broken node truncates transaction ids.\n");
662 if(tid_match(tid, "pn", NULL)) {
664 new_node(id, source, sourcelen, 2);
665 } else if(tid_match(tid, "fn", NULL)) {
666 debugf("Nodes found!\n");
667 if(nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
668 debugf("Unexpected length for node info!\n");
670 new_node(id, source, sourcelen, 2);
671 for(i = 0; i < nodes_len / 26; i++) {
672 unsigned char *ni = nodes + i * 26;
673 struct sockaddr_in sin;
674 if(id_cmp(ni, myid) == 0)
676 memset(&sin, 0, sizeof(sin));
677 sin.sin_family = AF_INET;
678 memcpy(&sin.sin_addr, ni + 20, 4);
679 memcpy(&sin.sin_port, ni + 24, 2);
680 new_node(ni, (struct sockaddr*)&sin, sizeof(sin),
683 for(i = 0; i < nodes6_len / 38; i++) {
684 unsigned char *ni = nodes6 + i * 38;
685 struct sockaddr_in6 sin6;
686 if(id_cmp(ni, myid) == 0)
688 memset(&sin6, 0, sizeof(sin6));
689 sin6.sin6_family = AF_INET6;
690 memcpy(&sin6.sin6_addr, ni + 20, 16);
691 memcpy(&sin6.sin6_port, ni + 36, 2);
692 new_node(ni, (struct sockaddr*)&sin6, sizeof(sin6),
697 debugf("Unexpected reply!\n");
702 debugf("Ping (%d)!\n", tid_len);
703 new_node(id, source, sourcelen, 1);
704 debugf("Sending pong.\n");
705 send_pong(source, sourcelen, tid, tid_len);
710 if(message == FIND_NODE)
711 debugf("Find node!\n");
713 debugf("Get peers!\n");
714 new_node(id, source, sourcelen, 1);
715 debugf("Sending nodes (%d).\n", want);
716 send_random_nodes(source, sourcelen,
717 tid, tid_len, target, want);
720 debugf("Announce peer!\n");
721 send_error(source, sourcelen, tid, tid_len,
722 203, "This node doesn't accept announces");
729 /* We need to be careful to avoid a positive feedback loop. Make
730 sure we send at most one packet each time through the select
735 else if(dht_socket < 0)
738 send4 = random() % 2;
742 dht_socket6 >= 0 && list_free(&v6_new) > 8 ?
744 if(!list_empty(&v4_new))
745 send_request(&v4_new, 1, list_free(&v4_new) < 8, want);
746 else if(!list_empty(&v4_confirmed))
747 send_request(&v4_confirmed, 0, 0, want);
750 dht_socket >= 0 && list_free(&v4_new) > 8 ?
752 if(!list_empty(&v6_new))
753 send_request(&v6_new, 1, list_free(&v6_new) < 8, want);
754 else if(!list_empty(&v6_confirmed))
755 send_request(&v6_confirmed, 0, 0, want);
762 fprintf(stderr, "dht-bootstrap [-q] [-4] [-6] port [node port...]\n");
766 /* We could use a proper bencoding printer and parser, but the format of
767 DHT messages is fairly stylised, so this seemed simpler. */
769 #define CHECK(offset, delta, size) \
770 if(delta < 0 || offset + delta > size) goto fail
772 #define INC(offset, delta, size) \
773 CHECK(offset, delta, size); \
776 #define COPY(buf, offset, src, delta, size) \
777 CHECK(offset, delta, size); \
778 memcpy(buf + offset, src, delta); \
781 #define ADD_V(buf, offset, size) \
783 COPY(buf, offset, my_v, sizeof(my_v), size); \
787 dht_send(const void *buf, size_t len, int flags,
788 const struct sockaddr *sa, int salen)
795 if(sa->sa_family == AF_INET)
797 else if(sa->sa_family == AF_INET6)
803 errno = EAFNOSUPPORT;
807 return sendto(s, buf, len, flags, sa, salen);
811 send_ping(struct sockaddr *sa, int salen,
812 const unsigned char *tid, int tid_len)
816 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
817 COPY(buf, i, myid, 20, 512);
818 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
820 COPY(buf, i, tid, tid_len, 512);
822 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
823 return dht_send(buf, i, 0, sa, salen);
831 send_pong(struct sockaddr *sa, int salen,
832 const unsigned char *tid, int tid_len)
836 rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:"); INC(i, rc, 512);
837 COPY(buf, i, myid, 20, 512);
838 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512);
839 COPY(buf, i, tid, tid_len, 512);
841 rc = snprintf(buf + i, 512 - i, "1:y1:re"); INC(i, rc, 512);
842 return dht_send(buf, i, 0, sa, salen);
850 send_find_node(struct sockaddr *sa, int salen,
851 const unsigned char *tid, int tid_len,
852 const unsigned char *target, int want, int confirm)
856 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
857 COPY(buf, i, myid, 20, 512);
858 rc = snprintf(buf + i, 512 - i, "6:target20:"); INC(i, rc, 512);
859 COPY(buf, i, target, 20, 512);
861 rc = snprintf(buf + i, 512 - i, "4:wantl%s%se",
862 (want & WANT4) ? "2:n4" : "",
863 (want & WANT6) ? "2:n6" : "");
866 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
868 COPY(buf, i, tid, tid_len, 512);
870 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
871 return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
879 send_nodes(struct sockaddr *sa, int salen,
880 const unsigned char *tid, int tid_len,
881 const unsigned char *nodes, int nodes_len,
882 const unsigned char *nodes6, int nodes6_len)
887 rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:"); INC(i, rc, 2048);
888 COPY(buf, i, myid, 20, 2048);
890 rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
892 COPY(buf, i, nodes, nodes_len, 2048);
895 rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
897 COPY(buf, i, nodes6, nodes6_len, 2048);
900 rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len); INC(i, rc, 2048);
901 COPY(buf, i, tid, tid_len, 2048);
903 rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048);
905 return dht_send(buf, i, 0, sa, salen);
913 buffer_random_nodes(int af, unsigned char *nodes)
915 struct circular_list *list;
916 struct sockaddr_storage ss;
918 unsigned char id[20];
923 case AF_INET: list = &v4_confirmed; break;
924 case AF_INET6: list = &v6_confirmed; break;
930 rc = list_random(list, id, &ss, &sslen);
935 struct sockaddr_in *sin = (struct sockaddr_in*)&ss;
936 memcpy(nodes + n * 26, id, 20);
937 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
938 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
943 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&ss;
944 memcpy(nodes + n * 38, id, 20);
945 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
946 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
958 send_random_nodes(struct sockaddr *sa, int salen,
959 const unsigned char *tid, int tid_len,
960 const unsigned char *id, int want)
962 unsigned char nodes[8 * 26];
963 unsigned char nodes6[8 * 38];
964 int numnodes = 0, numnodes6 = 0;
967 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
970 numnodes = buffer_random_nodes(AF_INET, nodes);
973 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
975 return send_nodes(sa, salen, tid, tid_len,
976 nodes, numnodes * 26,
977 nodes6, numnodes6 * 38);
981 send_error(struct sockaddr *sa, int salen,
982 unsigned char *tid, int tid_len,
983 int code, const char *message)
988 rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:",
989 code, (int)strlen(message));
991 COPY(buf, i, message, (int)strlen(message), 512);
992 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512);
993 COPY(buf, i, tid, tid_len, 512);
995 rc = snprintf(buf + i, 512 - i, "1:y1:ee"); INC(i, rc, 512);
996 return dht_send(buf, i, 0, sa, salen);
1010 memmem(const void *haystack, size_t haystacklen,
1011 const void *needle, size_t needlelen)
1013 const char *h = haystack;
1014 const char *n = needle;
1017 /* size_t is unsigned */
1018 if(needlelen > haystacklen)
1021 for(i = 0; i <= haystacklen - needlelen; i++) {
1022 if(memcmp(h + i, n, needlelen) == 0)
1023 return (void*)(h + i);
1030 parse_message(const unsigned char *buf, int buflen,
1031 unsigned char *tid_return, int *tid_len,
1032 unsigned char *id_return, unsigned char *info_hash_return,
1033 unsigned char *target_return, unsigned short *port_return,
1034 unsigned char *token_return, int *token_len,
1035 unsigned char *nodes_return, int *nodes_len,
1036 unsigned char *nodes6_return, int *nodes6_len,
1037 unsigned char *values_return, int *values_len,
1038 unsigned char *values6_return, int *values6_len,
1041 const unsigned char *p;
1043 /* This code will happily crash if the buffer is not NUL-terminated. */
1044 if(buf[buflen] != '\0') {
1045 debugf("Eek! parse_message with unterminated buffer.\n");
1049 #define CHECK(ptr, len) \
1050 if(((unsigned char*)ptr) + (len) > (buf) + (buflen)) goto overflow;
1053 p = memmem(buf, buflen, "1:t", 3);
1057 l = strtol((char*)p + 3, &q, 10);
1058 if(q && *q == ':' && l > 0 && l < *tid_len) {
1060 memcpy(tid_return, q + 1, l);
1067 p = memmem(buf, buflen, "2:id20:", 7);
1070 memcpy(id_return, p + 7, 20);
1072 memset(id_return, 0, 20);
1075 if(info_hash_return) {
1076 p = memmem(buf, buflen, "9:info_hash20:", 14);
1079 memcpy(info_hash_return, p + 14, 20);
1081 memset(info_hash_return, 0, 20);
1085 p = memmem(buf, buflen, "porti", 5);
1089 l = strtol((char*)p + 5, &q, 10);
1090 if(q && *q == 'e' && l > 0 && l < 0x10000)
1098 p = memmem(buf, buflen, "6:target20:", 11);
1101 memcpy(target_return, p + 11, 20);
1103 memset(target_return, 0, 20);
1107 p = memmem(buf, buflen, "5:token", 7);
1111 l = strtol((char*)p + 7, &q, 10);
1112 if(q && *q == ':' && l > 0 && l < *token_len) {
1114 memcpy(token_return, q + 1, l);
1123 p = memmem(buf, buflen, "5:nodes", 7);
1127 l = strtol((char*)p + 7, &q, 10);
1128 if(q && *q == ':' && l > 0 && l < *nodes_len) {
1130 memcpy(nodes_return, q + 1, l);
1139 p = memmem(buf, buflen, "6:nodes6", 8);
1143 l = strtol((char*)p + 8, &q, 10);
1144 if(q && *q == ':' && l > 0 && l < *nodes6_len) {
1146 memcpy(nodes6_return, q + 1, l);
1154 if(values_len || values6_len) {
1155 p = memmem(buf, buflen, "6:valuesl", 9);
1157 int i = p - buf + 9;
1162 l = strtol((char*)buf + i, &q, 10);
1163 if(q && *q == ':' && l > 0) {
1166 if(j + l > *values_len)
1168 i = q + 1 + l - (char*)buf;
1169 memcpy((char*)values_return + j, q + 1, l);
1171 } else if(l == 18) {
1172 if(j6 + l > *values6_len)
1174 i = q + 1 + l - (char*)buf;
1175 memcpy((char*)values6_return + j6, q + 1, l);
1178 debugf("Received weird value -- %d bytes.\n", (int)l);
1179 i = q + 1 + l - (char*)buf;
1185 if(i >= buflen || buf[i] != 'e')
1186 debugf("eek... unexpected end for values.\n");
1198 p = memmem(buf, buflen, "4:wantl", 7);
1200 int i = p - buf + 7;
1202 while(buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
1203 i + 2 + buf[i] - '0' < buflen) {
1204 CHECK(buf + i + 2, buf[i] - '0');
1205 if(buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
1206 *want_return |= WANT4;
1207 else if(buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
1208 *want_return |= WANT6;
1210 debugf("eek... unexpected want flag (%c)\n", buf[i]);
1211 i += 2 + buf[i] - '0';
1213 if(i >= buflen || buf[i] != 'e')
1214 debugf("eek... unexpected end for want.\n");
1222 if(memmem(buf, buflen, "1:y1:r", 6))
1224 if(memmem(buf, buflen, "1:y1:e", 6))
1226 if(!memmem(buf, buflen, "1:y1:q", 6))
1228 if(memmem(buf, buflen, "1:q4:ping", 9))
1230 if(memmem(buf, buflen, "1:q9:find_node", 14))
1232 if(memmem(buf, buflen, "1:q9:get_peers", 14))
1234 if(memmem(buf, buflen, "1:q13:announce_peer", 19))
1235 return ANNOUNCE_PEER;
1239 debugf("Truncated message.\n");