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");
410 dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
412 perror("socket(IPv4)");
416 dht_socket6 = socket(PF_INET6, SOCK_DGRAM, 0);
418 perror("socket(IPv6)");
421 if(dht_socket < 0 && dht_socket6 < 0) {
422 fprintf(stderr, "Eek!\n");
426 if(dht_socket >= 0) {
427 struct sockaddr_in sin;
429 memset(&sin, 0, sizeof(sin));
430 sin.sin_port = htons(port);
431 rc = bind(dht_socket, (struct sockaddr*)&sin, sizeof(sin));
433 perror("bind(IPv4)");
437 rc = fcntl(dht_socket, F_GETFL, 0);
443 rc = fcntl(dht_socket, F_SETFL, (rc | O_NONBLOCK));
450 if(dht_socket6 >= 0) {
451 struct sockaddr_in6 sin6;
455 rc = setsockopt(dht_socket6, IPPROTO_IPV6, IPV6_V6ONLY,
456 (char *)&val, sizeof(val));
458 perror("setsockopt(IPV6_V6ONLY)");
462 /* BEP-32 mandates that we should bind this socket to one of our
463 global IPv6 addresses. In this simple example, this only
464 happens if the user used the -b flag. */
466 memset(&sin6, 0, sizeof(sin6));
467 sin6.sin6_port = htons(port);
468 rc = bind(dht_socket6, (struct sockaddr*)&sin6, sizeof(sin6));
470 perror("bind(IPv6)");
474 rc = fcntl(dht_socket6, F_GETFL, 0);
480 rc = fcntl(dht_socket6, F_SETFL, (rc | O_NONBLOCK));
491 fd = open("/dev/urandom", O_RDONLY);
493 perror("open(random)");
497 rc = read(fd, myid, 20);
499 perror("open(random)");
503 rc = read(fd, &seed, sizeof(seed));
509 memcpy(my_v, "1:v4:JB\0\0", 9);
520 port = atoi(argv[i++]);
521 if(port <= 0 || port >= 0x10000)
525 struct addrinfo hints, *info, *infop;
526 memset(&hints, 0, sizeof(hints));
527 hints.ai_socktype = SOCK_DGRAM;
530 hints.ai_family = AF_INET6;
531 else if(dht_socket6 < 0)
532 hints.ai_family |= AF_INET;
533 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
535 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
545 make_tid(ttid, "pn", 0);
546 debugf("Sending ping.\n");
547 send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4);
548 infop = infop->ai_next;
555 token_bucket_time = time(NULL);
556 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
563 if((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
564 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
567 tv.tv_sec = random() % 30;
568 tv.tv_usec = random() % 1000000;
572 FD_SET(dht_socket, &readfds);
574 FD_SET(dht_socket6, &readfds);
577 debugf("%d+%d %d+%d\n",
578 list_elements(&v4_confirmed), list_elements(&v6_confirmed),
579 list_elements(&v4_new), list_elements(&v6_new));
581 rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL,
593 unsigned char tid[16], id[20], info_hash[20], target[20];
594 unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
595 int tid_len = 16, token_len = 128;
596 int nodes_len = 256, nodes6_len = 1024;
598 unsigned char values[2048], values6[2048];
599 int values_len = 2048, values6_len = 2048;
600 int want, want4, want6;
601 struct sockaddr_storage source_storage;
602 struct sockaddr *source = (struct sockaddr*)&source_storage;
603 socklen_t sourcelen = sizeof(source_storage);
604 if(dht_socket >= 0 && FD_ISSET(dht_socket, &readfds)) {
605 rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
606 } else if(dht_socket6 >= 0 && FD_ISSET(dht_socket6, &readfds)) {
607 rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
610 if(rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
613 if(is_martian(source))
616 /* There's a bug in parse_message -- it will happily overflow the
617 buffer if it's not NUL-terminated. For now, put a NUL at the
623 debugf("Overlong message.\n");
627 message = parse_message(buf, rc, tid, &tid_len, id, info_hash,
628 target, &port, token, &token_len,
629 nodes, &nodes_len, nodes6, &nodes6_len,
630 values, &values_len, values6, &values6_len,
633 if(id_cmp(id, myid) == 0) {
634 debugf("Received message from self.\n");
638 if(message > REPLY) {
639 /* Rate limit requests. */
640 if(!token_bucket()) {
641 debugf("Dropping request due to rate limiting.\n");
647 want4 = (want & WANT4);
648 want6 = (want & WANT6);
650 want4 = source->sa_family == AF_INET;
651 want6 = source->sa_family == AF_INET6;
657 debugf("Broken node truncates transaction ids.\n");
660 if(tid_match(tid, "pn", NULL)) {
662 new_node(id, source, sourcelen, 2);
663 } else if(tid_match(tid, "fn", NULL)) {
664 debugf("Nodes found!\n");
665 if(nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
666 debugf("Unexpected length for node info!\n");
668 new_node(id, source, sourcelen, 2);
669 for(i = 0; i < nodes_len / 26; i++) {
670 unsigned char *ni = nodes + i * 26;
671 struct sockaddr_in sin;
672 if(id_cmp(ni, myid) == 0)
674 memset(&sin, 0, sizeof(sin));
675 sin.sin_family = AF_INET;
676 memcpy(&sin.sin_addr, ni + 20, 4);
677 memcpy(&sin.sin_port, ni + 24, 2);
678 new_node(ni, (struct sockaddr*)&sin, sizeof(sin),
681 for(i = 0; i < nodes6_len / 38; i++) {
682 unsigned char *ni = nodes6 + i * 38;
683 struct sockaddr_in6 sin6;
684 if(id_cmp(ni, myid) == 0)
686 memset(&sin6, 0, sizeof(sin6));
687 sin6.sin6_family = AF_INET6;
688 memcpy(&sin6.sin6_addr, ni + 20, 16);
689 memcpy(&sin6.sin6_port, ni + 36, 2);
690 new_node(ni, (struct sockaddr*)&sin6, sizeof(sin6),
695 debugf("Unexpected reply!\n");
700 debugf("Ping (%d)!\n", tid_len);
701 new_node(id, source, sourcelen, 1);
702 debugf("Sending pong.\n");
703 send_pong(source, sourcelen, tid, tid_len);
708 if(message == FIND_NODE)
709 debugf("Find node!\n");
711 debugf("Get peers!\n");
712 new_node(id, source, sourcelen, 1);
713 debugf("Sending nodes (%d).\n", want);
714 send_random_nodes(source, sourcelen,
715 tid, tid_len, target, want);
718 debugf("Announce peer!\n");
719 send_error(source, sourcelen, tid, tid_len,
720 203, "This node doesn't accept announces");
727 /* We need to be careful to avoid a positive feedback loop. Make
728 sure we send at most one packet each time through the select
733 else if(dht_socket < 0)
736 send4 = random() % 2;
740 dht_socket6 >= 0 && list_free(&v6_new) > 8 ?
742 if(!list_empty(&v4_new))
743 send_request(&v4_new, 1, list_free(&v4_new) < 8, want);
744 else if(!list_empty(&v4_confirmed))
745 send_request(&v4_confirmed, 0, 0, want);
748 dht_socket >= 0 && list_free(&v4_new) > 8 ?
750 if(!list_empty(&v6_new))
751 send_request(&v6_new, 1, list_free(&v6_new) < 8, want);
752 else if(!list_empty(&v6_confirmed))
753 send_request(&v6_confirmed, 0, 0, want);
760 fprintf(stderr, "dht-bootstrap [-q] [-4] [-6] port [node port...]\n");
764 /* We could use a proper bencoding printer and parser, but the format of
765 DHT messages is fairly stylised, so this seemed simpler. */
767 #define CHECK(offset, delta, size) \
768 if(delta < 0 || offset + delta > size) goto fail
770 #define INC(offset, delta, size) \
771 CHECK(offset, delta, size); \
774 #define COPY(buf, offset, src, delta, size) \
775 CHECK(offset, delta, size); \
776 memcpy(buf + offset, src, delta); \
779 #define ADD_V(buf, offset, size) \
781 COPY(buf, offset, my_v, sizeof(my_v), size); \
785 dht_send(const void *buf, size_t len, int flags,
786 const struct sockaddr *sa, int salen)
793 if(sa->sa_family == AF_INET)
795 else if(sa->sa_family == AF_INET6)
801 errno = EAFNOSUPPORT;
805 return sendto(s, buf, len, flags, sa, salen);
809 send_ping(struct sockaddr *sa, int salen,
810 const unsigned char *tid, int tid_len)
814 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
815 COPY(buf, i, myid, 20, 512);
816 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
818 COPY(buf, i, tid, tid_len, 512);
820 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
821 return dht_send(buf, i, 0, sa, salen);
829 send_pong(struct sockaddr *sa, int salen,
830 const unsigned char *tid, int tid_len)
834 rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:"); INC(i, rc, 512);
835 COPY(buf, i, myid, 20, 512);
836 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512);
837 COPY(buf, i, tid, tid_len, 512);
839 rc = snprintf(buf + i, 512 - i, "1:y1:re"); INC(i, rc, 512);
840 return dht_send(buf, i, 0, sa, salen);
848 send_find_node(struct sockaddr *sa, int salen,
849 const unsigned char *tid, int tid_len,
850 const unsigned char *target, int want, int confirm)
854 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:"); INC(i, rc, 512);
855 COPY(buf, i, myid, 20, 512);
856 rc = snprintf(buf + i, 512 - i, "6:target20:"); INC(i, rc, 512);
857 COPY(buf, i, target, 20, 512);
859 rc = snprintf(buf + i, 512 - i, "4:wantl%s%se",
860 (want & WANT4) ? "2:n4" : "",
861 (want & WANT6) ? "2:n6" : "");
864 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
866 COPY(buf, i, tid, tid_len, 512);
868 rc = snprintf(buf + i, 512 - i, "1:y1:qe"); INC(i, rc, 512);
869 return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
877 send_nodes(struct sockaddr *sa, int salen,
878 const unsigned char *tid, int tid_len,
879 const unsigned char *nodes, int nodes_len,
880 const unsigned char *nodes6, int nodes6_len)
885 rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:"); INC(i, rc, 2048);
886 COPY(buf, i, myid, 20, 2048);
888 rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
890 COPY(buf, i, nodes, nodes_len, 2048);
893 rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
895 COPY(buf, i, nodes6, nodes6_len, 2048);
898 rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len); INC(i, rc, 2048);
899 COPY(buf, i, tid, tid_len, 2048);
901 rc = snprintf(buf + i, 2048 - i, "1:y1:re"); INC(i, rc, 2048);
903 return dht_send(buf, i, 0, sa, salen);
911 buffer_random_nodes(int af, unsigned char *nodes)
913 struct circular_list *list;
914 struct sockaddr_storage ss;
916 unsigned char id[20];
921 case AF_INET: list = &v4_confirmed; break;
922 case AF_INET6: list = &v6_confirmed; break;
928 rc = list_random(list, id, &ss, &sslen);
933 struct sockaddr_in *sin = (struct sockaddr_in*)&ss;
934 memcpy(nodes + n * 26, id, 20);
935 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
936 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
941 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&ss;
942 memcpy(nodes + n * 38, id, 20);
943 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
944 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
956 send_random_nodes(struct sockaddr *sa, int salen,
957 const unsigned char *tid, int tid_len,
958 const unsigned char *id, int want)
960 unsigned char nodes[8 * 26];
961 unsigned char nodes6[8 * 38];
962 int numnodes = 0, numnodes6 = 0;
965 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
968 numnodes = buffer_random_nodes(AF_INET, nodes);
971 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
973 return send_nodes(sa, salen, tid, tid_len,
974 nodes, numnodes * 26,
975 nodes6, numnodes6 * 38);
979 send_error(struct sockaddr *sa, int salen,
980 unsigned char *tid, int tid_len,
981 int code, const char *message)
986 rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:",
987 code, (int)strlen(message));
989 COPY(buf, i, message, (int)strlen(message), 512);
990 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len); INC(i, rc, 512);
991 COPY(buf, i, tid, tid_len, 512);
993 rc = snprintf(buf + i, 512 - i, "1:y1:ee"); INC(i, rc, 512);
994 return dht_send(buf, i, 0, sa, salen);
1008 memmem(const void *haystack, size_t haystacklen,
1009 const void *needle, size_t needlelen)
1011 const char *h = haystack;
1012 const char *n = needle;
1015 /* size_t is unsigned */
1016 if(needlelen > haystacklen)
1019 for(i = 0; i <= haystacklen - needlelen; i++) {
1020 if(memcmp(h + i, n, needlelen) == 0)
1021 return (void*)(h + i);
1028 parse_message(const unsigned char *buf, int buflen,
1029 unsigned char *tid_return, int *tid_len,
1030 unsigned char *id_return, unsigned char *info_hash_return,
1031 unsigned char *target_return, unsigned short *port_return,
1032 unsigned char *token_return, int *token_len,
1033 unsigned char *nodes_return, int *nodes_len,
1034 unsigned char *nodes6_return, int *nodes6_len,
1035 unsigned char *values_return, int *values_len,
1036 unsigned char *values6_return, int *values6_len,
1039 const unsigned char *p;
1041 /* This code will happily crash if the buffer is not NUL-terminated. */
1042 if(buf[buflen] != '\0') {
1043 debugf("Eek! parse_message with unterminated buffer.\n");
1047 #define CHECK(ptr, len) \
1048 if(((unsigned char*)ptr) + (len) > (buf) + (buflen)) goto overflow;
1051 p = memmem(buf, buflen, "1:t", 3);
1055 l = strtol((char*)p + 3, &q, 10);
1056 if(q && *q == ':' && l > 0 && l < *tid_len) {
1058 memcpy(tid_return, q + 1, l);
1065 p = memmem(buf, buflen, "2:id20:", 7);
1068 memcpy(id_return, p + 7, 20);
1070 memset(id_return, 0, 20);
1073 if(info_hash_return) {
1074 p = memmem(buf, buflen, "9:info_hash20:", 14);
1077 memcpy(info_hash_return, p + 14, 20);
1079 memset(info_hash_return, 0, 20);
1083 p = memmem(buf, buflen, "porti", 5);
1087 l = strtol((char*)p + 5, &q, 10);
1088 if(q && *q == 'e' && l > 0 && l < 0x10000)
1096 p = memmem(buf, buflen, "6:target20:", 11);
1099 memcpy(target_return, p + 11, 20);
1101 memset(target_return, 0, 20);
1105 p = memmem(buf, buflen, "5:token", 7);
1109 l = strtol((char*)p + 7, &q, 10);
1110 if(q && *q == ':' && l > 0 && l < *token_len) {
1112 memcpy(token_return, q + 1, l);
1121 p = memmem(buf, buflen, "5:nodes", 7);
1125 l = strtol((char*)p + 7, &q, 10);
1126 if(q && *q == ':' && l > 0 && l < *nodes_len) {
1128 memcpy(nodes_return, q + 1, l);
1137 p = memmem(buf, buflen, "6:nodes6", 8);
1141 l = strtol((char*)p + 8, &q, 10);
1142 if(q && *q == ':' && l > 0 && l < *nodes6_len) {
1144 memcpy(nodes6_return, q + 1, l);
1152 if(values_len || values6_len) {
1153 p = memmem(buf, buflen, "6:valuesl", 9);
1155 int i = p - buf + 9;
1160 l = strtol((char*)buf + i, &q, 10);
1161 if(q && *q == ':' && l > 0) {
1164 if(j + l > *values_len)
1166 i = q + 1 + l - (char*)buf;
1167 memcpy((char*)values_return + j, q + 1, l);
1169 } else if(l == 18) {
1170 if(j6 + l > *values6_len)
1172 i = q + 1 + l - (char*)buf;
1173 memcpy((char*)values6_return + j6, q + 1, l);
1176 debugf("Received weird value -- %d bytes.\n", (int)l);
1177 i = q + 1 + l - (char*)buf;
1183 if(i >= buflen || buf[i] != 'e')
1184 debugf("eek... unexpected end for values.\n");
1196 p = memmem(buf, buflen, "4:wantl", 7);
1198 int i = p - buf + 7;
1200 while(buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
1201 i + 2 + buf[i] - '0' < buflen) {
1202 CHECK(buf + i + 2, buf[i] - '0');
1203 if(buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
1204 *want_return |= WANT4;
1205 else if(buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
1206 *want_return |= WANT6;
1208 debugf("eek... unexpected want flag (%c)\n", buf[i]);
1209 i += 2 + buf[i] - '0';
1211 if(i >= buflen || buf[i] != 'e')
1212 debugf("eek... unexpected end for want.\n");
1220 if(memmem(buf, buflen, "1:y1:r", 6))
1222 if(memmem(buf, buflen, "1:y1:e", 6))
1224 if(!memmem(buf, buflen, "1:y1:q", 6))
1226 if(memmem(buf, buflen, "1:q4:ping", 9))
1228 if(memmem(buf, buflen, "1:q9:find_node", 14))
1230 if(memmem(buf, buflen, "1:q9:get_peers", 14))
1232 if(memmem(buf, buflen, "1:q13:announce_peer", 19))
1233 return ANNOUNCE_PEER;
1237 debugf("Truncated message.\n");