X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=dht-bootstrap.c;h=33ef79808d12d75080a1562bac7a344493f83caa;hb=b1e56d6f9899302434adc97e68b5a644d5ad750c;hp=a4fe67e9363ce7c698e40910ddfdb389c5478fe0;hpb=5bb5f9f8605072ff9f68723a8fd4887d709ce37f;p=dht-bootstrap.git diff --git a/dht-bootstrap.c b/dht-bootstrap.c index a4fe67e..33ef798 100644 --- a/dht-bootstrap.c +++ b/dht-bootstrap.c @@ -20,54 +20,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* For memmem. */ -#define _GNU_SOURCE - -#include #include #include #include #include +#include #include #include #include #include #include -#include -#include #include #include -#ifndef HAVE_MEMMEM -#ifdef __GLIBC__ -#define HAVE_MEMMEM -#endif -#endif - -#ifndef MSG_CONFIRM -#define MSG_CONFIRM 0 -#endif - -/* We set sin_family to 0 to mark unused slots. */ -#if AF_INET == 0 || AF_INET6 == 0 -#error You lose -#endif - -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -/* nothing */ -#elif defined(__GNUC__) -#define inline __inline -#if (__GNUC__ >= 3) -#define restrict __restrict -#else -#define restrict /**/ -#endif -#else -#define inline /**/ -#define restrict /**/ -#endif - -#define MAX(x, y) ((x) >= (y) ? (x) : (y)) #define MIN(x, y) ((x) <= (y) ? (x) : (y)) static int @@ -81,8 +46,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, @@ -395,19 +359,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; @@ -416,110 +418,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)"); - } + const char *port = strdup(argv[i++]); - 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 (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); @@ -531,6 +456,7 @@ main(int argc, char **argv) exit(1); } + unsigned int seed; rc = read(fd, &seed, sizeof(seed)); srandom(seed); @@ -543,6 +469,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)); @@ -576,24 +504,29 @@ main(int argc, char **argv) token_bucket_time = time(NULL); token_bucket_tokens = MAX_TOKEN_BUCKET_TOKENS; + int send4 = 0; + struct pollfd fds[2]; + if (dht_socket >= 0) { + fds[0].fd = dht_socket; + fds[0].events = POLLIN; + } else { + fds[0].fd = -1; + } + if (dht_socket6 >= 0) { + fds[1].fd = dht_socket6; + fds[1].events = POLLIN; + } else { + fds[1].fd = -1; + } 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( @@ -603,17 +536,16 @@ 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 = 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; @@ -625,10 +557,20 @@ main(int argc, char **argv) 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)) @@ -786,7 +728,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); } @@ -883,8 +825,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; @@ -909,7 +850,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; @@ -1067,26 +1008,6 @@ fail: #undef COPY #undef ADD_V -#ifndef HAVE_MEMMEM -static void * -memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) -{ - const char *h = haystack; - const char *n = needle; - size_t i; - - /* size_t is unsigned */ - if (needlelen > haystacklen) - return NULL; - - for (i = 0; i <= haystacklen - needlelen; i++) { - if (memcmp(h + i, n, needlelen) == 0) - return (void *)(h + i); - } - return NULL; -} -#endif - static int parse_message( const unsigned char *buf,