* [U-Boot] [PATCH] - add dns
@ 2009-07-17 19:53 Robin Getz
2009-07-17 20:55 ` Wolfgang Denk
2009-07-20 18:53 ` [U-Boot] [PATCH] v3 " Robin Getz
0 siblings, 2 replies; 16+ messages in thread
From: Robin Getz @ 2009-07-17 19:53 UTC (permalink / raw)
To: u-boot
On 04 Oct 2008 Pieter posted a dns implementation for U-Boot.
http://www.mail-archive.com/u-boot-users at 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 <rgetz@blackfin.uclinux.org>
Signed-off-by: Pieter Voorthuijsen <pieter.voorthuijsen@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.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[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 <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_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 */
+
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-17 19:53 [U-Boot] [PATCH] - add dns Robin Getz
@ 2009-07-17 20:55 ` Wolfgang Denk
2009-07-17 21:45 ` Robin Getz
2009-07-18 1:20 ` Robin Getz
2009-07-20 18:53 ` [U-Boot] [PATCH] v3 " Robin Getz
1 sibling, 2 replies; 16+ messages in thread
From: Wolfgang Denk @ 2009-07-17 20:55 UTC (permalink / raw)
To: u-boot
Dear Robin Getz,
In message <200907171553.08108.rgetz@blackfin.uclinux.org> you wrote:
> On 04 Oct 2008 Pieter posted a dns implementation for U-Boot.
>
> http://www.mail-archive.com/u-boot-users at 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
Note that the use of "$(...)" is deprecated. Please use "${...}"
instead,
> Signed-off-by: Robin Getz <rgetz@blackfin.uclinux.org>
> Signed-off-by: Pieter Voorthuijsen <pieter.voorthuijsen@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(-)
You probably should add a doc/README.* file to explain how that is
supposed to be used.
> Index: include/net.h
> ===================================================================
> --- include/net.h (revision 1968)
> +++ include/net.h (working copy)
Could you generate a git patch instead?
> @@ -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
Can this buffer overflow?
> 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>
> + * 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.
Hmmm... why do you assume that the address we're trying to resolve is
the server IP?
To me it makes at least as much sense to resolve the "ipaddr" value.
> +char NetDNSResolve[255]; /* The host to resolve */
See above.
> +static int DnsOurPort;
> +
> +static void
> +DnsSend(void)
> +{
...
> + 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 */
Why that?
> +static void
> +DnsHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len)
> +{
...
> + /* Received 0 answers */
> + if (header->nanswers == 0) {
> + debug("DNS server returned no answers\n");
> + puts("server can't find hostname\n");
Debug and regular output are redundant. Omit the debug().
Actually I recommend to use the debug() message text, which is IMO
more precise.
> + 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");
Ditto.
> + if (p + dlen <= e) {
> + ip_to_string(IPAddress, IPStr);
> + NetServerIP = IPAddress;
> + setenv("serverip", IPStr);
I object to this part. I think it is a very bad idea to meddle with
the NetServerIP and "serverip" settings here - this may be wanted by
the user, or maybe not.
I am aware that we don't have an easy way of passing results from a
command back to U-Boot's "shell", so I suggest a syntactical change,
see below.
> 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
Please keep list sorted.
> Index: common/cmd_net.c
> ===================================================================
> --- common/cmd_net.c (revision 1968)
> +++ common/cmd_net.c (working copy)
...
> +U_BOOT_CMD(
> + dns, 2, 1, do_dns,
> + "lookup the IP of a hostname",
> + "[machine to lookup]\n"
> +);
I suggest to change "machine to lookup" into "hostname".
Hmmm... is this argument really optional as the brackets suggest? I
don't think so. And why do you allow for 2 arguments? And the newline
is bogus, too.
I suggest to change this as follows:
U_BOOT_CMD(
dns, 2, 1, do_dns,
"lookup the IP of a hostname",
"hostname [envvar]"
);
If you use the command with one argument (just the host name to look
up), it will only print the result, like this:
=> dns www.denx.de
85.214.87.163
Note that this command does NOT change any environment settings!
To do the equivalent of your implementation, you have to tell the
command the name of the environment variable where trhe result (if
any) shall be stored:
=> dns www.denx.de serverip
85.214.87.163
In this case the command will print the result _and_ store the value
in the environment variable given on the command line. This seems more
flexible to me, as I can then also do things like
=> dns ${hostname} ipaddr
etc.
What do you think?
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Killing is wrong.
-- Losira, "That Which Survives", stardate unknown
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-17 20:55 ` Wolfgang Denk
@ 2009-07-17 21:45 ` Robin Getz
2009-07-17 22:01 ` Wolfgang Denk
2009-07-18 1:20 ` Robin Getz
1 sibling, 1 reply; 16+ messages in thread
From: Robin Getz @ 2009-07-17 21:45 UTC (permalink / raw)
To: u-boot
On Fri 17 Jul 2009 16:55, Wolfgang Denk pondered:
> Dear Robin Getz,
>
> In message <200907171553.08108.rgetz@blackfin.uclinux.org> you wrote:
> > On 04 Oct 2008 Pieter posted a dns implementation for U-Boot.
> >
> > http://www.mail-archive.com/u-boot-users at 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
>
> Note that the use of "$(...)" is deprecated. Please use "${...}"
> instead,
OK.
> > Signed-off-by: Robin Getz <rgetz@blackfin.uclinux.org>
> > Signed-off-by: Pieter Voorthuijsen <pieter.voorthuijsen@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(-)
>
> You probably should add a doc/README.* file to explain how that is
> supposed to be used.
Will do.
What is the rule for when things go in ./doc/README.* vs ./README ?
> > Index: include/net.h
> > ===================================================================
> > --- include/net.h (revision 1968)
> > +++ include/net.h (working copy)
>
> Could you generate a git patch instead?
Sure - I'll generate something from the net tree?
> > @@ -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
>
> Can this buffer overflow?
Shouldn't.
+ if (strlen(argv[1]) > sizeof(NetDNSResolve) - 1) {
+ puts("Name too long.\n");
+ return -1;
+ }
+
> > 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>
> > + * 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.
>
> Hmmm... why do you assume that the address we're trying to resolve is
> the server IP?
>
> To me it makes at least as much sense to resolve the "ipaddr" value.
Yeah, this was my biggest issue for things too (from the original patch).
but you can easily :
set nameip ${serverip}
to transfer it to something else. - or just use it directly.
Originally I thought about dnsip, but that pre-existing, and is used to store
the nameserver ip (which is poorly named IMHO).
any better suggestions welcome.
> > +char NetDNSResolve[255]; /* The host to resolve */
>
> See above.
See answer :)
> > +static int DnsOurPort;
> > +
> > +static void
> > +DnsSend(void)
> > +{
> ...
> > + 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 */
>
> Why that?
No idea - that was in the original....
Hmm -- according to my TCP/IP Illustrated - names are suppost to be double
null terminated - so I think that is a requirement.
> > +static void
> > +DnsHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len)
> > +{
> ...
> > + /* Received 0 answers */
> > + if (header->nanswers == 0) {
> > + debug("DNS server returned no answers\n");
> > + puts("server can't find hostname\n");
>
> Debug and regular output are redundant. Omit the debug().
> Actually I recommend to use the debug() message text, which is IMO
> more precise.
No problem.
> > + 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");
>
> Ditto.
>
> > + if (p + dlen <= e) {
> > + ip_to_string(IPAddress, IPStr);
> > + NetServerIP = IPAddress;
> > + setenv("serverip", IPStr);
>
> I object to this part. I think it is a very bad idea to meddle with
> the NetServerIP and "serverip" settings here - this may be wanted by
> the user, or maybe not.
>
> I am aware that we don't have an easy way of passing results from a
> command back to U-Boot's "shell", so I suggest a syntactical change,
> see below.
OK.
> > 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
>
> Please keep list sorted.
OK
> > Index: common/cmd_net.c
> > ===================================================================
> > --- common/cmd_net.c (revision 1968)
> > +++ common/cmd_net.c (working copy)
> ...
> > +U_BOOT_CMD(
> > + dns, 2, 1, do_dns,
> > + "lookup the IP of a hostname",
> > + "[machine to lookup]\n"
> > +);
>
> I suggest to change "machine to lookup" into "hostname".
OK
> Hmmm... is this argument really optional as the brackets suggest? I
> don't think so. And why do you allow for 2 arguments? And the newline
> is bogus, too.
Yeah, sorry - I don't completely grok the U-Boot help syntax. I'll fix.
> I suggest to change this as follows:
>
> U_BOOT_CMD(
> dns, 2, 1, do_dns,
> "lookup the IP of a hostname",
> "hostname [envvar]"
> );
>
> If you use the command with one argument (just the host name to look
> up), it will only print the result, like this:
>
> => dns www.denx.de
> 85.214.87.163
>
> Note that this command does NOT change any environment settings!
>
> To do the equivalent of your implementation, you have to tell the
> command the name of the environment variable where trhe result (if
> any) shall be stored:
>
> => dns www.denx.de serverip
> 85.214.87.163
>
> In this case the command will print the result _and_ store the value
> in the environment variable given on the command line. This seems more
> flexible to me, as I can then also do things like
>
> => dns ${hostname} ipaddr
>
> etc.
>
> What do you think?
that is more flexible that the current implementation...
but also a little more complex.
saving it in a predefined env var (like 'dnshostip') is also OK.
dns www.denx.de
set serverip ${dnshostip}
-- is going to be a little smaller...
Up to you...
-Robin
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-17 21:45 ` Robin Getz
@ 2009-07-17 22:01 ` Wolfgang Denk
2009-07-17 23:19 ` Robin Getz
2009-07-18 5:14 ` Robin Getz
0 siblings, 2 replies; 16+ messages in thread
From: Wolfgang Denk @ 2009-07-17 22:01 UTC (permalink / raw)
To: u-boot
Dear Robin Getz,
In message <200907171745.36176.rgetz@blackfin.uclinux.org> you wrote:
>
> > You probably should add a doc/README.* file to explain how that is
> > supposed to be used.
>
> Will do.
>
> What is the rule for when things go in ./doc/README.* vs ./README ?
Size - anything that takes more than 5...10 lines ?
> > Could you generate a git patch instead?
>
> Sure - I'll generate something from the net tree?
Please use the mainline repo / "master" branch as reference.
> > > +#if defined(CONFIG_CMD_DNS)
> > > +extern char NetDNSResolve[255]; /* The host to resolve */
> > > +#endif
> >
> > Can this buffer overflow?
>
> Shouldn't.
Agreed. I've seen the tests later in the code but forgot to remove
this.
...
> > Hmmm... why do you assume that the address we're trying to resolve is
> > the server IP?
> >
> > To me it makes at least as much sense to resolve the "ipaddr" value.
>
> Yeah, this was my biggest issue for things too (from the original patch).
>
> but you can easily :
>
> set nameip ${serverip}
>
> to transfer it to something else. - or just use it directly.
But you lost the original "serverip" setting, which may not be wanted.
> > > + *p++ = 0; /* Mark end of host name */
> > > + *p++ = 0; /* Well, lets put this byte as well */
> >
> > Why that?
>
> No idea - that was in the original....
>
> Hmm -- according to my TCP/IP Illustrated - names are suppost to be double
> null terminated - so I think that is a requirement.
Then please remove the comment that automatically triggers such "why
that?" questions (and eventually replace it with a better
explanation).
> > I suggest to change this as follows:
...
> > What do you think?
>
> that is more flexible that the current implementation...
Indeed :-)
> but also a little more complex.
Not really. Yes, you have to add 3 lines of code to check for the 2nd
argument, butexcept from that you just change the
setenv("serverip", IPStr);
into
setenv(argvp, IPStr);
> saving it in a predefined env var (like 'dnshostip') is also OK.
>
> dns www.denx.de
> set serverip ${dnshostip}
>
> -- is going to be a little smaller...
>
> Up to you...
I like my proposal better, as it avoids adding another predefined env
var which is of not much use to most users, as it will only serve as
temp storage; and your proposal requires a second command, i. e. more
typing and thus more chances for typos.
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The Wright Bothers weren't the first to fly. They were just the first
not to crash.
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-17 22:01 ` Wolfgang Denk
@ 2009-07-17 23:19 ` Robin Getz
2009-07-18 5:14 ` Robin Getz
1 sibling, 0 replies; 16+ messages in thread
From: Robin Getz @ 2009-07-17 23:19 UTC (permalink / raw)
To: u-boot
On Fri 17 Jul 2009 18:01, Wolfgang Denk pondered:
> Dear Robin Getz,
>
> In message <200907171745.36176.rgetz@blackfin.uclinux.org> you wrote:
> >
> > > You probably should add a doc/README.* file to explain how that is
> > > supposed to be used.
> >
> > Will do.
> >
> > What is the rule for when things go in ./doc/README.* vs ./README ?
>
> Size - anything that takes more than 5...10 lines ?
>
> > > Could you generate a git patch instead?
> >
> > Sure - I'll generate something from the net tree?
>
> Please use the mainline repo / "master" branch as reference.
Sure - but master's dhcp does not work for me until unassigned-patches/39 is
applied.
http://bugs.denx.de/databases/u-boot/prs/39
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-17 20:55 ` Wolfgang Denk
2009-07-17 21:45 ` Robin Getz
@ 2009-07-18 1:20 ` Robin Getz
2009-07-19 7:48 ` Wolfgang Denk
1 sibling, 1 reply; 16+ messages in thread
From: Robin Getz @ 2009-07-18 1:20 UTC (permalink / raw)
To: u-boot
On Fri 17 Jul 2009 16:55, Wolfgang Denk pondered:
> > 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
>
> Please keep list sorted.
sorted how? What we have today is:
COBJS-y += net.o
COBJS-y += tftp.o
COBJS-y += bootp.o
COBJS-y += rarp.o
COBJS-y += eth.o
COBJS-y += nfs.o
COBJS-$(CONFIG_CMD_SNTP) += sntp.o
It is not sorted alphabetically... ???
It's not sorted by length???
Seems to be sorted by date added, with the last ones on the bottom.
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-17 22:01 ` Wolfgang Denk
2009-07-17 23:19 ` Robin Getz
@ 2009-07-18 5:14 ` Robin Getz
2009-07-18 22:11 ` Mike Frysinger
1 sibling, 1 reply; 16+ messages in thread
From: Robin Getz @ 2009-07-18 5:14 UTC (permalink / raw)
To: u-boot
On Fri 17 Jul 2009 18:01, Wolfgang Denk pondered:
> Dear Robin Getz,
>
> In message <200907171745.36176.rgetz@blackfin.uclinux.org> you wrote:
> >
> > > You probably should add a doc/README.* file to explain how that is
> > > supposed to be used.
> >
> > Will do.
> >
> > What is the rule for when things go in ./doc/README.* vs ./README ?
>
> Size - anything that takes more than 5...10 lines ?
>
> > > Could you generate a git patch instead?
> >
> > Sure - I'll generate something from the net tree?
>
> Please use the mainline repo / "master" branch as reference.
v2 - based on mainline repo "master"
- implemented feedback from Wolfgang
common/cmd_net.c | 47 ++++++++
doc/README.dns | 64 +++++++++++
include/net.h | 5
net/Makefile | 1
net/dns.c | 212 ++++++++++++++++++++++++++++++++++++++
net/dns.h | 38 ++++++
net/net.c | 19 +++
8 files changed, 393 insertions(+)
-------
diff --git a/common/cmd_net.c b/common/cmd_net.c
index 68183c4..8899143 100644
--- a/common/cmd_net.c
+++ b/common/cmd_net.c
@@ -353,3 +353,50 @@ U_BOOT_CMD(
"[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 == 1) {
+ cmd_usage(cmdtp);
+ return -1;
+ }
+
+ /*
+ * We should check for a valid hostname:
+ * - Each label must be between 1 and 63 characters long
+ * - the entire hostname has a maximum of 255 characters
+ * - only the ASCII letters 'a' through 'z' (case-insensitive),
+ * the digits '0' through '9', and the hyphen
+ * - cannot begin or end with a hyphen
+ * - no other symbols, punctuation characters, or blank spaces are permitted
+ * but hey - this is a minimalist implmentation, so only check length
+ */
+ if (strlen(argv[1]) >= 255) {
+ printf("dns error: hostname too long\n");
+ return 1;
+ }
+
+ NetDNSResolve = argv[1];
+
+ if (argc == 3)
+ NetDNSenvvar = argv[2];
+ else
+ NetDNSenvvar = NULL;
+
+ if (NetLoop(DNS) < 0) {
+ printf("dns lookup of %s failed, check setup\n", argv[1]);
+ return 1;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ dns, 3, 1, do_dns,
+ "lookup the IP of a hostname",
+ "hostname [envvar]"
+);
+
+#endif /* CONFIG_CMD_DNS */
+
diff --git a/doc/README.dns b/doc/README.dns
new file mode 100644
index 0000000..deeccd7
--- /dev/null
+++ b/doc/README.dns
@@ -0,0 +1,64 @@
+Domain Name System
+-------------------------------------------
+
+The Domain Name System (DNS) is a hierarchical naming system for computers,
+services, or any resource participating in the Internet. It associates various
+information with domain names assigned to each of the participants. Most
+importantly, it translates domain names meaningful to humans into the numerical
+(binary) identifiers associated with networking equipment for the purpose of
+locating and addressing these devices world-wide. An often used analogy to
+explain the Domain Name System is that it serves as the "phone book" for the
+Internet by translating human-friendly computer hostnames into IP addresses.
+For example, www.example.com translates to 208.77.188.166.
+
+For more information on DNS - http://en.wikipedia.org/wiki/Domain_Name_System
+
+
+
+U-Boot and DNS
+------------------------------------------
+
+CONFIG_CMD_DNS - controls if the 'dns' command is compiled in. If it is, it
+ will send name lookups to the dns server (env var 'dnsip')
+ Turning this option on will about abou 1k to U-Boot's size.
+
+ Example:
+
+bfin> print dnsip
+dnsip=192.168.0.1
+
+bfin> dns www.google.com
+66.102.1.104
+
+ By default, dns does nothing except print the IP number on
+ the default console - which by itself, would be pretty
+ useless. Adding a third argument to the dns command will
+ use that as the environment variable to be set.
+
+ Example:
+
+bfin> print googleip
+## Error: "googleip" not defined
+bfin> dns www.google.com googleip
+64.233.161.104
+bfin> print googleip
+googleip=64.233.161.104
+bfin> ping ${googleip}
+Using Blackfin EMAC device
+host 64.233.161.104 is alive
+
+ In this way, you can lookup, and set many more meaningful
+ things.
+
+bfin> sntp
+ntpserverip not set
+bfin> dns pool.ntp.org ntpserverip
+72.18.205.156
+bfin> sntp
+Date: 2009-07-18 Time: 4:06:57
+
+ For some helpful things that can be related to DNS in U-Boot,
+ look at the top level README for these config options:
+ CONFIG_CMD_DHCP
+ CONFIG_BOOTP_DNS
+ CONFIG_BOOTP_DNS2
diff --git a/include/net.h b/include/net.h
index 5a1d36e..f66bbab 100644
--- a/include/net.h
+++ b/include/net.h
@@ -361,6 +361,11 @@ typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP
/* from net/net.c */
extern char BootFile[128]; /* Boot File name */
+#if defined(CONFIG_CMD_DNS)
+extern char *NetDNSResolve; /* The host to resolve */
+extern char *NetDNSenvvar; /* the env var to put the ip into */
+#endif
+
#if defined(CONFIG_CMD_PING)
extern IPaddr_t NetPingIP; /* the ip address to ping */
#endif
diff --git a/net/Makefile b/net/Makefile
index d341874..46c75c7 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -33,6 +33,7 @@ COBJS-y += bootp.o
COBJS-y += rarp.o
COBJS-y += eth.o
COBJS-y += nfs.o
+COBJS-$(CONFIG_CMD_DNS) += dns.o
COBJS-$(CONFIG_CMD_SNTP) += sntp.o
COBJS := $(COBJS-y)
diff --git a/net/dns.c b/net/dns.c
new file mode 100644
index 0000000..b813a52
--- /dev/null
+++ b/net/dns.c
@@ -0,0 +1,212 @@
+/*
+ * 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 = 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[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);
+ memset(NetServerEther, 0, 6);
+
+ DnsSend();
+}
+
diff --git a/net/dns.h b/net/dns.h
new file mode 100644
index 0000000..ea69c30
--- /dev/null
+++ b/net/dns.h
@@ -0,0 +1,38 @@
+/*
+ * (C) Masami Komiya <mkomiya@sonare.it> 2005
+ * Copyright 2009, Robin Getz <rgetz@blackfin.uclinux.org>
+ *
+ * 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_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
diff --git a/net/net.c b/net/net.c
index 5637cf5..85dda33 100644
--- a/net/net.c
+++ b/net/net.c
@@ -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)
@@ -291,6 +294,9 @@ NetInitLoop(proto_t protocol)
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 +435,11 @@ restart:
SntpStart();
break;
#endif
+#if defined(CONFIG_CMD_DNS)
+ case DNS:
+ DnsStart();
+ break;
+#endif
default:
break;
}
@@ -1518,6 +1532,14 @@ static int net_check_prereq (proto_t protocol)
}
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
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-18 5:14 ` Robin Getz
@ 2009-07-18 22:11 ` Mike Frysinger
2009-07-19 0:27 ` Robin Getz
0 siblings, 1 reply; 16+ messages in thread
From: Mike Frysinger @ 2009-07-18 22:11 UTC (permalink / raw)
To: u-boot
On Saturday 18 July 2009 01:14:25 Robin Getz wrote:
> + DnsOurPort = 10000 + (get_timer(0) % 4096);
4096 port range seems kind of small. i dont think the requests really need to
be greater than 10000. not sure if services would get pissed about being
below the 1024 limit though, so this is probably better:
1024 + (get_timer() % 0x8000);
keep the modulus something with only 1 bit set so gcc will optimize into a
simple and operation. probably add a comment about it too:
/* make src port a little random, but use something trivial to compute */
> +void
> +DnsStart(void)
> +{
> + NetSetTimeout(DNS_TIMEOUT, DnsTimeout);
> + NetSetHandler(DnsHandler);
> + memset(NetServerEther, 0, 6);
is clearing the ether address really necessary ? if so, why should the dns
code care about it ?
> +/* 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 };
that last }; should be on a line by itself, and the last entry should still
have a comma at the end
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20090718/ceb9e8c5/attachment.pgp
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-18 22:11 ` Mike Frysinger
@ 2009-07-19 0:27 ` Robin Getz
2009-07-19 1:15 ` Mike Frysinger
0 siblings, 1 reply; 16+ messages in thread
From: Robin Getz @ 2009-07-19 0:27 UTC (permalink / raw)
To: u-boot
On Sat 18 Jul 2009 18:11, Mike Frysinger pondered:
> On Saturday 18 July 2009 01:14:25 Robin Getz wrote:
> > + DnsOurPort = 10000 + (get_timer(0) % 4096);
>
> 4096 port range seems kind of small. i dont think the requests really need to
> be greater than 10000. not sure if services would get pissed about being
> below the 1024 limit though, so this is probably better:
> 1024 + (get_timer() % 0x8000);
Sure.
> keep the modulus something with only 1 bit set so gcc will optimize into a
> simple and operation. probably add a comment about it too:
> /* make src port a little random, but use something trivial to compute */
OK - So, this would give three different variations:
net/sntp.c: SntpOurPort = 10000 + (get_timer(0) % 4096);
net/tftp.c: TftpOurPort = 1024 + (get_timer(0) % 3072);
net/nfs.c: NfsOurPort = 4096 + (get_ticks() % 3072);
Does it make sense to have 4 different ones? (not to me)...
Or something new & common in ./net.c:random_port()
Ben?
> > +void
> > +DnsStart(void)
> > +{
> > + NetSetTimeout(DNS_TIMEOUT, DnsTimeout);
> > + NetSetHandler(DnsHandler);
> > + memset(NetServerEther, 0, 6);
>
> is clearing the ether address really necessary ? if so, why should the dns
> code care about it ?
Nope - I can remove that...
> > +/* 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 };
>
> that last }; should be on a line by itself, and the last entry should still
> have a comma at the end
Hmm - didn't notice that one from the orginal. Thanks
(I'm surprised that checkpatch didn't complain).
Since there aren't any functionality differences - I'll send out a new version on
Monday for Ben - since he is away anyway (unless someone else comments tomorrow).
-Robin
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-19 0:27 ` Robin Getz
@ 2009-07-19 1:15 ` Mike Frysinger
2009-07-19 23:30 ` Robin Getz
0 siblings, 1 reply; 16+ messages in thread
From: Mike Frysinger @ 2009-07-19 1:15 UTC (permalink / raw)
To: u-boot
On Saturday 18 July 2009 20:27:00 Robin Getz wrote:
> On Sat 18 Jul 2009 18:11, Mike Frysinger pondered:
> > keep the modulus something with only 1 bit set so gcc will optimize into
> > a simple and operation. probably add a comment about it too:
> > /* make src port a little random, but use something trivial to compute
> > */
>
> OK - So, this would give three different variations:
>
> net/sntp.c: SntpOurPort = 10000 + (get_timer(0) % 4096);
> net/tftp.c: TftpOurPort = 1024 + (get_timer(0) % 3072);
> net/nfs.c: NfsOurPort = 4096 + (get_ticks() % 3072);
>
> Does it make sense to have 4 different ones? (not to me)...
>
> Or something new & common in ./net.c:random_port()
i would make a new patch that adds a new random_port() function and converts
existing consumers to that, and then have the dns code rely on that.
and you should adopt my implementation because the generated code is much much
nicer than the others ;)
a quick google shows:
- sntp - any non-zero source port is OK
- tftp - "between 0 and 65535"
- nfs - couldnt find anything, but i'm pretty sure there isnt one
get_ticks() and get_timer(0) are pretty much equivalent
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20090718/905c3665/attachment.pgp
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-18 1:20 ` Robin Getz
@ 2009-07-19 7:48 ` Wolfgang Denk
2009-07-19 16:17 ` Robin Getz
0 siblings, 1 reply; 16+ messages in thread
From: Wolfgang Denk @ 2009-07-19 7:48 UTC (permalink / raw)
To: u-boot
Dear Robin Getz,
In message <200907172120.50413.rgetz@blackfin.uclinux.org> you wrote:
> On Fri 17 Jul 2009 16:55, Wolfgang Denk pondered:
> > > 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
> >
> > Please keep list sorted.
>
> sorted how? What we have today is:
>
> COBJS-y += net.o
> COBJS-y += tftp.o
> COBJS-y += bootp.o
> COBJS-y += rarp.o
> COBJS-y += eth.o
> COBJS-y += nfs.o
> COBJS-$(CONFIG_CMD_SNTP) += sntp.o
>
> It is not sorted alphabetically... ???
I see. Sorry. Well, please use the opportunity to sort that list,
then. Alphabetically.
> Seems to be sorted by date added, with the last ones on the bottom.
Indeed. But that's not what I meant :-) Thanks.
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A memorandum is written not to inform the reader, but to protect the
writer. -- Dean Acheson
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-19 7:48 ` Wolfgang Denk
@ 2009-07-19 16:17 ` Robin Getz
0 siblings, 0 replies; 16+ messages in thread
From: Robin Getz @ 2009-07-19 16:17 UTC (permalink / raw)
To: u-boot
On Sun 19 Jul 2009 03:48, Wolfgang Denk pondered:
> Dear Robin Getz,
> In message <200907172120.50413.rgetz@blackfin.uclinux.org> you wrote:
> > On Fri 17 Jul 2009 16:55, Wolfgang Denk pondered:
> > > Please keep list sorted.
> >
> > sorted how? What we have today is:
> >
> > COBJS-y += net.o
> > COBJS-y += tftp.o
> > COBJS-y += bootp.o
> > COBJS-y += rarp.o
> > COBJS-y += eth.o
> > COBJS-y += nfs.o
> > COBJS-$(CONFIG_CMD_SNTP) += sntp.o
> >
> > It is not sorted alphabetically... ???
>
> I see. Sorry. Well, please use the opportunity to sort that list,
> then. Alphabetically.
>
Ok -- what I have is this then. I'll wrap it up tomorrow and send to Ben,
assuming he doesn't have anything else...
diff --git a/net/Makefile b/net/Makefile
index d341874..835a04a 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -27,13 +27,14 @@ include $(TOPDIR)/config.mk
LIB = $(obj)libnet.a
-COBJS-y += net.o
-COBJS-y += tftp.o
COBJS-y += bootp.o
-COBJS-y += rarp.o
+COBJS-$(CONFIG_CMD_DNS) += dns.o
COBJS-y += eth.o
+COBJS-y += net.o
COBJS-y += nfs.o
+COBJS-y += rarp.o
COBJS-$(CONFIG_CMD_SNTP) += sntp.o
+COBJS-y += tftp.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-19 1:15 ` Mike Frysinger
@ 2009-07-19 23:30 ` Robin Getz
2009-07-20 2:36 ` Mike Frysinger
0 siblings, 1 reply; 16+ messages in thread
From: Robin Getz @ 2009-07-19 23:30 UTC (permalink / raw)
To: u-boot
On Sat 18 Jul 2009 21:15, Mike Frysinger pondered:
> On Saturday 18 July 2009 20:27:00 Robin Getz wrote:
> > On Sat 18 Jul 2009 18:11, Mike Frysinger pondered:
> > > keep the modulus something with only 1 bit set so gcc will optimize into
> > > a simple and operation. probably add a comment about it too:
> > > /* make src port a little random, but use something trivial to compute
> > > */
> >
> > OK - So, this would give three different variations:
> >
So, these are definitality ugly...
> > net/tftp.c: TftpOurPort = 1024 + (get_timer(0) % 3072);
00000000 <_random_port>:
0: 78 05 [--SP] = (R7:7);
2: 67 01 [--SP] = RETS;
4: a6 6f SP += -0xc; /* (-12) */
6: 00 60 R0 = 0x0 (X); /* R0=0x0( 0) */
8: ff e3 fc ff CALL 0x0 <_random_port>;
a: R_BFIN_PCREL24 _get_timer
c: 41 e1 aa aa R1.H = 0xaaaa; /* (-21846) R1=0xaaaa000c(-1431699444) */
10: 01 e1 ab aa R1.L = 0xaaab; /* (-21845) R1=0xaaaaaaab(-1431655765) */
14: 38 30 R7 = R0;
16: ff e3 f5 ff CALL 0x0 <_random_port>;
18: R_BFIN_PCREL24 ___umulsi3_highpart
1a: 58 4e R0 >>= 0xb;
1c: 21 e1 00 0c R1 = 0xc00 (X); /* R1=0xc00(3072) */
20: c8 40 R0 *= R1;
22: 66 6c SP += 0xc; /* ( 12) */
24: c7 53 R7 = R7 - R0;
26: 20 e1 00 04 R0 = 0x400 (X); /* R0=0x400(1024) */
2a: c7 51 R7 = R7 + R0;
2c: 27 01 RETS = [SP++];
2e: 07 30 R0 = R7;
30: 38 05 (R7:7) = [SP++];
32: 10 00 RTS;
Disassembly of section .text.NetSetTimeout:
> > net/nfs.c: NfsOurPort = 4096 + (get_ticks() % 3072);
00000000 <_random_port>:
0: 67 01 [--SP] = RETS;
2: 86 6f SP += -0x10; /* (-16) */
4: ff e3 fe ff CALL 0x0 <_random_port>;
6: R_BFIN_PCREL24 _get_ticks
8: 02 60 R2 = 0x0 (X); /* R2=0x0( 0) */
a: f2 b0 [SP + 0xc] = R2;
c: 22 e1 00 0c R2 = 0xc00 (X); /* R2=0xc00(3072) */
10: ff e3 f8 ff CALL 0x0 <_random_port>;
12: R_BFIN_PCREL24 ___umoddi3
14: 86 6c SP += 0x10; /* ( 16) */
16: 08 30 R1 = R0;
18: 27 01 RETS = [SP++];
1a: 20 e1 00 10 R0 = 0x1000 (X); /* R0=0x1000(4096) */
1e: 01 50 R0 = R1 + R0;
20: 10 00 RTS;
> > net/sntp.c: SntpOurPort = 10000 + (get_timer(0) % 4096);
00000000 <_random_port>:
0: 67 01 [--SP] = RETS;
2: a6 6f SP += -0xc; /* (-12) */
4: 00 60 R0 = 0x0 (X); /* R0=0x0( 0) */
6: ff e3 fd ff CALL 0x0 <_random_port>;
8: R_BFIN_PCREL24 _get_timer
a: 21 e1 ff 0f R1 = 0xfff (X); /* R1=0xfff(4095) */
e: 66 6c SP += 0xc; /* ( 12) */
10: 08 54 R0 = R0 & R1;
12: 27 01 RETS = [SP++];
14: 21 e1 10 27 R1 = 0x2710 (X); /* R1=0x2710(10000) */
18: 08 50 R0 = R0 + R1;
1a: 10 00 RTS;
Disassembly of section .text.NetSetTimeout:
> 1024 + (get_timer(0) % 0x8000);
00000000 <_random_port>:
0: 67 01 [--SP] = RETS;
2: a6 6f SP += -0xc; /* (-12) */
4: 00 60 R0 = 0x0 (X); /* R0=0x0( 0) */
6: ff e3 fd ff CALL 0x0 <_random_port>;
8: R_BFIN_PCREL24 _get_timer
a: 21 e1 ff 7f R1 = 0x7fff (X); /* R1=0x7fff(32767) */
e: 66 6c SP += 0xc; /* ( 12) */
10: 08 54 R0 = R0 & R1;
12: 27 01 RETS = [SP++];
14: 21 e1 00 04 R1 = 0x400 (X); /* R1=0x400(1024) */
18: 08 50 R0 = R0 + R1;
1a: 10 00 RTS;
Disassembly of section .text.NetSetTimeout:
> > Does it make sense to have 4 different ones? (not to me)...
> >
> > Or something new & common in ./net.c:random_port()
>
> i would make a new patch that adds a new random_port() function and converts
> existing consumers to that, and then have the dns code rely on that.
>
> and you should adopt my implementation because the generated code is
> much much nicer than the others ;)
At least on Blackfin - the sntp version and yours are computationally
equal - although I think yours ends up being more random - so yeah, I'll
use that one.
> a quick google shows:
> - sntp - any non-zero source port is OK
> - tftp - "between 0 and 65535"
> - nfs - couldnt find anything, but i'm pretty sure there isnt one
>
> get_ticks() and get_timer(0) are pretty much equivalent
Sounds great.
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] - add dns
2009-07-19 23:30 ` Robin Getz
@ 2009-07-20 2:36 ` Mike Frysinger
0 siblings, 0 replies; 16+ messages in thread
From: Mike Frysinger @ 2009-07-20 2:36 UTC (permalink / raw)
To: u-boot
On Sunday 19 July 2009 19:30:43 Robin Getz wrote:
> On Sat 18 Jul 2009 21:15, Mike Frysinger pondered:
> > On Saturday 18 July 2009 20:27:00 Robin Getz wrote:
> > > Does it make sense to have 4 different ones? (not to me)...
> > >
> > > Or something new & common in ./net.c:random_port()
> >
> > i would make a new patch that adds a new random_port() function and
> > converts existing consumers to that, and then have the dns code rely on
> > that.
> >
> > and you should adopt my implementation because the generated code is
> > much much nicer than the others ;)
>
> At least on Blackfin - the sntp version and yours are computationally
> equal - although I think yours ends up being more random - so yeah, I'll
> use that one.
any arch that has an instruction for doing the "and" operation should end up
being computationally as simple as the Blackfin code. afaik, pretty much all
do, and the ones who dont are screwed anyways, so nothing to be done for them.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20090719/a1e9be32/attachment-0001.pgp
^ permalink raw reply [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] v3 - add dns
2009-07-17 19:53 [U-Boot] [PATCH] - add dns Robin Getz
2009-07-17 20:55 ` Wolfgang Denk
@ 2009-07-20 18:53 ` Robin Getz
2009-07-21 4:48 ` Ben Warren
1 sibling, 1 reply; 16+ messages in thread
From: Robin Getz @ 2009-07-20 18:53 UTC (permalink / raw)
To: u-boot
On 04 Oct 2008 Pieter posted a dns implementation for U-Boot.
http://www.mail-archive.com/u-boot-users at 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)
- README.dns is added
- syntax is changed (now takes a third option, the env var to store
the result in)
- add a random port() function in net.c
- sort Makefile in ./net/Makefile
- dns just returns unless a env var is given
- 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.
Signed-off-by: Robin Getz <rgetz@blackfin.uclinux.org>
Signed-off-by: Pieter Voorthuijsen <pieter.voorthuijsen@prodrive.nl>
common/cmd_net.c | 49 ++++++++++
doc/README.dns | 64 +++++++++++++
include/net.h | 5 +
net/Makefile | 7 -
net/dns.c | 211 +++++++++++++++++++++++++++++++++++++++++++++
net/dns.h | 39 ++++++++
net/net.c | 29 ++++++
7 files changed, 401 insertions(+), 3 deletions(-)
---
diff --git a/common/cmd_net.c b/common/cmd_net.c
index 68183c4..ac706ae 100644
--- a/common/cmd_net.c
+++ b/common/cmd_net.c
@@ -353,3 +353,52 @@ U_BOOT_CMD(
"[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 == 1) {
+ cmd_usage(cmdtp);
+ return -1;
+ }
+
+ /*
+ * We should check for a valid hostname:
+ * - Each label must be between 1 and 63 characters long
+ * - the entire hostname has a maximum of 255 characters
+ * - only the ASCII letters 'a' through 'z' (case-insensitive),
+ * the digits '0' through '9', and the hyphen
+ * - cannot begin or end with a hyphen
+ * - no other symbols, punctuation characters, or blank spaces are
+ * permitted
+ * but hey - this is a minimalist implmentation, so only check length
+ * and let the name server deal with things.
+ */
+ if (strlen(argv[1]) >= 255) {
+ printf("dns error: hostname too long\n");
+ return 1;
+ }
+
+ NetDNSResolve = argv[1];
+
+ if (argc == 3)
+ NetDNSenvvar = argv[2];
+ else
+ NetDNSenvvar = NULL;
+
+ if (NetLoop(DNS) < 0) {
+ printf("dns lookup of %s failed, check setup\n", argv[1]);
+ return 1;
+ }
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ dns, 3, 1, do_dns,
+ "lookup the IP of a hostname",
+ "hostname [envvar]"
+);
+
+#endif /* CONFIG_CMD_DNS */
+
diff --git a/doc/README.dns b/doc/README.dns
new file mode 100644
index 0000000..deeccd7
--- /dev/null
+++ b/doc/README.dns
@@ -0,0 +1,64 @@
+Domain Name System
+-------------------------------------------
+
+The Domain Name System (DNS) is a hierarchical naming system for computers,
+services, or any resource participating in the Internet. It associates various
+information with domain names assigned to each of the participants. Most
+importantly, it translates domain names meaningful to humans into the numerical
+(binary) identifiers associated with networking equipment for the purpose of
+locating and addressing these devices world-wide. An often used analogy to
+explain the Domain Name System is that it serves as the "phone book" for the
+Internet by translating human-friendly computer hostnames into IP addresses.
+For example, www.example.com translates to 208.77.188.166.
+
+For more information on DNS - http://en.wikipedia.org/wiki/Domain_Name_System
+
+
+
+U-Boot and DNS
+------------------------------------------
+
+CONFIG_CMD_DNS - controls if the 'dns' command is compiled in. If it is, it
+ will send name lookups to the dns server (env var 'dnsip')
+ Turning this option on will about abou 1k to U-Boot's size.
+
+ Example:
+
+bfin> print dnsip
+dnsip=192.168.0.1
+
+bfin> dns www.google.com
+66.102.1.104
+
+ By default, dns does nothing except print the IP number on
+ the default console - which by itself, would be pretty
+ useless. Adding a third argument to the dns command will
+ use that as the environment variable to be set.
+
+ Example:
+
+bfin> print googleip
+## Error: "googleip" not defined
+bfin> dns www.google.com googleip
+64.233.161.104
+bfin> print googleip
+googleip=64.233.161.104
+bfin> ping ${googleip}
+Using Blackfin EMAC device
+host 64.233.161.104 is alive
+
+ In this way, you can lookup, and set many more meaningful
+ things.
+
+bfin> sntp
+ntpserverip not set
+bfin> dns pool.ntp.org ntpserverip
+72.18.205.156
+bfin> sntp
+Date: 2009-07-18 Time: 4:06:57
+
+ For some helpful things that can be related to DNS in U-Boot,
+ look at the top level README for these config options:
+ CONFIG_CMD_DHCP
+ CONFIG_BOOTP_DNS
+ CONFIG_BOOTP_DNS2
diff --git a/include/net.h b/include/net.h
index 5a1d36e..8340c9e 100644
--- a/include/net.h
+++ b/include/net.h
@@ -361,6 +361,11 @@ typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP
/* from net/net.c */
extern char BootFile[128]; /* Boot File name */
+#if defined(CONFIG_CMD_DNS)
+extern char *NetDNSResolve; /* The host to resolve */
+extern char *NetDNSenvvar; /* the env var to put the ip into */
+#endif
+
#if defined(CONFIG_CMD_PING)
extern IPaddr_t NetPingIP; /* the ip address to ping */
#endif
diff --git a/net/Makefile b/net/Makefile
index d341874..835a04a 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -27,13 +27,14 @@ include $(TOPDIR)/config.mk
LIB = $(obj)libnet.a
-COBJS-y += net.o
-COBJS-y += tftp.o
COBJS-y += bootp.o
-COBJS-y += rarp.o
+COBJS-$(CONFIG_CMD_DNS) += dns.o
COBJS-y += eth.o
+COBJS-y += net.o
COBJS-y += nfs.o
+COBJS-y += rarp.o
COBJS-$(CONFIG_CMD_SNTP) += sntp.o
+COBJS-y += tftp.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/net/dns.c b/net/dns.c
new file mode 100644
index 0000000..f25c3f8
--- /dev/null
+++ b/net/dns.c
@@ -0,0 +1,211 @@
+/*
+ * 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, 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();
+}
+
diff --git a/net/dns.h b/net/dns.h
new file mode 100644
index 0000000..277c093
--- /dev/null
+++ b/net/dns.h
@@ -0,0 +1,39 @@
+/*
+ * (C) Masami Komiya <mkomiya@sonare.it> 2005
+ * Copyright 2009, Robin Getz <rgetz@blackfin.uclinux.org>
+ *
+ * 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_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
diff --git a/net/net.c b/net/net.c
index 5637cf5..a7ac032 100644
--- a/net/net.c
+++ b/net/net.c
@@ -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)
@@ -291,6 +294,9 @@ NetInitLoop(proto_t protocol)
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 +435,11 @@ restart:
SntpStart();
break;
#endif
+#if defined(CONFIG_CMD_DNS)
+ case DNS:
+ DnsStart();
+ break;
+#endif
default:
break;
}
@@ -1518,6 +1532,14 @@ static int net_check_prereq (proto_t protocol)
}
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
@@ -1681,6 +1703,16 @@ void copy_filename (char *dst, char *src, int size)
#endif
+#if defined(CONFIG_CMD_NFS) || defined(CONFIG_CMD_SNTP) || defined(CONFIG_CMD_DNS)
+/*
+ * make port a little random, but use something trivial to compute
+ */
+unsigned int random_port(void)
+{
+ return 1024 + (get_timer(0) % 0x8000);;
+}
+#endif
+
void ip_to_string (IPaddr_t x, char *s)
{
x = ntohl (x);
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [U-Boot] [PATCH] v3 - add dns
2009-07-20 18:53 ` [U-Boot] [PATCH] v3 " Robin Getz
@ 2009-07-21 4:48 ` Ben Warren
0 siblings, 0 replies; 16+ messages in thread
From: Ben Warren @ 2009-07-21 4:48 UTC (permalink / raw)
To: u-boot
Hi Robin,
Robin Getz wrote:
> On 04 Oct 2008 Pieter posted a dns implementation for U-Boot.
>
> http://www.mail-archive.com/u-boot-users at 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)
> - README.dns is added
> - syntax is changed (now takes a third option, the env var to store
> the result in)
> - add a random port() function in net.c
> - sort Makefile in ./net/Makefile
> - dns just returns unless a env var is given
> - 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.
>
>
> Signed-off-by: Robin Getz <rgetz@blackfin.uclinux.org>
> Signed-off-by: Pieter Voorthuijsen <pieter.voorthuijsen@prodrive.nl>
>
Looks like I missed a pretty interesting discussion here. Anyway, patch
V3 is applied to the net repo with some cosmetic changes to the
changelog (no changes to the patch).
thanks,
Ben
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2009-07-21 4:48 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-17 19:53 [U-Boot] [PATCH] - add dns Robin Getz
2009-07-17 20:55 ` Wolfgang Denk
2009-07-17 21:45 ` Robin Getz
2009-07-17 22:01 ` Wolfgang Denk
2009-07-17 23:19 ` Robin Getz
2009-07-18 5:14 ` Robin Getz
2009-07-18 22:11 ` Mike Frysinger
2009-07-19 0:27 ` Robin Getz
2009-07-19 1:15 ` Mike Frysinger
2009-07-19 23:30 ` Robin Getz
2009-07-20 2:36 ` Mike Frysinger
2009-07-18 1:20 ` Robin Getz
2009-07-19 7:48 ` Wolfgang Denk
2009-07-19 16:17 ` Robin Getz
2009-07-20 18:53 ` [U-Boot] [PATCH] v3 " Robin Getz
2009-07-21 4:48 ` Ben Warren
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox