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)
379 opt = getopt(argc, argv, "q46");
403 port = atoi(argv[i++]);
404 if (port <= 0 || port >= 0x10000)
408 dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
410 perror("socket(IPv4)");
414 dht_socket6 = socket(PF_INET6, SOCK_DGRAM, 0);
416 perror("socket(IPv6)");
419 if (dht_socket < 0 && dht_socket6 < 0) {
420 fprintf(stderr, "Eek!\n");
424 if (dht_socket >= 0) {
425 struct sockaddr_in sin;
427 memset(&sin, 0, sizeof(sin));
428 sin.sin_family = AF_INET;
429 sin.sin_port = htons(port);
430 rc = bind(dht_socket, (struct sockaddr *)&sin, sizeof(sin));
432 perror("bind(IPv4)");
436 rc = fcntl(dht_socket, F_GETFL, 0);
442 rc = fcntl(dht_socket, F_SETFL, (rc | O_NONBLOCK));
449 if (dht_socket6 >= 0) {
450 struct sockaddr_in6 sin6;
455 dht_socket6, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val));
457 perror("setsockopt(IPV6_V6ONLY)");
461 /* BEP-32 mandates that we should bind this socket to one of our
462 global IPv6 addresses. In this program, this only happens if
463 the user used the -b flag. */
465 memset(&sin6, 0, sizeof(sin6));
466 sin6.sin6_family = AF_INET6;
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));
489 int fd = open("/dev/urandom", O_RDONLY);
491 perror("open(random)");
495 rc = read(fd, myid, 20);
497 perror("open(random)");
502 rc = read(fd, &seed, sizeof(seed));
508 memcpy(my_v, "1:v4:JB\0\0", 9);
514 unsigned char ttid[4];
517 struct addrinfo hints, *info, *infop;
518 memset(&hints, 0, sizeof(hints));
519 hints.ai_socktype = SOCK_DGRAM;
522 hints.ai_family = AF_INET6;
523 else if (dht_socket6 < 0)
524 hints.ai_family |= AF_INET;
525 rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
527 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
537 make_tid(ttid, "pn", 0);
538 debugf("Sending ping.\n");
539 send_ping(infop->ai_addr, infop->ai_addrlen, ttid, 4);
540 infop = infop->ai_next;
547 token_bucket_time = time(NULL);
548 token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
555 if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
556 (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
559 tv.tv_sec = random() % 30;
560 tv.tv_usec = random() % 1000000;
564 FD_SET(dht_socket, &readfds);
565 if (dht_socket6 >= 0)
566 FD_SET(dht_socket6, &readfds);
571 list_elements(&v4_confirmed),
572 list_elements(&v6_confirmed),
573 list_elements(&v4_new),
574 list_elements(&v6_new));
576 int rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL, &tv);
579 if (errno != EINTR) {
588 unsigned char tid[16], id[20], info_hash[20], target[20];
589 unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
590 int tid_len = 16, token_len = 128;
591 int nodes_len = 256, nodes6_len = 1024;
593 unsigned char values[2048], values6[2048];
594 int values_len = 2048, values6_len = 2048;
596 struct sockaddr_storage source_storage;
597 struct sockaddr *source = (struct sockaddr *)&source_storage;
598 socklen_t sourcelen = sizeof(source_storage);
599 if (dht_socket >= 0 && FD_ISSET(dht_socket, &readfds)) {
600 rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
601 } else if (dht_socket6 >= 0 && FD_ISSET(dht_socket6, &readfds)) {
602 rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
605 if (rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
608 if (is_martian(source))
611 /* There's a bug in parse_message -- it will happily overflow the
612 buffer if it's not NUL-terminated. For now, put a NUL at the
618 debugf("Overlong message.\n");
622 message = parse_message(
643 if (id_cmp(id, myid) == 0) {
644 debugf("Received message from self.\n");
648 if (message > REPLY) {
649 /* Rate limit requests. */
650 if (!token_bucket()) {
651 debugf("Dropping request due to rate limiting.\n");
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), 0);
682 for (i = 0; i < nodes6_len / 38; i++) {
683 unsigned char *ni = nodes6 + i * 38;
684 struct sockaddr_in6 sin6;
685 if (id_cmp(ni, myid) == 0)
687 memset(&sin6, 0, sizeof(sin6));
688 sin6.sin6_family = AF_INET6;
689 memcpy(&sin6.sin6_addr, ni + 20, 16);
690 memcpy(&sin6.sin6_port, ni + 36, 2);
691 new_node(ni, (struct sockaddr *)&sin6, sizeof(sin6), 0);
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, tid, tid_len, target, want);
717 debugf("Announce peer!\n");
724 "This node doesn't accept announces");
731 /* We need to be careful to avoid a positive feedback loop. Make
732 sure we send at most one packet each time through the select
737 else if (dht_socket < 0)
740 send4 = random() % 2;
743 int want = dht_socket6 >= 0 && list_free(&v6_new) > 8 ? (WANT4 | WANT6) : 0;
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);
749 int want = dht_socket >= 0 && list_free(&v4_new) > 8 ? (WANT4 | WANT6) : 0;
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) \
771 #define INC(offset, delta, size) \
772 CHECK(offset, delta, size); \
775 #define COPY(buf, offset, src, delta, size) \
776 CHECK(offset, delta, size); \
777 memcpy(buf + offset, src, delta); \
780 #define ADD_V(buf, offset, size) \
782 COPY(buf, offset, my_v, sizeof(my_v), size); \
786 dht_send(const void *buf, size_t len, int flags, 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, const unsigned char *tid, int tid_len)
813 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
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");
822 return dht_send(buf, i, 0, sa, salen);
830 send_pong(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len)
834 rc = snprintf(buf + i, 512 - i, "d1:rd2:id20:");
836 COPY(buf, i, myid, 20, 512);
837 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
839 COPY(buf, i, tid, tid_len, 512);
841 rc = snprintf(buf + i, 512 - i, "1:y1:re");
843 return dht_send(buf, i, 0, sa, salen);
854 const unsigned char *tid,
856 const unsigned char *target,
861 rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
863 COPY(buf, i, myid, 20, 512);
864 rc = snprintf(buf + i, 512 - i, "6:target20:");
866 COPY(buf, i, target, 20, 512);
872 (want & WANT4) ? "2:n4" : "",
873 (want & WANT6) ? "2:n6" : "");
876 rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
878 COPY(buf, i, tid, tid_len, 512);
880 rc = snprintf(buf + i, 512 - i, "1:y1:qe");
882 return dht_send(buf, i, 0, sa, salen);
893 const unsigned char *tid,
895 const unsigned char *nodes,
897 const unsigned char *nodes6,
903 rc = snprintf(buf + i, 2048 - i, "d1:rd2:id20:");
905 COPY(buf, i, myid, 20, 2048);
907 rc = snprintf(buf + i, 2048 - i, "5:nodes%d:", nodes_len);
909 COPY(buf, i, nodes, nodes_len, 2048);
911 if (nodes6_len > 0) {
912 rc = snprintf(buf + i, 2048 - i, "6:nodes6%d:", nodes6_len);
914 COPY(buf, i, nodes6, nodes6_len, 2048);
917 rc = snprintf(buf + i, 2048 - i, "e1:t%d:", tid_len);
919 COPY(buf, i, tid, tid_len, 2048);
921 rc = snprintf(buf + i, 2048 - i, "1:y1:re");
924 return dht_send(buf, i, 0, sa, salen);
932 buffer_random_nodes(int af, unsigned char *nodes)
934 struct circular_list *list;
935 struct sockaddr_storage ss;
937 unsigned char id[20];
943 list = &v4_confirmed;
946 list = &v6_confirmed;
954 rc = list_random(list, id, &ss, &sslen);
959 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
960 memcpy(nodes + n * 26, id, 20);
961 memcpy(nodes + n * 26 + 20, &sin->sin_addr, 4);
962 memcpy(nodes + n * 26 + 24, &sin->sin_port, 2);
967 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
968 memcpy(nodes + n * 38, id, 20);
969 memcpy(nodes + n * 38 + 20, &sin6->sin6_addr, 16);
970 memcpy(nodes + n * 38 + 36, &sin6->sin6_port, 2);
985 const unsigned char *tid,
987 const unsigned char *id,
990 unsigned char nodes[8 * 26];
991 unsigned char nodes6[8 * 38];
992 int numnodes = 0, numnodes6 = 0;
995 want = sa->sa_family == AF_INET ? WANT4 : WANT6;
998 numnodes = buffer_random_nodes(AF_INET, nodes);
1001 numnodes6 = buffer_random_nodes(AF_INET6, nodes6);
1004 sa, salen, tid, tid_len, nodes, numnodes * 26, nodes6, numnodes6 * 38);
1009 struct sockaddr *sa,
1014 const char *message)
1019 rc = snprintf(buf + i, 512 - i, "d1:eli%de%d:", code, (int)strlen(message));
1021 COPY(buf, i, message, (int)strlen(message), 512);
1022 rc = snprintf(buf + i, 512 - i, "e1:t%d:", tid_len);
1024 COPY(buf, i, tid, tid_len, 512);
1026 rc = snprintf(buf + i, 512 - i, "1:y1:ee");
1028 return dht_send(buf, i, 0, sa, salen);
1042 const unsigned char *buf,
1044 unsigned char *tid_return,
1046 unsigned char *id_return,
1047 unsigned char *info_hash_return,
1048 unsigned char *target_return,
1049 unsigned short *port_return,
1050 unsigned char *token_return,
1052 unsigned char *nodes_return,
1054 unsigned char *nodes6_return,
1056 unsigned char *values_return,
1058 unsigned char *values6_return,
1062 const unsigned char *p;
1064 /* This code will happily crash if the buffer is not NUL-terminated. */
1065 if (buf[buflen] != '\0') {
1066 debugf("Eek! parse_message with unterminated buffer.\n");
1070 #define CHECK(ptr, len) \
1071 if (((unsigned char *)ptr) + (len) > (buf) + (buflen)) \
1075 p = memmem(buf, buflen, "1:t", 3);
1079 l = strtol((char *)p + 3, &q, 10);
1080 if (q && *q == ':' && l > 0 && l < *tid_len) {
1082 memcpy(tid_return, q + 1, l);
1089 p = memmem(buf, buflen, "2:id20:", 7);
1092 memcpy(id_return, p + 7, 20);
1094 memset(id_return, 0, 20);
1097 if (info_hash_return) {
1098 p = memmem(buf, buflen, "9:info_hash20:", 14);
1101 memcpy(info_hash_return, p + 14, 20);
1103 memset(info_hash_return, 0, 20);
1107 p = memmem(buf, buflen, "porti", 5);
1111 l = strtol((char *)p + 5, &q, 10);
1112 if (q && *q == 'e' && l > 0 && l < 0x10000)
1119 if (target_return) {
1120 p = memmem(buf, buflen, "6:target20:", 11);
1123 memcpy(target_return, p + 11, 20);
1125 memset(target_return, 0, 20);
1129 p = memmem(buf, buflen, "5:token", 7);
1133 l = strtol((char *)p + 7, &q, 10);
1134 if (q && *q == ':' && l > 0 && l < *token_len) {
1136 memcpy(token_return, q + 1, l);
1145 p = memmem(buf, buflen, "5:nodes", 7);
1149 l = strtol((char *)p + 7, &q, 10);
1150 if (q && *q == ':' && l > 0 && l < *nodes_len) {
1152 memcpy(nodes_return, q + 1, l);
1161 p = memmem(buf, buflen, "6:nodes6", 8);
1165 l = strtol((char *)p + 8, &q, 10);
1166 if (q && *q == ':' && l > 0 && l < *nodes6_len) {
1168 memcpy(nodes6_return, q + 1, l);
1176 if (values_len || values6_len) {
1177 p = memmem(buf, buflen, "6:valuesl", 9);
1179 int i = p - buf + 9;
1184 l = strtol((char *)buf + i, &q, 10);
1185 if (q && *q == ':' && l > 0) {
1188 if (j + l > *values_len)
1190 i = q + 1 + l - (char *)buf;
1191 memcpy((char *)values_return + j, q + 1, l);
1193 } else if (l == 18) {
1194 if (j6 + l > *values6_len)
1196 i = q + 1 + l - (char *)buf;
1197 memcpy((char *)values6_return + j6, q + 1, l);
1200 debugf("Received weird value -- %d bytes.\n", (int)l);
1201 i = q + 1 + l - (char *)buf;
1207 if (i >= buflen || buf[i] != 'e')
1208 debugf("eek... unexpected end for values.\n");
1220 p = memmem(buf, buflen, "4:wantl", 7);
1222 int i = p - buf + 7;
1224 while (buf[i] > '0' && buf[i] <= '9' && buf[i + 1] == ':' &&
1225 i + 2 + buf[i] - '0' < buflen) {
1226 CHECK(buf + i + 2, buf[i] - '0');
1227 if (buf[i] == '2' && memcmp(buf + i + 2, "n4", 2) == 0)
1228 *want_return |= WANT4;
1229 else if (buf[i] == '2' && memcmp(buf + i + 2, "n6", 2) == 0)
1230 *want_return |= WANT6;
1232 debugf("eek... unexpected want flag (%c)\n", buf[i]);
1233 i += 2 + buf[i] - '0';
1235 if (i >= buflen || buf[i] != 'e')
1236 debugf("eek... unexpected end for want.\n");
1244 if (memmem(buf, buflen, "1:y1:r", 6))
1246 if (memmem(buf, buflen, "1:y1:e", 6))
1248 if (!memmem(buf, buflen, "1:y1:q", 6))
1250 if (memmem(buf, buflen, "1:q4:ping", 9))
1252 if (memmem(buf, buflen, "1:q9:find_node", 14))
1254 if (memmem(buf, buflen, "1:q9:get_peers", 14))
1256 if (memmem(buf, buflen, "1:q13:announce_peer", 19))
1257 return ANNOUNCE_PEER;
1261 debugf("Truncated message.\n");