Bug 694325: Add threadsafe getaddrinfo to libmozutils; restore multi-threading to nsHostResolver for DNS requests. r=mwu
authorSteve Workman <sworkman@mozilla.com>
Mon, 21 Nov 2011 18:21:21 -0800
changeset 80619 bfb56029f4bd348e5b4498fae049cc57f6729a12
parent 80618 40cb4adf09cc17016e63d5a23cc72b9c85cf994c
child 80620 33653bf11d1573822110629f5e3fcc45529f1007
push idunknown
push userunknown
push dateunknown
reviewersmwu
bugs694325
milestone11.0a1
Bug 694325: Add threadsafe getaddrinfo to libmozutils; restore multi-threading to nsHostResolver for DNS requests. r=mwu
configure.in
netwerk/dns/nsHostResolver.h
other-licenses/android/Makefile.in
other-licenses/android/arpa_nameser.h
other-licenses/android/arpa_nameser_compat.h
other-licenses/android/eventlib.h
other-licenses/android/getaddrinfo.c
other-licenses/android/res_debug.c
other-licenses/android/res_debug.h
other-licenses/android/res_init.c
other-licenses/android/res_mkquery.c
other-licenses/android/res_private.h
other-licenses/android/res_send.c
other-licenses/android/res_state.c
other-licenses/android/resolv_cache.h
other-licenses/android/resolv_private.h
other-licenses/android/resolv_static.h
xpcom/base/nsSystemInfo.cpp
--- a/configure.in
+++ b/configure.in
@@ -7279,17 +7279,17 @@ AC_SUBST(WIN32_CRT_LIBS)
 dnl Need to set this for make because NSS doesn't have configure
 AC_SUBST(DLLFLAGS)
 
 dnl We need to wrap dlopen and related functions on Android because we use
 dnl our own linker.
 if test "$OS_TARGET" = Android; then
     WRAP_LDFLAGS="${WRAP_LDFLAGS} -L$_objdir/dist/lib -lmozutils"
     if test "$MOZ_WIDGET_TOOLKIT" = android; then
-        WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=dlopen,--wrap=dlclose,--wrap=dlerror,--wrap=dlsym,--wrap=dladdr"
+        WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=dlopen,--wrap=dlclose,--wrap=dlerror,--wrap=dlsym,--wrap=dladdr,--wrap=getaddrinfo,--wrap=freeaddrinfo,--wrap=gai_strerror"
     fi
 fi
 
 dnl ========================================================
 dnl = Use malloc wrapper lib
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(wrap-malloc,
 [  --enable-wrap-malloc    Wrap malloc calls (gnu linker only)],
--- a/netwerk/dns/nsHostResolver.h
+++ b/netwerk/dns/nsHostResolver.h
@@ -66,29 +66,19 @@ class nsResolveHostCallback;
     PRInt32 Release() {                                                      \
         PRInt32 n = NS_AtomicDecrementRefcnt(_refc);                         \
         NS_LOG_RELEASE(this, n, #classname);                                 \
         if (n == 0)                                                          \
             delete this;                                                     \
         return n;                                                            \
     }
 
-#ifdef ANDROID
-// See bug 687367 - pre gingerbread android has race conditions involving stdio.
-// stdio is used as part of the getaddrinfo() implementation. In order to reduce
-// that race window limit ourselves to 1 lookup at a time on android.
-
-#define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY  0
-#define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 1
-#define MAX_NON_PRIORITY_REQUESTS 0
-#else
 #define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY  3
 #define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 5
 #define MAX_NON_PRIORITY_REQUESTS 150
-#endif
 
 #define MAX_RESOLVER_THREADS (MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
                               MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
 
 struct nsHostKey
 {
     const char *host;
     PRUint16    flags;
--- a/other-licenses/android/Makefile.in
+++ b/other-licenses/android/Makefile.in
@@ -66,18 +66,24 @@ CPPSRCS = \
   nsGeckoUtils.cpp \
   APKOpen.cpp \
   $(NULL)
 
 CSRCS = \
   ba.c \
   debugger.c \
   dlfcn.c \
+  getaddrinfo.c \
   linker.c \
   linker_format.c \
+  res_debug.c \
+  res_init.c \
+  res_mkquery.c \
+  res_send.c \
+  res_state.c \
   rt.c \
   $(NULL)
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/components/startup
 
 EXPORTS = APKOpen.h
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/arpa_nameser.h
@@ -0,0 +1,587 @@
+/*	$NetBSD: nameser.h,v 1.19 2005/12/26 19:01:47 perry Exp $	*/
+
+/*
+ * Copyright (c) 1983, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *	Id: nameser.h,v 1.2.2.4.4.1 2004/03/09 08:33:30 marka Exp
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#ifndef _ARPA_NAMESER_H_
+#define _ARPA_NAMESER_H_
+
+#define BIND_4_COMPAT
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+/*
+ * Revision information.  This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__NAMESER > 19931104)".  Do not
+ * compare for equality; rather, use it to determine whether your libbind.a
+ * contains a new enough lib/nameser/ to support the feature you need.
+ */
+
+#define __NAMESER	19991006	/* New interface version stamp. */
+
+/*
+ * Define constants based on RFC 883, RFC 1034, RFC 1035
+ */
+#define NS_PACKETSZ	512	/* default UDP packet size */
+#define NS_MAXDNAME	1025	/* maximum domain name */
+#define NS_MAXMSG	65535	/* maximum message size */
+#define NS_MAXCDNAME	255	/* maximum compressed domain name */
+#define NS_MAXLABEL	63	/* maximum length of domain label */
+#define NS_HFIXEDSZ	12	/* #/bytes of fixed data in header */
+#define NS_QFIXEDSZ	4	/* #/bytes of fixed data in query */
+#define NS_RRFIXEDSZ	10	/* #/bytes of fixed data in r record */
+#define NS_INT32SZ	4	/* #/bytes of data in a uint32_t */
+#define NS_INT16SZ	2	/* #/bytes of data in a uint16_t */
+#define NS_INT8SZ	1	/* #/bytes of data in a uint8_t */
+#define NS_INADDRSZ	4	/* IPv4 T_A */
+#define NS_IN6ADDRSZ	16	/* IPv6 T_AAAA */
+#define NS_CMPRSFLGS	0xc0	/* Flag bits indicating name compression. */
+#define NS_DEFAULTPORT	53	/* For both TCP and UDP. */
+
+/*
+ * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord()
+ * in synch with it.
+ */
+typedef enum __ns_sect {
+	ns_s_qd = 0,		/* Query: Question. */
+	ns_s_zn = 0,		/* Update: Zone. */
+	ns_s_an = 1,		/* Query: Answer. */
+	ns_s_pr = 1,		/* Update: Prerequisites. */
+	ns_s_ns = 2,		/* Query: Name servers. */
+	ns_s_ud = 2,		/* Update: Update. */
+	ns_s_ar = 3,		/* Query|Update: Additional records. */
+	ns_s_max = 4
+} ns_sect;
+
+/*
+ * This is a message handle.  It is caller allocated and has no dynamic data.
+ * This structure is intended to be opaque to all but ns_parse.c, thus the
+ * leading _'s on the member names.  Use the accessor functions, not the _'s.
+ */
+typedef struct __ns_msg {
+	const u_char	*_msg, *_eom;
+	uint16_t	_id, _flags, _counts[ns_s_max];
+	const u_char	*_sections[ns_s_max];
+	ns_sect		_sect;
+	int		_rrnum;
+	const u_char	*_msg_ptr;
+} ns_msg;
+
+/* Private data structure - do not use from outside library. */
+struct _ns_flagdata {  int mask, shift;  };
+extern const struct _ns_flagdata _ns_flagdata[];
+
+/* Accessor macros - this is part of the public interface. */
+
+#define ns_msg_id(handle) ((handle)._id + 0)
+#define ns_msg_base(handle) ((handle)._msg + 0)
+#define ns_msg_end(handle) ((handle)._eom + 0)
+#define ns_msg_size(handle) ((size_t)((handle)._eom - (handle)._msg))
+#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
+
+/*
+ * This is a parsed record.  It is caller allocated and has no dynamic data.
+ */
+typedef	struct __ns_rr {
+	char		name[NS_MAXDNAME];
+	uint16_t	type;
+	uint16_t	rr_class;
+	uint32_t	ttl;
+	uint16_t	rdlength;
+	const u_char *	rdata;
+} ns_rr;
+
+/* Accessor macros - this is part of the public interface. */
+#define ns_rr_name(rr)	(((rr).name[0] != '\0') ? (rr).name : ".")
+#define ns_rr_type(rr)	((ns_type)((rr).type + 0))
+#define ns_rr_class(rr)	((ns_class)((rr).rr_class + 0))
+#define ns_rr_ttl(rr)	((u_long)(rr).ttl + 0)
+#define ns_rr_rdlen(rr)	((size_t)(rr).rdlength + 0)
+#define ns_rr_rdata(rr)	((rr).rdata + 0)
+
+/*
+ * These don't have to be in the same order as in the packet flags word,
+ * and they can even overlap in some cases, but they will need to be kept
+ * in synch with ns_parse.c:ns_flagdata[].
+ */
+typedef enum __ns_flag {
+	ns_f_qr,		/* Question/Response. */
+	ns_f_opcode,		/* Operation code. */
+	ns_f_aa,		/* Authoritative Answer. */
+	ns_f_tc,		/* Truncation occurred. */
+	ns_f_rd,		/* Recursion Desired. */
+	ns_f_ra,		/* Recursion Available. */
+	ns_f_z,			/* MBZ. */
+	ns_f_ad,		/* Authentic Data (DNSSEC). */
+	ns_f_cd,		/* Checking Disabled (DNSSEC). */
+	ns_f_rcode,		/* Response code. */
+	ns_f_max
+} ns_flag;
+
+/*
+ * Currently defined opcodes.
+ */
+typedef enum __ns_opcode {
+	ns_o_query = 0,		/* Standard query. */
+	ns_o_iquery = 1,	/* Inverse query (deprecated/unsupported). */
+	ns_o_status = 2,	/* Name server status query (unsupported). */
+				/* Opcode 3 is undefined/reserved. */
+	ns_o_notify = 4,	/* Zone change notification. */
+	ns_o_update = 5,	/* Zone update message. */
+	ns_o_max = 6
+} ns_opcode;
+
+/*
+ * Currently defined response codes.
+ */
+typedef	enum __ns_rcode {
+	ns_r_noerror = 0,	/* No error occurred. */
+	ns_r_formerr = 1,	/* Format error. */
+	ns_r_servfail = 2,	/* Server failure. */
+	ns_r_nxdomain = 3,	/* Name error. */
+	ns_r_notimpl = 4,	/* Unimplemented. */
+	ns_r_refused = 5,	/* Operation refused. */
+	/* these are for BIND_UPDATE */
+	ns_r_yxdomain = 6,	/* Name exists */
+	ns_r_yxrrset = 7,	/* RRset exists */
+	ns_r_nxrrset = 8,	/* RRset does not exist */
+	ns_r_notauth = 9,	/* Not authoritative for zone */
+	ns_r_notzone = 10,	/* Zone of record different from zone section */
+	ns_r_max = 11,
+	/* The following are EDNS extended rcodes */
+	ns_r_badvers = 16,
+	/* The following are TSIG errors */
+	ns_r_badsig = 16,
+	ns_r_badkey = 17,
+	ns_r_badtime = 18
+} ns_rcode;
+
+/* BIND_UPDATE */
+typedef enum __ns_update_operation {
+	ns_uop_delete = 0,
+	ns_uop_add = 1,
+	ns_uop_max = 2
+} ns_update_operation;
+
+/*
+ * This structure is used for TSIG authenticated messages
+ */
+struct ns_tsig_key {
+        char name[NS_MAXDNAME], alg[NS_MAXDNAME];
+        unsigned char *data;
+        int len;
+};
+typedef struct ns_tsig_key ns_tsig_key;
+
+/*
+ * This structure is used for TSIG authenticated TCP messages
+ */
+struct ns_tcp_tsig_state {
+	int counter;
+	struct dst_key *key;
+	void *ctx;
+	unsigned char sig[NS_PACKETSZ];
+	int siglen;
+};
+typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
+
+#define NS_TSIG_FUDGE 300
+#define NS_TSIG_TCP_COUNT 100
+#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT"
+
+#define NS_TSIG_ERROR_NO_TSIG -10
+#define NS_TSIG_ERROR_NO_SPACE -11
+#define NS_TSIG_ERROR_FORMERR -12
+
+/*
+ * Currently defined type values for resources and queries.
+ */
+typedef enum __ns_type {
+	ns_t_invalid = 0,	/* Cookie. */
+	ns_t_a = 1,		/* Host address. */
+	ns_t_ns = 2,		/* Authoritative server. */
+	ns_t_md = 3,		/* Mail destination. */
+	ns_t_mf = 4,		/* Mail forwarder. */
+	ns_t_cname = 5,		/* Canonical name. */
+	ns_t_soa = 6,		/* Start of authority zone. */
+	ns_t_mb = 7,		/* Mailbox domain name. */
+	ns_t_mg = 8,		/* Mail group member. */
+	ns_t_mr = 9,		/* Mail rename name. */
+	ns_t_null = 10,		/* Null resource record. */
+	ns_t_wks = 11,		/* Well known service. */
+	ns_t_ptr = 12,		/* Domain name pointer. */
+	ns_t_hinfo = 13,	/* Host information. */
+	ns_t_minfo = 14,	/* Mailbox information. */
+	ns_t_mx = 15,		/* Mail routing information. */
+	ns_t_txt = 16,		/* Text strings. */
+	ns_t_rp = 17,		/* Responsible person. */
+	ns_t_afsdb = 18,	/* AFS cell database. */
+	ns_t_x25 = 19,		/* X_25 calling address. */
+	ns_t_isdn = 20,		/* ISDN calling address. */
+	ns_t_rt = 21,		/* Router. */
+	ns_t_nsap = 22,		/* NSAP address. */
+	ns_t_nsap_ptr = 23,	/* Reverse NSAP lookup (deprecated). */
+	ns_t_sig = 24,		/* Security signature. */
+	ns_t_key = 25,		/* Security key. */
+	ns_t_px = 26,		/* X.400 mail mapping. */
+	ns_t_gpos = 27,		/* Geographical position (withdrawn). */
+	ns_t_aaaa = 28,		/* Ip6 Address. */
+	ns_t_loc = 29,		/* Location Information. */
+	ns_t_nxt = 30,		/* Next domain (security). */
+	ns_t_eid = 31,		/* Endpoint identifier. */
+	ns_t_nimloc = 32,	/* Nimrod Locator. */
+	ns_t_srv = 33,		/* Server Selection. */
+	ns_t_atma = 34,		/* ATM Address */
+	ns_t_naptr = 35,	/* Naming Authority PoinTeR */
+	ns_t_kx = 36,		/* Key Exchange */
+	ns_t_cert = 37,		/* Certification record */
+	ns_t_a6 = 38,		/* IPv6 address (deprecates AAAA) */
+	ns_t_dname = 39,	/* Non-terminal DNAME (for IPv6) */
+	ns_t_sink = 40,		/* Kitchen sink (experimentatl) */
+	ns_t_opt = 41,		/* EDNS0 option (meta-RR) */
+	ns_t_apl = 42,		/* Address prefix list (RFC 3123) */
+	ns_t_tkey = 249,	/* Transaction key */
+	ns_t_tsig = 250,	/* Transaction signature. */
+	ns_t_ixfr = 251,	/* Incremental zone transfer. */
+	ns_t_axfr = 252,	/* Transfer zone of authority. */
+	ns_t_mailb = 253,	/* Transfer mailbox records. */
+	ns_t_maila = 254,	/* Transfer mail agent records. */
+	ns_t_any = 255,		/* Wildcard match. */
+	ns_t_zxfr = 256,	/* BIND-specific, nonstandard. */
+	ns_t_max = 65536
+} ns_type;
+
+/* Exclusively a QTYPE? (not also an RTYPE) */
+#define	ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \
+		      (t) == ns_t_mailb || (t) == ns_t_maila)
+/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */
+#define	ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt)
+/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */
+#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t))
+#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr)
+#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
+		       (t) == ns_t_zxfr)
+
+/*
+ * Values for class field
+ */
+typedef enum __ns_class {
+	ns_c_invalid = 0,	/* Cookie. */
+	ns_c_in = 1,		/* Internet. */
+	ns_c_2 = 2,		/* unallocated/unsupported. */
+	ns_c_chaos = 3,		/* MIT Chaos-net. */
+	ns_c_hs = 4,		/* MIT Hesiod. */
+	/* Query class values which do not appear in resource records */
+	ns_c_none = 254,	/* for prereq. sections in update requests */
+	ns_c_any = 255,		/* Wildcard match. */
+	ns_c_max = 65536
+} ns_class;
+
+/* DNSSEC constants. */
+
+typedef enum __ns_key_types {
+	ns_kt_rsa = 1,		/* key type RSA/MD5 */
+	ns_kt_dh  = 2,		/* Diffie Hellman */
+	ns_kt_dsa = 3,		/* Digital Signature Standard (MANDATORY) */
+	ns_kt_private = 254	/* Private key type starts with OID */
+} ns_key_types;
+
+typedef enum __ns_cert_types {
+	cert_t_pkix = 1,	/* PKIX (X.509v3) */
+	cert_t_spki = 2,	/* SPKI */
+	cert_t_pgp  = 3,	/* PGP */
+	cert_t_url  = 253,	/* URL private type */
+	cert_t_oid  = 254	/* OID private type */
+} ns_cert_types;
+
+/* Flags field of the KEY RR rdata. */
+#define	NS_KEY_TYPEMASK		0xC000	/* Mask for "type" bits */
+#define	NS_KEY_TYPE_AUTH_CONF	0x0000	/* Key usable for both */
+#define	NS_KEY_TYPE_CONF_ONLY	0x8000	/* Key usable for confidentiality */
+#define	NS_KEY_TYPE_AUTH_ONLY	0x4000	/* Key usable for authentication */
+#define	NS_KEY_TYPE_NO_KEY	0xC000	/* No key usable for either; no key */
+/* The type bits can also be interpreted independently, as single bits: */
+#define	NS_KEY_NO_AUTH		0x8000	/* Key unusable for authentication */
+#define	NS_KEY_NO_CONF		0x4000	/* Key unusable for confidentiality */
+#define	NS_KEY_RESERVED2	0x2000	/* Security is *mandatory* if bit=0 */
+#define	NS_KEY_EXTENDED_FLAGS	0x1000	/* reserved - must be zero */
+#define	NS_KEY_RESERVED4	0x0800  /* reserved - must be zero */
+#define	NS_KEY_RESERVED5	0x0400  /* reserved - must be zero */
+#define	NS_KEY_NAME_TYPE	0x0300	/* these bits determine the type */
+#define	NS_KEY_NAME_USER	0x0000	/* key is assoc. with user */
+#define	NS_KEY_NAME_ENTITY	0x0200	/* key is assoc. with entity eg host */
+#define	NS_KEY_NAME_ZONE	0x0100	/* key is zone key */
+#define	NS_KEY_NAME_RESERVED	0x0300	/* reserved meaning */
+#define	NS_KEY_RESERVED8	0x0080  /* reserved - must be zero */
+#define	NS_KEY_RESERVED9	0x0040  /* reserved - must be zero */
+#define	NS_KEY_RESERVED10	0x0020  /* reserved - must be zero */
+#define	NS_KEY_RESERVED11	0x0010  /* reserved - must be zero */
+#define	NS_KEY_SIGNATORYMASK	0x000F	/* key can sign RR's of same name */
+#define	NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
+				  NS_KEY_RESERVED4 | \
+				  NS_KEY_RESERVED5 | \
+				  NS_KEY_RESERVED8 | \
+				  NS_KEY_RESERVED9 | \
+				  NS_KEY_RESERVED10 | \
+				  NS_KEY_RESERVED11 )
+#define NS_KEY_RESERVED_BITMASK2 0xFFFF /* no bits defined here */
+
+/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
+#define	NS_ALG_MD5RSA		1	/* MD5 with RSA */
+#define	NS_ALG_DH               2	/* Diffie Hellman KEY */
+#define	NS_ALG_DSA              3	/* DSA KEY */
+#define	NS_ALG_DSS              NS_ALG_DSA
+#define	NS_ALG_EXPIRE_ONLY	253	/* No alg, no security */
+#define	NS_ALG_PRIVATE_OID	254	/* Key begins with OID giving alg */
+
+/* Protocol values  */
+/* value 0 is reserved */
+#define NS_KEY_PROT_TLS         1
+#define NS_KEY_PROT_EMAIL       2
+#define NS_KEY_PROT_DNSSEC      3
+#define NS_KEY_PROT_IPSEC       4
+#define NS_KEY_PROT_ANY		255
+
+/* Signatures */
+#define	NS_MD5RSA_MIN_BITS	 512	/* Size of a mod or exp in bits */
+#define	NS_MD5RSA_MAX_BITS	4096
+	/* Total of binary mod and exp */
+#define	NS_MD5RSA_MAX_BYTES	((NS_MD5RSA_MAX_BITS+7/8)*2+3)
+	/* Max length of text sig block */
+#define	NS_MD5RSA_MAX_BASE64	(((NS_MD5RSA_MAX_BYTES+2)/3)*4)
+#define NS_MD5RSA_MIN_SIZE	((NS_MD5RSA_MIN_BITS+7)/8)
+#define NS_MD5RSA_MAX_SIZE	((NS_MD5RSA_MAX_BITS+7)/8)
+
+#define NS_DSA_SIG_SIZE         41
+#define NS_DSA_MIN_SIZE         213
+#define NS_DSA_MAX_BYTES        405
+
+/* Offsets into SIG record rdata to find various values */
+#define	NS_SIG_TYPE	0	/* Type flags */
+#define	NS_SIG_ALG	2	/* Algorithm */
+#define	NS_SIG_LABELS	3	/* How many labels in name */
+#define	NS_SIG_OTTL	4	/* Original TTL */
+#define	NS_SIG_EXPIR	8	/* Expiration time */
+#define	NS_SIG_SIGNED	12	/* Signature time */
+#define	NS_SIG_FOOT	16	/* Key footprint */
+#define	NS_SIG_SIGNER	18	/* Domain name of who signed it */
+
+/* How RR types are represented as bit-flags in NXT records */
+#define	NS_NXT_BITS 8
+#define	NS_NXT_BIT_SET(  n,p) (p[(n)/NS_NXT_BITS] |=  (0x80>>((n)%NS_NXT_BITS)))
+#define	NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
+#define	NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] &   (0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_MAX 127
+
+/*
+ * EDNS0 extended flags, host order.
+ */
+#define NS_OPT_DNSSEC_OK	0x8000U
+
+/*
+ * Inline versions of get/put short/long.  Pointer is advanced.
+ */
+#define NS_GET16(s, cp) do { \
+	const u_char *t_cp = (const u_char *)(cp); \
+	(s) = ((uint16_t)t_cp[0] << 8) \
+	    | ((uint16_t)t_cp[1]) \
+	    ; \
+	(cp) += NS_INT16SZ; \
+} while (/*CONSTCOND*/0)
+
+#define NS_GET32(l, cp) do { \
+	const u_char *t_cp = (const u_char *)(cp); \
+	(l) = ((uint32_t)t_cp[0] << 24) \
+	    | ((uint32_t)t_cp[1] << 16) \
+	    | ((uint32_t)t_cp[2] << 8) \
+	    | ((uint32_t)t_cp[3]) \
+	    ; \
+	(cp) += NS_INT32SZ; \
+} while (/*CONSTCOND*/0)
+
+#define NS_PUT16(s, cp) do { \
+	uint32_t t_s = (uint32_t)(s); \
+	u_char *t_cp = (u_char *)(cp); \
+	*t_cp++ = t_s >> 8; \
+	*t_cp   = t_s; \
+	(cp) += NS_INT16SZ; \
+} while (/*CONSTCOND*/0)
+
+#define NS_PUT32(l, cp) do { \
+	uint32_t t_l = (uint32_t)(l); \
+	u_char *t_cp = (u_char *)(cp); \
+	*t_cp++ = t_l >> 24; \
+	*t_cp++ = t_l >> 16; \
+	*t_cp++ = t_l >> 8; \
+	*t_cp   = t_l; \
+	(cp) += NS_INT32SZ; \
+} while (/*CONSTCOND*/0)
+
+/*
+ * ANSI C identifier hiding for bind's lib/nameser.
+ */
+#define	ns_msg_getflag		__ns_msg_getflag
+#define ns_get16		__ns_get16
+#define ns_get32		__ns_get32
+#define ns_put16		__ns_put16
+#define ns_put32		__ns_put32
+#define ns_initparse		__ns_initparse
+#define ns_skiprr		__ns_skiprr
+#define ns_parserr		__ns_parserr
+#define	ns_sprintrr		__ns_sprintrr
+#define	ns_sprintrrf		__ns_sprintrrf
+#define	ns_format_ttl		__ns_format_ttl
+#define	ns_parse_ttl		__ns_parse_ttl
+#define ns_datetosecs		__ns_datetosecs
+#define	ns_name_ntol		__ns_name_ntol
+#define	ns_name_ntop		__ns_name_ntop
+#define	ns_name_pton		__ns_name_pton
+#define	ns_name_unpack		__ns_name_unpack
+#define	ns_name_pack		__ns_name_pack
+#define	ns_name_compress	__ns_name_compress
+#define	ns_name_uncompress	__ns_name_uncompress
+#define	ns_name_skip		__ns_name_skip
+#define	ns_name_rollback	__ns_name_rollback
+#define	ns_sign			__ns_sign
+#define	ns_sign2		__ns_sign2
+#define	ns_sign_tcp		__ns_sign_tcp
+#define	ns_sign_tcp2		__ns_sign_tcp2
+#define	ns_sign_tcp_init	__ns_sign_tcp_init
+#define ns_find_tsig		__ns_find_tsig
+#define	ns_verify		__ns_verify
+#define	ns_verify_tcp		__ns_verify_tcp
+#define	ns_verify_tcp_init	__ns_verify_tcp_init
+#define	ns_samedomain		__ns_samedomain
+#define	ns_subdomain		__ns_subdomain
+#define	ns_makecanon		__ns_makecanon
+#define	ns_samename		__ns_samename
+
+__BEGIN_DECLS
+int		ns_msg_getflag(ns_msg, int);
+uint16_t	ns_get16(const u_char *);
+uint32_t	ns_get32(const u_char *);
+void		ns_put16(uint16_t, u_char *);
+void		ns_put32(uint32_t, u_char *);
+int		ns_initparse(const u_char *, int, ns_msg *);
+int		ns_skiprr(const u_char *, const u_char *, ns_sect, int);
+int		ns_parserr(ns_msg *, ns_sect, int, ns_rr *);
+int		ns_sprintrr(const ns_msg *, const ns_rr *,
+				 const char *, const char *, char *, size_t);
+int		ns_sprintrrf(const u_char *, size_t, const char *,
+				  ns_class, ns_type, u_long, const u_char *,
+				  size_t, const char *, const char *,
+				  char *, size_t);
+int		ns_format_ttl(u_long, char *, size_t);
+int		ns_parse_ttl(const char *, u_long *);
+uint32_t	ns_datetosecs(const char *cp, int *errp);
+int		ns_name_ntol(const u_char *, u_char *, size_t);
+int		ns_name_ntop(const u_char *, char *, size_t);
+int		ns_name_pton(const char *, u_char *, size_t);
+int		ns_name_unpack(const u_char *, const u_char *,
+				    const u_char *, u_char *, size_t);
+int		ns_name_pack(const u_char *, u_char *, int,
+				  const u_char **, const u_char **);
+int		ns_name_uncompress(const u_char *, const u_char *,
+					const u_char *, char *, size_t);
+int		ns_name_compress(const char *, u_char *, size_t,
+				      const u_char **, const u_char **);
+int		ns_name_skip(const u_char **, const u_char *);
+void		ns_name_rollback(const u_char *, const u_char **,
+				      const u_char **);
+int		ns_sign(u_char *, int *, int, int, void *,
+			     const u_char *, int, u_char *, int *, time_t);
+int		ns_sign2(u_char *, int *, int, int, void *,
+			      const u_char *, int, u_char *, int *, time_t,
+			      u_char **, u_char **);
+int		ns_sign_tcp(u_char *, int *, int, int,
+				 ns_tcp_tsig_state *, int);
+int		ns_sign_tcp2(u_char *, int *, int, int,
+				  ns_tcp_tsig_state *, int,
+				  u_char **, u_char **);
+int		ns_sign_tcp_init(void *, const u_char *, int,
+					ns_tcp_tsig_state *);
+u_char		*ns_find_tsig(u_char *, u_char *);
+int		ns_verify(u_char *, int *, void *,
+			       const u_char *, int, u_char *, int *,
+			       time_t *, int);
+int		ns_verify_tcp(u_char *, int *, ns_tcp_tsig_state *, int);
+int		ns_verify_tcp_init(void *, const u_char *, int,
+					ns_tcp_tsig_state *);
+int		ns_samedomain(const char *, const char *);
+int		ns_subdomain(const char *, const char *);
+int		ns_makecanon(const char *, char *, size_t);
+int		ns_samename(const char *, const char *);
+__END_DECLS
+
+#ifdef BIND_4_COMPAT
+#include "arpa_nameser_compat.h"
+#endif
+
+#if 0
+#  include <logd.h>
+#  define  XLOG(...)   \
+    __libc_android_log_print(ANDROID_LOG_DEBUG,"libc",__VA_ARGS__)
+#else
+#define  XLOG(...)   do {} while (0)
+#endif
+
+#endif /* !_ARPA_NAMESER_H_ */
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/arpa_nameser_compat.h
@@ -0,0 +1,246 @@
+/*	$NetBSD: nameser_compat.h,v 1.1.1.2 2004/11/07 01:28:27 christos Exp $	*/
+
+/* Copyright (c) 1983, 1989
+ *    The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ * 	This product includes software developed by the University of
+ * 	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ *      from nameser.h	8.1 (Berkeley) 6/2/93
+ *	Id: nameser_compat.h,v 1.1.2.3.4.2 2004/07/01 04:43:41 marka Exp
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#ifndef _ARPA_NAMESER_COMPAT_
+#define	_ARPA_NAMESER_COMPAT_
+
+#define	__BIND		19950621	/* (DEAD) interface version stamp. */
+
+#include <endian.h>
+
+#ifndef BYTE_ORDER
+#if (BSD >= 199103)
+# include <machine/endian.h>
+#else
+#ifdef __linux
+# include <endian.h>
+#else
+#define	LITTLE_ENDIAN	1234	/* least-significant byte first (vax, pc) */
+#define	BIG_ENDIAN	4321	/* most-significant byte first (IBM, net) */
+#define	PDP_ENDIAN	3412	/* LSB first in word, MSW first in long (pdp)*/
+
+#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \
+    defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
+    defined(__alpha__) || defined(__alpha) || \
+    (defined(__Lynx__) && defined(__x86__))
+#define BYTE_ORDER	LITTLE_ENDIAN
+#endif
+
+#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
+    defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
+    defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
+    defined(apollo) || defined(__convex__) || defined(_CRAY) || \
+    defined(__hppa) || defined(__hp9000) || \
+    defined(__hp9000s300) || defined(__hp9000s700) || \
+    defined(__hp3000s900) || defined(__hpux) || defined(MPE) || \
+    defined (BIT_ZERO_ON_LEFT) || defined(m68k) || defined(__sparc) ||  \
+    (defined(__Lynx__) && \
+     (defined(__68k__) || defined(__sparc__) || defined(__powerpc__)))
+#define BYTE_ORDER	BIG_ENDIAN
+#endif
+#endif /* __linux */
+#endif /* BSD */
+#endif /* BYTE_ORDER */
+
+#if !defined(BYTE_ORDER) || \
+    (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \
+    BYTE_ORDER != PDP_ENDIAN)
+	/* you must determine what the correct bit order is for
+	 * your compiler - the next line is an intentional error
+	 * which will force your compiles to bomb until you fix
+	 * the above macros.
+	 */
+  #error "Undefined or invalid BYTE_ORDER";
+#endif
+
+/*
+ * Structure for query header.  The order of the fields is machine- and
+ * compiler-dependent, depending on the byte/bit order and the layout
+ * of bit fields.  We use bit fields only in int variables, as this
+ * is all ANSI requires.  This requires a somewhat confusing rearrangement.
+ */
+
+typedef struct {
+	unsigned	id :16;		/* query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+			/* fields in third byte */
+	unsigned	qr: 1;		/* response flag */
+	unsigned	opcode: 4;	/* purpose of message */
+	unsigned	aa: 1;		/* authoritive answer */
+	unsigned	tc: 1;		/* truncated message */
+	unsigned	rd: 1;		/* recursion desired */
+			/* fields in fourth byte */
+	unsigned	ra: 1;		/* recursion available */
+	unsigned	unused :1;	/* unused bits (MBZ as of 4.9.3a3) */
+	unsigned	ad: 1;		/* authentic data from named */
+	unsigned	cd: 1;		/* checking disabled by resolver */
+	unsigned	rcode :4;	/* response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+			/* fields in third byte */
+	unsigned	rd :1;		/* recursion desired */
+	unsigned	tc :1;		/* truncated message */
+	unsigned	aa :1;		/* authoritive answer */
+	unsigned	opcode :4;	/* purpose of message */
+	unsigned	qr :1;		/* response flag */
+			/* fields in fourth byte */
+	unsigned	rcode :4;	/* response code */
+	unsigned	cd: 1;		/* checking disabled by resolver */
+	unsigned	ad: 1;		/* authentic data from named */
+	unsigned	unused :1;	/* unused bits (MBZ as of 4.9.3a3) */
+	unsigned	ra :1;		/* recursion available */
+#endif
+			/* remaining bytes */
+	unsigned	qdcount :16;	/* number of question entries */
+	unsigned	ancount :16;	/* number of answer entries */
+	unsigned	nscount :16;	/* number of authority entries */
+	unsigned	arcount :16;	/* number of resource entries */
+} HEADER;
+
+#define PACKETSZ	NS_PACKETSZ
+#define MAXDNAME	NS_MAXDNAME
+#define MAXCDNAME	NS_MAXCDNAME
+#define MAXLABEL	NS_MAXLABEL
+#define	HFIXEDSZ	NS_HFIXEDSZ
+#define QFIXEDSZ	NS_QFIXEDSZ
+#define RRFIXEDSZ	NS_RRFIXEDSZ
+#define	INT32SZ		NS_INT32SZ
+#define	INT16SZ		NS_INT16SZ
+#define	INT8SZ		NS_INT8SZ
+#define	INADDRSZ	NS_INADDRSZ
+#define	IN6ADDRSZ	NS_IN6ADDRSZ
+#define	INDIR_MASK	NS_CMPRSFLGS
+#define NAMESERVER_PORT	NS_DEFAULTPORT
+
+#define S_ZONE		ns_s_zn
+#define S_PREREQ	ns_s_pr
+#define S_UPDATE	ns_s_ud
+#define S_ADDT		ns_s_ar
+
+#define QUERY		ns_o_query
+#define IQUERY		ns_o_iquery
+#define STATUS		ns_o_status
+#define	NS_NOTIFY_OP	ns_o_notify
+#define	NS_UPDATE_OP	ns_o_update
+
+#define NOERROR		ns_r_noerror
+#define FORMERR		ns_r_formerr
+#define SERVFAIL	ns_r_servfail
+#define NXDOMAIN	ns_r_nxdomain
+#define NOTIMP		ns_r_notimpl
+#define REFUSED		ns_r_refused
+#define YXDOMAIN	ns_r_yxdomain
+#define YXRRSET		ns_r_yxrrset
+#define NXRRSET		ns_r_nxrrset
+#define NOTAUTH		ns_r_notauth
+#define NOTZONE		ns_r_notzone
+/*#define BADSIG		ns_r_badsig*/
+/*#define BADKEY		ns_r_badkey*/
+/*#define BADTIME		ns_r_badtime*/
+
+
+#define DELETE		ns_uop_delete
+#define ADD		ns_uop_add
+
+#define T_A		ns_t_a
+#define T_NS		ns_t_ns
+#define T_MD		ns_t_md
+#define T_MF		ns_t_mf
+#define T_CNAME		ns_t_cname
+#define T_SOA		ns_t_soa
+#define T_MB		ns_t_mb
+#define T_MG		ns_t_mg
+#define T_MR		ns_t_mr
+#define T_NULL		ns_t_null
+#define T_WKS		ns_t_wks
+#define T_PTR		ns_t_ptr
+#define T_HINFO		ns_t_hinfo
+#define T_MINFO		ns_t_minfo
+#define T_MX		ns_t_mx
+#define T_TXT		ns_t_txt
+#define	T_RP		ns_t_rp
+#define T_AFSDB		ns_t_afsdb
+#define T_X25		ns_t_x25
+#define T_ISDN		ns_t_isdn
+#define T_RT		ns_t_rt
+#define T_NSAP		ns_t_nsap
+#define T_NSAP_PTR	ns_t_nsap_ptr
+#define	T_SIG		ns_t_sig
+#define	T_KEY		ns_t_key
+#define	T_PX		ns_t_px
+#define	T_GPOS		ns_t_gpos
+#define	T_AAAA		ns_t_aaaa
+#define	T_LOC		ns_t_loc
+#define	T_NXT		ns_t_nxt
+#define	T_EID		ns_t_eid
+#define	T_NIMLOC	ns_t_nimloc
+#define	T_SRV		ns_t_srv
+#define T_ATMA		ns_t_atma
+#define T_NAPTR		ns_t_naptr
+#define T_A6		ns_t_a6
+#define	T_TSIG		ns_t_tsig
+#define	T_IXFR		ns_t_ixfr
+#define T_AXFR		ns_t_axfr
+#define T_MAILB		ns_t_mailb
+#define T_MAILA		ns_t_maila
+#define T_ANY		ns_t_any
+
+#define C_IN		ns_c_in
+#define C_CHAOS		ns_c_chaos
+#define C_HS		ns_c_hs
+/* BIND_UPDATE */
+#define C_NONE		ns_c_none
+#define C_ANY		ns_c_any
+
+#define	GETSHORT		NS_GET16
+#define	GETLONG			NS_GET32
+#define	PUTSHORT		NS_PUT16
+#define	PUTLONG			NS_PUT32
+
+#endif /* _ARPA_NAMESER_COMPAT_ */
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/eventlib.h
@@ -0,0 +1,214 @@
+/*	$NetBSD: eventlib.h,v 1.1.1.3 2005/12/21 23:15:22 christos Exp $	*/
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-1999 by Internet Software Consortium
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* eventlib.h - exported interfaces for eventlib
+ * vix 09sep95 [initial]
+ *
+ * Id: eventlib.h,v 1.1.2.1.4.2 2005/07/28 07:43:18 marka Exp
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#ifndef _EVENTLIB_H
+#define _EVENTLIB_H
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+#ifndef __P
+# define __EVENTLIB_P_DEFINED
+# ifdef __STDC__
+#  define __P(x) x
+# else
+#  define __P(x) ()
+# endif
+#endif
+
+/* In the absence of branded types... */
+typedef struct { void *opaque; } evConnID;
+typedef struct { void *opaque; } evFileID;
+typedef struct { void *opaque; } evStreamID;
+typedef struct { void *opaque; } evTimerID;
+typedef struct { void *opaque; } evWaitID;
+typedef struct { void *opaque; } evContext;
+typedef struct { void *opaque; } evEvent;
+
+#define	evInitID(id) ((id)->opaque = NULL)
+#define	evTestID(id) ((id).opaque != NULL)
+
+typedef void (*evConnFunc)__P((evContext, void *, int, const void *, int,
+			       const void *, int));
+typedef void (*evFileFunc)__P((evContext, void *, int, int));
+typedef	void (*evStreamFunc)__P((evContext, void *, int, int));
+typedef void (*evTimerFunc)__P((evContext, void *,
+				struct timespec, struct timespec));
+typedef	void (*evWaitFunc)__P((evContext, void *, const void *));
+
+typedef	struct { unsigned char mask[256/8]; } evByteMask;
+#define	EV_BYTEMASK_BYTE(b) ((b) / 8)
+#define	EV_BYTEMASK_MASK(b) (1 << ((b) % 8))
+#define	EV_BYTEMASK_SET(bm, b) \
+	((bm).mask[EV_BYTEMASK_BYTE(b)] |= EV_BYTEMASK_MASK(b))
+#define	EV_BYTEMASK_CLR(bm, b) \
+	((bm).mask[EV_BYTEMASK_BYTE(b)] &= ~EV_BYTEMASK_MASK(b))
+#define	EV_BYTEMASK_TST(bm, b) \
+	((bm).mask[EV_BYTEMASK_BYTE(b)] & EV_BYTEMASK_MASK(b))
+
+#define	EV_POLL		1
+#define	EV_WAIT		2
+#define	EV_NULL		4
+
+#define	EV_READ		1
+#define	EV_WRITE	2
+#define	EV_EXCEPT	4
+
+#define EV_WASNONBLOCKING 8	/* Internal library use. */
+
+/* eventlib.c */
+#define evCreate	__evCreate
+#define evSetDebug	__evSetDebug
+#define evDestroy	__evDestroy
+#define evGetNext	__evGetNext
+#define evDispatch	__evDispatch
+#define evDrop		__evDrop
+#define evMainLoop	__evMainLoop
+#define evHighestFD	__evHighestFD
+#define evGetOption	__evGetOption
+#define evSetOption	__evSetOption
+
+int  evCreate __P((evContext *));
+void evSetDebug __P((evContext, int, FILE *));
+int  evDestroy __P((evContext));
+int  evGetNext __P((evContext, evEvent *, int));
+int  evDispatch __P((evContext, evEvent));
+void evDrop __P((evContext, evEvent));
+int  evMainLoop __P((evContext));
+int  evHighestFD __P((evContext));
+int  evGetOption __P((evContext *, const char *, int *));
+int  evSetOption __P((evContext *, const char *, int));
+
+/* ev_connects.c */
+#define evListen	__evListen
+#define evConnect	__evConnect
+#define evCancelConn	__evCancelConn
+#define evHold		__evHold
+#define evUnhold	__evUnhold
+#define evTryAccept	__evTryAccept
+
+int evListen __P((evContext, int, int, evConnFunc, void *, evConnID *));
+int evConnect __P((evContext, int, const void *, int,
+		   evConnFunc, void *, evConnID *));
+int evCancelConn __P((evContext, evConnID));
+int evHold __P((evContext, evConnID));
+int evUnhold __P((evContext, evConnID));
+int evTryAccept __P((evContext, evConnID, int *));
+
+/* ev_files.c */
+#define evSelectFD	__evSelectFD
+#define evDeselectFD	__evDeselectFD
+
+int evSelectFD __P((evContext, int, int, evFileFunc, void *, evFileID *));
+int evDeselectFD __P((evContext, evFileID));
+
+/* ev_streams.c */
+#define evConsIovec	__evConsIovec
+#define evWrite		__evWrite
+#define evRead		__evRead
+#define evTimeRW	__evTimeRW
+#define evUntimeRW	__evUntimeRW
+#define	evCancelRW	__evCancelRW
+
+struct iovec evConsIovec __P((void *, size_t));
+int evWrite __P((evContext, int, const struct iovec *, int,
+		 evStreamFunc func, void *, evStreamID *));
+int evRead __P((evContext, int, const struct iovec *, int,
+		evStreamFunc func, void *, evStreamID *));
+int evTimeRW __P((evContext, evStreamID, evTimerID timer));
+int evUntimeRW __P((evContext, evStreamID));
+int evCancelRW __P((evContext, evStreamID));
+
+/* ev_timers.c */
+#define evConsTime	__evConsTime
+#define evAddTime	__evAddTime
+#define evSubTime	__evSubTime
+#define evCmpTime	__evCmpTime
+#define	evTimeSpec	__evTimeSpec
+#define	evTimeVal	__evTimeVal
+
+#define evNowTime		__evNowTime
+#define evUTCTime		__evUTCTime
+#define evLastEventTime		__evLastEventTime
+#define evSetTimer		__evSetTimer
+#define evClearTimer		__evClearTimer
+#define evConfigTimer		__evConfigTimer
+#define evResetTimer		__evResetTimer
+#define evSetIdleTimer		__evSetIdleTimer
+#define evClearIdleTimer	__evClearIdleTimer
+#define evResetIdleTimer	__evResetIdleTimer
+#define evTouchIdleTimer	__evTouchIdleTimer
+
+struct timespec evConsTime __P((time_t sec, long nsec));
+struct timespec evAddTime __P((struct timespec, struct timespec));
+struct timespec evSubTime __P((struct timespec, struct timespec));
+struct timespec evNowTime __P((void));
+struct timespec evUTCTime __P((void));
+struct timespec evLastEventTime __P((evContext));
+struct timespec evTimeSpec __P((struct timeval));
+struct timeval evTimeVal __P((struct timespec));
+int evCmpTime __P((struct timespec, struct timespec));
+int evSetTimer __P((evContext, evTimerFunc, void *, struct timespec,
+		    struct timespec, evTimerID *));
+int evClearTimer __P((evContext, evTimerID));
+int evConfigTimer __P((evContext, evTimerID, const char *param,
+		      int value));
+int evResetTimer __P((evContext, evTimerID, evTimerFunc, void *,
+		      struct timespec, struct timespec));
+int evSetIdleTimer __P((evContext, evTimerFunc, void *, struct timespec,
+			evTimerID *));
+int evClearIdleTimer __P((evContext, evTimerID));
+int evResetIdleTimer __P((evContext, evTimerID, evTimerFunc, void *,
+			  struct timespec));
+int evTouchIdleTimer __P((evContext, evTimerID));
+
+/* ev_waits.c */
+#define evWaitFor	__evWaitFor
+#define evDo		__evDo
+#define evUnwait	__evUnwait
+#define evDefer		__evDefer
+
+int evWaitFor __P((evContext, const void *, evWaitFunc, void *, evWaitID *));
+int evDo __P((evContext, const void *));
+int evUnwait __P((evContext, evWaitID));
+int evDefer __P((evContext, evWaitFunc, void *));
+
+#ifdef __EVENTLIB_P_DEFINED
+# undef __P
+#endif
+
+#endif /*_EVENTLIB_H*/
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/getaddrinfo.c
@@ -0,0 +1,2355 @@
+/*	$NetBSD: getaddrinfo.c,v 1.82 2006/03/25 12:09:40 rpaulo Exp $	*/
+/*	$KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This version of getaddrinfo.c is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+#define ANDROID_CHANGES 1
+
+/*
+ * Issues to be discussed:
+ * - Return values.  There are nonstandard return values defined and used
+ *   in the source code.  This is because RFC2553 is silent about which error
+ *   code must be returned for which situation.
+ * - IPv4 classful (shortened) form.  RFC2553 is silent about it.  XNET 5.2
+ *   says to use inet_aton() to convert IPv4 numeric to binary (alows
+ *   classful form as a result).
+ *   current code - disallow classful form for IPv4 (due to use of inet_pton).
+ * - freeaddrinfo(NULL).  RFC2553 is silent about it.  XNET 5.2 says it is
+ *   invalid.
+ *   current code - SEGV on freeaddrinfo(NULL)
+ * Note:
+ * - We use getipnodebyname() just for thread-safeness.  There's no intent
+ *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
+ *   getipnodebyname().
+ * - MOZILLA: Thread safeness for pre-Honeycomb Android versions implemented by
+ *   way of open/gets/close and mmap rather than fopen/fgets/fclose.  Affects
+ *   _files_getaddrinfo for hosts file.  Note: Honeycomb and later versions use
+ *   a thread-safe stdio, so for those versions normal Bionic libc getaddrinfo
+ *   is used.
+ * - The code filters out AFs that are not supported by the kernel,
+ *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
+ *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
+ *   in ai_flags?
+ * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
+ *   (1) what should we do against numeric hostname (2) what should we do
+ *   against NULL hostname (3) what is AI_ADDRCONFIG itself.  AF not ready?
+ *   non-loopback address configured?  global address configured?
+ * - To avoid search order issue, we have a big amount of code duplicate
+ *   from gethnamaddr.c and some other places.  The issues that there's no
+ *   lower layer function to lookup "IPv4 or IPv6" record.  Calling
+ *   gethostbyname2 from getaddrinfo will end up in wrong search order, as
+ *   follows:
+ *	- The code makes use of following calls when asked to resolver with
+ *	  ai_family  = PF_UNSPEC:
+ *		getipnodebyname(host, AF_INET6);
+ *		getipnodebyname(host, AF_INET);
+ *	  This will result in the following queries if the node is configure to
+ *	  prefer /etc/hosts than DNS:
+ *		lookup /etc/hosts for IPv6 address
+ *		lookup DNS for IPv6 address
+ *		lookup /etc/hosts for IPv4 address
+ *		lookup DNS for IPv4 address
+ *	  which may not meet people's requirement.
+ *	  The right thing to happen is to have underlying layer which does
+ *	  PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
+ *	  This would result in a bit of code duplicate with _dns_ghbyname() and
+ *	  friends.
+ */
+
+#include <fcntl.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/mman.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "arpa_nameser.h"
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include "resolv_private.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <syslog.h>
+#include <stdarg.h>
+#include "nsswitch.h"
+
+#ifdef MOZ_GETADDRINFO_LOG_VERBOSE
+#include <android/log.h>
+#endif
+
+#ifdef ANDROID_CHANGES
+#include <sys/system_properties.h>
+#endif /* ANDROID_CHANGES */
+
+typedef struct _pseudo_FILE {
+    int fd;
+    off_t maplen;
+    void* mapping;
+    off_t offset;
+} _pseudo_FILE;
+
+#define _PSEUDO_FILE_INITIALIZER { -1, 0, MAP_FAILED, 0 }
+
+static void
+_pseudo_fclose(_pseudo_FILE * __restrict__ fp)
+{
+    assert(fp);
+    fp->offset = 0;
+    if (fp->mapping != MAP_FAILED) {
+        (void) munmap(fp->mapping, fp->maplen);
+        fp->mapping = MAP_FAILED;
+    }
+    fp->maplen = 0;
+    if (fp->fd != -1) {
+        (void) close(fp->fd);
+        fp->fd = -1;
+    }
+}
+
+static _pseudo_FILE *
+_pseudo_fopen_r(_pseudo_FILE * __restrict__ fp, const char* fname)
+{
+    struct stat statbuf;
+    assert(fp);
+    fp->fd = open(fname, O_RDONLY);
+    if (fp->fd < 0) {
+        fp->fd = -1;
+        return NULL;
+    }
+    if ((0 != fstat(fp->fd, &statbuf)) || (statbuf.st_size <= 0)) {
+        close(fp->fd);
+        fp->fd = -1;
+        return NULL;
+    }
+    fp->maplen = statbuf.st_size;
+    fp->mapping = mmap(NULL, fp->maplen, PROT_READ, MAP_PRIVATE, fp->fd, 0);
+    if (fp->mapping == MAP_FAILED) {
+        close(fp->fd);
+        fp->fd = -1;
+        return NULL;
+    }
+    fp->offset = 0;
+    return fp;
+}
+
+static void
+_pseudo_rewind(_pseudo_FILE * __restrict__ fp)
+{
+    assert(fp);
+    fp->offset = 0;
+}
+
+static char*
+_pseudo_fgets(char* buf, int bufsize, _pseudo_FILE * __restrict__ fp)
+{
+    char* current;
+    char* endp;
+    int maxcopy;
+    assert(fp);
+    maxcopy = fp->maplen - fp->offset;
+    if (fp->mapping == MAP_FAILED)
+        return NULL;
+    if (maxcopy > bufsize - 1)
+        maxcopy = bufsize - 1;
+    if (maxcopy <= 0)
+        return NULL;
+    current = ((char*) fp->mapping) + fp->offset;
+    endp = memccpy(buf, current, '\n', maxcopy);
+    if (endp)
+        maxcopy = endp - buf;
+    buf[maxcopy] = '\0';
+    fp->offset += maxcopy;
+    return buf;
+}
+
+typedef union sockaddr_union {
+    struct sockaddr     generic;
+    struct sockaddr_in  in;
+    struct sockaddr_in6 in6;
+} sockaddr_union;
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO  0
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in_loopback[] = { 127, 0, 0, 1 };
+#ifdef INET6
+static const char in6_addrany[] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in6_loopback[] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+#endif
+
+static const struct afd {
+	int a_af;
+	int a_addrlen;
+	int a_socklen;
+	int a_off;
+	const char *a_addrany;
+	const char *a_loopback;
+	int a_scoped;
+} afdl [] = {
+#ifdef INET6
+	{PF_INET6, sizeof(struct in6_addr),
+	 sizeof(struct sockaddr_in6),
+	 offsetof(struct sockaddr_in6, sin6_addr),
+	 in6_addrany, in6_loopback, 1},
+#endif
+	{PF_INET, sizeof(struct in_addr),
+	 sizeof(struct sockaddr_in),
+	 offsetof(struct sockaddr_in, sin_addr),
+	 in_addrany, in_loopback, 0},
+	{0, 0, 0, 0, NULL, NULL, 0},
+};
+
+struct explore {
+	int e_af;
+	int e_socktype;
+	int e_protocol;
+	const char *e_protostr;
+	int e_wild;
+#define WILD_AF(ex)		((ex)->e_wild & 0x01)
+#define WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
+#define WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
+};
+
+static const struct explore explore[] = {
+#if 0
+	{ PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
+#endif
+#ifdef INET6
+	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
+#endif
+	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
+	{ PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+	{ PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+	{ PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
+	{ -1, 0, 0, NULL, 0 },
+};
+
+#ifdef INET6
+#define PTON_MAX	16
+#else
+#define PTON_MAX	4
+#endif
+
+static const ns_src default_dns_files[] = {
+	{ NSSRC_FILES, 	NS_SUCCESS },
+	{ NSSRC_DNS, 	NS_SUCCESS },
+	{ 0, 0 }
+};
+
+#define MAXPACKET	(64*1024)
+
+typedef union {
+	HEADER hdr;
+	u_char buf[MAXPACKET];
+} querybuf;
+
+struct res_target {
+	struct res_target *next;
+	const char *name;	/* domain name */
+	int qclass, qtype;	/* class and type of query */
+	u_char *answer;		/* buffer to put answer */
+	int anslen;		/* size of answer buffer */
+	int n;			/* result length */
+};
+
+static int str2number(const char *);
+static int explore_fqdn(const struct addrinfo *, const char *,
+	const char *, struct addrinfo **);
+static int explore_null(const struct addrinfo *,
+	const char *, struct addrinfo **);
+static int explore_numeric(const struct addrinfo *, const char *,
+	const char *, struct addrinfo **, const char *);
+static int explore_numeric_scope(const struct addrinfo *, const char *,
+	const char *, struct addrinfo **);
+static int get_canonname(const struct addrinfo *,
+	struct addrinfo *, const char *);
+static struct addrinfo *get_ai(const struct addrinfo *,
+	const struct afd *, const char *);
+static int get_portmatch(const struct addrinfo *, const char *);
+static int get_port(const struct addrinfo *, const char *, int);
+static const struct afd *find_afd(int);
+#ifdef INET6
+static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
+#endif
+
+static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
+	const struct addrinfo *);
+static int _dns_getaddrinfo(void *, void *, va_list);
+static void _sethtent(_pseudo_FILE * __restrict__);
+static void _endhtent(_pseudo_FILE * __restrict__);
+static struct addrinfo *_gethtent(_pseudo_FILE * __restrict__, const char *,
+    const struct addrinfo *);
+static int _files_getaddrinfo(void *, void *, va_list);
+
+static int res_queryN(const char *, struct res_target *, res_state);
+static int res_searchN(const char *, struct res_target *, res_state);
+static int res_querydomainN(const char *, const char *,
+	struct res_target *, res_state);
+
+static const char * const ai_errlist[] = {
+	"Success",
+	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */
+	"Temporary failure in name resolution",		/* EAI_AGAIN      */
+	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */
+	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */
+	"ai_family not supported",			/* EAI_FAMILY     */
+	"Memory allocation failure", 			/* EAI_MEMORY     */
+	"No address associated with hostname", 		/* EAI_NODATA     */
+	"hostname nor servname provided, or not known",	/* EAI_NONAME     */
+	"servname not supported for ai_socktype",	/* EAI_SERVICE    */
+	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */
+	"System error returned in errno", 		/* EAI_SYSTEM     */
+	"Invalid value for hints",			/* EAI_BADHINTS	  */
+	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */
+	"Argument buffer overflow",			/* EAI_OVERFLOW   */
+	"Unknown error", 				/* EAI_MAX        */
+};
+
+/* XXX macros that make external reference is BAD. */
+
+#define GET_AI(ai, afd, addr) 					\
+do { 								\
+	/* external reference: pai, error, and label free */ 	\
+	(ai) = get_ai(pai, (afd), (addr)); 			\
+	if ((ai) == NULL) { 					\
+		error = EAI_MEMORY; 				\
+		goto free; 					\
+	} 							\
+} while (/*CONSTCOND*/0)
+
+#define GET_PORT(ai, serv) 					\
+do { 								\
+	/* external reference: error and label free */ 		\
+	error = get_port((ai), (serv), 0); 			\
+	if (error != 0) 					\
+		goto free; 					\
+} while (/*CONSTCOND*/0)
+
+#define GET_CANONNAME(ai, str) 					\
+do { 								\
+	/* external reference: pai, error and label free */ 	\
+	error = get_canonname(pai, (ai), (str)); 		\
+	if (error != 0) 					\
+		goto free; 					\
+} while (/*CONSTCOND*/0)
+
+#define ERR(err) 						\
+do { 								\
+	/* external reference: error, and label bad */ 		\
+	error = (err); 						\
+	goto bad; 						\
+	/*NOTREACHED*/ 						\
+} while (/*CONSTCOND*/0)
+
+#define MATCH_FAMILY(x, y, w) 						\
+	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || 	\
+	    (y) == PF_UNSPEC)))
+#define MATCH(x, y, w) 							\
+	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
+
+#pragma GCC visibility push(default)
+
+extern const char *
+__wrap_gai_strerror(int ecode);
+extern void
+__wrap_freeaddrinfo(struct addrinfo *ai);
+extern int
+__wrap_getaddrinfo(const char *hostname, const char *servname,
+    const struct addrinfo *hints, struct addrinfo **res);
+
+int android_sdk_version;
+
+#pragma GCC visibility pop
+
+int android_sdk_version = -1;
+
+static int honeycomb_or_later()
+{
+#ifdef MOZ_GETADDRINFO_LOG_VERBOSE
+	__android_log_print(ANDROID_LOG_INFO, "getaddrinfo",
+		"I am%s Honeycomb\n",
+		(android_sdk_version >= 11) ? "" : " not");
+#endif
+	return android_sdk_version >= 11;
+}
+
+const char *
+__wrap_gai_strerror(int ecode)
+{
+	if (honeycomb_or_later())
+		return gai_strerror(ecode);
+	if (ecode < 0 || ecode > EAI_MAX)
+		ecode = EAI_MAX;
+	return ai_errlist[ecode];
+}
+
+void
+__wrap_freeaddrinfo(struct addrinfo *ai)
+{
+	struct addrinfo *next;
+
+	if (honeycomb_or_later()) {
+		freeaddrinfo(ai);
+		return;
+	}
+
+	assert(ai != NULL);
+
+	do {
+		next = ai->ai_next;
+		if (ai->ai_canonname)
+			free(ai->ai_canonname);
+		/* no need to free(ai->ai_addr) */
+		free(ai);
+		ai = next;
+	} while (ai);
+}
+
+static int
+str2number(const char *p)
+{
+	char *ep;
+	unsigned long v;
+
+	assert(p != NULL);
+
+	if (*p == '\0')
+		return -1;
+	ep = NULL;
+	errno = 0;
+	v = strtoul(p, &ep, 10);
+	if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX)
+		return v;
+	else
+		return -1;
+}
+
+/*
+ * Connect a UDP socket to a given unicast address. This will cause no network
+ * traffic, but will fail fast if the system has no or limited reachability to
+ * the destination (e.g., no IPv4 address, no IPv6 default route, ...).
+ */
+static int
+_test_connect(int pf, struct sockaddr *addr, size_t addrlen) {
+	int s = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+	if (s < 0)
+		return 0;
+	int ret;
+	do {
+		ret = connect(s, addr, addrlen);
+	} while (ret < 0 && errno == EINTR);
+	int success = (ret == 0);
+	do {
+		ret = close(s);
+	} while (ret < 0 && errno == EINTR);
+	return success;
+}
+
+/*
+ * The following functions determine whether IPv4 or IPv6 connectivity is
+ * available in order to implement AI_ADDRCONFIG.
+ *
+ * Strictly speaking, AI_ADDRCONFIG should not look at whether connectivity is
+ * available, but whether addresses of the specified family are "configured
+ * on the local system". However, bionic doesn't currently support getifaddrs,
+ * so checking for connectivity is the next best thing.
+ */
+static int
+_have_ipv6() {
+	static const struct sockaddr_in6 sin6_test = {
+		.sin6_family = AF_INET6,
+		.sin6_addr.s6_addr = {  // 2000::
+			0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+		};
+        sockaddr_union addr = { .in6 = sin6_test };
+	return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6));
+}
+
+static int
+_have_ipv4() {
+	static const struct sockaddr_in sin_test = {
+		.sin_family = AF_INET,
+		.sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
+	};
+        sockaddr_union addr = { .in = sin_test };
+        return _test_connect(PF_INET, &addr.generic, sizeof(addr.in));
+}
+
+int
+__wrap_getaddrinfo(const char *hostname, const char *servname,
+    const struct addrinfo *hints, struct addrinfo **res)
+{
+	struct addrinfo sentinel;
+	struct addrinfo *cur;
+	int error = 0;
+	struct addrinfo ai;
+	struct addrinfo ai0;
+	struct addrinfo *pai;
+	const struct explore *ex;
+
+	if (honeycomb_or_later())
+		return getaddrinfo(hostname, servname, hints, res);
+
+	/* hostname is allowed to be NULL */
+	/* servname is allowed to be NULL */
+	/* hints is allowed to be NULL */
+	assert(res != NULL);
+
+	memset(&sentinel, 0, sizeof(sentinel));
+	cur = &sentinel;
+	pai = &ai;
+	pai->ai_flags = 0;
+	pai->ai_family = PF_UNSPEC;
+	pai->ai_socktype = ANY;
+	pai->ai_protocol = ANY;
+	pai->ai_addrlen = 0;
+	pai->ai_canonname = NULL;
+	pai->ai_addr = NULL;
+	pai->ai_next = NULL;
+
+	if (hostname == NULL && servname == NULL)
+		return EAI_NONAME;
+	if (hints) {
+		/* error check for hints */
+		if (hints->ai_addrlen || hints->ai_canonname ||
+		    hints->ai_addr || hints->ai_next)
+			ERR(EAI_BADHINTS); /* xxx */
+		if (hints->ai_flags & ~AI_MASK)
+			ERR(EAI_BADFLAGS);
+		switch (hints->ai_family) {
+		case PF_UNSPEC:
+		case PF_INET:
+#ifdef INET6
+		case PF_INET6:
+#endif
+			break;
+		default:
+			ERR(EAI_FAMILY);
+		}
+		memcpy(pai, hints, sizeof(*pai));
+
+		/*
+		 * if both socktype/protocol are specified, check if they
+		 * are meaningful combination.
+		 */
+		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
+			for (ex = explore; ex->e_af >= 0; ex++) {
+				if (pai->ai_family != ex->e_af)
+					continue;
+				if (ex->e_socktype == ANY)
+					continue;
+				if (ex->e_protocol == ANY)
+					continue;
+				if (pai->ai_socktype == ex->e_socktype
+				 && pai->ai_protocol != ex->e_protocol) {
+					ERR(EAI_BADHINTS);
+				}
+			}
+		}
+	}
+
+	/*
+	 * check for special cases.  (1) numeric servname is disallowed if
+	 * socktype/protocol are left unspecified. (2) servname is disallowed
+	 * for raw and other inet{,6} sockets.
+	 */
+	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
+#ifdef PF_INET6
+	 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
+#endif
+	    ) {
+		ai0 = *pai;	/* backup *pai */
+
+		if (pai->ai_family == PF_UNSPEC) {
+#ifdef PF_INET6
+			pai->ai_family = PF_INET6;
+#else
+			pai->ai_family = PF_INET;
+#endif
+		}
+		error = get_portmatch(pai, servname);
+		if (error)
+			ERR(error);
+
+		*pai = ai0;
+	}
+
+	ai0 = *pai;
+
+	/* NULL hostname, or numeric hostname */
+	for (ex = explore; ex->e_af >= 0; ex++) {
+		*pai = ai0;
+
+		/* PF_UNSPEC entries are prepared for DNS queries only */
+		if (ex->e_af == PF_UNSPEC)
+			continue;
+
+		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
+			continue;
+		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
+			continue;
+		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
+			continue;
+
+		if (pai->ai_family == PF_UNSPEC)
+			pai->ai_family = ex->e_af;
+		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+			pai->ai_socktype = ex->e_socktype;
+		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+			pai->ai_protocol = ex->e_protocol;
+
+		if (hostname == NULL)
+			error = explore_null(pai, servname, &cur->ai_next);
+		else
+			error = explore_numeric_scope(pai, hostname, servname,
+			    &cur->ai_next);
+
+		if (error)
+			goto free;
+
+		while (cur->ai_next)
+			cur = cur->ai_next;
+	}
+
+	/*
+	 * XXX
+	 * If numeric representation of AF1 can be interpreted as FQDN
+	 * representation of AF2, we need to think again about the code below.
+	 */
+	if (sentinel.ai_next)
+		goto good;
+
+	if (hostname == NULL)
+		ERR(EAI_NODATA);
+	if (pai->ai_flags & AI_NUMERICHOST)
+		ERR(EAI_NONAME);
+
+	/*
+	 * hostname as alphabetical name.
+	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
+	 * outer loop by AFs.
+	 */
+	for (ex = explore; ex->e_af >= 0; ex++) {
+		*pai = ai0;
+
+		/* require exact match for family field */
+		if (pai->ai_family != ex->e_af)
+			continue;
+
+		if (!MATCH(pai->ai_socktype, ex->e_socktype,
+				WILD_SOCKTYPE(ex))) {
+			continue;
+		}
+		if (!MATCH(pai->ai_protocol, ex->e_protocol,
+				WILD_PROTOCOL(ex))) {
+			continue;
+		}
+
+		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+			pai->ai_socktype = ex->e_socktype;
+		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+			pai->ai_protocol = ex->e_protocol;
+
+		error = explore_fqdn(pai, hostname, servname,
+			&cur->ai_next);
+
+		while (cur && cur->ai_next)
+			cur = cur->ai_next;
+	}
+
+	/* XXX */
+	if (sentinel.ai_next)
+		error = 0;
+
+	if (error)
+		goto free;
+	if (error == 0) {
+		if (sentinel.ai_next) {
+ good:
+			*res = sentinel.ai_next;
+			return SUCCESS;
+		} else
+			error = EAI_FAIL;
+	}
+ free:
+ bad:
+	if (sentinel.ai_next)
+		__wrap_freeaddrinfo(sentinel.ai_next);
+	*res = NULL;
+	return error;
+}
+
+/*
+ * FQDN hostname, DNS lookup
+ */
+static int
+explore_fqdn(const struct addrinfo *pai, const char *hostname,
+    const char *servname, struct addrinfo **res)
+{
+	struct addrinfo *result;
+	struct addrinfo *cur;
+	int error = 0;
+	static const ns_dtab dtab[] = {
+		NS_FILES_CB(_files_getaddrinfo, NULL)
+		{ NSSRC_DNS, _dns_getaddrinfo, NULL },	/* force -DHESIOD */
+		NS_NIS_CB(_yp_getaddrinfo, NULL)
+		{ 0, 0, 0 }
+	};
+
+	assert(pai != NULL);
+	/* hostname may be NULL */
+	/* servname may be NULL */
+	assert(res != NULL);
+
+	result = NULL;
+
+	/*
+	 * if the servname does not match socktype/protocol, ignore it.
+	 */
+	if (get_portmatch(pai, servname) != 0)
+		return 0;
+
+	switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
+			default_dns_files, hostname, pai)) {
+	case NS_TRYAGAIN:
+		error = EAI_AGAIN;
+		goto free;
+	case NS_UNAVAIL:
+		error = EAI_FAIL;
+		goto free;
+	case NS_NOTFOUND:
+		error = EAI_NODATA;
+		goto free;
+	case NS_SUCCESS:
+		error = 0;
+		for (cur = result; cur; cur = cur->ai_next) {
+			GET_PORT(cur, servname);
+			/* canonname should be filled already */
+		}
+		break;
+	}
+
+	*res = result;
+
+	return 0;
+
+free:
+	if (result)
+		__wrap_freeaddrinfo(result);
+	return error;
+}
+
+/*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+static int
+explore_null(const struct addrinfo *pai, const char *servname,
+    struct addrinfo **res)
+{
+	int s;
+	const struct afd *afd;
+	struct addrinfo *cur;
+	struct addrinfo sentinel;
+	int error;
+
+	assert(pai != NULL);
+	/* servname may be NULL */
+	assert(res != NULL);
+
+	*res = NULL;
+	sentinel.ai_next = NULL;
+	cur = &sentinel;
+
+	/*
+	 * filter out AFs that are not supported by the kernel
+	 * XXX errno?
+	 */
+	s = socket(pai->ai_family, SOCK_DGRAM, 0);
+	if (s < 0) {
+		if (errno != EMFILE)
+			return 0;
+	} else
+		close(s);
+
+	/*
+	 * if the servname does not match socktype/protocol, ignore it.
+	 */
+	if (get_portmatch(pai, servname) != 0)
+		return 0;
+
+	afd = find_afd(pai->ai_family);
+	if (afd == NULL)
+		return 0;
+
+	if (pai->ai_flags & AI_PASSIVE) {
+		GET_AI(cur->ai_next, afd, afd->a_addrany);
+		/* xxx meaningless?
+		 * GET_CANONNAME(cur->ai_next, "anyaddr");
+		 */
+		GET_PORT(cur->ai_next, servname);
+	} else {
+		GET_AI(cur->ai_next, afd, afd->a_loopback);
+		/* xxx meaningless?
+		 * GET_CANONNAME(cur->ai_next, "localhost");
+		 */
+		GET_PORT(cur->ai_next, servname);
+	}
+	cur = cur->ai_next;
+
+	*res = sentinel.ai_next;
+	return 0;
+
+free:
+	if (sentinel.ai_next)
+		__wrap_freeaddrinfo(sentinel.ai_next);
+	return error;
+}
+
+/*
+ * numeric hostname
+ */
+static int
+explore_numeric(const struct addrinfo *pai, const char *hostname,
+    const char *servname, struct addrinfo **res, const char *canonname)
+{
+	const struct afd *afd;
+	struct addrinfo *cur;
+	struct addrinfo sentinel;
+	int error;
+	char pton[PTON_MAX];
+
+	assert(pai != NULL);
+	/* hostname may be NULL */
+	/* servname may be NULL */
+	assert(res != NULL);
+
+	*res = NULL;
+	sentinel.ai_next = NULL;
+	cur = &sentinel;
+
+	/*
+	 * if the servname does not match socktype/protocol, ignore it.
+	 */
+	if (get_portmatch(pai, servname) != 0)
+		return 0;
+
+	afd = find_afd(pai->ai_family);
+	if (afd == NULL)
+		return 0;
+
+	switch (afd->a_af) {
+#if 0 /*X/Open spec*/
+	case AF_INET:
+		if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
+			if (pai->ai_family == afd->a_af ||
+			    pai->ai_family == PF_UNSPEC /*?*/) {
+				GET_AI(cur->ai_next, afd, pton);
+				GET_PORT(cur->ai_next, servname);
+				if ((pai->ai_flags & AI_CANONNAME)) {
+					/*
+					 * Set the numeric address itself as
+					 * the canonical name, based on a
+					 * clarification in rfc2553bis-03.
+					 */
+					GET_CANONNAME(cur->ai_next, canonname);
+				}
+				while (cur && cur->ai_next)
+					cur = cur->ai_next;
+			} else
+				ERR(EAI_FAMILY);	/*xxx*/
+		}
+		break;
+#endif
+	default:
+		if (inet_pton(afd->a_af, hostname, pton) == 1) {
+			if (pai->ai_family == afd->a_af ||
+			    pai->ai_family == PF_UNSPEC /*?*/) {
+				GET_AI(cur->ai_next, afd, pton);
+				GET_PORT(cur->ai_next, servname);
+				if ((pai->ai_flags & AI_CANONNAME)) {
+					/*
+					 * Set the numeric address itself as
+					 * the canonical name, based on a
+					 * clarification in rfc2553bis-03.
+					 */
+					GET_CANONNAME(cur->ai_next, canonname);
+				}
+				while (cur->ai_next)
+					cur = cur->ai_next;
+			} else
+				ERR(EAI_FAMILY);	/*xxx*/
+		}
+		break;
+	}
+
+	*res = sentinel.ai_next;
+	return 0;
+
+free:
+bad:
+	if (sentinel.ai_next)
+		__wrap_freeaddrinfo(sentinel.ai_next);
+	return error;
+}
+
+/*
+ * numeric hostname with scope
+ */
+static int
+explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
+    const char *servname, struct addrinfo **res)
+{
+#if !defined(SCOPE_DELIMITER) || !defined(INET6)
+	return explore_numeric(pai, hostname, servname, res, hostname);
+#else
+	const struct afd *afd;
+	struct addrinfo *cur;
+	int error;
+	char *cp, *hostname2 = NULL, *scope, *addr;
+	struct sockaddr_in6 *sin6;
+
+	assert(pai != NULL);
+	/* hostname may be NULL */
+	/* servname may be NULL */
+	assert(res != NULL);
+
+	/*
+	 * if the servname does not match socktype/protocol, ignore it.
+	 */
+	if (get_portmatch(pai, servname) != 0)
+		return 0;
+
+	afd = find_afd(pai->ai_family);
+	if (afd == NULL)
+		return 0;
+
+	if (!afd->a_scoped)
+		return explore_numeric(pai, hostname, servname, res, hostname);
+
+	cp = strchr(hostname, SCOPE_DELIMITER);
+	if (cp == NULL)
+		return explore_numeric(pai, hostname, servname, res, hostname);
+
+	/*
+	 * Handle special case of <scoped_address><delimiter><scope id>
+	 */
+	hostname2 = strdup(hostname);
+	if (hostname2 == NULL)
+		return EAI_MEMORY;
+	/* terminate at the delimiter */
+	hostname2[cp - hostname] = '\0';
+	addr = hostname2;
+	scope = cp + 1;
+
+	error = explore_numeric(pai, addr, servname, res, hostname);
+	if (error == 0) {
+		u_int32_t scopeid;
+
+		for (cur = *res; cur; cur = cur->ai_next) {
+			if (cur->ai_family != AF_INET6)
+				continue;
+			sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
+			if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
+				free(hostname2);
+				return(EAI_NODATA); /* XXX: is return OK? */
+			}
+			sin6->sin6_scope_id = scopeid;
+		}
+	}
+
+	free(hostname2);
+
+	return error;
+#endif
+}
+
+static int
+get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
+{
+
+	assert(pai != NULL);
+	assert(ai != NULL);
+	assert(str != NULL);
+
+	if ((pai->ai_flags & AI_CANONNAME) != 0) {
+		ai->ai_canonname = strdup(str);
+		if (ai->ai_canonname == NULL)
+			return EAI_MEMORY;
+	}
+	return 0;
+}
+
+static struct addrinfo *
+get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
+{
+	char *p;
+	struct addrinfo *ai;
+
+	assert(pai != NULL);
+	assert(afd != NULL);
+	assert(addr != NULL);
+
+	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
+		+ (afd->a_socklen));
+	if (ai == NULL)
+		return NULL;
+
+	memcpy(ai, pai, sizeof(struct addrinfo));
+	ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+	memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
+
+#ifdef HAVE_SA_LEN
+	ai->ai_addr->sa_len = afd->a_socklen;
+#endif
+
+	ai->ai_addrlen = afd->a_socklen;
+#if defined (__alpha__) || (defined(__i386__) && defined(_LP64)) || defined(__sparc64__)
+	ai->__ai_pad0 = 0;
+#endif
+	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
+	p = (char *)(void *)(ai->ai_addr);
+	memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
+	return ai;
+}
+
+static int
+get_portmatch(const struct addrinfo *ai, const char *servname)
+{
+
+	assert(ai != NULL);
+	/* servname may be NULL */
+
+	return get_port(ai, servname, 1);
+}
+
+static int
+get_port(const struct addrinfo *ai, const char *servname, int matchonly)
+{
+	const char *proto;
+	struct servent *sp;
+	int port;
+	int allownumeric;
+
+	assert(ai != NULL);
+	/* servname may be NULL */
+
+	if (servname == NULL)
+		return 0;
+	switch (ai->ai_family) {
+	case AF_INET:
+#ifdef AF_INET6
+	case AF_INET6:
+#endif
+		break;
+	default:
+		return 0;
+	}
+
+	switch (ai->ai_socktype) {
+	case SOCK_RAW:
+		return EAI_SERVICE;
+	case SOCK_DGRAM:
+	case SOCK_STREAM:
+		allownumeric = 1;
+		break;
+	case ANY:
+#if 1  /* ANDROID-SPECIFIC CHANGE TO MATCH GLIBC */
+		allownumeric = 1;
+#else
+		allownumeric = 0;
+#endif
+		break;
+	default:
+		return EAI_SOCKTYPE;
+	}
+
+	port = str2number(servname);
+	if (port >= 0) {
+		if (!allownumeric)
+			return EAI_SERVICE;
+		if (port < 0 || port > 65535)
+			return EAI_SERVICE;
+		port = htons(port);
+	} else {
+		if (ai->ai_flags & AI_NUMERICSERV)
+			return EAI_NONAME;
+
+		switch (ai->ai_socktype) {
+		case SOCK_DGRAM:
+			proto = "udp";
+			break;
+		case SOCK_STREAM:
+			proto = "tcp";
+			break;
+		default:
+			proto = NULL;
+			break;
+		}
+
+		if ((sp = getservbyname(servname, proto)) == NULL)
+			return EAI_SERVICE;
+		port = sp->s_port;
+	}
+
+	if (!matchonly) {
+		switch (ai->ai_family) {
+		case AF_INET:
+			((struct sockaddr_in *)(void *)
+			    ai->ai_addr)->sin_port = port;
+			break;
+#ifdef INET6
+		case AF_INET6:
+			((struct sockaddr_in6 *)(void *)
+			    ai->ai_addr)->sin6_port = port;
+			break;
+#endif
+		}
+	}
+
+	return 0;
+}
+
+static const struct afd *
+find_afd(int af)
+{
+	const struct afd *afd;
+
+	if (af == PF_UNSPEC)
+		return NULL;
+	for (afd = afdl; afd->a_af; afd++) {
+		if (afd->a_af == af)
+			return afd;
+	}
+	return NULL;
+}
+
+#ifdef INET6
+/* convert a string to a scope identifier. XXX: IPv6 specific */
+static int
+ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
+{
+	u_long lscopeid;
+	struct in6_addr *a6;
+	char *ep;
+
+	assert(scope != NULL);
+	assert(sin6 != NULL);
+	assert(scopeid != NULL);
+
+	a6 = &sin6->sin6_addr;
+
+	/* empty scopeid portion is invalid */
+	if (*scope == '\0')
+		return -1;
+
+	if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
+		/*
+		 * We currently assume a one-to-one mapping between links
+		 * and interfaces, so we simply use interface indices for
+		 * like-local scopes.
+		 */
+		*scopeid = if_nametoindex(scope);
+		if (*scopeid == 0)
+			goto trynumeric;
+		return 0;
+	}
+
+	/* still unclear about literal, allow numeric only - placeholder */
+	if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
+		goto trynumeric;
+	if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
+		goto trynumeric;
+	else
+		goto trynumeric;	/* global */
+
+	/* try to convert to a numeric id as a last resort */
+  trynumeric:
+	errno = 0;
+	lscopeid = strtoul(scope, &ep, 10);
+	*scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
+	if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
+		return 0;
+	else
+		return -1;
+}
+#endif
+
+/* code duplicate with gethnamaddr.c */
+
+static const char AskedForGot[] =
+	"gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+
+static struct addrinfo *
+getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
+    const struct addrinfo *pai)
+{
+	struct addrinfo sentinel, *cur;
+	struct addrinfo ai;
+	const struct afd *afd;
+	char *canonname;
+	const HEADER *hp;
+	const u_char *cp;
+	int n;
+	const u_char *eom;
+	char *bp, *ep;
+	int type, class, ancount, qdcount;
+	int haveanswer, had_error;
+	char tbuf[MAXDNAME];
+	int (*name_ok) (const char *);
+	char hostbuf[8*1024];
+
+	assert(answer != NULL);
+	assert(qname != NULL);
+	assert(pai != NULL);
+
+	memset(&sentinel, 0, sizeof(sentinel));
+	cur = &sentinel;
+
+	canonname = NULL;
+	eom = answer->buf + anslen;
+	switch (qtype) {
+	case T_A:
+	case T_AAAA:
+	case T_ANY:	/*use T_ANY only for T_A/T_AAAA lookup*/
+		name_ok = res_hnok;
+		break;
+	default:
+		return NULL;	/* XXX should be abort(); */
+	}
+	/*
+	 * find first satisfactory answer
+	 */
+	hp = &answer->hdr;
+	ancount = ntohs(hp->ancount);
+	qdcount = ntohs(hp->qdcount);
+	bp = hostbuf;
+	ep = hostbuf + sizeof hostbuf;
+	cp = answer->buf + HFIXEDSZ;
+	if (qdcount != 1) {
+		h_errno = NO_RECOVERY;
+		return (NULL);
+	}
+	n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+	if ((n < 0) || !(*name_ok)(bp)) {
+		h_errno = NO_RECOVERY;
+		return (NULL);
+	}
+	cp += n + QFIXEDSZ;
+	if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
+		/* res_send() has already verified that the query name is the
+		 * same as the one we sent; this just gets the expanded name
+		 * (i.e., with the succeeding search-domain tacked on).
+		 */
+		n = strlen(bp) + 1;		/* for the \0 */
+		if (n >= MAXHOSTNAMELEN) {
+			h_errno = NO_RECOVERY;
+			return (NULL);
+		}
+		canonname = bp;
+		bp += n;
+		/* The qname can be abbreviated, but h_name is now absolute. */
+		qname = canonname;
+	}
+	haveanswer = 0;
+	had_error = 0;
+	while (ancount-- > 0 && cp < eom && !had_error) {
+		n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+		if ((n < 0) || !(*name_ok)(bp)) {
+			had_error++;
+			continue;
+		}
+		cp += n;			/* name */
+		type = _getshort(cp);
+ 		cp += INT16SZ;			/* type */
+		class = _getshort(cp);
+ 		cp += INT16SZ + INT32SZ;	/* class, TTL */
+		n = _getshort(cp);
+		cp += INT16SZ;			/* len */
+		if (class != C_IN) {
+			/* XXX - debug? syslog? */
+			cp += n;
+			continue;		/* XXX - had_error++ ? */
+		}
+		if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
+		    type == T_CNAME) {
+			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+			if ((n < 0) || !(*name_ok)(tbuf)) {
+				had_error++;
+				continue;
+			}
+			cp += n;
+			/* Get canonical name. */
+			n = strlen(tbuf) + 1;	/* for the \0 */
+			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
+				had_error++;
+				continue;
+			}
+			strlcpy(bp, tbuf, (size_t)(ep - bp));
+			canonname = bp;
+			bp += n;
+			continue;
+		}
+		if (qtype == T_ANY) {
+			if (!(type == T_A || type == T_AAAA)) {
+				cp += n;
+				continue;
+			}
+		} else if (type != qtype) {
+			if (type != T_KEY && type != T_SIG)
+				syslog(LOG_NOTICE|LOG_AUTH,
+	       "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
+				       qname, p_class(C_IN), p_type(qtype),
+				       p_type(type));
+			cp += n;
+			continue;		/* XXX - had_error++ ? */
+		}
+		switch (type) {
+		case T_A:
+		case T_AAAA:
+			if (strcasecmp(canonname, bp) != 0) {
+				syslog(LOG_NOTICE|LOG_AUTH,
+				       AskedForGot, canonname, bp);
+				cp += n;
+				continue;	/* XXX - had_error++ ? */
+			}
+			if (type == T_A && n != INADDRSZ) {
+				cp += n;
+				continue;
+			}
+			if (type == T_AAAA && n != IN6ADDRSZ) {
+				cp += n;
+				continue;
+			}
+			if (type == T_AAAA) {
+				struct in6_addr in6;
+				memcpy(&in6, cp, IN6ADDRSZ);
+				if (IN6_IS_ADDR_V4MAPPED(&in6)) {
+					cp += n;
+					continue;
+				}
+			}
+			if (!haveanswer) {
+				int nn;
+
+				canonname = bp;
+				nn = strlen(bp) + 1;	/* for the \0 */
+				bp += nn;
+			}
+
+			/* don't overwrite pai */
+			ai = *pai;
+			ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
+			afd = find_afd(ai.ai_family);
+			if (afd == NULL) {
+				cp += n;
+				continue;
+			}
+			cur->ai_next = get_ai(&ai, afd, (const char *)cp);
+			if (cur->ai_next == NULL)
+				had_error++;
+			while (cur && cur->ai_next)
+				cur = cur->ai_next;
+			cp += n;
+			break;
+		default:
+			abort();
+		}
+		if (!had_error)
+			haveanswer++;
+	}
+	if (haveanswer) {
+		if (!canonname)
+			(void)get_canonname(pai, sentinel.ai_next, qname);
+		else
+			(void)get_canonname(pai, sentinel.ai_next, canonname);
+		h_errno = NETDB_SUCCESS;
+		return sentinel.ai_next;
+	}
+
+	h_errno = NO_RECOVERY;
+	return NULL;
+}
+
+struct addrinfo_sort_elem {
+	struct addrinfo *ai;
+	int has_src_addr;
+	sockaddr_union src_addr;
+	int original_order;
+};
+
+/*ARGSUSED*/
+static int
+_get_scope(const struct sockaddr *addr)
+{
+	if (addr->sa_family == AF_INET6) {
+		const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
+		if (IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) {
+			return IPV6_ADDR_MC_SCOPE(&addr6->sin6_addr);
+		} else if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) ||
+			   IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) {
+			/*
+			 * RFC 4291 section 2.5.3 says loopback is to be treated as having
+			 * link-local scope.
+			 */
+			return IPV6_ADDR_SCOPE_LINKLOCAL;
+		} else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) {
+			return IPV6_ADDR_SCOPE_SITELOCAL;
+		} else {
+			return IPV6_ADDR_SCOPE_GLOBAL;
+		}
+	} else if (addr->sa_family == AF_INET) {
+		const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
+		unsigned long int na = ntohl(addr4->sin_addr.s_addr);
+
+		if (IN_LOOPBACK(na) ||                          /* 127.0.0.0/8 */
+		    (na & 0xffff0000) == 0xa9fe0000) {          /* 169.254.0.0/16 */
+			return IPV6_ADDR_SCOPE_LINKLOCAL;
+		} else {
+			/*
+			 * According to draft-ietf-6man-rfc3484-revise-01 section 2.3,
+			 * it is best not to treat the private IPv4 ranges
+			 * (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) as being
+			 * in a special scope, so we don't.
+			 */
+			return IPV6_ADDR_SCOPE_GLOBAL;
+		}
+	} else {
+		/*
+		 * This should never happen.
+		 * Return a scope with low priority as a last resort.
+		 */
+		return IPV6_ADDR_SCOPE_NODELOCAL;
+	}
+}
+
+/* These macros are modelled after the ones in <netinet/in6.h>. */
+
+/* RFC 4380, section 2.6 */
+#define IN6_IS_ADDR_TEREDO(a)	 \
+	((*(const uint32_t *)(const void *)(&(a)->s6_addr[0]) == ntohl(0x20010000)))
+
+/* RFC 3056, section 2. */
+#define IN6_IS_ADDR_6TO4(a)	 \
+	(((a)->s6_addr[0] == 0x20) && ((a)->s6_addr[1] == 0x02))
+
+/* 6bone testing address area (3ffe::/16), deprecated in RFC 3701. */
+#define IN6_IS_ADDR_6BONE(a)      \
+	(((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe))
+
+/*
+ * Get the label for a given IPv4/IPv6 address.
+ * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01.
+ */
+
+/*ARGSUSED*/
+static int
+_get_label(const struct sockaddr *addr)
+{
+	if (addr->sa_family == AF_INET) {
+		return 3;
+	} else if (addr->sa_family == AF_INET6) {
+		const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
+		if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
+			return 0;
+		} else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
+			return 3;
+		} else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
+			return 4;
+		} else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
+			return 5;
+		} else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) {
+			return 10;
+		} else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) {
+			return 11;
+		} else if (IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
+			return 12;
+		} else {
+			return 2;
+		}
+	} else {
+		/*
+		 * This should never happen.
+		 * Return a semi-random label as a last resort.
+		 */
+		return 1;
+	}
+}
+
+/*
+ * Get the precedence for a given IPv4/IPv6 address.
+ * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01.
+ */
+
+/*ARGSUSED*/
+static int
+_get_precedence(const struct sockaddr *addr)
+{
+	if (addr->sa_family == AF_INET) {
+		return 30;
+	} else if (addr->sa_family == AF_INET6) {
+		const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
+		if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
+			return 60;
+		} else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
+			return 30;
+		} else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
+			return 20;
+		} else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
+			return 10;
+		} else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) ||
+		           IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) ||
+		           IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
+			return 1;
+		} else {
+			return 40;
+		}
+	} else {
+		return 1;
+	}
+}
+
+/*
+ * Find number of matching initial bits between the two addresses a1 and a2.
+ */
+
+/*ARGSUSED*/
+static int
+_common_prefix_len(const struct in6_addr *a1, const struct in6_addr *a2)
+{
+	const char *p1 = (const char *)a1;
+	const char *p2 = (const char *)a2;
+	unsigned i;
+
+	for (i = 0; i < sizeof(*a1); ++i) {
+		int x, j;
+
+		if (p1[i] == p2[i]) {
+			continue;
+		}
+		x = p1[i] ^ p2[i];
+		for (j = 0; j < CHAR_BIT; ++j) {
+			if (x & (1 << (CHAR_BIT - 1))) {
+				return i * CHAR_BIT + j;
+			}
+			x <<= 1;
+		}
+	}
+	return sizeof(*a1) * CHAR_BIT;
+}
+
+/*
+ * Compare two source/destination address pairs.
+ * RFC 3484, section 6.
+ */
+
+/*ARGSUSED*/
+static int
+_rfc3484_compare(const void *ptr1, const void* ptr2)
+{
+	const struct addrinfo_sort_elem *a1 = (const struct addrinfo_sort_elem *)ptr1;
+	const struct addrinfo_sort_elem *a2 = (const struct addrinfo_sort_elem *)ptr2;
+	int scope_src1, scope_dst1, scope_match1;
+	int scope_src2, scope_dst2, scope_match2;
+	int label_src1, label_dst1, label_match1;
+	int label_src2, label_dst2, label_match2;
+	int precedence1, precedence2;
+	int prefixlen1, prefixlen2;
+
+	/* Rule 1: Avoid unusable destinations. */
+	if (a1->has_src_addr != a2->has_src_addr) {
+		return a2->has_src_addr - a1->has_src_addr;
+	}
+
+	/* Rule 2: Prefer matching scope. */
+	scope_src1 = _get_scope(&a1->src_addr.generic);
+	scope_dst1 = _get_scope(a1->ai->ai_addr);
+	scope_match1 = (scope_src1 == scope_dst1);
+
+	scope_src2 = _get_scope(&a2->src_addr.generic);
+	scope_dst2 = _get_scope(a2->ai->ai_addr);
+	scope_match2 = (scope_src2 == scope_dst2);
+
+	if (scope_match1 != scope_match2) {
+		return scope_match2 - scope_match1;
+	}
+
+	/*
+	 * Rule 3: Avoid deprecated addresses.
+	 * TODO(sesse): We don't currently have a good way of finding this.
+	 */
+
+	/*
+	 * Rule 4: Prefer home addresses.
+	 * TODO(sesse): We don't currently have a good way of finding this.
+	 */
+
+	/* Rule 5: Prefer matching label. */
+	label_src1 = _get_label(&a1->src_addr.generic);
+	label_dst1 = _get_label(a1->ai->ai_addr);
+	label_match1 = (label_src1 == label_dst1);
+
+	label_src2 = _get_label(&a2->src_addr.generic);
+	label_dst2 = _get_label(a2->ai->ai_addr);
+	label_match2 = (label_src2 == label_dst2);
+
+	if (label_match1 != label_match2) {
+		return label_match2 - label_match1;
+	}
+
+	/* Rule 6: Prefer higher precedence. */
+	precedence1 = _get_precedence(a1->ai->ai_addr);
+	precedence2 = _get_precedence(a2->ai->ai_addr);
+	if (precedence1 != precedence2) {
+		return precedence2 - precedence1;
+	}
+
+	/*
+	 * Rule 7: Prefer native transport.
+	 * TODO(sesse): We don't currently have a good way of finding this.
+	 */
+
+	/* Rule 8: Prefer smaller scope. */
+	if (scope_dst1 != scope_dst2) {
+		return scope_dst1 - scope_dst2;
+	}
+
+	/*
+	 * Rule 9: Use longest matching prefix.
+         * We implement this for IPv6 only, as the rules in RFC 3484 don't seem
+         * to work very well directly applied to IPv4. (glibc uses information from
+         * the routing table for a custom IPv4 implementation here.)
+	 */
+	if (a1->has_src_addr && a1->ai->ai_addr->sa_family == AF_INET6 &&
+	    a2->has_src_addr && a2->ai->ai_addr->sa_family == AF_INET6) {
+		const struct sockaddr_in6 *a1_src = &a1->src_addr.in6;
+		const struct sockaddr_in6 *a1_dst = (const struct sockaddr_in6 *)a1->ai->ai_addr;
+		const struct sockaddr_in6 *a2_src = &a2->src_addr.in6;
+		const struct sockaddr_in6 *a2_dst = (const struct sockaddr_in6 *)a2->ai->ai_addr;
+		prefixlen1 = _common_prefix_len(&a1_src->sin6_addr, &a1_dst->sin6_addr);
+		prefixlen2 = _common_prefix_len(&a2_src->sin6_addr, &a2_dst->sin6_addr);
+		if (prefixlen1 != prefixlen2) {
+			return prefixlen2 - prefixlen1;
+		}
+	}
+
+	/*
+	 * Rule 10: Leave the order unchanged.
+	 * We need this since qsort() is not necessarily stable.
+	 */
+	return a1->original_order - a2->original_order;
+}
+
+/*
+ * Find the source address that will be used if trying to connect to the given
+ * address. src_addr must be large enough to hold a struct sockaddr_in6.
+ *
+ * Returns 1 if a source address was found, 0 if the address is unreachable,
+ * and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are
+ * undefined.
+ */
+
+/*ARGSUSED*/
+static int
+_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr)
+{
+	int sock;
+	int ret;
+	socklen_t len;
+
+	switch (addr->sa_family) {
+	case AF_INET:
+		len = sizeof(struct sockaddr_in);
+		break;
+	case AF_INET6:
+		len = sizeof(struct sockaddr_in6);
+		break;
+	default:
+		/* No known usable source address for non-INET families. */
+		return 0;
+	}
+
+	sock = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock == -1) {
+		if (errno == EAFNOSUPPORT) {
+			return 0;
+		} else {
+			return -1;
+		}
+	}
+
+	do {
+		ret = connect(sock, addr, len);
+	} while (ret == -1 && errno == EINTR);
+
+	if (ret == -1) {
+		close(sock);
+		return 0;
+	}
+
+	if (getsockname(sock, src_addr, &len) == -1) {
+		close(sock);
+		return -1;
+	}
+	close(sock);
+	return 1;
+}
+
+/*
+ * Sort the linked list starting at sentinel->ai_next in RFC3484 order.
+ * Will leave the list unchanged if an error occurs.
+ */
+
+/*ARGSUSED*/
+static void
+_rfc3484_sort(struct addrinfo *list_sentinel)
+{
+	struct addrinfo *cur;
+	int nelem = 0, i;
+	struct addrinfo_sort_elem *elems;
+
+	cur = list_sentinel->ai_next;
+	while (cur) {
+		++nelem;
+		cur = cur->ai_next;
+	}
+
+	elems = (struct addrinfo_sort_elem *)malloc(nelem * sizeof(struct addrinfo_sort_elem));
+	if (elems == NULL) {
+		goto error;
+	}
+
+	/*
+	 * Convert the linked list to an array that also contains the candidate
+	 * source address for each destination address.
+	 */
+	for (i = 0, cur = list_sentinel->ai_next; i < nelem; ++i, cur = cur->ai_next) {
+		int has_src_addr;
+		assert(cur != NULL);
+		elems[i].ai = cur;
+		elems[i].original_order = i;
+
+		has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic);
+		if (has_src_addr == -1) {
+			goto error;
+		}
+		elems[i].has_src_addr = has_src_addr;
+	}
+
+	/* Sort the addresses, and rearrange the linked list so it matches the sorted order. */
+	qsort((void *)elems, nelem, sizeof(struct addrinfo_sort_elem), _rfc3484_compare);
+
+	list_sentinel->ai_next = elems[0].ai;
+	for (i = 0; i < nelem - 1; ++i) {
+		elems[i].ai->ai_next = elems[i + 1].ai;
+	}
+	elems[nelem - 1].ai->ai_next = NULL;
+
+error:
+	free(elems);
+}
+
+/*ARGSUSED*/
+static int
+_dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
+{
+	struct addrinfo *ai;
+	querybuf *buf, *buf2;
+	const char *name;
+	const struct addrinfo *pai;
+	struct addrinfo sentinel, *cur;
+	struct res_target q, q2;
+	res_state res;
+
+	name = va_arg(ap, char *);
+	pai = va_arg(ap, const struct addrinfo *);
+	//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
+
+	memset(&q, 0, sizeof(q));
+	memset(&q2, 0, sizeof(q2));
+	memset(&sentinel, 0, sizeof(sentinel));
+	cur = &sentinel;
+
+	buf = malloc(sizeof(*buf));
+	if (buf == NULL) {
+		h_errno = NETDB_INTERNAL;
+		return NS_NOTFOUND;
+	}
+	buf2 = malloc(sizeof(*buf2));
+	if (buf2 == NULL) {
+		free(buf);
+		h_errno = NETDB_INTERNAL;
+		return NS_NOTFOUND;
+	}
+
+	switch (pai->ai_family) {
+	case AF_UNSPEC:
+		/* prefer IPv6 */
+		q.name = name;
+		q.qclass = C_IN;
+		q.answer = buf->buf;
+		q.anslen = sizeof(buf->buf);
+		int query_ipv6 = 1, query_ipv4 = 1;
+		if (pai->ai_flags & AI_ADDRCONFIG) {
+			query_ipv6 = _have_ipv6();
+			query_ipv4 = _have_ipv4();
+		}
+		if (query_ipv6) {
+			q.qtype = T_AAAA;
+			if (query_ipv4) {
+				q.next = &q2;
+				q2.name = name;
+				q2.qclass = C_IN;
+				q2.qtype = T_A;
+				q2.answer = buf2->buf;
+				q2.anslen = sizeof(buf2->buf);
+			}
+		} else if (query_ipv4) {
+			q.qtype = T_A;
+		} else {
+			free(buf);
+			free(buf2);
+			return NS_NOTFOUND;
+		}
+		break;
+	case AF_INET:
+		q.name = name;
+		q.qclass = C_IN;
+		q.qtype = T_A;
+		q.answer = buf->buf;
+		q.anslen = sizeof(buf->buf);
+		break;
+	case AF_INET6:
+		q.name = name;
+		q.qclass = C_IN;
+		q.qtype = T_AAAA;
+		q.answer = buf->buf;
+		q.anslen = sizeof(buf->buf);
+		break;
+	default:
+		free(buf);
+		free(buf2);
+		return NS_UNAVAIL;
+	}
+
+	res = __res_get_state();
+	if (res == NULL) {
+		free(buf);
+		free(buf2);
+		return NS_NOTFOUND;
+	}
+
+	if (res_searchN(name, &q, res) < 0) {
+		__res_put_state(res);
+		free(buf);
+		free(buf2);
+		return NS_NOTFOUND;
+	}
+	ai = getanswer(buf, q.n, q.name, q.qtype, pai);
+	if (ai) {
+		cur->ai_next = ai;
+		while (cur && cur->ai_next)
+			cur = cur->ai_next;
+	}
+	if (q.next) {
+		ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
+		if (ai)
+			cur->ai_next = ai;
+	}
+	free(buf);
+	free(buf2);
+	if (sentinel.ai_next == NULL) {
+		__res_put_state(res);
+		switch (h_errno) {
+		case HOST_NOT_FOUND:
+			return NS_NOTFOUND;
+		case TRY_AGAIN:
+			return NS_TRYAGAIN;
+		default:
+			return NS_UNAVAIL;
+		}
+	}
+
+	_rfc3484_sort(&sentinel);
+
+	__res_put_state(res);
+
+	*((struct addrinfo **)rv) = sentinel.ai_next;
+	return NS_SUCCESS;
+}
+
+static void
+_sethtent(_pseudo_FILE * __restrict__ hostf)
+{
+	assert(hostf);
+	if (hostf->mapping == MAP_FAILED)
+		(void) _pseudo_fopen_r(hostf, _PATH_HOSTS);
+	else
+		_pseudo_rewind(hostf);
+}
+
+static void
+_endhtent(_pseudo_FILE * __restrict__ hostf)
+{
+	assert(hostf);
+	(void) _pseudo_fclose(hostf);
+}
+
+static struct addrinfo *
+_gethtent(_pseudo_FILE * __restrict__ hostf, const char *name, const struct addrinfo *pai)
+{
+	char *p;
+	char *cp, *tname, *cname;
+	struct addrinfo hints, *res0, *res;
+	int error;
+	const char *addr;
+	char hostbuf[8*1024];
+
+	assert(hostf);
+//	fprintf(stderr, "_gethtent() name = '%s'\n", name);
+	assert(name != NULL);
+	assert(pai != NULL);
+
+	if (hostf->mapping == MAP_FAILED)
+		(void) _pseudo_fopen_r(hostf, _PATH_HOSTS);
+	if (hostf->mapping == MAP_FAILED)
+		return (NULL);
+ again:
+	if (!(p = _pseudo_fgets(hostbuf, sizeof hostbuf, hostf)))
+		return (NULL);
+	if (*p == '#')
+		goto again;
+	if (!(cp = strpbrk(p, "#\n")))
+		goto again;
+	*cp = '\0';
+	if (!(cp = strpbrk(p, " \t")))
+		goto again;
+	*cp++ = '\0';
+	addr = p;
+	/* if this is not something we're looking for, skip it. */
+	cname = NULL;
+	while (cp && *cp) {
+		if (*cp == ' ' || *cp == '\t') {
+			cp++;
+			continue;
+		}
+		if (!cname)
+			cname = cp;
+		tname = cp;
+		if ((cp = strpbrk(cp, " \t")) != NULL)
+			*cp++ = '\0';
+//		fprintf(stderr, "\ttname = '%s'", tname);
+		if (strcasecmp(name, tname) == 0)
+			goto found;
+	}
+	goto again;
+
+found:
+	hints = *pai;
+	hints.ai_flags = AI_NUMERICHOST;
+	error = __wrap_getaddrinfo(addr, NULL, &hints, &res0);
+	if (error)
+		goto again;
+	for (res = res0; res; res = res->ai_next) {
+		/* cover it up */
+		res->ai_flags = pai->ai_flags;
+
+		if (pai->ai_flags & AI_CANONNAME) {
+			if (get_canonname(pai, res, cname) != 0) {
+				__wrap_freeaddrinfo(res0);
+				goto again;
+			}
+		}
+	}
+	return res0;
+}
+
+/*ARGSUSED*/
+static int
+_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
+{
+	const char *name;
+	const struct addrinfo *pai;
+	struct addrinfo sentinel, *cur;
+	struct addrinfo *p;
+	_pseudo_FILE hostf = _PSEUDO_FILE_INITIALIZER;
+
+	name = va_arg(ap, char *);
+	pai = va_arg(ap, struct addrinfo *);
+
+//	fprintf(stderr, "_files_getaddrinfo() name = '%s'\n", name);
+	memset(&sentinel, 0, sizeof(sentinel));
+	cur = &sentinel;
+
+	_sethtent(&hostf);
+	while ((p = _gethtent(&hostf, name, pai)) != NULL) {
+		cur->ai_next = p;
+		while (cur && cur->ai_next)
+			cur = cur->ai_next;
+	}
+	_endhtent(&hostf);
+
+	*((struct addrinfo **)rv) = sentinel.ai_next;
+	if (sentinel.ai_next == NULL)
+		return NS_NOTFOUND;
+	return NS_SUCCESS;
+}
+
+/* resolver logic */
+
+/*
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in h_errno.
+ *
+ * Caller must parse answer and determine whether it answers the question.
+ */
+static int
+res_queryN(const char *name, /* domain name */ struct res_target *target,
+    res_state res)
+{
+	u_char buf[MAXPACKET];
+	HEADER *hp;
+	int n;
+	struct res_target *t;
+	int rcode;
+	int ancount;
+
+	assert(name != NULL);
+	/* XXX: target may be NULL??? */
+
+	rcode = NOERROR;
+	ancount = 0;
+
+	for (t = target; t; t = t->next) {
+		int class, type;
+		u_char *answer;
+		int anslen;
+
+		hp = (HEADER *)(void *)t->answer;
+		hp->rcode = NOERROR;	/* default */
+
+		/* make it easier... */
+		class = t->qclass;
+		type = t->qtype;
+		answer = t->answer;
+		anslen = t->anslen;
+#ifdef DEBUG
+		if (res->options & RES_DEBUG)
+			printf(";; res_nquery(%s, %d, %d)\n", name, class, type);
+#endif
+
+		n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
+		    buf, sizeof(buf));
+#ifdef RES_USE_EDNS0
+		if (n > 0 && (res->options & RES_USE_EDNS0) != 0)
+			n = res_nopt(res, n, buf, sizeof(buf), anslen);
+#endif
+		if (n <= 0) {
+#ifdef DEBUG
+			if (res->options & RES_DEBUG)
+				printf(";; res_nquery: mkquery failed\n");
+#endif
+			h_errno = NO_RECOVERY;
+			return n;
+		}
+		n = res_nsend(res, buf, n, answer, anslen);
+#if 0
+		if (n < 0) {
+#ifdef DEBUG
+			if (res->options & RES_DEBUG)
+				printf(";; res_query: send error\n");
+#endif
+			h_errno = TRY_AGAIN;
+			return n;
+		}
+#endif
+
+		if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+			rcode = hp->rcode;	/* record most recent error */
+#ifdef DEBUG
+			if (res->options & RES_DEBUG)
+				printf(";; rcode = %u, ancount=%u\n", hp->rcode,
+				    ntohs(hp->ancount));
+#endif
+			continue;
+		}
+
+		ancount += ntohs(hp->ancount);
+
+		t->n = n;
+	}
+
+	if (ancount == 0) {
+		switch (rcode) {
+		case NXDOMAIN:
+			h_errno = HOST_NOT_FOUND;
+			break;
+		case SERVFAIL:
+			h_errno = TRY_AGAIN;
+			break;
+		case NOERROR:
+			h_errno = NO_DATA;
+			break;
+		case FORMERR:
+		case NOTIMP:
+		case REFUSED:
+		default:
+			h_errno = NO_RECOVERY;
+			break;
+		}
+		return -1;
+	}
+	return ancount;
+}
+
+/*
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected.  Error code, if any, is left in h_errno.
+ */
+static int
+res_searchN(const char *name, struct res_target *target, res_state res)
+{
+	const char *cp, * const *domain;
+	HEADER *hp;
+	u_int dots;
+	int trailing_dot, ret, saved_herrno;
+	int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
+
+	assert(name != NULL);
+	assert(target != NULL);
+
+	hp = (HEADER *)(void *)target->answer;	/*XXX*/
+
+	errno = 0;
+	h_errno = HOST_NOT_FOUND;	/* default, if we never query */
+	dots = 0;
+	for (cp = name; *cp; cp++)
+		dots += (*cp == '.');
+	trailing_dot = 0;
+	if (cp > name && *--cp == '.')
+		trailing_dot++;
+
+
+        //fprintf(stderr, "res_searchN() name = '%s'\n", name);
+
+	/*
+	 * if there aren't any dots, it could be a user-level alias
+	 */
+	if (!dots && (cp = __hostalias(name)) != NULL) {
+		ret = res_queryN(cp, target, res);
+		return ret;
+	}
+
+	/*
+	 * If there are dots in the name already, let's just give it a try
+	 * 'as is'.  The threshold can be set with the "ndots" option.
+	 */
+	saved_herrno = -1;
+	if (dots >= res->ndots) {
+		ret = res_querydomainN(name, NULL, target, res);
+		if (ret > 0)
+			return (ret);
+		saved_herrno = h_errno;
+		tried_as_is++;
+	}
+
+	/*
+	 * We do at least one level of search if
+	 *	- there is no dot and RES_DEFNAME is set, or
+	 *	- there is at least one dot, there is no trailing dot,
+	 *	  and RES_DNSRCH is set.
+	 */
+	if ((!dots && (res->options & RES_DEFNAMES)) ||
+	    (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
+		int done = 0;
+
+		for (domain = (const char * const *)res->dnsrch;
+		   *domain && !done;
+		   domain++) {
+
+			ret = res_querydomainN(name, *domain, target, res);
+			if (ret > 0)
+				return ret;
+
+			/*
+			 * If no server present, give up.
+			 * If name isn't found in this domain,
+			 * keep trying higher domains in the search list
+			 * (if that's enabled).
+			 * On a NO_DATA error, keep trying, otherwise
+			 * a wildcard entry of another type could keep us
+			 * from finding this entry higher in the domain.
+			 * If we get some other error (negative answer or
+			 * server failure), then stop searching up,
+			 * but try the input name below in case it's
+			 * fully-qualified.
+			 */
+			if (errno == ECONNREFUSED) {
+				h_errno = TRY_AGAIN;
+				return -1;
+			}
+
+			switch (h_errno) {
+			case NO_DATA:
+				got_nodata++;
+				/* FALLTHROUGH */
+			case HOST_NOT_FOUND:
+				/* keep trying */
+				break;
+			case TRY_AGAIN:
+				if (hp->rcode == SERVFAIL) {
+					/* try next search element, if any */
+					got_servfail++;
+					break;
+				}
+				/* FALLTHROUGH */
+			default:
+				/* anything else implies that we're done */
+				done++;
+			}
+			/*
+			 * if we got here for some reason other than DNSRCH,
+			 * we only wanted one iteration of the loop, so stop.
+			 */
+			if (!(res->options & RES_DNSRCH))
+			        done++;
+		}
+	}
+
+	/*
+	 * if we have not already tried the name "as is", do that now.
+	 * note that we do this regardless of how many dots were in the
+	 * name or whether it ends with a dot.
+	 */
+	if (!tried_as_is) {
+		ret = res_querydomainN(name, NULL, target, res);
+		if (ret > 0)
+			return ret;
+	}
+
+	/*
+	 * if we got here, we didn't satisfy the search.
+	 * if we did an initial full query, return that query's h_errno
+	 * (note that we wouldn't be here if that query had succeeded).
+	 * else if we ever got a nodata, send that back as the reason.
+	 * else send back meaningless h_errno, that being the one from
+	 * the last DNSRCH we did.
+	 */
+	if (saved_herrno != -1)
+		h_errno = saved_herrno;
+	else if (got_nodata)
+		h_errno = NO_DATA;
+	else if (got_servfail)
+		h_errno = TRY_AGAIN;
+	return -1;
+}
+
+/*
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+static int
+res_querydomainN(const char *name, const char *domain,
+    struct res_target *target, res_state res)
+{
+	char nbuf[MAXDNAME];
+	const char *longname = nbuf;
+	size_t n, d;
+
+	assert(name != NULL);
+	/* XXX: target may be NULL??? */
+
+#ifdef DEBUG
+	if (res->options & RES_DEBUG)
+		printf(";; res_querydomain(%s, %s)\n",
+			name, domain?domain:"<Nil>");
+#endif
+	if (domain == NULL) {
+		/*
+		 * Check for trailing '.';
+		 * copy without '.' if present.
+		 */
+		n = strlen(name);
+		if (n + 1 > sizeof(nbuf)) {
+			h_errno = NO_RECOVERY;
+			return -1;
+		}
+		if (n > 0 && name[--n] == '.') {
+			strncpy(nbuf, name, n);
+			nbuf[n] = '\0';
+		} else
+			longname = name;
+	} else {
+		n = strlen(name);
+		d = strlen(domain);
+		if (n + 1 + d + 1 > sizeof(nbuf)) {
+			h_errno = NO_RECOVERY;
+			return -1;
+		}
+		snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
+	}
+	return res_queryN(longname, target, res);
+}
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/res_debug.c
@@ -0,0 +1,1184 @@
+/*	$NetBSD: res_debug.c,v 1.7 2004/11/07 02:25:01 christos Exp $	*/
+
+/*
+ * Copyright (c) 1985
+ *    The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ * 	This product includes software developed by the University of
+ * 	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#ifdef notdef
+static const char sccsid[] = "@(#)res_debug.c	8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "Id: res_debug.c,v 1.3.2.5.4.5 2004/07/28 20:16:46 marka Exp";
+#else
+__RCSID("$NetBSD: res_debug.c,v 1.7 2004/11/07 02:25:01 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "arpa_nameser.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include "resolv_private.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) sprintf x
+#endif
+
+static const char *precsize_ntoa(u_int32_t);
+
+extern const char * const _res_opcodes[];
+extern const char * const _res_sectioncodes[];
+
+#ifndef _LIBC
+/*
+ * Print the current options.
+ */
+void
+fp_resstat(const res_state statp, FILE *file) {
+	u_long mask;
+
+	fprintf(file, ";; res options:");
+	for (mask = 1;  mask != 0U;  mask <<= 1)
+		if (statp->options & mask)
+			fprintf(file, " %s", p_option(mask));
+	putc('\n', file);
+}
+#endif
+
+static void
+do_section(const res_state statp,
+	   ns_msg *handle, ns_sect section,
+	   int pflag, FILE *file)
+{
+	int n, sflag, rrnum;
+	int buflen = 2048;
+	char *buf;
+	ns_opcode opcode;
+	ns_rr rr;
+
+	/*
+	 * Print answer records.
+	 */
+	sflag = (statp->pfcode & pflag);
+	if (statp->pfcode && !sflag)
+		return;
+
+	buf = malloc((size_t)buflen);
+	if (buf == NULL) {
+		fprintf(file, ";; memory allocation failure\n");
+		return;
+	}
+
+	opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
+	rrnum = 0;
+	for (;;) {
+		if (ns_parserr(handle, section, rrnum, &rr)) {
+			if (errno != ENODEV)
+				fprintf(file, ";; ns_parserr: %s\n",
+					strerror(errno));
+			else if (rrnum > 0 && sflag != 0 &&
+				 (statp->pfcode & RES_PRF_HEAD1))
+				putc('\n', file);
+			goto cleanup;
+		}
+		if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
+			fprintf(file, ";; %s SECTION:\n",
+				p_section(section, opcode));
+		if (section == ns_s_qd)
+			fprintf(file, ";;\t%s, type = %s, class = %s\n",
+				ns_rr_name(rr),
+				p_type(ns_rr_type(rr)),
+				p_class(ns_rr_class(rr)));
+		else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
+			u_int32_t ttl = ns_rr_ttl(rr);
+			fprintf(file,
+				"; EDNS: version: %u, udp=%u, flags=%04x\n",
+				(ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);
+		} else {
+			n = ns_sprintrr(handle, &rr, NULL, NULL,
+					buf, (u_int)buflen);
+			if (n < 0) {
+				if (errno == ENOSPC) {
+					free(buf);
+					buf = NULL;
+					if (buflen < 131072)
+						buf = malloc((size_t)(buflen += 1024));
+					if (buf == NULL) {
+						fprintf(file,
+				              ";; memory allocation failure\n");
+					      return;
+					}
+					continue;
+				}
+				fprintf(file, ";; ns_sprintrr: %s\n",
+					strerror(errno));
+				goto cleanup;
+			}
+			fputs(buf, file);
+			fputc('\n', file);
+		}
+		rrnum++;
+	}
+ cleanup:
+	if (buf != NULL)
+		free(buf);
+}
+
+/*
+ * Print the contents of a query.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
+	ns_msg handle;
+	int qdcount, ancount, nscount, arcount;
+	u_int opcode, rcode, id;
+
+	if (ns_initparse(msg, len, &handle) < 0) {
+		fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
+		return;
+	}
+	opcode = ns_msg_getflag(handle, ns_f_opcode);
+	rcode = ns_msg_getflag(handle, ns_f_rcode);
+	id = ns_msg_id(handle);
+	qdcount = ns_msg_count(handle, ns_s_qd);
+	ancount = ns_msg_count(handle, ns_s_an);
+	nscount = ns_msg_count(handle, ns_s_ns);
+	arcount = ns_msg_count(handle, ns_s_ar);
+
+	/*
+	 * Print header fields.
+	 */
+	if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
+		fprintf(file,
+			";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
+			_res_opcodes[opcode], p_rcode((int)rcode), id);
+	if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
+		putc(';', file);
+	if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
+		fprintf(file, "; flags:");
+		if (ns_msg_getflag(handle, ns_f_qr))
+			fprintf(file, " qr");
+		if (ns_msg_getflag(handle, ns_f_aa))
+			fprintf(file, " aa");
+		if (ns_msg_getflag(handle, ns_f_tc))
+			fprintf(file, " tc");
+		if (ns_msg_getflag(handle, ns_f_rd))
+			fprintf(file, " rd");
+		if (ns_msg_getflag(handle, ns_f_ra))
+			fprintf(file, " ra");
+		if (ns_msg_getflag(handle, ns_f_z))
+			fprintf(file, " ??");
+		if (ns_msg_getflag(handle, ns_f_ad))
+			fprintf(file, " ad");
+		if (ns_msg_getflag(handle, ns_f_cd))
+			fprintf(file, " cd");
+	}
+	if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
+		fprintf(file, "; %s: %d",
+			p_section(ns_s_qd, (int)opcode), qdcount);
+		fprintf(file, ", %s: %d",
+			p_section(ns_s_an, (int)opcode), ancount);
+		fprintf(file, ", %s: %d",
+			p_section(ns_s_ns, (int)opcode), nscount);
+		fprintf(file, ", %s: %d",
+			p_section(ns_s_ar, (int)opcode), arcount);
+	}
+	if ((!statp->pfcode) || (statp->pfcode &
+		(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
+		putc('\n',file);
+	}
+	/*
+	 * Print the various sections.
+	 */
+	do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
+	do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
+	do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
+	do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
+	if (qdcount == 0 && ancount == 0 &&
+	    nscount == 0 && arcount == 0)
+		putc('\n', file);
+}
+
+const u_char *
+p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
+	char name[MAXDNAME];
+	int n;
+
+	if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
+		return (NULL);
+	if (name[0] == '\0')
+		putc('.', file);
+	else
+		fputs(name, file);
+	return (cp + n);
+}
+
+const u_char *
+p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
+	return (p_cdnname(cp, msg, PACKETSZ, file));
+}
+
+/* Return a fully-qualified domain name from a compressed name (with
+   length supplied).  */
+
+const u_char *
+p_fqnname(cp, msg, msglen, name, namelen)
+	const u_char *cp, *msg;
+	int msglen;
+	char *name;
+	int namelen;
+{
+	int n, newlen;
+
+	if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
+		return (NULL);
+	newlen = strlen(name);
+	if (newlen == 0 || name[newlen - 1] != '.') {
+		if (newlen + 1 >= namelen)	/* Lack space for final dot */
+			return (NULL);
+		else
+			strcpy(name + newlen, ".");
+	}
+	return (cp + n);
+}
+
+/* XXX:	the rest of these functions need to become length-limited, too. */
+
+const u_char *
+p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
+	char name[MAXDNAME];
+	const u_char *n;
+
+	n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+	if (n == NULL)
+		return (NULL);
+	fputs(name, file);
+	return (n);
+}
+
+/*
+ * Names of RR classes and qclasses.  Classes and qclasses are the same, except
+ * that C_ANY is a qclass but not a class.  (You can ask for records of class
+ * C_ANY, but you can't have any records of that class in the database.)
+ */
+const struct res_sym __p_class_syms[] = {
+	{C_IN,		"IN",		(char *)0},
+	{C_CHAOS,	"CH",		(char *)0},
+	{C_CHAOS,	"CHAOS",	(char *)0},
+	{C_HS,		"HS",		(char *)0},
+	{C_HS,		"HESIOD",	(char *)0},
+	{C_ANY,		"ANY",		(char *)0},
+	{C_NONE,	"NONE",		(char *)0},
+	{C_IN, 		(char *)0,	(char *)0}
+};
+
+/*
+ * Names of message sections.
+ */
+const struct res_sym __p_default_section_syms[] = {
+	{ns_s_qd,	"QUERY",	(char *)0},
+	{ns_s_an,	"ANSWER",	(char *)0},
+	{ns_s_ns,	"AUTHORITY",	(char *)0},
+	{ns_s_ar,	"ADDITIONAL",	(char *)0},
+	{0,             (char *)0,	(char *)0}
+};
+
+const struct res_sym __p_update_section_syms[] = {
+	{S_ZONE,	"ZONE",		(char *)0},
+	{S_PREREQ,	"PREREQUISITE",	(char *)0},
+	{S_UPDATE,	"UPDATE",	(char *)0},
+	{S_ADDT,	"ADDITIONAL",	(char *)0},
+	{0,             (char *)0,	(char *)0}
+};
+
+const struct res_sym __p_key_syms[] = {
+	{NS_ALG_MD5RSA,		"RSA",		"RSA KEY with MD5 hash"},
+	{NS_ALG_DH,		"DH",		"Diffie Hellman"},
+	{NS_ALG_DSA,		"DSA",		"Digital Signature Algorithm"},
+	{NS_ALG_EXPIRE_ONLY,	"EXPIREONLY",	"No algorithm"},
+	{NS_ALG_PRIVATE_OID,	"PRIVATE",	"Algorithm obtained from OID"},
+	{0,			NULL,		NULL}
+};
+
+const struct res_sym __p_cert_syms[] = {
+	{cert_t_pkix,	"PKIX",		"PKIX (X.509v3) Certificate"},
+	{cert_t_spki,	"SPKI",		"SPKI certificate"},
+	{cert_t_pgp,	"PGP",		"PGP certificate"},
+	{cert_t_url,	"URL",		"URL Private"},
+	{cert_t_oid,	"OID",		"OID Private"},
+	{0,		NULL,		NULL}
+};
+
+/*
+ * Names of RR types and qtypes.  Types and qtypes are the same, except
+ * that T_ANY is a qtype but not a type.  (You can ask for records of type
+ * T_ANY, but you can't have any records of that type in the database.)
+ */
+const struct res_sym __p_type_syms[] = {
+	{ns_t_a,	"A",		"address"},
+	{ns_t_ns,	"NS",		"name server"},
+	{ns_t_md,	"MD",		"mail destination (deprecated)"},
+	{ns_t_mf,	"MF",		"mail forwarder (deprecated)"},
+	{ns_t_cname,	"CNAME",	"canonical name"},
+	{ns_t_soa,	"SOA",		"start of authority"},
+	{ns_t_mb,	"MB",		"mailbox"},
+	{ns_t_mg,	"MG",		"mail group member"},
+	{ns_t_mr,	"MR",		"mail rename"},
+	{ns_t_null,	"NULL",		"null"},
+	{ns_t_wks,	"WKS",		"well-known service (deprecated)"},
+	{ns_t_ptr,	"PTR",		"domain name pointer"},
+	{ns_t_hinfo,	"HINFO",	"host information"},
+	{ns_t_minfo,	"MINFO",	"mailbox information"},
+	{ns_t_mx,	"MX",		"mail exchanger"},
+	{ns_t_txt,	"TXT",		"text"},
+	{ns_t_rp,	"RP",		"responsible person"},
+	{ns_t_afsdb,	"AFSDB",	"DCE or AFS server"},
+	{ns_t_x25,	"X25",		"X25 address"},
+	{ns_t_isdn,	"ISDN",		"ISDN address"},
+	{ns_t_rt,	"RT",		"router"},
+	{ns_t_nsap,	"NSAP",		"nsap address"},
+	{ns_t_nsap_ptr,	"NSAP_PTR",	"domain name pointer"},
+	{ns_t_sig,	"SIG",		"signature"},
+	{ns_t_key,	"KEY",		"key"},
+	{ns_t_px,	"PX",		"mapping information"},
+	{ns_t_gpos,	"GPOS",		"geographical position (withdrawn)"},
+	{ns_t_aaaa,	"AAAA",		"IPv6 address"},
+	{ns_t_loc,	"LOC",		"location"},
+	{ns_t_nxt,	"NXT",		"next valid name (unimplemented)"},
+	{ns_t_eid,	"EID",		"endpoint identifier (unimplemented)"},
+	{ns_t_nimloc,	"NIMLOC",	"NIMROD locator (unimplemented)"},
+	{ns_t_srv,	"SRV",		"server selection"},
+	{ns_t_atma,	"ATMA",		"ATM address (unimplemented)"},
+	{ns_t_tkey,	"TKEY",		"tkey"},
+	{ns_t_tsig,	"TSIG",		"transaction signature"},
+	{ns_t_ixfr,	"IXFR",		"incremental zone transfer"},
+	{ns_t_axfr,	"AXFR",		"zone transfer"},
+	{ns_t_zxfr,	"ZXFR",		"compressed zone transfer"},
+	{ns_t_mailb,	"MAILB",	"mailbox-related data (deprecated)"},
+	{ns_t_maila,	"MAILA",	"mail agent (deprecated)"},
+	{ns_t_naptr,	"NAPTR",	"URN Naming Authority"},
+	{ns_t_kx,	"KX",		"Key Exchange"},
+	{ns_t_cert,	"CERT",		"Certificate"},
+	{ns_t_a6,	"A6",		"IPv6 Address"},
+	{ns_t_dname,	"DNAME",	"dname"},
+	{ns_t_sink,	"SINK",		"Kitchen Sink (experimental)"},
+	{ns_t_opt,	"OPT",		"EDNS Options"},
+	{ns_t_any,	"ANY",		"\"any\""},
+	{0, 		NULL,		NULL}
+};
+
+/*
+ * Names of DNS rcodes.
+ */
+const struct res_sym __p_rcode_syms[] = {
+	{ns_r_noerror,	"NOERROR",		"no error"},
+	{ns_r_formerr,	"FORMERR",		"format error"},
+	{ns_r_servfail,	"SERVFAIL",		"server failed"},
+	{ns_r_nxdomain,	"NXDOMAIN",		"no such domain name"},
+	{ns_r_notimpl,	"NOTIMP",		"not implemented"},
+	{ns_r_refused,	"REFUSED",		"refused"},
+	{ns_r_yxdomain,	"YXDOMAIN",		"domain name exists"},
+	{ns_r_yxrrset,	"YXRRSET",		"rrset exists"},
+	{ns_r_nxrrset,	"NXRRSET",		"rrset doesn't exist"},
+	{ns_r_notauth,	"NOTAUTH",		"not authoritative"},
+	{ns_r_notzone,	"NOTZONE",		"Not in zone"},
+	{ns_r_max,	"",			""},
+	{ns_r_badsig,	"BADSIG",		"bad signature"},
+	{ns_r_badkey,	"BADKEY",		"bad key"},
+	{ns_r_badtime,	"BADTIME",		"bad time"},
+	{0, 		NULL,			NULL}
+};
+
+int
+sym_ston(const struct res_sym *syms, const char *name, int *success) {
+	for (; syms->name != 0; syms++) {
+		if (strcasecmp (name, syms->name) == 0) {
+			if (success)
+				*success = 1;
+			return (syms->number);
+		}
+	}
+	if (success)
+		*success = 0;
+	return (syms->number);		/* The default value. */
+}
+
+const char *
+sym_ntos(const struct res_sym *syms, int number, int *success) {
+	static char unname[20];
+
+	for (; syms->name != 0; syms++) {
+		if (number == syms->number) {
+			if (success)
+				*success = 1;
+			return (syms->name);
+		}
+	}
+
+	sprintf(unname, "%d", number);		/* XXX nonreentrant */
+	if (success)
+		*success = 0;
+	return (unname);
+}
+
+const char *
+sym_ntop(const struct res_sym *syms, int number, int *success) {
+	static char unname[20];
+
+	for (; syms->name != 0; syms++) {
+		if (number == syms->number) {
+			if (success)
+				*success = 1;
+			return (syms->humanname);
+		}
+	}
+	sprintf(unname, "%d", number);		/* XXX nonreentrant */
+	if (success)
+		*success = 0;
+	return (unname);
+}
+
+/*
+ * Return a string for the type.
+ */
+const char *
+p_type(int type) {
+	int success;
+	const char *result;
+	static char typebuf[20];
+
+	result = sym_ntos(__p_type_syms, type, &success);
+	if (success)
+		return (result);
+	if (type < 0 || type > 0xffff)
+		return ("BADTYPE");
+	sprintf(typebuf, "TYPE%d", type);
+	return (typebuf);
+}
+
+/*
+ * Return a string for the type.
+ */
+const char *
+p_section(int section, int opcode) {
+	const struct res_sym *symbols;
+
+	switch (opcode) {
+	case ns_o_update:
+		symbols = __p_update_section_syms;
+		break;
+	default:
+		symbols = __p_default_section_syms;
+		break;
+	}
+	return (sym_ntos(symbols, section, (int *)0));
+}
+
+/*
+ * Return a mnemonic for class.
+ */
+const char *
+p_class(int class) {
+	int success;
+	const char *result;
+	static char classbuf[20];
+
+	result = sym_ntos(__p_class_syms, class, &success);
+	if (success)
+		return (result);
+	if (class < 0 || class > 0xffff)
+		return ("BADCLASS");
+	sprintf(classbuf, "CLASS%d", class);
+	return (classbuf);
+}
+
+/*
+ * Return a mnemonic for an option
+ */
+const char *
+p_option(u_long option) {
+	static char nbuf[40];
+
+	switch (option) {
+	case RES_INIT:		return "init";
+	case RES_DEBUG:		return "debug";
+	case RES_AAONLY:	return "aaonly(unimpl)";
+	case RES_USEVC:		return "usevc";
+	case RES_PRIMARY:	return "primry(unimpl)";
+	case RES_IGNTC:		return "igntc";
+	case RES_RECURSE:	return "recurs";
+	case RES_DEFNAMES:	return "defnam";
+	case RES_STAYOPEN:	return "styopn";
+	case RES_DNSRCH:	return "dnsrch";
+	case RES_INSECURE1:	return "insecure1";
+	case RES_INSECURE2:	return "insecure2";
+	case RES_NOALIASES:	return "noaliases";
+	case RES_USE_INET6:	return "inet6";
+#ifdef RES_USE_EDNS0	/* KAME extension */
+	case RES_USE_EDNS0:	return "edns0";
+#endif
+#ifdef RES_USE_DNAME
+	case RES_USE_DNAME:	return "dname";
+#endif
+#ifdef RES_USE_DNSSEC
+	case RES_USE_DNSSEC:	return "dnssec";
+#endif
+#ifdef RES_NOTLDQUERY
+	case RES_NOTLDQUERY:	return "no-tld-query";
+#endif
+#ifdef RES_NO_NIBBLE2
+	case RES_NO_NIBBLE2:	return "no-nibble2";
+#endif
+				/* XXX nonreentrant */
+	default:		sprintf(nbuf, "?0x%lx?", (u_long)option);
+				return (nbuf);
+	}
+}
+
+/*
+ * Return a mnemonic for a time to live.
+ */
+const char *
+p_time(u_int32_t value) {
+	static char nbuf[40];		/* XXX nonreentrant */
+
+	if (ns_format_ttl((u_long)value, nbuf, sizeof nbuf) < 0)
+		sprintf(nbuf, "%u", value);
+	return (nbuf);
+}
+
+/*
+ * Return a string for the rcode.
+ */
+const char *
+p_rcode(int rcode) {
+	return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
+}
+
+/*
+ * Return a string for a res_sockaddr_union.
+ */
+const char *
+p_sockun(union res_sockaddr_union u, char *buf, size_t size) {
+	char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"];
+
+	switch (u.sin.sin_family) {
+	case AF_INET:
+		inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret);
+		break;
+#ifdef HAS_INET6_STRUCTS
+	case AF_INET6:
+		inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret);
+		break;
+#endif
+	default:
+		sprintf(ret, "[af%d]", u.sin.sin_family);
+		break;
+	}
+	if (size > 0U) {
+		strncpy(buf, ret, size - 1);
+		buf[size - 1] = '0';
+	}
+	return (buf);
+}
+
+/*
+ * routines to convert between on-the-wire RR format and zone file format.
+ * Does not contain conversion to/from decimal degrees; divide or multiply
+ * by 60*60*1000 for that.
+ */
+
+static const unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+				      1000000,10000000,100000000,1000000000};
+
+/* takes an XeY precision/size value, returns a string representation. */
+static const char *
+precsize_ntoa(prec)
+	u_int32_t prec;
+{
+	static char retbuf[sizeof "90000000.00"];	/* XXX nonreentrant */
+	unsigned long val;
+	int mantissa, exponent;
+
+	mantissa = (int)((prec >> 4) & 0x0f) % 10;
+	exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+	val = mantissa * poweroften[exponent];
+
+	(void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100);
+	return (retbuf);
+}
+
+/* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
+static u_int8_t
+precsize_aton(const char **strptr) {
+	unsigned int mval = 0, cmval = 0;
+	u_int8_t retval = 0;
+	const char *cp;
+	int exponent;
+	int mantissa;
+
+	cp = *strptr;
+
+	while (isdigit((unsigned char)*cp))
+		mval = mval * 10 + (*cp++ - '0');
+
+	if (*cp == '.') {		/* centimeters */
+		cp++;
+		if (isdigit((unsigned char)*cp)) {
+			cmval = (*cp++ - '0') * 10;
+			if (isdigit((unsigned char)*cp)) {
+				cmval += (*cp++ - '0');
+			}
+		}
+	}
+	cmval = (mval * 100) + cmval;
+
+	for (exponent = 0; exponent < 9; exponent++)
+		if (cmval < poweroften[exponent+1])
+			break;
+
+	mantissa = cmval / poweroften[exponent];
+	if (mantissa > 9)
+		mantissa = 9;
+
+	retval = (mantissa << 4) | exponent;
+
+	*strptr = cp;
+
+	return (retval);
+}
+
+/* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
+static u_int32_t
+latlon2ul(const char **latlonstrptr, int *which) {
+	const char *cp;
+	u_int32_t retval;
+	int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+	cp = *latlonstrptr;
+
+	while (isdigit((unsigned char)*cp))
+		deg = deg * 10 + (*cp++ - '0');
+
+	while (isspace((unsigned char)*cp))
+		cp++;
+
+	if (!(isdigit((unsigned char)*cp)))
+		goto fndhemi;
+
+	while (isdigit((unsigned char)*cp))
+		min = min * 10 + (*cp++ - '0');
+
+	while (isspace((unsigned char)*cp))
+		cp++;
+
+	if (!(isdigit((unsigned char)*cp)))
+		goto fndhemi;
+
+	while (isdigit((unsigned char)*cp))
+		secs = secs * 10 + (*cp++ - '0');
+
+	if (*cp == '.') {		/* decimal seconds */
+		cp++;
+		if (isdigit((unsigned char)*cp)) {
+			secsfrac = (*cp++ - '0') * 100;
+			if (isdigit((unsigned char)*cp)) {
+				secsfrac += (*cp++ - '0') * 10;
+				if (isdigit((unsigned char)*cp)) {
+					secsfrac += (*cp++ - '0');
+				}
+			}
+		}
+	}
+
+	while (!isspace((unsigned char)*cp))	/* if any trailing garbage */
+		cp++;
+
+	while (isspace((unsigned char)*cp))
+		cp++;
+
+ fndhemi:
+	switch (*cp) {
+	case 'N': case 'n':
+	case 'E': case 'e':
+		retval = ((unsigned)1<<31)
+			+ (((((deg * 60) + min) * 60) + secs) * 1000)
+			+ secsfrac;
+		break;
+	case 'S': case 's':
+	case 'W': case 'w':
+		retval = ((unsigned)1<<31)
+			- (((((deg * 60) + min) * 60) + secs) * 1000)
+			- secsfrac;
+		break;
+	default:
+		retval = 0;	/* invalid value -- indicates error */
+		break;
+	}
+
+	switch (*cp) {
+	case 'N': case 'n':
+	case 'S': case 's':
+		*which = 1;	/* latitude */
+		break;
+	case 'E': case 'e':
+	case 'W': case 'w':
+		*which = 2;	/* longitude */
+		break;
+	default:
+		*which = 0;	/* error */
+		break;
+	}
+
+	cp++;			/* skip the hemisphere */
+
+	while (!isspace((unsigned char)*cp))	/* if any trailing garbage */
+		cp++;
+
+	while (isspace((unsigned char)*cp))	/* move to next field */
+		cp++;
+
+	*latlonstrptr = cp;
+
+	return (retval);
+}
+
+/* converts a zone file representation in a string to an RDATA on-the-wire
+ * representation. */
+int
+loc_aton(ascii, binary)
+	const char *ascii;
+	u_char *binary;
+{
+	const char *cp, *maxcp;
+	u_char *bcp;
+
+	u_int32_t latit = 0, longit = 0, alt = 0;
+	u_int32_t lltemp1 = 0, lltemp2 = 0;
+	int altmeters = 0, altfrac = 0, altsign = 1;
+	u_int8_t hp = 0x16;	/* default = 1e6 cm = 10000.00m = 10km */
+	u_int8_t vp = 0x13;	/* default = 1e3 cm = 10.00m */
+	u_int8_t siz = 0x12;	/* default = 1e2 cm = 1.00m */
+	int which1 = 0, which2 = 0;
+
+	cp = ascii;
+	maxcp = cp + strlen(ascii);
+
+	lltemp1 = latlon2ul(&cp, &which1);
+
+	lltemp2 = latlon2ul(&cp, &which2);
+
+	switch (which1 + which2) {
+	case 3:			/* 1 + 2, the only valid combination */
+		if ((which1 == 1) && (which2 == 2)) { /* normal case */
+			latit = lltemp1;
+			longit = lltemp2;
+		} else if ((which1 == 2) && (which2 == 1)) { /* reversed */
+			longit = lltemp1;
+			latit = lltemp2;
+		} else {	/* some kind of brokenness */
+			return (0);
+		}
+		break;
+	default:		/* we didn't get one of each */
+		return (0);
+	}
+
+	/* altitude */
+	if (*cp == '-') {
+		altsign = -1;
+		cp++;
+	}
+
+	if (*cp == '+')
+		cp++;
+
+	while (isdigit((unsigned char)*cp))
+		altmeters = altmeters * 10 + (*cp++ - '0');
+
+	if (*cp == '.') {		/* decimal meters */
+		cp++;
+		if (isdigit((unsigned char)*cp)) {
+			altfrac = (*cp++ - '0') * 10;
+			if (isdigit((unsigned char)*cp)) {
+				altfrac += (*cp++ - '0');
+			}
+		}
+	}
+
+	alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+	while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */
+		cp++;
+
+	while (isspace((unsigned char)*cp) && (cp < maxcp))
+		cp++;
+
+	if (cp >= maxcp)
+		goto defaults;
+
+	siz = precsize_aton(&cp);
+
+	while (!isspace((unsigned char)*cp) && (cp < maxcp))	/* if trailing garbage or m */
+		cp++;
+
+	while (isspace((unsigned char)*cp) && (cp < maxcp))
+		cp++;
+
+	if (cp >= maxcp)
+		goto defaults;
+
+	hp = precsize_aton(&cp);
+
+	while (!isspace((unsigned char)*cp) && (cp < maxcp))	/* if trailing garbage or m */
+		cp++;
+
+	while (isspace((unsigned char)*cp) && (cp < maxcp))
+		cp++;
+
+	if (cp >= maxcp)
+		goto defaults;
+
+	vp = precsize_aton(&cp);
+
+ defaults:
+
+	bcp = binary;
+	*bcp++ = (u_int8_t) 0;	/* version byte */
+	*bcp++ = siz;
+	*bcp++ = hp;
+	*bcp++ = vp;
+	PUTLONG(latit,bcp);
+	PUTLONG(longit,bcp);
+	PUTLONG(alt,bcp);
+
+	return (16);		/* size of RR in octets */
+}
+
+/* takes an on-the-wire LOC RR and formats it in a human readable format. */
+const char *
+loc_ntoa(binary, ascii)
+	const u_char *binary;
+	char *ascii;
+{
+	static const char *error = "?";
+	static char tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+	const u_char *cp = binary;
+
+	int latdeg, latmin, latsec, latsecfrac;
+	int longdeg, longmin, longsec, longsecfrac;
+	char northsouth, eastwest;
+	const char *altsign;
+	int altmeters, altfrac;
+
+	const u_int32_t referencealt = 100000 * 100;
+
+	int32_t latval, longval, altval;
+	u_int32_t templ;
+	u_int8_t sizeval, hpval, vpval, versionval;
+
+	char *sizestr, *hpstr, *vpstr;
+
+	versionval = *cp++;
+
+	if (ascii == NULL)
+		ascii = tmpbuf;
+
+	if (versionval) {
+		(void) sprintf(ascii, "; error: unknown LOC RR version");
+		return (ascii);
+	}
+
+	sizeval = *cp++;
+
+	hpval = *cp++;
+	vpval = *cp++;
+
+	GETLONG(templ, cp);
+	latval = (templ - ((unsigned)1<<31));
+
+	GETLONG(templ, cp);
+	longval = (templ - ((unsigned)1<<31));
+
+	GETLONG(templ, cp);
+	if (templ < referencealt) { /* below WGS 84 spheroid */
+		altval = referencealt - templ;
+		altsign = "-";
+	} else {
+		altval = templ - referencealt;
+		altsign = "";
+	}
+
+	if (latval < 0) {
+		northsouth = 'S';
+		latval = -latval;
+	} else
+		northsouth = 'N';
+
+	latsecfrac = latval % 1000;
+	latval = latval / 1000;
+	latsec = latval % 60;
+	latval = latval / 60;
+	latmin = latval % 60;
+	latval = latval / 60;
+	latdeg = latval;
+
+	if (longval < 0) {
+		eastwest = 'W';
+		longval = -longval;
+	} else
+		eastwest = 'E';
+
+	longsecfrac = longval % 1000;
+	longval = longval / 1000;
+	longsec = longval % 60;
+	longval = longval / 60;
+	longmin = longval % 60;
+	longval = longval / 60;
+	longdeg = longval;
+
+	altfrac = altval % 100;
+	altmeters = (altval / 100);
+
+	sizestr = strdup(precsize_ntoa((u_int32_t)sizeval));
+	hpstr = strdup(precsize_ntoa((u_int32_t)hpval));
+	vpstr = strdup(precsize_ntoa((u_int32_t)vpval));
+
+	sprintf(ascii,
+	    "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm",
+		latdeg, latmin, latsec, latsecfrac, northsouth,
+		longdeg, longmin, longsec, longsecfrac, eastwest,
+		altsign, altmeters, altfrac,
+		(sizestr != NULL) ? sizestr : error,
+		(hpstr != NULL) ? hpstr : error,
+		(vpstr != NULL) ? vpstr : error);
+
+	if (sizestr != NULL)
+		free(sizestr);
+	if (hpstr != NULL)
+		free(hpstr);
+	if (vpstr != NULL)
+		free(vpstr);
+
+	return (ascii);
+}
+
+
+/* Return the number of DNS hierarchy levels in the name. */
+int
+dn_count_labels(const char *name) {
+	int i, len, count;
+
+	len = strlen(name);
+	for (i = 0, count = 0; i < len; i++) {
+		/* XXX need to check for \. or use named's nlabels(). */
+		if (name[i] == '.')
+			count++;
+	}
+
+	/* don't count initial wildcard */
+	if (name[0] == '*')
+		if (count)
+			count--;
+
+	/* don't count the null label for root. */
+	/* if terminating '.' not found, must adjust */
+	/* count to include last label */
+	if (len > 0 && name[len-1] != '.')
+		count++;
+	return (count);
+}
+
+
+/*
+ * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
+ * SIG records are required to be printed like this, by the Secure DNS RFC.
+ */
+char *
+p_secstodate (u_long secs) {
+	/* XXX nonreentrant */
+	static char output[15];		/* YYYYMMDDHHMMSS and null */
+	time_t myclock = secs;
+	struct tm *mytime;
+#ifdef HAVE_TIME_R
+	struct tm res;
+
+	mytime = gmtime_r(&myclock, &res);
+#else
+	mytime = gmtime(&myclock);
+#endif
+	mytime->tm_year += 1900;
+	mytime->tm_mon += 1;
+	sprintf(output, "%04d%02d%02d%02d%02d%02d",
+		mytime->tm_year, mytime->tm_mon, mytime->tm_mday,
+		mytime->tm_hour, mytime->tm_min, mytime->tm_sec);
+	return (output);
+}
+
+u_int16_t
+res_nametoclass(const char *buf, int *successp) {
+	unsigned long result;
+	char *endptr;
+	int success;
+
+	result = sym_ston(__p_class_syms, buf, &success);
+	if (success)
+		goto done;
+
+	if (strncasecmp(buf, "CLASS", 5) != 0 ||
+	    !isdigit((unsigned char)buf[5]))
+		goto done;
+	errno = 0;
+	result = strtoul(buf + 5, &endptr, 10);
+	if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
+		success = 1;
+ done:
+	if (successp)
+		*successp = success;
+	return (u_int16_t)(result);
+}
+
+u_int16_t
+res_nametotype(const char *buf, int *successp) {
+	unsigned long result;
+	char *endptr;
+	int success;
+
+	result = sym_ston(__p_type_syms, buf, &success);
+	if (success)
+		goto done;
+
+	if (strncasecmp(buf, "type", 4) != 0 ||
+	    !isdigit((unsigned char)buf[4]))
+		goto done;
+	errno = 0;
+	result = strtoul(buf + 4, &endptr, 10);
+	if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
+		success = 1;
+ done:
+	if (successp)
+		*successp = success;
+	return (u_int16_t)(result);
+}
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/res_debug.h
@@ -0,0 +1,46 @@
+/*	$NetBSD: res_debug.h,v 1.1.1.1 2004/05/20 17:18:55 christos Exp $	*/
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#ifndef _RES_DEBUG_H_
+#define _RES_DEBUG_H_
+
+#ifndef DEBUG
+#   define Dprint(cond, args) /*empty*/
+#   define DprintQ(cond, args, query, size) /*empty*/
+#   define Aerror(statp, file, string, error, address) /*empty*/
+#   define Perror(statp, file, string, error) /*empty*/
+#else
+#   define Dprint(cond, args) if (cond) {fprintf args;} else {}
+#   define DprintQ(cond, args, query, size) if (cond) {\
+			fprintf args;\
+			res_pquery(statp, query, size, stdout);\
+		} else {}
+#endif
+
+#endif /* _RES_DEBUG_H_ */ 
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/res_init.c
@@ -0,0 +1,914 @@
+/*	$NetBSD: res_init.c,v 1.8 2006/03/19 03:10:08 christos Exp $	*/
+
+/*
+ * Copyright (c) 1985, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ * 	This product includes software developed by the University of
+ * 	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#define ANDROID_CHANGES 1
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#ifdef notdef
+static const char sccsid[] = "@(#)res_init.c	8.1 (Berkeley) 6/7/93";
+static const char rcsid[] = "Id: res_init.c,v 1.9.2.5.4.2 2004/03/16 12:34:18 marka Exp";
+#else
+__RCSID("$NetBSD: res_init.c,v 1.8 2006/03/19 03:10:08 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "arpa_nameser.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+
+#ifdef ANDROID_CHANGES
+#include <sys/system_properties.h>
+#endif /* ANDROID_CHANGES */
+
+#ifndef MIN
+#define	MIN(x,y)	((x)<(y)?(x):(y))
+#endif
+
+/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
+#ifdef ANDROID_CHANGES
+#include "resolv_private.h"
+#define MAX_DNS_PROPERTIES 8
+#define DNS_PROP_NAME_PREFIX "net.dns"
+#define DNS_CHANGE_PROP_NAME "net.dnschange"
+#define DNS_SEARCH_PROP_NAME "net.dns.search"
+const prop_info *dns_change_prop;
+int dns_last_change_counter;
+static int _get_dns_change_count();
+#else
+#include <resolv.h>
+#endif
+
+#include "res_private.h"
+
+/* Options.  Should all be left alone. */
+#ifndef DEBUG
+#define DEBUG
+#endif
+
+static void res_setoptions __P((res_state, const char *, const char *));
+
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
+static u_int32_t net_mask __P((struct in_addr));
+
+#if !defined(isascii)	/* XXX - could be a function */
+# define isascii(c) (!(c & 0200))
+#endif
+
+/*
+ * Resolver state default settings.
+ */
+
+/*
+ * Set up default settings.  If the configuration file exist, the values
+ * there will have precedence.  Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
+ * rather than INADDR_ANY ("0.0.0.0") as the default name server address
+ * since it was noted that INADDR_ANY actually meant ``the first interface
+ * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
+ * it had to be "up" in order for you to reach your own name server.  It
+ * was later decided that since the recommended practice is to always
+ * install local static routes through 127.0.0.1 for all your network
+ * interfaces, that we could solve this problem without a code change.
+ *
+ * The configuration file should always be used, since it is the only way
+ * to specify a default domain.  If you are running a server on your local
+ * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
+ * in the configuration file.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+int
+res_ninit(res_state statp) {
+	extern int __res_vinit(res_state, int);
+
+	return (__res_vinit(statp, 0));
+}
+
+#ifdef ANDROID_CHANGES
+int load_domain_search_list(res_state statp) {
+	char propvalue[PROP_VALUE_MAX];
+	register char *cp, **pp;
+
+	if(__system_property_get(DNS_SEARCH_PROP_NAME, propvalue) >= 1) {
+		strlcpy(statp->defdname, propvalue, sizeof(statp->defdname));
+		if ((cp = strchr(statp->defdname, '\n')) != NULL)
+			*cp = '\0';
+		cp = statp->defdname;
+		pp = statp->dnsrch;
+		while ( pp < statp->dnsrch + MAXDNSRCH ) {
+			while (*cp == ' ' || *cp == '\t') /* skip leading white space */
+				cp++;
+			if (*cp == '\0')  /* stop if nothing more */
+				break;
+			*pp++ = cp;  /* record this search domain */
+			while (*cp) { /* zero-terminate it */
+				if (*cp == ' ' || *cp == '\t') {
+					*cp++ = '\0';
+					break;
+				}
+				cp++;
+			}
+		}
+		*pp = NULL; /* statp->dnsrch has MAXDNSRCH+1 items */
+		if (pp > statp->dnsrch)
+			return 1;
+	}
+	statp->defdname[0] = '\0';  /* no default domain name on Android */
+	statp->dnsrch[0] = NULL;
+	return 0;
+}
+#endif
+
+/* This function has to be reachable by res_data.c but not publicly. */
+int
+__res_vinit(res_state statp, int preinit) {
+	register FILE *fp;
+	register char *cp, **pp;
+	register int n;
+	char buf[BUFSIZ];
+	int nserv = 0;    /* number of nameserver records read from file */
+	int haveenv = 0;
+	int havesearch = 0;
+	int nsort = 0;
+	char *net;
+	int dots;
+	union res_sockaddr_union u[2];
+#ifdef ANDROID_CHANGES
+        pid_t mypid = getpid();
+        int use_proc_props = 0;
+        int found_prop;
+	char dnsProperty[PROP_VALUE_MAX];
+#endif
+
+	if (!preinit) {
+		statp->retrans = RES_TIMEOUT;
+		statp->retry = RES_DFLRETRY;
+		statp->options = RES_DEFAULT;
+		statp->id = res_randomid();
+	}
+
+  if ((statp->options & RES_INIT) != 0U)
+       res_ndestroy(statp);
+
+	memset(u, 0, sizeof(u));
+#ifdef USELOOPBACK
+	u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
+	u[nserv].sin.sin_addr.s_addr = INADDR_ANY;
+#endif
+	u[nserv].sin.sin_family = AF_INET;
+	u[nserv].sin.sin_port = htons(NAMESERVER_PORT);
+#ifdef HAVE_SA_LEN
+	u[nserv].sin.sin_len = sizeof(struct sockaddr_in);
+#endif
+	nserv++;
+#ifdef HAS_INET6_STRUCTS
+#ifdef USELOOPBACK
+	u[nserv].sin6.sin6_addr = in6addr_loopback;
+#else
+	u[nserv].sin6.sin6_addr = in6addr_any;
+#endif
+	u[nserv].sin6.sin6_family = AF_INET6;
+	u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT);
+#ifdef HAVE_SA_LEN
+	u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+	nserv++;
+#endif
+	statp->nscount = 0;
+	statp->ndots = 1;
+	statp->pfcode = 0;
+	statp->_vcsock = -1;
+	statp->_flags = 0;
+	statp->qhook = NULL;
+	statp->rhook = NULL;
+	statp->_u._ext.nscount = 0;
+	statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext));
+	if (statp->_u._ext.ext != NULL) {
+	        memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
+		statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr;
+		strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa");
+		strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int");
+	}
+	statp->nsort = 0;
+	res_setservers(statp, u, nserv);
+
+#if 0 /* IGNORE THE ENVIRONMENT */
+	/* Allow user to override the local domain definition */
+	if ((cp = getenv("LOCALDOMAIN")) != NULL) {
+		(void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+		statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+		haveenv++;
+
+		/*
+		 * Set search list to be blank-separated strings
+		 * from rest of env value.  Permits users of LOCALDOMAIN
+		 * to still have a search list, and anyone to set the
+		 * one that they want to use as an individual (even more
+		 * important now that the rfc1535 stuff restricts searches)
+		 */
+		cp = statp->defdname;
+		pp = statp->dnsrch;
+		*pp++ = cp;
+		for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
+			if (*cp == '\n')	/* silly backwards compat */
+				break;
+			else if (*cp == ' ' || *cp == '\t') {
+				*cp = 0;
+				n = 1;
+			} else if (n) {
+				*pp++ = cp;
+				n = 0;
+				havesearch = 1;
+			}
+		}
+		/* null terminate last domain if there are excess */
+		while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
+			cp++;
+		*cp = '\0';
+		*pp++ = 0;
+	}
+	if (nserv > 0)
+		statp->nscount = nserv;
+#endif
+#ifdef ANDROID_CHANGES /* READ FROM SYSTEM PROPERTIES */
+	dns_last_change_counter = _get_dns_change_count();
+
+	nserv = 0;
+	for(n = 1; n <= MAX_DNS_PROPERTIES && nserv < MAXNS; n++) {
+		char propname[PROP_NAME_MAX];
+		char propvalue[PROP_VALUE_MAX];
+
+		struct addrinfo hints, *ai;
+		char sbuf[NI_MAXSERV];
+		const size_t minsiz = sizeof(statp->_u._ext.ext->nsaddrs[0]);
+
+		/*
+		 * Check first for process-specific properties, and if those don't
+		 * exist, try the generic properties.
+		 */
+		found_prop = 0;
+		if (n == 1 || use_proc_props) {
+			snprintf(propname, sizeof(propname), "%s%d.%d", DNS_PROP_NAME_PREFIX, n, mypid);
+			if(__system_property_get(propname, propvalue) < 1) {
+				if (use_proc_props) {
+					break;
+				}
+			} else {
+				found_prop = 1;
+				use_proc_props = 1;
+			}
+		}
+		if (!found_prop) {
+			snprintf(propname, sizeof(propname), "%s%d", DNS_PROP_NAME_PREFIX, n);
+			if(__system_property_get(propname, propvalue) < 1) {
+				break;
+			}
+		}
+
+		cp = propvalue;
+
+		while (*cp == ' ' || *cp == '\t')
+			cp++;
+		cp[strcspn(cp, ";# \t\n")] = '\0';
+		if ((*cp != '\0') && (*cp != '\n')) {
+			memset(&hints, 0, sizeof(hints));
+			hints.ai_family = PF_UNSPEC;
+			hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
+			hints.ai_flags = AI_NUMERICHOST;
+			sprintf(sbuf, "%u", NAMESERVER_PORT);
+			if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
+			    (size_t)ai->ai_addrlen <= minsiz) {
+				if (statp->_u._ext.ext != NULL) {
+					memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+					       ai->ai_addr, ai->ai_addrlen);
+				}
+				if ((size_t)ai->ai_addrlen <=
+				    sizeof(statp->nsaddr_list[nserv])) {
+					memcpy(&statp->nsaddr_list[nserv],
+					       ai->ai_addr, ai->ai_addrlen);
+				} else {
+					statp->nsaddr_list[nserv].sin_family = 0;
+				}
+				freeaddrinfo(ai);
+				nserv++;
+			}
+		}
+	}
+
+	/* Add the domain search list */
+	havesearch = load_domain_search_list(statp);
+#else /* !ANDROID_CHANGES - IGNORE resolv.conf in Android */
+#define	MATCH(line, name) \
+	(!strncmp(line, name, sizeof(name) - 1) && \
+	(line[sizeof(name) - 1] == ' ' || \
+	 line[sizeof(name) - 1] == '\t'))
+
+	nserv = 0;
+	if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+	    /* read the config file */
+	    while (fgets(buf, sizeof(buf), fp) != NULL) {
+		/* skip comments */
+		if (*buf == ';' || *buf == '#')
+			continue;
+		/* read default domain name */
+		if (MATCH(buf, "domain")) {
+		    if (haveenv)	/* skip if have from environ */
+			    continue;
+		    cp = buf + sizeof("domain") - 1;
+		    while (*cp == ' ' || *cp == '\t')
+			    cp++;
+		    if ((*cp == '\0') || (*cp == '\n'))
+			    continue;
+		    strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+		    statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+		    if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
+			    *cp = '\0';
+		    havesearch = 0;
+		    continue;
+		}
+		/* set search list */
+		if (MATCH(buf, "search")) {
+		    if (haveenv)	/* skip if have from environ */
+			    continue;
+		    cp = buf + sizeof("search") - 1;
+		    while (*cp == ' ' || *cp == '\t')
+			    cp++;
+		    if ((*cp == '\0') || (*cp == '\n'))
+			    continue;
+		    strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+		    statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+		    if ((cp = strchr(statp->defdname, '\n')) != NULL)
+			    *cp = '\0';
+		    /*
+		     * Set search list to be blank-separated strings
+		     * on rest of line.
+		     */
+		    cp = statp->defdname;
+		    pp = statp->dnsrch;
+		    *pp++ = cp;
+		    for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
+			    if (*cp == ' ' || *cp == '\t') {
+				    *cp = 0;
+				    n = 1;
+			    } else if (n) {
+				    *pp++ = cp;
+				    n = 0;
+			    }
+		    }
+		    /* null terminate last domain if there are excess */
+		    while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+			    cp++;
+		    *cp = '\0';
+		    *pp++ = 0;
+		    havesearch = 1;
+		    continue;
+		}
+		/* read nameservers to query */
+		if (MATCH(buf, "nameserver") && nserv < MAXNS) {
+		    struct addrinfo hints, *ai;
+		    char sbuf[NI_MAXSERV];
+		    const size_t minsiz =
+		        sizeof(statp->_u._ext.ext->nsaddrs[0]);
+
+		    cp = buf + sizeof("nameserver") - 1;
+		    while (*cp == ' ' || *cp == '\t')
+			cp++;
+		    cp[strcspn(cp, ";# \t\n")] = '\0';
+		    if ((*cp != '\0') && (*cp != '\n')) {
+			memset(&hints, 0, sizeof(hints));
+			hints.ai_family = PF_UNSPEC;
+			hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
+			hints.ai_flags = AI_NUMERICHOST;
+			sprintf(sbuf, "%u", NAMESERVER_PORT);
+			if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
+			    ai->ai_addrlen <= minsiz) {
+			    if (statp->_u._ext.ext != NULL) {
+				memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+				    ai->ai_addr, ai->ai_addrlen);
+			    }
+			    if (ai->ai_addrlen <=
+			        sizeof(statp->nsaddr_list[nserv])) {
+				memcpy(&statp->nsaddr_list[nserv],
+				    ai->ai_addr, ai->ai_addrlen);
+			    } else
+				statp->nsaddr_list[nserv].sin_family = 0;
+			    freeaddrinfo(ai);
+			    nserv++;
+			}
+		    }
+		    continue;
+		}
+		if (MATCH(buf, "sortlist")) {
+		    struct in_addr a;
+
+		    cp = buf + sizeof("sortlist") - 1;
+		    while (nsort < MAXRESOLVSORT) {
+			while (*cp == ' ' || *cp == '\t')
+			    cp++;
+			if (*cp == '\0' || *cp == '\n' || *cp == ';')
+			    break;
+			net = cp;
+			while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
+			       isascii(*cp) && !isspace((unsigned char)*cp))
+				cp++;
+			n = *cp;
+			*cp = 0;
+			if (inet_aton(net, &a)) {
+			    statp->sort_list[nsort].addr = a;
+			    if (ISSORTMASK(n)) {
+				*cp++ = n;
+				net = cp;
+				while (*cp && *cp != ';' &&
+					isascii(*cp) &&
+					!isspace((unsigned char)*cp))
+				    cp++;
+				n = *cp;
+				*cp = 0;
+				if (inet_aton(net, &a)) {
+				    statp->sort_list[nsort].mask = a.s_addr;
+				} else {
+				    statp->sort_list[nsort].mask =
+					net_mask(statp->sort_list[nsort].addr);
+				}
+			    } else {
+				statp->sort_list[nsort].mask =
+				    net_mask(statp->sort_list[nsort].addr);
+			    }
+			    nsort++;
+			}
+			*cp = n;
+		    }
+		    continue;
+		}
+		if (MATCH(buf, "options")) {
+		    res_setoptions(statp, buf + sizeof("options") - 1, "conf");
+		    continue;
+		}
+	    }
+	    if (nserv > 0)
+		statp->nscount = nserv;
+	    statp->nsort = nsort;
+	    (void) fclose(fp);
+	}
+#endif /* !ANDROID_CHANGES */
+/*
+ * Last chance to get a nameserver.  This should not normally
+ * be necessary
+ */
+#ifdef NO_RESOLV_CONF
+	if(nserv == 0)
+		nserv = get_nameservers(statp);
+#endif
+
+	if (statp->defdname[0] == 0 &&
+	    gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
+	    (cp = strchr(buf, '.')) != NULL)
+		strcpy(statp->defdname, cp + 1);
+
+	/* find components of local domain that might be searched */
+	if (havesearch == 0) {
+		pp = statp->dnsrch;
+		*pp++ = statp->defdname;
+		*pp = NULL;
+
+		dots = 0;
+		for (cp = statp->defdname; *cp; cp++)
+			dots += (*cp == '.');
+
+		cp = statp->defdname;
+		while (pp < statp->dnsrch + MAXDFLSRCH) {
+			if (dots < LOCALDOMAINPARTS)
+				break;
+			cp = strchr(cp, '.') + 1;    /* we know there is one */
+			*pp++ = cp;
+			dots--;
+		}
+		*pp = NULL;
+#ifdef DEBUG
+		if (statp->options & RES_DEBUG) {
+			printf(";; res_init()... default dnsrch list:\n");
+			for (pp = statp->dnsrch; *pp; pp++)
+				printf(";;\t%s\n", *pp);
+			printf(";;\t..END..\n");
+		}
+#endif
+	}
+
+	if ((cp = getenv("RES_OPTIONS")) != NULL)
+		res_setoptions(statp, cp, "env");
+	if (nserv > 0) {
+		statp->nscount = nserv;
+		statp->options |= RES_INIT;
+	}
+	return (0);
+}
+
+static void
+res_setoptions(res_state statp, const char *options, const char *source)
+{
+	const char *cp = options;
+	int i;
+	struct __res_state_ext *ext = statp->_u._ext.ext;
+
+#ifdef DEBUG
+	if (statp->options & RES_DEBUG)
+		printf(";; res_setoptions(\"%s\", \"%s\")...\n",
+		       options, source);
+#endif
+	while (*cp) {
+		/* skip leading and inner runs of spaces */
+		while (*cp == ' ' || *cp == '\t')
+			cp++;
+		/* search for and process individual options */
+		if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
+			i = atoi(cp + sizeof("ndots:") - 1);
+			if (i <= RES_MAXNDOTS)
+				statp->ndots = i;
+			else
+				statp->ndots = RES_MAXNDOTS;
+#ifdef DEBUG
+			if (statp->options & RES_DEBUG)
+				printf(";;\tndots=%d\n", statp->ndots);
+#endif
+		} else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
+			i = atoi(cp + sizeof("timeout:") - 1);
+			if (i <= RES_MAXRETRANS)
+				statp->retrans = i;
+			else
+				statp->retrans = RES_MAXRETRANS;
+#ifdef DEBUG
+			if (statp->options & RES_DEBUG)
+				printf(";;\ttimeout=%d\n", statp->retrans);
+#endif
+		} else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
+			i = atoi(cp + sizeof("attempts:") - 1);
+			if (i <= RES_MAXRETRY)
+				statp->retry = i;
+			else
+				statp->retry = RES_MAXRETRY;
+#ifdef DEBUG
+			if (statp->options & RES_DEBUG)
+				printf(";;\tattempts=%d\n", statp->retry);
+#endif
+		} else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
+#ifdef DEBUG
+			if (!(statp->options & RES_DEBUG)) {
+				printf(";; res_setoptions(\"%s\", \"%s\")..\n",
+				       options, source);
+				statp->options |= RES_DEBUG;
+			}
+			printf(";;\tdebug\n");
+#endif
+		} else if (!strncmp(cp, "no_tld_query",
+				    sizeof("no_tld_query") - 1) ||
+			   !strncmp(cp, "no-tld-query",
+				    sizeof("no-tld-query") - 1)) {
+			statp->options |= RES_NOTLDQUERY;
+		} else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+			statp->options |= RES_USE_INET6;
+		} else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
+			statp->options |= RES_ROTATE;
+		} else if (!strncmp(cp, "no-check-names",
+				    sizeof("no-check-names") - 1)) {
+			statp->options |= RES_NOCHECKNAME;
+		}
+#ifdef RES_USE_EDNS0
+		else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
+			statp->options |= RES_USE_EDNS0;
+		}
+#endif
+		else if (!strncmp(cp, "dname", sizeof("dname") - 1)) {
+			statp->options |= RES_USE_DNAME;
+		}
+		else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) {
+			if (ext == NULL)
+				goto skip;
+			cp += sizeof("nibble:") - 1;
+			i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1);
+			strncpy(ext->nsuffix, cp, (size_t)i);
+			ext->nsuffix[i] = '\0';
+		}
+		else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) {
+			if (ext == NULL)
+				goto skip;
+			cp += sizeof("nibble2:") - 1;
+			i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1);
+			strncpy(ext->nsuffix2, cp, (size_t)i);
+			ext->nsuffix2[i] = '\0';
+		}
+		else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) {
+			cp += sizeof("v6revmode:") - 1;
+			/* "nibble" and "bitstring" used to be valid */
+			if (!strncmp(cp, "single", sizeof("single") - 1)) {
+				statp->options |= RES_NO_NIBBLE2;
+			} else if (!strncmp(cp, "both", sizeof("both") - 1)) {
+				statp->options &=
+					 ~RES_NO_NIBBLE2;
+			}
+		}
+		else {
+			/* XXX - print a warning here? */
+		}
+   skip:
+		/* skip to next run of spaces */
+		while (*cp && *cp != ' ' && *cp != '\t')
+			cp++;
+	}
+}
+
+/* XXX - should really support CIDR which means explicit masks always. */
+static u_int32_t
+net_mask(in)		/* XXX - should really use system's version of this */
+	struct in_addr in;
+{
+	register u_int32_t i = ntohl(in.s_addr);
+
+	if (IN_CLASSA(i))
+		return (htonl(IN_CLASSA_NET));
+	else if (IN_CLASSB(i))
+		return (htonl(IN_CLASSB_NET));
+	return (htonl(IN_CLASSC_NET));
+}
+
+u_int
+res_randomid(void) {
+	struct timeval now;
+
+	gettimeofday(&now, NULL);
+	return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
+}
+
+/*
+ * This routine is for closing the socket if a virtual circuit is used and
+ * the program wants to close it.  This provides support for endhostent()
+ * which expects to close the socket.
+ *
+ * This routine is not expected to be user visible.
+ */
+void
+res_nclose(res_state statp) {
+	int ns;
+
+	if (statp->_vcsock >= 0) {
+		(void) close(statp->_vcsock);
+		statp->_vcsock = -1;
+		statp->_flags &= ~(RES_F_VC | RES_F_CONN);
+	}
+	for (ns = 0; ns < statp->_u._ext.nscount; ns++) {
+		if (statp->_u._ext.nssocks[ns] != -1) {
+			(void) close(statp->_u._ext.nssocks[ns]);
+			statp->_u._ext.nssocks[ns] = -1;
+		}
+	}
+}
+
+void
+res_ndestroy(res_state statp) {
+	res_nclose(statp);
+	if (statp->_u._ext.ext != NULL)
+		free(statp->_u._ext.ext);
+	statp->options &= ~RES_INIT;
+	statp->_u._ext.ext = NULL;
+}
+
+const char *
+res_get_nibblesuffix(res_state statp) {
+	if (statp->_u._ext.ext)
+		return (statp->_u._ext.ext->nsuffix);
+	return ("ip6.arpa");
+}
+
+const char *
+res_get_nibblesuffix2(res_state statp) {
+	if (statp->_u._ext.ext)
+		return (statp->_u._ext.ext->nsuffix2);
+	return ("ip6.int");
+}
+
+void
+res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
+	int i, nserv;
+	size_t size;
+
+	/* close open servers */
+	res_nclose(statp);
+
+	/* cause rtt times to be forgotten */
+	statp->_u._ext.nscount = 0;
+
+	nserv = 0;
+	for (i = 0; i < cnt && nserv < MAXNS; i++) {
+		switch (set->sin.sin_family) {
+		case AF_INET:
+			size = sizeof(set->sin);
+			if (statp->_u._ext.ext)
+				memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+					&set->sin, size);
+			if (size <= sizeof(statp->nsaddr_list[nserv]))
+				memcpy(&statp->nsaddr_list[nserv],
+					&set->sin, size);
+#ifdef notdef
+			else
+				statp->nsaddr_list[nserv].sin_family = 0;
+#endif
+			nserv++;
+			break;
+
+#ifdef HAS_INET6_STRUCTS
+		case AF_INET6:
+			size = sizeof(set->sin6);
+			if (statp->_u._ext.ext)
+				memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+					&set->sin6, size);
+			if (size <= sizeof(statp->nsaddr_list[nserv]))
+				memcpy(&statp->nsaddr_list[nserv],
+					&set->sin6, size);
+			else
+				statp->nsaddr_list[nserv].sin_family = 0;
+			nserv++;
+			break;
+#endif
+
+		default:
+			break;
+		}
+		set++;
+	}
+	statp->nscount = nserv;
+
+}
+
+int
+res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
+	int i;
+	size_t size;
+	u_int16_t family;
+
+	for (i = 0; i < statp->nscount && i < cnt; i++) {
+		if (statp->_u._ext.ext)
+			family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family;
+		else
+			family = statp->nsaddr_list[i].sin_family;
+
+		switch (family) {
+		case AF_INET:
+			size = sizeof(set->sin);
+			if (statp->_u._ext.ext)
+				memcpy(&set->sin,
+				       &statp->_u._ext.ext->nsaddrs[i],
+				       size);
+			else
+				memcpy(&set->sin, &statp->nsaddr_list[i],
+				       size);
+			break;
+
+#ifdef HAS_INET6_STRUCTS
+		case AF_INET6:
+			size = sizeof(set->sin6);
+			if (statp->_u._ext.ext)
+				memcpy(&set->sin6,
+				       &statp->_u._ext.ext->nsaddrs[i],
+				       size);
+			else
+				memcpy(&set->sin6, &statp->nsaddr_list[i],
+				       size);
+			break;
+#endif
+
+		default:
+			set->sin.sin_family = 0;
+			break;
+		}
+		set++;
+	}
+	return (statp->nscount);
+}
+
+#ifdef ANDROID_CHANGES
+static int _get_dns_change_count()
+{
+	if (dns_change_prop == NULL) {
+		dns_change_prop = __system_property_find(DNS_CHANGE_PROP_NAME);
+	}
+	if (dns_change_prop != NULL) {
+		char propvalue[PROP_VALUE_MAX];
+		if (__system_property_read(dns_change_prop, NULL, propvalue) >= 1) {
+			return atoi(propvalue);
+		}
+	}
+	return -1;
+}
+
+int res_get_dns_changed()
+{
+	int change_count;
+
+	change_count = _get_dns_change_count();
+	if (change_count != dns_last_change_counter) {
+		if (change_count != -1) {
+			dns_last_change_counter = change_count;
+		}
+		return 1;
+	} else {
+		return 0;
+	}
+}
+#endif /* ANDROID_CHANGES */
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/res_mkquery.c
@@ -0,0 +1,288 @@
+/*	$NetBSD: res_mkquery.c,v 1.6 2006/01/24 17:40:32 christos Exp $	*/
+
+/*
+ * Copyright (c) 2008  Android Open Source Project (query id randomization)
+ * Copyright (c) 1985, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ * 	This product includes software developed by the University of
+ * 	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#define ANDROID_CHANGES 1
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#ifdef notdef
+static const char sccsid[] = "@(#)res_mkquery.c	8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "Id: res_mkquery.c,v 1.1.2.2.4.2 2004/03/16 12:34:18 marka Exp";
+#else
+__RCSID("$NetBSD: res_mkquery.c,v 1.6 2006/01/24 17:40:32 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include "arpa_nameser.h"
+#include <netdb.h>
+#ifdef ANDROID_CHANGES
+#include "resolv_private.h"
+#else
+#include <resolv.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+
+/* Options.  Leave them on. */
+#ifndef DEBUG
+#define DEBUG
+#endif
+
+#ifndef lint
+#define UNUSED(a)	(void)&a
+#else
+#define UNUSED(a)	a = a
+#endif
+
+extern const char *_res_opcodes[];
+
+/*
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+int
+res_nmkquery(res_state statp,
+	     int op,			/* opcode of query */
+	     const char *dname,		/* domain name */
+	     int class, int type,	/* class and type of query */
+	     const u_char *data,	/* resource record data */
+	     int datalen,		/* length of data */
+	     const u_char *newrr_in,	/* new rr for modify or append */
+	     u_char *buf,		/* buffer to put query */
+	     int buflen)		/* size of buffer */
+{
+	register HEADER *hp;
+	register u_char *cp, *ep;
+	register int n;
+	u_char *dnptrs[20], **dpp, **lastdnptr;
+
+	UNUSED(newrr_in);
+
+#ifdef DEBUG
+	if (statp->options & RES_DEBUG)
+		printf(";; res_nmkquery(%s, %s, %s, %s)\n",
+		       _res_opcodes[op], dname, p_class(class), p_type(type));
+#endif
+	/*
+	 * Initialize header fields.
+	 */
+	if ((buf == NULL) || (buflen < HFIXEDSZ))
+		return (-1);
+	memset(buf, 0, HFIXEDSZ);
+	hp = (HEADER *)(void *)buf;
+	hp->id = htons(res_randomid());
+	hp->opcode = op;
+	hp->rd = (statp->options & RES_RECURSE) != 0U;
+	hp->rcode = NOERROR;
+	cp = buf + HFIXEDSZ;
+	ep = buf + buflen;
+	dpp = dnptrs;
+	*dpp++ = buf;
+	*dpp++ = NULL;
+	lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+	/*
+	 * perform opcode specific processing
+	 */
+	switch (op) {
+	case QUERY:	/*FALLTHROUGH*/
+	case NS_NOTIFY_OP:
+		if (ep - cp < QFIXEDSZ)
+			return (-1);
+		if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
+		    lastdnptr)) < 0)
+			return (-1);
+		cp += n;
+		ns_put16(type, cp);
+		cp += INT16SZ;
+		ns_put16(class, cp);
+		cp += INT16SZ;
+		hp->qdcount = htons(1);
+		if (op == QUERY || data == NULL)
+			break;
+		/*
+		 * Make an additional record for completion domain.
+		 */
+		if ((ep - cp) < RRFIXEDSZ)
+			return (-1);
+		n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ,
+			    dnptrs, lastdnptr);
+		if (n < 0)
+			return (-1);
+		cp += n;
+		ns_put16(T_NULL, cp);
+		cp += INT16SZ;
+		ns_put16(class, cp);
+		cp += INT16SZ;
+		ns_put32(0, cp);
+		cp += INT32SZ;
+		ns_put16(0, cp);
+		cp += INT16SZ;
+		hp->arcount = htons(1);
+		break;
+
+	case IQUERY:
+		/*
+		 * Initialize answer section
+		 */
+		if (ep - cp < 1 + RRFIXEDSZ + datalen)
+			return (-1);
+		*cp++ = '\0';	/* no domain name */
+		ns_put16(type, cp);
+		cp += INT16SZ;
+		ns_put16(class, cp);
+		cp += INT16SZ;
+		ns_put32(0, cp);
+		cp += INT32SZ;
+		ns_put16(datalen, cp);
+		cp += INT16SZ;
+		if (datalen) {
+			memcpy(cp, data, (size_t)datalen);
+			cp += datalen;
+		}
+		hp->ancount = htons(1);
+		break;
+
+	default:
+		return (-1);
+	}
+	return (cp - buf);
+}
+
+#ifdef RES_USE_EDNS0
+/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
+#ifndef T_OPT
+#define T_OPT	41
+#endif
+
+int
+res_nopt(res_state statp,
+	 int n0,		/* current offset in buffer */
+	 u_char *buf,		/* buffer to put query */
+	 int buflen,		/* size of buffer */
+	 int anslen)		/* UDP answer buffer size */
+{
+	register HEADER *hp;
+	register u_char *cp, *ep;
+	u_int16_t flags = 0;
+
+#ifdef DEBUG
+	if ((statp->options & RES_DEBUG) != 0U)
+		printf(";; res_nopt()\n");
+#endif
+
+	hp = (HEADER *)(void *)buf;
+	cp = buf + n0;
+	ep = buf + buflen;
+
+	if ((ep - cp) < 1 + RRFIXEDSZ)
+		return (-1);
+
+	*cp++ = 0;	/* "." */
+
+	ns_put16(T_OPT, cp);	/* TYPE */
+	cp += INT16SZ;
+	ns_put16(anslen & 0xffff, cp);	/* CLASS = UDP payload size */
+	cp += INT16SZ;
+	*cp++ = NOERROR;	/* extended RCODE */
+	*cp++ = 0;		/* EDNS version */
+	if (statp->options & RES_USE_DNSSEC) {
+#ifdef DEBUG
+		if (statp->options & RES_DEBUG)
+			printf(";; res_opt()... ENDS0 DNSSEC\n");
+#endif
+		flags |= NS_OPT_DNSSEC_OK;
+	}
+	ns_put16(flags, cp);
+	cp += INT16SZ;
+	ns_put16(0, cp);	/* RDLEN */
+	cp += INT16SZ;
+	hp->arcount = htons(ntohs(hp->arcount) + 1);
+
+	return (cp - buf);
+}
+#endif
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/res_private.h
@@ -0,0 +1,32 @@
+/*	$NetBSD: res_private.h,v 1.1.1.1 2004/05/20 17:18:54 christos Exp $	*/
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#ifndef res_private_h
+#define res_private_h
+
+struct __res_state_ext {
+	union res_sockaddr_union nsaddrs[MAXNS];
+	struct sort_list {
+		int     af;
+		union {
+			struct in_addr  ina;
+			struct in6_addr in6a;
+		} addr, mask;
+	} sort_list[MAXRESOLVSORT];
+	char nsuffix[64];
+	char nsuffix2[64];
+};
+
+extern int
+res_ourserver_p(const res_state statp, const struct sockaddr *sa);
+
+#endif
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/res_send.c
@@ -0,0 +1,1179 @@
+/*	$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $	*/
+
+/*
+ * Copyright 2008  Android Open Source Project (source port randomization)
+ * Copyright (c) 1985, 1989, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ * 	This product includes software developed by the University of
+ * 	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#define ANDROID_CHANGES 1
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#ifdef notdef
+static const char sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp";
+#else
+__RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/* set to 1 to use our small/simple/limited DNS cache */
+#define  USE_RESOLV_CACHE  1
+
+/*
+ * Send query to name server and wait for reply.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include "arpa_nameser.h"
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#ifdef ANDROID_CHANGES
+#include "resolv_private.h"
+#else
+#include <resolv.h>
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "eventlib.h"
+
+#if USE_RESOLV_CACHE
+#  include <resolv_cache.h>
+#endif
+
+#ifndef DE_CONST
+#define DE_CONST(c,v)   v = ((c) ? \
+    strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL)
+#endif
+
+/* Options.  Leave them on. */
+#ifndef DEBUG
+#define DEBUG
+#endif
+#include "res_debug.h"
+#include "res_private.h"
+
+#define EXT(res) ((res)->_u._ext)
+
+static const int highestFD = FD_SETSIZE - 1;
+
+/* Forward. */
+
+static int		get_salen __P((const struct sockaddr *));
+static struct sockaddr * get_nsaddr __P((res_state, size_t));
+static int		send_vc(res_state, const u_char *, int,
+				u_char *, int, int *, int);
+static int		send_dg(res_state, const u_char *, int,
+				u_char *, int, int *, int,
+				int *, int *);
+static void		Aerror(const res_state, FILE *, const char *, int,
+			       const struct sockaddr *, int);
+static void		Perror(const res_state, FILE *, const char *, int);
+static int		sock_eq(struct sockaddr *, struct sockaddr *);
+#ifdef NEED_PSELECT
+static int		pselect(int, void *, void *, void *,
+				struct timespec *,
+				const sigset_t *);
+#endif
+void res_pquery(const res_state, const u_char *, int, FILE *);
+
+
+/* BIONIC-BEGIN: implement source port randomization */
+typedef union {
+    struct sockaddr      sa;
+    struct sockaddr_in   sin;
+    struct sockaddr_in6  sin6;
+} _sockaddr_union;
+
+static int
+random_bind( int  s, int  family )
+{
+    _sockaddr_union  u;
+    int              j;
+    socklen_t        slen;
+
+    /* clear all, this also sets the IP4/6 address to 'any' */
+    memset( &u, 0, sizeof u );
+
+    switch (family) {
+        case AF_INET:
+            u.sin.sin_family = family;
+            slen             = sizeof u.sin;
+            break;
+        case AF_INET6:
+            u.sin6.sin6_family = family;
+            slen               = sizeof u.sin6;
+            break;
+        default:
+            errno = EPROTO;
+            return -1;
+    }
+
+    /* first try to bind to a random source port a few times */
+    for (j = 0; j < 10; j++) {
+        /* find a random port between 1025 .. 65534 */
+        int  port = 1025 + (res_randomid() % (65535-1025));
+        if (family == AF_INET)
+            u.sin.sin_port = htons(port);
+        else
+            u.sin6.sin6_port = htons(port);
+
+        if ( !bind( s, &u.sa, slen ) )
+            return 0;
+    }
+
+    /* nothing after 10 tries, our network table is probably busy */
+    /* let the system decide which port is best */
+    if (family == AF_INET)
+        u.sin.sin_port = 0;
+    else
+        u.sin6.sin6_port = 0;
+
+    return bind( s, &u.sa, slen );
+}
+/* BIONIC-END */
+
+static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+
+/* Public. */
+
+/* int
+ * res_isourserver(ina)
+ *	looks up "ina" in _res.ns_addr_list[]
+ * returns:
+ *	0  : not found
+ *	>0 : found
+ * author:
+ *	paul vixie, 29may94
+ */
+int
+res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
+	const struct sockaddr_in *inp, *srv;
+	const struct sockaddr_in6 *in6p, *srv6;
+	int ns;
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		inp = (const struct sockaddr_in *)(const void *)sa;
+		for (ns = 0;  ns < statp->nscount;  ns++) {
+			srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns);
+			if (srv->sin_family == inp->sin_family &&
+			    srv->sin_port == inp->sin_port &&
+			    (srv->sin_addr.s_addr == INADDR_ANY ||
+			     srv->sin_addr.s_addr == inp->sin_addr.s_addr))
+				return (1);
+		}
+		break;
+	case AF_INET6:
+		if (EXT(statp).ext == NULL)
+			break;
+		in6p = (const struct sockaddr_in6 *)(const void *)sa;
+		for (ns = 0;  ns < statp->nscount;  ns++) {
+			srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns);
+			if (srv6->sin6_family == in6p->sin6_family &&
+			    srv6->sin6_port == in6p->sin6_port &&
+#ifdef HAVE_SIN6_SCOPE_ID
+			    (srv6->sin6_scope_id == 0 ||
+			     srv6->sin6_scope_id == in6p->sin6_scope_id) &&
+#endif
+			    (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
+			     IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
+				return (1);
+		}
+		break;
+	default:
+		break;
+	}
+	return (0);
+}
+
+/* int
+ * res_nameinquery(name, type, class, buf, eom)
+ *	look for (name,type,class) in the query section of packet (buf,eom)
+ * requires:
+ *	buf + HFIXEDSZ <= eom
+ * returns:
+ *	-1 : format error
+ *	0  : not found
+ *	>0 : found
+ * author:
+ *	paul vixie, 29may94
+ */
+int
+res_nameinquery(const char *name, int type, int class,
+		const u_char *buf, const u_char *eom)
+{
+	const u_char *cp = buf + HFIXEDSZ;
+	int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount);
+
+	while (qdcount-- > 0) {
+		char tname[MAXDNAME+1];
+		int n, ttype, tclass;
+
+		n = dn_expand(buf, eom, cp, tname, sizeof tname);
+		if (n < 0)
+			return (-1);
+		cp += n;
+		if (cp + 2 * INT16SZ > eom)
+			return (-1);
+		ttype = ns_get16(cp); cp += INT16SZ;
+		tclass = ns_get16(cp); cp += INT16SZ;
+		if (ttype == type && tclass == class &&
+		    ns_samename(tname, name) == 1)
+			return (1);
+	}
+	return (0);
+}
+
+/* int
+ * res_queriesmatch(buf1, eom1, buf2, eom2)
+ *	is there a 1:1 mapping of (name,type,class)
+ *	in (buf1,eom1) and (buf2,eom2)?
+ * returns:
+ *	-1 : format error
+ *	0  : not a 1:1 mapping
+ *	>0 : is a 1:1 mapping
+ * author:
+ *	paul vixie, 29may94
+ */
+int
+res_queriesmatch(const u_char *buf1, const u_char *eom1,
+		 const u_char *buf2, const u_char *eom2)
+{
+	const u_char *cp = buf1 + HFIXEDSZ;
+	int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount);
+
+	if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
+		return (-1);
+
+	/*
+	 * Only header section present in replies to
+	 * dynamic update packets.
+	 */
+	if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) &&
+	    (((const HEADER *)(const void *)buf2)->opcode == ns_o_update))
+		return (1);
+
+	if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount))
+		return (0);
+	while (qdcount-- > 0) {
+		char tname[MAXDNAME+1];
+		int n, ttype, tclass;
+
+		n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
+		if (n < 0)
+			return (-1);
+		cp += n;
+		if (cp + 2 * INT16SZ > eom1)
+			return (-1);
+		ttype = ns_get16(cp);	cp += INT16SZ;
+		tclass = ns_get16(cp); cp += INT16SZ;
+		if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
+			return (0);
+	}
+	return (1);
+}
+
+
+int
+res_nsend(res_state statp,
+	  const u_char *buf, int buflen, u_char *ans, int anssiz)
+{
+	int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
+	char abuf[NI_MAXHOST];
+#if USE_RESOLV_CACHE
+        struct resolv_cache*  cache;
+        ResolvCacheStatus     cache_status = RESOLV_CACHE_UNSUPPORTED;
+#endif
+
+	if (statp->nscount == 0) {
+		errno = ESRCH;
+		return (-1);
+	}
+	if (anssiz < HFIXEDSZ) {
+		errno = EINVAL;
+		return (-1);
+	}
+	DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
+		(stdout, ";; res_send()\n"), buf, buflen);
+	v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
+	gotsomewhere = 0;
+	terrno = ETIMEDOUT;
+
+#if USE_RESOLV_CACHE
+        cache = __get_res_cache();
+        if (cache != NULL) {
+            int  anslen = 0;
+            cache_status = _resolv_cache_lookup(
+                                cache, buf, buflen,
+                                ans, anssiz, &anslen);
+
+            if (cache_status == RESOLV_CACHE_FOUND) {
+                return anslen;
+            }
+        }
+#endif
+
+	/*
+	 * If the ns_addr_list in the resolver context has changed, then
+	 * invalidate our cached copy and the associated timing data.
+	 */
+	if (EXT(statp).nscount != 0) {
+		int needclose = 0;
+		struct sockaddr_storage peer;
+		socklen_t peerlen;
+
+		if (EXT(statp).nscount != statp->nscount)
+			needclose++;
+		else
+			for (ns = 0; ns < statp->nscount; ns++) {
+				if (statp->nsaddr_list[ns].sin_family &&
+				    !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns],
+					     (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) {
+					needclose++;
+					break;
+				}
+
+				if (EXT(statp).nssocks[ns] == -1)
+					continue;
+				peerlen = sizeof(peer);
+				if (getsockname(EXT(statp).nssocks[ns],
+				    (struct sockaddr *)(void *)&peer, &peerlen) < 0) {
+					needclose++;
+					break;
+				}
+				if (!sock_eq((struct sockaddr *)(void *)&peer,
+				    get_nsaddr(statp, (size_t)ns))) {
+					needclose++;
+					break;
+				}
+			}
+		if (needclose) {
+			res_nclose(statp);
+			EXT(statp).nscount = 0;
+		}
+	}
+
+	/*
+	 * Maybe initialize our private copy of the ns_addr_list.
+	 */
+	if (EXT(statp).nscount == 0) {
+		for (ns = 0; ns < statp->nscount; ns++) {
+			EXT(statp).nstimes[ns] = RES_MAXTIME;
+			EXT(statp).nssocks[ns] = -1;
+			if (!statp->nsaddr_list[ns].sin_family)
+				continue;
+			EXT(statp).ext->nsaddrs[ns].sin =
+				 statp->nsaddr_list[ns];
+		}
+		EXT(statp).nscount = statp->nscount;
+	}
+
+	/*
+	 * Some resolvers want to even out the load on their nameservers.
+	 * Note that RES_BLAST overrides RES_ROTATE.
+	 */
+	if ((statp->options & RES_ROTATE) != 0U &&
+	    (statp->options & RES_BLAST) == 0U) {
+		union res_sockaddr_union inu;
+		struct sockaddr_in ina;
+		int lastns = statp->nscount - 1;
+		int fd;
+		u_int16_t nstime;
+
+		if (EXT(statp).ext != NULL)
+			inu = EXT(statp).ext->nsaddrs[0];
+		ina = statp->nsaddr_list[0];
+		fd = EXT(statp).nssocks[0];
+		nstime = EXT(statp).nstimes[0];
+		for (ns = 0; ns < lastns; ns++) {
+			if (EXT(statp).ext != NULL)
+                                EXT(statp).ext->nsaddrs[ns] =
+					EXT(statp).ext->nsaddrs[ns + 1];
+			statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
+			EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
+			EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
+		}
+		if (EXT(statp).ext != NULL)
+			EXT(statp).ext->nsaddrs[lastns] = inu;
+		statp->nsaddr_list[lastns] = ina;
+		EXT(statp).nssocks[lastns] = fd;
+		EXT(statp).nstimes[lastns] = nstime;
+	}
+
+	/*
+	 * Send request, RETRY times, or until successful.
+	 */
+	for (try = 0; try < statp->retry; try++) {
+	    for (ns = 0; ns < statp->nscount; ns++) {
+		struct sockaddr *nsap;
+		int nsaplen;
+		nsap = get_nsaddr(statp, (size_t)ns);
+		nsaplen = get_salen(nsap);
+		statp->_flags &= ~RES_F_LASTMASK;
+		statp->_flags |= (ns << RES_F_LASTSHIFT);
+ same_ns:
+		if (statp->qhook) {
+			int done = 0, loops = 0;
+
+			do {
+				res_sendhookact act;
+
+				act = (*statp->qhook)(&nsap, &buf, &buflen,
+						      ans, anssiz, &resplen);
+				switch (act) {
+				case res_goahead:
+					done = 1;
+					break;
+				case res_nextns:
+					res_nclose(statp);
+					goto next_ns;
+				case res_done:
+					return (resplen);
+				case res_modified:
+					/* give the hook another try */
+					if (++loops < 42) /*doug adams*/
+						break;
+					/*FALLTHROUGH*/
+				case res_error:
+					/*FALLTHROUGH*/
+				default:
+					goto fail;
+				}
+			} while (!done);
+		}
+
+		Dprint(((statp->options & RES_DEBUG) &&
+			getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf),
+				    NULL, 0, niflags) == 0),
+		       (stdout, ";; Querying server (# %d) address = %s\n",
+			ns + 1, abuf));
+
+
+		if (v_circuit) {
+			/* Use VC; at most one attempt per server. */
+			try = statp->retry;
+			n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
+				    ns);
+			if (n < 0)
+				goto fail;
+			if (n == 0)
+				goto next_ns;
+			resplen = n;
+		} else {
+			/* Use datagrams. */
+			n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
+				    ns, &v_circuit, &gotsomewhere);
+			if (n < 0)
+				goto fail;
+			if (n == 0)
+				goto next_ns;
+			if (v_circuit)
+				goto same_ns;
+			resplen = n;
+		}
+
+		Dprint((statp->options & RES_DEBUG) ||
+		       ((statp->pfcode & RES_PRF_REPLY) &&
+			(statp->pfcode & RES_PRF_HEAD1)),
+		       (stdout, ";; got answer:\n"));
+
+		DprintQ((statp->options & RES_DEBUG) ||
+			(statp->pfcode & RES_PRF_REPLY),
+			(stdout, "%s", ""),
+			ans, (resplen > anssiz) ? anssiz : resplen);
+
+#if USE_RESOLV_CACHE
+                if (cache_status == RESOLV_CACHE_NOTFOUND) {
+                    _resolv_cache_add(cache, buf, buflen,
+                                      ans, resplen);
+                }
+#endif
+		/*
+		 * If we have temporarily opened a virtual circuit,
+		 * or if we haven't been asked to keep a socket open,
+		 * close the socket.
+		 */
+		if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
+		    (statp->options & RES_STAYOPEN) == 0U) {
+			res_nclose(statp);
+		}
+		if (statp->rhook) {
+			int done = 0, loops = 0;
+
+			do {
+				res_sendhookact act;
+
+				act = (*statp->rhook)(nsap, buf, buflen,
+						      ans, anssiz, &resplen);
+				switch (act) {
+				case res_goahead:
+				case res_done:
+					done = 1;
+					break;
+				case res_nextns:
+					res_nclose(statp);
+					goto next_ns;
+				case res_modified:
+					/* give the hook another try */
+					if (++loops < 42) /*doug adams*/
+						break;
+					/*FALLTHROUGH*/
+				case res_error:
+					/*FALLTHROUGH*/
+				default:
+					goto fail;
+				}
+			} while (!done);
+
+		}
+		return (resplen);
+ next_ns: ;
+	   } /*foreach ns*/
+	} /*foreach retry*/
+	res_nclose(statp);
+	if (!v_circuit) {
+		if (!gotsomewhere)
+			errno = ECONNREFUSED;	/* no nameservers found */
+		else
+			errno = ETIMEDOUT;	/* no answer obtained */
+	} else
+		errno = terrno;
+	return (-1);
+ fail:
+	res_nclose(statp);
+	return (-1);
+}
+
+/* Private */
+
+static int
+get_salen(sa)
+	const struct sockaddr *sa;
+{
+
+#ifdef HAVE_SA_LEN
+	/* There are people do not set sa_len.  Be forgiving to them. */
+	if (sa->sa_len)
+		return (sa->sa_len);
+#endif
+
+	if (sa->sa_family == AF_INET)
+		return (sizeof(struct sockaddr_in));
+	else if (sa->sa_family == AF_INET6)
+		return (sizeof(struct sockaddr_in6));
+	else
+		return (0);	/* unknown, die on connect */
+}
+
+/*
+ * pick appropriate nsaddr_list for use.  see res_init() for initialization.
+ */
+static struct sockaddr *
+get_nsaddr(statp, n)
+	res_state statp;
+	size_t n;
+{
+
+	if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
+		/*
+		 * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
+		 *   than struct sockaddr, and
+		 * - user code did not update statp->nsaddr_list[n].
+		 */
+		return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
+	} else {
+		/*
+		 * - user code updated statp->nsaddr_list[n], or
+		 * - statp->nsaddr_list[n] has the same content as
+		 *   EXT(statp).ext->nsaddrs[n].
+		 */
+		return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
+	}
+}
+
+static int
+send_vc(res_state statp,
+	const u_char *buf, int buflen, u_char *ans, int anssiz,
+	int *terrno, int ns)
+{
+	const HEADER *hp = (const HEADER *)(const void *)buf;
+	HEADER *anhp = (HEADER *)(void *)ans;
+	struct sockaddr *nsap;
+	int nsaplen;
+	int truncating, connreset, resplen, n;
+	struct iovec iov[2];
+	u_short len;
+	u_char *cp;
+	void *tmp;
+
+	nsap = get_nsaddr(statp, (size_t)ns);
+	nsaplen = get_salen(nsap);
+
+	connreset = 0;
+ same_ns:
+	truncating = 0;
+
+	/* Are we still talking to whom we want to talk to? */
+	if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
+		struct sockaddr_storage peer;
+		socklen_t size = sizeof peer;
+
+		if (getpeername(statp->_vcsock,
+				(struct sockaddr *)(void *)&peer, &size) < 0 ||
+		    !sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
+			res_nclose(statp);
+			statp->_flags &= ~RES_F_VC;
+		}
+	}
+
+	if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
+		if (statp->_vcsock >= 0)
+			res_nclose(statp);
+
+		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
+		if (statp->_vcsock > highestFD) {
+			res_nclose(statp);
+			errno = ENOTSOCK;
+		}
+		if (statp->_vcsock < 0) {
+			switch (errno) {
+			case EPROTONOSUPPORT:
+#ifdef EPFNOSUPPORT
+			case EPFNOSUPPORT:
+#endif
+			case EAFNOSUPPORT:
+				Perror(statp, stderr, "socket(vc)", errno);
+				return (0);
+			default:
+				*terrno = errno;
+				Perror(statp, stderr, "socket(vc)", errno);
+				return (-1);
+			}
+		}
+		errno = 0;
+		if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
+			*terrno = errno;
+			Aerror(statp, stderr, "bind/vc", errno, nsap,
+			    nsaplen);
+			res_nclose(statp);
+			return (0);
+		}
+		if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) {
+			*terrno = errno;
+			Aerror(statp, stderr, "connect/vc", errno, nsap,
+			    nsaplen);
+			res_nclose(statp);
+			return (0);
+		}
+		statp->_flags |= RES_F_VC;
+	}
+
+	/*
+	 * Send length & message
+	 */
+	ns_put16((u_short)buflen, (u_char*)(void *)&len);
+	iov[0] = evConsIovec(&len, INT16SZ);
+	DE_CONST(buf, tmp);
+	iov[1] = evConsIovec(tmp, (size_t)buflen);
+	if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
+		*terrno = errno;
+		Perror(statp, stderr, "write failed", errno);
+		res_nclose(statp);
+		return (0);
+	}
+	/*
+	 * Receive length & response
+	 */
+ read_len:
+	cp = ans;
+	len = INT16SZ;
+	while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) {
+		cp += n;
+		if ((len -= n) == 0)
+			break;
+	}
+	if (n <= 0) {
+		*terrno = errno;
+		Perror(statp, stderr, "read failed", errno);
+	  res_nclose(statp);
+		/*
+		 * A long running process might get its TCP
+		 * connection reset if the remote server was
+		 * restarted.  Requery the server instead of
+		 * trying a new one.  When there is only one
+		 * server, this means that a query might work
+		 * instead of failing.  We only allow one reset
+		 * per query to prevent looping.
+		 */
+		if (*terrno == ECONNRESET && !connreset) {
+			connreset = 1;
+			res_nclose(statp);
+			goto same_ns;
+		}
+		res_nclose(statp);
+		return (0);
+	}
+	resplen = ns_get16(ans);
+	if (resplen > anssiz) {
+		Dprint(statp->options & RES_DEBUG,
+		       (stdout, ";; response truncated\n")
+		       );
+		truncating = 1;
+		len = anssiz;
+	} else
+		len = resplen;
+	if (len < HFIXEDSZ) {
+		/*
+		 * Undersized message.
+		 */
+		Dprint(statp->options & RES_DEBUG,
+		       (stdout, ";; undersized: %d\n", len));
+		*terrno = EMSGSIZE;
+		res_nclose(statp);
+		return (0);
+	}
+	cp = ans;
+	while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){
+		cp += n;
+		len -= n;
+	}
+	if (n <= 0) {
+		*terrno = errno;
+		Perror(statp, stderr, "read(vc)", errno);
+		res_nclose(statp);
+		return (0);
+	}
+	if (truncating) {
+		/*
+		 * Flush rest of answer so connection stays in synch.
+		 */
+		anhp->tc = 1;
+		len = resplen - anssiz;
+		while (len != 0) {
+			char junk[PACKETSZ];
+
+			n = read(statp->_vcsock, junk,
+				 (len > sizeof junk) ? sizeof junk : len);
+			if (n > 0)
+				len -= n;
+			else
+				break;
+		}
+	}
+	/*
+	 * If the calling applicating has bailed out of
+	 * a previous call and failed to arrange to have
+	 * the circuit closed or the server has got
+	 * itself confused, then drop the packet and
+	 * wait for the correct one.
+	 */
+	if (hp->id != anhp->id) {
+		DprintQ((statp->options & RES_DEBUG) ||
+			(statp->pfcode & RES_PRF_REPLY),
+			(stdout, ";; old answer (unexpected):\n"),
+			ans, (resplen > anssiz) ? anssiz: resplen);
+		goto read_len;
+	}
+
+	/*
+	 * All is well, or the error is fatal.  Signal that the
+	 * next nameserver ought not be tried.
+	 */
+	return (resplen);
+}
+
+static int
+send_dg(res_state statp,
+	const u_char *buf, int buflen, u_char *ans, int anssiz,
+	int *terrno, int ns, int *v_circuit, int *gotsomewhere)
+{
+	const HEADER *hp = (const HEADER *)(const void *)buf;
+	HEADER *anhp = (HEADER *)(void *)ans;
+	const struct sockaddr *nsap;
+	int nsaplen;
+	struct timespec now, timeout, finish;
+	fd_set dsmask;
+	struct sockaddr_storage from;
+	socklen_t fromlen;
+	int resplen, seconds, n, s;
+
+	nsap = get_nsaddr(statp, (size_t)ns);
+	nsaplen = get_salen(nsap);
+	if (EXT(statp).nssocks[ns] == -1) {
+		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
+		if (EXT(statp).nssocks[ns] > highestFD) {
+			res_nclose(statp);
+			errno = ENOTSOCK;
+		}
+		if (EXT(statp).nssocks[ns] < 0) {
+			switch (errno) {
+			case EPROTONOSUPPORT:
+#ifdef EPFNOSUPPORT
+			case EPFNOSUPPORT:
+#endif
+			case EAFNOSUPPORT:
+				Perror(statp, stderr, "socket(dg)", errno);
+				return (0);
+			default:
+				*terrno = errno;
+				Perror(statp, stderr, "socket(dg)", errno);
+				return (-1);
+			}
+		}
+#ifndef CANNOT_CONNECT_DGRAM
+		/*
+		 * On a 4.3BSD+ machine (client and server,
+		 * actually), sending to a nameserver datagram
+		 * port with no nameserver will cause an
+		 * ICMP port unreachable message to be returned.
+		 * If our datagram socket is "connected" to the
+		 * server, we get an ECONNREFUSED error on the next
+		 * socket operation, and select returns if the
+		 * error message is received.  We can thus detect
+		 * the absence of a nameserver without timing out.
+		 */
+		if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) {
+			Aerror(statp, stderr, "bind(dg)", errno, nsap,
+			    nsaplen);
+			res_nclose(statp);
+			return (0);
+		}
+		if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) {
+			Aerror(statp, stderr, "connect(dg)", errno, nsap,
+			    nsaplen);
+			res_nclose(statp);
+			return (0);
+		}
+#endif /* !CANNOT_CONNECT_DGRAM */
+		Dprint(statp->options & RES_DEBUG,
+		       (stdout, ";; new DG socket\n"))
+	}
+	s = EXT(statp).nssocks[ns];
+#ifndef CANNOT_CONNECT_DGRAM
+	if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) {
+		Perror(statp, stderr, "send", errno);
+		res_nclose(statp);
+		return (0);
+	}
+#else /* !CANNOT_CONNECT_DGRAM */
+	if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
+	{
+		Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
+		res_nclose(statp);
+		return (0);
+	}
+#endif /* !CANNOT_CONNECT_DGRAM */
+
+	/*
+	 * Wait for reply.
+	 */
+	seconds = (statp->retrans << ns);
+	if (ns > 0)
+		seconds /= statp->nscount;
+	if (seconds <= 0)
+		seconds = 1;
+	now = evNowTime();
+	timeout = evConsTime((long)seconds, 0L);
+	finish = evAddTime(now, timeout);
+	goto nonow;
+ wait:
+	now = evNowTime();
+ nonow:
+	FD_ZERO(&dsmask);
+	FD_SET(s, &dsmask);
+	if (evCmpTime(finish, now) > 0)
+		timeout = evSubTime(finish, now);
+	else
+		timeout = evConsTime(0L, 0L);
+	n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
+	if (n == 0) {
+		Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
+		*gotsomewhere = 1;
+		return (0);
+	}
+	if (n < 0) {
+		if (errno == EINTR)
+			goto wait;
+		Perror(statp, stderr, "select", errno);
+		res_nclose(statp);
+		return (0);
+	}
+	errno = 0;
+	fromlen = sizeof(from);
+	resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0,
+			   (struct sockaddr *)(void *)&from, &fromlen);
+	if (resplen <= 0) {
+		Perror(statp, stderr, "recvfrom", errno);
+		res_nclose(statp);
+		return (0);
+	}
+	*gotsomewhere = 1;
+	if (resplen < HFIXEDSZ) {
+		/*
+		 * Undersized message.
+		 */
+		Dprint(statp->options & RES_DEBUG,
+		       (stdout, ";; undersized: %d\n",
+			resplen));
+		*terrno = EMSGSIZE;
+		res_nclose(statp);
+		return (0);
+	}
+	if (hp->id != anhp->id) {
+		/*
+		 * response from old query, ignore it.
+		 * XXX - potential security hazard could
+		 *	 be detected here.
+		 */
+		DprintQ((statp->options & RES_DEBUG) ||
+			(statp->pfcode & RES_PRF_REPLY),
+			(stdout, ";; old answer:\n"),
+			ans, (resplen > anssiz) ? anssiz : resplen);
+		goto wait;
+	}
+	if (!(statp->options & RES_INSECURE1) &&
+	    !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) {
+		/*
+		 * response from wrong server? ignore it.
+		 * XXX - potential security hazard could
+		 *	 be detected here.
+		 */
+		DprintQ((statp->options & RES_DEBUG) ||
+			(statp->pfcode & RES_PRF_REPLY),
+			(stdout, ";; not our server:\n"),
+			ans, (resplen > anssiz) ? anssiz : resplen);
+		goto wait;
+	}
+#ifdef RES_USE_EDNS0
+	if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
+		/*
+		 * Do not retry if the server do not understand EDNS0.
+		 * The case has to be captured here, as FORMERR packet do not
+		 * carry query section, hence res_queriesmatch() returns 0.
+		 */
+		DprintQ(statp->options & RES_DEBUG,
+			(stdout, "server rejected query with EDNS0:\n"),
+			ans, (resplen > anssiz) ? anssiz : resplen);
+		/* record the error */
+		statp->_flags |= RES_F_EDNS0ERR;
+		res_nclose(statp);
+		return (0);
+	}
+#endif
+	if (!(statp->options & RES_INSECURE2) &&
+	    !res_queriesmatch(buf, buf + buflen,
+			      ans, ans + anssiz)) {
+		/*
+		 * response contains wrong query? ignore it.
+		 * XXX - potential security hazard could
+		 *	 be detected here.
+		 */
+		DprintQ((statp->options & RES_DEBUG) ||
+			(statp->pfcode & RES_PRF_REPLY),
+			(stdout, ";; wrong query name:\n"),
+			ans, (resplen > anssiz) ? anssiz : resplen);
+		goto wait;
+	}
+	if (anhp->rcode == SERVFAIL ||
+	    anhp->rcode == NOTIMP ||
+	    anhp->rcode == REFUSED) {
+		DprintQ(statp->options & RES_DEBUG,
+			(stdout, "server rejected query:\n"),
+			ans, (resplen > anssiz) ? anssiz : resplen);
+		res_nclose(statp);
+		/* don't retry if called from dig */
+		if (!statp->pfcode)
+			return (0);
+	}
+	if (!(statp->options & RES_IGNTC) && anhp->tc) {
+		/*
+		 * To get the rest of answer,
+		 * use TCP with same server.
+		 */
+		Dprint(statp->options & RES_DEBUG,
+		       (stdout, ";; truncated answer\n"));
+		*v_circuit = 1;
+		res_nclose(statp);
+		return (1);
+	}
+	/*
+	 * All is well, or the error is fatal.  Signal that the
+	 * next nameserver ought not be tried.
+	 */
+	return (resplen);
+}
+
+static void
+Aerror(const res_state statp, FILE *file, const char *string, int error,
+       const struct sockaddr *address, int alen)
+{
+	int save = errno;
+	char hbuf[NI_MAXHOST];
+	char sbuf[NI_MAXSERV];
+
+	alen = alen;
+
+	if ((statp->options & RES_DEBUG) != 0U) {
+		if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf),
+		    sbuf, sizeof(sbuf), niflags)) {
+			strncpy(hbuf, "?", sizeof(hbuf) - 1);
+			hbuf[sizeof(hbuf) - 1] = '\0';
+			strncpy(sbuf, "?", sizeof(sbuf) - 1);
+			sbuf[sizeof(sbuf) - 1] = '\0';
+		}
+		fprintf(file, "res_send: %s ([%s].%s): %s\n",
+			string, hbuf, sbuf, strerror(error));
+	}
+	errno = save;
+}
+
+static void
+Perror(const res_state statp, FILE *file, const char *string, int error) {
+	int save = errno;
+
+	if ((statp->options & RES_DEBUG) != 0U)
+		fprintf(file, "res_send: %s: %s\n",
+			string, strerror(error));
+	errno = save;
+}
+
+static int
+sock_eq(struct sockaddr *a, struct sockaddr *b) {
+	struct sockaddr_in *a4, *b4;
+	struct sockaddr_in6 *a6, *b6;
+
+	if (a->sa_family != b->sa_family)
+		return 0;
+	switch (a->sa_family) {
+	case AF_INET:
+		a4 = (struct sockaddr_in *)(void *)a;
+		b4 = (struct sockaddr_in *)(void *)b;
+		return a4->sin_port == b4->sin_port &&
+		    a4->sin_addr.s_addr == b4->sin_addr.s_addr;
+	case AF_INET6:
+		a6 = (struct sockaddr_in6 *)(void *)a;
+		b6 = (struct sockaddr_in6 *)(void *)b;
+		return a6->sin6_port == b6->sin6_port &&
+#ifdef HAVE_SIN6_SCOPE_ID
+		    a6->sin6_scope_id == b6->sin6_scope_id &&
+#endif
+		    IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
+	default:
+		return 0;
+	}
+}
+
+#ifdef NEED_PSELECT
+/* XXX needs to move to the porting library. */
+static int
+pselect(int nfds, void *rfds, void *wfds, void *efds,
+	struct timespec *tsp, const sigset_t *sigmask)
+{
+	struct timeval tv, *tvp;
+	sigset_t sigs;
+	int n;
+
+	if (tsp) {
+		tvp = &tv;
+		tv = evTimeVal(*tsp);
+	} else
+		tvp = NULL;
+	if (sigmask)
+		sigprocmask(SIG_SETMASK, sigmask, &sigs);
+	n = select(nfds, rfds, wfds, efds, tvp);
+	if (sigmask)
+		sigprocmask(SIG_SETMASK, &sigs, NULL);
+	if (tsp)
+		*tsp = evTimeSpec(tv);
+	return (n);
+}
+#endif
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/res_state.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#define ANDROID_CHANGES 1
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include "arpa_nameser.h"
+#include <netdb.h>
+#include "resolv_private.h"
+#include "resolv_cache.h"
+#include <pthread.h>
+#include <stdlib.h>
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+static pthread_key_t   _res_key;
+static pthread_once_t  _res_once;
+
+typedef struct {
+    int                    _h_errno;
+    struct __res_state     _nres[1];
+    unsigned               _serial;
+    struct prop_info*      _pi;
+    struct res_static      _rstatic[1];
+} _res_thread;
+
+static _res_thread*
+_res_thread_alloc(void)
+{
+    _res_thread*  rt = malloc(sizeof(*rt));
+
+    if (rt) {
+        rt->_h_errno = 0;
+        /* Special system property which tracks any changes to 'net.*'. */
+        rt->_serial = 0;
+        rt->_pi = (struct prop_info*) __system_property_find("net.change");
+        if (rt->_pi) {
+            rt->_serial = rt->_pi->serial;
+        }
+        if ( res_ninit( rt->_nres ) < 0 ) {
+            free(rt);
+            rt = NULL;
+        } else {
+            memset(rt->_rstatic, 0, sizeof rt->_rstatic);
+        }
+    }
+    return rt;
+}
+
+static void
+_res_static_done( res_static  rs )
+{
+    /* fortunately, there is nothing to do here, since the
+     * points in h_addr_ptrs and host_aliases should all
+     * point to 'hostbuf'
+     */
+    if (rs->hostf) {  /* should not happen in theory, but just be safe */
+        fclose(rs->hostf);
+        rs->hostf = NULL;
+    }
+    free(rs->servent.s_aliases);
+}
+
+static void
+_res_thread_free( void*  _rt )
+{
+    _res_thread*  rt = _rt;
+
+    _res_static_done(rt->_rstatic);
+    res_ndestroy(rt->_nres);
+    free(rt);
+}
+
+static void
+_res_init_key( void )
+{
+    pthread_key_create( &_res_key, _res_thread_free );
+}
+
+static _res_thread*
+_res_thread_get(void)
+{
+    _res_thread*  rt;
+    pthread_once( &_res_once, _res_init_key );
+    rt = pthread_getspecific( _res_key );
+    if (rt == NULL) {
+        if ((rt = _res_thread_alloc()) == NULL) {
+            return NULL;
+        }
+        rt->_h_errno = 0;
+        rt->_serial = 0;
+        pthread_setspecific( _res_key, rt );
+    }
+    /* Check the serial value for any chanes to net.* properties. */
+    if (rt->_pi == NULL) {
+        rt->_pi = (struct prop_info*) __system_property_find("net.change");
+    }
+    if (rt->_pi == NULL || rt->_serial == rt->_pi->serial) {
+        return rt;
+    }
+    rt->_serial = rt->_pi->serial;
+    /* Reload from system properties. */
+    if ( res_ninit( rt->_nres ) < 0 ) {
+        free(rt);
+        rt = NULL;
+        pthread_setspecific( _res_key, rt );
+    }
+    _resolv_cache_reset(rt->_serial);
+    return rt;
+}
+
+struct __res_state _nres;
+
+#if 0
+struct resolv_cache*
+__get_res_cache(void)
+{
+    _res_thread*  rt = _res_thread_get();
+
+    if (!rt)
+        return NULL;
+
+    if (!rt->_cache) {
+        rt->_cache = _resolv_cache_create();
+    }
+    return rt->_cache;
+}
+#endif
+
+int*
+__get_h_errno(void)
+{
+    _res_thread*  rt    = _res_thread_get();
+    static int    panic = NETDB_INTERNAL;
+
+    return rt ? &rt->_h_errno : &panic;
+}
+
+res_state
+__res_get_state(void)
+{
+    _res_thread*  rt = _res_thread_get();
+
+    return rt ? rt->_nres : NULL;
+}
+
+void
+__res_put_state(res_state res)
+{
+    /* nothing to do */
+    res=res;
+}
+
+res_static
+__res_get_static(void)
+{
+    _res_thread*  rt = _res_thread_get();
+
+    return rt ? rt->_rstatic : NULL;
+}
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/resolv_cache.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#ifndef _RESOLV_CACHE_H_
+#define _RESOLV_CACHE_H_
+
+struct resolv_cache;  /* forward */
+
+/* get cache instance, can be NULL if cache is disabled
+ * (e.g. through an environment variable) */
+extern struct resolv_cache*  __get_res_cache(void);
+
+/* this gets called everytime we detect some changes in the DNS configuration
+ * and will flush the cache */
+extern void   _resolv_cache_reset( unsigned  generation );
+
+typedef enum {
+    RESOLV_CACHE_UNSUPPORTED,  /* the cache can't handle that kind of queries */
+                               /* or the answer buffer is too small */
+    RESOLV_CACHE_NOTFOUND,     /* the cache doesn't know about this query */
+    RESOLV_CACHE_FOUND         /* the cache found the answer */
+} ResolvCacheStatus;
+
+extern ResolvCacheStatus
+_resolv_cache_lookup( struct resolv_cache*  cache,
+                      const void*           query,
+                      int                   querylen,
+                      void*                 answer,
+                      int                   answersize,
+                      int                  *answerlen );
+
+/* add a (query,answer) to the cache, only call if _resolv_cache_lookup
+ * did return RESOLV_CACHE_NOTFOUND
+ */
+extern void
+_resolv_cache_add( struct resolv_cache*  cache,
+                   const void*           query,
+                   int                   querylen,
+                   const void*           answer,
+                   int                   answerlen );
+
+#endif /* _RESOLV_CACHE_H_ */
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/resolv_private.h
@@ -0,0 +1,509 @@
+/*	$NetBSD: resolv.h,v 1.31 2005/12/26 19:01:47 perry Exp $	*/
+
+/*
+ * Copyright (c) 1983, 1987, 1989
+ *    The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *	@(#)resolv.h	8.1 (Berkeley) 6/2/93
+ *	Id: resolv.h,v 1.7.2.11.4.2 2004/06/25 00:41:05 marka Exp
+ */
+
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#ifndef _RESOLV_PRIVATE_H_
+#define	_RESOLV_PRIVATE_H_
+
+#include <resolv.h>
+#include "resolv_static.h"
+
+/*
+ * Revision information.  This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__RES > 19931104)".  Do not
+ * compare for equality; rather, use it to determine whether your resolver
+ * is new enough to contain a certain feature.
+ */
+
+#define	__RES	20030124
+
+/*
+ * This used to be defined in res_query.c, now it's in herror.c.
+ * [XXX no it's not.  It's in irs/irs_data.c]
+ * It was
+ * never extern'd by any *.h file before it was placed here.  For thread
+ * aware programs, the last h_errno value set is stored in res->h_errno.
+ *
+ * XXX:	There doesn't seem to be a good reason for exposing RES_SET_H_ERRNO
+ *	(and __h_errno_set) to the public via <resolv.h>.
+ * XXX:	__h_errno_set is really part of IRS, not part of the resolver.
+ *	If somebody wants to build and use a resolver that doesn't use IRS,
+ *	what do they do?  Perhaps something like
+ *		#ifdef WANT_IRS
+ *		# define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x)
+ *		#else
+ *		# define RES_SET_H_ERRNO(r,x) (h_errno = (r)->res_h_errno = (x))
+ *		#endif
+ */
+
+#define RES_SET_H_ERRNO(r,x) (h_errno = (r)->res_h_errno = (x))
+struct __res_state; /* forward */
+
+/*
+ * Resolver configuration file.
+ * Normally not present, but may contain the address of the
+ * initial name server(s) to query and the domain search list.
+ */
+
+#ifndef _PATH_RESCONF
+#ifdef ANDROID_CHANGES
+#define _PATH_RESCONF        "/etc/ppp/resolv.conf"
+#else
+#define _PATH_RESCONF        "/etc/resolv.conf"
+#endif
+#endif
+
+typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
+	res_sendhookact;
+
+typedef res_sendhookact (*res_send_qhook)(struct sockaddr * const *,
+					      const u_char **, int *,
+					      u_char *, int, int *);
+
+typedef res_sendhookact (*res_send_rhook)(const struct sockaddr *,
+					      const u_char *, int, u_char *,
+					      int, int *);
+
+struct res_sym {
+	int		number;	   /* Identifying number, like T_MX */
+	const char *	name;	   /* Its symbolic name, like "MX" */
+	const char *	humanname; /* Its fun name, like "mail exchanger" */
+};
+
+/*
+ * Global defines and variables for resolver stub.
+ */
+#define	MAXNS			3	/* max # name servers we'll track */
+#define	MAXDFLSRCH		3	/* # default domain levels to try */
+#define	MAXDNSRCH		6	/* max # domains in search path */
+#define	LOCALDOMAINPARTS	2	/* min levels in name that is "local" */
+
+#define	RES_TIMEOUT		5	/* min. seconds between retries */
+#define	MAXRESOLVSORT		10	/* number of net to sort on */
+#define	RES_MAXNDOTS		15	/* should reflect bit field size */
+#define	RES_MAXRETRANS		30	/* only for resolv.conf/RES_OPTIONS */
+#define	RES_MAXRETRY		5	/* only for resolv.conf/RES_OPTIONS */
+#define	RES_DFLRETRY		2	/* Default #/tries. */
+#define	RES_MAXTIME		65535	/* Infinity, in milliseconds. */
+
+struct __res_state_ext;
+
+struct __res_state {
+	int	retrans;	 	/* retransmission time interval */
+	int	retry;			/* number of times to retransmit */
+#ifdef sun
+	u_int	options;		/* option flags - see below. */
+#else
+	u_long	options;		/* option flags - see below. */
+#endif
+	int	nscount;		/* number of name servers */
+	struct sockaddr_in
+		nsaddr_list[MAXNS];	/* address of name server */
+#define	nsaddr	nsaddr_list[0]		/* for backward compatibility */
+	u_short	id;			/* current message id */
+	char	*dnsrch[MAXDNSRCH+1];	/* components of domain to search */
+	char	defdname[256];		/* default domain (deprecated) */
+#ifdef sun
+	u_int	pfcode;			/* RES_PRF_ flags - see below. */
+#else
+	u_long	pfcode;			/* RES_PRF_ flags - see below. */
+#endif
+	unsigned ndots:4;		/* threshold for initial abs. query */
+	unsigned nsort:4;		/* number of elements in sort_list[] */
+	char	unused[3];
+	struct {
+		struct in_addr	addr;
+		uint32_t	mask;
+	} sort_list[MAXRESOLVSORT];
+#ifdef __OLD_RES_STATE
+	char lookups[4];
+#else
+	res_send_qhook qhook;		/* query hook */
+	res_send_rhook rhook;		/* response hook */
+	int	res_h_errno;		/* last one set for this context */
+	int	_vcsock;		/* PRIVATE: for res_send VC i/o */
+	u_int	_flags;			/* PRIVATE: see below */
+	u_int	_pad;			/* make _u 64 bit aligned */
+	union {
+		/* On an 32-bit arch this means 512b total. */
+		char	pad[72 - 4*sizeof (int) - 2*sizeof (void *)];
+		struct {
+			uint16_t		nscount;
+			uint16_t		nstimes[MAXNS];	/* ms. */
+			int			nssocks[MAXNS];
+			struct __res_state_ext *ext;	/* extention for IPv6 */
+		} _ext;
+	} _u;
+#endif
+        struct res_static   rstatic[1];
+};
+
+typedef struct __res_state *res_state;
+
+union res_sockaddr_union {
+	struct sockaddr_in	sin;
+#ifdef IN6ADDR_ANY_INIT
+	struct sockaddr_in6	sin6;
+#endif
+#ifdef ISC_ALIGN64
+	int64_t			__align64;	/* 64bit alignment */
+#else
+	int32_t			__align32;	/* 32bit alignment */
+#endif
+	char			__space[128];   /* max size */
+};
+
+/*
+ * Resolver flags (used to be discrete per-module statics ints).
+ */
+#define	RES_F_VC	0x00000001	/* socket is TCP */
+#define	RES_F_CONN	0x00000002	/* socket is connected */
+#define	RES_F_EDNS0ERR	0x00000004	/* EDNS0 caused errors */
+#define	RES_F__UNUSED	0x00000008	/* (unused) */
+#define	RES_F_LASTMASK	0x000000F0	/* ordinal server of last res_nsend */
+#define	RES_F_LASTSHIFT	4		/* bit position of LASTMASK "flag" */
+#define	RES_GETLAST(res) (((res)._flags & RES_F_LASTMASK) >> RES_F_LASTSHIFT)
+
+/* res_findzonecut2() options */
+#define	RES_EXHAUSTIVE	0x00000001	/* always do all queries */
+#define	RES_IPV4ONLY	0x00000002	/* IPv4 only */
+#define	RES_IPV6ONLY	0x00000004	/* IPv6 only */
+
+/*
+ * Resolver options (keep these in synch with res_debug.c, please)
+ */
+#define RES_INIT	0x00000001	/* address initialized */
+#define RES_DEBUG	0x00000002	/* print debug messages */
+#define RES_AAONLY	0x00000004	/* authoritative answers only (!IMPL)*/
+#define RES_USEVC	0x00000008	/* use virtual circuit */
+#define RES_PRIMARY	0x00000010	/* query primary server only (!IMPL) */
+#define RES_IGNTC	0x00000020	/* ignore trucation errors */
+#define RES_RECURSE	0x00000040	/* recursion desired */
+#define RES_DEFNAMES	0x00000080	/* use default domain name */
+#define RES_STAYOPEN	0x00000100	/* Keep TCP socket open */
+#define RES_DNSRCH	0x00000200	/* search up local domain tree */
+#define	RES_INSECURE1	0x00000400	/* type 1 security disabled */
+#define	RES_INSECURE2	0x00000800	/* type 2 security disabled */
+#define	RES_NOALIASES	0x00001000	/* shuts off HOSTALIASES feature */
+#define	RES_USE_INET6	0x00002000	/* use/map IPv6 in gethostbyname() */
+#define RES_ROTATE	0x00004000	/* rotate ns list after each query */
+#define	RES_NOCHECKNAME	0x00008000	/* do not check names for sanity. */
+#define	RES_KEEPTSIG	0x00010000	/* do not strip TSIG records */
+#define	RES_BLAST	0x00020000	/* blast all recursive servers */
+#define RES_NOTLDQUERY	0x00100000	/* don't unqualified name as a tld */
+#define RES_USE_DNSSEC	0x00200000	/* use DNSSEC using OK bit in OPT */
+/* #define RES_DEBUG2	0x00400000 */	/* nslookup internal */
+/* KAME extensions: use higher bit to avoid conflict with ISC use */
+#define RES_USE_DNAME	0x10000000	/* use DNAME */
+#define RES_USE_EDNS0	0x40000000	/* use EDNS0 if configured */
+#define RES_NO_NIBBLE2	0x80000000	/* disable alternate nibble lookup */
+
+#define RES_DEFAULT	(RES_RECURSE | RES_DEFNAMES | \
+			 RES_DNSRCH | RES_NO_NIBBLE2)
+
+/*
+ * Resolver "pfcode" values.  Used by dig.
+ */
+#define RES_PRF_STATS	0x00000001
+#define RES_PRF_UPDATE	0x00000002
+#define RES_PRF_CLASS   0x00000004
+#define RES_PRF_CMD	0x00000008
+#define RES_PRF_QUES	0x00000010
+#define RES_PRF_ANS	0x00000020
+#define RES_PRF_AUTH	0x00000040
+#define RES_PRF_ADD	0x00000080
+#define RES_PRF_HEAD1	0x00000100
+#define RES_PRF_HEAD2	0x00000200
+#define RES_PRF_TTLID	0x00000400
+#define RES_PRF_HEADX	0x00000800
+#define RES_PRF_QUERY	0x00001000
+#define RES_PRF_REPLY	0x00002000
+#define RES_PRF_INIT	0x00004000
+#define RES_PRF_TRUNC	0x00008000
+/*			0x00010000	*/
+
+/* Things involving an internal (static) resolver context. */
+__BEGIN_DECLS
+extern struct __res_state *__res_get_state(void);
+extern void __res_put_state(struct __res_state *);
+
+#ifndef ANDROID_CHANGES
+/*
+ * Source and Binary compatibility; _res will not work properly
+ * with multi-threaded programs.
+ */
+extern struct __res_state *__res_state(void);
+#define _res (*__res_state())
+#endif
+
+__END_DECLS
+
+#ifndef __BIND_NOSTATIC
+#define fp_nquery		__fp_nquery
+#define fp_query		__fp_query
+#define hostalias		__hostalias
+#define p_query			__p_query
+#define res_close		__res_close
+#define res_opt			__res_opt
+#define res_isourserver		__res_isourserver
+#define	res_querydomain		__res_querydomain
+#define res_send		__res_send
+#define res_sendsigned		__res_sendsigned
+
+#ifdef BIND_RES_POSIX3
+#define	dn_expand	__dn_expand
+#define	res_init	__res_init
+#define	res_query	__res_query
+#define	res_search	__res_search
+#define	res_mkquery	__res_mkquery
+#endif
+
+__BEGIN_DECLS
+void		fp_nquery(const u_char *, int, FILE *);
+void		fp_query(const u_char *, FILE *);
+const char *	hostalias(const char *);
+void		p_query(const u_char *);
+void		res_close(void);
+int		res_init(void);
+int		res_opt(int, u_char *, int, int);
+int		res_isourserver(const struct sockaddr_in *);
+int		res_mkquery(int, const char *, int, int, const u_char *, int, const u_char *, u_char *, int);
+int		res_query(const char *, int, int, u_char *, int);
+int		res_querydomain(const char *, const char *, int, int, u_char *, int);
+int		res_search(const char *, int, int, u_char *, int);
+int		res_send(const u_char *, int, u_char *, int);
+int		res_sendsigned(const u_char *, int, ns_tsig_key *, u_char *, int);
+__END_DECLS
+#endif
+
+#if !defined(SHARED_LIBBIND) || defined(LIB)
+/*
+ * If libbind is a shared object (well, DLL anyway)
+ * these externs break the linker when resolv.h is
+ * included by a lib client (like named)
+ * Make them go away if a client is including this
+ *
+ */
+extern const struct res_sym __p_key_syms[];
+extern const struct res_sym __p_cert_syms[];
+extern const struct res_sym __p_class_syms[];
+extern const struct res_sym __p_type_syms[];
+extern const struct res_sym __p_rcode_syms[];
+#endif /* SHARED_LIBBIND */
+
+#ifndef ADNROID_CHANGES
+#define b64_ntop		__b64_ntop
+#define b64_pton		__b64_pton
+#endif
+
+#define dn_comp			__dn_comp
+#define dn_count_labels		__dn_count_labels
+#define dn_skipname		__dn_skipname
+#define fp_resstat		__fp_resstat
+#define loc_aton		__loc_aton
+#define loc_ntoa		__loc_ntoa
+#define p_cdname		__p_cdname
+#define p_cdnname		__p_cdnname
+#define p_class			__p_class
+#define p_fqname		__p_fqname
+#define p_fqnname		__p_fqnname
+#define p_option		__p_option
+#define p_secstodate		__p_secstodate
+#define p_section		__p_section
+#define p_time			__p_time
+#define p_type			__p_type
+#define p_rcode			__p_rcode
+#define p_sockun		__p_sockun
+#define putlong			__putlong
+#define putshort		__putshort
+#define res_dnok		__res_dnok
+#define res_findzonecut		__res_findzonecut
+#define res_findzonecut2	__res_findzonecut2
+#define res_hnok		__res_hnok
+#define res_hostalias		__res_hostalias
+#define res_mailok		__res_mailok
+#define res_nameinquery		__res_nameinquery
+#define res_nclose		__res_nclose
+#define res_ninit		__res_ninit
+#define res_nmkquery		__res_nmkquery
+#define res_pquery		__res_pquery
+#define res_nquery		__res_nquery
+#define res_nquerydomain	__res_nquerydomain
+#define res_nsearch		__res_nsearch
+#define res_nsend		__res_nsend
+#define res_nsendsigned		__res_nsendsigned
+#define res_nisourserver	__res_nisourserver
+#define res_ownok		__res_ownok
+#define res_queriesmatch	__res_queriesmatch
+#define res_randomid		__res_randomid
+#define sym_ntop		__sym_ntop
+#define sym_ntos		__sym_ntos
+#define sym_ston		__sym_ston
+#define res_nopt		__res_nopt
+#define res_ndestroy		__res_ndestroy
+#define	res_nametoclass		__res_nametoclass
+#define	res_nametotype		__res_nametotype
+#define	res_setservers		__res_setservers
+#define	res_getservers		__res_getservers
+#define	res_buildprotolist	__res_buildprotolist
+#define	res_destroyprotolist	__res_destroyprotolist
+#define	res_destroyservicelist	__res_destroyservicelist
+#define	res_get_nibblesuffix	__res_get_nibblesuffix
+#define	res_get_nibblesuffix2	__res_get_nibblesuffix2
+#define	res_ourserver_p		__res_ourserver_p
+#define	res_protocolname	__res_protocolname
+#define	res_protocolnumber	__res_protocolnumber
+#define	res_send_setqhook	__res_send_setqhook
+#define	res_send_setrhook	__res_send_setrhook
+#define	res_servicename		__res_servicename
+#define	res_servicenumber	__res_servicenumber
+__BEGIN_DECLS
+int		res_hnok(const char *);
+int		res_ownok(const char *);
+int		res_mailok(const char *);
+int		res_dnok(const char *);
+int		sym_ston(const struct res_sym *, const char *, int *);
+const char *	sym_ntos(const struct res_sym *, int, int *);
+const char *	sym_ntop(const struct res_sym *, int, int *);
+#ifndef ANDROID_CHANGES
+int		b64_ntop(u_char const *, size_t, char *, size_t);
+int		b64_pton(char const *, u_char *, size_t);
+#endif
+int		loc_aton(const char *, u_char *);
+const char *	loc_ntoa(const u_char *, char *);
+int		dn_skipname(const u_char *, const u_char *);
+void		putlong(uint32_t, u_char *);
+void		putshort(uint16_t, u_char *);
+#ifndef __ultrix__
+uint16_t	_getshort(const u_char *);
+uint32_t	_getlong(const u_char *);
+#endif
+const char *	p_class(int);
+const char *	p_time(uint32_t);
+const char *	p_type(int);
+const char *	p_rcode(int);
+const char *	p_sockun(union res_sockaddr_union, char *, size_t);
+const u_char *	p_cdnname(const u_char *, const u_char *, int, FILE *);
+const u_char *	p_cdname(const u_char *, const u_char *, FILE *);
+const u_char *	p_fqnname(const u_char *, const u_char *,
+			       int, char *, int);
+const u_char *	p_fqname(const u_char *, const u_char *, FILE *);
+const char *	p_option(u_long);
+char *		p_secstodate(u_long);
+int		dn_count_labels(const char *);
+int		dn_comp(const char *, u_char *, int, u_char **, u_char **);
+int		dn_expand(const u_char *, const u_char *, const u_char *,
+			       char *, int);
+u_int		res_randomid(void);
+int		res_nameinquery(const char *, int, int, const u_char *,
+				     const u_char *);
+int		res_queriesmatch(const u_char *, const u_char *,
+				      const u_char *, const u_char *);
+const char *	p_section(int, int);
+/* Things involving a resolver context. */
+int		res_ninit(res_state);
+int		res_nisourserver(const res_state, const struct sockaddr_in *);
+void		fp_resstat(const res_state, FILE *);
+void		res_pquery(const res_state, const u_char *, int, FILE *);
+const char *	res_hostalias(const res_state, const char *, char *, size_t);
+int		res_nquery(res_state, const char *, int, int, u_char *, int);
+int		res_nsearch(res_state, const char *, int, int, u_char *, int);
+int		res_nquerydomain(res_state, const char *, const char *,
+				      int, int, u_char *, int);
+int		res_nmkquery(res_state, int, const char *, int, int,
+				  const u_char *, int, const u_char *,
+				  u_char *, int);
+int		res_nsend(res_state, const u_char *, int, u_char *, int);
+int		res_nsendsigned(res_state, const u_char *, int,
+				     ns_tsig_key *, u_char *, int);
+int		res_findzonecut(res_state, const char *, ns_class, int,
+				     char *, size_t, struct in_addr *, int);
+int		res_findzonecut2(res_state, const char *, ns_class, int,
+				      char *, size_t,
+				      union res_sockaddr_union *, int);
+void		res_nclose(res_state);
+int		res_nopt(res_state, int, u_char *, int, int);
+void		res_send_setqhook(res_send_qhook);
+void		res_send_setrhook(res_send_rhook);
+int		__res_vinit(res_state, int);
+void		res_destroyservicelist(void);
+const char *	res_servicename(uint16_t, const char *);
+const char *	res_protocolname(int);
+void		res_destroyprotolist(void);
+void		res_buildprotolist(void);
+const char *	res_get_nibblesuffix(res_state);
+const char *	res_get_nibblesuffix2(res_state);
+void		res_ndestroy(res_state);
+uint16_t	res_nametoclass(const char *, int *);
+uint16_t	res_nametotype(const char *, int *);
+void		res_setservers(res_state,
+				    const union res_sockaddr_union *, int);
+int		res_getservers(res_state,
+				    union res_sockaddr_union *, int);
+
+int res_get_dns_changed();
+u_int  res_randomid(void);
+
+__END_DECLS
+
+#endif /* !_RESOLV_PRIVATE_H_ */
new file mode 100644
--- /dev/null
+++ b/other-licenses/android/resolv_static.h
@@ -0,0 +1,42 @@
+/*
+ * This version of this file is derived from Android 2.3 "Gingerbread",
+ * which contains uncredited changes by Android/Google developers.  It has
+ * been modified in 2011 for use in the Android build of Mozilla Firefox by
+ * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
+ * and Steve Workman <sjhworkman@gmail.com>).
+ * These changes are offered under the same license as the original NetBSD
+ * file, whose copyright and license are unchanged above.
+ */
+
+#ifndef _RESOLV_STATIC_H
+#define _RESOLV_STATIC_H
+
+#include <netdb.h>
+
+/* this structure contains all the variables that were declared
+ * 'static' in the original NetBSD resolver code.
+ *
+ * this caused vast amounts of crashes and memory corruptions
+ * when the resolver was being used by multiple threads.
+ *
+ * (note: the OpenBSD/FreeBSD resolver has similar 'issues')
+ */
+
+#define	MAXALIASES	35
+#define	MAXADDRS	35
+
+typedef struct res_static {
+    char*           h_addr_ptrs[MAXADDRS + 1];
+    char*           host_aliases[MAXALIASES];
+    char            hostbuf[8*1024];
+    u_int32_t       host_addr[16 / sizeof(u_int32_t)];  /* IPv4 or IPv6 */
+    FILE*           hostf;
+    int             stayopen;
+    const char*     servent_ptr;
+    struct servent  servent;
+    struct hostent  host;
+} *res_static;
+
+extern res_static __res_get_static(void);
+
+#endif /* _RESOLV_STATIC_H */
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -46,16 +46,20 @@
 #include "mozilla/arm.h"
 
 #ifdef MOZ_WIDGET_GTK2
 #include <gtk/gtk.h>
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
+
+extern "C" {
+extern int android_sdk_version;
+}
 #endif
 
 using namespace mozilla;
 
 nsSystemInfo::nsSystemInfo()
 {
 }
 
@@ -179,16 +183,17 @@ nsSystemInfo::Init()
         nsAutoString str;
         if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MODEL", str))
             SetPropertyAsAString(NS_LITERAL_STRING("device"), str);
         if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MANUFACTURER", str))
             SetPropertyAsAString(NS_LITERAL_STRING("manufacturer"), str);
         PRInt32 version;
         if (!mozilla::AndroidBridge::Bridge()->GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &version))
             version = 0;
+        android_sdk_version = version;
         if (version >= 8 && mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "HARDWARE", str))
             SetPropertyAsAString(NS_LITERAL_STRING("hardware"), str);
         SetPropertyAsAString(NS_LITERAL_STRING("shellName"), NS_LITERAL_STRING("Android"));
         if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "CODENAME", str)) {
             if (version) {
                 str.Append(NS_LITERAL_STRING(" ("));
                 str.AppendInt(version);
                 str.Append(NS_LITERAL_STRING(")"));