diff options
Diffstat (limited to 'opentracker.c')
| -rw-r--r-- | opentracker.c | 543 |
1 files changed, 15 insertions, 528 deletions
diff --git a/opentracker.c b/opentracker.c index 1b0e119..698669c 100644 --- a/opentracker.c +++ b/opentracker.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | /* Opentracker */ | 28 | /* Opentracker */ |
| 29 | #include "ot_accesslist.h" | 29 | #include "ot_accesslist.h" |
| 30 | #include "ot_config.h" | ||
| 30 | #include "ot_hex.h" | 31 | #include "ot_hex.h" |
| 31 | #include "ot_http.h" | 32 | #include "ot_http.h" |
| 32 | #include "ot_ip.h" | 33 | #include "ot_ip.h" |
| @@ -41,29 +42,10 @@ | |||
| 41 | 42 | ||
| 42 | /* Globals */ | 43 | /* Globals */ |
| 43 | time_t g_now_seconds; | 44 | time_t g_now_seconds; |
| 44 | char *g_redirecturl; | ||
| 45 | uint32_t g_tracker_id; | 45 | uint32_t g_tracker_id; |
| 46 | volatile int g_opentracker_running = 1; | 46 | volatile int g_opentracker_running = 1; |
| 47 | int g_self_pipe[2]; | 47 | int g_self_pipe[2]; |
| 48 | 48 | ||
| 49 | static char *g_serverdir; | ||
| 50 | static char *g_serveruser; | ||
| 51 | |||
| 52 | typedef struct { | ||
| 53 | ot_ip6 ip; | ||
| 54 | uint16_t port; | ||
| 55 | PROTO_FLAG proto; | ||
| 56 | int shared; | ||
| 57 | int workers; | ||
| 58 | int64_t sock; | ||
| 59 | } ot_listen; | ||
| 60 | #define OT_LISTEN_INHERIT (-1) | ||
| 61 | |||
| 62 | /* Config entries collected from command line and config files */ | ||
| 63 | static ot_listen *g_listen; | ||
| 64 | static size_t g_listen_count; | ||
| 65 | static int g_listen_shared; | ||
| 66 | static int g_listen_workers; | ||
| 67 | 49 | ||
| 68 | static void panic(const char *routine) __attribute__((noreturn)); | 50 | static void panic(const char *routine) __attribute__((noreturn)); |
| 69 | static void panic(const char *routine) { | 51 | static void panic(const char *routine) { |
| @@ -115,42 +97,6 @@ static void install_signal_handlers(void) { | |||
| 115 | pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL); | 97 | pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL); |
| 116 | } | 98 | } |
| 117 | 99 | ||
| 118 | static void usage(char *name) { | ||
| 119 | fprintf(stderr, | ||
| 120 | "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-u user] [-A ip[/bits]] [-f config] [-s livesyncport]" | ||
| 121 | #ifdef WANT_ACCESSLIST_BLACK | ||
| 122 | " [-b blacklistfile]" | ||
| 123 | #elif defined(WANT_ACCESSLIST_WHITE) | ||
| 124 | " [-w whitelistfile]" | ||
| 125 | #endif | ||
| 126 | "\n", | ||
| 127 | name); | ||
| 128 | } | ||
| 129 | |||
| 130 | #define HELPLINE(opt, desc) fprintf(stderr, "\t%-10s%s\n", opt, desc) | ||
| 131 | static void help(char *name) { | ||
| 132 | usage(name); | ||
| 133 | |||
| 134 | HELPLINE("-f config", "include and execute the config file"); | ||
| 135 | HELPLINE("-i ip", "specify ip to bind to with next -[pP] (default: any, overrides preceeding ones)"); | ||
| 136 | HELPLINE("-p port", "do bind to tcp port (default: 6969, you may specify more than one)"); | ||
| 137 | HELPLINE("-P port", "do bind to udp port (default: 6969, you may specify more than one)"); | ||
| 138 | HELPLINE("-r redirecturl", "specify url where / should be redirected to (default none)"); | ||
| 139 | HELPLINE("-d dir", "specify directory to try to chroot to (default: \".\")"); | ||
| 140 | HELPLINE("-u user", "specify user under whose privileges opentracker should run (default: \"nobody\")"); | ||
| 141 | HELPLINE("-A ip[/bits]", "bless an ip address or net as admin address (e.g. to allow syncs from this address)"); | ||
| 142 | #ifdef WANT_ACCESSLIST_BLACK | ||
| 143 | HELPLINE("-b file", "specify blacklist file."); | ||
| 144 | #elif defined(WANT_ACCESSLIST_WHITE) | ||
| 145 | HELPLINE("-w file", "specify whitelist file."); | ||
| 146 | #endif | ||
| 147 | |||
| 148 | fprintf(stderr, "\nExample: ./opentracker -i 127.0.0.1 -p 6969 -P 6969 -f ./opentracker.conf -i 10.1.1.23 -p 2710 -p 80\n"); | ||
| 149 | fprintf(stderr, " Here -i 127.0.0.1 selects the ip address for the next -p 6969 and -P 6969.\n"); | ||
| 150 | fprintf(stderr, " If no port is bound from config file or command line, the last address given\n"); | ||
| 151 | fprintf(stderr, " (or ::1 if none is set) will be used on port 6969.\n"); | ||
| 152 | } | ||
| 153 | #undef HELPLINE | ||
| 154 | 100 | ||
| 155 | static ssize_t header_complete(char *request, ssize_t byte_count) { | 101 | static ssize_t header_complete(char *request, ssize_t byte_count) { |
| 156 | ssize_t i = 0, state = 0; | 102 | ssize_t i = 0, state = 0; |
| @@ -353,91 +299,9 @@ static void *server_mainloop(void *args) { | |||
| 353 | return 0; | 299 | return 0; |
| 354 | } | 300 | } |
| 355 | 301 | ||
| 356 | static void listen_append(const ot_ip6 ip, uint16_t port, PROTO_FLAG proto, int shared, int workers) { | ||
| 357 | ot_listen *grown = realloc(g_listen, (g_listen_count + 1) * sizeof(ot_listen)); | ||
| 358 | ot_listen *entry; | ||
| 359 | |||
| 360 | if (!grown) | ||
| 361 | panic("listen_append"); | ||
| 362 | g_listen = grown; | ||
| 363 | |||
| 364 | entry = g_listen + g_listen_count++; | ||
| 365 | memcpy(entry->ip, ip, sizeof(ot_ip6)); | ||
| 366 | entry->port = port; | ||
| 367 | entry->proto = proto; | ||
| 368 | entry->shared = shared; | ||
| 369 | entry->workers = workers; | ||
| 370 | entry->sock = -1; | ||
| 371 | } | ||
| 372 | |||
| 373 | typedef enum { LISTEN_OPTION_UNKNOWN, LISTEN_OPTION_SHARED, LISTEN_OPTION_WORKERS } listen_option_kind; | ||
| 374 | |||
| 375 | typedef struct { | ||
| 376 | const char *name; | ||
| 377 | size_t len; | ||
| 378 | listen_option_kind kind; | ||
| 379 | int takes_value; | ||
| 380 | } listen_option_key; | ||
| 381 | |||
| 382 | #define LISTEN_OPTION_KEY(s, k, v) {s, sizeof(s) - 1, k, v} | ||
| 383 | |||
| 384 | static const listen_option_key listen_option_keys[] = { | ||
| 385 | LISTEN_OPTION_KEY("shared", LISTEN_OPTION_SHARED, 0), | ||
| 386 | LISTEN_OPTION_KEY("workers", LISTEN_OPTION_WORKERS, 1), | ||
| 387 | }; | ||
| 388 | static const size_t listen_option_count = sizeof(listen_option_keys) / sizeof(listen_option_keys[0]); | ||
| 389 | |||
| 390 | static listen_option_kind parse_listen_option(char **p) { | ||
| 391 | size_t i; | ||
| 392 | |||
| 393 | for (i = 0; i < listen_option_count; ++i) { | ||
| 394 | const listen_option_key *key = &listen_option_keys[i]; | ||
| 395 | char delimiter = (*p)[key->len]; | ||
| 396 | |||
| 397 | if (strncmp(*p, key->name, key->len)) | ||
| 398 | continue; | ||
| 399 | if (key->takes_value ? delimiter != '=' : (delimiter && !isspace((unsigned char)delimiter))) | ||
| 400 | continue; | ||
| 401 | |||
| 402 | *p += key->len + (key->takes_value ? 1 : 0); | ||
| 403 | return key->kind; | ||
| 404 | } | ||
| 405 | return LISTEN_OPTION_UNKNOWN; | ||
| 406 | } | ||
| 407 | |||
| 408 | /* Options trailing an address in a listen statement, in any order */ | ||
| 409 | static int listen_scan_options(char *p, int *shared, int *workers) { | ||
| 410 | uint64_t value; | ||
| 411 | |||
| 412 | for (;;) { | ||
| 413 | while (isspace((unsigned char)*p)) | ||
| 414 | ++p; | ||
| 415 | if (!*p) | ||
| 416 | return 1; | ||
| 417 | |||
| 418 | switch (parse_listen_option(&p)) { | ||
| 419 | case LISTEN_OPTION_SHARED: | ||
| 420 | *shared = 1; | ||
| 421 | break; | ||
| 422 | case LISTEN_OPTION_WORKERS: { | ||
| 423 | size_t off = scan_udec(p, &value, UINT_MAX); | ||
| 424 | |||
| 425 | if (!off) | ||
| 426 | return 0; | ||
| 427 | *workers = (int)value; | ||
| 428 | p += off; | ||
| 429 | break; | ||
| 430 | } | ||
| 431 | default: | ||
| 432 | return 0; | ||
| 433 | } | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | static int listen_option(int value, int fallback) { return value == OT_LISTEN_INHERIT ? fallback : value; } | ||
| 438 | 302 | ||
| 439 | static void listen_bind_one(ot_listen *entry) { | 303 | static void listen_bind_one(ot_listen *entry) { |
| 440 | socket_sharing sharing = listen_option(entry->shared, g_listen_shared) ? SOCKET_SHARED : SOCKET_EXCLUSIVE; | 304 | socket_sharing sharing = entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE; |
| 441 | 305 | ||
| 442 | #ifdef _DEBUG | 306 | #ifdef _DEBUG |
| 443 | { | 307 | { |
| @@ -482,305 +346,31 @@ static void listen_bind_one(ot_listen *entry) { | |||
| 482 | /* Bound in the order the entries were given. | 346 | /* Bound in the order the entries were given. |
| 483 | Note: On macOS SO_REUSEPORT delivers everything to the socket that bound last. */ | 347 | Note: On macOS SO_REUSEPORT delivers everything to the socket that bound last. */ |
| 484 | static void listen_bind_all(void) { | 348 | static void listen_bind_all(void) { |
| 485 | size_t i; | 349 | size_t count, i; |
| 350 | ot_listen *entries = config_listen_entries(&count); | ||
| 486 | 351 | ||
| 487 | for (i = 0; i < g_listen_count; ++i) | 352 | for (i = 0; i < count; ++i) |
| 488 | listen_bind_one(g_listen + i); | 353 | listen_bind_one(entries + i); |
| 489 | } | 354 | } |
| 490 | 355 | ||
| 491 | static void listen_start_udp_workers(void) { | 356 | static void listen_start_udp_workers(void) { |
| 492 | size_t i; | 357 | size_t count, i; |
| 358 | ot_listen *entries = config_listen_entries(&count); | ||
| 493 | 359 | ||
| 494 | udp_init(); | 360 | udp_init(); |
| 495 | 361 | ||
| 496 | for (i = 0; i < g_listen_count; ++i) { | 362 | for (i = 0; i < count; ++i) { |
| 497 | ot_listen *entry = g_listen + i; | 363 | ot_listen *entry = entries + i; |
| 498 | int workers = listen_option(entry->workers, g_listen_workers); | ||
| 499 | 364 | ||
| 500 | if (entry->proto != FLAG_UDP || workers <= 0) | 365 | if (entry->proto != FLAG_UDP || entry->workers <= 0) |
| 501 | continue; | 366 | continue; |
| 502 | 367 | ||
| 503 | io_block(entry->sock); | 368 | io_block(entry->sock); |
| 504 | udp_workers_install(entry->sock, (unsigned int)workers); | 369 | udp_workers_install(entry->sock, (unsigned int)entry->workers); |
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 508 | char *set_config_option(char **option, char *value) { | ||
| 509 | #ifdef _DEBUG | ||
| 510 | fprintf(stderr, "Setting config option: %s\n", value); | ||
| 511 | #endif | ||
| 512 | while (isspace(*value)) | ||
| 513 | ++value; | ||
| 514 | free(*option); | ||
| 515 | return *option = strdup(value); | ||
| 516 | } | ||
| 517 | |||
| 518 | static int scan_ip6_port(const char *src, ot_ip6 ip, uint16_t *port) { | ||
| 519 | const char *s = src; | ||
| 520 | uint64_t value; | ||
| 521 | int off, bracket = 0; | ||
| 522 | while (isspace(*s)) | ||
| 523 | ++s; | ||
| 524 | if (*s == '[') | ||
| 525 | ++s, ++bracket; /* for v6 style notation */ | ||
| 526 | if (!(off = ip_scan(s, ip))) | ||
| 527 | return 0; | ||
| 528 | s += off; | ||
| 529 | if (bracket && *s == ']') | ||
| 530 | ++s; | ||
| 531 | if (*s == 0 || isspace(*s)) | ||
| 532 | return s - src; | ||
| 533 | if (!ip_is_v4mapped(ip)) { | ||
| 534 | if (*s != ':' && *s != '.') | ||
| 535 | return 0; | ||
| 536 | if (!bracket && *(s) == ':') | ||
| 537 | return 0; | ||
| 538 | s++; | ||
| 539 | } else { | ||
| 540 | if (*(s++) != ':') | ||
| 541 | return 0; | ||
| 542 | } | ||
| 543 | if (!(off = scan_udec(s, &value, 65535))) | ||
| 544 | return 0; | ||
| 545 | *port = (uint16_t)value; | ||
| 546 | return off + s - src; | ||
| 547 | } | ||
| 548 | |||
| 549 | static int scan_ip6_net(const char *src, ot_net *net) { | ||
| 550 | const char *s = src; | ||
| 551 | uint64_t value; | ||
| 552 | int off; | ||
| 553 | while (isspace(*s)) | ||
| 554 | ++s; | ||
| 555 | if (!(off = ip_scan(s, net->address))) | ||
| 556 | return 0; | ||
| 557 | s += off; | ||
| 558 | if (*s != '/') | ||
| 559 | net->bits = 128; | ||
| 560 | else { | ||
| 561 | s++; | ||
| 562 | if (!(off = scan_udec(s, &value, 128))) | ||
| 563 | return 0; | ||
| 564 | net->bits = (int)value; | ||
| 565 | if (ip_is_v4mapped(net->address)) | ||
| 566 | net->bits += 96; | ||
| 567 | if (net->bits > 128) | ||
| 568 | return 0; | ||
| 569 | s += off; | ||
| 570 | } | 370 | } |
| 571 | return off + s - src; | ||
| 572 | } | ||
| 573 | |||
| 574 | typedef enum { | ||
| 575 | CONFIG_UNKNOWN, | ||
| 576 | CONFIG_TRACKER_ROOTDIR, | ||
| 577 | CONFIG_TRACKER_USER, | ||
| 578 | CONFIG_LISTEN_TCP_UDP, | ||
| 579 | CONFIG_LISTEN_TCP, | ||
| 580 | CONFIG_LISTEN_UDP, | ||
| 581 | CONFIG_LISTEN_UDP_WORKERS, | ||
| 582 | CONFIG_LISTEN_SHARED, | ||
| 583 | CONFIG_ACCESS_WHITELIST, | ||
| 584 | CONFIG_ACCESS_BLACKLIST, | ||
| 585 | CONFIG_ACCESS_FIFO_ADD, | ||
| 586 | CONFIG_ACCESS_FIFO_DELETE, | ||
| 587 | CONFIG_ACCESS_STATS, | ||
| 588 | CONFIG_ACCESS_STATS_PATH, | ||
| 589 | CONFIG_ACCESS_PROXY, | ||
| 590 | CONFIG_TRACKER_REDIRECT_URL, | ||
| 591 | CONFIG_LIVESYNC_CLUSTER_NODE_IP, | ||
| 592 | CONFIG_LIVESYNC_CLUSTER_LISTEN, | ||
| 593 | } config_kind; | ||
| 594 | |||
| 595 | typedef struct { | ||
| 596 | const char *name; | ||
| 597 | size_t len; | ||
| 598 | config_kind kind; | ||
| 599 | } config_key; | ||
| 600 | |||
| 601 | #define CONFIG_KEY(s, k) { s, sizeof(s) - 1, k } | ||
| 602 | |||
| 603 | static const config_key config_keys[] = { | ||
| 604 | CONFIG_KEY("tracker.rootdir", CONFIG_TRACKER_ROOTDIR), | ||
| 605 | CONFIG_KEY("tracker.user", CONFIG_TRACKER_USER), | ||
| 606 | CONFIG_KEY("listen.tcp_udp", CONFIG_LISTEN_TCP_UDP), | ||
| 607 | CONFIG_KEY("listen.tcp", CONFIG_LISTEN_TCP), | ||
| 608 | CONFIG_KEY("listen.udp", CONFIG_LISTEN_UDP), | ||
| 609 | CONFIG_KEY("listen.udp.workers", CONFIG_LISTEN_UDP_WORKERS), | ||
| 610 | CONFIG_KEY("listen.shared", CONFIG_LISTEN_SHARED), | ||
| 611 | #ifdef WANT_ACCESSLIST_WHITE | ||
| 612 | CONFIG_KEY("access.whitelist", CONFIG_ACCESS_WHITELIST), | ||
| 613 | #elif defined(WANT_ACCESSLIST_BLACK) | ||
| 614 | CONFIG_KEY("access.blacklist", CONFIG_ACCESS_BLACKLIST), | ||
| 615 | #endif | ||
| 616 | #ifdef WANT_DYNAMIC_ACCESSLIST | ||
| 617 | CONFIG_KEY("access.fifo_add", CONFIG_ACCESS_FIFO_ADD), | ||
| 618 | CONFIG_KEY("access.fifo_delete", CONFIG_ACCESS_FIFO_DELETE), | ||
| 619 | #endif | ||
| 620 | #ifdef WANT_RESTRICT_STATS | ||
| 621 | CONFIG_KEY("access.stats", CONFIG_ACCESS_STATS), | ||
| 622 | #endif | ||
| 623 | CONFIG_KEY("access.stats_path", CONFIG_ACCESS_STATS_PATH), | ||
| 624 | #ifdef WANT_IP_FROM_PROXY | ||
| 625 | CONFIG_KEY("access.proxy", CONFIG_ACCESS_PROXY), | ||
| 626 | #endif | ||
| 627 | CONFIG_KEY("tracker.redirect_url", CONFIG_TRACKER_REDIRECT_URL), | ||
| 628 | #ifdef WANT_SYNC_LIVE | ||
| 629 | CONFIG_KEY("livesync.cluster.node_ip", CONFIG_LIVESYNC_CLUSTER_NODE_IP), | ||
| 630 | CONFIG_KEY("livesync.cluster.listen", CONFIG_LIVESYNC_CLUSTER_LISTEN), | ||
| 631 | #endif | ||
| 632 | }; | ||
| 633 | static const size_t config_entry_count = sizeof(config_keys) / sizeof(config_keys[0]); | ||
| 634 | |||
| 635 | static config_kind parse_config_key(char **p) { | ||
| 636 | size_t i; | ||
| 637 | for (i = 0; i < config_entry_count; ++i) { | ||
| 638 | const config_key *key = &config_keys[i]; | ||
| 639 | if (strncmp(*p, key->name, key->len) == 0 && isspace((unsigned char)(*p)[key->len])) { | ||
| 640 | *p += key->len + 1; | ||
| 641 | /* Skip white spaces */ | ||
| 642 | while (isspace((unsigned char)**p)) | ||
| 643 | ++(*p); | ||
| 644 | return key->kind; | ||
| 645 | } | ||
| 646 | } | ||
| 647 | return CONFIG_UNKNOWN; | ||
| 648 | } | 371 | } |
| 649 | 372 | ||
| 650 | int parse_configfile(char *config_filename) { | ||
| 651 | FILE *config_file_handle; | ||
| 652 | char inbuf[512]; | ||
| 653 | ot_ip6 tmpip; | ||
| 654 | #if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE) | ||
| 655 | ot_net tmpnet; | ||
| 656 | #endif | ||
| 657 | int bound = 0; | ||
| 658 | 373 | ||
| 659 | config_file_handle = fopen(config_filename, "r"); | ||
| 660 | |||
| 661 | if (config_file_handle == NULL) { | ||
| 662 | fprintf(stderr, "Warning: Can't open config file: %s.", config_filename); | ||
| 663 | return 0; | ||
| 664 | } | ||
| 665 | |||
| 666 | while (fgets(inbuf, sizeof(inbuf), config_file_handle)) { | ||
| 667 | char *p = inbuf, *end; | ||
| 668 | uint64_t value; | ||
| 669 | uint16_t tmpport = 6969; | ||
| 670 | config_kind kind; | ||
| 671 | |||
| 672 | /* Skip white spaces */ | ||
| 673 | while (isspace((unsigned char)*p)) | ||
| 674 | ++p; | ||
| 675 | |||
| 676 | /* Ignore comments and empty lines */ | ||
| 677 | if ((*p == '#') || (*p == '\n') || (*p == 0)) | ||
| 678 | continue; | ||
| 679 | |||
| 680 | /* consume trailing new lines and spaces */ | ||
| 681 | end = p + strlen(p); | ||
| 682 | while (end > p && isspace((unsigned char)end[-1])) | ||
| 683 | *--end = 0; | ||
| 684 | |||
| 685 | /* Scan for commands */ | ||
| 686 | kind = parse_config_key(&p); | ||
| 687 | switch (kind) { | ||
| 688 | case CONFIG_TRACKER_ROOTDIR: | ||
| 689 | set_config_option(&g_serverdir, p); | ||
| 690 | break; | ||
| 691 | case CONFIG_TRACKER_USER: | ||
| 692 | set_config_option(&g_serveruser, p); | ||
| 693 | break; | ||
| 694 | case CONFIG_LISTEN_TCP_UDP: | ||
| 695 | case CONFIG_LISTEN_TCP: | ||
| 696 | case CONFIG_LISTEN_UDP: { | ||
| 697 | int shared = OT_LISTEN_INHERIT; | ||
| 698 | int workers = OT_LISTEN_INHERIT; | ||
| 699 | int off = scan_ip6_port(p, tmpip, &tmpport); | ||
| 700 | |||
| 701 | if (!off || !listen_scan_options(p + off, &shared, &workers)) | ||
| 702 | goto parse_error; | ||
| 703 | if (kind != CONFIG_LISTEN_UDP) | ||
| 704 | listen_append(tmpip, tmpport, FLAG_TCP, shared, OT_LISTEN_INHERIT), ++bound; | ||
| 705 | if (kind != CONFIG_LISTEN_TCP) | ||
| 706 | listen_append(tmpip, tmpport, FLAG_UDP, shared, workers), ++bound; | ||
| 707 | break; | ||
| 708 | } | ||
| 709 | case CONFIG_LISTEN_UDP_WORKERS: | ||
| 710 | if (!scan_udec(p, &value, UINT_MAX)) | ||
| 711 | goto parse_error; | ||
| 712 | g_listen_workers = (int)value; | ||
| 713 | break; | ||
| 714 | case CONFIG_LISTEN_SHARED: | ||
| 715 | if (!scan_udec(p, &value, 1)) | ||
| 716 | goto parse_error; | ||
| 717 | g_listen_shared = (int)value; | ||
| 718 | break; | ||
| 719 | #ifdef WANT_ACCESSLIST_WHITE | ||
| 720 | case CONFIG_ACCESS_WHITELIST: | ||
| 721 | set_config_option(&g_accesslist_filename, p); | ||
| 722 | break; | ||
| 723 | #elif defined(WANT_ACCESSLIST_BLACK) | ||
| 724 | case CONFIG_ACCESS_BLACKLIST: | ||
| 725 | set_config_option(&g_accesslist_filename, p); | ||
| 726 | break; | ||
| 727 | #endif | ||
| 728 | #ifdef WANT_DYNAMIC_ACCESSLIST | ||
| 729 | case CONFIG_ACCESS_FIFO_ADD: | ||
| 730 | set_config_option(&g_accesslist_pipe_add, p); | ||
| 731 | break; | ||
| 732 | case CONFIG_ACCESS_FIFO_DELETE: | ||
| 733 | set_config_option(&g_accesslist_pipe_delete, p); | ||
| 734 | break; | ||
| 735 | #endif | ||
| 736 | #ifdef WANT_RESTRICT_STATS | ||
| 737 | case CONFIG_ACCESS_STATS: | ||
| 738 | if (!scan_ip6_net(p, &tmpnet)) | ||
| 739 | goto parse_error; | ||
| 740 | accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT); | ||
| 741 | break; | ||
| 742 | #endif | ||
| 743 | case CONFIG_ACCESS_STATS_PATH: | ||
| 744 | set_config_option(&g_stats_path, p); | ||
| 745 | break; | ||
| 746 | #ifdef WANT_IP_FROM_PROXY | ||
| 747 | case CONFIG_ACCESS_PROXY: | ||
| 748 | if (!scan_ip6_net(p, &tmpnet)) | ||
| 749 | goto parse_error; | ||
| 750 | accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY); | ||
| 751 | break; | ||
| 752 | #endif | ||
| 753 | case CONFIG_TRACKER_REDIRECT_URL: | ||
| 754 | set_config_option(&g_redirecturl, p); | ||
| 755 | break; | ||
| 756 | #ifdef WANT_SYNC_LIVE | ||
| 757 | case CONFIG_LIVESYNC_CLUSTER_NODE_IP: | ||
| 758 | if (!scan_ip6_net(p, &tmpnet)) | ||
| 759 | goto parse_error; | ||
| 760 | accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC); | ||
| 761 | break; | ||
| 762 | case CONFIG_LIVESYNC_CLUSTER_LISTEN: | ||
| 763 | tmpport = LIVESYNC_PORT; | ||
| 764 | { | ||
| 765 | int shared = OT_LISTEN_INHERIT, dummy = OT_LISTEN_INHERIT; | ||
| 766 | int off = scan_ip6_port(p, tmpip, &tmpport); | ||
| 767 | |||
| 768 | if (!off || !listen_scan_options(p + off, &shared, &dummy)) | ||
| 769 | goto parse_error; | ||
| 770 | listen_append(tmpip, tmpport, FLAG_MCA, shared, OT_LISTEN_INHERIT); | ||
| 771 | } | ||
| 772 | break; | ||
| 773 | #endif | ||
| 774 | default: | ||
| 775 | fprintf(stderr, "Unhandled line in config file: %s\n", inbuf); | ||
| 776 | break; | ||
| 777 | parse_error: | ||
| 778 | fprintf(stderr, "Parse error in config file: %s\n", inbuf); | ||
| 779 | } | ||
| 780 | } | ||
| 781 | fclose(config_file_handle); | ||
| 782 | return bound; | ||
| 783 | } | ||
| 784 | 374 | ||
| 785 | void load_state(const char *const state_filename) { | 375 | void load_state(const char *const state_filename) { |
| 786 | FILE *state_filehandle; | 376 | FILE *state_filehandle; |
| @@ -873,114 +463,11 @@ static void *time_caching_worker(void *args) { | |||
| 873 | } | 463 | } |
| 874 | 464 | ||
| 875 | int main(int argc, char **argv) { | 465 | int main(int argc, char **argv) { |
| 876 | ot_ip6 serverip; | ||
| 877 | ot_net tmpnet; | ||
| 878 | int bound = 0, scanon = 1; | ||
| 879 | uint64_t value; | ||
| 880 | char *statefile = 0; | ||
| 881 | pthread_t thread_id; /* time cacher */ | 466 | pthread_t thread_id; /* time cacher */ |
| 882 | 467 | ||
| 883 | memset(serverip, 0, sizeof(ot_ip6)); | ||
| 884 | #ifdef WANT_V4_ONLY | ||
| 885 | serverip[10] = serverip[11] = -1; | ||
| 886 | #endif | ||
| 887 | |||
| 888 | random_init(); | 468 | random_init(); |
| 469 | config_parse(argc, argv); | ||
| 889 | 470 | ||
| 890 | while (scanon) { | ||
| 891 | switch (getopt(argc, argv, | ||
| 892 | ":i:p:A:P:d:u:r:s:f:l:v" | ||
| 893 | #ifdef WANT_ACCESSLIST_BLACK | ||
| 894 | "b:" | ||
| 895 | #elif defined(WANT_ACCESSLIST_WHITE) | ||
| 896 | "w:" | ||
| 897 | #endif | ||
| 898 | "h")) { | ||
| 899 | case -1: | ||
| 900 | scanon = 0; | ||
| 901 | break; | ||
| 902 | case 'i': | ||
| 903 | if (!ip_scan(optarg, serverip)) { | ||
| 904 | usage(argv[0]); | ||
| 905 | exit(1); | ||
| 906 | } | ||
| 907 | break; | ||
| 908 | #ifdef WANT_ACCESSLIST_BLACK | ||
| 909 | case 'b': | ||
| 910 | set_config_option(&g_accesslist_filename, optarg); | ||
| 911 | break; | ||
| 912 | #elif defined(WANT_ACCESSLIST_WHITE) | ||
| 913 | case 'w': | ||
| 914 | set_config_option(&g_accesslist_filename, optarg); | ||
| 915 | break; | ||
| 916 | #endif | ||
| 917 | case 'p': | ||
| 918 | if (!scan_udec(optarg, &value, 65535)) { | ||
| 919 | usage(argv[0]); | ||
| 920 | exit(1); | ||
| 921 | } | ||
| 922 | listen_append(serverip, (uint16_t)value, FLAG_TCP, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); | ||
| 923 | bound++; | ||
| 924 | break; | ||
| 925 | case 'P': | ||
| 926 | if (!scan_udec(optarg, &value, 65535)) { | ||
| 927 | usage(argv[0]); | ||
| 928 | exit(1); | ||
| 929 | } | ||
| 930 | listen_append(serverip, (uint16_t)value, FLAG_UDP, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); | ||
| 931 | bound++; | ||
| 932 | break; | ||
| 933 | #ifdef WANT_SYNC_LIVE | ||
| 934 | case 's': | ||
| 935 | if (!scan_udec(optarg, &value, 65535)) { | ||
| 936 | usage(argv[0]); | ||
| 937 | exit(1); | ||
| 938 | } | ||
| 939 | listen_append(serverip, (uint16_t)value, FLAG_MCA, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); | ||
| 940 | break; | ||
| 941 | #endif | ||
| 942 | case 'd': | ||
| 943 | set_config_option(&g_serverdir, optarg); | ||
| 944 | break; | ||
| 945 | case 'u': | ||
| 946 | set_config_option(&g_serveruser, optarg); | ||
| 947 | break; | ||
| 948 | case 'r': | ||
| 949 | set_config_option(&g_redirecturl, optarg); | ||
| 950 | break; | ||
| 951 | case 'l': | ||
| 952 | statefile = optarg; | ||
| 953 | break; | ||
| 954 | case 'A': | ||
| 955 | if (!scan_ip6_net(optarg, &tmpnet)) { | ||
| 956 | usage(argv[0]); | ||
| 957 | exit(1); | ||
| 958 | } | ||
| 959 | accesslist_bless_net(&tmpnet, 0xffff); /* Allow everything for now */ | ||
| 960 | break; | ||
| 961 | case 'f': | ||
| 962 | bound += parse_configfile(optarg); | ||
| 963 | break; | ||
| 964 | case 'h': | ||
| 965 | help(argv[0]); | ||
| 966 | exit(0); | ||
| 967 | case 'v': { | ||
| 968 | char buffer[8192]; | ||
| 969 | stats_return_tracker_version(buffer); | ||
| 970 | fputs(buffer, stderr); | ||
| 971 | exit(0); | ||
| 972 | } | ||
| 973 | default: | ||
| 974 | case '?': | ||
| 975 | usage(argv[0]); | ||
| 976 | exit(1); | ||
| 977 | } | ||
| 978 | } | ||
| 979 | |||
| 980 | if (!bound) { | ||
| 981 | listen_append(serverip, 6969, FLAG_TCP, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); | ||
| 982 | listen_append(serverip, 6969, FLAG_UDP, OT_LISTEN_INHERIT, OT_LISTEN_INHERIT); | ||
| 983 | } | ||
| 984 | 471 | ||
| 985 | listen_bind_all(); | 472 | listen_bind_all(); |
| 986 | 473 | ||
| @@ -1017,8 +504,8 @@ int main(int argc, char **argv) { | |||
| 1017 | fprintf(stderr, "... done.\n"); | 504 | fprintf(stderr, "... done.\n"); |
| 1018 | #endif | 505 | #endif |
| 1019 | 506 | ||
| 1020 | if (statefile) | 507 | if (g_statefile) |
| 1021 | load_state(statefile); | 508 | load_state(g_statefile); |
| 1022 | 509 | ||
| 1023 | install_signal_handlers(); | 510 | install_signal_handlers(); |
| 1024 | 511 | ||
