[BACK]Return to gethnamaddr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / net

Annotation of src/lib/libc/net/gethnamaddr.c, Revision 1.93

1.93    ! is          1: /*     $NetBSD: gethnamaddr.c,v 1.92 2015/09/22 16:16:02 christos Exp $        */
1.2       mrg         2:
1.1       mrg         3: /*
                      4:  * ++Copyright++ 1985, 1988, 1993
                      5:  * -
                      6:  * Copyright (c) 1985, 1988, 1993
                      7:  *    The Regents of the University of California.  All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
1.55      agc        17:  * 3. Neither the name of the University nor the names of its contributors
1.1       mrg        18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  * -
                     33:  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
                     34:  *
                     35:  * Permission to use, copy, modify, and distribute this software for any
                     36:  * purpose with or without fee is hereby granted, provided that the above
                     37:  * copyright notice and this permission notice appear in all copies, and that
                     38:  * the name of Digital Equipment Corporation not be used in advertising or
                     39:  * publicity pertaining to distribution of the document or software without
                     40:  * specific, written prior permission.
                     41:  *
                     42:  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
                     43:  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
                     44:  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
                     45:  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     46:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     47:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
                     48:  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     49:  * SOFTWARE.
                     50:  * -
                     51:  * --Copyright--
                     52:  */
                     53:
1.2       mrg        54: #include <sys/cdefs.h>
1.1       mrg        55: #if defined(LIBC_SCCS) && !defined(lint)
1.2       mrg        56: #if 0
1.1       mrg        57: static char sccsid[] = "@(#)gethostnamadr.c    8.1 (Berkeley) 6/4/93";
1.4       perry      58: static char rcsid[] = "Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp ";
1.2       mrg        59: #else
1.93    ! is         60: __RCSID("$NetBSD: gethnamaddr.c,v 1.92 2015/09/22 16:16:02 christos Exp $");
1.2       mrg        61: #endif
1.1       mrg        62: #endif /* LIBC_SCCS and not lint */
                     63:
1.6       kleink     64: #if defined(_LIBC)
1.3       thorpej    65: #include "namespace.h"
1.6       kleink     66: #endif
1.1       mrg        67: #include <sys/param.h>
                     68: #include <sys/socket.h>
                     69: #include <netinet/in.h>
                     70: #include <arpa/inet.h>
                     71: #include <arpa/nameser.h>
                     72:
1.25      lukem      73: #include <assert.h>
                     74: #include <ctype.h>
                     75: #include <errno.h>
1.1       mrg        76: #include <netdb.h>
                     77: #include <resolv.h>
1.44      wiz        78: #include <stdarg.h>
1.25      lukem      79: #include <stdio.h>
1.1       mrg        80: #include <syslog.h>
                     81:
                     82: #ifndef LOG_AUTH
                     83: # define LOG_AUTH 0
                     84: #endif
                     85:
                     86: #define MULTI_PTRS_ARE_ALIASES 1       /* XXX - experimental */
                     87:
1.9       lukem      88: #include <nsswitch.h>
1.2       mrg        89: #include <stdlib.h>
                     90: #include <string.h>
1.1       mrg        91:
1.2       mrg        92: #ifdef YP
                     93: #include <rpc/rpc.h>
                     94: #include <rpcsvc/yp_prot.h>
                     95: #include <rpcsvc/ypclnt.h>
1.5       kleink     96: #endif
                     97:
1.80      christos   98: #include "hostent.h"
                     99:
1.6       kleink    100: #if defined(_LIBC) && defined(__weak_alias)
1.29      mycroft   101: __weak_alias(gethostbyaddr,_gethostbyaddr)
                    102: __weak_alias(gethostbyname,_gethostbyname)
1.63      ginsbach  103: __weak_alias(gethostent,_gethostent)
1.1       mrg       104: #endif
                    105:
1.79      christos  106: #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
                    107:                                (ok)(nm) != 0)
                    108: #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
                    109: #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
                    110:
1.87      christos  111: #define addalias(d, s, arr, siz) do {                  \
1.89      drochner  112:        if (d >= &arr[siz]) {                           \
                    113:                char **xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \
1.87      christos  114:                if (xptr == NULL)                       \
                    115:                        goto nospc;                     \
                    116:                d = xptr + (d - arr);                   \
                    117:                arr = xptr;                             \
                    118:                siz += 10;                              \
                    119:        }                                               \
                    120:        *d++ = s;                                       \
1.86      christos  121: } while (/*CONSTCOND*/0)
                    122:
1.87      christos  123: #define setup(arr, siz) do {                           \
1.89      drochner  124:        arr = malloc((siz = 10) * sizeof(*arr));        \
1.87      christos  125:        if (arr == NULL)                                \
                    126:                goto nospc;                             \
1.86      christos  127: } while (/*CONSTCOND*/0)
                    128:
1.79      christos  129:
1.1       mrg       130: static const char AskedForGot[] =
1.80      christos  131:     "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1.1       mrg       132:
                    133:
1.2       mrg       134: #ifdef YP
                    135: static char *__ypdomain;
                    136: #endif
                    137:
1.52      itojun    138: #define        MAXPACKET       (64*1024)
1.1       mrg       139:
                    140: typedef union {
1.80      christos  141:        HEADER hdr;
                    142:        u_char buf[MAXPACKET];
1.1       mrg       143: } querybuf;
                    144:
                    145: typedef union {
1.80      christos  146:        int32_t al;
                    147:        char ac;
1.1       mrg       148: } align;
                    149:
                    150: #ifdef DEBUG
1.76      christos  151: static void debugprintf(const char *, res_state, ...)
1.59      christos  152:        __attribute__((__format__(__printf__, 1, 3)));
1.2       mrg       153: #endif
1.59      christos  154: static struct hostent *getanswer(const querybuf *, int, const char *, int,
1.80      christos  155:     res_state, struct hostent *, char *, size_t, int *);
1.59      christos  156: static void map_v4v6_address(const char *, char *);
                    157: static void map_v4v6_hostent(struct hostent *, char **, char *);
1.66      tsarna    158: static void addrsort(char **, int, res_state);
1.2       mrg       159:
1.59      christos  160: void dns_service(void);
1.39      christos  161: #undef dn_skipname
1.59      christos  162: int dn_skipname(const u_char *, const u_char *);
1.80      christos  163:
1.2       mrg       164: #ifdef YP
1.80      christos  165: static struct hostent *_yp_hostent(char *, int, struct getnamaddr *);
1.2       mrg       166: #endif
                    167:
1.80      christos  168: static struct hostent *gethostbyname_internal(const char *, int, res_state,
                    169:     struct hostent *, char *, size_t, int *);
1.59      christos  170:
1.12      lukem     171: static const ns_src default_dns_files[] = {
1.27      lukem     172:        { NSSRC_FILES,  NS_SUCCESS },
1.11      lukem     173:        { NSSRC_DNS,    NS_SUCCESS },
1.71      christos  174:        { 0, 0 }
1.11      lukem     175: };
                    176:
1.2       mrg       177:
                    178: #ifdef DEBUG
1.1       mrg       179: static void
1.76      christos  180: debugprintf(const char *msg, res_state res, ...)
1.1       mrg       181: {
1.25      lukem     182:        _DIAGASSERT(msg != NULL);
                    183:
1.59      christos  184:        if (res->options & RES_DEBUG) {
1.1       mrg       185:                int save = errno;
1.38      sommerfe  186:                va_list ap;
1.1       mrg       187:
1.68      christos  188:                va_start (ap, res);
1.38      sommerfe  189:                vprintf(msg, ap);
                    190:                va_end (ap);
                    191:
1.1       mrg       192:                errno = save;
                    193:        }
                    194: }
                    195: #else
