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