view rtp-mgr/readconf.c @ 5:4a5560ef0807

include/rtp_defs.h: #include <stdint.h> dependency
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 27 May 2024 20:50:51 +0000
parents 247f4bbde24c
children 9499d41fc393
line wrap: on
line source

/*
 * In this module we implement the reading of /var/gsm/themwi-rtp.cfg:
 * we parse and save the configured IP address and port range for each
 * of our two sides, GSM and PSTN.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <syslog.h>
#include "struct.h"

struct bind_range_cfg bind_range_gsm, bind_range_pstn;
int syslog_facility = LOG_USER;

static const char config_file_pathname[] = "/var/gsm/themwi-rtp.cfg";

struct parse_state {
	int lineno;
	int set_mask;
};

static void
handle_bind_ip(st, kw, brc, line)
	struct parse_state *st;
	char *kw, *line;
	struct bind_range_cfg *brc;
{
	char *cp, *np;

	for (cp = line; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#') {
inv_syntax:	fprintf(stderr,
			"%s line %d: %s setting requires one argument\n",
			config_file_pathname, st->lineno, kw);
		exit(1);
	}
	for (np = cp; *cp && !isspace(*cp); cp++)
		;
	if (*cp)
		*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp != '\0' && *cp != '#')
		goto inv_syntax;
	brc->bind_ip.s_addr = inet_addr(np);
	if (brc->bind_ip.s_addr == INADDR_NONE) {
		fprintf(stderr,
			"%s line %d: invalid IP address argument \"%s\"\n",
			config_file_pathname, st->lineno, np);
		exit(1);
	}
}

static void
handle_port_range(st, kw, brc, line)
	struct parse_state *st;
	char *kw, *line;
	struct bind_range_cfg *brc;
{
	char *cp, *np1, *np2;

	for (cp = line; isspace(*cp); cp++)
		;
	if (!isdigit(*cp)) {
inv_syntax:	fprintf(stderr,
		"%s line %d: %s setting requires two numeric arguments\n",
			config_file_pathname, st->lineno, kw);
		exit(1);
	}
	for (np1 = cp; isdigit(*cp); cp++)
		;
	if (!isspace(*cp))
		goto inv_syntax;
	while (isspace(*cp))
		cp++;
	if (!isdigit(*cp))
		goto inv_syntax;
	for (np2 = cp; isdigit(*cp); cp++)
		;
	if (*cp && !isspace(*cp))
		goto inv_syntax;
	while (isspace(*cp))
		cp++;
	if (*cp != '\0' && *cp != '#')
		goto inv_syntax;
	brc->port_range_start = atoi(np1);
	brc->port_range_end = atoi(np2);
	if (brc->port_range_start & 1) {
		fprintf(stderr, "%s line %d: start port must be even\n",
			config_file_pathname, st->lineno);
		exit(1);
	}
	if (!(brc->port_range_end & 1)) {
		fprintf(stderr, "%s line %d: end port must be odd\n",
			config_file_pathname, st->lineno);
		exit(1);
	}
	if (brc->port_range_end <= brc->port_range_start) {
		fprintf(stderr,
		"%s line %d: end port must be greater than start port\n",
			config_file_pathname, st->lineno);
		exit(1);
	}
	brc->port_next = brc->port_range_start;
	brc->port_tries = (brc->port_range_end - brc->port_range_start + 1) / 2;
}

static void
handle_syslog_facility(st, kw, dummy_ptr, line)
	struct parse_state *st;
	char *kw, *line;
	void *dummy_ptr;
{
	char *cp, *np;

	for (cp = line; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#') {
inv_syntax:	fprintf(stderr,
			"%s line %d: %s setting requires one argument\n",
			config_file_pathname, st->lineno, kw);
		exit(1);
	}
	for (np = cp; *cp && !isspace(*cp); cp++)
		;
	if (*cp)
		*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp != '\0' && *cp != '#')
		goto inv_syntax;
	if (!strcmp(np, "authpriv"))
		syslog_facility = LOG_AUTHPRIV;
	else if (!strcmp(np, "cron"))
		syslog_facility = LOG_CRON;
	else if (!strcmp(np, "daemon"))
		syslog_facility = LOG_DAEMON;
	else if (!strcmp(np, "ftp"))
		syslog_facility = LOG_FTP;
	else if (!strcmp(np, "lpr"))
		syslog_facility = LOG_LPR;
	else if (!strcmp(np, "mail"))
		syslog_facility = LOG_MAIL;
	else if (!strcmp(np, "news"))
		syslog_facility = LOG_NEWS;
	else if (!strcmp(np, "user"))
		syslog_facility = LOG_USER;
	else if (!strcmp(np, "uucp"))
		syslog_facility = LOG_UUCP;
	else if (!strcmp(np, "local0"))
		syslog_facility = LOG_LOCAL0;
	else if (!strcmp(np, "local1"))
		syslog_facility = LOG_LOCAL1;
	else if (!strcmp(np, "local2"))
		syslog_facility = LOG_LOCAL2;
	else if (!strcmp(np, "local3"))
		syslog_facility = LOG_LOCAL3;
	else if (!strcmp(np, "local4"))
		syslog_facility = LOG_LOCAL4;
	else if (!strcmp(np, "local5"))
		syslog_facility = LOG_LOCAL5;
	else if (!strcmp(np, "local6"))
		syslog_facility = LOG_LOCAL6;
	else if (!strcmp(np, "local7"))
		syslog_facility = LOG_LOCAL7;
	else {
		fprintf(stderr,
		"%s line %d: \"%s\" is not a recognized syslog facility\n",
			config_file_pathname, st->lineno, np);
		exit(1);
	}
}

static void
process_line(st, line)
	struct parse_state *st;
	char *line;
{
	char *cp, *np;
	void (*handler)();
	struct bind_range_cfg *ipside;
	int set_id;

	if (!index(line, '\n')) {
		fprintf(stderr, "%s line %d: too long or missing newline\n",
			config_file_pathname, st->lineno);
		exit(1);
	}
	for (cp = line; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#')
		return;
	for (np = cp; *cp && !isspace(*cp); cp++)
		;
	if (*cp)
		*cp++ = '\0';
	if (!strcmp(np, "gsm-ip-addr")) {
		handler = handle_bind_ip;
		ipside = &bind_range_gsm;
		set_id = 1;
	} else if (!strcmp(np, "gsm-port-range")) {
		handler = handle_port_range;
		ipside = &bind_range_gsm;
		set_id = 2;
	} else if (!strcmp(np, "pstn-ip-addr")) {
		handler = handle_bind_ip;
		ipside = &bind_range_pstn;
		set_id = 4;
	} else if (!strcmp(np, "pstn-port-range")) {
		handler = handle_port_range;
		ipside = &bind_range_pstn;
		set_id = 8;
	} else if (!strcmp(np, "syslog-facility")) {
		handler = handle_syslog_facility;
		ipside = NULL;
		set_id = 0;
	} else {
		fprintf(stderr, "%s line %d: non-understood keyword \"%s\"\n",
			config_file_pathname, st->lineno, np);
		exit(1);
	}
	if (st->set_mask & set_id) {
		fprintf(stderr, "%s line %d: duplicate %s setting\n",
			config_file_pathname, st->lineno, np);
		exit(1);
	}
	handler(st, np, ipside, cp);
	st->set_mask |= set_id;
}

read_config_file()
{
	FILE *inf;
	struct parse_state pst;
	char linebuf[256];

	inf = fopen(config_file_pathname, "r");
	if (!inf) {
		perror(config_file_pathname);
		exit(1);
	}
	pst.set_mask = 0;
	for (pst.lineno = 1; fgets(linebuf, sizeof linebuf, inf); pst.lineno++)
		process_line(&pst, linebuf);
	fclose(inf);
	if (pst.set_mask != 15) {
		fprintf(stderr, "error: %s did not set all required settings\n",
			config_file_pathname);
		exit(1);
	}
}