/*
 * Copyright (c) 2003-2007, OpenFWTK Development Group
 * All rights reserved. See LICENSE.
 */

/*
 * dnsctl, a djb dnscache configuration program
 * (C) Copyright 2003 by ArkanoiD <ark@eltex.net>
 *
 */

static char rcsid[] = "$Id:";

#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <dirent.h>
#include <inttypes.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "firewall.h"
#include "firewall2.h"
#include "fwfunc.h"

#ifndef	INADDR_NONE
#define INADDR_NONE (in_addr_t) -1
#endif

#define	DEFAULT_BASE	PREFIX"/var/djbtools"

static	void
clear_dir(char *path)
{
	DIR		*dir;
	struct	dirent	*de;
	char		fnam[MAXPATHLEN];

	if (!(dir=opendir(path))) {
		syslog(LLEV,"fwtksyserr: cannot clean directory %.128s, %.128s",
			path,strerror(errno));
		exit(1);
	}
	syslog(LLEV,"unlp %s",path);
	while ((de=readdir(dir))) {
		if (*(de->d_name) == '.')
			continue;
		snprintf(fnam,MAXPATHLEN-1,"%s/%s",path,de->d_name);
		syslog(LLEV,"unl %s",fnam);
		if (unlink(fnam)) {
			syslog(LLEV,"fwtksyserr: cannot unlink %.128s, %.128s",
				fnam, strerror(errno));
			exit(1);
		}
	}
}


static	void
do_export(char *base, char *instance)
{
	Cfg		*cf;
	Cfg		*cfentry;
	FILE		*f;
	char		fname[MAXPATHLEN];
	char		*s;
	in_addr_t	bind_addr;

	if ((cf = cfg_read(instance)) == (Cfg *)-1) {
		syslog(LLEV,
			"fwtkcfgerr: no configuration records for %.128s",
			instance);
		return;
	}
	cfg_append(PERMFILE,cf,proxy_name);
	if ((!(s = proxy_conf_string(cf,"bind"))) ||
	    ((bind_addr = inet_addr(s)) == INADDR_NONE)) {
		syslog(LLEV,
			"fwtkcfgerr: interface address missing or invalid for %.128s",
			instance);
		return;
	}
	snprintf(fname,MAXPATHLEN-1,"%.128s/%.128s/env/IP",base,instance);
	if (!(f = fopen(fname,"w"))) {
		syslog(LLEV,
			"fwtksyserr: cannot create file %.128s, %.128s",fname, strerror(errno));
		return;
	}
	fputs(s,f);
	fclose(f);
	snprintf(fname,MAXPATHLEN-1,"%.128s/%.128s/root/servers", 
		 base,instance);
	clear_dir(fname);
	snprintf(fname,MAXPATHLEN-1,"%.128s/%.128s/root/ip", base,instance);
	clear_dir(fname);
	for (cfentry = cfg_get("zone",cf); cfentry ; 
	     cfentry = cfg_get("zone", (Cfg*) NULL)) {
		int    x;
		int    serverp = 0;
		syslog(LLEV,"got zone, %s",cfentry->argv[0]);
		for (x = 0; x < cfentry->argc ; x++) {
			if (!strcmp(cfentry->argv[x],"-servers")) {
				serverp = x;
				break;
			}
		}
		if ((!serverp) || (x >= cfentry->argc - 1)) {
			syslog(LLEV,
				"fwtkcfgerr: no servers specified for instance %.128s",instance);
			return;
		}
		for (x = 0; x < serverp ; x++)  {
			int x1;
			snprintf(fname,MAXPATHLEN-1,"%.128s/%.128s/root/servers"
				 "/%.128s",base,instance,cfentry->argv[x]);
			if (!(f = fopen(fname,"w"))) {
				syslog(LLEV, "fwtksyserr: cannot create file"
					"%.128s, %.128s",fname,strerror(errno));
				return;
			}
			for (x1 = serverp + 1; x1 < cfentry->argc ; x1++) 
				fprintf(f,"%.128s\n",cfentry->argv[x1]);
			fclose(f);
		}
	}
	for (cfentry = cfg_get("default-servers",cf); cfentry ; 
	     cfentry = cfg_get("default-servers", (Cfg*) NULL)) {
		int x;
		snprintf(fname,MAXPATHLEN-1,"%.128s/%.128s/root/servers"
			 "/@",base,instance);
		if (!(f = fopen(fname,"w"))) {
			syslog(LLEV, "fwtksyserr: cannot create file"
				"%.128s, %.128s",fname,strerror(errno));
			return;
		}
		for (x = 0; x < cfentry->argc ; x++) 
			fprintf(f,"%.128s\n",cfentry->argv[x]);
		fclose(f);
	}
	for (cfentry = cfg_get("hosts",cf); cfentry ; 
	     cfentry = cfg_get("hosts", (Cfg*) NULL)) {
		int x;
		char *p;
		for (x = 0; x < cfentry->argc ; x++) {
			snprintf(fname,MAXPATHLEN-1,"%.128s/%.128s/root/ip"
				 "/%.128s",base,instance,cfentry->argv[x]);
			if ((p = strstr(fname,".*")))
				*p = '\0';
		}
		if (!(f = fopen(fname,"w"))) {
			syslog(LLEV, "fwtksyserr: cannot create file"
				"%.128s, %.128s",fname,strerror(errno));
			return;
		}
		fclose(f);
	}
}

int
main(ac, av)
int ac;
char **av;

{
	char	*base;
	Cfg	*cf;

	strlcpy(proxy_name, basename(av[0]), MAX_STR);

#ifndef LOG_DAEMON
	openlog(proxy_name, LOG_PID);
#else
	openlog(proxy_name, LOG_PID | LOG_NDELAY, LFAC);
#endif

/*
 *	To allow ld -z weakextract, we have no other references to soio.o
 */
	sotimeout(proxy_timeout);

	if (ac == 2 && !strcmp(av[ac - 1], "-v")) {
		fprintf(stderr, "version %s\n", rcsid);
		syslog(LLEV, "version %s", rcsid);
		exit(0);
	}


	if ((proxy_confp = cfg_read(proxy_name)) == (Cfg *)-1)
		exit(1);

	if (!(base = proxy_conf_string(proxy_confp,"base")))
		base = DEFAULT_BASE;

	cf = cfg_get("instances",proxy_confp);
	for (cf = cfg_get("instances",proxy_confp); cf ; 
	     cf = cfg_get("instances",NULL)) {
		int x;
		if (cf->argc < 1) {
			syslog(LLEV,
				"fwtkcfgerr: instances require at least one parameter, line %d",
				cf->ln);
			exit(1);
		}
		for (x = 0 ; x < cf->argc ; x++) 
			do_export(base,cf->argv[x]);
	}
	return(0);
}
