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

glibc/2.7/resolv/res_send.c

    1: /*
    2:  * Copyright (c) 1985, 1989, 1993
    3:  *    The Regents of the University of California.  All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer.
   10:  * 2. Redistributions in binary form must reproduce the above copyright
   11:  *    notice, this list of conditions and the following disclaimer in the
   12:  *    documentation and/or other materials provided with the distribution.
   13:  * 4. Neither the name of the University nor the names of its contributors
   14:  *    may be used to endorse or promote products derived from this software
   15:  *    without specific prior written permission.
   16:  *
   17:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27:  * SUCH DAMAGE.
   28:  */
   29: 
   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: 
   50: /*
   51:  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
   52:  *
   53:  * Permission to use, copy, modify, and distribute this software for any
   54:  * purpose with or without fee is hereby granted, provided that the above
   55:  * copyright notice and this permission notice appear in all copies.
   56:  *
   57:  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
   58:  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
   59:  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
   60:  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
   61:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
   62:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
   63:  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   64:  * SOFTWARE.
   65:  */
   66: 
   67: #if defined(LIBC_SCCS) && !defined(lint)
   68: static const char sccsid[] = "@(#)res_send.c    8.1 (Berkeley) 6/4/93";
   69: static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixie Exp $";
   70: #endif /* LIBC_SCCS and not lint */
   71: 
   72: /*
   73:  * Send query to name server and wait for reply.
   74:  */
   75: 
   76: #include <assert.h>
   77: #include <sys/types.h>
   78: #include <sys/param.h>
   79: #include <sys/time.h>
   80: #include <sys/socket.h>
   81: #include <sys/uio.h>
   82: #include <sys/poll.h>
   83: 
   84: #include <netinet/in.h>
   85: #include <arpa/nameser.h>
   86: #include <arpa/inet.h>
   87: #include <sys/ioctl.h>
   88: 
   89: #include <errno.h>
   90: #include <fcntl.h>
   91: #include <netdb.h>
   92: #include <resolv.h>
   93: #include <signal.h>
   94: #include <stdio.h>
   95: #include <stdlib.h>
   96: #include <string.h>
   97: #include <unistd.h>
   98: 
   99: #if PACKETSZ > 65536
  100: #define MAXPACKET       PACKETSZ
  101: #else
  102: #define MAXPACKET       65536
  103: #endif
  104: 
  105: 
  106: /* From ev_streams.c.  */
  107: 
  108: static inline void
  109: __attribute ((always_inline))
  110: evConsIovec(void *buf, size_t cnt, struct iovec *vec) {
  111:         memset(vec, 0xf5, sizeof (*vec));
  112:         vec->iov_base = buf;
  113:         vec->iov_len = cnt;
  114: }
  115: 
  116: /* From ev_timers.c.  */
  117: 
  118: #define BILLION 1000000000
  119: 
  120: static inline void
  121: evConsTime(struct timespec *res, time_t sec, long nsec) {
  122:         res->tv_sec = sec;
  123:         res->tv_nsec = nsec;
  124: }
  125: 
  126: static inline void
  127: evAddTime(struct timespec *res, const struct timespec *addend1,
  128:           const struct timespec *addend2) {
  129:         res->tv_sec = addend1->tv_sec + addend2->tv_sec;
  130:         res->tv_nsec = addend1->tv_nsec + addend2->tv_nsec;
  131:         if (res->tv_nsec >= BILLION) {
  132:                 res->tv_sec++;
  133:                 res->tv_nsec -= BILLION;
  134:         }
  135: }
  136: 
  137: static inline void
  138: evSubTime(struct timespec *res, const struct timespec *minuend,
  139:           const struct timespec *subtrahend) {
  140:        res->tv_sec = minuend->tv_sec - subtrahend->tv_sec;
  141:         if (minuend->tv_nsec >= subtrahend->tv_nsec)
  142:                 res->tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec;
  143:         else {
  144:                 res->tv_nsec = (BILLION
  145:                                 - subtrahend->tv_nsec + minuend->tv_nsec);
  146:                 res->tv_sec--;
  147:         }
  148: }
  149: 
  150: static inline int
  151: evCmpTime(struct timespec a, struct timespec b) {
  152:         long x = a.tv_sec - b.tv_sec;
  153: 
  154:         if (x == 0L)
  155:                 x = a.tv_nsec - b.tv_nsec;
  156:         return (x < 0L ? (-1) : x > 0L ? (1) : (0));
  157: }
  158: 
  159: static inline void
  160: evNowTime(struct timespec *res) {
  161:         struct timeval now;
  162: 
  163:         if (gettimeofday(&now, NULL) < 0)
  164:                 evConsTime(res, 0, 0);
  165:         else
  166:                 TIMEVAL_TO_TIMESPEC (&now, res);
  167: }
  168: 
  169: 
  170: /* Options.  Leave them on. */
  171: /* #undef DEBUG */
  172: #include "res_debug.h"
  173: 
  174: #define EXT(res) ((res)->_u._ext)
  175: 
  176: /* Forward. */
  177: 
  178: static int              send_vc(res_state, const u_char *, int,
  179:                                 u_char **, int *, int *, int, u_char **);
  180: static int              send_dg(res_state, const u_char *, int,
  181:                                 u_char **, int *, int *, int,
  182:                                 int *, int *, u_char **);
  183: #ifdef DEBUG
  184: static void             Aerror(const res_state, FILE *, const char *, int,
  185:                                const struct sockaddr *);
  186: static void             Perror(const res_state, FILE *, const char *, int);
  187: #endif
  188: static int              sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
  189: 
  190: /* Reachover. */
  191: 
  192: static void convaddr4to6(struct sockaddr_in6 *sa);
  193: void res_pquery(const res_state, const u_char *, int, FILE *);
  194: 
  195: /* Public. */
  196: 
  197: /* int
  198:  * res_isourserver(ina)
  199:  *      looks up "ina" in _res.ns_addr_list[]
  200:  * returns:
  201:  *      0  : not found
  202:  *      >0 : found
  203:  * author:
  204:  *      paul vixie, 29may94
  205:  */
  206: int
  207: res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
  208: {
  209:         int ns;
  210: 
  211:         if (inp->sin6_family == AF_INET) {
  212:             struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
  213:             in_port_t port = in4p->sin_port;
  214:             in_addr_t addr = in4p->sin_addr.s_addr;
  215: 
  216:             for (ns = 0;  ns < MAXNS;  ns++) {
  217:                 const struct sockaddr_in *srv =
  218:                     (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
  219: 
  220:                 if ((srv != NULL) && (srv->sin_family == AF_INET) &&
  221:                     (srv->sin_port == port) &&
  222:                     (srv->sin_addr.s_addr == INADDR_ANY ||
  223:                      srv->sin_addr.s_addr == addr))
  224:                     return (1);
  225:             }
  226:         } else if (inp->sin6_family == AF_INET6) {
  227:             for (ns = 0;  ns < MAXNS;  ns++) {
  228:                 const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
  229:                 if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
  230:                     (srv->sin6_port == inp->sin6_port) &&
  231:                     !(memcmp(&srv->sin6_addr, &in6addr_any,
  232:                              sizeof (struct in6_addr)) &&
  233:                       memcmp(&srv->sin6_addr, &inp->sin6_addr,
  234:                              sizeof (struct in6_addr))))
  235:                     return (1);
  236:             }
  237:         }
  238:         return (0);
  239: }
  240: 
  241: /* int
  242:  * res_nameinquery(name, type, class, buf, eom)
  243:  *      look for (name,type,class) in the query section of packet (buf,eom)
  244:  * requires:
  245:  *      buf + HFIXEDSZ <= eom
  246:  * returns:
  247:  *      -1 : format error
  248:  *      0  : not found
  249:  *      >0 : found
  250:  * author:
  251:  *      paul vixie, 29may94
  252:  */
  253: int
  254: res_nameinquery(const char *name, int type, int class,
  255:                 const u_char *buf, const u_char *eom)
  256: {
  257:         const u_char *cp = buf + HFIXEDSZ;
  258:         int qdcount = ntohs(((HEADER*)buf)->qdcount);
  259: 
  260:         while (qdcount-- > 0) {
  261:                 char tname[MAXDNAME+1];
  262:                 int n, ttype, tclass;
  263: 
  264:                 n = dn_expand(buf, eom, cp, tname, sizeof tname);
  265:                 if (n < 0)
  266:                         return (-1);
  267:                 cp += n;
  268:                 if (cp + 2 * INT16SZ > eom)
  269:                         return (-1);
  270:                 NS_GET16(ttype, cp);
  271:                 NS_GET16(tclass, cp);
  272:                 if (ttype == type && tclass == class &&
  273:                     ns_samename(tname, name) == 1)
  274:                         return (1);
  275:         }
  276:         return (0);
  277: }
  278: libresolv_hidden_def (res_nameinquery)
  279: 
  280: /* int
  281:  * res_queriesmatch(buf1, eom1, buf2, eom2)
  282:  *      is there a 1:1 mapping of (name,type,class)
  283:  *      in (buf1,eom1) and (buf2,eom2)?
  284:  * returns:
  285:  *      -1 : format error
  286:  *      0  : not a 1:1 mapping
  287:  *      >0 : is a 1:1 mapping
  288:  * author:
  289:  *      paul vixie, 29may94
  290:  */
  291: int
  292: res_queriesmatch(const u_char *buf1, const u_char *eom1,
  293:                  const u_char *buf2, const u_char *eom2)
  294: {
  295:         if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
  296:                 return (-1);
  297: 
  298:         /*
  299:          * Only header section present in replies to
  300:          * dynamic update packets.
  301:          */
  302:         if ((((HEADER *)buf1)->opcode == ns_o_update) &&
  303:             (((HEADER *)buf2)->opcode == ns_o_update))
  304:                 return (1);
  305: 
  306:         /* Note that we initially do not convert QDCOUNT to the host byte
  307:            order.  We can compare it with the second buffer's QDCOUNT
  308:            value without doing this.  */
  309:         int qdcount = ((HEADER*)buf1)->qdcount;
  310:         if (qdcount != ((HEADER*)buf2)->qdcount)
  311:                 return (0);
  312: 
  313:         qdcount = htons (qdcount);
  314:         const u_char *cp = buf1 + HFIXEDSZ;
  315: 
  316:         while (qdcount-- > 0) {
  317:                 char tname[MAXDNAME+1];
  318:                 int n, ttype, tclass;
  319: 
  320:                 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
  321:                 if (n < 0)
  322:                         return (-1);
  323:                 cp += n;
  324:                 if (cp + 2 * INT16SZ > eom1)
  325:                         return (-1);
  326:                 NS_GET16(ttype, cp);
  327:                 NS_GET16(tclass, cp);
  328:                 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
  329:                         return (0);
  330:         }
  331:         return (1);
  332: }
  333: libresolv_hidden_def (res_queriesmatch)
  334: 
  335: int
  336: __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
  337:                  u_char *ans, int anssiz, u_char **ansp)
  338: {
  339:         int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
  340: 
  341:         if (statp->nscount == 0) {
  342:                 __set_errno (ESRCH);
  343:                 return (-1);
  344:         }
  345: 
  346:         if (anssiz < HFIXEDSZ) {
  347:                 __set_errno (EINVAL);
  348:                 return (-1);
  349:         }
  350: 
  351:         if ((statp->qhook || statp->rhook) && anssiz < MAXPACKET && ansp) {
  352:                 u_char *buf = malloc (MAXPACKET);
  353:                 if (buf == NULL)
  354:                         return (-1);
  355:                 memcpy (buf, ans, HFIXEDSZ);
  356:                 *ansp = buf;
  357:                 ans = buf;
  358:                 anssiz = MAXPACKET;
  359:         }
  360: 
  361:         DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
  362:                 (stdout, ";; res_send()\n"), buf, buflen);
  363:         v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
  364:         gotsomewhere = 0;
  365:         terrno = ETIMEDOUT;
  366: 
  367:         /*
  368:          * If the ns_addr_list in the resolver context has changed, then
  369:          * invalidate our cached copy and the associated timing data.
  370:          */
  371:         if (EXT(statp).nsinit) {
  372:                 int needclose = 0;
  373: 
  374:                 if (EXT(statp).nscount != statp->nscount)
  375:                         needclose++;
  376:                 else
  377:                         for (ns = 0; ns < MAXNS; ns++) {
  378:                                 unsigned int map = EXT(statp).nsmap[ns];
  379:                                 if (map < MAXNS
  380:                                     && !sock_eq((struct sockaddr_in6 *)
  381:                                                 &statp->nsaddr_list[map],
  382:                                                 EXT(statp).nsaddrs[ns]))
  383:                                 {
  384:                                         needclose++;
  385:                                         break;
  386:                                 }
  387:                         }
  388:                 if (needclose)
  389:                         __res_iclose(statp, false);
  390:         }
  391: 
  392:         /*
  393:          * Maybe initialize our private copy of the ns_addr_list.
  394:          */
  395:         if (EXT(statp).nsinit == 0) {
  396:                 unsigned char map[MAXNS];
  397: 
  398:                 memset (map, MAXNS, sizeof (map));
  399:                 for (n = 0; n < MAXNS; n++) {
  400:                         ns = EXT(statp).nsmap[n];
  401:                         if (ns < statp->nscount)
  402:                                 map[ns] = n;
  403:                         else if (ns < MAXNS) {
  404:                                 free(EXT(statp).nsaddrs[n]);
  405:                                 EXT(statp).nsaddrs[n] = NULL;
  406:                                 EXT(statp).nsmap[n] = MAXNS;
  407:                         }
  408:                 }
  409:                 n = statp->nscount;
  410:                 if (statp->nscount > EXT(statp).nscount)
  411:                         for (n = EXT(statp).nscount, ns = 0;
  412:                              n < statp->nscount; n++) {
  413:                                 while (ns < MAXNS
  414:                                        && EXT(statp).nsmap[ns] != MAXNS)
  415:                                         ns++;
  416:                                 if (ns == MAXNS)
  417:                                         break;
  418:                                 EXT(statp).nsmap[ns] = n;
  419:                                 map[n] = ns++;
  420:                         }
  421:                 EXT(statp).nscount = n;
  422:                 for (ns = 0; ns < EXT(statp).nscount; ns++) {
  423:                         n = map[ns];
  424:                         if (EXT(statp).nsaddrs[n] == NULL)
  425:                                 EXT(statp).nsaddrs[n] =
  426:                                     malloc(sizeof (struct sockaddr_in6));
  427:                         if (EXT(statp).nsaddrs[n] != NULL) {
  428:                                 memset (mempcpy(EXT(statp).nsaddrs[n],
  429:                                                 &statp->nsaddr_list[ns],
  430:                                                 sizeof (struct sockaddr_in)),
  431:                                         '\0',
  432:                                         sizeof (struct sockaddr_in6)
  433:                                         - sizeof (struct sockaddr_in));
  434:                                 EXT(statp).nssocks[n] = -1;
  435:                                 n++;
  436:                         }
  437:                 }
  438:                 EXT(statp).nsinit = 1;
  439:         }
  440: 
  441:         /*
  442:          * Some resolvers want to even out the load on their nameservers.
  443:          * Note that RES_BLAST overrides RES_ROTATE.
  444:          */
  445:         if ((statp->options & RES_ROTATE) != 0 &&
  446:             (statp->options & RES_BLAST) == 0) {
  447:                 struct sockaddr_in6 *ina;
  448:                 unsigned int map;
  449: 
  450:                 n = 0;
  451:                 while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
  452:                         n++;
  453:                 if (n < MAXNS) {
  454:                         ina = EXT(statp).nsaddrs[n];
  455:                         map = EXT(statp).nsmap[n];
  456:                         for (;;) {
  457:                                 ns = n + 1;
  458:                                 while (ns < MAXNS
  459:                                        && EXT(statp).nsmap[ns] == MAXNS)
  460:                                         ns++;
  461:                                 if (ns == MAXNS)
  462:                                         break;
  463:                                 EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
  464:                                 EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
  465:                                 n = ns;
  466:                         }
  467:                         EXT(statp).nsaddrs[n] = ina;
  468:                         EXT(statp).nsmap[n] = map;
  469:                 }
  470:         }
  471: 
  472:         /*
  473:          * Send request, RETRY times, or until successful.
  474:          */
  475:         for (try = 0; try < statp->retry; try++) {
  476:             for (ns = 0; ns < MAXNS; ns++)
  477:             {
  478:                 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
  479: 
  480:                 if (nsap == NULL)
  481:                         goto next_ns;
  482:  same_ns:
  483:                 if (statp->qhook) {
  484:                         int done = 0, loops = 0;
  485: 
  486:                         do {
  487:                                 res_sendhookact act;
  488: 
  489:                                 struct sockaddr_in *nsap4;
  490:                                 nsap4 = (struct sockaddr_in *) nsap;
  491:                                 act = (*statp->qhook)(&nsap4, &buf, &buflen,
  492:                                                       ans, anssiz, &resplen);
  493:                                 nsap = (struct sockaddr_in6 *) nsap4;
  494:                                 switch (act) {
  495:                                 case res_goahead:
  496:                                         done = 1;
  497:                                         break;
  498:                                 case res_nextns:
  499:                                         __res_iclose(statp, false);
  500:                                         goto next_ns;
  501:                                 case res_done:
  502:                                         return (resplen);
  503:                                 case res_modified:
  504:                                         /* give the hook another try */
  505:                                         if (++loops < 42) /*doug adams*/
  506:                                                 break;
  507:                                         /*FALLTHROUGH*/
  508:                                 case res_error:
  509:                                         /*FALLTHROUGH*/
  510:                                 default:
  511:                                         return (-1);
  512:                                 }
  513:                         } while (!done);
  514:                 }
  515: 
  516: #ifdef DEBUG
  517:                 char tmpbuf[40];
  518: #endif
  519:                 Dprint(statp->options & RES_DEBUG,
  520:                        (stdout, ";; Querying server (# %d) address = %s\n",
  521:                         ns + 1, inet_ntop(AF_INET6, &nsap->sin6_addr,
  522:                                           tmpbuf, sizeof (tmpbuf))));
  523: 
  524:                 if (v_circuit) {
  525:                         /* Use VC; at most one attempt per server. */
  526:                         try = statp->retry;
  527:                         n = send_vc(statp, buf, buflen, &ans, &anssiz, &terrno,
  528:                                     ns, ansp);
  529:                         if (n < 0)
  530:                                 return (-1);
  531:                         if (n == 0)
  532:                                 goto next_ns;
  533:                         resplen = n;
  534: