/* config.c    config file reader
 *
 * $Id: config.c,v 1.3 1995/03/19 17:21:06 bdale Exp $
 *
 * Copyright 1991, Michael Westerhof, Sun Microsystems, Inc.
 * This software may be freely used, distributed, or modified, providing
 * this header is not removed.
 *
 */

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <ctype.h>
#include <syslog.h>
#include <stdlib.h>

#include "ipip.h"

static void cerr();		/* General error printer */
static void init_config();
static void c_interface();
static void print_config();
struct interface ifs[MAX_IFACES];
int ifs_top;

static int clineno;
static int cerrflag;

/*
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * open and read the interface config file. Also initialize the iface defs
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 */
int
read_config(f)
char *f;
{
	FILE *cf;
	char buf[256], *p;

	init_config();

/* Open the file */
	if((cf = fopen(f,"r"))==NULL){
		syslog(LOG_ERR, "Config file %s not found or could not be opened",f);
		return -1;
	}

	while(fgets(buf, 255, cf)!=NULL){
		clineno++;
		if((p = strtok(buf, " \t\n\r")) == NULL)continue;
		if(*p=='#' || *p==';')continue;

		if(strcmp(p,"interface")==0)c_interface();
/*		else if(strcmp(p,"whatever")==0)c_dowhatever(); */
		else cerr("Unrecognized command: %s",p);
	}

	if(ifs_top==0)cerr("No interfaces defined","");

	if(debugd)print_config();

	return cerrflag;
}

/*
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Initialize defaults and setup the interface structures
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 */
static void
init_config()
{
	int i;

	for(i=0;i<MAX_IFACES;i++){
		ifs[i].type = IF_TYPE_NONE;
		ifs[i].status = 0;
		ifs[i].id = NULL;
		ifs[i].devname = NULL;
		ifs[i].unit = 0;
		ifs[i].fd = -1;
		ifs[i].private = NULL;
		ifs[i].ifopen = NULL;
		ifs[i].ifread = NULL;
		ifs[i].ifsend = NULL;
		ifs[i].in = 0;
		ifs[i].out = 0;
		ifs[i].out_overruns = 0;
		ifs[i].martians_in = 0;
		ifs[i].bogus_in = 0;
		ifs[i].looped_in = 0;
	}
	ifs_top = 0;

	clineno = 0;
	cerrflag = 0;
}

/*
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Print out the config table (DEBUG)
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 */
static void
print_config()
{
	int i;
	char *id, *dev;

	if(cerrflag==0) syslog(LOG_DEBUG, "%d interfaces:\n",ifs_top);
	else syslog(LOG_DEBUG, "%d interfaces (there are errors):\n", ifs_top);
	for(i=0;i<ifs_top;i++){

		if(ifs[i].id == NULL) id = "(none)";
		else id = ifs[i].id;

		if(ifs[i].devname == NULL) dev = "(none)";
		else dev = ifs[i].devname;

		if(ifs[i].type == IF_TYPE_NONE){
			syslog(LOG_DEBUG,"interface %-4s  type NONE  devicename %s  unit %d\n",
				id, dev, ifs[i].unit);
		} else if(ifs[i].type == IF_TYPE_SLIP){
			syslog(LOG_DEBUG,"interface %-4s  type slip  devicename %s  speed %d\n",
				id, dev, ifs[i].unit);
		} else if(ifs[i].type == IF_TYPE_TUN){
			syslog(LOG_DEBUG,"interface %-4s  type tun  devicename %s\n",
				id, dev);
		} else if(ifs[i].type == IF_TYPE_IPUDP){
			syslog(LOG_DEBUG,"interface %-4s  type udp  port %d\n",
				id, ifs[i].unit);
		} else if(ifs[i].type == IF_TYPE_IPIP){
			syslog(LOG_DEBUG,"interface %-4s  type ip  protocol id %d\n",
				id, ifs[i].unit);
		} else {
			syslog(LOG_DEBUG,"interface %-4s  type UNKNOWN  devicename %s  unit %d\n",
				id, dev, ifs[i].unit);
		}
	}
}

/*
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Print a general config file error
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 */
static void
cerr(s,a)
char *s;
char *a;
{
	syslog(LOG_ERR,"Config file error at line %d:\n",clineno);
	(void)fprintf(stderr,s,a);
	(void)fprintf(stderr,"\n");
	cerrflag--;
}

/*
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Handle the "define" command
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 */
static void
c_interface()
{
	int syntax;
	char *q;

	if(ifs_top>=MAX_IFACES){
		cerr("Too many interfaces defined","");
		return;
	}

	syntax = 0;

	if((q = strtok((char *)NULL, " \t\n\r"))){
		ifs[ifs_top].id = strdup(q);
	} else syntax++;

	if((q = strtok((char *)NULL, " \t\n\r"))){
		if(strcmp(q,"tunnel")==0){
			ifs[ifs_top].type = IF_TYPE_TUN;
			ifs[ifs_top].ifopen = tun_open;
			ifs[ifs_top].ifread = tun_read;
			ifs[ifs_top].ifsend = tun_send;
		} else if(strcmp(q,"slip")==0){
			ifs[ifs_top].type = IF_TYPE_SLIP;
			ifs[ifs_top].ifopen = slip_open;
			ifs[ifs_top].ifread = slip_read;
			ifs[ifs_top].ifsend = slip_send;
		} else if(strcmp(q,"ip")==0){
			ifs[ifs_top].type = IF_TYPE_IPIP;
			ifs[ifs_top].ifopen = ip_open;
			ifs[ifs_top].ifread = ip_read;
			ifs[ifs_top].ifsend = ip_send;
		} else if(strcmp(q,"udp")==0){
			ifs[ifs_top].type = IF_TYPE_IPUDP;
			ifs[ifs_top].ifopen = ip_open;
			ifs[ifs_top].ifread = ip_read;
			ifs[ifs_top].ifsend = ip_send;
		} else cerr("Bad interface type: %s",q);
	} else syntax++;

	if((q = strtok((char *)NULL, " \t\n\r"))){
		ifs[ifs_top].devname = strdup(q);
	} else syntax++;

	if((q = strtok((char *)NULL, " \t\n\r"))){
		ifs[ifs_top].unit = atoi(q);
	} else syntax++;

	if(syntax)cerr("Syntax error (interface <name> <type> <device> <int>","");

	ifs_top++;
}
