Index: include/net.h
===================================================================
--- include/net.h	(revision 4)
+++ include/net.h	(working copy)
@@ -341,6 +341,10 @@
 /* from net/net.c */
 extern char	BootFile[128];			/* Boot File name		*/
 
+#if (CONFIG_COMMANDS & CFG_CMD_DNS)
+extern char	NetDNSResolve[255];			/* The host to resolve	*/
+#endif
+
 #if (CONFIG_COMMANDS & CFG_CMD_PING)
 extern IPaddr_t	NetPingIP;			/* the ip address to ping 		*/
 #endif
Index: include/cmd_confdefs.h
===================================================================
--- include/cmd_confdefs.h	(revision 4)
+++ include/cmd_confdefs.h	(working copy)
@@ -94,6 +94,7 @@
 #define CFG_CMD_EXT2	0x1000000000000000ULL	/* EXT2 Support			*/
 #define CFG_CMD_SNTP	0x2000000000000000ULL	/* SNTP support			*/
 #define CFG_CMD_DISPLAY	0x4000000000000000ULL	/* Display support		*/
+#define CFG_CMD_DNS	0x8000000000000000ULL	/* DNS support			*/
 
 #define CFG_CMD_ALL	0xFFFFFFFFFFFFFFFFULL	/* ALL commands			*/
 
Index: net/dns.c
===================================================================
--- net/dns.c	(revision 0)
+++ net/dns.c	(revision 0)
@@ -0,0 +1,213 @@
+/*
+ * DNS support driver
+ *
+ * Copyright (c) 2008 Pieter Voorthuijsen <pieter.voorthuijsen@prodrive.nl>
+ *
+ * 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 TFTP
+ * transfer.
+ *
+ * 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 <rtc.h>
+
+#include "dns.h"
+
+#if ((CONFIG_COMMANDS & CFG_CMD_NET) && (CONFIG_COMMANDS & CFG_CMD_DNS))
+
+static int DnsOurPort;
+
+static void
+DnsSend (void)
+{
+	int sport;
+	struct header	*header;
+	int		i, n, name_len;
+	char	pkt[DNS_PACKET_LEN], *p;
+	const char 	*s;
+	char	IP_Str[50];
+	const char *name;
+	enum dns_query_type qtype = DNS_A_RECORD;
+
+	name = NetDNSResolve;
+
+	/* Prepare DNS packet header */
+	header		= (struct header *) pkt;
+	header->tid	= 1;
+	header->flags	= htons(0x100);		/* Haha. guess what it is */
+	header->nqueries= htons(1);		/* Just one query */
+	header->nanswers= 0;
+	header->nauth	= 0;
+	header->nother	= 0;
+
+	/* Encode DNS name */
+	name_len = strlen(name);
+	p = (char *) &header->data;	/* For encoding host name into packet */
+
+	do {
+		if ((s = strchr(name, '.')) == NULL)
+			s = name + name_len;
+
+		n = s - name;			/* Chunk length */
+		*p++ = n;				/* Copy length */
+		for (i = 0; i < n; i++)	/* Copy chunk */
+			*p++ = name[i];
+
+		if (*s == '.')
+			n++;
+
+		name += n;
+		name_len -= n;
+	} while (*s != '\0');
+
+	*p++ = 0;						/* Mark end of host name */
+	*p++ = 0;						/* Well, lets put this byte as well */
+	*p++ = (unsigned char) qtype;	/* Query Type */
+
+	*p++ = 0;
+	*p++ = 1;						/* Class: inet, 0x0001 */
+
+	n = p - pkt;					/* Total packet length */
+	dbg("Packet size %d\n", n);
+
+	memcpy ((char *)NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE, (char *)&pkt, n);
+
+	DnsOurPort = 10000 + (get_timer(0) % 4096);
+	sport = DNS_SERVICE_PORT;
+
+	ip_to_string(NetOurDNSIP, IP_Str);
+	dbg("DNS ip %s\n", IP_Str);
+
+	NetSendUDPPacket (NetServerEther, NetOurDNSIP, sport, DnsOurPort, n);
+	dbg("DNS packet sent\n");
+}
+
+static void
+DnsTimeout (void)
+{
+	puts ("Timeout\n");
+	NetState = NETLOOP_FAIL;
+	return;
+}
+
+static void
+DnsHandler (uchar *pkt, unsigned dest, unsigned src, unsigned len)
+{
+	struct header		*header;
+	const unsigned char	*p, *e, *s;
+
+	uint16_t		type;
+	volatile 	uint16_t		i;
+	int			found, stop, dlen, nlen;
+	char		IPStr[255];
+	IPaddr_t	IPAddress;
+
+
+	dbg("%s\n", __FUNCTION__);
+	if (dest != DnsOurPort) return;
+
+	for(i=0;i<len;i+=4)
+		dbg("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) {
+		dbg("DNS server returned no answers\n");
+		return;
+	}
+
+	/* Skip host name */
+	for (e = pkt + len, nlen = 0, s = p = &header->data[0];
+	    p < e && *p != '\0'; p++)
+			nlen++;
+
+#define	NTOHS(p)	(((p)[0] << 8) | (p)[1])
+
+	/* We sent query class 1, query type 1 */
+	if (&p[5] > e || NTOHS(p + 1) != DNS_A_RECORD) {
+		dbg("Query was not A record\n");
+		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--;
+		}
+		dbg("Name (Offset in header): %d\n", p[1]);
+
+		type = NTOHS(p+2);
+		dbg("type = %d\n", type);
+		if (type == 5) {
+			/* CNAME answer. shift to the next section */
+			dbg("Found canonical name\n");
+			dlen = NTOHS(p+10);
+			dbg("dlen = %d\n", dlen);
+			p += 12 + dlen;
+		} else if (type == DNS_A_RECORD) {
+			dbg("Found A-record\n");
+			found = stop = 1;
+		} else {
+			dbg("Unknown type\n");
+			stop = 1;
+		}
+	}
+
+	if (found && &p[12] < e) {
+
+		dlen = NTOHS(p+10);
+		p += 12;
+		memcpy(&IPAddress, p, 4);
+
+		if (p + dlen <= e) {
+			ip_to_string (IPAddress, IPStr);
+			NetServerIP = IPAddress;
+			setenv("serverip", IPStr);
+			printf("%s\n", IPStr);
+		}
+		else
+			return;
+	}
+
+	NetState = NETLOOP_SUCCESS;
+}
+
+void
+DnsStart (void)
+{
+	debug ("%s\n", __FUNCTION__);
+
+	NetSetTimeout (DNS_TIMEOUT * CFG_HZ, DnsTimeout);
+	NetSetHandler(DnsHandler);
+	memset (NetServerEther, 0, 6);
+
+	DnsSend ();
+}
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_DNS */
Index: net/net.c
===================================================================
--- net/net.c	(revision 4)
+++ net/net.c	(working copy)
@@ -89,6 +89,9 @@
 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
 #include "sntp.h"
 #endif
