/*
 * 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 <asm/unaligned.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_UDP_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");
	net_set_state(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;


	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 one query. We want to have a single answer: */
	header = (struct header *) pkt;
	if (ntohs(header->nqueries) != 1)
		return;

	/* Received 0 answers */
	if (header->nanswers == 0) {
		puts("DNS: host not found\n");
		net_set_state(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 */
	if (&p[5] > e || get_unaligned_be16(p+1) != DNS_A_RECORD) {
		puts("DNS: response was not an A record\n");
		net_set_state(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]);

		type = get_unaligned_be16(p+2);
		debug("type = %d\n", type);
		if (type == DNS_CNAME_RECORD) {
			/* CNAME answer. shift to the next section */
			debug("Found canonical name\n");
			dlen = get_unaligned_be16(p+10);
			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) {

		dlen = get_unaligned_be16(p+10);
		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");
	}

	net_set_state(NETLOOP_SUCCESS);
}

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

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

	DnsSend();
}
