THE SOFTWARE.
*/
+#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/resource.h>
#include <sys/socket.h>
#include <time.h>
#include <unistd.h>
#define MIN(x, y) ((x) <= (y) ? (x) : (y))
+#ifdef __linux__
+// clang-format off
+void setproctitle_fast(const char *_fmt, ...) {}
+// clang-format on
+#endif
+
static int
send_ping(struct sockaddr *sa, int salen, const unsigned char *tid, int tid_len);
static int
struct node nodes[CIRCULAR_LIST_SIZE];
};
-struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
+static struct circular_list v4_new, v6_new, v4_confirmed, v6_confirmed;
#define MAX_TOKEN_BUCKET_TOKENS 40
static time_t token_bucket_time;
static int token_bucket_tokens;
-FILE *dht_debug = NULL;
+static FILE *dht_debug = NULL;
-#ifdef __GNUC__
-__attribute__((format(printf, 1, 2)))
-#endif
static void
debugf(const char *format, ...)
{
+ if (dht_debug == NULL)
+ return;
va_list args;
va_start(args, format);
- if (dht_debug)
- vfprintf(dht_debug, format, args);
+ vfprintf(dht_debug, format, args);
va_end(args);
fflush(dht_debug);
}
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 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) {
- 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);
- }
+ 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) {
- perror("F_SETFL");
- exit(1);
- }
+ 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()");
+ }
+}
+
int
main(int argc, char **argv)
{
if (argc < i + 1)
goto usage;
- const char *port = strdup(argv[i++]);
-
+ const char *ourPort = strdup(argv[i++]);
if (ipv4addr != NULL) {
- dht_socket = newSock(ipv4addr, port);
+ dht_socket = newSock(ipv4addr, ourPort);
}
if (ipv6addr != NULL) {
- dht_socket6 = newSock(ipv6addr, port);
+ dht_socket6 = newSock(ipv6addr, ourPort);
}
arc4random_buf(myid, sizeof myid);
else if (dht_socket6 < 0)
hints.ai_family |= AF_INET;
rc = getaddrinfo(argv[i], argv[i + 1], &hints, &info);
- if (rc != 0) {
- fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rc));
- exit(1);
- }
+ if (rc != 0)
+ err(EXIT_FAILURE, "getaddrinfo: %s\n", gai_strerror(rc));
i++;
if (i >= argc)
fds[1].fd = dht_socket6;
fds[1].events = POLLIN;
+ close(STDIN_FILENO);
+ if (quiet)
+ close(STDOUT_FILENO);
+ rlimited(RLIMIT_NPROC);
+ rlimited(RLIMIT_FSIZE);
+#if __FreeBSD__
+ rlimited(RLIMIT_NOFILE);
+#endif // __FreeBSD__
+
while (1) {
int tv_sec = 0;
if ((dht_socket >= 0 && list_elements(&v4_confirmed) <= 16) ||
tv_sec = random() % 30;
int tv_msec = random() % 1000;
- if (dht_debug)
- debugf(
- "%d+%d %d+%d\n",
- list_elements(&v4_confirmed),
- list_elements(&v6_confirmed),
- list_elements(&v4_new),
- list_elements(&v6_new));
-
- int rc = poll(fds, 2, tv_sec * 1000 + tv_msec);
+ setproctitle_fast(
+ "%d+%d %d+%d",
+ list_elements(&v4_confirmed),
+ list_elements(&v6_confirmed),
+ list_elements(&v4_new),
+ list_elements(&v6_new));
+ rc = poll(fds, 2, tv_sec * 1000 + tv_msec);
if (rc < 0) {
perror("poll");
sleep(1);
}
if (rc > 0) {
- 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];
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 ADDR4] [-6 ADDR6] port [node port...]\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
/* We could use a proper bencoding printer and parser, but the format of