]> Sergey Matveev's repositories - dht-bootstrap.git/blobdiff - dht-bootstrap.c
Specify bind addresses explicitly
[dht-bootstrap.git] / dht-bootstrap.c
index 2e6e77dc25fe1aac8a5c858886a64e4b1b84554e..de5bb395c5416b1412712d76e3688f519a1b2092 100644 (file)
@@ -35,10 +35,6 @@ THE SOFTWARE.
 #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))
 
@@ -53,8 +49,7 @@ send_find_node(
     const unsigned char *tid,
     int tid_len,
     const unsigned char *target,
-    int want,
-    int confirm);
+    int want);
 static int
 send_nodes(
     struct sockaddr *sa,
@@ -367,19 +362,57 @@ send_request(struct circular_list *list, int dopop, int doping, int want)
             id[i] = random() & 0xFF;
         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;
 
@@ -388,110 +421,33 @@ main(int argc, char **argv)
             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);
-    }
-
-    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);
-        }
+    const char *port = strdup(argv[i++]);
 
-        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 rc = 0;
     {
-        int fd;
-        unsigned int seed;
-
-        fd = open("/dev/urandom", O_RDONLY);
+        int fd = open("/dev/urandom", O_RDONLY);
         if (fd < 0) {
             perror("open(random)");
             exit(1);
@@ -503,6 +459,7 @@ main(int argc, char **argv)
             exit(1);
         }
 
+        unsigned int seed;
         rc = read(fd, &seed, sizeof(seed));
         srandom(seed);
 
@@ -515,6 +472,8 @@ main(int argc, char **argv)
     if (!quiet)
         dht_debug = stdout;
 
+    unsigned char ttid[4];
+
     while (i < argc) {
         struct addrinfo hints, *info, *infop;
         memset(&hints, 0, sizeof(hints));
@@ -548,11 +507,11 @@ main(int argc, char **argv)
 
     token_bucket_time = time(NULL);
     token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS;
+    int send4 = 0;
 
     while (1) {
         struct timeval tv;
         fd_set readfds;
-        int rc;
 
         if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
             (dht_socket6 >= 0 && list_elements(&v6_confirmed) <= 16))
@@ -575,7 +534,7 @@ main(int argc, char **argv)
                 list_elements(&v4_new),
                 list_elements(&v6_new));
 
-        rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL, &tv);
+        int rc = select(MAX(dht_socket, dht_socket6) + 1, &readfds, NULL, NULL, &tv);
 
         if (rc < 0) {
             if (errno != EINTR) {
@@ -585,7 +544,8 @@ main(int argc, char **argv)
         }
 
         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;
@@ -758,7 +718,7 @@ main(int argc, char **argv)
     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);
 }
 
@@ -855,8 +815,7 @@ send_find_node(
     const unsigned char *tid,
     int tid_len,
     const unsigned char *target,
-    int want,
-    int confirm)
+    int want)
 {
     char buf[512];
     int i = 0, rc;
@@ -881,7 +840,7 @@ send_find_node(
     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;