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>
38 #define MAX(x, y) ((x) >= (y) ? (x) : (y))
39 #define MIN(x, y) ((x) <= (y) ? (x) : (y))
42 send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
44 send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
49 const unsigned char *tid,
51 const unsigned char *target,
57 const unsigned char *tid,
59 const unsigned char *nodes,
61 const unsigned char *nodes6,
67 const unsigned char *tid,
69 const unsigned char *id,
85 #define ANNOUNCE_PEER 5
92 const unsigned char *buf,
94 unsigned char *tid_return,
96 unsigned char *id_return,
97 unsigned char *info_hash_return,
98 unsigned char *target_return,
99 unsigned short *port_return,
100 unsigned char *token_return,
102 unsigned char *nodes_return,
104 unsigned char *nodes6_return,
106 unsigned char *values_return,
108 unsigned char *values6_return,
112 static const unsigned char zeroes[20] = {0};
113 static const unsigned char v4prefix[16] =
114 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0};
116 static unsigned char myid[20];
117 static int have_v = 0;
118 static unsigned char my_v[9];
120 static int dht_socket = -1;
121 static int dht_socket6 = -1;
124 unsigned char id[160];
125 struct sockaddr_storage ss;
129 #define CIRCULAR_LIST_SIZE 256
131 struct circular_list {
134 struct node nodes[CIRCULAR_LIST_SIZE];
137 struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
139 #define MAX_TOKEN_BUCKET_TOKENS 40
140 static time_t token_bucket_time;
141 static int token_bucket_tokens;
143 FILE *dht_debug = NULL;
146 __attribute__((format(printf, 1, 2)))
149 debugf(const char *format, ...)
152 va_start(args, format);
154 vfprintf(dht_debug, format, args);
160 is_martian(struct sockaddr *sa)
162 switch (sa->sa_family) {
164 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
165 const unsigned char *address = (const unsigned char *)&sin->sin_addr;
166 return sin->sin_port == 0 || (address[0] == 0) || (address[0] == 127) ||
167 ((address[0] & 0xE0) == 0xE0);
170 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
171 const unsigned char *address = (const unsigned char *)&sin6->sin6_addr;
172 return sin6->sin6_port == 0 || (address[0] == 0xFF) ||
173 (address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
174 (memcmp(address, zeroes, 15) == 0 &&
175 (address[15] == 0 || address[15] == 1)) ||
176 (memcmp(address, v4prefix, 12) == 0);
184 /* Forget about the ``XOR-metric''. An id is just a path from the
185 root of the tree, so bits are numbered from the start. */
188 id_cmp(const unsigned char *restrict id1, const unsigned char *restrict id2)
190 /* Memcmp is guaranteed to perform an unsigned comparison. */
191 return memcmp(id1, id2, 20);
194 /* Our transaction-ids are 4-bytes long, with the first two bytes identi-
195 fying the kind of request, and the remaining two a sequence number in
199 make_tid(unsigned char *tid_return, const char *prefix, unsigned short seqno)
201 tid_return[0] = prefix[0] & 0xFF;
202 tid_return[1] = prefix[1] & 0xFF;
203 memcpy(tid_return + 2, &seqno, 2);
207 tid_match(const unsigned char *tid, const char *prefix, unsigned short *seqno_return)
209 if (tid[0] == (prefix[0] & 0xFF) && tid[1] == (prefix[1] & 0xFF)) {
211 memcpy(seqno_return, tid + 2, 2);
218 circular(int from, int to)
222 return x + CIRCULAR_LIST_SIZE;
227 list_elements(struct circular_list *list)
229 return circular(list->head, list->tail);
233 list_empty(struct circular_list *list)
235 return list_elements(list) == 0;
239 list_free(struct circular_list *list)
241 return circular(list->tail + 1, list->head);
245 list_pop(struct circular_list *list, struct sockaddr_storage *ss, socklen_t *sslen)
247 if (list->head == list->tail)
250 memcpy(ss, &list->nodes[list->head].ss, list->nodes[list->head].sslen);
251 *sslen = list->nodes[list->head].sslen;
252 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
258 struct circular_list *list,
260 struct sockaddr_storage *ss,
264 if (list->head == list->tail)
267 n = random() % (list->tail - list->head);
268 n = (list->head + n) % CIRCULAR_LIST_SIZE;
271 memcpy(id, &list->nodes[n].id, 20);
272 memcpy(ss, &list->nodes[n].ss, list->nodes[n].sslen);
273 *sslen = list->nodes[n].sslen;
277 /* We just learnt about a node, not necessarily a new one. Confirm is 1 if
278 the node sent a message, 2 if it sent us a reply. */
281 new_node(unsigned char *id, struct sockaddr *sa, socklen_t salen, int confirm)
283 struct circular_list *list;
286 if (sa->sa_family == AF_INET)
287 list = confirm >= 2 ? &v4_confirmed : &v4_new;
288 else if (sa->sa_family == AF_INET6)
289 list = confirm >= 2 ? &v6_confirmed : &v6_new;
293 /* A node that sends us a request is most probably bootstrapping.
294 We want to avoid getting our tables full of very young nodes -- only
295 include such a node if we have plenty of space. */
297 if (confirm == 1 && list_free(list) < 32)
300 for (i = list->head; i != list->tail; i = (i + 1) % CIRCULAR_LIST_SIZE) {
301 struct node *n = &list->nodes[i];
302 if (n->sslen == salen && memcmp(&n->ss, sa, salen) == 0)
306 memcpy(&list->nodes[list->tail].id, id, 160);
307 memcpy(&list->nodes[list->tail].ss, sa, salen);
308 list->nodes[list->tail].sslen = salen;
309 list->tail = (list->tail + 1) % CIRCULAR_LIST_SIZE;
310 if (list->head == list->tail)
311 list->head = (list->head + 1) % CIRCULAR_LIST_SIZE;
319 time_t now = time(NULL);
320 if (token_bucket_tokens == 0) {
321 token_bucket_tokens =
322 MIN(MAX_TOKEN_BUCKET_TOKENS, 4 * (now - token_bucket_time));
323 token_bucket_time = now;
326 if (token_bucket_tokens == 0)
329 token_bucket_tokens--;
334 send_request(struct circular_list *list, int dopop, int doping, int want)
336 unsigned char ttid[4];
337 struct sockaddr_storage ss;
341 if (list_empty(list))
345 rc = list_pop(list, &ss, &sslen);
349 rc = list_random(list, NULL, &ss, &sslen);
355 make_tid(ttid, "pn", 0);
356 debugf("Sending ping.\n");
357 return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
359 unsigned char id[20];
361 for (i = 0; i < 20; i++)
362 id[i] = random() & 0xFF;
363 make_tid(ttid, "fn", 0);
364 debugf("Sending find_node.\n");
365 return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want);
370 main(int argc, char **argv)
372 int port = 6881, quiet = 0, ipv4 = 1, ipv6 = 1;
373 int opt, rc, i, send4;
374 unsigned char ttid[4];
377 opt = getopt(argc, argv, "q46");
401 port = atoi(argv[i++]);
402 if (port <= 0 || port >= 0x10000)
406 dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
408 perror("socket(IPv4)");
412 dht_socket6 = socket(PF_INET6, SOCK_DGRAM, 0);
414 perror("socket(IPv6)");
417 if (dht_socket < 0 && dht_socket6 < 0) {
418 fprintf(stderr, "Eek!\n");
422 if (dht_socket >= 0) {
423 struct sockaddr_in sin;
425 memset(&sin, 0, sizeof(sin));
426 sin.sin_family = AF_INET;
427 sin.sin_port = htons(port);
428 rc = bind(dht_socket, (struct sockaddr *)&sin, sizeof(sin));
430 perror("bind(IPv4)");
434 rc = fcntl(dht_socket, F_GETFL, 0);
440 rc = fcntl(dht_socket, F_SETFL, (rc | O_NONBLOCK));
447 if (dht_socket6 >= 0) {
448 struct sockaddr_in6 sin6;
453 dht_socket6, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val));
455 perror("setsockopt(IPV6_V6ONLY)");
459 /* BEP-32 mandates that we should bind this socket to one of our
460 global IPv6 addresses. In this program, this only happens if
461 the user used the -b flag. */
463 memset(&sin6, 0, sizeof(sin6));
464 sin6.sin6_family = AF_INET6;
465 sin6.sin6_port = htons(port);
466 rc = bind(dht_socket6, (struct sockaddr *)&sin6, sizeof(sin6));
468 perror("bind(IPv6)");
472 rc = fcntl(dht_socket6, F_GETFL, 0);
478 rc = fcntl(dht_socket6, F_SETFL, (rc | O_NONBLOCK));
489 fd = open("/dev/urandom", O_RDONLY);
491 perror("open(random)");
495 rc = read(fd, myid, 20);
497 perror("open(random)");
501 rc = read(fd, &seed, sizeof(seed));
507 memcpy(my_v, "1:v4:JB\0\0", 9);
514 struct addrinfo hints, *info, *infop;
515 memset(&hints, 0, sizeof(hints));
516 hints.ai_socktype = SOCK_DGRAM;
519 hints.ai_family = AF_INET6;
520 else if (dht_socket6 < 0)
521 hints.ai_family |= AF_INET;
522 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
524 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
534 make_tid(ttid, "pn", 0);
535 debugf("Sending ping.\n");
536 send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4);
537 infop = infop->ai_next;
544 token_bucket_time = time(NULL);
545 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
552 if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
553 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
556 tv.tv_sec = random() % 30;
557 tv.tv_usec = random() % 1000000;
561 FD_SET(dht_socket, &readfds);
562 if (dht_socket6 >= 0)
563 FD_SET(dht_socket6, &readfds);
568 list_elements(&v4_confirmed),
569 list_elements(&v6_confirmed),
570 list_elements(&v4_new),
571 list_elements(&v6_new));
573 rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL, &tv);
576 if (errno != EINTR) {
584 unsigned char tid[16], id[20], info_hash[20], target[20];
585 unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
586 int tid_len = 16, token_len = 128;
587 int nodes_len = 256, nodes6_len = 1024;
589 unsigned char values[2048], values6[2048];
590 int values_len = 2048, values6_len = 2048;
592 struct sockaddr_storage source_storage;
593 struct sockaddr *source = (struct sockaddr *)&source_storage;
594 socklen_t sourcelen = sizeof(source_storage);
595 if (dht_socket >= 0 && FD_ISSET(dht_socket, &readfds)) {
596 rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
597 } else if (dht_socket6 >= 0 && FD_ISSET(dht_socket6, &readfds)) {
598 rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
601 if (rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
604 if (is_martian(source))
607 /* There's a bug in parse_message -- it will happily overflow the
608 buffer if it's not NUL-terminated. For now, put a NUL at the
614 debugf("Overlong message.\n");
618 message = parse_message(
639 if (id_cmp(id, myid) == 0) {
640 debugf("Received message from self.\n");
644 if (message > REPLY) {
645 /* Rate limit requests. */
646 if (!token_bucket()) {
647 debugf("Dropping request due to rate limiting.\n");
655 debugf("Broken node truncates transaction ids.\n");
658 if (tid_match(tid, "pn", NULL)) {
660 new_node(id, source, sourcelen, 2);
661 } else if (tid_match(tid, "fn", NULL)) {
662 debugf("Nodes found!\n");
663 if (nodes_len % 26 != 0 || nodes6_len % 38 != 0) {
664 debugf("Unexpected length for node info!\n");
666 new_node(id, source, sourcelen, 2);
667 for (i = 0; i < nodes_len / 26; i++) {
668 unsigned char *ni = nodes + i * 26;
669 struct sockaddr_in sin;
670 if (id_cmp(ni, myid) == 0)
672 memset(&sin, 0, sizeof(sin));
673 sin.sin_family = AF_INET;
674 memcpy(&sin.sin_addr, ni + 20, 4);
675 memcpy(&sin.sin_port, ni + 24, 2);
676 new_node(ni, (struct sockaddr *)&sin, sizeof(sin), 0);
678 for (i = 0; i < nodes6_len / 38; i++) {
679 unsigned char *ni = nodes6 + i * 38;
680 struct sockaddr_in6 sin6;
681 if (id_cmp(ni, myid) == 0)
683 memset(&sin6, 0, sizeof(sin6));
684 sin6.sin6_family = AF_INET6;
685 memcpy(&sin6.sin6_addr, ni + 20, 16);
686 memcpy(&sin6.sin6_port, ni + 36, 2);
687 new_node(ni, (struct sockaddr *)&sin6, sizeof(sin6), 0);
691 debugf("Unexpected reply!\n");
696 debugf("Ping (%d)!\n", tid_len);
697 new_node(id, source, sourcelen, 1);
698 debugf("Sending pong.\n");
699 send_pong(source, sourcelen, tid, tid_len);
704 if (message == FIND_NODE)
705 debugf("Find node!\n");
707 debugf("Get peers!\n");
708 new_node(id, source, sourcelen, 1);
709 debugf("Sending nodes (%d).\n", want);
710 send_random_nodes(source, sourcelen, tid, tid_len, target, want);
713 debugf("Announce peer!\n");
720 "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;
739 int want = dht_socket6 >= 0 && list_free(&v6_new) > 8 ? (WANT4 | WANT6) : 0;
740 if (!list_empty(&v4_new))
741 send_request(&v4_new, 1, list_free(&v4_new) < 8, want);
742 else if (!list_empty(&v4_confirmed))
743 send_request(&v4_confirmed, 0, 0, want);
745 int want = dht_socket >= 0 && list_free(&v4_new) > 8 ? (WANT4 | WANT6) : 0;
746 if (!list_empty(&v6_new))
747 send_request(&v6_new, 1, list_free(&v6_new) < 8, want);
748 else if (!list_empty(&v6_confirmed))
749 send_request(&v6_confirmed, 0, 0, want);
756 fprintf(stderr, "dht-bootstrap [-q] [-4] [-6] port [node port...]\n");
760 /* We could use a proper bencoding printer and parser, but the format of
761 DHT messages is fairly stylised, so this seemed simpler. */
763 #define CHECK(offset, delta, size) \
764 if (delta < 0 || offset + delta > size) \
767 #define INC(offset, delta, size) \
768 CHECK(offset, delta, size); \
771 #define COPY(buf, offset, src, delta, size) \
772 CHECK(offset, delta, size); \
773 memcpy(buf + offset, src, delta); \
776 #define ADD_V(buf, offset, size) \
778 COPY(buf, offset, my_v, sizeof(my_v), size); \
782 dht_send(const void *buf, size_t len, int flags, const struct sockaddr *sa, int salen)
789 if (sa->sa_family == AF_INET)
791 else if (sa->sa_family == AF_INET6)
797 errno = EAFNOSUPPORT;
801 return sendto(s, buf, len, flags, sa, salen);
805 send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
809 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
811 COPY(buf, i, myid, 20, 512);
812 rc = snprintf(buf + i, 512 - i, "e1:q4:ping1:t%d:", tid_len);
814 COPY(buf, i, tid, tid_len, 512);
816 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
818 return dht_send(buf, i, 0, sa, salen);
826 send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
830 rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:");
832 COPY(buf, i, myid, 20, 512);
833 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
835 COPY(buf, i, tid, tid_len, 512);
837 rc = snprintf(buf + i, 512 - i, "1:y1:re");
839 return dht_send(buf, i, 0, sa, salen);
850 const unsigned char *tid,
852 const unsigned char *target,
857 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
859 COPY(buf, i, myid, 20, 512);
860 rc = snprintf(buf + i, 512 - i, "6:target20:");
862 COPY(buf, i, target, 20, 512);
868 (want & WANT4) ? "2:n4" : "",
869 (want & WANT6) ? "2:n6" : "");
872 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
874 COPY(buf, i, tid, tid_len, 512);
876 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
878 return dht_send(buf, i, 0, sa, salen);
889 const unsigned char *tid,
891 const unsigned char *nodes,
893 const unsigned char *nodes6,
899 rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:");
901 COPY(buf, i, myid, 20, 2048);
903 rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
905 COPY(buf, i, nodes, nodes_len, 2048);
907 if (nodes6_len > 0) {
908 rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
910 COPY(buf, i, nodes6, nodes6_len, 2048);
913 rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len);
915 COPY(buf, i, tid, tid_len, 2048);
917 rc = snprintf(buf + i, 2048 - i, "1:y1:re");
920 return dht_send(buf, i, 0, sa, salen);
928 buffer_random_nodes(int af, unsigned char *nodes)
930 struct circular_list *list;
931 struct sockaddr_storage ss;
933 unsigned char id[20];
939 list = &v4_confirmed;
942 list = &v6_confirmed;
950 rc = list_random(list, id, &ss, &sslen);
955 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
956 memcpy(nodes + n * 26, id, 20);
957 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
958 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
963 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
964 memcpy(nodes + n * 38, id, 20);
965 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
966 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
981 const unsigned char *tid,
983 const unsigned char *id,
986 unsigned char nodes[8 * 26];
987 unsigned char nodes6[8 * 38];
988 int numnodes = 0, numnodes6 = 0;
991 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
994 numnodes = buffer_random_nodes(AF_INET, nodes);
997 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
1000 sa, salen, tid, tid_len, nodes, numnodes * 26, nodes6, numnodes6 * 38);
1005 struct sockaddr *sa,
1010 const char *message)
1015 rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, (int)strlen(message));
1017 COPY(buf, i, message, (int)strlen(message), 512);
1018 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
1020 COPY(buf, i, tid, tid_len, 512);
1022 rc = snprintf(buf + i, 512 - i, "1:y1:ee");
1024 return dht_send(buf, i, 0, sa, salen);
1038 const unsigned char *buf,
1040 unsigned char *tid_return,
1042 unsigned char *id_return,
1043 unsigned char *info_hash_return,
1044 unsigned char *target_return,
1045 unsigned short *port_return,
1046 unsigned char *token_return,
1048 unsigned char *nodes_return,
1050 unsigned char *nodes6_return,
1052 unsigned char *values_return,
1054 unsigned char *values6_return,
1058 const unsigned char *p;
1060 /* This code will happily crash if the buffer is not NUL-terminated. */
1061 if (buf[buflen] != '\0') {
1062 debugf("Eek! parse_message with unterminated buffer.\n");
1066 #define CHECK(ptr, len) \
1067 if (((unsigned char *)ptr) + (len) > (buf) + (buflen)) \
1071 p = memmem(buf, buflen, "1:t", 3);
1075 l = strtol((char *)p + 3, &q, 10);
1076 if (q && *q == ':' && l > 0 && l < *tid_len) {
1078 memcpy(tid_return, q + 1, l);
1085 p = memmem(buf, buflen, "2:id20:", 7);
1088 memcpy(id_return, p + 7, 20);
1090 memset(id_return, 0, 20);
1093 if (info_hash_return) {
1094 p = memmem(buf, buflen, "9:info_hash20:", 14);
1097 memcpy(info_hash_return, p + 14, 20);
1099 memset(info_hash_return, 0, 20);
1103 p = memmem(buf, buflen, "porti", 5);
1107 l = strtol((char *)p + 5, &q, 10);
1108 if (q && *q == 'e' && l > 0 && l < 0x10000)
1115 if (target_return) {
1116 p = memmem(buf, buflen, "6:target20:", 11);
1119 memcpy(target_return, p + 11, 20);
1121 memset(target_return, 0, 20);
1125 p = memmem(buf, buflen, "5:token", 7);
1129 l = strtol((char *)p + 7, &q, 10);
1130 if (q && *q == ':' && l > 0 && l < *token_len) {
1132 memcpy(token_return, q + 1, l);
1141 p = memmem(buf, buflen, "5:nodes", 7);
1145 l = strtol((char *)p + 7, &q, 10);
1146 if (q && *q == ':' && l > 0 && l < *nodes_len) {
1148 memcpy(nodes_return, q + 1, l);
1157 p = memmem(buf, buflen, "6:nodes6", 8);
1161 l = strtol((char *)p + 8, &q, 10);
1162 if (q && *q == ':' && l > 0 && l < *nodes6_len) {
1164 memcpy(nodes6_return, q + 1, l);
1172 if (values_len || values6_len) {
1173 p = memmem(buf, buflen, "6:valuesl", 9);
1175 int i = p - buf + 9;
1180 l = strtol((char *)buf + i, &q, 10);
1181 if (q && *q == ':' && l > 0) {
1184 if (j + l > *values_len)
1186 i = q + 1 + l - (char *)buf;
1187 memcpy((char *)values_return + j, q + 1, l);
1189 } else if (l == 18) {
1190 if (j6 + l > *values6_len)
1192 i = q + 1 + l - (char *)buf;
1193 memcpy((char *)values6_return + j6, q + 1, l);
1196 debugf("Received weird value -- %d bytes.\n", (int)l);
1197 i = q + 1 + l - (char *)buf;
1203 if (i >= buflen || buf[i] != 'e')
1204 debugf("eek... unexpected end for values.\n");
1216 p = memmem(buf, buflen, "4:wantl", 7);
1218 int i = p - buf + 7;
1220 while (buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
1221 i + 2 + buf[i] - '0' < buflen) {
1222 CHECK(buf + i + 2, buf[i] - '0');
1223 if (buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
1224 *want_return |= WANT4;
1225 else if (buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
1226 *want_return |= WANT6;
1228 debugf("eek... unexpected want flag (%c)\n", buf[i]);
1229 i += 2 + buf[i] - '0';
1231 if (i >= buflen || buf[i] != 'e')
1232 debugf("eek... unexpected end for want.\n");
1240 if (memmem(buf, buflen, "1:y1:r", 6))
1242 if (memmem(buf, buflen, "1:y1:e", 6))
1244 if (!memmem(buf, buflen, "1:y1:q", 6))
1246 if (memmem(buf, buflen, "1:q4:ping", 9))
1248 if (memmem(buf, buflen, "1:q9:find_node", 14))
1250 if (memmem(buf, buflen, "1:q9:get_peers", 14))
1252 if (memmem(buf, buflen, "1:q13:announce_peer", 19))
1253 return ANNOUNCE_PEER;
1257 debugf("Truncated message.\n");