+ char buf[512];
+ int i = 0;
+ int rc = snprintf(buf + i, 512 - i, "d1:ad2:id20:");
+ INC(i, rc, 512);
+ COPY(buf, i, myid, 20, 512);
+ rc = snprintf(buf + i, 512 - i, "6:target20:");
+ INC(i, rc, 512);
+ COPY(buf, i, target, 20, 512);
+ if (want > 0) {
+ rc = snprintf(
+ buf + i,
+ 512 - i,
+ "4:wantl%s%se",
+ (want & WANT4) ? "2:n4" : "",
+ (want & WANT6) ? "2:n6" : "");
+ INC(i, rc, 512);
+ }
+ rc = snprintf(buf + i, 512 - i, "e1:q9:find_node1:t%d:", tid_len);
+ INC(i, rc, 512);
+ COPY(buf, i, tid, tid_len, 512);
+ ADD_V(buf, i, 512);
+ rc = snprintf(buf + i, 512 - i, "1:y1:qe");
+ INC(i, rc, 512);
+ if (verbose)
+ printf("%s <- FIND_NODE\n", getAddr(sa, salen));
+ return dht_send(buf, i, 0, sa, salen);
+
+fail:
+ errno = ENOSPC;
+ return -1;
+}
+
+static int
+send_request(struct circular_list *list, int dopop, int doping, int want)
+{
+ if (list_empty(list))
+ return 0;
+
+ struct sockaddr_storage ss;
+ socklen_t sslen;
+ int rc;
+ if (dopop) {
+ rc = list_pop(list, &ss, &sslen);
+ if (rc == 0)
+ return 0;
+ } else {
+ rc = list_random(list, NULL, &ss, &sslen);
+ if (rc == 0)
+ return 0;
+ }
+
+ unsigned char ttid[4];
+ if (doping) {
+ make_tid(ttid, "pn", 0);
+ return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
+ } else {
+ unsigned char id[20];
+ arc4random_buf(id, sizeof id);
+ make_tid(ttid, "fn", 0);
+ return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want);
+ }
+}
+
+static int
+newSock(const char *host, const char *port)
+{
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ struct addrinfo *res = NULL;
+ int rc = getaddrinfo(host, port, &hints, &res);
+ if (rc != 0)
+ err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
+ int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (sock == -1)
+ err(EXIT_FAILURE, "socket()");
+ if (bind(sock, res->ai_addr, res->ai_addrlen) != 0)
+ err(EXIT_FAILURE, "bind()");
+ rc = fcntl(sock, F_GETFL, 0);
+ if (rc < 0)
+ err(EXIT_FAILURE, "F_GETFL");
+ rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
+ if (rc < 0)
+ err(EXIT_FAILURE, "F_SETFL");
+ freeaddrinfo(res);
+ return sock;
+}
+
+static void
+rlimited(int res)
+{
+ struct rlimit r;
+ r.rlim_cur = 0;
+ r.rlim_max = 0;
+ if (setrlimit(res, &r) == -1) {
+ err(EXIT_FAILURE, "can not setrlimit()");