]> git.ipfire.org Git - thirdparty/glibc.git/blame - resolv/res_send.c
* locales/ks_IN: New file.
[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
UD
201
202/* Reachover. */
203
438e8239 204static void convaddr4to6(struct sockaddr_in6 *sa);
28f540f4 205
e685e07d
UD
206/* Public. */
207
28f540f4
RM
208/* int
209 * res_isourserver(ina)
210 * looks up "ina" in _res.ns_addr_list[]
211 * returns:
212 * 0 : not found
213 * >0 : found
214 * author:
215 * paul vixie, 29may94
216 */
217int
438e8239 218res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
438e8239 219{
b43b13ac 220 int ns;
28f540f4 221
438e8239 222 if (inp->sin6_family == AF_INET) {
e62b2105
UD
223 struct sockaddr_in *in4p = (struct sockaddr_in *) inp;
224 in_port_t port = in4p->sin_port;
225 in_addr_t addr = in4p->sin_addr.s_addr;
438e8239
UD
226
227 for (ns = 0; ns < MAXNS; ns++) {
228 const struct sockaddr_in *srv =
229 (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
230
231 if ((srv != NULL) && (srv->sin_family == AF_INET) &&
e62b2105 232 (srv->sin_port == port) &&
438e8239 233 (srv->sin_addr.s_addr == INADDR_ANY ||
e62b2105 234 srv->sin_addr.s_addr == addr))
438e8239
UD
235 return (1);
236 }
237 } else if (inp->sin6_family == AF_INET6) {
238 for (ns = 0; ns < MAXNS; ns++) {
239 const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
240 if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
241 (srv->sin6_port == inp->sin6_port) &&
242 !(memcmp(&srv->sin6_addr, &in6addr_any,
243 sizeof (struct in6_addr)) &&
244 memcmp(&srv->sin6_addr, &inp->sin6_addr,
245 sizeof (struct in6_addr))))
246 return (1);
247 }
248 }
b43b13ac 249 return (0);
28f540f4
RM
250}
251
252/* int
253 * res_nameinquery(name, type, class, buf, eom)
254 * look for (name,type,class) in the query section of packet (buf,eom)
66715f83 255 * requires:
b43b13ac 256 * buf + HFIXEDSZ <= eom
28f540f4
RM
257 * returns:
258 * -1 : format error
259 * 0 : not found
260 * >0 : found
261 * author:
262 * paul vixie, 29may94
263 */
264int
b43b13ac
UD
265res_nameinquery(const char *name, int type, int class,
266 const u_char *buf, const u_char *eom)
28f540f4 267{
b43b13ac 268 const u_char *cp = buf + HFIXEDSZ;
28f540f4
RM
269 int qdcount = ntohs(((HEADER*)buf)->qdcount);
270
271 while (qdcount-- > 0) {
272 char tname[MAXDNAME+1];
b43b13ac 273 int n, ttype, tclass;
28f540f4
RM
274
275 n = dn_expand(buf, eom, cp, tname, sizeof tname);
276 if (n < 0)
277 return (-1);
278 cp += n;
66715f83
UD
279 if (cp + 2 * INT16SZ > eom)
280 return (-1);
697e1628
UD
281 NS_GET16(ttype, cp);
282 NS_GET16(tclass, cp);
b43b13ac
UD
283 if (ttype == type && tclass == class &&
284 ns_samename(tname, name) == 1)
28f540f4
RM
285 return (1);
286 }
287 return (0);
288}
6f9d8e68 289libresolv_hidden_def (res_nameinquery)
28f540f4
RM
290
291/* int
292 * res_queriesmatch(buf1, eom1, buf2, eom2)
293 * is there a 1:1 mapping of (name,type,class)
294 * in (buf1,eom1) and (buf2,eom2)?
295 * returns:
296 * -1 : format error
297 * 0 : not a 1:1 mapping
298 * >0 : is a 1:1 mapping
299 * author:
300 * paul vixie, 29may94
301 */
302int
b43b13ac
UD
303res_queriesmatch(const u_char *buf1, const u_char *eom1,
304 const u_char *buf2, const u_char *eom2)
28f540f4 305{
66715f83
UD
306 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
307 return (-1);
308
b43b13ac
UD
309 /*
310 * Only header section present in replies to
311 * dynamic update packets.
312 */
e685e07d
UD
313 if ((((HEADER *)buf1)->opcode == ns_o_update) &&
314 (((HEADER *)buf2)->opcode == ns_o_update))
b43b13ac
UD
315 return (1);
316
697e1628 317 /* Note that we initially do not convert QDCOUNT to the host byte
8e45b1ac 318 order. We can compare it with the second buffer's QDCOUNT
697e1628
UD
319 value without doing this. */
320 int qdcount = ((HEADER*)buf1)->qdcount;
321 if (qdcount != ((HEADER*)buf2)->qdcount)
28f540f4 322 return (0);
697e1628
UD
323
324 qdcount = htons (qdcount);
325 const u_char *cp = buf1 + HFIXEDSZ;
326
28f540f4
RM
327 while (qdcount-- > 0) {
328 char tname[MAXDNAME+1];
b43b13ac 329 int n, ttype, tclass;
28f540f4
RM
330
331 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
332 if (n < 0)
333 return (-1);
334 cp += n;
66715f83
UD
335 if (cp + 2 * INT16SZ > eom1)
336 return (-1);
697e1628
UD
337 NS_GET16(ttype, cp);
338 NS_GET16(tclass, cp);
28f540f4
RM
339 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
340 return (0);
341 }
342 return (1);
343}
6f9d8e68 344libresolv_hidden_def (res_queriesmatch)
28f540f4
RM
345
346int
0420d888 347__libc_res_nsend(res_state statp, const u_char *buf, int buflen,
1eb946b9
UD
348 const u_char *buf2, int buflen2,
349 u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
b7da31a1 350 int *nansp2, int *resplen2)
28f540f4 351{
b7da31a1 352 int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
28f540f4 353
e685e07d
UD
354 if (statp->nscount == 0) {
355 __set_errno (ESRCH);
356 return (-1);
357 }
0420d888 358
1eb946b9 359 if (anssiz < (buf2 == NULL ? 1 : 2) * HFIXEDSZ) {
66715f83
UD
360 __set_errno (EINVAL);
361 return (-1);
362 }
0420d888 363
1eb946b9
UD
364#ifdef USE_HOOKS
365 if (__builtin_expect (statp->qhook || statp->rhook, 0)) {
366 if (anssiz < MAXPACKET && ansp) {
367 u_char *buf = malloc (MAXPACKET);
368 if (buf == NULL)
369 return (-1);
370 memcpy (buf, ans, HFIXEDSZ);
371 *ansp = buf;
372 ans = buf;
373 anssiz = MAXPACKET;
374 }
0420d888 375 }
1eb946b9 376#endif
0420d888 377
b43b13ac 378 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
3d61b63c 379 (stdout, ";; res_send()\n"), buf, buflen);
1eb946b9
UD
380 v_circuit = ((statp->options & RES_USEVC)
381 || buflen > PACKETSZ
382 || buflen2 > PACKETSZ);
28f540f4 383 gotsomewhere = 0;
28f540f4 384 terrno = ETIMEDOUT;
28f540f4 385
b43b13ac 386 /*
e685e07d
UD
387 * If the ns_addr_list in the resolver context has changed, then
388 * invalidate our cached copy and the associated timing data.
b43b13ac 389 */
03fbfeb5 390 if (EXT(statp).nsinit) {
e685e07d
UD
391 int needclose = 0;
392
393 if (EXT(statp).nscount != statp->nscount)
394 needclose++;
395 else
b64e1566
UD
396 for (ns = 0; ns < MAXNS; ns++) {
397 unsigned int map = EXT(statp).nsmap[ns];
398 if (map < MAXNS
399 && !sock_eq((struct sockaddr_in6 *)
400 &statp->nsaddr_list[map],
401 EXT(statp).nsaddrs[ns]))
438e8239 402 {
e685e07d
UD
403 needclose++;
404 break;
405 }
b64e1566 406 }
e685e07d 407 if (needclose)
cb07f6f6 408 __res_iclose(statp, false);
e685e07d
UD
409 }
410
411 /*
412 * Maybe initialize our private copy of the ns_addr_list.
413 */
03fbfeb5 414 if (EXT(statp).nsinit == 0) {
b64e1566
UD
415 unsigned char map[MAXNS];
416
417 memset (map, MAXNS, sizeof (map));
418 for (n = 0; n < MAXNS; n++) {
419 ns = EXT(statp).nsmap[n];
420 if (ns < statp->nscount)
421 map[ns] = n;
422 else if (ns < MAXNS) {
423 free(EXT(statp).nsaddrs[n]);
424 EXT(statp).nsaddrs[n] = NULL;
425 EXT(statp).nsmap[n] = MAXNS;
426 }
427 }
428 n = statp->nscount;
429 if (statp->nscount > EXT(statp).nscount)
430 for (n = EXT(statp).nscount, ns = 0;
431 n < statp->nscount; n++) {
432 while (ns < MAXNS
433 && EXT(statp).nsmap[ns] != MAXNS)
434 ns++;
435 if (ns == MAXNS)
436 break;
437 EXT(statp).nsmap[ns] = n;
438 map[n] = ns++;
439 }
440 EXT(statp).nscount = n;
441 for (ns = 0; ns < EXT(statp).nscount; ns++) {
442 n = map[ns];
438e8239
UD
443 if (EXT(statp).nsaddrs[n] == NULL)
444 EXT(statp).nsaddrs[n] =
445 malloc(sizeof (struct sockaddr_in6));
446 if (EXT(statp).nsaddrs[n] != NULL) {
0f8f993c
UD
447 memset (mempcpy(EXT(statp).nsaddrs[n],
448 &statp->nsaddr_list[ns],
449 sizeof (struct sockaddr_in)),
450 '\0',
451 sizeof (struct sockaddr_in6)
452 - sizeof (struct sockaddr_in));
438e8239
UD
453 EXT(statp).nssocks[n] = -1;
454 n++;
455 }
b64e1566 456 }
b64e1566 457 EXT(statp).nsinit = 1;
e685e07d
UD
458 }
459
460 /*
461 * Some resolvers want to even out the load on their nameservers.
462 * Note that RES_BLAST overrides RES_ROTATE.
463 */
1eb946b9 464 if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
e685e07d 465 (statp->options & RES_BLAST) == 0) {
438e8239 466 struct sockaddr_in6 *ina;
b64e1566 467 unsigned int map;
438e8239 468
b64e1566
UD
469 n = 0;
470 while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
471 n++;
472 if (n < MAXNS) {
473 ina = EXT(statp).nsaddrs[n];
474 map = EXT(statp).nsmap[n];
475 for (;;) {
476 ns = n + 1;
477 while (ns < MAXNS
478 && EXT(statp).nsmap[ns] == MAXNS)
479 ns++;
480 if (ns == MAXNS)
481 break;
482 EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
483 EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
484 n = ns;
485 }
486 EXT(statp).nsaddrs[n] = ina;
487 EXT(statp).nsmap[n] = map;
488 }
b43b13ac 489 }
30f9ca19 490
28f540f4 491 /*
e685e07d 492 * Send request, RETRY times, or until successful.
28f540f4 493 */
b43b13ac 494 for (try = 0; try < statp->retry; try++) {
438e8239 495 for (ns = 0; ns < MAXNS; ns++)
438e8239 496 {
438e8239
UD
497 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
498
499 if (nsap == NULL)
500 goto next_ns;
1eb946b9
UD
501 same_ns:
502#ifdef USE_HOOKS
503 if (__builtin_expect (statp->qhook != NULL, 0)) {
28f540f4
RM
504 int done = 0, loops = 0;
505
506 do {
507 res_sendhookact act;
508
25337753
UD
509 struct sockaddr_in *nsap4;
510 nsap4 = (struct sockaddr_in *) nsap;
511 act = (*statp->qhook)(&nsap4, &buf, &buflen,
438e8239 512 ans, anssiz, &resplen);
25337753 513 nsap = (struct sockaddr_in6 *) nsap4;
28f540f4
RM
514 switch (act) {
515 case res_goahead:
516 done = 1;
517 break;
518 case res_nextns:
cb07f6f6 519 __res_iclose(statp, false);
28f540f4
RM
520 goto next_ns;
521 case res_done:
b43b13ac 522 return (resplen);
28f540f4
RM
523 case res_modified:
524 /* give the hook another try */
525 if (++loops < 42) /*doug adams*/
526 break;
527 /*FALLTHROUGH*/
528 case res_error:
529 /*FALLTHROUGH*/
530 default:
b43b13ac 531 return (-1);
28f540f4
RM
532 }
533 } while (!done);
534 }
1eb946b9 535#endif
28f540f4 536
3bc99c11 537#ifdef DEBUG
020a9a23 538 char tmpbuf[40];
3bc99c11 539#endif
020a9a23
UD
540 Dprint(statp->options & RES_DEBUG,
541 (stdout, ";; Querying server (# %d) address = %s\n",
542 ns + 1, inet_ntop(AF_INET6, &nsap->sin6_addr,
543 tmpbuf, sizeof (tmpbuf))));
28f540f4 544
1eb946b9 545 if (__builtin_expect (v_circuit, 0)) {
b43b13ac
UD
546 /* Use VC; at most one attempt per server. */
547 try = statp->retry;
1eb946b9
UD
548 n = send_vc(statp, buf, buflen, buf2, buflen2,
549 &ans, &anssiz, &terrno,
b7da31a1 550 ns, ansp, ansp2, nansp2, resplen2);
e685e07d
UD
551 if (n < 0)
552 return (-1);
553 if (n == 0)
28f540f4 554 goto next_ns;
28f540f4 555 } else {
e685e07d 556 /* Use datagrams. */
1eb946b9
UD
557 n = send_dg(statp, buf, buflen, buf2, buflen2,
558 &ans, &anssiz, &terrno,
559 ns, &v_circuit, &gotsomewhere, ansp,
b7da31a1 560 ansp2, nansp2, resplen2);
e685e07d
UD
561 if (n < 0)
562 return (-1);
563 if (n == 0)
b43b13ac 564 goto next_ns;
e685e07d 565 if (v_circuit)
1eb946b9 566 // XXX Check whether both requests failed or
b7da31a1 567 // XXX whether one has been answered successfully
28f540f4 568 goto same_ns;
e685e07d
UD
569 }
570
1eb946b9
UD
571 resplen = n;
572
b43b13ac
UD
573 Dprint((statp->options & RES_DEBUG) ||
574 ((statp->pfcode & RES_PRF_REPLY) &&
575 (statp->pfcode & RES_PRF_HEAD1)),
a4219bc4 576 (stdout, ";; got answer:\n"));
e685e07d 577
b43b13ac
UD
578 DprintQ((statp->options & RES_DEBUG) ||
579 (statp->pfcode & RES_PRF_REPLY),
020a9a23 580 (stdout, "%s", ""),
e685e07d 581 ans, (resplen > anssiz) ? anssiz : resplen);
1eb946b9
UD
582 if (buf2 != NULL)
583 DprintQ((statp->options & RES_DEBUG) ||
584 (statp->pfcode & RES_PRF_REPLY),
585 (stdout, "%s", ""),
b7da31a1 586 *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2);
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,
b7da31a1 890 (rlen > *thisanssiz) ? *thisanssiz: 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
e685e07d 911send_dg(res_state statp,
1eb946b9
UD
912 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
913 u_char **ansp, int *anssizp,
914 int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
915 u_char **ansp2, int *anssizp2, int *resplen2)
e685e07d
UD
916{
917 const HEADER *hp = (HEADER *) buf;
1eb946b9 918 const HEADER *hp2 = (HEADER *) buf2;
0420d888 919 u_char *ans = *ansp;
1eb946b9 920 int orig_anssizp = *anssizp;
438e8239 921 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
e685e07d 922 struct timespec now, timeout, finish;
e685e07d
UD
923 struct pollfd pfd[1];
924 int ptimeout;
438e8239 925 struct sockaddr_in6 from;
9cfe5381 926 int resplen, seconds, n;
e685e07d
UD
927
928 if (EXT(statp).nssocks[ns] == -1) {
438e8239 929 /* only try IPv6 if IPv6 NS and if not failed before */
ae1ad3ae 930 if ((EXT(statp).nscount6 > 0) && !statp->ipv6_unavail) {
9744268c
UD
931 if (__have_o_nonblock >= 0) {
932 EXT(statp).nssocks[ns] =
933 socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK,
934 0);
200da00a 935#ifndef __ASSUME_SOCK_CLOEXEC
9744268c
UD
936 if (__have_o_nonblock == 0)
937 __have_o_nonblock
938 = (EXT(statp).nssocks[ns] == -1
939 && errno == EINVAL ? -1 : 1);
940#endif
941 }
942 if (__have_o_nonblock < 0)
943 EXT(statp).nssocks[ns] =
944 socket(PF_INET6, SOCK_DGRAM, 0);
ae1ad3ae
UD
945 if (EXT(statp).nssocks[ns] < 0)
946 statp->ipv6_unavail = errno == EAFNOSUPPORT;
947 /* If IPv6 socket and nsap is IPv4, make it
948 IPv4-mapped */
949 else if (nsap->sin6_family == AF_INET)
950 convaddr4to6(nsap);
438e8239 951 }
9744268c
UD
952 if (EXT(statp).nssocks[ns] < 0) {
953 if (__have_o_nonblock >= 0) {
954 EXT(statp).nssocks[ns]
955 = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK,
956 0);
200da00a 957#ifndef __ASSUME_SOCK_CLOEXEC
9744268c
UD
958 if (__have_o_nonblock == 0)
959 __have_o_nonblock
960 = (EXT(statp).nssocks[ns] == -1
961 && errno == EINVAL ? -1 : 1);
962#endif
963 }
964 if (__have_o_nonblock < 0)
965 EXT(statp).nssocks[ns]
966 = socket(PF_INET, SOCK_DGRAM, 0);
967 }
e685e07d
UD
968 if (EXT(statp).nssocks[ns] < 0) {
969 *terrno = errno;
970 Perror(statp, stderr, "socket(dg)", errno);
971 return (-1);
972 }
ae1ad3ae 973
e685e07d
UD
974 /*
975 * On a 4.3BSD+ machine (client and server,
976 * actually), sending to a nameserver datagram
977 * port with no nameserver will cause an
978 * ICMP port unreachable message to be returned.
979 * If our datagram socket is "connected" to the
980 * server, we get an ECONNREFUSED error on the next
981 * socket operation, and select returns if the
982 * error message is received. We can thus detect
983 * the absence of a nameserver without timing out.
984 */
985 if (connect(EXT(statp).nssocks[ns], (struct sockaddr *)nsap,
986 sizeof *nsap) < 0) {
020a9a23
UD
987 Aerror(statp, stderr, "connect(dg)", errno,
988 (struct sockaddr *) nsap);
cb07f6f6 989 __res_iclose(statp, false);
e685e07d
UD
990 return (0);
991 }
9744268c
UD
992 if (__have_o_nonblock < 0) {
993 /* Make socket non-blocking. */
994 int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL);
995 if (fl != -1)
996 __fcntl (EXT(statp).nssocks[ns], F_SETFL,
997 fl | O_NONBLOCK);
998 Dprint(statp->options & RES_DEBUG,
999 (stdout, ";; new DG socket\n"))
1000 }
e685e07d 1001 }
17a10319 1002
f433b06b
UD
1003 /*
1004 * Compute time for the total operation.
1005 */
1006 seconds = (statp->retrans << ns);
1007 if (ns > 0)
1008 seconds /= statp->nscount;
1009 if (seconds <= 0)
1010 seconds = 1;
1011 evNowTime(&now);
1012 evConsTime(&timeout, seconds, 0);
1013 evAddTime(&finish, &now, &timeout);
1014 int need_recompute = 0;
17a10319 1015 int nwritten = 0;
1eb946b9
UD
1016 int recvresp1 = 0;
1017 int recvresp2 = buf2 == NULL;
17a10319
UD
1018 pfd[0].fd = EXT(statp).nssocks[ns];
1019 pfd[0].events = POLLOUT;
5908f779
UD
1020 if (resplen2 != NULL)
1021 *resplen2 = 0;
17a10319
UD
1022 wait:
1023 if (need_recompute) {
8e45b1ac 1024 recompute_resend:
17a10319
UD
1025 evNowTime(&now);
1026 if (evCmpTime(finish, now) <= 0) {
8e45b1ac
UD
1027 poll_err_out:
1028 Perror(statp, stderr, "poll", errno);
1029 err_out:
cb07f6f6 1030 __res_iclose(statp, false);
17a10319
UD
1031 return (0);
1032 }
1033 evSubTime(&timeout, &finish, &now);
1034 }
f433b06b
UD
1035 /* Convert struct timespec in milliseconds. */
1036 ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
1037
17a10319
UD
1038 n = 0;
1039 if (nwritten == 0)
1040 n = __poll (pfd, 1, 0);
f433b06b
UD
1041 if (__builtin_expect (n == 0, 0)) {
1042 n = __poll (pfd, 1, ptimeout);
1043 need_recompute = 1;
1044 }
f433b06b 1045 if (n == 0) {
e2003883 1046 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
332c4465 1047 if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
e2003883
UD
1048 {
1049 *resplen2 = 1;
1050 return resplen;
1051 }
5908f779 1052
f433b06b
UD
1053 *gotsomewhere = 1;
1054 return (0);
1055 }
1056 if (n < 0) {
8e45b1ac
UD
1057 if (errno == EINTR)
1058 goto recompute_resend;
1059
1060 goto poll_err_out;
f433b06b
UD
1061 }
1062 __set_errno (0);
17a10319 1063 if (pfd[0].revents & POLLOUT) {
1eb946b9
UD
1064 ssize_t sr;
1065 if (nwritten != 0)
1066 sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
1067 else
1068 sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
1069
1070 if (sr != buflen) {
17a10319
UD
1071 if (errno == EINTR || errno == EAGAIN)
1072 goto recompute_resend;
1073 Perror(statp, stderr, "send", errno);
8e45b1ac 1074 goto err_out;
f433b06b 1075 }
1eb946b9
UD
1076 if (nwritten != 0 || buf2 == NULL)
1077 pfd[0].events = POLLIN;
1078 else
1079 pfd[0].events = POLLIN | POLLOUT;
17a10319
UD
1080 ++nwritten;
1081 goto wait;
8aeb5058 1082 } else if (pfd[0].revents & POLLIN) {
1eb946b9
UD
1083 int *thisanssizp;
1084 u_char **thisansp;
1085 int *thisresplenp;
1086
1087 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1088 thisanssizp = anssizp;
1089 thisansp = anscp ?: ansp;
1090 assert (anscp != NULL || ansp2 == NULL);
1091 thisresplenp = &resplen;
1092 } else {
1093 if (*anssizp != MAXPACKET) {
1094 /* No buffer allocated for the first
1095 reply. We can try to use the rest
1096 of the user-provided buffer. */
ad12e635 1097#ifdef _STRING_ARCH_unaligned
1eb946b9
UD
1098 *anssizp2 = orig_anssizp - resplen;
1099 *ansp2 = *ansp + resplen;
ad12e635
UD
1100#else
1101 int aligned_resplen
1102 = ((resplen + __alignof__ (HEADER) - 1)
1103 & ~(__alignof__ (HEADER) - 1));
1104 *anssizp2 = orig_anssizp - aligned_resplen;
1105 *ansp2 = *ansp + aligned_resplen;
1106#endif
1eb946b9
UD
1107 } else {
1108 /* The first reply did not fit into the
1109 user-provided buffer. Maybe the second
1110 answer will. */
1111 *anssizp2 = orig_anssizp;
1112 *ansp2 = *ansp;
1113 }
1114
1115 thisanssizp = anssizp2;
1116 thisansp = ansp2;
1117 thisresplenp = resplen2;
1118 }
1119
1120 if (*thisanssizp < MAXPACKET
1121 /* Yes, we test ANSCP here. If we have two buffers
1122 both will be allocatable. */
17a10319 1123 && anscp
1eb946b9
UD
1124 && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
1125 || *thisanssizp < *thisresplenp)) {
1126 u_char *newp = malloc (MAXPACKET);
1127 if (newp != NULL) {
17a10319 1128 *anssizp = MAXPACKET;
1eb946b9 1129 *thisansp = ans = newp;
17a10319
UD
1130 }
1131 }
1eb946b9
UD
1132 HEADER *anhp = (HEADER *) *thisansp;
1133 socklen_t fromlen = sizeof(struct sockaddr_in6);
1134 assert (sizeof(from) <= fromlen);
1135 *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
1136 *thisanssizp, 0,
1137 (struct sockaddr *)&from, &fromlen);
b7da31a1 1138 if (__builtin_expect (*thisresplenp <= 0, 0)) {
17a10319
UD
1139 if (errno == EINTR || errno == EAGAIN) {
1140 need_recompute = 1;
1141 goto wait;
1142 }
1143 Perror(statp, stderr, "recvfrom", errno);
8e45b1ac 1144 goto err_out;
17a10319 1145 }
e685e07d 1146 *gotsomewhere = 1;
b7da31a1 1147 if (__builtin_expect (*thisresplenp < HFIXEDSZ, 0)) {
17a10319
UD
1148 /*
1149 * Undersized message.
1150 */
1151 Dprint(statp->options & RES_DEBUG,
1152 (stdout, ";; undersized: %d\n",
1eb946b9 1153 *thisresplen));
17a10319 1154 *terrno = EMSGSIZE;
8e45b1ac 1155 goto err_out;
17a10319 1156 }
1eb946b9
UD
1157 if ((recvresp1 || hp->id != anhp->id)
1158 && (recvresp2 || hp2->id != anhp->id)) {
17a10319
UD
1159 /*
1160 * response from old query, ignore it.
1161 * XXX - potential security hazard could
1162 * be detected here.
1163 */
1164 DprintQ((statp->options & RES_DEBUG) ||
1165 (statp->pfcode & RES_PRF_REPLY),
1166 (stdout, ";; old answer:\n"),
1eb946b9
UD
1167 thisansp,
1168 (*thisresplen > *thisanssiz)
1169 ? *thisanssiz : *thisresplen);
f433b06b 1170 goto wait;
e685e07d 1171 }
17a10319
UD
1172 if (!(statp->options & RES_INSECURE1) &&
1173 !res_ourserver_p(statp, &from)) {
1174 /*
1175 * response from wrong server? ignore it.
1176 * XXX - potential security hazard could
1177 * be detected here.
1178 */
1179 DprintQ((statp->options & RES_DEBUG) ||
1180 (statp->pfcode & RES_PRF_REPLY),
1181 (stdout, ";; not our server:\n"),
1eb946b9
UD
1182 thisansp,
1183 (*thisresplen > *thisanssiz)
1184 ? *thisanssiz : *thisresplen);
17a10319 1185 goto wait;
0420d888 1186 }
2bbb7d5b
UD
1187#ifdef RES_USE_EDNS0
1188 if (anhp->rcode == FORMERR
1189 && (statp->options & RES_USE_EDNS0) != 0U) {
1190 /*
1eb946b9 1191 * Do not retry if the server does not understand
2bbb7d5b
UD
1192 * EDNS0. The case has to be captured here, as
1193 * FORMERR packet do not carry query section, hence
1194 * res_queriesmatch() returns 0.
1195 */
1196 DprintQ(statp->options & RES_DEBUG,
1197 (stdout,
1198 "server rejected query with EDNS0:\n"),
1eb946b9
UD
1199 thisans,
1200 (*thisresplen > *thisanssiz)
1201 ? *thisanssiz : *thisresplen);
2bbb7d5b
UD
1202 /* record the error */
1203 statp->_flags |= RES_F_EDNS0ERR;
1204 goto err_out;
1205 }
1206#endif
1eb946b9
UD
1207 if (!(statp->options & RES_INSECURE2)
1208 && (recvresp1 || !res_queriesmatch(buf, buf + buflen,
1209 *thisansp,
1210 *thisansp
1211 + *thisanssizp))
1212 && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2,
1213 *thisansp,
1214 *thisansp
1215 + *thisanssizp))) {
17a10319
UD
1216 /*
1217 * response contains wrong query? ignore it.
1218 * XXX - potential security hazard could
1219 * be detected here.
1220 */
1221 DprintQ((statp->options & RES_DEBUG) ||
1222 (statp->pfcode & RES_PRF_REPLY),
1223 (stdout, ";; wrong query name:\n"),
1eb946b9
UD
1224 thisansp,
1225 (*thisresplen > *thisanssiz)
1226 ? *thisanssiz : *thisresplen);
f433b06b
UD
1227 goto wait;
1228 }
17a10319
UD
1229 if (anhp->rcode == SERVFAIL ||
1230 anhp->rcode == NOTIMP ||
1231 anhp->rcode == REFUSED) {
1232 DprintQ(statp->options & RES_DEBUG,
1233 (stdout, "server rejected query:\n"),
1eb946b9
UD
1234 thisansp,
1235 (*thisresplen > *thisanssiz)
1236 ? *thisanssiz : *thisresplen);
e2003883
UD
1237
1238 if (recvresp1 || (buf2 != NULL && recvresp2))
1239 {
1240 *resplen2 = 1;
1241 return resplen;
1242 }
1243 if (buf2 != NULL)
1244 {
1245 /* We are waiting for a possible second reply. */
1246 resplen = 1;
1247 if (hp->id == anhp->id)
1248 recvresp1 = 1;
1249 else
1250 recvresp2 = 1;
1251
1252 goto wait;
1253 }
1254
359bb2ef 1255 next_ns:
cb07f6f6 1256 __res_iclose(statp, false);
17a10319
UD
1257 /* don't retry if called from dig */
1258 if (!statp->pfcode)
1259 return (0);
1260 }
359bb2ef
UD
1261 if (anhp->rcode == NOERROR && anhp->ancount == 0
1262 && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
1263 DprintQ(statp->options & RES_DEBUG,
1264 (stdout, "referred query:\n"),
1eb946b9
UD
1265 thisansp,
1266 (*thisresplen > *thisanssiz)
1267 ? *thisanssiz : *thisresplen);
359bb2ef
UD
1268 goto next_ns;
1269 }
17a10319
UD
1270 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1271 /*
1272 * To get the rest of answer,
1273 * use TCP with same server.
1274 */
1275 Dprint(statp->options & RES_DEBUG,
1276 (stdout, ";; truncated answer\n"));
1277 *v_circuit = 1;
cb07f6f6 1278 __res_iclose(statp, false);
1eb946b9
UD
1279 // XXX if we have received one reply we could
1280 // XXX use it and not repeat it over TCP...
17a10319
UD
1281 return (1);
1282 }
1eb946b9
UD
1283 /* Mark which reply we received. */
1284 if (recvresp1 == 0 && hp->id == anhp->id)
1285 recvresp1 = 1;
1286 else
1287 recvresp2 = 1;
1288 /* Repeat waiting if we have a second answer to arrive. */
1289 if ((recvresp1 & recvresp2) == 0)
1290 goto wait;
e685e07d 1291 /*
17a10319
UD
1292 * All is well, or the error is fatal. Signal that the
1293 * next nameserver ought not be tried.
e685e07d 1294 */
17a10319 1295 return (resplen);
8aeb5058
UD
1296 } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
1297 /* Something went wrong. We can stop trying. */
8e45b1ac 1298 goto err_out;
e685e07d 1299 }
9cfe5381
RM
1300 else {
1301 /* poll should not have returned > 0 in this case. */
1302 abort ();
1303 }
e685e07d
UD
1304}
1305
1306#ifdef DEBUG
1307static void
1308Aerror(const res_state statp, FILE *file, const char *string, int error,
020a9a23 1309 const struct sockaddr *address)
e685e07d
UD
1310{
1311 int save = errno;
1312
1313 if ((statp->options & RES_DEBUG) != 0) {
020a9a23 1314 char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
e685e07d
UD
1315
1316 fprintf(file, "res_send: %s ([%s].%u): %s\n",
1317 string,
e2a99d8e
UD
1318 (address->sa_family == AF_INET
1319 ? inet_ntop(address->sa_family,
1320 &((const struct sockaddr_in *) address)->sin_addr,
1321 tmp, sizeof tmp)
1322 : inet_ntop(address->sa_family,
1323 &((const struct sockaddr_in6 *) address)->sin6_addr,
1324 tmp, sizeof tmp)),
020a9a23
UD
1325 (address->sa_family == AF_INET
1326 ? ntohs(((struct sockaddr_in *) address)->sin_port)
1327 : address->sa_family == AF_INET6
1328 ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
1329 : 0),
e685e07d
UD
1330 strerror(error));
1331 }
1332 __set_errno (save);
1333}
1334
1335static void
1336Perror(const res_state statp, FILE *file, const char *string, int error) {
1337 int save = errno;
1338
1339 if ((statp->options & RES_DEBUG) != 0)
1340 fprintf(file, "res_send: %s: %s\n",
1341 string, strerror(error));
1342 __set_errno (save);
1343}
1344#endif
1345
1346static int
438e8239
UD
1347sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
1348 if (a1->sin6_family == a2->sin6_family) {
1349 if (a1->sin6_family == AF_INET)
1350 return ((((struct sockaddr_in *)a1)->sin_port ==
1351 ((struct sockaddr_in *)a2)->sin_port) &&
1352 (((struct sockaddr_in *)a1)->sin_addr.s_addr ==
1353 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1354 else
1355 return ((a1->sin6_port == a2->sin6_port) &&
1356 !memcmp(&a1->sin6_addr, &a2->sin6_addr,
1357 sizeof (struct in6_addr)));
1358 }
1359 if (a1->sin6_family == AF_INET) {
1360 struct sockaddr_in6 *sap = a1;
1361 a1 = a2;
1362 a2 = sap;
1363 } /* assumes that AF_INET and AF_INET6 are the only possibilities */
1364 return ((a1->sin6_port == ((struct sockaddr_in *)a2)->sin_port) &&
1365 IN6_IS_ADDR_V4MAPPED(&a1->sin6_addr) &&
1366 (a1->sin6_addr.s6_addr32[3] ==
1367 ((struct sockaddr_in *)a2)->sin_addr.s_addr));
1368}
438e8239 1369
438e8239
UD
1370/*
1371 * Converts IPv4 family, address and port to
1372 * IPv6 family, IPv4-mapped IPv6 address and port.
1373 */
1374static void
1375convaddr4to6(struct sockaddr_in6 *sa)
1376{
e62b2105
UD
1377 struct sockaddr_in *sa4p = (struct sockaddr_in *) sa;
1378 in_port_t port = sa4p->sin_port;
1379 in_addr_t addr = sa4p->sin_addr.s_addr;
438e8239
UD
1380
1381 sa->sin6_family = AF_INET6;
e62b2105 1382 sa->sin6_port = port;
438e8239
UD
1383 sa->sin6_addr.s6_addr32[0] = 0;
1384 sa->sin6_addr.s6_addr32[1] = 0;
1385 sa->sin6_addr.s6_addr32[2] = htonl(0xFFFF);
e62b2105 1386 sa->sin6_addr.s6_addr32[3] = addr;
438e8239 1387}