]> git.ipfire.org Git - thirdparty/glibc.git/blame - resolv/res_send.c
Assume that SOCK_CLOEXEC is available and works
[thirdparty/glibc.git] / resolv / res_send.c
CommitLineData
28f540f4 1/*
28f540f4
RM
2 * Copyright (c) 1985, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
e62b2105 4 *
28f540f4
RM
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
28f540f4
RM
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
e62b2105 16 *
28f540f4
RM
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
b43b13ac
UD
28 */
29
30/*
28f540f4 31 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
e62b2105 32 *
28f540f4
RM
33 * Permission to use, copy, modify, and distribute this software for any
34 * purpose with or without fee is hereby granted, provided that the above
35 * copyright notice and this permission notice appear in all copies, and that
36 * the name of Digital Equipment Corporation not be used in advertising or
37 * publicity pertaining to distribution of the document or software without
38 * specific, written prior permission.
e62b2105 39 *
28f540f4
RM
40 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
41 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
42 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
43 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 * SOFTWARE.
b43b13ac
UD
48 */
49
50/*
51 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
52 *
53 * Permission to use, copy, modify, and distribute this software for any
54 * purpose with or without fee is hereby granted, provided that the above
55 * copyright notice and this permission notice appear in all copies.
56 *
57 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
58 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
60 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
61 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
62 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
63 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
64 * SOFTWARE.
28f540f4
RM
65 */
66
67#if defined(LIBC_SCCS) && !defined(lint)
b43b13ac 68static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
e685e07d 69static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixie Exp $";
28f540f4
RM
70#endif /* LIBC_SCCS and not lint */
71
28f540f4
RM
72/*
73 * Send query to name server and wait for reply.
74 */
75
17a10319 76#include <assert.h>
df21c858 77#include <sys/types.h>
28f540f4
RM
78#include <sys/param.h>
79#include <sys/time.h>
80#include <sys/socket.h>
81#include <sys/uio.h>
e685e07d 82#include <sys/poll.h>
b43b13ac 83
28f540f4
RM
84#include <netinet/in.h>
85#include <arpa/nameser.h>
86#include <arpa/inet.h>
0420d888 87#include <sys/ioctl.h>
28f540f4 88
28f540f4 89#include <errno.h>
f433b06b 90#include <fcntl.h>
b43b13ac 91#include <netdb.h>
28f540f4 92#include <resolv.h>
b43b13ac
UD
93#include <signal.h>
94#include <stdio.h>
95#include <stdlib.h>
96#include <string.h>
97#include <unistd.h>
9744268c 98#include <kernel-features.h>
48e435cd 99#include <libc-internal.h>
b43b13ac 100
0420d888
UD
101#if PACKETSZ > 65536
102#define MAXPACKET PACKETSZ
103#else
104#define MAXPACKET 65536
105#endif
106
e685e07d 107/* From ev_streams.c. */
e62b2105 108
25337753
UD
109static inline void
110__attribute ((always_inline))
111evConsIovec(void *buf, size_t cnt, struct iovec *vec) {
112 memset(vec, 0xf5, sizeof (*vec));
113 vec->iov_base = buf;
114 vec->iov_len = cnt;
e685e07d 115}
28f540f4 116
e685e07d 117/* From ev_timers.c. */
30f9ca19 118
b43b13ac 119#define BILLION 1000000000
e685e07d 120
25337753
UD
121static inline void
122evConsTime(struct timespec *res, time_t sec, long nsec) {
123 res->tv_sec = sec;
124 res->tv_nsec = nsec;
b43b13ac 125}
28f540f4 126
25337753
UD
127static inline void
128evAddTime(struct timespec *res, const struct timespec *addend1,
129 const struct timespec *addend2) {
130 res->tv_sec = addend1->tv_sec + addend2->tv_sec;
131 res->tv_nsec = addend1->tv_nsec + addend2->tv_nsec;
132 if (res->tv_nsec >= BILLION) {
133 res->tv_sec++;
134 res->tv_nsec -= BILLION;
b43b13ac 135 }
b43b13ac
UD
136}
137
25337753
UD
138static inline void
139evSubTime(struct timespec *res, const struct timespec *minuend,
140 const struct timespec *subtrahend) {
141 res->tv_sec = minuend->tv_sec - subtrahend->tv_sec;
142 if (minuend->tv_nsec >= subtrahend->tv_nsec)
143 res->tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec;
b43b13ac 144 else {
25337753
UD
145 res->tv_nsec = (BILLION
146 - subtrahend->tv_nsec + minuend->tv_nsec);
147 res->tv_sec--;
b43b13ac 148 }
b43b13ac
UD
149}
150
f1d70dad 151static int
b43b13ac
UD
152evCmpTime(struct timespec a, struct timespec b) {
153 long x = a.tv_sec - b.tv_sec;
154
155 if (x == 0L)
156 x = a.tv_nsec - b.tv_nsec;
157 return (x < 0L ? (-1) : x > 0L ? (1) : (0));
158}
159
f1d70dad 160static void
25337753 161evNowTime(struct timespec *res) {
b43b13ac
UD
162 struct timeval now;
163
164 if (gettimeofday(&now, NULL) < 0)
25337753
UD
165 evConsTime(res, 0, 0);
166 else
167 TIMEVAL_TO_TIMESPEC (&now, res);
b43b13ac 168}
b43b13ac 169
28f540f4 170
e685e07d
UD
171/* Options. Leave them on. */
172/* #undef DEBUG */
173#include "res_debug.h"
b43b13ac 174
e685e07d 175#define EXT(res) ((res)->_u._ext)
28f540f4 176
e685e07d
UD
177/* Forward. */
178
2212c142 179static struct sockaddr *get_nsaddr (res_state, int);
e685e07d 180static int send_vc(res_state, const u_char *, int,
1eb946b9
UD
181 const u_char *, int,
182 u_char **, int *, int *, int, u_char **,
ab09bf61 183 u_char **, int *, int *, int *);
e685e07d 184static int send_dg(res_state, const u_char *, int,
1eb946b9 185 const u_char *, int,
0420d888 186 u_char **, int *, int *, int,
1eb946b9 187 int *, int *, u_char **,
ab09bf61 188 u_char **, int *, int *, int *);
e685e07d
UD
189#ifdef DEBUG
190static void Aerror(const res_state, FILE *, const char *, int,
020a9a23 191 const struct sockaddr *);
e685e07d
UD
192static void Perror(const res_state, FILE *, const char *, int);
193#endif
438e8239 194static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
e685e07d 195
e685e07d
UD
196/* Public. */
197
28f540f4
RM
198/* int
199 * res_isourserver(ina)
200 * looks up "ina" in _res.ns_addr_list[]
201 * returns:
202 * 0 : not found
203 * >0 : found
204 * author:
205 * paul vixie, 29may94
206 */
207int
438e8239 208res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
438e8239 209{
b43b13ac 210 int ns;
28f540f4 211
3a85895f
PB
212 if (inp->sin6_family == AF_INET) {
213 struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
e62b2105
UD
214 in_port_t port = in4p->sin_port;
215 in_addr_t addr = in4p->sin_addr.s_addr;
438e8239 216
2212c142 217 for (ns = 0; ns < statp->nscount; ns++) {
3a85895f 218 const struct sockaddr_in *srv =
2212c142 219 (struct sockaddr_in *) get_nsaddr (statp, ns);
438e8239 220
2212c142 221 if ((srv->sin_family == AF_INET) &&
3a85895f
PB
222 (srv->sin_port == port) &&
223 (srv->sin_addr.s_addr == INADDR_ANY ||
224 srv->sin_addr.s_addr == addr))
225 return (1);
226 }
227 } else if (inp->sin6_family == AF_INET6) {
2212c142
AS
228 for (ns = 0; ns < statp->nscount; ns++) {
229 const struct sockaddr_in6 *srv
230 = (struct sockaddr_in6 *) get_nsaddr (statp, ns);
231 if ((srv->sin6_family == AF_INET6) &&
3a85895f
PB
232 (srv->sin6_port == inp->sin6_port) &&
233 !(memcmp(&srv->sin6_addr, &in6addr_any,
234 sizeof (struct in6_addr)) &&
235 memcmp(&srv->sin6_addr, &inp->sin6_addr,
236 sizeof (struct in6_addr))))
237 return (1);
238 }
239 }
b43b13ac 240 return (0);
28f540f4
RM
241}
242
243/* int
244 * res_nameinquery(name, type, class, buf, eom)
245 * look for (name,type,class) in the query section of packet (buf,eom)
66715f83 246 * requires:
b43b13ac 247 * buf + HFIXEDSZ <= eom
28f540f4
RM
248 * returns:
249 * -1 : format error
250 * 0 : not found
251 * >0 : found
252 * author:
253 * paul vixie, 29may94
254 */
255int
b43b13ac
UD
256res_nameinquery(const char *name, int type, int class,
257 const u_char *buf, const u_char *eom)
28f540f4 258{
b43b13ac 259 const u_char *cp = buf + HFIXEDSZ;
28f540f4
RM
260 int qdcount = ntohs(((HEADER*)buf)->qdcount);
261
262 while (qdcount-- > 0) {
263 char tname[MAXDNAME+1];
b43b13ac 264 int n, ttype, tclass;
28f540f4
RM
265
266 n = dn_expand(buf, eom, cp, tname, sizeof tname);
267 if (n < 0)
268 return (-1);
269 cp += n;
66715f83
UD
270 if (cp + 2 * INT16SZ > eom)
271 return (-1);
697e1628
UD
272 NS_GET16(ttype, cp);
273 NS_GET16(tclass, cp);
b43b13ac
UD
274 if (ttype == type && tclass == class &&
275 ns_samename(tname, name) == 1)
28f540f4
RM
276 return (1);
277 }
278 return (0);
279}
6f9d8e68 280libresolv_hidden_def (res_nameinquery)
28f540f4
RM
281
282/* int
283 * res_queriesmatch(buf1, eom1, buf2, eom2)
284 * is there a 1:1 mapping of (name,type,class)
285 * in (buf1,eom1) and (buf2,eom2)?
286 * returns:
287 * -1 : format error
288 * 0 : not a 1:1 mapping
289 * >0 : is a 1:1 mapping
290 * author:
291 * paul vixie, 29may94
292 */
293int
b43b13ac
UD
294res_queriesmatch(const u_char *buf1, const u_char *eom1,
295 const u_char *buf2, const u_char *eom2)
28f540f4 296{
66715f83
UD
297 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
298 return (-1);
299
b43b13ac
UD
300 /*
301 * Only header section present in replies to
302 * dynamic update packets.
303 */
e685e07d
UD
304 if ((((HEADER *)buf1)->opcode == ns_o_update) &&
305 (((HEADER *)buf2)->opcode == ns_o_update))
b43b13ac
UD
306 return (1);
307
697e1628 308 /* Note that we initially do not convert QDCOUNT to the host byte
8e45b1ac 309 order. We can compare it with the second buffer's QDCOUNT
697e1628
UD
310 value without doing this. */
311 int qdcount = ((HEADER*)buf1)->qdcount;
312 if (qdcount != ((HEADER*)buf2)->qdcount)
28f540f4 313 return (0);
697e1628
UD
314
315 qdcount = htons (qdcount);
316 const u_char *cp = buf1 + HFIXEDSZ;
317
28f540f4
RM
318 while (qdcount-- > 0) {
319 char tname[MAXDNAME+1];
b43b13ac 320 int n, ttype, tclass;
28f540f4
RM
321
322 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
323 if (n < 0)
324 return (-1);
325 cp += n;
66715f83
UD
326 if (cp + 2 * INT16SZ > eom1)
327 return (-1);
697e1628
UD
328 NS_GET16(ttype, cp);
329 NS_GET16(tclass, cp);
28f540f4
RM
330 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
331 return (0);
332 }
333 return (1);
334}
6f9d8e68 335libresolv_hidden_def (res_queriesmatch)
28f540f4
RM
336
337int
0420d888 338__libc_res_nsend(res_state statp, const u_char *buf, int buflen,
1eb946b9
UD
339 const u_char *buf2, int buflen2,
340 u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
ab09bf61 341 int *nansp2, int *resplen2, int *ansp2_malloced)
28f540f4 342{
b7da31a1 343 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
28f540f4 344
e685e07d
UD
345 if (statp->nscount == 0) {
346 __set_errno (ESRCH);
347 return (-1);
348 }
0420d888 349
1eb946b9 350 if (anssiz < (buf2 == NULL ? 1 : 2) * HFIXEDSZ) {
66715f83
UD
351 __set_errno (EINVAL);
352 return (-1);
353 }
0420d888 354
1eb946b9 355#ifdef USE_HOOKS
a1ffb40e 356 if (__glibc_unlikely (statp->qhook || statp->rhook)) {
1eb946b9
UD
357 if (anssiz < MAXPACKET && ansp) {
358 u_char *buf = malloc (MAXPACKET);
359 if (buf == NULL)
360 return (-1);
361 memcpy (buf, ans, HFIXEDSZ);
362 *ansp = buf;
363 ans = buf;
364 anssiz = MAXPACKET;
365 }
0420d888 366 }
1eb946b9 367#endif
0420d888 368
b43b13ac 369 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
3d61b63c 370 (stdout, ";; res_send()\n"), buf, buflen);
1eb946b9
UD
371 v_circuit = ((statp->options & RES_USEVC)
372 || buflen > PACKETSZ
373 || buflen2 > PACKETSZ);
28f540f4 374 gotsomewhere = 0;
28f540f4 375 terrno = ETIMEDOUT;
28f540f4 376
b43b13ac 377 /*
e685e07d
UD
378 * If the ns_addr_list in the resolver context has changed, then
379 * invalidate our cached copy and the associated timing data.
b43b13ac 380 */
2212c142 381 if (EXT(statp).nscount != 0) {
e685e07d
UD
382 int needclose = 0;
383
384 if (EXT(statp).nscount != statp->nscount)
385 needclose++;
386 else
2212c142
AS
387 for (ns = 0; ns < statp->nscount; ns++) {
388 if (statp->nsaddr_list[ns].sin_family != 0
b64e1566 389 && !sock_eq((struct sockaddr_in6 *)
2212c142 390 &statp->nsaddr_list[ns],
b64e1566 391 EXT(statp).nsaddrs[ns]))
438e8239 392 {
e685e07d
UD
393 needclose++;
394 break;
395 }
b64e1566 396 }
2212c142 397 if (needclose) {
cb07f6f6 398 __res_iclose(statp, false);
2212c142
AS
399 EXT(statp).nscount = 0;
400 }
e685e07d
UD
401 }
402
403 /*
404 * Maybe initialize our private copy of the ns_addr_list.
405 */
2212c142
AS
406 if (EXT(statp).nscount == 0) {
407 for (ns = 0; ns < statp->nscount; ns++) {
408 EXT(statp).nssocks[ns] = -1;
409 if (statp->nsaddr_list[ns].sin_family == 0)
410 continue;
411 if (EXT(statp).nsaddrs[ns] == NULL)
412 EXT(statp).nsaddrs[ns] =
438e8239 413 malloc(sizeof (struct sockaddr_in6));
2212c142
AS
414 if (EXT(statp).nsaddrs[ns] != NULL)
415 memset (mempcpy(EXT(statp).nsaddrs[ns],
cabba934 416 &statp->nsaddr_list[ns],
0f8f993c
UD
417 sizeof (struct sockaddr_in)),
418 '\0',
419 sizeof (struct sockaddr_in6)
420 - sizeof (struct sockaddr_in));
b64e1566 421 }
2212c142 422 EXT(statp).nscount = statp->nscount;
e685e07d
UD
423 }
424
425 /*
426 * Some resolvers want to even out the load on their nameservers.
427 * Note that RES_BLAST overrides RES_ROTATE.
428 */
1eb946b9 429 if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
e685e07d 430 (statp->options & RES_BLAST) == 0) {
2212c142
AS
431 struct sockaddr_in ina;
432 struct sockaddr_in6 *inp;
433 int lastns = statp->nscount - 1;
434 int fd;
435
436 inp = EXT(statp).nsaddrs[0];
437 ina = statp->nsaddr_list[0];
438 fd = EXT(statp).nssocks[0];
439 for (ns = 0; ns < lastns; ns++) {
440 EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1];
441 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
442 EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
b64e1566 443 }
2212c142
AS
444 EXT(statp).nsaddrs[lastns] = inp;
445 statp->nsaddr_list[lastns] = ina;
446 EXT(statp).nssocks[lastns] = fd;
b43b13ac 447 }
30f9ca19 448
28f540f4 449 /*
e685e07d 450 * Send request, RETRY times, or until successful.
28f540f4 451 */
b43b13ac 452 for (try = 0; try < statp->retry; try++) {
2212c142 453 for (ns = 0; ns < statp->nscount; ns++)
438e8239 454 {
a092b645
YD
455#ifdef DEBUG
456 char tmpbuf[40];
457#endif
2212c142
AS
458#if defined USE_HOOKS || defined DEBUG
459 struct sockaddr *nsap = get_nsaddr (statp, ns);
460#endif
438e8239 461
1eb946b9
UD
462 same_ns:
463#ifdef USE_HOOKS
a1ffb40e 464 if (__glibc_unlikely (statp->qhook != NULL)) {
28f540f4
RM
465 int done = 0, loops = 0;
466
467 do {
468 res_sendhookact act;
469
25337753
UD
470 struct sockaddr_in *nsap4;
471 nsap4 = (struct sockaddr_in *) nsap;
472 act = (*statp->qhook)(&nsap4, &buf, &buflen,
438e8239 473 ans, anssiz, &resplen);
25337753 474 nsap = (struct sockaddr_in6 *) nsap4;
28f540f4
RM
475 switch (act) {
476 case res_goahead:
477 done = 1;
478 break;
479 case res_nextns:
cb07f6f6 480 __res_iclose(statp, false);
28f540f4
RM
481 goto next_ns;
482 case res_done:
b43b13ac 483 return (resplen);
28f540f4
RM
484 case res_modified:
485 /* give the hook another try */
486 if (++loops < 42) /*doug adams*/
487 break;
488 /*FALLTHROUGH*/
489 case res_error:
490 /*FALLTHROUGH*/
491 default:
b43b13ac 492 return (-1);
28f540f4
RM
493 }
494 } while (!done);
495 }
1eb946b9 496#endif
28f540f4 497
020a9a23
UD
498 Dprint(statp->options & RES_DEBUG,
499 (stdout, ";; Querying server (# %d) address = %s\n",
2212c142
AS
500 ns + 1, inet_ntop(nsap->sa_family,
501 (nsap->sa_family == AF_INET6
502 ? &((struct sockaddr_in6 *) nsap)->sin6_addr
94308fd0 503 : &((struct sockaddr_in *) nsap)->sin_addr),
020a9a23 504 tmpbuf, sizeof (tmpbuf))));
28f540f4 505
a1ffb40e 506 if (__glibc_unlikely (v_circuit)) {
b43b13ac
UD
507 /* Use VC; at most one attempt per server. */
508 try = statp->retry;
1eb946b9
UD
509 n = send_vc(statp, buf, buflen, buf2, buflen2,
510 &ans, &anssiz, &terrno,
ab09bf61
AS
511 ns, ansp, ansp2, nansp2, resplen2,
512 ansp2_malloced);
e685e07d
UD
513 if (n < 0)
514 return (-1);
57912a71 515 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
28f540f4 516 goto next_ns;
28f540f4 517 } else {
e685e07d 518 /* Use datagrams. */
1eb946b9
UD
519 n = send_dg(statp, buf, buflen, buf2, buflen2,
520 &ans, &anssiz, &terrno,
521 ns, &v_circuit, &gotsomewhere, ansp,
ab09bf61 522 ansp2, nansp2, resplen2, ansp2_malloced);
e685e07d
UD
523 if (n < 0)
524 return (-1);
57912a71 525 if (n == 0 && (buf2 == NULL || *resplen2 == 0))
b43b13ac 526 goto next_ns;
e685e07d 527 if (v_circuit)
1eb946b9 528 // XXX Check whether both requests failed or
b7da31a1 529 // XXX whether one has been answered successfully
28f540f4 530 goto same_ns;
e685e07d
UD
531 }
532
1eb946b9
UD
533 resplen = n;
534
b43b13ac
UD
535 Dprint((statp->options & RES_DEBUG) ||
536 ((statp->pfcode & RES_PRF_REPLY) &&
537 (statp->pfcode & RES_PRF_HEAD1)),
a4219bc4 538 (stdout, ";; got answer:\n"));
e685e07d 539
b43b13ac
UD
540 DprintQ((statp->options & RES_DEBUG) ||
541 (statp->pfcode & RES_PRF_REPLY),
020a9a23 542 (stdout, "%s", ""),
e685e07d 543 ans, (resplen > anssiz) ? anssiz : resplen);
a092b645 544 if (buf2 != NULL) {
1eb946b9
UD
545 DprintQ((statp->options & RES_DEBUG) ||
546 (statp->pfcode & RES_PRF_REPLY),
547 (stdout, "%s", ""),
b7da31a1 548 *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2);
a092b645 549 }
e685e07d 550
28f540f4 551 /*
28f540f4
RM
552 * If we have temporarily opened a virtual circuit,
553 * or if we haven't been asked to keep a socket open,
554 * close the socket.
555 */
e685e07d
UD
556 if ((v_circuit && (statp->options & RES_USEVC) == 0) ||
557 (statp->options & RES_STAYOPEN) == 0) {
cb07f6f6 558 __res_iclose(statp, false);
28f540f4 559 }
1eb946b9 560#ifdef USE_HOOKS
a1ffb40e 561 if (__glibc_unlikely (statp->rhook)) {
28f540f4
RM
562 int done = 0, loops = 0;
563
564 do {
565 res_sendhookact act;
566
438e8239
UD
567 act = (*statp->rhook)((struct sockaddr_in *)
568 nsap, buf, buflen,
569 ans, anssiz, &resplen);
28f540f4
RM
570 switch (act) {
571 case res_goahead:
572 case res_done:
573 done = 1;
574 break;
575 case res_nextns:
cb07f6f6 576 __res_iclose(statp, false);
28f540f4
RM
577 goto next_ns;
578 case res_modified:
579 /* give the hook another try */
580 if (++loops < 42) /*doug adams*/
581 break;
582 /*FALLTHROUGH*/
583 case res_error:
584 /*FALLTHROUGH*/
585 default:
b43b13ac 586 return (-1);
28f540f4
RM
587 }
588 } while (!done);
589
590 }
1eb946b9 591#endif
b43b13ac
UD
592 return (resplen);
593 next_ns: ;
28f540f4
RM
594 } /*foreach ns*/
595 } /*foreach retry*/
cb07f6f6 596 __res_iclose(statp, false);
7ef90c15 597 if (!v_circuit) {
28f540f4 598 if (!gotsomewhere)
b43b13ac 599 __set_errno (ECONNREFUSED); /* no nameservers found */
28f540f4 600 else
b43b13ac 601 __set_errno (ETIMEDOUT); /* no answer obtained */
7ef90c15 602 } else
c4029823 603 __set_errno (terrno);
b43b13ac 604 return (-1);
28f540f4
RM
605}
606
0420d888
UD
607int
608res_nsend(res_state statp,
609 const u_char *buf, int buflen, u_char *ans, int anssiz)
610{
1eb946b9 611 return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
ab09bf61 612 NULL, NULL, NULL, NULL, NULL);
0420d888 613}
6f9d8e68 614libresolv_hidden_def (res_nsend)
0420d888 615
e685e07d
UD
616/* Private */
617
2212c142
AS
618static struct sockaddr *
619get_nsaddr (res_state statp, int n)
620{
621
622 if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL)
623 /* EXT(statp).nsaddrs[n] holds an address that is larger than
624 struct sockaddr, and user code did not update
625 statp->nsaddr_list[n]. */
626 return (struct sockaddr *) EXT(statp).nsaddrs[n];
627 else
628 /* User code updated statp->nsaddr_list[n], or statp->nsaddr_list[n]
629 has the same content as EXT(statp).nsaddrs[n]. */
630 return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
631}
632
e685e07d
UD
633static int
634send_vc(res_state statp,
1eb946b9
UD
635 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
636 u_char **ansp, int *anssizp,
637 int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
ab09bf61 638 int *resplen2, int *ansp2_malloced)
e685e07d
UD
639{
640 const HEADER *hp = (HEADER *) buf;
1eb946b9 641 const HEADER *hp2 = (HEADER *) buf2;
0420d888 642 u_char *ans = *ansp;
1eb946b9
UD
643 int orig_anssizp = *anssizp;
644 // XXX REMOVE
645 // int anssiz = *anssizp;
e685e07d 646 HEADER *anhp = (HEADER *) ans;
2212c142 647 struct sockaddr *nsap = get_nsaddr (statp, ns);
48e435cd
SL
648 int truncating, connreset, n;
649 /* On some architectures compiler might emit a warning indicating
650 'resplen' may be used uninitialized. However if buf2 == NULL
651 then this code won't be executed; if buf2 != NULL, then first
652 time round the loop recvresp1 and recvresp2 will be 0 so this
653 code won't be executed but "thisresplenp = &resplen;" followed
654 by "*thisresplenp = rlen;" will be executed so that subsequent
655 times round the loop resplen has been initialized. So this is
656 a false-positive.
657 */
658#if __GNUC_PREREQ (4, 7)
659 DIAG_PUSH_NEEDS_COMMENT;
660 DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
661#endif
662 int resplen;
663#if __GNUC_PREREQ (4, 7)
664 DIAG_POP_NEEDS_COMMENT;
665#endif
1eb946b9 666 struct iovec iov[4];
e685e07d 667 u_short len;
1eb946b9 668 u_short len2;
e685e07d
UD
669 u_char *cp;
670
b7da31a1
UD
671 if (resplen2 != NULL)
672 *resplen2 = 0;
e685e07d
UD
673 connreset = 0;
674 same_ns:
675 truncating = 0;
676
677 /* Are we still talking to whom we want to talk to? */
678 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
438e8239 679 struct sockaddr_in6 peer;
9cfe5381 680 socklen_t size = sizeof peer;
e685e07d
UD
681
682 if (getpeername(statp->_vcsock,
683 (struct sockaddr *)&peer, &size) < 0 ||
2212c142
AS
684 !sock_eq(&peer, (struct sockaddr_in6 *) nsap)) {
685 __res_iclose(statp, false);
e685e07d
UD
686 statp->_flags &= ~RES_F_VC;
687 }
688 }
689
690 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
691 if (statp->_vcsock >= 0)
cb07f6f6 692 __res_iclose(statp, false);
e685e07d 693
2212c142 694 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
e685e07d
UD
695 if (statp->_vcsock < 0) {
696 *terrno = errno;
697 Perror(statp, stderr, "socket(vc)", errno);
698 return (-1);
699 }
700 __set_errno (0);
2212c142
AS
701 if (connect(statp->_vcsock, nsap,
702 nsap->sa_family == AF_INET
9fc42dfd
UD
703 ? sizeof (struct sockaddr_in)
704 : sizeof (struct sockaddr_in6)) < 0) {
e685e07d 705 *terrno = errno;
2212c142 706 Aerror(statp, stderr, "connect/vc", errno, nsap);
cb07f6f6 707 __res_iclose(statp, false);
e685e07d
UD
708 return (0);
709 }
710 statp->_flags |= RES_F_VC;
28f540f4 711 }
e685e07d
UD
712
713 /*
714 * Send length & message
715 */
1eb946b9 716 len = htons ((u_short) buflen);
25337753
UD
717 evConsIovec(&len, INT16SZ, &iov[0]);
718 evConsIovec((void*)buf, buflen, &iov[1]);
1eb946b9
UD
719 int niov = 2;
720 ssize_t explen = INT16SZ + buflen;
721 if (buf2 != NULL) {
722 len2 = htons ((u_short) buflen2);
723 evConsIovec(&len2, INT16SZ, &iov[2]);
724 evConsIovec((void*)buf2, buflen2, &iov[3]);
725 niov = 4;
726 explen += INT16SZ + buflen2;
727 }
728 if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
e685e07d
UD
729 *terrno = errno;
730 Perror(statp, stderr, "write failed", errno);
cb07f6f6 731 __res_iclose(statp, false);
e685e07d
UD
732 return (0);
733 }
734 /*
735 * Receive length & response
736 */
1eb946b9
UD
737 int recvresp1 = 0;
738 int recvresp2 = buf2 == NULL;
b7da31a1 739 uint16_t rlen16;
e39e6946
UD
740 read_len:
741 cp = (u_char *)&rlen16;
b7da31a1 742 len = sizeof(rlen16);
e39e6946 743 while ((n = TEMP_FAILURE_RETRY (read(statp->_vcsock, cp,
25337753 744 (int)len))) > 0) {
e685e07d
UD
745 cp += n;
746 if ((len -= n) <= 0)
747 break;
748 }
749 if (n <= 0) {
750 *terrno = errno;
751 Perror(statp, stderr, "read failed", errno);
cb07f6f6 752 __res_iclose(statp, false);
e685e07d
UD
753 /*
754 * A long running process might get its TCP
755 * connection reset if the remote server was
756 * restarted. Requery the server instead of
757 * trying a new one. When there is only one
758 * server, this means that a query might work
759 * instead of failing. We only allow one reset
760 * per query to prevent looping.
761 */
762 if (*terrno == ECONNRESET && !connreset) {
763 connreset = 1;
e685e07d
UD
764 goto same_ns;
765 }
e685e07d
UD
766 return (0);
767 }
b7da31a1 768 int rlen = ntohs (rlen16);
1eb946b9
UD
769
770 int *thisanssizp;
771 u_char **thisansp;
772 int *thisresplenp;
773 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
774 thisanssizp = anssizp;
775 thisansp = anscp ?: ansp;
776 assert (anscp != NULL || ansp2 == NULL);
777 thisresplenp = &resplen;
778 } else {
779 if (*anssizp != MAXPACKET) {
780 /* No buffer allocated for the first
781 reply. We can try to use the rest
782 of the user-provided buffer. */
48e435cd
SL
783#if __GNUC_PREREQ (4, 7)
784 DIAG_PUSH_NEEDS_COMMENT;
785 DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
786#endif
27822ce6 787#if _STRING_ARCH_unaligned
1eb946b9
UD
788 *anssizp2 = orig_anssizp - resplen;
789 *ansp2 = *ansp + resplen;
e39e6946
UD
790#else
791 int aligned_resplen
792 = ((resplen + __alignof__ (HEADER) - 1)
ad12e635 793 & ~(__alignof__ (HEADER) - 1));
e39e6946
UD
794 *anssizp2 = orig_anssizp - aligned_resplen;
795 *ansp2 = *ansp + aligned_resplen;
48e435cd
SL
796#endif
797#if __GNUC_PREREQ (4, 7)
798 DIAG_POP_NEEDS_COMMENT;
e39e6946 799#endif
1eb946b9
UD
800 } else {
801 /* The first reply did not fit into the
802 user-provided buffer. Maybe the second
803 answer will. */
804 *anssizp2 = orig_anssizp;
805 *ansp2 = *ansp;
806 }
807
808 thisanssizp = anssizp2;
809 thisansp = ansp2;
810 thisresplenp = resplen2;
811 }
812 anhp = (HEADER *) *thisansp;
813
b7da31a1
UD
814 *thisresplenp = rlen;
815 if (rlen > *thisanssizp) {
1eb946b9
UD
816 /* Yes, we test ANSCP here. If we have two buffers
817 both will be allocatable. */
a1ffb40e 818 if (__glibc_likely (anscp != NULL)) {
1eb946b9
UD
819 u_char *newp = malloc (MAXPACKET);
820 if (newp == NULL) {
0420d888 821 *terrno = ENOMEM;
cb07f6f6 822 __res_iclose(statp, false);
0420d888
UD
823 return (0);
824 }
1eb946b9
UD
825 *thisanssizp = MAXPACKET;
826 *thisansp = newp;
ab09bf61
AS
827 if (thisansp == ansp2)
828 *ansp2_malloced = 1;
1eb946b9 829 anhp = (HEADER *) newp;
b7da31a1 830 len = rlen;
0420d888
UD
831 } else {
832 Dprint(statp->options & RES_DEBUG,
833 (stdout, ";; response truncated\n")
834 );
835 truncating = 1;
1eb946b9 836 len = *thisanssizp;
0420d888 837 }
e685e07d 838 } else
b7da31a1 839 len = rlen;
1eb946b9 840
a1ffb40e 841 if (__glibc_unlikely (len < HFIXEDSZ)) {
e685e07d
UD
842 /*
843 * Undersized message.
844 */
845 Dprint(statp->options & RES_DEBUG,
846 (stdout, ";; undersized: %d\n", len));
847 *terrno = EMSGSIZE;
cb07f6f6 848 __res_iclose(statp, false);
e685e07d
UD
849 return (0);
850 }
1eb946b9
UD
851
852 cp = *thisansp;
e685e07d
UD
853 while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){
854 cp += n;
855 len -= n;
856 }
a1ffb40e 857 if (__glibc_unlikely (n <= 0)) {
e685e07d
UD
858 *terrno = errno;
859 Perror(statp, stderr, "read(vc)", errno);
cb07f6f6 860 __res_iclose(statp, false);
e685e07d
UD
861 return (0);
862 }
a1ffb40e 863 if (__glibc_unlikely (truncating)) {
e685e07d
UD
864 /*
865 * Flush rest of answer so connection stays in synch.
866 */
867 anhp->tc = 1;
b7da31a1 868 len = rlen - *thisanssizp;
e685e07d
UD
869 while (len != 0) {
870 char junk[PACKETSZ];
871
872 n = read(statp->_vcsock, junk,
873 (len > sizeof junk) ? sizeof junk : len);
874 if (n > 0)
875 len -= n;
876 else
877 break;
878 }
879 }
880 /*
c0c3f78a 881 * If the calling application has bailed out of
e685e07d
UD
882 * a previous call and failed to arrange to have
883 * the circuit closed or the server has got
884 * itself confused, then drop the packet and
885 * wait for the correct one.
886 */
1eb946b9
UD
887 if ((recvresp1 || hp->id != anhp->id)
888 && (recvresp2 || hp2->id != anhp->id)) {
e685e07d
UD
889 DprintQ((statp->options & RES_DEBUG) ||
890 (statp->pfcode & RES_PRF_REPLY),
891 (stdout, ";; old answer (unexpected):\n"),
1eb946b9 892 *thisansp,
a092b645 893 (rlen > *thisanssizp) ? *thisanssizp: rlen);
e685e07d
UD
894 goto read_len;
895 }
896
1eb946b9
UD
897 /* Mark which reply we received. */
898 if (recvresp1 == 0 && hp->id == anhp->id)
899 recvresp1 = 1;
900 else
901 recvresp2 = 1;
902 /* Repeat waiting if we have a second answer to arrive. */
903 if ((recvresp1 & recvresp2) == 0)
904 goto read_len;
905
e685e07d
UD
906 /*
907 * All is well, or the error is fatal. Signal that the
908 * next nameserver ought not be tried.
909 */
b7da31a1 910 return resplen;
28f540f4 911}
845dcb57 912
b43b13ac 913static int
44d20bca 914reopen (res_state statp, int *terrno, int ns)
e685e07d 915{
e685e07d 916 if (EXT(statp).nssocks[ns] == -1) {
2212c142 917 struct sockaddr *nsap = get_nsaddr (statp, ns);
ace4e23f 918 socklen_t slen;
44d20bca 919
438e8239 920 /* only try IPv6 if IPv6 NS and if not failed before */
ace4e23f 921 if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
52fb79d6
FW
922 EXT(statp).nssocks[ns]
923 = socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK, 0);
ae1ad3ae
UD
924 if (EXT(statp).nssocks[ns] < 0)
925 statp->ipv6_unavail = errno == EAFNOSUPPORT;
ace4e23f
UD
926 slen = sizeof (struct sockaddr_in6);
927 } else if (nsap->sa_family == AF_INET) {
52fb79d6
FW
928 EXT(statp).nssocks[ns]
929 = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, 0);
ace4e23f 930 slen = sizeof (struct sockaddr_in);
9744268c 931 }
e685e07d
UD
932 if (EXT(statp).nssocks[ns] < 0) {
933 *terrno = errno;
934 Perror(statp, stderr, "socket(dg)", errno);
935 return (-1);
936 }
ae1ad3ae 937
e685e07d
UD
938 /*
939 * On a 4.3BSD+ machine (client and server,
940 * actually), sending to a nameserver datagram
941 * port with no nameserver will cause an
942 * ICMP port unreachable message to be returned.
943 * If our datagram socket is "connected" to the
944 * server, we get an ECONNREFUSED error on the next
945 * socket operation, and select returns if the
946 * error message is received. We can thus detect
947 * the absence of a nameserver without timing out.
948 */
ace4e23f
UD
949 if (connect(EXT(statp).nssocks[ns], nsap, slen) < 0) {
950 Aerror(statp, stderr, "connect(dg)", errno, nsap);
cb07f6f6 951 __res_iclose(statp, false);
e685e07d
UD
952 return (0);
953 }
e685e07d 954 }
17a10319 955
44d20bca
UD
956 return 1;
957}
958
959static int
960send_dg(res_state statp,
961 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
962 u_char **ansp, int *anssizp,
963 int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
ab09bf61 964 u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced)
44d20bca
UD
965{
966 const HEADER *hp = (HEADER *) buf;
967 const HEADER *hp2 = (HEADER *) buf2;
968 u_char *ans = *ansp;
969 int orig_anssizp = *anssizp;
970 struct timespec now, timeout, finish;
971 struct pollfd pfd[1];
3a85895f 972 int ptimeout;
44d20bca 973 struct sockaddr_in6 from;
75ded9bc
UD
974 int resplen = 0;
975 int n;
44d20bca 976
f433b06b
UD
977 /*
978 * Compute time for the total operation.
979 */
ae061910 980 int seconds = (statp->retrans << ns);
f433b06b
UD
981 if (ns > 0)
982 seconds /= statp->nscount;
983 if (seconds <= 0)
984 seconds = 1;
44d20bca 985 bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;
c030f70c
UD
986 bool single_request = (((statp->options & RES_SNGLKUP) != 0)
987 | single_request_reopen);
ae061910 988 int save_gotsomewhere = *gotsomewhere;
44d20bca
UD
989
990 int retval;
991 retry_reopen:
992 retval = reopen (statp, terrno, ns);
993 if (retval <= 0)
994 return retval;
ae061910 995 retry:
f433b06b
UD
996 evNowTime(&now);
997 evConsTime(&timeout, seconds, 0);
998 evAddTime(&finish, &now, &timeout);
999 int need_recompute = 0;
17a10319 1000 int nwritten = 0;
1eb946b9
UD
1001 int recvresp1 = 0;
1002 int recvresp2 = buf2 == NULL;
17a10319
UD
1003 pfd[0].fd = EXT(statp).nssocks[ns];
1004 pfd[0].events = POLLOUT;
5908f779
UD
1005 if (resplen2 != NULL)
1006 *resplen2 = 0;
17a10319
UD
1007 wait:
1008 if (need_recompute) {
8e45b1ac 1009 recompute_resend:
17a10319
UD
1010 evNowTime(&now);
1011 if (evCmpTime(finish, now) <= 0) {
8e45b1ac
UD
1012 poll_err_out:
1013 Perror(statp, stderr, "poll", errno);
1014 err_out:
cb07f6f6 1015 __res_iclose(statp, false);
17a10319
UD
1016 return (0);
1017 }
1018 evSubTime(&timeout, &finish, &now);
ae061910 1019 need_recompute = 0;
17a10319 1020 }
3a85895f 1021 /* Convert struct timespec in milliseconds. */
f433b06b
UD
1022 ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
1023
17a10319
UD
1024 n = 0;
1025 if (nwritten == 0)
1026 n = __poll (pfd, 1, 0);
a1ffb40e 1027 if (__glibc_unlikely (n == 0)) {
f433b06b
UD
1028 n = __poll (pfd, 1, ptimeout);
1029 need_recompute = 1;
1030 }
f433b06b 1031 if (n == 0) {
e2003883 1032 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
74b3cf22 1033 if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
e2003883 1034 {
ae061910
UD
1035 /* There are quite a few broken name servers out
1036 there which don't handle two outstanding
1037 requests from the same source. There are also
1038 broken firewall settings. If we time out after
1039 having received one answer switch to the mode
1040 where we send the second request only once we
1041 have received the first answer. */
74b3cf22
UD
1042 if (!single_request)
1043 {
310647e9 1044 statp->options |= RES_SNGLKUP;
74b3cf22
UD
1045 single_request = true;
1046 *gotsomewhere = save_gotsomewhere;
1047 goto retry;
1048 }
44d20bca
UD
1049 else if (!single_request_reopen)
1050 {
1051 statp->options |= RES_SNGLKUPREOP;
1052 single_request_reopen = true;
1053 *gotsomewhere = save_gotsomewhere;
1054 __res_iclose (statp, false);
1055 goto retry_reopen;
1056 }
74b3cf22
UD
1057
1058 *resplen2 = 1;
1059 return resplen;
e2003883 1060 }
5908f779 1061
f433b06b
UD
1062 *gotsomewhere = 1;
1063 return (0);
1064 }
1065 if (n < 0) {
8e45b1ac
UD
1066 if (errno == EINTR)
1067 goto recompute_resend;
1068
1069 goto poll_err_out;
f433b06b
UD
1070 }
1071 __set_errno (0);
17a10319 1072 if (pfd[0].revents & POLLOUT) {
c030f70c
UD
1073#ifndef __ASSUME_SENDMMSG
1074 static int have_sendmmsg;
1075#else
1076# define have_sendmmsg 1
1077#endif
1078 if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL
1079 && !single_request)
1080 {
1081 struct iovec iov[2];
1082 struct mmsghdr reqs[2];
1083 reqs[0].msg_hdr.msg_name = NULL;
1084 reqs[0].msg_hdr.msg_namelen = 0;
1085 reqs[0].msg_hdr.msg_iov = &iov[0];
1086 reqs[0].msg_hdr.msg_iovlen = 1;
1087 iov[0].iov_base = (void *) buf;
1088 iov[0].iov_len = buflen;
1089 reqs[0].msg_hdr.msg_control = NULL;
1090 reqs[0].msg_hdr.msg_controllen = 0;
1091
1092 reqs[1].msg_hdr.msg_name = NULL;
1093 reqs[1].msg_hdr.msg_namelen = 0;
1094 reqs[1].msg_hdr.msg_iov = &iov[1];
1095 reqs[1].msg_hdr.msg_iovlen = 1;
1096 iov[1].iov_base = (void *) buf2;
1097 iov[1].iov_len = buflen2;
1098 reqs[1].msg_hdr.msg_control = NULL;
1099 reqs[1].msg_hdr.msg_controllen = 0;
1100
123be9de 1101 int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL);
a1ffb40e 1102 if (__glibc_likely (ndg == 2))
c030f70c 1103 {
966977f1
UD
1104 if (reqs[0].msg_len != buflen
1105 || reqs[1].msg_len != buflen2)
1106 goto fail_sendmmsg;
1eb946b9 1107
c030f70c
UD
1108 pfd[0].events = POLLIN;
1109 nwritten += 2;
1110 }
1111 else if (ndg == 1 && reqs[0].msg_len == buflen)
1112 goto just_one;
966977f1 1113 else if (ndg < 0 && (errno == EINTR || errno == EAGAIN))
c030f70c
UD
1114 goto recompute_resend;
1115 else
1116 {
1117#ifndef __ASSUME_SENDMMSG
a1ffb40e 1118 if (__glibc_unlikely (have_sendmmsg == 0))
c030f70c 1119 {
966977f1 1120 if (ndg < 0 && errno == ENOSYS)
c030f70c
UD
1121 {
1122 have_sendmmsg = -1;
1123 goto try_send;
1124 }
1125 have_sendmmsg = 1;
1126 }
1127#endif
1128
966977f1 1129 fail_sendmmsg:
c030f70c 1130 Perror(statp, stderr, "sendmmsg", errno);
8e45b1ac 1131 goto err_out;
c030f70c
UD
1132 }
1133 }
1eb946b9 1134 else
c030f70c
UD
1135 {
1136 ssize_t sr;
1137#ifndef __ASSUME_SENDMMSG
1138 try_send:
1139#endif
1140 if (nwritten != 0)
1141 sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
1142 else
1143 sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
1144
8e6d1083 1145 if (sr != (nwritten != 0 ? buflen2 : buflen)) {
c030f70c
UD
1146 if (errno == EINTR || errno == EAGAIN)
1147 goto recompute_resend;
1148 Perror(statp, stderr, "send", errno);
1149 goto err_out;
1150 }
1151 just_one:
1152 if (nwritten != 0 || buf2 == NULL || single_request)
1153 pfd[0].events = POLLIN;
1154 else
1155 pfd[0].events = POLLIN | POLLOUT;
1156 ++nwritten;
1157 }
17a10319 1158 goto wait;
8aeb5058 1159 } else if (pfd[0].revents & POLLIN) {
1eb946b9
UD
1160 int *thisanssizp;
1161 u_char **thisansp;
1162 int *thisresplenp;
1163
1164 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1165 thisanssizp = anssizp;
1166 thisansp = anscp ?: ansp;
1167 assert (anscp != NULL || ansp2 == NULL);
1168 thisresplenp = &resplen;
1169 } else {
1170 if (*anssizp != MAXPACKET) {
1171 /* No buffer allocated for the first
1172 reply. We can try to use the rest
1173 of the user-provided buffer. */
27822ce6 1174#if _STRING_ARCH_unaligned
1eb946b9
UD
1175 *anssizp2 = orig_anssizp - resplen;
1176 *ansp2 = *ansp + resplen;
ad12e635
UD
1177#else
1178 int aligned_resplen
1179 = ((resplen + __alignof__ (HEADER) - 1)
1180 & ~(__alignof__ (HEADER) - 1));
1181 *anssizp2 = orig_anssizp - aligned_resplen;
1182 *ansp2 = *ansp + aligned_resplen;
1183#endif
1eb946b9
UD
1184 } else {
1185 /* The first reply did not fit into the
1186 user-provided buffer. Maybe the second
1187 answer will. */
1188 *anssizp2 = orig_anssizp;
1189 *ansp2 = *ansp;
1190 }
1191
1192 thisanssizp = anssizp2;
1193 thisansp = ansp2;
1194 thisresplenp = resplen2;
1195 }
1196
1197 if (*thisanssizp < MAXPACKET
1198 /* Yes, we test ANSCP here. If we have two buffers
1199 both will be allocatable. */
17a10319 1200 && anscp
c4e42566 1201#ifdef FIONREAD
1eb946b9 1202 && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
c4e42566
RM
1203 || *thisanssizp < *thisresplenp)
1204#endif
1205 ) {
1eb946b9
UD
1206 u_char *newp = malloc (MAXPACKET);
1207 if (newp != NULL) {
17a10319 1208 *anssizp = MAXPACKET;
1eb946b9 1209 *thisansp = ans = newp;
ab09bf61
AS
1210 if (thisansp == ansp2)
1211 *ansp2_malloced = 1;
17a10319
UD
1212 }
1213 }
1eb946b9
UD
1214 HEADER *anhp = (HEADER *) *thisansp;
1215 socklen_t fromlen = sizeof(struct sockaddr_in6);
1216 assert (sizeof(from) <= fromlen);
1217 *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
1218 *thisanssizp, 0,
1219 (struct sockaddr *)&from, &fromlen);
a1ffb40e 1220 if (__glibc_unlikely (*thisresplenp <= 0)) {
17a10319
UD
1221 if (errno == EINTR || errno == EAGAIN) {
1222 need_recompute = 1;
1223 goto wait;
1224 }
1225 Perror(statp, stderr, "recvfrom", errno);
8e45b1ac 1226 goto err_out;
17a10319 1227 }
e685e07d 1228 *gotsomewhere = 1;
a1ffb40e 1229 if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
17a10319
UD
1230 /*
1231 * Undersized message.
1232 */
1233 Dprint(statp->options & RES_DEBUG,
1234 (stdout, ";; undersized: %d\n",
a092b645 1235 *thisresplenp));
17a10319 1236 *terrno = EMSGSIZE;
8e45b1ac 1237 goto err_out;
17a10319 1238 }
1eb946b9
UD
1239 if ((recvresp1 || hp->id != anhp->id)
1240 && (recvresp2 || hp2->id != anhp->id)) {
17a10319
UD
1241 /*
1242 * response from old query, ignore it.
1243 * XXX - potential security hazard could
1244 * be detected here.
1245 */
1246 DprintQ((statp->options & RES_DEBUG) ||
1247 (statp->pfcode & RES_PRF_REPLY),
1248 (stdout, ";; old answer:\n"),
94308fd0 1249 *thisansp,
a092b645
YD
1250 (*thisresplenp > *thisanssizp)
1251 ? *thisanssizp : *thisresplenp);
f433b06b 1252 goto wait;
e685e07d 1253 }
17a10319
UD
1254 if (!(statp->options & RES_INSECURE1) &&
1255 !res_ourserver_p(statp, &from)) {
1256 /*
1257 * response from wrong server? ignore it.
1258 * XXX - potential security hazard could
1259 * be detected here.
1260 */
1261 DprintQ((statp->options & RES_DEBUG) ||
1262 (statp->pfcode & RES_PRF_REPLY),
1263 (stdout, ";; not our server:\n"),
94308fd0 1264 *thisansp,
a092b645
YD
1265 (*thisresplenp > *thisanssizp)
1266 ? *thisanssizp : *thisresplenp);
17a10319 1267 goto wait;
0420d888 1268 }
2bbb7d5b
UD
1269#ifdef RES_USE_EDNS0
1270 if (anhp->rcode == FORMERR
1271 && (statp->options & RES_USE_EDNS0) != 0U) {
1272 /*
1eb946b9 1273 * Do not retry if the server does not understand
2bbb7d5b
UD
1274 * EDNS0. The case has to be captured here, as
1275 * FORMERR packet do not carry query section, hence
1276 * res_queriesmatch() returns 0.
1277 */
1278 DprintQ(statp->options & RES_DEBUG,
1279 (stdout,
1280 "server rejected query with EDNS0:\n"),
94308fd0 1281 *thisansp,
a092b645
YD
1282 (*thisresplenp > *thisanssizp)
1283 ? *thisanssizp : *thisresplenp);
2bbb7d5b
UD
1284 /* record the error */
1285 statp->_flags |= RES_F_EDNS0ERR;
1286 goto err_out;
3a85895f 1287 }
2bbb7d5b 1288#endif
1eb946b9
UD
1289 if (!(statp->options & RES_INSECURE2)
1290 && (recvresp1 || !res_queriesmatch(buf, buf + buflen,
1291 *thisansp,
1292 *thisansp
1293 + *thisanssizp))
1294 && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
1295 *thisansp,
1296 *thisansp
1297 + *thisanssizp))) {
17a10319
UD
1298 /*
1299 * response contains wrong query? ignore it.
1300 * XXX - potential security hazard could
1301 * be detected here.
1302 */
1303 DprintQ((statp->options & RES_DEBUG) ||
1304 (statp->pfcode & RES_PRF_REPLY),
1305 (stdout, ";; wrong query name:\n"),
94308fd0 1306 *thisansp,
a092b645
YD
1307 (*thisresplenp > *thisanssizp)
1308 ? *thisanssizp : *thisresplenp);
f433b06b
UD
1309 goto wait;
1310 }
17a10319
UD
1311 if (anhp->rcode == SERVFAIL ||
1312 anhp->rcode == NOTIMP ||
1313 anhp->rcode == REFUSED) {
1314 DprintQ(statp->options & RES_DEBUG,
1315 (stdout, "server rejected query:\n"),
94308fd0 1316 *thisansp,
a092b645
YD
1317 (*thisresplenp > *thisanssizp)
1318 ? *thisanssizp : *thisresplenp);
e2003883 1319
16b293a7 1320 next_ns:
4769ae77
UD
1321 if (recvresp1 || (buf2 != NULL && recvresp2)) {
1322 *resplen2 = 0;
e28b969b 1323 return resplen;
4769ae77 1324 }
e2003883
UD
1325 if (buf2 != NULL)
1326 {
4769ae77
UD
1327 /* No data from the first reply. */
1328 resplen = 0;
e2003883 1329 /* We are waiting for a possible second reply. */
e2003883
UD
1330 if (hp->id == anhp->id)
1331 recvresp1 = 1;
1332 else
1333 recvresp2 = 1;
1334
1335 goto wait;
1336 }
1337
cb07f6f6 1338 __res_iclose(statp, false);
17a10319
UD
1339 /* don't retry if called from dig */
1340 if (!statp->pfcode)
1341 return (0);
1342 }
359bb2ef
UD
1343 if (anhp->rcode == NOERROR && anhp->ancount == 0
1344 && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
1345 DprintQ(statp->options & RES_DEBUG,
1346 (stdout, "referred query:\n"),
94308fd0 1347 *thisansp,
a092b645
YD
1348 (*thisresplenp > *thisanssizp)
1349 ? *thisanssizp : *thisresplenp);
359bb2ef
UD
1350 goto next_ns;
1351 }
17a10319
UD
1352 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1353 /*
1354 * To get the rest of answer,
1355 * use TCP with same server.
1356 */
1357 Dprint(statp->options & RES_DEBUG,
1358 (stdout, ";; truncated answer\n"));
1359 *v_circuit = 1;
cb07f6f6 1360 __res_iclose(statp, false);
1eb946b9
UD
1361 // XXX if we have received one reply we could
1362 // XXX use it and not repeat it over TCP...
17a10319
UD
1363 return (1);
1364 }
1eb946b9
UD
1365 /* Mark which reply we received. */
1366 if (recvresp1 == 0 && hp->id == anhp->id)
1367 recvresp1 = 1;
1368 else
1369 recvresp2 = 1;
1370 /* Repeat waiting if we have a second answer to arrive. */
ae061910 1371 if ((recvresp1 & recvresp2) == 0) {
c030f70c 1372 if (single_request) {
ae061910 1373 pfd[0].events = POLLOUT;
44d20bca
UD
1374 if (single_request_reopen) {
1375 __res_iclose (statp, false);
1376 retval = reopen (statp, terrno, ns);
1377 if (retval <= 0)
1378 return retval;
f9d2d032 1379 pfd[0].fd = EXT(statp).nssocks[ns];
44d20bca
UD
1380 }
1381 }
1eb946b9 1382 goto wait;
ae061910 1383 }
e685e07d 1384 /*
17a10319
UD
1385 * All is well, or the error is fatal. Signal that the
1386 * next nameserver ought not be tried.
e685e07d 1387 */
17a10319 1388 return (resplen);
8aeb5058
UD
1389 } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
1390 /* Something went wrong. We can stop trying. */
8e45b1ac 1391 goto err_out;
e685e07d 1392 }
9cfe5381 1393 else {
4769ae77 1394 /* poll should not have returned > 0 in this case. */
9cfe5381
RM
1395 abort ();
1396 }
e685e07d
UD
1397}
1398
1399#ifdef DEBUG
1400static void
1401Aerror(const res_state statp, FILE *file, const char *string, int error,
020a9a23 1402 const struct sockaddr *address)
e685e07d
UD
1403{
1404 int save = errno;
1405
1406 if ((statp->options & RES_DEBUG) != 0) {
020a9a23 1407 char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
e685e07d
UD
1408
1409 fprintf(file, "res_send: %s ([%s].%u): %s\n",
1410 string,
e2a99d8e
UD
1411 (address->sa_family == AF_INET
1412 ? inet_ntop(address->sa_family,
1413 &((const struct sockaddr_in *) address)->sin_addr,
1414 tmp, sizeof tmp)
1415 : inet_ntop(address->sa_family,
1416 &((const struct sockaddr_in6 *) address)->sin6_addr,
1417 tmp, sizeof tmp)),
020a9a23
UD
1418 (address->sa_family == AF_INET
1419 ? ntohs(((struct sockaddr_in *) address)->sin_port)
1420 : address->sa_family == AF_INET6
1421 ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
1422 : 0),
e685e07d
UD
1423 strerror(error));
1424 }
1425 __set_errno (save);
1426}
1427
1428static void
1429Perror(const res_state statp, FILE *file, const char *string, int error) {
1430 int save = errno;
1431
1432 if ((statp->options & RES_DEBUG) != 0)
1433 fprintf(file, "res_send: %s: %s\n",
1434 string, strerror(error));
1435 __set_errno (save);
1436}
1437#endif
1438
1439static int
438e8239
UD
1440sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
1441 if (a1->sin6_family == a2->sin6_family) {
1442 if (a1->sin6_family == AF_INET)
1443 return ((((struct sockaddr_in *)a1)->sin_port ==
1444 ((struct sockaddr_in *)a2)->sin_port) &&
1445 (((struct sockaddr_in *)a1)->sin_addr.s_addr ==
1446 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1447 else
1448 return ((a1->sin6_port == a2->sin6_port) &&
1449 !memcmp(&a1->sin6_addr, &a2->sin6_addr,
1450 sizeof (struct in6_addr)));
1451 }
1452 if (a1->sin6_family == AF_INET) {
1453 struct sockaddr_in6 *sap = a1;
1454 a1 = a2;
1455 a2 = sap;
1456 } /* assumes that AF_INET and AF_INET6 are the only possibilities */
1457 return ((a1->sin6_port == ((struct sockaddr_in *)a2)->sin_port) &&
1458 IN6_IS_ADDR_V4MAPPED(&a1->sin6_addr) &&
1459 (a1->sin6_addr.s6_addr32[3] ==
1460 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1461}