summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2022-12-31 18:09:39 +0100
committerAnton Luka Šijanec <anton@sijanec.eu>2022-12-31 18:09:39 +0100
commitbe5631dff1f4f28636ba1b88e9d17034fe4551d0 (patch)
treec462139b9ab130579be5e7f14247fe069a9d4032 /src
parentdns resolving for bootstrapping, dht.c compiles, but is untested (diff)
downloadtravnik-be5631dff1f4f28636ba1b88e9d17034fe4551d0.tar
travnik-be5631dff1f4f28636ba1b88e9d17034fe4551d0.tar.gz
travnik-be5631dff1f4f28636ba1b88e9d17034fe4551d0.tar.bz2
travnik-be5631dff1f4f28636ba1b88e9d17034fe4551d0.tar.lz
travnik-be5631dff1f4f28636ba1b88e9d17034fe4551d0.tar.xz
travnik-be5631dff1f4f28636ba1b88e9d17034fe4551d0.tar.zst
travnik-be5631dff1f4f28636ba1b88e9d17034fe4551d0.zip
Diffstat (limited to 'src')
-rw-r--r--src/bencoding.c23
-rw-r--r--src/dht.c24
-rw-r--r--src/main.c82
3 files changed, 94 insertions, 35 deletions
diff --git a/src/bencoding.c b/src/bencoding.c
index bcf8f17..66b43b3 100644
--- a/src/bencoding.c
+++ b/src/bencoding.c
@@ -146,20 +146,13 @@ struct bencoding * bstrs_set (struct bencoding * b, char * s) {
* @param num [in] the number to be converted to a bencoding number
*/
-struct bencoding * bnum (long int num) {
+struct bencoding * bnum (long int nr) {
struct bencoding * b = calloc(1, sizeof *b);
if (!b)
return NULL;
b->type = num;
- /* char buf[512];
- sprintf(buf, "%ld", num);
- b->value = strdup(buf);
- if (!b->intvalue) {
- free(b);
- return NULL;
- } */ // we could do this, but I don't think it's necessary.
b->valuelen = 0;
- b->intvalue = num;
+ b->intvalue = nr;
return b;
}
@@ -513,7 +506,7 @@ struct bencoding * bdecode_safe (const char * s, int len, enum benc opts, unsign
return NULL;
default:
if (!(s[0] >= '0' && s[0] <= '9')) { /* not a string. not checking this would allow DoS for parsing "lx" */
- fprintf(stderr, "bencoding: unknown type %c\n", s[0]);
+ fprintf(stderr, "bencoding: unknown type %d - %c\n", s[0], s[0]);
free(b);
return NULL;
}
@@ -523,7 +516,7 @@ struct bencoding * bdecode_safe (const char * s, int len, enum benc opts, unsign
if (len != -1 && (unsigned)len < b->valuelen + (ch+1 - s) /* len minus prefix; strlen & colon */)
b->valuelen = len - (ch+1 - s); /* malformed bencoded data, truncating string */
b->value = malloc(b->valuelen+1);
- strncpy(b->value, ch+1, b->valuelen);
+ memcpy(b->value, ch+1, b->valuelen); // ofc not strncpy - binary strs
b->value[b->valuelen] = '\0';
b->after = ch+1+b->valuelen;
} else {
@@ -541,7 +534,7 @@ struct bencoding * bdecode_safe (const char * s, int len, enum benc opts, unsign
*
* nonstandard things: this parser allows for dict keys to be of any type, valuekey
*
- * this is a wrapper function, the implementation is in bdecode_safe that was made as an afterthought to prevent stack overflows and limits the number of elements bdecoded to 2**16.
+ * this is a wrapper function, the implementation is in bdecode_safe that was made as an afterthought to prevent stack overflows and limits the number of elements bdecoded.
*
* @param len [in] * if set to -1, string is assumed to be correct and not NULL terminated, NULLs may be in strings.
* - malicious strings may trigger reads past the end of the buffer, which may lead to undefined
@@ -560,7 +553,7 @@ struct bencoding * bdecode_safe (const char * s, int len, enum benc opts, unsign
*/
struct bencoding * bdecode (const char * s, int len, enum benc opts) {
- return bdecode_safe(s, len, opts, 0, 65535);
+ return bdecode_safe(s, len, opts, 0, 1 << 21);
}
/**
@@ -664,7 +657,7 @@ int bencode_length (struct bencoding * b) {
return strlen(buf)+bencode_length(b->key)+2;
}
if (b->type & string) {
- sprintf(buf, "%ld", b->valuelen);
+ sprintf(buf, "%zu", b->valuelen);
return strlen(buf)+1+b->valuelen+bencode_length(b->key);
}
if (b->type & (list | dict)) {
@@ -704,7 +697,7 @@ char * bencode (char * dest, struct bencoding * b) {
*dest++ = 'e';
}
if (b->type & string) {
- sprintf(buf, "%ld:", b->valuelen);
+ sprintf(buf, "%zu:", b->valuelen);
strncpy(dest, buf, strlen(buf));
dest += strlen(buf);
memcpy(dest, b->value, b->valuelen);
diff --git a/src/dht.c b/src/dht.c
index 996dcb1..b11580a 100644
--- a/src/dht.c
+++ b/src/dht.c
@@ -158,7 +158,6 @@ struct torrent {
enum interested type; /**< is truthy only for manually added torrents */
unsigned char hash[20]; /**< infohash */
struct peer * peers;
- time_t last; /**< last operation on this torrent, so that inactive torrents are purged */
struct node * nodes; /**< closest K DHT nodes to this hash, used only for announce, peers, info and dl torrents */
struct torrent * next;
struct torrent * prev; /**< prev is here so that we can easily pop the oldest torrent. dht->last_torrent is useful here */
@@ -590,7 +589,8 @@ struct node * find (const unsigned char * id, struct bucket ** b, struct node **
prev = node;
node = node->next;
}
- *n = prev;
+ if (n)
+ *n = prev;
return node;
}
@@ -959,7 +959,7 @@ void compact (struct dht * d, const char * value, int len, struct torrent * t) {
return;
}
struct node * node = node_init();
- memcpy(node->addr.sin6_addr.s6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\xFF\xFF\xFF\xFF", 12);
+ memcpy(node->addr.sin6_addr.s6_addr, "\0\0\0\0\0\0\0\0\0\0\xFF\xFF", 12);
node->addr.sin6_port = *((uint16_t *) (value + len-2));
memcpy(node->addr.sin6_addr.s6_addr+(len == 4+2+20 ? 8 : 0), value + 20, len == 4+2+20 ? 4 : 16);
memcpy(node->id, value, 20);
@@ -1343,7 +1343,7 @@ void handle (struct dht * d, char * pkt, int len, struct sockaddr_in6 addr) {
if (!(p->type & string) || (p->valuelen != 6 && p->valuelen != 18))
break;
struct peer * peer = calloc(1, sizeof *peer);
- memcpy(peer->addr.sin6_addr.s6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\xFF\xFF\xFF\xFF", 12);
+ memcpy(peer->addr.sin6_addr.s6_addr, "\0\0\0\0\0\0\0\0\0\0\xFF\xFF", 12);
peer->addr.sin6_port = *((uint16_t *) (p->value + p->valuelen-2));
memcpy(peer->addr.sin6_addr.s6_addr+(p->valuelen == 6 ? 8 : 0), p->value, p->valuelen == 6 ? 4 : 16);
add_peer(d, torrent, peer);
@@ -1427,14 +1427,13 @@ void handle (struct dht * d, char * pkt, int len, struct sockaddr_in6 addr) {
.sin6_family = AF_INET6,
.sin6_port = *((uint16_t *) pkt)
};
- memcpy(a.sin6_addr.s6_addr, "\0\0\0\0\0\0\0\0\xFF\xFF\xFF\xFF", 12);
+ memcpy(a.sin6_addr.s6_addr, "\0\0\0\0\0\0\0\0\0\0\xFF\xFF", 12);
memcpy(a.sin6_addr.s6_addr+12, rr.rdata, 4);
potential_node(NULL, &a, NULL);
break;
case 16:
- if (!inet_ntop(AF_INET6, rr.rdata, address, INET6_ADDRSTRLEN+INET_ADDRSTRLEN+7)) {
+ if (!inet_ntop(AF_INET6, rr.rdata, address, INET6_ADDRSTRLEN+INET_ADDRSTRLEN+7))
L(d->log, "%s !inet_ntop(AF_INET6)", remote);
- }
sprintf(address+strlen(address), ":%u", ntohs(*((uint16_t *) pkt)));
L(d->log, "%s: AAAA %s", remote, address);
struct sockaddr_in6 aaaa = {
@@ -1586,7 +1585,7 @@ void periodic (struct dht * d) {
if (!refresh(d->buckets6))
dns++;
if (dns) {
- char packet[65536];
+ char packet[512];
struct __res_state state;
if (res_ninit(&state) == -1) {
L(d->log, "res_ninit(&state) == -1");
@@ -1594,7 +1593,7 @@ void periodic (struct dht * d) {
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-sign"
- int size = res_nmkquery(&state, QUERY, "_dht._udp.travnik.sijanec.eu", ns_c_in, ns_t_srv, NULL, 0, NULL, packet, 65536) != -1;
+ int size = res_nmkquery(&state, QUERY, "_dht._udp.travnik.sijanec.eu", ns_c_in, ns_t_srv, NULL, 0, NULL, packet, 512) != -1; // for some reason always returns 1
#pragma GCC diagnostic pop
if (size == -1) {
L(d->log, "res_nmkquery(SRV) == -1");
@@ -1604,7 +1603,7 @@ void periodic (struct dht * d) {
#pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
for (int i = 0; i < state.nscount; i++)
if (state.nsaddr_list[i].sin_family == AF_INET) { // leider
- if (sendto(d->socket, packet, size, MSG_DONTWAIT | MSG_NOSIGNAL, &state.nsaddr_list[i], sizeof state.nsaddr_list[i]) == -1)
+ if (sendto(d->socket, packet, 512, MSG_DONTWAIT | MSG_NOSIGNAL, &state.nsaddr_list[i], sizeof state.nsaddr_list[i]) == -1)
L(d->log, "sendto: %s", strerror(errno));
d->txp++;
d->txb += size;
@@ -1669,6 +1668,7 @@ void periodic (struct dht * d) {
*/
void work (struct dht * d) {
+ L(d->log, "work()");
char packet[65536];
struct sockaddr_in6 addr;
socklen_t addrlen = sizeof addr;
@@ -1681,8 +1681,8 @@ void work (struct dht * d) {
else if (ret > 65536)
L(d->log, "recvfrom()d larger packet than 65536, not parsing packet");
else if (ret < 0) {
- if (ret != EAGAIN)
- L(d->log, "recvfrom(): %s", strerror(errno));
+ if (errno != EAGAIN)
+ L(d->log, "recvfrom(): %s (%d)", strerror(errno), errno);
else
periodic(d);
} else {
diff --git a/src/main.c b/src/main.c
index c054e31..c14af38 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,51 +6,117 @@
#include <error.h>
#include <fcntl.h>
#include <signal.h>
+#include <poll.h>
+#include <sys/time.h>
#define S0(x) (x ? x : "")
#include <dht.c>
+int samomor = 0;
+int periodično = 0;
+void handler (int s) {
+ switch (s) {
+ case SIGINT:
+ case SIGTERM:
+ samomor++;
+ break;
+ case SIGALRM:
+ periodično++;
+ break;
+ }
+}
int main (int argc, char ** argv) {
int r = 0;
+ struct dht * dht = NULL;
+ struct sigaction sigact = {
+ .sa_handler = handler,
+ .sa_flags = SA_RESTART
+ };
+ if (sigaction(SIGALRM, &sigact, NULL) == -1)
+ error_at_line(1, errno, __FILE__, __LINE__, "sigaction(SIGALRM)");
+ if (sigaction(SIGINT, &sigact, NULL) == -1)
+ error_at_line(2, errno, __FILE__, __LINE__, "sigaction(SIGINT)");
+ if (sigaction(SIGTERM, &sigact, NULL) == -1)
+ error_at_line(3, errno, __FILE__, __LINE__, "sigaction(SIGTERM)");
if (argc != 1+1)
- error_at_line(1, 0, __FILE__, __LINE__, "%s configfile.ben", S0(argv[0]));
+ error_at_line(4, 0, __FILE__, __LINE__, "%s configfile.ben", S0(argv[0]));
int cf = open(argv[1], O_RDWR | O_CLOEXEC | O_CREAT, 00664);
if (cf == -1)
- error_at_line(2, errno, __FILE__, __LINE__, "open(%s)", argv[1]);
+ error_at_line(5, errno, __FILE__, __LINE__, "open(%s)", argv[1]);
struct stat statbuf;
if (fstat(cf, &statbuf) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "fstat(cf, &statbuf)");
- r = 3;
+ r = 6;
goto r;
}
char * cfr = NULL;
if (statbuf.st_size && !(cfr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, cf, 0))) {
error_at_line(0, errno, __FILE__, __LINE__, "mmap(NULL, %ld, PROT_READ, MAP_SHARED, cf, 0)", statbuf.st_size);
- r = 4;
+ r = 7;
goto r;
}
struct bencoding * config = bdecode(cfr, statbuf.st_size, replace);
- struct dht * dht = dht_init(config);
+ dht = dht_init(config);
free_bencoding(config);
+ struct torrent * torrent = calloc(1, sizeof *torrent);
+ memcpy(torrent->hash, "\xdd\x82\x55\xec\xdc\x7c\xa5\x5f\xb0\xbb\xf8\x13\x23\xd8\x70\x62\xdb\x1f\x6d\x1c", 20);
+ torrent->type = announce | peers;
+ add_torrent(dht, torrent);
+ work(dht);
+ struct pollfd pollfd = {
+ .fd = dht->socket,
+ .events = POLLIN
+ };
+ struct itimerval itimerval = {
+ .it_interval = {
+ .tv_sec = 13*60
+ }
+ };
+ setitimer(ITIMER_REAL, &itimerval, NULL);
+w:
+ while (poll(&pollfd, 1, -1) == 1) {
+ work(dht);
+ }
+ if (errno == EINTR) {
+ if (periodično) {
+ periodično = 0;
+ work(dht);
+ goto w;
+ }
+ if (!samomor) {
+ error_at_line(0, errno, __FILE__, __LINE__, "poll");
+ r = 108;
+ }
+ } else {
+ error_at_line(0, errno, __FILE__, __LINE__, "poll");
+ r = 109;
+ goto r;
+ }
config = persistent(dht);
dht_free(dht);
+ dht = NULL;
if (cfr && munmap(cfr, statbuf.st_size) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "munmap(cf, %ld)", statbuf.st_size);
- r = 105;
+ r = 110;
goto r;
}
cfr = NULL;
if (ftruncate(cf, (statbuf.st_size = bencode_length(config))) == -1) {
error_at_line(0, errno, __FILE__, __LINE__, "ftruncate(cf, %ld)", statbuf.st_size);
- r = 106;
+ r = 111;
goto r;
}
if (!(cfr = mmap(NULL, statbuf.st_size, PROT_WRITE, MAP_SHARED, cf, 0))) {
error_at_line(0, errno, __FILE__, __LINE__, "mmap(NULL, %ld, PROT_READ, MAP_SHARED, cf, 0)", statbuf.st_size);
- r = 107;
+ r = 112;
goto r;
}
bencode(cfr, config);
free_bencoding(config);
+ config = NULL;
r:
+ if (dht) {
+ dht_free(dht);
+ dht = NULL;
+ }
if (cfr && munmap(cfr, statbuf.st_size) == -1)
error_at_line(0, errno, __FILE__, __LINE__, "munmap(cf, %ld)", statbuf.st_size);
if (close(cf) == -1)