2 * Copyright (c) 1985, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies, and that
40 * the name of Digital Equipment Corporation not be used in advertising or
41 * publicity pertaining to distribution of the document or software without
42 * specific, written prior permission.
44 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
47 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
55 * Portions Copyright (c) 1996 by Internet Software Consortium.
57 * Permission to use, copy, modify, and distribute this software for any
58 * purpose with or without fee is hereby granted, provided that the above
59 * copyright notice and this permission notice appear in all copies.
61 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
62 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
63 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
64 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
65 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
66 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
67 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
71 #if defined(LIBC_SCCS) && !defined(lint)
72 static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
73 static char rcsid[] = "$Id: res_send.c,v 8.20 1998/04/06 23:27:51 halley Exp $";
74 #endif /* LIBC_SCCS and not lint */
77 * Send query to name server and wait for reply.
80 #include "port_before.h"
81 #include "fd_setsize.h"
83 #include <sys/types.h>
84 #include <sys/param.h>
86 #include <sys/socket.h>
89 #include <netinet/in.h>
90 #include <arpa/nameser.h>
91 #include <arpa/inet.h>
101 #include "port_after.h"
103 /* Options. Leave them on. */
105 #define CHECK_SRVR_ADDR
107 static int s = -1; /* socket used for communications */
108 static int connected = 0; /* is the socket connected */
109 static int vc = 0; /* is the socket a virtual circuit? */
110 static res_send_qhook Qhook = NULL;
111 static res_send_rhook Rhook = NULL;
115 # define Dprint(cond, args) /*empty*/
116 # define DprintQ(cond, args, query, size) /*empty*/
117 # define Aerror(file, string, error, address) /*empty*/
118 # define Perror(file, string, error) /*empty*/
120 # define Dprint(cond, args) if (cond) {fprintf args;} else {}
121 # define DprintQ(cond, args, query, size) if (cond) {\
123 __fp_nquery(query, size, stdout);\
126 Aerror(file, string, error, address)
130 struct sockaddr_in address;
134 if (_res.options & RES_DEBUG) {
135 fprintf(file, "res_send: %s ([%s].%u): %s\n",
137 inet_ntoa(address.sin_addr),
138 ntohs(address.sin_port),
144 Perror(file, string, error)
151 if (_res.options & RES_DEBUG) {
152 fprintf(file, "res_send: %s: %s\n",
153 string, strerror(error));
160 res_send_setqhook(res_send_qhook hook) {
165 res_send_setrhook(res_send_rhook hook) {
170 * res_isourserver(ina)
171 * looks up "ina" in _res.ns_addr_list[]
176 * paul vixie, 29may94
179 res_isourserver(const struct sockaddr_in *inp) {
180 struct sockaddr_in ina;
185 for (ns = 0; ns < _res.nscount; ns++) {
186 const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
188 if (srv->sin_family == ina.sin_family &&
189 srv->sin_port == ina.sin_port &&
190 (srv->sin_addr.s_addr == INADDR_ANY ||
191 srv->sin_addr.s_addr == ina.sin_addr.s_addr)) {
200 * res_nameinquery(name, type, class, buf, eom)
201 * look for (name,type,class) in the query section of packet (buf,eom)
203 * buf + HFIXEDSZ <= eom
209 * paul vixie, 29may94
212 res_nameinquery(const char *name, int type, int class,
213 const u_char *buf, const u_char *eom)
215 const u_char *cp = buf + HFIXEDSZ;
216 int qdcount = ntohs(((HEADER*)buf)->qdcount);
218 while (qdcount-- > 0) {
219 char tname[MAXDNAME+1];
220 int n, ttype, tclass;
222 n = dn_expand(buf, eom, cp, tname, sizeof tname);
226 if (cp + 2 * INT16SZ > eom)
228 ttype = ns_get16(cp); cp += INT16SZ;
229 tclass = ns_get16(cp); cp += INT16SZ;
232 strcasecmp(tname, name) == 0)
239 * res_queriesmatch(buf1, eom1, buf2, eom2)
240 * is there a 1:1 mapping of (name,type,class)
241 * in (buf1,eom1) and (buf2,eom2)?
244 * 0 : not a 1:1 mapping
245 * >0 : is a 1:1 mapping
247 * paul vixie, 29may94
250 res_queriesmatch(const u_char *buf1, const u_char *eom1,
251 const u_char *buf2, const u_char *eom2)
253 const u_char *cp = buf1 + HFIXEDSZ;
254 int qdcount = ntohs(((HEADER*)buf1)->qdcount);
256 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
260 * Only header section present in replies to
261 * dynamic update packets.
263 if ( (((HEADER *)buf1)->opcode == ns_o_update) &&
264 (((HEADER *)buf2)->opcode == ns_o_update) )
267 if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
269 while (qdcount-- > 0) {
270 char tname[MAXDNAME+1];
271 int n, ttype, tclass;
273 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
277 if (cp + 2 * INT16SZ > eom1)
279 ttype = ns_get16(cp); cp += INT16SZ;
280 tclass = ns_get16(cp); cp += INT16SZ;
281 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
288 res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
289 HEADER *hp = (HEADER *) buf;
290 HEADER *anhp = (HEADER *) ans;
291 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns, n;
292 u_int badns; /* XXX NSMAX can't exceed #/bits in this variable */
294 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
295 /* errno should have been set by res_init() in this case. */
298 if (anssiz < HFIXEDSZ) {
302 DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
303 (stdout, ";; res_send()\n"), buf, buflen);
304 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
311 * Send request, RETRY times, or until successful
313 for (try = 0; try < _res.retry; try++) {
314 for (ns = 0; ns < _res.nscount; ns++) {
315 struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
317 if (badns & (1 << ns)) {
323 int done = 0, loops = 0;
328 act = (*Qhook)(&nsap, &buf, &buflen,
329 ans, anssiz, &resplen);
340 /* give the hook another try */
341 if (++loops < 42) /*doug adams*/
352 Dprint(_res.options & RES_DEBUG,
353 (stdout, ";; Querying server (# %d) address = %s\n",
354 ns + 1, inet_ntoa(nsap->sin_addr)));
363 * Use virtual circuit;
364 * at most one attempt per server.
368 if (s < 0 || !vc || hp->opcode == ns_o_update) {
372 s = socket(PF_INET, SOCK_STREAM, 0);
375 Perror(stderr, "socket(vc)", errno);
379 if (connect(s, (struct sockaddr *)nsap,
382 Aerror(stderr, "connect/vc",
391 * Send length & message
393 putshort((u_short)buflen, (u_char*)&len);
394 iov[0].iov_base = (caddr_t)&len;
395 iov[0].iov_len = INT16SZ;
396 iov[1].iov_base = (caddr_t)buf;
397 iov[1].iov_len = buflen;
398 if (writev(s, iov, 2) != (INT16SZ + buflen)) {
400 Perror(stderr, "write failed", errno);
406 * Receive length & response
411 while ((n = read(s, (char *)cp, (int)len)) > 0) {
418 Perror(stderr, "read failed", errno);
421 * A long running process might get its TCP
422 * connection reset if the remote server was
423 * restarted. Requery the server instead of
424 * trying a new one. When there is only one
425 * server, this means that a query might work
426 * instead of failing. We only allow one reset
427 * per query to prevent looping.
429 if (terrno == ECONNRESET && !connreset) {
437 resplen = ns_get16(ans);
438 if (resplen > anssiz) {
439 Dprint(_res.options & RES_DEBUG,
440 (stdout, ";; response truncated\n")
446 if (len < HFIXEDSZ) {
448 * Undersized message.
450 Dprint(_res.options & RES_DEBUG,
451 (stdout, ";; undersized: %d\n", len));
459 (n = read(s, (char *)cp, (int)len)) > 0) {
465 Perror(stderr, "read(vc)", errno);
471 * Flush rest of answer
472 * so connection stays in synch.
475 len = resplen - anssiz;
479 n = (len > sizeof(junk)
482 if ((n = read(s, junk, n)) > 0)
489 * The calling applicating has bailed out of
490 * a previous call and failed to arrange to have
491 * the circuit closed or the server has got
492 * itself confused. Anyway drop the packet and
493 * wait for the correct one.
495 if (hp->id != anhp->id) {
496 DprintQ((_res.options & RES_DEBUG) ||
497 (_res.pfcode & RES_PRF_REPLY),
498 (stdout, ";; old answer (unexpected):\n"),
499 ans, (resplen>anssiz)?anssiz:resplen);
506 struct timeval timeout;
508 struct sockaddr_in from;
514 s = socket(PF_INET, SOCK_DGRAM, 0);
516 #ifndef CAN_RECONNECT
520 Perror(stderr, "socket(dg)", errno);
525 #ifndef CANNOT_CONNECT_DGRAM
527 * On a 4.3BSD+ machine (client and server,
528 * actually), sending to a nameserver datagram
529 * port with no nameserver will cause an
530 * ICMP port unreachable message to be returned.
531 * If our datagram socket is "connected" to the
532 * server, we get an ECONNREFUSED error on the next
533 * socket operation, and select returns if the
534 * error message is received. We can thus detect
535 * the absence of a nameserver without timing out.
536 * If we have sent queries to at least two servers,
537 * however, we don't want to remain connected,
538 * as we wish to receive answers from the first
541 if (_res.nscount == 1 || (try == 0 && ns == 0)) {
543 * Connect only if we are sure we won't
544 * receive a response from another server.
547 if (connect(s, (struct sockaddr *)nsap,
559 if (send(s, (char*)buf, buflen, 0) != buflen) {
560 Perror(stderr, "send", errno);
567 * Disconnect if we want to listen
568 * for responses from more than one server.
572 struct sockaddr_in no_addr;
574 no_addr.sin_family = AF_INET;
575 no_addr.sin_addr.s_addr = INADDR_ANY;
576 no_addr.sin_port = 0;
582 int s1 = socket(PF_INET, SOCK_DGRAM,0);
587 Dprint(_res.options & RES_DEBUG,
588 (stdout, ";; new DG socket\n"))
589 #endif /* CAN_RECONNECT */
593 #endif /* !CANNOT_CONNECT_DGRAM */
594 if (sendto(s, (char*)buf, buflen, 0,
595 (struct sockaddr *)nsap,
598 Aerror(stderr, "sendto", errno, *nsap);
603 #ifndef CANNOT_CONNECT_DGRAM
605 #endif /* !CANNOT_CONNECT_DGRAM */
610 timeout.tv_sec = (_res.retrans << try);
612 timeout.tv_sec /= _res.nscount;
613 if ((long) timeout.tv_sec <= 0)
617 if (s < 0 || s >= FD_SETSIZE) {
618 Perror(stderr, "s out-of-bounds", EMFILE);
624 n = select(s+1, &dsmask, (fd_set *)NULL,
625 (fd_set *)NULL, &timeout);
629 Perror(stderr, "select", errno);
637 Dprint(_res.options & RES_DEBUG,
638 (stdout, ";; timeout\n"));
644 fromlen = sizeof(struct sockaddr_in);
645 resplen = recvfrom(s, (char*)ans, anssiz, 0,
646 (struct sockaddr *)&from, &fromlen);
648 Perror(stderr, "recvfrom", errno);
653 if (resplen < HFIXEDSZ) {
655 * Undersized message.
657 Dprint(_res.options & RES_DEBUG,
658 (stdout, ";; undersized: %d\n",
665 if (hp->id != anhp->id) {
667 * response from old query, ignore it.
668 * XXX - potential security hazard could
671 DprintQ((_res.options & RES_DEBUG) ||
672 (_res.pfcode & RES_PRF_REPLY),
673 (stdout, ";; old answer:\n"),
674 ans, (resplen>anssiz)?anssiz:resplen);
677 #ifdef CHECK_SRVR_ADDR
678 if (!(_res.options & RES_INSECURE1) &&
679 !res_isourserver(&from)) {
681 * response from wrong server? ignore it.
682 * XXX - potential security hazard could
685 DprintQ((_res.options & RES_DEBUG) ||
686 (_res.pfcode & RES_PRF_REPLY),
687 (stdout, ";; not our server:\n"),
688 ans, (resplen>anssiz)?anssiz:resplen);
692 if (!(_res.options & RES_INSECURE2) &&
693 !res_queriesmatch(buf, buf + buflen,
694 ans, ans + anssiz)) {
696 * response contains wrong query? ignore it.
697 * XXX - potential security hazard could
700 DprintQ((_res.options & RES_DEBUG) ||
701 (_res.pfcode & RES_PRF_REPLY),
702 (stdout, ";; wrong query name:\n"),
703 ans, (resplen>anssiz)?anssiz:resplen);
706 if (anhp->rcode == SERVFAIL ||
707 anhp->rcode == NOTIMP ||
708 anhp->rcode == REFUSED) {
709 DprintQ(_res.options & RES_DEBUG,
710 (stdout, "server rejected query:\n"),
711 ans, (resplen>anssiz)?anssiz:resplen);
714 /* don't retry if called from dig */
718 if (!(_res.options & RES_IGNTC) && anhp->tc) {
720 * get rest of answer;
721 * use TCP with same server.
723 Dprint(_res.options & RES_DEBUG,
724 (stdout, ";; truncated answer\n"));
730 Dprint((_res.options & RES_DEBUG) ||
731 ((_res.pfcode & RES_PRF_REPLY) &&
732 (_res.pfcode & RES_PRF_HEAD1)),
733 (stdout, ";; got answer:\n"));
734 DprintQ((_res.options & RES_DEBUG) ||
735 (_res.pfcode & RES_PRF_REPLY),
737 ans, (resplen>anssiz)?anssiz:resplen);
739 * If using virtual circuits, we assume that the first server
740 * is preferred over the rest (i.e. it is on the local
741 * machine) and only keep that one open.
742 * If we have temporarily opened a virtual circuit,
743 * or if we haven't been asked to keep a socket open,
746 if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
747 !(_res.options & RES_STAYOPEN)) {
751 int done = 0, loops = 0;
756 act = (*Rhook)(nsap, buf, buflen,
757 ans, anssiz, &resplen);
767 /* give the hook another try */
768 if (++loops < 42) /*doug adams*/
786 errno = ECONNREFUSED; /* no nameservers found */
788 errno = ETIMEDOUT; /* no answer obtained */
795 * This routine is for closing the socket if a virtual circuit is used and
796 * the program wants to close it. This provides support for endhostent()
797 * which expects to close the socket.
799 * This routine is not expected to be user visible.