(linenum→info "unix/slp.c:2238")

glibc/2.7/resolv/gethnamaddr.c

    1: /*
    2:  * ++Copyright++ 1985, 1988, 1993
    3:  * -
    4:  * Copyright (c) 1985, 1988, 1993
    5:  *    The Regents of the University of California.  All rights reserved.
    6:  *
    7:  * Redistribution and use in source and binary forms, with or without
    8:  * modification, are permitted provided that the following conditions
    9:  * are met:
   10:  * 1. Redistributions of source code must retain the above copyright
   11:  *    notice, this list of conditions and the following disclaimer.
   12:  * 2. Redistributions in binary form must reproduce the above copyright
   13:  *    notice, this list of conditions and the following disclaimer in the
   14:  *    documentation and/or other materials provided with the distribution.
   15:  * 4. Neither the name of the University nor the names of its contributors
   16:  *    may be used to endorse or promote products derived from this software
   17:  *    without specific prior written permission.
   18:  *
   19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29:  * SUCH DAMAGE.
   30:  * -
   31:  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
   32:  *
   33:  * Permission to use, copy, modify, and distribute this software for any
   34:  * purpose with or without fee is hereby granted, provided that the above
   35:  * copyright notice and this permission notice appear in all copies, and that
   36:  * the name of Digital Equipment Corporation not be used in advertising or
   37:  * publicity pertaining to distribution of the document or software without
   38:  * specific, written prior permission.
   39:  *
   40:  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
   41:  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
   42:  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
   43:  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
   44:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
   45:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
   46:  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   47:  * SOFTWARE.
   48:  * -
   49:  * --Copyright--
   50:  */
   51: 
   52: #if defined(LIBC_SCCS) && !defined(lint)
   53: static char sccsid[] = "@(#)gethostnamadr.c     8.1 (Berkeley) 6/4/93";
   54: #endif /* LIBC_SCCS and not lint */
   55: 
   56: #include <sys/types.h>
   57: #include <sys/param.h>
   58: #include <sys/socket.h>
   59: #include <netinet/in.h>
   60: #include <arpa/inet.h>
   61: #include <arpa/nameser.h>
   62: 
   63: #include <stdio.h>
   64: #include <netdb.h>
   65: #include <resolv.h>
   66: #include <ctype.h>
   67: #include <errno.h>
   68: #include <syslog.h>
   69: 
   70: #define RESOLVSORT
   71: 
   72: #ifndef LOG_AUTH
   73: # define LOG_AUTH 0
   74: #endif
   75: 
   76: #define MULTI_PTRS_ARE_ALIASES 1        /* XXX - experimental */
   77: 
   78: #if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
   79: # include <stdlib.h>
   80: # include <string.h>
   81: #else
   82: # include "../conf/portability.h"
   83: #endif
   84: 
   85: #if defined(USE_OPTIONS_H)
   86: # include <../conf/options.h>
   87: #endif
   88: 
   89: #ifdef SPRINTF_CHAR
   90: # define SPRINTF(x) strlen(sprintf/**/x)
   91: #else
   92: # define SPRINTF(x) ((size_t)sprintf x)
   93: #endif
   94: 
   95: #define MAXALIASES      35
   96: #define MAXADDRS        35
   97: 
   98: static const char AskedForGot[] =
   99:                           "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
  100: 
  101: static char *h_addr_ptrs[MAXADDRS + 1];
  102: 
  103: static struct hostent host;
  104: static char *host_aliases[MAXALIASES];
  105: static char hostbuf[8*1024];
  106: static u_char host_addr[16];    /* IPv4 or IPv6 */
  107: static FILE *hostf = NULL;
  108: static int stayopen = 0;
  109: 
  110: static void map_v4v6_address (const char *src, char *dst) __THROW;
  111: static void map_v4v6_hostent (struct hostent *hp, char **bp, int *len) __THROW;
  112: 
  113: #ifdef RESOLVSORT
  114: extern void addrsort (char **, int) __THROW;
  115: #endif
  116: 
  117: #if PACKETSZ > 65536
  118: #define MAXPACKET       PACKETSZ
  119: #else
  120: #define MAXPACKET       65536
  121: #endif
  122: 
  123: /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length.  */
  124: #ifdef MAXHOSTNAMELEN
  125: # undef MAXHOSTNAMELEN
  126: #endif
  127: #define MAXHOSTNAMELEN 256
  128: 
  129: typedef union {
  130:     HEADER hdr;
  131:     u_char buf[MAXPACKET];
  132: } querybuf;
  133: 
  134: typedef union {
  135:     int32_t al;
  136:     char ac;
  137: } align;
  138: 
  139: #ifndef h_errno
  140: extern int h_errno;
  141: #endif
  142: 
  143: #ifdef DEBUG
  144: static void
  145: Dprintf(msg, num)
  146:         char *msg;
  147:         int num;
  148: {
  149:         if (_res.options & RES_DEBUG) {
  150:                 int save = errno;
  151: 
  152:                 printf(msg, num);
  153:                 __set_errno (save);
  154:         }
  155: }
  156: #else
  157: # define Dprintf(msg, num) /*nada*/
  158: #endif
  159: 
  160: #define BOUNDED_INCR(x) \
  161:         do { \
  162:                 cp += x; \
  163:                 if (cp > eom) { \
  164:                         __set_h_errno (NO_RECOVERY); \
  165:                         return (NULL); \
  166:                 } \
  167:         } while (0)
  168: 
  169: #define BOUNDS_CHECK(ptr, count) \
  170:         do { \
  171:                 if ((ptr) + (count) > eom) { \
  172:                         __set_h_errno (NO_RECOVERY); \
  173:                         return (NULL); \
  174:                 } \
  175:         } while (0)
  176: 
  177: 
  178: static struct hostent *
  179: getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
  180: {
  181:         register const HEADER *hp;
  182:         register const u_char *cp;
  183:         register int n;
  184:         const u_char *eom, *erdata;
  185:         char *bp, **ap, **hap;
  186:         int type, class, buflen, ancount, qdcount;
  187:         int haveanswer, had_error;
  188:         int toobig = 0;
  189:         char tbuf[MAXDNAME];
  190:         const char *tname;
  191:         int (*name_ok) (const char *);
  192: 
  193:         tname = qname;
  194:         host.h_name = NULL;
  195:         eom = answer->buf + anslen;
  196:         switch (qtype) {
  197:         case T_A:
  198:         case T_AAAA:
  199:                 name_ok = res_hnok;
  200:                 break;
  201:         case T_PTR:
  202:                 name_ok = res_dnok;
  203:                 break;
  204:         default:
  205:                 return (NULL);        /* XXX should be abort(); */
  206:         }
  207:         /*
  208:          * find first satisfactory answer
  209:          */
  210:         hp = &answer->hdr;
  211:         ancount = ntohs(hp->ancount);
  212:         qdcount = ntohs(hp->qdcount);
  213:         bp = hostbuf;
  214:         buflen = sizeof hostbuf;
  215:         cp = answer->buf;
  216:         BOUNDED_INCR(HFIXEDSZ);
  217:         if (qdcount != 1) {
  218:                 __set_h_errno (NO_RECOVERY);
  219:                 return (NULL);
  220:         }
  221:         n = dn_expand(answer->buf, eom, cp, bp, buflen);
  222:         if ((n < 0) || !(*name_ok)(bp)) {
  223:                 __set_h_errno (NO_RECOVERY);
  224:                 return (NULL);
  225:         }
  226:         BOUNDED_INCR(n + QFIXEDSZ);
  227:         if (qtype == T_A || qtype == T_AAAA) {
  228:                 /* res_send() has already verified that the query name is the
  229:                  * same as the one we sent; this just gets the expanded name
  230:                  * (i.e., with the succeeding search-domain tacked on).
  231:                  */
  232:                 n = strlen(bp) + 1;           /* for the \0 */
  233:                 if (n >= MAXHOSTNAMELEN) {
  234:                         __set_h_errno (NO_RECOVERY);
  235:                         return (NULL);
  236:                 }
  237:                 host.h_name = bp;
  238:                 bp += n;
  239:                 buflen -= n;
  240:                 /* The qname can be abbreviated, but h_name is now absolute. */
  241:                 qname = host.h_name;
  242:         }
  243:         ap = host_aliases;
  244:         *ap = NULL;
  245:         host.h_aliases = host_aliases;
  246:         hap = h_addr_ptrs;
  247:         *hap = NULL;
  248:         host.h_addr_list = h_addr_ptrs;
  249:         haveanswer = 0;
  250:         had_error = 0;
  251:         while (ancount-- > 0 && cp < eom && !had_error) {
  252:                 n = dn_expand(answer->buf, eom, cp, bp, buflen);
  253:                 if ((n < 0) || !(*name_ok)(bp)) {
  254:                         had_error++;
  255:                         continue;
  256:                 }
  257:                 cp += n;                      /* name */
  258:                 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
  259:                 type = ns_get16(cp);
  260:                 cp += INT16SZ;                        /* type */
  261:                 class = ns_get16(cp);
  262:                 cp += INT16SZ + INT32SZ;      /* class, TTL */
  263:                 n = ns_get16(cp);
  264:                 cp += INT16SZ;                        /* len */
  265:                 BOUNDS_CHECK(cp, n);
  266:                 erdata = cp + n;
  267:                 if (class != C_IN) {
  268:                         /* XXX - debug? syslog? */
  269:                         cp += n;
  270:                         continue;            /* XXX - had_error++ ? */
  271:                 }
  272:                 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
  273:                         if (ap >= &host_aliases[MAXALIASES-1])
  274:                                 continue;
  275:                         n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
  276:                         if ((n < 0) || !(*name_ok)(tbuf)) {
  277:                                 had_error++;
  278:                                 continue;
  279:                         }
  280:                         cp += n;
  281:                         if (cp != erdata) {
  282:                                 __set_h_errno (NO_RECOVERY);
  283:                                 return (NULL);
  284:                         }
  285:                         /* Store alias. */
  286:                         *ap++ = bp;
  287:                         n = strlen(bp) + 1;  /* for the \0 */
  288:                         if (n >= MAXHOSTNAMELEN) {
  289:                                 had_error++;
  290:                                 continue;
  291:                         }
  292:                         bp += n;
  293:                         buflen -= n;
  294:                         /* Get canonical name. */
  295:                         n = strlen(tbuf) + 1;        /* for the \0 */
  296:                         if (n > buflen || n >= MAXHOSTNAMELEN) {
  297:                                 had_error++;
  298:                                 continue;
  299:                         }
  300:                         strcpy(bp, tbuf);
  301:                         host.h_name = bp;
  302:                         bp += n;
  303:                         buflen -= n;
  304:                         continue;
  305:                 }
  306:                 if (qtype == T_PTR && type == T_CNAME) {
  307:                         n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
  308:                         if (n < 0 || !res_dnok(tbuf)) {
  309:                                 had_error++;
  310:                                 continue;
  311:                         }
  312:                         cp += n;
  313:                         if (cp != erdata) {
  314:                                 __set_h_errno (NO_RECOVERY);
  315:                                 return (NULL);
  316:                         }
  317:                         /* Get canonical name. */
  318:                         n = strlen(tbuf) + 1;        /* for the \0 */
  319:                         if (n > buflen || n >= MAXHOSTNAMELEN) {
  320:                                 had_error++;
  321:                                 continue;
  322:                         }
  323:                         strcpy(bp, tbuf);
  324:                         tname = bp;
  325:                         bp += n;
  326:                         buflen -= n;
  327:                         continue;
  328:                 }
  329:                 if ((type == T_SIG) || (type == T_KEY) || (type == T_NXT)) {
  330:                         /* We don't support DNSSEC yet.  For now, ignore
  331:                          * the record and send a low priority message
  332:                          * to syslog.
  333:                          */
  334:                         syslog(LOG_DEBUG|LOG_AUTH,
  335:                "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
  336:                                qname, p_class(C_IN), p_type(qtype),
  337:                                p_type(type));
  338:                         cp += n;
  339:                         continue;
  340:                 }
  341:                 if (type != qtype) {
  342:                         syslog(LOG_NOTICE|LOG_AUTH,
  343:                "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
  344:                                qname, p_class(C_IN), p_type(qtype),
  345:                                p_type(type));
  346:                         cp += n;
  347:                         continue;            /* XXX - had_error++ ? */
  348:                 }
  349:                 switch (type) {
  350:                 case T_PTR:
  351:                         if (strcasecmp(tname, bp) != 0) {
  352:                                 syslog(LOG_NOTICE|LOG_AUTH,
  353:                                        AskedForGot, qname, bp);
  354:                                 cp += n;
  355:                                 continue;   /* XXX - had_error++ ? */
  356:                         }
  357:                         n = dn_expand(answer->buf, eom, cp, bp, buflen);
  358:                         if ((n < 0) || !res_hnok(bp)) {
  359:                                 had_error++;
  360:                                 break;
  361:                         }
  362: #if MULTI_PTRS_ARE_ALIASES
  363:                         cp += n;
  364:                         if (cp != erdata) {
  365:                                 __set_h_errno (NO_RECOVERY);
  366:                                 return (NULL);
  367:                         }
  368:                         if (!haveanswer)
  369:                                 host.h_name = bp;
  370:                         else if (ap < &host_aliases[MAXALIASES-1])
  371:                                 *ap++ = bp;
  372:                         else
  373:                                 n = -1;
  374:                         if (n != -1) {
  375:                                 n = strlen(bp) + 1; /* for the \0 */
  376:                                 if (n >= MAXHOSTNAMELEN) {
  377:                                         had_error++;
  378:                                         break;
  379:                                 }
  380:                                 bp += n;
  381:                                 buflen -= n;
  382:                         }
  383:                         break;
  384: #else
  385:                         host.h_name = bp;
  386:                         if (_res.options & RES_USE_INET6) {
  387:                                 n = strlen(bp) + 1; /* for the \0 */
  388:                                 if (n >= MAXHOSTNAMELEN) {
  389:                                         had_error++;
  390:                                         break;
  391:                                 }
  392:                                 bp += n;
  393:                                 buflen -= n;
  394:                                 map_v4v6_hostent(&host, &bp, &buflen);
  395:                         }
  396:                         __set_h_errno (NETDB_SUCCESS);
  397:                         return (&host);
  398: #endif
  399:                 case T_A:
  400:                 case T_AAAA:
  401:                         if (strcasecmp(host.h_name, bp) != 0) {
  402:                                 syslog(LOG_NOTICE|LOG_AUTH,
  403:                                        AskedForGot, host.h_name, bp);
  404:                                 cp += n;
  405:                                 continue;   /* XXX - had_error++ ? */
  406:                         }
  407:                         if (n != host.h_length) {
  408:                                 cp += n;
  409:                                 continue;
  410:                         }
  411:                         if (!haveanswer) {
  412:                                 register int nn;
  413: 
  414:                                 host.h_name = bp;
  415:                                 nn = strlen(bp) + 1;        /* for the \0 */
  416:                                 bp += nn;
  417:                                 buflen -= nn;
  418:                         }
  419: 
  420:                         /* XXX: when incrementing bp, we have to decrement
  421:                          * buflen by the same amount --okir */
  422:                         buflen -= sizeof(align) - ((u_long)bp % sizeof(align));
  423: 
  424:                         bp += sizeof(align) - ((u_long)bp % sizeof(align));
  425: 
  426:                         if (bp + n >= &hostbuf[sizeof hostbuf]) {
  427:                                 Dprintf("size (%d) too big\n", n);
  428:                                 had_error++;
  429:                                 continue;
  430:                         }
  431:                         if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
  432:                                 if (!toobig++) {
  433:                                         Dprintf("Too many addresses (%d)\n",
  434:                                                 MAXADDRS);
  435:                                 }
  436:                                 cp += n;
  437:                                 continue;
  438:                         }
  439:                         memmove(*hap++ = bp, cp, n);
  440:                         bp += n;
  441:                         buflen -= n;
  442:                         cp += n;
  443:                         if (cp != erdata) {
  444:                                 __set_h_errno (NO_RECOVERY);
  445:                                 return (NULL);
  446:                         }
  447:                         break;
  448:                 default:
  449:                         abort();
  450:                 }
  451:                 if (!had_error)
  452:                         haveanswer++;
  453:         }
  454:         if (haveanswer) {
  455:                 *ap = NULL;
  456:                 *hap = NULL;
  457: # if defined(RESOLVSORT)
  458:                 /*
  459:                  * Note: we sort even if host can take only one address
  460:                  * in its return structures - should give it the "best"
  461:                  * address in that case, not some random one
  462:                  */
  463:                 if (_res.nsort && haveanswer > 1 && qtype == T_A)
  464:                         addrsort(h_addr_ptrs, haveanswer);
  465: # endif /*RESOLVSORT*/
  466:                 if (!host.h_name) {
  467:                         n = strlen(qname) + 1;       /* for the \0 */
  468:                         if (n > buflen || n >= MAXHOSTNAMELEN)
  469:                                 goto no_recovery;
  470:                         strcpy(bp, qname);
  471:                         host.h_name = bp;
  472:                         bp += n;
  473:                         buflen -= n;
  474:                 }
  475:                 if (_res.options & RES_USE_INET6)
  476:                         map_v4v6_hostent(&host, &bp, &buflen);
  477:                 __set_h_errno (NETDB_SUCCESS);
  478:                 return (&host);
  479:         }
  480:  no_recovery:
  481:         __set_h_errno (NO_RECOVERY);
  482:         return (NULL);
  483: }
  484: 
  485: extern struct hostent *gethostbyname2(const char *name, int af);
  486: libresolv_hidden_proto (gethostbyname2)
  487: 
  488: struct hostent *
  489: gethostbyname(name)
  490:         const char *name;
  491: {
  492:         struct hostent *hp;
  493: 
  494:         if (__res_maybe_init (&_res, 0) == -1) {
  495:                 __set_h_errno (NETDB_INTERNAL);
  496:                 return (NULL);
  497:         }
  498:         if (_res.options & RES_USE_INET6) {
  499:                 hp = gethostbyname2(name, AF_INET6);
  500:                 if (hp)
  501:                         return (hp);
  502:         }
  503:         return (gethostbyname2(name, AF_INET));
  504: }
  505: 
  506: struct hostent *
  507: gethostbyname2(name, af)
  508:         const char *name;
  509:         int af;
  510: {
  511:         union
  512:         {
  513:           querybuf *buf;
  514:           u_char *ptr;
  515:         } buf;
  516:         querybuf *origbuf;
  517:         register const char *cp;
  518:         char *bp;
  519:         int n, size, type, len;
  520:         struct hostent *ret;
  521: 
  522:         if (__res_maybe_init (&_res, 0) == -1) {
  523:                 __set_h_errno (NETDB_INTERNAL);
  524:                 return (NULL);
  525:         }
  526: 
  527:         switch (af) {
  528:         case AF_INET:
  529:                 size = INADDRSZ;
  530:                 type = T_A;
  531:                 break;
  532:         case AF_INET6:
  533:                 size = IN6ADDRSZ;
  534:                 type = T_AAAA;
  535:                 break;
  536:         default:
  537:                 __set_h_errno (NETDB_INTERNAL);
  538:                 __set_errno (EAFNOSUPPORT);
  539:                 return (NULL);
  540:         }
  541: 
  542:         host.h_addrtype = af;
  543:         host.h_length = size;
  544: