OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [net/] [ns/] [dns/] [v2_0/] [src/] [dns.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//=============================================================================
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
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//=============================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):   andrew.lunn
44
// Contributors:andrew.lunn, jskov
45
// Date:        2001-09-18
46
// Description: Provides DNS lookup as per RFC 1034/1035.
47
// 
48
// Note:        Does only support A and PTR lookups. Maybe add for other
49
//              types as well?
50
//
51
//              parse_answer() only returns the first found record.
52
//
53
//              Add tracing and assertions.
54
//
55
//####DESCRIPTIONEND####
56
//
57
//=============================================================================
58
 
59
#include <pkgconf/system.h>
60
#ifdef CYGPKG_KERNEL
61
# include <pkgconf/kernel.h>
62
# include <cyg/kernel/kapi.h>
63
#endif
64
#include <cyg/hal/drv_api.h>
65
#include <cyg/infra/cyg_type.h>
66
#include <cyg/infra/cyg_trac.h>         /* Tracing support */
67
 
68
#include <netdb.h>
69
 
70
#include <sys/time.h>
71
#include <sys/types.h>
72
#include <sys/socket.h>
73
#include <arpa/inet.h>
74
 
75
#include <ctype.h>
76
#include <unistd.h>
77
#include <stdio.h>
78
#include <string.h>
79
#include <stdlib.h>
80
 
81
#include <cyg/ns/dns/dns_priv.h>
82
 
83
static short id = 0;              /* ID of the last query */
84
static int s = -1;                /* Socket to the DNS server */
85
static cyg_drv_mutex_t dns_mutex; /* Mutex to stop multiple queries as once */
86
static cyg_ucount32 ptdindex;     /* Index for the per thread data */
87
static char * domainname=NULL;    /* Domain name used for queries */
88
 
89
/* Allocate space for string of length len. Return NULL on failure. */
90
static inline char*
91
alloc_string(int len)
92
{
93
    return malloc(len);
94
}
95
 
96
static inline void
97
free_string(char* s)
98
{
99
    free(s);
100
}
101
 
102
/* Deallocate the memory taken to hold a hent structure */
103
static void
104
free_hent(struct hostent * hent)
105
{
106
    if (hent->h_name) {
107
        free_string(hent->h_name);
108
    }
109
 
110
    if (hent->h_addr_list) {
111
        int i = 0;
112
        while (hent->h_addr_list[i]) {
113
            free(hent->h_addr_list[i]);
114
            i++;
115
        }
116
        free(hent->h_addr_list);
117
    }
118
    free(hent);
119
}
120
 
121
/* Allocate hent structure with room for one in_addr. Returns NULL on
122
   failure. */
123
static struct hostent*
124
alloc_hent(void)
125
{
126
    struct hostent *hent;
127
 
128
    hent = malloc(sizeof(struct hostent));
129
    if (hent) {
130
        memset(hent, 0, sizeof(struct hostent));
131
        hent->h_addr_list = malloc(sizeof(char *)*2);
132
        if (!hent->h_addr_list) {
133
            free_hent(hent);
134
            return NULL;
135
        }
136
        hent->h_addr_list[0] = malloc(sizeof(struct in_addr));
137
        if (!hent->h_addr_list[0]) {
138
            free_hent(hent);
139
            return NULL;
140
        }
141
        hent->h_addr_list[1] = NULL;
142
    }
143
 
144
    return hent;
145
}
146
 
147
/* Thread destructor used to free stuff stored in per-thread data slot. */
148
static void
149
thread_destructor(CYG_ADDRWORD data)
150
{
151
    struct hostent *hent;
152
    hent = (struct hostent *)cyg_thread_get_data(ptdindex);
153
    if (hent)
154
        free_hent(hent);
155
    return;
156
    data=data;
157
}
158
 
159
/* Store the hent away in the per-thread data. */
160
static void
161
store_hent(struct hostent *hent)
162
{
163
    // Prevent memory leaks by setting a destructor to be
164
    // called on thread exit to free per-thread data.
165
    cyg_thread_add_destructor( &thread_destructor, 0 );
166
    cyg_thread_set_data(ptdindex, (CYG_ADDRWORD)hent);
167
}
168
 
169
/* If there is an answer to an old query, free the memory it uses. */
170
static void
171
free_stored_hent(void)
172
{
173
    struct hostent *hent;
174
    hent = (struct hostent *)cyg_thread_get_data(ptdindex);
175
    if (hent) {
176
        free_hent(hent);
177
        cyg_thread_set_data(ptdindex, (CYG_ADDRWORD)NULL);
178
        cyg_thread_rem_destructor( &thread_destructor, 0 );
179
    }
180
}
181
 
182
/* Send the query to the server and read the response back. Return -1
183
   if it fails, otherwise put the response back in msg and return the
184
   length of the response. */
185
static int
186
send_recv(char * msg, int len, int msglen)
187
{
188
    struct dns_header *dns_hdr;
189
    struct timeval timeout;
190
    int finished = false;
191
    int backoff = 1;
192
    fd_set readfds;
193
    int written;
194
    int ret;
195
 
196
    CYG_REPORT_FUNCNAMETYPE( "send_recv", "returning %d" );
197
    CYG_REPORT_FUNCARG3( "msg=%08x, len=%d, msglen", msg, len, msglen );
198
 
199
    CYG_CHECK_DATA_PTR( msg, "msg is not a valid pointer!" );
200
 
201
    dns_hdr = (struct dns_header *) msg;
202
 
203
    do {
204
        written = write(s, msg, len);
205
        if (written < 0) {
206
            ret = -1;
207
            break;
208
        }
209
 
210
        FD_ZERO(&readfds);
211
        FD_SET(s, &readfds);
212
 
213
        timeout.tv_sec = backoff;
214
        timeout.tv_usec = 0;
215
        backoff = backoff << 1;
216
 
217
        ret = select(s+1, &readfds, NULL, NULL, &timeout);
218
        if (ret < 0) {
219
            ret = -1;
220
            break;
221
        }
222
        /* Timeout */
223
        if (ret == 0) {
224
            if (backoff > 16) {
225
                h_errno = TRY_AGAIN;
226
                ret = -1;
227
                break;
228
            }
229
        }
230
        if (ret == 1) {
231
            ret = read(s, msg, msglen);
232
            if (ret < 0) {
233
                ret = -1;
234
                break;
235
            }
236
 
237
            /* Reply to an old query. Ignore it */
238
            if (ntohs(dns_hdr->id) != (id-1)) {
239
                continue;
240
            }
241
            finished = true;
242
        }
243
    } while (!finished);
244
 
245
    CYG_REPORT_RETVAL( ret );
246
 
247
    return ret;
248
}
249
 
250
/* Include the DNS client implementation code */
251
#include <cyg/ns/dns/dns_impl.inl>
252
 
253
/* Initialise the resolver. Open a socket and bind it to the address
254
   of the server.  return -1 if something goes wrong, otherwise 0. If
255
   we are being called a second time we have to be careful to allow
256
   any ongoing lookups to finish before we close the socket and
257
   connect to a different DNS server. The danger here is that we may
258
   have to wait for upto 32 seconds if the DNS server is down.
259
 */
260
int
261
cyg_dns_res_init(struct in_addr *dns_server)
262
{
263
    struct sockaddr_in server;
264
    struct servent *sent;
265
    static int init =0;
266
 
267
    CYG_REPORT_FUNCNAMETYPE( "cyg_dns_res_init", "returning %d" );
268
    CYG_REPORT_FUNCARG1( "dns_server=%08x", dns_server );
269
 
270
    CYG_CHECK_DATA_PTR( dns_server, "dns_server is not a valid pointer!" );
271
 
272
    if (init) {
273
      cyg_drv_mutex_lock(&dns_mutex);
274
      cyg_thread_free_data_index(ptdindex);
275
      if (s >= 0) {
276
        close(s);
277
      }
278
    } else {
279
      init = 1;
280
      cyg_drv_mutex_init(&dns_mutex);
281
      cyg_drv_mutex_lock(&dns_mutex);
282
    }
283
 
284
 
285
    s = socket(PF_INET, SOCK_DGRAM, 0);
286
    if (s < 0) {
287
        cyg_drv_mutex_unlock(&dns_mutex);
288
        CYG_REPORT_RETVAL( -1 );
289
        return -1;
290
    }
291
 
292
    sent = getservbyname("domain", "udp");
293
    if (sent == (struct servent *)0) {
294
        s = -1;
295
        cyg_drv_mutex_unlock(&dns_mutex);
296
        CYG_REPORT_RETVAL( -1 );
297
        return -1;
298
    }
299
 
300
    memcpy((char *)&server.sin_addr, dns_server, sizeof(server.sin_addr));
301
    server.sin_port = sent->s_port;
302
    server.sin_family = AF_INET;
303
    server.sin_len = sizeof(server);
304
 
305
    if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
306
        s = -1;
307
        cyg_drv_mutex_unlock(&dns_mutex);
308
        CYG_REPORT_RETVAL( -1 );
309
        return -1;
310
    }
311
    ptdindex = cyg_thread_new_data_index();
312
 
313
    cyg_drv_mutex_unlock(&dns_mutex);
314
 
315
    CYG_REPORT_RETVAL( 0 );
316
    return 0;
317
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.