#include <iostream>
#include <stdlib.h>
#include "common.h"
#include "ethernet.h"
#include "ipv4.h"
#include "ipv6.h"
#include "udp.h"
#include "bootp.h"
#include "pcap.h"

#ifndef DEV
#define DEV "em0"
#endif

int main(int argc, char *argv[])
{
	Ethernet *e = new Ethernet();
	Buffer buf;
	debug = 2;
	bool finish = false;
	string dev(DEV);

	if (argc == 2) dev = argv[1];
	else 
	if (argc > 2) {
		cerr << argv[0] << ": [intf]" << endl;
		return 1;
	}

	Ethernet te;
	te.src("12:23:45:67:89:ab");
	te.dest("ff:ff:ff:ff:ff:ff");

	IPv4 tip;
	tip.src("0.0.0.0");
	tip.dest("255.255.255.255");

	// bootps/bootps
	UDP tudp(67, 67);
	te.attach(&tip);
	tip.attach(&tudp);

	// bootp packet
	BOOTP btp;
	btp.xid(random());
	btp.client_mac(te.src());
	tudp.attach(&btp);

	Buffer pkt;
	te.build(pkt); // full packet build
        cout << tudp.to_string(2) << endl;

        cout << pkt << endl;

	PCAP pcap;
	pcap.open(dev);
	pcap.set_filter("ip and udp dst port 67");
	Buffer bp;
	while (!finish) {
		// get packet
		if (!pcap.read(buf, dev)) continue;
		// full decode
		if (!e->decode(buf)) continue;
		// is any decoded payload?
		if (!e->payload()) continue;
		// is IPv4 packet?
		if (dynamic_cast<IPv4 *>(e->payload()) == NULL) continue;
		IPv4 *ipv4 = dynamic_cast<IPv4 *>(e->payload());
		cout << ipv4 << endl;
		// is any decoded payload?
		if (!ipv4->payload()) {
			cout << "No payload" << endl;
			continue;
		}
		if (dynamic_cast<UDP *>(ipv4->payload()) == NULL) {
			cout << "Not UDP payload" << endl;
			continue;
		}
		UDP *udp = dynamic_cast<UDP *>(ipv4->payload());
		cout << udp->to_string(1) << endl;
		if (udp->dst_port() != 67) continue;
		if (udp->src_port() != 67 && udp->src_port() != 68) continue;
		// setup bootp decode
		bp.buf(udp->get_data(), udp->length());
		if (!btp.decode(bp)) continue;
		cout << btp.to_string(2) << endl;
	}
}
