}
}
+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;
quiet = 1;
break;
case '4':
- ipv6 = 0;
+ ipv4addr = strdup(optarg);
break;
case '6':
- ipv4 = 0;
+ ipv6addr = strdup(optarg);
break;
default:
goto usage;
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;
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);
}