source: rtems/cpukit/libnetworking/libc/gethostbyht.c @ 068c3ee1

4.104.114.84.95
Last change on this file since 068c3ee1 was 068c3ee1, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 2, 2006 at 9:48:41 PM

2006-11-02 Steven Johnson <sjohnson@…>

  • libnetworking/netdb.h, libnetworking/libc/gethostbyht.c, libnetworking/libc/gethostnamadr.c: This patch adds a functional gethostbyname_r to RTEMS. We were having problems with multiple threads calling gethostbyname, so we decided the best way to deal with it was to do it properly, rather than kludge up our code to make gethostbyname safe. We have found several slightly different parameter lists for this function, it does not seem to be standard. The one we used has the linux interface. In RTEMS there was an existing gethostbyname_r inside a #ifdef _THREAD_SAFE which was NOT Threadsafe, as this just called gethostbyname. So we have placed all of the additional code inside the #ifdef _THREAD_SAFE.
  • Property mode set to 100644
File size: 8.2 KB
Line 
1/*-
2 * Copyright (c) 1985, 1988, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 * -
33 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55static char sccsid[] = "@(#)gethostnamadr.c     8.1 (Berkeley) 6/4/93";
56static char rcsid[] = "$Id$";
57#endif /* LIBC_SCCS and not lint */
58
59#include <sys/param.h>
60#include <sys/socket.h>
61#include <netinet/in.h>
62#include <arpa/inet.h>
63#include <netdb.h>
64#include <stdio.h>
65#include <ctype.h>
66#include <errno.h>
67#include <string.h>
68#include <arpa/nameser.h>       /* XXX */
69#include <resolv.h>             /* XXX */
70#include <sys/fcntl.h>
71
72#define MAXALIASES      35
73
74static struct hostent host;
75static char *host_aliases[MAXALIASES];
76static char hostbuf[BUFSIZ+1];
77static FILE *hostf = NULL;
78static u_char host_addr[16];    /* IPv4 or IPv6 */
79static char *h_addr_ptrs[2];
80static int stayopen = 0;
81
82static char* hostmap = NULL;
83static unsigned int hostlen = 0; 
84static char *cur;
85
86void
87_sethosthtent(f)
88        int f;
89{
90        if (!hostf)
91                hostf = fopen(_PATH_HOSTS, "r" );
92        else
93                rewind(hostf);
94        stayopen = f;
95}
96
97void
98_endhosthtent()
99{
100        if (hostf && !stayopen) {
101                (void) fclose(hostf);
102                hostf = NULL;
103        }
104}
105
106struct hostent *
107gethostent()
108{
109        char *p;
110        register char *cp, **q;
111        int af, len;
112
113        if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
114                h_errno = NETDB_INTERNAL;
115                return (NULL);
116        }
117 again:
118        if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
119                h_errno = HOST_NOT_FOUND;
120                return (NULL);
121        }
122        if (*p == '#')
123                goto again;
124        if (!(cp = strpbrk(p, "#\n")))
125                goto again;
126        *cp = '\0';
127        if (!(cp = strpbrk(p, " \t")))
128                goto again;
129        *cp++ = '\0';
130        if (inet_pton(AF_INET6, p, host_addr) > 0) {
131                af = AF_INET6;
132                len = IN6ADDRSZ;
133        } else if (inet_pton(AF_INET, p, host_addr) > 0) {
134                if (_res.options & RES_USE_INET6) {
135                        _map_v4v6_address((char*)host_addr, (char*)host_addr);
136                        af = AF_INET6;
137                        len = IN6ADDRSZ;
138                } else {
139                        af = AF_INET;
140                        len = INADDRSZ;
141                }
142        } else {
143                goto again;
144        }
145        h_addr_ptrs[0] = (char *)host_addr;
146        h_addr_ptrs[1] = NULL;
147        host.h_addr_list = h_addr_ptrs;
148        host.h_length = len;
149        host.h_addrtype = af;
150        while (*cp == ' ' || *cp == '\t')
151                cp++;
152        host.h_name = cp;
153        q = host.h_aliases = host_aliases;
154        if ((cp = strpbrk(cp, " \t")) != NULL)
155                *cp++ = '\0';
156        while (cp && *cp) {
157                if (*cp == ' ' || *cp == '\t') {
158                        cp++;
159                        continue;
160                }
161                if (q < &host_aliases[MAXALIASES - 1])
162                        *q++ = cp;
163                if ((cp = strpbrk(cp, " \t")) != NULL)
164                        *cp++ = '\0';
165        }
166        *q = NULL;
167        h_errno = NETDB_SUCCESS;
168        return (&host);
169}
170
171struct hostent *
172_gethostbyhtname(name, af)
173        const char *name;
174        int af;
175{
176        register struct hostent *p;
177        register char **cp;
178       
179        sethostent(0);
180        while ((p = gethostent()) != NULL) {
181                if (p->h_addrtype != af)
182                        continue;
183                if (strcasecmp(p->h_name, name) == 0)
184                        break;
185                for (cp = p->h_aliases; *cp != 0; cp++)
186                        if (strcasecmp(*cp, name) == 0)
187                                goto found;
188        }
189found:
190        endhostent();
191        return (p);
192}
193
194struct hostent *
195_gethostbyhtaddr(addr, len, af)
196        const char *addr;
197        int len, af;
198{
199        register struct hostent *p;
200
201        sethostent(0);
202        while ((p = gethostent()) != NULL)
203                if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
204                        break;
205        endhostent();
206        return (p);
207}
208
209
210#ifdef _THREAD_SAFE
211
212static int isblank ( int ch )
213{
214    return ch == ' '  ||  ch == '\t';
215}
216
217struct hostent* gethostent_r(char* buf, int len) 
218{
219  char  *dest;
220  struct hostent* pe=(struct hostent*)buf;
221  char*  last;
222  char*  max=buf+len;
223  int    aliasidx;
224  int    curlen;
225 
226   
227  if (hostf<0) return 0;
228  fseek(hostf,0,SEEK_END);
229  curlen=ftell(hostf);
230  fseek(hostf,0,SEEK_SET);
231 
232  if (curlen > hostlen) {
233    if (hostmap) {
234      hostmap = realloc(hostmap,curlen);
235    }
236    else {
237      hostmap = malloc(curlen);
238    }
239  }
240  hostlen = curlen;
241 
242  if (hostmap) {
243    if (fread(hostmap,hostlen,1,hostf) != hostlen) {
244        hostmap=0; goto error; 
245    }
246    cur=hostmap;
247  }
248  last=hostmap+hostlen;
249again:
250  if ((size_t)len<sizeof(struct hostent)+11*sizeof(char*)) goto nospace;
251  dest=buf+sizeof(struct hostent);
252  pe->h_name=0;
253  pe->h_aliases=(char**)dest; pe->h_aliases[0]=0; dest+=10*sizeof(char*);
254  pe->h_addr_list=(char**)dest; dest+=2*sizeof(char**);
255  if (cur>=last) return 0;
256  if (*cur=='#' || *cur=='\n') goto parseerror;
257  /* first, the ip number */
258  pe->h_name=cur;
259  while (cur<last && !isspace(*cur)) cur++;
260  if (cur>=last) return 0;
261  if (*cur=='\n') goto parseerror;
262  {
263    char save=*cur;
264    *cur=0;
265    pe->h_addr_list[0]=dest;
266    pe->h_addr_list[1]=0;
267    if (max-dest<16) goto nospace;
268    if (inet_pton(AF_INET6,pe->h_name,dest)>0) {
269      pe->h_addrtype=AF_INET6;
270      pe->h_length=16;
271      dest+=16;
272    } else if (inet_pton(AF_INET,pe->h_name,dest)>0) {
273      pe->h_addrtype=AF_INET;
274      pe->h_length=4;
275      dest+=4;
276    } else {
277      *cur=save;
278      goto parseerror;
279    }
280    *cur=save;
281  }
282  ++cur;
283  /* now the aliases */
284  for (aliasidx=0;aliasidx<9;++aliasidx) {
285    while (cur<last && isblank(*cur)) ++cur;
286    pe->h_aliases[aliasidx]=cur;
287    while (cur<last && !isspace(*cur)) ++cur;
288    {
289      char *from=pe->h_aliases[aliasidx];
290      int len=cur-from;
291      if (max-dest<len+2) goto nospace;
292      pe->h_aliases[aliasidx]=dest;
293      memmove(dest,from,(size_t)(cur-from));
294      dest+=len;
295      *dest=0; ++dest;
296    }
297    if (*cur=='\n') { ++cur; ++aliasidx; break; }
298    if (cur>=last || !isblank(*cur)) break;
299    cur++;
300  }
301  pe->h_aliases[aliasidx]=0;
302  pe->h_name=pe->h_aliases[0];
303  pe->h_aliases++;
304  return pe;
305parseerror:
306  while (cur<last && *cur!='\n') cur++;
307  cur++;
308  goto again;
309nospace:
310  errno=ERANGE;
311  goto __error;
312error:
313  errno=ENOMEM;
314__error:
315  if (hostmap!=NULL) free(hostmap);
316  hostmap=NULL;
317  return 0;
318}
319#endif
Note: See TracBrowser for help on using the repository browser.