11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*	$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $	*/
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright 2008  Android Open Source Project (source port randomization)
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1985, 1989, 1993
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    The Regents of the University of California.  All rights reserved.
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    documentation and/or other materials provided with the distribution.
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. All advertising materials mentioning features or use of this software
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    must display the following acknowledgement:
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 	This product includes software developed by the University of
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 	California, Berkeley and its contributors.
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 4. Neither the name of the University nor the names of its contributors
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    may be used to endorse or promote products derived from this software
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    without specific prior written permission.
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE.
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Portions Copyright (c) 1993 by Digital Equipment Corporation.
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this software for any
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * purpose with or without fee is hereby granted, provided that the above
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copyright notice and this permission notice appear in all copies, and that
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the name of Digital Equipment Corporation not be used in advertising or
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * publicity pertaining to distribution of the document or software without
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * specific, written prior permission.
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SOFTWARE.
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this software for any
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * purpose with or without fee is hereby granted, provided that the above
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copyright notice and this permission notice appear in all copies.
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h>
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if defined(LIBC_SCCS) && !defined(lint)
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef notdef
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93";
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp";
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* LIBC_SCCS and not lint */
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Send query to name server and wait for reply.
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h>
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/param.h>
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/time.h>
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h>
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/uio.h>
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h>
95569fb9887d00104509df79fa77d92e3cf9afe7dbCalin Juravle#include <arpa/nameser.h>
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <arpa/inet.h>
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h>
99ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt#include <fcntl.h>
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netdb.h>
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ANDROID_CHANGES
102ea9bf6788144b83cc51c454b2bfe6b980d6e947cSzymon Jakubczak#include "resolv_netid.h"
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h"
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <resolv.h>
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <signal.h>
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
111ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt#include <time.h>
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <unistd.h>
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <isc/eventlib.h>
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1164d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai#include <resolv_cache.h>
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
118eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/libc_logging.h"
119ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef DE_CONST
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DE_CONST(c,v)   v = ((c) ? \
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL)
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Options.  Leave them on. */
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef DEBUG
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DEBUG
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "res_debug.h"
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "res_private.h"
1314d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai#include "resolv_stats.h"
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define EXT(res) ((res)->_u._ext)
134ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt#define DBG 0
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const int highestFD = FD_SETSIZE - 1;
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Forward. */
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		get_salen __P((const struct sockaddr *));
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct sockaddr * get_nsaddr __P((res_state, size_t));
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		send_vc(res_state, const u_char *, int,
1434d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai				u_char *, int, int *, int,
1444d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai				time_t *, int *, int *);
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		send_dg(res_state, const u_char *, int,
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				u_char *, int, int *, int,
1474d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai				int *, int *,
1484d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai				time_t *, int *, int *);
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void		Aerror(const res_state, FILE *, const char *, int,
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			       const struct sockaddr *, int);
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void		Perror(const res_state, FILE *, const char *, int);
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		sock_eq(struct sockaddr *, struct sockaddr *);
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef NEED_PSELECT
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		pselect(int, void *, void *, void *,
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				struct timespec *,
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				const sigset_t *);
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid res_pquery(const res_state, const u_char *, int, FILE *);
159ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int connect_with_timeout(int sock, const struct sockaddr *nsap,
160ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			socklen_t salen, int sec);
161ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int retrying_select(const int sock, fd_set *readset, fd_set *writeset,
162ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			const struct timespec *finish);
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* BIONIC-BEGIN: implement source port randomization */
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef union {
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    struct sockaddr      sa;
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    struct sockaddr_in   sin;
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    struct sockaddr_in6  sin6;
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} _sockaddr_union;
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectrandom_bind( int  s, int  family )
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    _sockaddr_union  u;
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    int              j;
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    socklen_t        slen;
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    /* clear all, this also sets the IP4/6 address to 'any' */
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    memset( &u, 0, sizeof u );
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    switch (family) {
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case AF_INET:
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            u.sin.sin_family = family;
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            slen             = sizeof u.sin;
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            break;
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case AF_INET6:
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            u.sin6.sin6_family = family;
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            slen               = sizeof u.sin6;
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            break;
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        default:
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            errno = EPROTO;
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return -1;
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    /* first try to bind to a random source port a few times */
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    for (j = 0; j < 10; j++) {
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* find a random port between 1025 .. 65534 */
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        int  port = 1025 + (res_randomid() % (65535-1025));
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (family == AF_INET)
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            u.sin.sin_port = htons(port);
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            u.sin6.sin6_port = htons(port);
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if ( !bind( s, &u.sa, slen ) )
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return 0;
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    /* nothing after 10 tries, our network table is probably busy */
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    /* let the system decide which port is best */
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if (family == AF_INET)
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        u.sin.sin_port = 0;
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    else
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        u.sin6.sin6_port = 0;
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return bind( s, &u.sa, slen );
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* BIONIC-END */
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Public. */
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * res_isourserver(ina)
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	looks up "ina" in _res.ns_addr_list[]
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * returns:
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0  : not found
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	>0 : found
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author:
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	paul vixie, 29may94
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2327cc5666d94615d9249163dc7ac0f58c2614497ceJim Huang__LIBC_HIDDEN__ int
2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_ourserver_p(const res_state statp, const struct sockaddr *sa) {
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const struct sockaddr_in *inp, *srv;
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const struct sockaddr_in6 *in6p, *srv6;
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int ns;
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (sa->sa_family) {
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET:
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		inp = (const struct sockaddr_in *)(const void *)sa;
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (ns = 0;  ns < statp->nscount;  ns++) {
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (srv->sin_family == inp->sin_family &&
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    srv->sin_port == inp->sin_port &&
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    (srv->sin_addr.s_addr == INADDR_ANY ||
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			     srv->sin_addr.s_addr == inp->sin_addr.s_addr))
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (1);
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET6:
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).ext == NULL)
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		in6p = (const struct sockaddr_in6 *)(const void *)sa;
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (ns = 0;  ns < statp->nscount;  ns++) {
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (srv6->sin6_family == in6p->sin6_family &&
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    srv6->sin6_port == in6p->sin6_port &&
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAVE_SIN6_SCOPE_ID
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    (srv6->sin6_scope_id == 0 ||
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			     srv6->sin6_scope_id == in6p->sin6_scope_id) &&
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			     IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (1);
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (0);
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * res_nameinquery(name, type, class, buf, eom)
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	look for (name,type,class) in the query section of packet (buf,eom)
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * requires:
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	buf + HFIXEDSZ <= eom
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * returns:
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	-1 : format error
2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0  : not found
2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	>0 : found
2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author:
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	paul vixie, 29may94
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_nameinquery(const char *name, int type, int class,
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		const u_char *buf, const u_char *eom)
2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp = buf + HFIXEDSZ;
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (qdcount-- > 0) {
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		char tname[MAXDNAME+1];
2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int n, ttype, tclass;
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = dn_expand(buf, eom, cp, tname, sizeof tname);
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (n < 0)
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += n;
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (cp + 2 * INT16SZ > eom)
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ttype = ns_get16(cp); cp += INT16SZ;
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tclass = ns_get16(cp); cp += INT16SZ;
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (ttype == type && tclass == class &&
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ns_samename(tname, name) == 1)
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (1);
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (0);
3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * res_queriesmatch(buf1, eom1, buf2, eom2)
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	is there a 1:1 mapping of (name,type,class)
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	in (buf1,eom1) and (buf2,eom2)?
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * returns:
3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	-1 : format error
3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0  : not a 1:1 mapping
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	>0 : is a 1:1 mapping
3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author:
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	paul vixie, 29may94
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_queriesmatch(const u_char *buf1, const u_char *eom1,
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 const u_char *buf2, const u_char *eom2)
3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp = buf1 + HFIXEDSZ;
3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Only header section present in replies to
3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * dynamic update packets.
3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (1);
3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (qdcount-- > 0) {
3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		char tname[MAXDNAME+1];
3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int n, ttype, tclass;
3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (n < 0)
3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += n;
3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (cp + 2 * INT16SZ > eom1)
3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ttype = ns_get16(cp);	cp += INT16SZ;
3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tclass = ns_get16(cp); cp += INT16SZ;
3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (1);
3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_nsend(res_state statp,
3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	  const u_char *buf, int buflen, u_char *ans, int anssiz)
3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char abuf[NI_MAXHOST];
3664d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	ResolvCacheStatus     cache_status = RESOLV_CACHE_UNSUPPORTED;
367c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (anssiz < HFIXEDSZ) {
3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EINVAL;
3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		(stdout, ";; res_send()\n"), buf, buflen);
3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	gotsomewhere = 0;
3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	terrno = ETIMEDOUT;
3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
37841d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen	int  anslen = 0;
37941d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen	cache_status = _resolv_cache_lookup(
38041d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen			statp->netid, buf, buflen,
38141d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen			ans, anssiz, &anslen);
38241d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen
38341d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen	if (cache_status == RESOLV_CACHE_FOUND) {
38441d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen		return anslen;
38541d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen	} else if (cache_status != RESOLV_CACHE_UNSUPPORTED) {
38641d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen		// had a cache miss for a known network, so populate the thread private
38741d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen		// data so the normal resolve path can do its thing
38841d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen		_resolv_populate_res_for_net(statp);
389c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
390c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	if (statp->nscount == 0) {
391e5477f83b0a639b86d8cbe710f25d9808a8f72afLorenzo Colitti		// We have no nameservers configured, so there's no point trying.
392e5477f83b0a639b86d8cbe710f25d9808a8f72afLorenzo Colitti		// Tell the cache the query failed, or any retries and anyone else asking the same
393e5477f83b0a639b86d8cbe710f25d9808a8f72afLorenzo Colitti		// question will block for PENDING_REQUEST_TIMEOUT seconds instead of failing fast.
394e5477f83b0a639b86d8cbe710f25d9808a8f72afLorenzo Colitti		_resolv_cache_query_failed(statp->netid, buf, buflen);
395c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		errno = ESRCH;
396c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		return (-1);
397c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * If the ns_addr_list in the resolver context has changed, then
4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * invalidate our cached copy and the associated timing data.
4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (EXT(statp).nscount != 0) {
4041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int needclose = 0;
4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		struct sockaddr_storage peer;
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		socklen_t peerlen;
4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4084d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		if (EXT(statp).nscount != statp->nscount) {
4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			needclose++;
4104d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		} else {
4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			for (ns = 0; ns < statp->nscount; ns++) {
4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (statp->nsaddr_list[ns].sin_family &&
4131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
4141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					     (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					needclose++;
4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
4171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
4181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (EXT(statp).nssocks[ns] == -1)
4201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					continue;
4211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				peerlen = sizeof(peer);
42287043f9c89593125a27199d0c1b4069d088672d7Jim Huang				if (getpeername(EXT(statp).nssocks[ns],
4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
4241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					needclose++;
4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
4271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!sock_eq((struct sockaddr *)(void *)&peer,
4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    get_nsaddr(statp, (size_t)ns))) {
4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					needclose++;
4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4334d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		}
4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (needclose) {
4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nscount = 0;
4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Maybe initialize our private copy of the ns_addr_list.
4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (EXT(statp).nscount == 0) {
4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (ns = 0; ns < statp->nscount; ns++) {
4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nstimes[ns] = RES_MAXTIME;
4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nssocks[ns] = -1;
4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (!statp->nsaddr_list[ns].sin_family)
4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).ext->nsaddrs[ns].sin =
4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 statp->nsaddr_list[ns];
4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		EXT(statp).nscount = statp->nscount;
4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
4561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Some resolvers want to even out the load on their nameservers.
4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Note that RES_BLAST overrides RES_ROTATE.
4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((statp->options & RES_ROTATE) != 0U &&
4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    (statp->options & RES_BLAST) == 0U) {
4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		union res_sockaddr_union inu;
4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		struct sockaddr_in ina;
4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int lastns = statp->nscount - 1;
4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int fd;
4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		u_int16_t nstime;
4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).ext != NULL)
4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			inu = EXT(statp).ext->nsaddrs[0];
4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ina = statp->nsaddr_list[0];
4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fd = EXT(statp).nssocks[0];
4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nstime = EXT(statp).nstimes[0];
4721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (ns = 0; ns < lastns; ns++) {
4731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (EXT(statp).ext != NULL)
4744d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai				EXT(statp).ext->nsaddrs[ns] =
4751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					EXT(statp).ext->nsaddrs[ns + 1];
4761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
4771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
4781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).ext != NULL)
4811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).ext->nsaddrs[lastns] = inu;
4821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->nsaddr_list[lastns] = ina;
4831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		EXT(statp).nssocks[lastns] = fd;
4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		EXT(statp).nstimes[lastns] = nstime;
4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Send request, RETRY times, or until successful.
4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (try = 0; try < statp->retry; try++) {
491589afca92c2fa026f908ec2c54c0450c438c602cPierre Imai	    struct __res_stats stats[MAXNS];
4924d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	    struct __res_params params;
4934d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	    int revision_id = _resolv_cache_get_resolver_stats(statp->netid, &params, stats);
494589afca92c2fa026f908ec2c54c0450c438c602cPierre Imai	    bool usable_servers[MAXNS];
49521bf06372742b0524c358502eb692a2245d64ddaPierre Imai	    android_net_res_stats_get_usable_servers(&params, stats, statp->nscount,
49621bf06372742b0524c358502eb692a2245d64ddaPierre Imai		    usable_servers);
4974d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai
4981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    for (ns = 0; ns < statp->nscount; ns++) {
4994d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		if (!usable_servers[ns]) continue;
5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		struct sockaddr *nsap;
5011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int nsaplen;
5024d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		time_t now = 0;
5034d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		int rcode = RCODE_INTERNAL_ERROR;
5044d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		int delay = 0;
5051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nsap = get_nsaddr(statp, (size_t)ns);
5061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nsaplen = get_salen(nsap);
5071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->_flags &= ~RES_F_LASTMASK;
5081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->_flags |= (ns << RES_F_LASTSHIFT);
5094d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai
5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project same_ns:
5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->qhook) {
5121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			int done = 0, loops = 0;
5131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			do {
5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				res_sendhookact act;
5161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				act = (*statp->qhook)(&nsap, &buf, &buflen,
5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						      ans, anssiz, &resplen);
5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				switch (act) {
5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_goahead:
5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					done = 1;
5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_nextns:
5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					res_nclose(statp);
5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto next_ns;
5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_done:
5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (resplen);
5281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_modified:
5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/* give the hook another try */
5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (++loops < 42) /*doug adams*/
5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						break;
5321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/*FALLTHROUGH*/
5331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_error:
5341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/*FALLTHROUGH*/
5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				default:
5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto fail;
5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} while (!done);
5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(((statp->options & RES_DEBUG) &&
5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
543ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				NULL, 0, niflags) == 0),
544ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				(stdout, ";; Querying server (# %d) address = %s\n",
545ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				ns + 1, abuf));
5461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (v_circuit) {
5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Use VC; at most one attempt per server. */
5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			try = statp->retry;
551ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
5521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
5534d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai				    ns, &now, &rcode, &delay);
5544d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai
5550b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			/*
5560b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			 * Only record stats the first time we try a query. This ensures that
5570b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			 * queries that deterministically fail (e.g., a name that always returns
5580b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			 * SERVFAIL or times out) do not unduly affect the stats.
5590b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			 */
5600b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			if (try == 0) {
5610b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai				struct __res_sample sample;
5620b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai				_res_stats_set_sample(&sample, now, rcode, delay);
5630b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai				_resolv_cache_add_resolver_stats_sample(statp->netid, revision_id,
5640b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai					ns, &sample, params.max_samples);
5650b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			}
566ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
567ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
5688f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes				__libc_format_log(ANDROID_LOG_DEBUG, "libc",
569ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt					"used send_vc %d\n", n);
570ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
571ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
5721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n < 0)
5731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto fail;
5741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n == 0)
5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto next_ns;
5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			resplen = n;
5771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else {
5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Use datagrams. */
579ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
5808f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes				__libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_dg\n");
581ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
582ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
5844d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai				    ns, &v_circuit, &gotsomewhere, &now, &rcode, &delay);
5854d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai
5860b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			/* Only record stats the first time we try a query. See above. */
5870b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			if (try == 0) {
5880b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai				struct __res_sample sample;
5890b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai				_res_stats_set_sample(&sample, now, rcode, delay);
5900b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai				_resolv_cache_add_resolver_stats_sample(statp->netid, revision_id,
5910b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai					ns, &sample, params.max_samples);
5920b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai			}
5934d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai
594ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
5958f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes				__libc_format_log(ANDROID_LOG_DEBUG, "libc", "used send_dg %d\n",n);
596ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
597ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n < 0)
5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto fail;
6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n == 0)
6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto next_ns;
602ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
603bb0b09cad6cb950a824cfa46743fe27a0997411bKito Cheng				__libc_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n",
6044d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai						  time(NULL));
605ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (v_circuit)
6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto same_ns;
6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			resplen = n;
6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint((statp->options & RES_DEBUG) ||
6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       ((statp->pfcode & RES_PRF_REPLY) &&
6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_HEAD1)),
6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; got answer:\n"));
6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, "%s", ""),
6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6214d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		if (cache_status == RESOLV_CACHE_NOTFOUND) {
6224d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		    _resolv_cache_add(statp->netid, buf, buflen,
6234d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai				      ans, resplen);
6244d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		}
6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
6261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * If we have temporarily opened a virtual circuit,
6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * or if we haven't been asked to keep a socket open,
6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * close the socket.
6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    (statp->options & RES_STAYOPEN) == 0U) {
6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->rhook) {
6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			int done = 0, loops = 0;
6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			do {
6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				res_sendhookact act;
6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				act = (*statp->rhook)(nsap, buf, buflen,
6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						      ans, anssiz, &resplen);
6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				switch (act) {
6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_goahead:
6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_done:
6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					done = 1;
6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_nextns:
6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					res_nclose(statp);
6491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto next_ns;
6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_modified:
6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/* give the hook another try */
6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (++loops < 42) /*doug adams*/
6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						break;
6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/*FALLTHROUGH*/
6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_error:
6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/*FALLTHROUGH*/
6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				default:
6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto fail;
6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} while (!done);
6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (resplen);
6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project next_ns: ;
6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   } /*foreach ns*/
6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} /*foreach retry*/
6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_nclose(statp);
6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!v_circuit) {
6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (!gotsomewhere)
6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = ECONNREFUSED;	/* no nameservers found */
6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		else
6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = ETIMEDOUT;	/* no answer obtained */
6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else
6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = terrno;
675ce5ba8bfcd8ecfb7bfee4412f4f686cecc17e39bHenrik Engström
6764d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	_resolv_cache_query_failed(statp->netid, buf, buflen);
677ce5ba8bfcd8ecfb7bfee4412f4f686cecc17e39bHenrik Engström
6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (-1);
6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fail:
6804d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai
68141d9a503716ed6f3291f4cae097dca08d459429cPaul Jensen	_resolv_cache_query_failed(statp->netid, buf, buflen);
6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_nclose(statp);
6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (-1);
6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Private */
6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_salen(sa)
6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const struct sockaddr *sa;
6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAVE_SA_LEN
6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* There are people do not set sa_len.  Be forgiving to them. */
6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sa->sa_len)
6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (sa->sa_len);
6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sa->sa_family == AF_INET)
7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (sizeof(struct sockaddr_in));
7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	else if (sa->sa_family == AF_INET6)
7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (sizeof(struct sockaddr_in6));
7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	else
7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);	/* unknown, die on connect */
7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
7081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * pick appropriate nsaddr_list for use.  see res_init() for initialization.
7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct sockaddr *
7111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_nsaddr(statp, n)
7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_state statp;
7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t n;
7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *   than struct sockaddr, and
7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * - user code did not update statp->nsaddr_list[n].
7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else {
7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * - user code updated statp->nsaddr_list[n], or
7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * - statp->nsaddr_list[n] has the same content as
7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *   EXT(statp).ext->nsaddrs[n].
7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
733ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int get_timeout(const res_state statp, const int ns)
734ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt{
735ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	int timeout = (statp->retrans << ns);
736ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (ns > 0) {
737ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout /= statp->nscount;
738ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
739ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (timeout <= 0) {
740ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout = 1;
741ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
742ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
7438f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes		__libc_format_log(ANDROID_LOG_DEBUG, "libc", "using timeout of %d sec\n", timeout);
744ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
745ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
746ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	return timeout;
747ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt}
748ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
7501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsend_vc(res_state statp,
7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *buf, int buflen, u_char *ans, int anssiz,
7524d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	int *terrno, int ns, time_t* at, int* rcode, int* delay)
7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
7540b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai	*at = time(NULL);
7554d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	*rcode = RCODE_INTERNAL_ERROR;
7564d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	*delay = 0;
7571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const HEADER *hp = (const HEADER *)(const void *)buf;
7581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	HEADER *anhp = (HEADER *)(void *)ans;
7591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct sockaddr *nsap;
7601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int nsaplen;
7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int truncating, connreset, resplen, n;
7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct iovec iov[2];
7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_short len;
7641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *cp;
7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	void *tmp;
7661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
767ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
7688f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes		__libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_vc\n");
769ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
770ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
7711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nsap = get_nsaddr(statp, (size_t)ns);
7721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nsaplen = get_salen(nsap);
7731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	connreset = 0;
7751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project same_ns:
7761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	truncating = 0;
7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7784d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	struct timespec now = evNowTime();
7794d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai
7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Are we still talking to whom we want to talk to? */
7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
7821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		struct sockaddr_storage peer;
7831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		socklen_t size = sizeof peer;
784ea9bf6788144b83cc51c454b2bfe6b980d6e947cSzymon Jakubczak		unsigned old_mark;
78537b1b5bbcd1cddf833c9ca18a5976efbbf88dabfElliott Hughes		socklen_t mark_size = sizeof(old_mark);
7861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (getpeername(statp->_vcsock,
7871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				(struct sockaddr *)(void *)&peer, &size) < 0 ||
788c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker		    !sock_eq((struct sockaddr *)(void *)&peer, nsap) ||
789c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker			getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 ||
790c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker			old_mark != statp->_mark) {
7911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
7921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			statp->_flags &= ~RES_F_VC;
7931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
7941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
7951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
7971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->_vcsock >= 0)
7981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
7991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8001781ed7774671d5a750839650b9582ff0abbcf42Nick Kralevich		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
8011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->_vcsock > highestFD) {
8021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
8031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = ENOTSOCK;
8041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
8051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->_vcsock < 0) {
8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			switch (errno) {
8071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EPROTONOSUPPORT:
8081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef EPFNOSUPPORT
8091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EPFNOSUPPORT:
8101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
8111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EAFNOSUPPORT:
8121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				Perror(statp, stderr, "socket(vc)", errno);
8131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (0);
8141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			default:
8151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*terrno = errno;
8161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				Perror(statp, stderr, "socket(vc)", errno);
8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
8191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
820ea9bf6788144b83cc51c454b2bfe6b980d6e947cSzymon Jakubczak		if (statp->_mark != MARK_UNSET) {
821c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker			if (setsockopt(statp->_vcsock, SOL_SOCKET,
8224d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai				    SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) {
823c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker				*terrno = errno;
824c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker				Perror(statp, stderr, "setsockopt", errno);
825c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker				return -1;
826c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker			}
827c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker		}
8281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = 0;
8291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
8301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*terrno = errno;
8311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			Aerror(statp, stderr, "bind/vc", errno, nsap,
8321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    nsaplen);
8331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
8341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
8351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
836ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t)nsaplen,
837ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				get_timeout(statp, ns)) < 0) {
8381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*terrno = errno;
8391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			Aerror(statp, stderr, "connect/vc", errno, nsap,
8401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    nsaplen);
8411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
8424d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			/*
8434d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			 * The way connect_with_timeout() is implemented prevents us from reliably
8444d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			 * determining whether this was really a timeout or e.g. ECONNREFUSED. Since
8454d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			 * currently both cases are handled in the same way, there is no need to
8464d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			 * change this (yet). If we ever need to reliably distinguish between these
8474d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			 * cases, both connect_with_timeout() and retrying_select() need to be
8484d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			 * modified, though.
8494d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			 */
8504d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			*rcode = RCODE_TIMEOUT;
8511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
8521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
8531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->_flags |= RES_F_VC;
8541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
8571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Send length & message
8581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
8591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	ns_put16((u_short)buflen, (u_char*)(void *)&len);
8601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	iov[0] = evConsIovec(&len, INT16SZ);
8611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	DE_CONST(buf, tmp);
8621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	iov[1] = evConsIovec(tmp, (size_t)buflen);
8631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
8641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = errno;
8651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "write failed", errno);
8661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
8671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
8681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
8701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Receive length & response
8711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
8721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project read_len:
8731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = ans;
8741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	len = INT16SZ;
8751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
8761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += n;
8771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((len -= n) == 0)
8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
8791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n <= 0) {
8811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = errno;
8821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "read failed", errno);
8831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * A long running process might get its TCP
8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * connection reset if the remote server was
8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * restarted.  Requery the server instead of
8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * trying a new one.  When there is only one
8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * server, this means that a query might work
8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * instead of failing.  We only allow one reset
8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * per query to prevent looping.
8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (*terrno == ECONNRESET && !connreset) {
8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			connreset = 1;
8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto same_ns;
8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	resplen = ns_get16(ans);
9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (resplen > anssiz) {
9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; response truncated\n")
9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       );
9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		truncating = 1;
9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len = anssiz;
9081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else
9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len = resplen;
9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (len < HFIXEDSZ) {
9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Undersized message.
9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; undersized: %d\n", len));
9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = EMSGSIZE;
9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = ans;
9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += n;
9231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len -= n;
9241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n <= 0) {
9261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = errno;
9271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "read(vc)", errno);
9281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
9291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
9301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9314d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai
9321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (truncating) {
9331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
9341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Flush rest of answer so connection stays in synch.
9351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
9361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		anhp->tc = 1;
9371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len = resplen - anssiz;
9381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		while (len != 0) {
9391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			char junk[PACKETSZ];
9401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n = read(statp->_vcsock, junk,
9421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 (len > sizeof junk) ? sizeof junk : len);
9431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n > 0)
9441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				len -= n;
9451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else
9461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				break;
9471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
9481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
9501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * If the calling applicating has bailed out of
9511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * a previous call and failed to arrange to have
9521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * the circuit closed or the server has got
9531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * itself confused, then drop the packet and
9541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * wait for the correct one.
9551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
9561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (hp->id != anhp->id) {
9571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
9581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, ";; old answer (unexpected):\n"),
9601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz: resplen);
9611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		goto read_len;
9621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
9651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * All is well, or the error is fatal.  Signal that the
9661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * next nameserver ought not be tried.
9671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
9684d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	if (resplen > 0) {
9690b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai	    struct timespec done = evNowTime();
9704d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	    *delay = _res_stats_calculate_rtt(&done, &now);
9714d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	    *rcode = anhp->rcode;
9724d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	}
9731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (resplen);
9741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
9751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
976ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt/* return -1 on error (errno set), 0 on success */
977ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int
978ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltconnect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int sec)
979ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt{
980ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	int res, origflags;
981ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	fd_set rset, wset;
982ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	struct timespec now, timeout, finish;
983ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
984ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	origflags = fcntl(sock, F_GETFL, 0);
985ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
986ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
98731ad03761d35ce5bff48cc1cb3764816727ac1f0Paul Jensen	res = __connect(sock, nsap, salen);
988ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (res < 0 && errno != EINPROGRESS) {
9894d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		res = -1;
9904d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		goto done;
991ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
992ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (res != 0) {
993ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		now = evNowTime();
994ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout = evConsTime((long)sec, 0L);
995ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		finish = evAddTime(now, timeout);
996ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (DBG) {
9978f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes			__libc_format_log(ANDROID_LOG_DEBUG, "libc", "  %d send_vc\n", sock);
998ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
999ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1000ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		res = retrying_select(sock, &rset, &wset, &finish);
1001ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (res <= 0) {
10024d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			res = -1;
1003ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
1004ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1005ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltdone:
1006ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	fcntl(sock, F_SETFL, origflags);
1007ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
10088f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes		__libc_format_log(ANDROID_LOG_DEBUG, "libc",
1009bb0b09cad6cb950a824cfa46743fe27a0997411bKito Cheng			"  %d connect_with_timeout returning %d\n", sock, res);
1010ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1011ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	return res;
1012ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt}
1013ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1014ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int
1015ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltretrying_select(const int sock, fd_set *readset, fd_set *writeset, const struct timespec *finish)
1016ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt{
1017ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	struct timespec now, timeout;
1018ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	int n, error;
1019ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	socklen_t len;
1020ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1021ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1022ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltretry:
1023ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
10244d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		__libc_format_log(ANDROID_LOG_DEBUG, "libc", "  %d retrying_select\n", sock);
1025ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1026ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1027ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	now = evNowTime();
1028ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (readset) {
1029ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		FD_ZERO(readset);
1030ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		FD_SET(sock, readset);
1031ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1032ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (writeset) {
1033ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		FD_ZERO(writeset);
1034ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		FD_SET(sock, writeset);
1035ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1036ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (evCmpTime(*finish, now) > 0)
1037ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout = evSubTime(*finish, now);
1038ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	else
1039ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout = evConsTime(0L, 0L);
1040ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1041ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	n = pselect(sock + 1, readset, writeset, NULL, &timeout, NULL);
1042ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (n == 0) {
1043ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (DBG) {
10448f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes			__libc_format_log(ANDROID_LOG_DEBUG, " libc",
1045ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				"  %d retrying_select timeout\n", sock);
1046ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
1047ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		errno = ETIMEDOUT;
1048ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		return 0;
1049ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1050ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (n < 0) {
1051ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (errno == EINTR)
1052ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			goto retry;
1053ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (DBG) {
10548f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes			__libc_format_log(ANDROID_LOG_DEBUG, "libc",
1055ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				"  %d retrying_select got error %d\n",sock, n);
1056ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
1057ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		return n;
1058ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1059ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if ((readset && FD_ISSET(sock, readset)) || (writeset && FD_ISSET(sock, writeset))) {
1060ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		len = sizeof(error);
1061ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
1062ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			errno = error;
1063ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
10648f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes				__libc_format_log(ANDROID_LOG_DEBUG, "libc",
1065ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt					"  %d retrying_select dot error2 %d\n", sock, errno);
1066ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
1067ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1068ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			return -1;
1069ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
1070ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1071ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
10728f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes		__libc_format_log(ANDROID_LOG_DEBUG, "libc",
1073bb0b09cad6cb950a824cfa46743fe27a0997411bKito Cheng			"  %d retrying_select returning %d\n",sock, n);
1074ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1075ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1076ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	return n;
1077ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt}
1078ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
10791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
10801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsend_dg(res_state statp,
10811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *buf, int buflen, u_char *ans, int anssiz,
10824d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	int *terrno, int ns, int *v_circuit, int *gotsomewhere,
10834d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	time_t *at, int *rcode, int* delay)
10841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
10850b1a71f9a49ed13a680ff299c8d798cf36d565eaPierre Imai	*at = time(NULL);
10864d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	*rcode = RCODE_INTERNAL_ERROR;
10874d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	*delay = 0;
10881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const HEADER *hp = (const HEADER *)(const void *)buf;
10891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	HEADER *anhp = (HEADER *)(void *)ans;
10901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const struct sockaddr *nsap;
10911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int nsaplen;
10924d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	struct timespec now, timeout, finish, done;
10931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fd_set dsmask;
10941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct sockaddr_storage from;
10951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	socklen_t fromlen;
10961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int resplen, seconds, n, s;
10971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nsap = get_nsaddr(statp, (size_t)ns);
10991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nsaplen = get_salen(nsap);
11001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (EXT(statp).nssocks[ns] == -1) {
11011781ed7774671d5a750839650b9582ff0abbcf42Nick Kralevich		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
11021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).nssocks[ns] > highestFD) {
11031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
11041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = ENOTSOCK;
11051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
11061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).nssocks[ns] < 0) {
11071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			switch (errno) {
11081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EPROTONOSUPPORT:
11091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef EPFNOSUPPORT
11101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EPFNOSUPPORT:
11111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
11121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EAFNOSUPPORT:
11131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				Perror(statp, stderr, "socket(dg)", errno);
11141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (0);
11151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			default:
11161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*terrno = errno;
11171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				Perror(statp, stderr, "socket(dg)", errno);
11181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
11191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
11201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
1121c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker
1122ea9bf6788144b83cc51c454b2bfe6b980d6e947cSzymon Jakubczak		if (statp->_mark != MARK_UNSET) {
1123c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker			if (setsockopt(EXT(statp).nssocks[ns], SOL_SOCKET,
1124c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker					SO_MARK, &(statp->_mark), sizeof(statp->_mark)) < 0) {
1125c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker				res_nclose(statp);
1126c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker				return -1;
1127c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker			}
1128c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker		}
11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef CANNOT_CONNECT_DGRAM
11301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
11311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * On a 4.3BSD+ machine (client and server,
11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * actually), sending to a nameserver datagram
11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * port with no nameserver will cause an
11341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * ICMP port unreachable message to be returned.
11351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * If our datagram socket is "connected" to the
11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * server, we get an ECONNREFUSED error on the next
11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * socket operation, and select returns if the
11381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * error message is received.  We can thus detect
11391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * the absence of a nameserver without timing out.
11401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
11411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) {
11421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			Aerror(statp, stderr, "bind(dg)", errno, nsap,
11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    nsaplen);
11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
11461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
114731ad03761d35ce5bff48cc1cb3764816727ac1f0Paul Jensen		if (__connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
11481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			Aerror(statp, stderr, "connect(dg)", errno, nsap,
11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    nsaplen);
11501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !CANNOT_CONNECT_DGRAM */
11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
11551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; new DG socket\n"))
1156c39214e0ac49b9f7de6fd9989331145c6e1cd584Chad Brubaker
11571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	s = EXT(statp).nssocks[ns];
11591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef CANNOT_CONNECT_DGRAM
11601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
11611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "send", errno);
11621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
11631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
11641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else /* !CANNOT_CONNECT_DGRAM */
11661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
11671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	{
11681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
11691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
11701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
11711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !CANNOT_CONNECT_DGRAM */
11731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
11751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Wait for reply.
11761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
1177ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	seconds = get_timeout(statp, ns);
11781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	now = evNowTime();
11791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	timeout = evConsTime((long)seconds, 0L);
11801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	finish = evAddTime(now, timeout);
1181ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltretry:
1182ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	n = retrying_select(s, &dsmask, NULL, &finish);
1183ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
11841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n == 0) {
11854d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		*rcode = RCODE_TIMEOUT;
11861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
11871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*gotsomewhere = 1;
11881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
11891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n < 0) {
11911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "select", errno);
11921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
11931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
11941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	errno = 0;
11961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fromlen = sizeof(from);
11971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
11981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			   (struct sockaddr *)(void *)&from, &fromlen);
11991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (resplen <= 0) {
12001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "recvfrom", errno);
12011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
12021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
12031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*gotsomewhere = 1;
12051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (resplen < HFIXEDSZ) {
12061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
12071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Undersized message.
12081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
12091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
12101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; undersized: %d\n",
12111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			resplen));
12121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = EMSGSIZE;
12131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
12141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
12151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (hp->id != anhp->id) {
12171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
12181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * response from old query, ignore it.
12191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * XXX - potential security hazard could
12201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *	 be detected here.
12211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1222524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#ifdef ANDROID_CHANGES
1223524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra		__libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_OLD_RESPONSE);
1224524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#endif
12251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
12261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
12271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, ";; old answer:\n"),
12281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
1229ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		goto retry;
12301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!(statp->options & RES_INSECURE1) &&
12321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
12331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
12341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * response from wrong server? ignore it.
12351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * XXX - potential security hazard could
12361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *	 be detected here.
12371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1238524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#ifdef ANDROID_CHANGES
1239524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra		__libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_SERVER);
1240524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#endif
12411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
12421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
12431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, ";; not our server:\n"),
12441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
1245ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		goto retry;
12461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef RES_USE_EDNS0
12481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
12491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
12501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Do not retry if the server do not understand EDNS0.
12511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * The case has to be captured here, as FORMERR packet do not
12521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * carry query section, hence res_queriesmatch() returns 0.
12531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
12541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ(statp->options & RES_DEBUG,
12551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, "server rejected query with EDNS0:\n"),
12561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
12571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* record the error */
12581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->_flags |= RES_F_EDNS0ERR;
12591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
12601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
12611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
12631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!(statp->options & RES_INSECURE2) &&
12641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    !res_queriesmatch(buf, buf + buflen,
12651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			      ans, ans + anssiz)) {
12661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
12671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * response contains wrong query? ignore it.
12681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * XXX - potential security hazard could
12691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *	 be detected here.
12701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1271524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#ifdef ANDROID_CHANGES
1272524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra		__libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_QUERY);
1273524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#endif
12741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
12751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
12761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, ";; wrong query name:\n"),
12771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
1278ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		goto retry;;
12791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12804d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	done = evNowTime();
12814d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	*delay = _res_stats_calculate_rtt(&done, &now);
12821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (anhp->rcode == SERVFAIL ||
12831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    anhp->rcode == NOTIMP ||
12841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    anhp->rcode == REFUSED) {
12851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ(statp->options & RES_DEBUG,
12861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, "server rejected query:\n"),
12871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
12881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
12891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* don't retry if called from dig */
12904d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		if (!statp->pfcode) {
12914d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai			*rcode = anhp->rcode;
12921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
12934d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		}
12941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!(statp->options & RES_IGNTC) && anhp->tc) {
12961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
12971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * To get the rest of answer,
12981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * use TCP with same server.
12991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
13001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
13011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; truncated answer\n"));
13021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*v_circuit = 1;
13031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
13041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (1);
13051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
13061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
13071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * All is well, or the error is fatal.  Signal that the
13081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * next nameserver ought not be tried.
13091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
13104d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	if (resplen > 0) {
13114d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai		*rcode = anhp->rcode;
13124d8e740b0868b2670599b949ff07d74e5f317114Pierre Imai	}
13131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (resplen);
13141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
13151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void
13171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectAerror(const res_state statp, FILE *file, const char *string, int error,
13181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       const struct sockaddr *address, int alen)
13191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
13201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int save = errno;
13211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char hbuf[NI_MAXHOST];
13221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char sbuf[NI_MAXSERV];
13231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((statp->options & RES_DEBUG) != 0U) {
13251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
13261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    sbuf, sizeof(sbuf), niflags)) {
13271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			strncpy(hbuf, "?", sizeof(hbuf) - 1);
13281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			hbuf[sizeof(hbuf) - 1] = '\0';
13291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			strncpy(sbuf, "?", sizeof(sbuf) - 1);
13301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			sbuf[sizeof(sbuf) - 1] = '\0';
13311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
13321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fprintf(file, "res_send: %s ([%s].%s): %s\n",
13331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			string, hbuf, sbuf, strerror(error));
13341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
13351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	errno = save;
13361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
13371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void
13391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectPerror(const res_state statp, FILE *file, const char *string, int error) {
13401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int save = errno;
13411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((statp->options & RES_DEBUG) != 0U)
13431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fprintf(file, "res_send: %s: %s\n",
13441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			string, strerror(error));
13451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	errno = save;
13461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
13471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
13491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsock_eq(struct sockaddr *a, struct sockaddr *b) {
13501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct sockaddr_in *a4, *b4;
13511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct sockaddr_in6 *a6, *b6;
13521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (a->sa_family != b->sa_family)
13541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return 0;
13551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (a->sa_family) {
13561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET:
13571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		a4 = (struct sockaddr_in *)(void *)a;
13581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		b4 = (struct sockaddr_in *)(void *)b;
13591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return a4->sin_port == b4->sin_port &&
13601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    a4->sin_addr.s_addr == b4->sin_addr.s_addr;
13611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET6:
13621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		a6 = (struct sockaddr_in6 *)(void *)a;
13631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		b6 = (struct sockaddr_in6 *)(void *)b;
13641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return a6->sin6_port == b6->sin6_port &&
13651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAVE_SIN6_SCOPE_ID
13661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    a6->sin6_scope_id == b6->sin6_scope_id &&
13671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
13681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
13691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
13701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return 0;
13711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
13721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
13731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef NEED_PSELECT
13751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* XXX needs to move to the porting library. */
13761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
13771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectpselect(int nfds, void *rfds, void *wfds, void *efds,
13781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct timespec *tsp, const sigset_t *sigmask)
13791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
13801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct timeval tv, *tvp;
13811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	sigset_t sigs;
13821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n;
13831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (tsp) {
13851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tvp = &tv;
13861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tv = evTimeVal(*tsp);
13871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else
13881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tvp = NULL;
13891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sigmask)
13901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		sigprocmask(SIG_SETMASK, sigmask, &sigs);
13911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n = select(nfds, rfds, wfds, efds, tvp);
13921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sigmask)
13931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		sigprocmask(SIG_SETMASK, &sigs, NULL);
13941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (tsp)
13951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*tsp = evTimeSpec(tv);
13961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (n);
13971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
13981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1399