
#include <sys/types.h>
#include <sys/time.h>

#include <netinet/in.h>

#include <pcap/pcap.h>


//struct pcap_pkthdr {
//        struct timeval ts;      /* time stamp */
//        bpf_u_int32 caplen;     /* length of portion present */
//        bpf_u_int32 len;        /* length this packet (off wire) */
//};
char *Phones[(74-60)*2]={	// this can change after every reboot
"Guest","Tim",
"??","HR",
//"HR",	//0
//"tony", "reception", "Curtis", "4", "5", "6","aw","8","9","10",
//"11","Tim","comp room","dee","sharon","mervyn","paul","leonard","bryan","20",
//"sarah","Julian","Geoff","24","geoff","28","27"	// Sarah & Bri may be swaped
////,"28","29","30",
////31","32","33","34","35","36","37","38","39","40"
};
char *Months[13]={"a","j","f","m","a","may","june","jul","aug","sep","oct","nov","dec"};
static pcap_t *pd;
int count=0;

struct packet {
	char dest[6];	// ehter addr
	char src[6];	// ehter addr
	short proto;	// 0x8868
	short type;	//'HA'
	char orig[6];	// ehter addr
	short seq;
	unsigned char data[4];	// its bigger...
};

print_ether_addr(unsigned char *x) {
	//printf("%x:%x:%x:%x:%x:%x\n",x[0],x[1],x[2],x[3],x[4],x[5]);
}

void fn(u_char *u,const struct pcap_pkthdr *pcap,const u_char *data) {
	int i=0;
	int ph_cnt;
	time_t time_t;
	struct packet *d;
	int bcast=0;
	FILE *OUT;
	char fname[100];
	int s=pcap->caplen;
	int S=pcap->caplen-sizeof(struct packet);
	//printf("ok %d (%d)\n",count++,s);
	//printf("\n");
	d=(void *)data;
	if(d->dest[0]==1)
		bcast=1;
	//	print_ether_addr(d->orig);
	if(data[14]==0 && data[15]==1) {
		if( data[16]==0x88 && data[17]==0x68) {
			//printf("Vlan 1\n");
			//data+=4;
//0:e0:bb:3:d0:b1:0:e0:bb:b:d8:be:81:0:0:1:88:68:48:52:0:e0:bb:b:d8:be:
//0:e0:bb:3:d0:b1:0:e0:bb:b:d8:be:xx:x:x:x:88:68:48:52:0:e0:bb:b:d8:be:
			bcopy(&data[16],&data[12],S);
                     

		} else {
			// vlan and not for me
			return;
		}
	}
	switch(data[15]) {
	case	'A':	//// Voice Packet
	 break;
	case	'R':	//// Request?
	 //break;
		//printf("Request: %d\n",bcast);
		//for(i=0;i<S;i++) {
		////for(i=14+32+32;i<14+48+20+20;i++) {	/// for for strings...
			//printf( "%02x",d->data[i]);
			//if(i%4==1) printf(" ");
		//}
		if( data[14+32+32-2]==2 &&  data[14+32+32-1]==32) {
		time(&time_t);
		sprintf(fname,"/tmp/%x:%x:%x:%x:%x:%x", data[0], data[1],data[2],data[3],data[4],data[5]);
		if(OUT=fopen(fname,"a+")) {
			fprintf(OUT,"%x:%x:%x:%x:%x:%x %lu ", data[0], data[1],data[2],data[3],data[4],data[5],time_t);
		
			fprintf(OUT,"\"%s\"\n",&data[14+32+32]);
			fclose(OUT);
		}
		//printf("%x:%x:%x:%x:%x:%x %lu ", data[0], data[1],data[2],data[3],data[4],data[5],time_t);
		//printf("%d %d: ", data[14+32+32-2], data[14+32+32-1]);
		//printf("\"%s\"\n",&data[14+32+32]);
		}
	case	'E':	//// durring Init
	case	'I':	//// durring Init
	case	'Y':	//// durring Init
	case	'H':	//// Ack?
		break;
	case	'U'+1:	//// 0x55 update
			//// broadcast every second or so
			//// sometimes to specifc phones
		printf("SysUpdate: %d\n",bcast);
		for(i=0;i<S;i++) {
			printf( "%02x",d->data[i]);
			if(i%4==1) printf(" ");
		}
		printf("\n");
		break;
	case	'U':	//// 0x55 update
			//// broadcast every second or so
			//// sometimes to specifc phones
	break;
		printf("Update: \n");
		//for(i=14+32;i<14+48;i++) {
		for(i=14+32;i<s;i++) {
			printf( "%02x",data[i]);
			if(i%4==1) printf(" ");
		}
		
		printf("some month %d %d:%02d  %d \n",
			data[47], data[48]%12, data[49], data[50], data[51]);
		//printf("%s %d %d:%02d  %d \n",Months[data[14+32]],
			//data[47], data[48]%12, data[49], data[50], data[51]);
//dec11 213 ???????               h
//0c0b 0e0b e2900300 00000200 000e3000
//48   50   52       56           60
// real structure is:
// 2:  0x0200
//     2 byte size (rounded to words)
// ... each phone is 4 bits
//     phones are '3'
		//for(i=62;i<80;i++) {
		ph_cnt=0;
	printf("type of table=%04x\n",data[59-2]+data[58-2]*256);
	printf("size of table=%d\n",data[59]+data[58]*256);
		for(i=60;i<72;i++) {
			int a,b;
			a=b=data[i];
			a=a>>4;
			b=b&0xf;
			if(a) ph_cnt++;
			if(b) ph_cnt++;
			if(a) 
				printf("phone %d (%s) on a %x (%02x)\n",(i-60)*2,
					Phones[(i-60)*2],a,data[i]);
			if(b) 
				printf("phone %d (%s) on a %x (%02x)\n",(i-60)*2+1,
					Phones[(i-60)*2+1],b,data[i]);
		}
		printf("%d phones on line\n",ph_cnt);
		break;

	default:
		printf("Unknown Packet Type: (%d,%d)\n",data[14],data[15]);
		//printf(" %c%c ",data[14],data[15]);
		for(i=0;i<30;i++) {
			printf( "%x:",data[i]);
		}
	
	}
	//printf("\n");

}

//typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
//                             const u_char *);

main() {
	char *device="eth1";
	//char *device="eth0";
	//char *device="";
	char ebuf[PCAP_ERRBUF_SIZE];
	int snaplen=500;
	struct bpf_program filter;
	int x=0;
	int pid;


	/* daemonize */
	if((pid = fork())<0) {
		perror("Cannot fork");
		exit(-1);
	}
   
	if(pid>0) /* Parent exits. */
		exit(0);
   
	/* Child continues. */
	setsid();


	pd = pcap_open_live(device, snaplen, 1, 1000, ebuf);
	//pd = pcap_open_offline("nbx-startup-trace", ebuf);
	//pd = pcap_open_live(device, snaplen, 0, 1000, ebuf);

	//x=pcap_compile(pd, &filter, "",1,0xffffff00);
	//fprintf(stderr,"pd=%d\n",pd);
	//x=pcap_compile(pd, &filter, "ether proto 0x8868 and len < 200",1,0xffffff00);
	// proto 0x8868 works great for raw nets
	x=pcap_compile(pd, &filter, "ether proto 0x8868 and len < 800",1,0xffffff00);
	// cisco vlans the packets so proto 0x8868 wont work
	x=pcap_compile(pd, &filter, "ether proto 0x8100 and vlan 1 and len < 800",1,0xffffff00);
	//fprintf(stderr,"x=%d\n",x);
	x=pcap_setfilter(pd, &filter);
	//fprintf(stderr,"x=%d\n",x);
	
	if(pd== NULL) {
		printf("pcap_open died");
		perror("open");
		exit(0);
	}
	while(1) {
		x=pcap_dispatch(pd,-1,&fn,0);
		//x=pcap_dispatch(pd,1,&fn,0);
		//printf("x=%d\n",x);
	}
}


/*
    count                        type
      3                          4845 00e0  E
      8                          4859 00e0  Y
    272                          4849 00e0  I
     83                          4848 00e0  H   ack
     78                          4852 00e0  R	Request
      8                          4855 00e0  U	update display

*/

