#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/time.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <sys/sysinfo.h>
#include <sys/vfs.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <poll.h>
#include <strings.h>
#include <sys/time.h>
#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <zlib.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <net/if.h>
#include <netdb.h>
#include "base32.h"
#include "gix_img.h"
#include "sysdefs.h"
#include "webtool.h"
#include "tools.h"

struct dhcp_features {
	char wants_dhcp; // 0...A simple BOOTP-REQUEST
	char wants_broadcast; // Reply not on unicast, but multicast (Use same address as was used originally --> also on ethernet level)
	char wants_subnetmask; // 1
	char wants_router; // 3
	char wants_bootfile; // 67
	char wants_nameserver; // 5
	char wants_broadcastaddress; // 28
	char wants_bootfile_size; // 13
	char wants_domain_name; // 15
	char wants_hostname; // 12
	char wants_dhcp_server_id; // 54
	char wants_renewal_time; // 58
	u_int8_t *class_id;
	u_int8_t source_mac[6];

	
};


#pragma pack(push,1)
struct bootp_packet {
	u_int8_t op;
	u_int8_t htype;
	u_int8_t hlen;
	u_int8_t hops;
	u_int32_t xid;
	u_int16_t secs;
	u_int16_t flags;
	u_int32_t ciaddr;
	u_int32_t yiaddr;
	u_int32_t siaddr;
	u_int32_t giaddr;
	u_int8_t chaddr[16];
	u_int8_t sname[64];
	u_int8_t file[128];
};
#pragma pack(pop) 

u_int8_t ether_bcast[6];
u_int8_t dhcp_magic_cookie[] = { 0x63, 0x82, 0x53, 0x63 };

#define GIX_INETD_UPDATESERVER "2001:4100:0:65::1"
#define GIX_INETD_VERSION "GIX-INETD-ADMIN-SERVER 3.32-TDS"
#define CONFIG_FILE "/big/GIX_INETD/conf/ginetd.conf"
#define LOG_FILE    "/big/GIX_INETD/logs/ginetd.log"
#define INETD_KEY   0xCAFE1970
#define INETD_KEY2 0xDAFE1970
#define INETD_OPTIONS 0xAFFE1970
#define MAX_CONNS   8192
#define MAX_BACKLOG 10
#define MAX_TFTP_SESSIONS 64
#define TFTP_TIMEOUT 10 // 60 seconds timeout for TFTP-Request
#define TFTP_DEFAULT_PACKSIZE 512 
#define TFTP_MAX_PACKSIZE 1408


char *dump_mac_addr(u_int8_t *mac){
	static char retval[32];
	sprintf(retval,"%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3],mac[4], mac[5]);
	return(retval);
}

char *dhcp_message_type(int typ){
	static char retval[64];
	switch (typ ){
		case 1:
			return("DHCPDISCOVER");	
			break;
		case 2:
			return("DHCPOFFER");	
			break;
		case 3:
			return("DHCPREQUEST");	
			break;
		case 4:
			return("DHCPDECLINE");	
			break;
		case 5:
			return("DHCPACK");	
			break;
		case 6:
			return("DHCPNAK");	
			break;
		case 7:
			return("DHCPRELEASE");	
			break;
		case 8:
			return("DHCPINFORM");	
			break;
		case 9:
			return("DHCPFORCERENEW");	
			break;
		case 10:	
			return("DHCPLEASEQUERY");
			break;
		case 11:	
			return("DHCPLEASEUNASSIGNED");
			break;
		case 12:	
			return("DHCPLEASEUNKNOWN");
			break;
		case 13:	
			return("DHCPLEASEACTIVE");
			break;
		case 14:	
			return("DHCPBULKLEASEQUERY");
			break;
		case 15:	
			return("DHCPLEASEQUERYDONE");
			break;
		case 16:	
			return("DHCPACTIVELEASEQUERY");
			break;
		case 17:	
			return("DHCPLEASEQUERYSTATUS");
			break;
		case 18:	
			return("DHCPTLS");
			break;
		default:
			sprintf(retval,"UNKNOWN(%d)",typ);
			break;
	}	
	return(retval);
}



struct sockaddr_in *check_valid_ipv4(char *addr,short port,int sock_type){
	static struct sockaddr_in sockaddr;

	bzero(&sockaddr,sizeof(sockaddr));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port   = htons(port);
	sockaddr.sin_addr.s_addr = inet_addr(addr);
	if ( sockaddr.sin_addr.s_addr  == INADDR_NONE ) return(NULL);
	return(&sockaddr);
}
struct sockaddr_in6 *check_valid_ipv6(char *addr,short port,int sock_type ){
	static struct sockaddr_in6 socky;
	struct addrinfo *res;
	struct addrinfo hints;
	char _port[12];
	bzero(&hints,sizeof(hints));
	hints.ai_family   = AF_INET6;
#ifdef AI_NUMERICHOST
	hints.ai_flags    = AI_NUMERICHOST;
#endif
	hints.ai_socktype = sock_type;
	sprintf(_port,"%d",(int)port);
	if ( getaddrinfo(addr,_port,&hints,&res)  ){
		return(NULL);
	} else {
		memcpy( (void *)&socky,(void *)res->ai_addr,res->ai_addrlen);
		freeaddrinfo(res);	
		return(&socky);
	}
}



#ifdef IPV6_V6ONLY
#define FRAG_SIZE st.f_frsize
#else
#define FRAG_SIZE 4096
#endif

#define CTRL_SHM 0xAFFE0000


#define MAX_BUFFER 4096


void start_tftp();
void start_dhcp();

int shm_id;
int webserver_pid;
int entries;
char prefix[1024];
int global_index;
int connection_index;
int semid;
int semid2;
int shmid_options;
int msg_id;

char my_hostname[1024];

#define TFTP_REQUEST_READ  0
#define TFTP_REQUEST_WRITE 1


struct gix_inetd_options *gix_options = NULL;


#define DHCP_IP_LEASES_FILE "/big/GIX_INETD/run/dhcp_leases.v4"
#define DHCP_IP6_LEASES_FILE "/big/GIX_INETD/run/dhcp_leases.v6"
#define DHCP_IP_LEASES_FILE_TMP "/big/GIX_INETD/run/dhcp_leases.v4~"
#define DHCP_IP6_LEASES_FILE_TMP "/big/GIX_INETD/run/dhcp_leases.v6~"

#pragma pack(push,1)
struct dhcp_ip_file_entry_t {
	u_int8_t mac[6];
	u_int8_t ip[4];
	time_t created;
	time_t changed;
	time_t expiry;
};
#pragma pack(pop)

// No locking is required here, as there is only a single process accessing the files :-)

/* All return 0 on success */
int dhcp_ip_remove_entry(u_int8_t *mac_addr){
}

int dhcp_ip_refresh_entry(u_int8_t *mac_addr,time_t new_relase_time){
}


struct dhcp_ip_file_entry_t *dhcp_ip_get_entry(u_int8_t *mac_addr){
	FILE *in;
	static struct dhcp_ip_file_entry_t entry;
	in = fopen(DHCP_IP_LEASES_FILE,"r");
	if ( in == NULL ) return(NULL);
	while ( fread(&entry,sizeof(entry),1,in) == 1 ){
		if ( memcmp(mac_addr,entry.mac,6) == 0 ){
			fclose(in);
			return(entry);
		}
	}
	fclose(in);
	return(NULL);	
}

int dhcp_ip_add_entry(struct dhcp_ip_file_entry_t *req){
	FILE *in;
	FILE *out;
	struct stat st;
	struct dhcp_ip_file_entry_t dummy;
	if ( dhcp_ip_get_entry(req->mac) != NULL ) return(-1); // Entry already exists
	if ( stat(DHCP_IP_LEASES_FILE,&st) == 0 ){ // File exists
		in = fopen(DHCP_IP_LEASES_FILE,"r");
		if ( in == NULL ){
			logger(prefix,"FATAL: Cannot open leases-file [%s] for reading\n",DHCP_IP_LEASES_FILE);
			return(-2);
		}
		unlink(DHCP_IP_LEASES_FILE_TMP);
		out = fopen(DHCP_IP_LEASES_FILE_TMP,"w");
		if ( out == NULL ){
			fclose(in);
			logger(prefix,"FATAL: Cannot open leases-file [%s] for reading\n",DHCP_IP_LEASES_FILE);
			return(-3);
		}
		while ( fread(dummy,sizeof(dummy),1,in) == 1 ){
		}
		fclose(in);
		fclose(out);
#ifdef 
	} else {
		unlink(DHCP_IP_LEASES_FILE_TMP);
		out = fopen(DHCP_IP_LEASES_FILE_TMP,"w");
	}
	
}


#define MAX_DHCP_INTERFACES 32
#define MAX_DHCP_BOOTFILES  128
#define MAX_DHCP_HOSTS	4096
#define MAX_DHCP_DNS_SERVERS 8

#define DHCP_DEFAULT_PORT_IN  67
#define DHCP_DEFAULT_PORT_OUT 68
#define DHCP_DEFAULT_LEASE_TIME 21600 // 6 hours

struct dhcp_interface_config {

	int index; // Index of interface in if_config-list
	time_t leasetime; 
	u_int8_t mac[6];
	int socket;

	struct sockaddr_in ip_me;
	struct sockaddr_in ip_router;
	char ip_netmask[128]; // "255.255.255.0"
	struct sockaddr_in ip_range_start;
	struct sockaddr_in ip_range_end;
	char ip_domain[256];
	struct sockaddr_in ip_nameserver[MAX_DHCP_DNS_SERVERS];
	int ip_nameservers;
	unsigned short ip_port_in;  
	unsigned short ip_port_out; 

	struct sockaddr_in6 ip6_me;
	struct sockaddr_in6 ip6_router;
	char ip6_netmask[128]; // (/32)
	struct sockaddr_in6 ip6_range_start;
	struct sockaddr_in6 ip6_range_end;
	char ip6_domain[256];
	struct sockaddr_in6 ip6_nameserver[MAX_DHCP_DNS_SERVERS];
	int ip6_nameservers;
	unsigned short ip6_port_in;  
	unsigned short ip6_port_out; 
};

/*
 * [PXEClient:Arch:00000:UNDI:002001]...
 */

struct dhcp_bootfile_config {
	char def;         // If no matching architecture can be found...use this bootfile 1
	char bootimage[256];
	char class_id[128];
};

struct dhcp_host_config {
	struct ether_addr mac;  // 48 Bits of network-address
	struct sockaddr_in ip_addr;
	struct sockaddr_in6 ip6_addr;
	char bootfile[512];
};



struct tftp_request {
	int packsize;
	char kind_request;
	char active;
	time_t started;
	time_t lastaction;
	char ipname[1024];
	int port;
	int addr_family;
	char filename[1024];
	size_t offset;	
	size_t cur_packet;	
	size_t fullsize;
	int sock;
	int fd;
	int options;
};

struct gix_inetd_options {
	int debug;

	char tftp_enabled;
	int tftp_requests_read;
	int tftp_requests_write;
	char tftp_readonly;
	char tftp_root[1024];
	int tftp_port;
	int tftp_pid;
	struct tftp_request tr[MAX_TFTP_SESSIONS];

	char dhcp_enabled;
	struct dhcp_interface_config dhcp_interface[MAX_DHCP_INTERFACES];
	struct dhcp_bootfile_config dhcp_bootfile[MAX_DHCP_BOOTFILES];
	struct dhcp_host_config dhcp_host[MAX_DHCP_HOSTS];
	int  dhcp_interfaces;
	int  dhcp_bootfiles;
	int  dhcp_hosts;
	int  dhcp_pid;
};






struct interface_config *if_config;
int if_count;


u_int8_t *get_my_mac(char *iname){
	static u_int8_t retval[6];
	int i;
	for ( i = 0; i < if_count; i++ ){
		if ( if_config[i].addrtype == AF_PACKET && strcmp(if_config[i].ethname,iname) == 0 ){
			sscanf(if_config[i].addr,"%02X:%02X:%02X:%02X:%02X:%02X",
				&retval[0], &retval[1], &retval[2], &retval[3], &retval[4], &retval[5]);
			return(retval);
		}
	}
	return(NULL);
}


#define TEST_PING  1
#define TEST_HTTP  2
#define TEST_HTTPS 3
#define TEST_POP3  4
#define TEST_SMTP  5


char *get_interface_address(char *ifname, int addrfamily){
	int i;
	for ( i = 0; i < if_count; i++ ){
		if ( if_config[i].addrtype == addrfamily && strcmp(ifname,if_config[i].ethname) == 0 ) return(if_config[i].addr);
	}

	return("");
}




char *get_diskname(char *dev){
	static char retval[32];
	char copy[1024];
	char *help;
	char *ptr;
	int r_major, r_minor;
	FILE *fp;
	char buf[1024];


	if ( *dev == '/' ){ // A path...we look in /etc/fstab
		fp = fopen("/etc/fstab","r");
		if ( fp == NULL ) return("n.a.");
		while ( fgets(buf,1024,fp) != NULL ){
			help = buf;
			ptr = strtok_r(buf,"\t \r\n",&help);
			if ( ptr == NULL ) continue;
			if ( strncmp(ptr,"/dev/",5) == 0 ) ptr += 5;
			strcpy(retval,ptr);
			ptr = strtok_r(NULL,"\t \r\n",&help);
			if ( ptr == NULL ) continue;
			if ( strcmp(ptr,dev) == 0 ){
				fclose(fp);
				return(retval);
			}

		}
		fclose(fp);
		return("n.a.");
	}


	strcpy(copy,dev);
	help = copy;
	ptr = strtok_r(copy,": \t\r\n",&help);
	if ( ptr == NULL ) return("n.A.");	
	r_major = atoi(ptr);
	ptr = strtok_r(NULL,": \t\r\n",&help);
	if ( ptr == NULL ) return("N.a.");	
	r_minor = atoi(ptr);
	
	fp = fopen("/proc/diskstats","r");
	if ( fp == NULL ) return("N.A.");
	while ( fgets(buf,1024,fp) != NULL ){
		int major, minor;
		char *ptr;
		help = buf;
		ptr = strtok_r(buf,"\t \r\n",&help);
		if ( ptr == NULL ) continue;
		major = atoi(ptr);
		ptr = strtok_r(NULL,"\t \r\n",&help);
		if ( ptr == NULL ) continue;
		minor = atoi(ptr);
		ptr = strtok_r(NULL,"\t \r\n",&help);
		if ( ptr == NULL ) continue;
		if ( major == r_major && minor == r_minor ){
			strcpy(retval,ptr);
			fclose(fp);
			return(retval);
		}
	}
	fclose(fp);

	return("n.a.");
}



struct test_info {
	int test_kind;
	char remote_name[1024];
	char url[1024];
	int port;
	int addr_family; // AF_INET, AT_INET6
	
	
};

char *convert_bytes(double inp,char *prefix){
	static char retval[1024];

	sprintf(retval,"%d&nbsp;%s",(int)inp,prefix);
	if ( inp > 1024.0 ) sprintf(retval,"%.02f&nbsp;k%s",inp/1024.0,prefix);
	if ( inp > (1024.0*1024.0) ) sprintf(retval,"%.02f&nbsp;M%s",inp/(1024.0*1024.0),prefix);
	if ( inp > (1024.0*1024.0*1024.0) ) sprintf(retval,"%.02f&nbsp;G%s",inp/(1024.0*1024.0*1024.0),prefix);
	if ( inp > (1024.0*1024.0*1024.0*1024.0) ) sprintf(retval,"%.02f&nbsp;T%s",inp/(1024.0*1024.0*1024.0*1024.0),prefix);
	return(retval);
}


struct fsinfo {
	char path[1024];
};

struct ethinfo {
	char ifname[64];
	char if_mac[128];
	char if_ipv4[64];
	char if_ipv6[256];
	struct timeval stamp1;	
	struct timeval stamp2;	

	long long bytes_receive_1;
	long long bytes_receive_2;
	char bytes_receive_t[64];
	double bytes_receive_sec;
	char bytes_receive_sec_t[64];

	long long packets_receive_1;
	long long packets_receive_2;
	char packets_receive_t[64];
	double packets_receive_sec;
	char packets_receive_sec_t[64];

	long long error_receive_1;
	long long error_receive_2;
	char error_receive_t[64];
	double error_receive_sec;
	char error_receive_sec_t[64];

	long long drop_receive_1;
	long long drop_receive_2;
	char drop_receive_t[64];
	double drop_receive_sec;
	char drop_receive_sec_t[64];

	long long bytes_transmit_1;
	long long bytes_transmit_2;
	char bytes_transmit_t[64];
	double bytes_transmit_sec;
	char bytes_transmit_sec_t[64];

	long long packets_transmit_1;
	long long packets_transmit_2;
	char packets_transmit_t[64];
	double packets_transmit_sec;
	char packets_transmit_sec_t[64];

	long long error_transmit_1;
	long long error_transmit_2;
	char error_transmit_t[64];
	double error_transmit_sec;
	char error_transmit_sec_t[64];

	long long drop_transmit_1;
	long long drop_transmit_2;
	char drop_transmit_t[64];
	double drop_transmit_sec;
	char drop_transmit_sec_t[64];

	long long colls_1;
	long long colls_2;
	char colls_t[64];
	double colls_sec;
	char colls_sec_t[64];

	double timestamp_calc;
};


struct process_info {
	int pid;
	int ppid;
	char program[256];
	unsigned long vmsize;
	char vmtext[32];
	long priority;
	long nice;
	unsigned long utime;
	unsigned long stime;
	struct timeval stamp;
	unsigned long utime2; // After sleeping 0.5 secs --> Check ticks again
	unsigned long stime2; // After sleeping 0.5 secs --> Check ticks again
	struct timeval stamp2; // To get the exact 0.5 seconds :-)
	time_t ptime;
	time_t starttime;
	double cpu_usage;
	long num_threads;
	long rss;
	int cpu;
};







char *gix_display_uptime(time_t starttime,char *pathname, char *buf){
        struct stat st;
        time_t tim;
        int seconds;

        if ( starttime == 0 && pathname == NULL){
                // We want system uptime
                struct sysinfo sys;
                sysinfo(&sys);
                seconds   = sys.uptime;
                // r_seconds = sys.uptime;
        } else {
                if ( pathname != NULL ){
                        if ( stat(pathname,&st) != 0 ){
                                tim = time(NULL);
                                seconds = 0;
                        } else {
                                seconds = time(NULL) - st.st_mtime;
                        }
                } else {
                        seconds = time(NULL) - starttime;
                }
        }
        strcpy(buf,"");
        if ( seconds > (365 * 24 * 3600) ){
                if ( seconds / (365 * 24 * 3600) == 1 )
                        sprintf(&buf[strlen(buf)],"%d year ",seconds / (365 * 24 * 3600) );
                else
                        sprintf(&buf[strlen(buf)],"%d years ",seconds / (365 * 24 * 3600) );
                seconds -= (seconds / (365 * 24 * 3600)) * (365 * 24 * 3600);
        }
        if ( seconds > (7 * 24 * 3600) ){
                if ( seconds / (7 * 24 * 3600)  == 1 )
                        sprintf(&buf[strlen(buf)],"%d week ",seconds / (7 * 24 * 3600) );
                else
                        sprintf(&buf[strlen(buf)],"%d weeks ",seconds / (7 * 24 * 3600) );
                seconds -= (seconds / (7 * 24 * 3600)) * (7 * 24 * 3600);
        }
        if ( seconds > ( 24 * 3600) ){
                if ( seconds / (24 * 3600)  == 1 )
                        sprintf(&buf[strlen(buf)],"%d day ",seconds / (24 * 3600) );
                else
                        sprintf(&buf[strlen(buf)],"%d days ",seconds / (24 * 3600) );
                seconds -= (seconds / (24 * 3600)) * (24 * 3600);
        }
        if ( seconds > (  3600) ){
                if ( seconds / 3600  == 1 )
                        sprintf(&buf[strlen(buf)],"%d hour ",seconds / ( 3600) );
                else
                        sprintf(&buf[strlen(buf)],"%d hours ",seconds / ( 3600) );
                seconds -= (seconds / ( 3600)) * ( 3600);
        }
        if ( seconds > (  60) ){
                if ( (seconds / 60) == 1 )
                        sprintf(&buf[strlen(buf)],"%d minute ",seconds / ( 60) );
                else
                        sprintf(&buf[strlen(buf)],"%d minutes ",seconds / ( 60) );
                seconds -= (seconds / ( 60)) * ( 60);
        }
        if ( seconds == 1 )
                sprintf(&buf[strlen(buf)],"%d second",seconds );
        else
                sprintf(&buf[strlen(buf)],"%d seconds",seconds );
        return(buf);

}



struct connection {
	int sock;
	int pid;
	int cpid; // Child-PID i.e.: The program executed
	char source[128];
	char target[128];
	unsigned  port;
	unsigned  t_port;
	time_t created;
	time_t lastin;
};

struct server {
        unsigned short port;
        time_t timeout;
	time_t data_timeout;
        char cmdline[1024];
        int max_conns;
        int pid;
	unsigned short family;  // AF_INET or AF_INET6
	time_t reset;
	int connections;
	int total_count;
	struct connection co[MAX_CONNS];
};

char *month_name[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
char *wday_name[]  = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };


char *ctime_o(time_t *tim, char *retbuf){
        struct tm tm;

        gmtime_r(tim,&tm);

        sprintf(retbuf,"%s, %d %s %04d %02d:%02d:%02d GMT",
                wday_name[tm.tm_wday], tm.tm_mday, month_name[tm.tm_mon], tm.tm_year + 1900,
                tm.tm_hour, tm.tm_min, tm.tm_sec);
        return(retbuf);
}



struct server *servlist;



void logger(char *prefix, const char *fmt, ...){
	char p[102400]; 
	struct stat st;
	FILE *log;
	va_list ap;
	struct timeval tv;
	struct tm _tm;
	struct tm *tm;
	char datestamp[512];
	gettimeofday(&tv,NULL);
	tm = localtime_r(&tv.tv_sec,&_tm);



	sprintf(datestamp,"[%04d-%02d-%02d %02d:%02d:%02d.%06d]{%d} (%s)",
		tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
		tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec,
		getpid(), prefix == NULL ? "NULL" : prefix );

	va_start(ap,fmt);
	vsnprintf(p,102400,fmt,ap);
	va_end(ap);

	log = fopen(LOG_FILE,"a");
	if ( log == NULL ) return;
	// while ( flock(fileno(log),LOCK_EX)  && errno == EINTR );
	fprintf(log,"%s %s",datestamp,p);
	fflush(log);	
	// while ( flock(fileno(log),LOCK_UN)  && errno == EINTR );
	fclose(log);
	/*
	if ( stat(LOG_FILE,&st) == 0 && st.st_size > (10 * 1024 * 1024 )){
		char newname[1024];
		sprintf(newname,"%s_%04d-%02d-%02d_%02d_%02d_%02d",LOG_FILE,tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
		rename(LOG_FILE,newname);
	}	
	*/
}

void init_defaults_dhcp(struct dhcp_interface_config *interface){
		u_int8_t *macaddr;
		interface->ip_port_in   = (unsigned short) DHCP_DEFAULT_PORT_IN;
		interface->ip_port_out  = (unsigned short) DHCP_DEFAULT_PORT_OUT;
		interface->ip6_port_in  = (unsigned short) DHCP_DEFAULT_PORT_IN;
		interface->ip6_port_out = (unsigned short) DHCP_DEFAULT_PORT_OUT;
		interface->leasetime    = DHCP_DEFAULT_LEASE_TIME;
		macaddr = get_my_mac(if_config[interface->index].ethname);
		if ( macaddr == NULL ){
			logger(prefix,"WARNING: Cannot get MAC-Address for interface [%s]\n",if_config[interface->index].ethname);
		} else {
			memcpy(interface->mac,macaddr,6);	
			logger(prefix,"INFO: MAC-Address of interface [%s] is [%s]\n",if_config[interface->index].ethname,dump_mac_addr(interface->mac));
		}
}

int _gzip_string(char *file, int line, char *in, char *out){
	FILE *tmp;
	gzFile gz;
	int newfd;
	int ori_size;
	int retval;
	struct stat st;

	ori_size = strlen(in);
	tmp = tmpfile();
	if ( tmp == NULL ) return(-1);
	gz = gzdopen(fileno(tmp),"w");
	if ( gz == NULL ){ fclose(tmp); return(-2); }
	retval = gzwrite(gz,in,ori_size);
	if ( retval != ori_size ){ fclose(tmp); return(-3); }
	newfd = dup(fileno(tmp));	
	gzclose(gz);
	if ( fstat(newfd,&st) ){ close(newfd); return(-4); }
	bzero(out,st.st_size + 1);	
	if ( lseek(newfd,(off_t)0,SEEK_SET) == (off_t) -1 ){
		close(newfd); 
		return(-5);
	}
	if ( read(newfd,out,st.st_size) != st.st_size ){
		close(newfd); 
		return(-6);
	}
	close(newfd);
	logger(prefix,"GZIP(%s:%d): [%d] --> [%d]\n",file,line,strlen(in),st.st_size);
	return(st.st_size);
}

#define gzip_string(a,b) _gzip_string(__FILE__,__LINE__,(a),(b))


int _m_kill(char *file, int line, int pid, int sig){
	// logger(prefix,"[%s: %d] KILLER PROCESS(%d) --> %d, Signal: %d\n",file,line,getpid(),pid,sig);
	if ( pid ) kill(pid,sig);
}

#define m_kill(a,b) _m_kill(__FILE__,__LINE__,(a),(b))

static int comparer(const void *_p1, const void *_p2){
	struct process_info *p1;
	struct process_info *p2;
	unsigned long time1,time2;

	p1 = (struct process_info *)_p1;
	p2 = (struct process_info *)_p2;

	if ( p1->cpu_usage != p2->cpu_usage ){
		return((int) ((p2->cpu_usage - p1->cpu_usage) * 100.0) );
	} else {
		return(p2->ptime - p1->ptime);
	}


}
static int comparer_eth(const void *_p1, const void *_p2){
	struct ethinfo *p1;
	struct ethinfo *p2;

	p1 = (struct ethinfo *)_p1;
	p2 = (struct ethinfo *)_p2;
	return(strcmp(p1->ifname,p2->ifname));
}

void send_valid_header(FILE *ss, char *referer){
	time_t tim;
	char dater[1024];

	tim = time(NULL);
	fprintf(ss,"HTTP/1.1 200 OK\r\n");
	if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
	fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
	fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
	fprintf(ss,"WWW-Authenticate: Basic realm=\"GIX-INETD-Admin\"\r\n");
	fprintf(ss,"Connection: close\r\n");
	fprintf(ss,"Content-Type: text/plain\r\n\r\n");
	return;
}


struct socket_info {
	char local_addr[256];
	char remote_addr[256];
	unsigned int local_port;	
	unsigned int remote_port;	
	int family;
	int state;
	unsigned long inode;
	unsigned short timer_kind;
	unsigned long timer_value;
	int uid;
	int pid;
	int protocol;
};

char *procnet[] = { "/proc/net/tcp" , "/proc/net/tcp6", "/proc/net/udp", "/proc/net/udp6", "/proc/net/unix",  NULL };


char *get_ipv4(char *addr){
	static char raddr[256];
	unsigned int a;
	unsigned int b;
	unsigned int c;
	unsigned int d;
	if ( sscanf(addr,"%02X%02X%02X%02X",&a,&b,&c,&d) != 4 ){
		return("0.0.0.0");
	} else {
		sprintf(raddr,"%d.%d.%d.%d",d,c,b,a);
		return(raddr);
	}
}

#define SOCK6_ADDR socky.sin6_addr.s6_addr

char *get_ipv6(char *addr){
	unsigned int addrlist[16];
	static char raddr[256];
	struct sockaddr_in6 socky;
	if ( sscanf(addr,"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
		&addrlist[3], &addrlist[2], &addrlist[1], &addrlist[0],
		&addrlist[7], &addrlist[6], &addrlist[5], &addrlist[4],
		&addrlist[11], &addrlist[10], &addrlist[9], &addrlist[8],
		&addrlist[15], &addrlist[14], &addrlist[13], &addrlist[12]) != 16 ){
		return("invalid");
	} else {
		int i;
		for ( i = 0; i < 16; i ++ ){
			SOCK6_ADDR[i] = (unsigned char) addrlist[i];
		}
		bzero(raddr,256);
		/*
		sprintf(raddr,"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
			SOCK6_ADDR[0],SOCK6_ADDR[1],SOCK6_ADDR[2],SOCK6_ADDR[3],
			SOCK6_ADDR[4],SOCK6_ADDR[5],SOCK6_ADDR[6],SOCK6_ADDR[7],
			SOCK6_ADDR[8],SOCK6_ADDR[9],SOCK6_ADDR[10],SOCK6_ADDR[11],
			SOCK6_ADDR[12],SOCK6_ADDR[13],SOCK6_ADDR[14],SOCK6_ADDR[15]);
		*/
		inet_ntop(AF_INET6,&(socky.sin6_addr),raddr,256);	
		return(raddr);
	}
			
}

struct socket_info *get_socket_info(unsigned long inode, int rpid){
	static struct socket_info si;
	unsigned char local[256];
	unsigned char remote[256];
	unsigned char _state[16];
	unsigned int local_port;
	unsigned int remote_port;
	unsigned long timer_value;
	unsigned int timer_kind;
	unsigned long f_inode;
	int uid; 
	int state;
	int fi;
	FILE *fp;
	char buf[1024];

	bzero(&si,sizeof( si));
	for ( fi = 0; procnet[fi] != NULL; fi++ ){
		fp = fopen(procnet[fi],"r");
		if ( fp == NULL ){
			logger("SOCKINFO","WARNING(%s:%d): Cannot open [%s]\n",__FILE__,__LINE__,procnet[fi]);
			return(NULL);
		}	
		while ( fgets(buf,1024,fp) != NULL ){
			char *ptr;
			char *help;
			help = buf;
			bzero(local,sizeof(local));
			bzero(remote,sizeof(remote));
			bzero(_state,sizeof(_state));
			state = 0;
			local_port = 0;	
			remote_port = 0;	
			f_inode = 0;	
			timer_value = 0;	
			timer_kind = 0;	
			if ( strcmp(procnet[fi],"/proc/net/udp") == 0 || strcmp(procnet[fi],"/proc/net/udp6") == 0 ) {
				ptr = strtok_r(buf," \t\r\n",&help);
				if ( ptr == NULL ) continue; // INDEX
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // LOCAL
				strcpy(local,ptr);
				ptr = &local[strlen(local)-1]; 
				while ( ptr > (char *)&local[0] && *ptr != ':' ) ptr--;
				if ( *ptr != ':' ) continue; // Headline is skipped
				*ptr = '\0';
				ptr++;
				if ( sscanf(ptr,"%04X",&local_port) != 1 ) continue;
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // REMOTE
				strcpy(remote,ptr);
				ptr = &remote[strlen(remote)-1]; 
				while ( ptr > (char *)&remote[0] && *ptr != ':' ) ptr--;
				if ( *ptr != ':' ) continue; // Headline is skipped
				*ptr = '\0';
				ptr++;
				if ( sscanf(ptr,"%04X",&remote_port) != 1 ) continue;
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // STATE
				strcpy(_state,ptr);
				sscanf(_state,"%02X",&state);
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // TX-Q, RX-Q
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // TM->WHEN
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // RET
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // UID
				uid = atoi(ptr);
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // TIMEOUT
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // INODE
				f_inode = atol(ptr);
			}
			if ( strcmp(procnet[fi],"/proc/net/unix") == 0 ){
				ptr = strtok_r(buf," \t\r\n",&help);
				if ( ptr == NULL ) continue; // NUM
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // REF
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // PROT
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // FLAGS
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // TYPE
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // State
				if ( sscanf(ptr,"%02X",&state) != 1 ) continue;
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // Inode
				f_inode = atol(ptr);
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // Inode
				strcpy(local,ptr);
			}
			if ( strcmp(procnet[fi],"/proc/net/tcp") == 0 || strcmp(procnet[fi],"/proc/net/tcp6") == 0 ) {
				ptr = strtok_r(buf," \t\r\n",&help);
				if ( ptr == NULL ) continue; // INDEX
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // LOCAL
				strcpy(local,ptr);
				ptr = &local[strlen(local)-1]; 
				while ( ptr > (char *)&local[0] && *ptr != ':' ) ptr--;
				if ( *ptr != ':' ) continue; // Headline is skipped
				*ptr = '\0';
				ptr++;
				if ( sscanf(ptr,"%04X",&local_port) != 1 ) continue;
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // REMOTE
				strcpy(remote,ptr);
				ptr = &remote[strlen(remote)-1]; 
				while ( ptr > (char *)&remote[0] && *ptr != ':' ) ptr--;
				if ( *ptr != ':' ) continue; // Headline is skipped
				*ptr = '\0';
				ptr++;
				if ( sscanf(ptr,"%04X",&remote_port) != 1 ) continue;
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // STATE
				strcpy(_state,ptr);
				sscanf(_state,"%02X",&state);
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // NIX
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // TIMER
				if ( sscanf(ptr,"%02X:%08lX",&timer_kind,&timer_value) != 2 ) continue;
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // SOMETHING
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // UID
				uid = atoi(ptr);
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // TIMEOUT
				ptr = strtok_r(NULL," \t\r\n",&help);
				if ( ptr == NULL ) continue; // INODE
				f_inode = atol(ptr);
			}
			if ( f_inode == inode ){
				logger("SOCKINFO","[%ld] Local: [%s]:%d Remote: [%s]:%d State: [%s] %d Timer: [%d] Value: [%ld] UID: %d Inode: %ld\n",inode,local,local_port,remote,remote_port,_state,state,timer_kind,timer_value,uid,f_inode);	
				if ( strcmp(procnet[fi],"/proc/net/tcp6") == 0 ){
					// Convert IPv4
					si.family = AF_INET6;
					si.state = state;
					si.uid = uid;
					si.timer_value = timer_value;
					si.timer_kind = timer_kind;
					si.local_port = local_port;					
					si.remote_port = remote_port;					
					si.protocol = SOCK_STREAM;
					strcpy(si.local_addr,get_ipv6(local));
					strcpy(si.remote_addr,get_ipv6(remote));
					fclose(fp);
					return(&si);
				}
				if ( strcmp(procnet[fi],"/proc/net/udp6") == 0 ){
					// Convert IPv4
					si.family = AF_INET6;
					si.state = state;
					si.uid = uid;
					si.timer_value = timer_value;
					si.timer_kind = timer_kind;
					si.local_port = local_port;					
					si.remote_port = remote_port;					
					si.protocol = SOCK_DGRAM;
					strcpy(si.local_addr,get_ipv4(local));
					strcpy(si.remote_addr,get_ipv4(remote));
					fclose(fp);
					return(&si);
				}
				if ( strcmp(procnet[fi],"/proc/net/tcp") == 0 ){
					// Convert IPv4
					si.family = AF_INET;
					si.state = state;
					si.uid = uid;
					si.timer_value = timer_value;
					si.timer_kind = timer_kind;
					si.local_port = local_port;					
					si.remote_port = remote_port;					
					si.protocol = SOCK_STREAM;
					strcpy(si.local_addr,get_ipv4(local));
					strcpy(si.remote_addr,get_ipv4(remote));
					fclose(fp);
					return(&si);
				}
				if ( strcmp(procnet[fi],"/proc/net/udp") == 0 ){
					// Convert IPv4
					si.family = AF_INET;
					si.state = state;
					si.uid = uid;
					si.timer_value = timer_value;
					si.timer_kind = timer_kind;
					si.local_port = local_port;					
					si.remote_port = remote_port;					
					si.protocol = SOCK_DGRAM;
					strcpy(si.local_addr,get_ipv4(local));
					strcpy(si.remote_addr,get_ipv4(remote));
					fclose(fp);
					return(&si);
				}
				if ( strcmp(procnet[fi],"/proc/net/unix") == 0 ){
					// Convert IPv4
					si.family = AF_UNIX;
					si.state = state;
					si.uid = uid;
					si.timer_value = 0;
					si.timer_kind = 0;
					si.local_port = 0;
					si.remote_port = 0;
					si.protocol = -1;
					strcpy(si.local_addr,local);
					strcpy(si.remote_addr,"");
					fclose(fp);
					return(&si);
				}
			}
		}
		fclose(fp);
	}

	return(NULL);
}

int sem_lock(int sem_id){
        struct sembuf ops;
	int retval;
	// logger(prefix,"SEM_LOCK (Current-Value: %d)\n",semctl(semid,0,GETVAL));
        ops.sem_num = 0;
        ops.sem_flg = 0;
        ops.sem_op  = -1;
	while (  (retval = semop(sem_id,&ops,1)) < 0 && errno == EINTR );
	// logger(prefix,"SEM_LOCK finished (Retval: %d) Error: [%s] NEWVAL: %d\n",retval, retval < 0 ? strerror(errno) : "no error" ,semctl(semid,0,GETVAL));
        return(retval);
}
int sem_unlock(int sem_id){
        struct sembuf ops;
	int retval;
	// logger(prefix,"SEM_UNLOCK (Current-Value: %d)\n",semctl(semid,0,GETVAL));
        ops.sem_num = 0;
        ops.sem_flg = 0;
        ops.sem_op  = 1;
	while (  (retval = semop(sem_id,&ops,1)) < 0 && errno == EINTR );
	// logger(prefix,"SEM_UNLOCK finished (Retval: %d) Error: [%s] NEWVAL: %d\n",retval, retval < 0 ? strerror(errno) : "no error",semctl(semid,0,GETVAL) );
        return(retval);
}
int sem_set(int sem_id,int val){
        struct sembuf ops;
        ops.sem_num = 0;
        ops.sem_flg = 0;
        ops.sem_op  = val;
        return(semop(sem_id,&ops,1));
}

#define CCON servlist[global_index].co[connection_index]
#define CSERVER servlist[global_index]

void main_reaper(){
	int status;
	int pid;
	while ( (pid = wait(&status)) < 0 );
	// logger(prefix,"Process %d exited with Status: %d\n",pid,status);
}



struct message {
	int pid;
	char mtext[1];	
};
void slave_reaper(int sig, siginfo_t *siginfo, void *context ){
	struct message mess;
	int status;
	int pid;
	while ( (pid = wait(&status)) < 0 );
	// logger(prefix,"WHILE_WAIT AT SLOT %d --> %d received iIGCHLD [Child: %d]\n",global_index,getpid(),pid);
	
	mess.pid = (long)pid;
	mess.mtext[0] = 'C';
	msgsnd(msg_id, &mess, sizeof(struct message), 0);
	return;
}

void garbage_collect(){
	int pid;
	int wstatus;
	struct message mess;
	char exit_msg[64];
	while ( (pid = waitpid(-1,&wstatus,WNOHANG)) > 0 ){
		sprintf(exit_msg,"OTHER REASON (0x%08X)",wstatus); 
		if ( WIFEXITED(wstatus) ){
			sprintf(exit_msg,"NORMAL EXIT");
		}
		if ( WIFSIGNALED(wstatus) ){
			sprintf(exit_msg,"RECEIVED SIGNAL %d, Core-Dump: [%s]",WTERMSIG(wstatus), WCOREDUMP(wstatus) ? "yes" : "no" );
		}
		if ( WIFSTOPPED(wstatus) ){
			sprintf(exit_msg,"RECEIVED STOP-SIGNAL");
		}
#ifdef WIFCONTINUED
		if ( WIFCONTINUED(wstatus) ){
			sprintf(exit_msg,"RECEIVED CONT-SIGNAL");
		}
#endif
		logger(prefix,"GARBAGE-COLLECT Found PID: %d, EXIT-STATUS: %d REASON: [%s]\n",pid,WEXITSTATUS(wstatus),exit_msg);
		mess.pid = (long)pid;
		mess.mtext[0] = 'C';
		msgsnd(msg_id, &mess, sizeof(struct message), 0);
	}
}


void server_reaper(int sig, siginfo_t *siginfo, void *context){
	struct message mess;
	int status;
	int pid;
	while ( (pid = waitpid(-1,&status,WNOHANG)) > 0 ){
		mess.pid = (long)pid;
		mess.mtext[0] = 'C';
		msgsnd(msg_id, &mess, sizeof(struct message), 0);
	}
	return;
}

void server_reaper_process(){
	struct message mess;
	int status;
	int pid;
	int i;
	semid = semget(INETD_KEY + global_index,1,0);
	semid2 = semget(INETD_KEY2 + global_index,1,0);
	servlist = (struct server *)shmat(shm_id,NULL,0);
	msg_id = msgget(INETD_KEY + global_index,0);
	logger(prefix,"SERVER_REAPER_PROCESS for slot [%d] starting SEMID: %d, SEMID2: %d, Servlist: 0x%08lX\n",global_index,semid,semid2,servlist);
	while ( 1 ){
		int retval;
		// logger(prefix,"START_WAIT AT SLOT %d [%d]\n",global_index,getpid());
		/*
		while ( (pid = waitpid(-1,&status,WNOHANG)) < 0 ){
			logger(prefix,"POLLED_WAIT AT SLOT %d, ERRNO: %d [%s]\n",global_index,errno,strerror(errno));
			sleep(1);
		}
		*/
		bzero(&mess,sizeof(struct message));
		retval = msgrcv(msg_id, &mess,sizeof(struct message),0,0);
		pid = (int) mess.pid;
		sem_lock(semid2);
		for ( i = 0; i < MAX_CONNS; i++ ){
			if ( CSERVER.co[i].cpid == pid  ){
				if ( CSERVER.co[i].port != 0 ){
					logger(prefix,"RECEIVED MESSAGE --> CPID: %d Index: %d\n",pid,i);
					m_kill(CSERVER.co[i].pid,SIGTERM);
					CSERVER.connections--;
					sem_unlock(semid);
					CSERVER.co[i].port = 0;	
				}
			}
			if ( CSERVER.co[i].pid == pid ){
					logger(prefix,"RECEIVED MESSAGE --> PID: %d Index: %d\n",pid,i);
				logger(prefix,"Connection [%s:%d] closed (%d Seconds active)\n",
					CSERVER.co[i].source,CSERVER.co[i].port,time(NULL) - CSERVER.co[i].created);
				if ( CSERVER.co[i].port != 0 ){
					CSERVER.connections--;
					sem_unlock(semid);
					CSERVER.co[i].port = 0;	
				}
				m_kill(CSERVER.co[i].cpid,SIGTERM);
				m_kill(CSERVER.co[i].cpid,SIGHUP);
				m_kill(CSERVER.co[i].cpid,SIGKILL);
				CSERVER.co[i].cpid = 0;	
			}
		}
		sem_unlock(semid2);
	}
	return;
}

#define TYPE_HTML 0
#define TYPE_CSS  1
#define TYPE_AJAX 2
#define HTML_MIME "text/html"
#define CSS_MIME "text/css"
#define AJAX_MIME "text/plain"

void call_webserver(int sock, char *pwd){
	FILE *ss;
	int html_done;
	char buf[102400];
	char temp[1024];
	char temp2[1024];
	char etag[256];
	char referer[1024];
	int content_length;
	int authok;
	int valid;
	char url[128];
	time_t tim;
	char dater[64];
	char *ptr;
	int lines;
	int type_req;
	char method[16];
	char boundary[256];
	char *content;

	gix_options = (struct gix_inetd_options *)shmat(shmid_options,NULL,0);
	if ( gix_options == NULL ){
		logger(prefix,"FATAL(%s:%d) Cannot attach shared-memory\n",__FILE__,__LINE__);
		shutdown(sock,SHUT_RDWR);
		close(sock);
		return;
	}

	servlist = (struct server *)shmat(shm_id,NULL,0);
	if ( servlist == NULL ){
		logger(prefix,"Cannot attach SHM!\n");
		shutdown(sock,SHUT_RDWR);
		close(sock);
		return;
	}
	// logger(prefix,"CALLED ADMIN PWD: [%s]\n",pwd);
	authok = 0;
	valid  = 0;
	{
		int on;
		struct linger linny;
		linny.l_onoff = 1;
		linny.l_linger = 3; // 3 seconds and than die :-)
		if ( setsockopt(sock,SOL_SOCKET,SO_LINGER,&linny,sizeof(linny)) ){
			logger(prefix,"WARNING: cannot set socket to linger-timeout 3\n");
		}	
		on = 1;
		if ( setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,&on,sizeof(on)) ){
			logger(prefix,"WARNING: cannot set socket to KEEP-ALIVE\n");
		}	
		

	}
	ss = fdopen(sock,"w+");
	lines = 0;
	bzero(etag,256);	
	strcpy(referer,"");
	strcpy(method,"");
	content_length = 0;
	bzero(boundary,256);
	while ( fgets(buf,102400,ss) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n' )  buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n' )  buf[strlen(buf)-1] = '\0';
		if ( lines == 0 ){
			if ( strncasecmp(buf,"POST",4) == 0 ){
			 strcpy(method,"POST");
			 valid = 1;
			 ptr = &buf[4];
			 while ( *ptr && ( *ptr == ' ' || *ptr == '\t' ) ) ptr++;
			 strcpy(url,ptr);
			 ptr = url;
			 while ( *ptr && ( *ptr != ' ' && *ptr != '\t' ) ) ptr++;
			 *ptr = '\0';
			}
			if ( strncasecmp(buf,"GET",3) == 0 ){
			 strcpy(method,"GET");
			 valid = 1;
			 ptr = &buf[3];
			 while ( *ptr && ( *ptr == ' ' || *ptr == '\t' ) ) ptr++;
			 strcpy(url,ptr);
			 ptr = url;
			 while ( *ptr && ( *ptr != ' ' && *ptr != '\t' ) ) ptr++;
			 *ptr = '\0';
			}
			if ( strncasecmp(buf,"OPTIONS",7) == 0 ){
			 strcpy(method,"OPTIONS");
			 valid = 1;
			 ptr = &buf[7];
			 while ( *ptr && ( *ptr == ' ' || *ptr == '\t' ) ) ptr++;
			 strcpy(url,ptr);
			 ptr = url;
			 while ( *ptr && ( *ptr != ' ' && *ptr != '\t' ) ) ptr++;
			 *ptr = '\0';
			}
		}
		lines++;
		if ( strncasecmp(buf,"Content-Type:",strlen("Content-Type:")) == 0 ){
			char *ptr2;
			ptr = &buf[strlen("Content-Type:")];
			while ( *ptr && ( *ptr == ' ' || *ptr == '\t' ) ) ptr++;
			strcpy(temp,ptr);
			ptr2 = temp;
			while ( *ptr2 && !isspace(*ptr2) ) ptr2++;
			*ptr2 = '\0';
			ptr += strlen(temp);
			if ( temp[strlen(temp)-1] == ';' ) temp[strlen(temp)-1] = '\0';
			// logger(prefix,"HTML------------> PTR:     [%s]\n",ptr);
			// logger(prefix,"HTML------------> CONTENT: [%s]\n",temp);
			if ( strcasecmp(temp,"multipart/form-data") == 0 ) {
				ptr2 = strstr(ptr,"boundary=");
				if ( ptr2 != NULL ){
					ptr = ptr2 + strlen("boundary=");
					strcpy(boundary,ptr);
					ptr = boundary;
					while ( *ptr && !isspace(*ptr) && *ptr != ';' ) ptr++;
					*ptr = '\0';	
					ptr = boundary;
					// logger(prefix,"HTML------------> BOUNDARY: [%s]\n",boundary);
				}	
			}
			
		}
		if ( strncasecmp(buf,"Content-Length:",strlen("Content-Length:")) == 0 ){
			ptr = &buf[strlen("Content-Length:")];
			while ( *ptr && ( *ptr == ' ' || *ptr == '\t' ) ) ptr++;
			content_length = atoi(ptr);
		}
		if ( strncasecmp(buf,"Authorization:",strlen("Authorization:")) == 0 ){
			ptr = &buf[strlen("Authorization:")];
			while ( *ptr && ( *ptr == ' ' || *ptr == '\t' ) ) ptr++;
			strcpy(temp,ptr);	
			ptr = temp;
			while ( *ptr && ( *ptr != ' ' && *ptr != '\t' ) ) ptr++;
			*ptr = '\0';
			if ( strcasecmp(temp,"basic") == 0 ){
				unsigned char credentials[128];
			
				int len;
				ptr++;
				while ( *ptr && ( *ptr == ' ' || *ptr == '\t' ) ) ptr++;
				strcpy(temp2,ptr);
				ptr = temp2;
				while ( *ptr && ( *ptr != ' ' && *ptr != '\t' ) ) ptr++;
				*ptr = '\0';
				len = debase64(temp2,credentials);
				// logger(prefix,"AUTH-BASE64: [%s] --> [%s], should be: [*:%s]\n",temp2,credentials,pwd);	
				ptr = strtok(credentials,":");
				if ( ptr != NULL ){
					// We do not care about user :-)		
					ptr = strtok(NULL,":");
					if ( ptr != NULL ){
						if ( strcmp(ptr,pwd) == 0 ) authok = 1;
					}
				}
			}
		}
		if ( strncasecmp(buf,"Referer:",strlen("Referer:")) == 0 ){
			char gaense;
			int slashes;
			ptr = &buf[strlen("Referer:")];
			while ( *ptr && ( *ptr == ' ' || *ptr == '\t' ) ) ptr++;
			strcpy(referer,ptr);
			slashes = 0;
			ptr = referer;
			while ( *ptr ){
				if ( *ptr == '/' ) slashes++;
				if ( slashes == 3 ) break;
				ptr++;
			}
			*ptr = '\0';
			
		}
		if ( strncasecmp(buf,"If-None-Match:",strlen("If-None-Match:")) == 0 ){
			char gaense;
			ptr = &buf[strlen("If-None-Match:")];
			while ( *ptr && ( *ptr == ' ' || *ptr == '\t' ) ) ptr++;
			if ( *ptr == '\"' || *ptr == '\'' ){
				ptr++;
				strcpy(etag,ptr);
				if ( etag[strlen(etag)-1] == '\"' || etag[strlen(etag)-1] == '\'' ) etag[strlen(etag)-1] = '\0';
			} else {
				strcpy(etag,ptr);
			}
		}
		if ( strlen(buf) < 1 ) break;
		// logger(prefix,"HTML<< [%s]\n",buf);
	}	
	// logger(prefix,"HTML-----------------------------------\n");
	logger(prefix,"HTML << METHOD: [%s] C-LENGTH: %d, URL: [%s] Auth-OK: [%d] Valid-Request: [%d] ETAG: [%s] Referer: [%s] BOUNDARY: [%s]\n",method,content_length,url,authok,valid,etag,referer,boundary);
	if ( content_length ){
		content = (char *)malloc(content_length + 1);
		if ( fread(content,1,content_length,ss) != content_length ){
			tim = time(NULL);
			fprintf(ss,"HTTP/1.1 401 Authorization Required\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"WWW-Authenticate: Basic realm=\"GIX-INETD-Admin\"\r\n");
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"Content-Type: text/html\r\n\r\n");
			fprintf(ss,"<H1>Access denied</H1>\r\n");
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
	}
	if ( strcmp(method,"POST") == 0 ){
		char ACTION[32];
		struct multi *mul;
		int multis;
		int idx;

		multis = load_multis(content,content_length,boundary);
		for ( idx = 0; idx < multis; idx++ ){
			mul = read_multi_index(idx);
			logger(prefix,"MULTI[%d] Name: [%s](%d Bytes) --> [%.20s]\n",idx,mul->name,mul->size,mul->content);
		}
		

		mul = read_multi("ACTION");
		if ( mul == NULL ){
			logger(prefix,"NO ACTION specified!\n");
			tim = time(NULL);
			fprintf(ss,"HTTP/1.1 401 Authorization Required\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"WWW-Authenticate: Basic realm=\"GIX-INETD-Admin\"\r\n");
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"Content-Type: text/html\r\n\r\n");
			fprintf(ss,"<H1>Access denied</H1>\r\n");
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		strcpy(ACTION,mul->content);
		logger(prefix,"REQUESTED ACTION: [%s]\n",ACTION);	

		if ( strcmp(ACTION,"SAVE_CONFIG") == 0 ){
			char FILENAME[1024];
			char fname[1024];
			FILE *fp;

			send_valid_header(ss,referer);

			mul = read_multi("FILE");
			if ( mul == 0 ){
				fprintf(ss,"ERR[No FILE specified]\r\n");
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			strcpy(FILENAME,mul->content);
			sprintf(fname,"/big/GIX_INETD/conf/%s",FILENAME);
			logger(prefix,"Using file: [%s]\n",fname);

			mul = read_multi("DATA");
			if ( mul == 0 ){
				fprintf(ss,"ERR[No DATA specified]\r\n");
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			logger(prefix,"Saving %d Bytes to [%s]\n",mul->size,fname);

			unlink(fname);

			fp = fopen(fname,"w");
			if ( fp == NULL ){
				fprintf(ss,"ERR[Cannot open '%s']\r\n",fname);
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			fwrite(mul->content,1,mul->size,fp);
			fclose(fp);

			fprintf(ss,"OK[Configuration saved]\r\n");
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		if ( strcmp(ACTION,"LOAD_CONFIG") == 0 ){
			char FILENAME[1024];
			char fname[1024];
			struct stat st;
			char *json;
			FILE *fp;

			send_valid_header(ss,referer);

			mul = read_multi("FILE");
			if ( mul == 0 ){
				fprintf(ss,"ERR[No FILE specified]\r\n");
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			strcpy(FILENAME,mul->content);
			sprintf(fname,"/big/GIX_INETD/conf/%s",FILENAME);
			logger(prefix,"Reading file: [%s]\n",fname);
			if ( stat(fname,&st) ){
				fprintf(ss,"ERR[Cannot stat '%s']\r\n",fname);
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			json = (char *)malloc(st.st_size+1);
			bzero(json,st.st_size+1);
		
			fp = fopen(fname,"r");
			if ( fp == NULL ){
				fprintf(ss,"ERR[Cannot open '%s']\r\n",fname);
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			fread(json,1,st.st_size,fp);
			fclose(fp);
			if ( json[strlen(json)-1] == '\r' || json[strlen(json)-1] == '\n' ) json[strlen(json)-1] = '\0';
			if ( json[strlen(json)-1] == '\r' || json[strlen(json)-1] == '\n' ) json[strlen(json)-1] = '\0';
			fprintf(ss,"OK[%s]\r\n",json);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		
		send_valid_header(ss,referer);
		logger(prefix,"NO valid ACTION specified!\n");
		fprintf(ss,"ERR[No valid action!]\r\n");
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
		
	}
	
	

	if ( strcmp(method,"OPTIONS") == 0 ){
		// logger(prefix,"HTML>> HTTP/1.1 204 No content\r\n");
		fprintf(ss,"HTTP/1.1 204 No content\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		if ( strlen(referer)) logger(prefix,"HTML>> Access-Control-Allow-Origin: %s\r\n",referer);
		// logger(prefix,"HTML>> Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n");
		fprintf(ss,"Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n");
		// logger(prefix,"HTML>> Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Access-Control-Allow-Headers: Authorization, Content-Type\r\n");
		// logger(prefix,"HTML>> Access-Control-Allow-Headers: Authorization, Content-Type\r\n");
		fprintf(ss,"Access-Control-Allow-Credentials: true\r\n");
		// logger(prefix,"HTML>> Access-Control-Allow-Credentials: true\r\n");
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		// logger(prefix,"HTML>> Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		// logger(prefix,"HTML>> Connection: close\r\n\r\n");
		fprintf(ss,"Connection: close\r\n\r\n");
		fflush(ss);
		logger(prefix,"OPTIONS-HEADER processed...\n");
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}

	if ( valid == 0 ){
		tim = time(NULL);
		fprintf(ss,"HTTP/1.1 401 Authorization Required\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"WWW-Authenticate: Basic realm=\"GIX-INETD-Admin\"\r\n");
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Content-Type: text/html\r\n\r\n");
		fprintf(ss,"<H1>Access denied</H1>\r\n");
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}

	// Only version asking is allowed :-)
	if ( strcmp(url,"/version") == 0 ){
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Content-Type: text/plain;\r\n\r\n");
		fprintf(ss,"OK[{\"hostname\":\"%s\",\"version\":\"%s\"}]\r\n",my_hostname,GIX_INETD_VERSION);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}

	if ( authok == 0 ){
		tim = time(NULL);
		fprintf(ss,"HTTP/1.1 401 Authorization Required\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"WWW-Authenticate: Basic realm=\"GIX-INETD-Admin\"\r\n");
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Content-Type: text/html\r\n\r\n");
		fprintf(ss,"<H1>Access denied</H1>\r\n");
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
	if ( strcmp(url,"/version_s") == 0 ){
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Content-Type: text/plain;\r\n\r\n");
		fprintf(ss,"OK[{\"hostname\":\"%s\",\"version\":\"%s\"}]\r\n",my_hostname,GIX_INETD_VERSION);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
	if ( strncmp(url,"/update_version/",strlen("/update_version/")) == 0 ){
		char tempfile[1024];
		char filelist[1024];
		char buf[1024];
		int retval;
		FILE *in, *out;

		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Content-Type: text/plain;\r\n\r\n");

		sprintf(tempfile,"/tmp/dirlist_ginetd_%d.data",getpid());
		sprintf(filelist,"/tmp/list_ginetd_%d.data",getpid());
		unlink(tempfile);
		unlink(filelist);
		ftp_list(GIX_INETD_UPDATESERVER,"/big/GIX_INETD/src",tempfile);
		logger(prefix,"Getting directory-list from [%s] Path: [%s] --> %d\n",GIX_INETD_UPDATESERVER,tempfile,retval);
		
		in = fopen(tempfile,"r");
		if ( in == NULL ){
			unlink(tempfile);
			unlink(filelist);
			fprintf(ss,"ERR[Cannot open '%s' for reading]\r\n",tempfile);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}		
		out = fopen(filelist,"w");
		if ( out == NULL ){
			unlink(tempfile);
			unlink(filelist);
			fprintf(ss,"ERR[Cannot open '%s' for writing]\r\n",filelist);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		while ( fgets(buf,1024,in) != NULL ){
			char *ptr;
			if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n' ) buf[strlen(buf)-1] = '\0';
			if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n' ) buf[strlen(buf)-1] = '\0';
			ptr = &buf[strlen(buf)-1];
			while ( ptr > buf && !isspace(*ptr) ) ptr--;
			if ( isspace(*ptr) ) ptr++;
			if ( strcmp(ptr,"Makefile") == 0 ){
				fprintf(out,"%s\n",ptr);
			}
			if ( strcmp(ptr,"update.sh") == 0 ){
				fprintf(out,"%s\n",ptr);
			}
			if ( strlen(ptr) > 2 && ( strcmp(&ptr[strlen(ptr)-2],".c") == 0 || strcmp(&ptr[strlen(ptr)-2],".h") == 0 ) ){
				fprintf(out,"%s\n",ptr);
			}
		}
		fclose(in);
		fclose(out);
		unlink(tempfile);
		in = fopen(filelist,"r");
		if ( in == NULL ){
			unlink(tempfile);
			unlink(filelist);
			fprintf(ss,"ERR[Cannot open '%s' for reading]\r\n",filelist);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}		
		while ( fgets(buf,1024,in) != NULL ){
			char fname[1024];
			if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n' ) buf[strlen(buf)-1] = '\0';
			if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n' ) buf[strlen(buf)-1] = '\0';
			sprintf(fname,"/big/GIX_INETD/src/%s",buf);
			logger(prefix,"UPDATE...Getting: [%s]\n",fname);
			ftp_get(GIX_INETD_UPDATESERVER,fname,fname);	
		}
		fclose(in);
		


		logger(prefix,"Starting update...\n");
		chdir("/big/GIX_INETD/src");
		system("make clean ; make > /tmp/make.log 2>&1");
		// Ok we have the list :-)
			
		fprintf(ss,"OK[Update will be done...]\r\n");
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
	tim = time(NULL);
        if ( strcmp(url,"/favicon.ico") == 0 ){
		if ( strlen(etag) && strcmp(etag,gix_img_gixicon_etag) == 0 ){
			// logger(prefix,"HTML --> Sending ETAG-OK Header\n");
			fprintf(ss,"HTTP/1.1 304 Not Modified\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"ETag: \"%s\"\r\n\r\n",etag);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer) )fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Accept-Ranges: bytes\r\n");
		fprintf(ss,"Content-Length: %d\r\n",gix_img_gixicon_len);
		fprintf(ss,"ETag: \"%s\"\r\n",gix_img_gixicon_etag);
		fprintf(ss,"Content-Type: image/x-icon\r\n\r\n");
		fwrite(gix_img_gixicon_bin,1,gix_img_gixicon_len,ss);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
        if ( strcmp(url,"/gix_logo.png") == 0 ){
		if ( strlen(etag) && strcmp(etag,gix_img_gixlogo_etag) == 0 ){
			// logger(prefix,"HTML --> Sending ETAG-OK Header\n");
			fprintf(ss,"HTTP/1.1 304 Not Modified\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"ETag: \"%s\"\r\n\r\n",etag);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Accept-Ranges: bytes\r\n");
		fprintf(ss,"Content-Length: %d\r\n",gix_img_gixlogo_len);
		fprintf(ss,"ETag: \"%s\"\r\n",gix_img_gixlogo_etag);
		fprintf(ss,"Content-Type: image/png\r\n\r\n");
		fwrite(gix_img_gixlogo_bin,1,gix_img_gixlogo_len,ss);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
        if ( strcmp(url,"/led_orange.gif") == 0 ){
		if ( strlen(etag) && strcmp(etag,gix_img_led_orange_etag) == 0 ){ 
			// logger(prefix,"HTML --> Sending ETAG-OK Header\n");
			fprintf(ss,"HTTP/1.1 304 Not Modified\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"ETag: \"%s\"\r\n\r\n",etag);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Accept-Ranges: bytes\r\n");
		fprintf(ss,"Content-Length: %d\r\n",gix_img_led_orange_len);
		fprintf(ss,"ETag: \"%s\"\r\n",gix_img_led_orange_etag);
		fprintf(ss,"Content-Type: image/gif\r\n\r\n");
		fwrite(gix_img_led_orange_bin,1,gix_img_led_orange_len,ss);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
        if ( strcmp(url,"/led_red.gif") == 0 ){
		if ( strlen(etag) && strcmp(etag,gix_img_led_red_etag) == 0 ){ 
			// logger(prefix,"HTML --> Sending ETAG-OK Header\n");
			fprintf(ss,"HTTP/1.1 304 Not Modified\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"ETag: \"%s\"\r\n\r\n",etag);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Accept-Ranges: bytes\r\n");
		fprintf(ss,"Content-Length: %d\r\n",gix_img_led_red_len);
		fprintf(ss,"ETag: \"%s\"\r\n",gix_img_led_red_etag);
		fprintf(ss,"Content-Type: image/gif\r\n\r\n");
		fwrite(gix_img_led_red_bin,1,gix_img_led_red_len,ss);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
        if ( strcmp(url,"/led_blue.gif") == 0 ){
		if ( strlen(etag) && strcmp(etag,gix_img_led_red_etag) == 0 ){ 
			// logger(prefix,"HTML --> Sending ETAG-OK Header\n");
			fprintf(ss,"HTTP/1.1 304 Not Modified\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"ETag: \"%s\"\r\n\r\n",etag);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Accept-Ranges: bytes\r\n");
		fprintf(ss,"Content-Length: %d\r\n",gix_img_led_blue_len);
		fprintf(ss,"ETag: \"%s\"\r\n",gix_img_led_blue_etag);
		fprintf(ss,"Content-Type: image/gif\r\n\r\n");
		fwrite(gix_img_led_blue_bin,1,gix_img_led_blue_len,ss);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
        if ( strcmp(url,"/led_green.gif") == 0 ){
		if ( strlen(etag) && strcmp(etag,gix_img_led_red_etag) == 0 ){ 
			// logger(prefix,"HTML --> Sending ETAG-OK Header\n");
			fprintf(ss,"HTTP/1.1 304 Not Modified\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"ETag: \"%s\"\r\n\r\n",etag);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Accept-Ranges: bytes\r\n");
		fprintf(ss,"Content-Length: %d\r\n",gix_img_led_green_len);
		fprintf(ss,"ETag: \"%s\"\r\n",gix_img_led_green_etag);
		fprintf(ss,"Content-Type: image/gif\r\n\r\n");
		fwrite(gix_img_led_green_bin,1,gix_img_led_green_len,ss);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
        if ( strcmp(url,"/empty.gif") == 0 ){
		if ( strlen(etag) && strcmp(etag,gix_img_empty_etag) == 0 ){ 
			// logger(prefix,"HTML --> Sending ETAG-OK Header\n");
			fprintf(ss,"HTTP/1.1 304 Not Modified\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"ETag: \"%s\"\r\n\r\n",etag);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Accept-Ranges: bytes\r\n");
		fprintf(ss,"Content-Length: %d\r\n",gix_img_empty_len);
		fprintf(ss,"ETag: \"%s\"\r\n",gix_img_empty_etag);
		fprintf(ss,"Content-Type: image/gif\r\n\r\n");
		fwrite(gix_img_empty_bin,1,gix_img_empty_len,ss);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
        if ( strcmp(url,"/new_rotator_small.gif") == 0 ){
		if ( strlen(etag) && strcmp(etag,gix_img_new_rotator_small_etag) == 0 ){ 
			// logger(prefix,"HTML --> Sending ETAG-OK Header\n");
			fprintf(ss,"HTTP/1.1 304 Not Modified\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"ETag: \"%s\"\r\n\r\n",etag);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Accept-Ranges: bytes\r\n");
		fprintf(ss,"Content-Length: %d\r\n",gix_img_new_rotator_small_len);
		fprintf(ss,"ETag: \"%s\"\r\n",gix_img_new_rotator_small_etag);
		fprintf(ss,"Content-Type: image/gif\r\n\r\n");
		fwrite(gix_img_new_rotator_small_bin,1,gix_img_new_rotator_small_len,ss);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
        if ( strcmp(url,"/new_rotator_big.gif") == 0 ){
		if ( strlen(etag) && strcmp(etag,gix_img_new_rotator_big_etag) == 0 ){ 
			// logger(prefix,"HTML --> Sending ETAG-OK Header\n");
			fprintf(ss,"HTTP/1.1 304 Not Modified\r\n");
			if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
			fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
			fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
			fprintf(ss,"Connection: close\r\n");
			fprintf(ss,"ETag: \"%s\"\r\n\r\n",etag);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		fprintf(ss,"HTTP/1.1 200 OK\r\n");
		if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
		fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
		fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
		fprintf(ss,"Connection: close\r\n");
		fprintf(ss,"Accept-Ranges: bytes\r\n");
		fprintf(ss,"Content-Length: %d\r\n",gix_img_new_rotator_big_len);
		fprintf(ss,"ETag: \"%s\"\r\n",gix_img_new_rotator_big_etag);
		fprintf(ss,"Content-Type: image/gif\r\n\r\n");
		fwrite(gix_img_new_rotator_big_bin,1,gix_img_new_rotator_big_len,ss);
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
	fprintf(ss,"HTTP/1.1 200 OK\r\n");
	if ( strlen(referer)) fprintf(ss,"Access-Control-Allow-Origin: %s\r\n",referer);
	fprintf(ss,"Date: %s\r\n",ctime_o(&tim,dater));
	fprintf(ss,"Server: %s\r\n",GIX_INETD_VERSION);
	fprintf(ss,"Connection: close\r\n");
	type_req = TYPE_HTML;
	if ( strstr(url,"/ajax/") != NULL ) type_req = TYPE_AJAX;
	if ( strcmp(url,"/style.css") == 0  ) type_req = TYPE_CSS;

	if ( type_req == TYPE_CSS ){
		fprintf(ss,"Content-Type: text/css\r\n\r\n");
		fprintf(ss,"div.fixed_download {\n");
		fprintf(ss," display: block;\n");
		fprintf(ss," visibility: hidden;\n");
		fprintf(ss," z-index: 13;\n");
		fprintf(ss," position: fixed;\n");
		fprintf(ss," top: 5%;\n");
		fprintf(ss," left: 5%;\n");
		fprintf(ss," width: 90%;\n");
		fprintf(ss," height: 90%;\n");
		fprintf(ss," border: 1px solid black;\n");
		fprintf(ss," box-shadow: 10px 15px 20px black;\n");
		fprintf(ss," padding: 5px;\n");
		fprintf(ss," overflow: auto;\n");
		fprintf(ss," background-color: rgba(0,0,0,0.9);\n");
		fprintf(ss,"}\n");
		fprintf(ss,".mainbody {\n");
		fprintf(ss," background-color: rgb(200,200,200);\n");
		fprintf(ss,"}\n");
		fprintf(ss,".headline {\n");
		fprintf(ss," left: 5%%;\n");
		fprintf(ss," right: 5%%;\n");
		fprintf(ss," z-index: 10;\n");
		fprintf(ss," border: 1px solid black;\n");
		fprintf(ss," position:  fixed;\n");
		fprintf(ss," top: 10px;\n");
		fprintf(ss," margin-right: auto;\n");
		fprintf(ss," margin-left: auto;\n");
		fprintf(ss," background-color: rgb(180,180,180);\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 24px;\n");
		fprintf(ss," width: 90%%;\n");
		fprintf(ss," padding: 4px;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".rotator_div {\n");
		// fprintf(ss," border: 1px solid green;\n");
		// fprintf(ss," width: 100px;\n");
		// fprintf(ss," height: 100px;\n");
		fprintf(ss," padding-left: 40%%;\n");
		fprintf(ss," padding-right: 10px;\n");
		fprintf(ss," padding-top: 25px;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".fd_div {\n");
		fprintf(ss," max-height: 500px;\n");
		fprintf(ss," overflow-y: auto;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".table_list2 {\n");
		fprintf(ss," position: relative;\n");
		fprintf(ss," background-color: grey;\n");
		// fprintf(ss," width: 90%%;\n");
		fprintf(ss," height: 85%%;\n");
		// fprintf(ss," left: 5%%;\n");
		fprintf(ss," top: 5%%;\n");
		fprintf(ss," border: 1px solid white;\n");
		fprintf(ss," overflow-y: auto;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".table_list {\n");
		fprintf(ss," position: relative;\n");
		fprintf(ss," background-color: grey;\n");
		// fprintf(ss," width: 90%%;\n");
		fprintf(ss," height: 85%%;\n");
		// fprintf(ss," left: 5%%;\n");
		fprintf(ss," top: 5%%;\n");
		fprintf(ss," border: 1px solid white;\n");
		fprintf(ss," overflow-y: auto;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".headliner {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 20px;\n");
		fprintf(ss," font-weight: bold;\n");
		fprintf(ss,"}\n");

		fprintf(ss,".gcanvas1 {\n");
		// fprintf(ss," width: 400;\n");
		// fprintf(ss," height: 100;\n");
		fprintf(ss," border: 1px solid black;\n");
		fprintf(ss," background-color: white;\n");
		fprintf(ss,"}\n");

		fprintf(ss,".ethlist {\n");
		// fprintf(ss," max-height: 300px;\n");
		// fprintf(ss," overflow-y: auto;\n");
		fprintf(ss,"}\n");

		fprintf(ss,".mainscreen {\n");
		fprintf(ss," left: 5%%;\n");
		fprintf(ss," right: 5%%;\n");
		fprintf(ss," z-index: 10;\n");
		fprintf(ss," overflow-y: auto;\n");
		fprintf(ss," position:  fixed;\n");
		fprintf(ss," margin-right: auto;\n");
		fprintf(ss," margin-left: auto;\n");
		fprintf(ss," background-color: rgb(180,180,180);\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 16px;\n");
		fprintf(ss," padding: 10px;\n");
		fprintf(ss," border: 1px solid black;\n");
		fprintf(ss," width: 90%%;\n");
		fprintf(ss," max-height: 70%%;\n");
		fprintf(ss," top: 15%%;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".procinfo {\n");
		fprintf(ss,"  height: 400px;\n");
		fprintf(ss,"  overflow-y: scroll;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".theadbig {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 24px;\n");
		fprintf(ss," color: white;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead1s {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," color: red;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".input1s {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," color: red;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".input2s {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," color: black;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".input2serror {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," border: 2px solid red;\n");
		fprintf(ss," color: red;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead2s {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," color: black;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead2sw {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," color: orange;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead2slink {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss," color: blue;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead2slink:hover {\n");
		fprintf(ss," font-weight: bold;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead3s {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," color: blue;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead3s:hover {\n");
		fprintf(ss," font-weight: bold;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead4s {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," color: green;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead1 {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 14px;\n");
		fprintf(ss," color: red;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead2 {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 14px;\n");
		fprintf(ss," color: black;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead2link {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 14px;\n");
		fprintf(ss," color: blue;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead2links {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," color: blue;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead2link:hover {\n");
		fprintf(ss," font-weight: bold;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead3 {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 14px;\n");
		fprintf(ss," font-weight: bold;\n");
		fprintf(ss," color: green;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead10 {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 14px;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss," color: red;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead20 {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 14px;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss," color: black;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead30 {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 14px;\n");
		fprintf(ss," font-weight: bold;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss," color: green;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead20s {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss," color: black;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".thead30s {\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," font-weight: bold;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss," color: green;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".info_div {\n");
		fprintf(ss,"  position: fixed;\n");
		fprintf(ss,"  padding: 4px;\n");
		fprintf(ss,"  z-index: 13;\n");
		fprintf(ss,"  border: 1px solid black;\n");
		fprintf(ss,"  top: 10%%;\n");
		fprintf(ss,"  left: 5%%;\n");
		fprintf(ss,"  width: 90%%;\n");
		fprintf(ss,"  height: 80%%;\n");
		fprintf(ss,"  box-shadow: 10px 15px 20px black;\n");
		fprintf(ss,"  background-color: rgba(0,0,0,0.9);\n");
		fprintf(ss,"}\n");
		fprintf(ss,".footer {\n");
		fprintf(ss," position:  fixed;\n");
		fprintf(ss," z-index: 10;\n");
		fprintf(ss," border: 1px solid black;\n");
		fprintf(ss," background-color: rgb(180,180,180);\n");
		fprintf(ss," left: 5%%;\n");
		fprintf(ss," right: 5%%;\n");
		fprintf(ss," margin-right: auto;\n");
		fprintf(ss," margin-left: auto;\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 16px;\n");
		fprintf(ss," top: 90%%;\n");
		fprintf(ss," width: 90%%;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".filemanagerclose2 {\n");
		fprintf(ss,"  font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss,"  color: white;\n");
		fprintf(ss,"  font-size: 48px;\n");
		fprintf(ss,"  font-weight: bold;\n");
		fprintf(ss,"  cursor: pointer;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".filemanagerclose2:hover {\n");
		fprintf(ss,"  color: green;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".standard_buttons {\n");
		fprintf(ss," background-color: #DD2211;\n");
		fprintf(ss," border: none;\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 12px;\n");
		fprintf(ss," text-align: center;\n");
		fprintf(ss," text-decoration: none;\n");
		fprintf(ss," display: inline-block;\n");
		fprintf(ss," color: white;\n");
		fprintf(ss," padding: 2px 5px;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".standard_buttons:hover {\n");
		fprintf(ss," font-weight: bold;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".standard_button {\n");
		fprintf(ss," background-color: #DD2211;\n");
		fprintf(ss," border: none;\n");
		fprintf(ss," font-family: Optima, Geneva, sans-serif;\n");
		fprintf(ss," font-size: 14px;\n");
		fprintf(ss," text-align: center;\n");
		fprintf(ss," text-decoration: none;\n");
		fprintf(ss," display: inline-block;\n");
		fprintf(ss," color: white;\n");
		fprintf(ss," padding: 4px 10px;\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".standard_button:hover {\n");
		fprintf(ss," font-weight: bold;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".l_image {\n");
		fprintf(ss," cursor: pointer;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".l_image:hover {\n");
		fprintf(ss," border: 1px solid black;\n");
		fprintf(ss,"}\n");
		fprintf(ss,".simple_div: {\n");
		fprintf(ss," border: 1px solid black;\n");
		fprintf(ss,"}\n");


		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
	if ( type_req == TYPE_AJAX ){
		char command[256];
		char argument[256];
		char *ptr;
		fprintf(ss,"Content-Type: %s\r\n",AJAX_MIME);
		ptr = &url[strlen("/ajax/")];
		bzero(command,256);
		strcpy(command,ptr);
		ptr = command;
		while ( *ptr && ( *ptr != '/' )) ptr++;
		*ptr = '\0';
		ptr++;
		strcpy(argument,ptr);
		logger(prefix,"AJAX-COMMAND: [%s] Argument: [%s]\n",command,argument);	


		if ( strcmp(command,"SET_TFTP_ENABLE") == 0 ){
			gix_options->tftp_enabled = atoi(argument);
			fprintf(ss,"\r\n[OK]\r\n"); 
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		if ( strcmp(command,"SET_TFTP_READONLY") == 0 ){
			gix_options->tftp_readonly = atoi(argument);
			fprintf(ss,"\r\n[OK]\r\n"); 
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		if ( strcmp(command,"SET_TFTP_ROOT") == 0 ){
			strcpy(gix_options->tftp_root,argument);
			fprintf(ss,"\r\n[OK]\r\n"); 
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}



		if ( strcmp(command,"CONNSLIST") == 0 ){
			int idx,i;
			char *result;
			char line[1024];
			idx = atoi(argument);
			if ( idx >= entries ){
				fprintf(ss,"\r\nERR[Bad Index]\r\n");
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			result = strdup("[");
			sem_lock(semid2);
			for ( i = 0; i < MAX_CONNS; i++ ){
				if ( servlist[idx].co[i].port != 0 ){
					struct tm *tm;
					char procfile[1024];
					char cmdline[1024];
					char stack[128];
					char cwd[512];
					char data[128];
					char exe[128];
					char lib[128];
					size_t _io_read;
					size_t _io_write;
					double io_read;
					double io_write;
					double io_read_sec;
					double io_write_sec;
					char io_read_text[1024];
					char io_write_text[1024];
					char io_read_sec_text[1024];
					char io_write_sec_text[1024];
					char source_addr_text[128];	
					char target_addr_text[128];	
					char netstat_file[1024];
					char tcp_state[16];
					char tcp_timeout[32];
					double helper;
					double diff;
					int threads;
					char *ptr;
					FILE *fp;


					strcpy(netstat_file,"");
					strcpy(tcp_state,"UNKNOWN");	
					strcpy(tcp_timeout,"UNKNOWN");	
					bzero(lib,sizeof(lib));
					bzero(exe,sizeof(exe));
					bzero(stack,sizeof(stack));
					bzero(data,sizeof(data));
					bzero(procfile,sizeof(procfile));
					bzero(cmdline,sizeof(cmdline));
					bzero(io_read_text,sizeof(io_read_text));
					bzero(io_write_text,sizeof(io_write_text));
					bzero(io_read_sec_text,sizeof(io_read_sec_text));
					bzero(io_write_sec_text,sizeof(io_write_sec_text));
					bzero(source_addr_text,sizeof(source_addr_text));
					bzero(target_addr_text,sizeof(target_addr_text));
					bzero(cwd,512);


					sprintf(procfile,"/proc/%d/cwd",servlist[idx].co[i].cpid);
					if ( readlink(procfile,cwd,512) < 0 ){
						logger(prefix,"####################### Failed to read symlink [%s]\n",procfile);
						strcpy(cwd,"n.a.");
					}
					
					if ( servlist[idx].family == AF_INET6 ){
						int j;
				        	struct addrinfo *res;
       						struct addrinfo hints;
						struct sockaddr_in6 sin6;
						sprintf(netstat_file,"/proc/net/tcp6");
						bzero(&hints,sizeof(hints));
						hints.ai_family   = AF_INET6;
						hints.ai_flags    = AI_NUMERICHOST;
						hints.ai_socktype = SOCK_STREAM;
						if ( getaddrinfo(servlist[idx].co[i].source,NULL,&hints,&res)  ){
							logger(prefix,"##################### FAILED TO CONVERT: [%s]\n",servlist[idx].co[i].source);
						} else {
							unsigned char hlp[16];
							unsigned long *x0,*x2,*x3,*x4;
							memcpy( (void *)&sin6,(void *)res->ai_addr,res->ai_addrlen);
							hlp[0] = (unsigned char) sin6.sin6_addr.s6_addr[3];
							hlp[1] = (unsigned char) sin6.sin6_addr.s6_addr[2];
							hlp[2] = (unsigned char) sin6.sin6_addr.s6_addr[1];
							hlp[3] = (unsigned char) sin6.sin6_addr.s6_addr[0];
							hlp[4] = (unsigned char) sin6.sin6_addr.s6_addr[7];
							hlp[5] = (unsigned char) sin6.sin6_addr.s6_addr[6];
							hlp[6] = (unsigned char) sin6.sin6_addr.s6_addr[5];
							hlp[7] = (unsigned char) sin6.sin6_addr.s6_addr[4];
							hlp[8] = (unsigned char) sin6.sin6_addr.s6_addr[11];
							hlp[9] = (unsigned char) sin6.sin6_addr.s6_addr[10];
							hlp[10] = (unsigned char) sin6.sin6_addr.s6_addr[9];
							hlp[11] = (unsigned char) sin6.sin6_addr.s6_addr[8];
							hlp[12] = (unsigned char) sin6.sin6_addr.s6_addr[15];
							hlp[13] = (unsigned char) sin6.sin6_addr.s6_addr[14];
							hlp[14] = (unsigned char) sin6.sin6_addr.s6_addr[13];
							hlp[15] = (unsigned char) sin6.sin6_addr.s6_addr[12];
							strcpy(source_addr_text,"");
							for ( j = 0; j < 16; j++ ){
								sprintf(&source_addr_text[strlen(source_addr_text)],"%02X",(unsigned char) hlp[j]);
							}	
							sprintf(&source_addr_text[strlen(source_addr_text)],":%04X",(unsigned int)servlist[idx].co[i].port);
							// logger(prefix,"ADDRESS_CONV_SOURCE ********** [%s]:[%d] --> [%s]\n",servlist[idx].co[i].source,servlist[idx].co[i].port,source_addr_text);
						}
						if ( getaddrinfo(servlist[idx].co[i].target,NULL,&hints,&res)  ){
							logger(prefix,"##################### FAILED TO CONVERT: [%s]\n",servlist[idx].co[i].target);
						} else {
							unsigned char hlp[16];
							unsigned long *x0,*x2,*x3,*x4;
							memcpy( (void *)&sin6,(void *)res->ai_addr,res->ai_addrlen);
							hlp[0] = (unsigned char) sin6.sin6_addr.s6_addr[3];
							hlp[1] = (unsigned char) sin6.sin6_addr.s6_addr[2];
							hlp[2] = (unsigned char) sin6.sin6_addr.s6_addr[1];
							hlp[3] = (unsigned char) sin6.sin6_addr.s6_addr[0];
							hlp[4] = (unsigned char) sin6.sin6_addr.s6_addr[7];
							hlp[5] = (unsigned char) sin6.sin6_addr.s6_addr[6];
							hlp[6] = (unsigned char) sin6.sin6_addr.s6_addr[5];
							hlp[7] = (unsigned char) sin6.sin6_addr.s6_addr[4];
							hlp[8] = (unsigned char) sin6.sin6_addr.s6_addr[11];
							hlp[9] = (unsigned char) sin6.sin6_addr.s6_addr[10];
							hlp[10] = (unsigned char) sin6.sin6_addr.s6_addr[9];
							hlp[11] = (unsigned char) sin6.sin6_addr.s6_addr[8];
							hlp[12] = (unsigned char) sin6.sin6_addr.s6_addr[15];
							hlp[13] = (unsigned char) sin6.sin6_addr.s6_addr[14];
							hlp[14] = (unsigned char) sin6.sin6_addr.s6_addr[13];
							hlp[15] = (unsigned char) sin6.sin6_addr.s6_addr[12];
							strcpy(target_addr_text,"");
							for ( j = 0; j < 16; j++ ){
								sprintf(&target_addr_text[strlen(target_addr_text)],"%02X",(unsigned char) hlp[j]);
							}	
							sprintf(&target_addr_text[strlen(target_addr_text)],":%04X",(unsigned int)servlist[idx].co[i].t_port);
							// logger(prefix,"ADDRESS_CONV_TARGET ********** [%s]:[%d] --> [%s]\n",servlist[idx].co[i].target,servlist[idx].co[i].t_port,target_addr_text);
						}
					}	
					if ( servlist[idx].family == AF_INET ){
						int j;
				        	struct addrinfo *res;
       						struct addrinfo hints;
						struct sockaddr_in sin4;
						sprintf(netstat_file,"/proc/net/tcp");
						bzero(&hints,sizeof(hints));
						hints.ai_family   = AF_INET;
						hints.ai_flags    = AI_NUMERICHOST;
						hints.ai_socktype = SOCK_STREAM;
						if ( getaddrinfo(servlist[idx].co[i].source,NULL,&hints,&res)  ){
							logger(prefix,"##################### FAILED TO CONVERT: [%s]\n",servlist[idx].co[i].source);
						} else {
							unsigned char hlp[16];
							unsigned long *x0,*x2,*x3,*x4;
							memcpy( (void *)&sin4,(void *)res->ai_addr,res->ai_addrlen);
							hlp[0] = (unsigned char) (( sin4.sin_addr.s_addr & 0xFF000000 ) >> 24 );
							hlp[1] = (unsigned char) (( sin4.sin_addr.s_addr & 0x00FF0000 ) >> 16 );
							hlp[2] = (unsigned char) (( sin4.sin_addr.s_addr & 0x0000FF00 ) >> 8 );
							hlp[3] = (unsigned char) (( sin4.sin_addr.s_addr & 0x000000FF ) );
							strcpy(source_addr_text,"");
							for ( j = 0; j < 4; j++ ){
								sprintf(&source_addr_text[strlen(source_addr_text)],"%02X",(unsigned char) hlp[j]);
							}	
							sprintf(&source_addr_text[strlen(source_addr_text)],":%04X",(unsigned int)servlist[idx].co[i].port);
							// logger(prefix,"ADDRESS_CONV_SOURCE ********** [%s]:[%d] --> [%s]\n",servlist[idx].co[i].source,servlist[idx].co[i].port,source_addr_text);
						}
						if ( getaddrinfo(servlist[idx].co[i].target,NULL,&hints,&res)  ){
							logger(prefix,"##################### FAILED TO CONVERT: [%s]\n",servlist[idx].co[i].target);
						} else {
							unsigned char hlp[16];
							unsigned long *x0,*x2,*x3,*x4;
							memcpy( (void *)&sin4,(void *)res->ai_addr,res->ai_addrlen);
							hlp[0] = (unsigned char) (( sin4.sin_addr.s_addr & 0xFF000000 ) >> 24 );
							hlp[1] = (unsigned char) (( sin4.sin_addr.s_addr & 0x00FF0000 ) >> 16 );
							hlp[2] = (unsigned char) (( sin4.sin_addr.s_addr & 0x0000FF00 ) >> 8 );
							hlp[3] = (unsigned char) (( sin4.sin_addr.s_addr & 0x000000FF ) );
							strcpy(target_addr_text,"");
							for ( j = 0; j < 4; j++ ){
								sprintf(&target_addr_text[strlen(target_addr_text)],"%02X",(unsigned char) hlp[j]);
							}	
							sprintf(&target_addr_text[strlen(target_addr_text)],":%04X",(unsigned int)servlist[idx].co[i].t_port);
							// logger(prefix,"ADDRESS_CONV_TARGET ********** [%s]:[%d] --> [%s]\n",servlist[idx].co[i].target,servlist[idx].co[i].t_port,target_addr_text);
						}
					}	
					if ( strlen(netstat_file) && (fp = fopen(netstat_file,"r")) != NULL ){
						char buf[1024];
						while ( fgets(buf,1024,fp) != NULL ){
							int state;
							int timer_mode;
							unsigned long timer_value;
							if ( strstr(buf,":") == NULL ) continue;
							ptr = strtok(buf," \t\r\n");
							if ( ptr == NULL ) continue;
							ptr = strtok(NULL," \t\r\n");
							if ( ptr == NULL ) continue;
							if ( strcmp(ptr,target_addr_text) != 0 ) continue;
							ptr = strtok(NULL," \t\r\n");
							if ( ptr == NULL ) continue;
							if ( strcmp(ptr,source_addr_text) != 0 ) continue;
							ptr = strtok(NULL," \t\r\n");
							if ( ptr == NULL ) continue;
							sscanf(ptr,"%02X",&state);
							ptr = strtok(NULL," \t\r\n");
							if ( ptr == NULL ) continue;
							ptr = strtok(NULL," \t\r\n");
							if ( ptr == NULL ) continue;
							sscanf(ptr,"%02X:%08lX",&timer_mode,&timer_value);
							// logger(prefix,"NETSTAT_CONV_(%s) --> [0x%02X] Timer: [0x%02X] Timer-Value: [0x%08lX]\n",netstat_file,state,timer_mode,timer_value);
							switch ( timer_mode ){
								case 0: sprintf(tcp_timeout,"");
									break;
								case 1: sprintf(tcp_timeout,"Retrans.&nbsp;%d&nbsp;s",timer_value);
									break;
								case 2: sprintf(tcp_timeout,"Other&nbsp;%d&nbsp;s",timer_value);
									break;
								case 3: sprintf(tcp_timeout,"TIME_WAIT&nbsp;%d&nbsp;s",timer_value);
									break;
								case 4: sprintf(tcp_timeout,"ZERO_WIN&nbsp;%d&nbsp;s",timer_value);
									break;
								default: 
									sprintf(tcp_timeout,"[0x%02X]&nbsp;%d&nbsp;s",timer_mode,timer_value);
									break;
							}
							switch ( state ){
									case 0x01: 
										strcpy(tcp_state,"ESTABLISHED");
										break;
									case 0x02: 
										strcpy(tcp_state,"SYN_SENT");
										break;
									case 0x03: 
										strcpy(tcp_state,"SYN_RECV");
										break;
									case 0x04: 
										strcpy(tcp_state,"FIN_WAIT1");
										break;
									case 0x05: 
										strcpy(tcp_state,"FIN_WAIT2");
										break;
									case 0x06: 
										strcpy(tcp_state,"TIME_WAIT");
										break;
									case 0x07: 
										strcpy(tcp_state,"CLOSE");
										break;
									case 0x08: 
										strcpy(tcp_state,"CLOSE_WAIT");
										break;
									case 0x09: 
										strcpy(tcp_state,"LAST_ACK");
										break;
									case 0x0A: 
										strcpy(tcp_state,"LISTEN");
										break;
									case 0x0B: 
										strcpy(tcp_state,"CLOSING");
										break;
									default: 
										sprintf(tcp_state,"UNKNOWN(%02X)",state);
										break;
							}
						}
						fclose(fp);
					}
						
					sprintf(stack,"- kB");
					sprintf(data,"- kB");
					sprintf(exe,"- kB");
					threads = 1;
					sprintf(procfile,"/proc/%d/status",servlist[idx].co[i].cpid);
					fp = fopen(procfile,"r");
					if ( fp != NULL ){
						while ( fgets(cmdline,1024,fp) != NULL ){
							if ( strncmp(cmdline,"VmData:",strlen("VmData:")) == 0 ){
								ptr = &cmdline[strlen("VmData:")];
								while ( *ptr && (*ptr == ' ' || *ptr == '\t' ) ) ptr++;
								strcpy(data,ptr);
								ptr = &data[strlen(data)-1];
								while ( ptr > data && ( *ptr == '\r' || *ptr == '\n' ) )ptr--;
								if ( ptr > data ) ptr++;
								*ptr = '\0';
								continue;
							}
							if ( strncmp(cmdline,"VmStk:",strlen("VmStk:")) == 0 ){
								ptr = &cmdline[strlen("VmStk:")];
								while ( *ptr && (*ptr == ' ' || *ptr == '\t' ) ) ptr++;
								strcpy(stack,ptr);
								ptr = &stack[strlen(stack)-1];
								while ( ptr > stack && ( *ptr == '\r' || *ptr == '\n' ) )ptr--;
								if ( ptr > stack ) ptr++;
								*ptr = '\0';
								continue;
							}
							if ( strncmp(cmdline,"VmExe:",strlen("VmExe:")) == 0 ){
								ptr = &cmdline[strlen("VmExe:")];
								while ( *ptr && (*ptr == ' ' || *ptr == '\t' ) ) ptr++;
								strcpy(exe,ptr);
								ptr = &exe[strlen(exe)-1];
								while ( ptr > exe && ( *ptr == '\r' || *ptr == '\n' ) )ptr--;
								if ( ptr > exe ) ptr++;
								*ptr = '\0';
								continue;
							}
							if ( strncmp(cmdline,"VmLib:",strlen("VmLib:")) == 0 ){
								ptr = &cmdline[strlen("VmLib:")];
								while ( *ptr && (*ptr == ' ' || *ptr == '\t' ) ) ptr++;
								strcpy(lib,ptr);
								ptr = &lib[strlen(lib)-1];
								while ( ptr > lib && ( *ptr == '\r' || *ptr == '\n' ) )ptr--;
								if ( ptr > lib ) ptr++;
								*ptr = '\0';
								continue;
							}
						}
						fclose(fp);
					}
					sprintf(procfile,"/proc/%d/io",servlist[idx].co[i].cpid);
					fp = fopen(procfile,"r");
					_io_read  = 0;
					_io_write = 0;
					if ( fp != NULL ){
						while ( fgets(cmdline,1024,fp) != NULL ){
							if ( strncmp(cmdline,"rchar:",strlen("rchar:")) == 0 ){
								ptr = &cmdline[strlen("rchar:")];
								while ( *ptr && (*ptr == ' ' || *ptr == '\t' ) ) ptr++;
								_io_read = atoll(ptr);
								continue;
							}
							if ( strncmp(cmdline,"wchar:",strlen("wchar:")) == 0 ){
								ptr = &cmdline[strlen("wchar:")];
								while ( *ptr && (*ptr == ' ' || *ptr == '\t' ) ) ptr++;
								_io_write = atoll(ptr);
								continue;
							}
						}
						fclose(fp);
					}
#define BIG1024 (1024.0)
					diff = (double) (time(NULL) - servlist[idx].co[i].created);
					if ( diff <= 0 ) diff = 1.0; // Avoid division by zero
					io_read = (double) _io_read;
					io_read_sec = io_read / diff;
					sprintf(io_read_text,"%d&nbsp;Bytes",(int)io_read);
					if ( io_read > 1024.0 ){
						sprintf(io_read_text,"%.02f&nbsp;kB",io_read / BIG1024);
					}
					if ( io_read > (BIG1024*BIG1024) ){
						sprintf(io_read_text,"%.02f&nbsp;MB",io_read / (BIG1024 * BIG1024));
					}
					if ( io_read > (BIG1024*BIG1024*BIG1024) ){
						sprintf(io_read_text,"%.02f&nbsp;GB",io_read / (BIG1024 * BIG1024 * BIG1024));
					}
					if ( io_read > (BIG1024*BIG1024*BIG1024*BIG1024) ){
						sprintf(io_read_text,"%.02f&nbsp;TB",io_read / (BIG1024 * BIG1024 * BIG1024 * BIG1024));
					}
					if ( io_read > (BIG1024*BIG1024*BIG1024*BIG1024*BIG1024) ){
						sprintf(io_read_text,"%.02f&nbsp;PB",io_read / (BIG1024 * BIG1024 * BIG1024 * BIG1024 * BIG1024));
					}
					sprintf(io_read_sec_text,"%d Bytes/s",(int)io_read_sec);
					if ( io_read_sec > 1024.0 ){
						sprintf(io_read_sec_text,"%.02f&nbsp;kBytes/s",io_read_sec/1024.0);
					}
					if ( io_read_sec > (1024.0*1024.0) ){
						sprintf(io_read_sec_text,"%.02f&nbsp;MBytes/s",io_read_sec/(1024.0 * 1024.0));
					}
					if ( io_read_sec > (1024.0*1024.0*1024.0) ){
						sprintf(io_read_sec_text,"%.02f&nbsp;GBytes/s",io_read_sec/(1024.0 * 1024.0 * 1024.0));
					}
					if ( io_read_sec > (1024.0*1024.0*1024.0*1024.0) ){
						sprintf(io_read_sec_text,"%.02f&nbsp;TBytes/s",io_read_sec/(1024.0 * 1024.0 * 1024.0 * 1024.0));
					}
					if ( io_read_sec > (1024.0*1024.0*1024.0*1024.0*1024.0) ){
						sprintf(io_read_sec_text,"%.02f&nbsp;PBytes/s",io_read_sec/(1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0));
					}
					io_write = (double) _io_write;
					io_write_sec = io_write / diff;
					sprintf(io_write_text,"%d&nbsp;Bytes",(int)io_write);
					if ( io_write > 1024.0 ){
						sprintf(io_write_text,"%.02f&nbsp;kB",io_write / BIG1024);
					}
					if ( io_write > (BIG1024*BIG1024) ){
						sprintf(io_write_text,"%.02f&nbsp;MB",io_write / (BIG1024 * BIG1024));
					}
					if ( io_write > (BIG1024*BIG1024*BIG1024) ){
						sprintf(io_write_text,"%.02f&nbsp;GB",io_write / (BIG1024 * BIG1024 * BIG1024));
					}
					if ( io_write > (BIG1024*BIG1024*BIG1024*BIG1024) ){
						sprintf(io_write_text,"%.02f&nbsp;TB",io_write / (BIG1024 * BIG1024 * BIG1024 * BIG1024));
					}
					if ( io_write > (BIG1024*BIG1024*BIG1024*BIG1024*BIG1024) ){
						sprintf(io_write_text,"%.02f&nbsp;PB",io_write / (BIG1024 * BIG1024 * BIG1024 * BIG1024 * BIG1024));
					}
					sprintf(io_write_sec_text,"%d&nbsp;Bytes/s",(int)io_write_sec);
					if ( io_write_sec > 1024.0 ){
						sprintf(io_write_sec_text,"%.02f&nbsp;kBytes/s",io_write_sec/1024.0);
					}
					if ( io_write_sec > (1024.0*1024.0) ){
						sprintf(io_write_sec_text,"%.0fg&nbsp;MBytes/s",io_write_sec/(1024.0 * 1024.0));
					}
					if ( io_write_sec > (1024.0*1024.0*1024.0) ){
						sprintf(io_write_sec_text,"%.02f&nbsp;GBytes/s",io_write_sec/(1024.0 * 1024.0 * 1024.0));
					}
					if ( io_write_sec > (1024.0*1024.0*1024.0*1024.0) ){
						sprintf(io_write_sec_text,"%.02f&nbsp;TBytes/s",io_write_sec/(1024.0 * 1024.0 * 1024.0 * 1024.0));
					}
					if ( io_write_sec > (1024.0*1024.0*1024.0*1024.0*1024.0) ){
						sprintf(io_write_sec_text,"%.02f&nbsp;PBytes/s",io_write_sec/(1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0));
					}



					sprintf(procfile,"/proc/%d/exe",servlist[idx].co[i].cpid);
					bzero(cmdline,1024);
					if ( readlink(procfile,cmdline,1024) < 0 ){
						sprintf(cmdline,"Executable not found");
					} 
					{
						char copy[1024];
						char *in;
						char *out;
						strcpy(copy,stack);
						in = copy;
						out = stack;
						while ( *in ){
							if ( *in == ' ' || *in == '\t' ){
								*out = '&';	
								out++;
								*out = 'n';	
								out++;
								*out = 'b';	
								out++;
								*out = 's';	
								out++;
								*out = 'p';	
								out++;
								*out = ';';	
								out++;
								in++; 
							} else {
								*out = *in;
								in++; out++;
							}
						}
						*out = '\0';
						strcpy(copy,data);
						in = copy;
						out = data;
						while ( *in ){
							if ( *in == ' ' || *in == '\t' ){
								*out = '&';	
								out++;
								*out = 'n';	
								out++;
								*out = 'b';	
								out++;
								*out = 's';	
								out++;
								*out = 'p';	
								out++;
								*out = ';';	
								out++;
								in++; 
							} else {
								*out = *in;
								in++; out++;
							}
						}
						*out = '\0';
						strcpy(copy,lib);
						in = copy;
						out = lib;
						while ( *in ){
							if ( *in == ' ' || *in == '\t' ){
								*out = '&';	
								out++;
								*out = 'n';	
								out++;
								*out = 'b';	
								out++;
								*out = 's';	
								out++;
								*out = 'p';	
								out++;
								*out = ';';	
								out++;
								in++; 
							} else {
								*out = *in;
								in++; out++;
							}
						}
						*out = '\0';
						strcpy(copy,exe);
						in = copy;
						out = exe;
						while ( *in ){
							if ( *in == ' ' || *in == '\t' ){
								*out = '&';	
								out++;
								*out = 'n';	
								out++;
								*out = 'b';	
								out++;
								*out = 's';	
								out++;
								*out = 'p';	
								out++;
								*out = ';';	
								out++;
								in++; 
							} else {
								*out = *in;
								in++; out++;
							}
						}
						*out = '\0';
					}
					
					tm = localtime(&servlist[idx].co[i].created);
					sprintf(line,"{\"cwd\":\"%s\",\"slot\":\"%d/%d\",\"tcp_state\":\"%s\",\"tcp_timeout\":\"%s\",\"io_read\":\"%s\",\"io_read_sec\":\"%s\",\"io_write\":\"%s\",\"io_write_sec\":\"%s\",\"vm_stack\":\"%s\",\"vm_lib\":\"%s\",\"vm_exe\":\"%s\",\"vm_data\":\"%s\",\"cmdline\":\"%s\",\"index\":%d,\"pid\":%d,\"cpid\":%d,\"source\":\"%s\",\"target\":\"%s\",\"source_port\":%d,\"target_port\":%d,\"created\":\"%04d.%02d.%02d&nbsp;%02d:%02d:%02d\"},",
						cwd, i,idx, tcp_state,tcp_timeout,
						io_read_text,io_read_sec_text,
						io_write_text,io_write_sec_text,
						stack,lib,exe,data, cmdline, i,servlist[idx].co[i].pid,servlist[idx].co[i].cpid,servlist[idx].co[i].source,servlist[idx].co[i].target,servlist[idx].co[i].port,servlist[idx].co[i].t_port,tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
						 tm->tm_hour, tm->tm_min, tm->tm_sec);	
					result = (char *)realloc(result, strlen(result) + strlen(line) + 1 );
					strcat(result,line);
				}	
			}
			sem_unlock(semid2);	
			if ( result[strlen(result)-1] == ',' ) result[strlen(result)-1] = '\0';
			strcat(result,"]");
			{
				char *in;
				char *out;
				int newsize;
				in = (char *)malloc(strlen(result) + 20);
				out = (char *)malloc(strlen(result) + 120);
				sprintf(in,"OK[%s]\r\n",result);
				newsize = gzip_string(in,out);
				if ( newsize > 0 ){
					fprintf(ss,"Accept-Range: bytes\r\n");
					fprintf(ss,"Content-Length: %d\r\n",newsize);	
					fprintf(ss,"Content-Encoding: gzip\r\n\r\n",newsize);	
					fwrite(out,1,newsize,ss);
					fflush(ss);
				} else {
					logger(prefix,"GZIP-FAILED: [%d] <-- [%d]\n",newsize,strlen(in));
					fprintf(ss,"\r\n%s",in);
				}
			}
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;		
		}
		if ( strcmp(command,"KILLTCP") == 0 ){
			int pid;
			int slot,index;
			char *ptr;
			fprintf(ss,"\r\n");
			logger(prefix,"KILLTCP ARGUMNET: [%s]\n",argument);
			slot = atoi(argument);
			ptr = argument;
			while ( *ptr && *ptr != '/' ) ptr++; 
			if ( *ptr == '/' ){
				logger(prefix,"KILLTCP 2 ARGUMNET: %d, PTR: [%s]\n",argument,ptr);
				ptr++;
				index = atoi(ptr);
				if ( servlist[slot].co[index].pid != 0 ) m_kill(servlist[slot].co[index].pid,SIGTERM); 
				fprintf(ss,"OK[Sent SIGTERM to %d]\r\n",pid);
			}
			
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}

		if ( strcmp(command,"CONNSCOUNT") == 0 ){
			int idx;
			fprintf(ss,"\r\n");
			idx = atoi(argument);
			if ( idx >= entries ){
				fprintf(ss,"ERR[Bad index]\r\n");
			} else {
				struct tm *tm;
				int semmel;
				tm = localtime(&servlist[idx].reset);
				semmel = semget(INETD_KEY2 + idx,1,0);
				if ( semmel < 0 ){
					logger(prefix,"Cannot get SEM [0x%08lX]\n",INETD_KEY2 + idx);
				} else {
					sem_lock(semmel);
					fprintf(ss,"OK[{\"connections\":%d,\"total_count\":%d,\"reset\":\"%04d.%02d.%02d %02d:%02d:%02d\",\"max_conns\":%d,\"pid\":%d}]\r\n",servlist[idx].connections,servlist[idx].total_count,
						tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
						tm->tm_hour, tm->tm_min, tm->tm_sec, servlist[idx].max_conns,servlist[idx].pid);
					sem_unlock(semmel);
				}
			}
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		if ( strcmp(command,"SIGNAL") == 0 ){
			int pid;
			int sig;
			char *ptr;
			fprintf(ss,"\r\n");
			pid = atoi(argument);
			ptr = argument;
			while ( *ptr && *ptr != '/' ) ptr++;
			if ( *ptr != '/' ){
				fprintf(ss,"ERR[No Signal given!]\r\n");
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			ptr++;
			sig = atoi(ptr);
			logger(prefix,"SIGNAL %d TO %d\n",sig,pid);
			if ( pid == getpid() || pid == getppid() || pid < 100 ){
				fprintf(ss,"ERR[No Signal to myself or parent or PID < 100!]\r\n");
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			kill(pid,sig);
			fprintf(ss,"OK[Signal sent!]\r\n");
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}
		if ( strcmp(command,"SYSINFO") == 0 ){
			double load[3];
			char uptimer[1024];
			struct sysinfo sys;
			int idx;
			int semmel;
			char *json_list;
			char *tftp_list;
			char *result;
			getloadavg(load,3);	
			sysinfo(&sys);
			// Get count of connections 
			tftp_list = strdup("[");
			if ( gix_options->tftp_enabled ){
				char line[1024];
				int iid;
				// logger(prefix,"SYSINFO starting parsing %d TFTP-Sessions\n",MAX_TFTP_SESSIONS);
				for ( iid = 0; iid < MAX_TFTP_SESSIONS; iid++ ){
					if ( gix_options->tr[iid].active ){
						sprintf(line,"{\"started\":%ld,\"lastaction\":%ld,\"filename\":\"%s\",\"remote_ip\":\"%s\",\"offset\":%ld,\"fullsize\":%ld,\"blksize\":%d,\"kind_transfer\":\"%s\"},",
							gix_options->tr[iid].started,
							gix_options->tr[iid].lastaction,
							gix_options->tr[iid].filename,
							gix_options->tr[iid].ipname,
							gix_options->tr[iid].offset,
							gix_options->tr[iid].fullsize,
							gix_options->tr[iid].packsize,
							gix_options->tr[iid].kind_request == TFTP_REQUEST_READ ? "READ" : "WRITE");
						tftp_list = (char *)realloc((char *)tftp_list,strlen(tftp_list) + strlen(line) + 10);
						strcat(tftp_list,line);
				
					}
				}
			}
			tftp_list = (char *)realloc((char *)tftp_list,strlen(tftp_list) + 10);
			if ( tftp_list[strlen(tftp_list)-1] == ',' ) tftp_list[strlen(tftp_list)-1] = '\0';
			strcat(tftp_list,"]");
			// logger(prefix,"SYSINFO TFTP processed [%d Bytes]\n",strlen(tftp_list));

			json_list = strdup("[");
			for ( idx = 0; (semmel = semget(INETD_KEY2 + idx,1,0)) >= 0; idx++ ){
				char line[1024];
				struct tm *tm;
				tm = localtime(&servlist[idx].reset);
				sem_lock(semmel);
				sprintf(line,"{\"connections\":%d,\"total_count\":%d,\"reset\":\"%04d.%02d.%02d %02d:%02d:%02d\",\"max_conns\":%d,\"pid\":%d},",
					servlist[idx].connections,servlist[idx].total_count,
					tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,tm->tm_hour, tm->tm_min, tm->tm_sec, servlist[idx].max_conns,servlist[idx].pid);
				sem_unlock(semmel);
				json_list = (char *)realloc(json_list,strlen(json_list) + strlen(line) + 10);
				strcat(json_list,line);
			}	
			json_list = (char *)realloc(json_list,strlen(json_list) + 10);
			if ( json_list[strlen(json_list)-1] == ',' ) json_list[strlen(json_list)-1] = '\0';
			sprintf(&json_list[strlen(json_list)],"]");
			// logger(prefix,"SYSINFO INETD-LIST processed [%d Bytes]\n",strlen(json_list));

			result = (char *)malloc(strlen(json_list) +  2048 + strlen(tftp_list));
			
			sprintf(result,"{\"tftp_requests_read\":%d,\"tftp_requests_write\":%d,\"tftp_enabled\":\"%d\",\"tftp_readonly\":\"%d\",\"tftp_root\":\"%s\",\"tftp_list\":%s,\"load1\":\"%.02g\",\"load5\":\"%.02g\",\"load15\":\"%.02g\",\"sys_procs\":%d,\"uptime\":\"%s\",\"inetlist\":%s}",
				gix_options->tftp_requests_read, 
				gix_options->tftp_requests_write, 
				gix_options->tftp_enabled, 
				gix_options->tftp_readonly, 
				gix_options->tftp_root, 
				tftp_list,
				load[0],load[1],load[2],sys.procs,gix_display_uptime(0,NULL,uptimer),json_list);
			{
				char *in;
				char *out;
				int newsize;
				in = (char *)malloc(strlen(result) + 20);
				out = (char *)malloc(strlen(result) + 120);
				sprintf(in,"OK[%s]\r\n",result);
				newsize = gzip_string(in,out);
				if ( newsize > 0 ){
					fprintf(ss,"Accept-Range: bytes\r\n");
					fprintf(ss,"Content-Length: %d\r\n",newsize);	
					fprintf(ss,"Content-Encoding: gzip\r\n\r\n",newsize);	
					fwrite(out,1,newsize,ss);
					fflush(ss);
				} else {
					logger(prefix,"GZIP-FAILED: [%d] <-- [%d]\n",newsize,strlen(in));
					fprintf(ss,"\r\n%s",in);
				}
			}
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			free(result);
			free(tftp_list);
			free(json_list);
			return;
		}
		if ( strcmp(command,"PROCDETAIL") == 0 ){
			int pid; 
			char *result;
                	struct sysinfo sys;
			struct timeval start;
			struct timeval end;
			long utime_ticks;
			long stime_ticks;
			long utime_ticks2;
			long stime_ticks2;
			double cpu_usage_usr;
			double cpu_usage_sys;
			char fname[1024];
			char exe[1024];
			char *helper;
			char full_exe[1024];
			char full_cwd[1024];
			char commandline[1024];
			int r_gid, r_uid;
			int e_gid, e_uid;
			int c_argc;
			char state;
			int ppid;
			long nice;
			long priority;
			long num_threads;
			long rss;
			int cpu_id;
			char *ptr;
			unsigned long vmsize;
			long long starttime;
			time_t p_start;
			FILE *fp;
			int slot, index;
			int fds;
			DIR *dir;
			struct dirent *diry;
			char dirname[1024];
			char *fd_array;
			fprintf(ss,"\r\n");

			slot = -1;
			index = -1;	

			sysinfo(&sys);
			pid = atoi(argument);


			sprintf(dirname,"/proc/%d/fd",pid);

			dir = opendir(dirname);

			fds = 0;

			fd_array = strdup("[");

			if ( dir != NULL ){
				while ( (diry = readdir(dir)) != NULL ){
					char help2[1024];
					char lname[1024];
					char ltarget[1024];
					char addrinfo[256];
					char type[1024];
					unsigned long inode;
					struct socket_info *si;

					bzero(addrinfo,256);

					sprintf(addrinfo,"\"valid_addr\":false,");

					if ( !isdigit(diry->d_name[0]) ) continue;
					sprintf(lname,"/proc/%d/fd/%s",pid,diry->d_name);
					bzero(ltarget,1024);
					if ( readlink(lname,ltarget,1024) < 0 ) continue;
					sprintf(type,"file");
					if ( strncmp(ltarget,"socket:",strlen("socket:")) == 0 ){
						strcpy(type,"socket");
						inode = atol(&ltarget[strlen("socket:[")]);
						logger(prefix,"PROCDETAIL (Requesting INODE: %ld)\n",inode);
						si = get_socket_info(inode,-1);
						if ( si != NULL ){
							sprintf(addrinfo,"\"valid_addr\":true,\"local_addr\":\"%s\",\"protocol\":%d,\"local_port\":%d,\"remote_addr\":\"%s\",\"remote_port\":%d,\"family\":%d,\"state\":%d,\"timer_kind\":%d,\"timer_value\":%ld,\"uid\":%d,",
								si->local_addr,si->protocol,si->local_port,si->remote_addr,si->remote_port,si->family,si->state,si->timer_kind,si->timer_value,si->uid);
						}
					}
					if ( strncmp(ltarget,"pipe:",strlen("pipe:")) == 0 ) strcpy(type,"pipe");
					if ( strncmp(ltarget,"anon_inode:",strlen("anon_inode:")) == 0 ) strcpy(type,"other");
					sprintf(help2,"{%s\"fd\":%d,\"name\":\"%s\",\"type\":\"%s\"},",addrinfo,atoi(diry->d_name),ltarget,type);
					fd_array = (char *)realloc(fd_array,strlen(fd_array) + strlen(help2) + 10);
					strcat(fd_array,help2);
				
				}
				closedir(dir);
			}
			if ( fd_array[strlen(fd_array)-1] == ',' ) fd_array[strlen(fd_array)-1] = '\0';	
			fd_array = (char *)realloc(fd_array,strlen(fd_array) + 10);
			strcat(fd_array,"]");

			helper = (char *)malloc(1024 + strlen(fd_array) * 2);

			
			if ( pid > 10 ) { 
				int k,l;
				for ( k = 0; k < entries; k++ ){
					for ( l = 0; l < MAX_CONNS; l++ ){
						if ( servlist[k].co[l].cpid == pid || servlist[k].co[l].pid == pid ){
							slot = k;
							index = l;
							break;
						}
					}
					if ( slot >= 0 ) break;
				}
			}

			logger(prefix,"PROCDETAIL[%d] --> Start\n",pid);
			result = strdup("{");

			sprintf(fname,"/proc/%d/exe",pid);
			bzero(full_exe,1024);
			if ( readlink(fname,full_exe,1024) < 0 ){
				strcpy(full_exe,"n.a.");	
			}
			sprintf(fname,"/proc/%d/cwd",pid);
			bzero(full_cwd,1024);
			if ( readlink(fname,full_cwd,1024) < 0 ){
				strcpy(full_cwd,"n.a.");	
			}

			r_uid = 0;
			r_gid = 0;
			e_uid = 0;
			e_gid = 0;

			sprintf(fname,"/proc/%d/status",pid);
			fp = fopen(fname,"r");
			if ( fp == NULL ){
				fprintf(ss,"ERR[Cannot open %s]\r\n",fname);
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}	
			while ( fgets(fname,1024,fp) != NULL ){
				if ( strncmp(fname,"Uid:",4) == 0 ){
					char *ptr;
					ptr = &fname[4];
					while ( *ptr && !isdigit(*ptr) ) ptr++;
					r_uid = atoi(ptr);
					while ( *ptr && isdigit(*ptr) ) ptr++;
					while ( *ptr && !isdigit(*ptr) ) ptr++;
					e_uid = atoi(ptr);
					continue;
				}	
				if ( strncmp(fname,"Gid:",4) == 0 ){
					char *ptr;
					ptr = &fname[4];
					while ( *ptr && !isdigit(*ptr) ) ptr++;
					r_gid = atoi(ptr);
					while ( *ptr && isdigit(*ptr) ) ptr++;
					while ( *ptr && !isdigit(*ptr) ) ptr++;
					e_gid = atoi(ptr);
					continue;
				}	
			}

			fclose(fp);
			


			sprintf(fname,"/proc/%d/cmdline",pid);
			fp = fopen(fname,"r");
			if ( fp == NULL ){
				fprintf(ss,"ERR[Cannot open %s]\r\n",fname);
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}	
			{
				int c; 
				int lastchar;
				char *ptr;
				ptr = commandline;
				bzero(commandline,1024);
				lastchar = -1;
				c_argc = 0;
				while ( (c = fgetc(fp)) != -1 ){
					if ( c == 0  ){
						c_argc++;
						*ptr = ' '; ptr++;
						continue;
					}
					if ( c == '\n'  ){
						*ptr = ' '; ptr++;
						continue;
					}
					if ( c == '\r'  ){
						*ptr = ' '; ptr++;
						continue;
					}
					if ( c == '\t'  ){
						*ptr = ' '; ptr++;
						continue;
					}
					if ( c == '>'  ){
						*ptr = '&'; ptr++;
						*ptr = 'g'; ptr++;
						*ptr = 't'; ptr++;
						*ptr = ';'; ptr++;
						continue;
					}
					if ( c == '<'  ){
						*ptr = '&'; ptr++;
						*ptr = 'l'; ptr++;
						*ptr = 't'; ptr++;
						*ptr = ';'; ptr++;
						continue;
					}
					*ptr = c;
					ptr++;
					lastchar = c;
				}
			}
			fclose(fp);
			while ( strlen(commandline) && commandline[strlen(commandline)-1] == ' ' ) commandline[strlen(commandline)-1] = '\0';
			if ( commandline[strlen(commandline)-1] == '\r' || commandline[strlen(commandline)-1] == '\n' ) commandline[strlen(commandline)-1] = '\0';
			if ( commandline[strlen(commandline)-1] == '\r' || commandline[strlen(commandline)-1] == '\n' ) commandline[strlen(commandline)-1] = '\0';
			// logger(prefix,"PROCDETAIL: COMMAND-LINE: [%s]\n",commandline);

			sprintf(fname,"/proc/%d/stat",pid);
			fp = fopen(fname,"r");
			if ( fp == NULL ){
				fprintf(ss,"ERR[Cannot open %s]\r\n",fname);
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}	
			if ( fgets(fname,1024,fp) == NULL ){ 
				fclose(fp); 
				fprintf(ss,"ERR[Cannot read %s]\r\n",fname);
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			fclose(fp);

#define EXIT_PROC_READ { fprintf(ss,"ERR[%s:%d corrupted file /proc/%d/stat]\r\n",__FILE__,__LINE__,pid); fflush(ss); shutdown(sock,SHUT_RDWR); fclose(ss); return; }
			ptr = strtok(fname," \t"); // PID
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // CMD
			if ( ptr == NULL ) EXIT_PROC_READ;	
			strcpy(exe,ptr);
			ptr = strtok(NULL," \t"); // STATE
			if ( ptr == NULL ) EXIT_PROC_READ;	
			state = *ptr;
			ptr = strtok(NULL," \t"); // PPID
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ppid = atoi(ptr);
			ptr = strtok(NULL," \t"); // PGRP
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // SESSION
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // TTYNR
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // TPGID
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // FLAGS
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // MINFLT
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // CMINFLT
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // MAJFLT
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // CMAJFLT
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // UTIME
			if ( ptr == NULL ) EXIT_PROC_READ;	
			utime_ticks = atol(ptr);	
			ptr = strtok(NULL," \t"); // STIME
			if ( ptr == NULL ) EXIT_PROC_READ;	
			stime_ticks = atol(ptr);	
			gettimeofday(&start,NULL);
			ptr = strtok(NULL," \t"); // CUTIME
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // CSTIME
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // PRIORITY
			if ( ptr == NULL ) EXIT_PROC_READ;	
			priority = atol(ptr);	
			ptr = strtok(NULL," \t"); // NICE
			if ( ptr == NULL ) EXIT_PROC_READ;	
			nice = atol(ptr);	
			ptr = strtok(NULL," \t"); // NUMTHREADS
			if ( ptr == NULL ) EXIT_PROC_READ;	
			num_threads = atol(ptr);	
			ptr = strtok(NULL," \t"); // ITREALVALUE
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // STARTTIME
			if ( ptr == NULL ) EXIT_PROC_READ;	
			starttime = atoll(ptr);	
			ptr = strtok(NULL," \t"); // VMSIZE
			if ( ptr == NULL ) EXIT_PROC_READ;	
			vmsize = atol(ptr);	
			ptr = strtok(NULL," \t"); // RSS
			if ( ptr == NULL ) EXIT_PROC_READ;	
			rss = atol(ptr);	
			ptr = strtok(NULL," \t"); // RSSLIM
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // STARTCODE
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // ENDCODE
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // STARTSTACK
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // KSTKESP
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // KSTKEIP
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // SIGNAL
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // BLOCKED
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // SIGIGNORE
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // SIGCATCH
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // WCHAN
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // NSWAP
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // CNSWAP
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // EXIT_SIGNAL
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // PROCESSOR
			if ( ptr == NULL ) EXIT_PROC_READ;	
			cpu_id = atoi(ptr);
			p_start = time(NULL) - (sys.uptime - (starttime / sysconf(_SC_CLK_TCK)));
			{ // Sleep now for 0.5 seconds...than check the ticks again
				struct timespec tv;
				struct timespec rem;
				tv.tv_sec = 0;
				tv.tv_nsec = 700000000;
				while ( nanosleep(&tv,&rem) < 0 && errno == EINTR && rem.tv_sec != 0 && rem.tv_nsec != 0 ){
					tv = rem;
				}
			}
			sprintf(fname,"/proc/%d/stat",pid);
			fp = fopen(fname,"r");
			if ( fp == NULL ){
				fprintf(ss,"ERR[Cannot open %s]\r\n",fname);
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			if ( fgets(fname,1024,fp) == NULL ){ 
				fprintf(ss,"ERR[Cannot read %s]\r\n",fname);
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				fclose(fp);  
				return;
			}	
			fclose(fp);
			ptr = strtok(fname," \t"); // PID
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // CMD
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // STATE
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // PPID
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // PGRP
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // SESSION
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // TTYNR
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // TPGID
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // FLAGS
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // MINFLT
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // CMINFLT
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // MAJFLT
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // CMAJFLT
			if ( ptr == NULL ) EXIT_PROC_READ;	
			ptr = strtok(NULL," \t"); // UTIME
			if ( ptr == NULL ) EXIT_PROC_READ;	
			utime_ticks2 = atol(ptr);	
			ptr = strtok(NULL," \t"); // STIME
			if ( ptr == NULL ) EXIT_PROC_READ;	
			stime_ticks2 = atol(ptr);	
			gettimeofday(&end,NULL);
			{
				double old, new;
				double ticks; 
				old = (double)start.tv_sec + ((double)start.tv_usec)/1000000.0;
				new = (double)end.tv_sec + ((double)end.tv_usec)/1000000.0;
				ticks = ((double) sysconf(_SC_CLK_TCK)) * (new - old);
				if ( utime_ticks2 ){
					cpu_usage_usr = ((double)(utime_ticks2 -  utime_ticks)/ ticks) * 100.0;
					if ( cpu_usage_usr > 100.0 ) cpu_usage_usr = 100.0;
				} else {
					cpu_usage_usr = 0.0;
				}
				// logger(prefix,"************************* PROCDETAIL: %d [%s] USR:[%.02f %%] Ticks-elapsed: %.02f, Time elapsed: %.02f TICKS: %d\n",pid,exe,cpu_usage_usr,ticks,new-old,utime_ticks2 -  utime_ticks);
				if ( stime_ticks2 ){
					cpu_usage_sys = ((double)(stime_ticks2 -  stime_ticks)/ ticks) * 100.0;
					if ( cpu_usage_sys > 100.0 ) cpu_usage_sys = 100.0;
				} else {
					cpu_usage_sys = 0.0;
				}
				// logger(prefix,"************************* PROCDETAIL: %d [%s] SYS:[%.02f %%] Ticks-elapsed: %.02f, Time elapsed: %.02f TICKS: %d\n",pid,exe,cpu_usage_sys,ticks,new-old,stime_ticks2 -  stime_ticks);

				sprintf(helper,"\"cmd\":\"%s\",\"cpu_usage_sys\":\"%.02f\",\"cpu_usage_usr\":\"%.02f\",",exe,cpu_usage_sys,cpu_usage_usr);		
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				sprintf(helper,"\"num_threads\":%d,",num_threads);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);
				sprintf(helper,"\"cpu\":%d,",cpu_id);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				sprintf(helper,"\"full_cwd\":\"%s\",",full_cwd);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				sprintf(helper,"\"name\":\"%s\",",exe);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				sprintf(helper,"\"commandline\":\"%s\",",commandline);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				sprintf(helper,"\"argc\":%d,",c_argc);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				switch(state){
					case 'R':
						sprintf(helper,"\"full_state\":\"R - Running\",");
						break;
					case 'S':
						sprintf(helper,"\"full_state\":\"S - Sleeping\",");
						break;
					case 'D':
						sprintf(helper,"\"full_state\":\"D - Waiting in disk-sleep\",");
						break;
					case 'Z':
						sprintf(helper,"\"full_state\":\"Z - Zombie (defunct)\",");
						break;
					case 'T':
					case 't':
						sprintf(helper,"\"full_state\":\"T - Stopped\",");
						break;
					case 'W':
						sprintf(helper,"\"full_state\":\"W - Paging/Waking\",");
						break;
					case 'X':
					case 'x':
						sprintf(helper,"\"full_state\":\"X - Dead\",");
						break;
					case 'P':
						sprintf(helper,"\"full_state\":\"P - Parked\",");
						break;
					case 'K':
						sprintf(helper,"\"full_state\":\"K - Wakekill\",");
						break;
					default:
						sprintf(helper,"\"full_state\":\"UNKNOWN(%c)\",",state);
						break;
				}	
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);
				{
					int hours;
					int minutes;
					int seconds;
					hours =   (stime_ticks2/sysconf(_SC_CLK_TCK)) / 3600;
					minutes = (stime_ticks2/sysconf(_SC_CLK_TCK) - hours * 3600)/60;
					seconds = (stime_ticks2/sysconf(_SC_CLK_TCK)) % 60;

					sprintf(helper,"\"sys_time\":\"%02d:%02d:%02d&nbsp;(%d ticks)\",",hours,minutes,seconds,stime_ticks2);
					result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
					strcat(result,helper);
				}
				{
					int hours;
					int minutes;
					int seconds;
					hours =   (utime_ticks2/sysconf(_SC_CLK_TCK)) / 3600;
					minutes = (utime_ticks2/sysconf(_SC_CLK_TCK) - hours * 3600)/60;
					seconds = (utime_ticks2/sysconf(_SC_CLK_TCK)) % 60;

					sprintf(helper,"\"usr_time\":\"%02d:%02d:%02d&nbsp;(%d ticks)\",",hours,minutes,seconds,utime_ticks2);
					result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
					strcat(result,helper);
				}

				sprintf(helper,"\"slot\":%d,",slot);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				sprintf(helper,"\"index\":%d,",index);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				sprintf(helper,"\"ppid\":%d,",ppid);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				sprintf(helper,"\"fds\":%s,",fd_array);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				{
					struct passwd *pwd;
					struct group  *grp;
					char username[1024];

					pwd = getpwuid(r_uid);
					if ( pwd == NULL ){
						sprintf(username,"%d",r_uid);
					} else {
						strcpy(username,pwd->pw_name);
					}

					sprintf(helper,"\"r_uid\":\"%d (%s)\",",r_uid,username);
					result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
					strcat(result,helper);

					grp = getgrgid(r_gid);
					if ( grp == NULL ){
						sprintf(username,"%d",r_gid);
					} else {
						strcpy(username,grp->gr_name);
					}
	
					sprintf(helper,"\"r_gid\":\"%d (%s)\",",r_gid,username);
					result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
					strcat(result,helper);

					pwd = getpwuid(e_uid);
					if ( pwd == NULL ){
						sprintf(username,"%d",e_uid);
					} else {
						strcpy(username,pwd->pw_name);
					}
	
					sprintf(helper,"\"e_uid\":\"%d (%s)\",",e_uid,username);
					result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
					strcat(result,helper);

					grp = getgrgid(e_gid);
					if ( grp == NULL ){
						sprintf(username,"%d",e_gid);
					} else {
						strcpy(username,grp->gr_name);
					}
	
					sprintf(helper,"\"e_gid\":\"%d (%s)\",",e_gid,username);
					result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
					strcat(result,helper);

				}

				sprintf(helper,"\"full_exe\":\"%s\",",full_exe);
				result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
				strcat(result,helper);

				{
					struct tm *tm;
					tm = localtime(&p_start);
					sprintf(helper,"\"p_start\":\"%04d.%02d.%02d&nbsp;%02d:%02d:%02d\",",
						tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
						tm->tm_hour, tm->tm_min, tm->tm_sec);
					result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
					strcat(result,helper);
				}
#define FAT1024 (1024.0)
				{
					double n_vmsize;
					n_vmsize = (double) vmsize;
					sprintf(helper,"\"vm_size\":\"%d&nbsp;Bytes\",", (int) n_vmsize);				
					if ( n_vmsize > FAT1024 ){ 
						sprintf(helper,"\"vm_size\":\"%.02f&nbsp;KBytes\",", n_vmsize/FAT1024);				
					}
					if ( n_vmsize > (FAT1024*FAT1024) ){ 
						sprintf(helper,"\"vm_size\":\"%.02f&nbsp;MBytes\",", n_vmsize/(FAT1024*FAT1024));				
					}
					if ( n_vmsize > (FAT1024*FAT1024*FAT1024) ){ 
						sprintf(helper,"\"vm_size\":\"%.02f&nbsp;GBytes\",", n_vmsize/(FAT1024*FAT1024*FAT1024));				
					}
					if ( n_vmsize > (FAT1024*FAT1024*FAT1024*FAT1024) ){ 
						sprintf(helper,"\"vm_size\":\"%.02f&nbsp;TBytes\",", n_vmsize/(FAT1024*FAT1024*FAT1024*FAT1024));				
					}
					result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
					strcat(result,helper);
				}
				{	
					double n_rss;
					n_rss = ((double) rss) * ((double) sysconf(_SC_PAGESIZE));
					sprintf(helper,"\"rss\":\"%d&nbsp;Bytes\",", (int)n_rss);				
					if ( n_rss > FAT1024 ){ 
						sprintf(helper,"\"rss\":\"%.02f&nbsp;KBytes\",", n_rss/FAT1024);				
					}
					if ( n_rss > (FAT1024*FAT1024) ){ 
						sprintf(helper,"\"rss\":\"%.02f&nbsp;MBytes\",", n_rss/(FAT1024*FAT1024));				
					}
					if ( n_rss > (FAT1024*FAT1024*FAT1024) ){ 
						sprintf(helper,"\"rss\":\"%.02f&nbsp;GBytes\",", n_rss/(FAT1024*FAT1024*FAT1024));				
					}
					if ( n_rss > (FAT1024*FAT1024*FAT1024*FAT1024) ){ 
						sprintf(helper,"\"rss\":\"%.02f&nbsp;TBytes\",", n_rss/(FAT1024*FAT1024*FAT1024*FAT1024));				
					}
					result = (char *)realloc(result,strlen(result) + strlen(helper) + 10);
					strcat(result,helper);
				}


			}
			if ( result[strlen(result)-1] == ',' ) result[strlen(result)-1] = '\0';
			result = (char *)realloc(result,strlen(result)+2);
			strcat(result,"}");	
			fprintf(ss,"OK[%s]\r\n",result);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
			
		}
		if ( strcmp(command,"PROCLIST") == 0 ){
			int ix;
			int lentries;
			struct ethinfo *eth;
			struct process_info *list;
			DIR *dir;
			struct dirent *diry;
			char *result;
			struct sysinfo sys;
			int cpu_count;
			double *usage_sum;
			int ethcount;
			char *ethjson;
			char *fsjson;
			double loader[4];
			getloadavg(loader,1);	
			cpu_count = 0;
			{
				FILE *fp;
				fp = fopen("/proc/stat","r");
				if ( fp != NULL ){
					char buf[1024];
					while ( fgets(buf,1024,fp) != NULL ){
						if ( strncmp(buf,"cpu",3) == 0 ){
							if ( !isspace(buf[3]) ) cpu_count++;
						}
					}
					fclose(fp);
				} 
				if ( cpu_count < 1 ){
					logger(prefix,"PROCLIST: WARNING no CPUs found...assuming 1 CPU\n");
					cpu_count = 1;
				}
			}
			usage_sum = (double *)malloc(sizeof(double) * cpu_count);
			bzero(usage_sum,sizeof(double) * cpu_count);

			{ 
				FILE *fp;
				char buf[1024];

				ethcount = 0;
				fp = fopen("/proc/net/dev","r");
				if ( fp == NULL ){
					fprintf(ss,"\r\nERR[Cannot open /proc/net/dev]\r\n");
					fflush(ss);
					shutdown(sock,SHUT_RDWR);
					fclose(ss);
					return;
				}				
				eth = NULL;
				while ( fgets(buf,1024,fp) != NULL ){
					char ifname[256];
					char *ptr;
					char bytes_receive[64];
					char packets_receive[64];
					char errs_receive[64];
					char drop_receive[64];
					char bytes_transmit[64];
					char packets_transmit[64];
					char errs_transmit[64];
					char drop_transmit[64];
					char colls[64];
					if ( strstr(buf,":") == NULL ) continue;
					ptr = strtok(buf,":\t\r\n ");
					if ( ptr == NULL ) continue;
					sprintf(ifname,"%s",ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(bytes_receive,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(packets_receive,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(errs_receive,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(drop_receive,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // FIFO

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // FRAME

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // COMPRESSED

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // MULTICAST

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(bytes_transmit,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(packets_transmit,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(errs_transmit,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(drop_transmit,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // FIFO

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(colls,ptr);
					
					eth = (struct ethinfo *)realloc(eth,sizeof(struct ethinfo) * (ethcount+1));	
					bzero(&eth[ethcount],sizeof(struct ethinfo));
					gettimeofday(&(eth[ethcount].stamp1),NULL);	
					strcpy(eth[ethcount].ifname,ifname);
					strcpy(eth[ethcount].if_mac,get_interface_address(ifname,AF_PACKET));
					strcpy(eth[ethcount].if_ipv4,get_interface_address(ifname,AF_INET));
					strcpy(eth[ethcount].if_ipv6,get_interface_address(ifname,AF_INET6));
					eth[ethcount].bytes_receive_1 = atoll(bytes_receive);
					eth[ethcount].packets_receive_1 = atoll(packets_receive);
					eth[ethcount].error_receive_1 = atoll(errs_receive);
					eth[ethcount].drop_receive_1 = atoll(drop_receive);
					eth[ethcount].bytes_transmit_1 = atoll(bytes_transmit);
					eth[ethcount].packets_transmit_1 = atoll(packets_transmit);
					eth[ethcount].error_transmit_1 = atoll(errs_transmit);
					eth[ethcount].drop_transmit_1 = atoll(drop_transmit);
					eth[ethcount].colls_1 = atoll(colls);
					strcpy(eth[ethcount].bytes_receive_t,convert_bytes((double)eth[ethcount].bytes_receive_1,"Bytes"));
					strcpy(eth[ethcount].packets_receive_t,convert_bytes((double)eth[ethcount].packets_receive_1,"Packets"));
					strcpy(eth[ethcount].error_receive_t,convert_bytes((double)eth[ethcount].error_receive_1,"Packets"));
					strcpy(eth[ethcount].drop_receive_t,convert_bytes((double)eth[ethcount].drop_receive_1,"Packets"));
					strcpy(eth[ethcount].bytes_transmit_t,convert_bytes((double)eth[ethcount].bytes_transmit_1,"Bytes"));
					strcpy(eth[ethcount].packets_transmit_t,convert_bytes((double)eth[ethcount].packets_transmit_1,"Packets"));
					strcpy(eth[ethcount].error_transmit_t,convert_bytes((double)eth[ethcount].error_transmit_1,"Packets"));
					strcpy(eth[ethcount].drop_transmit_t,convert_bytes((double)eth[ethcount].drop_transmit_1,"Packets"));
					strcpy(eth[ethcount].colls_t,convert_bytes((double)eth[ethcount].colls_1,"Packets"));
					ethcount++;
					// logger(prefix,"ETHINFO [%s] --> Bytes: [%s]\n",eth[ethcount-1].ifname, eth[ethcount-1].bytes_receive_t);
				}		
				fclose(fp);	
			
			}


			sysinfo(&sys);

			list = NULL;
			lentries = 0;
			dir = opendir("/proc");
			if ( dir == NULL ){
				fprintf(ss,"\r\nERR[Cannot open /proc]\r\n");
				fflush(ss);
				shutdown(sock,SHUT_RDWR);
				fclose(ss);
				return;
			}
			while ( (diry = readdir(dir)) != NULL ){
				char fname[1024];
				char exe[1024];
				char state;
				unsigned long utime;
				unsigned long stime;
				unsigned long cutime;
				unsigned long cstime;
				long priority;
				long nice;
				long rss;
				long num_threads;
				long long starttime;
				unsigned long vmsize;
				int ppid;
				int cpu_id;
				char *ptr;
				int pid;
				FILE *fp;

				if ( !isdigit(diry->d_name[0]) ) continue;	
				pid = atoi(diry->d_name);
				sprintf(fname,"/proc/%d/stat",pid);
				fp = fopen(fname,"r");
				if ( fp == NULL ) continue;
				if ( fgets(fname,1024,fp) == NULL ){ fclose(fp); continue; }	
				fclose(fp);
				ptr = strtok(fname," \t"); // PID
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // CMD
				if ( ptr == NULL ) continue;	
				strcpy(exe,ptr);
				ptr = strtok(NULL," \t"); // STATE
				if ( ptr == NULL ) continue;	
				state = *ptr;
				ptr = strtok(NULL," \t"); // PPID
				if ( ptr == NULL ) continue;	
				ppid = atoi(ptr);
				ptr = strtok(NULL," \t"); // PGRP
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // SESSION
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // TTYNR
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // TPGID
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // FLAGS
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // MINFLT
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // CMINFLT
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // MAJFLT
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // CMAJFLT
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // UTIME
				if ( ptr == NULL ) continue;	
				utime = atol(ptr);	
				ptr = strtok(NULL," \t"); // STIME
				if ( ptr == NULL ) continue;	
				stime = atol(ptr);	
				ptr = strtok(NULL," \t"); // CUTIME
				if ( ptr == NULL ) continue;	
				cutime = atol(ptr);	
				ptr = strtok(NULL," \t"); // CSTIME
				if ( ptr == NULL ) continue;	
				cstime = atol(ptr);	
				ptr = strtok(NULL," \t"); // PRIORITY
				if ( ptr == NULL ) continue;	
				priority = atol(ptr);	
				ptr = strtok(NULL," \t"); // NICE
				if ( ptr == NULL ) continue;	
				nice = atol(ptr);	
				ptr = strtok(NULL," \t"); // NUMTHREADS
				if ( ptr == NULL ) continue;	
				num_threads = atol(ptr);	
				ptr = strtok(NULL," \t"); // ITREALVALUE
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // STARTTIME
				if ( ptr == NULL ) continue;	
				starttime = atoll(ptr);	
				ptr = strtok(NULL," \t"); // VMSIZE
				if ( ptr == NULL ) continue;	
				vmsize = atol(ptr);	
				ptr = strtok(NULL," \t"); // RSS
				if ( ptr == NULL ) continue;	
				rss = atol(ptr);	
				ptr = strtok(NULL," \t"); // RSSLIM
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // STARTCODE
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // ENDCODE
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // STARTSTACK
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // KSTKESP
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // KSTKEIP
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // SIGNAL
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // BLOCKED
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // SIGIGNORE
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // SIGCATCH
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // WCHAN
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // NSWAP
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // CNSWAP
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // EXIT_SIGNAL
				if ( ptr == NULL ) continue;	
				ptr = strtok(NULL," \t"); // PROCESSOR
				if ( ptr == NULL ) continue;	
				cpu_id = atoi(ptr);

				// logger(prefix,"PROCLIST (%d) CPU: [%d], RSS: [%ld], PPID: %d [%s] VMSIZE: %lu Bytes, NICE: %ld UTIME: %lu ticks STIME: %lu ticks (%d Ticks per second)\n",pid,cpu_id,rss,ppid,exe,vmsize,nice,utime,stime,sysconf(_SC_CLK_TCK));

				list = (struct process_info *)realloc(list,sizeof(struct process_info) * (lentries+1));
				list[lentries].pid  = pid;
				list[lentries].ppid = ppid;
				list[lentries].vmsize = vmsize;
				sprintf(list[lentries].vmtext,"%lu&nbsp;B",vmsize);
				if ( vmsize > 1024 ) sprintf(list[lentries].vmtext,"%lu&nbsp;kB",vmsize / 1024);
				if ( vmsize > (1024*1024) ) sprintf(list[lentries].vmtext,"%lu&nbsp;MB",vmsize / (1024 * 1024));
				strcpy(list[lentries].program,exe);
				list[lentries].nice = nice;
				list[lentries].num_threads = num_threads;
				list[lentries].cpu = cpu_id;
				list[lentries].rss = rss;
				list[lentries].priority = priority;
				list[lentries].ptime = (utime + stime) / sysconf(_SC_CLK_TCK);
				list[lentries].utime = utime;
				list[lentries].utime2 = -1;
				list[lentries].stime = stime;
				list[lentries].stime2 = -1;
				list[lentries].starttime = time(NULL) - (sys.uptime - (starttime / sysconf(_SC_CLK_TCK)));
				gettimeofday(&(list[lentries].stamp),NULL);
				lentries++;
			}
			closedir(dir); 	
			{ // Sleep now for 0.5 seconds...than check the ticks again
				struct timespec tv;
				struct timespec rem;
				tv.tv_sec = 0;
				tv.tv_nsec = 800000000;
				while ( nanosleep(&tv,&rem) < 0 && errno == EINTR && rem.tv_sec != 0 && rem.tv_nsec != 0 ){
					tv = rem;
				}
				for ( ix = 0; ix < lentries; ix++ ){
					char fname[1024];
					FILE *fp;
					unsigned long utime;
					unsigned long stime;
					
					sprintf(fname,"/proc/%d/stat",list[ix].pid);
					fp = fopen(fname,"r");
					if ( fp == NULL ) continue;
					if ( fgets(fname,1024,fp) == NULL ){ fclose(fp); continue; }	
					fclose(fp);
					ptr = strtok(fname," \t"); // PID
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // CMD
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // STATE
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // PPID
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // PGRP
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // SESSION
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // TTYNR
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // TPGID
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // FLAGS
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // MINFLT
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // CMINFLT
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // MAJFLT
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // CMAJFLT
					if ( ptr == NULL ) continue;	
					ptr = strtok(NULL," \t"); // UTIME
					if ( ptr == NULL ) continue;	
					utime = atol(ptr);	
					ptr = strtok(NULL," \t"); // STIME
					if ( ptr == NULL ) continue;	
					stime = atol(ptr);	
					list[ix].utime2 = utime - list[ix].utime;
					list[ix].stime2 = stime - list[ix].stime;
					gettimeofday(&(list[ix].stamp2),NULL);
					{
						double old, new;
						double ticks; 
						old = (double)list[ix].stamp.tv_sec + ((double)list[ix].stamp.tv_usec)/1000000.0;
						new = (double)list[ix].stamp2.tv_sec + ((double)list[ix].stamp2.tv_usec)/1000000.0;
						ticks = ((double) sysconf(_SC_CLK_TCK)) * (new - old);
						if ( list[ix].utime2 || list[ix].stime2 ){
							list[ix].cpu_usage = ((double)(list[ix].utime2 +  list[ix].stime2)/ ticks) * 100.0;
							if ( list[ix].cpu_usage >= 100.0 ) list[ix].cpu_usage = 100.0; // Quick & Dirty :-)
							//  logger(prefix,"************************* PROCLIST: %d [%s] [%.02f %%] Ticks-elapsed: %.02f, Time elapsed: %.02f, UTIME2: %d, STIME2: %d\n",list[ix].pid,list[ix].program,list[ix].cpu_usage,ticks,new-old, list[ix].utime2, list[ix].stime2);
						} else {
							list[ix].cpu_usage = 0.0;
						}
						
					}
				}	
			}
			{ 
				FILE *fp;
				char buf[1024];
				ethcount = 0;
				fp = fopen("/proc/net/dev","r");
				if ( fp == NULL ){
					fprintf(ss,"\r\nERR[Cannot open /proc/net/dev]\r\n");
					fflush(ss);
					shutdown(sock,SHUT_RDWR);
					fclose(ss);
					return;
				}				
				while ( fgets(buf,1024,fp) != NULL ){
					char ifname[256];
					char *ptr;
					char bytes_receive[64];
					char packets_receive[64];
					char errs_receive[64];
					char drop_receive[64];
					char bytes_transmit[64];
					char packets_transmit[64];
					char errs_transmit[64];
					char drop_transmit[64];
					char colls[64];
					if ( strstr(buf,":") == NULL ) continue;
					ptr = strtok(buf,":\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(ifname,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(bytes_receive,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(packets_receive,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(errs_receive,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(drop_receive,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // FIFO

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // FRAME

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // COMPRESSED

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // MULTICAST

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(bytes_transmit,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(packets_transmit,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(errs_transmit,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(drop_transmit,ptr);

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue; // FIFO

					ptr = strtok(NULL,"\t\r\n ");
					if ( ptr == NULL ) continue;
					strcpy(colls,ptr);
					
					gettimeofday(&(eth[ethcount].stamp2),NULL);	
					eth[ethcount].bytes_receive_2 = atoll(bytes_receive);
					eth[ethcount].packets_receive_2 = atoll(packets_receive);
					eth[ethcount].error_receive_2 = atoll(errs_receive);
					eth[ethcount].drop_receive_2 = atoll(drop_receive);
					eth[ethcount].bytes_transmit_2 = atoll(bytes_transmit);
					eth[ethcount].packets_transmit_2 = atoll(packets_transmit);
					eth[ethcount].error_transmit_2 = atoll(errs_transmit);
					eth[ethcount].drop_transmit_2 = atoll(drop_transmit);
					eth[ethcount].colls_2 = atoll(colls);
					strcpy(eth[ethcount].bytes_receive_t,convert_bytes((double)eth[ethcount].bytes_receive_2,"Bytes"));
					strcpy(eth[ethcount].packets_receive_t,convert_bytes((double)eth[ethcount].packets_receive_2,"Packets"));
					strcpy(eth[ethcount].error_receive_t,convert_bytes((double)eth[ethcount].error_receive_2,"Packets"));
					strcpy(eth[ethcount].drop_receive_t,convert_bytes((double)eth[ethcount].drop_receive_2,"Packets"));
					strcpy(eth[ethcount].bytes_transmit_t,convert_bytes((double)eth[ethcount].bytes_transmit_2,"Bytes"));
					strcpy(eth[ethcount].packets_transmit_t,convert_bytes((double)eth[ethcount].packets_transmit_2,"Packets"));
					strcpy(eth[ethcount].error_transmit_t,convert_bytes((double)eth[ethcount].error_transmit_2,"Packets"));
					strcpy(eth[ethcount].drop_transmit_t,convert_bytes((double)eth[ethcount].drop_transmit_2,"Packets"));
					strcpy(eth[ethcount].colls_t,convert_bytes((double)eth[ethcount].colls_2,"Packets"));
					{
						double timediff;
						double datadiff;	
						double datasec;

						eth[ethcount].timestamp_calc = (((double) eth[ethcount].stamp1.tv_sec) + ((double) eth[ethcount].stamp1.tv_usec) / 1000000.0);
						timediff = (((double) eth[ethcount].stamp2.tv_sec) + ((double) eth[ethcount].stamp2.tv_usec) / 1000000.0) - (((double) eth[ethcount].stamp1.tv_sec) + ((double) eth[ethcount].stamp1.tv_usec) / 1000000.0);

						datadiff = ((double) eth[ethcount].bytes_receive_2) -  ((double) eth[ethcount].bytes_receive_1);
						datasec = datadiff / timediff;
						eth[ethcount].bytes_receive_sec = datasec;
						sprintf(eth[ethcount].bytes_receive_sec_t,"%s/s",convert_bytes(datasec,"Bytes"));

						datadiff = ((double) eth[ethcount].packets_receive_2) -  ((double) eth[ethcount].packets_receive_1);
						datasec = datadiff / timediff;
						eth[ethcount].packets_receive_sec = datasec;
						sprintf(eth[ethcount].packets_receive_sec_t,"%s/s",convert_bytes(datasec,"Packets"));
						
						datadiff = ((double) eth[ethcount].error_receive_2) -  ((double) eth[ethcount].error_receive_1);
						datasec = datadiff / timediff;
						eth[ethcount].error_receive_sec = datasec;
						sprintf(eth[ethcount].error_receive_sec_t,"%s/s",convert_bytes(datasec,"Packets"));
						
						datadiff = ((double) eth[ethcount].drop_receive_2) -  ((double) eth[ethcount].drop_receive_1);
						datasec = datadiff / timediff;
						eth[ethcount].drop_receive_sec = datasec;
						sprintf(eth[ethcount].drop_receive_sec_t,"%s/s",convert_bytes(datasec,"Packets"));

						datadiff = ((double) eth[ethcount].bytes_transmit_2) -  ((double) eth[ethcount].bytes_transmit_1);
						datasec = datadiff / timediff;
						eth[ethcount].bytes_transmit_sec = datasec;
						sprintf(eth[ethcount].bytes_transmit_sec_t,"%s/s",convert_bytes(datasec,"Bytes"));

						datadiff = ((double) eth[ethcount].packets_transmit_2) -  ((double) eth[ethcount].packets_transmit_1);
						datasec = datadiff / timediff;
						eth[ethcount].packets_transmit_sec = datasec;
						sprintf(eth[ethcount].packets_transmit_sec_t,"%s/s",convert_bytes(datasec,"Packets"));
						
						datadiff = ((double) eth[ethcount].error_transmit_2) -  ((double) eth[ethcount].error_transmit_1);
						datasec = datadiff / timediff;
						eth[ethcount].error_transmit_sec = datasec;
						sprintf(eth[ethcount].error_transmit_sec_t,"%s/s",convert_bytes(datasec,"Packets"));
						
						datadiff = ((double) eth[ethcount].drop_transmit_2) -  ((double) eth[ethcount].drop_transmit_1);
						datasec = datadiff / timediff;
						eth[ethcount].drop_transmit_sec = datasec;
						sprintf(eth[ethcount].drop_transmit_sec_t,"%s/s",convert_bytes(datasec,"Packets"));

						datadiff = ((double) eth[ethcount].colls_2) -  ((double) eth[ethcount].colls_1);
						datasec = datadiff / timediff;
						eth[ethcount].colls_sec = datasec;
						sprintf(eth[ethcount].colls_sec_t,"%s/s",convert_bytes(datasec,"Packets"));



						// logger(prefix,"ETHINFO(2) [%s] --> B: [%llu] Timediff: %.02f D: %.02f Bytes [%s]\n",eth[ethcount].ifname, eth[ethcount].bytes_receive_1,timediff,datadiff,eth[ethcount].bytes_receive_sec_t);
					}
					ethcount++;
				}		
				fclose(fp);	
			}
			// logger(prefix,"ETHINFO: Interfaces found: %d\n",ethcount);
			qsort(&eth[0],ethcount,sizeof(struct ethinfo),comparer_eth);
			// logger(prefix,"ETHINFO: Interfaces found: %d\n",ethcount);
			{
				int idx;
				ethjson = strdup("[");
				for ( idx = 0; idx < ethcount; idx++ ){
					char line[1048];

					sprintf(line,"{\"ifname\":\"%s\",\"timestamp\":%.06f,",
						eth[idx].ifname, eth[idx].timestamp_calc);
					sprintf(&line[strlen(line)],"\"mac_addr\":\"%s\",\"ipv4_addr\":\"%s\",\"ipv6_addr\":\"%s\",",
						eth[idx].if_mac, eth[idx].if_ipv4,eth[idx].if_ipv6);
					sprintf(&line[strlen(line)],"\"bytes_in_t\":\"%s\",\"bytes_out_t\":\"%s\",",
						eth[idx].bytes_receive_t, eth[idx].bytes_transmit_t);
					sprintf(&line[strlen(line)],"\"packets_in_t\":\"%s\",\"packets_out_t\":\"%s\",",
						eth[idx].packets_receive_t, eth[idx].packets_transmit_t);
					sprintf(&line[strlen(line)],"\"bytes_in_sec\":\"%s\",\"bytes_out_sec\":\"%s\",",
						eth[idx].bytes_receive_sec_t, eth[idx].bytes_transmit_sec_t);
					sprintf(&line[strlen(line)],"\"bytes_in\":%llu,\"bytes_out\":%llu,",
						eth[idx].bytes_receive_1, eth[idx].bytes_transmit_1);
					sprintf(&line[strlen(line)],"\"packets_in\":%llu,\"packets_out\":%llu,",
						eth[idx].packets_receive_1, eth[idx].packets_transmit_1);
					sprintf(&line[strlen(line)],"\"packets_out_sec\":\"%s\",\"packets_in_sec\":\"%s\"},",
						eth[idx].packets_transmit_sec_t, eth[idx].packets_receive_sec_t);


					// logger(prefix,"ETHINFO[%d]: [%s] Timestamp: %.06f [%s], [%s] R: %llu T: %llu TRS: [%s] RRS: [%s] \n",idx,eth[idx].ifname, eth[idx].timestamp_calc,eth[idx].packets_transmit_sec_t, eth[idx].packets_receive_sec_t,  eth[idx].bytes_receive_1, eth[idx].bytes_transmit_1, eth[idx].bytes_receive_sec_t, eth[idx].bytes_transmit_sec_t);

					ethjson = (char *)realloc(ethjson,strlen(ethjson) + strlen(line) + 10);
					sprintf(&ethjson[strlen(ethjson)],"%s",line);
				}
				if ( ethjson[strlen(ethjson)-1] == ',' ) ethjson[strlen(ethjson)-1] = '\0';
				ethjson = (char *)realloc(ethjson,strlen(ethjson) +  10);
				strcat(ethjson,"]");
				
			}
			{ 
				// Get File-System information
				FILE *fp;
				char buf[1024];

				fsjson = strdup("[");

				fp = fopen("/proc/self/mountinfo","r");
				if ( fp != NULL ){
					while (fgets(buf,1024,fp)!= NULL ){
						char line[1024];
						char *ptr;
						char path[256];
						char dev[256];
						char dev_name[256];
						char type[256];
						struct statfs st;
						ptr = strtok(buf," \t\r\n");
						if ( ptr == NULL ) continue; // ID
						ptr = strtok(NULL," \t\r\n");
						if ( ptr == NULL ) continue; // Blabla
						ptr = strtok(NULL," \t\r\n");
						if ( ptr == NULL ) continue; // DEV
						strcpy(dev,ptr);
						ptr = strtok(NULL," \t\r\n");
						if ( ptr == NULL ) continue; // SLASH
						ptr = strtok(NULL," \t\r\n");
						if ( ptr == NULL ) continue; // PATH
						strcpy(path,ptr);
						ptr = strtok(NULL," \t\r\n");
						if ( ptr == NULL ) continue; // OPT
						ptr = strtok(NULL," \t\r\n");
						if ( ptr == NULL ) continue; // X
						ptr = strtok(NULL," \t\r\n");
						if ( ptr == NULL ) continue; // TYPE
						strcpy(type,ptr);
						if ( strncmp(type,"ext",3) != 0  ) continue;
						if ( statfs(path,&st) ) continue;
						logger(prefix,"DSINFO [%s] --> [%s] BLK-SIZE: %d BLOCKS: %llu\n",path,type,(int) FRAG_SIZE,(unsigned long long) st.f_blocks);	
						strcpy(dev_name, get_diskname(dev));
						sprintf(line,"{\"path\":\"%s\",",path);
						sprintf(&line[strlen(line)],"\"type\":\"%s\",",type);
						sprintf(&line[strlen(line)],"\"dev\":\"%s\",",dev);
						sprintf(&line[strlen(line)],"\"dev_name\":\"%s\",",dev_name);
						sprintf(&line[strlen(line)],"\"b_total\":%llu,",(unsigned long long) st.f_blocks * (unsigned long long) FRAG_SIZE);
						sprintf(&line[strlen(line)],"\"b_total_t\":\"%s\",",convert_bytes((double)((unsigned long long) st.f_blocks * (unsigned long long) FRAG_SIZE),"Bytes"));
						sprintf(&line[strlen(line)],"\"b_free\":%llu,",(unsigned long long) st.f_bfree * (unsigned long long) FRAG_SIZE);
						sprintf(&line[strlen(line)],"\"b_free_t\":\"%s\",",convert_bytes((double)((unsigned long long) st.f_bavail * (unsigned long long) FRAG_SIZE),"Bytes"));
						sprintf(&line[strlen(line)],"\"b_avail\":%llu,",(unsigned long long) st.f_bavail * (unsigned long long) FRAG_SIZE);
						sprintf(&line[strlen(line)],"\"b_avail_t\":\"%s\",",convert_bytes((double)((unsigned long long) st.f_bavail * (unsigned long long) FRAG_SIZE),"Bytes"));
						sprintf(&line[strlen(line)],"\"i_total\":%llu,",(unsigned long long) st.f_files);
						sprintf(&line[strlen(line)],"\"i_total_t\":\"%s\",",convert_bytes((double)((unsigned long long) st.f_files),"Inodes"));
						sprintf(&line[strlen(line)],"\"i_free\":%llu,",(unsigned long long) st.f_ffree );
						sprintf(&line[strlen(line)],"\"i_free_t\":\"%s\"",convert_bytes((double)((unsigned long long) st.f_ffree),"Inodes"));
						sprintf(&line[strlen(line)],"},");
						fsjson = (char *)realloc(fsjson,strlen(fsjson) + strlen(line) + 10);
						sprintf(&fsjson[strlen(fsjson)],"%s",line);

					}
					fclose(fp);
				} else {
					logger(prefix,"Getting Filesystems from /proc/mounts...\n");
					fp = fopen("/proc/mounts","r");
					if ( fp != NULL ){
						while (fgets(buf,1024,fp)!= NULL ){
							char line[1024];
							char *ptr;
							char path[256];
							char dev[256];
							char dev_name[256];
							char type[256];
							struct statfs st;
							ptr = strtok(buf," \t\r\n");
							if ( ptr == NULL ) continue; // DEV
							strcpy(dev,ptr);
							ptr = strtok(NULL," \t\r\n");
							if ( ptr == NULL ) continue; // PATH
							strcpy(path,ptr);
							ptr = strtok(NULL," \t\r\n");
							if ( ptr == NULL ) continue; // TYPE
							strcpy(type,ptr);
							if ( strncmp(type,"ext",3) != 0  ) continue;
							if ( statfs(path,&st) ) continue;
							logger(prefix,"DSINFO [%s] --> [%s] BLK-SIZE: %d BLOCKS: %llu\n",path,type,(int) FRAG_SIZE,(unsigned long long) st.f_blocks);	
							strcpy(dev_name, get_diskname(path));
							sprintf(line,"{\"path\":\"%s\",",path);
							sprintf(&line[strlen(line)],"\"type\":\"%s\",",type);
							sprintf(&line[strlen(line)],"\"dev\":\"%s\",",dev);
							sprintf(&line[strlen(line)],"\"dev_name\":\"%s\",",dev_name);
							sprintf(&line[strlen(line)],"\"b_total\":%llu,",(unsigned long long) st.f_blocks * (unsigned long long) FRAG_SIZE);
							sprintf(&line[strlen(line)],"\"b_total_t\":\"%s\",",convert_bytes((double)((unsigned long long) st.f_blocks * (unsigned long long) FRAG_SIZE),"Bytes"));
							sprintf(&line[strlen(line)],"\"b_free\":%llu,",(unsigned long long) st.f_bfree * (unsigned long long) FRAG_SIZE);
							sprintf(&line[strlen(line)],"\"b_free_t\":\"%s\",",convert_bytes((double)((unsigned long long) st.f_bavail * (unsigned long long) FRAG_SIZE),"Bytes"));
							sprintf(&line[strlen(line)],"\"b_avail\":%llu,",(unsigned long long) st.f_bavail * (unsigned long long) FRAG_SIZE);
							sprintf(&line[strlen(line)],"\"b_avail_t\":\"%s\",",convert_bytes((double)((unsigned long long) st.f_bavail * (unsigned long long) FRAG_SIZE),"Bytes"));
							sprintf(&line[strlen(line)],"\"i_total\":%llu,",(unsigned long long) st.f_files);
							sprintf(&line[strlen(line)],"\"i_total_t\":\"%s\",",convert_bytes((double)((unsigned long long) st.f_files),"Inodes"));
							sprintf(&line[strlen(line)],"\"i_free\":%llu,",(unsigned long long) st.f_ffree );
							sprintf(&line[strlen(line)],"\"i_free_t\":\"%s\"",convert_bytes((double)((unsigned long long) st.f_ffree),"Inodes"));
							sprintf(&line[strlen(line)],"},");
							fsjson = (char *)realloc(fsjson,strlen(fsjson) + strlen(line) + 10);
							sprintf(&fsjson[strlen(fsjson)],"%s",line);
						}
						fclose(fp);
					}
				}

				if ( fsjson[strlen(fsjson)-1] == ',' ) fsjson[strlen(fsjson)-1] = '\0';
				fsjson = (char *)realloc(fsjson,strlen(fsjson) + 10);
				sprintf(&fsjson[strlen(fsjson)],"]");
				
			}



			qsort(&list[0],lentries,sizeof(struct process_info), comparer);
			// logger(prefix,"************************PROCLIST:  Sorted %d processes\n",lentries);
			result = strdup("{\"pl\":[");
			for ( ix = 0; ix < lentries; ix++ ){
				char line[1024];
				char ptime[32];
				char stime[32];
				char rss[32];
				double rss_val;
				int slot, index;
				struct tm *tm;
				int hours;
				int minutes;
				int seconds;
				slot = -1;
				index = -1;
				if ( list[ix].pid > 10 ) { 
					int k,l;
					for ( k = 0; k < entries; k++ ){
						for ( l = 0; l < MAX_CONNS; l++ ){
							if ( servlist[k].co[l].cpid == list[ix].pid ){
								slot = k;
								index = l;
								break;
							}
						}
						if ( slot >= 0 ) break;
					}
				}
				hours = list[ix].ptime / 3600;
				minutes = (list[ix].ptime - hours * 3600)/60;
				seconds = list[ix].ptime % 60;
				tm = localtime(&list[ix].starttime);
				sprintf(ptime,"%02d:%02d:%02d",hours,minutes,seconds);
				sprintf(stime,"%04d.%02d.%02d&nbsp;%02d:%02d:%02d",
					tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
					tm->tm_hour, tm->tm_min, tm->tm_sec);


				rss_val = (double) (list[ix].rss * sysconf(_SC_PAGESIZE));
				sprintf(rss,"%d&nbsp;Bytes",(int)rss_val);
				if ( rss_val > 1024.0 ){
					sprintf(rss,"%.02f&nbsp;KB",rss_val / 1024.0);
				}
				if ( rss_val > (1024.0*1024.0) ){
					sprintf(rss,"%.02f&nbsp;MB",rss_val / (1024.0 * 1024.0));
				}
					

				sprintf(line,"{\"rss\":\"%s\",\"num_threads\":%d,\"cpu\":%d,\"cpu_usage\":\"%.02f\",\"pid\":%d,\"ppid\":%d,\"vmsize\":\"%s\",\"prg\":\"%s\",\"stime\":\"%s\",\"ptime\":\"%s\",\"slot\":%d,\"index\":%d,\"_utime\":%ld,\"_stime\":%ld,\"nice\":%ld,\"priority\":%ld},",
					rss, list[ix].num_threads, list[ix].cpu, list[ix].cpu_usage, list[ix].pid,list[ix].ppid,list[ix].vmtext,list[ix].program,stime,ptime,slot,index,list[ix].utime,list[ix].stime,list[ix].nice,list[ix].priority);
				// logger(prefix,"[%05d]PROCLIST: [%s] STRLEN RESULT: %d\n",ix,line,strlen(result));
				if ( list[ix].cpu > cpu_count ){
					usage_sum[0] += list[ix].cpu_usage;	
				} else {
					usage_sum[list[ix].cpu] += list[ix].cpu_usage;	
				}
				result = (char *)realloc(result,strlen(result)+strlen(line)+10);
				strcat(result,line);
			
			}
			if ( result[strlen(result)-1] == ',' ) result[strlen(result)-1] = '\0';
			{
				char tempbuf[20240];
				int dan;
				sprintf(tempbuf,"],\"eth\":%s,\"fs\":%s,\"cpu_count\":%d,\"load1\":%.02g,\"ul\":[",ethjson,fsjson,cpu_count,loader[0]);
				result = (char *)realloc(result,strlen(result)+strlen(tempbuf) + 10);
				strcat(result,tempbuf);
				for ( dan = 0; dan < cpu_count; dan++ ){
					if ( usage_sum[dan] > 100.0 ) usage_sum[dan] = 100.0;
					sprintf(tempbuf,"{\"total\":\"%.02f\"},",usage_sum[dan]);
					result = (char *)realloc(result,strlen(result)+strlen(tempbuf) + 10);
					strcat(result,tempbuf);
				}
				
				if ( result[strlen(result)-1] == ',' ) result[strlen(result)-1] = '\0';
				result = (char *)realloc(result,strlen(result)+ 10);
				strcat(result,"]}");
			}
			{
				char *in;
				char *out;
				int newsize;
				in = (char *)malloc(strlen(result) + 20);
				out = (char *)malloc(strlen(result) + 120);
				sprintf(in,"OK[%s]\r\n",result);
				newsize = gzip_string(in,out);
				if ( newsize > 0 ){
					fprintf(ss,"Accept-Range: bytes\r\n");
					fprintf(ss,"Content-Length: %d\r\n",newsize);	
					fprintf(ss,"Content-Encoding: gzip\r\n\r\n",newsize);	
					fwrite(out,1,newsize,ss);
					fflush(ss);
				} else {
					logger(prefix,"GZIP-FAILED: [%d] <-- [%d]\n",newsize,strlen(in));
					fprintf(ss,"\r\n%s",in);
				}
			}
			free(result);
			free(list);
			free(usage_sum);
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
			
		}

		if ( strcmp(command,"RESET") == 0 ){
			int idx;
			fprintf(ss,"\r\n");
			logger(prefix,"Resetting %d connections\n",entries);
			for ( idx = 0; idx < entries; idx++ ){
				int semmel;
				semmel = semget(INETD_KEY2 + idx,1,0);
				if ( semmel < 0 ){
					logger(prefix,"Cannot get SEM [0x%08lX]\n",INETD_KEY2 + idx);
				} else {
					sem_lock(semmel);
					servlist[idx].reset = time(NULL);
					servlist[idx].total_count = 0;
					sem_unlock(semmel);
				}
			}
			fprintf(ss,"OK[Reset done]\r\n");
			fflush(ss);
			shutdown(sock,SHUT_RDWR);
			fclose(ss);
			return;
		}


		fprintf(ss,"\r\n");
		fprintf(ss,"ERR[Bad function]\r\n");
		
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
	html_done = 0;
	if ( type_req == TYPE_HTML && strncmp(url,"/supervisor",strlen("/supervisor")) == 0 ){
		html_done = 1;
		fprintf(ss,"Content-Type: %s\r\n\r\n",HTML_MIME);
		fprintf(ss,"<HEAD><meta CHARSET=\"UTF-8\"><LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"/style.css\"></HEAD>\n");
		fprintf(ss,"<BODY CLASS='mainbody' onload=init_all()>");
		fprintf(ss,"<DIV CLASS='headline'><TABLE BORDER=0 WIDTH=100%%><TR><TD ALIGN=LEFT WIDTH=33%%><IMG CLASS=l_image onclick=go_main() SRC=/gix_logo.png></TD><TD WIDTH=33%%><CENTER><SPAN CLASS=headliner>%s (Supervisor) @ %s</SPAN></TD><TD ALIGN=RIGHT WIDTH=33%%><TABLE BORDER=0><TR><TD ALIGN=RIGHT>PID:</TD><TD ALIGN=LEFT><B>%d</B></TD></TR><TR><TD ALIGN=RIGHT>You:</TD><TD ALIGN=LEFT><B>%s</B></TD></TR><TR><TD ALIGN=RIGHT>Me:</TD><TD ALIGN=LEFT><B>%s</B></TD></TR></TABLE></TD></TR></TABLE>",
			GIX_INETD_VERSION, my_hostname,getppid(), CCON.source, CCON.target);
		fprintf(ss,"</DIV>");
		fprintf(ss,"<DIV ID='MAIN' CLASS=mainscreen>\n");
		fprintf(ss,"<CENTER>");
		fprintf(ss,"<TABLE BORDER=0 CELLSPACING=1>\n");
		fprintf(ss,"<TR><TD VALIGN=TOP>");
		fprintf(ss,"<DIV ID=HOSTLIST CLASS=simple_div></DIV>");
		fprintf(ss,"</TD></TR><TR><TD VALIGN=TOP><CENTER><BR><P>");
		fprintf(ss,"<TABLE BORDER=0 BGCOLOR=black CELLSPACING=1>\n");
		fprintf(ss,"<TR BGCOLOR=yellow><TD ALIGN=RIGHT><SPAN CLASS=thead2>Single-Check (IPv4, IPv6 or hostname):</SPAN></TD><TD ALIGN=LEFT><INPUT TYPE=TEXT CLASS=input2s ID=TEST_HOSTNAME></TD><TD ROWSPAN=1 VALIGN=BOTTOM><INPUT TYPE=BUTTON VALUE='Test host...' CLASS=standard_button onclick=test_host()></TD></TR>\n");
		fprintf(ss,"<TR BGCOLOR=lightblue><TD ALIGN=RIGHT><SPAN CLASS=thead2>Scan-IP Start (IPv4):</SPAN></TD><TD ALIGN=LEFT><INPUT TYPE=TEXT CLASS=input2s ID=IPSCAN_START onchange=update_end_field()></TD><TD ROWSPAN=2 VALIGN=BOTTOM><INPUT TYPE=BUTTON VALUE='Start scan...' CLASS=standard_button onclick=start_scan()></TD></TR>\n");
		fprintf(ss,"<TR BGCOLOR=lightblue><TD ALIGN=RIGHT><SPAN CLASS=thead2>Scan-IP End (IPv4):</SPAN></TD><TD ALIGN=LEFT><INPUT TYPE=TEXT CLASS=input2s ID=IPSCAN_END></TD></TR>\n");
		fprintf(ss,"</TABLE>\n");
		fprintf(ss,"</TD></TR>");
		fprintf(ss,"</TABLE>\n");
		fprintf(ss,"</DIV>");

		fprintf(ss,"<DIV CLASS=footer><CENTER>(C) Ing. Andy Paumann, globedom Bulgaria</DIV>");

		fprintf(ss,"<SCRIPT LANGUAGE=JavaScript>\n");
		
		fprintf(ss,"hostentry = {\n");
		fprintf(ss," url: '',\n");
		fprintf(ss," name: '',\n");
		fprintf(ss," version: '',\n");
		fprintf(ss," username: 'derDaniel',\n");
		fprintf(ss," password: '',\n");
		fprintf(ss," remark: '',\n");
		fprintf(ss," active: true\n");
		fprintf(ss,"};\n");


		fprintf(ss,"var hostlist = [];\n");
		fprintf(ss,"var s_hlisttimer = null;\n");

		fprintf(ss,"function sort_func(a,b){\n");
		fprintf(ss," return(a.remark.localeCompare(b.remark));\n");
		fprintf(ss,"}\n");
	
		fprintf(ss,"function init_all(){\n");
		fprintf(ss," load_cookie();\n");
		fprintf(ss," if ( hostlist.length == 0 ){\n");
		fprintf(ss,"  load_config();\n");
		fprintf(ss," }\n");
		fprintf(ss," hostlist.sort(sort_func);\n");
		fprintf(ss," s_hlisttimer = setInterval(update_responses,2000);\n");
		fprintf(ss," update_hostlist();\n");
		fprintf(ss," console.log('Init completed');\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function update_hostlist(){\n");
		fprintf(ss," var divvy = document.getElementById('HOSTLIST');\n");
		fprintf(ss," var result = '<CENTER><TABLE BORDER=0 CELLSPACING=1 BGCOLOR=black>';\n");
		fprintf(ss," result += '<TR BGCOLOR=white>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>&nbsp;</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Response</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Disks</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Load</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Remark</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Hostname</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>URL</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Version</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Password</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>&nbsp;</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>&nbsp;</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Response</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Disks</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Load</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Remark</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Hostname</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>URL</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Version</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>Password</SPAN></TD>';\n");
		fprintf(ss," result += '<TD><SPAN CLASS=thead1s>&nbsp;</SPAN></TD>';\n");
		fprintf(ss," result += '</TR>';\n");
		fprintf(ss," var lines = Math.floor(hostlist.length / 2);\n");
		fprintf(ss," if ( hostlist.length %% 2 ) lines++;\n");
		fprintf(ss," console.log('Lines: [' + lines + '] Hosts: [' + hostlist.length + ']');\n");
		fprintf(ss," for ( var i = 0; i < hostlist.length; i++ ){\n");
		fprintf(ss,"  var color = 'lightblue';\n");
		fprintf(ss,"  if ( i %% 2 ) color = 'yellow';\n");
		fprintf(ss,"  if ( (i %% 2) == 0 ) result += '<TR>';\n");
		fprintf(ss,"  var idx = Math.floor(i/2) + (i%%2);\n");
		fprintf(ss,"  if ( i %% 2 ) idx += (lines-1);\n");
		fprintf(ss,"  console.log('Index: [' + i + '] IDX: [' + idx + ']');\n");
		fprintf(ss,"  if ( idx >= hostlist.length ){\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' COLSPAN=10>';\n");
		fprintf(ss,"   continue;\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  if ( hostlist[idx].active ){\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + '><INPUT TYPE=CHECKBOX ID=ACTIVE_' + idx + ' CHECKED onchange=save_active(' + idx + ',false)></TD>';\n");
		fprintf(ss,"   result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s ID=RESPONSE_TIME_' + idx + '></SPAN></TD>';\n");
		fprintf(ss,"  } else {\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + '><INPUT TYPE=CHECKBOX ID=ACTIVE_' + idx + '  onchange=save_active(' + idx + ',true)></TD>';\n");
		fprintf(ss,"   result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead4s ID=RESPONSE_TIME_' + idx + '>not monitored</SPAN></TD>';\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  result += '<TD ALIGN=CENTER ID=DISK_WARN_' + idx + ' BGCOLOR=' + color + '></TD>';\n"); // DISK-WARN
		fprintf(ss,"  result += '<TD ALIGN=CENTER ID=LOAD_WARN_' + idx + ' BGCOLOR=' + color + '></TD>';\n"); // CPU-WARN
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + '><INPUT TYPE=TEXT CLASS=input2s VALUE=\"' + hostlist[idx].remark + '\" ID=REMARK_' + idx + ' onchange=save_remark(' + idx + ')></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + hostlist[idx].name + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + color + '><SPAN CLASS=thead2links onclick=goto_url(\"' + hostlist[idx].url + '\")>' + hostlist[idx].url.substr(7) + '</SPAN></TD>';\n");

		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s ID=VERSION_' + idx + '>' + get_version_number(hostlist[idx].version) + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + '><INPUT TYPE=TEXT CLASS=input2s SIZE=6 VALUE=\"' + hostlist[idx].password + '\" ID=PASSWORD_' + idx + ' onchange=save_pwd(' + idx + ')></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + '>';\n");
		fprintf(ss,"  result += '<INPUT TYPE=BUTTON CLASS=standard_buttons VALUE=\"Delete\" onclick=del_element(' + idx + ')>';\n");
		fprintf(ss,"  result += '&nbsp;';\n");
		fprintf(ss,"  result += '<INPUT TYPE=BUTTON CLASS=standard_buttons VALUE=\"Check\" onclick=recheck(' + idx + ')>';\n");
		fprintf(ss,"  result += '&nbsp;';\n");
		fprintf(ss,"  result += '<INPUT TYPE=BUTTON CLASS=standard_buttons VALUE=\"Update\" onclick=update_version_r(' + idx + ')>';\n");
		fprintf(ss,"  result += '</TD>';\n");
		fprintf(ss,"  if ( (i %% 2) != 0 ) result += '</TR>';\n");
		fprintf(ss," }\n");
		fprintf(ss," if ( i %% 2 ) result += '<TD BGCOLOR=yellow COLSPAN=10></TD></TR>';\n");
		fprintf(ss," result += '</TABLE>';\n");
		fprintf(ss," result += '<P><CENTER>';\n");
		fprintf(ss," result += '<INPUT TYPE=BUTTON CLASS=standard_button VALUE=\"Save hostlist as new default\" onclick=save_config()>';\n");
		fprintf(ss," result += '&nbsp;<INPUT TYPE=BUTTON CLASS=standard_button VALUE=\"Save global hostlist\" onclick=save_config_x()>';\n");
		fprintf(ss," result += '&nbsp;<INPUT TYPE=BUTTON CLASS=standard_button VALUE=\"Clear local cookie (will load defaults on next reload)\" onclick=reset_cookie()>';\n");
		fprintf(ss," result += '&nbsp;<INPUT TYPE=BUTTON CLASS=standard_button VALUE=\"Save hostlist to Cookie\" onclick=save_cookie()>';\n");
		fprintf(ss," result += '&nbsp;<INPUT TYPE=BUTTON CLASS=standard_button VALUE=\"Clear hostlist\" onclick=del_hostlist()>';\n");
		fprintf(ss," divvy.innerHTML = result;\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function update_responses(){\n");
		fprintf(ss," for ( var i = 0; i < hostlist.length; i++ ){\n");
		fprintf(ss,"  if ( hostlist[i].active == false ) continue;\n");
		fprintf(ss,"  var req2 = new XMLHttpRequest();\n");
		fprintf(ss,"  req2.hostlist_idx = i;\n");
		fprintf(ss,"  req2.gix_start_time = Date.now();\n");
		fprintf(ss,"  req2.onreadystatechange = update_responses_callback;\n");
		// fprintf(ss,"  console.log('TESTING: [' + hostlist[i].url + '/version]');\n");
		fprintf(ss,"  req2.open('GET',hostlist[i].url + '/version',true);\n");
		fprintf(ss,"  req2.send();\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function update_version_r(idx){\n");
		fprintf(ss," var ii = 0;\n");
		fprintf(ss," var a_current_version = '%s';\n",GIX_INETD_VERSION);
		fprintf(ss," var a_installed_version = hostlist[idx].version;\n");
		fprintf(ss," for ( ii = 0; ii < a_current_version.length; ii++ ){\n");
		fprintf(ss,"  if ( a_current_version.charCodeAt(ii) > 47 && a_current_version.charCodeAt(ii) < 58 ) break;\n");
		fprintf(ss," }\n");
		fprintf(ss," var current_version_f = parseFloat(a_current_version.substr(ii));\n");
		fprintf(ss," if ( isNaN(current_version_f) ){ alert('Cannot determine current version'); return;}\n");
		fprintf(ss," console.log('Currently local version: [' + current_version_f + ']');\n");
		fprintf(ss," for ( ii = 0; ii < a_installed_version.length; ii++ ){\n");
		fprintf(ss,"  if ( a_installed_version.charCodeAt(ii) > 47 && a_installed_version.charCodeAt(ii) < 58 ) break;\n");
		fprintf(ss," }\n");
		fprintf(ss," var installed_version_f = parseFloat(a_installed_version.substr(ii));\n");
		fprintf(ss," if ( isNaN(installed_version_f) ){ alert('Cannot determine current version'); return;}\n");
		fprintf(ss," console.log('Currently installed version: [' + installed_version_f + ']');\n");
		fprintf(ss," if ( a_installed_version >= a_current_version ){\n");
		fprintf(ss,"  alert('There is already installed the actual/newer version (' + a_installed_version + ')');\n");
		fprintf(ss,"  return;\n");
		fprintf(ss," }\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.open('GET',hostlist[idx].url + '/update_version/0',true);\n");
		fprintf(ss," request.setRequestHeader('Authorization','Basic ' + btoa(hostlist[idx].username + ':' + hostlist[idx].password));\n");
		fprintf(ss," request.send();\n");
		fprintf(ss," alert('Update request sent...');\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function get_version_number(vers){\n");
		fprintf(ss," for ( var i = 0; i < vers.length; i++ ){\n");
		fprintf(ss,"  if ( vers.charCodeAt(i) > 47 && vers.charCodeAt(i) < 58 ) break;\n");
		fprintf(ss," }\n");
		fprintf(ss," return(vers.substr(i));\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function update_responses_callback(){\n");
		fprintf(ss," var req = this;\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status == 200 && req.responseText.charAt(0) == 'O' ){\n");
		fprintf(ss,"  var now = Date.now();\n");
		fprintf(ss,"  var vers = JSON.parse(extract_bracket_val(req.responseText));\n");
		// fprintf(ss,"  console.log('Received Version-String [' + get_version_number(vers.version) + '] for Index: [' + req.hostlist_idx + ']');\n");
		fprintf(ss,"  document.getElementById('VERSION_' + req.hostlist_idx).innerHTML = get_version_number(vers.version);\n");
		fprintf(ss,"  hostlist[req.hostlist_idx].version = vers.version;\n");
		fprintf(ss,"  var delta = now - req.gix_start_time;\n"); 
		// fprintf(ss,"  console.log('HOST [' + hostlist[req.hostlist_idx].url + '] Response-Time: [' + delta + ' ms]');\n");
		fprintf(ss,"  window.document.getElementById('RESPONSE_TIME_' + req.hostlist_idx).setAttribute('class','thead2s');\n");
		fprintf(ss,"  window.document.getElementById('RESPONSE_TIME_' + req.hostlist_idx).innerHTML = delta + '&nbsp;ms';\n");
		fprintf(ss," } else {\n");
		fprintf(ss,"  console.log('HOST [' + hostlist[req.hostlist_idx].url + '] Response-Time: [' + delta + ' ms] TIMEOUT!');\n");
		fprintf(ss,"  window.document.getElementById('RESPONSE_TIME_' + req.hostlist_idx).setAttribute('class','thead1s');\n");
		fprintf(ss,"  window.document.getElementById('RESPONSE_TIME_' + req.hostlist_idx).innerHTML = '<B>FAILED</B>';\n");
		fprintf(ss," }\n");
		// Get Disk & CPU Informations
		fprintf(ss," var req2 = new XMLHttpRequest();\n");
		fprintf(ss," req2.hostlist_idx = req.hostlist_idx;\n");
		fprintf(ss," req2.onreadystatechange = update_response_callback_callback;\n");
		fprintf(ss," req2.open('GET',hostlist[req2.hostlist_idx].url + '/ajax/PROCLIST/0',true);\n");
		fprintf(ss," req2.setRequestHeader('Authorization','Basic ' + btoa(hostlist[req2.hostlist_idx].username + ':' + hostlist[req2.hostlist_idx].password));\n");
		fprintf(ss," req2.send();\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function update_response_callback_callback(){\n");
		fprintf(ss," req = this;\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		// fprintf(ss," console.log('REQUEST-STATUS (' + hostlist[req.hostlist_idx].url  + ') --> [' + req.responseText + ']');\n");
		fprintf(ss," if ( req.responseText.charAt(0) != 'O' ) return;\n");
		fprintf(ss," var procinfo = JSON.parse(extract_bracket_val(req.responseText));\n");
		fprintf(ss," var normal_img = '/led_green.gif';\n");
		fprintf(ss," for ( var i = 0; i < procinfo.fs.length; i++ ){\n");
		fprintf(ss,"  var usage_percent = Math.round((100.0 - (procinfo.fs[i].b_avail * 100) / procinfo.fs[i].b_total)*100)/100;\n");
		// fprintf(ss,"  console.log('[' + hostlist[req.hostlist_idx].url + '](' + hostlist[req.hostlist_idx].name + ') FILESYSTEM: [' + procinfo.fs[i].path + '] AVAIL: [' + procinfo.fs[i].b_avail + '] TOTAL: [' + procinfo.fs[i].b_total + '] Factor: [' + usage_percent + '] Load: [' + procinfo.load1 + ']');\n");
		fprintf(ss,"  if ( usage_percent > 65 ) normal_img = '/led_orange.gif';\n");
		fprintf(ss,"  if ( usage_percent > 90 ){ normal_img = '/led_red.gif'; break; }\n");
		fprintf(ss," }\n");
		fprintf(ss," document.getElementById('DISK_WARN_' + req.hostlist_idx).innerHTML = '<IMG SRC=' + normal_img + ' WIDTH=24>';\n");
		fprintf(ss," normal_img = '/led_green.gif';\n");
		fprintf(ss," if ( procinfo.load1 > 1.0 ) normal_img = '/led_orange.gif';\n");
		fprintf(ss," if ( procinfo.load1 > 3.0 ) normal_img = '/led_red.gif';\n");
		fprintf(ss," document.getElementById('LOAD_WARN_' + req.hostlist_idx).innerHTML = '<IMG SRC=' + normal_img + ' WIDTH=24>';\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function setCookie(cname, cvalue, exmins) {\n");
		fprintf(ss,"  var d = new Date();\n");
		fprintf(ss,"  d.setTime(d.getTime() + (exmins*60*1000));\n");
		fprintf(ss,"  var expires = 'expires='+ d.toUTCString();\n");
		fprintf(ss,"  document.cookie = cname + '=' + cvalue + ';' + expires + ';path=/';\n");
		fprintf(ss,"}\n");
		fprintf(ss,"function delCookie(cname) {\n");
		fprintf(ss,"  var d = new Date();\n");
		fprintf(ss,"  d.setTime(d.getTime() - (500*24*60*60*1000) );\n");
		fprintf(ss,"  var expires = 'expires='+ d.toUTCString();\n");
		fprintf(ss,"  document.cookie = cname + '=' + null + ';' + expires + ';path=/';\n");
		fprintf(ss,"}\n");
		fprintf(ss,"\n");
		fprintf(ss,"function getCookie(cname) {\n");
		fprintf(ss,"  var name = cname + '=';\n");
		fprintf(ss,"  var decodedCookie = decodeURIComponent(document.cookie);\n");
		fprintf(ss,"  var ca = decodedCookie.split(';');\n");
		fprintf(ss,"  for(var i = 0; i <ca.length; i++) {\n");
		fprintf(ss,"    var c = ca[i];\n");
		fprintf(ss,"    while (c.charAt(0) == ' ') {\n");
		fprintf(ss,"      c = c.substring(1);\n");
		fprintf(ss,"    }\n");
		fprintf(ss,"    if (c.indexOf(name) == 0) {\n");
		fprintf(ss,"      return c.substring(name.length, c.length);\n");
		fprintf(ss,"    }\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  return '';\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function recheck(idx){\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.hostlist_idx = idx;\n");
		fprintf(ss," request.onreadystatechange = function() { recheck_callback(request); };\n");
		fprintf(ss," request.open('GET',hostlist[idx].url + '/version_s',true);\n");
		fprintf(ss," request.setRequestHeader('Authorization','Basic ' + btoa(hostlist[idx].username + ':' + hostlist[idx].password));\n");
		fprintf(ss," request.send();\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function recheck_callback(req){\n");
		fprintf(ss," console.log('ready-State: [' + req.readyState + '] Response-Code: [' + req.status + ']');\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status == 200 && req.responseText.charAt(0) == 'O' ){\n");
		fprintf(ss,"  console.log('Response: [' + req.responseText + ']');\n");
		fprintf(ss,"  var vers = JSON.parse(extract_bracket_val(req.responseText));\n");
		fprintf(ss,"  hostlist[req.hostlist_idx].version = vers.version;\n");
		fprintf(ss,"  hostlist[req.hostlist_idx].name = vers.hostname;\n");
		fprintf(ss,"  update_hostlist();\n");
		fprintf(ss,"  alert('Check successfull, Name and Versioninfo updated');\n");
		fprintf(ss,"  return;\n");
		fprintf(ss," }\n");
		fprintf(ss," alert('Check failed: HTTP-Status: [' + req.status + '] Response-Text: [' + req.responseText + ']');\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function del_hostlist(){\n");
		fprintf(ss," hostlist = [];\n");
		fprintf(ss," update_hostlist();\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function del_element(idx){\n");
		fprintf(ss," hostlist.splice(idx,1);\n");
		fprintf(ss," update_hostlist();\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function save_pwd(idx){\n");
		fprintf(ss,"  hostlist[idx].password = document.getElementById('PASSWORD_' + idx).value;\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function save_active(idx,newval){\n");
		fprintf(ss,"  hostlist[idx].active = newval;\n");
		fprintf(ss,"  if ( newval == false ){\n");
		fprintf(ss,"   window.document.getElementById('RESPONSE_TIME_' + idx).innerHTML = 'not monitored';\n");
		fprintf(ss,"   window.document.getElementById('RESPONSE_TIME_' + idx).setAttribute('class','thead3s');\n");
		fprintf(ss,"  }\n");
		fprintf(ss," update_hostlist();\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function save_remark(idx){\n");
		fprintf(ss,"  hostlist[idx].remark = document.getElementById('REMARK_' + idx).value;\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function reset_cookie(){\n");
		fprintf(ss," delCookie('gix_inetd_hostlist');\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function save_cookie(){\n");
		fprintf(ss," for ( var i = 0; i < hostlist.length; i++ ){\n");
		fprintf(ss,"  hostlist[i].password = document.getElementById('PASSWORD_' + i).value;\n");
		fprintf(ss,"  hostlist[i].remark = document.getElementById('REMARK_' + i).value;\n");
		fprintf(ss," }\n");
		fprintf(ss," var json_string = JSON.stringify(hostlist);\n");
		fprintf(ss," console.log('JSON_STRING: [' + json_string + ']');\n");
		fprintf(ss," setCookie('gix_inetd_hostlist',json_string,3000000);\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function save_config(){\n");
		fprintf(ss," if ( confirm('Are you sure, you want to overwrite system-configuration?') == false ) return;\n");
		fprintf(ss," var formData = new FormData();\n");
		fprintf(ss," formData.enctype = 'multipart/form-data';\n");
		fprintf(ss," formData.append('ACTION','SAVE_CONFIG');\n");
		fprintf(ss," formData.append('FILE','systems.cfg');\n");
		fprintf(ss," formData.append('DATA',JSON.stringify(hostlist));\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.onreadystatechange = save_config_callback;\n");
		fprintf(ss," request.open('POST','/ajax/AJAX',true);\n");
		fprintf(ss," // request.setRequestHeader('Authorization','Basic ' + btoa(hostlist[i].username + ':' + hostlist[i].password));\n");
		fprintf(ss," request.send(formData);\n");
		fprintf(ss," console.log('Sent SAVE-CONFIG Request to: myself');\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function save_config_callback(){\n");
		fprintf(ss," var request = this;\n");
		fprintf(ss," if ( request.readyState != 4 ) return;\n");
		fprintf(ss," console.log('(%s:%d) REQUEST-STATUS: [' + request.status + '] RESULT: [' + request.responseText + ']');\n",__FILE__,__LINE__);
		fprintf(ss," if ( request.status != 200 ){ alert('Bad response-Code from Server (check password and version): [' + request.status + ']'); return; }\n"); 
		fprintf(ss," if ( request.responseText.charAt(0) == 'O' ) { alert('Configuration successfully written '); return; }\n");
		fprintf(ss," alert('Saving configuration failed [' + request.responseText + ']');\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function save_config_x(){\n");
		fprintf(ss," if ( confirm('Are you sure, you want to overwrite system-configuration?') == false ) return;\n");
		fprintf(ss," for ( var i = 0; i < hostlist.length; i++ ){\n");
		fprintf(ss,"  var formData = new FormData();\n");
		fprintf(ss,"  formData.enctype = 'multipart/form-data';\n");
		fprintf(ss,"  formData.append('ACTION','SAVE_CONFIG');\n");
		fprintf(ss,"  formData.append('FILE','systems.cfg');\n");
		fprintf(ss,"  formData.append('DATA',JSON.stringify(hostlist));\n");
		fprintf(ss,"  var request = new XMLHttpRequest();\n");
		fprintf(ss,"  request.host_entry = hostlist[i];\n");
		fprintf(ss,"  request.onreadystatechange = save_config_x_callback;\n");
		fprintf(ss,"  request.open('POST',hostlist[i].url + '/ajax/AJAX',true);\n");
		fprintf(ss,"  request.setRequestHeader('Authorization','Basic ' + btoa(hostlist[i].username + ':' + hostlist[i].password));\n");
		fprintf(ss,"  request.send(formData);\n");
		fprintf(ss,"  console.log('Sent SAVE-CONFIG Request to: [' + hostlist[i].url + ']');\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function save_config_x_callback(){\n");
		fprintf(ss," var request = this;\n");
		fprintf(ss," if ( request.readyState != 4 ) return;\n");
		fprintf(ss," console.log('(%s:%d) REQUEST-STATUS: [' + request.status + '] RESULT: [' + request.responseText + ']');\n",__FILE__,__LINE__);
		fprintf(ss," if ( request.status != 200 ){ alert('Bad response-Code from Server (check password and version): [' + request.status + ']'); return; }\n"); 
		fprintf(ss," if ( request.responseText.charAt(0) == 'O' ) { alert('Configuration successfully written at: [' + request.host_entry.url + ']'); return; }\n");
		fprintf(ss," alert('Saving configuration failed at [' + request.host_entry.url + ']');\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function load_config(){\n");
		fprintf(ss," var formData = new FormData();\n");
		fprintf(ss," formData.enctype = 'multipart/form-data';\n");
		fprintf(ss," formData.append('ACTION','LOAD_CONFIG');\n");
		fprintf(ss," formData.append('FILE','systems.cfg');\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.open('POST','/ajax/AJAX',false);\n");
		fprintf(ss," request.send(formData);\n");
		fprintf(ss," console.log('(%s:%d) REQUEST-STATUS: [' + request.status + '] RESULT: [' + request.responseText + ']');\n",__FILE__,__LINE__);
		fprintf(ss," if ( request.responseText.charAt(0) != 'O' ){\n");
		fprintf(ss,"  alert('Cannot load config [' + extract_bracket_val(request.responseText) + ']');\n");
		fprintf(ss,"  return;\n");
		fprintf(ss," }\n");
		fprintf(ss," hostlist = JSON.parse(extract_bracket_val(request.responseText));\n");
		fprintf(ss," alert('Configuration successfully loaded');\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function load_cookie(){\n");
		fprintf(ss," var json_string = getCookie('gix_inetd_hostlist');\n");
		fprintf(ss," console.log('JSON_STRING ON LOAD: [' + json_string + ']');\n");
		fprintf(ss," if ( json_string.length > 3 ){\n");
		fprintf(ss,"  hostlist = JSON.parse(json_string);\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function goto_url(url){\n");
		fprintf(ss," window.open(url);\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function go_main(){\n");
		fprintf(ss," location = '/';\n");
		fprintf(ss,"}\n");	

		fprintf(ss,"function test_host(){\n");
		fprintf(ss," var hostname = window.document.getElementById('TEST_HOSTNAME').value.trim();\n");
		fprintf(ss," if ( hostname.indexOf(':') != -1 ) hostname = '[' + hostname + ']';\n");
		fprintf(ss," console.log('Testing HOST: {' + hostname + '}');\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.gix_inetd_addr = hostname;\n");
		fprintf(ss," request.gix_inetd_port = 9000;\n");
		fprintf(ss," request.onreadystatechange = scan_host_callback;\n");
		fprintf(ss," request.open('GET','http://' + hostname + ':' + 9000 + '/version',true);\n");
		fprintf(ss," request.send();\n");
		fprintf(ss," var request2 = new XMLHttpRequest();\n");
		fprintf(ss," request2.gix_inetd_addr = hostname;\n");
		fprintf(ss," request2.gix_inetd_port = 9887;\n");
		fprintf(ss," request2.onreadystatechange = scan_host_callback;\n");
		fprintf(ss," request2.open('GET','http://' + hostname + ':' + 9887 + '/version',true);\n");
		fprintf(ss," request2.send();\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function scan_host_callback(q){\n");
		fprintf(ss," var req = this;\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status != 200 ) return;\n");
		fprintf(ss," if ( req.responseText.charAt(0) == 'O' ){\n");
		fprintf(ss,"  var info = JSON.parse(extract_bracket_val(req.responseText));\n");
		fprintf(ss,"  for ( var idx = 0; idx < hostlist.length; idx ++ ){\n");
		fprintf(ss,"   if ( hostlist[idx].url == 'http://' + req.gix_inetd_addr + ':' + req.gix_inetd_port ) break;\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  if ( hostlist.length != 0 &&  idx != hostlist.length ) return;\n");
		fprintf(ss,"  console.log('Adding [' + req.gix_inetd_addr + ':' + req.gix_inetd_port + '] Response: [' + req.responseText + '] Current hostlist-length: [' + hostlist.length + ']');\n");
		fprintf(ss,"  hostlist[hostlist.length] = Object.create(hostentry);\n");
		fprintf(ss,"  hostlist[hostlist.length-1].url = 'http://' + req.gix_inetd_addr + ':' + req.gix_inetd_port;\n");
		fprintf(ss,"  hostlist[hostlist.length-1].name = info.hostname;\n");
		fprintf(ss,"  hostlist[hostlist.length-1].version = info.version;\n");
		fprintf(ss,"  hostlist[hostlist.length-1].username = 'derDaniel';\n");
		fprintf(ss,"  hostlist[hostlist.length-1].password = '';\n");
		fprintf(ss,"  hostlist[hostlist.length-1].remark = '';\n");
		fprintf(ss,"  hostlist[hostlist.length-1].active = true;\n");
		fprintf(ss,"  update_hostlist();\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function start_scan(){\n");
		fprintf(ss," var start_digits = window.document.getElementById('IPSCAN_START').value.trim().split('.');\n");
		fprintf(ss," var end_digits = window.document.getElementById('IPSCAN_END').value.trim().split('.');\n");
		fprintf(ss," window.document.getElementById('IPSCAN_START').setAttribute('class','input2s');\n");
		fprintf(ss," window.document.getElementById('IPSCAN_END').setAttribute('class','input2s');\n");
		fprintf(ss," if ( start_digits.length != 4 ){ alert('Please enter valid Start-Address'); window.document.getElementById('IPSCAN_START').setAttribute('class','input2serror'); return;}\n");
		fprintf(ss," if ( end_digits.length != 4 ){ alert('Please enter valid End-Address'); window.document.getElementById('IPSCAN_END').setAttribute('class','input2serror'); return;}\n");
		fprintf(ss," console.log('START_DIGITS consists of [' + start_digits.length + ']');\n");
		fprintf(ss," console.log('END_DIGITS consists of [' + end_digits.length + ']');\n");
		fprintf(ss," for ( i = 0; i < start_digits.length; i++ ){\n");
		fprintf(ss,"  start_digits[i] = parseInt(start_digits[i]);\n");
		fprintf(ss,"  if ( isNaN(start_digits[i]) ){ alert('Please enter valid Start-Address Error at: [' + i + ']'); window.document.getElementById('IPSCAN_START').setAttribute('class','input2serror'); return;}\n");
		fprintf(ss,"  if ( start_digits[i] < 0 || start_digits[i] > 255 ){ alert('Please enter valid Start-Address Range-Error at: [' + i + ']'); window.document.getElementById('IPSCAN_START').setAttribute('class','input2serror'); return;}\n");
		fprintf(ss," }\n");
		fprintf(ss," for ( i = 0; i < end_digits.length; i++ ){\n");
		fprintf(ss,"  end_digits[i] = parseInt(end_digits[i]);\n");
		fprintf(ss,"  if ( isNaN(end_digits[i]) ){ alert('Please enter valid End-Address Error at: [' + i + ']'); window.document.getElementById('IPSCAN_END').setAttribute('class','input2serror'); return;}\n");
		fprintf(ss,"  if ( end_digits[i] < 0 || end_digits[i] > 255 ){ alert('Please enter valid End-Address Range-Error at: [' + i + ']'); window.document.getElementById('IPSCAN_END').setAttribute('class','input2serror'); return;}\n");
		fprintf(ss," }\n");
		fprintf(ss," var start_long = start_digits[0] * 256 * 256 * 256 + start_digits[1] * 256 * 256 +  start_digits[2] * 256  + start_digits[3];\n");
		fprintf(ss," var end_long = end_digits[0] * 256 * 256 * 256 + end_digits[1] * 256 * 256 +  end_digits[2] * 256  + end_digits[3];\n");
		fprintf(ss," console.log('Will scan [' + ((end_long - start_long) + 1) + '] Addesses');\n");
		fprintf(ss," for ( var addr = start_long; addr <= end_long; addr++ ){\n");
		fprintf(ss,"  var addr_c = addr;\n");
		fprintf(ss,"  var a0 = Math.floor(addr_c / (256*256*256));\n");
		fprintf(ss,"  addr_c = addr_c - a0 * (256*256*256);\n");
		fprintf(ss,"  var a1 = Math.floor(addr_c / (256*256));\n");
		fprintf(ss,"  addr_c = addr_c - a1 * (256*256);\n");
		fprintf(ss,"  var a2 = Math.floor(addr_c / (256));\n");
		fprintf(ss,"  addr_c = addr_c - a2 * (256);\n");
		fprintf(ss,"  var a3 = addr_c;\n");
		// fprintf(ss,"  console.log('Scanning: [' + a0 + '.' + a1 + '.' + a2 + '.' + a3 + ']');\n");
		fprintf(ss,"  scan_ip(a0 + '.' + a1 + '.' + a2 + '.' + a3,'9000' );\n");
		fprintf(ss,"  scan_ip(a0 + '.' + a1 + '.' + a2 + '.' + a3,'9887' );\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function scan_ip(addr,port){\n");
		fprintf(ss," console.log('Start of scan at: [' + addr + ']');\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.gix_inetd_addr = addr;\n");
		fprintf(ss," request.gix_inetd_port = port;\n");
		fprintf(ss," request.onreadystatechange = scan_ip_callback;\n");
		fprintf(ss," request.open('GET','http://' + addr + ':' + port + '/version',true);\n");
		fprintf(ss," request.send();\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function scan_ip_callback(q){\n");
		fprintf(ss," var req = this;\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status != 200 ) return;\n");
		fprintf(ss," if ( req.responseText.charAt(0) == 'O' ){\n");
		fprintf(ss,"  var info = JSON.parse(extract_bracket_val(req.responseText));\n");
		fprintf(ss,"  for ( var idx = 0; idx < hostlist.length; idx ++ ){\n");
		fprintf(ss,"   if ( hostlist[idx].url == 'http://' + req.gix_inetd_addr + ':' + req.gix_inetd_port ) break;\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  if ( hostlist.length != 0 &&  idx != hostlist.length ) return;\n");
		fprintf(ss,"  console.log('Adding [' + req.gix_inetd_addr + ':' + req.gix_inetd_port + '] Response: [' + req.responseText + '] Current hostlist-length: [' + hostlist.length + ']');\n");
		fprintf(ss,"  hostlist[hostlist.length] = Object.create(hostentry);\n");
		fprintf(ss,"  hostlist[hostlist.length-1].url = 'http://' + req.gix_inetd_addr + ':' + req.gix_inetd_port;\n");
		fprintf(ss,"  hostlist[hostlist.length-1].name = info.hostname;\n");
		fprintf(ss,"  hostlist[hostlist.length-1].version = info.version;\n");
		fprintf(ss,"  hostlist[hostlist.length-1].username = 'derDaniel';\n");
		fprintf(ss,"  hostlist[hostlist.length-1].password = '';\n");
		fprintf(ss,"  hostlist[hostlist.length-1].remark = '';\n");
		fprintf(ss,"  hostlist[hostlist.length-1].active = true;\n");
		fprintf(ss,"  update_hostlist();\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function update_end_field(){\n");
		fprintf(ss," var id_start = window.document.getElementById('IPSCAN_START');\n");
		fprintf(ss," var id_end   = window.document.getElementById('IPSCAN_END');\n");
		fprintf(ss," if ( id_end.value.length < 1 )  id_end.value = id_start.value;\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function extract_bracket_val(msg){\n");
		fprintf(ss,"  var returner = '';\n");
		fprintf(ss,"  var n1 = msg.indexOf('[');\n");
		fprintf(ss,"  n1++;\n");
		fprintf(ss,"  var n2 = msg.lastIndexOf(']');\n");
		fprintf(ss,"  returner = msg.substring(n1,n2);\n");
		fprintf(ss,"  return(returner);\n");
		fprintf(ss," }\n");
		fprintf(ss," function extract_bracket_val2(msg,index){\n");
		fprintf(ss,"  var xx = extract_bracket_val(msg);\n");
		fprintf(ss,"  var i = 0;\n");
		fprintf(ss,"  var idx = 0;\n");
		fprintf(ss,"  while ( 1 ){\n");
		fprintf(ss,"   var returner = '';\n");
		fprintf(ss,"   for ( ; i < xx.length; i++ ){\n");
		fprintf(ss,"    var j = 0;\n");
		fprintf(ss,"    if ( xx.charAt(i) == ',' ){ i++; break;}\n");
		fprintf(ss,"    returner = returner + xx.charAt(i);  \n");
		fprintf(ss,"   }\n");
		fprintf(ss,"   if ( idx >= index ) return(returner);\n");
		fprintf(ss,"   idx++;\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  return('');\n");
		fprintf(ss," }\n");
		fprintf(ss,"\n");
		fprintf(ss," function extract_bracket_val3(msg,index){\n");
		fprintf(ss,"  var xx = msg;\n");
		fprintf(ss,"  var i = 0;\n");
		fprintf(ss,"  var idx = 0;\n");
		fprintf(ss,"  while ( 1 ){\n");
		fprintf(ss,"   var returner = '';\n");
		fprintf(ss,"   for ( ; i < xx.length; i++ ){\n");
		fprintf(ss,"    var j = 0;\n");
		fprintf(ss,"    if ( xx.charAt(i) == ';' ){ i++; break;}\n");
		fprintf(ss,"    returner = returner + xx.charAt(i);  \n");
		fprintf(ss,"   }\n");
		fprintf(ss,"   if ( idx >= index ) return(returner);\n");
		fprintf(ss,"   idx++;\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  return('');\n");
		fprintf(ss," }\n");
		fprintf(ss,"</SCRIPT>\n");
	}
	
	if ( type_req == TYPE_HTML && html_done == 0 ){
		int i;
		fprintf(ss,"Content-Type: %s\r\n\r\n",HTML_MIME);
		fprintf(ss,"<HEAD><meta CHARSET=\"UTF-8\"><LINK REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"/style.css\"></HEAD>\n");
		fprintf(ss,"<BODY CLASS='mainbody' onload=init_all()>");
		fprintf(ss,"<DIV CLASS='headline'><TABLE BORDER=0 WIDTH=100%%><TR><TD ALIGN=LEFT WIDTH=33%%><IMG CLASS=l_image onclick=go_supervisor() SRC=/gix_logo.png></TD><TD WIDTH=33%%><CENTER><SPAN CLASS=headliner>%s @ %s</SPAN></TD><TD ALIGN=RIGHT WIDTH=33%%><TABLE BORDER=0><TR><TD ALIGN=RIGHT>You:</TD><TD ALIGN=LEFT><B>%s</B></TD></TR><TR><TD ALIGN=RIGHT>Me:</TD><TD ALIGN=LEFT><B>%s</B></TD></TR></TABLE></TD></TR></TABLE>",
			GIX_INETD_VERSION,my_hostname,  CCON.source, CCON.target);
		fprintf(ss,"<CENTER><INPUT TYPE=BUTTON CLASS=standard_button onclick=reset_counters() VALUE=\"Reset counters\">&nbsp;<SPAN ID=GIGA_ROTATOR><IMG SRC=/empty.gif HEIGHT=32></SPAN>&nbsp;<INPUT TYPE=BUTTON CLASS=standard_button onclick=toggle_giga_refresh()  VALUE='Enable Auto-Refresh' ID=REFRESH_GIGA_BUTTON></DIV>");

		fprintf(ss,"<SCRIPT LANGUAGE=JavaScript>\n");
		fprintf(ss,"function go_supervisor(){\n");
		fprintf(ss," location = '/supervisor';\n");
		fprintf(ss,"}\n");
		fprintf(ss,"</SCRIPT>\n");

		fprintf(ss,"<DIV CLASS=footer><CENTER>(C) Ing. Andy Paumann, globedom Bulgaria</DIV>");

		fprintf(ss,"<DIV ID='MAIN' CLASS=mainscreen>\n");
		fprintf(ss,"<CENTER>");
		fprintf(ss,"<TABLE BORDER=0>");
		fprintf(ss,"<TR><TD VALIGN=TOP>");
		fprintf(ss,"<CENTER>");
		fprintf(ss,"<TABLE CELLSPACING=1 BORDER=0 BGCOLOR=black>\n");
		fprintf(ss,"<TR><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead2s>Uptime(1 min)</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s ID=LOAD1></SPAN></TD><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead2s>(5 min)</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s ID=LOAD5></SPAN></TD><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead2s>(15 min)</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s ID=LOAD15></SPAN></TD></TR>");
		fprintf(ss,"<TR><TD BGCOLOR=white COLSPAN=6><CENTER><DIV ID=FSINFO></DIV></TD></TR>\n");
		fprintf(ss,"<TR><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead2s>Uptime</SPAN></TD><TD COLSPAN=5 BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s ID=UPTIME></SPAN></TD></TR>");
		fprintf(ss,"<TR><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead2s>Processes</SPAN></TD><TD COLSPAN=5 BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s ID=SYS_PROCS></SPAN></TD></TR>");
		fprintf(ss,"<TR><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead2s>CPU-count</SPAN></TD><TD COLSPAN=5 BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s ID=CPU_COUNT></SPAN></TD></TR>");
		fprintf(ss,"<TR><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead2s>CPU-Usage (sys + usr)</SPAN></TD><TD COLSPAN=5 BGCOLOR=white ALIGN=LEFT><DIV ID=CPU_INFO></DIV></TD></TR>");
		fprintf(ss,"<TR><TD COLSPAN=6 BGCOLOR=black><DIV ID=PROCINFO></DIV></TD></TR>");
		fprintf(ss,"</TABLE>");
		// fprintf(ss,"<P><INPUT TYPE=BUTTON CLASS=standard_button onclick=reset_counters() VALUE=\"Reset counters\">&nbsp;<SPAN ID=GIGA_ROTATOR><IMG SRC=/empty.gif HEIGHT=32></SPAN>&nbsp;<INPUT TYPE=BUTTON CLASS=standard_button onclick=toggle_giga_refresh()  VALUE='Enable Auto-Refresh' ID=REFRESH_GIGA_BUTTON></P>\n");
		fprintf(ss,"</CENTER>");
		fprintf(ss,"</TD><TD VALIGN=TOP ALIGN=LEFT><CENTER>");
		fprintf(ss,"<P>");
		fprintf(ss,"<TABLE BORDER=0 CELLSPACING=1 BGCOLOR=black>\n");
		fprintf(ss,"<TR><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead1s>TFTP-enabled:</SPAN>");
		if ( gix_options->tftp_enabled ){
			fprintf(ss,"<INPUT TYPE=CHECKBOX CHECKED ID=TFTP_ENABLED>");
		} else {
			fprintf(ss,"<INPUT TYPE=CHECKBOX ID=TFTP_ENABLED>");
		}
		fprintf(ss,"</TD><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead1s>TFTP-readonly:</SPAN>");
		if ( gix_options->tftp_readonly ){
			fprintf(ss,"<INPUT TYPE=CHECKBOX CHECKED ID=TFTP_READONLY>");
		} else {
			fprintf(ss,"<INPUT TYPE=CHECKBOX ID=TFTP_READONLY>");
		}
		fprintf(ss,"</TD><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead1s>TFTP-root:</SPAN><INPUT ID=TFTP_ROOT TYPE=TEXT VALUE='%s' CLASS=input2s></TD>",gix_options->tftp_root);
		fprintf(ss,"<TD BGCOLOR=white ALIGN=CENTER><INPUT TYPE=BUTTON VALUE='Save TFTP settings' onclick=save_tftp_settings() CLASS=standard_buttons></TD></TR>");
		fprintf(ss,"<TR><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead1s>Read-Requests processed:</SPAN></TD><TD ALIGN=RIGHT BGCOLOR=white><SPAN ID=TFTP_REQUESTS_READ CLASS=thead2s></SPAN></TD>");
		fprintf(ss,"<TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead1s>Write-Requests processed:</SPAN></TD><TD ALIGN=RIGHT BGCOLOR=white><SPAN ID=TFTP_REQUESTS_WRITE CLASS=thead2s></SPAN></TD></TR>");
		fprintf(ss,"<TR><TD COLSPAN=4 BGCOLOR=white><DIV ID=TFTP_LIST></DIV></TD></TR>");
		fprintf(ss,"</TABLE>\n");
		fprintf(ss,"</P>");
		fprintf(ss,"<TABLE BORDER=0 CELLSPACING=1 BGCOLOR=black>\n");
		fprintf(ss,"<TR><TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Slot</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>IP-Version</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>IP-Port</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Command</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Max-Connections</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Total-Timeout (Seconds)</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Idle-Timeout (Seconds)</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Active connections</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Total connections</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Last reset (counters)</SPAN></CENTER></TD>");
		fprintf(ss,"<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Process ID</SPAN></CENTER></TD>");
		fprintf(ss,"</TR>");
		for ( i = 0; i < entries; i++ ){
			char *color;
			if ( i % 2 ){
				color = "yellow";
			} else {
				color = "lightblue";
			}
			fprintf(ss,"<TR>");
			fprintf(ss,"<TD BGCOLOR=%s><CENTER><SPAN CLASS=thead2s>%d</SPAN></TD>",color,i);
			fprintf(ss,"<TD BGCOLOR=%s><CENTER>",color);
			fprintf(ss,"<SPAN CLASS=thead2s>%s</SPAN>", servlist[i].family == AF_INET6 ? "IPv6" : "IPv4");
			fprintf(ss,"</CENTER></TD>");
			fprintf(ss,"<TD BGCOLOR=%s ALIGN=right>",color);
			fprintf(ss,"<SPAN CLASS=thead2s>%d</SPAN>", servlist[i].port);
			fprintf(ss,"</TD>");
			if ( strncmp(servlist[i].cmdline,"ADMIN",5) == 0 ){
				fprintf(ss,"<TD BGCOLOR=%s ALIGN=center>",color);
				fprintf(ss,"<SPAN CLASS=thead30s onclick=conns_list(%d,-1)>ADMIN</SPAN>",i);
				fprintf(ss,"</TD>");
			} else {
				fprintf(ss,"<TD BGCOLOR=%s ALIGN=right>",color);
				fprintf(ss,"<SPAN CLASS=thead20s onclick=conns_list(%d,-1)>%s</SPAN>",i, servlist[i].cmdline);
				fprintf(ss,"</TD>");
			}
			fprintf(ss,"<TD BGCOLOR=%s ALIGN=RIGHT>",color);
			fprintf(ss,"<SPAN CLASS=thead2s>%d</SPAN>", servlist[i].max_conns);
			fprintf(ss,"</TD>");
			if ( servlist[i].timeout == -1 ){
				fprintf(ss,"<TD BGCOLOR=%s ALIGN=center>",color);
				fprintf(ss,"<SPAN CLASS=thead30s>No timeout</SPAN>");
				fprintf(ss,"</TD>");
			} else {
				fprintf(ss,"<TD BGCOLOR=%s ALIGN=right>",color);
				fprintf(ss,"<SPAN CLASS=thead2s>%d</SPAN>", servlist[i].timeout);
				fprintf(ss,"</TD>");
			}
			if ( servlist[i].data_timeout == -1 ){
				fprintf(ss,"<TD BGCOLOR=%s ALIGN=center>",color);
				fprintf(ss,"<SPAN CLASS=thead30s>No timeout</SPAN>");
				fprintf(ss,"</TD>");
			} else {
				fprintf(ss,"<TD BGCOLOR=%s ALIGN=right>",color);
				fprintf(ss,"<SPAN CLASS=thead2s>%d</SPAN>", servlist[i].data_timeout);
				fprintf(ss,"</TD>");
			}
			fprintf(ss,"<TD BGCOLOR=%s ALIGN=RIGHT>",color);
			fprintf(ss,"<SPAN CLASS=thead2s ID=CONNECTIONS_%d></SPAN>", i);
			fprintf(ss,"</TD>");
			fprintf(ss,"<TD BGCOLOR=%s ALIGN=RIGHT>",color);
			fprintf(ss,"<SPAN CLASS=thead2s ID=TOTAL_COUNT_%d></SPAN>", i);
			fprintf(ss,"</TD>");
			fprintf(ss,"<TD BGCOLOR=%s ALIGN=RIGHT>",color);
			fprintf(ss,"<SPAN CLASS=thead2s ID=RESET_%d></SPAN>", i);
			fprintf(ss,"</TD>");
			fprintf(ss,"<TD BGCOLOR=%s ALIGN=RIGHT>",color);
			fprintf(ss,"<SPAN CLASS=thead2links ID=PID_%d onclick=show_proc_info('PID_%d')></SPAN>", i,i);
			fprintf(ss,"</TD>");
			fprintf(ss,"</TR>");
		}
		fprintf(ss,"</TABLE>\n");
		fprintf(ss,"<P>");
		fprintf(ss,"<DIV ID=ETHLIST CLASS=ethlist>init</DIV>");
		fprintf(ss,"</P>");
		fprintf(ss,"</TD></TR></TABLE>");
		fprintf(ss,"</DIV>\n");

		fprintf(ss,"<SCRIPT LANGUAGE=JavaScript>\n");

		fprintf(ss,"var megatimer = null;\n");
		fprintf(ss,"var gigatimer = null;\n");
		fprintf(ss,"var megatimer_active = false;\n");
		fprintf(ss,"var gigatimer_active = false;\n");
		fprintf(ss,"var gigatimer_stored = false;\n");
		fprintf(ss,"var leth = null;\n");




		fprintf(ss,"function show_proc_info(diver){\n");
		fprintf(ss," diver_id = document.getElementById(diver);\n");
		fprintf(ss," console.log('DIVER_ID: [' + diver_id.innerHTML + '] Text: [' + diver_id.innerText + ']');\n");
		fprintf(ss," var pid = parseInt(diver_id.innerHTML);\n");
		fprintf(ss," if ( isNaN(pid) || pid == 0 ) pid = parseInt(diver_id.innerText);\n");
		fprintf(ss," process_detail(pid);\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function extract_bracket_val(msg){\n");
		fprintf(ss,"  var returner = '';\n");
		fprintf(ss,"  var n1 = msg.indexOf('[');\n");
		fprintf(ss,"  n1++;\n");
		fprintf(ss,"  var n2 = msg.lastIndexOf(']');\n");
		fprintf(ss,"  returner = msg.substring(n1,n2);\n");
		fprintf(ss,"  return(returner);\n");
		fprintf(ss," }\n");
		fprintf(ss," function extract_bracket_val2(msg,index){\n");
		fprintf(ss,"  var xx = extract_bracket_val(msg);\n");
		fprintf(ss,"  var i = 0;\n");
		fprintf(ss,"  var idx = 0;\n");
		fprintf(ss,"  while ( 1 ){\n");
		fprintf(ss,"   var returner = '';\n");
		fprintf(ss,"   for ( ; i < xx.length; i++ ){\n");
		fprintf(ss,"    var j = 0;\n");
		fprintf(ss,"    if ( xx.charAt(i) == ',' ){ i++; break;}\n");
		fprintf(ss,"    returner = returner + xx.charAt(i);  \n");
		fprintf(ss,"   }\n");
		fprintf(ss,"   if ( idx >= index ) return(returner);\n");
		fprintf(ss,"   idx++;\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  return('');\n");
		fprintf(ss," }\n");
		fprintf(ss,"\n");
		fprintf(ss," function extract_bracket_val3(msg,index){\n");
		fprintf(ss,"  var xx = msg;\n");
		fprintf(ss,"  var i = 0;\n");
		fprintf(ss,"  var idx = 0;\n");
		fprintf(ss,"  while ( 1 ){\n");
		fprintf(ss,"   var returner = '';\n");
		fprintf(ss,"   for ( ; i < xx.length; i++ ){\n");
		fprintf(ss,"    var j = 0;\n");
		fprintf(ss,"    if ( xx.charAt(i) == ';' ){ i++; break;}\n");
		fprintf(ss,"    returner = returner + xx.charAt(i);  \n");
		fprintf(ss,"   }\n");
		fprintf(ss,"   if ( idx >= index ) return(returner);\n");
		fprintf(ss,"   idx++;\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  return('');\n");
		fprintf(ss," }\n");



		fprintf(ss,"function reset_counters(){\n");
		fprintf(ss," console.log('Requesting RESET of counters!');\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.onreadystatechange = function() { reset_counters_callback(request); };\n");
		fprintf(ss," request.open('GET','/ajax/RESET/0',true);\n");
		fprintf(ss," request.send();\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function reset_counters_callback(req){\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status != 200 ) return;\n");
		fprintf(ss," console.log('Callback for RESET -> Response: [' + req.responseText + ']');\n");
		fprintf(ss," if ( req.responseText.charAt(0) != 'O' ){\n");
		fprintf(ss,"  alert('Could not reset');\n");
		fprintf(ss," }\n");
		fprintf(ss," if ( gigatimer_active == false ) update_connections();\n");
		fprintf(ss,"}\n");




		fprintf(ss,"function update_conns_display(inl){\n");
		fprintf(ss," for ( idx = 0; idx < inl.length; idx++ ){\n");
		fprintf(ss,"  var id = document.getElementById('CONNECTIONS_' + idx);\n");
		fprintf(ss,"  if ( id != undefined && id != null ) id.innerHTML = inl[idx].connections;\n");
		fprintf(ss,"  var id = document.getElementById('RESET_' + idx);\n");
		fprintf(ss,"  if ( id != undefined && id != null ) id.innerHTML = inl[idx].reset;\n");
		fprintf(ss,"  var id = document.getElementById('TOTAL_COUNT_' + idx);\n");
		fprintf(ss,"  if ( id != undefined && id != null ) id.innerHTML = inl[idx].total_count;\n");
		fprintf(ss,"  var id = document.getElementById('PID_' + idx);\n");
		fprintf(ss,"  if ( id != undefined && id != null ) id.innerHTML = inl[idx].pid;\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function update_connections(){\n");
		fprintf(ss," document.getElementById('GIGA_ROTATOR').innerHTML = '<IMG SRC=/new_rotator_big.gif HEIGHT=32>';\n");
		fprintf(ss,"  if ( gigatimer != null ) clearInterval(gigatimer);\n");
		fprintf(ss,"  var request = new XMLHttpRequest();\n");
		fprintf(ss,"  request.onreadystatechange = function() { update_connections_callback(request); };\n");
		fprintf(ss,"  request.open('GET','/ajax/PROCLIST/0' ,true);\n");
		fprintf(ss,"  request.send();\n");
		fprintf(ss,"}\n");
		


		fprintf(ss,"function display_proclist(proclist){\n");
		fprintf(ss," var cpu_count_id = document.getElementById('CPU_COUNT');\n");
		fprintf(ss," cpu_count_id.innerHTML = proclist.cpu_count;\n");

		fprintf(ss," var cpu_info_id = document.getElementById('CPU_INFO');\n");
		fprintf(ss," var result = '<TABLE CELLSPACING=1 BORDER=0 BGCOLOR=blue>';\n");
		fprintf(ss," for ( var idx = 0; idx < proclist.cpu_count; idx++ ){\n");
		fprintf(ss,"  if ( idx && !(idx %% 4 )) result += '</TR>';\n");
		fprintf(ss,"  if (  !(idx %% 4 ) ) result += '<TR>';\n");
		fprintf(ss,"  if ( proclist.ul[idx].total > 80.0 ){\n");
		fprintf(ss,"   result += '<TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s><B>CPU-' + idx + '</B></SPAN></TD><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead1s><B>' + proclist.ul[idx].total + '%%</B></SPAN></TD>';\n");
		fprintf(ss,"  } else {\n");
		fprintf(ss,"   if ( proclist.ul[idx].total > 50.0 ){\n");
		fprintf(ss,"    result += '<TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s><B>CPU-' + idx + '</B></SPAN></TD><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead2sw><B>' + proclist.ul[idx].total + '%%</B></SPAN></TD>';\n");
		fprintf(ss,"   } else {\n");
		fprintf(ss,"    result += '<TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s><B>CPU-' + idx + '</B></SPAN></TD><TD BGCOLOR=white ALIGN=RIGHT><SPAN CLASS=thead2s>' + proclist.ul[idx].total + '%%</SPAN></TD>';\n");
		fprintf(ss,"   }\n");
		fprintf(ss,"  }\n");
		fprintf(ss," }\n");
		fprintf(ss," result += '</TR></TABLE>';\n");
		fprintf(ss," cpu_info_id.innerHTML = result;\n");
		fprintf(ss," var div_id = document.getElementById('PROCINFO');\n");
		fprintf(ss," div_id.setAttribute('class','procinfo');\n");
		fprintf(ss," var result = '<TABLE CELLSPACING=1 BGCOLOR=black>';\n");
		fprintf(ss," result += '<TR>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>PID</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>PPID</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>CPU</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Trs.</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Command</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>V-Size</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>RSS</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Started</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Load</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Time</SPAN></TD>';\n");
		fprintf(ss," result += '</TR>';\n");
		fprintf(ss," for ( var i = 0; i < proclist.pl.length; i++ ){\n");
		fprintf(ss,"  var color = 'lightblue';\n");
		fprintf(ss,"  if ( i %% 2 ) color = 'yellow';\n");
		fprintf(ss,"  result += '<TR>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead3s onclick=process_detail1(' + proclist.pl[i].pid + ')>' + proclist.pl[i].pid + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead3s onclick=process_detail1(' + proclist.pl[i].ppid + ')>' + proclist.pl[i].ppid + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + proclist.pl[i].cpu + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + proclist.pl[i].num_threads + '</SPAN></TD>';\n");
		// fprintf(ss,"  console.log('PID: [' + proclist.pl[i].pid + '] Slot: [' + proclist.pl[i].slot + '] Index: [' + proclist.pl[i].index + ']');\n");
		fprintf(ss,"  if ( proclist.pl[i].slot > -1 && proclist.pl[i].index > -1 ){\n");
		fprintf(ss,"   result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead3s onclick=conns_list1(' + proclist.pl[i].slot + ',' + proclist.pl[i].index + ')>' + proclist.pl[i].prg + '</SPAN></TD>';\n");
		fprintf(ss,"  } else {\n");
		fprintf(ss,"   result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + proclist.pl[i].prg + '</SPAN></TD>';\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + proclist.pl[i].vmsize + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + proclist.pl[i].rss + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + proclist.pl[i].stime + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + proclist.pl[i].cpu_usage + '%%</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + proclist.pl[i].ptime + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '</TR>';\n");
		fprintf(ss," }\n");
		fprintf(ss," result += '</TABLE>';\n");
		fprintf(ss," div_id.innerHTML = result;\n");
		fprintf(ss,"}\n");


		fprintf(ss,"rawdata_obj = {\n");
		fprintf(ss," name: '',\n");
		fprintf(ss," timestamp: 0,\n");
		fprintf(ss," bytes_in: 0,\n");
		fprintf(ss," bytes_out: 0\n");
		fprintf(ss,"}\n");

		fprintf(ss,"ilist_obj = {\n");
		fprintf(ss," rawdata: null,\n");
		fprintf(ss," array_in: null,\n");
		fprintf(ss," array_out: null,\n");
		fprintf(ss," canvas_in: null,\n");
		fprintf(ss," canvas_out: null,\n");
		fprintf(ss," ifname: ''\n");
		fprintf(ss,"}\n");

		fprintf(ss,"eth_obj = {\n");
		fprintf(ss," ilist: []\n");
		fprintf(ss,"}\n");

		fprintf(ss,"var colorarray = [ 'red', 'blue','green' ];\n");

		fprintf(ss,"GIXGraph = {\n");
		fprintf(ss," id: null,\n");
		fprintf(ss," color: 'blue',\n");
		fprintf(ss," bgcolor: 'black',\n");
		fprintf(ss," tcolor: 'green',\n");
		fprintf(ss," x_caption: '',\n");
		fprintf(ss," y_caption: '',\n");
		fprintf(ss," x_start_label: '',\n");
		fprintf(ss," x_end_label: '',\n");
		fprintf(ss," y_caption: '',\n");
		fprintf(ss," headline: 'Head',\n");
		fprintf(ss," samples: '',\n");
		fprintf(ss," canvas_width: 0,\n");
		fprintf(ss," canvas_height: 0,\n");
		fprintf(ss," canvas_offset_x: 1,\n");
		fprintf(ss," canvas_offset_y: 1,\n");
		fprintf(ss," script_size: 10,\n");
		fprintf(ss," ctx: null,\n");
		fprintf(ss," init: function(_id, _color,_bgcolor,_tcolor,_headline,_x_caption,_y_caption){\n"); // _samples is an array of values with X and Y values 
		fprintf(ss,"  if ( _id == undefined ) return(false);\n");
		fprintf(ss,"  this.id = window.document.getElementById(_id);\n");
		fprintf(ss,"  if ( this.id == undefined || this.id == null ) return false;\n");
		fprintf(ss,"  this.canvas_width = parseInt(this.id.getBoundingClientRect().width) - this.canvas_offset_x * 2;\n");
		fprintf(ss,"  this.canvas_height = parseInt(this.id.getBoundingClientRect().height) - this.canvas_offset_y * 2;\n");
		fprintf(ss,"  console.log('CANVAS-SIZE: [' + this.canvas_width + ' x ' + this.canvas_height + '] BORDER: [' + this.id.style.border + ']');\n");
		fprintf(ss,"  if ( _color != undefined ) this.color = _color;\n");
		fprintf(ss,"  if ( _bgcolor != undefined ) this.bgcolor = _bgcolor;\n");
		fprintf(ss,"  if ( _tcolor != undefined ) this.tcolor = _tcolor;\n");
		fprintf(ss,"  if ( _headline != undefined ) this.headline = _headline;\n");
		fprintf(ss,"  if ( _x_caption != undefined ) this.x_caption = _x_caption;\n");
		fprintf(ss,"  if ( _y_caption != undefined ) this.y_caption = _y_caption;\n");
		fprintf(ss,"  if ( (this.ctx = this.id.getContext(\"2d\")) == undefined || this.ctx == null ) return false;\n");
		fprintf(ss,"  return true;\n");
		fprintf(ss," },\n");
		fprintf(ss," draw_graph: function(_samples,_x_start_label,_x_end_label){\n");
		fprintf(ss,"  this.ctx.clearRect(0,0,this.id.width, this.id.height);\n");
		fprintf(ss,"  if ( _x_start_label != undefined ) this.x_start_label = _x_start_label;\n");
		fprintf(ss,"  if ( _x_end_label != undefined ) this.x_end_label = _x_end_label;\n");
		fprintf(ss,"  this.samples = _samples;\n");
		fprintf(ss,"  if ( this.samples.length < 1 ) return;\n");
		fprintf(ss,"  var draw_width = this.canvas_width - 2 * this.canvas_offset_x;\n");
		fprintf(ss,"  var draw_height = this.canvas_height - (2 * this.canvas_offset_y + this.script_size + 2);\n");
		fprintf(ss,"  var max = this.samples[0];\n");
		fprintf(ss,"  var min = this.samples[0];\n");
		fprintf(ss,"  var sum = 0.0;\n");
		fprintf(ss,"  for ( idx = 0; idx < this.samples.length; idx++ ){\n");
		fprintf(ss,"   if ( this.samples[idx] > max ) max = this.samples[idx];\n");
		fprintf(ss,"   if ( this.samples[idx] < min ) min = this.samples[idx];\n");
		fprintf(ss,"   sum += this.samples[idx];\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  var min_word = this.roundup(min) + ' ' + this.y_caption;\n");
		fprintf(ss,"  if ( min > 1024 ) min_word = this.roundup(min/1024) + ' k' +  this.y_caption;\n");
		fprintf(ss,"  if ( min > (1024*1024) ) min_word = this.roundup(min/(1024*1024)) + ' M' +  this.y_caption;\n");
		fprintf(ss,"  if ( min > (1024*1024*1024) ) min_word = this.roundup(min/(1024*1024*1024)) + ' G' +  this.y_caption;\n");
		fprintf(ss,"  if ( min > (1024*1024*1024*1024) ) min_word = this.roundup(min/(1024*1024*1024*1024)) + ' T' +  this.y_caption;\n");
		fprintf(ss,"  var max_word = this.roundup(max) + ' ' + this.y_caption;\n");
		fprintf(ss,"  if ( max > 1024 ) max_word = this.roundup(max/1024) + ' k' +  this.y_caption;\n");
		fprintf(ss,"  if ( max > (1024*1024) ) max_word = this.roundup(max/(1024*1024)) + ' M' +  this.y_caption;\n");
		fprintf(ss,"  if ( max > (1024*1024*1024) ) max_word = this.roundup(max/(1024*1024*1024)) + ' G' +  this.y_caption;\n");
		fprintf(ss,"  if ( max > (1024*1024*1024*1024) ) max_word = this.roundup(max/(1024*1024*1024*1024)) + ' T'  + this.y_caption;\n");
		fprintf(ss,"  var y_factor = draw_height / (max - min);\n");
		fprintf(ss,"  var x_factor = draw_width / this.samples.length;\n");
		fprintf(ss,"  console.log('Min-Value: [' + min + '] Max: [' + max + '] Sum: [' + sum + '] Y-Factor: [' + y_factor + '] X-Factor: [' + x_factor + ']');\n");
		fprintf(ss,"  for ( var idx = 0; idx < this.samples.length; idx++ ){\n");
		fprintf(ss,"   var sample_value = this.samples[idx] - min;\n");
		fprintf(ss,"   var draw_height = sample_value * y_factor;\n");
		fprintf(ss,"   var x_start = idx * x_factor + this.canvas_offset_x;\n");
		fprintf(ss,"   var x_end = x_factor;\n");
		fprintf(ss,"   var y_start = this.canvas_height - (this.canvas_offset_y +  this.canvas_offset_y + this.script_size + 2);\n");
		fprintf(ss,"   var y_end   =  draw_height  * (-1) ;\n");
		fprintf(ss,"   if ( y_end >= 0 ) y_end = -1;\n");
		fprintf(ss,"   var color = colorarray[idx %% colorarray.length];\n");
		// fprintf(ss,"   console.log('VALUE[' + idx  + ']: [' + sample_value + '] X_START: [' + x_start + '] X_END: [' + x_end + '] Draw_HEIGHT: ['  + draw_height + '] Y_START: [' + y_start + '] Y_END: [' + y_end + '] COLOR: [' + color + ']');\n");
		fprintf(ss,"   this.ctx.fillStyle = this.color;\n");
		fprintf(ss,"   this.ctx.fillRect(x_start,y_start,x_end,y_end);\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  this.ctx.font = this.script_size + 'px monospace';\n");
		fprintf(ss,"  this.ctx.strokeStyle =  this.tcolor;\n");
		fprintf(ss,"  this.ctx.strokeText(max_word,this.canvas_offset_x ,this.script_size + 2);\n");
		fprintf(ss,"  this.ctx.strokeText(min_word,this.canvas_offset_x ,this.canvas_height - (this.canvas_offset_y +  this.canvas_offset_y + this.script_size + 6));\n");
		fprintf(ss,"  this.ctx.strokeText(this.headline,this.canvas_width / 2 ,this.script_size + 2);\n");
		fprintf(ss,"  this.ctx.strokeText(this.x_start_label,this.canvas_offset_x,this.canvas_height - this.canvas_offset_y -1);\n"); 
		fprintf(ss,"  this.ctx.strokeText(this.x_end_label,this.canvas_width - ( this.canvas_offset_x + (this.script_size - 3) * this.x_end_label.length),this.canvas_height - this.canvas_offset_y - 1);\n"); 
		fprintf(ss," },\n");
		fprintf(ss," roundup: function(x){\n");
		fprintf(ss,"  return(Math.round(x*100)/100);\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");

		fprintf(ss,"var testarray = [ 10,2048,1230,1350,14,-40,12,1234,900,1299 ];\n");	
		

		fprintf(ss,"function display_int_info(ethlist){\n");
		fprintf(ss," console.log('ETHLIST-LEN: ['  + ethlist.length + '] ETH-Length: [' + leth.ilist.length + ']');\n");
		fprintf(ss," for ( var j = 0; j < ethlist.length; j++ ){\n");
		fprintf(ss,"  console.log('ETHLIST-Index: [' + j + '] Name: ['  + ethlist[j].ifname + ']');\n");
		fprintf(ss,"  for ( var i = 0; i < leth.ilist.length; i++ ){\n");
		fprintf(ss,"   if ( leth.ilist[i].ifname == ethlist[j].ifname ){\n");
		fprintf(ss,"    var rawdata_len = leth.ilist[i].rawdata.length;\n");
		fprintf(ss,"    console.log('[' + j + '] Updating [' + i + '] NAME: [' + leth.ilist[i].ifname + '] Size currently: [' + rawdata_len + '] Name: [' + leth.ilist[i].rawdata[0].name + ']');\n");
		fprintf(ss,"    leth.ilist[i].rawdata[rawdata_len] = Object.create(rawdata_obj);\n");
		fprintf(ss,"    leth.ilist[i].rawdata[rawdata_len].timestamp = ethlist[j].timestamp;\n");
		fprintf(ss,"    leth.ilist[i].rawdata[rawdata_len].bytes_in = ethlist[j].bytes_in;\n");
		fprintf(ss,"    leth.ilist[i].rawdata[rawdata_len].bytes_out = ethlist[j].bytes_out;\n");
		fprintf(ss,"    var canvas_array_length = leth.ilist[i].array_in.length;\n");
		fprintf(ss,"    leth.ilist[i].array_in[canvas_array_length] = (leth.ilist[i].rawdata[rawdata_len].bytes_in - leth.ilist[i].rawdata[rawdata_len-1].bytes_in) / (leth.ilist[i].rawdata[rawdata_len].timestamp - leth.ilist[i].rawdata[rawdata_len-1].timestamp);\n");
		fprintf(ss,"    leth.ilist[i].array_out[canvas_array_length] = (leth.ilist[i].rawdata[rawdata_len].bytes_out - leth.ilist[i].rawdata[rawdata_len-1].bytes_out) / (leth.ilist[i].rawdata[rawdata_len].timestamp - leth.ilist[i].rawdata[rawdata_len-1].timestamp);\n");
		fprintf(ss,"    var date = new Date(parseInt(leth.ilist[i].rawdata[0].timestamp * 1000));\n");
		fprintf(ss,"    var hours = '0' + date.getHours();\n");
		fprintf(ss,"    var mins = '0' + date.getMinutes();\n");
		fprintf(ss,"    var secs = '0' + date.getSeconds();\n");
		fprintf(ss,"    var start_date = hours.substr(-2) + ':' + mins.substr(-2) + ':' + secs.substr(-2);\n");
		fprintf(ss,"    var date = new Date(parseInt(leth.ilist[i].rawdata[rawdata_len].timestamp * 1000));\n");
		fprintf(ss,"    hours = '0' + date.getHours();\n");
		fprintf(ss,"    mins = '0' + date.getMinutes();\n");
		fprintf(ss,"    secs = '0' + date.getSeconds();\n");
		fprintf(ss,"    var end_date = hours.substr(-2) + ':' + mins.substr(-2) + ':' + secs.substr(-2);\n");
		fprintf(ss,"    leth.ilist[i].canvas_in.draw_graph(leth.ilist[i].array_in,start_date,end_date);\n");
		fprintf(ss,"    leth.ilist[i].canvas_out.draw_graph(leth.ilist[i].array_out,start_date,end_date);\n");
		fprintf(ss,"    console.log('Updated [' + i + '] NAME: [' + leth.ilist[i].ifname + '] Size currently: [' + leth.ilist[i].rawdata.length + ']');\n");
		fprintf(ss,"    break;\n");
		fprintf(ss,"   }\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  console.log('[' + j + '] ILIST-INDEX: [' + i + '/' + leth.ilist.length + '] ETHLIST-INDEX: [' + j + ']');\n");
		fprintf(ss,"  if ( i == leth.ilist.length ){\n");
		fprintf(ss,"   var ilist_length = leth.ilist.length;\n");
		fprintf(ss,"   console.log('Creating object [' + ilist_length + ']');\n");
		fprintf(ss,"   leth.ilist[ilist_length] = Object.create(ilist_obj);\n");
		fprintf(ss,"   leth.ilist[ilist_length].ifname = ethlist[j].ifname;\n");
		fprintf(ss,"   leth.ilist[ilist_length].array_in  = [];\n");
		fprintf(ss,"   leth.ilist[ilist_length].array_out = [];\n");
		fprintf(ss,"   leth.ilist[ilist_length].rawdata   = [];\n");
		fprintf(ss,"   leth.ilist[ilist_length].rawdata[0] = Object.create(rawdata_obj);\n");
		fprintf(ss,"   leth.ilist[ilist_length].rawdata[0].name = ethlist[j].ifname;\n");
		fprintf(ss,"   leth.ilist[ilist_length].rawdata[0].timestamp = ethlist[j].timestamp;\n");
		fprintf(ss,"   leth.ilist[ilist_length].rawdata[0].bytes_in = ethlist[j].bytes_in;\n");
		fprintf(ss,"   leth.ilist[ilist_length].rawdata[0].bytes_out = ethlist[j].bytes_out;\n");
		fprintf(ss,"   leth.ilist[ilist_length].canvas_in = Object.create(GIXGraph);\n");
		fprintf(ss,"   leth.ilist[ilist_length].canvas_out = Object.create(GIXGraph);\n");
		fprintf(ss,"   console.log('Created object [' + ilist_length + '] Name: [' + leth.ilist[ilist_length].ifname + ']');\n");
		fprintf(ss,"  }\n");
		fprintf(ss," }\n");
		fprintf(ss," for ( var i = 0; i < leth.ilist.length; i++ ){\n");
		fprintf(ss,"   console.log('Final object [' + i + '] Name: [' + leth.ilist[i].ifname + '] Raw-Data[0] [' + leth.ilist[i].rawdata[0].name + ']');\n");
		fprintf(ss," }\n");
		fprintf(ss," var divvy = document.getElementById('ETHLIST');\n");
		fprintf(ss," console.log('Processing ETH-Display for ' + ethlist.length + ' Interfaces');\n");
		fprintf(ss," if ( divvy.innerHTML == 'init' ){\n");
		fprintf(ss,"  console.log('Initializing ETH-Display');\n");
		fprintf(ss,"  var result = '<TABLE CELLSPACING=1 BORDER=0 BGCOLOR=black>';\n");
		fprintf(ss,"  result += '<TR><TD BGCOLOR=white COLSPAN=4><CENTER><SPAN CLASS=thead1><B>Network-Interfaces</B></SPAN></TD></TR>';\n");
		fprintf(ss,"  result += '<TR><TD BGCOLOR=white COLSPAN=2><SPAN CLASS=thead2>Total Samples:</SPAN></TD><TD COLSPAN=2 BGCOLOR=white><SPAN CLASS=thead2 ID=TOTAL_SAMPLES></SPAN></TD></TR>';\n");
		fprintf(ss,"  result += '</TR>';\n");
		fprintf(ss,"  for ( var x = 0; x < ethlist.length; x++ ){\n");
		fprintf(ss,"   var color = 'yellow';\n");
		fprintf(ss,"   if ( x %% 2 ) color = 'lightblue';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ROWSPAN=11 VALIGN=TOP><SPAN CLASS=thead2><B>' + ethlist[x].ifname + '</B></SPAN></TD>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>Bytes in:</SPAN></TD><TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s ID=BYTES_SEC_IN_' + x + '>' + ethlist[x].bytes_in_sec + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ROWSPAN=11><CANVAS WIDTH=500 HEIGHT=100 ID=C_RECEIVE_' + x + ' CLASS=gcanvas1></CANVAS><BR><CANVAS  WIDTH=500 HEIGHT=100 CLASS=gcanvas1 ID=C_TRANSMIT_' + x + '></CANVAS></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>Bytes out:</SPAN></TD>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s ID=BYTES_SEC_OUT_' + x + '>' + ethlist[x].bytes_out_sec + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>Total Bytes in:</SPAN></TD><TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s ID=BYTES_IN_T_' + x + '>' + ethlist[x].bytes_in_t + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>Total Bytes out:</SPAN></TD>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s ID=BYTES_OUT_T_' + x + '>' + ethlist[x].bytes_out_t + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>Packets in:</SPAN></TD><TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s ID=PACKETS_SEC_IN_' + x + '>' + ethlist[x].packets_in_sec + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead1s>Packets out:</SPAN></TD>';\n");
		fprintf(ss,"   result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s ID=PACKETS_SEC_OUT_' + x + '>' + ethlist[x].packets_out_sec + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>Total Packets in:</SPAN></TD><TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s ID=PACKETS_IN_T_' + x + '>' + ethlist[x].packets_in_t + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>Total Packets out:</SPAN></TD>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s ID=PACKETS_OUT_T_' + x + '>' + ethlist[x].packets_out_t + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>MAC-Address</SPAN></TD><TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + ethlist[x].mac_addr + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>IPv4</SPAN></TD>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + ethlist[x].ipv4_addr + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"   result += '<TR>';\n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead1s>IPv6</SPAN></TD>';\n");
		fprintf(ss,"   result += '<TD ALIGN=RIGHT BGCOLOR=' + color + '><SPAN CLASS=thead2s>' + ethlist[x].ipv6_addr + '</SPAN></TD>';\n");
		fprintf(ss,"   result += '</TR>';\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  result += '</TABLE>';\n");
		fprintf(ss,"  divvy.innerHTML = result;\n");
		fprintf(ss,"  var id = document.getElementById('TOTAL_SAMPLES');\n");
		fprintf(ss,"  console.log('Total Samples: [' + leth.ilist[0].rawdata.length + ']');\n");
		fprintf(ss,"  if ( id != undefined ) id.innerHTML = leth.ilist[0].rawdata.length;\n");
		fprintf(ss,"  for ( var idx = 0; idx < leth.ilist.length; idx++ ){\n");
		fprintf(ss,"   leth.ilist[idx].canvas_in.init('C_RECEIVE_' + idx, 'green','red','black','Bytes in','','Bytes/s');\n");
		fprintf(ss,"   leth.ilist[idx].canvas_out.init('C_TRANSMIT_' + idx, 'green','red','black','Bytes out','','Bytes/s');\n");
		fprintf(ss,"  }\n");
		fprintf(ss," } else {\n"); // Just update
		fprintf(ss,"  console.log('Total Samples: [' + leth.ilist[0].rawdata.length + ']');\n");
		fprintf(ss,"  var id = document.getElementById('TOTAL_SAMPLES');\n");
		fprintf(ss,"  if ( id != undefined ) id.innerHTML = leth.ilist[0].rawdata.length;\n");
		fprintf(ss,"  for ( var x = 0; x < ethlist.length; x++ ){\n");
		fprintf(ss,"   var id = document.getElementById('BYTES_SEC_IN_' + x);\n");
		fprintf(ss,"   if ( id != undefined ) id.innerHTML = ethlist[x].bytes_in_sec;\n");
		fprintf(ss,"   var id = document.getElementById('BYTES_SEC_OUT_' + x);\n");
		fprintf(ss,"   if ( id != undefined ) id.innerHTML = ethlist[x].bytes_out_sec;\n");
		fprintf(ss,"   var id = document.getElementById('PACKETS_SEC_IN_' + x);\n");
		fprintf(ss,"   if ( id != undefined ) id.innerHTML = ethlist[x].packets_in_sec;\n");
		fprintf(ss,"   var id = document.getElementById('PACKETS_SEC_OUT_' + x);\n");
		fprintf(ss,"   if ( id != undefined ) id.innerHTML = ethlist[x].packets_out_sec;\n");
		fprintf(ss,"   var id = document.getElementById('BYTES_IN_T_' + x);\n");
		fprintf(ss,"   if ( id != undefined ) id.innerHTML = ethlist[x].bytes_in_t;\n");
		fprintf(ss,"   var id = document.getElementById('BYTES_OUT_T_' + x);\n");
		fprintf(ss,"   if ( id != undefined ) id.innerHTML = ethlist[x].bytes_out_t;\n");
		fprintf(ss,"   var id = document.getElementById('PACKETS_IN_T_' + x);\n");
		fprintf(ss,"   if ( id != undefined ) id.innerHTML = ethlist[x].packets_in_t;\n");
		fprintf(ss,"   var id = document.getElementById('PACKETS_OUT_T_' + x);\n");
		fprintf(ss,"   if ( id != undefined ) id.innerHTML = ethlist[x].packets_out_t;\n");
		fprintf(ss,"  }\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function display_fs_info(fsinfo){\n");
		fprintf(ss," console.log('Displaying info for [' + fsinfo.length + '] Filesystems');\n");
		fprintf(ss," var id = document.getElementById('FSINFO');\n");
		fprintf(ss," var result = '<TABLE CELLSPACING=1 BORDER=0 BGCOLOR=black>';\n");
		fprintf(ss," result += '<TR>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Device</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Path</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Total Size</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Avail Size</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Used Size(%%)</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Total Inodes</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Free Inodes</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Used Inodes(%%)</SPAN></TD>';\n");
		fprintf(ss," result += '</TR>';\n");
		fprintf(ss," for ( var i = 0; i < fsinfo.length; i++ ){\n");
		fprintf(ss,"  var color = 'lightblue';\n");
		fprintf(ss,"  if ( i %% 2 ) color = 'yellow';\n");
		fprintf(ss,"  var b_percent_size = Math.round((100.0 - (fsinfo[i].b_avail * 100) / fsinfo[i].b_total)*100)/100;\n");
		fprintf(ss,"  var i_percent_size = Math.round((100.0 - (fsinfo[i].i_free * 100) / fsinfo[i].i_total)*100)/100;\n");
		fprintf(ss,"  console.log('PATH: [' + fsinfo[i].path	 + '] Percent Blocks: [' + b_percent_size + '] Percent Inodes: [' + i_percent_size + ']');\n");
		fprintf(ss,"  result += '<TR>';\n");
		fprintf(ss,"  var bgcolor = color;\n");
		fprintf(ss,"  var bolder = '';\n");
		fprintf(ss,"  var endbolder = '';\n");
		fprintf(ss,"  if ( b_percent_size > 65 || i_percent_size > 60 ){ bolder = '<B>'; endbolder = '</B>'; bgcolor = 'orange'; }\n");
		fprintf(ss,"  if ( b_percent_size > 90 || i_percent_size > 95 ){ bolder = '<B>'; endbolder = '</B>'; bgcolor = 'red'; }\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + bgcolor + '><SPAN CLASS=thead2s>' + bolder + '/dev/' + fsinfo[i].dev_name + endbolder + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + bgcolor + '><SPAN CLASS=thead2s>' + bolder + fsinfo[i].path + endbolder + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + bgcolor + '><SPAN CLASS=thead2s>' + bolder + fsinfo[i].b_total_t + endbolder + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + bgcolor + '><SPAN CLASS=thead2s>' + bolder + fsinfo[i].b_avail_t + endbolder + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + bgcolor + '><SPAN CLASS=thead2s>' + bolder + b_percent_size + '%%' + endbolder + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + bgcolor + '><SPAN CLASS=thead2s>' + bolder + fsinfo[i].i_free_t + endbolder + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + bgcolor + '><SPAN CLASS=thead2s>' + bolder + fsinfo[i].i_free_t + endbolder + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=LEFT BGCOLOR=' + bgcolor + '><SPAN CLASS=thead2s>' + bolder + i_percent_size + '%%' + endbolder + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '</TR>';\n");
		fprintf(ss," }\n");
		fprintf(ss," result += '</TABLE>';\n");
		fprintf(ss," id.innerHTML = result;\n");	
		fprintf(ss,"}\n");


		fprintf(ss,"function update_connections_callback(req){\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status != 200 ) return;\n");
		fprintf(ss," if ( req.responseText.charAt(0) == 'O' ){\n");
		// fprintf(ss,"  console.log('JSON-REPLY: ' + req.responseText);\n");
		fprintf(ss,"  var proclist = JSON.parse(extract_bracket_val(req.responseText));\n");
		fprintf(ss,"  display_proclist(proclist);\n"); 
		fprintf(ss,"  display_int_info(proclist.eth);\n");
		fprintf(ss,"  display_fs_info(proclist.fs);\n");
		fprintf(ss," }\n");
		// fprintf(ss,"  for ( var i = 0; i < %d; i++ ){\n",entries);
		// fprintf(ss,"   get_conns(i);\n");
		// fprintf(ss,"  }\n");
		fprintf(ss,"  var request = new XMLHttpRequest();\n");
		fprintf(ss,"  request.onreadystatechange = function() { update_connections_callback_callback(request); };\n");
		fprintf(ss,"  request.open('GET','/ajax/SYSINFO/0' ,true);\n");
		fprintf(ss,"  request.send();\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function update_connections_callback_callback(req){\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status != 200 ) return;\n");
		fprintf(ss," console.log('Callback for SYSINFO ->  Response: [' + req.responseText + ']');\n");
		fprintf(ss," if ( req.responseText.charAt(0) == 'O' ){\n");
		fprintf(ss,"  var jresp = JSON.parse(extract_bracket_val(req.responseText));\n");
		fprintf(ss,"  var id = document.getElementById('LOAD1');\n");
		fprintf(ss,"  if ( id != undefined && id != null ) id.innerHTML = jresp.load1;\n");
		fprintf(ss,"  var id = document.getElementById('LOAD5');\n");
		fprintf(ss,"  if ( id != undefined && id != null ) id.innerHTML = jresp.load5;\n");
		fprintf(ss,"  var id = document.getElementById('LOAD15');\n");
		fprintf(ss,"  if ( id != undefined && id != null ) id.innerHTML = jresp.load15;\n");
		fprintf(ss,"  var id = document.getElementById('UPTIME');\n");
		fprintf(ss,"  if ( id != undefined && id != null ) id.innerHTML = jresp.uptime;\n");
		fprintf(ss,"  var id = document.getElementById('SYS_PROCS');\n");
		fprintf(ss,"  if ( id != undefined && id != null ) id.innerHTML = jresp.sys_procs;\n");
		fprintf(ss," }\n");
		fprintf(ss," update_tftp_display(jresp);\n");
		fprintf(ss," update_conns_display(jresp.inetlist);\n");
		fprintf(ss," document.getElementById('GIGA_ROTATOR').innerHTML = '<IMG SRC=/empty.gif HEIGHT=32>';\n");
		fprintf(ss," if ( gigatimer_active ) gigatimer = setInterval(update_connections,2000);\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function update_tftp_display(js){\n");
		fprintf(ss," document.getElementById('TFTP_REQUESTS_READ').innerHTML = js.tftp_requests_read;\n");
		fprintf(ss," document.getElementById('TFTP_REQUESTS_WRITE').innerHTML = js.tftp_requests_write;\n");
		fprintf(ss," document.getElementById('TFTP_ROOT').value = js.tftp_root;\n");
		fprintf(ss," if ( js.tftp_enabled > 0 ){\n");
		fprintf(ss,"  document.getElementById('TFTP_ENABLED').checked = true;\n");
		fprintf(ss," } else {\n");
		fprintf(ss,"  document.getElementById('TFTP_ENABLED').checked = false;\n");
		fprintf(ss," }\n");
		fprintf(ss," if ( js.tftp_readonly > 0 ){\n");
		fprintf(ss,"  document.getElementById('TFTP_READONLY').checked = true;\n");
		fprintf(ss," } else {\n");
		fprintf(ss,"  document.getElementById('TFTP_READONLY').checked = false;\n");
		fprintf(ss," }\n");
		fprintf(ss," var divvy = document.getElementById('TFTP_LIST');\n");
		fprintf(ss," if ( js.tftp_list.length < 1 ){\n");
		fprintf(ss,"  divvy.innerHTML = '';\n");
		fprintf(ss,"  return;\n");
		fprintf(ss," }\n");
		fprintf(ss," var result = '<TABLE BGCOLOR=black CELLSPACING=1>';\n");
		fprintf(ss," result += '<TR>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Type</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Remote-IP</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>File</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Size</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Transferred</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Started</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><SPAN CLASS=thead1s>Block-Size</SPAN></TD>';\n");
		fprintf(ss," result += '</TR>';\n");
		fprintf(ss," for ( var idx = 0; idx < js.tftp_list.length; idx++ ){\n");
		fprintf(ss,"  var color = 'yellow';\n");
		fprintf(ss,"  if ( idx %% 2 ) color = 'lightblue';\n");
		fprintf(ss,"  var percent = '-';\n");
		fprintf(ss,"  var date_start = new Date(js.tftp_list[idx].started * 1000);\n");
		fprintf(ss,"  var hours = '0' + date_start.getHours();\n");
		fprintf(ss,"  var mins  = '0' + date_start.getMinutes();\n");
		fprintf(ss,"  var secs  = '0' + date_start.getSeconds();\n");
		fprintf(ss,"  var date_string = hours.substr(-2) + ':' + mins.substr(-2) + ':' + secs.substr(-2);\n");
		fprintf(ss,"  if ( js.tftp_list[idx].fullsize ){ percent = Math.round((10000 * js.tftp_list[idx].offset)/js.tftp_list[idx].fullsize)/100 + '%%'; }\n"); 
		fprintf(ss,"  result += '<TR BGCOLOR=' + color + '>';\n");
		fprintf(ss,"  result += '<TD ALIGN=CENTER><SPAN CLASS=thead2s>' + js.tftp_list[idx].kind_transfer + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT><SPAN CLASS=thead2s>' + js.tftp_list[idx].remote_ip + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT><SPAN CLASS=thead2s>' + js.tftp_list[idx].filename + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT><SPAN CLASS=thead2s>' + js.tftp_list[idx].fullsize + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT><SPAN CLASS=thead2s>' + js.tftp_list[idx].offset + '(' + percent + ')</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT><SPAN CLASS=thead2s>' + date_string + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD ALIGN=RIGHT><SPAN CLASS=thead2s>' + js.tftp_list[idx].blksize + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '</TR>';\n");
		fprintf(ss," }\n");	
		fprintf(ss," result += '</TABLE>';\n");
		fprintf(ss," divvy.innerHTML = result;\n");
		fprintf(ss,"}\n");	

		fprintf(ss,"function save_tftp_settings(){\n");
		fprintf(ss,"  var newval = 1;\n");
		fprintf(ss,"  if ( document.getElementById('TFTP_ENABLED').checked == false ) newval = 0;\n");
		fprintf(ss,"  var request = new XMLHttpRequest();\n");
		fprintf(ss,"  request.open('GET','/ajax/SET_TFTP_ENABLE/' + newval ,false);\n");
		fprintf(ss,"  request.send();\n");
		fprintf(ss,"  console.log('Request-Status: [' + request.status + ']');\n");
		fprintf(ss,"  newval = 1;\n");
		fprintf(ss,"  if ( document.getElementById('TFTP_READONLY').checked == false ) newval = 0;\n");
		fprintf(ss,"  var request = new XMLHttpRequest();\n");
		fprintf(ss,"  request.open('GET','/ajax/SET_TFTP_READONLY/' + newval ,false);\n");
		fprintf(ss,"  request.send();\n");
		fprintf(ss,"  console.log('Request-Status: [' + request.status + ']');\n");
		fprintf(ss,"  var request = new XMLHttpRequest();\n");
		fprintf(ss,"  request.open('GET','/ajax/SET_TFTP_ROOT/' + document.getElementById('TFTP_ROOT').value  ,false);\n");
		fprintf(ss,"  request.send();\n");
		fprintf(ss,"  console.log('Request-Status: [' + request.status + ']');\n");
		fprintf(ss,"}\n");



		fprintf(ss,"function toggle_giga_refresh(){\n");
		fprintf(ss," if ( gigatimer_active ){\n");
		fprintf(ss,"  document.getElementById('REFRESH_GIGA_BUTTON').value = 'Enable Auto-Refresh';\n");
		fprintf(ss,"  gigatimer_active = false;\n");
		fprintf(ss,"  if ( gigatimer != null ){ clearInterval(gigatimer); }\n");
		fprintf(ss," } else {\n");
		fprintf(ss,"  document.getElementById('REFRESH_GIGA_BUTTON').value = 'Stop Auto-Refresh';\n");
		fprintf(ss,"  gigatimer_active = true;\n");
		fprintf(ss,"  update_connections();\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");



		fprintf(ss,"function show_info_rotator(){\n");
		// fprintf(ss," var refresh_button = document.getElementById('REFRESH_BUTTON');\n");
		fprintf(ss," var rotator_id = document.getElementById('ROTATOR');\n");
		// fprintf(ss," refresh_button.style.visibility = 'hidden';\n");
		fprintf(ss," rotator_id.innerHTML = '<IMG SRC=/new_rotator_big.gif HEIGHT=32>';\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function hide_info_rotator(){\n");
		// fprintf(ss," var refresh_button = document.getElementById('REFRESH_BUTTON');\n");
		fprintf(ss," var rotator_id = document.getElementById('ROTATOR');\n");
		// fprintf(ss," refresh_button.style.visibility = 'visible';\n");
		fprintf(ss," rotator_id.innerHTML = '<IMG SRC=/empty.gif HEIGHT=32>';\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function process_detail1(pid){\n");
		fprintf(ss," if ( gigatimer_active ) { toggle_giga_refresh(); }\n");
		fprintf(ss," if ( megatimer != null ) clearInterval(megatimer);\n");
		fprintf(ss," megatimer_active = false;\n");
		fprintf(ss," process_detail(pid);\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function process_detail(pid){\n");
		fprintf(ss," close_info_window();\n");
		fprintf(ss," var main = document.getElementById('MAIN');\n");
		fprintf(ss," var newdiv = document.createElement('DIV');\n");
		fprintf(ss," newdiv.setAttribute('class','info_div');\n");
		fprintf(ss," newdiv.id = 'NEWDIV';\n");
		fprintf(ss," var closer_span = document.createElement('SPAN');\n");
		fprintf(ss," closer_span.setAttribute('class','filemanagerclose2');\n");
		fprintf(ss," closer_span.style.styleFloat = 'right';\n");
		fprintf(ss," closer_span.style.cssFloat = 'right';\n");
		fprintf(ss," closer_span.innerHTML = '&times';\n");
		fprintf(ss," closer_span.id = 'CLOSER';\n");
		fprintf(ss," var refresh_button = document.createElement('BUTTON');\n");
		fprintf(ss," refresh_button.id = 'REFRESH_BUTTON';\n");
		fprintf(ss," refresh_button.setAttribute('class','standard_button');\n");
		fprintf(ss," refresh_button.innerHTML = 'Enable Auto-Refresh';\n");
		fprintf(ss," newdiv.appendChild(closer_span);\n");
		fprintf(ss," var rotator_id = document.createElement('SPAN');\n");
		fprintf(ss," rotator_id.id = 'ROTATOR';\n");
		fprintf(ss," rotator_id.setAttribute('class','rotator_div');\n");
		fprintf(ss," rotator_id.innerHTML = '<IMG SRC=/empty.gif HEIGHT=32>';\n");
		fprintf(ss," newdiv.appendChild(rotator_id);\n");
		fprintf(ss," newdiv.appendChild(refresh_button);\n");
		fprintf(ss," var tdiv = document.createElement('DIV');\n");
		fprintf(ss," closer_span.addEventListener('click',function() { close_info_window(); });\n");
		fprintf(ss," refresh_button.addEventListener('click',function() { process_detail_refresh_toggle(pid,tdiv); });\n");
		fprintf(ss," tdiv.setAttribute('class','table_list2');\n");
		fprintf(ss," tdiv.id = 'TDIV';\n");
		fprintf(ss," tdiv.style.backgroundColor = 'black';\n");
		fprintf(ss," newdiv.appendChild(tdiv);\n");
		fprintf(ss," main.appendChild(newdiv);\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," show_info_rotator();\n");
		fprintf(ss," request.onreadystatechange = function() { process_detail_callback(request,pid,tdiv); };\n");
		fprintf(ss," request.open('GET','/ajax/PROCDETAIL/' + pid, true);\n");
		fprintf(ss," request.send();\n");
		fprintf(ss," if ( megatimer_active ) megatimer = setInterval(function() { process_detail_refresh(pid,tdiv); },2000);\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function process_detail_refresh_toggle(pid,tdiv){\n");
		fprintf(ss," var id = document.getElementById('REFRESH_BUTTON');\n");
		fprintf(ss," if ( megatimer_active ){\n");
		fprintf(ss,"  if ( megatimer != null ) { clearInterval(megatimer); megatimer = null; };\n");
		fprintf(ss,"  id.innerHTML = 'Enable Auto-Refresh';\n");
		fprintf(ss,"  megatimer_active = false;\n");
		fprintf(ss," } else {\n");
		fprintf(ss,"  if ( megatimer != null ) { clearInterval(megatimer); megatimer = null; };\n");
		fprintf(ss,"  megatimer = setInterval(function() { process_detail_refresh(pid,tdiv); },2000);\n");
		fprintf(ss,"  id.innerHTML = 'Stop Auto-Refresh';\n");
		fprintf(ss,"  process_detail_refresh(pid,tdiv);\n");
		fprintf(ss,"  megatimer_active = true;\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function process_detail_refresh(pid,tdiv){\n");
		fprintf(ss," if ( megatimer != null ) clearInterval(megatimer);\n");
		fprintf(ss," show_info_rotator();\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.onreadystatechange = function() { process_detail_callback(request,pid,tdiv); };\n");
		fprintf(ss," request.open('GET','/ajax/PROCDETAIL/' + pid, true);\n");
		fprintf(ss," request.send();\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function process_detail_callback(req,pid,tdiv){\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status != 200 ) return;\n");
		fprintf(ss," console.log('Callback for PROCESS_DETAIL(' + pid + ') ->  Response: [' + req.responseText + ']');\n");
		fprintf(ss," hide_info_rotator();\n");
		fprintf(ss," var result = '<CENTER>';\n");
		fprintf(ss," result += '<P><SPAN CLASS=theadbig>Information for Process: <B>' + pid + '</B></SPAN></P>';\n");
		fprintf(ss," result += '<P><INPUT TYPE=BUTTON CLASS=standard_buttons VALUE=\"Send HUP Signal\" onclick=send_signal(' + pid + ',1)>&nbsp;';\n");
		fprintf(ss," result += '<INPUT TYPE=BUTTON CLASS=standard_buttons VALUE=\"Send KILL Signal\" onclick=send_signal(' + pid + ',9)></P>';\n");
		fprintf(ss," if ( req.responseText.charAt(0) != 'O' ){\n");
		fprintf(ss,"  tdiv.innerHTML = result;\n");
		fprintf(ss,"  alert('Could not get process details [' + extract_bracket_val(req.responseText) + ']');\n");
		fprintf(ss,"  close_info_window();\n");
		fprintf(ss,"  return;\n");
		fprintf(ss," }\n");
		fprintf(ss," var pd = JSON.parse(extract_bracket_val(req.responseText));\n");
		fprintf(ss," result += '<P>';\n");
		fprintf(ss," result += '<TABLE CELLSPACING=1 BORDER=0 BGCOLOR=black>';\n");
		fprintf(ss," result += '<TR><TD VALIGN=TOP>';\n");
		fprintf(ss," result += '<TABLE CELLSPACING=1 BORDER=0 BGCOLOR=blue>';\n");
		fprintf(ss," if ( pd.ppid == 0 ){\n");
		fprintf(ss,"  result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Parent-PID:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>No parent</SPAN></TD></TR>';\n");
		fprintf(ss," } else {\n");
		fprintf(ss,"  result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Parent-PID:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2slink onclick=process_detail1(' + pd.ppid + ')>' + pd.ppid + '</SPAN></TD></TR>';\n");
		fprintf(ss," }\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Process-state:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.full_state + '</B></SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Real-UID:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.r_uid + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Real-GID:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.r_gid + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Effective-UID:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.e_uid + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Effective-GID:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.e_gid + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Name:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.name + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Executeable-path:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.full_exe + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Working-directory:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.full_cwd + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Commandline:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.commandline + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>CPU-Usage (sys):</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.cpu_usage_sys + '%%</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>CPU-Time (sys):</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.sys_time + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>CPU-Usage (usr):</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.cpu_usage_usr + '%%</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>CPU-Time (usr):</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.usr_time + '</SPAN></TD></TR>';\n");
		fprintf(ss," if ( pd.slot > -1 && pd.index > -1 ){\n");
		fprintf(ss,"  result += '<TR><TD ALIGN=CENTER BGCOLOR=white COLSPAN=2><INPUT TYPE=BUTTON CLASS=standard_button VALUE=\"Show GINETD-Connection\" onclick=conns_list1(' + pd.slot + ',' + pd.index + ')></TD></TR>';\n");
		fprintf(ss," }\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Process-started:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.p_start + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Virtual memory:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.vm_size + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Real memory:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.rss + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Threads:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.num_threads + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>CPU:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.cpu + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '<TR><TD ALIGN=RIGHT BGCOLOR=white><SPAN CLASS=thead2s>Count of fds:</SPAN></TD><TD BGCOLOR=white ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.fds.length + '</SPAN></TD></TR>';\n");
		fprintf(ss," result += '</TABLE>';\n");
		fprintf(ss," result += '</TD>';\n");
		fprintf(ss," result += '<TD VALIGN=TOP>';\n");
		fprintf(ss," result += '<DIV CLASS=fd_div>';\n");
		fprintf(ss," result += '<TABLE CELLSPACING=1 BGCOLOR=blue>';\n");
		fprintf(ss," result += '<TR><TD BGCOLOR=white><SPAN CLASS=thead1>FD</SPAN></TD><TD BGCOLOR=white><SPAN CLASS=thead1>Type</SPAN></TD><TD BGCOLOR=white><SPAN CLASS=thead1>Name</SPAN></TD></TR>';\n");
		fprintf(ss," for ( var ix = 0; ix < pd.fds.length; ix++ ){\n");
		fprintf(ss,"  var color = 'yellow';\n");
		fprintf(ss,"  if ( ix %% 2 ) color = 'lightblue';\n");
		fprintf(ss,"  result += '<TR>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + pd.fds[ix].fd + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + pd.fds[ix].type + '</SPAN></TD>';\n");
		fprintf(ss,"  if ( pd.fds[ix].valid_addr == true ){\n");
		fprintf(ss,"   var status = 'unknown&nbsp;' + pd.fds[ix].state;\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 1 ) status = 'ESTABLISHED';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 2 ) status = 'SYN_SENT';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 3 ) status = 'SYN_RECV';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 4 ) status = 'FIN_WAIT1';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 5 ) status = 'FIN_WAIT2';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 6 ) status = 'TIME_WAIT(' + pd.fds[ix].timer_value + ')';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 7 ) status = 'CLOSE';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 8 ) status = 'CLOSE_WAIT(' + pd.fds[ix].timer_value + ')';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 9 ) status = 'LAST_ACK';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 10 ) status = 'LISTEN';\n");
		fprintf(ss,"   if ( pd.fds[ix].state == 11 ) status = 'CLOSING';\n");
		fprintf(ss,"   var family = 'unknown&nbsp;' + pd.fds[ix].family;\n");
		fprintf(ss,"   if ( pd.fds[ix].family == %d ) family = 'IPv6';\n",AF_INET6);
		fprintf(ss,"   if ( pd.fds[ix].family == %d ) family = 'IPv4';\n",AF_INET);
		fprintf(ss,"   if ( pd.fds[ix].family == %d ) family = 'unix';\n",AF_UNIX);
		fprintf(ss,"   var protocol = 'unknown&nbsp;' + pd.fds[ix].protocol;\n");
		fprintf(ss,"   if ( pd.fds[ix].protocol == %d ) protocol = 'TCP';\n",SOCK_STREAM);
		fprintf(ss,"   if ( pd.fds[ix].protocol == %d ) protocol = 'UDP';\n",SOCK_DGRAM);
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=LEFT><SPAN CLASS=thead2s>[' + family + '][' + protocol + '] [' + pd.fds[ix].local_addr + ']:' + pd.fds[ix].local_port + ' - [' + pd.fds[ix].remote_addr + ']:' + pd.fds[ix].remote_port + ' (' + status + ')</SPAN></TD>';\n");
		fprintf(ss,"  } else { \n");
		fprintf(ss,"   result += '<TD BGCOLOR=' + color + ' ALIGN=LEFT><SPAN CLASS=thead2s>' + pd.fds[ix].name + '</SPAN></TD>';\n");
		fprintf(ss,"  }\n");
		fprintf(ss,"  result += '</TR>';\n");
		fprintf(ss," }\n");
		fprintf(ss," result += '</TABLE>';\n");
		fprintf(ss," result += '</DIV>';\n");
		fprintf(ss," result += '</TD>';\n");
		fprintf(ss," result += '</TR>';\n");
		fprintf(ss," result += '</TABLE>';\n");
		fprintf(ss," result += '</P>';\n");
		fprintf(ss," tdiv.innerHTML = result;\n");
		fprintf(ss," if ( megatimer_active ) megatimer = setInterval(function() { process_detail_refresh(pid,tdiv); },2000);\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function conns_list1(idx,item){\n");
		fprintf(ss," if ( gigatimer_active ) { toggle_giga_refresh(); }\n");
		fprintf(ss," if ( megatimer != null ) clearInterval(megatimer);\n");
		fprintf(ss," megatimer_active = false;\n");
		fprintf(ss," conns_list(idx,item);\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function send_signal(pid, sig){\n");
		fprintf(ss," console.log('Sending Signal [' + sig + '] to process-ID: [' + pid + ']');\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.onreadystatechange = send_signal_callback;\n");
		fprintf(ss," request.open('GET','/ajax/SIGNAL/' + pid + '/' + sig , true);\n");
		fprintf(ss," request.send();\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function send_signal_callback(){\n");
		fprintf(ss," if ( this.readyState != 4 ) return;\n");
		fprintf(ss," console.log('Status: [' + this.status + '] Response: [' + this.responseText + ']');\n");
		fprintf(ss," if ( this.responseText.charAt(0) == 'O' ) {\n");
		fprintf(ss,"  alert('Sent signal to process');\n");
		fprintf(ss," } else {\n");
		fprintf(ss,"  alert('Sending signal to process failed!');\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");



		fprintf(ss,"function  conns_list(idx,item){\n");
		fprintf(ss," close_info_window();\n");
		fprintf(ss," var main = document.getElementById('MAIN');\n");
		fprintf(ss," var newdiv = document.createElement('DIV');\n");
		fprintf(ss," newdiv.setAttribute('class','info_div');\n");
		fprintf(ss," newdiv.id = 'NEWDIV';\n");
		fprintf(ss," var closer_span = document.createElement('SPAN');\n");
		fprintf(ss," closer_span.setAttribute('class','filemanagerclose2');\n");
		fprintf(ss," closer_span.style.styleFloat = 'right';\n");
		fprintf(ss," closer_span.style.cssFloat = 'right';\n");
		fprintf(ss," closer_span.innerHTML = '&times';\n");
		fprintf(ss," closer_span.id = 'CLOSER';\n");
		fprintf(ss," var refresh_button = document.createElement('BUTTON');\n");
		fprintf(ss," refresh_button.id = 'REFRESH_BUTTON';\n");
		fprintf(ss," refresh_button.setAttribute('class','standard_button');\n");
		fprintf(ss," refresh_button.innerHTML = 'Enable Auto-Refresh';\n");
		fprintf(ss," newdiv.appendChild(closer_span);\n");
		fprintf(ss," var rotator_id = document.createElement('SPAN');\n");
		fprintf(ss," rotator_id.id = 'ROTATOR';\n");
		fprintf(ss," rotator_id.setAttribute('class','rotator_div');\n");
		fprintf(ss," newdiv.appendChild(rotator_id);\n");
		fprintf(ss," newdiv.appendChild(refresh_button);\n");
		fprintf(ss," var tdiv = document.createElement('DIV');\n");
		fprintf(ss," closer_span.addEventListener('click',function() { close_info_window(); });\n");
		fprintf(ss," refresh_button.addEventListener('click',function() { reload_conns_list_toggle(idx,item); });\n");
		fprintf(ss," tdiv.setAttribute('class','table_list');\n");
		fprintf(ss," tdiv.id = 'TDIV';\n");
		fprintf(ss," newdiv.appendChild(tdiv);\n");
		fprintf(ss," main.appendChild(newdiv);\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," show_info_rotator();\n");
		fprintf(ss," request.onreadystatechange = function() { conns_list_callback(request,idx,item); };\n");
		fprintf(ss," request.open('GET','/ajax/CONNSLIST/' + idx, true);\n");
		fprintf(ss," request.send();\n");
		fprintf(ss," if ( megatimer_active ) megatimer = setInterval(function() { reload_conns_list(idx,item); },1000);\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function reload_conns_list_toggle(idx,item){\n");
		fprintf(ss," var id = document.getElementById('REFRESH_BUTTON');\n");
		fprintf(ss," if ( megatimer_active ){\n");
		fprintf(ss,"  if ( megatimer != null ) { clearInterval(megatimer); megatimer = null; };\n");
		fprintf(ss,"  id.innerHTML = 'Enable Auto-Refresh';\n");
		fprintf(ss,"  megatimer_active = false;\n");
		fprintf(ss," } else {\n");
		fprintf(ss,"  if ( megatimer != null ) { clearInterval(megatimer); megatimer = null; };\n");
		fprintf(ss,"  megatimer = setInterval(function() { reload_conns_list(idx,item); },1000);\n");
		fprintf(ss,"  id.innerHTML = 'Stop Auto-Refresh';\n");
		fprintf(ss,"  reload_conns_list(idx,item);\n");
		fprintf(ss,"  megatimer_active = true;\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function reload_conns_list(idx,item){\n");
		fprintf(ss," if ( megatimer != null ) clearInterval(megatimer);\n");
		fprintf(ss," show_info_rotator();\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.onreadystatechange = function() { conns_list_callback(request,idx,item); };\n");
		fprintf(ss," request.open('GET','/ajax/CONNSLIST/' + idx, true);\n");
		fprintf(ss," request.send();\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function conns_list_callback(req,idx,item){\n");
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status != 200 ) return;\n");
		fprintf(ss," console.log('Callback for CONNSLIST ->  Response: [' + req.responseText + ']');\n");
		fprintf(ss," hide_info_rotator();\n");
		fprintf(ss," if ( req.responseText.charAt(0) != 'O' ){\n");
		fprintf(ss,"  alert('Could not get list of connections');\n");
		fprintf(ss,"  return;\n");
		fprintf(ss," }\n");
		fprintf(ss," var connection = JSON.parse(extract_bracket_val(req.responseText));\n");
		fprintf(ss," console.log('Found [' + connection.length + '] records');\n");
		fprintf(ss," var cid = document.getElementById('TDIV');\n");
		fprintf(ss," var result = '<TABLE CELLSPACING=1 BORDER=0 BGCOLOR=black><TR><TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Index</SPAN></TD><TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Source</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Target</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>PID</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Prog&nbsp;PID</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Created</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>CWD</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Data</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Stack</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Exe</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>Libs</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>IO-Read</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>IO-Write</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>TCP&nbsp;State</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>TCP&nbsp;Timeout</SPAN></TD>';\n");
		fprintf(ss," result += '<TD BGCOLOR=white><CENTER><SPAN CLASS=thead1>&nbsp;</SPAN></TD>';\n");
		fprintf(ss," result += '</TR>';\n");
		fprintf(ss," for ( var i = 0; i < connection.length; i++ ){\n");
		fprintf(ss,"  var color = 'lightblue';\n");
		fprintf(ss,"  if ( i % 2 ) color = 'yellow';\n");
		fprintf(ss,"  if ( i == item ) color = 'orange';\n");
		fprintf(ss,"  result += '<TR>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' +  connection[i].slot +  '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + '><SPAN CLASS=thead2s><B>' + connection[i].source + '</B>:' + connection[i].source_port + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + '><SPAN CLASS=thead2s><B>' + connection[i].target + '</B>:' + connection[i].target_port + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2links onclick=process_detail1(' + connection[i].pid + ')>' + connection[i].pid + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2links onclick=process_detail1(' + connection[i].cpid + ')>' + connection[i].cpid + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].created + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].cwd + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].vm_data + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].vm_stack + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].vm_exe + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].vm_lib + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].io_read + '(' + connection[i].io_read_sec + ')</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].io_write + '(' + connection[i].io_write_sec + ')</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].tcp_state + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=RIGHT><SPAN CLASS=thead2s>' + connection[i].tcp_timeout + '</SPAN></TD>';\n");
		fprintf(ss,"  result += '<TD BGCOLOR=' + color + ' ALIGN=CENTER><INPUT TYPE=BUTTON CLASS=standard_button onclick=kill_connection(' + connection[i].cpid + ',' + idx + ',' + i + ') VALUE=\"Disconnect\"></TD>';\n");
		fprintf(ss,"  result += '</TR>';\n");
		fprintf(ss," }\n");
		fprintf(ss," cid.innerHTML = result;\n");
		fprintf(ss," if ( megatimer )  megatimer = setInterval(function() { reload_conns_list(idx,item); },1000);\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function kill_connection(pid, main_idx, co_index){\n");
		fprintf(ss," var request = new XMLHttpRequest();\n");
		fprintf(ss," request.onreadystatechange = function() { kill_connection_callback(request,pid,main_idx,co_index); };\n");
		fprintf(ss," request.open('GET','/ajax/KILLTCP/' + main_idx + '/' + co_index, true);\n");
		fprintf(ss," request.send();\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function kill_connection_callback(req,pid,main_idx,co_idx){\n"); 
		fprintf(ss," if ( req.readyState != 4 ) return;\n");
		fprintf(ss," if ( req.status != 200 ) return;\n");
		fprintf(ss," if ( req.responseText.charAt(0) != 'O' ){\n");
		fprintf(ss,"  alert('Could kill connection');\n");
		fprintf(ss,"  return;\n");
		fprintf(ss," } else {\n");
		fprintf(ss,"  alert('Connection received kill');\n");
		fprintf(ss,"  return;\n");
		fprintf(ss," }\n");
		fprintf(ss,"}\n");


		fprintf(ss,"function close_info_window(){\n");
		fprintf(ss,"var newdiv =  document.getElementById('NEWDIV');\n");
		fprintf(ss,"var rotator = document.getElementById('ROTATOR');\n");
		fprintf(ss,"var closer =  document.getElementById('CLOSER');\n");
		fprintf(ss,"var main =    document.getElementById('MAIN');\n");
		fprintf(ss,"var tdiv =    document.getElementById('TDIV');\n");
		fprintf(ss," if ( megatimer != undefined && megatimer != null ){ clearInterval(megatimer); megatimer = null; } \n");
		fprintf(ss," if ( newdiv != undefined && rotator != undefined ) newdiv.removeChild(rotator);\n");
		fprintf(ss," if ( newdiv != undefined && closer != undefined )  newdiv.removeChild(closer);\n");
		fprintf(ss," if ( newdiv != undefined && tdiv != undefined )    newdiv.removeChild(tdiv);\n");
		fprintf(ss," if ( main != undefined && newdiv != undefined )    main.removeChild(newdiv);\n");
		fprintf(ss," megatimer_active = false;\n");
		fprintf(ss," if ( megatimer ) { clearInterval(megatimer); megatimer = null; }\n");
		fprintf(ss,"}\n");

		fprintf(ss,"function init_all(){\n");
		fprintf(ss," console.log('Initializing everything');\n");
		fprintf(ss," megatimer = null;\n");
		fprintf(ss," gigatimer = null;\n");
		fprintf(ss," megatimer_active = false;\n");
		fprintf(ss," gigatimer_active = false;\n");
		fprintf(ss," gigatimer_stored = false;\n");
		fprintf(ss," leth = Object.create(eth_obj);\n");
		fprintf(ss," update_connections();\n"); // Initial call
		fprintf(ss,"}\n");

		fprintf(ss,"</SCRIPT>\n");
	}




	if ( type_req == TYPE_HTML ){
		fprintf(ss,"</BODY>\n");
		fflush(ss);
		shutdown(sock,SHUT_RDWR);
		fclose(ss);
		return;
	}
		
	shutdown(sock,SHUT_RDWR);
	fclose(ss);
	return;
}


void process_client(int index){
	char nprefix[256];
	long safe_fd;
	struct pollfd polly[2];
	unsigned char buffer[MAX_BUFFER];
	int pid;
	connection_index = index;
	sprintf(nprefix,"%s IDX:%d [%s:%d] [%s]",prefix,index,CCON.source,CCON.port,CSERVER.cmdline);
	strcpy(prefix,nprefix);
	// logger(prefix,"STARTING\n");

	
	{
		struct sigaction act;
		bzero(&act,sizeof(act));
		act.sa_sigaction = &slave_reaper;
		act.sa_flags = SA_SIGINFO | SA_RESTART;
		sigaction(SIGCHLD,&act,NULL);
		// signal(SIGCHLD,server_reaper);
	}
	// logger(prefix,"About to start: [%s]\n",CSERVER.cmdline);
	if ( (pid = fork()) == 0 ){
		char **pp;
		char *cmd;
		char *prg;
		char *ptr;
		int args;
		pp = NULL;

		if ( strncmp(CSERVER.cmdline,"ADMIN",5) == 0 ){
			char pwd[128];
			ptr = &(CSERVER.cmdline)[5];
			while ( *ptr && ( *ptr == ' ' || *ptr == '\t' )) ptr++;
			strcpy(pwd,ptr);
			ptr = &pwd[strlen(pwd)-1];
			while ( ptr > pwd && ( *ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n' )) ptr--;
			strcat(prefix,"{ADMIN}");
			call_webserver(CCON.sock,pwd);
			exit(0);
		}


		cmd = strdup(CSERVER.cmdline);
		args = 0;
		while ( (ptr = strtok(cmd," \t\r\n")) != NULL ){
			cmd = NULL;
			if ( args == 0 ){
				prg = strdup(ptr);	
			}
			pp = (char **)realloc(pp,sizeof(char *) * (args+1));
			pp[args++] = strdup(ptr);
			pp[args] = NULL;
		}
		logger(prefix,"Will execute [%s] with %d args PID: %d\n",prg,args,getpid());
		dup2(CCON.sock, fileno(stdin));
		dup2(CCON.sock, fileno(stdout));
		execvp(prg,pp);
		logger(prefix,"Cannot execute: [%s]\n",prg);
		exit(9);
		
	} 
	CCON.cpid = pid;



	/*	
	// Make everything non-blocking
	safe_fd = fcntl(CCON.sock,F_GETFL);
	safe_fd |= O_NONBLOCK;
	if ( fcntl(CCON.sock,F_SETFL,safe_fd) < 0){
		logger(prefix,"Cannot set socket non-blocking!\n");
		kill(CCON.cpid,9);
		exit(0);
	}
	*/

	while(1){
		int received;
		int fat_timeout;
		struct timespec tmo_p;
		sigset_t mask;

		polly[0].fd     = CCON.sock;
#ifdef POLLRDHUP
		polly[0].events =  POLLHUP | POLLERR | POLLRDHUP;
#else
		polly[0].events =  POLLHUP | POLLERR;
#endif
		if ( CSERVER.data_timeout > 0 ) polly[0].events |=  POLLIN;

		if ( CSERVER.timeout < 0  ){
			fat_timeout = CSERVER.data_timeout;
		} else {
			if ( CSERVER.data_timeout < 0 ){
				fat_timeout = CSERVER.timeout;
			} else {
				if ( CSERVER.data_timeout < CSERVER.timeout ){
					fat_timeout = CSERVER.data_timeout;
				} else {
					fat_timeout = CSERVER.timeout;
				}
			}
		}
		// logger(prefix,"POLLING...\n");	
		if ( fat_timeout <= 0 ){
			tmo_p.tv_sec = 31536000;
		} else {
			tmo_p.tv_sec = fat_timeout;
		}
		tmo_p.tv_nsec = 0;
		sigemptyset(&mask);
		// sigaddset(&mask,SIGTERM);
		// sigaddset(&mask,SIGHUP);
		// sigaddset(&mask,SIGCHLD);
		sigaddset(&mask,SIGPIPE);
		sigaddset(&mask,SIGINT);
		sigaddset(&mask,SIGUSR1);
		sigaddset(&mask,SIGUSR2);
		/* if ( (received =  ppoll(polly,1,&tmo_p,&mask)) < 1 ) */
#ifdef IPV6_V6ONLY
		if ( (received =  ppoll(polly,1,&tmo_p,NULL)) < 1 ){
#else
		if ( (received =  poll(polly,1,tmo_p.tv_sec * 1000)) < 1 ){
#endif
		
			if ( CSERVER.timeout > 0 && (CSERVER.timeout + CCON.created) <= time(NULL) ){
				logger(prefix,"Connection ran into timeout (%d Seconds)\n", CSERVER.timeout);
				if ( CCON.cpid ) kill(CCON.cpid,9);
				exit(0);
			} else { // A data-timeout
				if ( CSERVER.data_timeout > 0 ){
					if ( (CCON.lastin + CSERVER.data_timeout) <= time(NULL) ){
						logger(prefix,"Connection canceled because of data-timeout (%d Seconds) [Total-Session-time: %d]\n", CSERVER.data_timeout,time(NULL) - CCON.created);
						close(CCON.sock);
						if ( CCON.cpid ) m_kill(CCON.cpid,9);
						exit(0);
					}
				}
			}
		}
#ifdef POLLRDHUP		
		logger(prefix,"POLL[SOCKET]: [%s,%s,%s,%s,%s]\n",
			polly[0].revents & POLLNVAL ? "NVAL" : "",
			polly[0].revents & POLLIN ? "IN" : "",
			polly[0].revents & POLLHUP ? "HUP" : "",
			polly[0].revents & POLLRDHUP ? "RDHUP" : "",
			polly[0].revents & POLLERR ? "ERR" : "");
		if ( (polly[0].revents & POLLHUP) || (polly[0].revents & POLLRDHUP) ){
				logger(prefix,"SOCKET finished connection (%d Seconds active) Socket-ID: %d\n", time(NULL) - CCON.created,CCON.sock);
				close(CCON.sock);
				if ( CCON.cpid ) m_kill(CCON.cpid,9);
				exit(0);
		}
#else
		logger(prefix,"POLL[SOCKET]: [%s,%s,%s,%s]\n",
			polly[0].revents & POLLNVAL ? "NVAL" : "",
			polly[0].revents & POLLIN ? "IN" : "",
			polly[0].revents & POLLHUP ? "HUP" : "",
			polly[0].revents & POLLERR ? "ERR" : "");
		if ( (polly[0].revents & POLLHUP)  ){
				logger(prefix,"SOCKET finished connection (%d Seconds active) Socket-ID: %d\n", time(NULL) - CCON.created,CCON.sock);
				close(CCON.sock);
				if ( CCON.cpid ) m_kill(CCON.cpid,9);
				exit(0);
		}
#endif
		if ( (polly[0].revents & POLLIN) ){
			CCON.lastin = time(NULL);
		}
		if ( CSERVER.data_timeout > 0 ){
			if ( (CCON.lastin + CSERVER.data_timeout) <= time(NULL) ){
				logger(prefix,"Connection canceled because of data-timeout (%d Seconds) [Total-Session-time: %d]\n", CSERVER.data_timeout,time(NULL) - CCON.created);
				close(CCON.sock);
				if ( CCON.cpid ) m_kill(CCON.cpid,9);
				exit(0);
			}
		}
	}	
	close(CCON.sock);
	exit(0);	
}



void start_server(int index){
	int sock;
	int on;
	struct sockaddr *saddr;
	int saddr_len;
	struct sockaddr_in sock4;
	struct sockaddr_in6 sock6;

	global_index = index;
	servlist = (struct server *)shmat(shm_id,NULL,0);
	if ( servlist == NULL ){
		logger("MAIN","FATAL(%s:%d) Cannot attach shared-memory\n",__FILE__,__LINE__);
		exit(3);
	}
	sprintf(prefix,"[%d] S-PORT %d [%s]",index,servlist[index].port,servlist[index].family == AF_INET6 ? "IPv6" : "IPv4");
	logger(prefix,"Initializing...\n");
	sock = socket(CSERVER.family,SOCK_STREAM,0);
	if ( sock < 0 ){
		logger	(prefix,"FATAL(%s:%d) Cannot create socket\n",__FILE__,__LINE__);
		exit(3);
	}
	on = 1;
	if ( setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) < 0 ){
		logger	(prefix,"FATAL(%s:%d) Cannot SO_REUSEADDR socket\n",__FILE__,__LINE__);
		exit(3);
	}
	if ( CSERVER.family == AF_INET ){
		sock4.sin_family = AF_INET;
		sock4.sin_addr.s_addr = INADDR_ANY;
		sock4.sin_port = htons(CSERVER.port);
		saddr = (struct sockaddr *)&sock4;
		saddr_len = sizeof(sock4);
	} else {
#ifdef IPV6_V6ONLY
		if ( setsockopt(sock,IPPROTO_IPV6, IPV6_V6ONLY,&on,sizeof(on)) < 0 ){
			logger	(prefix,"FATAL(%s:%d) Cannot IPV6_V6ONLY socket\n",__FILE__,__LINE__);
			exit(3);
		}
#endif
		sock6.sin6_family = AF_INET6;
		sock6.sin6_port   = htons(CSERVER.port);
		sock6.sin6_addr   = in6addr_any;
		saddr = (struct sockaddr *)&sock6;
		saddr_len = sizeof(sock6);
	}	
	if ( bind(sock,saddr,saddr_len) < 0 ){
		logger	(prefix,"FATAL(%s:%d) Cannot bind socket\n",__FILE__,__LINE__);
		exit(3);
	}
	listen(sock,MAX_BACKLOG);
	semid2 = semget(INETD_KEY2 + global_index,1,0);
	if ( semid2 >= 0 ) semctl(semid2,IPC_RMID,0);
	semid2 = semget(INETD_KEY2 + global_index,1,0600|IPC_CREAT);
	semctl(semid2,0,SETVAL,1);
	semid = semget(INETD_KEY + global_index,1,0);
	if ( semid >= 0 ) semctl(semid,IPC_RMID,0);
	semid = semget(INETD_KEY + global_index,1,0600|IPC_CREAT);
	semctl(semid,0,SETVAL,1);
	sem_set(semid,CSERVER.max_conns-1);	
	msg_id = msgget(INETD_KEY + global_index,0);
	if ( msg_id >= 0 ) msgctl(msg_id,IPC_RMID,0);
	msg_id = msgget(INETD_KEY + global_index,IPC_CREAT | 0600);
	signal(SIGCHLD,SIG_IGN);
	if ( fork() == 0 ){
		server_reaper_process();
		exit(0);
	}
	{
		struct sigaction act;
		bzero(&act,sizeof(act));
		act.sa_sigaction = &server_reaper;
		act.sa_flags = SA_SIGINFO | SA_RESTART;
		sigaction(SIGCHLD,&act,NULL);
		// signal(SIGCHLD,server_reaper);
	}
	while ( 1 ){
		sem_lock(semid);
		if ( CSERVER.connections > CSERVER.max_conns ){
			logger(prefix,"Cannot  handle connection semaphore (Goint to accept %d/%d)\n",CSERVER.connections+1, CSERVER.max_conns);
			continue;
		}
		{
			int newsock;
			struct sockaddr from_addr;
			int from_addr_len;	
			if ( CSERVER.family == AF_INET )
				from_addr_len = sizeof(sock4);
			else	
				from_addr_len = sizeof(sock6);
			newsock = accept(sock,&from_addr,&from_addr_len);
			if ( newsock > 0 ){
				char ip_name[256];
				char ips_name[256];
				int  ip_port;
				int  ips_port;
				int pid;
				int i;
				if ( CSERVER.family == AF_INET ){
					struct sockaddr_in *s;	
					s = (struct sockaddr_in *)&from_addr;
					ip_port = ntohs(s->sin_port);
					sprintf(ip_name,"%s",inet_ntoa(s->sin_addr));
				} else {
					struct sockaddr_in6 *s;	
					s = (struct sockaddr_in6 *)&from_addr;
					ip_port = ntohs(s->sin6_port);
					inet_ntop(AF_INET6,&(s->sin6_addr),ip_name,256);	
				}
				logger(prefix,"New connection from: [%s:%d]\n",ip_name,ip_port);
				// Find slot :-)
				sem_lock(semid2);	
				for ( i = 0; i < MAX_CONNS; i++ ){
					if ( CSERVER.co[i].port == 0 ) break;
				}
				if ( i == MAX_CONNS ){ // We have to kick out the connection
					sem_unlock(semid2);	
					logger(prefix,"System-Limit reached (more than %d connections) --> closing connection\n",MAX_CONNS);
					close(newsock);
					continue;
				}
				CSERVER.co[i].sock      = newsock;
				CSERVER.co[i].port      = ip_port;
				CSERVER.co[i].created   = time(NULL);
				CSERVER.connections++;
				CSERVER.total_count++;
				if ( CSERVER.family == AF_INET ) {
					struct sockaddr_in _s;	
					struct sockaddr_in *s;	
					int s_len;
					s_len = sizeof(_s);
					getsockname(newsock,(struct sockaddr *)&_s,&s_len);
					s = (struct sockaddr_in *)&_s;
					ips_port = ntohs(s->sin_port);
					sprintf(ips_name,"%s",inet_ntoa(s->sin_addr));
				}
				if ( CSERVER.family == AF_INET6 ) {
					struct sockaddr_in6 _s;	
					struct sockaddr_in6 *s;	
					int s_len;
					s_len = sizeof(_s);
					getsockname(newsock,(struct sockaddr *)&_s,&s_len);
					s = (struct sockaddr_in6 *)&_s;
					ips_port = ntohs(s->sin6_port);
					inet_ntop(AF_INET6,&(s->sin6_addr),ips_name,256);	
				}
				strcpy(CSERVER.co[i].target,ips_name);
				CSERVER.co[i].t_port      = ips_port;
				strcpy(CSERVER.co[i].source,ip_name);
				sem_unlock(semid2);	
				pid = fork();
				if ( pid == 0 ){
					process_client(i);
					exit(0);
				} else {
					close(newsock);
					CSERVER.co[i].pid = pid;
				}
			} else {
				logger(prefix,"ACCEPT FAILED! (%s)\n",strerror(errno));
			}
			garbage_collect();
		}
		
	}

	exit(0);
}

void terminator(){
	int i,j;
	logger(prefix,"*** TERMINATOR Terminating all childs...\n");
	for ( i  = 0; i < entries; i++ ){
		for ( j = 0; j < MAX_CONNS; j++ ){
			if ( servlist[i].co[j].port != 0 && servlist[i].co[j].cpid != 0 ){ 
				m_kill(servlist[i].co[j].cpid,SIGTERM); 
				m_kill(servlist[i].co[j].cpid,SIGHUP); 
				m_kill(servlist[i].co[j].cpid,SIGKILL); 
				logger(prefix,"*** TERMINATOR Killed connection: [%s]:%d <--> [%s]:%d PID: %d\n",servlist[i].co[j].source,servlist[i].co[j].port, servlist[i].co[j].target, servlist[i].co[j].t_port, servlist[i].co[j].cpid);
				if ( servlist[i].co[j].pid != 0 ){
					m_kill(servlist[i].co[j].pid,SIGTERM); 
				}
			}
		}	
	}
	exit(0);
}


void main(int argc, char **argv){
        FILE *fp;
        char buf[1024];
	int idx;
	int i;
	int semmel;
	int tftp_pid;
	int dhcp_pid;
	int config_lines;

	ether_bcast[0] = 0xFF;
	ether_bcast[1] = 0xFF;
	ether_bcast[2] = 0xFF;
	ether_bcast[3] = 0xFF;
	ether_bcast[4] = 0xFF;
	ether_bcast[5] = 0xFF;
	
	if ( gethostname(my_hostname,1024) < 0 )strcpy(my_hostname,"unknown");



	mkdir("/big/GIX_INETD/logs",00777);
	mkdir("/big/GIX_INETD/conf",00777);
	mkdir("/big/GIX_INETD/run",00777);

	// Cleanup a little bit :-)
	for ( i = 0; i < 8192; i++ ){
		semmel = semget(INETD_KEY + i,1,0);
		if ( semmel >= 0 ) semctl(semmel,IPC_RMID,0);
		semmel = semget(INETD_KEY2 + i,1,0);
		if ( semmel >= 0 ) semctl(semmel,IPC_RMID,0);
		semmel = msgget(INETD_KEY + i,0);
		if ( semmel >= 0 ) msgctl(semmel,IPC_RMID,0);
	}
	semmel = shmget(INETD_KEY,0,0);
	if ( semmel >= 0 ) shmctl(semmel,IPC_RMID,0);

	semmel = shmget(INETD_OPTIONS,0,0);
	if ( semmel >= 0 ) shmctl(semmel,IPC_RMID,0);


	strcpy(prefix,"MAIN");

	logger(prefix,"Server starting at: [%s]...delaying for 4 seconds\n",my_hostname);
	sleep(4); // Wait a little bit...to avoid respawn
	logger(prefix,"Starting up now\n");

	if_count = get_interfaces(&if_config);
	for ( i = 0; i < if_count; i++ ){
		logger(prefix,"[%d] [%s] --> [%s]\n",i,if_config[i].ethname,if_config[i].addr);
	}
	
	
	shmid_options = shmget(INETD_OPTIONS,sizeof(struct gix_inetd_options),0600|IPC_CREAT);
	if ( shmid_options < 0 ){
		logger(prefix,"FATAL(%s:%d) Cannot allocate shared-memory\n",__FILE__,__LINE__);
		exit(0);
	}
	gix_options = (struct gix_inetd_options *)shmat(shmid_options,NULL,0);
	if ( gix_options == NULL ){
		logger(prefix,"FATAL(%s:%d) Cannot attach shared-memory\n",__FILE__,__LINE__);
		exit(0);
	}


        fp = fopen(CONFIG_FILE,"r");
        if ( fp == NULL ){
                logger(prefix,"%s: Cannot open '%s'\n",argv[0],CONFIG_FILE);
                exit(2);
        }
        entries = 0;
        while ( fgets(buf,1024,fp) != NULL ){
		if ( buf[0] == '[' ) continue;
		if ( strlen(buf) < 4 || buf[0] == '#' || buf[0] == ';' ) continue;
                entries++;
        }
        rewind(fp);
	shm_id = shmget(INETD_KEY,0,0);
	if ( shm_id >= 0 ){
		shmctl(shm_id,IPC_RMID,0);
	}
	shm_id = shmget(INETD_KEY,sizeof(struct server) * (entries *2),0600|IPC_CREAT);
	if ( shm_id < 0 ){
		logger(prefix,"FATAL(%s:%d) Cannot allocate shared-memory\n",__FILE__,__LINE__);
		exit(0);
	}
	servlist = (struct server *)shmat(shm_id,NULL,0);
	if ( servlist == NULL ){
		logger(prefix,"FATAL(%s:%d) Cannot attach shared-memory\n",__FILE__,__LINE__);
		exit(0);
	}
	bzero((void *)servlist,sizeof(struct server) * entries * 2);
	bzero((void *)gix_options,sizeof(struct gix_inetd_options));
	idx = 0;
	config_lines = 0;
	while ( fgets(buf,1024,fp) != NULL ){
		int port;
		int max_conns;
		int timeout;
		int data_timeout;
		char *ptr;
		char cmdline[1024];
		config_lines++;

		if ( strncmp(buf,"[DHCP=yes]",strlen("[DHCP=yes]")) == 0 ){
			gix_options->dhcp_enabled = 1;
			logger(prefix,"DHCP-->ENABLED\n");
			continue;
		}
		if ( strncmp(buf,"[DHCP_IP6_PORT_OUT=",strlen("[DHCP_IP6_PORT_OUT=")) == 0 ){
			char interface[256];
			int idx, i_index;
			int port;
			ptr = &buf[strlen("[DHCP_IP6_PORT_OUT=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			while ( *ptr && isspace(*ptr) ) ptr++;
			port = atoi(ptr);
			if ( port < 1 || port > 32767){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) Bad Port\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			gix_options->dhcp_interface[idx].ip6_port_out = (unsigned short) port;
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->IP6_PORT_OUT Interface: [%s](%d), PORT: [%d] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,port,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP6_PORT_IN=",strlen("[DHCP_IP6_PORT_IN=")) == 0 ){
			char interface[256];
			int idx, i_index;
			int port;
			ptr = &buf[strlen("[DHCP_IP6_PORT_IN=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			while ( *ptr && isspace(*ptr) ) ptr++;
			port = atoi(ptr);
			if ( port < 1 || port > 32767){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) Bad Port\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			gix_options->dhcp_interface[idx].ip6_port_in = (unsigned short) port;
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->IP6_PORT_IN Interface: [%s](%d), PORT: [%d] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,port,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP_PORT_OUT=",strlen("[DHCP_IP_PORT_OUT=")) == 0 ){
			char interface[256];
			int idx, i_index;
			int port;
			ptr = &buf[strlen("[DHCP_IP_PORT_OUT=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			while ( *ptr && isspace(*ptr) ) ptr++;
			port = atoi(ptr);
			if ( port < 1 || port > 32767){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) Bad Port\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			gix_options->dhcp_interface[idx].ip_port_out = (unsigned short) port;
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->IP_PORT_OUT Interface: [%s](%d), PORT: [%d] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,port,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP_PORT_IN=",strlen("[DHCP_IP_PORT_IN=")) == 0 ){
			char interface[256];
			int idx, i_index;
			int port;
			ptr = &buf[strlen("[DHCP_IP_PORT_IN=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			while ( *ptr && isspace(*ptr) ) ptr++;
			port = atoi(ptr);
			if ( port < 1 || port > 32767){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) Bad Port\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			gix_options->dhcp_interface[idx].ip_port_in = (unsigned short) port;
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->IP_PORT_IN Interface: [%s](%d), PORT: [%d] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,port,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP_NETMASK=",strlen("[DHCP_IP_NETMASK=")) == 0 ){
			char interface[256];
			int idx, i_index;
			char domain[256];
			ptr = &buf[strlen("[DHCP_IP_NETMASK=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			while ( *ptr && isspace(*ptr) ) ptr++;
			strcpy(domain,ptr);
			ptr = &domain[strlen(domain)-1];
			while ( ptr > domain &&  ( *ptr == '\r' || *ptr == '\n' || isspace(*ptr) || *ptr == ']' )) ptr--;
			ptr++;
			*ptr = '\0';
			if ( strlen(domain) < 3 ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) Bad NETMASK\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			strcpy(gix_options->dhcp_interface[idx].ip_netmask,domain);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->NETMASK Interface: [%s](%d), NETMASK: [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,domain,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP6_NETMASK=",strlen("[DHCP_IP6_NETMASK=")) == 0 ){
			char interface[256];
			int idx, i_index;
			char domain[256];
			ptr = &buf[strlen("[DHCP_IP6_NETMASK=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			while ( *ptr && isspace(*ptr) ) ptr++;
			strcpy(domain,ptr);
			ptr = &domain[strlen(domain)-1];
			while ( ptr > domain &&  ( *ptr == '\r' || *ptr == '\n' || isspace(*ptr) || *ptr == ']' )) ptr--;
			ptr++;
			*ptr = '\0';
			if ( strlen(domain) < 3 ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) Bad NETMASK\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			strcpy(gix_options->dhcp_interface[idx].ip6_netmask,domain);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->NETMASK6 Interface: [%s](%d), NETMASK: [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,domain,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP6_DOMAIN=",strlen("[DHCP_IP6_DOMAIN=")) == 0 ){
			char interface[256];
			int idx, i_index;
			char domain[256];
			ptr = &buf[strlen("[DHCP_IP6_DOMAIN=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			while ( *ptr && isspace(*ptr) ) ptr++;
			strcpy(domain,ptr);
			ptr = &domain[strlen(domain)-1];
			while ( ptr > domain &&  ( *ptr == '\r' || *ptr == '\n' || isspace(*ptr) || *ptr == ']' )) ptr--;
			ptr++;
			*ptr = '\0';
			if ( strlen(domain) < 3 ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) Bad domain\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			strcpy(gix_options->dhcp_interface[idx].ip6_domain,domain);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->DOMAIN6 Interface: [%s](%d), Domain: [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,domain,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP_DOMAIN=",strlen("[DHCP_IP_DOMAIN=")) == 0 ){
			char interface[256];
			int idx, i_index;
			char domain[256];
			ptr = &buf[strlen("[DHCP_IP_DOMAIN=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			while ( *ptr && isspace(*ptr) ) ptr++;
			strcpy(domain,ptr);
			ptr = &domain[strlen(domain)-1];
			while ( ptr > domain &&  ( *ptr == '\r' || *ptr == '\n' || isspace(*ptr) || *ptr == ']' )) ptr--;
			ptr++;
			*ptr = '\0';
			if ( strlen(domain) < 3 ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) Bad domain\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			strcpy(gix_options->dhcp_interface[idx].ip_domain,domain);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->DOMAIN Interface: [%s](%d), Domain: [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,domain,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_LEASE_TIME=",strlen("[DHCP_LEASE_TIME=")) == 0 ){
			char interface[256];
			int idx, i_index;
			time_t leasetime;
			ptr = &buf[strlen("[DHCP_IP6_ROUTER=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			leasetime = atoi(ptr);
			if ( leasetime == 0 ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) Bad lease time...ignoring\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			gix_options->dhcp_interface[idx].leasetime = leasetime;
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->Lease-Time Interface: [%s](%d), Lease-Time: [%ld] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,leasetime,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP6_ROUTER=",strlen("[DHCP_IP6_ROUTER=")) == 0 ){
			char interface[256];
			int i_index;
			struct sockaddr_in6 *retaddr;
			char ip[64];
			int idx;
			ptr = &buf[strlen("[DHCP_IP6_ROUTER=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			strcpy(ip,ptr);
			ptr = ip;
			while ( *ptr && (*ptr == ':' || ( *ptr >= '0' && *ptr <= '9' ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) )ptr++;
			*ptr = '\0';
			if ( (retaddr = check_valid_ipv6(ip,DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv6 address\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			memcpy(&(gix_options->dhcp_interface[idx].ip6_router),retaddr,sizeof(struct sockaddr_in6));
			inet_ntop(AF_INET6,&(gix_options->dhcp_interface[idx].ip6_router.sin6_addr),ip,64);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->Router6 Interface: [%s](%d), IP: [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,ip,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP6_ME=",strlen("[DHCP_IP6_ME=")) == 0 ){
			char interface[256];
			int i_index;
			struct sockaddr_in6 *retaddr;
			char ip[64];
			int idx;
			ptr = &buf[strlen("[DHCP_IP6_ME=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			strcpy(ip,ptr);
			ptr = ip;
			while ( *ptr && (*ptr == ':' || ( *ptr >= '0' && *ptr <= '9' ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) )ptr++;
			*ptr = '\0';
			if ( (retaddr = check_valid_ipv6(ip,DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv6 address\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			memcpy(&(gix_options->dhcp_interface[idx].ip6_me),retaddr,sizeof(struct sockaddr_in6));
			inet_ntop(AF_INET6,&(gix_options->dhcp_interface[idx].ip6_me.sin6_addr),ip,64);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->ME6 Interface: [%s](%d), IP: [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,ip,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP_DNS=",strlen("[DHCP_IP_DNS=")) == 0 ){
			int i_index;
			char interface[256];
			struct sockaddr_in *retaddr;
			struct sockaddr_in a_ip[MAX_DHCP_DNS_SERVERS];
			char ip[MAX_DHCP_DNS_SERVERS][64];
			char ip_help[64];
			char nslist[1024];
			int idx;
			int dns_idx;

			ptr = &buf[strlen("[DHCP_IP_DNS=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for (dns_idx = 0; dns_idx < MAX_DHCP_DNS_SERVERS; dns_idx++ ){
				strcpy(ip[dns_idx],ptr);
				ptr = ip[dns_idx];
				while ( *ptr && (*ptr == '.' || ( *ptr >= '0' && *ptr <= '9' )) )ptr++;
				*ptr = '\0';
				if ( (retaddr = check_valid_ipv4(ip[dns_idx],DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ) break;
				memcpy(&(a_ip[dns_idx]),retaddr,sizeof(struct sockaddr_in));
				ptr++;
				while ( *ptr && isspace(*ptr) ) ptr++;
			}
			if ( dns_idx == 0 ){
				logger(prefix,"WARNING: You must specify at least 1 nameserver for this interface\n");
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			gix_options->dhcp_interface[idx].ip_nameservers = dns_idx;
			strcpy(nslist,"");
			for ( dns_idx = 0; dns_idx < gix_options->dhcp_interface[idx].ip_nameservers; dns_idx++ ){
				memcpy(&(gix_options->dhcp_interface[idx].ip_nameserver[dns_idx]),&a_ip[dns_idx],sizeof(struct sockaddr_in));
				inet_ntop(AF_INET,&(gix_options->dhcp_interface[idx].ip_nameserver[dns_idx].sin_addr),ip_help,64);
				strcat(nslist,ip_help);
				strcat(nslist,",");
			}
			if ( strlen(nslist) && nslist[strlen(nslist)-1] == ',' ) nslist[strlen(nslist)-1] = '\0';
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->DNS Interface: [%s](%d), Count: %d [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,dns_idx,nslist,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP6_DNS=",strlen("[DHCP_IP6_DNS=")) == 0 ){
			int i_index;
			char interface[256];
			struct sockaddr_in6 *retaddr;
			struct sockaddr_in6 a_ip[MAX_DHCP_DNS_SERVERS];
			char ip[MAX_DHCP_DNS_SERVERS][64];
			char ip_help[64];
			char nslist[1024];
			int idx;
			int dns_idx;

			ptr = &buf[strlen("[DHCP_IP6_DNS=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for (dns_idx = 0; dns_idx < MAX_DHCP_DNS_SERVERS; dns_idx++ ){
				strcpy(ip[dns_idx],ptr);
				ptr = ip[dns_idx];
				while ( *ptr && (*ptr == ':' || ( *ptr >= '0' && *ptr <= '9' ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) )ptr++;
				*ptr = '\0';
				if ( (retaddr = check_valid_ipv6(ip[dns_idx],DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ) break;
				memcpy(&(a_ip[dns_idx]),retaddr,sizeof(struct sockaddr_in6));
				ptr++;
				while ( *ptr && isspace(*ptr) ) ptr++;
			}
			if ( dns_idx == 0 ){
				logger(prefix,"WARNING: You must specify at least 1 nameserver for this interface\n");
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			gix_options->dhcp_interface[idx].ip6_nameservers = dns_idx;
			strcpy(nslist,"");
			for ( dns_idx = 0; dns_idx < gix_options->dhcp_interface[idx].ip6_nameservers; dns_idx++ ){
				memcpy(&(gix_options->dhcp_interface[idx].ip6_nameserver[dns_idx]),&a_ip[dns_idx],sizeof(struct sockaddr_in6));
				inet_ntop(AF_INET6,&(gix_options->dhcp_interface[idx].ip6_nameserver[dns_idx].sin6_addr),ip_help,64);
				strcat(nslist,ip_help);
				strcat(nslist,",");
			}
			if ( strlen(nslist) && nslist[strlen(nslist)-1] == ',' ) nslist[strlen(nslist)-1] = '\0';
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->DNS6 Interface: [%s](%d), Count: %d [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,dns_idx,nslist,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP6_MAC=",strlen("[DHCP_IP6_MAC=")) == 0 ){
			char mac_addr[64];
			char ip_addr[128];
			struct ether_addr eth_raw; 
			int idx;
			struct sockaddr_in6 *ret_addr;
			char boot_image[512];
			ptr = &buf[strlen("[DHCP_IP6_MAC=")];
			strcpy(mac_addr,ptr);
			ptr = mac_addr;
			while ( *ptr && ( *ptr == ':' || ( *ptr >= '0' && *ptr <= '9' ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) ){ *ptr = toupper(*ptr); ptr++; }
			*ptr = '\0';
			ptr++;

			if ( sscanf(mac_addr,"%02X:%02X:%02X:%02X:%02X:%02X", &(eth_raw.ether_addr_octet[0]), &(eth_raw.ether_addr_octet[1]), &(eth_raw.ether_addr_octet[2]), &(eth_raw.ether_addr_octet[3]), &(eth_raw.ether_addr_octet[4]), &(eth_raw.ether_addr_octet[5])) != 6 ){
				logger(prefix,"WARNING: Syntax error in line %d (invalid MAC address)\n",config_lines);
				continue;
			}
			
			while ( *ptr && isspace(*ptr) ) ptr++;
			strcpy(ip_addr,ptr);
			ptr = ip_addr;
			while ( *ptr && (*ptr == ':' || ( *ptr >= '0' && *ptr <= '9' ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) )ptr++;
			*ptr = '\0';
			ptr++;
			if ( (ret_addr = check_valid_ipv6(ip_addr,DHCP_DEFAULT_PORT_OUT,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax error in line %d (invalid IPv6 address)\n",config_lines);
				continue;
			}
			while ( *ptr && isspace(*ptr) ) ptr++;
			strcpy(boot_image,ptr);
			ptr = boot_image;
			while ( *ptr && ( !isspace(*ptr) && *ptr != ']' && *ptr != '\r' && *ptr != '\n' ) )ptr++;
			*ptr = '\0';
			for ( idx = 0; idx < gix_options->dhcp_hosts; idx++ ){
				if ( memcmp(&gix_options->dhcp_host[idx].mac,&eth_raw,sizeof(struct ether_addr)) == 0 ) break;
			}
			if ( idx >= MAX_DHCP_HOSTS ){
				logger(prefix,"FATAL: Too many DHCP-Hosts defined (Max: %d)\n",MAX_DHCP_HOSTS);
				continue;
			}			
			if ( idx == gix_options->dhcp_hosts ){
				memcpy(&(gix_options->dhcp_host[idx].mac),&eth_raw,sizeof(struct ether_addr));
				gix_options->dhcp_hosts++;
			}
			memcpy(&gix_options->dhcp_host[idx].ip6_addr,ret_addr,sizeof(struct sockaddr_in6));
			if ( strlen(boot_image) ) strcpy(gix_options->dhcp_host[idx].bootfile,boot_image); // Do not overwrite, if already specified 
			inet_ntop(AF_INET6,&(gix_options->dhcp_host[idx].ip6_addr.sin6_addr),ip_addr,128);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->IP6_MAC: [%02X:%02X:%02X:%02X:%02X:%02X] IP: [%s] BOOT-FILE: [%s](%d Bytes) [%d/%d]\n",
				gix_options->dhcp_host[idx].mac.ether_addr_octet[0], gix_options->dhcp_host[idx].mac.ether_addr_octet[1], gix_options->dhcp_host[idx].mac.ether_addr_octet[2],
				gix_options->dhcp_host[idx].mac.ether_addr_octet[3], gix_options->dhcp_host[idx].mac.ether_addr_octet[4], gix_options->dhcp_host[idx].mac.ether_addr_octet[5],
				ip_addr,gix_options->dhcp_host[idx].bootfile,strlen(gix_options->dhcp_host[idx].bootfile),idx,gix_options->dhcp_hosts);
#endif
			continue;	
		}
		if ( strncmp(buf,"[DHCP_IP_MAC=",strlen("[DHCP_IP_MAC=")) == 0 ){
			char mac_addr[64];
			char ip_addr[128];
			struct ether_addr eth_raw; 
			int idx;
			struct sockaddr_in *ret_addr;
			char boot_image[512];
			ptr = &buf[strlen("[DHCP_IP_MAC=")];
			strcpy(mac_addr,ptr);
			ptr = mac_addr;
			while ( *ptr && ( *ptr == ':' || ( *ptr >= '0' && *ptr <= '9' ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) ){ *ptr = toupper(*ptr); ptr++; }
			*ptr = '\0';
			ptr++;

			if ( sscanf(mac_addr,"%02X:%02X:%02X:%02X:%02X:%02X", &(eth_raw.ether_addr_octet[0]), &(eth_raw.ether_addr_octet[1]), &(eth_raw.ether_addr_octet[2]), &(eth_raw.ether_addr_octet[3]), &(eth_raw.ether_addr_octet[4]), &(eth_raw.ether_addr_octet[5])) != 6 ){
				logger(prefix,"WARNING: Syntax error in line %d (invalid MAC address)\n",config_lines);
				continue;
			}
			
			while ( *ptr && isspace(*ptr) ) ptr++;
			strcpy(ip_addr,ptr);
			ptr = ip_addr;
			while ( *ptr && ( *ptr == '.' || ( *ptr >= '0' && *ptr <= '9' ) )  ) ptr++;
			*ptr = '\0';
			ptr++;
			if ( (ret_addr = check_valid_ipv4(ip_addr,DHCP_DEFAULT_PORT_OUT,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax error in line %d (invalid IPv4 address)\n",config_lines);
				continue;
			}
			while ( *ptr && isspace(*ptr) ) ptr++;
			strcpy(boot_image,ptr);
			ptr = boot_image;
			while ( *ptr && ( !isspace(*ptr) && *ptr != ']' && *ptr != '\r' && *ptr != '\n' ) )ptr++;
			*ptr = '\0';
			for ( idx = 0; idx < gix_options->dhcp_hosts; idx++ ){
				if ( memcmp(&gix_options->dhcp_host[idx].mac,&eth_raw,sizeof(struct ether_addr)) == 0 ) break;
			}
			if ( idx >= MAX_DHCP_HOSTS ){
				logger(prefix,"FATAL: Too many DHCP-Hosts defined (Max: %d)\n",MAX_DHCP_HOSTS);
				continue;
			}			
			if ( idx == gix_options->dhcp_hosts ){
				memcpy(&(gix_options->dhcp_host[idx].mac),&eth_raw,sizeof(struct ether_addr));
				gix_options->dhcp_hosts++;
			}
			memcpy(&gix_options->dhcp_host[idx].ip_addr,ret_addr,sizeof(struct sockaddr_in));
			if ( strlen(boot_image) ) strcpy(gix_options->dhcp_host[idx].bootfile,boot_image); // Do not overwrite, if already specified 
			inet_ntop(AF_INET,&(gix_options->dhcp_host[idx].ip_addr.sin_addr),ip_addr,128);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->IP_MAC: [%02X:%02X:%02X:%02X:%02X:%02X] IP: [%s] BOOT-FILE: [%s](%d Bytes) [%d/%d]\n",
				gix_options->dhcp_host[idx].mac.ether_addr_octet[0], gix_options->dhcp_host[idx].mac.ether_addr_octet[1], gix_options->dhcp_host[idx].mac.ether_addr_octet[2],
				gix_options->dhcp_host[idx].mac.ether_addr_octet[3], gix_options->dhcp_host[idx].mac.ether_addr_octet[4], gix_options->dhcp_host[idx].mac.ether_addr_octet[5],
				ip_addr,gix_options->dhcp_host[idx].bootfile,strlen(gix_options->dhcp_host[idx].bootfile),idx,gix_options->dhcp_hosts);
#endif
			continue;	
		}
		if ( strncmp(buf,"[DHCP_BOOTIMAGE=",strlen("[DHCP_BOOTIMAGE=")) == 0 ){
			char image_name[1024];
			char class_id[1024];
			ptr = &buf[strlen("[DHCP_BOOTIMAGE=")];
			strcpy(image_name,ptr);
			ptr = image_name;
			while ( *ptr && !isspace(*ptr) && *ptr != ']' )ptr++;
			*ptr = '\0';
			ptr++;		
			while ( *ptr && isspace(*ptr) )ptr++;
			strcpy(class_id,ptr);
			ptr = &class_id[strlen(class_id)-1];
			while ( ptr > class_id && ( *ptr == '\r' ||  *ptr == '\n' || *ptr == ']' ) )ptr--;
			ptr++;
			*ptr = '\0';
			if ( gix_options->dhcp_bootfiles >= MAX_DHCP_BOOTFILES ){
				logger(prefix,"WARNING: A maximum of %d DHCP-Bootfiles is allowed!\n",MAX_DHCP_BOOTFILES);
				continue;
			}
			strcpy(gix_options->dhcp_bootfile[gix_options->dhcp_bootfiles].bootimage,image_name);
			strcpy(gix_options->dhcp_bootfile[gix_options->dhcp_bootfiles].class_id,class_id);
			if ( strlen(class_id) == 0 ){
				gix_options->dhcp_bootfile[gix_options->dhcp_bootfiles].def = 1;
			} else {
				gix_options->dhcp_bootfile[gix_options->dhcp_bootfiles].def = 0;
			}
			gix_options->dhcp_bootfiles++;
			
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->BOOTIMAGE [%s](%d Bytes) CLASS-ID: [%s](%d Bytes) Index: %d Default: [%s]\n",image_name,strlen(image_name),class_id,strlen(class_id),gix_options->dhcp_bootfiles-1, gix_options->dhcp_bootfile[gix_options->dhcp_bootfiles-1].def == 1 ? "YES" : "NO");
#endif
			
			continue;
		}
		if ( strncmp(buf,"[DHCP_IP6_RANGE=",strlen("[DHCP_IP6_RANGE=")) == 0 ){
			int i_index;
			char interface[256];
			struct sockaddr_in6 *retaddr;
			struct sockaddr_in6 a_ip1;
			struct sockaddr_in6 a_ip2;
			char ip1[64];
			char ip2[64];
			int idx;
			ptr = &buf[strlen("[DHCP_IP6_RANGE=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			strcpy(ip1,ptr);
			ptr = ip1;
			while ( *ptr && (*ptr == ':' || ( *ptr >= '0' && *ptr <= '9' ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) )ptr++;
			*ptr = '\0';
			ptr++;
			if ( (retaddr = check_valid_ipv6(ip1,DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv6 address\n",config_lines);
				continue;
			}
			memcpy(&a_ip1,retaddr,sizeof(struct sockaddr_in6));
			while ( *ptr && isspace(*ptr) ) ptr++;
			if ( !*ptr ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv6 address\n",config_lines);
				continue;
			}
			strcpy(ip2,ptr);
			ptr = ip2;
			while ( *ptr && (*ptr == ':' || ( *ptr >= '0' && *ptr <= '9' ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) )ptr++;
			*ptr = '\0';
			if ( (retaddr = check_valid_ipv6(ip2,DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv6 address\n",config_lines);
				continue;
			}
			memcpy(&a_ip2,retaddr,sizeof(struct sockaddr_in6));

			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			memcpy(&(gix_options->dhcp_interface[idx].ip6_range_start),&a_ip1,sizeof(struct sockaddr_in6));
			memcpy(&(gix_options->dhcp_interface[idx].ip6_range_end),&a_ip2,sizeof(struct sockaddr_in6));
			inet_ntop(AF_INET6,&(gix_options->dhcp_interface[idx].ip6_range_start.sin6_addr),ip1,64);
			inet_ntop(AF_INET6,&(gix_options->dhcp_interface[idx].ip6_range_end.sin6_addr),ip2,64);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->RANGE6 Interface: [%s](%d), IP: [%s - %s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,ip1,ip2,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP_RANGE=",strlen("[DHCP_IP_RANGE=")) == 0 ){
			int i_index;
			char interface[256];
			struct sockaddr_in *retaddr;
			struct sockaddr_in a_ip1;
			struct sockaddr_in a_ip2;
			char ip1[64];
			char ip2[64];
			int idx;
			ptr = &buf[strlen("[DHCP_IP_RANGE=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			strcpy(ip1,ptr);
			ptr = ip1;
			while ( *ptr && (*ptr == '.' || ( *ptr >= '0' && *ptr <= '9' )) )ptr++;
			*ptr = '\0';
			ptr++;
			if ( (retaddr = check_valid_ipv4(ip1,DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv4 address\n",config_lines);
				continue;
			}
			memcpy(&a_ip1,retaddr,sizeof(struct sockaddr_in));
			while ( *ptr && isspace(*ptr) ) ptr++;
			if ( !*ptr ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv4 address\n",config_lines);
				continue;
			}
			strcpy(ip2,ptr);
			ptr = ip2;
			while ( *ptr && (*ptr == '.' || ( *ptr >= '0' && *ptr <= '9' )) )ptr++;
			*ptr = '\0';
			if ( (retaddr = check_valid_ipv4(ip2,DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv4 address\n",config_lines);
				continue;
			}
			memcpy(&a_ip2,retaddr,sizeof(struct sockaddr_in));

			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			memcpy(&(gix_options->dhcp_interface[idx].ip_range_start),&a_ip1,sizeof(struct sockaddr_in));
			memcpy(&(gix_options->dhcp_interface[idx].ip_range_end),&a_ip2,sizeof(struct sockaddr_in));
			inet_ntop(AF_INET,&(gix_options->dhcp_interface[idx].ip_range_start.sin_addr),ip1,64);
			inet_ntop(AF_INET,&(gix_options->dhcp_interface[idx].ip_range_end.sin_addr),ip2,64);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->RANGE Interface: [%s](%d), IP: [%s - %s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,ip1,ip2,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP_ME=",strlen("[DHCP_IP_ME=")) == 0 ){
			int i_index;
			char interface[256];
			struct sockaddr_in *retaddr;
			char ip[64];
			int idx;
			ptr = &buf[strlen("[DHCP_IP_ME=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			strcpy(ip,ptr);
			ptr = ip;
			while ( *ptr && (*ptr == '.' || ( *ptr >= '0' && *ptr <= '9' )) )ptr++;
			*ptr = '\0';
			if ( (retaddr = check_valid_ipv4(ip,DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv4 address\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			memcpy(&(gix_options->dhcp_interface[idx].ip_me),retaddr,sizeof(struct sockaddr_in));
			inet_ntop(AF_INET,&(gix_options->dhcp_interface[idx].ip_me.sin_addr),ip,64);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->ME Interface: [%s](%d), IP: [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,ip,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}
		if ( strncmp(buf,"[DHCP_IP_ROUTER=",strlen("[DHCP_IP_ROUTER=")) == 0 ){
			int i_index;
			char interface[256];
			struct sockaddr_in *retaddr;
			char ip[64];
			int idx;
			ptr = &buf[strlen("[DHCP_IP_ROUTER=")];
			strcpy(interface,ptr);
			ptr = interface;
			while ( *ptr && *ptr != ':' ) ptr++;
			if ( *ptr != ':' ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d)\n",config_lines);
				continue;
			}
			*ptr = '\0';
			ptr++;
			strcpy(ip,ptr);
			ptr = ip;
			while ( *ptr && (*ptr == '.' || ( *ptr >= '0' && *ptr <= '9' )) )ptr++;
			*ptr = '\0';
			if ( (retaddr = check_valid_ipv4(ip,DHCP_DEFAULT_PORT_IN,SOCK_DGRAM)) == NULL ){
				logger(prefix,"WARNING: Syntax Error in config-file (Line: %d) --> Invalid IPv4 address\n",config_lines);
				continue;
			}
			for ( i_index = 0; i_index < if_count; i_index++ ){
				if ( strcmp(interface,if_config[i_index].ethname) == 0 ) break;
			}
			if ( i_index == if_count ){
				logger(prefix,"FATAL: Interface [%s] does not exist!\n",interface);
				continue;
			}
			for ( idx = 0; idx < gix_options->dhcp_interfaces && idx < MAX_DHCP_INTERFACES; idx++ ){
				if ( gix_options->dhcp_interface[idx].index == i_index ) break;
			}
			if ( idx >= MAX_DHCP_INTERFACES ){
				logger(prefix,"WARNING: Error in config-file (Line: %d) --> Too many interfaces defined (Max: %d)n",config_lines,MAX_DHCP_INTERFACES);
				continue;
			}
			if ( idx == gix_options->dhcp_interfaces ){
				gix_options->dhcp_interface[idx].index = i_index;
				init_defaults_dhcp(&gix_options->dhcp_interface[idx]);
				gix_options->dhcp_interfaces++;
			} 
			memcpy(&(gix_options->dhcp_interface[idx].ip_router),retaddr,sizeof(struct sockaddr_in));
			inet_ntop(AF_INET,&(gix_options->dhcp_interface[idx].ip_router.sin_addr),ip,64);
#ifdef DEBUG_DHCP
			logger(prefix,"DHCP->Router Interface: [%s](%d), IP: [%s] Interface-Index: [%d/%d]\n",if_config[i_index].ethname,i_index,ip,idx,gix_options->dhcp_interfaces);
#endif
			continue;
		
		}

		if ( strncmp(buf,"[TFTP=yes]",strlen("[TFTP=yes]")) == 0 ){
			gix_options->tftp_enabled = 1;
			gix_options->tftp_port = 69;
			if ( strlen(gix_options->tftp_root) == 0 ){
				strcpy(gix_options->tftp_root,"/TFTP");
			}
			logger(prefix,"TFTP-->ENABLED\n");
			continue;
		}
		if ( strncmp(buf,"[TFTP_DIR=",strlen("[TFTP_DIR=")) == 0 ){
			char *ptr;
			strcpy(gix_options->tftp_root,&buf[strlen("[TFTP_DIR=")]);
			ptr = gix_options->tftp_root;
			while ( *ptr ){
				if ( *ptr == ']' ){ *ptr = '\0'; break; }
				ptr++;
			}	
		}
		if ( strncmp(buf,"[TFTP_READONLY=yes]",strlen("[TFTP_READONLY=yes]")) == 0 ){
			gix_options->tftp_readonly = 1;
			continue;
		}
		if ( strncmp(buf,"[TFTP_READONLY=no]",strlen("[TFTP_READONLY=no]")) == 0 ){
			gix_options->tftp_readonly = 0;
			continue;
		}

		if ( strlen(buf) < 4 || buf[0] == '#' || buf[0] == ';' ) continue;
		port = atoi(buf);
		ptr = buf;
		while ( *ptr && *ptr != ' ' && *ptr != '\t' ) ptr++;
		if ( *ptr == '\0' ) continue;

		while ( *ptr && ( *ptr == ' ' ||  *ptr == '\t' ) ) ptr++;
		if ( *ptr == '\0' ) continue;
		max_conns = atoi(ptr);

		while ( *ptr && *ptr != ' ' && *ptr != '\t' ) ptr++;
		if ( *ptr == '\0' ) continue;

		while ( *ptr && ( *ptr == ' ' ||  *ptr == '\t' ) ) ptr++;
		if ( *ptr == '\0' ) continue;

		timeout = atoi(ptr);
		while ( *ptr && *ptr != ' ' && *ptr != '\t' ) ptr++;
		if ( *ptr == '\0' ) continue;

		while ( *ptr && ( *ptr == ' ' ||  *ptr == '\t' ) ) ptr++;
		if ( *ptr == '\0' ) continue;

		data_timeout = atoi(ptr);
		while ( *ptr && *ptr != ' ' && *ptr != '\t' ) ptr++;
		if ( *ptr == '\0' ) continue;
		while ( *ptr && ( *ptr == ' ' ||  *ptr == '\t' ) ) ptr++;
		if ( *ptr == '\0' ) continue;
		strcpy(cmdline,ptr);

		if ( strlen(cmdline) < 2 ) continue;
		if ( cmdline[strlen(cmdline)-1] == '\r' || cmdline[strlen(cmdline)-1] == '\n' ) cmdline[strlen(cmdline)-1] = '\0';
		if ( cmdline[strlen(cmdline)-1] == '\r' || cmdline[strlen(cmdline)-1] == '\n' ) cmdline[strlen(cmdline)-1] = '\0';
		if ( max_conns <= 0 ) max_conns = MAX_CONNS;
		logger("MAIN","[%d] Port: %d, Max-Connections: %d, Timeout: %d, Data-Timeout: %d, Command: [%s]\n",idx,port,max_conns,timeout,data_timeout,cmdline);
		servlist[idx].port = port;
		servlist[idx].max_conns = max_conns;			
		servlist[idx].timeout = timeout;			
		servlist[idx].data_timeout = data_timeout;			
		servlist[idx].family = AF_INET;
		servlist[idx].reset = time(NULL);
		strcpy(servlist[idx].cmdline,cmdline);
		idx++;
		servlist[idx].port = port;
		servlist[idx].max_conns = max_conns;			
		servlist[idx].timeout = timeout;			
		servlist[idx].data_timeout = data_timeout;			
		servlist[idx].family = AF_INET6;
		servlist[idx].reset = time(NULL);
		strcpy(servlist[idx].cmdline,cmdline);
		idx++;
	}
        fclose(fp);
	entries = idx;
        logger(prefix,"Starting servers with %d entries\n",entries);
	logger(prefix,"TFTP-Enabled: %d, TFTP-Root-PATH: [%s], TFTP-READONLY: %d\n",gix_options->tftp_enabled, gix_options->tftp_root, gix_options->tftp_readonly);
	signal(SIGCHLD,SIG_IGN);
	for ( i = 0; i < idx; i++ ){
		int pid;
		if ( (pid = fork()) == 0 ){
			start_server(i);
			exit(0);
		} else {
			servlist[i].pid = pid;
		}
	}
	signal(SIGTERM,terminator);
	tftp_pid = 0;
	dhcp_pid = 0;
	while(1){ 
		int status;
		sleep(1);
		if ( gix_options->dhcp_enabled == 1 && gix_options->dhcp_pid == 0 ){
			if ( (dhcp_pid = fork()) == 0 ){
				start_dhcp();
				exit(0);
			} 
			gix_options->dhcp_pid = dhcp_pid;
			logger(prefix,"DHCP-SERVER Started (PID: %d)\n",dhcp_pid);
		}
		if ( dhcp_pid && waitpid(dhcp_pid,&status,WNOHANG) == dhcp_pid ){
			if ( gix_options->dhcp_enabled == 1 ) logger(prefix,"DHCP-SERVER[W] died unexpected...will be restarted soon\n");
			if ( gix_options->dhcp_enabled == 0 ) logger(prefix,"DHCP-SERVER[W] turned off\n");
			gix_options->dhcp_pid = 0;
			dhcp_pid = 0;
			
		}
		if ( dhcp_pid && kill(dhcp_pid,0) ){
			if ( gix_options->dhcp_enabled == 1 ) logger(prefix,"DHCP-SERVER died unexpected...will be restarted soon\n");
			if ( gix_options->dhcp_enabled == 0 ) logger(prefix,"DHCP-SERVER turned off\n");
			gix_options->dhcp_pid = 0;
			dhcp_pid = 0;
		}

		if ( gix_options->tftp_enabled == 1 && gix_options->tftp_pid == 0 ){
			if ( (tftp_pid = fork()) == 0 ){
				start_tftp();
				exit(0);
			} 
			gix_options->tftp_pid = tftp_pid;
			logger(prefix,"TFTP-SERVER Started (PID: %d)\n",tftp_pid);
		}
		if ( tftp_pid && waitpid(tftp_pid,&status,WNOHANG) == tftp_pid ){
			if ( gix_options->tftp_enabled == 1 ) logger(prefix,"TFTP-SERVER[W] died unexpected...will be restarted soon\n");
			if ( gix_options->tftp_enabled == 0 ) logger(prefix,"TFTP-SERVER[W] turned off\n");
			gix_options->tftp_pid = 0;
			tftp_pid = 0;
			
		}
		if ( tftp_pid && kill(tftp_pid,0) ){
			if ( gix_options->tftp_enabled == 1 ) logger(prefix,"TFTP-SERVER died unexpected...will be restarted soon\n");
			if ( gix_options->tftp_enabled == 0 ) logger(prefix,"TFTP-SERVER turned off\n");
			gix_options->tftp_pid = 0;
			tftp_pid = 0;
		}
	}
}


void process_tftp_packet(int socket, unsigned char *data, int len, char *ipname, int port, struct sockaddr *addrinfo, int addr_len);
void process_data_packet(int slot, int sock, struct sockaddr *addr, int addr_len);


void start_tftp(){
	int s4, s6;
	int on;
	struct sockaddr *saddr6;
	struct sockaddr *saddr4;
	int saddr6_len;
	int saddr4_len;
	struct sockaddr_in sock4;
	struct sockaddr_in6 sock6;
	struct pollfd polly[MAX_TFTP_SESSIONS+3];
	int fdcnt;

	sprintf(prefix,"TFTPSERVER");
	logger(prefix,"TFTP-Server starting!\n");	
	gix_options = (struct gix_inetd_options *)shmat(shmid_options,NULL,0);
	if ( gix_options == NULL ){
		logger(prefix,"FATAL(%s:%d) Cannot attach shared-memory\n",__FILE__,__LINE__);
		exit(0);
	}
	bzero((void *)gix_options->tr,sizeof(struct tftp_request) * MAX_TFTP_SESSIONS);

	s4 = socket(AF_INET,SOCK_DGRAM,0);
	if ( s4 < 0 ){
		logger(prefix,"FATAL(%s:%d) Cannot create socket!\n",__FILE__,__LINE__);
		exit(0);
	}	
	s6 = socket(AF_INET6,SOCK_DGRAM,0);
	if ( s6 < 0 ){
		logger(prefix,"FATAL(%s:%d) Cannot create socket!\n",__FILE__,__LINE__);
		exit(0);
	}	

	on = 1;
	if ( setsockopt(s6,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) < 0 ){
		logger	(prefix,"FATAL(%s:%d) Cannot SO_REUSEADDR socket\n",__FILE__,__LINE__);
		exit(3);
	}
	if ( setsockopt(s4,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) < 0 ){
		logger	(prefix,"FATAL(%s:%d) Cannot SO_REUSEADDR socket\n",__FILE__,__LINE__);
		exit(3);
	}

	sock4.sin_family = AF_INET;
	sock4.sin_addr.s_addr = INADDR_ANY;
	sock4.sin_port = htons(gix_options->tftp_port);
	saddr4 = (struct sockaddr *)&sock4;
	saddr4_len = sizeof(sock4);
#ifdef IPV6_V6ONLY
	if ( setsockopt(s6,IPPROTO_IPV6, IPV6_V6ONLY,&on,sizeof(on)) < 0 ){
		logger	(prefix,"FATAL(%s:%d) Cannot IPV6_V6ONLY socket\n",__FILE__,__LINE__);
		exit(3);
	}
#endif
	sock6.sin6_family = AF_INET6;
	sock6.sin6_port   = htons(gix_options->tftp_port);
	sock6.sin6_addr   = in6addr_any;
	saddr6 = (struct sockaddr *)&sock6;
	saddr6_len = sizeof(sock6);


	
	if ( bind(s4,saddr4,saddr4_len) < 0 ){
		logger	(prefix,"FATAL(%s:%d) Cannot bind socket (IPv4)\n",__FILE__,__LINE__);
		exit(3);
	}
	if ( bind(s6,saddr6,saddr6_len) < 0 ){
		logger	(prefix,"FATAL(%s:%d) Cannot bind socket (IPv6)\n",__FILE__,__LINE__);
		exit(3);
	}

	
	while ( 1 ){
		int x,y;
		int retval;
		int packlen;
		unsigned char recvbuf[1024];
		polly[0].fd = s4;
		polly[1].fd = s6;
		polly[0].events = POLLIN;
		polly[1].events = POLLIN;
		fdcnt = 2;

		// Are we still enabled?

		if ( gix_options->tftp_enabled ){
			// Still enabled...
		} else {
			logger(prefix,"TFTP-disabled...exiting\n");
			close(s4);
			close(s6); // Main sockets closed
			for ( x = 0; x < MAX_TFTP_SESSIONS; x++ ){
				if ( gix_options->tr[x].active ){
					logger(prefix,"TFTP-Session in Slot %d cancelling...\n",x);
					if ( gix_options->tr[x].sock > 0 ) close(gix_options->tr[x].sock);
					if ( gix_options->tr[x].fd > 0 ) close(gix_options->tr[x].fd);
				}
				bzero((void *)&gix_options->tr[x],sizeof(struct tftp_request));
			}	
			exit(0);
		}	

		// Check for timeouts :-)

		for ( x = 0; x < MAX_TFTP_SESSIONS; x++ ){
			if ( gix_options->tr[x].active && time(NULL) > (gix_options->tr[x].lastaction + TFTP_TIMEOUT) ){
				logger(prefix,"TFTP-Session in Slot %d timed out! Cancelling...\n",x);
				if ( gix_options->tr[x].sock > 0 ) close(gix_options->tr[x].sock);
				if ( gix_options->tr[x].fd > 0 ) close(gix_options->tr[x].fd);
				bzero((void *)&gix_options->tr[x],sizeof(struct tftp_request));
			}
		}

		for ( x = 0; x < MAX_TFTP_SESSIONS; x++ ){
			if ( gix_options->tr[x].active && gix_options->tr[x].sock > 0 ){
				polly[fdcnt].fd = gix_options->tr[x].sock;
				polly[fdcnt++].events = POLLIN;
			}
		}
		retval = poll(polly,fdcnt,1000);
		if ( retval > 0 ){
			if ( polly[0].revents & POLLIN ){
				struct sockaddr_in socky4;
				int slen4;
				char ipname[1024];
				int port;
				bzero(ipname,1024);
				bzero(recvbuf,1024);
				slen4 = sizeof(socky4);
				packlen = recvfrom(s4,recvbuf,1023,0,&socky4,&slen4);
				inet_ntop(AF_INET,&(socky4.sin_addr),ipname,1024);
				port = (int) ntohs(socky4.sin_port);
				logger(prefix,"READ FOR IPv4 (%d Bytes) from: [%s]:%d\n",packlen,ipname,port);
				process_tftp_packet(s4,recvbuf,packlen,ipname,port,(struct sockaddr *)&socky4,slen4);
				sprintf(prefix,"TFTPSERVER");
			}	
			if ( polly[1].revents & POLLIN ){
				struct sockaddr_in6 socky6;
				int slen6;
				char ipname[1024];
				int port;
				bzero(ipname,1024);
				bzero(recvbuf,1024);
				slen6 = sizeof(socky6);
				packlen = recvfrom(s6,recvbuf,1023,0,&socky6,&slen6);
				inet_ntop(AF_INET6,&(socky6.sin6_addr),ipname,1024);
				port = (int) ntohs(socky6.sin6_port);
				logger(prefix,"READ FOR IPv6 (%d Bytes) from: [%s]:%d\n",packlen,ipname,port);
				process_tftp_packet(s6,recvbuf,packlen,ipname,port,(struct sockaddr *)&socky6,slen6);
				sprintf(prefix,"TFTPSERVER");
			}	
			for ( x = 2; x < fdcnt; x++ ){
				if ( polly[x].revents & POLLIN ){
					for ( y = 0; y < MAX_TFTP_SESSIONS; y++ ){
						if ( gix_options->tr[y].sock == polly[x].fd ){
							if ( gix_options->tr[y].addr_family == AF_INET ){
								struct sockaddr_in socky4;
								int slen4;
								char ipname[1024];
								int port;
								bzero(ipname,1024);
								bzero(recvbuf,1024);
								slen4 = sizeof(socky4);
								packlen = recvfrom(polly[x].fd,recvbuf,1023,0,&socky4,&slen4);
								inet_ntop(AF_INET,&(socky4.sin_addr),ipname,1024);
								port = (int) ntohs(socky4.sin_port);
								logger(prefix,"READ FOR SLOT[%d]-IPv4 (%d Bytes) from: [%s]:%d\n",y,packlen,ipname,port);
								process_tftp_packet(polly[x].fd,recvbuf,packlen,ipname,port,(struct sockaddr *)&socky4,slen4);
								sprintf(prefix,"TFTPSERVER");
							}
							if (  gix_options->tr[y].addr_family == AF_INET6 ){
								struct sockaddr_in6 socky6;
								int slen6;
								char ipname[1024];
								int port;
								bzero(ipname,1024);
								bzero(recvbuf,1024);
								slen6 = sizeof(socky6);
								packlen = recvfrom(polly[x].fd,recvbuf,1023,0,&socky6,&slen6);
								inet_ntop(AF_INET6,&(socky6.sin6_addr),ipname,1024);
								port = (int) ntohs(socky6.sin6_port);
								logger(prefix,"READ FOR SLOT[%d]-IPv6 (%d Bytes) from: [%s]:%d\n",y,packlen,ipname,port);
								process_tftp_packet(polly[x].fd,recvbuf,packlen,ipname,port,(struct sockaddr *)&socky6,slen6);
								sprintf(prefix,"TFTPSERVER");
							}
						}
					}
				}			
			}
		}
	}	
	

	logger(prefix,"TFTP-Server ending!\n");	
	exit(0);
}

#define TFTP_SLOT gix_options->tr[slot]

void process_tftp_packet(int sock, unsigned char *data, int len, char *ipname,int port, struct sockaddr *addrinfo, int addr_len){
	unsigned int opcode;
	unsigned char reply[1024];
	char fullname[1024];
	int ret;
	int packsize;
	sprintf(prefix,"TFTPSERVER([%s]:%d)",ipname,port);
	opcode = ((unsigned int)data[1]) + ((unsigned int)data[0]) * 256; 
	logger(prefix,"OPCODE: %d\n",opcode);


	if ( opcode == 4 ){
		int slot;
		int pindex;
		pindex = data[2] * 256 + data[3];
		logger(prefix,"ACK for Packet-ID: %d\n",pindex);
		for ( slot = 0; slot < MAX_TFTP_SESSIONS; slot++ ){
			if ( strcmp(TFTP_SLOT.ipname,ipname) == 0 && TFTP_SLOT.port == port ) break;
		}
		if ( slot == MAX_TFTP_SESSIONS ){
			logger(prefix,"Slot not found --> Ignoring\n");
			return;
		}
		logger(prefix,"Processing packet from slot %d\n",slot);
		process_data_packet(slot,sock,addrinfo,addr_len);
		return;	
	}
	if ( opcode == 5 ){
		int slot;
		int error;
		char errtext[1024];
		bzero(errtext,1024);
		error = data[2] * 256 + data[3];
		strncpy(errtext,&data[4],len-4);
		for ( slot = 0; slot < MAX_TFTP_SESSIONS; slot++ ){
			if ( strcmp(TFTP_SLOT.ipname,ipname) == 0 && TFTP_SLOT.port == port ) break;
		}
		logger(prefix,"Received error (Code: %d) Text: [%s] for slot: %d\n",error,errtext,slot);
		return;
	}

	if ( opcode == 1 ){
		int i;
		int fd;
		int tsize_requested;
		int blksize_requested;
		int blksize_requested_value;	
		int timeout_requested;
		int options;
		int new_socket;
		char optscmd[1024];
		struct stat st;
		char filename[1024];
		char filemode[1024];
		bzero(filename,1024);
		bzero(filemode,1024);
		strcpy(filename,&data[2]);
		gix_options->tftp_requests_read++; // Every try is counted ;-)
		if ( strlen(filename)+3 < len ){
			strcpy(filemode,&data[3+strlen(filename)]);
		}
		tsize_requested = 0;
		blksize_requested = 0;
		timeout_requested = 0;
		if ( (strlen(filename) + strlen(filemode) + 4) < len ){
			int lastoffset;
			options = 1;
			lastoffset = strlen(filename) + strlen(filemode) + 4;
			while ( lastoffset < len ){
				memcpy(optscmd,&data[lastoffset],len - lastoffset);
				logger(prefix,"Option: [%s] Offset: %d\n",optscmd,lastoffset);
				if ( strcmp(optscmd,"tsize") == 0 ){
					tsize_requested = 1;
				}
				if ( strcmp(optscmd,"blksize") == 0 ){
					char blksize[64];
					blksize_requested = 1;
					lastoffset += strlen(optscmd)+1;
					strcpy(blksize,&data[lastoffset]);
					blksize_requested_value = atoi(blksize);
					logger(prefix,"Requested BLKSIZE: %d Bytes\n",blksize_requested_value);
				}
				if ( strcmp(optscmd,"timeout") == 0 ){
					timeout_requested = 1;
				}
				lastoffset += strlen(optscmd)+1;
			}
		} else {
			options = 0;
			strcpy(optscmd,"");
		}
		logger(prefix,"Requested File: [%s] Mode: [%s] Options: %d (%d vs %d)\n",filename,filemode,options,len, strlen(filename) + strlen(filemode) + 4);
		// Ok...lets check the file
		if ( strstr(filename,"..") != NULL ){
			// Do not be tricky :-)
			reply[0] = 0;
			reply[1] = 5;
			reply[2] = 0;
			reply[3] = 1; // File not found :-)
			sprintf(&reply[4],"Invalid File");
			packsize = 4 + strlen(&reply[4]) + 1;	
			ret = sendto(sock,reply,packsize,0,addrinfo,addr_len);
			logger(prefix,"Invalid filename: [%s] --> Send returned: %d\n",filename,ret);
			return;
		}
		if ( filename[0] == '/' )
			sprintf(fullname,"%s%s",gix_options->tftp_root,filename);
		else
			sprintf(fullname,"%s/%s",gix_options->tftp_root,filename);
		if ( stat(fullname,&st) ){
			reply[0] = 0;
			reply[1] = 5;
			reply[2] = 0;
			reply[3] = 1; // File not found :-)
			sprintf(&reply[4],"File not found");
			packsize = 4 + strlen(&reply[4]) + 1;	
			ret = sendto(sock,reply,packsize,0,addrinfo,addr_len);
			logger(prefix,"File not found: [%s] --> Send returned: %d\n",filename,ret);
			return;
		}
		logger(prefix,"Requesting file: [%s], %d Bytes\n",fullname,st.st_size);
		fd = open(fullname,O_RDONLY);
		if ( fd < 0 ){
			reply[0] = 0;
			reply[1] = 5;
			reply[2] = 0;
			reply[3] = 1; // File not found :-)
			sprintf(&reply[4],"FILE NOT FOUND");
			packsize = 4 + strlen(&reply[4]) + 1;	
			ret = sendto(sock,reply,packsize,0,addrinfo,addr_len);
			logger(prefix,"File not found: [%s] --> Send returned: %d\n",filename,ret);
			return;
		}
		new_socket = socket(addrinfo->sa_family,SOCK_DGRAM,0);
		if ( new_socket < 0 ){
			close(fd);
			reply[0] = 0;
			reply[1] = 5;
			reply[2] = 0;
			reply[3] = 0; // No more sockets available
			sprintf(&reply[4],"Server busy...Try again later");
			packsize = 4 + strlen(&reply[4]) + 1;	
			ret = sendto(sock,reply,packsize,0,addrinfo,addr_len);
			logger(prefix,"No more sockets! [%s] --> Send returned: %d\n",filename,ret);
			return;
		}
		for ( i = 0; i < MAX_TFTP_SESSIONS; i++ ){
			if ( gix_options->tr[i].active == 0 ){
				gix_options->tr[i].active = 1;
				gix_options->tr[i].lastaction = time(NULL);
				gix_options->tr[i].started = gix_options->tr[i].lastaction;
				strcpy(gix_options->tr[i].ipname,ipname);
				strcpy(gix_options->tr[i].filename,filename);
				gix_options->tr[i].port = port;
				gix_options->tr[i].kind_request = TFTP_REQUEST_READ;
				gix_options->tr[i].fullsize = st.st_size;
				gix_options->tr[i].fd = fd;
				gix_options->tr[i].offset = (size_t) 0;
				gix_options->tr[i].cur_packet = (size_t) 0;
				gix_options->tr[i].addr_family = addrinfo->sa_family;
				gix_options->tr[i].options = options;
				gix_options->tr[i].sock = new_socket;
				if ( blksize_requested ){
					if ( blksize_requested_value > TFTP_MAX_PACKSIZE ){
						gix_options->tr[i].packsize = TFTP_MAX_PACKSIZE;
					} else {
						gix_options->tr[i].packsize = blksize_requested_value;
					}
				} else {
					gix_options->tr[i].packsize = TFTP_DEFAULT_PACKSIZE;
				}
				logger(prefix,"Will use a packsize of %d Bytes\n",gix_options->tr[i].packsize);
				break;
			}
		}	
		if ( i == MAX_TFTP_SESSIONS ){
			close(fd);
			reply[0] = 0;
			reply[1] = 5;
			reply[2] = 0;
			reply[3] = 0; // File not found :-)
			sprintf(&reply[4],"Server busy...try again later");
			packsize = 4 + strlen(&reply[4]) + 1;	
			ret = sendto(sock,reply,packsize,0,addrinfo,addr_len);
			logger(prefix,"MAX_TFTP_SESSIONS reached! [%s] --> Send returned: %d\n",filename,ret);
			return;
		}
		if ( options ){
			int current_offset;
			current_offset = 0;
			reply[current_offset++] = 0;
			reply[current_offset++] = 6;
			if ( tsize_requested ){
				sprintf(&reply[current_offset],"tsize");
				current_offset += strlen(&reply[current_offset])+1;	
				sprintf(&reply[current_offset],"%ld",st.st_size);
				current_offset += strlen(&reply[current_offset])+1;	
			}
			if ( blksize_requested ){
				sprintf(&reply[current_offset],"blksize");
				current_offset += strlen(&reply[current_offset])+1;	
				sprintf(&reply[current_offset],"%d",gix_options->tr[i].packsize);
				current_offset += strlen(&reply[current_offset])+1;	
			}
			if ( timeout_requested ){
				sprintf(&reply[current_offset],"timeout");
				current_offset += strlen(&reply[current_offset])+1;	
				sprintf(&reply[current_offset],"200");
				current_offset += strlen(&reply[current_offset])+1;	
			}
			ret = sendto(gix_options->tr[i].sock,reply,current_offset,0,addrinfo,addr_len);
			logger(prefix,"SENDING OPTIONS TO Client (%d Bytes) --> %d\n",current_offset,ret);
		}
		logger(prefix,"File [%s] will be processed from Slot %d (Addr-Family: %d, SOCKET-FD: %d)\n",fullname,i,addrinfo->sa_family,gix_options->tr[i].sock);
		process_data_packet(i,sock,addrinfo,addr_len);
		return;
	}
}


void process_data_packet(int slot, int sock, struct sockaddr *addrinfo, int addr_len){
	unsigned char send_data[TFTP_MAX_PACKSIZE+10];
	int packsize;
	int red;
	int ret;
	red = read(TFTP_SLOT.fd,&send_data[4],TFTP_SLOT.packsize);
	if ( red < 0 ){
		close(TFTP_SLOT.fd);	
		bzero(&TFTP_SLOT,sizeof(struct tftp_request));
		send_data[0] = 0;
		send_data[1] = 5;
		send_data[2] = 0;
		send_data[3] = 0; // File not found :-)
		sprintf(&send_data[4],"File-Read-Error");
		packsize = 4 + strlen(&send_data[4]) + 1;	
		ret = sendto(sock,send_data,packsize,0,addrinfo,addr_len);
		logger(prefix,"File read error: [%s] --> Send returned: %d\n",TFTP_SLOT.filename,ret);
		return;
	}
	logger(prefix,"[%d] Read from file %s [Current Offset: %d/%d, Packet-Nr: %d] Read: %d\n",slot,TFTP_SLOT.filename,TFTP_SLOT.offset,TFTP_SLOT.fullsize,TFTP_SLOT.cur_packet,red);
	TFTP_SLOT.lastaction = time(NULL);
	TFTP_SLOT.offset += red;
	TFTP_SLOT.cur_packet++;
	send_data[0] = 0;
	send_data[1] = 3;
	send_data[2] = TFTP_SLOT.cur_packet / 256;
	send_data[3] = TFTP_SLOT.cur_packet & 0xFF;
	packsize = 4 + red;
	ret = sendto(TFTP_SLOT.sock,send_data,packsize,0,addrinfo,addr_len);
	logger(prefix,"File read OK: [%d] --> Send returned: %d/%d [%02X][%02X]\n",slot,ret,packsize,send_data[2],send_data[3]);
	if ( red == 0 ){ 
		close(TFTP_SLOT.fd); 
		close(TFTP_SLOT.sock); 
		bzero(&TFTP_SLOT,sizeof(struct tftp_request));
		logger(prefix,"File finished! Freeing slot %d\n",slot);
	}
	return;
}

#define DHCP_INTERFACE            gix_options->dhcp_interface[idx]
#define DHCP_INTERFACE_IF_CONFIG  if_config[DHCP_INTERFACE.index]

void process_dhcp_packet(int idx);

void start_dhcp(){
	int idx;

	sprintf(prefix,"DHCPSERVER");
	logger(prefix,"DHCP-Server starting (%d Bytes for IPv4 DHCP)\n",sizeof(struct bootp_packet));
	for ( idx = 0; idx < gix_options->dhcp_interfaces; idx++ ){
		if ( (DHCP_INTERFACE.socket = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL))) < 0 ){
			logger(prefix,"FATAL: Cannot open socket for interface: [%s](%s)\n",DHCP_INTERFACE_IF_CONFIG.ethname,strerror(errno));
			continue;
		}
		if ( strlen(DHCP_INTERFACE_IF_CONFIG.ethname) > IFNAMSIZ ){
			logger(prefix,"FATAL: Cannot set socket-binding for interface: [%s] (Name to long)\n",DHCP_INTERFACE_IF_CONFIG.ethname);
			continue;
		}
		if ( setsockopt(DHCP_INTERFACE.socket,SOL_SOCKET, SO_BINDTODEVICE, DHCP_INTERFACE_IF_CONFIG.ethname, strlen(DHCP_INTERFACE_IF_CONFIG.ethname)) < 0 ){
			logger(prefix,"FATAL: Cannot set socket-binding for interface: [%s] (SO_BINDTODEVICE: %s)\n",DHCP_INTERFACE_IF_CONFIG.ethname,strerror(errno));
			continue;
		}
		logger(prefix,"Interface: [%s]...assigned socket: %d, MAC-Addr: [%s] Port: %d\n",
			DHCP_INTERFACE_IF_CONFIG.ethname, DHCP_INTERFACE.socket,dump_mac_addr(DHCP_INTERFACE.mac), DHCP_INTERFACE.ip_port_in);
	}
	// Main-Loop...poll and wait for packets :-)
	while (1){
		struct pollfd polly[MAX_DHCP_INTERFACES];
		int pollfds;
		int retval;

		if ( gix_options->dhcp_enabled == 0 ) goto EXIT_DHCP; // Is it still wanted, that we work?
		
		pollfds = gix_options->dhcp_interfaces;
		
		for ( idx = 0; idx < pollfds; idx++ ){
			polly[idx].fd = DHCP_INTERFACE.socket;
#ifdef POLLRDHUP
			polly[idx].events = POLLIN | POLLERR | POLLHUP | POLLRDHUP;
#else
			polly[idx].events = POLLIN | POLLERR | POLLHUP;
#endif
			polly[idx].revents = 0;
		}
		retval = poll(polly,pollfds,1000);
		if ( retval < 0 ){
			logger(prefix,"POLL failed...exiting [%s]\n",strerror(errno));
			goto EXIT_DHCP;
		}
		if ( retval > 0 ){
			for ( idx = 0; idx < pollfds; idx++ ){
				if ( polly[idx].revents & POLLIN ){
					process_dhcp_packet(idx);
					continue;
				}
				if ( (polly[idx].revents & POLLHUP) ||  (polly[idx].revents & POLLRDHUP) || (polly[idx].revents & POLLERR ) ){
					logger(prefix,"Socket for interface [%s] corrupted...closing DHCP-Server (will be restarted automatically)\n",DHCP_INTERFACE_IF_CONFIG.ethname);
					goto EXIT_DHCP;
				}
			}
		}
	
	}

	// Never reached (normally) :-)
EXIT_DHCP:
	for ( idx = 0; idx < gix_options->dhcp_interfaces; idx++ ){
		if ( DHCP_INTERFACE.socket ) close(DHCP_INTERFACE.socket);
	}
	logger(prefix,"Ending\n");
	exit(0);
}

void process_dhcp_packet(int idx){
	u_int8_t packet[8192]; // Even big enough for jumbo-frames :-)
	struct ethhdr *ethhdr;
	int p_size;
	char ether_source[64];
	char ether_target[64];


	p_size = recv(DHCP_INTERFACE.socket,packet,8192,0);
	ethhdr = (struct ethhdr *)packet;
	if ( memcmp(ethhdr->h_source,DHCP_INTERFACE.mac,6) == 0 ){
		return;
	}
	if ( memcmp(ethhdr->h_dest,DHCP_INTERFACE.mac,6) != 0 && memcmp(ethhdr->h_dest,ether_bcast,6) != 0 ){
		return;
	}
	// We are only interested in IP and IPv6 Packets  

	strcpy(ether_source,dump_mac_addr(ethhdr->h_source));
	strcpy(ether_target,dump_mac_addr(ethhdr->h_dest));
	if ( ntohs(ethhdr->h_proto) == ETH_P_IPV6 ){
		// logger(prefix,"IPv6[%s] (%d Bytes data) [%s] Proto: [0x%04X]\n",DHCP_INTERFACE_IF_CONFIG.ethname,p_size,dump_mac_addr(ethhdr->h_source),ntohs(ethhdr->h_proto));
		return;
	}
	if ( ntohs(ethhdr->h_proto) == ETH_P_IP ){ // A IPv4 BootP/DHCP-Request;
		int opt_len; // If 0...only a BOOTP-Request
		struct dhcp_features features;
		struct bootp_packet *bootp;
		u_int8_t magic_cookie[4];	
		struct ip *iphdr;
		struct udphdr *udphdr;
		int ip_hlen;
		int udp_datalen;
		int p_len;
		int d_len;
		unsigned short s_port;
		unsigned short d_port;
		iphdr = (struct ip *)&packet[sizeof(struct ethhdr)];
		ip_hlen = (int)(((unsigned int)(iphdr->ip_hl)) << 2);
		// We are only interested in UDP
		if ( iphdr->ip_p != IPPROTO_UDP ) return; 
		bzero(&features,sizeof(struct dhcp_features));
		memcpy(features.source_mac,ethhdr->h_source,6);

		struct sockaddr_in ip_source;
		struct sockaddr_in ip_target; 	
#ifdef DEBUG_DHCP
		char source_ip[128];
		char target_ip[128];
#endif
		ip_source.sin_family = AF_INET;
		ip_target.sin_family = AF_INET;
		memcpy(&ip_source.sin_addr,&(iphdr->ip_src),4);
		memcpy(&ip_target.sin_addr,&(iphdr->ip_dst),4);
#ifdef DEBUG_DHCP
		inet_ntop(AF_INET,&ip_source.sin_addr,source_ip,128);
		inet_ntop(AF_INET,&ip_target.sin_addr,target_ip,128);
#endif
		udphdr = (struct udphdr *)&packet[sizeof(struct ethhdr)+ip_hlen];
		s_port = ntohs(udphdr->uh_sport);	
		d_port = ntohs(udphdr->uh_dport);	

		if ( d_port != DHCP_INTERFACE.ip_port_in ) return; // We only want DHCP packets :-)
		udp_datalen = ntohs(udphdr->uh_ulen);
		p_len = udp_datalen + sizeof(struct ethhdr) + ip_hlen;
		if ( p_len != p_size ){
			logger(prefix,"WARNING: ignoring corrupted packet:[%s] (%d Bytes) ETH[%s]->[%s] (%s:%d) -> (%s:%d) IP-HLEN: %d Bytes Calc-Len: %d\n",DHCP_INTERFACE_IF_CONFIG.ethname,p_size,ether_source,ether_target,source_ip,(int) s_port,target_ip,(int) d_port,ip_hlen,p_len);
			return;
		}
		d_len = p_len - (sizeof(struct ethhdr) + ip_hlen +  sizeof(struct udphdr));		
#ifdef DEBUG_DHCP
		logger(prefix,"IP[%s] (%d Bytes) ETH[%s]->[%s] (%s:%d) -> (%s:%d) IP-HLEN: %d Bytes DHCP-Len: %d\n",DHCP_INTERFACE_IF_CONFIG.ethname,p_size,ether_source,ether_target,source_ip,(int) s_port,target_ip,(int) d_port,ip_hlen,d_len);
#endif
		bootp = (struct bootp_packet *)&packet[sizeof(struct ethhdr) + ip_hlen + sizeof(struct udphdr)];
		opt_len = d_len - sizeof(struct bootp_packet);
		if ( bootp->flags & 0x80 ) features.wants_broadcast = 1;
		logger(prefix,"(%d Bytes) BOOTP-OP: %d  HTYPE: %d HLEN: %d HOPS: %d XID: 0x%08X FLAGS: 0x%02X SNAME: [%.64s] Total: %d Bytes, Options: %d Bytes DHCP: [%s] Broadcast-Reply: [%s]\n",
			sizeof(struct bootp_packet),bootp->op, bootp->htype, bootp->hlen, bootp->hops, bootp->xid, bootp->flags, bootp->sname, d_len, opt_len, opt_len > 0 ? "YES" : "NO", features.wants_broadcast ? "YES" : "NO");


#define DHCP_OPTIONS_OFFSET (sizeof(struct ethhdr) + ip_hlen + sizeof(struct udphdr)+sizeof(struct bootp_packet))
		if ( opt_len > 0 ){ // A DHCP-Request :-)
			int offset;
			int msg_type;
			features.wants_dhcp = 1;	
			memcpy(magic_cookie,&packet[DHCP_OPTIONS_OFFSET],4);
#ifdef DEBUG_DHCP
			logger(prefix,"MAGIC-COOKIE: %02X%02X%02X%02X\n", magic_cookie[0], magic_cookie[1], magic_cookie[2], magic_cookie[3]);
#endif
			if ( memcmp(magic_cookie,dhcp_magic_cookie,4) != 0 ){
				logger(prefix,"WARNING: Illegal DHCP request (wrong magic cookie value [%02X%02X%02X%02X])\n", magic_cookie[0], magic_cookie[1], magic_cookie[2], magic_cookie[3]);
				return;
			}
			// Now let us parse the options :-)
			offset = DHCP_OPTIONS_OFFSET + 4; // Jump over magic-cookie
			while ( offset < p_size ){
				u_int8_t option;
				u_int8_t optlen;
				option = packet[offset++];
				if ( option == 0 ) continue; // Padding
				if ( option == 255 ) break;  // Options done
				optlen = packet[offset++];
				logger(prefix,"[%04d/%04d]Option: %d [%s], Len: %d, Value: [%s]\n",offset,p_size,option,get_type_name(option),optlen,make_print(&packet[offset],optlen));
				if ( option == 53 ){ 
					msg_type = (int)packet[offset];
					logger(prefix,"REQUEST-TYPE: [%s]\n",dhcp_message_type(msg_type));
					offset += optlen;
					continue;
				}
				if ( option == 60 ){ // Client Class-ID
					features.class_id = (u_int8_t *)malloc(optlen);
					memcpy(features.class_id,&packet[offset],optlen);
					logger(prefix,"Client-Class: [%s] (%d Bytes)\n",make_print(&packet[offset],optlen),optlen);
					offset += optlen;
				}
				if ( option == 55 ){
					int i;
					logger(prefix,"CLIENT WANTS: %d Options\n",optlen);
					for ( i = 0; i < optlen; i++ ){
						logger(prefix,"OPTION[%d]: [%d] [%s]\n",i,(int)packet[offset+i],get_type_name((int)packet[offset+i]));
					}
					offset += optlen;
					continue;
				}
				
				offset += optlen;
			}	
#ifdef DEBUG_DHCP
			logger(prefix,"Options parsed: Offset: %d\n",offset);
#endif
			if ( msg_type == 1 ){ // A DHCPDISCOVER-Request :-)
				logger(prefix,"Processing DHCPDISCOVERY FOR: [%s]\n",dump_mac_addr(features.source_mac));		
				
			}
				
		}

		return;
	}

}
