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
26 #include <arpa/inet.h>
30 #include <netinet/in.h>
35 #include <sys/socket.h>
37 #include <sys/types.h>
51 /* We set sin_family to 0 to mark unused slots. */
52 #if AF_INET == 0 || AF_INET6 == 0
56 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
58 #elif defined(__GNUC__)
59 #define inline __inline
61 #define restrict __restrict
70 #define MAX(x, y) ((x) >= (y) ? (x) : (y))
71 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
74 send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
76 send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
81 const unsigned char *tid,
83 const unsigned char *target,
90 const unsigned char *tid,
92 const unsigned char *nodes,
94 const unsigned char *nodes6,
100 const unsigned char *tid,
102 const unsigned char *id,
111 const char *message);
118 #define ANNOUNCE_PEER 5
125 const unsigned char *buf,
127 unsigned char *tid_return,
129 unsigned char *id_return,
130 unsigned char *info_hash_return,
131 unsigned char *target_return,
132 unsigned short *port_return,
133 unsigned char *token_return,
135 unsigned char *nodes_return,
137 unsigned char *nodes6_return,
139 unsigned char *values_return,
141 unsigned char *values6_return,
145 static const unsigned char zeroes[20] = {0};
146 static const unsigned char v4prefix[16] =
147 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0};
149 static unsigned char myid[20];
150 static int have_v = 0;
151 static unsigned char my_v[9];
153 static int dht_socket = -1;
154 static int dht_socket6 = -1;
157 unsigned char id[160];
158 struct sockaddr_storage ss;
162 #define CIRCULAR_LIST_SIZE 256
164 struct circular_list {
167 struct node nodes[CIRCULAR_LIST_SIZE];
170 struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
172 #define MAX_TOKEN_BUCKET_TOKENS 40
173 static time_t token_bucket_time;
174 static int token_bucket_tokens;
176 FILE *dht_debug = NULL;
179 __attribute__((format(printf, 1, 2)))
182 debugf(const char *format, ...)
185 va_start(args, format);
187 vfprintf(dht_debug, format, args);
193 is_martian(struct sockaddr *sa)
195 switch (sa->sa_family) {
197 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
198 const unsigned char *address = (const unsigned char *)&sin->sin_addr;
199 return sin->sin_port == 0 || (address[0] == 0) || (address[0] == 127) ||
200 ((address[0] & 0xE0) == 0xE0);
203 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
204 const unsigned char *address = (const unsigned char *)&sin6->sin6_addr;
205 return sin6->sin6_port == 0 || (address[0] == 0xFF) ||
206 (address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
207 (memcmp(address, zeroes, 15) == 0 &&
208 (address[15] == 0 || address[15] == 1)) ||
209 (memcmp(address, v4prefix, 12) == 0);
217 /* Forget about the ``XOR-metric''. An id is just a path from the
218 root of the tree, so bits are numbered from the start. */
221 id_cmp(const unsigned char *restrict id1, const unsigned char *restrict id2)
223 /* Memcmp is guaranteed to perform an unsigned comparison. */
224 return memcmp(id1, id2, 20);
227 /* Our transaction-ids are 4-bytes long, with the first two bytes identi-
228 fying the kind of request, and the remaining two a sequence number in
232 make_tid(unsigned char *tid_return, const char *prefix, unsigned short seqno)
234 tid_return[0] = prefix[0] & 0xFF;
235 tid_return[1] = prefix[1] & 0xFF;
236 memcpy(tid_return + 2, &seqno, 2);
240 tid_match(const unsigned char *tid, const char *prefix, unsigned short *seqno_return)
242 if (tid[0] == (prefix[0] & 0xFF) && tid[1] == (prefix[1] & 0xFF)) {
244 memcpy(seqno_return, tid + 2, 2);
251 circular(int from, int to)
255 return x + CIRCULAR_LIST_SIZE;
260 list_elements(struct circular_list *list)
262 return circular(list->head, list->tail);
266 list_empty(struct circular_list *list)
268 return list_elements(list) == 0;
272 list_free(struct circular_list *list)
274 return circular(list->tail + 1, list->head);
278 list_pop(struct circular_list *list, struct sockaddr_storage *ss, socklen_t *sslen)
280 if (list->head == list->tail)
283 memcpy(ss, &list->nodes[list->head].ss, list->nodes[list->head].sslen);
284 *sslen = list->nodes[list->head].sslen;
285 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
291 struct circular_list *list,
293 struct sockaddr_storage *ss,
297 if (list->head == list->tail)
300 n = random() % (list->tail - list->head);
301 n = (list->head + n) % CIRCULAR_LIST_SIZE;
304 memcpy(id, &list->nodes[n].id, 20);
305 memcpy(ss, &list->nodes[n].ss, list->nodes[n].sslen);
306 *sslen = list->nodes[n].sslen;
310 /* We just learnt about a node, not necessarily a new one. Confirm is 1 if
311 the node sent a message, 2 if it sent us a reply. */
314 new_node(unsigned char *id, struct sockaddr *sa, socklen_t salen, int confirm)
316 struct circular_list *list;
319 if (sa->sa_family == AF_INET)
320 list = confirm >= 2 ? &v4_confirmed : &v4_new;
321 else if (sa->sa_family == AF_INET6)
322 list = confirm >= 2 ? &v6_confirmed : &v6_new;
326 /* A node that sends us a request is most probably bootstrapping.
327 We want to avoid getting our tables full of very young nodes -- only
328 include such a node if we have plenty of space. */
330 if (confirm == 1 && list_free(list) < 32)
333 for (i = list->head; i != list->tail; i = (i + 1) % CIRCULAR_LIST_SIZE) {
334 struct node *n = &list->nodes[i];
335 if (n->sslen == salen && memcmp(&n->ss, sa, salen) == 0)
339 memcpy(&list->nodes[list->tail].id, id, 160);
340 memcpy(&list->nodes[list->tail].ss, sa, salen);
341 list->nodes[list->tail].sslen = salen;
342 list->tail = (list->tail + 1) % CIRCULAR_LIST_SIZE;
343 if (list->head == list->tail)
344 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
352 time_t now = time(NULL);
353 if (token_bucket_tokens == 0) {
354 token_bucket_tokens =
355 MIN(MAX_TOKEN_BUCKET_TOKENS, 4 * (now - token_bucket_time));
356 token_bucket_time = now;
359 if (token_bucket_tokens == 0)
362 token_bucket_tokens--;
367 send_request(struct circular_list *list, int dopop, int doping, int want)
369 unsigned char ttid[4];
370 struct sockaddr_storage ss;
374 if (list_empty(list))
378 rc = list_pop(list, &ss, &sslen);
382 rc = list_random(list, NULL, &ss, &sslen);
388 make_tid(ttid, "pn", 0);
389 debugf("Sending ping.\n");
390 return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
392 unsigned char id[20];
394 for (i = 0; i < 20; i++)
395 id[i] = random() & 0xFF;
396 make_tid(ttid, "fn", 0);
397 debugf("Sending find_node.\n");
398 return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want, 0);
403 main(int argc, char **argv)
405 int port = 6881, quiet = 0, ipv4 = 1, ipv6 = 1;
406 int opt, rc, i, send4;
407 unsigned char ttid[4];
410 opt = getopt(argc, argv, "q46");
434 port = atoi(argv[i++]);
435 if (port <= 0 || port >= 0x10000)
439 dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
441 perror("socket(IPv4)");
445 dht_socket6 = socket(PF_INET6, SOCK_DGRAM, 0);
447 perror("socket(IPv6)");
450 if (dht_socket < 0 && dht_socket6 < 0) {
451 fprintf(stderr, "Eek!\n");
455 if (dht_socket >= 0) {
456 struct sockaddr_in sin;
458 memset(&sin, 0, sizeof(sin));
459 sin.sin_family = AF_INET;
460 sin.sin_port = htons(port);
461 rc = bind(dht_socket, (struct sockaddr *)&sin, sizeof(sin));
463 perror("bind(IPv4)");
467 rc = fcntl(dht_socket, F_GETFL, 0);
473 rc = fcntl(dht_socket, F_SETFL, (rc | O_NONBLOCK));
480 if (dht_socket6 >= 0) {
481 struct sockaddr_in6 sin6;
486 dht_socket6, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val));
488 perror("setsockopt(IPV6_V6ONLY)");
492 /* BEP-32 mandates that we should bind this socket to one of our
493 global IPv6 addresses. In this program, this only happens if
494 the user used the -b flag. */
496 memset(&sin6, 0, sizeof(sin6));
497 sin6.sin6_family = AF_INET6;
498 sin6.sin6_port = htons(port);
499 rc = bind(dht_socket6, (struct sockaddr *)&sin6, sizeof(sin6));
501 perror("bind(IPv6)");
505 rc = fcntl(dht_socket6, F_GETFL, 0);
511 rc = fcntl(dht_socket6, F_SETFL, (rc | O_NONBLOCK));
522 fd = open("/dev/urandom", O_RDONLY);
524 perror("open(random)");
528 rc = read(fd, myid, 20);
530 perror("open(random)");
534 rc = read(fd, &seed, sizeof(seed));
540 memcpy(my_v, "1:v4:JB\0\0", 9);
547 struct addrinfo hints, *info, *infop;
548 memset(&hints, 0, sizeof(hints));
549 hints.ai_socktype = SOCK_DGRAM;
552 hints.ai_family = AF_INET6;
553 else if (dht_socket6 < 0)
554 hints.ai_family |= AF_INET;
555 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
557 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
567 make_tid(ttid, "pn", 0);
568 debugf("Sending ping.\n");
569 send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4);
570 infop = infop->ai_next;
577 token_bucket_time = time(NULL);
578 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
585 if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
586 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
589 tv.tv_sec = random() % 30;
590 tv.tv_usec = random() % 1000000;
594 FD_SET(dht_socket, &readfds);
595 if (dht_socket6 >= 0)
596 FD_SET(dht_socket6, &readfds);
601 list_elements(&v4_confirmed),
602 list_elements(&v6_confirmed),
603 list_elements(&v4_new),
604 list_elements(&v6_new));
606 rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL, &tv);
609 if (errno != EINTR) {
617 unsigned char tid[16], id[20], info_hash[20], target[20];
618 unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
619 int tid_len = 16, token_len = 128;
620 int nodes_len = 256, nodes6_len = 1024;
622 unsigned char values[2048], values6[2048];
623 int values_len = 2048, values6_len = 2048;
625 struct sockaddr_storage source_storage;
626 struct sockaddr *source = (struct sockaddr *)&source_storage;
627 socklen_t sourcelen = sizeof(source_storage);
628 if (dht_socket >= 0 && FD_ISSET(dht_socket, &readfds)) {
629 rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
630 } else if (dht_socket6 >= 0 && FD_ISSET(dht_socket6, &readfds)) {
631 rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
634 if (rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
637 if (is_martian(source))
640 /* There's a bug in parse_message -- it will happily overflow the
641 buffer if it's not NUL-terminated. For now, put a NUL at the
647 debugf("Overlong message.\n");
651 message = parse_message(
672 if (id_cmp(id, myid) == 0) {
673 debugf("Received message from self.\n");
677 if (message > REPLY) {
678 /* Rate limit requests. */
679 if (!token_bucket()) {
680 debugf("Dropping request due to rate limiting.\n");
688 debugf("Broken node truncates transaction ids.\n");
691 if (tid_match(tid, "pn", NULL)) {
693 new_node(id, source, sourcelen, 2);
694 } else if (tid_match(tid, "fn", NULL)) {
695 debugf("Nodes found!\n");
696 if (nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
697 debugf("Unexpected length for node info!\n");
699 new_node(id, source, sourcelen, 2);
700 for (i = 0; i < nodes_len / 26; i++) {
701 unsigned char *ni = nodes + i * 26;
702 struct sockaddr_in sin;
703 if (id_cmp(ni, myid) == 0)
705 memset(&sin, 0, sizeof(sin));
706 sin.sin_family = AF_INET;
707 memcpy(&sin.sin_addr, ni + 20, 4);
708 memcpy(&sin.sin_port, ni + 24, 2);
709 new_node(ni, (struct sockaddr *)&sin, sizeof(sin), 0);
711 for (i = 0; i < nodes6_len / 38; i++) {
712 unsigned char *ni = nodes6 + i * 38;
713 struct sockaddr_in6 sin6;
714 if (id_cmp(ni, myid) == 0)
716 memset(&sin6, 0, sizeof(sin6));
717 sin6.sin6_family = AF_INET6;
718 memcpy(&sin6.sin6_addr, ni + 20, 16);
719 memcpy(&sin6.sin6_port, ni + 36, 2);
720 new_node(ni, (struct sockaddr *)&sin6, sizeof(sin6), 0);
724 debugf("Unexpected reply!\n");
729 debugf("Ping (%d)!\n", tid_len);
730 new_node(id, source, sourcelen, 1);
731 debugf("Sending pong.\n");
732 send_pong(source, sourcelen, tid, tid_len);
737 if (message == FIND_NODE)
738 debugf("Find node!\n");
740 debugf("Get peers!\n");
741 new_node(id, source, sourcelen, 1);
742 debugf("Sending nodes (%d).\n", want);
743 send_random_nodes(source, sourcelen, tid, tid_len, target, want);
746 debugf("Announce peer!\n");
753 "This node doesn't accept announces");
760 /* We need to be careful to avoid a positive feedback loop. Make
761 sure we send at most one packet each time through the select
766 else if (dht_socket < 0)
769 send4 = random() % 2;
772 int want = dht_socket6 >= 0 && list_free(&v6_new) > 8 ? (WANT4 | WANT6) : 0;
773 if (!list_empty(&v4_new))
774 send_request(&v4_new, 1, list_free(&v4_new) < 8, want);
775 else if (!list_empty(&v4_confirmed))
776 send_request(&v4_confirmed, 0, 0, want);
778 int want = dht_socket >= 0 && list_free(&v4_new) > 8 ? (WANT4 | WANT6) : 0;
779 if (!list_empty(&v6_new))
780 send_request(&v6_new, 1, list_free(&v6_new) < 8, want);
781 else if (!list_empty(&v6_confirmed))
782 send_request(&v6_confirmed, 0, 0, want);
789 fprintf(stderr, "dht-bootstrap [-q] [-4] [-6] port [node port...]\n");
793 /* We could use a proper bencoding printer and parser, but the format of
794 DHT messages is fairly stylised, so this seemed simpler. */
796 #define CHECK(offset, delta, size) \
797 if (delta < 0 || offset + delta > size) \
800 #define INC(offset, delta, size) \
801 CHECK(offset, delta, size); \
804 #define COPY(buf, offset, src, delta, size) \
805 CHECK(offset, delta, size); \
806 memcpy(buf + offset, src, delta); \
809 #define ADD_V(buf, offset, size) \
811 COPY(buf, offset, my_v, sizeof(my_v), size); \
815 dht_send(const void *buf, size_t len, int flags, const struct sockaddr *sa, int salen)
822 if (sa->sa_family == AF_INET)
824 else if (sa->sa_family == AF_INET6)
830 errno = EAFNOSUPPORT;
834 return sendto(s, buf, len, flags, sa, salen);
838 send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
842 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
844 COPY(buf, i, myid, 20, 512);
845 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
847 COPY(buf, i, tid, tid_len, 512);
849 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
851 return dht_send(buf, i, 0, sa, salen);
859 send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
863 rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:");
865 COPY(buf, i, myid, 20, 512);
866 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
868 COPY(buf, i, tid, tid_len, 512);
870 rc = snprintf(buf + i, 512 - i, "1:y1:re");
872 return dht_send(buf, i, 0, sa, salen);
883 const unsigned char *tid,
885 const unsigned char *target,
891 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
893 COPY(buf, i, myid, 20, 512);
894 rc = snprintf(buf + i, 512 - i, "6:target20:");
896 COPY(buf, i, target, 20, 512);
902 (want & WANT4) ? "2:n4" : "",
903 (want & WANT6) ? "2:n6" : "");
906 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
908 COPY(buf, i, tid, tid_len, 512);
910 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
912 return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
923 const unsigned char *tid,
925 const unsigned char *nodes,
927 const unsigned char *nodes6,
933 rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:");
935 COPY(buf, i, myid, 20, 2048);
937 rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
939 COPY(buf, i, nodes, nodes_len, 2048);
941 if (nodes6_len > 0) {
942 rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
944 COPY(buf, i, nodes6, nodes6_len, 2048);
947 rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len);
949 COPY(buf, i, tid, tid_len, 2048);
951 rc = snprintf(buf + i, 2048 - i, "1:y1:re");
954 return dht_send(buf, i, 0, sa, salen);
962 buffer_random_nodes(int af, unsigned char *nodes)
964 struct circular_list *list;
965 struct sockaddr_storage ss;
967 unsigned char id[20];
973 list = &v4_confirmed;
976 list = &v6_confirmed;
984 rc = list_random(list, id, &ss, &sslen);
989 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
990 memcpy(nodes + n * 26, id, 20);
991 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
992 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
997 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
998 memcpy(nodes + n * 38, id, 20);
999 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
1000 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
1013 struct sockaddr *sa,
1015 const unsigned char *tid,
1017 const unsigned char *id,
1020 unsigned char nodes[8 * 26];
1021 unsigned char nodes6[8 * 38];
1022 int numnodes = 0, numnodes6 = 0;
1025 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
1028 numnodes = buffer_random_nodes(AF_INET, nodes);
1031 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
1034 sa, salen, tid, tid_len, nodes, numnodes * 26, nodes6, numnodes6 * 38);
1039 struct sockaddr *sa,
1044 const char *message)
1049 rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, (int)strlen(message));
1051 COPY(buf, i, message, (int)strlen(message), 512);
1052 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
1054 COPY(buf, i, tid, tid_len, 512);
1056 rc = snprintf(buf + i, 512 - i, "1:y1:ee");
1058 return dht_send(buf, i, 0, sa, salen);
1072 memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)
1074 const char *h = haystack;
1075 const char *n = needle;
1078 /* size_t is unsigned */
1079 if (needlelen > haystacklen)
1082 for (i = 0; i <= haystacklen - needlelen; i++) {
1083 if (memcmp(h + i, n, needlelen) == 0)
1084 return (void *)(h + i);
1092 const unsigned char *buf,
1094 unsigned char *tid_return,
1096 unsigned char *id_return,
1097 unsigned char *info_hash_return,
1098 unsigned char *target_return,
1099 unsigned short *port_return,
1100 unsigned char *token_return,
1102 unsigned char *nodes_return,
1104 unsigned char *nodes6_return,
1106 unsigned char *values_return,
1108 unsigned char *values6_return,
1112 const unsigned char *p;
1114 /* This code will happily crash if the buffer is not NUL-terminated. */
1115 if (buf[buflen] != '\0') {
1116 debugf("Eek! parse_message with unterminated buffer.\n");
1120 #define CHECK(ptr, len) \
1121 if (((unsigned char *)ptr) + (len) > (buf) + (buflen)) \
1125 p = memmem(buf, buflen, "1:t", 3);
1129 l = strtol((char *)p + 3, &q, 10);
1130 if (q && *q == ':' && l > 0 && l < *tid_len) {
1132 memcpy(tid_return, q + 1, l);
1139 p = memmem(buf, buflen, "2:id20:", 7);
1142 memcpy(id_return, p + 7, 20);
1144 memset(id_return, 0, 20);
1147 if (info_hash_return) {
1148 p = memmem(buf, buflen, "9:info_hash20:", 14);
1151 memcpy(info_hash_return, p + 14, 20);
1153 memset(info_hash_return, 0, 20);
1157 p = memmem(buf, buflen, "porti", 5);
1161 l = strtol((char *)p + 5, &q, 10);
1162 if (q && *q == 'e' && l > 0 && l < 0x10000)
1169 if (target_return) {
1170 p = memmem(buf, buflen, "6:target20:", 11);
1173 memcpy(target_return, p + 11, 20);
1175 memset(target_return, 0, 20);
1179 p = memmem(buf, buflen, "5:token", 7);
1183 l = strtol((char *)p + 7, &q, 10);
1184 if (q && *q == ':' && l > 0 && l < *token_len) {
1186 memcpy(token_return, q + 1, l);
1195 p = memmem(buf, buflen, "5:nodes", 7);
1199 l = strtol((char *)p + 7, &q, 10);
1200 if (q && *q == ':' && l > 0 && l < *nodes_len) {
1202 memcpy(nodes_return, q + 1, l);
1211 p = memmem(buf, buflen, "6:nodes6", 8);
1215 l = strtol((char *)p + 8, &q, 10);
1216 if (q && *q == ':' && l > 0 && l < *nodes6_len) {
1218 memcpy(nodes6_return, q + 1, l);
1226 if (values_len || values6_len) {
1227 p = memmem(buf, buflen, "6:valuesl", 9);
1229 int i = p - buf + 9;
1234 l = strtol((char *)buf + i, &q, 10);
1235 if (q && *q == ':' && l > 0) {
1238 if (j + l > *values_len)
1240 i = q + 1 + l - (char *)buf;
1241 memcpy((char *)values_return + j, q + 1, l);
1243 } else if (l == 18) {
1244 if (j6 + l > *values6_len)
1246 i = q + 1 + l - (char *)buf;
1247 memcpy((char *)values6_return + j6, q + 1, l);
1250 debugf("Received weird value -- %d bytes.\n", (int)l);
1251 i = q + 1 + l - (char *)buf;
1257 if (i >= buflen || buf[i] != 'e')
1258 debugf("eek... unexpected end for values.\n");
1270 p = memmem(buf, buflen, "4:wantl", 7);
1272 int i = p - buf + 7;
1274 while (buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
1275 i + 2 + buf[i] - '0' < buflen) {
1276 CHECK(buf + i + 2, buf[i] - '0');
1277 if (buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
1278 *want_return |= WANT4;
1279 else if (buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
1280 *want_return |= WANT6;
1282 debugf("eek... unexpected want flag (%c)\n", buf[i]);
1283 i += 2 + buf[i] - '0';
1285 if (i >= buflen || buf[i] != 'e')
1286 debugf("eek... unexpected end for want.\n");
1294 if (memmem(buf, buflen, "1:y1:r", 6))
1296 if (memmem(buf, buflen, "1:y1:e", 6))
1298 if (!memmem(buf, buflen, "1:y1:q", 6))
1300 if (memmem(buf, buflen, "1:q4:ping", 9))
1302 if (memmem(buf, buflen, "1:q9:find_node", 14))
1304 if (memmem(buf, buflen, "1:q9:get_peers", 14))
1306 if (memmem(buf, buflen, "1:q13:announce_peer", 19))
1307 return ANNOUNCE_PEER;
1311 debugf("Truncated message.\n");