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