1.76      christos  196: # define debugprintf(msg, res, num) /*nada*/
1.1       mrg       197: #endif
                    198:
1.32      itojun    199: #define BOUNDED_INCR(x) \
                    200:        do { \
1.58      enami     201:                cp += (x); \
1.90      christos  202:                if (cp > eom) \
                    203:                        goto no_recovery; \
1.34      christos  204:        } while (/*CONSTCOND*/0)
1.32      itojun    205:
                    206: #define BOUNDS_CHECK(ptr, count) \
                    207:        do { \
1.90      christos  208:                if ((ptr) + (count) > eom) \
                    209:                        goto no_recovery; \
1.34      christos  210:        } while (/*CONSTCOND*/0)
1.32      itojun    211:
1.1       mrg       212: static struct hostent *
1.59      christos  213: getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
1.80      christos  214:     res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
1.1       mrg       215: {
1.25      lukem     216:        const HEADER *hp;
                    217:        const u_char *cp;
                    218:        int n;
1.80      christos  219:        size_t qlen;
1.32      itojun    220:        const u_char *eom, *erdata;
1.46      itojun    221:        char *bp, **ap, **hap, *ep;
                    222:        int type, class, ancount, qdcount;
1.1       mrg       223:        int haveanswer, had_error;
                    224:        int toobig = 0;
                    225:        char tbuf[MAXDNAME];
1.86      christos  226:        char **aliases;
                    227:        size_t maxaliases;
1.83      christos  228:        char *addr_ptrs[MAXADDRS];
1.1       mrg       229:        const char *tname;
1.59      christos  230:        int (*name_ok)(const char *);
1.1       mrg       231:
1.25      lukem     232:        _DIAGASSERT(answer != NULL);
                    233:        _DIAGASSERT(qname != NULL);
                    234:
1.1       mrg       235:        tname = qname;
1.80      christos  236:        hent->h_name = NULL;
1.1       mrg       237:        eom = answer->buf + anslen;
                    238:        switch (qtype) {
                    239:        case T_A:
                    240:        case T_AAAA:
                    241:                name_ok = res_hnok;
                    242:                break;
                    243:        case T_PTR:
                    244:                name_ok = res_dnok;
                    245:                break;
                    246:        default:
1.92      christos  247:                *he = NO_RECOVERY;
1.59      christos  248:                return NULL;    /* XXX should be abort(); */
1.1       mrg       249:        }
1.86      christos  250:
                    251:        setup(aliases, maxaliases);
1.1       mrg       252:        /*
                    253:         * find first satisfactory answer
                    254:         */
                    255:        hp = &answer->hdr;
                    256:        ancount = ntohs(hp->ancount);
                    257:        qdcount = ntohs(hp->qdcount);
1.80      christos  258:        bp = buf;
                    259:        ep = buf + buflen;
1.32      itojun    260:        cp = answer->buf;
                    261:        BOUNDED_INCR(HFIXEDSZ);
1.80      christos  262:        if (qdcount != 1)
                    263:                goto no_recovery;
                    264:
1.78      christos  265:        n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
1.80      christos  266:        if ((n < 0) || !maybe_ok(res, bp, name_ok))
                    267:                goto no_recovery;
                    268:
1.32      itojun    269:        BOUNDED_INCR(n + QFIXEDSZ);
1.1       mrg       270:        if (qtype == T_A || qtype == T_AAAA) {
                    271:                /* res_send() has already verified that the query name is the
                    272:                 * same as the one we sent; this just gets the expanded name
                    273:                 * (i.e., with the succeeding search-domain tacked on).
                    274:                 */
1.78      christos  275:                n = (int)strlen(bp) + 1;                /* for the \0 */
1.80      christos  276:                if (n >= MAXHOSTNAMELEN)
                    277:                        goto no_recovery;
                    278:                hent->h_name = bp;
1.1       mrg       279:                bp += n;
                    280:                /* The qname can be abbreviated, but h_name is now absolute. */
1.80      christos  281:                qname = hent->h_name;
1.1       mrg       282:        }
1.80      christos  283:        hent->h_aliases = ap = aliases;
                    284:        hent->h_addr_list = hap = addr_ptrs;
1.1       mrg       285:        *ap = NULL;
                    286:        *hap = NULL;
                    287:        haveanswer = 0;
                    288:        had_error = 0;
                    289:        while (ancount-- > 0 && cp < eom && !had_error) {
1.78      christos  290:                n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
1.79      christos  291:                if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
1.1       mrg       292:                        had_error++;
                    293:                        continue;
                    294:                }
                    295:                cp += n;                        /* name */
1.32      itojun    296:                BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
1.1       mrg       297:                type = _getshort(cp);
                    298:                cp += INT16SZ;                  /* type */
                    299:                class = _getshort(cp);
                    300:                cp += INT16SZ + INT32SZ;        /* class, TTL */
                    301:                n = _getshort(cp);
                    302:                cp += INT16SZ;                  /* len */
1.32      itojun    303:                BOUNDS_CHECK(cp, n);
                    304:                erdata = cp + n;
1.1       mrg       305:                if (class != C_IN) {
                    306:                        /* XXX - debug? syslog? */
                    307:                        cp += n;
                    308:                        continue;               /* XXX - had_error++ ? */
                    309:                }
                    310:                if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
1.80      christos  311:                        n = dn_expand(answer->buf, eom, cp, tbuf,
                    312:                            (int)sizeof tbuf);
1.79      christos  313:                        if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
1.1       mrg       314:                                had_error++;
                    315:                                continue;
                    316:                        }
                    317:                        cp += n;
1.80      christos  318:                        if (cp != erdata)
                    319:                                goto no_recovery;
1.1       mrg       320:                        /* Store alias. */
1.87      christos  321:                        addalias(ap, bp, aliases, maxaliases);
1.78      christos  322:                        n = (int)strlen(bp) + 1;        /* for the \0 */
1.1       mrg       323:                        if (n >= MAXHOSTNAMELEN) {
                    324:                                had_error++;
                    325:                                continue;
                    326:                        }
                    327:                        bp += n;
                    328:                        /* Get canonical name. */
1.78      christos  329:                        n = (int)strlen(tbuf) + 1;      /* for the \0 */
1.46      itojun    330:                        if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1.1       mrg       331:                                had_error++;
                    332:                                continue;
                    333:                        }
1.54      itojun    334:                        strlcpy(bp, tbuf, (size_t)(ep - bp));
1.80      christos  335:                        hent->h_name = bp;
1.1       mrg       336:                        bp += n;
                    337:                        continue;
                    338:                }
                    339:                if (qtype == T_PTR && type == T_CNAME) {
1.80      christos  340:                        n = dn_expand(answer->buf, eom, cp, tbuf,
                    341:                            (int)sizeof tbuf);
1.79      christos  342:                        if (n < 0 || !maybe_dnok(res, tbuf)) {
1.1       mrg       343:                                had_error++;
                    344:                                continue;
                    345:                        }
                    346:                        cp += n;
1.80      christos  347:                        if (cp != erdata)
                    348:                                goto no_recovery;
1.1       mrg       349:                        /* Get canonical name. */
1.78      christos  350:                        n = (int)strlen(tbuf) + 1;      /* for the \0 */
1.46      itojun    351:                        if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1.1       mrg       352:                                had_error++;
                    353:                                continue;
                    354:                        }
1.54      itojun    355:                        strlcpy(bp, tbuf, (size_t)(ep - bp));
1.1       mrg       356:                        tname = bp;
                    357:                        bp += n;
                    358:                        continue;
                    359:                }
                    360:                if (type != qtype) {
1.93    ! is        361:                        if (type != T_KEY && type != T_SIG && type != T_DNAME)
1.28      assar     362:                                syslog(LOG_NOTICE|LOG_AUTH,
1.1       mrg       363:               "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1.28      assar     364:                                       qname, p_class(C_IN), p_type(qtype),
                    365:                                       p_type(type));
1.1       mrg       366:                        cp += n;
                    367:                        continue;               /* XXX - had_error++ ? */
                    368:                }
                    369:                switch (type) {
                    370:                case T_PTR:
                    371:                        if (strcasecmp(tname, bp) != 0) {
                    372:                                syslog(LOG_NOTICE|LOG_AUTH,
                    373:                                       AskedForGot, qname, bp);
                    374:                                cp += n;
                    375:                                continue;       /* XXX - had_error++ ? */
                    376:                        }
1.78      christos  377:                        n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
1.79      christos  378:                        if ((n < 0) || !maybe_hnok(res, bp)) {
1.1       mrg       379:                                had_error++;
                    380:                                break;
                    381:                        }
                    382: #if MULTI_PTRS_ARE_ALIASES
                    383:                        cp += n;
1.80      christos  384:                        if (cp != erdata)
                    385:                                goto no_recovery;
1.1       mrg       386:                        if (!haveanswer)
1.80      christos  387:                                hent->h_name = bp;
1.87      christos  388:                        else
                    389:                                addalias(ap, bp, aliases, maxaliases);
1.1       mrg       390:                        if (n != -1) {
1.78      christos  391:                                n = (int)strlen(bp) + 1;        /* for the \0 */
1.1       mrg       392:                                if (n >= MAXHOSTNAMELEN) {
                    393:                                        had_error++;
                    394:                                        break;
                    395:                                }
                    396:                                bp += n;
                    397:                        }
                    398:                        break;
                    399: #else
1.80      christos  400:                        hent->h_name = bp;
1.59      christos  401:                        if (res->options & RES_USE_INET6) {
1.1       mrg       402:                                n = strlen(bp) + 1;     /* for the \0 */
                    403:                                if (n >= MAXHOSTNAMELEN) {
                    404:                                        had_error++;
                    405:                                        break;
                    406:                                }
                    407:                                bp += n;
1.80      christos  408:                                map_v4v6_hostent(hent, &bp, ep);
1.1       mrg       409:                        }
1.80      christos  410:                        goto success;
1.1       mrg       411: #endif
                    412:                case T_A:
                    413:                case T_AAAA:
1.80      christos  414:                        if (strcasecmp(hent->h_name, bp) != 0) {
1.1       mrg       415:                                syslog(LOG_NOTICE|LOG_AUTH,
1.80      christos  416:                                       AskedForGot, hent->h_name, bp);
1.1       mrg       417:                                cp += n;
                    418:                                continue;       /* XXX - had_error++ ? */
                    419:                        }
1.80      christos  420:                        if (n != hent->h_length) {
1.1       mrg       421:                                cp += n;
                    422:                                continue;
1.51      itojun    423:                        }
                    424:                        if (type == T_AAAA) {
                    425:                                struct in6_addr in6;
1.80      christos  426:                                memcpy(&in6, cp, NS_IN6ADDRSZ);
1.51      itojun    427:                                if (IN6_IS_ADDR_V4MAPPED(&in6)) {
                    428:                                        cp += n;
                    429:                                        continue;
                    430:                                }
1.1       mrg       431:                        }
                    432:                        if (!haveanswer) {
1.25      lukem     433:                                int nn;
1.1       mrg       434:
1.80      christos  435:                                hent->h_name = bp;
1.78      christos  436:                                nn = (int)strlen(bp) + 1;       /* for the \0 */
1.1       mrg       437:                                bp += nn;
                    438:                        }
                    439:
1.14      lukem     440:                        bp += sizeof(align) -
                    441:                            (size_t)((u_long)bp % sizeof(align));
1.1       mrg       442:
1.80      christos  443:                        if (bp + n >= ep) {
1.76      christos  444:                                debugprintf("size (%d) too big\n", res, n);
1.1       mrg       445:                                had_error++;
                    446:                                continue;
                    447:                        }
1.80      christos  448:                        if (hap >= &addr_ptrs[MAXADDRS - 1]) {
1.71      christos  449:                                if (!toobig++) {
1.76      christos  450:                                        debugprintf("Too many addresses (%d)\n",
1.59      christos  451:                                                res, MAXADDRS);
1.71      christos  452:                                }
1.1       mrg       453:                                cp += n;
                    454:                                continue;
                    455:                        }
1.7       kleink    456:                        (void)memcpy(*hap++ = bp, cp, (size_t)n);
1.1       mrg       457:                        bp += n;
                    458:                        cp += n;
1.80      christos  459:                        if (cp != erdata)
                    460:                                goto no_recovery;
1.1       mrg       461:                        break;
                    462:                default:
                    463:                        abort();
                    464:                }
                    465:                if (!had_error)
                    466:                        haveanswer++;
                    467:        }
                    468:        if (haveanswer) {
                    469:                *ap = NULL;
                    470:                *hap = NULL;
                    471:                /*
                    472:                 * Note: we sort even if host can take only one address
                    473:                 * in its return structures - should give it the "best"
                    474:                 * address in that case, not some random one
                    475:                 */
1.59      christos  476:                if (res->nsort && haveanswer > 1 && qtype == T_A)
1.80      christos  477:                        addrsort(addr_ptrs, haveanswer, res);
                    478:                if (!hent->h_name) {
1.78      christos  479:                        n = (int)strlen(qname) + 1;     /* for the \0 */
1.46      itojun    480:                        if (n > ep - bp || n >= MAXHOSTNAMELEN)
1.1       mrg       481:                                goto no_recovery;
1.54      itojun    482:                        strlcpy(bp, qname, (size_t)(ep - bp));
1.80      christos  483:                        hent->h_name = bp;
1.1       mrg       484:                        bp += n;
                    485:                }
1.59      christos  486:                if (res->options & RES_USE_INET6)
1.80      christos  487:                        map_v4v6_hostent(hent, &bp, ep);
                    488:                goto success;
1.1       mrg       489:        }
1.80      christos  490: no_recovery:
1.86      christos  491:        free(aliases);
1.80      christos  492:        *he = NO_RECOVERY;
                    493:        return NULL;
                    494: success:
                    495:        bp = (char *)ALIGN(bp);
                    496:        n = (int)(ap - aliases);
                    497:        qlen = (n + 1) * sizeof(*hent->h_aliases);
                    498:        if ((size_t)(ep - bp) < qlen)
                    499:                goto nospc;
                    500:        hent->h_aliases = (void *)bp;
                    501:        memcpy(bp, aliases, qlen);
1.86      christos  502:        free(aliases);
1.90      christos  503:        aliases = NULL;
1.80      christos  504:
                    505:        bp += qlen;
                    506:        n = (int)(hap - addr_ptrs);
                    507:        qlen = (n + 1) * sizeof(*hent->h_addr_list);
                    508:        if ((size_t)(ep - bp) < qlen)
                    509:                goto nospc;
                    510:        hent->h_addr_list = (void *)bp;
                    511:        memcpy(bp, addr_ptrs, qlen);
                    512:        *he = NETDB_SUCCESS;
                    513:        return hent;
                    514: nospc:
1.86      christos  515:        free(aliases);
1.80      christos  516:        errno = ENOSPC;
                    517:        *he = NETDB_INTERNAL;
1.59      christos  518:        return NULL;
1.1       mrg       519: }
                    520:
                    521: struct hostent *
1.80      christos  522: gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
                    523:     int *he)
1.1       mrg       524: {
1.59      christos  525:        res_state res = __res_get_state();
1.1       mrg       526:
1.80      christos  527:        if (res == NULL) {
                    528:                *he = NETDB_INTERNAL;
1.60      christos  529:                return NULL;
1.80      christos  530:        }
1.60      christos  531:
1.25      lukem     532:        _DIAGASSERT(name != NULL);
                    533:
1.59      christos  534:        if (res->options & RES_USE_INET6) {
1.85      christos  535:                struct hostent *nhp = gethostbyname_internal(name, AF_INET6,
                    536:                    res, hp, buf, buflen, he);
                    537:                if (nhp) {
1.59      christos  538:                        __res_put_state(res);
1.85      christos  539:                        return nhp;
1.59      christos  540:                }
1.1       mrg       541:        }
1.80      christos  542:        hp = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, he);
1.59      christos  543:        __res_put_state(res);
                    544:        return hp;
1.1       mrg       545: }
                    546:
                    547: struct hostent *
1.80      christos  548: gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
                    549:     size_t buflen, int *he)
1.59      christos  550: {
                    551:        res_state res = __res_get_state();
1.60      christos  552:
1.80      christos  553:        if (res == NULL) {
                    554:                *he = NETDB_INTERNAL;
1.60      christos  555:                return NULL;
1.80      christos  556:        }
                    557:        hp = gethostbyname_internal(name, af, res, hp, buf, buflen, he);
1.59      christos  558:        __res_put_state(res);
                    559:        return hp;
                    560: }
                    561:
                    562: static struct hostent *
1.80      christos  563: gethostbyname_internal(const char *name, int af, res_state res,
                    564:     struct hostent *hp, char *buf, size_t buflen, int *he)
1.1       mrg       565: {
1.2       mrg       566:        const char *cp;
1.80      christos  567:        struct getnamaddr info;
1.85      christos  568:        char hbuf[MAXHOSTNAMELEN];
1.80      christos  569:        size_t size;
1.12      lukem     570:        static const ns_dtab dtab[] = {
1.80      christos  571:                NS_FILES_CB(_hf_gethtbyname, NULL)
1.9       lukem     572:                { NSSRC_DNS, _dns_gethtbyname, NULL },  /* force -DHESIOD */
1.11      lukem     573:                NS_NIS_CB(_yp_gethtbyname, NULL)
1.71      christos  574:                NS_NULL_CB
1.9       lukem     575:        };
1.1       mrg       576:
1.25      lukem     577:        _DIAGASSERT(name != NULL);
                    578:
1.1       mrg       579:        switch (af) {
                    580:        case AF_INET:
1.80      christos  581:                size = NS_INADDRSZ;
1.1       mrg       582:                break;
                    583:        case AF_INET6:
1.80      christos  584:                size = NS_IN6ADDRSZ;
1.1       mrg       585:                break;
                    586:        default:
1.80      christos  587:                *he = NETDB_INTERNAL;
1.1       mrg       588:                errno = EAFNOSUPPORT;
1.59      christos  589:                return NULL;
1.1       mrg       590:        }
1.80      christos  591:        if (buflen < size)
                    592:                goto nospc;
1.1       mrg       593:
1.80      christos  594:        hp->h_addrtype = af;
                    595:        hp->h_length = (int)size;
1.1       mrg       596:
                    597:        /*
1.75      wiz       598:         * if there aren't any dots, it could be a user-level alias.
1.59      christos  599:         * this is also done in res_nquery() since we are not the only
1.1       mrg       600:         * function that looks up host names.
                    601:         */
1.85      christos  602:        if (!strchr(name, '.') && (cp = res_hostalias(res, name,
                    603:            hbuf, sizeof(hbuf))))
1.1       mrg       604:                name = cp;
                    605:
                    606:        /*
                    607:         * disallow names consisting only of digits/dots, unless
                    608:         * they end in a dot.
                    609:         */
1.35      itohy     610:        if (isdigit((u_char) name[0]))
1.1       mrg       611:                for (cp = name;; ++cp) {
                    612:                        if (!*cp) {
                    613:                                if (*--cp == '.')
                    614:                                        break;
                    615:                                /*
                    616:                                 * All-numeric, no dot at the end.
                    617:                                 * Fake up a hostent as if we'd actually
                    618:                                 * done a lookup.
                    619:                                 */
1.80      christos  620:                                goto fake;
1.1       mrg       621:                        }
1.35      itohy     622:                        if (!isdigit((u_char) *cp) && *cp != '.')
1.1       mrg       623:                                break;
                    624:                }
1.35      itohy     625:        if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
1.1       mrg       626:            name[0] == ':')
                    627:                for (cp = name;; ++cp) {
                    628:                        if (!*cp) {
                    629:                                if (*--cp == '.')
                    630:                                        break;
                    631:                                /*
                    632:                                 * All-IPv6-legal, no dot at the end.
                    633:                                 * Fake up a hostent as if we'd actually
                    634:                                 * done a lookup.
                    635:                                 */
1.80      christos  636:                                goto fake;
1.1       mrg       637:                        }
1.35      itohy     638:                        if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
1.1       mrg       639:                                break;
                    640:                }
                    641:
1.80      christos  642:        *he = NETDB_INTERNAL;
                    643:        info.hp = hp;
                    644:        info.buf = buf;
                    645:        info.buflen = buflen;
                    646:        info.he = he;
                    647:        if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
1.45      itojun    648:            default_dns_files, name, strlen(name), af) != NS_SUCCESS)
1.59      christos  649:                return NULL;
1.80      christos  650:        *he = NETDB_SUCCESS;
                    651:        return hp;
                    652: nospc:
                    653:        *he = NETDB_INTERNAL;
                    654:        errno = ENOSPC;
                    655:        return NULL;
                    656: fake:
1.84      christos  657:        HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
                    658:        HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
1.80      christos  659:
                    660:        hp->h_aliases[0] = NULL;
                    661:        if (size > buflen)
                    662:                goto nospc;
                    663:
                    664:        if (inet_pton(af, name, buf) <= 0) {
                    665:                *he = HOST_NOT_FOUND;
                    666:                return NULL;
                    667:        }
                    668:        hp->h_addr_list[0] = buf;
                    669:        hp->h_addr_list[1] = NULL;
                    670:        buf += size;
                    671:        buflen -= size;
1.84      christos  672:        HENT_SCOPY(hp->h_name, name, buf, buflen);
1.80      christos  673:        if (res->options & RES_USE_INET6)
                    674:                map_v4v6_hostent(hp, &buf, buf + buflen);
                    675:        *he = NETDB_SUCCESS;
1.59      christos  676:        return hp;
1.1       mrg       677: }
                    678:
                    679: struct hostent *
1.80      christos  680: gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp,
                    681:     char *buf, size_t buflen, int *he)
1.1       mrg       682: {
                    683:        const u_char *uaddr = (const u_char *)addr;
1.53      thorpej   684:        socklen_t size;
1.80      christos  685:        struct getnamaddr info;
1.12      lukem     686:        static const ns_dtab dtab[] = {
1.80      christos  687:                NS_FILES_CB(_hf_gethtbyaddr, NULL)
1.9       lukem     688:                { NSSRC_DNS, _dns_gethtbyaddr, NULL },  /* force -DHESIOD */
1.11      lukem     689:                NS_NIS_CB(_yp_gethtbyaddr, NULL)
1.71      christos  690:                NS_NULL_CB
1.9       lukem     691:        };
1.1       mrg       692:
1.25      lukem     693:        _DIAGASSERT(addr != NULL);
                    694:
1.80      christos  695:        if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
                    696:            (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
                    697:             IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
                    698:                *he = HOST_NOT_FOUND;
1.59      christos  699:                return NULL;
1.41      itojun    700:        }
1.80      christos  701:        if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
                    702:            (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
                    703:             IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
1.1       mrg       704:                /* Unmap. */
1.80      christos  705:                uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
                    706:                addr = uaddr;
1.1       mrg       707:                af = AF_INET;
1.80      christos  708:                len = NS_INADDRSZ;
1.1       mrg       709:        }
                    710:        switch (af) {
                    711:        case AF_INET:
1.80      christos  712:                size = NS_INADDRSZ;
1.1       mrg       713:                break;
                    714:        case AF_INET6:
1.80      christos  715:                size = NS_IN6ADDRSZ;
1.1       mrg       716:                break;
                    717:        default:
                    718:                errno = EAFNOSUPPORT;
1.80      christos  719:                *he = NETDB_INTERNAL;
1.59      christos  720:                return NULL;
1.1       mrg       721:        }
                    722:        if (size != len) {
                    723:                errno = EINVAL;
1.80      christos  724:                *he = NETDB_INTERNAL;
1.59      christos  725:                return NULL;
1.1       mrg       726:        }
1.80      christos  727:        info.hp = hp;
                    728:        info.buf = buf;
                    729:        info.buflen = buflen;
                    730:        info.he = he;
                    731:        *he = NETDB_INTERNAL;
                    732:        if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
1.11      lukem     733:            default_dns_files, uaddr, len, af) != NS_SUCCESS)
1.59      christos  734:                return NULL;
1.80      christos  735:        *he = NETDB_SUCCESS;
1.59      christos  736:        return hp;
1.1       mrg       737: }
                    738:
                    739: struct hostent *
1.80      christos  740: gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
1.1       mrg       741: {
1.80      christos  742:        char *p, *name;
1.25      lukem     743:        char *cp, **q;
1.1       mrg       744:        int af, len;
1.91      christos  745:        size_t anum;
1.86      christos  746:        char **aliases;
                    747:        size_t maxaliases;
1.80      christos  748:        struct in6_addr host_addr;
1.1       mrg       749:
1.80      christos  750:        if (hf == NULL) {
                    751:                *he = NETDB_INTERNAL;
                    752:                errno = EINVAL;
1.59      christos  753:                return NULL;
1.1       mrg       754:        }
1.91      christos  755:        p = NULL;
1.86      christos  756:        setup(aliases, maxaliases);
1.91      christos  757:        for (;;) {
                    758:                free(p);
                    759:                p = fparseln(hf, NULL, NULL, NULL, FPARSELN_UNESCALL);
                    760:                if (p == NULL) {
                    761:                        free(aliases);
                    762:                        *he = HOST_NOT_FOUND;
                    763:                        return NULL;
                    764:                }
                    765:                if (!(cp = strpbrk(p, " \t")))
                    766:                        continue;
                    767:                *cp++ = '\0';
                    768:                if (inet_pton(AF_INET6, p, &host_addr) > 0) {
1.1       mrg       769:                        af = AF_INET6;
1.80      christos  770:                        len = NS_IN6ADDRSZ;
1.1       mrg       771:                } else {
1.91      christos  772:                        if (inet_pton(AF_INET, p, &host_addr) <= 0)
                    773:                                continue;
                    774:
                    775:                        res_state res = __res_get_state();
                    776:                        if (res == NULL)
                    777:                                goto nospc;
                    778:                        if (res->options & RES_USE_INET6) {
                    779:                                map_v4v6_address(buf, buf);
                    780:                                af = AF_INET6;
                    781:                                len = NS_IN6ADDRSZ;
                    782:                        } else {
                    783:                                af = AF_INET;
                    784:                                len = NS_INADDRSZ;
                    785:                        }
                    786:                        __res_put_state(res);
1.1       mrg       787:                }
1.80      christos  788:
1.91      christos  789:                /* if this is not something we're looking for, skip it. */
                    790:                if (hent->h_addrtype != 0 && hent->h_addrtype != af)
                    791:                        continue;
                    792:                if (hent->h_length != 0 && hent->h_length != len)
                    793:                        continue;
                    794:
                    795:                while (*cp == ' ' || *cp == '\t')
1.1       mrg       796:                        cp++;
1.91      christos  797:                if ((cp = strpbrk(name = cp, " \t")) != NULL)
                    798:                        *cp++ = '\0';
                    799:                q = aliases;
                    800:                while (cp && *cp) {
                    801:                        if (*cp == ' ' || *cp == '\t') {
                    802:                                cp++;
                    803:                                continue;
                    804:                        }
                    805:                        addalias(q, cp, aliases, maxaliases);
                    806:                        if ((cp = strpbrk(cp, " \t")) != NULL)
                    807:                                *cp++ = '\0';
1.1       mrg       808:                }
1.91      christos  809:                break;
1.1       mrg       810:        }
1.80      christos  811:        hent->h_length = len;
                    812:        hent->h_addrtype = af;
1.84      christos  813:        HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
1.80      christos  814:        anum = (size_t)(q - aliases);
1.84      christos  815:        HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
                    816:        HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
                    817:            buflen);
1.80      christos  818:        hent->h_addr_list[1] = NULL;
                    819:
1.84      christos  820:        HENT_SCOPY(hent->h_name, name, buf, buflen);
1.80      christos  821:        for (size_t i = 0; i < anum; i++)
1.84      christos  822:                HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
1.80      christos  823:        hent->h_aliases[anum] = NULL;
                    824:
                    825:        *he = NETDB_SUCCESS;
1.91      christos  826:        free(p);
1.86      christos  827:        free(aliases);
1.80      christos  828:        return hent;
                    829: nospc:
1.91      christos  830:        free(p);
1.86      christos  831:        free(aliases);
1.80      christos  832:        errno = ENOSPC;
                    833:        *he = NETDB_INTERNAL;
                    834:        return NULL;
1.1       mrg       835: }
                    836:
                    837: static void
1.59      christos  838: map_v4v6_address(const char *src, char *dst)
1.1       mrg       839: {
                    840:        u_char *p = (u_char *)dst;
1.80      christos  841:        char tmp[NS_INADDRSZ];
1.1       mrg       842:        int i;
                    843:
1.25      lukem     844:        _DIAGASSERT(src != NULL);
                    845:        _DIAGASSERT(dst != NULL);
                    846:
1.1       mrg       847:        /* Stash a temporary copy so our caller can update in place. */
1.80      christos  848:        (void)memcpy(tmp, src, NS_INADDRSZ);
1.1       mrg       849:        /* Mark this ipv6 addr as a mapped ipv4. */
                    850:        for (i = 0; i < 10; i++)
                    851:                *p++ = 0x00;
                    852:        *p++ = 0xff;
                    853:        *p++ = 0xff;
                    854:        /* Retrieve the saved copy and we're done. */
1.80      christos  855:        (void)memcpy(p, tmp, NS_INADDRSZ);
1.1       mrg       856: }
                    857:
                    858: static void
