/*
 * DNS support driver
 *
 * Copyright (c) 2008 Pieter Voorthuijsen <pieter.voorthuijsen@prodrive.nl>
 * Copyright (c) 2009 Robin Getz <rgetz@blackfin.uclinux.org>
 *
 * This is a simple DNS implementation for U-Boot. It will use the first IP
 * in the DNS response as NetServerIP. This can then be used for any other
 * network related activities.
 *
 * The packet handling is partly based on TADNS, original copyrights
 * follow below.
 *
 */

/*
 * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
 *
 * "THE BEER-WARE LICENSE" (Revision 42):
 * Sergey Lyubka wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.
 */

#include <common.h>
#include <command.h>
#include <net.h>

#include "dns.h"

char *NetDNSResolve;	/* The host to resolve  */
char *NetDNSenvvar;	/* The envvar to store the answer in */

static int DnsOurPort;

static void
DnsSend(void)
{
	struct header *header;
	int n, name_len;
	uchar *p, *pkt;
	const char *s;
	const char *name;
	enum dns_query_type qtype = DNS_A_RECORD;

	name = NetDNSResolve;
	pkt = p = (uchar *)(NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE);

	/* Prepare DNS packet header */
	header           = (struct header *) pkt;
	header->tid      = 1;
	header->flags    = htons(0x100);	/* standard query */
	header->nqueries = htons(1);		/* Just one query */
	header->nanswers = 0;
	header->nauth    = 0;
	header->nother   = 0;

	/* Encode DNS name */
	name_len = strlen(name);
	p = (uchar *) &header->data;	/* For encoding host name into packet */

	do {
		s = strchr(name, '.');
		if (!s)
			s = name + name_len;

		n = s - name;			/* Chunk length */
		*p++ = n;			/* Copy length  */
		memcpy(p, name, n);		/* Copy chunk   */
		p += n;

		if (*s == '.')
			n++;

		name += n;
		name_len -= n;
	} while (*s != '\0');

	*p++ = 0;			/* Mark end of host name */
	*p++ = 0;			/* Some servers require double null */
	*p++ = (unsigned char) qtype;	/* Query Type */

	*p++ = 0;
	*p++ = 1;				/* Class: inet, 0x0001 */

	n = p - pkt;				/* Total packet length */
	debug("Packet size %d\n", n);

	DnsOurPort = random_port();

	NetSendUDPPacket(NetServerEther, NetOurDNSIP, DNS_SERVICE_PORT,
		DnsOurPort, n);
	debug("DNS packet sent\n");
}

static void
DnsTimeout(void)
{
	puts("Timeout\n");
	NetState = NETLOOP_FAIL;
}

static void
DnsHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src, unsigned len)
{
	struct header *header;
	const unsigned char *p, *e, *s;
	u16 type, i;
	int found, stop, dlen;
	char IPStr[22];
	IPaddr_t IPAddress;
	short tmp;


	debug("%s\n", __func__);
	if (dest != DnsOurPort)
		return;

	for (i = 0; i < len; i += 4)
		debug("0x%p - 0x%.2x  0x%.2x  0x%.2x  0x%.2x\n",
			pkt+i, pkt[i], pkt[i+1], pkt[i+2], pkt[i+3]);

	/* We sent 1 query. We want to see more that 1 answer. */
	header = (struct header *) pkt;
	if (ntohs(header->nqueries) != 1)
		return;

	/* Received 0 answers */
	if (header->nanswers == 0) {
		puts("DNS server returned no answers\n");
		NetState = NETLOOP_SUCCESS;
		return;
	}

	/* Skip host name */
	s = &header->data[0];
	e = pkt + len;
	for (p = s; p < e && *p != '\0'; p++)
		continue;

	/* We sent query class 1, query type 1 */
	tmp = p[1] | (p[2] << 8);
	if (&p[5] > e || ntohs(tmp) != DNS_A_RECORD) {
		puts("DNS response was not A record\n");
		NetState = NETLOOP_SUCCESS;
		return;
	}

	/* Go to the first answer section */
	p += 5;

	/* Loop through the answers, we want A type answer */
	for (found = stop = 0; !stop && &p[12] < e; ) {

		/* Skip possible name in CNAME answer */
		if (*p != 0xc0) {
			while (*p && &p[12] < e)
				p++;
			p--;
		}
		debug("Name (Offset in header): %d\n", p[1]);

		tmp = p[2] | (p[3] << 8);
		type = ntohs(tmp);
		debug("type = %d\n", type);
		if (type == DNS_CNAME_RECORD) {
			/* CNAME answer. shift to the next section */
			debug("Found canonical name\n");
			tmp = p[10] | (p[11] << 8);
			dlen = ntohs(tmp);
			debug("dlen = %d\n", dlen);
			p += 12 + dlen;
		} else if (type == DNS_A_RECORD) {
			debug("Found A-record\n");
			found = stop = 1;
		} else {
			debug("Unknown type\n");
			stop = 1;
		}
	}

	if (found && &p[12] < e) {

		tmp = p[10] | (p[11] << 8);
		dlen = ntohs(tmp);
		p += 12;
		memcpy(&IPAddress, p, 4);

		if (p + dlen <= e) {
			ip_to_string(IPAddress, IPStr);
			printf("%s\n", IPStr);
			if (NetDNSenvvar)
				setenv(NetDNSenvvar, IPStr);
		} else
			puts("server responded with invalid IP number\n");
	}

	NetState = NETLOOP_SUCCESS;
}

void
DnsStart(void)
{
	debug("%s\n", __func__);

	NetSetTimeout(DNS_TIMEOUT, DnsTimeout);
	NetSetHandler(DnsHandler);

	DnsSend();
}
