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/* set to 1 to use our small/simple/limited DNS cache */
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define  USE_RESOLV_CACHE  1
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Send query to name server and wait for reply.
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h>
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/param.h>
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/time.h>
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h>
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/uio.h>
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h>
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "arpa_nameser.h"
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <arpa/inet.h>
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h>
102ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt#include <fcntl.h>
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netdb.h>
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ANDROID_CHANGES
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h"
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <resolv.h>
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <signal.h>
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
113ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt#include <time.h>
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <unistd.h>
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <isc/eventlib.h>
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if USE_RESOLV_CACHE
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#  include <resolv_cache.h>
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
122ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt#include "logd.h"
123ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef DE_CONST
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DE_CONST(c,v)   v = ((c) ? \
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL)
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Options.  Leave them on. */
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef DEBUG
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DEBUG
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "res_debug.h"
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "res_private.h"
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define EXT(res) ((res)->_u._ext)
137ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt#define DBG 0
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const int highestFD = FD_SETSIZE - 1;
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Forward. */
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		get_salen __P((const struct sockaddr *));
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct sockaddr * get_nsaddr __P((res_state, size_t));
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		send_vc(res_state, const u_char *, int,
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				u_char *, int, int *, int);
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		send_dg(res_state, const u_char *, int,
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				u_char *, int, int *, int,
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				int *, int *);
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void		Aerror(const res_state, FILE *, const char *, int,
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			       const struct sockaddr *, int);
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void		Perror(const res_state, FILE *, const char *, int);
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		sock_eq(struct sockaddr *, struct sockaddr *);
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef NEED_PSELECT
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int		pselect(int, void *, void *, void *,
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				struct timespec *,
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				const sigset_t *);
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid res_pquery(const res_state, const u_char *, int, FILE *);
160ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int connect_with_timeout(int sock, const struct sockaddr *nsap,
161ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			socklen_t salen, int sec);
162ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int retrying_select(const int sock, fd_set *readset, fd_set *writeset,
163ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			const struct timespec *finish);
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* BIONIC-BEGIN: implement source port randomization */
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef union {
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    struct sockaddr      sa;
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    struct sockaddr_in   sin;
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    struct sockaddr_in6  sin6;
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} _sockaddr_union;
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectrandom_bind( int  s, int  family )
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    _sockaddr_union  u;
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    int              j;
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    socklen_t        slen;
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    /* clear all, this also sets the IP4/6 address to 'any' */
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    memset( &u, 0, sizeof u );
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    switch (family) {
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case AF_INET:
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            u.sin.sin_family = family;
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            slen             = sizeof u.sin;
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            break;
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        case AF_INET6:
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            u.sin6.sin6_family = family;
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            slen               = sizeof u.sin6;
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            break;
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        default:
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            errno = EPROTO;
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return -1;
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    /* first try to bind to a random source port a few times */
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    for (j = 0; j < 10; j++) {
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        /* find a random port between 1025 .. 65534 */
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        int  port = 1025 + (res_randomid() % (65535-1025));
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (family == AF_INET)
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            u.sin.sin_port = htons(port);
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            u.sin6.sin6_port = htons(port);
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if ( !bind( s, &u.sa, slen ) )
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return 0;
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    /* nothing after 10 tries, our network table is probably busy */
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    /* let the system decide which port is best */
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if (family == AF_INET)
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        u.sin.sin_port = 0;
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    else
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        u.sin6.sin6_port = 0;
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return bind( s, &u.sa, slen );
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* BIONIC-END */
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Public. */
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * res_isourserver(ina)
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	looks up "ina" in _res.ns_addr_list[]
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * returns:
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0  : not found
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	>0 : found
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author:
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	paul vixie, 29may94
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2337cc5666d94615d9249163dc7ac0f58c2614497ceJim Huang__LIBC_HIDDEN__ int
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_ourserver_p(const res_state statp, const struct sockaddr *sa) {
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const struct sockaddr_in *inp, *srv;
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const struct sockaddr_in6 *in6p, *srv6;
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int ns;
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (sa->sa_family) {
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET:
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		inp = (const struct sockaddr_in *)(const void *)sa;
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (ns = 0;  ns < statp->nscount;  ns++) {
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (srv->sin_family == inp->sin_family &&
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    srv->sin_port == inp->sin_port &&
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    (srv->sin_addr.s_addr == INADDR_ANY ||
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			     srv->sin_addr.s_addr == inp->sin_addr.s_addr))
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (1);
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET6:
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).ext == NULL)
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		in6p = (const struct sockaddr_in6 *)(const void *)sa;
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (ns = 0;  ns < statp->nscount;  ns++) {
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (srv6->sin6_family == in6p->sin6_family &&
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    srv6->sin6_port == in6p->sin6_port &&
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAVE_SIN6_SCOPE_ID
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    (srv6->sin6_scope_id == 0 ||
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			     srv6->sin6_scope_id == in6p->sin6_scope_id) &&
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			     IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (1);
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (0);
2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * res_nameinquery(name, type, class, buf, eom)
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	look for (name,type,class) in the query section of packet (buf,eom)
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * requires:
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	buf + HFIXEDSZ <= eom
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * returns:
2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	-1 : format error
2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0  : not found
2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	>0 : found
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author:
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	paul vixie, 29may94
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_nameinquery(const char *name, int type, int class,
2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		const u_char *buf, const u_char *eom)
2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp = buf + HFIXEDSZ;
2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (qdcount-- > 0) {
2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		char tname[MAXDNAME+1];
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int n, ttype, tclass;
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = dn_expand(buf, eom, cp, tname, sizeof tname);
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (n < 0)
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += n;
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (cp + 2 * INT16SZ > eom)
3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ttype = ns_get16(cp); cp += INT16SZ;
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tclass = ns_get16(cp); cp += INT16SZ;
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (ttype == type && tclass == class &&
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ns_samename(tname, name) == 1)
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (1);
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (0);
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* int
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * res_queriesmatch(buf1, eom1, buf2, eom2)
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	is there a 1:1 mapping of (name,type,class)
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	in (buf1,eom1) and (buf2,eom2)?
3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * returns:
3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	-1 : format error
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	0  : not a 1:1 mapping
3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	>0 : is a 1:1 mapping
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * author:
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	paul vixie, 29may94
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_queriesmatch(const u_char *buf1, const u_char *eom1,
3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 const u_char *buf2, const u_char *eom2)
3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp = buf1 + HFIXEDSZ;
3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Only header section present in replies to
3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * dynamic update packets.
3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (1);
3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (qdcount-- > 0) {
3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		char tname[MAXDNAME+1];
3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int n, ttype, tclass;
3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (n < 0)
3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += n;
3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (cp + 2 * INT16SZ > eom1)
3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (-1);
3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ttype = ns_get16(cp);	cp += INT16SZ;
3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tclass = ns_get16(cp); cp += INT16SZ;
3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (1);
3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_nsend(res_state statp,
3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	  const u_char *buf, int buflen, u_char *ans, int anssiz)
3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char abuf[NI_MAXHOST];
3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if USE_RESOLV_CACHE
3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        struct resolv_cache*  cache;
3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ResolvCacheStatus     cache_status = RESOLV_CACHE_UNSUPPORTED;
3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (statp->nscount == 0) {
3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = ESRCH;
3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (anssiz < HFIXEDSZ) {
3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EINVAL;
3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
3821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		(stdout, ";; res_send()\n"), buf, buflen);
3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	gotsomewhere = 0;
3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	terrno = ETIMEDOUT;
3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if USE_RESOLV_CACHE
3881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        cache = __get_res_cache();
3891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (cache != NULL) {
3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            int  anslen = 0;
3911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            cache_status = _resolv_cache_lookup(
3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                cache, buf, buflen,
3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                ans, anssiz, &anslen);
3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if (cache_status == RESOLV_CACHE_FOUND) {
3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return anslen;
3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            }
3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        }
3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * If the ns_addr_list in the resolver context has changed, then
4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * invalidate our cached copy and the associated timing data.
4041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (EXT(statp).nscount != 0) {
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int needclose = 0;
4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		struct sockaddr_storage peer;
4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		socklen_t peerlen;
4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).nscount != statp->nscount)
4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			needclose++;
4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		else
4131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			for (ns = 0; ns < statp->nscount; ns++) {
4141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (statp->nsaddr_list[ns].sin_family &&
4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					     (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
4171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					needclose++;
4181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
4191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
4201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (EXT(statp).nssocks[ns] == -1)
4221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					continue;
4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				peerlen = sizeof(peer);
42487043f9c89593125a27199d0c1b4069d088672d7Jim Huang				if (getpeername(EXT(statp).nssocks[ns],
4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					needclose++;
4271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (!sock_eq((struct sockaddr *)(void *)&peer,
4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    get_nsaddr(statp, (size_t)ns))) {
4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					needclose++;
4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (needclose) {
4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nscount = 0;
4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Maybe initialize our private copy of the ns_addr_list.
4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (EXT(statp).nscount == 0) {
4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (ns = 0; ns < statp->nscount; ns++) {
4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nstimes[ns] = RES_MAXTIME;
4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nssocks[ns] = -1;
4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (!statp->nsaddr_list[ns].sin_family)
4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).ext->nsaddrs[ns].sin =
4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 statp->nsaddr_list[ns];
4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		EXT(statp).nscount = statp->nscount;
4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Some resolvers want to even out the load on their nameservers.
4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Note that RES_BLAST overrides RES_ROTATE.
4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((statp->options & RES_ROTATE) != 0U &&
4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    (statp->options & RES_BLAST) == 0U) {
4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		union res_sockaddr_union inu;
4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		struct sockaddr_in ina;
4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int lastns = statp->nscount - 1;
4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int fd;
4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		u_int16_t nstime;
4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).ext != NULL)
4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			inu = EXT(statp).ext->nsaddrs[0];
4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ina = statp->nsaddr_list[0];
4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fd = EXT(statp).nssocks[0];
4721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nstime = EXT(statp).nstimes[0];
4731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (ns = 0; ns < lastns; ns++) {
4741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (EXT(statp).ext != NULL)
4751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                EXT(statp).ext->nsaddrs[ns] =
4761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					EXT(statp).ext->nsaddrs[ns + 1];
4771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
4781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).ext != NULL)
4821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			EXT(statp).ext->nsaddrs[lastns] = inu;
4831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->nsaddr_list[lastns] = ina;
4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		EXT(statp).nssocks[lastns] = fd;
4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		EXT(statp).nstimes[lastns] = nstime;
4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Send request, RETRY times, or until successful.
4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
4911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (try = 0; try < statp->retry; try++) {
4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    for (ns = 0; ns < statp->nscount; ns++) {
4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		struct sockaddr *nsap;
4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int nsaplen;
4951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nsap = get_nsaddr(statp, (size_t)ns);
4961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nsaplen = get_salen(nsap);
4971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->_flags &= ~RES_F_LASTMASK;
4981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->_flags |= (ns << RES_F_LASTSHIFT);
4991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project same_ns:
5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->qhook) {
5011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			int done = 0, loops = 0;
5021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			do {
5041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				res_sendhookact act;
5051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				act = (*statp->qhook)(&nsap, &buf, &buflen,
5071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						      ans, anssiz, &resplen);
5081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				switch (act) {
5091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_goahead:
5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					done = 1;
5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
5121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_nextns:
5131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					res_nclose(statp);
5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto next_ns;
5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_done:
5161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					return (resplen);
5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_modified:
5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/* give the hook another try */
5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (++loops < 42) /*doug adams*/
5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						break;
5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/*FALLTHROUGH*/
5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_error:
5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/*FALLTHROUGH*/
5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				default:
5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto fail;
5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} while (!done);
5281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(((statp->options & RES_DEBUG) &&
5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
532ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				NULL, 0, niflags) == 0),
533ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				(stdout, ";; Querying server (# %d) address = %s\n",
534ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				ns + 1, abuf));
5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (v_circuit) {
5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Use VC; at most one attempt per server. */
5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			try = statp->retry;
540ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
5411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    ns);
543ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
544ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
545ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
546ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt					"used send_vc %d\n", n);
547ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
548ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n < 0)
5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto fail;
5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n == 0)
5521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto next_ns;
5531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			resplen = n;
5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else {
5551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Use datagrams. */
556ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
557ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
558ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt					"using send_dg\n");
559ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
560ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
5611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				    ns, &v_circuit, &gotsomewhere);
563ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
564ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
565ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt					"used send_dg %d\n",n);
566ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
567ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
5681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n < 0)
5691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto fail;
5701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n == 0)
5711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto next_ns;
572ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
573ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
574ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt					"time=%d, %d\n",time(NULL), time(NULL)%2);
575ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (v_circuit)
5771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto same_ns;
5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			resplen = n;
5791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint((statp->options & RES_DEBUG) ||
5821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       ((statp->pfcode & RES_PRF_REPLY) &&
5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_HEAD1)),
5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; got answer:\n"));
5851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
5881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, "%s", ""),
5891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
5901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if USE_RESOLV_CACHE
5921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if (cache_status == RESOLV_CACHE_NOTFOUND) {
5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    _resolv_cache_add(cache, buf, buflen,
5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                      ans, resplen);
5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                }
5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * If we have temporarily opened a virtual circuit,
5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * or if we haven't been asked to keep a socket open,
6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * close the socket.
6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    (statp->options & RES_STAYOPEN) == 0U) {
6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
6051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->rhook) {
6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			int done = 0, loops = 0;
6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			do {
6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				res_sendhookact act;
6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				act = (*statp->rhook)(nsap, buf, buflen,
6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						      ans, anssiz, &resplen);
6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				switch (act) {
6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_goahead:
6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_done:
6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					done = 1;
6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_nextns:
6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					res_nclose(statp);
6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto next_ns;
6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_modified:
6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/* give the hook another try */
6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (++loops < 42) /*doug adams*/
6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						break;
6261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/*FALLTHROUGH*/
6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case res_error:
6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/*FALLTHROUGH*/
6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				default:
6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto fail;
6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} while (!done);
6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (resplen);
6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project next_ns: ;
6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	   } /*foreach ns*/
6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} /*foreach retry*/
6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_nclose(statp);
6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!v_circuit) {
6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (!gotsomewhere)
6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = ECONNREFUSED;	/* no nameservers found */
6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		else
6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = ETIMEDOUT;	/* no answer obtained */
6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else
6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = terrno;
647ce5ba8bfcd8ecfb7bfee4412f4f686cecc17e39bHenrik Engström
648ce5ba8bfcd8ecfb7bfee4412f4f686cecc17e39bHenrik Engström#if USE_RESOLV_CACHE
649ce5ba8bfcd8ecfb7bfee4412f4f686cecc17e39bHenrik Engström        _resolv_cache_query_failed(cache, buf, buflen);
650ce5ba8bfcd8ecfb7bfee4412f4f686cecc17e39bHenrik Engström#endif
651ce5ba8bfcd8ecfb7bfee4412f4f686cecc17e39bHenrik Engström
6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (-1);
6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fail:
654a59cfcfd0821f51ee77f13105099f700ccbf9252Mattias Falk#if USE_RESOLV_CACHE
655a59cfcfd0821f51ee77f13105099f700ccbf9252Mattias Falk	_resolv_cache_query_failed(cache, buf, buflen);
656a59cfcfd0821f51ee77f13105099f700ccbf9252Mattias Falk#endif
6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_nclose(statp);
6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (-1);
6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Private */
6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_salen(sa)
6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const struct sockaddr *sa;
6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAVE_SA_LEN
6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* There are people do not set sa_len.  Be forgiving to them. */
6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sa->sa_len)
6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (sa->sa_len);
6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sa->sa_family == AF_INET)
6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (sizeof(struct sockaddr_in));
6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	else if (sa->sa_family == AF_INET6)
6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (sizeof(struct sockaddr_in6));
6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	else
6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);	/* unknown, die on connect */
6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * pick appropriate nsaddr_list for use.  see res_init() for initialization.
6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct sockaddr *
6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_nsaddr(statp, n)
6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_state statp;
6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t n;
6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *   than struct sockaddr, and
6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * - user code did not update statp->nsaddr_list[n].
6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else {
6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * - user code updated statp->nsaddr_list[n], or
7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * - statp->nsaddr_list[n] has the same content as
7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *   EXT(statp).ext->nsaddrs[n].
7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
708ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int get_timeout(const res_state statp, const int ns)
709ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt{
710ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	int timeout = (statp->retrans << ns);
711ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (ns > 0) {
712ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout /= statp->nscount;
713ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
714ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (timeout <= 0) {
715ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout = 1;
716ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
717ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
718ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
719ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			"using timeout of %d sec\n", timeout);
720ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
721ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
722ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	return timeout;
723ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt}
724ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsend_vc(res_state statp,
7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *buf, int buflen, u_char *ans, int anssiz,
7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int *terrno, int ns)
7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const HEADER *hp = (const HEADER *)(const void *)buf;
7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	HEADER *anhp = (HEADER *)(void *)ans;
7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct sockaddr *nsap;
7331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int nsaplen;
7341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int truncating, connreset, resplen, n;
7351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct iovec iov[2];
7361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_short len;
7371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *cp;
7381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	void *tmp;
7391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
740ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
741ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		__libc_android_log_print(ANDROID_LOG_DEBUG, "libc", "using send_vc\n");
742ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
743ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
7441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nsap = get_nsaddr(statp, (size_t)ns);
7451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nsaplen = get_salen(nsap);
7461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	connreset = 0;
7481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project same_ns:
7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	truncating = 0;
7501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Are we still talking to whom we want to talk to? */
7521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		struct sockaddr_storage peer;
7541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		socklen_t size = sizeof peer;
7551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (getpeername(statp->_vcsock,
7571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				(struct sockaddr *)(void *)&peer, &size) < 0 ||
7581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    !sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
7591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
7601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			statp->_flags &= ~RES_F_VC;
7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->_vcsock >= 0)
7661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
7671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
7691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->_vcsock > highestFD) {
7701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
7711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = ENOTSOCK;
7721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
7731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (statp->_vcsock < 0) {
7741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			switch (errno) {
7751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EPROTONOSUPPORT:
7761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef EPFNOSUPPORT
7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EPFNOSUPPORT:
7781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
7791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EAFNOSUPPORT:
7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				Perror(statp, stderr, "socket(vc)", errno);
7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (0);
7821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			default:
7831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*terrno = errno;
7841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				Perror(statp, stderr, "socket(vc)", errno);
7851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
7861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
7871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
7881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = 0;
7891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
7901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*terrno = errno;
7911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			Aerror(statp, stderr, "bind/vc", errno, nsap,
7921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    nsaplen);
7931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
7941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
7951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
796ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (connect_with_timeout(statp->_vcsock, nsap, (socklen_t)nsaplen,
797ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				get_timeout(statp, ns)) < 0) {
7981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*terrno = errno;
7991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			Aerror(statp, stderr, "connect/vc", errno, nsap,
8001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    nsaplen);
8011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
8021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
8031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
8041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->_flags |= RES_F_VC;
8051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
8081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Send length & message
8091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
8101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	ns_put16((u_short)buflen, (u_char*)(void *)&len);
8111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	iov[0] = evConsIovec(&len, INT16SZ);
8121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	DE_CONST(buf, tmp);
8131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	iov[1] = evConsIovec(tmp, (size_t)buflen);
8141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
8151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = errno;
8161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "write failed", errno);
8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
8191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
8211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Receive length & response
8221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
8231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project read_len:
8241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = ans;
8251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	len = INT16SZ;
8261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
8271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += n;
8281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((len -= n) == 0)
8291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
8301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n <= 0) {
8321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = errno;
8331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "read failed", errno);
8341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
8351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
8361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * A long running process might get its TCP
8371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * connection reset if the remote server was
8381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * restarted.  Requery the server instead of
8391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * trying a new one.  When there is only one
8401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * server, this means that a query might work
8411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * instead of failing.  We only allow one reset
8421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * per query to prevent looping.
8431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
8441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (*terrno == ECONNRESET && !connreset) {
8451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			connreset = 1;
8461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
8471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto same_ns;
8481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
8491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
8501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
8511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	resplen = ns_get16(ans);
8531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (resplen > anssiz) {
8541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
8551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; response truncated\n")
8561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       );
8571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		truncating = 1;
8581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len = anssiz;
8591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else
8601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len = resplen;
8611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (len < HFIXEDSZ) {
8621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
8631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Undersized message.
8641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
8651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
8661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; undersized: %d\n", len));
8671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = EMSGSIZE;
8681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
8691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
8701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = ans;
8721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
8731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += n;
8741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len -= n;
8751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n <= 0) {
8771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = errno;
8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "read(vc)", errno);
8791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
8801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
8811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (truncating) {
8831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Flush rest of answer so connection stays in synch.
8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		anhp->tc = 1;
8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len = resplen - anssiz;
8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		while (len != 0) {
8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			char junk[PACKETSZ];
8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n = read(statp->_vcsock, junk,
8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 (len > sizeof junk) ? sizeof junk : len);
8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n > 0)
8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				len -= n;
8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else
8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				break;
8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * If the calling applicating has bailed out of
9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * a previous call and failed to arrange to have
9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * the circuit closed or the server has got
9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * itself confused, then drop the packet and
9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * wait for the correct one.
9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (hp->id != anhp->id) {
9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
9081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, ";; old answer (unexpected):\n"),
9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz: resplen);
9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		goto read_len;
9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * All is well, or the error is fatal.  Signal that the
9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * next nameserver ought not be tried.
9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (resplen);
9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
921ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt/* return -1 on error (errno set), 0 on success */
922ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int
923ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltconnect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int sec)
924ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt{
925ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	int res, origflags;
926ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	fd_set rset, wset;
927ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	struct timespec now, timeout, finish;
928ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
929ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	origflags = fcntl(sock, F_GETFL, 0);
930ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
931ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
932ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	res = connect(sock, nsap, salen);
933ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (res < 0 && errno != EINPROGRESS) {
934ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt                res = -1;
935ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt                goto done;
936ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
937ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (res != 0) {
938ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		now = evNowTime();
939ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout = evConsTime((long)sec, 0L);
940ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		finish = evAddTime(now, timeout);
941ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (DBG) {
942ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
943ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				"  %d send_vc\n", sock);
944ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
945ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
946ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		res = retrying_select(sock, &rset, &wset, &finish);
947ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (res <= 0) {
948ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt                        res = -1;
949ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
950ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
951ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltdone:
952ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	fcntl(sock, F_SETFL, origflags);
953ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
954ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
955ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			"  %d connect_with_timeout returning %s\n", sock, res);
956ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
957ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	return res;
958ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt}
959ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
960ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltstatic int
961ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltretrying_select(const int sock, fd_set *readset, fd_set *writeset, const struct timespec *finish)
962ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt{
963ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	struct timespec now, timeout;
964ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	int n, error;
965ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	socklen_t len;
966ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
967ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
968ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltretry:
969ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
970ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		__libc_android_log_print(ANDROID_LOG_DEBUG, "libc", "  %d retying_select\n", sock);
971ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
972ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
973ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	now = evNowTime();
974ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (readset) {
975ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		FD_ZERO(readset);
976ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		FD_SET(sock, readset);
977ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
978ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (writeset) {
979ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		FD_ZERO(writeset);
980ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		FD_SET(sock, writeset);
981ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
982ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (evCmpTime(*finish, now) > 0)
983ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout = evSubTime(*finish, now);
984ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	else
985ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		timeout = evConsTime(0L, 0L);
986ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
987ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	n = pselect(sock + 1, readset, writeset, NULL, &timeout, NULL);
988ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (n == 0) {
989ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (DBG) {
990ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			__libc_android_log_print(ANDROID_LOG_DEBUG, " libc",
991ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				"  %d retrying_select timeout\n", sock);
992ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
993ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		errno = ETIMEDOUT;
994ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		return 0;
995ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
996ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (n < 0) {
997ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (errno == EINTR)
998ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			goto retry;
999ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (DBG) {
1000ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
1001ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				"  %d retrying_select got error %d\n",sock, n);
1002ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
1003ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		return n;
1004ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1005ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if ((readset && FD_ISSET(sock, readset)) || (writeset && FD_ISSET(sock, writeset))) {
1006ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		len = sizeof(error);
1007ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
1008ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			errno = error;
1009ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			if (DBG) {
1010ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt				__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
1011ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt					"  %d retrying_select dot error2 %d\n", sock, errno);
1012ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			}
1013ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1014ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			return -1;
1015ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		}
1016ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1017ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	if (DBG) {
1018ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		__libc_android_log_print(ANDROID_LOG_DEBUG, "libc",
1019ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt			"  %d retrying_select returning %d for %d\n",sock, n);
1020ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	}
1021ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1022ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	return n;
1023ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt}
1024ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
1025ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
10261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
10271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsend_dg(res_state statp,
10281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *buf, int buflen, u_char *ans, int anssiz,
10291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int *terrno, int ns, int *v_circuit, int *gotsomewhere)
10301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
10311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const HEADER *hp = (const HEADER *)(const void *)buf;
10321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	HEADER *anhp = (HEADER *)(void *)ans;
10331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const struct sockaddr *nsap;
10341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int nsaplen;
10351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct timespec now, timeout, finish;
10361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fd_set dsmask;
10371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct sockaddr_storage from;
10381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	socklen_t fromlen;
10391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int resplen, seconds, n, s;
10401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nsap = get_nsaddr(statp, (size_t)ns);
10421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nsaplen = get_salen(nsap);
10431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (EXT(statp).nssocks[ns] == -1) {
10441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
10451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).nssocks[ns] > highestFD) {
10461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
10471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			errno = ENOTSOCK;
10481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
10491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (EXT(statp).nssocks[ns] < 0) {
10501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			switch (errno) {
10511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EPROTONOSUPPORT:
10521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef EPFNOSUPPORT
10531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EPFNOSUPPORT:
10541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
10551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			case EAFNOSUPPORT:
10561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				Perror(statp, stderr, "socket(dg)", errno);
10571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (0);
10581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			default:
10591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*terrno = errno;
10601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				Perror(statp, stderr, "socket(dg)", errno);
10611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return (-1);
10621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
10631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
10641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef CANNOT_CONNECT_DGRAM
10651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
10661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * On a 4.3BSD+ machine (client and server,
10671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * actually), sending to a nameserver datagram
10681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * port with no nameserver will cause an
10691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * ICMP port unreachable message to be returned.
10701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * If our datagram socket is "connected" to the
10711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * server, we get an ECONNREFUSED error on the next
10721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * socket operation, and select returns if the
10731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * error message is received.  We can thus detect
10741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * the absence of a nameserver without timing out.
10751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
10761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) {
10771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			Aerror(statp, stderr, "bind(dg)", errno, nsap,
10781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    nsaplen);
10791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
10801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
10811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
10821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
10831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			Aerror(statp, stderr, "connect(dg)", errno, nsap,
10841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    nsaplen);
10851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			res_nclose(statp);
10861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
10871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
10881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !CANNOT_CONNECT_DGRAM */
10891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
10901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; new DG socket\n"))
10911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
10921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	s = EXT(statp).nssocks[ns];
10931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef CANNOT_CONNECT_DGRAM
10941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
10951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "send", errno);
10961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
10971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
10981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
10991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else /* !CANNOT_CONNECT_DGRAM */
11001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
11011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	{
11021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
11031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
11041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
11051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* !CANNOT_CONNECT_DGRAM */
11071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
11091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Wait for reply.
11101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
1111ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	seconds = get_timeout(statp, ns);
11121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	now = evNowTime();
11131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	timeout = evConsTime((long)seconds, 0L);
11141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	finish = evAddTime(now, timeout);
1115ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwaltretry:
1116ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt	n = retrying_select(s, &dsmask, NULL, &finish);
1117ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt
11181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n == 0) {
11191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
11201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*gotsomewhere = 1;
11211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
11221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n < 0) {
11241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "select", errno);
11251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
11261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
11271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	errno = 0;
11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fromlen = sizeof(from);
11301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
11311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			   (struct sockaddr *)(void *)&from, &fromlen);
11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (resplen <= 0) {
11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Perror(statp, stderr, "recvfrom", errno);
11341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
11351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*gotsomewhere = 1;
11381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (resplen < HFIXEDSZ) {
11391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
11401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Undersized message.
11411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
11421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; undersized: %d\n",
11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			resplen));
11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*terrno = EMSGSIZE;
11461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
11471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
11481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (hp->id != anhp->id) {
11501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * response from old query, ignore it.
11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * XXX - potential security hazard could
11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *	 be detected here.
11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1155524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#ifdef ANDROID_CHANGES
1156524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra		__libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_OLD_RESPONSE);
1157524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#endif
11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
11591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
11601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, ";; old answer:\n"),
11611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
1162ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		goto retry;
11631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!(statp->options & RES_INSECURE1) &&
11651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
11661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
11671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * response from wrong server? ignore it.
11681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * XXX - potential security hazard could
11691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *	 be detected here.
11701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1171524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#ifdef ANDROID_CHANGES
1172524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra		__libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_SERVER);
1173524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#endif
11741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
11751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
11761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, ";; not our server:\n"),
11771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
1178ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		goto retry;
11791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef RES_USE_EDNS0
11811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
11821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
11831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Do not retry if the server do not understand EDNS0.
11841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * The case has to be captured here, as FORMERR packet do not
11851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * carry query section, hence res_queriesmatch() returns 0.
11861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
11871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ(statp->options & RES_DEBUG,
11881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, "server rejected query with EDNS0:\n"),
11891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
11901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* record the error */
11911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		statp->_flags |= RES_F_EDNS0ERR;
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#endif
11961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!(statp->options & RES_INSECURE2) &&
11971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    !res_queriesmatch(buf, buf + buflen,
11981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			      ans, ans + anssiz)) {
11991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
12001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * response contains wrong query? ignore it.
12011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * XXX - potential security hazard could
12021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *	 be detected here.
12031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1204524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#ifdef ANDROID_CHANGES
1205524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra		__libc_android_log_event_uid(BIONIC_EVENT_RESOLVER_WRONG_QUERY);
1206524c87c61c1d39dd60aaa8ae01ec3528ce212288Geremy Condra#endif
12071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ((statp->options & RES_DEBUG) ||
12081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(statp->pfcode & RES_PRF_REPLY),
12091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, ";; wrong query name:\n"),
12101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
1211ecd0e95a0276c1ba72c7331f5e4617815f015f22Robert Greenwalt		goto retry;;
12121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (anhp->rcode == SERVFAIL ||
12141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    anhp->rcode == NOTIMP ||
12151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    anhp->rcode == REFUSED) {
12161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		DprintQ(statp->options & RES_DEBUG,
12171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(stdout, "server rejected query:\n"),
12181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ans, (resplen > anssiz) ? anssiz : resplen);
12191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
12201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* don't retry if called from dig */
12211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (!statp->pfcode)
12221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return (0);
12231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!(statp->options & RES_IGNTC) && anhp->tc) {
12251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
12261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * To get the rest of answer,
12271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * use TCP with same server.
12281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
12291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		Dprint(statp->options & RES_DEBUG,
12301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		       (stdout, ";; truncated answer\n"));
12311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*v_circuit = 1;
12321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		res_nclose(statp);
12331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (1);
12341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
12361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * All is well, or the error is fatal.  Signal that the
12371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * next nameserver ought not be tried.
12381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
12391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (resplen);
12401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
12411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void
12431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectAerror(const res_state statp, FILE *file, const char *string, int error,
12441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       const struct sockaddr *address, int alen)
12451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
12461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int save = errno;
12471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char hbuf[NI_MAXHOST];
12481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char sbuf[NI_MAXSERV];
12491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	alen = alen;
12511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((statp->options & RES_DEBUG) != 0U) {
12531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
12541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    sbuf, sizeof(sbuf), niflags)) {
12551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			strncpy(hbuf, "?", sizeof(hbuf) - 1);
12561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			hbuf[sizeof(hbuf) - 1] = '\0';
12571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			strncpy(sbuf, "?", sizeof(sbuf) - 1);
12581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			sbuf[sizeof(sbuf) - 1] = '\0';
12591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
12601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fprintf(file, "res_send: %s ([%s].%s): %s\n",
12611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			string, hbuf, sbuf, strerror(error));
12621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	errno = save;
12641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
12651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void
12671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectPerror(const res_state statp, FILE *file, const char *string, int error) {
12681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int save = errno;
12691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((statp->options & RES_DEBUG) != 0U)
12711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fprintf(file, "res_send: %s: %s\n",
12721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			string, strerror(error));
12731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	errno = save;
12741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
12751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
12771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsock_eq(struct sockaddr *a, struct sockaddr *b) {
12781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct sockaddr_in *a4, *b4;
12791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct sockaddr_in6 *a6, *b6;
12801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (a->sa_family != b->sa_family)
12821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return 0;
12831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (a->sa_family) {
12841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET:
12851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		a4 = (struct sockaddr_in *)(void *)a;
12861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		b4 = (struct sockaddr_in *)(void *)b;
12871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return a4->sin_port == b4->sin_port &&
12881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    a4->sin_addr.s_addr == b4->sin_addr.s_addr;
12891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET6:
12901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		a6 = (struct sockaddr_in6 *)(void *)a;
12911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		b6 = (struct sockaddr_in6 *)(void *)b;
12921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return a6->sin6_port == b6->sin6_port &&
12931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAVE_SIN6_SCOPE_ID
12941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    a6->sin6_scope_id == b6->sin6_scope_id &&
12951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
12961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
12971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
12981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return 0;
12991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
13001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
13011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef NEED_PSELECT
13031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* XXX needs to move to the porting library. */
13041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
13051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectpselect(int nfds, void *rfds, void *wfds, void *efds,
13061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct timespec *tsp, const sigset_t *sigmask)
13071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
13081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct timeval tv, *tvp;
13091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	sigset_t sigs;
13101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n;
13111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (tsp) {
13131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tvp = &tv;
13141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tv = evTimeVal(*tsp);
13151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else
13161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		tvp = NULL;
13171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sigmask)
13181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		sigprocmask(SIG_SETMASK, sigmask, &sigs);
13191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n = select(nfds, rfds, wfds, efds, tvp);
13201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (sigmask)
13211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		sigprocmask(SIG_SETMASK, &sigs, NULL);
13221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (tsp)
13231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*tsp = evTimeSpec(tv);
13241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (n);
13251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
13261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1327