source: trunk/src/sh_static.c @ 481

Last change on this file since 481 was 481, checked in by katerina, 6 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

File size: 49.1 KB
RevLine 
[1]1/*  Copyright (C) 2003     Manuel Novoa III
2 *
3 *  This library is free software; you can redistribute it and/or
4 *  modify it under the terms of the GNU Library General Public
5 *  License as published by the Free Software Foundation; either
6 *  version 2 of the License, or (at your option) any later version.
7 *
8 *  This library is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 *  Library General Public License for more details.
12 *
13 *  You should have received a copy of the GNU Library General Public
14 *  License along with this library; if not, write to the Free
15 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 */
17
18/*  Nov 6, 2003  Initial version.
19 *
20 *  NOTE: This implementation is quite strict about requiring all
21 *    field seperators.  It also does not allow leading whitespace
22 *    except when processing the numeric fields.  glibc is more
23 *    lenient.  See the various glibc difference comments below.
24 *
25 *  TODO:
26 *    Move to dynamic allocation of (currently staticly allocated)
27 *      buffers; especially for the group-related functions since
28 *      large group member lists will cause error returns.
29 *
30 */
31
32/* Jul 20, 2004 Adapted for samhain. Rainer Wichmann.
33 *
34 *   Stripped all unneeded code.
35 */
36
37#include "config_xor.h"
38
39#if defined(SH_COMPILE_STATIC) && defined(__linux__)
40
41#define _GNU_SOURCE
42#include <features.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <stdint.h>
46#include <string.h>
47#include <stddef.h>
48#include <errno.h>
49#include <assert.h>
50#include <ctype.h>
51#include <pwd.h>
52#include <grp.h>
53
[134]54#include "sh_pthread.h"
55
[252]56extern  int sl_close_fd (const char * file, int line, int fd);
57extern  int sl_fclose (const char * file, int line, FILE * fp);
58
59
[1]60#ifndef _PATH_PASSWD
61#define _PATH_PASSWD "/etc/passwd"
62#endif
63#ifndef _PATH_GROUP
64#define _PATH_GROUP "/etc/group"
65#endif
66
[252]67#undef  FIL__
68#define FIL__  _("sh_static.c")
69
[22]70extern  int sl_strlcpy(char * dst, /*@null@*/const char * src, size_t siz);
71extern  int sl_strlcat(char * dst, /*@null@*/const char * src, size_t siz);
[1]72
73
74/**********************************************************************/
75/* Sizes for staticly allocated buffers. */
76
77#define PWD_BUFFER_SIZE 256
[428]78#define GRP_BUFFER_SIZE 3584
79#define GRP_BUFFER_SIZE_MALLOC 32768
[1]80
81/**********************************************************************/
82/* Prototypes for internal functions. */
83
84static int __parsepwent(void *pw, char *line);
85static int __parsegrent(void *gr, char *line);
86
87static int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
88                       char *__restrict line_buff, 
89                       size_t buflen, FILE *f);
90
91#undef  GETXXKEY_R_FUNC
92#undef  GETXXKEY_R_PARSER
93#undef  GETXXKEY_R_ENTTYPE
94#undef  GETXXKEY_R_TEST
95#undef  DO_GETXXKEY_R_KEYTYPE
96#undef  DO_GETXXKEY_R_PATHNAME
97#define GETXXKEY_R_FUNC                 sh_getpwnam_r
98#define GETXXKEY_R_PARSER       __parsepwent
99#define GETXXKEY_R_ENTTYPE              struct passwd
100#define GETXXKEY_R_TEST(ENT)    (!strcmp((ENT)->pw_name, key))
101#define DO_GETXXKEY_R_KEYTYPE   const char *__restrict
102#define DO_GETXXKEY_R_PATHNAME  _PATH_PASSWD
103
[145]104int GETXXKEY_R_FUNC(DO_GETXXKEY_R_KEYTYPE key,
105                    GETXXKEY_R_ENTTYPE *__restrict resultbuf,
106                    char *__restrict buffer, size_t buflen,
107                    GETXXKEY_R_ENTTYPE **__restrict result)
[1]108{
109  FILE *stream;
110  int rv;
111 
112  *result = NULL;
113 
114  if (!(stream = fopen(DO_GETXXKEY_R_PATHNAME, "r"))) {
115    rv = errno;
116  } else {
117    /* __STDIO_SET_USER_LOCKING(stream); */
118    do {
119      if (!(rv = __pgsreader(GETXXKEY_R_PARSER, resultbuf,
120                             buffer, buflen, stream))
121          ) {
122        if (GETXXKEY_R_TEST(resultbuf)) { /* Found key? */
123          *result = resultbuf;
124          break;
125        }
126      } else {
127        if (rv == ENOENT) {     /* end-of-file encountered. */
128          rv = 0;
129        }
130        break;
131      }
132    } while (1);
[252]133    sl_fclose(FIL__, __LINE__, stream);
[1]134  }
135 
136  return rv;
137}
138
139#undef  GETXXKEY_R_FUNC
140#undef  GETXXKEY_R_PARSER
141#undef  GETXXKEY_R_ENTTYPE
142#undef  GETXXKEY_R_TEST
143#undef  DO_GETXXKEY_R_KEYTYPE
144#undef  DO_GETXXKEY_R_PATHNAME
145#define GETXXKEY_R_FUNC                 sh_getgrnam_r
146#define GETXXKEY_R_PARSER       __parsegrent
147#define GETXXKEY_R_ENTTYPE              struct group
148#define GETXXKEY_R_TEST(ENT)    (!strcmp((ENT)->gr_name, key))
149#define DO_GETXXKEY_R_KEYTYPE   const char *__restrict
150#define DO_GETXXKEY_R_PATHNAME  _PATH_GROUP
151
[145]152int GETXXKEY_R_FUNC(DO_GETXXKEY_R_KEYTYPE key,
153                    GETXXKEY_R_ENTTYPE *__restrict resultbuf,
154                    char *__restrict buffer, size_t buflen,
155                    GETXXKEY_R_ENTTYPE **__restrict result)
[1]156{
157  FILE *stream;
158  int rv;
159 
160  *result = NULL;
161 
162  if (!(stream = fopen(DO_GETXXKEY_R_PATHNAME, "r"))) {
163    rv = errno;
164  } else {
165    /* __STDIO_SET_USER_LOCKING(stream); */
166    do {
167      if (!(rv = __pgsreader(GETXXKEY_R_PARSER, resultbuf,
168                             buffer, buflen, stream))
169          ) {
170        if (GETXXKEY_R_TEST(resultbuf)) { /* Found key? */
171          *result = resultbuf;
172          break;
173        }
174      } else {
175        if (rv == ENOENT) {     /* end-of-file encountered. */
176          rv = 0;
177        }
178        break;
179      }
180    } while (1);
[252]181    sl_fclose(FIL__, __LINE__, stream);
[1]182  }
183 
184  return rv;
185}
186
187#undef  GETXXKEY_R_FUNC
188#undef  GETXXKEY_R_PARSER
189#undef  GETXXKEY_R_ENTTYPE
190#undef  GETXXKEY_R_TEST
191#undef  DO_GETXXKEY_R_KEYTYPE
192#undef  DO_GETXXKEY_R_PATHNAME
193#define GETXXKEY_R_FUNC                 sh_getpwuid_r
194#define GETXXKEY_R_PARSER       __parsepwent
195#define GETXXKEY_R_ENTTYPE              struct passwd
196#define GETXXKEY_R_TEST(ENT)    ((ENT)->pw_uid == key)
197#define DO_GETXXKEY_R_KEYTYPE   uid_t
198#define DO_GETXXKEY_R_PATHNAME  _PATH_PASSWD
199
[145]200int GETXXKEY_R_FUNC(DO_GETXXKEY_R_KEYTYPE key,
201                    GETXXKEY_R_ENTTYPE *__restrict resultbuf,
202                    char *__restrict buffer, size_t buflen,
203                    GETXXKEY_R_ENTTYPE **__restrict result)
[1]204{
205  FILE *stream;
206  int rv;
207 
208  *result = NULL;
209 
210  if (!(stream = fopen(DO_GETXXKEY_R_PATHNAME, "r"))) {
211    rv = errno;
212  } else {
213    /* __STDIO_SET_USER_LOCKING(stream); */
214    do {
215      if (!(rv = __pgsreader(GETXXKEY_R_PARSER, resultbuf,
216                             buffer, buflen, stream))
217          ) {
218        if (GETXXKEY_R_TEST(resultbuf)) { /* Found key? */
219          *result = resultbuf;
220          break;
221        }
222      } else {
223        if (rv == ENOENT) {     /* end-of-file encountered. */
224          rv = 0;
225        }
226        break;
227      }
228    } while (1);
[252]229    sl_fclose(FIL__, __LINE__, stream);
[1]230  }
231 
232  return rv;
233}
234
235#undef  GETXXKEY_R_FUNC
236#undef  GETXXKEY_R_PARSER
237#undef  GETXXKEY_R_ENTTYPE
238#undef  GETXXKEY_R_TEST
239#undef  DO_GETXXKEY_R_KEYTYPE
240#undef  DO_GETXXKEY_R_PATHNAME
241#define GETXXKEY_R_FUNC                 sh_getgrgid_r
242#define GETXXKEY_R_PARSER       __parsegrent
243#define GETXXKEY_R_ENTTYPE              struct group
244#define GETXXKEY_R_TEST(ENT)    ((ENT)->gr_gid == key)
245#define DO_GETXXKEY_R_KEYTYPE   gid_t
246#define DO_GETXXKEY_R_PATHNAME  _PATH_GROUP
247
[145]248int GETXXKEY_R_FUNC(DO_GETXXKEY_R_KEYTYPE key,
249                    GETXXKEY_R_ENTTYPE *__restrict resultbuf,
250                    char *__restrict buffer, size_t buflen,
251                    GETXXKEY_R_ENTTYPE **__restrict result)
[1]252{
253  FILE *stream;
254  int rv;
255 
256  *result = NULL;
257 
258  if (!(stream = fopen(DO_GETXXKEY_R_PATHNAME, "r"))) {
259    rv = errno;
260  } else {
261    /* __STDIO_SET_USER_LOCKING(stream); */
262    do {
263      if (!(rv = __pgsreader(GETXXKEY_R_PARSER, resultbuf,
264                             buffer, buflen, stream))
265          ) {
266        if (GETXXKEY_R_TEST(resultbuf)) { /* Found key? */
267          *result = resultbuf;
268          break;
269        }
270      } else {
271        if (rv == ENOENT) {     /* end-of-file encountered. */
272          rv = 0;
273        }
274        break;
275      }
276    } while (1);
[252]277    sl_fclose(FIL__, __LINE__, stream);
[1]278  }
279 
280  return rv;
281}
282
283struct passwd * sh_getpwuid(uid_t uid)
284{
285        static char buffer[PWD_BUFFER_SIZE];
286        static struct passwd resultbuf;
287        struct passwd *result;
288
289        sh_getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result);
290        return result;
291}
292
[170]293struct passwd * getpwuid(uid_t uid)
294{
295        return sh_getpwuid(uid);
296}
297
[1]298struct group * sh_getgrgid(gid_t gid)
299{
300        static char buffer[GRP_BUFFER_SIZE];
301        static struct group resultbuf;
302        struct group *result;
303
304        sh_getgrgid_r(gid, &resultbuf, buffer, sizeof(buffer), &result);
305        return result;
306}
307
[170]308struct group * getgrgid(gid_t gid)
309{
310        return sh_getgrgid(gid);
311}
[1]312
313struct passwd * sh_getpwnam(const char *name)
314{
315        static char buffer[PWD_BUFFER_SIZE];
316        static struct passwd resultbuf;
317        struct passwd *result;
318
319        sh_getpwnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
320        return result;
321}
322
323struct group * sh_getgrnam(const char *name)
324{
325        static char buffer[GRP_BUFFER_SIZE];
326        static struct group resultbuf;
327        struct group *result;
328
329        sh_getgrnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);
330        return result;
331}
332
[134]333SH_MUTEX_STATIC(pwf_lock, PTHREAD_MUTEX_INITIALIZER);
[1]334
[134]335
[1]336static FILE *pwf = NULL;
337
338void  sh_setpwent(void)
339{
[134]340        SH_MUTEX_LOCK(pwf_lock);
[1]341        if (pwf) {
342                rewind(pwf);
343        }
[134]344        SH_MUTEX_UNLOCK(pwf_lock);
[1]345}
346
347void  sh_endpwent(void)
348{
[134]349        SH_MUTEX_LOCK(pwf_lock);
[1]350        if (pwf) {
[252]351                sl_fclose(FIL__, __LINE__, pwf);
[1]352                pwf = NULL;
353        }
[134]354        SH_MUTEX_UNLOCK(pwf_lock);
[1]355}
356
357
358static int  sh_getpwent_r(struct passwd *__restrict resultbuf, 
359                          char *__restrict buffer, size_t buflen,
360                          struct passwd **__restrict result)
361{
362        int rv;
363
[134]364        SH_MUTEX_LOCK(pwf_lock);
[1]365
366        *result = NULL;                         /* In case of error... */
367
368        if (!pwf) {
369                if (!(pwf = fopen(_PATH_PASSWD, "r"))) {
370                        rv = errno;
371                        goto ERR;
372                }
373                /* __STDIO_SET_USER_LOCKING(pwf); */
374        }
375
376        if (!(rv = __pgsreader(__parsepwent, resultbuf,
377                                                   buffer, buflen, pwf))) {
378                *result = resultbuf;
379        }
380
381 ERR:
[150]382        ; /* 'label at end of compound statement' */
[134]383        SH_MUTEX_UNLOCK(pwf_lock);
[1]384
385        return rv;
386}
387
[134]388SH_MUTEX_STATIC(grf_lock, PTHREAD_MUTEX_INITIALIZER);
[1]389
390static FILE *grf = NULL;
391
392void  sh_setgrent(void)
393{
[134]394        SH_MUTEX_LOCK(grf_lock);
[1]395        if (grf) {
396                rewind(grf);
397        }
[134]398        SH_MUTEX_UNLOCK(grf_lock);
[1]399}
400
401void  sh_endgrent(void)
402{
[134]403        SH_MUTEX_LOCK(grf_lock);
[1]404        if (grf) {
[252]405                sl_fclose(FIL__, __LINE__, grf);
[1]406                grf = NULL;
407        }
[134]408        SH_MUTEX_UNLOCK(grf_lock);
[1]409}
410
411static int sh_getgrent_r(struct group *__restrict resultbuf,
412                         char *__restrict buffer, size_t buflen,
413                         struct group **__restrict result)
414{
415        int rv;
416
[134]417        SH_MUTEX_LOCK(grf_lock);
[1]418
419        *result = NULL;                         /* In case of error... */
420
421        if (!grf) {
422                if (!(grf = fopen(_PATH_GROUP, "r"))) {
423                        rv = errno;
424                        goto ERR;
425                }
426                /* __STDIO_SET_USER_LOCKING(grf); */
427        }
428
429        if (!(rv = __pgsreader(__parsegrent, resultbuf,
430                                                   buffer, buflen, grf))) {
431                *result = resultbuf;
432        }
433
434 ERR:
[150]435        ; /* 'label at end of compound statement' */
[134]436        SH_MUTEX_UNLOCK(grf_lock);
[1]437
438        return rv;
439}
440
441
442struct passwd * sh_getpwent(void)
443{
444        static char line_buff[PWD_BUFFER_SIZE];
445        static struct passwd pwd;
446        struct passwd *result;
447
448        sh_getpwent_r(&pwd, line_buff, sizeof(line_buff), &result);
449        return result;
450}
451
452
453struct group * sh_getgrent(void)
454{
455        static char line_buff[GRP_BUFFER_SIZE];
456        static struct group gr;
457        struct group *result;
458
[134]459        sh_getgrent_r(&gr, line_buff, sizeof(line_buff), &result);
[1]460        return result;
461}
462
463int  sh_initgroups(const char *user, gid_t gid)
464{
465        FILE *grf;
466        gid_t *group_list;
467        int num_groups, rv;
468        char **m;
469        struct group group;
470
[454]471        char * buff = calloc(1,GRP_BUFFER_SIZE_MALLOC);
[428]472
[1]473        rv = -1;
474
475        /* We alloc space for 8 gids at a time. */
[454]476        if (((group_list = calloc(8,sizeof(gid_t *))) != NULL)
[1]477                && ((grf = fopen(_PATH_GROUP, "r")) != NULL)
478                ) {
479
480          /* __STDIO_SET_USER_LOCKING(grf); */
481
482                *group_list = gid;
483                num_groups = 1;
484
[428]485                while (!__pgsreader(__parsegrent, &group, buff, GRP_BUFFER_SIZE_MALLOC, grf)) {
[1]486                        assert(group.gr_mem); /* Must have at least a NULL terminator. */
487                        if (group.gr_gid != gid) {
488                                for (m=group.gr_mem ; *m ; m++) {
489                                        if (!strcmp(*m, user)) {
490                                                if (!(num_groups & 7)) {
491                                                        gid_t *tmp = (gid_t *)
492                                                                realloc(group_list,
493                                                                                (num_groups+8) * sizeof(gid_t *));
494                                                        if (!tmp) {
495                                                                rv = -1;
496                                                                goto DO_CLOSE;
497                                                        }
498                                                        group_list = tmp;
499                                                }
500                                                group_list[num_groups++] = group.gr_gid;
501                                                break;
502                                        }
503                                }
504                        }
505                }
506
507                rv = setgroups(num_groups, group_list);
508        DO_CLOSE:
[252]509                sl_fclose(FIL__, __LINE__, grf);
[1]510        }
511
512        /* group_list will be NULL if initial malloc failed, which may trigger
513         * warnings from various malloc debuggers. */
514        free(group_list);
[428]515        free(buff);
[1]516        return rv;
517}
518
519
520/**********************************************************************/
521/* Internal uClibc functions.                                         */
522/**********************************************************************/
523
524static const unsigned char pw_off[] = {
525        offsetof(struct passwd, pw_name),       /* 0 */
526        offsetof(struct passwd, pw_passwd),     /* 1 */
527        offsetof(struct passwd, pw_uid),        /* 2 - not a char ptr */
528        offsetof(struct passwd, pw_gid),        /* 3 - not a char ptr */
529        offsetof(struct passwd, pw_gecos),      /* 4 */
530        offsetof(struct passwd, pw_dir),        /* 5 */
531        offsetof(struct passwd, pw_shell)       /* 6 */
532};
533
534static int __parsepwent(void *data, char *line)
535{
536        char *endptr;
537        char *p;
538        int i;
539
540        i = 0;
541        do {
542                p = ((char *) ((struct passwd *) data)) + pw_off[i];
543
544                if ((i & 6) ^ 2) {      /* i!=2 and i!=3 */
545                        *((char **) p) = line;
546                        if (i==6) {
547                                return 0;
548                        }
549                        /* NOTE: glibc difference - glibc allows omission of
550                         * ':' seperators after the gid field if all remaining
551                         * entries are empty.  We require all separators. */
552                        if (!(line = strchr(line, ':'))) {
553                                break;
554                        }
555                } else {
556                        unsigned long t = strtoul(line, &endptr, 10);
557                        /* Make sure we had at least one digit, and that the
558                         * failing char is the next field seperator ':'.  See
559                         * glibc difference note above. */
560                        /* TODO: Also check for leading whitespace? */
561                        if ((endptr == line) || (*endptr != ':')) {
562                                break;
563                        }
564                        line = endptr;
565                        if (i & 1) {            /* i == 3 -- gid */
566                                *((gid_t *) p) = t;
567                        } else {                        /* i == 2 -- uid */
568                                *((uid_t *) p) = t;
569                        }
570                }
571
572                *line++ = 0;
573                ++i;
574        } while (1);
575
576        return -1;
577}
578
579static const unsigned char gr_off[] = {
580        offsetof(struct group, gr_name),        /* 0 */
581        offsetof(struct group, gr_passwd),      /* 1 */
582        offsetof(struct group, gr_gid)          /* 2 - not a char ptr */
583};
584
585static int __parsegrent(void *data, char *line)
586{
587        char *endptr;
588        char *p;
589        int i;
590        char **members;
591        char *end_of_buf;
592
593        end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */
594        i = 0;
595        do {
596                p = ((char *) ((struct group *) data)) + gr_off[i];
597
598                if (i < 2) {
599                        *((char **) p) = line;
600                        if (!(line = strchr(line, ':'))) {
601                                break;
602                        }
603                        *line++ = 0;
604                        ++i;
605                } else {
606                        *((gid_t *) p) = strtoul(line, &endptr, 10);
607
608                        /* NOTE: glibc difference - glibc allows omission of the
609                         * trailing colon when there is no member list.  We treat
610                         * this as an error. */
611
612                        /* Make sure we had at least one digit, and that the
613                         * failing char is the next field seperator ':'.  See
614                         * glibc difference note above. */
615                        if ((endptr == line) || (*endptr != ':')) {
616                                break;
617                        }
618
619                        i = 1;                          /* Count terminating NULL ptr. */
620                        p = endptr;
621
622                        if (p[1]) { /* We have a member list to process. */
623                                /* Overwrite the last ':' with a ',' before counting.
624                                 * This allows us to test for initial ',' and adds
625                                 * one ',' so that the ',' count equals the member
626                                 * count. */
627                                *p = ',';
628                                do {
629                                        /* NOTE: glibc difference - glibc allows and trims leading
630                                         * (but not trailing) space.  We treat this as an error. */
631                                        /* NOTE: glibc difference - glibc allows consecutive and
632                                         * trailing commas, and ignores "empty string" users.  We
633                                         * treat this as an error. */
634                                        if (*p == ',') {
635                                                ++i;
636                                                *p = 0; /* nul-terminate each member string. */
637                                                if (!*++p || (*p == ',') || isspace(*p)) {
638                                                        goto ERR;
639                                                }
640                                        }
641                                } while (*++p);
642                        }
643
644                        /* Now align (p+1), rounding up. */
645                        /* Assumes sizeof(char **) is a power of 2. */
646                        members = (char **)( (((intptr_t) p) + sizeof(char **))
647                                                                 & ~((intptr_t)(sizeof(char **) - 1)) );
648
649                        if (((char *)(members + i)) > end_of_buf) {     /* No space. */
650                                break;
651                        }
652
653                        ((struct group *) data)->gr_mem = members;
654
655                        if (--i) {
656                                p = endptr;     /* Pointing to char prior to first member. */
657                                do {
658                                        *members++ = ++p;
659                                        if (!--i) break;
660                                        while (*++p) {}
661                                } while (1);
662                        }                               
663                        *members = NULL;
664
665                        return 0;
666                }
667        } while (1);
668
669 ERR:
670        return -1;
671}
672
673/* Reads until if EOF, or until if finds a line which fits in the buffer
674 * and for which the parser function succeeds.
675 *
676 * Returns 0 on success and ENOENT for end-of-file (glibc concession).
677 */
678
679static int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data,
680                       char *__restrict line_buff, size_t buflen, FILE *f)
681{
682        size_t line_len; /* int -> size_t R.W. */
683        int skip;
684        int rv = ERANGE;
685
686        if (buflen < PWD_BUFFER_SIZE) {
687                errno = rv;
688        } else {
689          /* __STDIO_THREADLOCK(f); */
690
691                skip = 0;
692                do {
[134]693                        if (!fgets(line_buff, buflen, f)) {
694                                if (feof(f)) {
[1]695                                        rv = ENOENT;
696                                }
697                                break;
698                        }
699
700                        line_len = strlen(line_buff) - 1; /* strlen() must be > 0. */
701                        if (line_buff[line_len] == '\n') {
702                                line_buff[line_len] = 0;
703                        } else if (line_len + 2 == buflen) { /* line too long */
[428]704                                rv = ERANGE;
705                                break;
706                                /*
[1]707                                ++skip;
708                                continue;
[428]709                                */
[1]710                        }
711
712                        if (skip) {
713                                --skip;
714                                continue;
715                        }
716
717                        /* NOTE: glibc difference - glibc strips leading whitespace from
718                         * records.  We do not allow leading whitespace. */
719
720                        /* Skip empty lines, comment lines, and lines with leading
721                         * whitespace. */
722                        if (*line_buff && (*line_buff != '#') && !isspace(*line_buff)) {
723                                if (__parserfunc == __parsegrent) {     /* Do evil group hack. */
724                                        /* The group entry parsing function needs to know where
725                                         * the end of the buffer is so that it can construct the
726                                         * group member ptr table. */
727                                        ((struct group *) data)->gr_name = line_buff + buflen;
728                                }
729
730                                if (!__parserfunc(data, line_buff)) {
731                                        rv = 0;
732                                        break;
733                                }
734                        }
735                } while (1);
736
737                /* __STDIO_THREADUNLOCK(f); */
738        }
739
740        return rv;
741}
742
743/* resolv.c: DNS Resolver
744 *
745 * Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
746 *                     The Silver Hammer Group, Ltd.
747 *
748 * This library is free software; you can redistribute it and/or
749 * modify it under the terms of the GNU Library General Public
750 * License as published by the Free Software Foundation; either
751 * version 2 of the License, or (at your option) any later version.
752*/
753
754/*
755 * Portions Copyright (c) 1985, 1993
756 *    The Regents of the University of California.  All rights reserved.
757 *
758 * Redistribution and use in source and binary forms, with or without
759 * modification, are permitted provided that the following conditions
760 * are met:
761 * 1. Redistributions of source code must retain the above copyright
762 *    notice, this list of conditions and the following disclaimer.
763 * 2. Redistributions in binary form must reproduce the above copyright
764 *    notice, this list of conditions and the following disclaimer in the
765 *    documentation and/or other materials provided with the distribution.
766 * 4. Neither the name of the University nor the names of its contributors
767 *    may be used to endorse or promote products derived from this software
768 *    without specific prior written permission.
769 *
770 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
771 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
772 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
773 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
774 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
775 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
776 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
777 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
778 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
779 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
780 * SUCH DAMAGE.
781 */
782
783/*
784 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
785 *
786 * Permission to use, copy, modify, and distribute this software for any
787 * purpose with or without fee is hereby granted, provided that the above
788 * copyright notice and this permission notice appear in all copies, and that
789 * the name of Digital Equipment Corporation not be used in advertising or
790 * publicity pertaining to distribution of the document or software without
791 * specific, written prior permission.
792 *
793 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
794 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
795 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
796 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
797 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
798 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
799 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
800 * SOFTWARE.
801 */
802
803/*
804 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
805 *
806 * Permission to use, copy, modify, and distribute this software for any
807 * purpose with or without fee is hereby granted, provided that the above
808 * copyright notice and this permission notice appear in all copies.
809 *
810 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
811 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
812 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
813 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
814 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
815 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
816 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
817 * SOFTWARE.
818 */
819
820/*
821 *
822 *  5-Oct-2000 W. Greathouse  wgreathouse@smva.com
823 *                              Fix memory leak and memory corruption.
824 *                              -- Every name resolution resulted in
825 *                                 a new parse of resolv.conf and new
826 *                                 copy of nameservers allocated by
827 *                                 strdup.
828 *                              -- Every name resolution resulted in
829 *                                 a new read of resolv.conf without
830 *                                 resetting index from prior read...
831 *                                 resulting in exceeding array bounds.
832 *
833 *                              Limit nameservers read from resolv.conf
834 *
835 *                              Add "search" domains from resolv.conf
836 *
837 *                              Some systems will return a security
838 *                              signature along with query answer for
839 *                              dynamic DNS entries.
840 *                              -- skip/ignore this answer
841 *
842 *                              Include arpa/nameser.h for defines.
843 *
844 *                              General cleanup
845 *
846 * 20-Jun-2001 Michal Moskal <malekith@pld.org.pl>
847 *   partial IPv6 support (i.e. gethostbyname2() and resolve_address2()
848 *   functions added), IPv6 nameservers are also supported.
849 *
850 * 6-Oct-2001 Jari Korva <jari.korva@iki.fi>
851 *   more IPv6 support (IPv6 support for gethostbyaddr();
852 *   address family parameter and improved IPv6 support for get_hosts_byname
853 *   and read_etc_hosts; getnameinfo() port from glibc; defined
854 *   defined ip6addr_any and in6addr_loopback)
855 *
856 * 2-Feb-2002 Erik Andersen <andersee@debian.org>
857 * Added gethostent(), sethostent(), and endhostent()
858 *
859 * 17-Aug-2002 Manuel Novoa III <mjn3@codepoet.org>
860 *   Fixed __read_etc_hosts_r to return alias list, and modified buffer
861 *   allocation accordingly.  See MAX_ALIASES and ALIAS_DIM below.
862 *   This fixes the segfault in the Python 2.2.1 socket test.
863 *
864 * 04-Jan-2003 Jay Kulpinski <jskulpin@berkshire.rr.com>
865 *   Fixed __decode_dotted to count the terminating null character
866 *   in a host name.
867 *
868 * 02-Oct-2003 Tony J. White <tjw@tjw.org>
869 *   Lifted dn_expand() and dependent ns_name_uncompress(), ns_name_unpack(),
870 *   and ns_name_ntop() from glibc 2.3.2 for compatibility with ipsec-tools
871 *   and openldap.
872 *
873 */
874
875#include <sys/socket.h>
876#include <netinet/in.h>
877#include <arpa/inet.h>
878
[252]879/* sl_close_fd(FIL__, __LINE__, )
[1]880 */
881#include <unistd.h>
882
883/* 'struct hostent'
884 */
885#include <netdb.h>
886
887/* constanst like HFIXEDSZ
888 */
889#include <arpa/nameser.h>
890
[134]891SH_MUTEX_STATIC(resolv_lock, PTHREAD_MUTEX_INITIALIZER);
[1]892
893#define __UCLIBC_HAS_IPV6__
894#define MAX_RECURSE 5
895#define REPLY_TIMEOUT 10
896#define MAX_RETRIES 3
897#define MAX_SERVERS 3
898#define MAX_SEARCH 4
899#define MAX_ALIASES     5
900
901/* 1:ip + 1:full + MAX_ALIASES:aliases + 1:NULL */
902#define         ALIAS_DIM               (2 + MAX_ALIASES + 1)
903
904static int __nameservers;
905static char * __nameserver[MAX_SERVERS];
906static int __searchdomains;
907static char * __searchdomain[MAX_SEARCH];
908
909#undef DEBUG
910/*#define DEBUG*/
911
912#ifdef DEBUG
[22]913/* flawfinder: ignore *//* definition of debug macro */
[1]914#define DPRINTF(X,args...) fprintf(stderr, X, ##args)
915#else
916#define DPRINTF(X,args...)
917#endif /* DEBUG */
918
919struct resolv_header {
920        int id;
921        int qr,opcode,aa,tc,rd,ra,rcode;
922        int qdcount;
923        int ancount;
924        int nscount;
925        int arcount;
926};
927
928struct resolv_question {
929        char * dotted;
930        int qtype;
931        int qclass;
932};
933
934struct resolv_answer {
935        char * dotted;
936        int atype;
937        int aclass;
938        int ttl;
939        int rdlength;
940        unsigned char * rdata;
941        int rdoffset;
942};
943
944enum etc_hosts_action {
945    GET_HOSTS_BYNAME = 0,
946    GETHOSTENT,
947    GET_HOSTS_BYADDR,
948};
949
950static int __encode_header(struct resolv_header *h, unsigned char *dest, int maxlen)
951{
952        if (maxlen < HFIXEDSZ)
953                return -1;
954
955        dest[0] = (h->id & 0xff00) >> 8;
956        dest[1] = (h->id & 0x00ff) >> 0;
957        dest[2] = (h->qr ? 0x80 : 0) |
958                ((h->opcode & 0x0f) << 3) |
959                (h->aa ? 0x04 : 0) | 
960                (h->tc ? 0x02 : 0) | 
961                (h->rd ? 0x01 : 0);
962        dest[3] = (h->ra ? 0x80 : 0) | (h->rcode & 0x0f);
963        dest[4] = (h->qdcount & 0xff00) >> 8;
964        dest[5] = (h->qdcount & 0x00ff) >> 0;
965        dest[6] = (h->ancount & 0xff00) >> 8;
966        dest[7] = (h->ancount & 0x00ff) >> 0;
967        dest[8] = (h->nscount & 0xff00) >> 8;
968        dest[9] = (h->nscount & 0x00ff) >> 0;
969        dest[10] = (h->arcount & 0xff00) >> 8;
970        dest[11] = (h->arcount & 0x00ff) >> 0;
971
972        return HFIXEDSZ;
973}
974
975static int __decode_header(unsigned char *data, struct resolv_header *h)
976{
977        h->id = (data[0] << 8) | data[1];
978        h->qr = (data[2] & 0x80) ? 1 : 0;
979        h->opcode = (data[2] >> 3) & 0x0f;
980        h->aa = (data[2] & 0x04) ? 1 : 0;
981        h->tc = (data[2] & 0x02) ? 1 : 0;
982        h->rd = (data[2] & 0x01) ? 1 : 0;
983        h->ra = (data[3] & 0x80) ? 1 : 0;
984        h->rcode = data[3] & 0x0f;
985        h->qdcount = (data[4] << 8) | data[5];
986        h->ancount = (data[6] << 8) | data[7];
987        h->nscount = (data[8] << 8) | data[9];
988        h->arcount = (data[10] << 8) | data[11];
989
990        return HFIXEDSZ;
991}
992
993static int __length_dotted(const unsigned char *data, int offset)
994{
995        int orig_offset = offset;
996        int l;
997
998        if (!data)
999                return -1;
1000
[481]1001        while ((l = data[offset])) {
[1]1002
[481]1003                if (offset < INT_MAX)
1004                        offset++;
1005                else
1006                        return -1;
1007
[1]1008                if ((l & 0xc0) == (0xc0)) {
[481]1009                        if (offset < INT_MAX)
1010                          offset++;
1011                        else
1012                          return -1;
[1]1013                        break;
1014                }
1015
[481]1016                if (offset <= (INT_MAX - l))
1017                  offset += l;
1018                else
1019                  return -1;
[1]1020        }
1021
1022        return offset - orig_offset;
1023}
1024
1025static int __length_question(unsigned char *message, int offset)
1026{
1027        int i;
1028
1029        i = __length_dotted(message, offset);
1030        if (i < 0)
1031                return i;
[481]1032        if (i < (INT_MAX - 4))
1033          return i + 4;
1034        else
1035          return -1;
[1]1036}
1037
1038/* Decode a dotted string from nameserver transport-level encoding.
1039   This routine understands compressed data. */
1040
1041static int __decode_dotted(const unsigned char *data, int offset,
1042                                  char *dest, int maxlen)
1043{
1044        int l;
1045        int measure = 1;
1046        int total = 0;
1047        int used = 0;
1048
1049        if (!data)
1050                return -1;
[481]1051        while ((l=data[offset])) {
1052                if (offset < INT_MAX) offset++;
1053                else return -1;
1054                if (measure && (total < INT_MAX))
[1]1055                    total++;
1056                if ((l & 0xc0) == (0xc0)) {
[481]1057                        if (measure && (total < INT_MAX))
[1]1058                                total++;
[481]1059                        /* compressed item, redirect */ 
[1]1060                        offset = ((l & 0x3f) << 8) | data[offset];
[481]1061                        if (offset < 0)
1062                          return -1; 
[1]1063                        measure = 0;
1064                        continue;
1065                }
[481]1066               
1067                if (used >= (INT_MAX - l))
1068                  return -1;
[1]1069
1070                if ((used + l + 1) >= maxlen)
[481]1071                  return -1; 
[1]1072
1073                memcpy(dest + used, data + offset, l);
[481]1074               
1075                if (offset <= (INT_MAX - l))
1076                  offset += l;
1077                else
1078                  return -1;
1079
1080                if (used <= (INT_MAX - l))
1081                  used += l;
1082                else
1083                  return -1;
1084                if (measure && (total <= (INT_MAX - l)))
[1]1085                        total += l;
1086
[481]1087                if (used == INT_MAX)
1088                  return -1;
[1]1089                if (data[offset] != 0)
1090                        dest[used++] = '.';
1091                else
1092                        dest[used++] = '\0';
1093        }
1094
1095        /* The null byte must be counted too */
[481]1096        if (measure && (total < INT_MAX)) {
[1]1097            total++;
1098        }
1099
1100        DPRINTF("Total decode len = %d\n", total);
1101
1102        return total;
1103}
1104
1105static int __decode_answer(unsigned char *message, int offset,
1106                                  struct resolv_answer *a)
1107{
1108        char temp[256];
[481]1109        int i = 0;
[1]1110
1111        i = __decode_dotted(message, offset, temp, sizeof(temp));
1112        if (i < 0)
1113                return i;
1114
[481]1115        if (offset <= (INT_MAX - i))
1116          message += offset + i;
1117        else
1118          return -1;
[1]1119
1120        a->dotted = strdup(temp);
1121        a->atype = (message[0] << 8) | message[1];
1122        message += 2;
1123        a->aclass = (message[0] << 8) | message[1];
1124        message += 2;
1125        a->ttl = (message[0] << 24) |
1126                (message[1] << 16) | (message[2] << 8) | (message[3] << 0);
1127        message += 4;
1128        a->rdlength = (message[0] << 8) | message[1];
1129        message += 2;
1130        a->rdata = message;
1131        a->rdoffset = offset + i + RRFIXEDSZ;
1132
1133        DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength);
1134
[481]1135        if (RRFIXEDSZ <= (INT_MAX - i))
1136          i += RRFIXEDSZ;
1137        else
1138          return -1;
1139        if (a->rdlength <= (INT_MAX - i))
1140          return i + a->rdlength;
1141        else
1142          return -1;
[1]1143}
1144
1145
1146/* Encode a dotted string into nameserver transport-level encoding.
1147   This routine is fairly dumb, and doesn't attempt to compress
1148   the data */
1149
1150static int __encode_dotted(const char *dotted, unsigned char *dest, int maxlen)
1151{
1152        unsigned int used = 0;
1153
1154        while (dotted && *dotted) {
1155                char *c = strchr(dotted, '.');
1156                unsigned int l = c ? (unsigned int)(c - dotted) : strlen(dotted);
1157
1158                if (l >= ((unsigned int)maxlen - used - 1))
1159                        return -1;
1160
1161                dest[used++] = l;
1162                memcpy(dest + used, dotted, l);
1163                used += l;
1164
1165                if (c)
1166                        dotted = c + 1;
1167                else
1168                        break;
1169        }
1170
1171        if (maxlen < 1)
1172                return -1;
1173
1174        dest[used++] = 0;
1175
1176        return used;
1177}
1178
1179static int __encode_question(struct resolv_question *q,
1180                                        unsigned char *dest, int maxlen)
1181{
1182        int i;
1183
1184        i = __encode_dotted(q->dotted, dest, maxlen);
1185        if (i < 0)
1186                return i;
1187
1188        dest += i;
[481]1189        if (maxlen < i)
1190          return -1;
[1]1191        maxlen -= i;
1192
1193        if (maxlen < 4)
1194                return -1;
1195
1196        dest[0] = (q->qtype & 0xff00) >> 8;
1197        dest[1] = (q->qtype & 0x00ff) >> 0;
1198        dest[2] = (q->qclass & 0xff00) >> 8;
1199        dest[3] = (q->qclass & 0x00ff) >> 0;
1200
[481]1201        if (i <= (INT_MAX - 4))
1202          return i + 4;
1203        else
1204          return -1;
[1]1205}
1206
1207
1208/* Just for the record, having to lock __dns_lookup() just for these two globals
1209 * is pretty lame.  I think these two variables can probably be de-global-ized,
1210 * which should eliminate the need for doing locking here...  Needs a closer
1211 * look anyways. */
1212static int ns=0, id=1;
1213
1214static int __dns_lookup(const char *name, int type, int nscount, char **nsip,
1215                           unsigned char **outpacket, struct resolv_answer *a)
1216{
1217        int i, j, len, fd, pos, rc;
1218        struct timeval tv;
1219        fd_set fds;
1220        struct resolv_header h;
1221        struct resolv_question q;
1222        int retries = 0;
[454]1223        unsigned char * packet = calloc(1,PACKETSZ);
1224        char *dns, *lookup = calloc(1,MAXDNAME);
[1]1225        int variant = 0;
1226        struct sockaddr_in sa;
1227#ifdef __UCLIBC_HAS_IPV6__
1228        int v6;
1229        struct sockaddr_in6 sa6;
1230#endif
1231
1232        fd = -1;
1233
1234        if (!packet || !lookup || !nscount)
1235            goto fail;
1236
1237        DPRINTF("Looking up type %d answer for '%s'\n", type, name);
1238
[145]1239        SH_MUTEX_LOCK_UNSAFE(resolv_lock);
[1]1240        ns %= nscount;
[145]1241        SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1242
1243        while (retries++ < MAX_RETRIES) {
1244                if (fd != -1)
[252]1245                        sl_close_fd(FIL__, __LINE__, fd);
[1]1246
1247                memset(packet, 0, PACKETSZ);
1248
1249                memset(&h, 0, sizeof(h));
1250
1251                /* Mess with globals while under lock */
[145]1252                SH_MUTEX_LOCK_UNSAFE(resolv_lock);
[1]1253                ++id;
1254                id &= 0xffff;
1255                h.id = id;
1256                dns = nsip[ns];
[145]1257                SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1258
1259                h.qdcount = 1;
1260                h.rd = 1;
1261
1262                DPRINTF("encoding header\n", h.rd);
1263
1264                i = __encode_header(&h, packet, PACKETSZ);
1265                if (i < 0)
1266                        goto fail;
1267
[22]1268                sl_strlcpy(lookup,name,MAXDNAME);
[134]1269                SH_MUTEX_LOCK_UNSAFE(resolv_lock);
[1]1270                if (variant < __searchdomains && strchr(lookup, '.') == NULL)
1271                {
[22]1272                    sl_strlcat(lookup,".", MAXDNAME);
1273                    sl_strlcat(lookup,__searchdomain[variant], MAXDNAME);
[1]1274                }
[134]1275                SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1276                DPRINTF("lookup name: %s\n", lookup);
1277                q.dotted = (char *)lookup;
1278                q.qtype = type;
1279                q.qclass = C_IN; /* CLASS_IN */
1280
1281                j = __encode_question(&q, packet+i, PACKETSZ-i);
1282                if (j < 0)
1283                        goto fail;
1284
1285                len = i + j;
1286
1287                DPRINTF("On try %d, sending query to port %d of machine %s\n",
1288                                retries, NAMESERVER_PORT, dns);
1289
1290#ifdef __UCLIBC_HAS_IPV6__
1291                v6 = inet_pton(AF_INET6, dns, &sa6.sin6_addr) > 0;
1292                fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1293#else
1294                fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
1295#endif
1296                if (fd < 0) {
1297                    continue;
1298                }
1299
1300                /* Connect to the UDP socket so that asyncronous errors are returned */         
1301#ifdef __UCLIBC_HAS_IPV6__
1302                if (v6) {
1303                    sa6.sin6_family = AF_INET6;
1304                    sa6.sin6_port = htons(NAMESERVER_PORT);
1305                    /* sa6.sin6_addr is already here */
1306                    rc = connect(fd, (struct sockaddr *) &sa6, sizeof(sa6));
1307                } else {
1308#endif
1309                    sa.sin_family = AF_INET;
1310                    sa.sin_port = htons(NAMESERVER_PORT);
1311                    sa.sin_addr.s_addr = inet_addr(dns);
1312                    rc = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
1313#ifdef __UCLIBC_HAS_IPV6__
1314                }
1315#endif
1316                if (rc < 0) {
1317                    if (errno == ENETUNREACH) {
1318                        /* routing error, presume not transient */
1319                        goto tryall;
1320                    } else
1321                        /* retry */
1322                        continue;
1323                }
1324
1325                DPRINTF("Transmitting packet of length %d, id=%d, qr=%d\n",
1326                                len, h.id, h.qr);
1327
1328                send(fd, packet, len, 0);
1329
1330                FD_ZERO(&fds);
1331                FD_SET(fd, &fds);
1332                tv.tv_sec = REPLY_TIMEOUT;
1333                tv.tv_usec = 0;
1334                if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0) {
1335                    DPRINTF("Timeout\n");
1336
1337                        /* timed out, so retry send and receive,
1338                         * to next nameserver on queue */
1339                        goto again;
1340                }
1341
1342                i = recv(fd, packet, 512, 0);
1343                if (i < HFIXEDSZ) {
1344                        /* too short ! */
1345                        goto again;
1346                }
1347
1348                __decode_header(packet, &h);
1349
1350                DPRINTF("id = %d, qr = %d\n", h.id, h.qr);
1351
[145]1352                SH_MUTEX_LOCK_UNSAFE(resolv_lock);
[1]1353                if ((h.id != id) || (!h.qr)) {
[145]1354                        SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1355                        /* unsolicited */
1356                        goto again;
1357                }
[145]1358                SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1359
1360
1361                DPRINTF("Got response %s\n", "(i think)!");
1362                DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n",
1363                                h.qdcount, h.ancount, h.nscount, h.arcount);
1364                DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n",
1365                                h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode);
1366
1367                if ((h.rcode) || (h.ancount < 1)) {
1368                        /* negative result, not present */
1369                        goto again;
1370                }
1371
1372                pos = HFIXEDSZ;
1373
1374                for (j = 0; j < h.qdcount; j++) {
1375                        DPRINTF("Skipping question %d at %d\n", j, pos);
1376                        i = __length_question(packet, pos);
1377                        DPRINTF("Length of question %d is %d\n", j, i);
1378                        if (i < 0)
1379                                goto again;
1380                        pos += i;
1381                }
1382                DPRINTF("Decoding answer at pos %d\n", pos);
1383
1384                for (j=0;j<h.ancount;j++)
1385                {
1386                    i = __decode_answer(packet, pos, a);
1387
1388                    if (i<0) {
1389                        DPRINTF("failed decode %d\n", i);
1390                        goto again;
1391                    }
1392                    /* For all but T_SIG, accept first answer */
1393                    if (a->atype != T_SIG)
1394                        break;
1395
1396                    DPRINTF("skipping T_SIG %d\n", i);
1397                    free(a->dotted);
1398                    pos += i;
1399                }
1400
1401                DPRINTF("Answer name = |%s|\n", a->dotted);
1402                DPRINTF("Answer type = |%d|\n", a->atype);
1403
[252]1404                sl_close_fd(FIL__, __LINE__, fd);
[1]1405
1406                if (outpacket)
1407                        *outpacket = packet;
1408                else
1409                        free(packet);
1410                free(lookup);
1411                return (0);                             /* success! */
1412
1413          tryall:
1414                /* if there are other nameservers, give them a go,
1415                   otherwise return with error */
1416                {
1417                    int sdomains;
1418
[134]1419                    SH_MUTEX_LOCK_UNSAFE(resolv_lock);
[1]1420                    sdomains=__searchdomains;
[134]1421                    SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1422                    variant = 0;
1423                    if (retries >= nscount*(sdomains+1))
1424                        goto fail;
1425                }
1426
1427          again:
1428                /* if there are searchdomains, try them or fallback as passed */
1429                {
1430                    int sdomains;
[134]1431                    SH_MUTEX_LOCK_UNSAFE(resolv_lock);
[1]1432                    sdomains=__searchdomains;
[134]1433                    SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1434
1435                    if (variant < sdomains) {
1436                        /* next search */
1437                        variant++;
1438                    } else {
1439                        /* next server, first search */
[145]1440                        SH_MUTEX_LOCK_UNSAFE(resolv_lock);
[1]1441                        ns = (ns + 1) % nscount;
[145]1442                        SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1443                        variant = 0;
1444                    }
1445                }
1446        }
1447
1448fail:
1449        if (fd != -1)
[252]1450            sl_close_fd(FIL__, __LINE__, fd);
[1]1451        if (lookup)
1452            free(lookup);
1453        if (packet)
1454            free(packet);
1455        return -1;
1456}
1457
1458static void __open_etc_hosts(FILE **fp)
1459{
1460        if ((*fp = fopen("/etc/hosts", "r")) == NULL) {
1461                *fp = fopen("/etc/config/hosts", "r");
1462        }
1463        return;
1464}
1465
1466static int __read_etc_hosts_r(FILE * fp, const char * name, int type,
1467                     enum etc_hosts_action action,
1468                     struct hostent * result_buf,
1469                     char * buf, size_t buflen,
1470                     struct hostent ** result,
1471                     int * h_errnop)
1472{
1473        struct in_addr  *in=NULL;
1474        struct in_addr  **addr_list=NULL;
1475#ifdef __UCLIBC_HAS_IPV6__
1476        struct in6_addr *in6=NULL;
1477        struct in6_addr **addr_list6=NULL;
1478#endif /* __UCLIBC_HAS_IPV6__ */
1479        char                                    *cp;
1480        char                                    **alias;
1481        int                                             aliases, i;
1482        int             ret=HOST_NOT_FOUND;
1483
1484        if (buflen < sizeof(char *)*(ALIAS_DIM))
1485                return ERANGE;
1486        alias=(char **)buf;
1487        buf+=sizeof(char **)*(ALIAS_DIM);
1488        buflen-=sizeof(char **)*(ALIAS_DIM);
1489
1490        if (action!=GETHOSTENT) {
1491#ifdef __UCLIBC_HAS_IPV6__
1492                char *p=buf;
1493                size_t len=buflen;
1494#endif /* __UCLIBC_HAS_IPV6__ */
1495                *h_errnop=NETDB_INTERNAL;
1496                if (buflen < sizeof(*in))
1497                        return ERANGE;
1498                in=(struct in_addr*)buf;
1499                buf+=sizeof(*in);
1500                buflen-=sizeof(*in);
1501
1502                if (buflen < sizeof(*addr_list)*2)
1503                        return ERANGE;
1504                addr_list=(struct in_addr **)buf;
1505                buf+=sizeof(*addr_list)*2;
1506                buflen-=sizeof(*addr_list)*2;
1507
1508#ifdef __UCLIBC_HAS_IPV6__
1509                if (len < sizeof(*in6))
1510                        return ERANGE;
1511                in6=(struct in6_addr*)p;
1512                p+=sizeof(*in6);
1513                len-=sizeof(*in6);
1514
1515                if (len < sizeof(*addr_list6)*2)
1516                        return ERANGE;
1517                addr_list6=(struct in6_addr**)p;
1518                p+=sizeof(*addr_list6)*2;
1519                len-=sizeof(*addr_list6)*2;
1520
1521                if (len < buflen) {
1522                        buflen=len;
1523                        buf=p;
1524                }
1525#endif /* __UCLIBC_HAS_IPV6__ */
1526
1527                if (buflen < 80)
1528                        return ERANGE;
1529
1530                __open_etc_hosts(&fp);
1531                if (fp == NULL) {
1532                        result=NULL;
1533                        return errno;
1534                }
1535        }
1536
1537        *h_errnop=HOST_NOT_FOUND;
1538        while (fgets(buf, buflen, fp)) {
1539                if ((cp = strchr(buf, '#')))
1540                        *cp = '\0';
1541                DPRINTF("Looking at: %s\n", buf);
1542                aliases = 0;
1543
1544                cp = buf;
1545                while (*cp) {
1546                        while (*cp && isspace(*cp))
1547                                *cp++ = '\0';
1548                        if (!*cp)
1549                                continue;
1550                        if (aliases < (2+MAX_ALIASES))
1551                                alias[aliases++] = cp;
1552                        while (*cp && !isspace(*cp))
1553                                cp++;
1554                }
1555                alias[aliases] = 0;
1556
1557                if (aliases < 2)
1558                        continue; /* syntax error really */
1559               
1560                if (action==GETHOSTENT) {
1561                        /* Return whatever the next entry happens to be. */
1562                        break;
1563                } else if (action==GET_HOSTS_BYADDR) {
1564                        if (strcmp(name, alias[0]) != 0)
1565                                continue;
1566                } else {
1567                        /* GET_HOSTS_BYNAME */
1568                        for (i = 1; i < aliases; i++)
1569                                if (strcasecmp(name, alias[i]) == 0)
1570                                        break;
1571                        if (i >= aliases)
1572                                continue;
1573                }
1574
1575                if (type == AF_INET && inet_pton(AF_INET, alias[0], in) > 0) {
1576                        DPRINTF("Found INET\n");
1577                        addr_list[0] = in;
1578                        addr_list[1] = 0;
1579                        result_buf->h_name = alias[1];
1580                        result_buf->h_addrtype = AF_INET;
1581                        result_buf->h_length = sizeof(*in);
1582                        result_buf->h_addr_list = (char**) addr_list;
1583                        result_buf->h_aliases = alias + 2;
1584                        *result=result_buf;
1585                        ret=NETDB_SUCCESS;
1586#ifdef __UCLIBC_HAS_IPV6__
1587        } else if (type == AF_INET6 && inet_pton(AF_INET6, alias[0], in6) > 0) {
1588                        DPRINTF("Found INET6\n");
1589                        addr_list6[0] = in6;
1590                        addr_list6[1] = 0;
1591                        result_buf->h_name = alias[1];
1592                        result_buf->h_addrtype = AF_INET6;
1593                        result_buf->h_length = sizeof(*in6);
1594                        result_buf->h_addr_list = (char**) addr_list6;
1595                        result_buf->h_aliases = alias + 2;
1596                        *result=result_buf;
1597                        ret=NETDB_SUCCESS;
1598#endif /* __UCLIBC_HAS_IPV6__ */
1599                } else {
1600                        DPRINTF("Error\n");
1601                        ret=TRY_AGAIN;
1602                        break; /* bad ip address */
1603        }
1604       
1605                if (action!=GETHOSTENT) {
[252]1606                        sl_fclose(FIL__, __LINE__, fp);
[1]1607                }
1608                return ret;
1609        }
1610        if (action!=GETHOSTENT) {
[252]1611                sl_fclose(FIL__, __LINE__, fp);
[1]1612        }
1613        return ret;
1614}
1615
1616/*
1617 *      we currently read formats not quite the same as that on normal
1618 *      unix systems, we can have a list of nameservers after the keyword.
1619 */
1620int __get_hosts_byname_r(const char * name, int type,
1621                            struct hostent * result_buf,
1622                            char * buf, size_t buflen,
1623                            struct hostent ** result,
1624                            int * h_errnop)
1625{
1626        return(__read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME, result_buf, buf, buflen, result, h_errnop));
1627}
1628
[170]1629static int __open_nameservers(void)
[1]1630{
1631        FILE *fp;
1632        int i;
1633#define RESOLV_ARGS 5
1634        char szBuffer[128], *p, *argv[RESOLV_ARGS];
1635        int argc;
1636
[134]1637        SH_MUTEX_LOCK(resolv_lock);
1638        if (__nameservers > 0) {
1639          goto the_end;
[1]1640        }
1641
1642        if ((fp = fopen("/etc/resolv.conf", "r")) ||
1643                        (fp = fopen("/etc/config/resolv.conf", "r"))) {
1644
1645                while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
1646
1647                        for (p = szBuffer; *p && isspace(*p); p++)
1648                                /* skip white space */;
1649                        if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */
1650                                continue;
1651                        argc = 0;
1652                        while (*p && argc < RESOLV_ARGS) {
1653                                argv[argc++] = p;
1654                                while (*p && !isspace(*p) && *p != '\n')
1655                                        p++;
1656                                while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */
1657                                        *p++ = '\0';
1658                        }
1659
1660                        if (strcmp(argv[0], "nameserver") == 0) {
1661                                for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) {
1662                                        __nameserver[__nameservers++] = strdup(argv[i]);
1663                                        DPRINTF("adding nameserver %s\n", argv[i]);
1664                                }
1665                        }
1666
1667                        /* domain and search are mutually exclusive, the last one wins */
1668                        if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) {
1669                                while (__searchdomains > 0) {
1670                                        free(__searchdomain[--__searchdomains]);
1671                                        __searchdomain[__searchdomains] = NULL;
1672                                }
1673                                for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) {
1674                                        __searchdomain[__searchdomains++] = strdup(argv[i]);
1675                                        DPRINTF("adding search %s\n", argv[i]);
1676                                }
1677                        }
1678                }
[252]1679                sl_fclose(FIL__, __LINE__, fp);
[1]1680        } else {
1681            DPRINTF("failed to open %s\n", "resolv.conf");
1682        }
1683        DPRINTF("nameservers = %d\n", __nameservers);
[134]1684 the_end:
[150]1685        ; /* 'label at end of compound statement' */
[134]1686        SH_MUTEX_UNLOCK(resolv_lock);
[473]1687        /* cppcheck-suppress resourceLeak */
[1]1688        return 0;
1689}
1690
1691static int sh_gethostbyname_r(const char * name,
1692                            struct hostent * result_buf,
1693                            char * buf, size_t buflen,
1694                            struct hostent ** result,
1695                            int * h_errnop)
1696{
1697        struct in_addr *in;
1698        struct in_addr **addr_list;
1699        unsigned char *packet;
1700        struct resolv_answer a;
1701        int i;
1702        int nest = 0;
1703        int __nameserversXX;
1704        char ** __nameserverXX;
1705
1706        __open_nameservers();
1707
1708        *result=NULL;
1709        if (!name)
1710                return EINVAL;
1711
1712        /* do /etc/hosts first */
1713        if ((i=__get_hosts_byname_r(name, AF_INET, result_buf,
1714                                  buf, buflen, result, h_errnop))==0)
1715                return i;
1716        switch (*h_errnop) {
1717                case HOST_NOT_FOUND:
1718                case NO_ADDRESS:
1719                        break;
1720                case NETDB_INTERNAL:
1721                        if (errno == ENOENT) {
1722                            break;
1723                        }
1724                        /* else fall through */
1725                default:
1726                        return i;
1727        }
1728
1729        DPRINTF("Nothing found in /etc/hosts\n");
1730
1731        *h_errnop = NETDB_INTERNAL;
1732        if (buflen < sizeof(*in))
1733                return ERANGE;
1734        in=(struct in_addr*)buf;
1735        buf+=sizeof(*in);
1736        buflen-=sizeof(*in);
1737
1738        if (buflen < sizeof(*addr_list)*2)
1739                return ERANGE;
1740        addr_list=(struct in_addr**)buf;
1741        buf+=sizeof(*addr_list)*2;
1742        buflen-=sizeof(*addr_list)*2;
1743
1744        addr_list[0] = in;
1745        addr_list[1] = 0;
1746       
1747        if (buflen<256)
1748                return ERANGE;
1749        strncpy(buf, name, buflen);
1750
1751        /* First check if this is already an address */
1752        if (inet_aton(name, in)) {
1753            result_buf->h_name = buf;
1754            result_buf->h_addrtype = AF_INET;
1755            result_buf->h_length = sizeof(*in);
1756            result_buf->h_addr_list = (char **) addr_list;
1757            *result=result_buf;
1758            *h_errnop = NETDB_SUCCESS;
1759            return NETDB_SUCCESS;
1760        }
1761
1762        for (;;) {
1763
[134]1764        SH_MUTEX_LOCK_UNSAFE(resolv_lock);
[1]1765        __nameserversXX=__nameservers;
1766        __nameserverXX=__nameserver;
[134]1767        SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1768                i = __dns_lookup(buf, T_A, __nameserversXX, __nameserverXX, &packet, &a);
1769
1770                if (i < 0) {
1771                        *h_errnop = HOST_NOT_FOUND;
1772                        DPRINTF("__dns_lookup\n");
1773                        return TRY_AGAIN;
1774                }
1775
1776                strncpy(buf, a.dotted, buflen);
1777                free(a.dotted);
1778
1779                if (a.atype == T_CNAME) {               /* CNAME */
1780                        DPRINTF("Got a CNAME in gethostbyname()\n");
1781                        i = __decode_dotted(packet, a.rdoffset, buf, buflen);
1782                        free(packet);
1783
1784                        if (i < 0) {
1785                                *h_errnop = NO_RECOVERY;
1786                                DPRINTF("__decode_dotted\n");
1787                                return -1;
1788                        }
1789                        if (++nest > MAX_RECURSE) {
1790                                *h_errnop = NO_RECOVERY;
1791                                DPRINTF("recursion\n");
1792                                return -1;
1793                        }
1794                        continue;
1795                } else if (a.atype == T_A) {    /* ADDRESS */
1796                        memcpy(in, a.rdata, sizeof(*in));
1797                        result_buf->h_name = buf;
1798                        result_buf->h_addrtype = AF_INET;
1799                        result_buf->h_length = sizeof(*in);
1800                        result_buf->h_addr_list = (char **) addr_list;
1801                        free(packet);
1802                        break;
1803                } else {
1804                        free(packet);
1805                        *h_errnop=HOST_NOT_FOUND;
1806                        return TRY_AGAIN;
1807                }
1808        }
1809
1810        *result=result_buf;
1811        *h_errnop = NETDB_SUCCESS;
1812        return NETDB_SUCCESS;
1813}
1814
1815struct hostent * sh_gethostbyname(const char *name)
1816{
1817        static struct hostent h;
1818        static char buf[sizeof(struct in_addr) +
1819                        sizeof(struct in_addr *)*2 +
1820                        sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */];
1821        struct hostent *hp;
1822
1823        sh_gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno);
1824
1825        return hp;
1826}
1827
1828static int __get_hosts_byaddr_r(const char * addr, int len, int type,
1829                            struct hostent * result_buf,
1830                            char * buf, size_t buflen,
1831                            struct hostent ** result,
1832                            int * h_errnop)
1833{
1834#ifndef __UCLIBC_HAS_IPV6__
1835        char    ipaddr[INET_ADDRSTRLEN];
1836#else
1837        char    ipaddr[INET6_ADDRSTRLEN];
1838#endif /* __UCLIBC_HAS_IPV6__ */
1839
1840    switch (type) {
1841        case AF_INET:
1842                if (len != sizeof(struct in_addr))
1843                        return 0;
1844                break;
1845#ifdef __UCLIBC_HAS_IPV6__
1846        case AF_INET6:
1847                if (len != sizeof(struct in6_addr))
1848                        return 0;
1849                break;
1850#endif /* __UCLIBC_HAS_IPV6__ */
1851        default:
1852                return 0;
1853        }
1854
1855        inet_ntop(type, addr, ipaddr, sizeof(ipaddr));
1856
1857        return(__read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR, 
1858                    result_buf, buf, buflen, result, h_errnop));
1859}
1860
1861static int sh_gethostbyaddr_r (const void *addr, socklen_t len, int type,
1862                            struct hostent * result_buf,
1863                            char * buf, size_t buflen,
1864                            struct hostent ** result,
1865                            int * h_errnop)
1866
1867{
1868        struct in_addr *in;
1869        struct in_addr **addr_list;
1870#ifdef __UCLIBC_HAS_IPV6__
1871        char *qp;
1872        size_t plen;
1873        struct in6_addr *in6;
1874        struct in6_addr **addr_list6;
1875#endif /* __UCLIBC_HAS_IPV6__ */
1876        unsigned char *packet;
1877        struct resolv_answer a;
1878        int i;
1879        int nest = 0;
1880        int __nameserversXX;
1881        char ** __nameserverXX;
1882
1883        *result=NULL;
1884        if (!addr)
1885                return EINVAL;
1886       
1887        switch (type) {
1888                case AF_INET:
1889                        if (len != sizeof(struct in_addr))
1890                                return EINVAL;
1891                        break;
1892#ifdef __UCLIBC_HAS_IPV6__
1893                case AF_INET6:
1894                        if (len != sizeof(struct in6_addr))
1895                                return EINVAL;
1896                        break;
1897#endif /* __UCLIBC_HAS_IPV6__ */
1898                default:
1899                        return EINVAL;
1900        }
1901
1902        /* do /etc/hosts first */
1903        if ((i=__get_hosts_byaddr_r(addr, len, type, result_buf,
1904                                  buf, buflen, result, h_errnop))==0)
1905                return i;
1906        switch (*h_errnop) {
1907                case HOST_NOT_FOUND:
1908                case NO_ADDRESS:
1909                        break;
1910                default:
1911                        return i;
1912        }
1913
1914        __open_nameservers();
1915
1916#ifdef __UCLIBC_HAS_IPV6__
1917        qp=buf;
1918        plen=buflen;
1919#endif /* __UCLIBC_HAS_IPV6__ */
1920
1921        *h_errnop = NETDB_INTERNAL;
1922        if (buflen < sizeof(*in))
1923                return ERANGE;
1924        in=(struct in_addr*)buf;
1925        buf+=sizeof(*in);
1926        buflen-=sizeof(*in);
1927
1928        if (buflen < sizeof(*addr_list)*2)
1929                return ERANGE;
1930        addr_list=(struct in_addr**)buf;
1931        buf+=sizeof(*addr_list)*2;
1932        buflen-=sizeof(*addr_list)*2;
1933
1934#ifdef __UCLIBC_HAS_IPV6__
1935        if (plen < sizeof(*in6))
1936                return ERANGE;
1937        in6=(struct in6_addr*)qp;
1938        qp+=sizeof(*in6);
1939        plen-=sizeof(*in6);
1940
1941        if (plen < sizeof(*addr_list6)*2)
1942                return ERANGE;
1943        addr_list6=(struct in6_addr**)qp;
1944        qp+=sizeof(*addr_list6)*2;
1945        plen-=sizeof(*addr_list6)*2;
1946
1947        if (plen < buflen) {
1948                buflen=plen;
1949                buf=qp;
1950        }
1951#endif /* __UCLIBC_HAS_IPV6__ */
1952
1953        if (buflen<256)
1954                return ERANGE;
1955
1956        if(type == AF_INET) {
[170]1957                const unsigned char *tmp_addr = (const unsigned char *)addr;
[1]1958
1959                memcpy(&in->s_addr, addr, len);
1960
1961                addr_list[0] = in;
1962
1963                sprintf(buf, "%u.%u.%u.%u.in-addr.arpa",
1964                        tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]);
1965#ifdef __UCLIBC_HAS_IPV6__
1966        } else {
1967                memcpy(in6->s6_addr, addr, len);
1968
1969                addr_list6[0] = in6;
1970                qp = buf;
1971
1972                for (i = len - 1; i >= 0; i--) {
1973                        qp += sprintf(qp, "%x.%x.", in6->s6_addr[i] & 0xf,
1974                                (in6->s6_addr[i] >> 4) & 0xf);
1975        }
1976        strcpy(qp, "ip6.int");
1977#endif /* __UCLIBC_HAS_IPV6__ */
1978        }
1979
1980        addr_list[1] = 0;
1981
1982        for (;;) {
1983
[134]1984        SH_MUTEX_LOCK_UNSAFE(resolv_lock);
[1]1985        __nameserversXX=__nameservers;
1986        __nameserverXX=__nameserver;
[134]1987        SH_MUTEX_UNLOCK_UNSAFE(resolv_lock);
[1]1988                i = __dns_lookup(buf, T_PTR, __nameserversXX, __nameserverXX, &packet, &a);
1989
1990                if (i < 0) {
1991                        *h_errnop = HOST_NOT_FOUND;
1992                        return TRY_AGAIN;
1993                }
1994
1995                strncpy(buf, a.dotted, buflen);
1996                free(a.dotted);
1997
1998                if (a.atype == T_CNAME) {               /* CNAME */
1999                        DPRINTF("Got a CNAME in gethostbyaddr()\n");
2000                        i = __decode_dotted(packet, a.rdoffset, buf, buflen);
2001                        free(packet);
2002
2003                        if (i < 0) {
2004                                *h_errnop = NO_RECOVERY;
2005                                return -1;
2006                        }
2007                        if (++nest > MAX_RECURSE) {
2008                                *h_errnop = NO_RECOVERY;
2009                                return -1;
2010                        }
2011                        continue;
2012                } else if (a.atype == T_PTR) {  /* ADDRESS */
2013                        i = __decode_dotted(packet, a.rdoffset, buf, buflen);
2014                        free(packet);
2015
2016                        result_buf->h_name = buf;
2017                        result_buf->h_addrtype = type;
2018
2019                        if(type == AF_INET) {
2020                                result_buf->h_length = sizeof(*in);
2021#ifdef __UCLIBC_HAS_IPV6__
2022                        } else {
2023                                result_buf->h_length = sizeof(*in6);
2024#endif /* __UCLIBC_HAS_IPV6__ */
2025                }
2026
2027                        result_buf->h_addr_list = (char **) addr_list;
2028                        break;
2029                } else {
2030                        free(packet);
2031                        *h_errnop = NO_ADDRESS;
2032                        return TRY_AGAIN;
2033                }
2034        }
2035
2036        *result=result_buf;
2037        *h_errnop = NETDB_SUCCESS;
2038        return NETDB_SUCCESS;
2039}
2040
2041struct hostent * sh_gethostbyaddr (const void *addr, socklen_t len, int type)
2042{
2043        static struct hostent h;
2044        static char buf[
2045#ifndef __UCLIBC_HAS_IPV6__
2046                sizeof(struct in_addr) + sizeof(struct in_addr *)*2 +
2047#else
2048                sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 +
2049#endif /* __UCLIBC_HAS_IPV6__ */
2050                sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */];
2051        struct hostent *hp;
2052
2053        sh_gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno);
2054       
2055        return hp;
2056}
2057
2058/* NEED_STATIC_LIBS */
2059#else
2060
2061/* include something to avoid empty compilation unit */
2062#include <stdio.h>
2063
2064#endif
2065
Note: See TracBrowser for help on using the repository browser.