On 04 Oct 2008 Pieter posted a dns implementation for U-Boot. http://www.mail-archive.com/u-boot-us...@lists.sourceforge.net/msg10216.html
> DNS can be enabled by setting CFG_CMD_DNS. After performing a query, the > serverip environment var is updated. > > Probably there are some cosmetic issues with the patch. Unfortunatly I do > not have the time to correct these. So if anybody else likes DNS support in > U-Boot and has the time, feel free to patch it in the main tree. Here it is again - slightly modified & smaller: - update to 2009-06 (Pieter's patch was for U-Boot 1.2.0) - run through checkpatch, and clean up style issues - remove packet from stack - cleaned up some comments - failure returns much faster (if server responds, don't wait for timeout) - use built in functions (memcpy) rather than byte copy. bfin> dhcp BOOTP broadcast 1 DHCP client bound to address 192.168.0.4 bfin> dns pool.ntp.org 69.36.241.112 bfin> sntp $(serverip) Date: 2009-07-17 Time: 19:16:51 bfin> dns www.google.com 64.233.161.147 bfin> ping $(serverip) Using Blackfin EMAC device host 64.233.161.147 is alive Signed-off-by: Robin Getz <rg...@blackfin.uclinux.org> Signed-off-by: Pieter Voorthuijsen <pieter.voorthuij...@prodrive.nl> common/cmd_net.c | 32 ++++ include/configs/bfin_adi_common.h | 7 include/net.h | 4 net/Makefile | 1 net/dns.c | 213 ++++++++++++++++++++++++++++ net/dns.h | 38 ++++ net/net.c | 20 ++ 7 files changed, 314 insertions(+), 1 deletion(-) --- Index: include/net.h =================================================================== --- include/net.h (revision 1968) +++ include/net.h (working copy) @@ -361,6 +361,10 @@ /* from net/net.c */ extern char BootFile[128]; /* Boot File name */ +#if defined(CONFIG_CMD_DNS) +extern char NetDNSResolve[255]; /* The host to resolve */ +#endif + #if defined(CONFIG_CMD_PING) extern IPaddr_t NetPingIP; /* the ip address to ping */ #endif Index: include/configs/bfin_adi_common.h =================================================================== --- include/configs/bfin_adi_common.h (revision 1968) +++ include/configs/bfin_adi_common.h (working copy) @@ -13,6 +13,13 @@ # if ADI_CMDS_NETWORK # define CONFIG_CMD_DHCP # define CONFIG_CMD_PING +# define CONFIG_BOOTP_DNS +# define CONFIG_BOOTP_DNS2 +# define CONFIG_CMD_DNS +# ifdef CONFIG_RTC_BFIN +# define CONFIG_CMD_SNTP +# define CONFIG_BOOTP_NTPSERVER +# endif # ifdef CONFIG_BFIN_MAC # define CONFIG_CMD_MII # endif 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.voorthuij...@prodrive.nl> + * Copyright (c) 2009 Robin Getz <rg...@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 <vale...@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[255]; /* The host to resolve */ + +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; /* 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 */ + debug("Packet size %d\n", n); + + DnsOurPort = 10000 + (get_timer(0) % 4096); + + 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, unsigned src, unsigned len) +{ + struct header *header; + const unsigned char *p, *e, *s; + u16 type, i; + int found, stop, dlen; + char IPStr[255]; + 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) { + debug("DNS server returned no answers\n"); + puts("server can't find hostname\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) { + debug("Query was not A record\n"); + puts("server can't find IP number of hostname\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); + NetServerIP = IPAddress; + setenv("serverip", IPStr); + printf("%s\n", 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); + memset(NetServerEther, 0, 6); + + DnsSend(); +} + Index: net/net.c =================================================================== --- net/net.c (revision 1968) +++ net/net.c (working copy) @@ -92,6 +92,9 @@ #if defined(CONFIG_CDP_VERSION) #include <timestamp.h> #endif +#if defined(CONFIG_CMD_DNS) +#include "dns.h" +#endif #if defined(CONFIG_CMD_NET) @@ -165,7 +168,6 @@ ushort NetOurNativeVLAN = 0xFFFF; /* ditto */ char BootFile[128]; /* Boot File name */ - #if defined(CONFIG_CMD_PING) IPaddr_t NetPingIP; /* the ip address to ping */ @@ -291,6 +293,9 @@ NetServerIP = getenv_IPaddr ("serverip"); NetOurNativeVLAN = getenv_VLAN("nvlan"); NetOurVLAN = getenv_VLAN("vlan"); +#if defined(CONFIG_CMD_DNS) + NetOurDNSIP = getenv_IPaddr("dnsip"); +#endif env_changed_id = env_id; } @@ -426,6 +432,11 @@ SntpStart(); break; #endif +#if defined(CONFIG_CMD_DNS) + case DNS: + DnsStart(); + break; +#endif default: break; } @@ -1518,6 +1529,14 @@ } goto common; #endif +#if defined(CONFIG_CMD_DNS) + case DNS: + if (NetOurDNSIP == 0) { + puts("*** ERROR: DNS server address not given\n"); + return 1; + } + goto common; +#endif #if defined(CONFIG_CMD_NFS) case NFS: #endif Index: net/dns.h =================================================================== --- net/dns.h (revision 0) +++ net/dns.h (revision 0) @@ -0,0 +1,39 @@ +/* + * (C) Masami Komiya <mkom...@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_TIMEOUT 10000UL + +/* http://en.wikipedia.org/wiki/List_of_DNS_record_types */ +enum dns_query_type { + DNS_A_RECORD = 0x01, + DNS_CNAME_RECORD = 0x05, + 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 Index: net/Makefile =================================================================== --- net/Makefile (revision 1968) +++ net/Makefile (working copy) @@ -34,6 +34,7 @@ COBJS-y += eth.o COBJS-y += nfs.o COBJS-$(CONFIG_CMD_SNTP) += sntp.o +COBJS-$(CONFIG_CMD_DNS) += dns.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) Index: common/cmd_net.c =================================================================== --- common/cmd_net.c (revision 1968) +++ common/cmd_net.c (working copy) @@ -353,3 +353,35 @@ "[NTP server IP]\n" ); #endif + +#if defined(CONFIG_CMD_DNS) +int do_dns(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if (argc < 2) { + cmd_usage(cmdtp); + return -1; + } + + if (strlen(argv[1]) > sizeof(NetDNSResolve) - 1) { + puts("Name too long.\n"); + return -1; + } + + strcpy(NetDNSResolve, argv[1]); + + if (NetLoop(DNS) < 0) { + printf("dns lookup of %s failed, check setup\n", argv[1]); + return 1; + } + + return 0; +} + +U_BOOT_CMD( + dns, 2, 1, do_dns, + "lookup the IP of a hostname", + "[machine to lookup]\n" +); + +#endif /* CONFIG_CMD_DNS */ + _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot