#include <stdio.h>
#include <pcap.h>

void
printbytes(char *left, const u_char *p, int num, char delimiter, char *right)
{
	int i = 0;

	printf("%s", left);
	printf("%02x", p[i++]);
	while(i < num) printf("%c%02x", delimiter, p[i++]);
	printf("%s", right);
	return;
}

int
printelement(const u_char *p)
{
	char *name;
	switch(p[0]) {
	case 0:		name = "SSID"; break;
	case 1:		name = "Suppported Rate"; break;
	case 2:		name = "FH Parameter Set"; break;
	case 3:		name = "DS Parameter Set"; break;
	case 4:		name = "CF Parameter Set"; break;
	case 5:		name = "TIM"; break;
	case 6:		name = "IBSS Paramter Set"; break;
	case 16:	name = "Challenge Text"; break;
	default:	name = "Unknown"; break;
	}
	printf("Element: ID=%s(0x%02x) len=%d ", name, p[0], p[1]);
	printbytes("data=", &p[2], p[1], ' ', "\n");
	return p[1] + 2;
}

int
main(int argc, char *argv[])
{
	char ebuf[PCAP_ERRBUF_SIZE];
	struct bpf_program bpfprog;
	pcap_t *pc;
	int i;

	pc = pcap_open_live("ux0", 100, 1, 1000, ebuf);
	if(pc == NULL) err("%s", ebuf);

	if(pcap_compile(pc, &bpfprog, 0, 0, 0) < 0
	|| pcap_setfilter(pc, &bpfprog) < 0) err("%s", pcap_geterr(pc));

	for(;;) {
		struct pcap_pkthdr ph;
		const u_char *pkt;

		pkt = pcap_next(pc, &ph);

		printf("\n");
		printf("caplen=%d len=%d pktbuf=%08x\n",
						ph.caplen, ph.len, pkt);
		printbytes("", &pkt[ 0], 4, ' ', "\n");
		printbytes("", &pkt[ 4], 6, ':', "  ");
		printbytes("", &pkt[10], 6, ':', "  ");
		printbytes("", &pkt[16], 6, ':', "  ");
		printbytes("", &pkt[22], 2, ' ', "\n");

		if((pkt[0] & 0x0c) == 0x08) {
			printbytes("", &pkt[24], 6, ':', "  ");
			printbytes("", &pkt[30], 6, ':', "  ");
			printbytes("", &pkt[36], 2, ' ', "\n");
			if(pkt[36] == 8 && pkt[37] == 6) {	/* ARP */
				printbytes("", &pkt[38], 8, ' ', "\n");
				printbytes("", &pkt[46], 6, ':', "  ");
				printbytes("", &pkt[52], 4, '.', "\n");
				printbytes("", &pkt[56], 6, ':', "  ");
				printbytes("", &pkt[62], 4, '.', "\n");
			} else {
				printbytes("", &pkt[38], 16, ' ', "\n");
				printbytes("", &pkt[54], 16, ' ', "\n");
			}
		} else if((pkt[0] & 0x0c) == 0) switch(pkt[0] & 0xf0) {
		case 0x80:	/* beacon */
			printf("type=beacon\n");
			printbytes("timestamp=", &pkt[24], 8, ' ', "\n");
			printbytes("beacon interval=", &pkt[32], 2, ' ', "\n");
			printbytes("cap info=", &pkt[34], 2, ' ', "\n");
			for(i = 36; i < ph.caplen - 4; ) { /* last FCS */
				printf("[%d] ", i);
				i += printelement(&pkt[i]);
			}
			break;
		} else {
			printbytes("", &pkt[24], 16, ' ', "\n");
			printbytes("", &pkt[40], 16, ' ', "\n");
		}
	}
	return 0;
}