1.59      christos  859: map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1.1       mrg       860: {
                    861:        char **ap;
                    862:
1.25      lukem     863:        _DIAGASSERT(hp != NULL);
                    864:        _DIAGASSERT(bpp != NULL);
1.47      itojun    865:        _DIAGASSERT(ep != NULL);
1.25      lukem     866:
1.80      christos  867:        if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
1.1       mrg       868:                return;
                    869:        hp->h_addrtype = AF_INET6;
1.80      christos  870:        hp->h_length = NS_IN6ADDRSZ;
1.1       mrg       871:        for (ap = hp->h_addr_list; *ap; ap++) {
1.78      christos  872:                int i = (int)(sizeof(align) -
                    873:                    (size_t)((u_long)*bpp % sizeof(align)));
1.1       mrg       874:
1.80      christos  875:                if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
1.1       mrg       876:                        /* Out of memory.  Truncate address list here.  XXX */
                    877:                        *ap = NULL;
                    878:                        return;
                    879:                }
                    880:                *bpp += i;
                    881:                map_v4v6_address(*ap, *bpp);
                    882:                *ap = *bpp;
1.80      christos  883:                *bpp += NS_IN6ADDRSZ;
1.1       mrg       884:        }
                    885: }
                    886:
                    887: static void
1.59      christos  888: addrsort(char **ap, int num, res_state res)
1.1       mrg       889: {
                    890:        int i, j;
                    891:        char **p;
                    892:        short aval[MAXADDRS];
                    893:        int needsort = 0;
                    894:
1.25      lukem     895:        _DIAGASSERT(ap != NULL);
                    896:
1.1       mrg       897:        p = ap;
                    898:        for (i = 0; i < num; i++, p++) {
1.59      christos  899:            for (j = 0 ; (unsigned)j < res->nsort; j++)
                    900:                if (res->sort_list[j].addr.s_addr ==
1.14      lukem     901:                    (((struct in_addr *)(void *)(*p))->s_addr &
1.59      christos  902:                    res->sort_list[j].mask))
1.1       mrg       903:                        break;
                    904:            aval[i] = j;
                    905:            if (needsort == 0 && i > 0 && j < aval[i-1])
                    906:                needsort = i;
                    907:        }
                    908:        if (!needsort)
                    909:            return;
                    910:
                    911:        while (needsort < num) {
                    912:            for (j = needsort - 1; j >= 0; j--) {
                    913:                if (aval[j] > aval[j+1]) {
                    914:                    char *hp;
                    915:
                    916:                    i = aval[j];
                    917:                    aval[j] = aval[j+1];
                    918:                    aval[j+1] = i;
                    919:
                    920:                    hp = ap[j];
                    921:                    ap[j] = ap[j+1];
                    922:                    ap[j+1] = hp;
                    923:                } else
                    924:                    break;
                    925:            }
                    926:            needsort++;
                    927:        }
                    928: }
                    929:
                    930:
1.13      christos  931: /*ARGSUSED*/
1.9       lukem     932: int
1.61      ginsbach  933: _dns_gethtbyname(void *rv, void *cb_data, va_list ap)
1.9       lukem     934: {
1.52      itojun    935:        querybuf *buf;
1.9       lukem     936:        int n, type;
                    937:        struct hostent *hp;
                    938:        const char *name;
1.59      christos  939:        res_state res;
1.80      christos  940:        struct getnamaddr *info = rv;
1.9       lukem     941:
1.25      lukem     942:        _DIAGASSERT(rv != NULL);
                    943:
1.9       lukem     944:        name = va_arg(ap, char *);
1.80      christos  945:        /* NOSTRICT skip string len */(void)va_arg(ap, int);
                    946:        info->hp->h_addrtype = va_arg(ap, int);
1.9       lukem     947:
1.80      christos  948:        switch (info->hp->h_addrtype) {
1.9       lukem     949:        case AF_INET:
1.80      christos  950:                info->hp->h_length = NS_INADDRSZ;
1.9       lukem     951:                type = T_A;
                    952:                break;
                    953:        case AF_INET6:
1.80      christos  954:                info->hp->h_length = NS_IN6ADDRSZ;
1.9       lukem     955:                type = T_AAAA;
                    956:                break;
                    957:        default:
                    958:                return NS_UNAVAIL;
                    959:        }
1.52      itojun    960:        buf = malloc(sizeof(*buf));
                    961:        if (buf == NULL) {
1.80      christos  962:                *info->he = NETDB_INTERNAL;
1.52      itojun    963:                return NS_NOTFOUND;
                    964:        }
1.59      christos  965:        res = __res_get_state();
1.69      christos  966:        if (res == NULL) {
                    967:                free(buf);
1.92      christos  968:                *info->he = NETDB_INTERNAL;
1.60      christos  969:                return NS_NOTFOUND;
1.69      christos  970:        }
1.78      christos  971:        n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf));
1.52      itojun    972:        if (n < 0) {
                    973:                free(buf);
1.76      christos  974:                debugprintf("res_nsearch failed (%d)\n", res, n);
1.59      christos  975:                __res_put_state(res);
1.9       lukem     976:                return NS_NOTFOUND;
                    977:        }
1.80      christos  978:        hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
                    979:            info->buflen, info->he);
1.52      itojun    980:        free(buf);
1.59      christos  981:        __res_put_state(res);
1.9       lukem     982:        if (hp == NULL)
1.92      christos  983:                switch (*info->he) {
1.9       lukem     984:                case HOST_NOT_FOUND:
                    985:                        return NS_NOTFOUND;
                    986:                case TRY_AGAIN:
                    987:                        return NS_TRYAGAIN;
                    988:                default:
                    989:                        return NS_UNAVAIL;
                    990:                }
                    991:        return NS_SUCCESS;
                    992: }
                    993:
1.13      christos  994: /*ARGSUSED*/
1.9       lukem     995: int
1.59      christos  996: _dns_gethtbyaddr(void *rv, void        *cb_data, va_list ap)
1.9       lukem     997: {
1.49      itojun    998:        char qbuf[MAXDNAME + 1], *qp, *ep;
1.9       lukem     999:        int n;
1.52      itojun   1000:        querybuf *buf;
1.9       lukem    1001:        struct hostent *hp;
                   1002:        const unsigned char *uaddr;
1.80      christos 1003:        int advance;
1.59      christos 1004:        res_state res;
1.80      christos 1005:        char *bf;
                   1006:        size_t blen;
                   1007:        struct getnamaddr *info = rv;
1.9       lukem    1008:
1.25      lukem    1009:        _DIAGASSERT(rv != NULL);
                   1010:
1.9       lukem    1011:        uaddr = va_arg(ap, unsigned char *);
1.80      christos 1012:        info->hp->h_length = va_arg(ap, int);
                   1013:        info->hp->h_addrtype = va_arg(ap, int);
1.9       lukem    1014:
1.80      christos 1015:        switch (info->hp->h_addrtype) {
1.9       lukem    1016:        case AF_INET:
1.43      itojun   1017:                (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
                   1018:                    (uaddr[3] & 0xff), (uaddr[2] & 0xff),
                   1019:                    (uaddr[1] & 0xff), (uaddr[0] & 0xff));
1.9       lukem    1020:                break;
                   1021:
                   1022:        case AF_INET6:
                   1023:                qp = qbuf;
1.49      itojun   1024:                ep = qbuf + sizeof(qbuf) - 1;
1.80      christos 1025:                for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
1.49      itojun   1026:                        advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
                   1027:                            uaddr[n] & 0xf,
1.43      itojun   1028:                            ((unsigned int)uaddr[n] >> 4) & 0xf);
1.49      itojun   1029:                        if (advance > 0 && qp + advance < ep)
1.43      itojun   1030:                                qp += advance;
1.92      christos 1031:                        else
                   1032:                                goto norecovery;
1.50      itojun   1033:                }
1.92      christos 1034:                if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf))
                   1035:                        goto norecovery;
