summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-23 21:48:58 +0200
committerDirk Engling <erdgeist@erdgeist.org>2026-10-23 21:48:58 +0200
commitde67a4a721c0fda9a9b5955f235baafba9ba393d (patch)
tree38627ee2df6927e715e7043809d281b16abdbddc /opentracker.c
parenta8def0e5eac98500267b52c7f0d9a7fbc2145a81 (diff)
Rework config file parser and tidy up mem inits
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c233
1 files changed, 159 insertions, 74 deletions
diff --git a/opentracker.c b/opentracker.c
index f63db72..e24beb2 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -438,8 +438,82 @@ static int scan_ip6_net(const char *src, ot_net *net) {
438 return off + s - src; 438 return off + s - src;
439} 439}
440 440
441typedef enum {
442 CONFIG_UNKNOWN,
443 CONFIG_TRACKER_ROOTDIR,
444 CONFIG_TRACKER_USER,
445 CONFIG_LISTEN_TCP_UDP,
446 CONFIG_LISTEN_TCP,
447 CONFIG_LISTEN_UDP,
448 CONFIG_LISTEN_UDP_WORKERS,
449 CONFIG_ACCESS_WHITELIST,
450 CONFIG_ACCESS_BLACKLIST,
451 CONFIG_ACCESS_FIFO_ADD,
452 CONFIG_ACCESS_FIFO_DELETE,
453 CONFIG_ACCESS_STATS,
454 CONFIG_ACCESS_STATS_PATH,
455 CONFIG_ACCESS_PROXY,
456 CONFIG_TRACKER_REDIRECT_URL,
457 CONFIG_LIVESYNC_CLUSTER_NODE_IP,
458 CONFIG_LIVESYNC_CLUSTER_LISTEN,
459} config_kind;
460
461typedef struct {
462 const char *name;
463 size_t len;
464 config_kind kind;
465} config_key;
466
467#define CONFIG_KEY(s, k) { s, sizeof(s) - 1, k }
468
469static const config_key config_keys[] = {
470 CONFIG_KEY("tracker.rootdir", CONFIG_TRACKER_ROOTDIR),
471 CONFIG_KEY("tracker.user", CONFIG_TRACKER_USER),
472 CONFIG_KEY("listen.tcp_udp", CONFIG_LISTEN_TCP_UDP),
473 CONFIG_KEY("listen.tcp", CONFIG_LISTEN_TCP),
474 CONFIG_KEY("listen.udp", CONFIG_LISTEN_UDP),
475 CONFIG_KEY("listen.udp.workers", CONFIG_LISTEN_UDP_WORKERS),
476#ifdef WANT_ACCESSLIST_WHITE
477 CONFIG_KEY("access.whitelist", CONFIG_ACCESS_WHITELIST),
478#elif defined(WANT_ACCESSLIST_BLACK)
479 CONFIG_KEY("access.blacklist", CONFIG_ACCESS_BLACKLIST),
480#endif
481#ifdef WANT_DYNAMIC_ACCESSLIST
482 CONFIG_KEY("access.fifo_add", CONFIG_ACCESS_FIFO_ADD),
483 CONFIG_KEY("access.fifo_delete", CONFIG_ACCESS_FIFO_DELETE),
484#endif
485#ifdef WANT_RESTRICT_STATS
486 CONFIG_KEY("access.stats", CONFIG_ACCESS_STATS),
487#endif
488 CONFIG_KEY("access.stats_path", CONFIG_ACCESS_STATS_PATH),
489#ifdef WANT_IP_FROM_PROXY
490 CONFIG_KEY("access.proxy", CONFIG_ACCESS_PROXY),
491#endif
492 CONFIG_KEY("tracker.redirect_url", CONFIG_TRACKER_REDIRECT_URL),
493#ifdef WANT_SYNC_LIVE
494 CONFIG_KEY("livesync.cluster.node_ip", CONFIG_LIVESYNC_CLUSTER_NODE_IP),
495 CONFIG_KEY("livesync.cluster.listen", CONFIG_LIVESYNC_CLUSTER_LISTEN),
496#endif
497};
498static const size_t config_entry_count = sizeof(config_keys) / sizeof(config_keys[0]);
499
500static config_kind parse_config_key(char **p) {
501 size_t i;
502 for (i = 0; i < config_entry_count; ++i) {
503 const config_key *key = &config_keys[i];
504 if (strncmp(*p, key->name, key->len) == 0 && isspace((unsigned char)(*p)[key->len])) {
505 *p += key->len + 1;
506 /* Skip white spaces */
507 while (isspace((unsigned char)**p))
508 ++(*p);
509 return key->kind;
510 }
511 }
512 return CONFIG_UNKNOWN;
513}
514
441int parse_configfile(char *config_filename) { 515int parse_configfile(char *config_filename) {
442 FILE *accesslist_filehandle; 516 FILE *config_file_handle;
443 char inbuf[512]; 517 char inbuf[512];
444 ot_ip6 tmpip; 518 ot_ip6 tmpip;
445#if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE) 519#if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE)
@@ -447,19 +521,19 @@ int parse_configfile(char *config_filename) {
447#endif 521#endif
448 int bound = 0; 522 int bound = 0;
449 523
450 accesslist_filehandle = fopen(config_filename, "r"); 524 config_file_handle = fopen(config_filename, "r");
451 525
452 if (accesslist_filehandle == NULL) { 526 if (config_file_handle == NULL) {
453 fprintf(stderr, "Warning: Can't open config file: %s.", config_filename); 527 fprintf(stderr, "Warning: Can't open config file: %s.", config_filename);
454 return 0; 528 return 0;
455 } 529 }
456 530
457 while (fgets(inbuf, sizeof(inbuf), accesslist_filehandle)) { 531 while (fgets(inbuf, sizeof(inbuf), config_file_handle)) {
458 char *p = inbuf; 532 char *p = inbuf, *end;
459 size_t strl; 533 uint16_t tmpport = 6969;
460 534
461 /* Skip white spaces */ 535 /* Skip white spaces */
462 while (isspace(*p)) 536 while (isspace((unsigned char)*p))
463 ++p; 537 ++p;
464 538
465 /* Ignore comments and empty lines */ 539 /* Ignore comments and empty lines */
@@ -467,87 +541,98 @@ int parse_configfile(char *config_filename) {
467 continue; 541 continue;
468 542
469 /* consume trailing new lines and spaces */ 543 /* consume trailing new lines and spaces */
470 strl = strlen(p); 544 end = p + strlen(p);
471 while (strl && isspace(p[strl - 1])) 545 while (end > p && isspace((unsigned char)end[-1]))
472 p[--strl] = 0; 546 *--end = 0;
473 547
474 /* Scan for commands */ 548 /* Scan for commands */
475 if (!byte_diff(p, 15, "tracker.rootdir") && isspace(p[15])) { 549 switch (parse_config_key(&p)) {
476 set_config_option(&g_serverdir, p + 16); 550 case CONFIG_TRACKER_ROOTDIR:
477 } else if (!byte_diff(p, 12, "tracker.user") && isspace(p[12])) { 551 set_config_option(&g_serverdir, p);
478 set_config_option(&g_serveruser, p + 13); 552 break;
479 } else if (!byte_diff(p, 14, "listen.tcp_udp") && isspace(p[14])) { 553 case CONFIG_TRACKER_USER:
480 uint16_t tmpport = 6969; 554 set_config_option(&g_serveruser, p);
481 if (!scan_ip6_port(p + 15, tmpip, &tmpport)) 555 break;
482 goto parse_error; 556 case CONFIG_LISTEN_TCP_UDP:
483 ot_try_bind(tmpip, tmpport, FLAG_TCP); 557 if (!scan_ip6_port(p, tmpip, &tmpport))
484 ++bound; 558 goto parse_error;
485 ot_try_bind(tmpip, tmpport, FLAG_UDP); 559 ot_try_bind(tmpip, tmpport, FLAG_TCP);
486 ++bound; 560 ++bound;
487 } else if (!byte_diff(p, 10, "listen.tcp") && isspace(p[10])) { 561 ot_try_bind(tmpip, tmpport, FLAG_UDP);
488 uint16_t tmpport = 6969; 562 ++bound;
489 if (!scan_ip6_port(p + 11, tmpip, &tmpport)) 563 break;
490 goto parse_error; 564 case CONFIG_LISTEN_TCP:
491 ot_try_bind(tmpip, tmpport, FLAG_TCP); 565 if (!scan_ip6_port(p, tmpip, &tmpport))
492 ++bound; 566 goto parse_error;
493 } else if (!byte_diff(p, 10, "listen.udp") && isspace(p[10])) { 567 ot_try_bind(tmpip, tmpport, FLAG_TCP);
494 uint16_t tmpport = 6969; 568 ++bound;
495 if (!scan_ip6_port(p + 11, tmpip, &tmpport)) 569 break;
496 goto parse_error; 570 case CONFIG_LISTEN_UDP:
497 ot_try_bind(tmpip, tmpport, FLAG_UDP); 571 if (!scan_ip6_port(p, tmpip, &tmpport))
498 ++bound; 572 goto parse_error;
499 } else if (!byte_diff(p, 18, "listen.udp.workers") && isspace(p[18])) { 573 ot_try_bind(tmpip, tmpport, FLAG_UDP);
500 char *value = p + 18; 574 ++bound;
501 while (isspace(*value)) 575 case CONFIG_LISTEN_UDP_WORKERS:
502 ++value; 576 scan_uint(p, &g_udp_workers);
503 scan_uint(value, &g_udp_workers); 577 break;
504#ifdef WANT_ACCESSLIST_WHITE 578#ifdef WANT_ACCESSLIST_WHITE
505 } else if (!byte_diff(p, 16, "access.whitelist") && isspace(p[16])) { 579 case CONFIG_ACCESS_WHITELIST:
506 set_config_option(&g_accesslist_filename, p + 17); 580 set_config_option(&g_accesslist_filename, p);
581 break;
507#elif defined(WANT_ACCESSLIST_BLACK) 582#elif defined(WANT_ACCESSLIST_BLACK)
508 } else if (!byte_diff(p, 16, "access.blacklist") && isspace(p[16])) { 583 case CONFIG_ACCESS_BLACKLIST:
509 set_config_option(&g_accesslist_filename, p + 17); 584 set_config_option(&g_accesslist_filename, p);
585 break;
510#endif 586#endif
511#ifdef WANT_DYNAMIC_ACCESSLIST 587#ifdef WANT_DYNAMIC_ACCESSLIST
512 } else if (!byte_diff(p, 15, "access.fifo_add") && isspace(p[15])) { 588 case CONFIG_ACCESS_FIFO_ADD:
513 set_config_option(&g_accesslist_pipe_add, p + 16); 589 set_config_option(&g_accesslist_pipe_add, p);
514 } else if (!byte_diff(p, 18, "access.fifo_delete") && isspace(p[18])) { 590 break;
515 set_config_option(&g_accesslist_pipe_delete, p + 19); 591 case CONFIG_ACCESS_FIFO_DELETE:
592 set_config_option(&g_accesslist_pipe_delete, p);
593 break;
516#endif 594#endif
517#ifdef WANT_RESTRICT_STATS 595#ifdef WANT_RESTRICT_STATS
518 } else if (!byte_diff(p, 12, "access.stats") && isspace(p[12])) { 596 case CONFIG_ACCESS_STATS:
519 if (!scan_ip6_net(p + 13, &tmpnet)) 597 if (!scan_ip6_net(p, &tmpnet))
520 goto parse_error; 598 goto parse_error;
521 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT); 599 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT);
600 break;
522#endif 601#endif
523 } else if (!byte_diff(p, 17, "access.stats_path") && isspace(p[17])) { 602 case CONFIG_ACCESS_STATS_PATH:
524 set_config_option(&g_stats_path, p + 18); 603 set_config_option(&g_stats_path, p);
604 break;
525#ifdef WANT_IP_FROM_PROXY 605#ifdef WANT_IP_FROM_PROXY
526 } else if (!byte_diff(p, 12, "access.proxy") && isspace(p[12])) { 606 case CONFIG_ACCESS_PROXY:
527 if (!scan_ip6_net(p + 13, &tmpnet)) 607 if (!scan_ip6_net(p, &tmpnet))
528 goto parse_error; 608 goto parse_error;
529 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY); 609 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY);
610 break;
530#endif 611#endif
531 } else if (!byte_diff(p, 20, "tracker.redirect_url") && isspace(p[20])) { 612 case CONFIG_TRACKER_REDIRECT_URL:
532 set_config_option(&g_redirecturl, p + 21); 613 set_config_option(&g_redirecturl, p);
614 break;
533#ifdef WANT_SYNC_LIVE 615#ifdef WANT_SYNC_LIVE
534 } else if (!byte_diff(p, 24, "livesync.cluster.node_ip") && isspace(p[24])) { 616 case CONFIG_LIVESYNC_CLUSTER_NODE_IP:
535 if (!scan_ip6_net(p + 25, &tmpnet)) 617 if (!scan_ip6_net(p, &tmpnet))
536 goto parse_error; 618 goto parse_error;
537 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC); 619 accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC);
538 } else if (!byte_diff(p, 23, "livesync.cluster.listen") && isspace(p[23])) { 620 break;
539 uint16_t tmpport = LIVESYNC_PORT; 621 case CONFIG_LIVESYNC_CLUSTER_LISTEN:
540 if (!scan_ip6_port(p + 24, tmpip, &tmpport)) 622 tmpport = LIVESYNC_PORT;
541 goto parse_error; 623 if (!scan_ip6_port(p, tmpip, &tmpport))
542 livesync_bind_mcast(tmpip, tmpport); 624 goto parse_error;
625 livesync_bind_mcast(tmpip, tmpport);
626 break;
543#endif 627#endif
544 } else 628 default:
545 fprintf(stderr, "Unhandled line in config file: %s\n", inbuf); 629 fprintf(stderr, "Unhandled line in config file: %s\n", inbuf);
546 continue; 630 break;
547 parse_error: 631 parse_error:
548 fprintf(stderr, "Parse error in config file: %s\n", inbuf); 632 fprintf(stderr, "Parse error in config file: %s\n", inbuf);
633 }
549 } 634 }
550 fclose(accesslist_filehandle); 635 fclose(config_file_handle);
551 return bound; 636 return bound;
552} 637}
553 638