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

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f41a394 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 27, 2016 at 8:25:22 AM

Directly use <sys/types.h> provided by Newlib

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