summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c516
1 files changed, 56 insertions, 460 deletions
diff --git a/opentracker.c b/opentracker.c
index 5b197d1..60bdceb 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -23,10 +23,10 @@
23 23
24/* Libowfat */ 24/* Libowfat */
25#include "io.h" 25#include "io.h"
26#include "iob.h"
27 26
28/* Opentracker */ 27/* Opentracker */
29#include "ot_accesslist.h" 28#include "ot_accesslist.h"
29#include "ot_config.h"
30#include "ot_hex.h" 30#include "ot_hex.h"
31#include "ot_http.h" 31#include "ot_http.h"
32#include "ot_ip.h" 32#include "ot_ip.h"
@@ -35,20 +35,17 @@
35#include "ot_random.h" 35#include "ot_random.h"
36#include "ot_scan.h" 36#include "ot_scan.h"
37#include "ot_socket.h" 37#include "ot_socket.h"
38#include "ot_timeout.h"
38#include "ot_stats.h" 39#include "ot_stats.h"
39#include "ot_udp.h" 40#include "ot_udp.h"
40#include "trackerlogic.h" 41#include "trackerlogic.h"
41 42
42/* Globals */ 43/* Globals */
43time_t g_now_seconds; 44time_t g_now_seconds;
44char *g_redirecturl;
45uint32_t g_tracker_id; 45uint32_t g_tracker_id;
46volatile int g_opentracker_running = 1; 46volatile int g_opentracker_running = 1;
47int g_self_pipe[2]; 47int g_self_pipe[2];
48 48
49static char *g_serverdir;
50static char *g_serveruser;
51static unsigned int g_udp_workers;
52 49
53static void panic(const char *routine) __attribute__((noreturn)); 50static void panic(const char *routine) __attribute__((noreturn));
54static void panic(const char *routine) { 51static void panic(const char *routine) {
@@ -100,42 +97,6 @@ static void install_signal_handlers(void) {
100 pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL); 97 pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL);
101} 98}
102 99
103static void usage(char *name) {
104 fprintf(stderr,
105 "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-u user] [-A ip[/bits]] [-f config] [-s livesyncport]"
106#ifdef WANT_ACCESSLIST_BLACK
107 " [-b blacklistfile]"
108#elif defined(WANT_ACCESSLIST_WHITE)
109 " [-w whitelistfile]"
110#endif
111 "\n",
112 name);
113}
114
115#define HELPLINE(opt, desc) fprintf(stderr, "\t%-10s%s\n", opt, desc)
116static void help(char *name) {
117 usage(name);
118
119 HELPLINE("-f config", "include and execute the config file");
120 HELPLINE("-i ip", "specify ip to bind to with next -[pP] (default: any, overrides preceeding ones)");
121 HELPLINE("-p port", "do bind to tcp port (default: 6969, you may specify more than one)");
122 HELPLINE("-P port", "do bind to udp port (default: 6969, you may specify more than one)");
123 HELPLINE("-r redirecturl", "specify url where / should be redirected to (default none)");
124 HELPLINE("-d dir", "specify directory to try to chroot to (default: \".\")");
125 HELPLINE("-u user", "specify user under whose privileges opentracker should run (default: \"nobody\")");
126 HELPLINE("-A ip[/bits]", "bless an ip address or net as admin address (e.g. to allow syncs from this address)");
127#ifdef WANT_ACCESSLIST_BLACK
128 HELPLINE("-b file", "specify blacklist file.");
129#elif defined(WANT_ACCESSLIST_WHITE)
130 HELPLINE("-w file", "specify whitelist file.");
131#endif
132
133 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");
134 fprintf(stderr, " Here -i 127.0.0.1 selects the ip address for the next -p 6969 and -P 6969.\n");
135 fprintf(stderr, " If no port is bound from config file or command line, the last address given\n");
136 fprintf(stderr, " (or ::1 if none is set) will be used on port 6969.\n");
137}
138#undef HELPLINE
139 100
140static ssize_t header_complete(char *request, ssize_t byte_count) { 101static ssize_t header_complete(char *request, ssize_t byte_count) {
141 ssize_t i = 0, state = 0; 102 ssize_t i = 0, state = 0;
@@ -159,9 +120,8 @@ static ssize_t header_complete(char *request, ssize_t byte_count) {
159static void handle_dead(const int64_t sock) { 120static void handle_dead(const int64_t sock) {
160 struct http_data *cookie = io_getcookie(sock); 121 struct http_data *cookie = io_getcookie(sock);
161 if (cookie) { 122 if (cookie) {
162 size_t i; 123 if (cookie->batch)
163 for (i = 0; i < cookie->batches; ++i) 124 batch_reset(cookie->batch);
164 iob_reset(cookie->batch + i);
165 free(cookie->batch); 125 free(cookie->batch);
166 buf_reset(&cookie->request); 126 buf_reset(&cookie->request);
167 if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) 127 if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER))
@@ -217,33 +177,23 @@ static void handle_read(const int64_t sock, struct ot_workstruct *ws) {
217 177
218static void handle_write(const int64_t sock) { 178static void handle_write(const int64_t sock) {
219 struct http_data *cookie = io_getcookie(sock); 179 struct http_data *cookie = io_getcookie(sock);
220 size_t i;
221 int chunked = 0; 180 int chunked = 0;
222 181
223 /* Look for the first io_batch still containing bytes to write */
224 if (cookie) { 182 if (cookie) {
225 if (cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER) 183 if (cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)
226 chunked = 1; 184 chunked = 1;
227 185
228 for (i = 0; i < cookie->batches; ++i) { 186 if (cookie->batch) {
229 if (cookie->batch[i].bytesleft) { 187 if (batch_send(sock, cookie->batch) == BATCH_FAILED) {
230 int64_t res = iob_send(sock, cookie->batch + i); 188 handle_dead(sock);
231 189 return;
232 if (res == -3) {
233 handle_dead(sock);
234 return;
235 }
236
237 if (!cookie->batch[i].bytesleft)
238 continue;
239
240 if (res == -1 || res > 0 || i < cookie->batches - 1)
241 return;
242 } 190 }
191 if (batch_pending(cookie->batch))
192 return;
243 } 193 }
244 } 194 }
245 195
246 /* In a chunked transfer after all batches accumulated have been sent, wait for the next one */ 196 /* In a chunked transfer, wait for the next piece once everything queued has gone out */
247 if (chunked) 197 if (chunked)
248 io_dontwantwrite(sock); 198 io_dontwantwrite(sock);
249 else 199 else
@@ -255,7 +205,6 @@ static void handle_accept(const int64_t serversocket) {
255 int64_t sock; 205 int64_t sock;
256 ot_ip6 ip; 206 ot_ip6 ip;
257 uint16_t port; 207 uint16_t port;
258 tai6464 t;
259 208
260 while ((sock = socket_accept(serversocket, ip, &port)) != -1) { 209 while ((sock = socket_accept(serversocket, ip, &port)) != -1) {
261 210
@@ -274,11 +223,7 @@ static void handle_accept(const int64_t serversocket) {
274 223
275 stats_issue_event(EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip); 224 stats_issue_event(EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip);
276 225
277 /* That breaks taia encapsulation. But there is no way to take system 226 timeout_in(sock, OT_CLIENT_TIMEOUT);
278 time this often in FreeBSD and libowfat does not allow to set unix time */
279 taia_uint(&t, 0); /* Clear t */
280 tai_unix(&(t.sec), (g_now_seconds + OT_CLIENT_TIMEOUT));
281 io_timeout(sock, t);
282 } 227 }
283 io_eagain(serversocket); 228 io_eagain(serversocket);
284} 229}
@@ -338,320 +283,75 @@ static void *server_mainloop(void *args) {
338 return 0; 283 return 0;
339} 284}
340 285
341static int64_t ot_try_bind(ot_ip6 ip, uint16_t port, PROTO_FLAG proto) { 286
342 int64_t sock; 287static void listen_bind_one(ot_listen *entry) {
288 socket_sharing sharing = entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE;
343 289
344#ifdef _DEBUG 290#ifdef _DEBUG
345 { 291 {
346 char *protos[] = {"TCP", "UDP", "UDP mcast"}; 292 const char *protos[] = {"TCP", "UDP", "UDP mcast"};
347 char _debug[512]; 293 char _debug[512];
348 int off = snprintf(_debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto]); 294 int off = snprintf(_debug, sizeof(_debug), "Binding socket type %s to address [", protos[entry->proto]);
349 off += ip_format(_debug + off, ip); 295 off += ip_format(_debug + off, entry->ip);
350 snprintf(_debug + off, sizeof(_debug) - off, "]:%d...", port); 296 snprintf(_debug + off, sizeof(_debug) - off, "]:%d...", entry->port);
351 fputs(_debug, stderr); 297 fputs(_debug, stderr);
352 } 298 }
353#endif 299#endif
354 300
355 if (proto == FLAG_TCP) { 301#ifdef WANT_SYNC_LIVE
356 if ((sock = socket_tcp_listen(ip, port)) == -1) 302 if (entry->proto == FLAG_MCA) {
303 livesync_bind_mcast(entry->ip, entry->port);
304#ifdef _DEBUG
305 fputs(" success.\n", stderr);
306#endif
307 return;
308 }
309#endif
310
311 if (entry->proto == FLAG_TCP) {
312 if ((entry->sock = socket_tcp_listen(entry->ip, entry->port, sharing)) == -1)
357 panic("socket_tcp_listen"); 313 panic("socket_tcp_listen");
358 } else { 314 } else {
359 if ((sock = socket_udp_bind(ip, port)) == -1) 315 if ((entry->sock = socket_udp_bind(entry->ip, entry->port, sharing)) == -1)
360 panic("socket_udp_bind"); 316 panic("socket_udp_bind");
361 } 317 }
362 318
363 if (!io_fd(sock)) 319 if (!io_fd(entry->sock))
364 panic("io_fd"); 320 panic("io_fd");
365 321
366 io_setcookie(sock, (void *)proto); 322 io_setcookie(entry->sock, (void *)entry->proto);
367 323 io_wantread(entry->sock);
368 if ((proto == FLAG_UDP) && g_udp_workers) {
369 io_block(sock);
370 udp_init(sock, g_udp_workers);
371 } else
372 io_wantread(sock);
373 324
374#ifdef _DEBUG 325#ifdef _DEBUG
375 fputs(" success.\n", stderr); 326 fputs(" success.\n", stderr);
376#endif 327#endif
377
378 return sock;
379} 328}
380 329
381char *set_config_option(char **option, char *value) { 330/* Bound in the order the entries were given.
382#ifdef _DEBUG 331 Note: On macOS SO_REUSEPORT delivers everything to the socket that bound last. */
383 fprintf(stderr, "Setting config option: %s\n", value); 332static void listen_bind_all(void) {
384#endif 333 size_t count, i;
385 while (isspace(*value)) 334 ot_listen *entries = config_listen_entries(&count);
386 ++value;
387 free(*option);
388 return *option = strdup(value);
389}
390
391static int scan_ip6_port(const char *src, ot_ip6 ip, uint16_t *port) {
392 const char *s = src;
393 uint64_t value;
394 int off, bracket = 0;
395 while (isspace(*s))
396 ++s;
397 if (*s == '[')
398 ++s, ++bracket; /* for v6 style notation */
399 if (!(off = ip_scan(s, ip)))
400 return 0;
401 s += off;
402 if (bracket && *s == ']')
403 ++s;
404 if (*s == 0 || isspace(*s))
405 return s - src;
406 if (!ip_is_v4mapped(ip)) {
407 if (*s != ':' && *s != '.')
408 return 0;
409 if (!bracket && *(s) == ':')
410 return 0;
411 s++;
412 } else {
413 if (*(s++) != ':')
414 return 0;
415 }
416 if (!(off = scan_udec(s, &value, 65535)))
417 return 0;
418 *port = (uint16_t)value;
419 return off + s - src;
420}
421 335
422static int scan_ip6_net(const char *src, ot_net *net) { 336 for (i = 0; i < count; ++i)
423 const char *s = src; 337 listen_bind_one(entries + i);
424 uint64_t value;
425 int off;
426 while (isspace(*s))
427 ++s;
428 if (!(off = ip_scan(s, net->address)))
429 return 0;
430 s += off;
431 if (*s != '/')
432 net->bits = 128;
433 else {
434 s++;
435 if (!(off = scan_udec(s, &value, 128)))
436 return 0;
437 net->bits = (int)value;
438 if (ip_is_v4mapped(net->address))
439 net->bits += 96;
440 if (net->bits > 128)
441 return 0;
442 s += off;
443 }
444 return off + s - src;
445} 338}
446 339
447typedef enum { 340static void listen_start_udp_workers(void) {
448 CONFIG_UNKNOWN, 341 size_t count, i;
449 CONFIG_TRACKER_ROOTDIR, 342 ot_listen *entries = config_listen_entries(&count);
450 CONFIG_TRACKER_USER,
451 CONFIG_LISTEN_TCP_UDP,
452 CONFIG_LISTEN_TCP,
453 CONFIG_LISTEN_UDP,
454 CONFIG_LISTEN_UDP_WORKERS,
455 CONFIG_LISTEN_REUSEPORT,
456 CONFIG_ACCESS_WHITELIST,
457 CONFIG_ACCESS_BLACKLIST,
458 CONFIG_ACCESS_FIFO_ADD,
459 CONFIG_ACCESS_FIFO_DELETE,
460 CONFIG_ACCESS_STATS,
461 CONFIG_ACCESS_STATS_PATH,
462 CONFIG_ACCESS_PROXY,
463 CONFIG_TRACKER_REDIRECT_URL,
464 CONFIG_LIVESYNC_CLUSTER_NODE_IP,
465 CONFIG_LIVESYNC_CLUSTER_LISTEN,
466} config_kind;
467 343
468typedef struct { 344 udp_init();
469 const char *name;
470 size_t len;
471 config_kind kind;
472} config_key;
473 345
474#define CONFIG_KEY(s, k) { s, sizeof(s) - 1, k } 346 for (i = 0; i < count; ++i) {
347 ot_listen *entry = entries + i;
475 348
476static const config_key config_keys[] = { 349 if (entry->proto != FLAG_UDP || entry->workers <= 0)
477 CONFIG_KEY("tracker.rootdir", CONFIG_TRACKER_ROOTDIR),
478 CONFIG_KEY("tracker.user", CONFIG_TRACKER_USER),
479 CONFIG_KEY("listen.tcp_udp", CONFIG_LISTEN_TCP_UDP),
480 CONFIG_KEY("listen.tcp", CONFIG_LISTEN_TCP),
481 CONFIG_KEY("listen.udp", CONFIG_LISTEN_UDP),
482 CONFIG_KEY("listen.udp.workers", CONFIG_LISTEN_UDP_WORKERS),
483 CONFIG_KEY("listen.reuseport", CONFIG_LISTEN_REUSEPORT),
484#ifdef WANT_ACCESSLIST_WHITE
485 CONFIG_KEY("access.whitelist", CONFIG_ACCESS_WHITELIST),
486#elif defined(WANT_ACCESSLIST_BLACK)
487 CONFIG_KEY("access.blacklist", CONFIG_ACCESS_BLACKLIST),
488#endif
489#ifdef WANT_DYNAMIC_ACCESSLIST
490 CONFIG_KEY("access.fifo_add", CONFIG_ACCESS_FIFO_ADD),
491 CONFIG_KEY("access.fifo_delete", CONFIG_ACCESS_FIFO_DELETE),
492#endif
493#ifdef WANT_RESTRICT_STATS
494 CONFIG_KEY("access.stats", CONFIG_ACCESS_STATS),
495#endif
496 CONFIG_KEY("access.stats_path", CONFIG_ACCESS_STATS_PATH),
497#ifdef WANT_IP_FROM_PROXY
498 CONFIG_KEY("access.proxy", CONFIG_ACCESS_PROXY),
499#endif
500 CONFIG_KEY("tracker.redirect_url", CONFIG_TRACKER_REDIRECT_URL),
501#ifdef WANT_SYNC_LIVE
502 CONFIG_KEY("livesync.cluster.node_ip", CONFIG_LIVESYNC_CLUSTER_NODE_IP),
503 CONFIG_KEY("livesync.cluster.listen", CONFIG_LIVESYNC_CLUSTER_LISTEN),
504#endif
505};
506static const size_t config_entry_count = sizeof(config_keys) / sizeof(config_keys[0]);
507
508static config_kind parse_config_key(char **p) {
509 size_t i;
510 for (i = 0; i < config_entry_count; ++i) {
511 const config_key *key = &config_keys[i];
512 if (strncmp(*p, key->name, key->len) == 0 && isspace((unsigned char)(*p)[key->len])) {
513 *p += key->len + 1;
514 /* Skip white spaces */
515 while (isspace((unsigned char)**p))
516 ++(*p);
517 return key->kind;
518 }
519 }
520 return CONFIG_UNKNOWN;
521}
522
523int parse_configfile(char *config_filename) {
524 FILE *config_file_handle;
525 char inbuf[512];
526 ot_ip6 tmpip;
527#if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE)
528 ot_net tmpnet;
529#endif
530 int bound = 0;
531
532 config_file_handle = fopen(config_filename, "r");
533
534 if (config_file_handle == NULL) {
535 fprintf(stderr, "Warning: Can't open config file: %s.", config_filename);
536 return 0;
537 }
538
539 while (fgets(inbuf, sizeof(inbuf), config_file_handle)) {
540 char *p = inbuf, *end;
541 uint64_t value;
542 uint16_t tmpport = 6969;
543
544 /* Skip white spaces */
545 while (isspace((unsigned char)*p))
546 ++p;
547
548 /* Ignore comments and empty lines */
549 if ((*p == '#') || (*p == '\n') || (*p == 0))
550 continue; 350 continue;
551 351
552 /* consume trailing new lines and spaces */ 352 io_block(entry->sock);
553 end = p + strlen(p); 353 udp_workers_install(entry->sock, (unsigned int)entry->workers);
554 while (end > p && isspace((unsigned char)end[-1]))
555 *--end = 0;
556
557 /* Scan for commands */
558 switch (parse_config_key(&p)) {
559 case CONFIG_TRACKER_ROOTDIR:
560 set_config_option(&g_serverdir, p);
561 break;
562 case CONFIG_TRACKER_USER:
563 set_config_option(&g_serveruser, p);
564 break;
565 case CONFIG_LISTEN_TCP_UDP:
566 if (!scan_ip6_port(p, tmpip, &tmpport))
567 goto parse_error;
568 ot_try_bind(tmpip, tmpport, FLAG_TCP);
569 ++bound;
570 ot_try_bind(tmpip, tmpport, FLAG_UDP);
571 ++bound;
572 break;
573 case CONFIG_LISTEN_TCP:
574 if (!scan_ip6_port(p, tmpip, &tmpport))
575 goto parse_error;
576 ot_try_bind(tmpip, tmpport, FLAG_TCP);
577 ++bound;
578 break;
579 case CONFIG_LISTEN_UDP:
580 if (!scan_ip6_port(p, tmpip, &tmpport))
581 goto parse_error;
582 ot_try_bind(tmpip, tmpport, FLAG_UDP);
583 ++bound;
584 break;
585 case CONFIG_LISTEN_UDP_WORKERS:
586 if (scan_udec(p, &value, UINT_MAX))
587 g_udp_workers = (unsigned int)value;
588 break;
589 case CONFIG_LISTEN_REUSEPORT:
590 /* Like listen.udp.workers this is read when a socket is bound, so it
591 has to come before the listen lines it should apply to. */
592 if (!scan_udec(p, &value, 1))
593 goto parse_error;
594 g_socket_reuseport = (int)value;
595 break;
596#ifdef WANT_ACCESSLIST_WHITE
597 case CONFIG_ACCESS_WHITELIST:
598 set_config_option(&g_accesslist_filename, p);
599 break;
600#elif defined(WANT_ACCESSLIST_BLACK)
601 case CONFIG_ACCESS_BLACKLIST:
602 set_config_option(&g_accesslist_filename, p);
603 break;
604#endif
605#ifdef WANT_DYNAMIC_ACCESSLIST
606 case CONFIG_ACCESS_FIFO_ADD:
607 set_config_option(&g_accesslist_pipe_add, p);
608 break;
609 case CONFIG_ACCESS_FIFO_DELETE:
610 set_config_option(&g_accesslist_pipe_delete, p);
611 break;
612#endif
613#ifdef WANT_RESTRICT_STATS
614 case CONFIG_ACCESS_STATS:
615 if (!scan_ip6_net(p, &tmpnet))
616 goto parse_error;
617 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT);
618 break;
619#endif
620 case CONFIG_ACCESS_STATS_PATH:
621 set_config_option(&g_stats_path, p);
622 break;
623#ifdef WANT_IP_FROM_PROXY
624 case CONFIG_ACCESS_PROXY:
625 if (!scan_ip6_net(p, &tmpnet))
626 goto parse_error;
627 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY);
628 break;
629#endif
630 case CONFIG_TRACKER_REDIRECT_URL:
631 set_config_option(&g_redirecturl, p);
632 break;
633#ifdef WANT_SYNC_LIVE
634 case CONFIG_LIVESYNC_CLUSTER_NODE_IP:
635 if (!scan_ip6_net(p, &tmpnet))
636 goto parse_error;
637 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC);
638 break;
639 case CONFIG_LIVESYNC_CLUSTER_LISTEN:
640 tmpport = LIVESYNC_PORT;
641 if (!scan_ip6_port(p, tmpip, &tmpport))
642 goto parse_error;
643 livesync_bind_mcast(tmpip, tmpport);
644 break;
645#endif
646 default:
647 fprintf(stderr, "Unhandled line in config file: %s\n", inbuf);
648 break;
649 parse_error:
650 fprintf(stderr, "Parse error in config file: %s\n", inbuf);
651 }
652 } 354 }
653 fclose(config_file_handle);
654 return bound;
655} 355}
656 356
657void load_state(const char *const state_filename) { 357void load_state(const char *const state_filename) {
@@ -745,115 +445,12 @@ static void *time_caching_worker(void *args) {
745} 445}
746 446
747int main(int argc, char **argv) { 447int main(int argc, char **argv) {
748 ot_ip6 serverip;
749 ot_net tmpnet;
750 int bound = 0, scanon = 1;
751 uint64_t value;
752 char *statefile = 0;
753 pthread_t thread_id; /* time cacher */ 448 pthread_t thread_id; /* time cacher */
754 449
755 memset(serverip, 0, sizeof(ot_ip6));
756#ifdef WANT_V4_ONLY
757 serverip[10] = serverip[11] = -1;
758#endif
759
760 random_init(); 450 random_init();
451 config_parse(argc, argv);
761 452
762 while (scanon) { 453 listen_bind_all();
763 switch (getopt(argc, argv,
764 ":i:p:A:P:d:u:r:s:f:l:v"
765#ifdef WANT_ACCESSLIST_BLACK
766 "b:"
767#elif defined(WANT_ACCESSLIST_WHITE)
768 "w:"
769#endif
770 "h")) {
771 case -1:
772 scanon = 0;
773 break;
774 case 'i':
775 if (!ip_scan(optarg, serverip)) {
776 usage(argv[0]);
777 exit(1);
778 }
779 break;
780#ifdef WANT_ACCESSLIST_BLACK
781 case 'b':
782 set_config_option(&g_accesslist_filename, optarg);
783 break;
784#elif defined(WANT_ACCESSLIST_WHITE)
785 case 'w':
786 set_config_option(&g_accesslist_filename, optarg);
787 break;
788#endif
789 case 'p':
790 if (!scan_udec(optarg, &value, 65535)) {
791 usage(argv[0]);
792 exit(1);
793 }
794 ot_try_bind(serverip, (uint16_t)value, FLAG_TCP);
795 bound++;
796 break;
797 case 'P':
798 if (!scan_udec(optarg, &value, 65535)) {
799 usage(argv[0]);
800 exit(1);
801 }
802 ot_try_bind(serverip, (uint16_t)value, FLAG_UDP);
803 bound++;
804 break;
805#ifdef WANT_SYNC_LIVE
806 case 's':
807 if (!scan_udec(optarg, &value, 65535)) {
808 usage(argv[0]);
809 exit(1);
810 }
811 livesync_bind_mcast(serverip, (uint16_t)value);
812 break;
813#endif
814 case 'd':
815 set_config_option(&g_serverdir, optarg);
816 break;
817 case 'u':
818 set_config_option(&g_serveruser, optarg);
819 break;
820 case 'r':
821 set_config_option(&g_redirecturl, optarg);
822 break;
823 case 'l':
824 statefile = optarg;
825 break;
826 case 'A':
827 if (!scan_ip6_net(optarg, &tmpnet)) {
828 usage(argv[0]);
829 exit(1);
830 }
831 accesslist_bless_net(&tmpnet, 0xffff); /* Allow everything for now */
832 break;
833 case 'f':
834 bound += parse_configfile(optarg);
835 break;
836 case 'h':
837 help(argv[0]);
838 exit(0);
839 case 'v': {
840 char buffer[8192];
841 stats_return_tracker_version(buffer);
842 fputs(buffer, stderr);
843 exit(0);
844 }
845 default:
846 case '?':
847 usage(argv[0]);
848 exit(1);
849 }
850 }
851
852 /* Bind to our default tcp/udp ports */
853 if (!bound) {
854 ot_try_bind(serverip, 6969, FLAG_TCP);
855 ot_try_bind(serverip, 6969, FLAG_UDP);
856 }
857 454
858 defaul_signal_handlers(); 455 defaul_signal_handlers();
859 456
@@ -888,13 +485,12 @@ int main(int argc, char **argv) {
888 fprintf(stderr, "... done.\n"); 485 fprintf(stderr, "... done.\n");
889#endif 486#endif
890 487
891 if (statefile) 488 if (g_statefile)
892 load_state(statefile); 489 load_state(g_statefile);
893 490
894 install_signal_handlers(); 491 install_signal_handlers();
895 492
896 if (!g_udp_workers) 493 listen_start_udp_workers();
897 udp_init(-1, 0);
898 494
899 server_mainloop(0); 495 server_mainloop(0);
900 496