source: rtems/cpukit/libnetworking/libc/gethostnamadr.c @ 09fdb5e8

4.104.114.84.95
Last change on this file since 09fdb5e8 was 09fdb5e8, checked in by Ralf Corsepius <ralf.corsepius@…>, on 03/30/07 at 05:15:58

Eliminate SCCS, LINT. Add HAVE_CONFIG_H.

  • Property mode set to 100644
File size: 10.0 KB
Line 
1/*-
2 * Copyright (c) 1994, Garrett Wollman
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#if HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include <sys/param.h>
31#include <sys/socket.h>
32#include <netinet/in.h>
33#include <arpa/inet.h>
34#include <netdb.h>
35#include <stdio.h>
36#include <ctype.h>
37#include <errno.h>
38#include <string.h>
39#include <arpa/nameser.h>               /* XXX hack for _res */
40#include <resolv.h>                     /* XXX hack for _res */
41
42#define _PATH_HOSTCONF  "/etc/host.conf"
43
44enum service_type {
45  SERVICE_NONE = 0,
46  SERVICE_BIND,
47  SERVICE_HOSTS,
48  SERVICE_NIS };
49#define SERVICE_MAX     SERVICE_NIS
50
51static struct {
52  const char *name;
53  enum service_type type;
54} service_names[] = {
55  { "hosts", SERVICE_HOSTS },
56  { "/etc/hosts", SERVICE_HOSTS },
57  { "hosttable", SERVICE_HOSTS },
58  { "htable", SERVICE_HOSTS },
59  { "bind", SERVICE_BIND },
60  { "dns", SERVICE_BIND },
61  { "domain", SERVICE_BIND },
62  { "yp", SERVICE_NIS },
63  { "yellowpages", SERVICE_NIS },
64  { "nis", SERVICE_NIS },
65  { 0, SERVICE_NONE }
66};
67
68static enum service_type service_order[SERVICE_MAX + 1];
69static int service_done = 0;
70
71static enum service_type
72get_service_name(const char *name) {
73        int i;
74        for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
75                if(!strcasecmp(name, service_names[i].name)) {
76                        return service_names[i].type;
77                }
78        }
79        return SERVICE_NONE;
80}
81
82static void
83init_services()
84{
85        char *cp, *p, buf[BUFSIZ];
86        register int cc = 0;
87        FILE *fd;
88
89        if ((fd = (FILE *)fopen(_PATH_HOSTCONF, "r")) == NULL) {
90                                /* make some assumptions */
91                service_order[0] = SERVICE_BIND;
92                service_order[1] = SERVICE_HOSTS;
93                service_order[2] = SERVICE_NONE;
94        } else {
95                while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
96                        if(buf[0] == '#')
97                                continue;
98
99                        p = buf;
100                        while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
101                                ;
102                        if (cp == NULL)
103                                continue;
104                        do {
105                                if (isalpha((int)cp[0])) {
106                                        service_order[cc] = get_service_name(cp);
107                                        if(service_order[cc] != SERVICE_NONE)
108                                                cc++;
109                                }
110                                while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
111                                        ;
112                        } while(cp != NULL && cc < SERVICE_MAX);
113                }
114                service_order[cc] = SERVICE_NONE;
115                fclose(fd);
116        }
117        service_done = 1;
118}
119
120struct hostent *
121gethostbyname(const char *name)
122{
123        struct hostent *hp;
124
125        if (_res.options & RES_USE_INET6) {             /* XXX */
126                hp = gethostbyname2(name, AF_INET6);    /* XXX */
127                if (hp)                                 /* XXX */
128                        return (hp);                    /* XXX */
129        }                                               /* XXX */
130        return (gethostbyname2(name, AF_INET));
131}
132
133struct hostent *
134gethostbyname2(const char *name, int type)
135{
136        struct hostent *hp = 0;
137        int nserv = 0;
138
139        if (!service_done)
140                init_services();
141
142        while (!hp) {
143                switch (service_order[nserv]) {
144                      case SERVICE_NONE:
145                        return NULL;
146                      case SERVICE_HOSTS:
147                        hp = _gethostbyhtname(name, type);
148                        break;
149                      case SERVICE_BIND:
150                        hp = _gethostbydnsname(name, type);
151                        break;
152                      case SERVICE_NIS:
153                        hp = _gethostbynisname(name, type);
154                        break;
155                }
156                nserv++;
157        }
158        return hp;
159}
160
161struct hostent *
162gethostbyaddr(const char *addr, int len, int type)
163{
164        struct hostent *hp = 0;
165        int nserv = 0;
166
167        if (!service_done)
168                init_services();
169
170        while (!hp) {
171                switch (service_order[nserv]) {
172                      case SERVICE_NONE:
173                        return 0;
174                      case SERVICE_HOSTS:
175                        hp = _gethostbyhtaddr(addr, len, type);
176                        break;
177                      case SERVICE_BIND:
178                        hp = _gethostbydnsaddr(addr, len, type);
179                        break;
180                      case SERVICE_NIS:
181                        hp = _gethostbynisaddr(addr, len, type);
182                        break;
183                }
184                nserv++;
185        }
186        return hp;
187}
188
189void
190sethostent(stayopen)
191        int stayopen;
192{
193        _sethosthtent(stayopen);
194        _sethostdnsent(stayopen);
195}
196
197void
198endhostent()
199{
200        _endhosthtent();
201        _endhostdnsent();
202}
203
204#ifdef _THREAD_SAFE
205
206/* return length of decoded data or -1 */
207static int __dns_decodename(unsigned char *packet,unsigned int offset,unsigned char *dest,
208         unsigned int maxlen,unsigned char* behindpacket) {
209  unsigned char *tmp;
210  unsigned char *max=dest+maxlen;
211  unsigned char *after=packet+offset;
212  int ok=0;
213  for (tmp=after; maxlen>0&&*tmp; ) {
214    if (tmp>=behindpacket) return -1;
215    if ((*tmp>>6)==3) {   /* goofy DNS decompression */
216      unsigned int ofs=((unsigned int)(*tmp&0x3f)<<8)|*(tmp+1);
217      if (ofs>=(unsigned int)offset) return -1; /* RFC1035: "pointer to a _prior_ occurrance" */
218      if (after<tmp+2) after=tmp+2;
219      tmp=packet+ofs;
220      ok=0;
221    } else {
222      unsigned int duh;
223      if (dest+*tmp+1>max) return -1;
224      if (tmp+*tmp+1>=behindpacket) return -1;
225      for (duh=*tmp; duh>0; --duh)
226  *dest++=*++tmp;
227      *dest++='.'; ok=1;
228      ++tmp;
229      if (tmp>after) { after=tmp; if (!*tmp) ++after; }
230    }
231  }
232  if (ok) --dest;
233  *dest=0;
234  return after-packet;
235}
236
237static int __dns_gethostbyx_r(const char* name, struct hostent* result,
238      char *buf, size_t buflen,
239      struct hostent **RESULT, int *h_errnop, int lookfor) {
240
241  int names,ips;
242  unsigned char *cur;
243  unsigned char *max;
244  unsigned char inpkg[1500];
245  char* tmp;
246  int size;
247
248  if (lookfor==1) {
249    result->h_addrtype=AF_INET;
250    result->h_length=4;
251  } else {
252    result->h_addrtype=AF_INET6;
253    result->h_length=16;
254  }
255  result->h_aliases=(char**)(buf+8*sizeof(char*));
256  result->h_addr_list=(char**)buf;
257  result->h_aliases[0]=0;
258
259  cur=buf+16*sizeof(char*);
260  max=buf+buflen;
261  names=ips=0;
262
263  if ((size=res_query(name,C_IN,lookfor,inpkg,512))<0) {
264invalidpacket:
265    *h_errnop=HOST_NOT_FOUND;
266    return -1;
267  }
268  {
269    tmp=inpkg+12;
270    {
271      char Name[257];
272      unsigned short q=((unsigned short)inpkg[4]<<8)+inpkg[5];
273      while (q>0) {
274  if (tmp>(char*)inpkg+size) goto invalidpacket;
275  while (*tmp) { tmp+=*tmp+1; if (tmp>(char*)inpkg+size) goto invalidpacket; }
276  tmp+=5;
277  --q;
278      }
279      if (tmp>(char*)inpkg+size) goto invalidpacket;
280      q=((unsigned short)inpkg[6]<<8)+inpkg[7];
281      if (q<1) goto nodata;
282      while (q>0) {
283  int decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),Name,256,inpkg+size);
284  if (decofs<0) break;
285  tmp=inpkg+decofs;
286  --q;
287  if (tmp[0]!=0 || tmp[1]!=lookfor || /* TYPE != A */
288      tmp[2]!=0 || tmp[3]!=1) {   /* CLASS != IN */
289    if (tmp[1]==5) {  /* CNAME */
290      tmp+=10;
291      decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),Name,256,inpkg+size);
292      if (decofs<0) break;
293      tmp=inpkg+decofs;
294    } else
295      break;
296    continue;
297  }
298  tmp+=10;  /* skip type, class, TTL and length */
299  {
300    int slen;
301    if (lookfor==1 || lookfor==28) /* A or AAAA*/ {
302      slen=strlen(Name);
303      if (cur+slen+8+(lookfor==28?12:0)>=max) { *h_errnop=NO_RECOVERY; return -1; }
304    } else if (lookfor==12) /* PTR */ {
305      decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),Name,256,inpkg+size);
306      if (decofs<0) break;
307      tmp=inpkg+decofs;
308      slen=strlen(Name);
309    } else
310      slen=strlen(Name);
311    strcpy(cur,Name);
312    if (names==0)
313      result->h_name=cur;
314    else
315      result->h_aliases[names-1]=cur;
316    result->h_aliases[names]=0;
317    if (names<8) ++names;
318/*    cur+=slen+1; */
319    cur+=(slen|3)+1;
320    result->h_addr_list[ips++] = cur;
321    if (lookfor==1) /* A */ {
322      *(int*)cur=*(int*)tmp;
323      cur+=4;
324      result->h_addr_list[ips]=0;
325    } else if (lookfor==28) /* AAAA */ {
326      {
327        int k;
328        for (k=0; k<16; ++k) cur[k]=tmp[k];
329      }
330      cur+=16;
331      result->h_addr_list[ips]=0;
332    }
333  }
334/*        puts(Name); */
335      }
336    }
337  }
338  if (!names) {
339nodata:
340    *h_errnop=NO_DATA;
341    return -1;
342  }
343  *h_errnop=0;
344  *RESULT=result;
345  return 0;
346}
347
348
349
350
351int gethostbyname_r(const char*      name,
352        struct hostent*  result,
353        char            *buf,
354        int              buflen,
355        struct hostent **RESULT,
356        int             *h_errnop)
357{
358       
359  size_t L=strlen(name);
360  result->h_name=buf;
361  if (buflen<L) { *h_errnop=ERANGE; return 1; }
362  strcpy(buf,name);
363
364  result->h_addr_list=(char**)(buf+strlen(name)+1);
365  result->h_addr_list+=sizeof(unsigned long)-((unsigned long)(result->h_addr_list)&(sizeof(unsigned long)-1));
366  result->h_addr_list[0]=(char*)&result->h_addr_list[2];
367  if (inet_pton(AF_INET,name,result->h_addr_list[0])) {
368    result->h_addrtype=AF_INET;
369    result->h_length=4;
370commonip:
371    result->h_aliases=result->h_addr_list+2*sizeof(char**);
372    result->h_aliases[0]=0;
373    result->h_addr_list[1]=0;
374    *RESULT=result;
375    *h_errnop=0;
376    return 0;
377  } else if (inet_pton(AF_INET6,name,result->h_addr_list[0])) {
378    result->h_addrtype=AF_INET6;
379    result->h_length=16;
380    goto commonip;
381  }
382
383
384  {
385    struct hostent* r;
386    sethostent(0);
387    while ((r=gethostent_r(buf,buflen))) {
388      int i;
389      if (r->h_addrtype==AF_INET && !strcasecmp(r->h_name,name)) {  /* found it! */
390found:
391  memmove(result,r,sizeof(struct hostent));
392  *RESULT=result;
393  *h_errnop=0;
394  endhostent();
395  return 0;
396      }
397      for (i=0; i<16; ++i) {
398  if (r->h_aliases[i]) {
399    if (!strcasecmp(r->h_aliases[i],name)) goto found;
400  } else break;
401      }
402    }
403    endhostent();
404  }
405
406  return __dns_gethostbyx_r(name,result,buf+L,buflen-L,RESULT,h_errnop,1);
407}
408
409#endif
410
Note: See TracBrowser for help on using the repository browser.