1.9       lukem    1036:                break;
                   1037:        default:
1.92      christos 1038:                goto norecovery;
1.9       lukem    1039:        }
                   1040:
1.52      itojun   1041:        buf = malloc(sizeof(*buf));
                   1042:        if (buf == NULL) {
1.92      christos 1043:                goto nospc;
1.52      itojun   1044:        }
1.59      christos 1045:        res = __res_get_state();
1.70      christos 1046:        if (res == NULL) {
                   1047:                free(buf);
1.92      christos 1048:                goto nospc;
1.70      christos 1049:        }
1.78      christos 1050:        n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf));
1.9       lukem    1051:        if (n < 0) {
1.52      itojun   1052:                free(buf);
1.76      christos 1053:                debugprintf("res_nquery failed (%d)\n", res, n);
1.59      christos 1054:                __res_put_state(res);
1.92      christos 1055:                *info->he = HOST_NOT_FOUND;
1.9       lukem    1056:                return NS_NOTFOUND;
                   1057:        }
1.80      christos 1058:        hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
                   1059:            info->buflen, info->he);
1.52      itojun   1060:        free(buf);
1.59      christos 1061:        if (hp == NULL) {
                   1062:                __res_put_state(res);
1.80      christos 1063:                switch (*info->he) {
1.9       lukem    1064:                case HOST_NOT_FOUND:
                   1065:                        return NS_NOTFOUND;
                   1066:                case TRY_AGAIN:
                   1067:                        return NS_TRYAGAIN;
                   1068:                default:
                   1069:                        return NS_UNAVAIL;
                   1070:                }
1.59      christos 1071:        }
1.80      christos 1072:
                   1073:        bf = (void *)(hp->h_addr_list + 2);
                   1074:        blen = (size_t)(bf - info->buf);
                   1075:        if (blen + info->hp->h_length > info->buflen)
                   1076:                goto nospc;
                   1077:        hp->h_addr_list[0] = bf;
                   1078:        hp->h_addr_list[1] = NULL;
                   1079:        (void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
                   1080:        if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1.92      christos 1081:                if (blen + NS_IN6ADDRSZ > info->buflen) {
                   1082:                        __res_put_state(res);
1.80      christos 1083:                        goto nospc;
1.92      christos 1084:                }
1.80      christos 1085:                map_v4v6_address(bf, bf);
1.9       lukem    1086:                hp->h_addrtype = AF_INET6;
1.80      christos 1087:                hp->h_length = NS_IN6ADDRSZ;
1.9       lukem    1088:        }
                   1089:
1.59      christos 1090:        __res_put_state(res);
1.80      christos 1091:        *info->he = NETDB_SUCCESS;
1.9       lukem    1092:        return NS_SUCCESS;
1.80      christos 1093: nospc:
                   1094:        *info->he = NETDB_INTERNAL;
                   1095:        return NS_UNAVAIL;
1.92      christos 1096: norecovery:
                   1097:        *info->he = NO_RECOVERY;
                   1098:        return NS_UNAVAIL;
1.9       lukem    1099: }
                   1100:
1.2       mrg      1101: #ifdef YP
1.13      christos 1102: /*ARGSUSED*/
1.80      christos 1103: static struct hostent *
                   1104: _yp_hostent(char *line, int af, struct getnamaddr *info)
1.2       mrg      1105: {
1.80      christos 1106:        struct in6_addr host_addrs[MAXADDRS];
1.86      christos 1107:        char **aliases;
                   1108:        size_t maxaliases;
1.2       mrg      1109:        char *p = line;
1.80      christos 1110:        char *cp, **q, *ptr;
                   1111:        size_t len, anum, i;
1.37      itojun   1112:        int addrok;
1.2       mrg      1113:        int more;
1.53      thorpej  1114:        size_t naddrs;
1.80      christos 1115:        struct hostent *hp = info->hp;
1.2       mrg      1116:
1.25      lukem    1117:        _DIAGASSERT(line != NULL);
                   1118:
1.80      christos 1119:        hp->h_name = NULL;
                   1120:        hp->h_addrtype = af;
1.37      itojun   1121:        switch (af) {
                   1122:        case AF_INET:
1.80      christos 1123:                hp->h_length = NS_INADDRSZ;
1.37      itojun   1124:                break;
                   1125:        case AF_INET6:
1.80      christos 1126:                hp->h_length = NS_IN6ADDRSZ;
1.37      itojun   1127:                break;
                   1128:        default:
1.59      christos 1129:                return NULL;
1.37      itojun   1130:        }
1.86      christos 1131:        setup(aliases, maxaliases);
1.37      itojun   1132:        naddrs = 0;
1.80      christos 1133:        q = aliases;
1.2       mrg      1134:
                   1135: nextline:
1.36      itojun   1136:        /* check for host_addrs overflow */
1.80      christos 1137:        if (naddrs >= __arraycount(host_addrs))
1.36      itojun   1138:                goto done;
                   1139:
1.2       mrg      1140:        more = 0;
                   1141:        cp = strpbrk(p, " \t");
1.36      itojun   1142:        if (cp == NULL)
                   1143:                goto done;
1.2       mrg      1144:        *cp++ = '\0';
                   1145:
1.37      itojun   1146:        /* p has should have an address */
1.80      christos 1147:        addrok = inet_pton(af, p, &host_addrs[naddrs]);
1.37      itojun   1148:        if (addrok != 1) {
                   1149:                /* skip to the next line */
                   1150:                while (cp && *cp) {
                   1151:                        if (*cp == '\n') {
                   1152:                                cp++;
                   1153:                                goto nextline;
                   1154:                        }
                   1155:                        cp++;
                   1156:                }
                   1157:                goto done;
                   1158:        }
1.85      christos 1159:        naddrs++;
1.37      itojun   1160:
1.2       mrg      1161:        while (*cp == ' ' || *cp == '\t')
                   1162:                cp++;
                   1163:        p = cp;
                   1164:        cp = strpbrk(p, " \t\n");
                   1165:        if (cp != NULL) {
                   1166:                if (*cp == '\n')
                   1167:                        more = 1;
                   1168:                *cp++ = '\0';
                   1169:        }
1.80      christos 1170:        if (!hp->h_name)
                   1171:                hp->h_name = p;
                   1172:        else if (strcmp(hp->h_name, p) == 0)
1.2       mrg      1173:                ;
1.87      christos 1174:        else
                   1175:                addalias(q, p, aliases, maxaliases);
1.2       mrg      1176:        p = cp;
                   1177:        if (more)
                   1178:                goto nextline;
                   1179:
                   1180:        while (cp && *cp) {
                   1181:                if (*cp == ' ' || *cp == '\t') {
                   1182:                        cp++;
                   1183:                        continue;
                   1184:                }
                   1185:                if (*cp == '\n') {
                   1186:                        cp++;
                   1187:                        goto nextline;
                   1188:                }
1.87      christos 1189:                addalias(q, cp, aliases, maxaliases);
1.2       mrg      1190:                cp = strpbrk(cp, " \t");
                   1191:                if (cp != NULL)
                   1192:                        *cp++ = '\0';
                   1193:        }
1.37      itojun   1194:
1.2       mrg      1195: done:
1.86      christos 1196:        if (hp->h_name == NULL) {
                   1197:                free(aliases);
1.59      christos 1198:                return NULL;
1.86      christos 1199:        }
1.80      christos 1200:
                   1201:        ptr = info->buf;
                   1202:        len = info->buflen;
                   1203:
                   1204:        anum = (size_t)(q - aliases);
1.84      christos 1205:        HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
                   1206:        HENT_ARRAY(hp->h_aliases, anum, ptr, len);
1.80      christos 1207:
                   1208:        for (i = 0; i < naddrs; i++)
1.84      christos 1209:                HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
1.80      christos 1210:                    ptr, len);
                   1211:        hp->h_addr_list[naddrs] = NULL;
                   1212:
