#include "substdio.h"
#include "subfd.h"
#include "strerr.h"
#include "stralloc.h"
#include "alloc.h"
#include "cdb.h"

#define FATAL "tcprulescheck: fatal: "

char *fnrules;
int fdrules;

void die_usage()
{
  strerr_die1x(100,"tcprulescheck: usage: tcprulescheck rules.cdb tcpremoteip [ tcpremoteinfo ]");
}
void die_read()
{
  strerr_die4sys(111,FATAL,"unable to read ",fnrules,": ");
}
void nomem()
{
  strerr_die2x(111,FATAL,"out of memory");
}

static stralloc tmp = {0};

void dorule()
{
  char *data;
  uint32 dlen32;
  unsigned int datalen;
  unsigned int next0;

  switch(cdb_seek(fdrules,tmp.s,tmp.len,&dlen32)) {
    case -1: die_read();
    case 0: return;
  }

  datalen = dlen32;
  data = alloc(datalen);
  if (!data) nomem();
  if (cdb_bread(fdrules,data,datalen) != 0) die_read();

  substdio_puts(subfdout,"rule ");
  substdio_put(subfdout,tmp.s,tmp.len);
  substdio_puts(subfdout,":\n");
  while ((next0 = byte_chr(data,datalen,0)) < datalen) {
    switch(data[0]) {
      case 'D':
	substdio_puts(subfdout,"deny connection\n");
	substdio_flush(subfdout);
	_exit(0); /* XXX: could still set env vars for logs */
      case '+':
	substdio_puts(subfdout,"set environment variable ");
	substdio_puts(subfdout,data + 1);
	substdio_puts(subfdout,"\n");
	break;
    }
    data += next0 + 1; datalen -= next0 + 1;
  }
  substdio_puts(subfdout,"allow connection\n");
  substdio_flush(subfdout);
  _exit(0);
}

void main(argc,argv)
int argc;
char **argv;
{
  char *tcpremoteip;
  char *tcpremoteinfo;

  fnrules = argv[1];
  if (!fnrules) die_usage();

  tcpremoteip = argv[2];
  if (!tcpremoteip) die_usage();

  tcpremoteinfo = argv[3];

  fdrules = open_read(fnrules);
  if (fdrules == -1) die_read();

  if (tcpremoteinfo) {
    if (!stralloc_copys(&tmp,tcpremoteinfo)) nomem();
    if (!stralloc_cats(&tmp,"@")) nomem();
    if (!stralloc_cats(&tmp,tcpremoteip)) nomem();
    dorule();
  }

  if (!stralloc_copys(&tmp,tcpremoteip)) nomem();
  dorule();
  while (tmp.len > 0) {
    if (tcpremoteip[tmp.len - 1] == '.')
      dorule();
    --tmp.len;
  }

  dorule();

  substdio_putsflush(subfdout,"default:\nallow connection\n");
  _exit(0);
}
