1 //=============================================================================
7 //=============================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //=============================================================================
42 //#####DESCRIPTIONBEGIN####
47 // Description: Provides DNS lookup as per RFC 1034/1035.
49 // Note: This is a stripped down clone of dns.c from the CYGPKG_NS_DNS
50 // package which does not use malloc/free and has been tweaked to
51 // use UDP via RedBoot's network stack. Also adds commands
52 // to set the DNS server IP at runtime.
54 //####DESCRIPTIONEND####
56 //=============================================================================
58 #include <cyg/hal/drv_api.h>
59 #include <cyg/infra/cyg_type.h>
60 #include <cyg/infra/cyg_trac.h> /* Tracing support */
64 /* #include <cyg/ns/dns/dns.h> - it's been moved to redboot.h */
65 #include <cyg/ns/dns/dns_priv.h>
67 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
68 #include <flash_config.h>
70 RedBoot_config_option("DNS server IP address",
77 RedBoot_config_option("DNS domain name",
85 /* So we remember which ports have been used */
86 static int get_port = 7700;
88 #define DOMAIN_PORT 53
90 /* Some magic to make dns_impl.inl compile under RedBoot */
91 #define sprintf diag_sprintf
93 /* DNS server address possibly returned from bootp */
94 struct in_addr __bootp_dns_addr;
95 cyg_bool __bootp_dns_set = false;
97 /* DNS domain name possibly returned from bootp */
98 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_DHCP_DOMAIN
99 char __bootp_dns_domain[CYGNUM_REDBOOT_NETWORK_DNS_DOMAIN_BUFSIZE];
100 cyg_bool __bootp_dns_domain_set = false;
103 struct sockaddr_in server;
105 /* static buffers so we can make do without malloc */
106 static struct hostent _hent;
107 static char* _h_addr_list[2];
108 static struct in_addr _h_addr_list0;
109 static int _hent_alloc = 0;
111 #define _STRING_COUNT 2
112 #define _STRING_LENGTH 64
113 static char _strings[_STRING_COUNT][_STRING_LENGTH];
114 static int _strings_alloc = 0;
116 /* as in dns.c proper */
117 static short id = 0; /* ID of the last query */
118 static int s = -1; /* Socket to the DNS server */
119 static cyg_drv_mutex_t dns_mutex; /* Mutex to stop multiple queries as once */
120 static char * domainname=NULL; /* Domain name used for queries */
123 /* Allocate space for string of length (len). Return NULL on
126 alloc_string(int len)
130 if (len > _STRING_LENGTH)
133 for (i = 0; i < _STRING_COUNT; i++) {
134 if (_strings_alloc & (1 << i)) continue;
135 _strings_alloc |= (1<<i);
145 for (i = 0; i < _STRING_COUNT; i++) {
146 if (_strings[i] == s) {
147 _strings_alloc &= ~(1<<i);
153 /* Deallocate the memory taken to hold a hent structure */
155 free_hent(struct hostent * hent)
158 free_string(hent->h_name);
163 /* Allocate hent structure with room for one in_addr. Returns NULL on
165 static struct hostent*
168 struct hostent *hent;
170 if (_hent_alloc) return NULL;
173 memset(hent, 0, sizeof(struct hostent));
174 hent->h_addr_list = _h_addr_list;
175 hent->h_addr_list[0] = (char*)&_h_addr_list0;
176 hent->h_addr_list[1] = NULL;
182 static __inline__ void
183 free_stored_hent(void)
188 static __inline__ void
189 store_hent(struct hostent *hent)
191 hent=hent; // avoid warning
194 /* Send the query to the server and read the response back. Return -1
195 if it fails, otherwise put the response back in msg and return the
196 length of the response. */
198 send_recv(char * msg, int len, int msglen)
200 struct dns_header *dns_hdr;
201 int finished = false;
204 dns_hdr = (struct dns_header *) msg;
208 struct timeval timeout;
209 struct sockaddr_in local_addr, from_addr;
211 memset((char *)&local_addr, 0, sizeof(local_addr));
212 local_addr.sin_family = AF_INET;
213 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
214 local_addr.sin_port = htons(get_port++);
216 if (__udp_sendto(msg, len_togo, &server, &local_addr) < 0)
219 memset((char *)&from_addr, 0, sizeof(from_addr));
221 timeout.tv_sec = CYGNUM_REDBOOT_NETWORKING_DNS_TIMEOUT;
224 read = __udp_recvfrom(msg, len, &from_addr, &local_addr, &timeout);
228 /* Reply to an old query. Ignore it */
229 if (ntohs(dns_hdr->id) != (id-1)) {
239 set_dns(char* new_ip)
243 memset(&server.sin_addr, 0, sizeof(server.sin_addr));
244 if (!inet_aton(new_ip, &dns_ip)) {
245 diag_printf("Bad DNS server address: %s\n", new_ip);
247 memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip));
248 /* server config is valid */
256 diag_printf("\nDNS server IP: %s, DNS domain name: %s",
257 inet_ntoa((in_addr_t *)&server.sin_addr),
259 if (0 == server.sin_addr.s_addr) {
264 /* Initialise the resolver. Open a socket and bind it to the address
265 of the server. return -1 if something goes wrong, otherwise 0 */
267 redboot_dns_res_init(void)
269 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_FCONFIG_DOMAIN
270 char *dns_domain = NULL;
272 memset((char *)&server, 0, sizeof(server));
273 server.sin_len = sizeof(server);
274 server.sin_family = AF_INET;
275 server.sin_port = htons(DOMAIN_PORT);
276 cyg_drv_mutex_init(&dns_mutex);
278 /* Set the default DNS domain first, so that it can be overwritten
280 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_DEFAULT_DOMAIN
281 setdomainname(__Xstr(CYGPKG_REDBOOT_NETWORKING_DNS_DEFAULT_DOMAIN),
282 strlen(__Xstr(CYGPKG_REDBOOT_NETWORKING_DNS_DEFAULT_DOMAIN)));
284 /* Set the domain name from flash so that DHCP can later
286 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_FCONFIG_DOMAIN
287 flash_get_config("dns_domain", &dns_domain, CONFIG_STRING);
288 if(dns_domain != NULL && dns_domain[0] != '\0')
289 setdomainname(dns_domain, strlen(dns_domain));
292 /* If we got a DNS server address from the DHCP/BOOTP, then use
294 if ( __bootp_dns_set ) {
295 memcpy(&server.sin_addr, &__bootp_dns_addr,
296 sizeof(__bootp_dns_addr) );
298 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_DHCP_DOMAIN
299 if(__bootp_dns_domain_set)
300 setdomainname(__bootp_dns_domain, strlen(__bootp_dns_domain));
302 /* server config is valid */
306 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
310 flash_get_config("dns_ip", &dns_ip, CONFIG_IP);
311 if (dns_ip[0] == 0 && dns_ip[1] == 0 &&
312 dns_ip[2] == 0 && dns_ip[3] == 0)
314 memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip));
315 /* server config is valid */
319 // Use static configuration. If CYGPKG_REDBOOT_NETWORKING_DNS_IP
320 // is valid s will set set as a side effect.
321 set_dns(__Xstr(CYGPKG_REDBOOT_NETWORKING_DNS_IP));
328 /* Include the DNS client implementation code */
329 #include <cyg/ns/dns/dns_impl.inl>