1.84      christos 1213:        HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
1.80      christos 1214:
                   1215:        for (i = 0; i < anum; i++)
1.84      christos 1216:                HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
1.80      christos 1217:        hp->h_aliases[anum] = NULL;
1.86      christos 1218:        free(aliases);
1.80      christos 1219:
                   1220:        return hp;
                   1221: nospc:
1.86      christos 1222:        free(aliases);
1.80      christos 1223:        *info->he = NETDB_INTERNAL;
                   1224:        errno = ENOSPC;
                   1225:        return NULL;
1.2       mrg      1226: }
                   1227:
1.13      christos 1228: /*ARGSUSED*/
1.9       lukem    1229: int
1.59      christos 1230: _yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1.2       mrg      1231: {
1.59      christos 1232:        struct hostent *hp = NULL;
1.80      christos 1233:        char *ypcurrent;
                   1234:        int ypcurrentlen, r;
1.37      itojun   1235:        char name[INET6_ADDRSTRLEN];    /* XXX enough? */
1.9       lukem    1236:        const unsigned char *uaddr;
1.17      christos 1237:        int af;
1.37      itojun   1238:        const char *map;
1.80      christos 1239:        struct getnamaddr *info = rv;
1.9       lukem    1240:
1.25      lukem    1241:        _DIAGASSERT(rv != NULL);
                   1242:
1.9       lukem    1243:        uaddr = va_arg(ap, unsigned char *);
1.17      christos 1244:        /* NOSTRICT skip len */(void)va_arg(ap, int);
1.9       lukem    1245:        af = va_arg(ap, int);
1.2       mrg      1246:
                   1247:        if (!__ypdomain) {
                   1248:                if (_yp_check(&__ypdomain) == 0)
1.9       lukem    1249:                        return NS_UNAVAIL;
1.2       mrg      1250:        }
1.9       lukem    1251:        /*
1.37      itojun   1252:         * XXX unfortunately, we cannot support IPv6 extended scoped address
                   1253:         * notation here.  gethostbyaddr() is not scope-aware.  too bad.
1.9       lukem    1254:         */
1.78      christos 1255:        if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL)
1.37      itojun   1256:                return NS_UNAVAIL;
                   1257:        switch (af) {
                   1258:        case AF_INET:
                   1259:                map = "hosts.byaddr";
                   1260:                break;
                   1261:        default:
                   1262:                map = "ipnodes.byaddr";
                   1263:                break;
                   1264:        }
1.80      christos 1265:        ypcurrent = NULL;
1.37      itojun   1266:        r = yp_match(__ypdomain, map, name,
1.80      christos 1267:                (int)strlen(name), &ypcurrent, &ypcurrentlen);
1.59      christos 1268:        if (r == 0)
1.80      christos 1269:                hp = _yp_hostent(ypcurrent, af, info);
                   1270:        else
                   1271:                hp = NULL;
                   1272:        free(ypcurrent);
1.59      christos 1273:        if (hp == NULL) {
1.80      christos 1274:                *info->he = HOST_NOT_FOUND;
1.9       lukem    1275:                return NS_NOTFOUND;
                   1276:        }
                   1277:        return NS_SUCCESS;
1.2       mrg      1278: }
                   1279:
1.13      christos 1280: /*ARGSUSED*/
1.9       lukem    1281: int
1.59      christos 1282: _yp_gethtbyname(void *rv, void *cb_data, va_list ap)
1.2       mrg      1283: {
1.80      christos 1284:        struct hostent *hp;
                   1285:        char *ypcurrent;
                   1286:        int ypcurrentlen, r;
1.9       lukem    1287:        const char *name;
1.17      christos 1288:        int af;
1.37      itojun   1289:        const char *map;
1.80      christos 1290:        struct getnamaddr *info = rv;
1.25      lukem    1291:
                   1292:        _DIAGASSERT(rv != NULL);
1.9       lukem    1293:
                   1294:        name = va_arg(ap, char *);
1.80      christos 1295:        /* NOSTRICT skip string len */(void)va_arg(ap, int);
1.9       lukem    1296:        af = va_arg(ap, int);
1.2       mrg      1297:
                   1298:        if (!__ypdomain) {
                   1299:                if (_yp_check(&__ypdomain) == 0)
1.9       lukem    1300:                        return NS_UNAVAIL;
1.2       mrg      1301:        }
1.37      itojun   1302:        switch (af) {
                   1303:        case AF_INET:
                   1304:                map = "hosts.byname";
                   1305:                break;
                   1306:        default:
                   1307:                map = "ipnodes.byname";
                   1308:                break;
                   1309:        }
1.80      christos 1310:        ypcurrent = NULL;
1.37      itojun   1311:        r = yp_match(__ypdomain, map, name,
1.80      christos 1312:                (int)strlen(name), &ypcurrent, &ypcurrentlen);
1.59      christos 1313:        if (r == 0)
1.80      christos 1314:                hp = _yp_hostent(ypcurrent, af, info);
                   1315:        else
                   1316:                hp = NULL;
                   1317:        free(ypcurrent);
1.59      christos 1318:        if (hp == NULL) {
1.80      christos 1319:                *info->he = HOST_NOT_FOUND;
1.9       lukem    1320:                return NS_NOTFOUND;
                   1321:        }
                   1322:        return NS_SUCCESS;
1.2       mrg      1323: }
                   1324: #endif
1.80      christos 1325:
                   1326: /*
                   1327:  * Non-reentrant versions.
                   1328:  */
                   1329: FILE *_h_file;
                   1330: static struct hostent h_ent;
                   1331: static char h_buf[16384];
                   1332:
                   1333: struct hostent *
1.82      christos 1334: gethostbyaddr(const void *addr, socklen_t len, int af) {
1.80      christos 1335:        return gethostbyaddr_r(addr, len, af, &h_ent, h_buf, sizeof(h_buf),
                   1336:            &h_errno);
                   1337: }
                   1338:
                   1339: struct hostent *
                   1340: gethostbyname(const char *name) {
                   1341:        return gethostbyname_r(name, &h_ent, h_buf, sizeof(h_buf), &h_errno);
                   1342: }
                   1343:
                   1344: struct hostent *
                   1345: gethostbyname2(const char *name, int af) {
                   1346:        return gethostbyname2_r(name, af, &h_ent, h_buf, sizeof(h_buf),
                   1347:            &h_errno);
                   1348: }
                   1349:
                   1350: struct hostent *
                   1351: gethostent(void)
                   1352: {
                   1353:        if (_h_file == NULL) {
                   1354:                sethostent_r(&_h_file);
                   1355:                if (_h_file == NULL) {
                   1356:                        h_errno = NETDB_INTERNAL;
                   1357:                        return NULL;
                   1358:                }
                   1359:        }
                   1360:        memset(&h_ent, 0, sizeof(h_ent));
                   1361:        return gethostent_r(_h_file, &h_ent, h_buf, sizeof(h_buf), &h_errno);
                   1362: }
1.84      christos 1363:

CVSweb <webmaster@jp.NetBSD.org>