diff options
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | makefile | 2 | ||||
-rw-r--r-- | src/bencoding.c | 7 | ||||
-rw-r--r-- | src/dht.c | 18 | ||||
-rw-r--r-- | src/main.c | 26 |
5 files changed, 37 insertions, 19 deletions
@@ -1,2 +1,5 @@ # external libraries * https://github.com/kokke/tiny-AES-c + +# todo +* implement BEP-0042 DHT security extension @@ -1,7 +1,7 @@ DESTDIR=/ CC=cc MYCFLAGS=-Wall -Wextra -Wformat -pedantic -g -Isrc -Itmp -Itiny-AES-c -MYLDFLAGS=-lresolv +MYLDFLAGS=-lresolv -lmd default: mkdir -p tmp diff --git a/src/bencoding.c b/src/bencoding.c index b32e2ea..e456486 100644 --- a/src/bencoding.c +++ b/src/bencoding.c @@ -197,12 +197,16 @@ int b2json_charsize (unsigned char a) { return 2; if (a < ' ') return 6; + if (a > 127) + return 1; return 1; } /** * write a string representation of a character in a JSON string * + * non-ASCII characters are replaced with a '.' + * * @param dest [out] destination * @param a [in] the character in question * @return the destination pointer, incremented for the number of bytes written @@ -239,6 +243,9 @@ char * b2json_charrepr (char * dest, unsigned char a) { sprintf(buf, "\\u00%02x", a); strncpy(dest, buf, 6); return dest+6; + } else if (a > 127) { + *dest++ = '.'; + return dest; } else { *dest++ = a; return dest; @@ -12,6 +12,7 @@ #include <resolv.h> #include <limits.h> #include <assert.h> +#include <sha1.h> // http://github.com/clibs/sha1 and in major distributions #define ECB 1 #define AES128 1 #include <aes.c> @@ -166,6 +167,7 @@ void bucket_free (struct bucket * b) { */ struct peer { + int socket; /**< tcp socket for bep-0009 */ struct sockaddr_in6 addr; /**< peer ip address and port */ struct peer * next; }; @@ -209,8 +211,7 @@ void peer_print (FILE * s, const struct peer * p) { enum interested { announce = 1 << 0, /**< will announce myself on every work() call with no packet */ peers = 1 << 1, /**< will get peers on every work() call with no packet */ - info = 1 << 2, /**< download metadata into `dht->dl`/$hash.info */ - dl = 1 << 3 /**< download torrent content into `dht->dl`/$hash.blob TODO */ + info = 1 << 2 /**< download metadata into `dht->dl`/$hash.info */ }; /** @@ -221,7 +222,7 @@ struct torrent { enum interested type; /**< is truthy only for manually added torrents */ unsigned char hash[20]; /**< infohash */ struct peer * peers; - struct node * nodes; /**< closest K DHT nodes to this hash, used only for announce, peers, info and dl torrents */ + struct node * nodes; /**< closest K DHT nodes to this hash, used only for announce, peers and info 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 */ }; @@ -295,7 +296,7 @@ struct dht { struct bucket * buckets; struct bucket * buckets6; /**< IPv6 routing table */ struct torrent * torrents; /**< linked list of torrents for which we want to know peers */ - int dl; /**< dirfd storage directory for download and info torrents */ + int dl; /**< dirfd storage directory for info torrents */ void (* possible_torrent)(struct dht *, const unsigned char *); /**< a user callback function that is called whenever we come across a torrent hash from a network */ void * userdata; /**< unused, but left for the library user to set so he can refer back to his structures from callback code, such as dht->possible_torrent(d, h) */ unsigned torrents_num; /**< number of torrents. this number can rise indefinitely, so it can, and should be capped by the caller, depending on available memory */ @@ -395,6 +396,12 @@ void sendb (struct dht * d, struct bencoding * b, const struct sockaddr_in6 * a) struct bencoding * v = bstr(strdup("TK00")); v->key = bstr(strdup("v")); binsert(b, v); + struct bencoding * ip = calloc(1, sizeof *ip); + ip->type = string; + ip->key = bstr(strdup("key")); + memcpy((b->value = malloc(18)), a->sin6_addr.s6_addr + (family(a->sin6_addr.s6_addr) == AF_INET ? 12 : 0), (b->valuelen = family(a->sin6_addr.s6_addr) == AF_INET ? 6 : 18)); + memcpy(b->value + (family(a->sin6_addr.s6_addr) == AF_INET ? 4 : 16), &a->sin6_port, 2); + binsert(b, ip); int len = b2json_length(b); char json[len+1]; b2json(json, b); @@ -1495,8 +1502,9 @@ void handle (struct dht * d, char * pkt, int len, struct sockaddr_in6 addr) { char * qtype = ""; if (q && q->type & string) qtype = q->value; + struct bencoding * ro = bpath(b, "ro"); struct bencoding * rid = bpath(b, "a/id"); - if (rid && rid->type & string && rid->valuelen == 20) { + if (rid && rid->type & string && rid->valuelen == 20 && (!ro || !(ro->type & num) || ro->intvalue != 1 /* BEP-0043 */)) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpointer-sign" potential_node(d, &addr, rid->value); @@ -48,24 +48,24 @@ int main (int argc, char ** argv) { error_at_line(3, errno, __FILE__, __LINE__, "sigaction(SIGTERM)"); if (sigaction(SIGUSR1, &sigact, NULL) == -1) error_at_line(4, errno, __FILE__, __LINE__, "sigaction(SIGUSR1)"); - struct itimerval itimerval = { - .it_interval = { - .tv_sec = 13*60 - } - }; - if (setitimer(ITIMER_REAL, &itimerval, NULL)) - error_at_line(5, errno, __FILE__, __LINE__, "setitimer"); sigset_t sigset; if (sigemptyset(&sigset) == -1) - error_at_line(6, errno, __FILE__, __LINE__, "sigemptyset"); + error_at_line(5, errno, __FILE__, __LINE__, "sigemptyset"); if (sigaddset(&sigset, SIGUSR1) == -1) - error_at_line(7, errno, __FILE__, __LINE__, "sigaddset(SIGUSR1)"); + error_at_line(6, errno, __FILE__, __LINE__, "sigaddset(SIGUSR1)"); if (sigaddset(&sigset, SIGALRM) == -1) - error_at_line(8, errno, __FILE__, __LINE__, "sigaddset(SIGALRM)"); + error_at_line(7, errno, __FILE__, __LINE__, "sigaddset(SIGALRM)"); if (sigprocmask(SIG_UNBLOCK, &sigset, NULL) == -1) - error_at_line(9, errno, __FILE__, __LINE__, "sigprocmask"); + error_at_line(8, errno, __FILE__, __LINE__, "sigprocmask"); + /* struct itimerval itimerval = { + .it_interval = { + .tv_sec = 60 + } + }; + if (setitimer(ITIMER_REAL, &itimerval, NULL) == -1) + error_at_line(9, errno, __FILE__, __LINE__, "setitimer"); */ if (argc != 1+1) - error_at_line(10, 0, __FILE__, __LINE__, "%s configfile.ben > possible_torrents.L", S0(argv[0])); + error_at_line(10, 0, __FILE__, __LINE__, "%s configfile.ben >> possible_torrents.L", S0(argv[0])); int cf = open(argv[1], O_RDWR | O_CLOEXEC | O_CREAT, 00664); if (cf == -1) error_at_line(11, errno, __FILE__, __LINE__, "open(%s)", argv[1]); @@ -89,12 +89,12 @@ int main (int argc, char ** argv) { 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 }; w: + alarm(13*60); while (poll(&pollfd, 1, -1) == 1) work(dht); if (errno == EINTR) { |