source: rtems/cpukit/libnetworking/libc/gethostnamadr.c @ 199ccde

4.104.115
Last change on this file since 199ccde was 199ccde, checked in by Chris Johns <chrisj@…>, on 05/08/09 at 04:55:53

2009-05-08 Chris Johns <chrisj@…>

  • cpukit/libblock/src/bdpart.c, libmisc/shell/main_msdosfmt.c, libmisc/shell/main_rm.c, libnetworking/libc/gethostnamadr.c, score/include/rtems/score/bitfield.h, score/inline/rtems/score/priority.inl: Remove warnings.
  • Property mode set to 100644
File size: 10.5 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(void)
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
161int gethostbyaddr_r(const void *addr, socklen_t len, int type,
162               struct hostent *ret, char *buf, size_t buflen,
163               struct hostent **result, int *h_errnop)
164{
165  #warning "implement a proper gethostbyaddr_r"
166 
167  *result = gethostbyaddr( addr, len, type );
168  if ( *result )
169    return 0;
170  return -1;
171}
172
173struct hostent *
174gethostbyaddr(const void *addr, socklen_t len, int type)
175{
176        struct hostent *hp = 0;
177        int nserv = 0;
178
179        if (!service_done)
180                init_services();
181
182        while (!hp) {
183                switch (service_order[nserv]) {
184                      case SERVICE_NONE:
185                        return 0;
186                      case SERVICE_HOSTS:
187                        hp = _gethostbyhtaddr(addr, len, type);
188                        break;
189                      case SERVICE_BIND:
190                        hp = _gethostbydnsaddr(addr, len, type);
191                        break;
192                      case SERVICE_NIS:
193                        hp = _gethostbynisaddr(addr, len, type);
194                        break;
195                }
196                nserv++;
197        }
198        return hp;
199}
200
201void
202sethostent(int stayopen)
203{
204        _sethosthtent(stayopen);
205        _sethostdnsent(stayopen);
206}
207
208void
209endhostent(void)
210{
211        _endhosthtent();
212        _endhostdnsent();
213}
214
215#ifdef _THREAD_SAFE
216
217/* return length of decoded data or -1 */
218static int __dns_decodename(unsigned char *packet,unsigned int offset,unsigned char *dest,
219         unsigned int maxlen,unsigned char* behindpacket) {
220  unsigned char *tmp;
221  unsigned char *max=dest+maxlen;
222  unsigned char *after=packet+offset;
223  int ok=0;
224  for (tmp=after; maxlen>0&&*tmp; ) {
225    if (tmp>=behindpacket) return -1;
226    if ((*tmp>>6)==3) {   /* goofy DNS decompression */
227      unsigned int ofs=((unsigned int)(*tmp&0x3f)<<8)|*(tmp+1);
228      if (ofs>=(unsigned int)offset) return -1; /* RFC1035: "pointer to a _prior_ occurrance" */
229      if (after<tmp+2) after=tmp+2;
230      tmp=packet+ofs;
231      ok=0;
232    } else {
233      unsigned int duh;
234      if (dest+*tmp+1>max) return -1;
235      if (tmp+*tmp+1>=behindpacket) return -1;
236      for (duh=*tmp; duh>0; --duh)
237  *dest++=*++tmp;
238      *dest++='.'; ok=1;
239      ++tmp;
240      if (tmp>after) { after=tmp; if (!*tmp) ++after; }
241    }
242  }
243  if (ok) --dest;
244  *dest=0;
245  return after-packet;
246}
247
248static int __dns_gethostbyx_r(
249    const char* name,
250    struct hostent* result,
251    char *buf, size_t buflen,
252    struct hostent **RESULT,
253    int *h_errnop,
254    int lookfor)
255{
256
257  int names,ips;
258  unsigned char *cur;
259  unsigned char *max;
260  unsigned char inpkg[1500];
261  char* tmp;
262  int size;
263
264  if (lookfor==1) {
265    result->h_addrtype=AF_INET;
266    result->h_length=4;
267  } else {
268    result->h_addrtype=AF_INET6;
269    result->h_length=16;
270  }
271  result->h_aliases=(char**)(buf+8*sizeof(char*));
272  result->h_addr_list=(char**)buf;
273  result->h_aliases[0]=0;
274
275  cur=(unsigned char*)buf+16*sizeof(char*);
276  max=(unsigned char*)buf+buflen;
277  names=ips=0;
278
279  if ((size=res_query(name,C_IN,lookfor,inpkg,512))<0) {
280invalidpacket:
281    *h_errnop=HOST_NOT_FOUND;
282    return -1;
283  }
284  {
285    tmp=(char*)inpkg+12;
286    {
287      char Name[257];
288      unsigned short q=((unsigned short)inpkg[4]<<8)+inpkg[5];
289      while (q>0) {
290  if (tmp>(char*)inpkg+size) goto invalidpacket;
291  while (*tmp) { tmp+=*tmp+1; if (tmp>(char*)inpkg+size) goto invalidpacket; }
292  tmp+=5;
293  --q;
294      }
295      if (tmp>(char*)inpkg+size) goto invalidpacket;
296      q=((unsigned short)inpkg[6]<<8)+inpkg[7];
297      if (q<1) goto nodata;
298      while (q>0) {
299        int decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),(unsigned char*)Name,256,inpkg+size);
300  if (decofs<0) break;
301  tmp=(char*)inpkg+decofs;
302  --q;
303  if (tmp[0]!=0 || tmp[1]!=lookfor || /* TYPE != A */
304      tmp[2]!=0 || tmp[3]!=1) {   /* CLASS != IN */
305    if (tmp[1]==5) {  /* CNAME */
306      tmp+=10;
307      decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),(unsigned char*)Name,256,inpkg+size);
308      if (decofs<0) break;
309      tmp=(char*)inpkg+decofs;
310    } else
311      break;
312    continue;
313  }
314  tmp+=10;  /* skip type, class, TTL and length */
315  {
316    int slen;
317    if (lookfor==1 || lookfor==28) /* A or AAAA*/ {
318      slen=strlen(Name);
319      if (cur+slen+8+(lookfor==28?12:0)>=max) { *h_errnop=NO_RECOVERY; return -1; }
320    } else if (lookfor==12) /* PTR */ {
321      decofs=__dns_decodename(inpkg,(size_t)(tmp-(char*)inpkg),(unsigned char*)Name,256,inpkg+size);
322      if (decofs<0) break;
323      tmp=(char*)inpkg+decofs;
324      slen=strlen(Name);
325    } else
326      slen=strlen(Name);
327    strcpy((char*)cur,Name);
328    if (names==0)
329      result->h_name=(char*)cur;
330    else
331      result->h_aliases[names-1]=(char*)cur;
332    result->h_aliases[names]=0;
333    if (names<8) ++names;
334/*    cur+=slen+1; */
335    cur+=(slen|3)+1;
336    result->h_addr_list[ips++] = (char*)cur;
337    if (lookfor==1) /* A */ {
338      *(int*)cur=*(int*)tmp;
339      cur+=4;
340      result->h_addr_list[ips]=0;
341    } else if (lookfor==28) /* AAAA */ {
342      {
343        int k;
344        for (k=0; k<16; ++k) cur[k]=tmp[k];
345      }
346      cur+=16;
347      result->h_addr_list[ips]=0;
348    }
349  }
350/*        puts(Name); */
351      }
352    }
353  }
354  if (!names) {
355nodata:
356    *h_errnop=NO_DATA;
357    return -1;
358  }
359  *h_errnop=0;
360  *RESULT=result;
361  return 0;
362}
363
364
365
366
367int gethostbyname_r(const char*      name,
368        struct hostent*  result,
369        char            *buf,
370        int              buflen,
371        struct hostent **RESULT,
372        int             *h_errnop)
373{
374       
375  size_t L=strlen(name);
376  result->h_name=buf;
377  if (buflen<L) { *h_errnop=ERANGE; return 1; }
378  strcpy(buf,name);
379
380  result->h_addr_list=(char**)(buf+strlen(name)+1);
381  result->h_addr_list+=sizeof(unsigned long)-((unsigned long)(result->h_addr_list)&(sizeof(unsigned long)-1));
382  result->h_addr_list[0]=(char*)&result->h_addr_list[2];
383  if (inet_pton(AF_INET,name,result->h_addr_list[0])) {
384    result->h_addrtype=AF_INET;
385    result->h_length=4;
386commonip:
387    result->h_aliases=result->h_addr_list+2*sizeof(char**);
388    result->h_aliases[0]=0;
389    result->h_addr_list[1]=0;
390    *RESULT=result;
391    *h_errnop=0;
392    return 0;
393  } else if (inet_pton(AF_INET6,name,result->h_addr_list[0])) {
394    result->h_addrtype=AF_INET6;
395    result->h_length=16;
396    goto commonip;
397  }
398
399
400  {
401    struct hostent* r;
402    sethostent(0);
403    while ((r=gethostent_r(buf,buflen))) {
404      int i;
405      if (r->h_addrtype==AF_INET && !strcasecmp(r->h_name,name)) {  /* found it! */
406found:
407  memmove(result,r,sizeof(struct hostent));
408  *RESULT=result;
409  *h_errnop=0;
410  endhostent();
411  return 0;
412      }
413      for (i=0; i<16; ++i) {
414  if (r->h_aliases[i]) {
415    if (!strcasecmp(r->h_aliases[i],name)) goto found;
416  } else break;
417      }
418    }
419    endhostent();
420  }
421
422  return __dns_gethostbyx_r(name,result,buf+L,buflen-L,RESULT,h_errnop,1);
423}
424
425#endif
426
Note: See TracBrowser for help on using the repository browser.