summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c515
1 files changed, 61 insertions, 454 deletions
diff --git a/opentracker.c b/opentracker.c
index af336aa..60bdceb 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -23,11 +23,10 @@
23 23
24/* Libowfat */ 24/* Libowfat */
25#include "io.h" 25#include "io.h"
26#include "iob.h"
27#include "socket.h"
28 26
29/* Opentracker */ 27/* Opentracker */
30#include "ot_accesslist.h" 28#include "ot_accesslist.h"
29#include "ot_config.h"
31#include "ot_hex.h" 30#include "ot_hex.h"
32#include "ot_http.h" 31#include "ot_http.h"
33#include "ot_ip.h" 32#include "ot_ip.h"
@@ -35,20 +34,18 @@
35#include "ot_mutex.h" 34#include "ot_mutex.h"
36#include "ot_random.h" 35#include "ot_random.h"
37#include "ot_scan.h" 36#include "ot_scan.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
@@ -254,10 +204,9 @@ static void handle_accept(const int64_t serversocket) {
254 struct http_data *cookie; 204 struct http_data *cookie;
255 int64_t sock; 205 int64_t sock;
256 ot_ip6 ip; 206 ot_ip6 ip;
257 uint16 port; 207 uint16_t port;
258 tai6464 t;
259 208
260 while ((sock = socket_accept6(serversocket, ip, &port, NULL)) != -1) { 209 while ((sock = socket_accept(serversocket, ip, &port)) != -1) {
261 210
262 /* Put fd into a non-blocking mode */ 211 /* Put fd into a non-blocking mode */
263 io_nonblock(sock); 212 io_nonblock(sock);
@@ -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,309 +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 = proto == FLAG_TCP ? socket_tcp6() : socket_udp6(); 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 (socket_bind6_reuse(sock, ip, port, 0) == -1) 301#ifdef WANT_SYNC_LIVE
356 panic("socket_bind6_reuse"); 302 if (entry->proto == FLAG_MCA) {
357 303 livesync_bind_mcast(entry->ip, entry->port);
358 if ((proto == FLAG_TCP) && (socket_listen(sock, SOMAXCONN) == -1))
359 panic("socket_listen");
360
361 if (!io_fd(sock))
362 panic("io_fd");
363
364 io_setcookie(sock, (void *)proto);
365
366 if ((proto == FLAG_UDP) && g_udp_workers) {
367 io_block(sock);
368 udp_init(sock, g_udp_workers);
369 } else
370 io_wantread(sock);
371
372#ifdef _DEBUG 304#ifdef _DEBUG
373 fputs(" success.\n", stderr); 305 fputs(" success.\n", stderr);
374#endif 306#endif
375 307 return;
376 return sock; 308 }
377}
378
379char *set_config_option(char **option, char *value) {
380#ifdef _DEBUG
381 fprintf(stderr, "Setting config option: %s\n", value);
382#endif 309#endif
383 while (isspace(*value))
384 ++value;
385 free(*option);
386 return *option = strdup(value);
387}
388 310
389static int scan_ip6_port(const char *src, ot_ip6 ip, uint16_t *port) { 311 if (entry->proto == FLAG_TCP) {
390 const char *s = src; 312 if ((entry->sock = socket_tcp_listen(entry->ip, entry->port, sharing)) == -1)
391 uint64_t value; 313 panic("socket_tcp_listen");
392 int off, bracket = 0;
393 while (isspace(*s))
394 ++s;
395 if (*s == '[')
396 ++s, ++bracket; /* for v6 style notation */
397 if (!(off = ip_scan(s, ip)))
398 return 0;
399 s += off;
400 if (bracket && *s == ']')
401 ++s;
402 if (*s == 0 || isspace(*s))
403 return s - src;
404 if (!ip_is_v4mapped(ip)) {
405 if (*s != ':' && *s != '.')
406 return 0;
407 if (!bracket && *(s) == ':')
408 return 0;
409 s++;
410 } else { 314 } else {
411 if (*(s++) != ':') 315 if ((entry->sock = socket_udp_bind(entry->ip, entry->port, sharing)) == -1)
412 return 0; 316 panic("socket_udp_bind");
413 } 317 }
414 if (!(off = scan_udec(s, &value, 65535)))
415 return 0;
416 *port = (uint16_t)value;
417 return off + s - src;
418}
419 318
420static int scan_ip6_net(const char *src, ot_net *net) { 319 if (!io_fd(entry->sock))
421 const char *s = src; 320 panic("io_fd");
422 uint64_t value;
423 int off;
424 while (isspace(*s))
425 ++s;
426 if (!(off = ip_scan(s, net->address)))
427 return 0;
428 s += off;
429 if (*s != '/')
430 net->bits = 128;
431 else {
432 s++;
433 if (!(off = scan_udec(s, &value, 128)))
434 return 0;
435 net->bits = (int)value;
436 if (ip_is_v4mapped(net->address))
437 net->bits += 96;
438 if (net->bits > 128)
439 return 0;
440 s += off;
441 }
442 return off + s - src;
443}
444
445typedef enum {
446 CONFIG_UNKNOWN,
447 CONFIG_TRACKER_ROOTDIR,
448 CONFIG_TRACKER_USER,
449 CONFIG_LISTEN_TCP_UDP,
450 CONFIG_LISTEN_TCP,
451 CONFIG_LISTEN_UDP,
452 CONFIG_LISTEN_UDP_WORKERS,
453 CONFIG_ACCESS_WHITELIST,
454 CONFIG_ACCESS_BLACKLIST,
455 CONFIG_ACCESS_FIFO_ADD,
456 CONFIG_ACCESS_FIFO_DELETE,
457 CONFIG_ACCESS_STATS,
458 CONFIG_ACCESS_STATS_PATH,
459 CONFIG_ACCESS_PROXY,
460 CONFIG_TRACKER_REDIRECT_URL,
461 CONFIG_LIVESYNC_CLUSTER_NODE_IP,
462 CONFIG_LIVESYNC_CLUSTER_LISTEN,
463} config_kind;
464
465typedef struct {
466 const char *name;
467 size_t len;
468 config_kind kind;
469} config_key;
470 321
471#define CONFIG_KEY(s, k) { s, sizeof(s) - 1, k } 322 io_setcookie(entry->sock, (void *)entry->proto);
323 io_wantread(entry->sock);
472 324
473static const config_key config_keys[] = { 325#ifdef _DEBUG
474 CONFIG_KEY("tracker.rootdir", CONFIG_TRACKER_ROOTDIR), 326 fputs(" success.\n", stderr);
475 CONFIG_KEY("tracker.user", CONFIG_TRACKER_USER),
476 CONFIG_KEY("listen.tcp_udp", CONFIG_LISTEN_TCP_UDP),
477 CONFIG_KEY("listen.tcp", CONFIG_LISTEN_TCP),
478 CONFIG_KEY("listen.udp", CONFIG_LISTEN_UDP),
479 CONFIG_KEY("listen.udp.workers", CONFIG_LISTEN_UDP_WORKERS),
480#ifdef WANT_ACCESSLIST_WHITE
481 CONFIG_KEY("access.whitelist", CONFIG_ACCESS_WHITELIST),
482#elif defined(WANT_ACCESSLIST_BLACK)
483 CONFIG_KEY("access.blacklist", CONFIG_ACCESS_BLACKLIST),
484#endif
485#ifdef WANT_DYNAMIC_ACCESSLIST
486 CONFIG_KEY("access.fifo_add", CONFIG_ACCESS_FIFO_ADD),
487 CONFIG_KEY("access.fifo_delete", CONFIG_ACCESS_FIFO_DELETE),
488#endif
489#ifdef WANT_RESTRICT_STATS
490 CONFIG_KEY("access.stats", CONFIG_ACCESS_STATS),
491#endif
492 CONFIG_KEY("access.stats_path", CONFIG_ACCESS_STATS_PATH),
493#ifdef WANT_IP_FROM_PROXY
494 CONFIG_KEY("access.proxy", CONFIG_ACCESS_PROXY),
495#endif
496 CONFIG_KEY("tracker.redirect_url", CONFIG_TRACKER_REDIRECT_URL),
497#ifdef WANT_SYNC_LIVE
498 CONFIG_KEY("livesync.cluster.node_ip", CONFIG_LIVESYNC_CLUSTER_NODE_IP),
499 CONFIG_KEY("livesync.cluster.listen", CONFIG_LIVESYNC_CLUSTER_LISTEN),
500#endif 327#endif
501};
502static const size_t config_entry_count = sizeof(config_keys) / sizeof(config_keys[0]);
503
504static config_kind parse_config_key(char **p) {
505 size_t i;
506 for (i = 0; i < config_entry_count; ++i) {
507 const config_key *key = &config_keys[i];
508 if (strncmp(*p, key->name, key->len) == 0 && isspace((unsigned char)(*p)[key->len])) {
509 *p += key->len + 1;
510 /* Skip white spaces */
511 while (isspace((unsigned char)**p))
512 ++(*p);
513 return key->kind;
514 }
515 }
516 return CONFIG_UNKNOWN;
517} 328}
518 329
519int parse_configfile(char *config_filename) { 330/* Bound in the order the entries were given.
520 FILE *config_file_handle; 331 Note: On macOS SO_REUSEPORT delivers everything to the socket that bound last. */
521 char inbuf[512]; 332static void listen_bind_all(void) {
522 ot_ip6 tmpip; 333 size_t count, i;
523#if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE) 334 ot_listen *entries = config_listen_entries(&count);
524 ot_net tmpnet;
525#endif
526 int bound = 0;
527 335
528 config_file_handle = fopen(config_filename, "r"); 336 for (i = 0; i < count; ++i)
337 listen_bind_one(entries + i);
338}
529 339
530 if (config_file_handle == NULL) { 340static void listen_start_udp_workers(void) {
531 fprintf(stderr, "Warning: Can't open config file: %s.", config_filename); 341 size_t count, i;
532 return 0; 342 ot_listen *entries = config_listen_entries(&count);
533 }
534 343
535 while (fgets(inbuf, sizeof(inbuf), config_file_handle)) { 344 udp_init();
536 char *p = inbuf, *end;
537 uint64_t value;
538 uint16_t tmpport = 6969;
539 345
540 /* Skip white spaces */ 346 for (i = 0; i < count; ++i) {
541 while (isspace((unsigned char)*p)) 347 ot_listen *entry = entries + i;
542 ++p;
543 348
544 /* Ignore comments and empty lines */ 349 if (entry->proto != FLAG_UDP || entry->workers <= 0)
545 if ((*p == '#') || (*p == '\n') || (*p == 0))
546 continue; 350 continue;
547 351
548 /* consume trailing new lines and spaces */ 352 io_block(entry->sock);
549 end = p + strlen(p); 353 udp_workers_install(entry->sock, (unsigned int)entry->workers);
550 while (end > p && isspace((unsigned char)end[-1]))
551 *--end = 0;
552
553 /* Scan for commands */
554 switch (parse_config_key(&p)) {
555 case CONFIG_TRACKER_ROOTDIR:
556 set_config_option(&g_serverdir, p);
557 break;
558 case CONFIG_TRACKER_USER:
559 set_config_option(&g_serveruser, p);
560 break;
561 case CONFIG_LISTEN_TCP_UDP:
562 if (!scan_ip6_port(p, tmpip, &tmpport))
563 goto parse_error;
564 ot_try_bind(tmpip, tmpport, FLAG_TCP);
565 ++bound;
566 ot_try_bind(tmpip, tmpport, FLAG_UDP);
567 ++bound;
568 break;
569 case CONFIG_LISTEN_TCP:
570 if (!scan_ip6_port(p, tmpip, &tmpport))
571 goto parse_error;
572 ot_try_bind(tmpip, tmpport, FLAG_TCP);
573 ++bound;
574 break;
575 case CONFIG_LISTEN_UDP:
576 if (!scan_ip6_port(p, tmpip, &tmpport))
577 goto parse_error;
578 ot_try_bind(tmpip, tmpport, FLAG_UDP);
579 ++bound;
580 break;
581 case CONFIG_LISTEN_UDP_WORKERS:
582 if (scan_udec(p, &value, UINT_MAX))
583 g_udp_workers = (unsigned int)value;
584 break;
585#ifdef WANT_ACCESSLIST_WHITE
586 case CONFIG_ACCESS_WHITELIST:
587 set_config_option(&g_accesslist_filename, p);
588 break;
589#elif defined(WANT_ACCESSLIST_BLACK)
590 case CONFIG_ACCESS_BLACKLIST:
591 set_config_option(&g_accesslist_filename, p);
592 break;
593#endif
594#ifdef WANT_DYNAMIC_ACCESSLIST
595 case CONFIG_ACCESS_FIFO_ADD:
596 set_config_option(&g_accesslist_pipe_add, p);
597 break;
598 case CONFIG_ACCESS_FIFO_DELETE:
599 set_config_option(&g_accesslist_pipe_delete, p);
600 break;
601#endif
602#ifdef WANT_RESTRICT_STATS
603 case CONFIG_ACCESS_STATS:
604 if (!scan_ip6_net(p, &tmpnet))
605 goto parse_error;
606 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT);
607 break;
608#endif
609 case CONFIG_ACCESS_STATS_PATH:
610 set_config_option(&g_stats_path, p);
611 break;
612#ifdef WANT_IP_FROM_PROXY
613 case CONFIG_ACCESS_PROXY:
614 if (!scan_ip6_net(p, &tmpnet))
615 goto parse_error;
616 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY);
617 break;
618#endif
619 case CONFIG_TRACKER_REDIRECT_URL:
620 set_config_option(&g_redirecturl, p);
621 break;
622#ifdef WANT_SYNC_LIVE
623 case CONFIG_LIVESYNC_CLUSTER_NODE_IP:
624 if (!scan_ip6_net(p, &tmpnet))
625 goto parse_error;
626 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC);
627 break;
628 case CONFIG_LIVESYNC_CLUSTER_LISTEN:
629 tmpport = LIVESYNC_PORT;
630 if (!scan_ip6_port(p, tmpip, &tmpport))
631 goto parse_error;
632 livesync_bind_mcast(tmpip, tmpport);
633 break;
634#endif
635 default:
636 fprintf(stderr, "Unhandled line in config file: %s\n", inbuf);
637 break;
638 parse_error:
639 fprintf(stderr, "Parse error in config file: %s\n", inbuf);
640 }
641 } 354 }
642 fclose(config_file_handle);
643 return bound;
644} 355}
645 356
646void load_state(const char *const state_filename) { 357void load_state(const char *const state_filename) {
@@ -734,115 +445,12 @@ static void *time_caching_worker(void *args) {
734} 445}
735 446
736int main(int argc, char **argv) { 447int main(int argc, char **argv) {
737 ot_ip6 serverip;
738 ot_net tmpnet;
739 int bound = 0, scanon = 1;
740 uint64_t value;
741 char *statefile = 0;
742 pthread_t thread_id; /* time cacher */ 448 pthread_t thread_id; /* time cacher */
743 449
744 memset(serverip, 0, sizeof(ot_ip6));
745#ifdef WANT_V4_ONLY
746 serverip[10] = serverip[11] = -1;
747#endif
748
749 random_init(); 450 random_init();
451 config_parse(argc, argv);
750 452
751 while (scanon) { 453 listen_bind_all();
752 switch (getopt(argc, argv,
753 ":i:p:A:P:d:u:r:s:f:l:v"
754#ifdef WANT_ACCESSLIST_BLACK
755 "b:"
756#elif defined(WANT_ACCESSLIST_WHITE)
757 "w:"
758#endif
759 "h")) {
760 case -1:
761 scanon = 0;
762 break;
763 case 'i':
764 if (!ip_scan(optarg, serverip)) {
765 usage(argv[0]);
766 exit(1);
767 }
768 break;
769#ifdef WANT_ACCESSLIST_BLACK
770 case 'b':
771 set_config_option(&g_accesslist_filename, optarg);
772 break;
773#elif defined(WANT_ACCESSLIST_WHITE)
774 case 'w':
775 set_config_option(&g_accesslist_filename, optarg);
776 break;
777#endif
778 case 'p':
779 if (!scan_udec(optarg, &value, 65535)) {
780 usage(argv[0]);
781 exit(1);
782 }
783 ot_try_bind(serverip, (uint16_t)value, FLAG_TCP);
784 bound++;
785 break;
786 case 'P':
787 if (!scan_udec(optarg, &value, 65535)) {
788 usage(argv[0]);
789 exit(1);
790 }
791 ot_try_bind(serverip, (uint16_t)value, FLAG_UDP);
792 bound++;
793 break;
794#ifdef WANT_SYNC_LIVE
795 case 's':
796 if (!scan_udec(optarg, &value, 65535)) {
797 usage(argv[0]);
798 exit(1);
799 }
800 livesync_bind_mcast(serverip, (uint16_t)value);
801 break;
802#endif
803 case 'd':
804 set_config_option(&g_serverdir, optarg);
805 break;
806 case 'u':
807 set_config_option(&g_serveruser, optarg);
808 break;
809 case 'r':
810 set_config_option(&g_redirecturl, optarg);
811 break;
812 case 'l':
813 statefile = optarg;
814 break;
815 case 'A':
816 if (!scan_ip6_net(optarg, &tmpnet)) {
817 usage(argv[0]);
818 exit(1);
819 }
820 accesslist_bless_net(&tmpnet, 0xffff); /* Allow everything for now */
821 break;
822 case 'f':
823 bound += parse_configfile(optarg);
824 break;
825 case 'h':
826 help(argv[0]);
827 exit(0);
828 case 'v': {
829 char buffer[8192];
830 stats_return_tracker_version(buffer);
831 fputs(buffer, stderr);
832 exit(0);
833 }
834 default:
835 case '?':
836 usage(argv[0]);
837 exit(1);
838 }
839 }
840
841 /* Bind to our default tcp/udp ports */
842 if (!bound) {
843 ot_try_bind(serverip, 6969, FLAG_TCP);
844 ot_try_bind(serverip, 6969, FLAG_UDP);
845 }
846 454
847 defaul_signal_handlers(); 455 defaul_signal_handlers();
848 456
@@ -877,13 +485,12 @@ int main(int argc, char **argv) {
877 fprintf(stderr, "... done.\n"); 485 fprintf(stderr, "... done.\n");
878#endif 486#endif
879 487
880 if (statefile) 488 if (g_statefile)
881 load_state(statefile); 489 load_state(g_statefile);
882 490
883 install_signal_handlers(); 491 install_signal_handlers();
884 492
885 if (!g_udp_workers) 493 listen_start_udp_workers();
886 udp_init(-1, 0);
887 494
888 server_mainloop(0); 495 server_mainloop(0);
889 496