source: rtems/cpukit/libnetworking/libc/gethostnamadr.c @ cb68253

5
Last change on this file since cb68253 was cb68253, checked in by Sebastian Huber <sebastian.huber@…>, on 09/07/18 at 04:19:02

network: Use kernel/user space header files

Add and use <machine/rtems-bsd-kernel-space.h> and
<machine/rtems-bsd-user-space.h> similar to the libbsd to avoid command
line defines and defines scattered throught the code base.

Simplify cpukit/libnetworking/Makefile.am.

Update #3375.

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