THE SOFTWARE.
*/
-#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
+#include <poll.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/types.h>
#include <time.h>
#include <unistd.h>
-#ifndef MSG_CONFIRM
-#define MSG_CONFIRM 0
-#endif
-
-#define MAX(x, y) ((x) >= (y) ? (x) : (y))
#define MIN(x, y) ((x) <= (y) ? (x) : (y))
static int
const unsigned char *tid,
int tid_len,
const unsigned char *target,
- int want,
- int confirm);
+ int want);
static int
send_nodes(
struct sockaddr *sa,
return send_ping((struct sockaddr *)&ss, sslen, ttid, 4);
} else {
unsigned char id[20];
- int i;
- for (i = 0; i < 20; i++)
- id[i] = random() & 0xFF;
+ arc4random_buf(id, sizeof id);
make_tid(ttid, "fn", 0);
debugf("Sending find_node.\n");
- return send_find_node((struct sockaddr *)&ss, sslen, ttid, 4, id, want, 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 err = getaddrinfo(host, port, &hints, &res);
+ if (err != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
+ exit(1);
+ }
+ int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (sock == -1) {
+ perror("socket");
+ exit(1);
+ }
+ if (bind(sock, res->ai_addr, res->ai_addrlen) != 0) {
+ perror("bind");
+ exit(1);
+ }
+ int rc = fcntl(sock, F_GETFL, 0);
+ if (rc < 0) {
+ perror("F_GETFL");
+ exit(1);
+ }
+ rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
+ if (rc < 0) {
+ perror("F_SETFL");
+ exit(1);
+ }
+ freeaddrinfo(res);
+ return sock;
+}
+
int
main(int argc, char **argv)
{
- int port = 6881, quiet = 0, ipv4 = 1, ipv6 = 1;
- int opt, rc, i, send4;
- unsigned char ttid[4];
+ errno = 0;
+ int quiet = 0;
+ char *ipv4addr = NULL;
+ char *ipv6addr = NULL;
+ int opt = 0;
while (1) {
- opt = getopt(argc, argv, "q46");
+ opt = getopt(argc, argv, "q4:6:");
if (opt < 0)
break;
quiet = 1;
break;
case '4':
- ipv6 = 0;
+ ipv4addr = strdup(optarg);
break;
case '6':
- ipv4 = 0;
+ ipv6addr = strdup(optarg);
break;
default:
goto usage;
}
}
- i = optind;
+ int i = optind;
if (argc < i + 1)
goto usage;
- port = atoi(argv[i++]);
- if (port <= 0 || port >= 0x10000)
- goto usage;
-
- if (ipv4) {
- dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
- if (dht_socket < 0)
- perror("socket(IPv4)");
- }
-
- if (ipv6) {
- dht_socket6 = socket(PF_INET6, SOCK_DGRAM, 0);
- if (dht_socket6 < 0)
- perror("socket(IPv6)");
- }
-
- if (dht_socket < 0 && dht_socket6 < 0) {
- fprintf(stderr, "Eek!\n");
- exit(1);
- }
+ const char *port = strdup(argv[i++]);
- if (dht_socket >= 0) {
- struct sockaddr_in sin;
- int rc;
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- rc = bind(dht_socket, (struct sockaddr *)&sin, sizeof(sin));
- if (rc < 0) {
- perror("bind(IPv4)");
- exit(1);
- }
-
- rc = fcntl(dht_socket, F_GETFL, 0);
- if (rc < 0) {
- perror("F_GETFL");
- exit(1);
- }
-
- rc = fcntl(dht_socket, F_SETFL, (rc | O_NONBLOCK));
- if (rc < 0) {
- perror("F_SETFL");
- exit(1);
- }
+ if (ipv4addr != NULL) {
+ dht_socket = newSock(ipv4addr, port);
}
-
- if (dht_socket6 >= 0) {
- struct sockaddr_in6 sin6;
- int rc;
- int val = 1;
-
- rc = setsockopt(
- dht_socket6, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val));
- if (rc < 0) {
- perror("setsockopt(IPV6_V6ONLY)");
- exit(1);
- }
-
- /* BEP-32 mandates that we should bind this socket to one of our
- global IPv6 addresses. In this program, this only happens if
- the user used the -b flag. */
-
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_family = AF_INET6;
- sin6.sin6_port = htons(port);
- rc = bind(dht_socket6, (struct sockaddr *)&sin6, sizeof(sin6));
- if (rc < 0) {
- perror("bind(IPv6)");
- exit(1);
- }
-
- rc = fcntl(dht_socket6, F_GETFL, 0);
- if (rc < 0) {
- perror("F_GETFL");
- exit(1);
- }
-
- rc = fcntl(dht_socket6, F_SETFL, (rc | O_NONBLOCK));
- if (rc < 0) {
- perror("F_SETFL");
- exit(1);
- }
+ if (ipv6addr != NULL) {
+ dht_socket6 = newSock(ipv6addr, port);
}
- {
- int fd;
- unsigned int seed;
-
- fd = open("/dev/urandom", O_RDONLY);
- if (fd < 0) {
- perror("open(random)");
- exit(1);
- }
-
- rc = read(fd, myid, 20);
- if (rc < 20) {
- perror("open(random)");
- exit(1);
- }
-
- rc = read(fd, &seed, sizeof(seed));
- srandom(seed);
-
- close(fd);
- }
+ arc4random_buf(myid, sizeof myid);
memcpy(my_v, "1:v4:JB\0\0", 9);
have_v = 1;
if (!quiet)
dht_debug = stdout;
+ int rc = 0;
+ unsigned char ttid[4];
+
while (i < argc) {
struct addrinfo hints, *info, *infop;
memset(&hints, 0, sizeof(hints));
token_bucket_time = time(NULL);
token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
+ int send4 = 0;
+ struct pollfd fds[2];
+ fds[0].fd = dht_socket;
+ fds[0].events = POLLIN;
+ fds[1].fd = dht_socket6;
+ fds[1].events = POLLIN;
while (1) {
- struct timeval tv;
- fd_set readfds;
- int rc;
-
+ int tv_sec = 0;
if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
(dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
- tv.tv_sec = 0;
+ tv_sec = 0;
else
- tv.tv_sec = random() % 30;
- tv.tv_usec = random() % 1000000;
-
- FD_ZERO(&readfds);
- if (dht_socket >= 0)
- FD_SET(dht_socket, &readfds);
- if (dht_socket6 >= 0)
- FD_SET(dht_socket6, &readfds);
+ tv_sec = random() % 30;
+ int tv_msec = random() % 1000;
if (dht_debug)
debugf(
list_elements(&v4_new),
list_elements(&v6_new));
- rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL, &tv);
+ int rc = poll(fds, 2, tv_sec * 1000 + tv_msec);
if (rc < 0) {
- if (errno != EINTR) {
- perror("select");
- sleep(1);
- }
+ perror("poll");
+ sleep(1);
}
if (rc > 0) {
- int rc, message;
+ int rc = 0;
+ int message;
unsigned char tid[16], id[20], info_hash[20], target[20];
unsigned char buf[1536], nodes[256], nodes6[1024], token[128];
int tid_len = 16, token_len = 128;
struct sockaddr_storage source_storage;
struct sockaddr *source = (struct sockaddr *)&source_storage;
socklen_t sourcelen = sizeof(source_storage);
- if (dht_socket >= 0 && FD_ISSET(dht_socket, &readfds)) {
- rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
- } else if (dht_socket6 >= 0 && FD_ISSET(dht_socket6, &readfds)) {
- rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
+ if (fds[0].revents != 0) {
+ if ((fds[0].revents & (POLLERR | POLLNVAL)) > 0) {
+ fprintf(stderr, "error in fds[0]");
+ rc = -1;
+ } else {
+ rc = recvfrom(dht_socket, buf, 1536, 0, source, &sourcelen);
+ }
+ } else if (fds[1].revents != 0) {
+ if ((fds[1].revents & (POLLERR | POLLNVAL)) > 0) {
+ fprintf(stderr, "error in fds[1]");
+ rc = -1;
+ } else {
+ rc = recvfrom(dht_socket6, buf, 1536, 0, source, &sourcelen);
+ };
}
if (rc < 0 || sourcelen > sizeof(struct sockaddr_storage))
return 0;
usage:
- fprintf(stderr, "dht-bootstrap [-q] [-4] [-6] port [node port...]\n");
+ fprintf(stderr, "dht-bootstrap [-q] [-4 ADDR4] [-6 ADDR6] port [node port...]\n");
exit(1);
}
const unsigned char *tid,
int tid_len,
const unsigned char *target,
- int want,
- int confirm)
+ int want)
{
char buf[512];
int i = 0, rc;
ADD_V(buf, i, 512);
rc = snprintf(buf + i, 512 - i, "1:y1:qe");
INC(i, rc, 512);
- return dht_send(buf, i, confirm ? MSG_CONFIRM : 0, sa, salen);
+ return dht_send(buf, i, 0, sa, salen);
fail:
errno = ENOSPC;