]>
git.ipfire.org Git - people/ms/u-boot.git/blob - net/dns.c
4 * Copyright (c) 2008 Pieter Voorthuijsen <pieter.voorthuijsen@prodrive.nl>
5 * Copyright (c) 2009 Robin Getz <rgetz@blackfin.uclinux.org>
7 * This is a simple DNS implementation for U-Boot. It will use the first IP
8 * in the DNS response as NetServerIP. This can then be used for any other
9 * network related activities.
11 * The packet handling is partly based on TADNS, original copyrights
17 * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
19 * "THE BEER-WARE LICENSE" (Revision 42):
20 * Sergey Lyubka wrote this file. As long as you retain this notice you
21 * can do whatever you want with this stuff. If we meet some day, and you think
22 * this stuff is worth it, you can buy me a beer in return.
31 char *NetDNSResolve
; /* The host to resolve */
32 char *NetDNSenvvar
; /* The envvar to store the answer in */
34 static int DnsOurPort
;
39 struct header
*header
;
44 enum dns_query_type qtype
= DNS_A_RECORD
;
47 pkt
= p
= (uchar
*)(NetTxPacket
+ NetEthHdrSize() + IP_HDR_SIZE
);
49 /* Prepare DNS packet header */
50 header
= (struct header
*) pkt
;
52 header
->flags
= htons(0x100); /* standard query */
53 header
->nqueries
= htons(1); /* Just one query */
59 name_len
= strlen(name
);
60 p
= (uchar
*) &header
->data
; /* For encoding host name into packet */
63 s
= strchr(name
, '.');
67 n
= s
- name
; /* Chunk length */
68 *p
++ = n
; /* Copy length */
69 memcpy(p
, name
, n
); /* Copy chunk */
79 *p
++ = 0; /* Mark end of host name */
80 *p
++ = 0; /* Some servers require double null */
81 *p
++ = (unsigned char) qtype
; /* Query Type */
84 *p
++ = 1; /* Class: inet, 0x0001 */
86 n
= p
- pkt
; /* Total packet length */
87 debug("Packet size %d\n", n
);
89 DnsOurPort
= random_port();
91 NetSendUDPPacket(NetServerEther
, NetOurDNSIP
, DNS_SERVICE_PORT
,
93 debug("DNS packet sent\n");
100 NetState
= NETLOOP_FAIL
;
104 DnsHandler(uchar
*pkt
, unsigned dest
, unsigned src
, unsigned len
)
106 struct header
*header
;
107 const unsigned char *p
, *e
, *s
;
109 int found
, stop
, dlen
;
115 debug("%s\n", __func__
);
116 if (dest
!= DnsOurPort
)
119 for (i
= 0; i
< len
; i
+= 4)
120 debug("0x%p - 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
121 pkt
+i
, pkt
[i
], pkt
[i
+1], pkt
[i
+2], pkt
[i
+3]);
123 /* We sent 1 query. We want to see more that 1 answer. */
124 header
= (struct header
*) pkt
;
125 if (ntohs(header
->nqueries
) != 1)
128 /* Received 0 answers */
129 if (header
->nanswers
== 0) {
130 puts("DNS server returned no answers\n");
131 NetState
= NETLOOP_SUCCESS
;
136 s
= &header
->data
[0];
138 for (p
= s
; p
< e
&& *p
!= '\0'; p
++)
141 /* We sent query class 1, query type 1 */
142 tmp
= p
[1] | (p
[2] << 8);
143 if (&p
[5] > e
|| ntohs(tmp
) != DNS_A_RECORD
) {
144 puts("DNS response was not A record\n");
145 NetState
= NETLOOP_SUCCESS
;
149 /* Go to the first answer section */
152 /* Loop through the answers, we want A type answer */
153 for (found
= stop
= 0; !stop
&& &p
[12] < e
; ) {
155 /* Skip possible name in CNAME answer */
157 while (*p
&& &p
[12] < e
)
161 debug("Name (Offset in header): %d\n", p
[1]);
163 tmp
= p
[2] | (p
[3] << 8);
165 debug("type = %d\n", type
);
166 if (type
== DNS_CNAME_RECORD
) {
167 /* CNAME answer. shift to the next section */
168 debug("Found canonical name\n");
169 tmp
= p
[10] | (p
[11] << 8);
171 debug("dlen = %d\n", dlen
);
173 } else if (type
== DNS_A_RECORD
) {
174 debug("Found A-record\n");
177 debug("Unknown type\n");
182 if (found
&& &p
[12] < e
) {
184 tmp
= p
[10] | (p
[11] << 8);
187 memcpy(&IPAddress
, p
, 4);
190 ip_to_string(IPAddress
, IPStr
);
191 printf("%s\n", IPStr
);
193 setenv(NetDNSenvvar
, IPStr
);
195 puts("server responded with invalid IP number\n");
198 NetState
= NETLOOP_SUCCESS
;
204 debug("%s\n", __func__
);
206 NetSetTimeout(DNS_TIMEOUT
, DnsTimeout
);
207 NetSetHandler(DnsHandler
);