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

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since c1e56a5 was c1e56a5, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 1, 2012 at 2:46:13 PM

res_send.c: Now compiles

This required adding ISC .h files and adding some defines to
port_before.h.

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