]> Sergey Matveev's repositories - dht-bootstrap.git/commitdiff
Specify bind addresses explicitly
authorSergey Matveev <stargrave@stargrave.org>
Wed, 9 Nov 2022 08:45:35 +0000 (11:45 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Wed, 9 Nov 2022 10:14:54 +0000 (13:14 +0300)
CHANGES
dht-bootstrap.c

diff --git a/CHANGES b/CHANGES
index cc312427e53c3b40d6375f953659ce184f295afd..3e586500254ecdf74a8527d33b06490f2323fdb8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+2022-11-09:
+
+  * Ability to explicitly specify IP addresses to bind to
+
 20 November 2011: dht-bootstrap-0.2
 
   * Fixed a bug that could cause EAFNOSUPPORT errors.
index cd6c96e46b3734432230e5ba8a2d4f3a9def829e..de5bb395c5416b1412712d76e3688f519a1b2092 100644 (file)
@@ -366,17 +366,53 @@ send_request(struct circular_list *list, int dopop, int doping, int 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)
 {
     errno = 0;
     int quiet = 0;
-    int ipv4 = 1;
-    int ipv6 = 1;
+    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;
 
@@ -385,10 +421,10 @@ 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;
@@ -400,88 +436,13 @@ main(int argc, char **argv)
     if (argc < i + 1)
         goto usage;
 
-    port = atoi(argv[i++]);
-    if (port <= 0 || port >= 0x10000)
-        goto usage;
+    const char *port = strdup(argv[i++]);
 
-    if (ipv4) {
-        dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
-        if (dht_socket < 0)
-            perror("socket(IPv4)");
+    if (ipv4addr != NULL) {
+        dht_socket = newSock(ipv4addr, port);
     }
-
-    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);
-        }
-
-        rc = fcntl(dht_socket, F_SETFL, (rc | O_NONBLOCK));
-        if (rc < 0) {
-            perror("F_SETFL");
-            exit(1);
-        }
-    }
-
-    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;
@@ -757,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);
 }