/* NAT_control.c  --  user interface and control functions for NAT */

#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#include "NAT_shared_defs.h"
#include "NAT_types.h"

#define USAGE \
"Usage: %s [ show | clear | silent | arp | nat | verbose ]\n", argv[0]

void AppShow( void )
{
	int i;
	u_int32_t  *p1, *p2;
	char buf[1024];
	int  natfd;
	natfd = open(NAT_DEV_FILE, O_RDWR, 0);
	if ( natfd == -1 ) {
		printf("Failed to open %s\n",NAT_DEV_FILE);
		return;
	}
	p1=(u_int32_t *)buf; /* ingress counters */
	p2=(u_int32_t *)(buf+RX_CNTR_SIZE); /* egress counters */
	ioctl(natfd,GET_RX_COUNTER,p1);
	ioctl(natfd,GET_TX_COUNTER,p2);
	for( i=0; i<3; i++ ) {
		printf("Port %d\n", i);
		printf("  Ingress Counters\n");
		printf("    Received packets:    %10u\n", *p1++);
		printf("    Dropped packets:     %10u\n", *p1++);
		printf("    Exception packets:   %10u\n", *p1++);
		printf("    Bytes received:      %10u\n", *p1++);
		printf("  Egress Counters\n");
		printf("    Transmitted packets: %10u\n", *p2++);
		printf("    Dropped packets:     %10u\n", *p2++);
		printf("    Transmitted bytes:   %10u\n", *p2++);
		printf("    Dropped bytes:       %10u\n\n", *p2++);
	}
	close(natfd);
	return;
}

void AppSilent()
{
	int natfd;
	natfd = open(NAT_DEV_FILE, O_RDWR, 0);
	if ( natfd == -1 ) {
		printf("Failed to open %s\n",NAT_DEV_FILE);
		return;
	}
	ioctl(natfd,SILENT,NULL);
	close(natfd);
}

void AppVerbose()
{
	int natfd;
	natfd = open(NAT_DEV_FILE, O_RDWR, 0);
	if ( natfd == -1 ) {
		printf("Failed to open %s\n",NAT_DEV_FILE);
		return;
	}
	ioctl(natfd,VERBOSE,NULL);
	close(natfd);
}

void AppClear( void )
{
	int natfd;
	natfd = open(NAT_DEV_FILE, O_RDWR, 0);
	if ( natfd == -1 ) {
		printf("Failed to open %s\n",NAT_DEV_FILE);
		return;
	}
	ioctl(natfd,CLR_RX_COUNTER,NULL);
	ioctl(natfd,CLR_TX_COUNTER,NULL);
	close(natfd);
	printf("Counters cleared\n");
	return;
}

void AppGetArpTbl( void )
{
	int natfd,i;
	arp_entry buf[ARP_TABLE_SIZE];
	natfd = open(NAT_DEV_FILE, O_RDWR, 0);
	if ( natfd == -1 ) {
		printf("Failed to open %s\n",NAT_DEV_FILE);
		return;
	}
	ioctl(natfd,GET_ARP_TABLE,buf);
	close(natfd);
	for (i=0;i<ARP_TABLE_SIZE;i++) {
	  if (buf[i].valid)
	    printf(
	     "%i.%i.%i.%i -> %02X:%02X:%02X:%02X:%02X:%02X  iface: %i\n",
	     IP2B(buf[i].ip_addr), ETH2B(buf[i].eth_w0),
	     buf[i].ifnum);
	}
	return;
}

void AppGetNatTbl( void )
{
	int natfd,i;
	nat_entry buf[NAT_TABLE_SIZE];
	unsigned char timer[2*NAT_TABLE_SIZE];
	natfd = open(NAT_DEV_FILE, O_RDWR, 0);
	if ( natfd == -1 ) {
		printf("Failed to open %s\n",NAT_DEV_FILE);
		return;
	}
	ioctl(natfd,GET_NAT_TABLE,buf);
	ioctl(natfd,GET_TIMER_TABLE,timer);
	for (i=0;i<NAT_TABLE_SIZE;i++) {
	  if (buf[i].valid) {
	    printf("IP local: %i.%i.%i.%i port local: %i\n",
	           IP2B(buf[i].ip_addr_loc), buf[i].lport);
	    printf("IP remote: %i.%i.%i.%i port remote: %i\n",
	           IP2B(buf[i].ip_addr_rem), buf[i].rport);
	    printf("protocol: %i port (NAT): %i timer: %i index: %i\n\n",
	           buf[i].prot, buf[i].nport,
	           timer[i]|timer[NAT_TABLE_SIZE+i],i);
	  }
	}
	close(natfd);
	return;
}


int main(int argc, char **argv)
{
	if (argc != 2) {
		printf(USAGE);
		return 0;
	}
	if (strncmp(argv[1], "show", 4) == 0) {
		AppShow();
	} else if (strncmp(argv[1], "clear", 5) == 0) {
		AppClear();
	} else if (strncmp(argv[1], "silent", 6) == 0) {
		AppSilent();
	} else if (strncmp(argv[1], "verbose", 7) == 0) {
		AppVerbose();
	} else if (strncmp(argv[1], "arp", 3) == 0) {
		AppGetArpTbl();
	} else if (strncmp(argv[1], "nat", 3) == 0) {
		AppGetNatTbl();
	} else {
		printf("Invalid parameter\n");
		printf(USAGE);
	}
	return 0;
}
