On 04 Oct 2008 Pieter posted a dns implementation for U-Boot. http://www.mail-archive.com/u-boot-users@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> Signed-off-by: Ben Warren <biggerbadderben@gmail.com>master
parent
88ad3fd91c
commit
1a32bf4188
@ -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 |
@ -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(); |
||||
} |
||||
|
@ -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 |
Loading…
Reference in new issue