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
23 #include <arpa/inet.h>
27 #include <netinet/in.h>
32 #include <sys/socket.h>
34 #include <sys/types.h>
42 #define MAX(x, y) ((x) >= (y) ? (x) : (y))
43 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
46 send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
48 send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
53 const unsigned char *tid,
55 const unsigned char *target,
62 const unsigned char *tid,
64 const unsigned char *nodes,
66 const unsigned char *nodes6,
72 const unsigned char *tid,
74 const unsigned char *id,
90 #define ANNOUNCE_PEER 5
97 const unsigned char *buf,
99 unsigned char *tid_return,
101 unsigned char *id_return,
102 unsigned char *info_hash_return,
103 unsigned char *target_return,
104 unsigned short *port_return,
105 unsigned char *token_return,
107 unsigned char *nodes_return,
109 unsigned char *nodes6_return,
111 unsigned char *values_return,
113 unsigned char *values6_return,
117 static const unsigned char zeroes[20] = {0};
118 static const unsigned char v4prefix[16] =
119 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0};
121 static unsigned char myid[20];
122 static int have_v = 0;
123 static unsigned char my_v[9];
125 static int dht_socket = -1;
126 static int dht_socket6 = -1;
129 unsigned char id[160];
130 struct sockaddr_storage ss;
134 #define CIRCULAR_LIST_SIZE 256
136 struct circular_list {
139 struct node nodes[CIRCULAR_LIST_SIZE];
142 struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
144 #define MAX_TOKEN_BUCKET_TOKENS 40
145 static time_t token_bucket_time;
146 static int token_bucket_tokens;
148 FILE *dht_debug = NULL;
151 __attribute__((format(printf, 1, 2)))
154 debugf(const char *format, ...)
157 va_start(args, format);
159 vfprintf(dht_debug, format, args);
165 is_martian(struct sockaddr *sa)
167 switch (sa->sa_family) {
169 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
170 const unsigned char *address = (const unsigned char *)&sin->sin_addr;
171 return sin->sin_port == 0 || (address[0] == 0) || (address[0] == 127) ||
172 ((address[0] & 0xE0) == 0xE0);
175 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
176 const unsigned char *address = (const unsigned char *)&sin6->sin6_addr;
177 return sin6->sin6_port == 0 || (address[0] == 0xFF) ||
178 (address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
179 (memcmp(address, zeroes, 15) == 0 &&
180 (address[15] == 0 || address[15] == 1)) ||
181 (memcmp(address, v4prefix, 12) == 0);
189 /* Forget about the ``XOR-metric''. An id is just a path from the
190 root of the tree, so bits are numbered from the start. */
193 id_cmp(const unsigned char *restrict id1, const unsigned char *restrict id2)
195 /* Memcmp is guaranteed to perform an unsigned comparison. */
196 return memcmp(id1, id2, 20);
199 /* Our transaction-ids are 4-bytes long, with the first two bytes identi-
200 fying the kind of request, and the remaining two a sequence number in
204 make_tid(unsigned char *tid_return, const char *prefix, unsigned short seqno)
206 tid_return[0] = prefix[0] & 0xFF;
207 tid_return[1] = prefix[1] & 0xFF;
208 memcpy(tid_return + 2, &seqno, 2);
212 tid_match(const unsigned char *tid, const char *prefix, unsigned short *seqno_return)
214 if (tid[0] == (prefix[0] & 0xFF) && tid[1] == (prefix[1] & 0xFF)) {
216 memcpy(seqno_return, tid + 2, 2);
223 circular(int from, int to)
227 return x + CIRCULAR_LIST_SIZE;
232 list_elements(struct circular_list *list)
234 return circular(list->head, list->tail);
238 list_empty(struct circular_list *list)
240 return list_elements(list) == 0;
244 list_free(struct circular_list *list)
246 return circular(list->tail + 1, list->head);
250 list_pop(struct circular_list *list, struct sockaddr_storage *ss, socklen_t *sslen)
252 if (list->head == list->tail)
255 memcpy(ss, &list->nodes[list->head].ss, list->nodes[list->head].sslen);
256 *sslen = list->nodes[list->head].sslen;
257 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
263 struct circular_list *list,
265 struct sockaddr_storage *ss,
269 if (list->head == list->tail)
272 n = random() % (list->tail - list->head);
273 n = (list->head + n) % CIRCULAR_LIST_SIZE;
276 memcpy(id, &list->nodes[n].id, 20);
277 memcpy(ss, &list->nodes[n].ss, list->nodes[n].sslen);
278 *sslen = list->nodes[n].sslen;
282 /* We just learnt about a node, not necessarily a new one. Confirm is 1 if
283 the node sent a message, 2 if it sent us a reply. */
286 new_node(unsigned char *id, struct sockaddr *sa, socklen_t salen, int confirm)
288 struct circular_list *list;
291 if (sa->sa_family == AF_INET)
292 list = confirm >= 2 ? &v4_confirmed : &v4_new;
293 else if (sa->sa_family == AF_INET6)
294 list = confirm >= 2 ? &v6_confirmed : &v6_new;
298 /* A node that sends us a request is most probably bootstrapping.
299 We want to avoid getting our tables full of very young nodes -- only
300 include such a node if we have plenty of space. */
302 if (confirm == 1 && list_free(list) < 32)
305 for (i = list->head; i != list->tail; i = (i + 1) % CIRCULAR_LIST_SIZE) {
306 struct node *n = &list->nodes[i];
307 if (n->sslen == salen && memcmp(&n->ss, sa, salen) == 0)
311 memcpy(&list->nodes[list->tail].id, id, 160);
312 memcpy(&list->nodes[list->tail].ss, sa, salen);
313 list->nodes[list->tail].sslen = salen;
314 list->tail = (list->tail + 1) % CIRCULAR_LIST_SIZE;
315 if (list->head == list->tail)
316 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
324 time_t now = time(NULL);
325 if (token_bucket_tokens == 0) {
326 token_bucket_tokens =
327 MIN(MAX_TOKEN_BUCKET_TOKENS, 4 * (now - token_bucket_time));
328 token_bucket_time = now;
331 if (token_bucket_tokens == 0)
334 token_bucket_tokens--;
339 send_request(struct circular_list *list, int dopop, int doping, int want)
341 unsigned char ttid[4];
342 struct sockaddr_storage ss;
346 if (list_empty(list))
350 rc = list_pop(list, &ss, &sslen);
354 rc = list_random(list, NULL, &ss, &sslen);
360 make_tid(ttid, "pn", 0);
361 debugf("Sending ping.\n");
362 return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
364 unsigned char id[20];
366 for (i = 0; i < 20; i++)
367 id[i] = random() & 0xFF;
368 make_tid(ttid, "fn", 0);
369 debugf("Sending find_node.\n");
370 return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want, 0);
375 main(int argc, char **argv)
377 int port = 6881, quiet = 0, ipv4 = 1, ipv6 = 1;
378 int opt, rc, i, send4;
379 unsigned char ttid[4];
382 opt = getopt(argc, argv, "q46");
406 port = atoi(argv[i++]);
407 if (port <= 0 || port >= 0x10000)
411 dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
413 perror("socket(IPv4)");
417 dht_socket6 = socket(PF_INET6, SOCK_DGRAM, 0);
419 perror("socket(IPv6)");
422 if (dht_socket < 0 && dht_socket6 < 0) {
423 fprintf(stderr, "Eek!\n");
427 if (dht_socket >= 0) {
428 struct sockaddr_in sin;
430 memset(&sin, 0, sizeof(sin));
431 sin.sin_family = AF_INET;
432 sin.sin_port = htons(port);
433 rc = bind(dht_socket, (struct sockaddr *)&sin, sizeof(sin));
435 perror("bind(IPv4)");
439 rc = fcntl(dht_socket, F_GETFL, 0);
445 rc = fcntl(dht_socket, F_SETFL, (rc | O_NONBLOCK));
452 if (dht_socket6 >= 0) {
453 struct sockaddr_in6 sin6;
458 dht_socket6, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val));
460 perror("setsockopt(IPV6_V6ONLY)");
464 /* BEP-32 mandates that we should bind this socket to one of our
465 global IPv6 addresses. In this program, this only happens if
466 the user used the -b flag. */
468 memset(&sin6, 0, sizeof(sin6));
469 sin6.sin6_family = AF_INET6;
470 sin6.sin6_port = htons(port);
471 rc = bind(dht_socket6, (struct sockaddr *)&sin6, sizeof(sin6));
473 perror("bind(IPv6)");
477 rc = fcntl(dht_socket6, F_GETFL, 0);
483 rc = fcntl(dht_socket6, F_SETFL, (rc | O_NONBLOCK));
494 fd = open("/dev/urandom", O_RDONLY);
496 perror("open(random)");
500 rc = read(fd, myid, 20);
502 perror("open(random)");
506 rc = read(fd, &seed, sizeof(seed));
512 memcpy(my_v, "1:v4:JB\0\0", 9);
519 struct addrinfo hints, *info, *infop;
520 memset(&hints, 0, sizeof(hints));
521 hints.ai_socktype = SOCK_DGRAM;
524 hints.ai_family = AF_INET6;
525 else if (dht_socket6 < 0)
526 hints.ai_family |= AF_INET;
527 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
529 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
539 make_tid(ttid, "pn", 0);
540 debugf("Sending ping.\n");
541 send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4);
542 infop = infop->ai_next;
549 token_bucket_time = time(NULL);
550 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
557 if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
558 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
561 tv.tv_sec = random() % 30;
562 tv.tv_usec = random() % 1000000;
566 FD_SET(dht_socket, &readfds);
567 if (dht_socket6 >= 0)
568 FD_SET(dht_socket6, &readfds);
573 list_elements(&v4_confirmed),
574 list_elements(&v6_confirmed),
575 list_elements(&v4_new),
576 list_elements(&v6_new));
578 rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL, &tv);
581 if (errno != EINTR) {
589 unsigned char tid[16], id[20], info_hash[20], target[20];
590 unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
591 int tid_len = 16, token_len = 128;
592 int nodes_len = 256, nodes6_len = 1024;
594 unsigned char values[2048], values6[2048];
595 int values_len = 2048, values6_len = 2048;
597 struct sockaddr_storage source_storage;
598 struct sockaddr *source = (struct sockaddr *)&source_storage;
599 socklen_t sourcelen = sizeof(source_storage);
600 if (dht_socket >= 0 && FD_ISSET(dht_socket, &readfds)) {
601 rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
602 } else if (dht_socket6 >= 0 && FD_ISSET(dht_socket6, &readfds)) {
603 rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
606 if (rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
609 if (is_martian(source))
612 /* There's a bug in parse_message -- it will happily overflow the
613 buffer if it's not NUL-terminated. For now, put a NUL at the
619 debugf("Overlong message.\n");
623 message = parse_message(
644 if (id_cmp(id, myid) == 0) {
645 debugf("Received message from self.\n");
649 if (message > REPLY) {
650 /* Rate limit requests. */
651 if (!token_bucket()) {
652 debugf("Dropping request due to rate limiting.\n");
660 debugf("Broken node truncates transaction ids.\n");
663 if (tid_match(tid, "pn", NULL)) {
665 new_node(id, source, sourcelen, 2);
666 } else if (tid_match(tid, "fn", NULL)) {
667 debugf("Nodes found!\n");
668 if (nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
669 debugf("Unexpected length for node info!\n");
671 new_node(id, source, sourcelen, 2);
672 for (i = 0; i < nodes_len / 26; i++) {
673 unsigned char *ni = nodes + i * 26;
674 struct sockaddr_in sin;
675 if (id_cmp(ni, myid) == 0)
677 memset(&sin, 0, sizeof(sin));
678 sin.sin_family = AF_INET;
679 memcpy(&sin.sin_addr, ni + 20, 4);
680 memcpy(&sin.sin_port, ni + 24, 2);
681 new_node(ni, (struct sockaddr *)&sin, sizeof(sin), 0);
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), 0);
696 debugf("Unexpected reply!\n");
701 debugf("Ping (%d)!\n", tid_len);
702 new_node(id, source, sourcelen, 1);
703 debugf("Sending pong.\n");
704 send_pong(source, sourcelen, tid, tid_len);
709 if (message == FIND_NODE)
710 debugf("Find node!\n");
712 debugf("Get peers!\n");
713 new_node(id, source, sourcelen, 1);
714 debugf("Sending nodes (%d).\n", want);
715 send_random_nodes(source, sourcelen, tid, tid_len, target, want);
718 debugf("Announce peer!\n");
725 "This node doesn't accept announces");
732 /* We need to be careful to avoid a positive feedback loop. Make
733 sure we send at most one packet each time through the select
738 else if (dht_socket < 0)
741 send4 = random() % 2;
744 int want = dht_socket6 >= 0 && list_free(&v6_new) > 8 ? (WANT4 | WANT6) : 0;
745 if (!list_empty(&v4_new))
746 send_request(&v4_new, 1, list_free(&v4_new) < 8, want);
747 else if (!list_empty(&v4_confirmed))
748 send_request(&v4_confirmed, 0, 0, want);
750 int want = dht_socket >= 0 && list_free(&v4_new) > 8 ? (WANT4 | WANT6) : 0;
751 if (!list_empty(&v6_new))
752 send_request(&v6_new, 1, list_free(&v6_new) < 8, want);
753 else if (!list_empty(&v6_confirmed))
754 send_request(&v6_confirmed, 0, 0, want);
761 fprintf(stderr, "dht-bootstrap [-q] [-4] [-6] port [node port...]\n");
765 /* We could use a proper bencoding printer and parser, but the format of
766 DHT messages is fairly stylised, so this seemed simpler. */
768 #define CHECK(offset, delta, size) \
769 if (delta < 0 || offset + delta > size) \
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, const struct sockaddr *sa, int salen)
794 if (sa->sa_family == AF_INET)
796 else if (sa->sa_family == AF_INET6)
802 errno = EAFNOSUPPORT;
806 return sendto(s, buf, len, flags, sa, salen);
810 send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
814 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
816 COPY(buf, i, myid, 20, 512);
817 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
819 COPY(buf, i, tid, tid_len, 512);
821 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
823 return dht_send(buf, i, 0, sa, salen);
831 send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
835 rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:");
837 COPY(buf, i, myid, 20, 512);
838 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
840 COPY(buf, i, tid, tid_len, 512);
842 rc = snprintf(buf + i, 512 - i, "1:y1:re");
844 return dht_send(buf, i, 0, sa, salen);
855 const unsigned char *tid,
857 const unsigned char *target,
863 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
865 COPY(buf, i, myid, 20, 512);
866 rc = snprintf(buf + i, 512 - i, "6:target20:");
868 COPY(buf, i, target, 20, 512);
874 (want & WANT4) ? "2:n4" : "",
875 (want & WANT6) ? "2:n6" : "");
878 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
880 COPY(buf, i, tid, tid_len, 512);
882 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
884 return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
895 const unsigned char *tid,
897 const unsigned char *nodes,
899 const unsigned char *nodes6,
905 rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:");
907 COPY(buf, i, myid, 20, 2048);
909 rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
911 COPY(buf, i, nodes, nodes_len, 2048);
913 if (nodes6_len > 0) {
914 rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
916 COPY(buf, i, nodes6, nodes6_len, 2048);
919 rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len);
921 COPY(buf, i, tid, tid_len, 2048);
923 rc = snprintf(buf + i, 2048 - i, "1:y1:re");
926 return dht_send(buf, i, 0, sa, salen);
934 buffer_random_nodes(int af, unsigned char *nodes)
936 struct circular_list *list;
937 struct sockaddr_storage ss;
939 unsigned char id[20];
945 list = &v4_confirmed;
948 list = &v6_confirmed;
956 rc = list_random(list, id, &ss, &sslen);
961 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
962 memcpy(nodes + n * 26, id, 20);
963 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
964 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
969 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
970 memcpy(nodes + n * 38, id, 20);
971 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
972 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
987 const unsigned char *tid,
989 const unsigned char *id,
992 unsigned char nodes[8 * 26];
993 unsigned char nodes6[8 * 38];
994 int numnodes = 0, numnodes6 = 0;
997 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
1000 numnodes = buffer_random_nodes(AF_INET, nodes);
1003 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
1006 sa, salen, tid, tid_len, nodes, numnodes * 26, nodes6, numnodes6 * 38);
1011 struct sockaddr *sa,
1016 const char *message)
1021 rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, (int)strlen(message));
1023 COPY(buf, i, message, (int)strlen(message), 512);
1024 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
1026 COPY(buf, i, tid, tid_len, 512);
1028 rc = snprintf(buf + i, 512 - i, "1:y1:ee");
1030 return dht_send(buf, i, 0, sa, salen);
1044 const unsigned char *buf,
1046 unsigned char *tid_return,
1048 unsigned char *id_return,
1049 unsigned char *info_hash_return,
1050 unsigned char *target_return,
1051 unsigned short *port_return,
1052 unsigned char *token_return,
1054 unsigned char *nodes_return,
1056 unsigned char *nodes6_return,
1058 unsigned char *values_return,
1060 unsigned char *values6_return,
1064 const unsigned char *p;
1066 /* This code will happily crash if the buffer is not NUL-terminated. */
1067 if (buf[buflen] != '\0') {
1068 debugf("Eek! parse_message with unterminated buffer.\n");
1072 #define CHECK(ptr, len) \
1073 if (((unsigned char *)ptr) + (len) > (buf) + (buflen)) \
1077 p = memmem(buf, buflen, "1:t", 3);
1081 l = strtol((char *)p + 3, &q, 10);
1082 if (q && *q == ':' && l > 0 && l < *tid_len) {
1084 memcpy(tid_return, q + 1, l);
1091 p = memmem(buf, buflen, "2:id20:", 7);
1094 memcpy(id_return, p + 7, 20);
1096 memset(id_return, 0, 20);
1099 if (info_hash_return) {
1100 p = memmem(buf, buflen, "9:info_hash20:", 14);
1103 memcpy(info_hash_return, p + 14, 20);
1105 memset(info_hash_return, 0, 20);
1109 p = memmem(buf, buflen, "porti", 5);
1113 l = strtol((char *)p + 5, &q, 10);
1114 if (q && *q == 'e' && l > 0 && l < 0x10000)
1121 if (target_return) {
1122 p = memmem(buf, buflen, "6:target20:", 11);
1125 memcpy(target_return, p + 11, 20);
1127 memset(target_return, 0, 20);
1131 p = memmem(buf, buflen, "5:token", 7);
1135 l = strtol((char *)p + 7, &q, 10);
1136 if (q && *q == ':' && l > 0 && l < *token_len) {
1138 memcpy(token_return, q + 1, l);
1147 p = memmem(buf, buflen, "5:nodes", 7);
1151 l = strtol((char *)p + 7, &q, 10);
1152 if (q && *q == ':' && l > 0 && l < *nodes_len) {
1154 memcpy(nodes_return, q + 1, l);
1163 p = memmem(buf, buflen, "6:nodes6", 8);
1167 l = strtol((char *)p + 8, &q, 10);
1168 if (q && *q == ':' && l > 0 && l < *nodes6_len) {
1170 memcpy(nodes6_return, q + 1, l);
1178 if (values_len || values6_len) {
1179 p = memmem(buf, buflen, "6:valuesl", 9);
1181 int i = p - buf + 9;
1186 l = strtol((char *)buf + i, &q, 10);
1187 if (q && *q == ':' && l > 0) {
1190 if (j + l > *values_len)
1192 i = q + 1 + l - (char *)buf;
1193 memcpy((char *)values_return + j, q + 1, l);
1195 } else if (l == 18) {
1196 if (j6 + l > *values6_len)
1198 i = q + 1 + l - (char *)buf;
1199 memcpy((char *)values6_return + j6, q + 1, l);
1202 debugf("Received weird value -- %d bytes.\n", (int)l);
1203 i = q + 1 + l - (char *)buf;
1209 if (i >= buflen || buf[i] != 'e')
1210 debugf("eek... unexpected end for values.\n");
1222 p = memmem(buf, buflen, "4:wantl", 7);
1224 int i = p - buf + 7;
1226 while (buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
1227 i + 2 + buf[i] - '0' < buflen) {
1228 CHECK(buf + i + 2, buf[i] - '0');
1229 if (buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
1230 *want_return |= WANT4;
1231 else if (buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
1232 *want_return |= WANT6;
1234 debugf("eek... unexpected want flag (%c)\n", buf[i]);
1235 i += 2 + buf[i] - '0';
1237 if (i >= buflen || buf[i] != 'e')
1238 debugf("eek... unexpected end for want.\n");
1246 if (memmem(buf, buflen, "1:y1:r", 6))
1248 if (memmem(buf, buflen, "1:y1:e", 6))
1250 if (!memmem(buf, buflen, "1:y1:q", 6))
1252 if (memmem(buf, buflen, "1:q4:ping", 9))
1254 if (memmem(buf, buflen, "1:q9:find_node", 14))
1256 if (memmem(buf, buflen, "1:q9:get_peers", 14))
1258 if (memmem(buf, buflen, "1:q13:announce_peer", 19))
1259 return ANNOUNCE_PEER;
1263 debugf("Truncated message.\n");