/* sockd_rdroute */


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <syslog.h>
#include "socks.h"

int sockd_rdroute(filename, rtAddrPtr, NrtPtr, useSyslog)
char *filename;
struct config **rtAddrPtr;
int *NrtPtr;
int useSyslog;
{
	FILE	*fd;
	static char	buf[1024];
	char	*bp;
	int	linenum = 0, permit;
	char	*argv[10];
	int	argc;
	int	next_arg;
	long	p;
	int Nrt = 0, maxrt = 0;
	struct config *rtAddr, *cp;
	int	has_error = 0;
	int	i;


	if ((fd = fopen(filename, "r")) == NULL) {
		if (useSyslog)
			syslog(LOG_HIGH, "Cannot open route file %s: %m\n", filename);
		else
			fprintf(stderr, "Cannot open route file %s: %m\n", filename);
		exit(1);
	}

	for (i = 0, cp = *rtAddrPtr; i++ < *NrtPtr; cp++) {
		if (cp->ddomain != NULL)
			free(cp->ddomain);
	}
	if (*rtAddrPtr)
		free(*rtAddrPtr);

	maxrt = CONF_INCR;
	rtAddr = (struct config *) malloc( maxrt * sizeof(struct config));
	if (rtAddr == NULL) {
		goto out_of_memory;
	}
	Nrt = 0;
	cp = rtAddr;

	while (fgets(buf, sizeof(buf) - 1, fd) != NULL) {
		linenum++;
		bzero(cp, sizeof(struct config));
		/*
		**  Comments start with a '#' anywhere on the line
		*/
		if ((bp = index(buf, '\n')) != NULL)
			*bp = '\0';
		for (bp = buf; *bp != '\0'; bp++) {
			if (*bp == ':') {
				*bp++ = '\0';
				cp->cmdp = strdup(bp);
				if (cp->cmdp == NULL)
					goto out_of_memory;
				break;
			} else if (*bp == '#') {
				*bp = '\0';
				break;
			} else if (*bp == '\t')
				*bp = ' ';
		}
		if (strlen(buf) == 0) continue;
		socks_mkargs(buf, &argc, argv, 10);
		if (argc == 0) {
			continue;
		}
		if (argc != 3) {
			if (useSyslog)
				syslog(LOG_HIGH, "Invalid entry at line %d in file %s", linenum, filename);
			else
				fprintf(stderr, "Invalid entry at line %d in file %s\n", linenum, filename);
			exit(1);
		}
		
		if (socks_GetQuad(argv[0], &cp->saddr) == -1) {
			if (useSyslog)
				syslog(LOG_HIGH, "illegal interface address at line %d in file %s", linenum, filename);
			else
				fprintf(stderr, "illegal interface address at line %d in file %s\n", linenum, filename);
			has_error = 1;
			continue;
		}
		if (socks_GetAddr(argv[1], &cp->daddr, &cp->ddomain) == -1){
			goto out_of_memory;
		}
		if (socks_GetQuad(argv[2], &cp->dmask) == -1) {
			if (useSyslog)
				syslog(LOG_HIGH, "illegal destination mask at line %d in file %s", linenum, filename);
			else
				fprintf(stderr, "illegal destination mask at line %d in file %s\n", linenum, filename);
			has_error = 1;
			continue;
		}

update_count:
		if (++Nrt >= maxrt) {
			maxrt += CONF_INCR;
			rtAddr = (struct config *) realloc(rtAddr, maxrt * sizeof(struct config));
		}
		if (rtAddr == NULL) {
			goto out_of_memory;
		}
		cp = rtAddr + Nrt;
	}
	fclose(fd);

	if (Nrt == 0) {
		if (useSyslog)
			syslog(LOG_HIGH, "No valid entires in file %s", filename);
		else
			fprintf(stderr, "No valid entires in file %s\n", filename);
		exit(1);
	}
	if (has_error)
		exit(1);
	if (Nrt < maxrt)
		rtAddr = (struct config *) realloc(rtAddr, Nrt * sizeof(struct config));
	*NrtPtr = Nrt;
	*rtAddrPtr = rtAddr;
	return 0;

out_of_memory:
	if (useSyslog)
		syslog(LOG_HIGH, "Out of memory\n");
	else
		fprintf(stderr, "Out of memory\n");
	exit(1);

}
