/*
 * ipconfig/bootp_proto.c
 *
 * BOOTP packet protocol handling.
 */
#include <sys/types.h>
#include <linux/types.h>	/* for __u8 */
#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 */
				memcpy(&dev->ip_netmask, ext, len > 4 ? 4 : len);
				break;
			case 3: /* default gateway */
				memcpy(&dev->ip_gateway, ext, len > 4 ? 4 : len);
				break;
			case 6:	/* DNS server */
				memcpy(&dev->ip_nameserver, ext, len > 8 ? 8 : 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 */
				memcpy(&dev->ip_broadcast, ext, len > 4 ? 4 : 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;
}
