/*
 * ipconfig/bootp_proto.c
 *
 * BOOTP packet protocol handling.
 */
#include <sys/types.h>
#include <sys/uio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <netinet/in.h>

#include "ipconfig.h"
#include "netdev.h"
#include "bootp_packet.h"
#include "bootp_proto.h"
#include "packet.h"

static __u8 bootp_options[312] = {
	[0]   = 99, 130, 83, 99,/* RFC1048 magic cookie */
	[4]   = 1, 4,		/*   4-  9 subnet mask */
	[10]  = 3, 4,		/*  10- 15 default gateway */
	[16]  = 5, 8,		/*  16- 25 nameserver */
	[26]  = 12, 32,		/*  26- 59 host name */
	[60]  = 40, 32,		/*  60- 95 nis domain name */
	[96]  = 17, 40,		/*  96-137 boot path */
	[138] = 57, 2, 1, 150,	/* 138-141 extension buffer */
	[142] = 255,		/* end of list */
};

/*
 * Send a plain bootp request packet with options
 */
int bootp_send_request(struct netdev *dev)
{
	struct bootp_hdr bootp;
	struct iovec iov[] = {
		/* [0] = ip + udp headers */
		[1] = { &bootp, sizeof(bootp) },
		[2] = { bootp_options, 312 }
	};

	memset(&bootp, 0, sizeof(struct bootp_hdr));

	bootp.op     = BOOTP_REQUEST,
	bootp.htype  = dev->hwtype;
	bootp.hlen   = dev->hwlen;
	bootp.xid    = dev->bootp.xid;
	bootp.ciaddr = dev->ip_addr;
	bootp.secs   = htons(time(NULL) - dev->open_time);
	memcpy(bootp.chaddr, dev->hwaddr, 16);

	DEBUG(("-> bootp xid 0x%08x secs 0x%08x ",
	       bootp.xid, ntohs(bootp.secs)));

	return packet_send(dev, iov, 2);
}

/*
 * Parse a bootp reply packet
 */
int
bootp_parse(struct netdev *dev, struct bootp_hdr *hdr, __u8 *exts, int extlen)
{
	dev->bootp.gateway    = hdr->giaddr;
	dev->ip_addr          = hdr->yiaddr;
	dev->ip_server        = hdr->siaddr;
	dev->ip_netmask       = INADDR_ANY;
	dev->ip_broadcast     = INADDR_ANY;
	dev->ip_gateway       = hdr->giaddr;
	dev->ip_nameserver[0] = INADDR_ANY;
	dev->ip_nameserver[1] = INADDR_ANY;
	dev->hostname[0]      = '\0';
	dev->nisdomainname[0] = '\0';
	dev->bootpath[0]      = '\0';

	if (extlen >= 4 && exts[0] == 99 && exts[1] == 130 &&
	    exts[2] == 83 && exts[3] == 99) {
		__u8 *ext;

		for (ext = exts + 4; ext - exts < extlen; ) {
			__u8 len, opt = *ext++;
			if (opt == 0)
				continue;

			len = *ext++;

			switch (opt) {
			case 1:	/* subnet mask */
				if (len > 4)
					len = 4;
				memcpy(&dev->ip_netmask, ext, len);
				break;
			case 3: /* default gateway */
				if (len > 4)
					len = 4;
				memcpy(&dev->ip_gateway, ext, len);
				break;
			case 6:	/* DNS server */
				if (len > 8)
					len = 8;
				memcpy(&dev->ip_nameserver, ext, len);
				break;
			case 12: /* host name */
				if (len > sizeof(dev->hostname) - 1)
					len = sizeof(dev->hostname) - 1;
				memcpy(&dev->hostname, ext, len);
				dev->hostname[len] = '\0';
				break;
			case 15: /* domain name */
				if (len > sizeof(dev->dnsdomainname) - 1)
					len = sizeof(dev->dnsdomainname) - 1;
				memcpy(&dev->dnsdomainname, ext, len);
				dev->dnsdomainname[len] = '\0';
				break;
			case 17: /* root path */
				if (len > sizeof(dev->bootpath) - 1)
					len = sizeof(dev->bootpath) - 1;
				memcpy(&dev->bootpath, ext, len);
				dev->bootpath[len] = '\0';
				break;
			case 26: /* interface MTU */
				if ( len == 2  )
					dev->mtu = (ext[0] << 8) + ext[1];
				break;
			case 28: /* broadcast addr */
				if (len > 4)
					len = 4;
				memcpy(&dev->ip_broadcast, ext, len);
				break;
			case 40: /* NIS domain name */
				if (len > sizeof(dev->nisdomainname) - 1)
					len = sizeof(dev->nisdomainname) - 1;
				memcpy(&dev->nisdomainname, ext, len);
				dev->nisdomainname[len] = '\0';
				break;
			}				

			ext += len;
		}
	}

	/*
	 * Got packet.
	 */
	return 1;
}

/*
 * Receive a bootp reply and parse packet
 */
int bootp_recv_reply(struct netdev *dev)
{
	struct bootp_hdr bootp;
	__u8 bootp_options[312];
	struct iovec iov[] = {
		/* [0] = ip + udp headers */
		[1] = { &bootp, sizeof(struct bootp_hdr) },
		[2] = { bootp_options, 312 }
	};
	int ret;

	ret = packet_recv(iov, 3);
	if (ret <= 0)
		return ret;

	if (ret < sizeof(struct bootp_hdr) ||
	    bootp.op != BOOTP_REPLY ||		/* RFC951 7.5 */
	    bootp.xid != dev->bootp.xid ||
	    memcmp(bootp.chaddr, dev->hwaddr, 16))
		return 0;

	ret -= sizeof(struct bootp_hdr);

	return bootp_parse(dev, &bootp, bootp_options, ret);
}

/*
 * Initialise interface for bootp.
 */
int bootp_init_if(struct netdev *dev)
{
	short flags;

	/*
	 * Get the device flags
	 */
	if (netdev_getflags(dev, &flags))
		return -1;

	/*
	 * We can't do DHCP nor BOOTP if this device
	 * doesn't support broadcast.
	 */
	if (dev->mtu < 364 || (flags & IFF_BROADCAST) == 0) {
		dev->caps &= ~(CAP_BOOTP | CAP_DHCP);
		return 0;
	}
	
	/*
	 * Get a random XID
	 */
	dev->bootp.xid = (__u32)lrand48();
	dev->open_time = time(NULL);

	return 0;
}
