1 /*
2 * aprsc
3 *
4 * (c) Heikki Hannikainen, OH7LZB <hessu@hes.iki.fi>
5 *
6 * This program is licensed under the BSD license, which can be found
7 * in the file LICENSE.
8 *
9 */
10
11 /*
12 * config.c: configuration parsing, based on Tomi's code
13 */
14
15 #include <string.h>
16 #include <strings.h>
17 #include <stdio.h>
18 #include <sys/types.h>
19 #include <netdb.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <ctype.h>
23 #include <sys/resource.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <sys/stat.h>
27
28 #include "config.h"
29 #include "hmalloc.h"
30 #include "hlog.h"
31 #include "cfgfile.h"
32 #include "worker.h"
33 #include "filter.h"
34 #include "parse_qc.h"
35 #include "ssl.h"
36
37 char def_cfgfile[] = "aprsc.conf";
38 char def_webdir[] = "web";
39
40 char *cfgfile = def_cfgfile;
41 char *pidfile;
42 char *new_rundir;
43 char *rundir;
44 //char *new_webdir;
45 char *webdir = def_webdir;
46 char *chrootdir = NULL;
47 char *setuid_s = NULL;
48
49 int disallow_other_protocol_id = 1; /* drop packets with other Q protocol identifiers */
50 #define Q_PROTOCOL_ID_DEFAULT 'A' /* A for APRS-IS */
51 char q_protocol_id = Q_PROTOCOL_ID_DEFAULT;
52
53 char def_logname[] = "aprsc";
54 char *logname = def_logname; /* syslog entries use this program name */
55
56 char *serverid;
57 int serverid_len;
58 char *passcode;
59 char *myemail;
60 char *myadmin;
61 char *fake_version;
62 char *new_serverid;
63 char *new_passcode;
64 char *new_myemail;
65 char *new_myadmin;
66 char *new_fake_version;
67
68 char **disallow_srccall_glob, **new_disallow_srccall_glob;
69 char **disallow_login_glob, **new_disallow_login_glob;
70
71 int listen_low_ports = 0; /* do we have any < 1024 ports set? need POSIX capabilities? */
72
73 struct sockaddr_in uplink_bind_v4;
74 socklen_t uplink_bind_v4_len = 0;
75 struct sockaddr_in6 uplink_bind_v6;
76 socklen_t uplink_bind_v6_len = 0;
77
78 struct uplink_config_t *uplink_config_install; /* uplink config waiting to be installed by uplink thread */
79 int uplink_config_updated = 0;
80 struct uplink_config_t *new_uplink_config; /* uplink config being generated from config file */
81
82 struct peerip_config_t *peerip_config;
83 struct peerip_config_t *new_peerip_config;
84
85 struct http_config_t *http_config = NULL;
86 struct http_config_t *new_http_config = NULL;
87 char http_bind_default[] = "0.0.0.0";
88 char *http_bind = http_bind_default; /* http address string to listen on */
89 int http_port = 14501;
90 char *new_http_bind;
91 int new_http_port;
92 char *http_bind_upload = NULL; /* http address string to listen on */
93 int http_port_upload = 8080;
94 char *new_http_bind_upload;
95 int new_http_port_upload;
96
97 char *http_status_options = NULL;
98 char *new_http_status_options = NULL;
99
100 int fork_a_daemon; /* fork a daemon */
101
102 int dump_splay; /* print splay tree information */
103
104 int workers_configured = 2; /* number of workers to run */
105
106 int expiry_interval = 30;
107 int stats_interval = 1 * 60;
108
109 int lastposition_storetime = 24*60*60; /* how long the last position packet of each station is stored */
110 int dupefilter_storetime = 30; /* how long to store information required for dupe filtering */
111
112 int heard_list_storetime = 3*60*60; /* how long to store "client X has heard station Y" information,
113 * to support text message routing */
114 int courtesy_list_storetime = 30*60; /* how long to store "client X has been given MSG from station Y" information,
115 * to support courtesy position transmission after text message routing */
116
117 int pbuf_global_expiration = 4*60; /* 4 minutes */ /* 10 sec for load testing */
118 int pbuf_global_dupe_expiration = 4*60; /* 4 minutes */ /* 10 sec for load testing */
119
120 int upstream_timeout = 30; /* after N seconds of no input from an upstream, disconnect */
121 int client_timeout = 48*60*60; /* after N seconds of no input from a client, disconnect */
122 int client_login_timeout = 30; /* after N seconds of no login command from a client, disconnect */
123
124 int disallow_unverified = 1; /* disallow packets from unverified clients */
125 int quirks_mode = 0; /* enable quirks mode for all clients by default */
126
127 int maxclients = 500; /* maximum number of clients */
128
129 /* These two are not currently used. The fixed defines are in worker.h,
130 * OBUF_SIZE and IBUF_SIZE.
131 */
132 int ibuf_size = 8*1024; /* size of input buffer for clients */
133 int obuf_size = 8*1024; /* size of output buffer for clients */
134
135 int new_fileno_limit;
136
137 int verbose;
138
139
140 /* address:port pairs being listened */
141 struct listen_config_t *listen_config = NULL;
142 struct listen_config_t *listen_config_new = NULL;
143
144 int do_httpstatus(char *new, int argc, char **argv);
145 int do_httpupload(char *new, int argc, char **argv);
146 int do_listen(struct listen_config_t **lq, int argc, char **argv);
147 int do_interval(int *dest, int argc, char **argv);
148 int do_peergroup(struct peerip_config_t **lq, int argc, char **argv);
149 int do_uplink(struct uplink_config_t **lq, int argc, char **argv);
150 int do_uplinkbind(void *new, int argc, char **argv);
151 int do_logrotate(int *dest, int argc, char **argv);
152
153 /*
154 * Configuration file commands
155 */
156
157 #define _CFUNC_ (int (*)(void *dest, int argc, char **argv))
158
159 static struct cfgcmd cfg_cmds[] = {
160 { "rundir", _CFUNC_ do_string, &new_rundir },
161 { "logrotate", _CFUNC_ do_logrotate, &log_rotate_size },
162 { "serverid", _CFUNC_ do_string, &new_serverid },
163 { "passcode", _CFUNC_ do_string, &new_passcode },
164 { "myemail", _CFUNC_ do_string, &new_myemail },
165 { "myadmin", _CFUNC_ do_string, &new_myadmin },
166 { "workerthreads", _CFUNC_ do_int, &workers_configured },
167 { "statsinterval", _CFUNC_ do_interval, &stats_interval },
168 { "expiryinterval", _CFUNC_ do_interval, &expiry_interval },
169 { "lastpositioncache", _CFUNC_ do_interval, &lastposition_storetime },
170 { "upstreamtimeout", _CFUNC_ do_interval, &upstream_timeout },
171 { "clienttimeout", _CFUNC_ do_interval, &client_timeout },
172 { "logintimeout", _CFUNC_ do_interval, &client_login_timeout },
173 { "filelimit", _CFUNC_ do_int, &new_fileno_limit },
174 { "maxclients", _CFUNC_ do_int, &maxclients },
175 { "ibufsize", _CFUNC_ do_int, &ibuf_size },
176 { "obufsize", _CFUNC_ do_int, &obuf_size },
177 { "httpstatus", _CFUNC_ do_httpstatus, &new_http_bind },
178 { "httpupload", _CFUNC_ do_httpupload, &new_http_bind_upload },
179 { "httpstatusoptions", _CFUNC_ do_string, &new_http_status_options },
180 { "listen", _CFUNC_ do_listen, &listen_config_new },
181 { "uplinkbind", _CFUNC_ do_uplinkbind, NULL },
182 { "uplink", _CFUNC_ do_uplink, &new_uplink_config },
183 { "peergroup", _CFUNC_ do_peergroup, &new_peerip_config },
184 { "q_protocol_id", _CFUNC_ do_char, &q_protocol_id },
185 { "disallow_other_q_protocols",_CFUNC_ do_boolean, &disallow_other_protocol_id },
186 { "disallow_unverified",_CFUNC_ do_boolean, &disallow_unverified },
187 { "quirks_mode", _CFUNC_ do_boolean, &quirks_mode },
188 { "fake_version", _CFUNC_ do_string, &new_fake_version },
189 { "disallowlogincall", _CFUNC_ do_string_array, &new_disallow_login_glob },
190 { "disallowsourcecall", _CFUNC_ do_string_array, &new_disallow_srccall_glob },
191 { NULL, NULL, NULL }
192 };
193
194 /*
195 * Parse a command line to argv, not honoring quotes or such
196 */
197
parse_args_noshell(char * argv[],char * cmd)198 int parse_args_noshell(char *argv[],char *cmd)
199 {
200 int ct = 0;
201
202 while (ct < 255)
203 {
204 while (*cmd && isspace((int)*cmd))
205 cmd++;
206 if (*cmd == 0)
207 break;
208 argv[ct++] = cmd;
209 while (*cmd && !isspace((int)*cmd))
210 cmd++;
211 if (*cmd)
212 *cmd++ = 0;
213 }
214 argv[ct] = NULL;
215 return ct;
216 }
217
218 /*
219 * Sanitize an user-entered ASCII string to not contain control chars
220 */
221
sanitize_ascii_string(char * s)222 void sanitize_ascii_string(char *s)
223 {
224 unsigned char *p;
225
226 for (p = (unsigned char *)s; *p; p++) {
227 if (iscntrl(*p) || !(isascii(*p)))
228 *p = '_';
229 }
230 }
231
232
233 /*
234 * Free a listen config tree
235 */
236
free_listen_config(struct listen_config_t ** lc)237 void free_listen_config(struct listen_config_t **lc)
238 {
239 struct listen_config_t *this;
240 int i;
241
242 while (*lc) {
243 this = *lc;
244 *lc = this->next;
245 hfree((void*)this->name);
246 hfree((void*)this->host);
247 hfree((void*)this->proto);
248 for (i = 0; i < (sizeof(this->filters)/sizeof(this->filters[0])); ++i)
249 if (this->filters[i])
250 hfree((void*)this->filters[i]);
251 freeaddrinfo(this->ai);
252 if (this->acl)
253 acl_free(this->acl);
254 if (this->keyfile)
255 hfree((void *)this->keyfile);
256 if (this->certfile)
257 hfree((void *)this->certfile);
258 if (this->cafile)
259 hfree((void *)this->cafile);
260 if (this->crlfile)
261 hfree((void *)this->crlfile);
262 hfree(this);
263 }
264 }
265
find_listen_config_id(struct listen_config_t * l,int id)266 struct listen_config_t *find_listen_config_id(struct listen_config_t *l, int id)
267 {
268 while (l) {
269 if (l->id == id)
270 return l;
271 l = l->next;
272 }
273
274 return NULL;
275 }
276
find_listen_config(struct listen_config_t * l,const char * proto,const char * host,int portnum)277 static struct listen_config_t *find_listen_config(struct listen_config_t *l,
278 const char *proto, const char *host, int portnum)
279 {
280 while (l) {
281 if (l->portnum == portnum
282 && strcmp(l->host, host) == 0
283 && strcmp(l->proto, proto) == 0)
284 return l;
285
286 l = l->next;
287 }
288
289 return NULL;
290 }
291
292
293 /*
294 * Free a peer-ip config tree
295 */
296
free_peerip_config(struct peerip_config_t ** lc)297 void free_peerip_config(struct peerip_config_t **lc)
298 {
299 struct peerip_config_t *this;
300
301 while (*lc) {
302 this = *lc;
303 *lc = this->next;
304 hfree((void*)this->name);
305 hfree((void*)this->host);
306 hfree((void*)this->serverid);
307 freeaddrinfo(this->ai);
308 hfree(this);
309 }
310 }
311
312 /*
313 * Free a http config tree
314 */
315
free_http_config(struct http_config_t ** lc)316 void free_http_config(struct http_config_t **lc)
317 {
318 struct http_config_t *this;
319
320 while (*lc) {
321 this = *lc;
322 *lc = this->next;
323 hfree((void*)this->host);
324 hfree(this);
325 }
326 }
327
328 /*
329 * Free a uplink config tree
330 */
331
free_uplink_config(struct uplink_config_t ** lc)332 void free_uplink_config(struct uplink_config_t **lc)
333 {
334 struct uplink_config_t *this;
335
336 while (*lc) {
337 this = *lc;
338 *lc = this->next;
339 this->next = (void *)1; /* poison the list, in case of referencing freed entries */
340 this->prevp = (void *)1;
341 hfree((void*)this->name);
342 hfree((void*)this->proto);
343 hfree((void*)this->host);
344 hfree((void*)this->port);
345 hfree((void*)this->keyfile);
346 hfree((void*)this->certfile);
347 hfree((void*)this->cafile);
348 hfree((void*)this->crlfile);
349 #ifdef USE_SSL
350 if (this->ssl)
351 ssl_free(this->ssl);
352 #endif
353 hfree(this);
354 }
355 }
356
357 /*
358 * Match two addrinfo chains, return 1 if there are matching
359 * addresses in the chains
360 */
361
ai_comp(struct addrinfo * a,struct addrinfo * b)362 int ai_comp(struct addrinfo *a, struct addrinfo *b)
363 {
364 struct addrinfo *ap, *bp;
365 union sockaddr_u *au, *bu;
366
367 for (ap = a; ap; ap = ap->ai_next) {
368 for (bp = b; bp; bp = bp->ai_next) {
369 if (ap->ai_family != bp->ai_family)
370 continue;
371 if (ap->ai_addrlen != bp->ai_addrlen)
372 continue;
373
374 au = (union sockaddr_u *)ap->ai_addr;
375 bu = (union sockaddr_u *)bp->ai_addr;
376
377 if (ap->ai_family == AF_INET) {
378 if (memcmp(&au->si.sin_addr, &bu->si.sin_addr, sizeof(au->si.sin_addr)) != 0)
379 continue;
380 if (au->si.sin_port != bu->si.sin_port)
381 continue;
382
383 return 1; // Oops, there is a match
384 }
385
386 if (ap->ai_family == AF_INET6) {
387 if (memcmp(&au->si6.sin6_addr, &bu->si6.sin6_addr, sizeof(au->si6.sin6_addr)) != 0)
388 continue;
389 if (au->si6.sin6_port != bu->si6.sin6_port)
390 continue;
391
392 return 1; // Oops, there is a match
393 }
394 }
395 }
396
397 return 0;
398 }
399
400 /*
401 * parse an interval specification
402 */
403
parse_interval(char * origs)404 time_t parse_interval(char *origs)
405 {
406 time_t t = 0;
407 int i;
408 char *s, *np, *p, c;
409
410 np = p = s = hstrdup(origs);
411
412 while (*p) {
413 if (!isdigit((int)*p)) {
414 c = tolower(*p);
415 *p = '\0';
416 i = atoi(np);
417 if (c == 's')
418 t += i;
419 else if (c == 'm')
420 t += 60 * i;
421 else if (c == 'h')
422 t += 60 * 60 * i;
423 else if (c == 'd')
424 t += 24 * 60 * 60 * i;
425 np = p + 1;
426 }
427 p++;
428 }
429
430 if (*np)
431 t += atoi(np);
432
433 hfree(s);
434 return t;
435 }
436
437
438 /*
439 * Parse an interval configuration entry
440 */
441
do_interval(int * dest,int argc,char ** argv)442 int do_interval(int *dest, int argc, char **argv)
443 {
444 if (argc < 2)
445 return -1;
446
447 *dest = parse_interval(argv[1]);
448 return 0;
449 }
450
451 /*
452 * Parse a peer definition directive
453 *
454 * "keyword" <token?> [udp|sctp] <localhost>:<localport> <remotehost1>:<remoteport> <remote2> ...
455 *
456 */
457
458
parse_hostport(char * s,char ** host_s,char ** port_s)459 int parse_hostport(char *s, char **host_s, char **port_s)
460 {
461 char *colon;
462 char *bracket;
463
464 colon = strrchr(s, ':');
465 if (colon == NULL)
466 return -1;
467
468 *colon = 0;
469
470 *host_s = s;
471 *port_s = colon+1;
472
473 if (**host_s == '[') {
474 bracket = strrchr(*host_s, ']');
475 if (!bracket)
476 return -1;
477
478 *bracket = 0;
479 *host_s = *host_s + 1;
480 }
481
482 return 0;
483 }
484
do_peergroup(struct peerip_config_t ** lq,int argc,char ** argv)485 int do_peergroup(struct peerip_config_t **lq, int argc, char **argv)
486 {
487 int localport, port, i, d;
488 struct peerip_config_t *pe;
489 struct listen_config_t *li;
490 struct addrinfo req, *my_ai, *ai, *a;
491 char *peerid = NULL;
492 char *fullhost, *host_s, *port_s;
493 int af;
494
495 ai = my_ai = a = NULL;
496
497 if (argc < 4)
498 return -1;
499
500 memset(&req, 0, sizeof(req));
501 req.ai_family = 0;
502 req.ai_socktype = SOCK_STREAM;
503 req.ai_protocol = IPPROTO_TCP;
504 req.ai_flags = 0;
505 my_ai = NULL;
506
507 // Only UDP and SCTP are acceptable for peergroups
508 if (strcasecmp(argv[2], "udp") == 0) {
509 req.ai_socktype = SOCK_DGRAM;
510 req.ai_protocol = IPPROTO_UDP;
511 #ifdef USE_SCTP
512 } else if (strcasecmp(argv[2], "sctp") == 0) {
513 req.ai_socktype = SOCK_STREAM;
514 req.ai_protocol = IPPROTO_SCTP;
515 #endif
516 } else {
517 hlog(LOG_ERR, "PeerGroup: Unsupported protocol '%s'", argv[2]);
518 return -2;
519 }
520
521 fullhost = hstrdup(argv[3]);
522
523 if (parse_hostport(argv[3], &host_s, &port_s)) {
524 hlog(LOG_ERR, "PeerGroup: Invalid local host:port specification '%s'", fullhost);
525 hfree(fullhost);
526 return -2;
527 }
528
529 localport = atoi(port_s);
530 i = getaddrinfo(host_s, port_s, &req, &my_ai);
531 if (i != 0) {
532 hlog(LOG_ERR, "PeerGroup: address parsing or hostname lookup failure for %s: %s", fullhost, gai_strerror(i));
533 hfree(fullhost);
534 return -2;
535 }
536
537 d = 0;
538 for (a = my_ai; (a); a = a->ai_next, ++d);
539 if (d != 1) {
540 hlog(LOG_ERR, "PeerGroup: address parsing for local address %s returned %d addresses - can only have one", fullhost, d);
541 hfree(fullhost);
542 freeaddrinfo(my_ai);
543 return -2;
544 }
545
546 af = my_ai->ai_family;
547
548 //hlog(LOG_DEBUG, "PeerGroup: configuring with local address %s (local port %d)", fullhost, localport);
549
550 /* Configure a listener */
551 li = hmalloc(sizeof(*li));
552 memset(li, 0, sizeof(*li));
553 // coverity[dont_call] // squelch warning: not security sensitive use of random(): local id
554 li->id = random();
555 li->corepeer = 1;
556 li->name = hstrdup(argv[1]);
557 li->host = fullhost;
558 li->proto = hstrdup("udp");
559 li->portnum = localport;
560 li->client_flags = 0;
561 li->clients_max = 1;
562 li->ai = my_ai;
563 li->acl = NULL;
564 li->next = NULL;
565 li->prevp = NULL;
566
567 /* there are no filters between peers */
568 for (i = 0; i < LISTEN_MAX_FILTERS; i++)
569 li->filters[i] = NULL;
570
571 /* put in the list */
572 li->next = listen_config_new;
573 if (li->next)
574 li->next->prevp = &li->next;
575 listen_config_new = li;
576
577 fullhost = NULL;
578
579 // TODO: when returning, should free the whole li tree
580 for (i = 4; i < argc; i++) {
581 //hlog(LOG_DEBUG, "PeerGroup: configuring peer %s", argv[i]);
582
583 peerid = hstrdup(argv[i]);
584 i++;
585
586 if (i >= argc) {
587 hlog(LOG_ERR, "PeerGroup: No host:port specified for peer ServerID '%s'", peerid);
588 goto err;
589 }
590
591 /* Parse address */
592 fullhost = hstrdup(argv[i]);
593 if (parse_hostport(argv[i], &host_s, &port_s)) {
594 hlog(LOG_ERR, "PeerGroup: Invalid remote host:port specification '%s'", fullhost);
595 goto err;
596 }
597
598 port = atoi(port_s);
599 if (port < 1 || port > 65535) {
600 hlog(LOG_ERR, "PeerGroup: Invalid port number '%s' for remote address '%s'", port_s, fullhost);
601 goto err;
602 }
603
604 ai = NULL;
605 d = getaddrinfo(host_s, port_s, &req, &ai);
606 if (d != 0) {
607 hlog(LOG_ERR, "PeerGroup: address parsing or hostname lookup failure for %s: %s", fullhost, gai_strerror(d));
608 goto err;
609 }
610
611 /* we can only take one address per peer at this point, SCTP multihoming ignored */
612 d = 0;
613 for (a = ai; (a); a = a->ai_next, ++d);
614 if (d != 1) {
615 hlog(LOG_ERR, "PeerGroup: address parsing for remote %s returned %d addresses - can only have one", fullhost, d);
616 goto err;
617 }
618
619 if (ai->ai_family != af) {
620 hlog(LOG_ERR, "PeerGroup: remote address %s has different address family than the local address - mixing IPv4 and IPv6, are we?", fullhost);
621 goto err;
622 }
623
624 /* Check that the address is not mine (loop!), and that we don't have
625 * it configured already (dupes!). My address is ignored quietly, allowing symmetric
626 * peer configs on all nodes.
627 */
628
629 if (ai_comp(ai, my_ai)) {
630 //hlog(LOG_DEBUG, "PeerGroup: Ignoring %s - it's me, my local address", fullhost);
631 hfree(fullhost);
632 fullhost = NULL;
633 hfree(peerid);
634 freeaddrinfo(ai);
635 ai = NULL;
636 continue;
637 }
638
639 for (pe = *lq; (pe); pe = pe->next) {
640 if (ai_comp(ai, pe->ai)) {
641 hlog(LOG_ERR, "PeerGroup: remote address %s is configured as a peer twice, would cause duplicate transmission!", fullhost);
642 goto err;
643 }
644 }
645
646 hfree(fullhost);
647 fullhost = NULL;
648
649 /* Ok, enough checks. Go for it! */
650 pe = hmalloc(sizeof(*pe));
651 memset(pe, 0, sizeof(*pe));
652 pe->name = hstrdup(host_s);
653 pe->host = hstrdup(host_s);
654 pe->serverid = peerid;
655 peerid = NULL;
656 pe->af = af;
657 pe->local_port = localport;
658 pe->remote_port = port;
659 pe->client_flags = 0; // ???
660 pe->ai = ai;
661
662 /* put in the list */
663 pe->next = *lq;
664 if (pe->next)
665 pe->next->prevp = &pe->next;
666 *lq = pe;
667 }
668
669 return 0;
670 err:
671 if (fullhost)
672 hfree(fullhost);
673 if (peerid)
674 hfree(peerid);
675 if (ai)
676 freeaddrinfo(ai);
677
678 return -2;
679 }
680
681 /*
682 * Uplink ssl string option handler
683 */
684
config_uplink_ssl(char ** argv,int argc,int * i,const char * key,char ** dst)685 int config_uplink_ssl(char **argv, int argc, int *i, const char *key, char **dst)
686 {
687 #ifdef USE_SSL
688 (*i)++;
689 if (*i >= argc) {
690 hlog(LOG_ERR, "Uplink: '%s' argument is missing the file parameter for '%s'", key, argv[1]);
691 return -2;
692 }
693
694 if (*dst) {
695 hlog(LOG_ERR, "Uplink: second '%s' not allowed for '%s'", key, argv[1]);
696 return -2;
697 }
698
699 *dst = hstrdup(argv[*i]);
700 return 0;
701 #else
702 hlog(LOG_ERR, "Uplink: '%s' not available for '%s' - server not built with OpenSSL", key, argv[1]);
703 return -2;
704 #endif
705 }
706
707 /*
708 * Parse a uplink definition directive
709 *
710 * uplink <label> <token> {tcp|udp|sctp} <hostname> <portnum> [<filter> [..<more_filters>]]
711 *
712 */
713
do_uplink(struct uplink_config_t ** lq,int argc,char ** argv)714 int do_uplink(struct uplink_config_t **lq, int argc, char **argv)
715 {
716 struct uplink_config_t *l;
717 int port;
718 int clflags = CLFLAGS_UPLINKPORT;
719 int i;
720
721 if (argc < 5)
722 return -1;
723
724 /* argv[1] is name label for this uplink */
725
726 if (strcasecmp(argv[2], "ro")==0) {
727 clflags |= CLFLAGS_PORT_RO;
728 } else if (strcasecmp(argv[2], "multiro")==0) {
729 clflags |= CLFLAGS_PORT_RO|CLFLAGS_UPLINKMULTI;
730 } else if (strcasecmp(argv[2], "full") == 0) {
731 /* regular */
732 } else {
733 hlog(LOG_ERR, "Uplink: Unsupported uplink type '%s'", argv[2]);
734 return -2;
735 }
736
737 if (strcasecmp(argv[3], "tcp") == 0) {
738 // well, do nothing for now.
739 } else if (strcasecmp(argv[3], "udp") == 0) {
740 #ifdef USE_SCTP
741 } else if (strcasecmp(argv[3], "sctp") == 0) {
742 #endif
743 } else {
744 hlog(LOG_ERR, "Uplink: Unsupported protocol '%s'", argv[3]);
745 return -2;
746 }
747
748 port = atoi(argv[5]);
749 if (port < 1 || port > 65535) {
750 hlog(LOG_ERR, "Uplink: Invalid port number '%s'", argv[5]);
751 return -2;
752 }
753
754 /* For uplinks, we don't really wish to do a DNS lookup at this point
755 * - we do it when connecting, the address might have changed at that
756 * point. Also, the lookup might slow up the startup considerably if
757 * servers time out. And if the network comes up later than aprsc
758 * after a power failure, we must not ignore the uplink configs now.
759 */
760
761 l = hmalloc(sizeof(*l));
762 memset(l, 0, sizeof(*l));
763 l->name = hstrdup(argv[1]);
764 l->proto = hstrdup(argv[3]);
765 l->host = hstrdup(argv[4]);
766 l->port = hstrdup(argv[5]);
767 l->client_flags = clflags;
768 l->state = UPLINK_ST_UNKNOWN;
769
770 for (i = 6; i < argc; i++) {
771 if (strcasecmp(argv[i], "sslkey") == 0) {
772 if (config_uplink_ssl(argv, argc, &i, "sslkey", (char **)&l->keyfile)) {
773 free_uplink_config(&l);
774 return -2;
775 }
776 } else if (strcasecmp(argv[i], "sslcert") == 0) {
777 if (config_uplink_ssl(argv, argc, &i, "sslcert", (char **)&l->certfile)) {
778 free_uplink_config(&l);
779 return -2;
780 }
781 } else if (strcasecmp(argv[i], "sslca") == 0) {
782 if (config_uplink_ssl(argv, argc, &i, "sslca", (char **)&l->cafile)) {
783 free_uplink_config(&l);
784 return -2;
785 }
786 } else if (strcasecmp(argv[i], "sslcrl") == 0) {
787 if (config_uplink_ssl(argv, argc, &i, "sslcrl", (char **)&l->crlfile)) {
788 free_uplink_config(&l);
789 return -2;
790 }
791 } else {
792 hlog(LOG_ERR, "Uplink %s: Invalid parameter '%s'", argv[1], argv[i]);
793 free_uplink_config(&l);
794 return -2;
795 }
796 }
797
798 /* put in the end of the list */
799 while (*lq)
800 lq = &(*lq)->next;
801
802 l->prevp = lq;
803 l->next = NULL;
804 *lq = l;
805
806 return 0;
807 }
808
809 /*
810 * Uplink source address binding configuration
811 */
812
do_uplinkbind(void * new,int argc,char ** argv)813 int do_uplinkbind(void *new, int argc, char **argv)
814 {
815 struct addrinfo req, *ai, *a;
816 int i, d;
817
818 if (argc < 2)
819 return -1;
820
821 memset(&req, 0, sizeof(req));
822 req.ai_family = 0;
823 req.ai_socktype = SOCK_STREAM;
824 req.ai_protocol = IPPROTO_TCP;
825 req.ai_flags = 0;
826
827 for (i = 1; i < argc; i++) {
828 hlog(LOG_DEBUG, "UplinkBind: looking up %s", argv[i]);
829
830 ai = NULL;
831 d = getaddrinfo(argv[i], "0", &req, &ai);
832 if (d != 0 || !(ai)) {
833 hlog(LOG_ERR, "UplinkBind: address parsing or hostname lookup failure for %s: %s", argv[i], gai_strerror(d));
834 return -2;
835 }
836
837 /* we can only take one address per peer at this point, SCTP multihoming ignored */
838 d = 0;
839 for (a = ai; (a); a = a->ai_next, ++d);
840 if (d != 1) {
841 hlog(LOG_ERR, "UplinkBind: address parsing for %s returned %d addresses - can only have one", argv[i], d);
842 freeaddrinfo(ai);
843 return -2;
844 }
845
846 if (ai->ai_family == AF_INET) {
847 memcpy(&uplink_bind_v4, ai->ai_addr, ai->ai_addrlen);
848 uplink_bind_v4_len = ai->ai_addrlen;
849 } else if (ai->ai_family == AF_INET6) {
850 memcpy(&uplink_bind_v6, ai->ai_addr, ai->ai_addrlen);
851 uplink_bind_v6_len = ai->ai_addrlen;
852 } else {
853 hlog(LOG_ERR, "UplinkBind: address %s has unknown address family %d", argv[i], ai->ai_family);
854 freeaddrinfo(ai);
855 return -2;
856 }
857
858 freeaddrinfo(ai);
859 }
860
861 return 0;
862 }
863
864
865 /*
866 * Parse a Listen directive
867 *
868 * listen <label> <token> [tcp|udp|sctp] <hostname> <portnum> [<filter> [..<more_filters>]]
869 *
870 */
871
config_parse_listen_filter(struct listen_config_t * l,char * filt_string,char * portname)872 int config_parse_listen_filter(struct listen_config_t *l, char *filt_string, char *portname)
873 {
874 int argc;
875 char *argv[256];
876 int i;
877
878 argc = parse_args_noshell(argv, filt_string);
879 if (argc == 0) {
880 hlog(LOG_ERR, "Listen: Bad filter definition for '%s': '%s' - no filter arguments found",
881 portname, filt_string);
882 return -1;
883 }
884
885 if (argc > LISTEN_MAX_FILTERS) {
886 hlog(LOG_ERR, "Listen: Bad filter definition for '%s': '%s' - too many (%d) filter arguments found, max %d",
887 portname, filt_string, argc, LISTEN_MAX_FILTERS);
888 return -1;
889 }
890
891 for (i = 0; i < argc && i < LISTEN_MAX_FILTERS; i++) {
892 if (filter_parse(NULL, argv[i], 0) < 0) {
893 hlog(LOG_ERR, "Listen: Bad filter definition for '%s': '%s' - filter parsing failed",
894 portname, argv[i]);
895 return -1;
896 }
897 l->filters[i] = hstrdup(argv[i]);
898 }
899
900 return 0;
901 }
902
config_listen_ssl(char ** argv,int argc,int * i,const char * key,char ** dst)903 int config_listen_ssl(char **argv, int argc, int *i, const char *key, char **dst)
904 {
905 #ifdef USE_SSL
906 (*i)++;
907 if (*i >= argc) {
908 hlog(LOG_ERR, "Listen: '%s' argument is missing the file parameter for '%s'", key, argv[1]);
909 return -2;
910 }
911
912 if (*dst) {
913 hlog(LOG_ERR, "Listen: second '%s' not allowed for '%s'", key, argv[1]);
914 return -2;
915 }
916
917 *dst = hstrdup(argv[*i]);
918 return 0;
919 #else
920 hlog(LOG_ERR, "Listen: '%s' not available for '%s' - server not built with OpenSSL", key, argv[1]);
921 return -2;
922 #endif
923 }
924
do_listen(struct listen_config_t ** lq,int argc,char ** argv)925 int do_listen(struct listen_config_t **lq, int argc, char **argv)
926 {
927 int i, port;
928 struct listen_config_t *l;
929 struct addrinfo req, *ai;
930 /* default parameters for a listener */
931 int clflags = CLFLAGS_INPORT;
932 int clients_max = 200;
933 char *proto;
934
935 memset(&req, 0, sizeof(req));
936 req.ai_family = 0;
937 req.ai_socktype = SOCK_STREAM;
938 req.ai_protocol = IPPROTO_TCP;
939 req.ai_flags = 0;
940 ai = NULL;
941
942 if (argc < 6)
943 return -1;
944
945 if (strcasecmp(argv[2], "userfilter") == 0) {
946 clflags |= CLFLAGS_USERFILTEROK;
947 clflags |= CLFLAGS_IGATE;
948 } else if (strcasecmp(argv[2], "igate") == 0) {
949 clflags |= CLFLAGS_USERFILTEROK;
950 clflags |= CLFLAGS_IGATE;
951 } else if (strcasecmp(argv[2], "fullfeed") == 0) {
952 clflags |= CLFLAGS_FULLFEED;
953 } else if (strcasecmp(argv[2], "dupefeed") == 0) {
954 clflags |= CLFLAGS_DUPEFEED;
955 } else if (strcasecmp(argv[2], "clientonly") == 0) {
956 clflags |= CLFLAGS_CLIENTONLY;
957 clflags |= CLFLAGS_USERFILTEROK;
958 clflags |= CLFLAGS_IGATE;
959 } else if (strcasecmp(argv[2], "udpsubmit") == 0) {
960 clflags |= CLFLAGS_CLIENTONLY;
961 clflags |= CLFLAGS_UDPSUBMIT;
962 clients_max = 1;
963 } else {
964 hlog(LOG_ERR, "Listen: unknown port type: %s", argv[2]);
965 }
966
967 proto = argv[3];
968 if (strcasecmp(proto, "tcp") == 0) {
969 /* well, do nothing for now. */
970 } else if (strcasecmp(proto, "udp") == 0) {
971 req.ai_socktype = SOCK_DGRAM;
972 req.ai_protocol = IPPROTO_UDP;
973 #ifdef USE_SCTP
974 } else if (strcasecmp(proto, "sctp") == 0) {
975 req.ai_socktype = SOCK_STREAM;
976 req.ai_protocol = IPPROTO_SCTP;
977 #endif
978 } else {
979 hlog(LOG_ERR, "Listen: Unsupported protocol '%s'\n", proto);
980 return -2;
981 }
982
983 if ((clflags & CLFLAGS_UDPSUBMIT) && req.ai_protocol != IPPROTO_UDP) {
984 hlog(LOG_ERR, "Listen: Invalid protocol '%s' for udpsubmit port - only UDP is supported\n", proto);
985 return -2;
986 }
987
988 port = atoi(argv[5]);
989 if (port < 1 || port > 65535) {
990 hlog(LOG_ERR, "Listen: Invalid port number '%s'\n", argv[5]);
991 return -2;
992 }
993
994 i = getaddrinfo(argv[4], argv[5], &req, &ai);
995 if (i != 0) {
996 hlog(LOG_ERR, "Listen: address parse failure of '%s' '%s': %s", argv[4], argv[5], gai_strerror(i));
997 return -2;
998 }
999
1000 l = hmalloc(sizeof(*l));
1001 memset(l, 0, sizeof(*l));
1002 l->name = hstrdup(argv[1]);
1003 l->host = hstrdup(argv[4]);
1004 l->proto = hstrdup(proto);
1005 l->portnum = port;
1006 l->client_flags = clflags;
1007 l->clients_max = clients_max;
1008 l->ai = ai;
1009 l->acl = NULL;
1010 l->next = NULL;
1011 l->prevp = NULL;
1012
1013 /* by default, no filters */
1014 for (i = 0; i < LISTEN_MAX_FILTERS; i++)
1015 l->filters[i] = NULL;
1016
1017 /* parse rest of arguments */
1018 i = 6;
1019 while (i < argc) {
1020 if (strcasecmp(argv[i], "filter") == 0) {
1021 /* set a filter for the clients */
1022 i++;
1023 if (i >= argc) {
1024 hlog(LOG_ERR, "Listen: 'filter' argument is missing the filter parameter for '%s'", argv[1]);
1025 free_listen_config(&l);
1026 return -2;
1027 }
1028
1029 if (clflags & (CLFLAGS_FULLFEED|CLFLAGS_UDPSUBMIT|CLFLAGS_DUPEFEED)) {
1030 hlog(LOG_ERR, "Listen: '%s': 'filter' argument is not valid for port type of '%s'", argv[1], argv[2]);
1031 free_listen_config(&l);
1032 return -2;
1033 }
1034
1035 if (config_parse_listen_filter(l, argv[i], argv[1])) {
1036 free_listen_config(&l);
1037 return -2;
1038 }
1039 } else if (strcasecmp(argv[i], "maxclients") == 0) {
1040 /* Limit amount of clients */
1041 i++;
1042 if (i >= argc) {
1043 hlog(LOG_ERR, "Listen: 'maxclients' argument is missing the numeric max clients limit for '%s'", argv[1]);
1044 free_listen_config(&l);
1045 return -2;
1046 }
1047 l->clients_max = atoi(argv[i]);
1048 } else if (strcasecmp(argv[i], "acl") == 0) {
1049 /* Access list */
1050 i++;
1051 if (i >= argc) {
1052 hlog(LOG_ERR, "Listen: 'acl' argument is missing the acl parameter for '%s'", argv[1]);
1053 free_listen_config(&l);
1054 return -2;
1055 }
1056
1057 if (l->acl) {
1058 hlog(LOG_ERR, "Listen: second 'acl' not allowed for '%s'", argv[1]);
1059 free_listen_config(&l);
1060 return -2;
1061 }
1062
1063 l->acl = acl_load(argv[i]);
1064 if (!l->acl) {
1065 free_listen_config(&l);
1066 return -2;
1067 }
1068
1069
1070 } else if (strcasecmp(argv[i], "sslkey") == 0) {
1071 if (config_listen_ssl(argv, argc, &i, "sslkey", (char **)&l->keyfile)) {
1072 free_listen_config(&l);
1073 return -2;
1074 }
1075 } else if (strcasecmp(argv[i], "sslcert") == 0) {
1076 if (config_listen_ssl(argv, argc, &i, "sslcert", (char **)&l->certfile)) {
1077 free_listen_config(&l);
1078 return -2;
1079 }
1080 } else if (strcasecmp(argv[i], "sslca") == 0) {
1081 if (config_listen_ssl(argv, argc, &i, "sslca", (char **)&l->cafile)) {
1082 free_listen_config(&l);
1083 return -2;
1084 }
1085 } else if (strcasecmp(argv[i], "sslcrl") == 0) {
1086 if (config_listen_ssl(argv, argc, &i, "sslcrl", (char **)&l->crlfile)) {
1087 free_listen_config(&l);
1088 return -2;
1089 }
1090 } else if (strcasecmp(argv[i], "hidden") == 0) {
1091 /* Hide the listener from status view */
1092 l->hidden = 1;
1093 } else {
1094 hlog(LOG_ERR, "Listen: Unknown argument '%s' for '%s'", argv[i], argv[1]);
1095 free_listen_config(&l);
1096 return -2;
1097 }
1098 i++;
1099 }
1100
1101 /* SSL requires both a cert and a key */
1102 if ((l->certfile && !l->keyfile) || (l->keyfile && !l->certfile)) {
1103 hlog(LOG_ERR, "Listen: Only one of sslkey and sslcert defined for '%' - both needed for SSL", argv[1]);
1104 free_listen_config(&l);
1105 return -2;
1106 }
1107
1108 /* dupefeed port is always hidden */
1109 if (clflags & CLFLAGS_DUPEFEED)
1110 l->hidden = 1;
1111
1112 if (clflags & CLFLAGS_UDPSUBMIT)
1113 l->clients_max = 1;
1114
1115 /* if low ports are configured, make a note of that, so that
1116 * POSIX capability to bind low ports can be reserved
1117 * at startup.
1118 */
1119 if (port < 1024)
1120 listen_low_ports = 1;
1121
1122 /* find existing config for same proto-host-port combination */
1123 struct listen_config_t *old_l;
1124 old_l = find_listen_config(listen_config, l->proto, l->host, l->portnum);
1125 if (old_l) {
1126 /* this is an old config... see if it changed in a way which
1127 * would require listener reconfiguration
1128 */
1129 l->id = old_l->id;
1130 } else {
1131 /* new config, assign new id */
1132 // coverity[dont_call] // squelch warning: not security sensitive use of random(): local id
1133 l->id = random();
1134 }
1135
1136 /* put in the list */
1137 l->next = *lq;
1138 if (l->next)
1139 l->next->prevp = &l->next;
1140 *lq = l;
1141
1142 return 0;
1143 }
1144
do_http_listener(char * what,int upload_type,int argc,char ** argv)1145 int do_http_listener(char *what, int upload_type, int argc, char **argv)
1146 {
1147 struct http_config_t *l;
1148
1149 if (argc != 3) {
1150 hlog(LOG_ERR, "%s: Invalid number of arguments", what);
1151 return -1;
1152 }
1153
1154 l = hmalloc(sizeof(*l));
1155 memset(l, 0, sizeof(*l));
1156 l->host = hstrdup(argv[1]);
1157 l->port = atoi(argv[2]);
1158 l->upload_port = upload_type;
1159
1160 l->next = new_http_config;
1161 if (new_http_config)
1162 new_http_config->prevp = &l->next;
1163 new_http_config = l;
1164 l->prevp = &new_http_config;
1165
1166 return 0;
1167 }
1168
do_httpstatus(char * new,int argc,char ** argv)1169 int do_httpstatus(char *new, int argc, char **argv)
1170 {
1171 return do_http_listener("HTTPStatus", 0, argc, argv);
1172 }
1173
do_httpupload(char * new,int argc,char ** argv)1174 int do_httpupload(char *new, int argc, char **argv)
1175 {
1176 return do_http_listener("HTTPUpload", 1, argc, argv);
1177 }
1178
1179 /*
1180 * Log rotation config
1181 */
1182
do_logrotate(int * dest,int argc,char ** argv)1183 int do_logrotate(int *dest, int argc, char **argv)
1184 {
1185 int i;
1186
1187 if (argc != 3) {
1188 hlog(LOG_ERR, "LogRotate: Invalid number of arguments");
1189 return -1;
1190 }
1191
1192 i = atoi(argv[1]);
1193 if (i < 1) {
1194 hlog(LOG_ERR, "LogRotate: Invalid megabytes value: %s", argv[1]);
1195 return -1;
1196 }
1197
1198 log_rotate_size = i * 1024 * 1024;
1199
1200 i = atoi(argv[2]);
1201 if (i < 1) {
1202 hlog(LOG_ERR, "LogRotate: Invalid file count: %s", argv[2]);
1203 log_rotate_size = 0;
1204 return -1;
1205 }
1206
1207 log_rotate_num = i;
1208
1209 hlog(LOG_DEBUG, "LogRotate: Enabled at %d megabytes, %d files",
1210 log_rotate_size/1024/1024, log_rotate_num);
1211
1212 return 0;
1213 }
1214
1215 /*
1216 * upcase
1217 */
1218
strupr(char * s)1219 char *strupr(char *s)
1220 {
1221 char *p;
1222
1223 for (p = s; (*p); p++)
1224 *p = toupper(*p);
1225
1226 return s;
1227 }
1228
1229 /*
1230 * test if a path points to a directory
1231 */
1232
test_directory(const char * path)1233 static int test_directory(const char *path)
1234 {
1235 struct stat sb;
1236
1237 if (stat(path, &sb) != 0) {
1238 hlog(LOG_ERR, "stat(%s) failed: %s", path, strerror(errno));
1239 return -1;
1240 }
1241
1242 if (!S_ISDIR(sb.st_mode)) {
1243 hlog(LOG_ERR, "%s: Not a directory", path);
1244 return -1;
1245 }
1246
1247 return 0;
1248 }
1249
1250 /*
1251 * Read configuration files, should add checks for this program's
1252 * specific needs and obvious misconfigurations!
1253 */
1254
read_config(void)1255 int read_config(void)
1256 {
1257 int failed = 0;
1258 char *s;
1259
1260 if (read_cfgfile(cfgfile, cfg_cmds))
1261 return -1;
1262
1263 /* these parameters will only be used when reading the configuration
1264 * for the first time.
1265 */
1266 if (!rundir) {
1267 /* initial setup */
1268 if (new_rundir) {
1269 rundir = new_rundir;
1270 new_rundir = NULL;
1271 } else {
1272 hlog(LOG_CRIT, "Config: rundir not defined.");
1273 failed = 1;
1274 }
1275
1276 if ((rundir) && test_directory(rundir)) {
1277 hlog(LOG_CRIT, "Config: rundir %s is not a directory.", rundir);
1278 failed = 1;
1279 }
1280 } else {
1281 /* reconfig */
1282 if (new_rundir) {
1283 hfree(new_rundir);
1284 new_rundir = NULL;
1285 }
1286 }
1287
1288 if (!log_dir) {
1289 hlog(LOG_CRIT, "Config: logdir not defined.");
1290 failed = 1;
1291 }
1292
1293 /* serverid is only applied when running for the first time. */
1294 if (serverid) {
1295 if (new_serverid && strcasecmp(new_serverid, serverid) != 0)
1296 hlog(LOG_ERR, "Config: Not changing serverid while running.");
1297 hfree(new_serverid);
1298 new_serverid = NULL;
1299 } else {
1300 if (!new_serverid) {
1301 hlog(LOG_CRIT, "Config: serverid is not defined.");
1302 failed = 1;
1303 } else if (check_invalid_q_callsign(new_serverid, strlen(new_serverid)) != 0
1304 || strlen(new_serverid) < 3 || strlen(new_serverid) > CALLSIGNLEN_MAX) {
1305 hlog(LOG_CRIT, "Config: serverid '%s' is not valid.", new_serverid);
1306 failed = 1;
1307 } else {
1308 strupr(new_serverid);
1309 serverid = new_serverid;
1310 serverid_len = strlen(serverid);
1311 new_serverid = NULL;
1312 }
1313 }
1314
1315 if (new_passcode) {
1316 if (passcode)
1317 hfree(passcode);
1318 passcode = new_passcode;
1319 new_passcode = NULL;
1320 } else {
1321 hlog(LOG_ERR, "Config: passcode is not defined.");
1322 failed = 1;
1323 }
1324
1325 if (new_myadmin) {
1326 if (myadmin)
1327 hfree(myadmin);
1328 myadmin = new_myadmin;
1329 new_myadmin = NULL;
1330 } else {
1331 hlog(LOG_ERR, "Config: myadmin is not defined.");
1332 failed = 1;
1333 }
1334
1335 if (new_myemail) {
1336 if (myemail)
1337 hfree(myemail);
1338 myemail = new_myemail;
1339 new_myemail = NULL;
1340 } else {
1341 hlog(LOG_ERR, "Config: myemail is not defined.");
1342 failed = 1;
1343 }
1344
1345 if (new_http_bind) {
1346 if (http_bind && http_bind != http_bind_default)
1347 hfree(http_bind);
1348 http_bind = new_http_bind;
1349 new_http_bind = NULL;
1350 http_port = new_http_port;
1351 }
1352
1353 if (new_http_bind_upload) {
1354 if (http_bind_upload)
1355 hfree(http_bind_upload);
1356 http_bind_upload = new_http_bind_upload;
1357 new_http_bind_upload = NULL;
1358 http_port_upload = new_http_port_upload;
1359 }
1360
1361 if (new_http_status_options) {
1362 char *o = http_status_options;
1363 http_status_options = new_http_status_options;
1364 new_http_status_options = NULL;
1365 if (o)
1366 hfree(o);
1367 } else {
1368 char *o = http_status_options;
1369 http_status_options = NULL;
1370 hfree(o);
1371 }
1372
1373 if (new_fake_version) {
1374 char *o = fake_version;
1375 fake_version = new_fake_version;
1376 new_fake_version = NULL;
1377 if (o)
1378 hfree(o);
1379 } else {
1380 char *o = fake_version;
1381 fake_version = NULL;
1382 hfree(o);
1383 }
1384
1385 if (new_disallow_srccall_glob) {
1386 char **o = disallow_srccall_glob;
1387 disallow_srccall_glob = new_disallow_srccall_glob;
1388 new_disallow_srccall_glob = NULL;
1389 if (o)
1390 free_string_array(o);
1391 } else if (disallow_srccall_glob) {
1392 char **o = disallow_srccall_glob;
1393 disallow_srccall_glob = NULL;
1394 free_string_array(o);
1395 }
1396
1397 if (new_disallow_login_glob) {
1398 char **o = disallow_login_glob;
1399 disallow_login_glob = new_disallow_login_glob;
1400 new_disallow_login_glob = NULL;
1401 if (o)
1402 free_string_array(o);
1403 } else if (disallow_login_glob) {
1404 char **o = disallow_login_glob;
1405 disallow_login_glob = NULL;
1406 free_string_array(o);
1407 }
1408
1409 /* validate uplink config: if there is a single 'multiro' connection
1410 * configured, all of the uplinks must be 'multiro'
1411 */
1412 int uplink_config_failed = 0;
1413 int got_multiro = 0;
1414 int got_non_multiro = 0;
1415 struct uplink_config_t *up;
1416 for (up = new_uplink_config; (up); up = up->next) {
1417 if (up->client_flags & CLFLAGS_UPLINKMULTI)
1418 got_multiro = 1;
1419 else
1420 got_non_multiro = 1;
1421 if ((up->client_flags & CLFLAGS_UPLINKMULTI) && !(up->client_flags & CLFLAGS_PORT_RO)) {
1422 uplink_config_failed = 1;
1423 hlog(LOG_ERR, "Config: uplink with non-RO MULTI uplink - would cause a loop, not allowed.");
1424 }
1425 }
1426 if ((got_multiro) && (got_non_multiro)) {
1427 hlog(LOG_ERR, "Config: Configured both multiro and non-multiro uplinks - would cause a loop, not allowed.");
1428 failed = 1;
1429 free_uplink_config(&new_uplink_config);
1430 }
1431 if (uplink_config_failed)
1432 free_uplink_config(&new_uplink_config);
1433
1434 if (workers_configured < 1) {
1435 hlog(LOG_WARNING, "Configured less than 1 worker threads. Using 1.");
1436 } else if (workers_configured > 32) {
1437 hlog(LOG_WARNING, "Configured more than 32 worker threads. Using 32.");
1438 workers_configured = 32;
1439 }
1440
1441 if (!listen_config_new) {
1442 hlog(LOG_ERR, "No Listen directives found in configuration.");
1443 failed = 1;
1444 } else {
1445 /* put in the new listening config */
1446 free_listen_config(&listen_config);
1447 listen_config = listen_config_new;
1448 if (listen_config)
1449 listen_config->prevp = &listen_config;
1450 listen_config_new = NULL;
1451 }
1452
1453 /* put in the new aprsis-uplink config */
1454 if (uplink_config_install) {
1455 // too quick reconfig - uplink thread has not reconfigured yet
1456 hlog(LOG_WARNING, "New uplink config discarded - too quick reload, Uplink thread has not reconfigured yet");
1457 free_uplink_config(&new_uplink_config);
1458 } else {
1459 uplink_config_install = new_uplink_config;
1460 new_uplink_config = NULL;
1461 __sync_synchronize();
1462 uplink_config_updated = 1;
1463 }
1464
1465 /* put in the new aprsis-peerip config */
1466 free_peerip_config(&peerip_config);
1467 peerip_config = new_peerip_config;
1468 if (peerip_config)
1469 peerip_config->prevp = &peerip_config;
1470 new_peerip_config = NULL;
1471
1472 /* put in new http config */
1473 free_http_config(&http_config);
1474 http_config = new_http_config;
1475 if (http_config)
1476 http_config->prevp = &http_config;
1477 new_http_config = NULL;
1478
1479 if (failed)
1480 return -1;
1481
1482 if (!pidfile) {
1483 s = hmalloc(strlen(log_dir) + 1 + strlen(logname) + 4 + 1);
1484 sprintf(s, "%s/%s.pid", log_dir, logname);
1485
1486 pidfile = s;
1487 }
1488
1489 /* log network ID if not default */
1490 if (q_protocol_id != Q_PROTOCOL_ID_DEFAULT)
1491 hlog(LOG_INFO, "Q protocol ID: %c - %s", q_protocol_id, (disallow_other_protocol_id) ? "dropping others" : "allowing others");
1492
1493 return 0;
1494 }
1495
1496 /*
1497 * Free configuration variables
1498 */
1499
free_config(void)1500 void free_config(void)
1501 {
1502 if (log_dir)
1503 hfree(log_dir);
1504 log_dir = NULL;
1505 if (rundir)
1506 hfree(rundir);
1507 rundir = NULL;
1508 if (pidfile)
1509 hfree(pidfile);
1510 pidfile = NULL;
1511 if (cfgfile != def_cfgfile)
1512 hfree(cfgfile);
1513 cfgfile = NULL;
1514 if (logname != def_logname)
1515 hfree(logname);
1516 if (webdir != def_webdir)
1517 hfree(webdir);
1518 hfree(serverid);
1519 hfree(passcode);
1520 hfree(myemail);
1521 hfree(myadmin);
1522 serverid = passcode = myemail = myadmin = NULL;
1523 logname = NULL;
1524 if (fake_version)
1525 hfree(fake_version);
1526 fake_version = NULL;
1527 free_listen_config(&listen_config);
1528 free_peerip_config(&peerip_config);
1529 free_http_config(&http_config);
1530 if (disallow_srccall_glob) {
1531 free_string_array(disallow_srccall_glob);
1532 disallow_srccall_glob = NULL;
1533 }
1534 if (disallow_login_glob) {
1535 free_string_array(disallow_login_glob);
1536 disallow_login_glob = NULL;
1537 }
1538 }
1539
1540