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