#include <iostream>
#include "common.h"
#include "ethernet.h"
#include "ipv6.h"
#include "ipv4.h"
#include "icmpv6.h"


int main()
{
	Ethernet *p = new Ethernet();
	Buffer *pkt = new Buffer();
	debug = 2;

	p->src("12:23:45:67:89:ab");
	p->dest("cd:ef:45:67:89:ab");

	IPv6 *ip6 = new IPv6();
	ip6->src("2001:718:802:809::93e5:90b");
	ip6->dest("2001:718:802:809::93e5:90c");
	IPv6HopByHopHeader *hbh = new IPv6HopByHopHeader();
	IPv6OptionRouterAlert *ra = new IPv6OptionRouterAlert(IPv6OptionRouterAlert::RSVPMessage);
	hbh->add_option(ra);
	ip6->add_exthdr(hbh);
	p->attach(ip6);

	ICMPv6DestinationUnreachable *du = new ICMPv6DestinationUnreachable(4, *pkt);
	ip6->attach(du);
	if (!p->build(*pkt)) {
		cout << "build failed" << endl;
		return 0;
	}
	cout << ip6 << endl;
	cout << du << endl;
	cout << pkt << endl;
	pkt->setup(pkt->length());

	Ethernet *de = new Ethernet();
	if (de->decode(*pkt)) {
		cout << "OK: " << de << endl;
		cout << "OK: " << de->payload() << endl;
		cout << "OK: " << de->payload()->payload() << endl;
	} else {
		cout << "FAIL Ethernet decode" << endl;
	}

	pkt->clear();
	// scapy:
	// p=IPv6(src="2001:718:802:809::93e5:90b",dst="2001:718:802:809::93e5:90c")/IPv6ExtHdrHopByHop(options=RouterAlert(value=1))/ICMPv6ND_RA(chlim=64,prf=0)/ICMPv6NDOptSrcLLAddr(lladdr="22:33:44:55:66:77")/ICMPv6NDOptPrefixInfo(prefix='2001:718:802:909::',prefixlen=64,validlifetime=2592000,preferredlifetime=604800)
	cout << endl << "Test ND_RA:" << endl;
	ICMPv6ND_RA *nd_ra = new ICMPv6ND_RA();
	NDOptionSourceLLA *slla = new NDOptionSourceLLA("22:33:44:55:66:77");
	nd_ra->add_option(slla);
	NDOptionPrefixInfo *pi = new NDOptionPrefixInfo("2001:718:802:909::", 64);
	nd_ra->add_option(pi);
	ip6->attach(nd_ra);
	cout << "Raw ND_RA:" << endl;
	cout << nd_ra << endl;

	if (!p->build(*pkt)) {
		cout << "build failed" << endl;
		return 0;
	}
	cout << "After build:" << endl;
	cout << ip6 << endl;
	cout << nd_ra << endl;

	cout << "Raw packet:" << endl;
	cout << pkt << endl;

	pkt->setup(pkt->length());
	cout << "Decoded packet:" << endl;
	if (de->decode(*pkt)) {
		cout << "OK: " << de << endl;
		cout << "OK: " << de->payload() << endl;
		cout << "OK: " << de->payload()->payload() << endl;
	} else {
		cout << "FAIL Ethernet decode" << endl;
	}
}
