source: rtems-libbsd/freebsd/lib/libc/resolv/res_send.c

6-freebsd-12
Last change on this file was 18fa92c, checked in by Sebastian Huber <sebastian.huber@…>, on 08/20/18 at 13:53:03

Update to FreeBSD head 2018-02-01

Git mirror commit d079ae0442af8fa3cfd6d7ede190d04e64a2c0d4.

Update #3472.

  • Property mode set to 100644
File size: 29.8 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*-
4 * SPDX-License-Identifier: (ISC AND BSD-3-Clause)
5 *
6 * Portions Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
7 * Portions Copyright (C) 1996-2003  Internet Software Consortium.
8 *
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
14 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
16 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
18 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * Copyright (c) 1985, 1989, 1993
24 *    The Regents of the University of California.  All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 *    notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 *    notice, this list of conditions and the following disclaimer in the
33 *    documentation and/or other materials provided with the distribution.
34 * 3. Neither the name of the University nor the names of its contributors
35 *    may be used to endorse or promote products derived from this software
36 *    without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 */
50
51/*
52 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
53 *
54 * Permission to use, copy, modify, and distribute this software for any
55 * purpose with or without fee is hereby granted, provided that the above
56 * copyright notice and this permission notice appear in all copies, and that
57 * the name of Digital Equipment Corporation not be used in advertising or
58 * publicity pertaining to distribution of the document or software without
59 * specific, written prior permission.
60 *
61 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
62 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
63 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
64 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
65 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
66 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
67 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
68 * SOFTWARE.
69 */
70
71#if defined(LIBC_SCCS) && !defined(lint)
72static const char sccsid[] = "@(#)res_send.c    8.1 (Berkeley) 6/4/93";
73static const char rcsid[] = "$Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp $";
74#endif /* LIBC_SCCS and not lint */
75#include <sys/cdefs.h>
76__FBSDID("$FreeBSD$");
77
78/*! \file
79 * \brief
80 * Send query to name server and wait for reply.
81 */
82
83#include "port_before.h"
84#if !defined(USE_KQUEUE) && !defined(USE_POLL)
85#include "fd_setsize.h"
86#endif
87
88#include "namespace.h"
89#include <sys/param.h>
90#include <sys/time.h>
91#include <sys/socket.h>
92#include <sys/uio.h>
93
94#include <netinet/in.h>
95#include <arpa/nameser.h>
96#include <arpa/inet.h>
97
98#include <errno.h>
99#include <netdb.h>
100#include <resolv.h>
101#include <signal.h>
102#include <stdio.h>
103#include <stdlib.h>
104#include <string.h>
105#include <unistd.h>
106
107#include <isc/eventlib.h>
108
109#include "port_after.h"
110
111#ifdef USE_KQUEUE
112#include <sys/event.h>
113#else
114#ifdef USE_POLL
115#ifdef HAVE_STROPTS_H
116#include <stropts.h>
117#endif
118#include <poll.h>
119#endif /* USE_POLL */
120#endif
121
122#include "un-namespace.h"
123
124/* Options.  Leave them on. */
125#ifndef DEBUG
126#define DEBUG
127#endif
128#include "res_debug.h"
129#include "res_private.h"
130
131#define EXT(res) ((res)->_u._ext)
132
133#if !defined(USE_POLL) && !defined(USE_KQUEUE)
134static const int highestFD = FD_SETSIZE - 1;
135#endif
136
137/* Forward. */
138
139static int              get_salen(const struct sockaddr *);
140static struct sockaddr * get_nsaddr(res_state, size_t);
141static int              send_vc(res_state, const u_char *, int,
142                                u_char *, int, int *, int);
143static int              send_dg(res_state,
144#ifdef USE_KQUEUE
145                                int kq,
146#endif
147                                const u_char *, int,
148                                u_char *, int, int *, int, int,
149                                int *, int *);
150static void             Aerror(const res_state, FILE *, const char *, int,
151                               const struct sockaddr *, int);
152static void             Perror(const res_state, FILE *, const char *, int);
153static int              sock_eq(struct sockaddr *, struct sockaddr *);
154#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
155static int              pselect(int, void *, void *, void *,
156                                struct timespec *,
157                                const sigset_t *);
158#endif
159void res_pquery(const res_state, const u_char *, int, FILE *);
160
161static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
162
163/* Public. */
164
165/*%
166 *      looks up "ina" in _res.ns_addr_list[]
167 *
168 * returns:
169 *\li   0  : not found
170 *\li   >0 : found
171 *
172 * author:
173 *\li   paul vixie, 29may94
174 */
175int
176res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
177        const struct sockaddr_in *inp, *srv;
178        const struct sockaddr_in6 *in6p, *srv6;
179        int ns;
180
181        switch (sa->sa_family) {
182        case AF_INET:
183                inp = (const struct sockaddr_in *)sa;
184                for (ns = 0;  ns < statp->nscount;  ns++) {
185                        srv = (struct sockaddr_in *)get_nsaddr(statp, ns);
186                        if (srv->sin_family == inp->sin_family &&
187                            srv->sin_port == inp->sin_port &&
188                            (srv->sin_addr.s_addr == INADDR_ANY ||
189                             srv->sin_addr.s_addr == inp->sin_addr.s_addr))
190                                return (1);
191                }
192                break;
193        case AF_INET6:
194                if (EXT(statp).ext == NULL)
195                        break;
196                in6p = (const struct sockaddr_in6 *)sa;
197                for (ns = 0;  ns < statp->nscount;  ns++) {
198                        srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns);
199                        if (srv6->sin6_family == in6p->sin6_family &&
200                            srv6->sin6_port == in6p->sin6_port &&
201#ifdef HAVE_SIN6_SCOPE_ID
202                            (srv6->sin6_scope_id == 0 ||
203                             srv6->sin6_scope_id == in6p->sin6_scope_id) &&
204#endif
205                            (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
206                             IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
207                                return (1);
208                }
209                break;
210        default:
211                break;
212        }
213        return (0);
214}
215
216/*%
217 *      look for (name,type,class) in the query section of packet (buf,eom)
218 *
219 * requires:
220 *\li   buf + HFIXEDSZ <= eom
221 *
222 * returns:
223 *\li   -1 : format error
224 *\li   0  : not found
225 *\li   >0 : found
226 *
227 * author:
228 *\li   paul vixie, 29may94
229 */
230int
231res_nameinquery(const char *name, int type, int class,
232                const u_char *buf, const u_char *eom)
233{
234        const u_char *cp = buf + HFIXEDSZ;
235        int qdcount = ntohs(((const HEADER*)buf)->qdcount);
236
237        while (qdcount-- > 0) {
238                char tname[MAXDNAME+1];
239                int n, ttype, tclass;
240
241                n = dn_expand(buf, eom, cp, tname, sizeof tname);
242                if (n < 0)
243                        return (-1);
244                cp += n;
245                if (cp + 2 * INT16SZ > eom)
246                        return (-1);
247                ttype = ns_get16(cp); cp += INT16SZ;
248                tclass = ns_get16(cp); cp += INT16SZ;
249                if (ttype == type && tclass == class &&
250                    ns_samename(tname, name) == 1)
251                        return (1);
252        }
253        return (0);
254}
255
256/*%
257 *      is there a 1:1 mapping of (name,type,class)
258 *      in (buf1,eom1) and (buf2,eom2)?
259 *
260 * returns:
261 *\li   -1 : format error
262 *\li   0  : not a 1:1 mapping
263 *\li   >0 : is a 1:1 mapping
264 *
265 * author:
266 *\li   paul vixie, 29may94
267 */
268int
269res_queriesmatch(const u_char *buf1, const u_char *eom1,
270                 const u_char *buf2, const u_char *eom2)
271{
272        const u_char *cp = buf1 + HFIXEDSZ;
273        int qdcount = ntohs(((const HEADER*)buf1)->qdcount);
274
275        if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
276                return (-1);
277
278        /*
279         * Only header section present in replies to
280         * dynamic update packets.
281         */
282        if ((((const HEADER *)buf1)->opcode == ns_o_update) &&
283            (((const HEADER *)buf2)->opcode == ns_o_update))
284                return (1);
285
286        if (qdcount != ntohs(((const HEADER*)buf2)->qdcount))
287                return (0);
288        while (qdcount-- > 0) {
289                char tname[MAXDNAME+1];
290                int n, ttype, tclass;
291
292                n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
293                if (n < 0)
294                        return (-1);
295                cp += n;
296                if (cp + 2 * INT16SZ > eom1)
297                        return (-1);
298                ttype = ns_get16(cp);   cp += INT16SZ;
299                tclass = ns_get16(cp); cp += INT16SZ;
300                if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
301                        return (0);
302        }
303        return (1);
304}
305
306int
307res_nsend(res_state statp,
308          const u_char *buf, int buflen, u_char *ans, int anssiz)
309{
310        int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
311#ifdef USE_KQUEUE
312        int kq;
313#endif
314        char abuf[NI_MAXHOST];
315
316        /* No name servers or res_init() failure */
317        if (statp->nscount == 0 || EXT(statp).ext == NULL) {
318                errno = ESRCH;
319                return (-1);
320        }
321        if (anssiz < HFIXEDSZ) {
322                errno = EINVAL;
323                return (-1);
324        }
325        DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
326                (stdout, ";; res_send()\n"), buf, buflen);
327        v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
328        gotsomewhere = 0;
329        terrno = ETIMEDOUT;
330
331#ifdef USE_KQUEUE
332        if ((kq = kqueue()) < 0) {
333                Perror(statp, stderr, "kqueue", errno);
334                return (-1);
335        }
336#endif
337
338        /*
339         * If the ns_addr_list in the resolver context has changed, then
340         * invalidate our cached copy and the associated timing data.
341         */
342        if (EXT(statp).nscount != 0) {
343                int needclose = 0;
344                struct sockaddr_storage peer;
345                ISC_SOCKLEN_T peerlen;
346
347                if (EXT(statp).nscount != statp->nscount)
348                        needclose++;
349                else
350                        for (ns = 0; ns < statp->nscount; ns++) {
351                                if (statp->nsaddr_list[ns].sin_family &&
352                                    !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns],
353                                             (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) {
354                                        needclose++;
355                                        break;
356                                }
357
358                                if (EXT(statp).nssocks[ns] == -1)
359                                        continue;
360                                peerlen = sizeof(peer);
361                                if (_getpeername(EXT(statp).nssocks[ns],
362                                    (struct sockaddr *)&peer, &peerlen) < 0) {
363                                        needclose++;
364                                        break;
365                                }
366                                if (!sock_eq((struct sockaddr *)&peer,
367                                    get_nsaddr(statp, ns))) {
368                                        needclose++;
369                                        break;
370                                }
371                        }
372                if (needclose) {
373                        res_nclose(statp);
374                        EXT(statp).nscount = 0;
375                }
376        }
377
378        /*
379         * Maybe initialize our private copy of the ns_addr_list.
380         */
381        if (EXT(statp).nscount == 0) {
382                for (ns = 0; ns < statp->nscount; ns++) {
383                        EXT(statp).nstimes[ns] = RES_MAXTIME;
384                        EXT(statp).nssocks[ns] = -1;
385                        if (!statp->nsaddr_list[ns].sin_family)
386                                continue;
387                        EXT(statp).ext->nsaddrs[ns].sin =
388                                 statp->nsaddr_list[ns];
389                }
390                EXT(statp).nscount = statp->nscount;
391        }
392
393        /*
394         * Some resolvers want to even out the load on their nameservers.
395         * Note that RES_BLAST overrides RES_ROTATE.
396         */
397        if ((statp->options & RES_ROTATE) != 0U &&
398            (statp->options & RES_BLAST) == 0U) {
399                union res_sockaddr_union inu;
400                struct sockaddr_in ina;
401                int lastns = statp->nscount - 1;
402                int fd;
403                u_int16_t nstime;
404
405                if (EXT(statp).ext != NULL)
406                        inu = EXT(statp).ext->nsaddrs[0];
407                ina = statp->nsaddr_list[0];
408                fd = EXT(statp).nssocks[0];
409                nstime = EXT(statp).nstimes[0];
410                for (ns = 0; ns < lastns; ns++) {
411                        if (EXT(statp).ext != NULL)
412                                EXT(statp).ext->nsaddrs[ns] =
413                                        EXT(statp).ext->nsaddrs[ns + 1];
414                        statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
415                        EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
416                        EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
417                }
418                if (EXT(statp).ext != NULL)
419                        EXT(statp).ext->nsaddrs[lastns] = inu;
420                statp->nsaddr_list[lastns] = ina;
421                EXT(statp).nssocks[lastns] = fd;
422                EXT(statp).nstimes[lastns] = nstime;
423        }
424
425        /*
426         * Send request, RETRY times, or until successful.
427         */
428        for (tries = 0; tries < statp->retry; tries++) {
429            for (ns = 0; ns < statp->nscount; ns++) {
430                struct sockaddr *nsap;
431                int nsaplen;
432                nsap = get_nsaddr(statp, ns);
433                nsaplen = get_salen(nsap);
434                statp->_flags &= ~RES_F_LASTMASK;
435                statp->_flags |= (ns << RES_F_LASTSHIFT);
436 same_ns:
437                if (statp->qhook) {
438                        int done = 0, loops = 0;
439
440                        do {
441                                res_sendhookact act;
442
443                                act = (*statp->qhook)(&nsap, &buf, &buflen,
444                                                      ans, anssiz, &resplen);
445                                switch (act) {
446                                case res_goahead:
447                                        done = 1;
448                                        break;
449                                case res_nextns:
450                                        res_nclose(statp);
451                                        goto next_ns;
452                                case res_done:
453#ifdef USE_KQUEUE
454                                        _close(kq);
455#endif
456                                        return (resplen);
457                                case res_modified:
458                                        /* give the hook another try */
459                                        if (++loops < 42) /*doug adams*/
460                                                break;
461                                        /*FALLTHROUGH*/
462                                case res_error:
463                                        /*FALLTHROUGH*/
464                                default:
465                                        goto fail;
466                                }
467                        } while (!done);
468                }
469
470                Dprint(((statp->options & RES_DEBUG) &&
471                        getnameinfo(nsap, nsaplen, abuf, sizeof(abuf),
472                                    NULL, 0, niflags) == 0),
473                       (stdout, ";; Querying server (# %d) address = %s\n",
474                        ns + 1, abuf));
475
476
477                if (v_circuit) {
478                        /* Use VC; at most one attempt per server. */
479                        tries = statp->retry;
480                        n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
481                                    ns);
482                        if (n < 0)
483                                goto fail;
484                        if (n == 0)
485                                goto next_ns;
486                        resplen = n;
487                } else {
488                        /* Use datagrams. */
489                        n = send_dg(statp,
490#ifdef USE_KQUEUE
491                                    kq,
492#endif
493                                    buf, buflen, ans, anssiz, &terrno,
494                                    ns, tries, &v_circuit, &gotsomewhere);
495                        if (n < 0)
496                                goto fail;
497                        if (n == 0)
498                                goto next_ns;
499                        if (v_circuit)
500                                goto same_ns;
501                        resplen = n;
502                }
503
504                Dprint((statp->options & RES_DEBUG) ||
505                       ((statp->pfcode & RES_PRF_REPLY) &&
506                        (statp->pfcode & RES_PRF_HEAD1)),
507                       (stdout, ";; got answer:\n"));
508
509                DprintQ((statp->options & RES_DEBUG) ||
510                        (statp->pfcode & RES_PRF_REPLY),
511                        (stdout, "%s", ""),
512                        ans, (resplen > anssiz) ? anssiz : resplen);
513
514                /*
515                 * If we have temporarily opened a virtual circuit,
516                 * or if we haven't been asked to keep a socket open,
517                 * close the socket.
518                 */
519                if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
520                    (statp->options & RES_STAYOPEN) == 0U) {
521                        res_nclose(statp);
522                }
523                if (statp->rhook) {
524                        int done = 0, loops = 0;
525
526                        do {
527                                res_sendhookact act;
528
529                                act = (*statp->rhook)(nsap, buf, buflen,
530                                                      ans, anssiz, &resplen);
531                                switch (act) {
532                                case res_goahead:
533                                case res_done:
534                                        done = 1;
535                                        break;
536                                case res_nextns:
537                                        res_nclose(statp);
538                                        goto next_ns;
539                                case res_modified:
540                                        /* give the hook another try */
541                                        if (++loops < 42) /*doug adams*/
542                                                break;
543                                        /*FALLTHROUGH*/
544                                case res_error:
545                                        /*FALLTHROUGH*/
546                                default:
547                                        goto fail;
548                                }
549                        } while (!done);
550
551                }
552#ifdef USE_KQUEUE
553                _close(kq);
554#endif
555                return (resplen);
556 next_ns: ;
557           } /*foreach ns*/
558        } /*foreach retry*/
559        res_nclose(statp);
560#ifdef USE_KQUEUE
561        _close(kq);
562#endif
563        if (!v_circuit) {
564                if (!gotsomewhere)
565                        errno = ECONNREFUSED;   /*%< no nameservers found */
566                else
567                        errno = ETIMEDOUT;      /*%< no answer obtained */
568        } else
569                errno = terrno;
570        return (-1);
571 fail:
572        res_nclose(statp);
573#ifdef USE_KQUEUE
574        _close(kq);
575#endif
576        return (-1);
577}
578
579/* Private */
580
581static int
582get_salen(const struct sockaddr *sa)
583{
584
585#ifdef HAVE_SA_LEN
586        /* There are people do not set sa_len.  Be forgiving to them. */
587        if (sa->sa_len)
588                return (sa->sa_len);
589#endif
590
591        if (sa->sa_family == AF_INET)
592                return (sizeof(struct sockaddr_in));
593        else if (sa->sa_family == AF_INET6)
594                return (sizeof(struct sockaddr_in6));
595        else
596                return (0);     /*%< unknown, die on connect */
597}
598
599/*%
600 * pick appropriate nsaddr_list for use.  see res_init() for initialization.
601 */
602static struct sockaddr *
603get_nsaddr(res_state statp, size_t n)
604{
605
606        if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
607                /*
608                 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
609                 *   than struct sockaddr, and
610                 * - user code did not update statp->nsaddr_list[n].
611                 */
612                return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
613        } else {
614                /*
615                 * - user code updated statp->nsaddr_list[n], or
616                 * - statp->nsaddr_list[n] has the same content as
617                 *   EXT(statp).ext->nsaddrs[n].
618                 */
619                return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
620        }
621}
622
623static int
624send_vc(res_state statp,
625        const u_char *buf, int buflen, u_char *ans, int anssiz,
626        int *terrno, int ns)
627{
628        const HEADER *hp = (const HEADER *) buf;
629        HEADER *anhp = (HEADER *) ans;
630        struct sockaddr *nsap;
631        int nsaplen;
632        int truncating, connreset, resplen, n;
633        struct iovec iov[2];
634        u_short len;
635        u_char *cp;
636        void *tmp;
637#ifdef SO_NOSIGPIPE
638        int on = 1;
639#endif
640
641        nsap = get_nsaddr(statp, ns);
642        nsaplen = get_salen(nsap);
643
644        connreset = 0;
645 same_ns:
646        truncating = 0;
647
648        /* Are we still talking to whom we want to talk to? */
649        if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
650                struct sockaddr_storage peer;
651                ISC_SOCKLEN_T size = sizeof peer;
652
653                if (_getpeername(statp->_vcsock,
654                                (struct sockaddr *)&peer, &size) < 0 ||
655                    !sock_eq((struct sockaddr *)&peer, nsap)) {
656                        res_nclose(statp);
657                        statp->_flags &= ~RES_F_VC;
658                }
659        }
660
661        if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
662                if (statp->_vcsock >= 0)
663                        res_nclose(statp);
664
665                statp->_vcsock = _socket(nsap->sa_family, SOCK_STREAM |
666                    SOCK_CLOEXEC, 0);
667#if !defined(USE_POLL) && !defined(USE_KQUEUE)
668                if (statp->_vcsock > highestFD) {
669                        res_nclose(statp);
670                        errno = ENOTSOCK;
671                }
672#endif
673                if (statp->_vcsock < 0) {
674                        switch (errno) {
675                        case EPROTONOSUPPORT:
676#ifdef EPFNOSUPPORT
677                        case EPFNOSUPPORT:
678#endif
679                        case EAFNOSUPPORT:
680                                Perror(statp, stderr, "socket(vc)", errno);
681                                return (0);
682                        default:
683                                *terrno = errno;
684                                Perror(statp, stderr, "socket(vc)", errno);
685                                return (-1);
686                        }
687                }
688#ifdef SO_NOSIGPIPE
689                /*
690                 * Disable generation of SIGPIPE when writing to a closed
691                 * socket.  Write should return -1 and set errno to EPIPE
692                 * instead.
693                 *
694                 * Push on even if setsockopt(SO_NOSIGPIPE) fails.
695                 */
696                (void)_setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
697                                 sizeof(on));
698#endif
699                errno = 0;
700                if (_connect(statp->_vcsock, nsap, nsaplen) < 0) {
701                        *terrno = errno;
702                        Aerror(statp, stderr, "connect/vc", errno, nsap,
703                            nsaplen);
704                        res_nclose(statp);
705                        return (0);
706                }
707                statp->_flags |= RES_F_VC;
708        }
709
710        /*
711         * Send length & message
712         */
713        ns_put16((u_short)buflen, (u_char*)&len);
714        iov[0] = evConsIovec(&len, INT16SZ);
715        DE_CONST(buf, tmp);
716        iov[1] = evConsIovec(tmp, buflen);
717        if (_writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
718                *terrno = errno;
719                Perror(statp, stderr, "write failed", errno);
720                res_nclose(statp);
721                return (0);
722        }
723        /*
724         * Receive length & response
725         */
726 read_len:
727        cp = ans;
728        len = INT16SZ;
729        while ((n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
730                cp += n;
731                if ((len -= n) == 0)
732                        break;
733        }
734        if (n <= 0) {
735                *terrno = errno;
736                Perror(statp, stderr, "read failed", errno);
737                res_nclose(statp);
738                /*
739                 * A long running process might get its TCP
740                 * connection reset if the remote server was
741                 * restarted.  Requery the server instead of
742                 * trying a new one.  When there is only one
743                 * server, this means that a query might work
744                 * instead of failing.  We only allow one reset
745                 * per query to prevent looping.
746                 */
747                if (*terrno == ECONNRESET && !connreset) {
748                        connreset = 1;
749                        res_nclose(statp);
750                        goto same_ns;
751                }
752                res_nclose(statp);
753                return (0);
754        }
755        resplen = ns_get16(ans);
756        if (resplen > anssiz) {
757                Dprint(statp->options & RES_DEBUG,
758                       (stdout, ";; response truncated\n")
759                       );
760                truncating = 1;
761                len = anssiz;
762        } else
763                len = resplen;
764        if (len < HFIXEDSZ) {
765                /*
766                 * Undersized message.
767                 */
768                Dprint(statp->options & RES_DEBUG,
769                       (stdout, ";; undersized: %d\n", len));
770                *terrno = EMSGSIZE;
771                res_nclose(statp);
772                return (0);
773        }
774        cp = ans;
775        while (len != 0 &&
776            (n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
777                cp += n;
778                len -= n;
779        }
780        if (n <= 0) {
781                *terrno = errno;
782                Perror(statp, stderr, "read(vc)", errno);
783                res_nclose(statp);
784                return (0);
785        }
786        if (truncating) {
787                /*
788                 * Flush rest of answer so connection stays in synch.
789                 */
790                anhp->tc = 1;
791                len = resplen - anssiz;
792                while (len != 0) {
793                        char junk[PACKETSZ];
794
795                        n = _read(statp->_vcsock, junk,
796                            (len > sizeof junk) ? sizeof junk : len);
797                        if (n > 0)
798                                len -= n;
799                        else
800                                break;
801                }
802        }
803        /*
804         * If the calling applicating has bailed out of
805         * a previous call and failed to arrange to have
806         * the circuit closed or the server has got
807         * itself confused, then drop the packet and
808         * wait for the correct one.
809         */
810        if (hp->id != anhp->id) {
811                DprintQ((statp->options & RES_DEBUG) ||
812                        (statp->pfcode & RES_PRF_REPLY),
813                        (stdout, ";; old answer (unexpected):\n"),
814                        ans, (resplen > anssiz) ? anssiz: resplen);
815                goto read_len;
816        }
817
818        /*
819         * All is well, or the error is fatal.  Signal that the
820         * next nameserver ought not be tried.
821         */
822        return (resplen);
823}
824
825static int
826send_dg(res_state statp,
827#ifdef USE_KQUEUE
828        int kq,
829#endif
830        const u_char *buf, int buflen, u_char *ans,
831        int anssiz, int *terrno, int ns, int tries, int *v_circuit,
832        int *gotsomewhere)
833{
834        const HEADER *hp = (const HEADER *) buf;
835        HEADER *anhp = (HEADER *) ans;
836        const struct sockaddr *nsap;
837        int nsaplen;
838        struct timespec now, timeout, finish;
839        struct sockaddr_storage from;
840        ISC_SOCKLEN_T fromlen;
841        int resplen, seconds, n, s;
842#ifdef USE_KQUEUE
843        struct kevent kv;
844#else
845#ifdef USE_POLL
846        int     polltimeout;
847        struct pollfd   pollfd;
848#else
849        fd_set dsmask;
850#endif
851#endif
852
853        nsap = get_nsaddr(statp, ns);
854        nsaplen = get_salen(nsap);
855        if (EXT(statp).nssocks[ns] == -1) {
856                EXT(statp).nssocks[ns] = _socket(nsap->sa_family,
857                    SOCK_DGRAM | SOCK_CLOEXEC, 0);
858#if !defined(USE_POLL) && !defined(USE_KQUEUE)
859                if (EXT(statp).nssocks[ns] > highestFD) {
860                        res_nclose(statp);
861                        errno = ENOTSOCK;
862                }
863#endif
864                if (EXT(statp).nssocks[ns] < 0) {
865                        switch (errno) {
866                        case EPROTONOSUPPORT:
867#ifdef EPFNOSUPPORT
868                        case EPFNOSUPPORT:
869#endif
870                        case EAFNOSUPPORT:
871                                Perror(statp, stderr, "socket(dg)", errno);
872                                return (0);
873                        default:
874                                *terrno = errno;
875                                Perror(statp, stderr, "socket(dg)", errno);
876                                return (-1);
877                        }
878                }
879#ifndef CANNOT_CONNECT_DGRAM
880                /*
881                 * On a 4.3BSD+ machine (client and server,
882                 * actually), sending to a nameserver datagram
883                 * port with no nameserver will cause an
884                 * ICMP port unreachable message to be returned.
885                 * If our datagram socket is "connected" to the
886                 * server, we get an ECONNREFUSED error on the next
887                 * socket operation, and select returns if the
888                 * error message is received.  We can thus detect
889                 * the absence of a nameserver without timing out.
890                 *
891                 * When the option "insecure1" is specified, we'd
892                 * rather expect to see responses from an "unknown"
893                 * address.  In order to let the kernel accept such
894                 * responses, do not connect the socket here.
895                 * XXX: or do we need an explicit option to disable
896                 * connecting?
897                 */
898                if (!(statp->options & RES_INSECURE1) &&
899                    _connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) {
900                        Aerror(statp, stderr, "connect(dg)", errno, nsap,
901                            nsaplen);
902                        res_nclose(statp);
903                        return (0);
904                }
905#endif /* !CANNOT_CONNECT_DGRAM */
906                Dprint(statp->options & RES_DEBUG,
907                       (stdout, ";; new DG socket\n"))
908        }
909        s = EXT(statp).nssocks[ns];
910#ifndef CANNOT_CONNECT_DGRAM
911        if (statp->options & RES_INSECURE1) {
912                if (_sendto(s,
913                    (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) {
914                        Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
915                        res_nclose(statp);
916                        return (0);
917                }
918        } else if (send(s, (const char*)buf, buflen, 0) != buflen) {
919                Perror(statp, stderr, "send", errno);
920                res_nclose(statp);
921                return (0);
922        }
923#else /* !CANNOT_CONNECT_DGRAM */
924        if (_sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
925        {
926                Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
927                res_nclose(statp);
928                return (0);
929        }
930#endif /* !CANNOT_CONNECT_DGRAM */
931
932        /*
933         * Wait for reply.
934         */
935        seconds = (statp->retrans << tries);
936        if (ns > 0)
937                seconds /= statp->nscount;
938        if (seconds <= 0)
939                seconds = 1;
940        now = evNowTime();
941        timeout = evConsTime(seconds, 0);
942        finish = evAddTime(now, timeout);
943        goto nonow;
944 wait:
945        now = evNowTime();
946 nonow:
947#ifndef USE_POLL
948        if (evCmpTime(finish, now) > 0)
949                timeout = evSubTime(finish, now);
950        else
951                timeout = evConsTime(0, 0);
952#ifdef USE_KQUEUE
953        EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0);
954        n = _kevent(kq, &kv, 1, &kv, 1, &timeout);
955#else
956        FD_ZERO(&dsmask);
957        FD_SET(s, &dsmask);
958        n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
959#endif
960#else
961        timeout = evSubTime(finish, now);
962        if (timeout.tv_sec < 0)
963                timeout = evConsTime(0, 0);
964        polltimeout = 1000*timeout.tv_sec +
965                timeout.tv_nsec/1000000;
966        pollfd.fd = s;
967        pollfd.events = POLLRDNORM;
968        n = _poll(&pollfd, 1, polltimeout);
969#endif /* USE_POLL */
970
971        if (n == 0) {
972                Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
973                *gotsomewhere = 1;
974                return (0);
975        }
976        if (n < 0) {
977                if (errno == EINTR)
978                        goto wait;
979#ifdef USE_KQUEUE
980                Perror(statp, stderr, "kevent", errno);
981#else
982#ifndef USE_POLL
983                Perror(statp, stderr, "select", errno);
984#else
985                Perror(statp, stderr, "poll", errno);
986#endif /* USE_POLL */
987#endif
988                res_nclose(statp);
989                return (0);
990        }
991#ifdef USE_KQUEUE
992        if (kv.ident != s)
993                goto wait;
994#endif
995        errno = 0;
996        fromlen = sizeof(from);
997        resplen = _recvfrom(s, (char*)ans, anssiz,0,
998                           (struct sockaddr *)&from, &fromlen);
999        if (resplen <= 0) {
1000                Perror(statp, stderr, "recvfrom", errno);
1001                res_nclose(statp);
1002                return (0);
1003        }
1004        *gotsomewhere = 1;
1005        if (resplen < HFIXEDSZ) {
1006                /*
1007                 * Undersized message.
1008                 */
1009                Dprint(statp->options & RES_DEBUG,
1010                       (stdout, ";; undersized: %d\n",
1011                        resplen));
1012                *terrno = EMSGSIZE;
1013                res_nclose(statp);
1014                return (0);
1015        }
1016        if (hp->id != anhp->id) {
1017                /*
1018                 * response from old query, ignore it.
1019                 * XXX - potential security hazard could
1020                 *       be detected here.
1021                 */
1022                DprintQ((statp->options & RES_DEBUG) ||
1023                        (statp->pfcode & RES_PRF_REPLY),
1024                        (stdout, ";; old answer:\n"),
1025                        ans, (resplen > anssiz) ? anssiz : resplen);
1026                goto wait;
1027        }
1028        if (!(statp->options & RES_INSECURE1) &&
1029            !res_ourserver_p(statp, (struct sockaddr *)&from)) {
1030                /*
1031                 * response from wrong server? ignore it.
1032                 * XXX - potential security hazard could
1033                 *       be detected here.
1034                 */
1035                DprintQ((statp->options & RES_DEBUG) ||
1036                        (statp->pfcode & RES_PRF_REPLY),
1037                        (stdout, ";; not our server:\n"),
1038                        ans, (resplen > anssiz) ? anssiz : resplen);
1039                goto wait;
1040        }
1041#ifdef RES_USE_EDNS0
1042        if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
1043                /*
1044                 * Do not retry if the server do not understand EDNS0.
1045                 * The case has to be captured here, as FORMERR packet do not
1046                 * carry query section, hence res_queriesmatch() returns 0.
1047                 */
1048                DprintQ(statp->options & RES_DEBUG,
1049                        (stdout, "server rejected query with EDNS0:\n"),
1050                        ans, (resplen > anssiz) ? anssiz : resplen);
1051                /* record the error */
1052                statp->_flags |= RES_F_EDNS0ERR;
1053                res_nclose(statp);
1054                return (0);
1055        }
1056#endif
1057        if (!(statp->options & RES_INSECURE2) &&
1058            !res_queriesmatch(buf, buf + buflen,
1059                              ans, ans + anssiz)) {
1060                /*
1061                 * response contains wrong query? ignore it.
1062                 * XXX - potential security hazard could
1063                 *       be detected here.
1064                 */
1065                DprintQ((statp->options & RES_DEBUG) ||
1066                        (statp->pfcode & RES_PRF_REPLY),
1067                        (stdout, ";; wrong query name:\n"),
1068                        ans, (resplen > anssiz) ? anssiz : resplen);
1069                goto wait;
1070        }
1071        if (anhp->rcode == SERVFAIL ||
1072            anhp->rcode == NOTIMP ||
1073            anhp->rcode == REFUSED) {
1074                DprintQ(statp->options & RES_DEBUG,
1075                        (stdout, "server rejected query:\n"),
1076                        ans, (resplen > anssiz) ? anssiz : resplen);
1077                res_nclose(statp);
1078                /* don't retry if called from dig */
1079                if (!statp->pfcode)
1080                        return (0);
1081        }
1082        if (!(statp->options & RES_IGNTC) && anhp->tc) {
1083                /*
1084                 * To get the rest of answer,
1085                 * use TCP with same server.
1086                 */
1087                Dprint(statp->options & RES_DEBUG,
1088                       (stdout, ";; truncated answer\n"));
1089                *v_circuit = 1;
1090                res_nclose(statp);
1091                return (1);
1092        }
1093        /*
1094         * All is well, or the error is fatal.  Signal that the
1095         * next nameserver ought not be tried.
1096         */
1097        return (resplen);
1098}
1099
1100static void
1101Aerror(const res_state statp, FILE *file, const char *string, int error,
1102       const struct sockaddr *address, int alen)
1103{
1104        int save = errno;
1105        char hbuf[NI_MAXHOST];
1106        char sbuf[NI_MAXSERV];
1107
1108        if ((statp->options & RES_DEBUG) != 0U) {
1109                if (getnameinfo(address, alen, hbuf, sizeof(hbuf),
1110                    sbuf, sizeof(sbuf), niflags)) {
1111                        strncpy(hbuf, "?", sizeof(hbuf) - 1);
1112                        hbuf[sizeof(hbuf) - 1] = '\0';
1113                        strncpy(sbuf, "?", sizeof(sbuf) - 1);
1114                        sbuf[sizeof(sbuf) - 1] = '\0';
1115                }
1116                fprintf(file, "res_send: %s ([%s].%s): %s\n",
1117                        string, hbuf, sbuf, strerror(error));
1118        }
1119        errno = save;
1120}
1121
1122static void
1123Perror(const res_state statp, FILE *file, const char *string, int error) {
1124        int save = errno;
1125
1126        if ((statp->options & RES_DEBUG) != 0U)
1127                fprintf(file, "res_send: %s: %s\n",
1128                        string, strerror(error));
1129        errno = save;
1130}
1131
1132static int
1133sock_eq(struct sockaddr *a, struct sockaddr *b) {
1134        struct sockaddr_in *a4, *b4;
1135        struct sockaddr_in6 *a6, *b6;
1136
1137        if (a->sa_family != b->sa_family)
1138                return 0;
1139        switch (a->sa_family) {
1140        case AF_INET:
1141                a4 = (struct sockaddr_in *)a;
1142                b4 = (struct sockaddr_in *)b;
1143                return a4->sin_port == b4->sin_port &&
1144                    a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1145        case AF_INET6:
1146                a6 = (struct sockaddr_in6 *)a;
1147                b6 = (struct sockaddr_in6 *)b;
1148                return a6->sin6_port == b6->sin6_port &&
1149#ifdef HAVE_SIN6_SCOPE_ID
1150                    a6->sin6_scope_id == b6->sin6_scope_id &&
1151#endif
1152                    IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1153        default:
1154                return 0;
1155        }
1156}
1157
1158#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
1159/* XXX needs to move to the porting library. */
1160static int
1161pselect(int nfds, void *rfds, void *wfds, void *efds,
1162        struct timespec *tsp, const sigset_t *sigmask)
1163{
1164        struct timeval tv, *tvp;
1165        sigset_t sigs;
1166        int n;
1167
1168        if (tsp) {
1169                tvp = &tv;
1170                tv = evTimeVal(*tsp);
1171        } else
1172                tvp = NULL;
1173        if (sigmask)
1174                sigprocmask(SIG_SETMASK, sigmask, &sigs);
1175        n = select(nfds, rfds, wfds, efds, tvp);
1176        if (sigmask)
1177                sigprocmask(SIG_SETMASK, &sigs, NULL);
1178        if (tsp)
1179                *tsp = evTimeSpec(tv);
1180        return (n);
1181}
1182#endif
Note: See TracBrowser for help on using the repository browser.