blob: 5a79f2898cce5a4f2718e94e0393457042c7828d [file] [log] [blame]
Bernie Innocenti55864192018-08-30 04:05:20 +09001/* $NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $ */
2
3/*
4 * Copyright (c) 1985, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36/*
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 */
55
56/*
57 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
58 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
59 *
60 * Permission to use, copy, modify, and distribute this software for any
61 * purpose with or without fee is hereby granted, provided that the above
62 * copyright notice and this permission notice appear in all copies.
63 *
64 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
65 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
66 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
67 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
68 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
69 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
70 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
71 */
72
Bernie Innocenti55864192018-08-30 04:05:20 +090073/*
74 * Send query to name server and wait for reply.
75 */
76
Bernie Innocentie9ba09c2018-09-12 23:20:10 +090077constexpr bool kVerboseLogging = false;
78#define LOG_TAG "res_send"
79
Bernie Innocenti55864192018-08-30 04:05:20 +090080#include <sys/param.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090081#include <sys/socket.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090082#include <sys/time.h>
83#include <sys/types.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090084#include <sys/uio.h>
85
Bernie Innocenti55864192018-08-30 04:05:20 +090086#include <arpa/inet.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090087#include <arpa/nameser.h>
88#include <netinet/in.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090089
90#include <errno.h>
91#include <fcntl.h>
92#include <netdb.h>
93#include <poll.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090094#include <signal.h>
95#include <stdio.h>
96#include <stdlib.h>
97#include <string.h>
98#include <time.h>
99#include <unistd.h>
100
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900101#include <android-base/logging.h>
Bernie Innocenti55864192018-08-30 04:05:20 +0900102
Bernie Innocenti189eb502018-10-01 23:10:18 +0900103#include "netd_resolv/resolv.h"
104#include "netd_resolv/stats.h"
Bernie Innocenti2fd418e2018-08-30 12:04:03 +0900105#include "private/android_filesystem_config.h"
Bernie Innocenti189eb502018-10-01 23:10:18 +0900106#include "res_state_ext.h"
Bernie Innocenti2fd418e2018-08-30 12:04:03 +0900107#include "resolv_cache.h"
Bernie Innocenti2fd418e2018-08-30 12:04:03 +0900108#include "resolv_private.h"
Bernie Innocenti2fd418e2018-08-30 12:04:03 +0900109
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900110
111#define VLOG if (!kVerboseLogging) {} else LOG(INFO)
112
113#ifndef RESOLV_ALLOW_VERBOSE_LOGGING
114static_assert(kVerboseLogging == false,
115 "Verbose logging floods logs at high-rate and exposes privacy-sensitive information. "
116 "Do not enable in release builds.");
Bernie Innocenti55864192018-08-30 04:05:20 +0900117#endif
Bernie Innocenti2fd418e2018-08-30 12:04:03 +0900118
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900119#ifndef DEBUG
120#define Dprint(cond, args) /*empty*/
121#define DprintQ(cond, args, query, size) /*empty*/
122#else
123// TODO: convert to Android logging
124#define Dprint(cond, args) \
125 if (cond) { \
126 fprintf args; \
127 } else { \
128 }
129#define DprintQ(cond, args, query, size) \
130 if (cond) { \
131 fprintf args; \
132 res_pquery(statp, query, size, stdout); \
133 } else { \
134 }
135#endif // DEBUG
Bernie Innocenti55864192018-08-30 04:05:20 +0900136
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900137static int get_salen(const struct sockaddr*);
138static struct sockaddr* get_nsaddr(res_state, size_t);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900139static int send_vc(res_state, struct __res_params* params, const u_char*, int, u_char*, int, int*,
140 int, time_t*, int*, int*);
141static int send_dg(res_state, struct __res_params* params, const u_char*, int, u_char*, int, int*,
142 int, int*, int*, time_t*, int*, int*);
143static void Aerror(const res_state, FILE*, const char*, int, const struct sockaddr*, int);
144static void Perror(const res_state, FILE*, const char*, int);
145static int sock_eq(struct sockaddr*, struct sockaddr*);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900146static int connect_with_timeout(int sock, const struct sockaddr* nsap, socklen_t salen,
147 const struct timespec timeout);
Bernie Innocenti55864192018-08-30 04:05:20 +0900148static int retrying_poll(const int sock, short events, const struct timespec* finish);
149
150/* BIONIC-BEGIN: implement source port randomization */
Bernie Innocenti55864192018-08-30 04:05:20 +0900151
Bernie Innocentif89b3512018-08-30 07:34:37 +0900152// BEGIN: Code copied from ISC eventlib
153// TODO: move away from this code
154
155#define BILLION 1000000000
156
157static struct timespec evConsTime(time_t sec, long nsec) {
158 struct timespec x;
159
160 x.tv_sec = sec;
161 x.tv_nsec = nsec;
162 return (x);
163}
164
165static struct timespec evAddTime(struct timespec addend1, struct timespec addend2) {
166 struct timespec x;
167
168 x.tv_sec = addend1.tv_sec + addend2.tv_sec;
169 x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec;
170 if (x.tv_nsec >= BILLION) {
171 x.tv_sec++;
172 x.tv_nsec -= BILLION;
173 }
174 return (x);
175}
176
177static struct timespec evSubTime(struct timespec minuend, struct timespec subtrahend) {
178 struct timespec x;
179
180 x.tv_sec = minuend.tv_sec - subtrahend.tv_sec;
181 if (minuend.tv_nsec >= subtrahend.tv_nsec)
182 x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec;
183 else {
184 x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec;
185 x.tv_sec--;
186 }
187 return (x);
188}
189
190static int evCmpTime(struct timespec a, struct timespec b) {
191#define SGN(x) ((x) < 0 ? (-1) : (x) > 0 ? (1) : (0));
192 time_t s = a.tv_sec - b.tv_sec;
193 long n;
194
195 if (s != 0) return SGN(s);
196
197 n = a.tv_nsec - b.tv_nsec;
198 return SGN(n);
199}
200
Bernie Innocentif89b3512018-08-30 07:34:37 +0900201static struct timespec evNowTime(void) {
Bernie Innocentif89b3512018-08-30 07:34:37 +0900202 struct timespec tsnow;
Bernie Innocenti357339c2018-08-31 16:11:41 +0900203 clock_gettime(CLOCK_REALTIME, &tsnow);
204 return tsnow;
Bernie Innocentif89b3512018-08-30 07:34:37 +0900205}
206
207static struct iovec evConsIovec(void* buf, size_t cnt) {
208 struct iovec ret;
209
210 memset(&ret, 0xf5, sizeof ret);
211 ret.iov_base = buf;
212 ret.iov_len = cnt;
Bernie Innocenti357339c2018-08-31 16:11:41 +0900213 return ret;
Bernie Innocentif89b3512018-08-30 07:34:37 +0900214}
215
216// END: Code copied from ISC eventlib
217
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900218static int random_bind(int s, int family) {
nuccachene172a4e2018-10-23 17:10:58 +0800219 sockaddr_union u;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900220 int j;
221 socklen_t slen;
Bernie Innocenti55864192018-08-30 04:05:20 +0900222
223 /* clear all, this also sets the IP4/6 address to 'any' */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900224 memset(&u, 0, sizeof u);
Bernie Innocenti55864192018-08-30 04:05:20 +0900225
226 switch (family) {
227 case AF_INET:
228 u.sin.sin_family = family;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900229 slen = sizeof u.sin;
Bernie Innocenti55864192018-08-30 04:05:20 +0900230 break;
231 case AF_INET6:
232 u.sin6.sin6_family = family;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900233 slen = sizeof u.sin6;
Bernie Innocenti55864192018-08-30 04:05:20 +0900234 break;
235 default:
236 errno = EPROTO;
237 return -1;
238 }
239
240 /* first try to bind to a random source port a few times */
241 for (j = 0; j < 10; j++) {
242 /* find a random port between 1025 .. 65534 */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900243 int port = 1025 + (res_randomid() % (65535 - 1025));
Bernie Innocenti55864192018-08-30 04:05:20 +0900244 if (family == AF_INET)
245 u.sin.sin_port = htons(port);
246 else
247 u.sin6.sin6_port = htons(port);
248
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900249 if (!bind(s, &u.sa, slen)) return 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900250 }
251
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900252 // nothing after 10 attempts, our network table is probably busy
253 // let the system decide which port is best
Bernie Innocenti55864192018-08-30 04:05:20 +0900254 if (family == AF_INET)
255 u.sin.sin_port = 0;
256 else
257 u.sin6.sin6_port = 0;
258
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900259 return bind(s, &u.sa, slen);
Bernie Innocenti55864192018-08-30 04:05:20 +0900260}
261/* BIONIC-END */
262
Bernie Innocenti55864192018-08-30 04:05:20 +0900263/* int
264 * res_isourserver(ina)
265 * looks up "ina" in _res.ns_addr_list[]
266 * returns:
267 * 0 : not found
268 * >0 : found
269 * author:
270 * paul vixie, 29may94
271 */
Bernie Innocenti4acba1a2018-09-26 11:52:04 +0900272static int res_ourserver_p(const res_state statp, const sockaddr* sa) {
273 const sockaddr_in *inp, *srv;
274 const sockaddr_in6 *in6p, *srv6;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900275 int ns;
Bernie Innocenti55864192018-08-30 04:05:20 +0900276
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900277 switch (sa->sa_family) {
278 case AF_INET:
279 inp = (const struct sockaddr_in*) (const void*) sa;
280 for (ns = 0; ns < statp->nscount; ns++) {
281 srv = (struct sockaddr_in*) (void*) get_nsaddr(statp, (size_t) ns);
282 if (srv->sin_family == inp->sin_family && srv->sin_port == inp->sin_port &&
283 (srv->sin_addr.s_addr == INADDR_ANY ||
284 srv->sin_addr.s_addr == inp->sin_addr.s_addr))
Bernie Innocenti4acba1a2018-09-26 11:52:04 +0900285 return 1;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900286 }
287 break;
288 case AF_INET6:
Ken Chencf6ded62018-10-16 23:12:09 +0800289 if (statp->_u._ext.ext == NULL) break;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900290 in6p = (const struct sockaddr_in6*) (const void*) sa;
291 for (ns = 0; ns < statp->nscount; ns++) {
292 srv6 = (struct sockaddr_in6*) (void*) get_nsaddr(statp, (size_t) ns);
293 if (srv6->sin6_family == in6p->sin6_family && srv6->sin6_port == in6p->sin6_port &&
Bernie Innocenti55864192018-08-30 04:05:20 +0900294#ifdef HAVE_SIN6_SCOPE_ID
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900295 (srv6->sin6_scope_id == 0 || srv6->sin6_scope_id == in6p->sin6_scope_id) &&
Bernie Innocenti55864192018-08-30 04:05:20 +0900296#endif
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900297 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
298 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
Bernie Innocenti4acba1a2018-09-26 11:52:04 +0900299 return 1;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900300 }
301 break;
302 default:
303 break;
304 }
Bernie Innocenti4acba1a2018-09-26 11:52:04 +0900305 return 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900306}
307
308/* int
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900309 * res_nameinquery(name, type, cl, buf, eom)
310 * look for (name, type, cl) in the query section of packet (buf, eom)
Bernie Innocenti55864192018-08-30 04:05:20 +0900311 * requires:
312 * buf + HFIXEDSZ <= eom
313 * returns:
314 * -1 : format error
315 * 0 : not found
316 * >0 : found
317 * author:
318 * paul vixie, 29may94
319 */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900320int res_nameinquery(const char* name, int type, int cl, const u_char* buf, const u_char* eom) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900321 const u_char* cp = buf + HFIXEDSZ;
322 int qdcount = ntohs(((const HEADER*) (const void*) buf)->qdcount);
Bernie Innocenti55864192018-08-30 04:05:20 +0900323
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900324 while (qdcount-- > 0) {
325 char tname[MAXDNAME + 1];
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900326 int n = dn_expand(buf, eom, cp, tname, sizeof tname);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900327 if (n < 0) return (-1);
328 cp += n;
329 if (cp + 2 * INT16SZ > eom) return (-1);
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900330 int ttype = ns_get16(cp);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900331 cp += INT16SZ;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900332 int tclass = ns_get16(cp);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900333 cp += INT16SZ;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900334 if (ttype == type && tclass == cl && ns_samename(tname, name) == 1) return (1);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900335 }
336 return (0);
Bernie Innocenti55864192018-08-30 04:05:20 +0900337}
338
339/* int
340 * res_queriesmatch(buf1, eom1, buf2, eom2)
341 * is there a 1:1 mapping of (name,type,class)
342 * in (buf1,eom1) and (buf2,eom2)?
343 * returns:
344 * -1 : format error
345 * 0 : not a 1:1 mapping
346 * >0 : is a 1:1 mapping
347 * author:
348 * paul vixie, 29may94
349 */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900350int res_queriesmatch(const u_char* buf1, const u_char* eom1, const u_char* buf2,
351 const u_char* eom2) {
352 const u_char* cp = buf1 + HFIXEDSZ;
353 int qdcount = ntohs(((const HEADER*) (const void*) buf1)->qdcount);
Bernie Innocenti55864192018-08-30 04:05:20 +0900354
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900355 if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) return (-1);
Bernie Innocenti55864192018-08-30 04:05:20 +0900356
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900357 /*
358 * Only header section present in replies to
359 * dynamic update packets.
360 */
361 if ((((const HEADER*) (const void*) buf1)->opcode == ns_o_update) &&
362 (((const HEADER*) (const void*) buf2)->opcode == ns_o_update))
363 return (1);
Bernie Innocenti55864192018-08-30 04:05:20 +0900364
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900365 if (qdcount != ntohs(((const HEADER*) (const void*) buf2)->qdcount)) return (0);
366 while (qdcount-- > 0) {
367 char tname[MAXDNAME + 1];
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900368 int n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900369 if (n < 0) return (-1);
370 cp += n;
371 if (cp + 2 * INT16SZ > eom1) return (-1);
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900372 int ttype = ns_get16(cp);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900373 cp += INT16SZ;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900374 int tclass = ns_get16(cp);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900375 cp += INT16SZ;
376 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) return (0);
377 }
378 return (1);
Bernie Innocenti55864192018-08-30 04:05:20 +0900379}
380
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900381int res_nsend(res_state statp, const u_char* buf, int buflen, u_char* ans, int anssiz) {
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900382 int gotsomewhere, terrno, v_circuit, resplen, n;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900383 ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED;
Bernie Innocenti55864192018-08-30 04:05:20 +0900384
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900385 if (anssiz < HFIXEDSZ) {
386 errno = EINVAL;
387 return (-1);
388 }
389 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
390 (stdout, ";; res_send()\n"), buf, buflen);
391 v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
392 gotsomewhere = 0;
393 terrno = ETIMEDOUT;
Bernie Innocenti55864192018-08-30 04:05:20 +0900394
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900395 int anslen = 0;
396 cache_status = _resolv_cache_lookup(statp->netid, buf, buflen, ans, anssiz, &anslen);
Bernie Innocenti55864192018-08-30 04:05:20 +0900397
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900398 if (cache_status == RESOLV_CACHE_FOUND) {
399 return anslen;
400 } else if (cache_status != RESOLV_CACHE_UNSUPPORTED) {
401 // had a cache miss for a known network, so populate the thread private
402 // data so the normal resolve path can do its thing
403 _resolv_populate_res_for_net(statp);
404 }
405 if (statp->nscount == 0) {
406 // We have no nameservers configured, so there's no point trying.
407 // Tell the cache the query failed, or any retries and anyone else asking the same
408 // question will block for PENDING_REQUEST_TIMEOUT seconds instead of failing fast.
409 _resolv_cache_query_failed(statp->netid, buf, buflen);
410 errno = ESRCH;
411 return (-1);
412 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900413
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900414 /*
415 * If the ns_addr_list in the resolver context has changed, then
416 * invalidate our cached copy and the associated timing data.
417 */
Ken Chencf6ded62018-10-16 23:12:09 +0800418 if (statp->_u._ext.nscount != 0) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900419 int needclose = 0;
420 struct sockaddr_storage peer;
421 socklen_t peerlen;
Bernie Innocenti55864192018-08-30 04:05:20 +0900422
Ken Chencf6ded62018-10-16 23:12:09 +0800423 if (statp->_u._ext.nscount != statp->nscount) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900424 needclose++;
425 } else {
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900426 for (int ns = 0; ns < statp->nscount; ns++) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900427 if (statp->nsaddr_list[ns].sin_family &&
428 !sock_eq((struct sockaddr*) (void*) &statp->nsaddr_list[ns],
Ken Chencf6ded62018-10-16 23:12:09 +0800429 (struct sockaddr*) (void*) &statp->_u._ext.ext->nsaddrs[ns])) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900430 needclose++;
431 break;
432 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900433
Ken Chencf6ded62018-10-16 23:12:09 +0800434 if (statp->_u._ext.nssocks[ns] == -1) continue;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900435 peerlen = sizeof(peer);
Ken Chencf6ded62018-10-16 23:12:09 +0800436 if (getpeername(statp->_u._ext.nssocks[ns], (struct sockaddr*) (void*) &peer,
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900437 &peerlen) < 0) {
438 needclose++;
439 break;
440 }
441 if (!sock_eq((struct sockaddr*) (void*) &peer, get_nsaddr(statp, (size_t) ns))) {
442 needclose++;
443 break;
444 }
445 }
446 }
447 if (needclose) {
448 res_nclose(statp);
Ken Chencf6ded62018-10-16 23:12:09 +0800449 statp->_u._ext.nscount = 0;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900450 }
451 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900452
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900453 /*
454 * Maybe initialize our private copy of the ns_addr_list.
455 */
Ken Chencf6ded62018-10-16 23:12:09 +0800456 if (statp->_u._ext.nscount == 0) {
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900457 for (int ns = 0; ns < statp->nscount; ns++) {
Ken Chencf6ded62018-10-16 23:12:09 +0800458 statp->_u._ext.nstimes[ns] = RES_MAXTIME;
459 statp->_u._ext.nssocks[ns] = -1;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900460 if (!statp->nsaddr_list[ns].sin_family) continue;
Ken Chencf6ded62018-10-16 23:12:09 +0800461 statp->_u._ext.ext->nsaddrs[ns].sin = statp->nsaddr_list[ns];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900462 }
Ken Chencf6ded62018-10-16 23:12:09 +0800463 statp->_u._ext.nscount = statp->nscount;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900464 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900465
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900466 /*
467 * Some resolvers want to even out the load on their nameservers.
468 * Note that RES_BLAST overrides RES_ROTATE.
469 */
470 if ((statp->options & RES_ROTATE) != 0U && (statp->options & RES_BLAST) == 0U) {
nuccachene172a4e2018-10-23 17:10:58 +0800471 sockaddr_union inu;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900472 struct sockaddr_in ina;
473 int lastns = statp->nscount - 1;
474 int fd;
475 u_int16_t nstime;
Bernie Innocenti55864192018-08-30 04:05:20 +0900476
Ken Chencf6ded62018-10-16 23:12:09 +0800477 if (statp->_u._ext.ext != NULL) inu = statp->_u._ext.ext->nsaddrs[0];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900478 ina = statp->nsaddr_list[0];
Ken Chencf6ded62018-10-16 23:12:09 +0800479 fd = statp->_u._ext.nssocks[0];
480 nstime = statp->_u._ext.nstimes[0];
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900481 for (int ns = 0; ns < lastns; ns++) {
Ken Chencf6ded62018-10-16 23:12:09 +0800482 if (statp->_u._ext.ext != NULL)
483 statp->_u._ext.ext->nsaddrs[ns] = statp->_u._ext.ext->nsaddrs[ns + 1];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900484 statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
Ken Chencf6ded62018-10-16 23:12:09 +0800485 statp->_u._ext.nssocks[ns] = statp->_u._ext.nssocks[ns + 1];
486 statp->_u._ext.nstimes[ns] = statp->_u._ext.nstimes[ns + 1];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900487 }
Ken Chencf6ded62018-10-16 23:12:09 +0800488 if (statp->_u._ext.ext != NULL) statp->_u._ext.ext->nsaddrs[lastns] = inu;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900489 statp->nsaddr_list[lastns] = ina;
Ken Chencf6ded62018-10-16 23:12:09 +0800490 statp->_u._ext.nssocks[lastns] = fd;
491 statp->_u._ext.nstimes[lastns] = nstime;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900492 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900493
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900494 /*
495 * Send request, RETRY times, or until successful.
496 */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900497 for (int attempt = 0; attempt < statp->retry; ++attempt) {
Bernie Innocenti189eb502018-10-01 23:10:18 +0900498 struct res_stats stats[MAXNS];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900499 struct __res_params params;
Bernie Innocenti189eb502018-10-01 23:10:18 +0900500 int revision_id = resolv_cache_get_resolver_stats(statp->netid, &params, stats);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900501 bool usable_servers[MAXNS];
502 android_net_res_stats_get_usable_servers(&params, stats, statp->nscount, usable_servers);
Bernie Innocenti55864192018-08-30 04:05:20 +0900503
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900504 for (int ns = 0; ns < statp->nscount; ns++) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900505 if (!usable_servers[ns]) continue;
506 struct sockaddr* nsap;
507 int nsaplen;
508 time_t now = 0;
509 int rcode = RCODE_INTERNAL_ERROR;
510 int delay = 0;
511 nsap = get_nsaddr(statp, (size_t) ns);
512 nsaplen = get_salen(nsap);
513 statp->_flags &= ~RES_F_LASTMASK;
514 statp->_flags |= (ns << RES_F_LASTSHIFT);
Bernie Innocenti55864192018-08-30 04:05:20 +0900515
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900516 same_ns:
517 if (statp->qhook) {
518 int done = 0, loops = 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900519
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900520 do {
521 res_sendhookact act;
Bernie Innocenti55864192018-08-30 04:05:20 +0900522
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900523 act = (*statp->qhook)(&nsap, &buf, &buflen, ans, anssiz, &resplen);
524 switch (act) {
525 case res_goahead:
526 done = 1;
527 break;
528 case res_nextns:
529 res_nclose(statp);
530 goto next_ns;
531 case res_done:
532 if (cache_status == RESOLV_CACHE_NOTFOUND) {
533 _resolv_cache_add(statp->netid, buf, buflen, ans, resplen);
534 }
535 return (resplen);
536 case res_modified:
537 /* give the hook another try */
538 if (++loops < 42) /*doug adams*/
539 break;
Bernie Innocenti8bb94ba2018-10-10 22:30:12 +0900540 [[fallthrough]];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900541 case res_error:
Bernie Innocenti8bb94ba2018-10-10 22:30:12 +0900542 [[fallthrough]];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900543 default:
544 goto fail;
545 }
546 } while (!done);
547 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900548
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900549 [[maybe_unused]] static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
550 [[maybe_unused]] char abuf[NI_MAXHOST];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900551 Dprint(((statp->options & RES_DEBUG) &&
552 getnameinfo(nsap, (socklen_t) nsaplen, abuf, sizeof(abuf), NULL, 0, niflags) ==
553 0),
554 (stdout, ";; Querying server (# %d) address = %s\n", ns + 1, abuf));
Bernie Innocenti55864192018-08-30 04:05:20 +0900555
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900556 if (v_circuit) {
557 /* Use VC; at most one attempt per server. */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900558 attempt = statp->retry;
Bernie Innocenti55864192018-08-30 04:05:20 +0900559
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900560 n = send_vc(statp, &params, buf, buflen, ans, anssiz, &terrno, ns, &now, &rcode,
561 &delay);
Bernie Innocenti55864192018-08-30 04:05:20 +0900562
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900563 /*
564 * Only record stats the first time we try a query. This ensures that
565 * queries that deterministically fail (e.g., a name that always returns
566 * SERVFAIL or times out) do not unduly affect the stats.
567 */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900568 if (attempt == 0) {
Bernie Innocenti189eb502018-10-01 23:10:18 +0900569 res_sample sample;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900570 _res_stats_set_sample(&sample, now, rcode, delay);
571 _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, ns, &sample,
572 params.max_samples);
573 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900574
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900575 VLOG << "used send_vc " << n;
Bernie Innocenti55864192018-08-30 04:05:20 +0900576
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900577 if (n < 0) goto fail;
578 if (n == 0) goto next_ns;
579 resplen = n;
580 } else {
581 /* Use datagrams. */
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900582 VLOG << "using send_dg";
Bernie Innocenti55864192018-08-30 04:05:20 +0900583
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900584 n = send_dg(statp, &params, buf, buflen, ans, anssiz, &terrno, ns, &v_circuit,
585 &gotsomewhere, &now, &rcode, &delay);
Bernie Innocenti55864192018-08-30 04:05:20 +0900586
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900587 /* Only record stats the first time we try a query. See above. */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900588 if (attempt == 0) {
Bernie Innocenti189eb502018-10-01 23:10:18 +0900589 res_sample sample;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900590 _res_stats_set_sample(&sample, now, rcode, delay);
591 _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, ns, &sample,
592 params.max_samples);
593 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900594
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900595 VLOG << "used send_dg " << n;
Bernie Innocenti55864192018-08-30 04:05:20 +0900596
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900597 if (n < 0) goto fail;
598 if (n == 0) goto next_ns;
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900599 VLOG << "time=" << time(NULL);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900600 if (v_circuit) goto same_ns;
601 resplen = n;
602 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900603
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900604 Dprint((statp->options & RES_DEBUG) ||
605 ((statp->pfcode & RES_PRF_REPLY) && (statp->pfcode & RES_PRF_HEAD1)),
606 (stdout, ";; got answer:\n"));
Bernie Innocenti55864192018-08-30 04:05:20 +0900607
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900608 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY),
609 (stdout, "%s", ""), ans, (resplen > anssiz) ? anssiz : resplen);
Bernie Innocenti55864192018-08-30 04:05:20 +0900610
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900611 if (cache_status == RESOLV_CACHE_NOTFOUND) {
612 _resolv_cache_add(statp->netid, buf, buflen, ans, resplen);
613 }
614 /*
615 * If we have temporarily opened a virtual circuit,
616 * or if we haven't been asked to keep a socket open,
617 * close the socket.
618 */
619 if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
620 (statp->options & RES_STAYOPEN) == 0U) {
621 res_nclose(statp);
622 }
623 if (statp->rhook) {
624 int done = 0, loops = 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900625
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900626 do {
627 res_sendhookact act;
Bernie Innocenti55864192018-08-30 04:05:20 +0900628
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900629 act = (*statp->rhook)(nsap, buf, buflen, ans, anssiz, &resplen);
630 switch (act) {
631 case res_goahead:
632 case res_done:
633 done = 1;
634 break;
635 case res_nextns:
636 res_nclose(statp);
637 goto next_ns;
638 case res_modified:
639 /* give the hook another try */
640 if (++loops < 42) /*doug adams*/
641 break;
Bernie Innocenti8bb94ba2018-10-10 22:30:12 +0900642 [[fallthrough]];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900643 case res_error:
Bernie Innocenti8bb94ba2018-10-10 22:30:12 +0900644 [[fallthrough]];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900645 default:
646 goto fail;
647 }
648 } while (!done);
649 }
650 return (resplen);
651 next_ns:;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900652 } // for each ns
653 } // for each retry
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900654 res_nclose(statp);
655 if (!v_circuit) {
656 if (!gotsomewhere)
657 errno = ECONNREFUSED; /* no nameservers found */
658 else
659 errno = ETIMEDOUT; /* no answer obtained */
660 } else
661 errno = terrno;
Bernie Innocenti55864192018-08-30 04:05:20 +0900662
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900663 _resolv_cache_query_failed(statp->netid, buf, buflen);
Bernie Innocenti55864192018-08-30 04:05:20 +0900664
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900665 return (-1);
666fail:
Bernie Innocenti55864192018-08-30 04:05:20 +0900667
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900668 _resolv_cache_query_failed(statp->netid, buf, buflen);
669 res_nclose(statp);
670 return (-1);
Bernie Innocenti55864192018-08-30 04:05:20 +0900671}
672
673/* Private */
674
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900675static int get_salen(const struct sockaddr* sa) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900676 if (sa->sa_family == AF_INET)
677 return (sizeof(struct sockaddr_in));
678 else if (sa->sa_family == AF_INET6)
679 return (sizeof(struct sockaddr_in6));
680 else
681 return (0); /* unknown, die on connect */
Bernie Innocenti55864192018-08-30 04:05:20 +0900682}
683
684/*
685 * pick appropriate nsaddr_list for use. see res_init() for initialization.
686 */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900687static struct sockaddr* get_nsaddr(res_state statp, size_t n) {
Ken Chencf6ded62018-10-16 23:12:09 +0800688 if (!statp->nsaddr_list[n].sin_family && statp->_u._ext.ext) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900689 /*
Ken Chencf6ded62018-10-16 23:12:09 +0800690 * - statp->_u._ext.ext->nsaddrs[n] holds an address that is larger
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900691 * than struct sockaddr, and
692 * - user code did not update statp->nsaddr_list[n].
693 */
Ken Chencf6ded62018-10-16 23:12:09 +0800694 return (struct sockaddr*) (void*) &statp->_u._ext.ext->nsaddrs[n];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900695 } else {
696 /*
697 * - user code updated statp->nsaddr_list[n], or
698 * - statp->nsaddr_list[n] has the same content as
Ken Chencf6ded62018-10-16 23:12:09 +0800699 * statp->_u._ext.ext->nsaddrs[n].
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900700 */
701 return (struct sockaddr*) (void*) &statp->nsaddr_list[n];
702 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900703}
704
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900705static struct timespec get_timeout(const res_state statp, const struct __res_params* params,
706 const int ns) {
707 int msec;
708 if (params->base_timeout_msec != 0) {
709 // TODO: scale the timeout by retry attempt and maybe number of servers
710 msec = params->base_timeout_msec;
711 } else {
712 // Legacy algorithm which scales the timeout by nameserver number.
713 // For instance, with 4 nameservers: 5s, 2.5s, 5s, 10s
714 // This has no effect with 1 or 2 nameservers
715 msec = (statp->retrans * 1000) << ns;
716 if (ns > 0) {
717 msec /= statp->nscount;
718 }
719 if (msec < 1000) {
720 msec = 1000; // Use at least 100ms
721 }
722 }
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900723 VLOG << "using timeout of " << msec << " msec";
Bernie Innocenti55864192018-08-30 04:05:20 +0900724
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900725 struct timespec result;
726 result.tv_sec = msec / 1000;
727 result.tv_nsec = (msec % 1000) * 1000000;
728 return result;
Bernie Innocenti55864192018-08-30 04:05:20 +0900729}
730
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900731static int send_vc(res_state statp, struct __res_params* params, const u_char* buf, int buflen,
732 u_char* ans, int anssiz, int* terrno, int ns, time_t* at, int* rcode,
733 int* delay) {
734 *at = time(NULL);
735 *rcode = RCODE_INTERNAL_ERROR;
736 *delay = 0;
737 const HEADER* hp = (const HEADER*) (const void*) buf;
738 HEADER* anhp = (HEADER*) (void*) ans;
739 struct sockaddr* nsap;
740 int nsaplen;
741 int truncating, connreset, resplen, n;
742 struct iovec iov[2];
743 u_short len;
744 u_char* cp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900745
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900746 VLOG << "using send_vc";
Bernie Innocenti55864192018-08-30 04:05:20 +0900747
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900748 nsap = get_nsaddr(statp, (size_t) ns);
749 nsaplen = get_salen(nsap);
Bernie Innocenti55864192018-08-30 04:05:20 +0900750
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900751 connreset = 0;
752same_ns:
753 truncating = 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900754
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900755 struct timespec now = evNowTime();
Bernie Innocenti55864192018-08-30 04:05:20 +0900756
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900757 /* Are we still talking to whom we want to talk to? */
758 if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
759 struct sockaddr_storage peer;
760 socklen_t size = sizeof peer;
761 unsigned old_mark;
762 socklen_t mark_size = sizeof(old_mark);
763 if (getpeername(statp->_vcsock, (struct sockaddr*) (void*) &peer, &size) < 0 ||
764 !sock_eq((struct sockaddr*) (void*) &peer, nsap) ||
765 getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 ||
766 old_mark != statp->_mark) {
767 res_nclose(statp);
768 statp->_flags &= ~RES_F_VC;
769 }
770 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900771
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900772 if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
773 if (statp->_vcsock >= 0) res_nclose(statp);
Bernie Innocenti55864192018-08-30 04:05:20 +0900774
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900775 statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
776 if (statp->_vcsock < 0) {
777 switch (errno) {
778 case EPROTONOSUPPORT:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900779 case EPFNOSUPPORT:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900780 case EAFNOSUPPORT:
781 Perror(statp, stderr, "socket(vc)", errno);
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900782 return 0;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900783 default:
784 *terrno = errno;
785 Perror(statp, stderr, "socket(vc)", errno);
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900786 return -1;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900787 }
788 }
789 fchown(statp->_vcsock, AID_DNS, -1);
790 if (statp->_mark != MARK_UNSET) {
791 if (setsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &statp->_mark,
792 sizeof(statp->_mark)) < 0) {
793 *terrno = errno;
794 Perror(statp, stderr, "setsockopt", errno);
795 return -1;
796 }
797 }
798 errno = 0;
799 if (random_bind(statp->_vcsock, nsap->sa_family) < 0) {
800 *terrno = errno;
801 Aerror(statp, stderr, "bind/vc", errno, nsap, nsaplen);
802 res_nclose(statp);
803 return (0);
804 }
805 if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t) nsaplen,
806 get_timeout(statp, params, ns)) < 0) {
807 *terrno = errno;
808 Aerror(statp, stderr, "connect/vc", errno, nsap, nsaplen);
809 res_nclose(statp);
810 /*
811 * The way connect_with_timeout() is implemented prevents us from reliably
812 * determining whether this was really a timeout or e.g. ECONNREFUSED. Since
813 * currently both cases are handled in the same way, there is no need to
814 * change this (yet). If we ever need to reliably distinguish between these
815 * cases, both connect_with_timeout() and retrying_poll() need to be
816 * modified, though.
817 */
818 *rcode = RCODE_TIMEOUT;
819 return (0);
820 }
821 statp->_flags |= RES_F_VC;
822 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900823
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900824 /*
825 * Send length & message
826 */
827 ns_put16((u_short) buflen, (u_char*) (void*) &len);
828 iov[0] = evConsIovec(&len, INT16SZ);
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900829 iov[1] = evConsIovec((void*) buf, (size_t) buflen);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900830 if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
831 *terrno = errno;
832 Perror(statp, stderr, "write failed", errno);
833 res_nclose(statp);
834 return (0);
835 }
836 /*
837 * Receive length & response
838 */
839read_len:
840 cp = ans;
841 len = INT16SZ;
842 while ((n = read(statp->_vcsock, (char*) cp, (size_t) len)) > 0) {
843 cp += n;
844 if ((len -= n) == 0) break;
845 }
846 if (n <= 0) {
847 *terrno = errno;
848 Perror(statp, stderr, "read failed", errno);
849 res_nclose(statp);
850 /*
851 * A long running process might get its TCP
852 * connection reset if the remote server was
853 * restarted. Requery the server instead of
854 * trying a new one. When there is only one
855 * server, this means that a query might work
856 * instead of failing. We only allow one reset
857 * per query to prevent looping.
858 */
859 if (*terrno == ECONNRESET && !connreset) {
860 connreset = 1;
861 res_nclose(statp);
862 goto same_ns;
863 }
864 res_nclose(statp);
865 return (0);
866 }
867 resplen = ns_get16(ans);
868 if (resplen > anssiz) {
869 Dprint(statp->options & RES_DEBUG, (stdout, ";; response truncated\n"));
870 truncating = 1;
871 len = anssiz;
872 } else
873 len = resplen;
874 if (len < HFIXEDSZ) {
875 /*
876 * Undersized message.
877 */
878 Dprint(statp->options & RES_DEBUG, (stdout, ";; undersized: %d\n", len));
879 *terrno = EMSGSIZE;
880 res_nclose(statp);
881 return (0);
882 }
883 cp = ans;
884 while (len != 0 && (n = read(statp->_vcsock, (char*) cp, (size_t) len)) > 0) {
885 cp += n;
886 len -= n;
887 }
888 if (n <= 0) {
889 *terrno = errno;
890 Perror(statp, stderr, "read(vc)", errno);
891 res_nclose(statp);
892 return (0);
893 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900894
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900895 if (truncating) {
896 /*
897 * Flush rest of answer so connection stays in synch.
898 */
899 anhp->tc = 1;
900 len = resplen - anssiz;
901 while (len != 0) {
902 char junk[PACKETSZ];
Bernie Innocenti55864192018-08-30 04:05:20 +0900903
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900904 n = read(statp->_vcsock, junk, (len > sizeof junk) ? sizeof junk : len);
905 if (n > 0)
906 len -= n;
907 else
908 break;
909 }
910 }
911 /*
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900912 * If the calling application has bailed out of
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900913 * a previous call and failed to arrange to have
914 * the circuit closed or the server has got
915 * itself confused, then drop the packet and
916 * wait for the correct one.
917 */
918 if (hp->id != anhp->id) {
919 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY),
920 (stdout, ";; old answer (unexpected):\n"), ans,
921 (resplen > anssiz) ? anssiz : resplen);
922 goto read_len;
923 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900924
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900925 /*
926 * All is well, or the error is fatal. Signal that the
927 * next nameserver ought not be tried.
928 */
929 if (resplen > 0) {
930 struct timespec done = evNowTime();
931 *delay = _res_stats_calculate_rtt(&done, &now);
932 *rcode = anhp->rcode;
933 }
934 return (resplen);
Bernie Innocenti55864192018-08-30 04:05:20 +0900935}
936
937/* return -1 on error (errno set), 0 on success */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900938static int connect_with_timeout(int sock, const struct sockaddr* nsap, socklen_t salen,
939 const struct timespec timeout) {
940 int res, origflags;
Bernie Innocenti55864192018-08-30 04:05:20 +0900941
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900942 origflags = fcntl(sock, F_GETFL, 0);
943 fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
Bernie Innocenti55864192018-08-30 04:05:20 +0900944
Bernie Innocentif89b3512018-08-30 07:34:37 +0900945 res = connect(sock, nsap, salen);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900946 if (res < 0 && errno != EINPROGRESS) {
947 res = -1;
948 goto done;
949 }
950 if (res != 0) {
951 struct timespec now = evNowTime();
952 struct timespec finish = evAddTime(now, timeout);
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900953 VLOG << sock << " send_vc";
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900954 res = retrying_poll(sock, POLLIN | POLLOUT, &finish);
955 if (res <= 0) {
956 res = -1;
957 }
958 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900959done:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900960 fcntl(sock, F_SETFL, origflags);
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900961 VLOG << sock << " connect_with_const timeout returning " << res;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900962 return res;
Bernie Innocenti55864192018-08-30 04:05:20 +0900963}
964
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900965static int retrying_poll(const int sock, const short events, const struct timespec* finish) {
966 struct timespec now, timeout;
Bernie Innocenti55864192018-08-30 04:05:20 +0900967
968retry:
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900969 VLOG << " " << sock << " retrying_poll";
Bernie Innocenti55864192018-08-30 04:05:20 +0900970
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900971 now = evNowTime();
972 if (evCmpTime(*finish, now) > 0)
973 timeout = evSubTime(*finish, now);
974 else
975 timeout = evConsTime(0L, 0L);
976 struct pollfd fds = {.fd = sock, .events = events};
977 int n = ppoll(&fds, 1, &timeout, /*sigmask=*/NULL);
978 if (n == 0) {
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900979 VLOG << " " << sock << "retrying_poll timeout";
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900980 errno = ETIMEDOUT;
981 return 0;
982 }
983 if (n < 0) {
984 if (errno == EINTR) goto retry;
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900985 VLOG << " " << sock << " retrying_poll got error " << n;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900986 return n;
987 }
988 if (fds.revents & (POLLIN | POLLOUT | POLLERR)) {
989 int error;
990 socklen_t len = sizeof(error);
991 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
992 errno = error;
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900993 VLOG << " " << sock << " retrying_poll dot error2 " << errno;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900994 return -1;
995 }
996 }
Bernie Innocentie9ba09c2018-09-12 23:20:10 +0900997 VLOG << " " << sock << " retrying_poll returning " << n;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900998 return n;
Bernie Innocenti55864192018-08-30 04:05:20 +0900999}
1000
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001001static int send_dg(res_state statp, struct __res_params* params, const u_char* buf, int buflen,
1002 u_char* ans, int anssiz, int* terrno, int ns, int* v_circuit, int* gotsomewhere,
1003 time_t* at, int* rcode, int* delay) {
1004 *at = time(NULL);
1005 *rcode = RCODE_INTERNAL_ERROR;
1006 *delay = 0;
1007 const HEADER* hp = (const HEADER*) (const void*) buf;
1008 HEADER* anhp = (HEADER*) (void*) ans;
1009 const struct sockaddr* nsap;
1010 int nsaplen;
1011 struct timespec now, timeout, finish, done;
1012 struct sockaddr_storage from;
1013 socklen_t fromlen;
1014 int resplen, n, s;
Bernie Innocenti55864192018-08-30 04:05:20 +09001015
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001016 nsap = get_nsaddr(statp, (size_t) ns);
1017 nsaplen = get_salen(nsap);
Ken Chencf6ded62018-10-16 23:12:09 +08001018 if (statp->_u._ext.nssocks[ns] == -1) {
1019 statp->_u._ext.nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1020 if (statp->_u._ext.nssocks[ns] < 0) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001021 switch (errno) {
1022 case EPROTONOSUPPORT:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001023 case EPFNOSUPPORT:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001024 case EAFNOSUPPORT:
1025 Perror(statp, stderr, "socket(dg)", errno);
1026 return (0);
1027 default:
1028 *terrno = errno;
1029 Perror(statp, stderr, "socket(dg)", errno);
1030 return (-1);
1031 }
1032 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001033
Ken Chencf6ded62018-10-16 23:12:09 +08001034 fchown(statp->_u._ext.nssocks[ns], AID_DNS, -1);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001035 if (statp->_mark != MARK_UNSET) {
Ken Chencf6ded62018-10-16 23:12:09 +08001036 if (setsockopt(statp->_u._ext.nssocks[ns], SOL_SOCKET, SO_MARK, &(statp->_mark),
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001037 sizeof(statp->_mark)) < 0) {
1038 res_nclose(statp);
1039 return -1;
1040 }
1041 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001042#ifndef CANNOT_CONNECT_DGRAM
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001043 /*
1044 * On a 4.3BSD+ machine (client and server,
1045 * actually), sending to a nameserver datagram
1046 * port with no nameserver will cause an
1047 * ICMP port unreachable message to be returned.
1048 * If our datagram socket is "connected" to the
1049 * server, we get an ECONNREFUSED error on the next
1050 * socket operation, and select returns if the
1051 * error message is received. We can thus detect
1052 * the absence of a nameserver without timing out.
1053 */
Ken Chencf6ded62018-10-16 23:12:09 +08001054 if (random_bind(statp->_u._ext.nssocks[ns], nsap->sa_family) < 0) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001055 Aerror(statp, stderr, "bind(dg)", errno, nsap, nsaplen);
1056 res_nclose(statp);
1057 return (0);
1058 }
Ken Chencf6ded62018-10-16 23:12:09 +08001059 if (connect(statp->_u._ext.nssocks[ns], nsap, (socklen_t) nsaplen) < 0) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001060 Aerror(statp, stderr, "connect(dg)", errno, nsap, nsaplen);
1061 res_nclose(statp);
1062 return (0);
1063 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001064#endif /* !CANNOT_CONNECT_DGRAM */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001065 Dprint(statp->options & RES_DEBUG, (stdout, ";; new DG socket\n"))
1066 }
Ken Chencf6ded62018-10-16 23:12:09 +08001067 s = statp->_u._ext.nssocks[ns];
Bernie Innocenti55864192018-08-30 04:05:20 +09001068#ifndef CANNOT_CONNECT_DGRAM
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001069 if (send(s, (const char*) buf, (size_t) buflen, 0) != buflen) {
1070 Perror(statp, stderr, "send", errno);
1071 res_nclose(statp);
1072 return (0);
1073 }
1074#else /* !CANNOT_CONNECT_DGRAM */
1075 if (sendto(s, (const char*) buf, buflen, 0, nsap, nsaplen) != buflen) {
1076 Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
1077 res_nclose(statp);
1078 return (0);
1079 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001080#endif /* !CANNOT_CONNECT_DGRAM */
1081
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001082 /*
1083 * Wait for reply.
1084 */
1085 timeout = get_timeout(statp, params, ns);
1086 now = evNowTime();
1087 finish = evAddTime(now, timeout);
Bernie Innocenti55864192018-08-30 04:05:20 +09001088retry:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001089 n = retrying_poll(s, POLLIN, &finish);
Bernie Innocenti55864192018-08-30 04:05:20 +09001090
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001091 if (n == 0) {
1092 *rcode = RCODE_TIMEOUT;
1093 Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
1094 *gotsomewhere = 1;
1095 return (0);
1096 }
1097 if (n < 0) {
1098 Perror(statp, stderr, "poll", errno);
1099 res_nclose(statp);
1100 return (0);
1101 }
1102 errno = 0;
1103 fromlen = sizeof(from);
1104 resplen = recvfrom(s, (char*) ans, (size_t) anssiz, 0, (struct sockaddr*) (void*) &from,
1105 &fromlen);
1106 if (resplen <= 0) {
1107 Perror(statp, stderr, "recvfrom", errno);
1108 res_nclose(statp);
1109 return (0);
1110 }
1111 *gotsomewhere = 1;
1112 if (resplen < HFIXEDSZ) {
1113 /*
1114 * Undersized message.
1115 */
1116 Dprint(statp->options & RES_DEBUG, (stdout, ";; undersized: %d\n", resplen));
1117 *terrno = EMSGSIZE;
1118 res_nclose(statp);
1119 return (0);
1120 }
1121 if (hp->id != anhp->id) {
1122 /*
1123 * response from old query, ignore it.
1124 * XXX - potential security hazard could
1125 * be detected here.
1126 */
1127 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY),
1128 (stdout, ";; old answer:\n"), ans, (resplen > anssiz) ? anssiz : resplen);
1129 goto retry;
1130 }
1131 if (!(statp->options & RES_INSECURE1) &&
1132 !res_ourserver_p(statp, (struct sockaddr*) (void*) &from)) {
1133 /*
1134 * response from wrong server? ignore it.
1135 * XXX - potential security hazard could
1136 * be detected here.
1137 */
1138 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY),
1139 (stdout, ";; not our server:\n"), ans, (resplen > anssiz) ? anssiz : resplen);
1140 goto retry;
1141 }
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001142 if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
1143 /*
1144 * Do not retry if the server do not understand EDNS0.
1145 * The case has to be captured here, as FORMERR packet do not
1146 * carry query section, hence res_queriesmatch() returns 0.
1147 */
1148 DprintQ(statp->options & RES_DEBUG, (stdout, "server rejected query with EDNS0:\n"), ans,
1149 (resplen > anssiz) ? anssiz : resplen);
1150 /* record the error */
1151 statp->_flags |= RES_F_EDNS0ERR;
1152 res_nclose(statp);
1153 return (0);
1154 }
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001155 if (!(statp->options & RES_INSECURE2) &&
1156 !res_queriesmatch(buf, buf + buflen, ans, ans + anssiz)) {
1157 /*
1158 * response contains wrong query? ignore it.
1159 * XXX - potential security hazard could
1160 * be detected here.
1161 */
1162 DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_REPLY),
1163 (stdout, ";; wrong query name:\n"), ans, (resplen > anssiz) ? anssiz : resplen);
1164 goto retry;
1165 ;
1166 }
1167 done = evNowTime();
1168 *delay = _res_stats_calculate_rtt(&done, &now);
1169 if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || anhp->rcode == REFUSED) {
1170 DprintQ(statp->options & RES_DEBUG, (stdout, "server rejected query:\n"), ans,
1171 (resplen > anssiz) ? anssiz : resplen);
1172 res_nclose(statp);
1173 /* don't retry if called from dig */
1174 if (!statp->pfcode) {
1175 *rcode = anhp->rcode;
1176 return (0);
1177 }
1178 }
1179 if (!(statp->options & RES_IGNTC) && anhp->tc) {
1180 /*
1181 * To get the rest of answer,
1182 * use TCP with same server.
1183 */
1184 Dprint(statp->options & RES_DEBUG, (stdout, ";; truncated answer\n"));
1185 *v_circuit = 1;
1186 res_nclose(statp);
1187 return (1);
1188 }
1189 /*
1190 * All is well, or the error is fatal. Signal that the
1191 * next nameserver ought not be tried.
1192 */
1193 if (resplen > 0) {
1194 *rcode = anhp->rcode;
1195 }
1196 return (resplen);
Bernie Innocenti55864192018-08-30 04:05:20 +09001197}
1198
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001199static void Aerror(const res_state statp, FILE* file, const char* string, int error,
1200 const struct sockaddr* address, int alen) {
Bernie Innocentie9ba09c2018-09-12 23:20:10 +09001201 if (!kVerboseLogging) return;
1202
1203 const int save = errno;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001204 char hbuf[NI_MAXHOST];
1205 char sbuf[NI_MAXSERV];
Bernie Innocentie9ba09c2018-09-12 23:20:10 +09001206 constexpr int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
Bernie Innocenti55864192018-08-30 04:05:20 +09001207
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001208 if ((statp->options & RES_DEBUG) != 0U) {
1209 if (getnameinfo(address, (socklen_t) alen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
1210 niflags)) {
1211 strncpy(hbuf, "?", sizeof(hbuf) - 1);
1212 hbuf[sizeof(hbuf) - 1] = '\0';
1213 strncpy(sbuf, "?", sizeof(sbuf) - 1);
1214 sbuf[sizeof(sbuf) - 1] = '\0';
1215 }
1216 fprintf(file, "res_send: %s ([%s].%s): %s\n", string, hbuf, sbuf, strerror(error));
1217 }
1218 errno = save;
Bernie Innocenti55864192018-08-30 04:05:20 +09001219}
1220
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001221static void Perror(const res_state statp, FILE* file, const char* string, int error) {
Bernie Innocentie9ba09c2018-09-12 23:20:10 +09001222 if (!kVerboseLogging) return;
Bernie Innocenti55864192018-08-30 04:05:20 +09001223
Bernie Innocentie9ba09c2018-09-12 23:20:10 +09001224 const int save = errno;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001225 if ((statp->options & RES_DEBUG) != 0U)
1226 fprintf(file, "res_send: %s: %s\n", string, strerror(error));
1227 errno = save;
Bernie Innocenti55864192018-08-30 04:05:20 +09001228}
1229
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001230static int sock_eq(struct sockaddr* a, struct sockaddr* b) {
1231 struct sockaddr_in *a4, *b4;
1232 struct sockaddr_in6 *a6, *b6;
Bernie Innocenti55864192018-08-30 04:05:20 +09001233
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001234 if (a->sa_family != b->sa_family) return 0;
1235 switch (a->sa_family) {
1236 case AF_INET:
1237 a4 = (struct sockaddr_in*) (void*) a;
1238 b4 = (struct sockaddr_in*) (void*) b;
1239 return a4->sin_port == b4->sin_port && a4->sin_addr.s_addr == b4->sin_addr.s_addr;
1240 case AF_INET6:
1241 a6 = (struct sockaddr_in6*) (void*) a;
1242 b6 = (struct sockaddr_in6*) (void*) b;
1243 return a6->sin6_port == b6->sin6_port &&
Bernie Innocenti55864192018-08-30 04:05:20 +09001244#ifdef HAVE_SIN6_SCOPE_ID
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001245 a6->sin6_scope_id == b6->sin6_scope_id &&
Bernie Innocenti55864192018-08-30 04:05:20 +09001246#endif
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001247 IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
1248 default:
1249 return 0;
1250 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001251}