/*
 * 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 uint8_t 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,
		uint8_t *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) {
		uint8_t *ext;

		for (ext = exts + 4; ext - exts < extlen;) {
			int len;
			uint8_t opt = *ext++;

			if (opt == 0)
				continue;
			else if (opt == 255)
				break;

			len = *ext++;

			switch (opt) {
			case 1:	/* subnet mask */
				if (len == 4)
					memcpy(&dev->ip_netmask, ext, 4);
				break;
			case 3:	/* default gateway */
				if (len >= 4)
					memcpy(&dev->ip_gateway, ext, 4);
				break;
			case 6:	/* DNS server */
				if (len >= 4)
					memcpy(&dev->ip_nameserver, ext,
					       len >= 8 ? 8 : 4);
				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)
					memcpy(&dev->ip_broadcast, ext, 4);
				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;
			case 54: 	/* server identifier */
				if (len == 4 && !dev->ip_server)
					memcpy(&dev->ip_server, ext, 4);
				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;
	uint8_t 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 = (uint32_t) lrand48();
	dev->open_time = time(NULL);

	return 0;
}
