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",
78 /* So we remember which ports have been used */
79 static int get_port = 7700;
81 #define DOMAIN_PORT 53
83 /* Some magic to make dns_impl.inl compile under RedBoot */
84 #define sprintf diag_sprintf
86 /* DNS server address possibly returned from bootp */
87 struct in_addr __bootp_dns_addr;
88 cyg_bool __bootp_dns_set = false;
90 struct sockaddr_in server;
92 /* static buffers so we can make do without malloc */
93 static struct hostent _hent;
94 static char* _h_addr_list[2];
95 static struct in_addr _h_addr_list0;
96 static int _hent_alloc = 0;
98 #define _STRING_COUNT 2
99 #define _STRING_LENGTH 64
100 static char _strings[_STRING_COUNT][_STRING_LENGTH];
101 static int _strings_alloc = 0;
103 /* as in dns.c proper */
104 static short id = 0; /* ID of the last query */
105 static int s = -1; /* Socket to the DNS server */
106 static cyg_drv_mutex_t dns_mutex; /* Mutex to stop multiple queries as once */
107 static char * domainname=NULL; /* Domain name used for queries */
110 /* Allocate space for string of length (len). Return NULL on
113 alloc_string(int len)
117 if (len > _STRING_LENGTH)
120 for (i = 0; i < _STRING_COUNT; i++) {
121 if (_strings_alloc & (1 << i)) continue;
122 _strings_alloc |= (1<<i);
132 for (i = 0; i < _STRING_COUNT; i++) {
133 if (_strings[i] == s) {
134 _strings_alloc &= ~(1<<i);
140 /* Deallocate the memory taken to hold a hent structure */
142 free_hent(struct hostent * hent)
145 free_string(hent->h_name);
150 /* Allocate hent structure with room for one in_addr. Returns NULL on
152 static struct hostent*
155 struct hostent *hent;
157 if (_hent_alloc) return NULL;
160 memset(hent, 0, sizeof(struct hostent));
161 hent->h_addr_list = _h_addr_list;
162 hent->h_addr_list[0] = (char*)&_h_addr_list0;
163 hent->h_addr_list[1] = NULL;
169 static __inline__ void
170 free_stored_hent(void)
175 static __inline__ void
176 store_hent(struct hostent *hent)
178 hent=hent; // avoid warning
181 /* Send the query to the server and read the response back. Return -1
182 if it fails, otherwise put the response back in msg and return the
183 length of the response. */
185 send_recv(char * msg, int len, int msglen)
187 struct dns_header *dns_hdr;
188 int finished = false;
191 dns_hdr = (struct dns_header *) msg;
195 struct timeval timeout;
196 struct sockaddr_in local_addr, from_addr;
198 memset((char *)&local_addr, 0, sizeof(local_addr));
199 local_addr.sin_family = AF_INET;
200 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
201 local_addr.sin_port = htons(get_port++);
203 if (__udp_sendto(msg, len_togo, &server, &local_addr) < 0)
206 memset((char *)&from_addr, 0, sizeof(from_addr));
208 timeout.tv_sec = CYGNUM_REDBOOT_NETWORKING_DNS_TIMEOUT;
211 read = __udp_recvfrom(msg, len, &from_addr, &local_addr, &timeout);
215 /* Reply to an old query. Ignore it */
216 if (ntohs(dns_hdr->id) != (id-1)) {
226 set_dns(char* new_ip)
230 memset(&server.sin_addr, 0, sizeof(server.sin_addr));
231 if (!inet_aton(new_ip, &dns_ip)) {
232 diag_printf("Bad DNS server address: %s\n", new_ip);
234 memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip));
235 /* server config is valid */
243 diag_printf(", DNS server IP: %s", inet_ntoa((in_addr_t *)&server.sin_addr));
244 if (0 == server.sin_addr.s_addr) {
249 /* Initialise the resolver. Open a socket and bind it to the address
250 of the server. return -1 if something goes wrong, otherwise 0 */
252 redboot_dns_res_init(void)
254 memset((char *)&server, 0, sizeof(server));
255 server.sin_len = sizeof(server);
256 server.sin_family = AF_INET;
257 server.sin_port = htons(DOMAIN_PORT);
258 cyg_drv_mutex_init(&dns_mutex);
260 /* If we got a DNS server address from the DHCP/BOOTP, then use that address */
261 if ( __bootp_dns_set ) {
262 memcpy(&server.sin_addr, &__bootp_dns_addr, sizeof(__bootp_dns_addr) );
266 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
270 flash_get_config("dns_ip", &dns_ip, CONFIG_IP);
271 if (dns_ip[0] == 0 && dns_ip[1] == 0 && dns_ip[2] == 0 && dns_ip[3] == 0)
273 memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip));
274 /* server config is valid */
278 // Use static configuration
279 set_dns(__Xstr(CYGPKG_REDBOOT_NETWORKING_DNS_IP));
286 /* Include the DNS client implementation code */
287 #include <cyg/ns/dns/dns_impl.inl>