summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c261
1 files changed, 165 insertions, 96 deletions
diff --git a/opentracker.c b/opentracker.c
index f63db72..f218589 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -5,7 +5,6 @@
5 $Id$ */ 5 $Id$ */
6 6
7/* System */ 7/* System */
8#include <arpa/inet.h>
9#include <ctype.h> 8#include <ctype.h>
10#include <errno.h> 9#include <errno.h>
11#include <pthread.h> 10#include <pthread.h>
@@ -21,7 +20,6 @@
21#endif 20#endif
22 21
23/* Libowfat */ 22/* Libowfat */
24#include "byte.h"
25#include "io.h" 23#include "io.h"
26#include "iob.h" 24#include "iob.h"
27#include "ip6.h" 25#include "ip6.h"
@@ -30,9 +28,11 @@
30 28
31/* Opentracker */ 29/* Opentracker */
32#include "ot_accesslist.h" 30#include "ot_accesslist.h"
31#include "ot_hex.h"
33#include "ot_http.h" 32#include "ot_http.h"
34#include "ot_livesync.h" 33#include "ot_livesync.h"
35#include "ot_mutex.h" 34#include "ot_mutex.h"
35#include "ot_random.h"
36#include "ot_stats.h" 36#include "ot_stats.h"
37#include "ot_udp.h" 37#include "ot_udp.h"
38#include "trackerlogic.h" 38#include "trackerlogic.h"
@@ -296,13 +296,7 @@ static void *server_mainloop(void *args) {
296 if (!ws.inbuf || !ws.outbuf) 296 if (!ws.inbuf || !ws.outbuf)
297 panic("Initializing worker failed"); 297 panic("Initializing worker failed");
298 298
299#ifdef WANT_ARC4RANDOM 299 random_bytes(ws.rand48_state, sizeof(ws.rand48_state));
300 arc4random_buf(&ws.rand48_state[0], 3 * sizeof(uint16_t));
301#else
302 ws.rand48_state[0] = (uint16_t)random();
303 ws.rand48_state[1] = (uint16_t)random();
304 ws.rand48_state[2] = (uint16_t)random();
305#endif
306 300
307 for (;;) { 301 for (;;) {
308 int64 sock; 302 int64 sock;
@@ -438,8 +432,82 @@ static int scan_ip6_net(const char *src, ot_net *net) {
438 return off + s - src; 432 return off + s - src;
439} 433}
440 434
435typedef enum {
436 CONFIG_UNKNOWN,
437 CONFIG_TRACKER_ROOTDIR,
438 CONFIG_TRACKER_USER,
439 CONFIG_LISTEN_TCP_UDP,
440 CONFIG_LISTEN_TCP,
441 CONFIG_LISTEN_UDP,
442 CONFIG_LISTEN_UDP_WORKERS,
443 CONFIG_ACCESS_WHITELIST,
444 CONFIG_ACCESS_BLACKLIST,
445 CONFIG_ACCESS_FIFO_ADD,
446 CONFIG_ACCESS_FIFO_DELETE,
447 CONFIG_ACCESS_STATS,
448 CONFIG_ACCESS_STATS_PATH,
449 CONFIG_ACCESS_PROXY,
450 CONFIG_TRACKER_REDIRECT_URL,
451 CONFIG_LIVESYNC_CLUSTER_NODE_IP,
452 CONFIG_LIVESYNC_CLUSTER_LISTEN,
453} config_kind;
454
455typedef struct {
456 const char *name;
457 size_t len;
458 config_kind kind;
459} config_key;
460
461#define CONFIG_KEY(s, k) { s, sizeof(s) - 1, k }
462
463static const config_key config_keys[] = {
464 CONFIG_KEY("tracker.rootdir", CONFIG_TRACKER_ROOTDIR),
465 CONFIG_KEY("tracker.user", CONFIG_TRACKER_USER),
466 CONFIG_KEY("listen.tcp_udp", CONFIG_LISTEN_TCP_UDP),
467 CONFIG_KEY("listen.tcp", CONFIG_LISTEN_TCP),
468 CONFIG_KEY("listen.udp", CONFIG_LISTEN_UDP),
469 CONFIG_KEY("listen.udp.workers", CONFIG_LISTEN_UDP_WORKERS),
470#ifdef WANT_ACCESSLIST_WHITE
471 CONFIG_KEY("access.whitelist", CONFIG_ACCESS_WHITELIST),
472#elif defined(WANT_ACCESSLIST_BLACK)
473 CONFIG_KEY("access.blacklist", CONFIG_ACCESS_BLACKLIST),
474#endif
475#ifdef WANT_DYNAMIC_ACCESSLIST
476 CONFIG_KEY("access.fifo_add", CONFIG_ACCESS_FIFO_ADD),
477 CONFIG_KEY("access.fifo_delete", CONFIG_ACCESS_FIFO_DELETE),
478#endif
479#ifdef WANT_RESTRICT_STATS
480 CONFIG_KEY("access.stats", CONFIG_ACCESS_STATS),
481#endif
482 CONFIG_KEY("access.stats_path", CONFIG_ACCESS_STATS_PATH),
483#ifdef WANT_IP_FROM_PROXY
484 CONFIG_KEY("access.proxy", CONFIG_ACCESS_PROXY),
485#endif
486 CONFIG_KEY("tracker.redirect_url", CONFIG_TRACKER_REDIRECT_URL),
487#ifdef WANT_SYNC_LIVE
488 CONFIG_KEY("livesync.cluster.node_ip", CONFIG_LIVESYNC_CLUSTER_NODE_IP),
489 CONFIG_KEY("livesync.cluster.listen", CONFIG_LIVESYNC_CLUSTER_LISTEN),
490#endif
491};
492static const size_t config_entry_count = sizeof(config_keys) / sizeof(config_keys[0]);
493
494static config_kind parse_config_key(char **p) {
495 size_t i;
496 for (i = 0; i < config_entry_count; ++i) {
497 const config_key *key = &config_keys[i];
498 if (strncmp(*p, key->name, key->len) == 0 && isspace((unsigned char)(*p)[key->len])) {
499 *p += key->len + 1;
500 /* Skip white spaces */
501 while (isspace((unsigned char)**p))
502 ++(*p);
503 return key->kind;
504 }
505 }
506 return CONFIG_UNKNOWN;
507}
508
441int parse_configfile(char *config_filename) { 509int parse_configfile(char *config_filename) {
442 FILE *accesslist_filehandle; 510 FILE *config_file_handle;
443 char inbuf[512]; 511 char inbuf[512];
444 ot_ip6 tmpip; 512 ot_ip6 tmpip;
445#if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE) 513#if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE)
@@ -447,19 +515,19 @@ int parse_configfile(char *config_filename) {
447#endif 515#endif
448 int bound = 0; 516 int bound = 0;
449 517
450 accesslist_filehandle = fopen(config_filename, "r"); 518 config_file_handle = fopen(config_filename, "r");
451 519
452 if (accesslist_filehandle == NULL) { 520 if (config_file_handle == NULL) {
453 fprintf(stderr, "Warning: Can't open config file: %s.", config_filename); 521 fprintf(stderr, "Warning: Can't open config file: %s.", config_filename);
454 return 0; 522 return 0;
455 } 523 }
456 524
457 while (fgets(inbuf, sizeof(inbuf), accesslist_filehandle)) { 525 while (fgets(inbuf, sizeof(inbuf), config_file_handle)) {
458 char *p = inbuf; 526 char *p = inbuf, *end;
459 size_t strl; 527 uint16_t tmpport = 6969;
460 528
461 /* Skip white spaces */ 529 /* Skip white spaces */
462 while (isspace(*p)) 530 while (isspace((unsigned char)*p))
463 ++p; 531 ++p;
464 532
465 /* Ignore comments and empty lines */ 533 /* Ignore comments and empty lines */
@@ -467,87 +535,98 @@ int parse_configfile(char *config_filename) {
467 continue; 535 continue;
468 536
469 /* consume trailing new lines and spaces */ 537 /* consume trailing new lines and spaces */
470 strl = strlen(p); 538 end = p + strlen(p);
471 while (strl && isspace(p[strl - 1])) 539 while (end > p && isspace((unsigned char)end[-1]))
472 p[--strl] = 0; 540 *--end = 0;
473 541
474 /* Scan for commands */ 542 /* Scan for commands */
475 if (!byte_diff(p, 15, "tracker.rootdir") && isspace(p[15])) { 543 switch (parse_config_key(&p)) {
476 set_config_option(&g_serverdir, p + 16); 544 case CONFIG_TRACKER_ROOTDIR:
477 } else if (!byte_diff(p, 12, "tracker.user") && isspace(p[12])) { 545 set_config_option(&g_serverdir, p);
478 set_config_option(&g_serveruser, p + 13); 546 break;
479 } else if (!byte_diff(p, 14, "listen.tcp_udp") && isspace(p[14])) { 547 case CONFIG_TRACKER_USER:
480 uint16_t tmpport = 6969; 548 set_config_option(&g_serveruser, p);
481 if (!scan_ip6_port(p + 15, tmpip, &tmpport)) 549 break;
482 goto parse_error; 550 case CONFIG_LISTEN_TCP_UDP:
483 ot_try_bind(tmpip, tmpport, FLAG_TCP); 551 if (!scan_ip6_port(p, tmpip, &tmpport))
484 ++bound; 552 goto parse_error;
485 ot_try_bind(tmpip, tmpport, FLAG_UDP); 553 ot_try_bind(tmpip, tmpport, FLAG_TCP);
486 ++bound; 554 ++bound;
487 } else if (!byte_diff(p, 10, "listen.tcp") && isspace(p[10])) { 555 ot_try_bind(tmpip, tmpport, FLAG_UDP);
488 uint16_t tmpport = 6969; 556 ++bound;
489 if (!scan_ip6_port(p + 11, tmpip, &tmpport)) 557 break;
490 goto parse_error; 558 case CONFIG_LISTEN_TCP:
491 ot_try_bind(tmpip, tmpport, FLAG_TCP); 559 if (!scan_ip6_port(p, tmpip, &tmpport))
492 ++bound; 560 goto parse_error;
493 } else if (!byte_diff(p, 10, "listen.udp") && isspace(p[10])) { 561 ot_try_bind(tmpip, tmpport, FLAG_TCP);
494 uint16_t tmpport = 6969; 562 ++bound;
495 if (!scan_ip6_port(p + 11, tmpip, &tmpport)) 563 break;
496 goto parse_error; 564 case CONFIG_LISTEN_UDP:
497 ot_try_bind(tmpip, tmpport, FLAG_UDP); 565 if (!scan_ip6_port(p, tmpip, &tmpport))
498 ++bound; 566 goto parse_error;
499 } else if (!byte_diff(p, 18, "listen.udp.workers") && isspace(p[18])) { 567 ot_try_bind(tmpip, tmpport, FLAG_UDP);
500 char *value = p + 18; 568 ++bound;
501 while (isspace(*value)) 569 case CONFIG_LISTEN_UDP_WORKERS:
502 ++value; 570 scan_uint(p, &g_udp_workers);
503 scan_uint(value, &g_udp_workers); 571 break;
504#ifdef WANT_ACCESSLIST_WHITE 572#ifdef WANT_ACCESSLIST_WHITE
505 } else if (!byte_diff(p, 16, "access.whitelist") && isspace(p[16])) { 573 case CONFIG_ACCESS_WHITELIST:
506 set_config_option(&g_accesslist_filename, p + 17); 574 set_config_option(&g_accesslist_filename, p);
575 break;
507#elif defined(WANT_ACCESSLIST_BLACK) 576#elif defined(WANT_ACCESSLIST_BLACK)
508 } else if (!byte_diff(p, 16, "access.blacklist") && isspace(p[16])) { 577 case CONFIG_ACCESS_BLACKLIST:
509 set_config_option(&g_accesslist_filename, p + 17); 578 set_config_option(&g_accesslist_filename, p);
579 break;
510#endif 580#endif
511#ifdef WANT_DYNAMIC_ACCESSLIST 581#ifdef WANT_DYNAMIC_ACCESSLIST
512 } else if (!byte_diff(p, 15, "access.fifo_add") && isspace(p[15])) { 582 case CONFIG_ACCESS_FIFO_ADD:
513 set_config_option(&g_accesslist_pipe_add, p + 16); 583 set_config_option(&g_accesslist_pipe_add, p);
514 } else if (!byte_diff(p, 18, "access.fifo_delete") && isspace(p[18])) { 584 break;
515 set_config_option(&g_accesslist_pipe_delete, p + 19); 585 case CONFIG_ACCESS_FIFO_DELETE:
586 set_config_option(&g_accesslist_pipe_delete, p);
587 break;
516#endif 588#endif
517#ifdef WANT_RESTRICT_STATS 589#ifdef WANT_RESTRICT_STATS
518 } else if (!byte_diff(p, 12, "access.stats") && isspace(p[12])) { 590 case CONFIG_ACCESS_STATS:
519 if (!scan_ip6_net(p + 13, &tmpnet)) 591 if (!scan_ip6_net(p, &tmpnet))
520 goto parse_error; 592 goto parse_error;
521 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT); 593 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT);
594 break;
522#endif 595#endif
523 } else if (!byte_diff(p, 17, "access.stats_path") && isspace(p[17])) { 596 case CONFIG_ACCESS_STATS_PATH:
524 set_config_option(&g_stats_path, p + 18); 597 set_config_option(&g_stats_path, p);
598 break;
525#ifdef WANT_IP_FROM_PROXY 599#ifdef WANT_IP_FROM_PROXY
526 } else if (!byte_diff(p, 12, "access.proxy") && isspace(p[12])) { 600 case CONFIG_ACCESS_PROXY:
527 if (!scan_ip6_net(p + 13, &tmpnet)) 601 if (!scan_ip6_net(p, &tmpnet))
528 goto parse_error; 602 goto parse_error;
529 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY); 603 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY);
604 break;
530#endif 605#endif
531 } else if (!byte_diff(p, 20, "tracker.redirect_url") && isspace(p[20])) { 606 case CONFIG_TRACKER_REDIRECT_URL:
532 set_config_option(&g_redirecturl, p + 21); 607 set_config_option(&g_redirecturl, p);
608 break;
533#ifdef WANT_SYNC_LIVE 609#ifdef WANT_SYNC_LIVE
534 } else if (!byte_diff(p, 24, "livesync.cluster.node_ip") && isspace(p[24])) { 610 case CONFIG_LIVESYNC_CLUSTER_NODE_IP:
535 if (!scan_ip6_net(p + 25, &tmpnet)) 611 if (!scan_ip6_net(p, &tmpnet))
536 goto parse_error; 612 goto parse_error;
537 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC); 613 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC);
538 } else if (!byte_diff(p, 23, "livesync.cluster.listen") && isspace(p[23])) { 614 break;
539 uint16_t tmpport = LIVESYNC_PORT; 615 case CONFIG_LIVESYNC_CLUSTER_LISTEN:
540 if (!scan_ip6_port(p + 24, tmpip, &tmpport)) 616 tmpport = LIVESYNC_PORT;
541 goto parse_error; 617 if (!scan_ip6_port(p, tmpip, &tmpport))
542 livesync_bind_mcast(tmpip, tmpport); 618 goto parse_error;
619 livesync_bind_mcast(tmpip, tmpport);
620 break;
543#endif 621#endif
544 } else 622 default:
545 fprintf(stderr, "Unhandled line in config file: %s\n", inbuf); 623 fprintf(stderr, "Unhandled line in config file: %s\n", inbuf);
546 continue; 624 break;
547 parse_error: 625 parse_error:
548 fprintf(stderr, "Parse error in config file: %s\n", inbuf); 626 fprintf(stderr, "Parse error in config file: %s\n", inbuf);
627 }
549 } 628 }
550 fclose(accesslist_filehandle); 629 fclose(config_file_handle);
551 return bound; 630 return bound;
552} 631}
553 632
@@ -568,16 +647,10 @@ void load_state(const char *const state_filename) {
568 /* We do ignore anything that is not of the form "^[:xdigit:]:\d+:\d+" */ 647 /* We do ignore anything that is not of the form "^[:xdigit:]:\d+:\d+" */
569 while (fgets(inbuf, sizeof(inbuf), state_filehandle)) { 648 while (fgets(inbuf, sizeof(inbuf), state_filehandle)) {
570 size_t i; 649 size_t i;
571 for (i = 0; i < sizeof(ot_hash); ++i) {
572 int eger = 16 * scan_fromhex(inbuf[2 * i]) + scan_fromhex(inbuf[1 + 2 * i]);
573 if (eger < 0)
574 continue;
575 infohash[i] = eger;
576 }
577 650
578 if (i != sizeof(ot_hash)) 651 if (!hex_tohash(infohash, inbuf))
579 continue; 652 continue;
580 i *= 2; 653 i = 2 * sizeof(ot_hash);
581 654
582 if (inbuf[i++] != ':' || !(consumed = scan_ulonglong(inbuf + i, &base))) 655 if (inbuf[i++] != ':' || !(consumed = scan_ulonglong(inbuf + i, &base)))
583 continue; 656 continue;
@@ -660,11 +733,7 @@ int main(int argc, char **argv) {
660 serverip[10] = serverip[11] = -1; 733 serverip[10] = serverip[11] = -1;
661#endif 734#endif
662 735
663#ifdef WANT_DEV_RANDOM 736 random_init();
664 srandomdev();
665#else
666 srandom(time(NULL));
667#endif
668 737
669 while (scanon) { 738 while (scanon) {
670 switch (getopt(argc, argv, 739 switch (getopt(argc, argv,