+#if (CONFIG_COMMANDS & CFG_CMD_DNS)
+#include "dns.h"
+#endif
 
 #if (CONFIG_COMMANDS & CFG_CMD_NET)
 
@@ -150,6 +153,10 @@
 
 char		BootFile[128];		/* Boot File name			*/
 
+#if (CONFIG_COMMANDS & CFG_CMD_DNS)
+char	NetDNSResolve[255];			/* The host to resolve	*/
+#endif
+
 #if (CONFIG_COMMANDS & CFG_CMD_PING)
 IPaddr_t	NetPingIP;		/* the ip address to ping 		*/
 
@@ -335,6 +342,10 @@
 #if (CONFIG_COMMANDS & CFG_CMD_SNTP)
 	case SNTP:
 #endif
+#if (CONFIG_COMMANDS & CFG_CMD_DNS)
+	case DNS:
+		NetOurDNSIP = getenv_IPaddr ("dnsip");
+#endif
 	case NETCONS:
 	case TFTP:
 		NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
@@ -450,6 +461,11 @@
 			SntpStart();
 			break;
 #endif
+#if (CONFIG_COMMANDS & CFG_CMD_DNS)
+		case DNS:
+			DnsStart();
+			break;
+#endif
 		default:
 			break;
 		}
@@ -1512,6 +1528,14 @@
 		}
 		goto common;
 #endif
+#if (CONFIG_COMMANDS & CFG_CMD_DNS)
+	case DNS:
+		if (NetOurDNSIP == 0) {
+			puts ("*** ERROR: DNS server address not given\n");
+			return (1);
+		}
+		goto common;
+#endif
 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
 	case NFS:
 #endif
Index: net/dns.h
===================================================================
--- net/dns.h	(revision 0)
+++ net/dns.h	(revision 0)
@@ -0,0 +1,35 @@
+/*
+ * (C) Masami Komiya <mkomiya@sonare.it> 2005
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ */
+
+#ifndef __DNS_H__
+#define __DNS_H__
+
+#define DNS_SERVICE_PORT	53
+#define	DNS_MAX				1025	/* Maximum host name */
+#define	DNS_PACKET_LEN		2048	/* Buffer size for DNS packet */
+#define DNS_TIMEOUT			5
+
+enum dns_query_type {DNS_A_RECORD = 0x01, DNS_MX_RECORD = 0x0f};
+
+/*
+ * DNS network packet
+ */
+struct header {
+	uint16_t	tid;		/* Transaction ID */
+	uint16_t	flags;		/* Flags */
+	uint16_t	nqueries;	/* Questions */
+	uint16_t	nanswers;	/* Answers */
+	uint16_t	nauth;		/* Authority PRs */
+	uint16_t	nother;		/* Other PRs */
+	unsigned char	data[1];	/* Data, variable length */
+};
+
+extern void	DnsStart (void);	/* Begin DNS */
+
+#endif /* __SNTP_H__ */
Index: net/Makefile
===================================================================
--- net/Makefile	(revision 4)
+++ net/Makefile	(working copy)
@@ -27,7 +27,7 @@
 
 LIB	= $(obj)libnet.a
 
-COBJS	= net.o tftp.o bootp.o rarp.o eth.o nfs.o sntp.o
+COBJS	= net.o tftp.o bootp.o rarp.o eth.o nfs.o sntp.o dns.o
 
 SRCS	:= $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
Index: common/cmd_net.c
===================================================================
--- common/cmd_net.c	(revision 4)
+++ common/cmd_net.c	(working copy)
@@ -329,5 +329,31 @@
 	"[NTP server IP]\n"
 );
 #endif	/* CFG_CMD_SNTP */
+#if (CONFIG_COMMANDS & CFG_CMD_DNS)
+int do_dns (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	if (argc < 2)
+		return -1;
 
+	if (strlen(argv[1]) > sizeof(NetDNSResolve)) {
+		printf ("Name too long.\n");
+		return -1;
+	}
+
+	strcpy(NetDNSResolve, argv[1]);
+
+	if (NetLoop(DNS) < 0) {
+		printf("DNS failed, check setup\n", argv[1]);
+		return 1;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	dns,	2,	1,	do_dns,
+	"dns\t- Request the IP of a hostname\n",
+	"www.example.nl\n"
+);
+#endif	/* CFG_CMD_DNS */
 #endif	/* CFG_CMD_NET */
