root/ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/net/dns.c

Revision 12368, 7.6 kB (checked in by BrainSlayer, 5 months ago)

tftp server added, supports wiligear, ubiquiti and dd-wrt webflash format

Line 
1 //=============================================================================
2 //
3 //      dns.c
4 //
5 //      DNS client code
6 //
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
13 //
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.
17 //
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
21 // for more details.
22 //
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.
26 //
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.
33 //
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.
36 //
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####
43 //
44 // Author(s):   jskov
45 // Contributors:jskov
46 // Date:        2001-09-26
47 // Description: Provides DNS lookup as per RFC 1034/1035.
48 //
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.
53 //
54 //####DESCRIPTIONEND####
55 //
56 //=============================================================================
57
58 #include <cyg/hal/drv_api.h>
59 #include <cyg/infra/cyg_type.h>
60 #include <cyg/infra/cyg_trac.h> /* Tracing support */
61
62 #include <net/net.h>
63 #include <redboot.h>
64 /* #include <cyg/ns/dns/dns.h> - it's been moved to redboot.h */
65 #include <cyg/ns/dns/dns_priv.h>
66
67 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
68 #include <flash_config.h>
69
70 RedBoot_config_option("DNS server IP address",
71                       dns_ip, ALWAYS_ENABLED, true, CONFIG_IP, 0);
72 #endif
73
74 /* So we remember which ports have been used */
75 static int get_port = 7700;
76
77 #define DOMAIN_PORT           53
78
79 /* Some magic to make dns_impl.inl compile under RedBoot */
80 #define sprintf diag_sprintf
81
82 /* DNS server address possibly returned from bootp */
83 struct in_addr __bootp_dns_addr;
84 cyg_bool __bootp_dns_set = false;
85
86 struct sockaddr_in server;
87
88 /* static buffers so we can make do without malloc */
89 static struct hostent _hent;
90 static char *_h_addr_list[2];
91 static struct in_addr _h_addr_list0;
92 static int _hent_alloc = 0;
93
94 #define _STRING_COUNT  2
95 #define _STRING_LENGTH 64
96 static char _strings[_STRING_COUNT][_STRING_LENGTH];
97 static int _strings_alloc = 0;
98
99 /* as in dns.c proper */
100 static short id = 0;            /* ID of the last query */
101 static int s = -1;              /* Socket to the DNS server */
102 static cyg_drv_mutex_t dns_mutex;       /* Mutex to stop multiple queries as once */
103 static char *domainname = NULL; /* Domain name used for queries */
104
105 /* Allocate space for string of length (len). Return NULL on
106    failure. */
107 static char *alloc_string(int len)
108 {
109         int i;
110
111         if (len > _STRING_LENGTH)
112                 return NULL;
113
114         for (i = 0; i < _STRING_COUNT; i++) {
115                 if (_strings_alloc & (1 << i))
116                         continue;
117                 _strings_alloc |= (1 << i);
118                 return _strings[i];
119         }
120         return NULL;
121 }
122
123 static void free_string(char *s)
124 {
125         int i;
126         for (i = 0; i < _STRING_COUNT; i++) {
127                 if (_strings[i] == s) {
128                         _strings_alloc &= ~(1 << i);
129                         break;
130                 }
131         }
132 }
133
134 /* Deallocate the memory taken to hold a hent structure */
135 static void free_hent(struct hostent *hent)
136 {
137         if (hent->h_name) {
138                 free_string(hent->h_name);
139         }
140         _hent_alloc = 0;
141 }
142
143 /* Allocate hent structure with room for one in_addr. Returns NULL on
144    failure. */
145 static struct hostent *alloc_hent(void)
146 {
147         struct hostent *hent;
148
149         if (_hent_alloc)
150                 return NULL;
151
152         hent = &_hent;
153         memset(hent, 0, sizeof(struct hostent));
154         hent->h_addr_list = _h_addr_list;
155         hent->h_addr_list[0] = (char *)&_h_addr_list0;
156         hent->h_addr_list[1] = NULL;
157         _hent_alloc = 1;
158
159         return hent;
160 }
161
162 static __inline__ void free_stored_hent(void)
163 {
164         free_hent(&_hent);
165 }
166
167 static __inline__ void store_hent(struct hostent *hent)
168 {
169         hent = hent;            // avoid warning
170 }
171
172 /* Send the query to the server and read the response back. Return -1
173    if it fails, otherwise put the response back in msg and return the
174    length of the response. */
175 static int send_recv(char *msg, int len, int msglen)
176 {
177         struct dns_header *dns_hdr;
178         int finished = false;
179         int read = 0;
180
181         dns_hdr = (struct dns_header *)msg;
182
183         do {
184                 int len_togo = len;
185                 struct timeval timeout;
186                 struct sockaddr_in local_addr, from_addr;
187
188                 memset((char *)&local_addr, 0, sizeof(local_addr));
189                 local_addr.sin_family = AF_INET;
190                 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
191                 local_addr.sin_port = htons(get_port++);
192
193                 if (__udp_sendto(msg, len_togo, &server, &local_addr) < 0)
194                         return -1;
195
196                 memset((char *)&from_addr, 0, sizeof(from_addr));
197
198                 timeout.tv_sec = CYGNUM_REDBOOT_NETWORKING_DNS_TIMEOUT;
199                 timeout.tv_usec = 0;
200
201                 read =
202                     __udp_recvfrom(msg, len, &from_addr, &local_addr, &timeout);
203                 if (read < 0)
204                         return -1;
205
206                 /* Reply to an old query. Ignore it */
207                 if (ntohs(dns_hdr->id) != (id - 1)) {
208                         continue;
209                 }
210                 finished = true;
211         } while (!finished);
212
213         return read;
214 }
215
216 void set_dns(char *new_ip)
217 {
218         in_addr_t dns_ip;
219
220         memset(&server.sin_addr, 0, sizeof(server.sin_addr));
221         if (!inet_aton(new_ip, &dns_ip)) {
222                 diag_printf("Bad DNS server address: %s\n", new_ip);
223         } else {
224                 memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip));
225                 /* server config is valid */
226                 s = 0;
227         }
228 }
229
230 void show_dns(void)
231 {
232         diag_printf(", DNS server IP: %s",
233                     inet_ntoa((in_addr_t *) & server.sin_addr));
234         if (0 == server.sin_addr.s_addr) {
235                 s = -1;
236         }
237 }
238
239 /* Initialise the resolver. Open a socket and bind it to the address
240    of the server.  return -1 if something goes wrong, otherwise 0 */
241 int redboot_dns_res_init(void)
242 {
243         memset((char *)&server, 0, sizeof(server));
244         server.sin_len = sizeof(server);
245         server.sin_family = AF_INET;
246         server.sin_port = htons(DOMAIN_PORT);
247         cyg_drv_mutex_init(&dns_mutex);
248
249         /* If we got a DNS server address from the DHCP/BOOTP, then use that address */
250         if (__bootp_dns_set) {
251                 memcpy(&server.sin_addr, &__bootp_dns_addr,
252                        sizeof(__bootp_dns_addr));
253                 s = 0;
254         } else {
255 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
256                 {
257                         ip_addr_t dns_ip;
258
259                         flash_get_config("dns_ip", &dns_ip, CONFIG_IP);
260                         if (dns_ip[0] == 0 && dns_ip[1] == 0 && dns_ip[2] == 0
261                             && dns_ip[3] == 0)
262                                 return -1;
263                         memcpy(&server.sin_addr, &dns_ip, sizeof(dns_ip));
264                         /* server config is valid */
265                         s = 0;
266                 }
267 #else
268                 // Use static configuration
269                 set_dns(__Xstr(CYGPKG_REDBOOT_NETWORKING_DNS_IP));
270 #endif
271         }
272
273         return 0;
274 }
275
276 /* Include the DNS client implementation code */
277 #include <cyg/ns/dns/dns_impl.inl>
Note: See TracBrowser for help on using the browser.