11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* $NetBSD: getaddrinfo.c,v 1.82 2006/03/25 12:09:40 rpaulo Exp $ */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */ 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved. 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * documentation and/or other materials provided with the distribution. 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. Neither the name of the project nor the names of its contributors 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * may be used to endorse or promote products derived from this software 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * without specific prior written permission. 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Issues to be discussed: 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - Thread safe-ness must be checked. 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - Return values. There are nonstandard return values defined and used 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * in the source code. This is because RFC2553 is silent about which error 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * code must be returned for which situation. 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * says to use inet_aton() to convert IPv4 numeric to binary (alows 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * classful form as a result). 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * current code - disallow classful form for IPv4 (due to use of inet_pton). 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * invalid. 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * current code - SEGV on freeaddrinfo(NULL) 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Note: 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - We use getipnodebyname() just for thread-safeness. There's no intent 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * getipnodebyname(). 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - The code filters out AFs that are not supported by the kernel, 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * when globbing NULL hostname (to loopback, or wildcard). Is it the right 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * in ai_flags? 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (1) what should we do against numeric hostname (2) what should we do 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * non-loopback address configured? global address configured? 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - To avoid search order issue, we have a big amount of code duplicate 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * from gethnamaddr.c and some other places. The issues that there's no 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * lower layer function to lookup "IPv4 or IPv6" record. Calling 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * gethostbyname2 from getaddrinfo will end up in wrong search order, as 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * follows: 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - The code makes use of following calls when asked to resolver with 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ai_family = PF_UNSPEC: 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * getipnodebyname(host, AF_INET6); 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * getipnodebyname(host, AF_INET); 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * This will result in the following queries if the node is configure to 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * prefer /etc/hosts than DNS: 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * lookup /etc/hosts for IPv6 address 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * lookup DNS for IPv6 address 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * lookup /etc/hosts for IPv4 address 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * lookup DNS for IPv4 address 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * which may not meet people's requirement. 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The right thing to happen is to have underlying layer which does 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * PF_UNSPEC lookup (lookup both) and return chain of addrinfos. 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * This would result in a bit of code duplicate with _dns_ghbyname() and 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * friends. 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 80a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick#include <fcntl.h> 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h> 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h> 83a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick#include <sys/stat.h> 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/param.h> 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h> 86a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick#include <sys/un.h> 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <net/if.h> 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h> 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <arpa/inet.h> 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "arpa_nameser.h" 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <assert.h> 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <ctype.h> 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netdb.h> 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h" 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stddef.h> 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h> 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h> 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h> 1002cc2b2be692f1d559a09d2066e56e450249cc9c0Carl Shapiro#include <strings.h> 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <unistd.h> 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <syslog.h> 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdarg.h> 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "nsswitch.h" 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1077858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick#ifdef ANDROID_CHANGES 1087858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick#include <sys/system_properties.h> 1097858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick#endif /* ANDROID_CHANGES */ 1107858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick 11150ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turnertypedef union sockaddr_union { 11250ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner struct sockaddr generic; 11350ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner struct sockaddr_in in; 11450ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner struct sockaddr_in6 in6; 11550ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner} sockaddr_union; 11650ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define SUCCESS 0 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define ANY 0 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define YES 1 1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define NO 0 1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char in_addrany[] = { 0, 0, 0, 0 }; 1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char in_loopback[] = { 127, 0, 0, 1 }; 1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char in6_addrany[] = { 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char in6_loopback[] = { 1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct afd { 1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_af; 1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_addrlen; 1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_socklen; 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_off; 1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *a_addrany; 1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *a_loopback; 1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_scoped; 1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} afdl [] = { 1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {PF_INET6, sizeof(struct in6_addr), 1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sizeof(struct sockaddr_in6), 1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project offsetof(struct sockaddr_in6, sin6_addr), 1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project in6_addrany, in6_loopback, 1}, 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {PF_INET, sizeof(struct in_addr), 1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sizeof(struct sockaddr_in), 1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project offsetof(struct sockaddr_in, sin_addr), 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project in_addrany, in_loopback, 0}, 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {0, 0, 0, 0, NULL, NULL, 0}, 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct explore { 1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int e_af; 1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int e_socktype; 1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int e_protocol; 1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *e_protostr; 1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int e_wild; 1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define WILD_AF(ex) ((ex)->e_wild & 0x01) 1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct explore explore[] = { 1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, 1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 }, 1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { -1, 0, 0, NULL, 0 }, 1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define PTON_MAX 16 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define PTON_MAX 4 1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const ns_src default_dns_files[] = { 191b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti { NSSRC_FILES, NS_SUCCESS }, 192b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti { NSSRC_DNS, NS_SUCCESS }, 1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 0, 0 } 1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define MAXPACKET (64*1024) 1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef union { 1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HEADER hdr; 2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char buf[MAXPACKET]; 2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} querybuf; 2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct res_target { 2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target *next; 2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *name; /* domain name */ 2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int qclass, qtype; /* class and type of query */ 2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *answer; /* buffer to put answer */ 2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int anslen; /* size of answer buffer */ 2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n; /* result length */ 2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int str2number(const char *); 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int explore_fqdn(const struct addrinfo *, const char *, 2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *, struct addrinfo **); 2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int explore_null(const struct addrinfo *, 2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *, struct addrinfo **); 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int explore_numeric(const struct addrinfo *, const char *, 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *, struct addrinfo **, const char *); 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int explore_numeric_scope(const struct addrinfo *, const char *, 2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *, struct addrinfo **); 2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int get_canonname(const struct addrinfo *, 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *, const char *); 2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo *get_ai(const struct addrinfo *, 2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *, const char *); 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int get_portmatch(const struct addrinfo *, const char *); 2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int get_port(const struct addrinfo *, const char *, int); 2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct afd *find_afd(int); 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); 2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo *getanswer(const querybuf *, int, const char *, int, 2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *); 2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int _dns_getaddrinfo(void *, void *, va_list); 2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void _sethtent(FILE **); 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void _endhtent(FILE **); 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo *_gethtent(FILE **, const char *, 2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *); 2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int _files_getaddrinfo(void *, void *, va_list); 2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int res_queryN(const char *, struct res_target *, res_state); 2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int res_searchN(const char *, struct res_target *, res_state); 2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int res_querydomainN(const char *, const char *, 2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target *, res_state); 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char * const ai_errlist[] = { 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Success", 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Temporary failure in name resolution", /* EAI_AGAIN */ 250b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "Invalid value for ai_flags", /* EAI_BADFLAGS */ 251b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "Non-recoverable failure in name resolution", /* EAI_FAIL */ 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "ai_family not supported", /* EAI_FAMILY */ 253b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "Memory allocation failure", /* EAI_MEMORY */ 254b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "No address associated with hostname", /* EAI_NODATA */ 2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "hostname nor servname provided, or not known", /* EAI_NONAME */ 2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "servname not supported for ai_socktype", /* EAI_SERVICE */ 257b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "ai_socktype not supported", /* EAI_SOCKTYPE */ 258b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "System error returned in errno", /* EAI_SYSTEM */ 2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Invalid value for hints", /* EAI_BADHINTS */ 2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Resolved protocol is unknown", /* EAI_PROTOCOL */ 2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Argument buffer overflow", /* EAI_OVERFLOW */ 262b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "Unknown error", /* EAI_MAX */ 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* XXX macros that make external reference is BAD. */ 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 267b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define GET_AI(ai, afd, addr) \ 268b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colittido { \ 269b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /* external reference: pai, error, and label free */ \ 270b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti (ai) = get_ai(pai, (afd), (addr)); \ 271b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti if ((ai) == NULL) { \ 272b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti error = EAI_MEMORY; \ 273b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti goto free; \ 274b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti } \ 2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (/*CONSTCOND*/0) 2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 277b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define GET_PORT(ai, serv) \ 278b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colittido { \ 279b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /* external reference: error and label free */ \ 280b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti error = get_port((ai), (serv), 0); \ 281b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti if (error != 0) \ 282b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti goto free; \ 2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (/*CONSTCOND*/0) 2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 285b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define GET_CANONNAME(ai, str) \ 286b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colittido { \ 287b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /* external reference: pai, error and label free */ \ 288b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti error = get_canonname(pai, (ai), (str)); \ 289b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti if (error != 0) \ 290b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti goto free; \ 2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (/*CONSTCOND*/0) 2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 293b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define ERR(err) \ 294b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colittido { \ 295b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /* external reference: error, and label bad */ \ 296b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti error = (err); \ 297b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti goto bad; \ 298b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /*NOTREACHED*/ \ 2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (/*CONSTCOND*/0) 3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 301b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define MATCH_FAMILY(x, y, w) \ 302b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \ 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (y) == PF_UNSPEC))) 304b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define MATCH(x, y, w) \ 3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectconst char * 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectgai_strerror(int ecode) 3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ecode < 0 || ecode > EAI_MAX) 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ecode = EAI_MAX; 3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ai_errlist[ecode]; 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfreeaddrinfo(struct addrinfo *ai) 3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *next; 3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(ai != NULL); 3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { 3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project next = ai->ai_next; 3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai->ai_canonname) 3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(ai->ai_canonname); 3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* no need to free(ai->ai_addr) */ 3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(ai); 3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = next; 3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } while (ai); 3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstr2number(const char *p) 3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *ep; 3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned long v; 3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(p != NULL); 3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*p == '\0') 3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ep = NULL; 3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = 0; 3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v = strtoul(p, &ep, 10); 3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) 3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return v; 3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 351ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti/* 352ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * Connect a UDP socket to a given unicast address. This will cause no network 353ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * traffic, but will fail fast if the system has no or limited reachability to 354ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * the destination (e.g., no IPv4 address, no IPv6 default route, ...). 355ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti */ 3563d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colittistatic int 357ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti_test_connect(int pf, struct sockaddr *addr, size_t addrlen) { 358ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti int s = socket(pf, SOCK_DGRAM, IPPROTO_UDP); 3593d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti if (s < 0) 3603d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti return 0; 3613d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti int ret; 3623d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti do { 363ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti ret = connect(s, addr, addrlen); 3643d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti } while (ret < 0 && errno == EINTR); 365ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti int success = (ret == 0); 3663d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti do { 3673d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti ret = close(s); 3683d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti } while (ret < 0 && errno == EINTR); 369ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti return success; 370ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti} 371ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti 372ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti/* 373ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * The following functions determine whether IPv4 or IPv6 connectivity is 374ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * available in order to implement AI_ADDRCONFIG. 375ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * 376ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * Strictly speaking, AI_ADDRCONFIG should not look at whether connectivity is 377ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * available, but whether addresses of the specified family are "configured 378ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * on the local system". However, bionic doesn't currently support getifaddrs, 379ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * so checking for connectivity is the next best thing. 380ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti */ 381ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colittistatic int 382b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti_have_ipv6() { 383b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti static const struct sockaddr_in6 sin6_test = { 384b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti .sin6_family = AF_INET6, 385b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti .sin6_addr.s6_addr = { // 2000:: 386b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 387b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti }; 388b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti sockaddr_union addr = { .in6 = sin6_test }; 389b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6)); 390ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti} 391ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti 392ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colittistatic int 393b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti_have_ipv4() { 394b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti static const struct sockaddr_in sin_test = { 395b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti .sin_family = AF_INET, 396b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti .sin_addr.s_addr = __constant_htonl(0x08080808L) // 8.8.8.8 397b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti }; 398b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti sockaddr_union addr = { .in = sin_test }; 399b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti return _test_connect(PF_INET, &addr.generic, sizeof(addr.in)); 4003d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti} 4013d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti 402a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick// Returns 0 on success, else returns non-zero on error (in which case 403a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick// getaddrinfo should continue as normal) 404a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrickstatic int 405a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrickandroid_getaddrinfo_proxy( 406a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick const char *hostname, const char *servname, 407a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick const struct addrinfo *hints, struct addrinfo **res) 408a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick{ 409a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick int sock; 410a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick const int one = 1; 411a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct sockaddr_un proxy_addr; 412a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick const char* cache_mode = getenv("ANDROID_DNS_MODE"); 413a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick FILE* proxy = NULL; 414a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick int success = 0; 415a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 416a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Clear this at start, as we use its non-NULLness later (in the 417a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // error path) to decide if we have to free up any memory we 418a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // allocated in the process (before failing). 419a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick *res = NULL; 420a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 421a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) { 422a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Don't use the proxy in local mode. This is used by the 423a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // proxy itself. 424a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 425a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 426a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 4277858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick // Temporary cautious hack to disable the DNS proxy for processes 4287858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick // requesting special treatment. Ideally the DNS proxy should 4297858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick // accomodate these apps, though. 4307858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick char propname[PROP_NAME_MAX]; 4317858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick char propvalue[PROP_VALUE_MAX]; 4327858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick snprintf(propname, sizeof(propname), "net.dns1.%d", getpid()); 4337858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick if (__system_property_get(propname, propvalue) > 0) { 4347858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick return -1; 4357858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick } 4367858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick 437a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Bogus things we can't serialize. Don't use the proxy. 438a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if ((hostname != NULL && 439a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick strcspn(hostname, " \n\r\t^'\"") != strlen(hostname)) || 440a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick (servname != NULL && 441a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick strcspn(servname, " \n\r\t^'\"") != strlen(servname))) { 442a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 443a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 444a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 445a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick sock = socket(AF_UNIX, SOCK_STREAM, 0); 446a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (sock < 0) { 447a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 448a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 449a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 450a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 451a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick memset(&proxy_addr, 0, sizeof(proxy_addr)); 452a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick proxy_addr.sun_family = AF_UNIX; 453a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", 454a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick sizeof(proxy_addr.sun_path)); 455a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (TEMP_FAILURE_RETRY(connect(sock, 456a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick (const struct sockaddr*) &proxy_addr, 457a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick sizeof(proxy_addr))) != 0) { 458a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick close(sock); 459a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 460a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 461a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 462a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Send the request. 463a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick proxy = fdopen(sock, "r+"); 464a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d", 465a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hostname == NULL ? "^" : hostname, 466a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick servname == NULL ? "^" : servname, 467a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hints == NULL ? -1 : hints->ai_flags, 468a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hints == NULL ? -1 : hints->ai_family, 469a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hints == NULL ? -1 : hints->ai_socktype, 470a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hints == NULL ? -1 : hints->ai_protocol) < 0) { 471a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick goto exit; 472a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 473a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // literal NULL byte at end, required by FrameworkListener 474a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fputc(0, proxy) == EOF || 475a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick fflush(proxy) != 0) { 476a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick goto exit; 477a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 478a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 479a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick int remote_rv; 480a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(&remote_rv, sizeof(int), 1, proxy) != 1) { 481a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick goto exit; 482a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 483a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 484a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (remote_rv != 0) { 485a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick goto exit; 486a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 487a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 488a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct addrinfo* ai = NULL; 489a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct addrinfo** nextres = res; 490a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick while (1) { 491a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick uint32_t addrinfo_len; 492a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(&addrinfo_len, sizeof(addrinfo_len), 493a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 1, proxy) != 1) { 494a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 495a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 496a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick addrinfo_len = ntohl(addrinfo_len); 497a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (addrinfo_len == 0) { 498a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick success = 1; 499a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 500a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 501a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 502a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (addrinfo_len < sizeof(struct addrinfo)) { 503a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 504a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 505a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct addrinfo* ai = calloc(1, addrinfo_len + 506a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick sizeof(struct sockaddr_storage)); 507a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (ai == NULL) { 508a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 509a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 510a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 511a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(ai, addrinfo_len, 1, proxy) != 1) { 512a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Error; fall through. 513a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 514a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 515a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 516a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Zero out the pointer fields we copied which aren't 517a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // valid in this address space. 518a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_addr = NULL; 519a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_canonname = NULL; 520a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_next = NULL; 521a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 522a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // struct sockaddr 523a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick uint32_t addr_len; 524a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(&addr_len, sizeof(addr_len), 1, proxy) != 1) { 525a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 526a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 527a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick addr_len = ntohl(addr_len); 528a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (addr_len != 0) { 529a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (addr_len > sizeof(struct sockaddr_storage)) { 530a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Bogus; too big. 531a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 532a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 533a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct sockaddr* addr = (struct sockaddr*)(ai + 1); 534a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(addr, addr_len, 1, proxy) != 1) { 535a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 536a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 537a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_addr = addr; 538a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 539a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 540a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // cannonname 541a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick uint32_t name_len; 542a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) { 543a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 544a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 5450ee092fb23318bc479de8e6514fbf2e05e0ce646Mattias Falk name_len = ntohl(name_len); 546a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (name_len != 0) { 547a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_canonname = (char*) malloc(name_len); 548a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(ai->ai_canonname, name_len, 1, proxy) != 1) { 549a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 550a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 551a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (ai->ai_canonname[name_len - 1] != '\0') { 552a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // The proxy should be returning this 553a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // NULL-terminated. 554a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 555a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 556a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 557a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 558a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick *nextres = ai; 559a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick nextres = &ai->ai_next; 560a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai = NULL; 561a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 562a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 563a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (ai != NULL) { 564a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Clean up partially-built addrinfo that we never ended up 565a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // attaching to the response. 566a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick freeaddrinfo(ai); 567a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 568a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrickexit: 569a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (proxy != NULL) { 570a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick fclose(proxy); 571a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 572a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 573a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (success) { 574a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return 0; 575a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 576a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 577a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Proxy failed; fall through to local 578a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // resolver case. But first clean up any 579a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // memory we might've allocated. 580a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (*res) { 581a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick freeaddrinfo(*res); 582a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick *res = NULL; 583a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 584a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 585a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick} 586a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 5881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectgetaddrinfo(const char *hostname, const char *servname, 5891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *hints, struct addrinfo **res) 5901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel; 5921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error = 0; 5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo ai; 5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo ai0; 5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *pai; 5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct explore *ex; 5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hostname is allowed to be NULL */ 6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname is allowed to be NULL */ 6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hints is allowed to be NULL */ 6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&sentinel, 0, sizeof(sentinel)); 6051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai = &ai; 6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_flags = 0; 6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family = PF_UNSPEC; 6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_socktype = ANY; 6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_protocol = ANY; 6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_addrlen = 0; 6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_canonname = NULL; 6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_addr = NULL; 6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_next = NULL; 6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hostname == NULL && servname == NULL) 6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_NONAME; 6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hints) { 6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* error check for hints */ 6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hints->ai_addrlen || hints->ai_canonname || 6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hints->ai_addr || hints->ai_next) 6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_BADHINTS); /* xxx */ 6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hints->ai_flags & ~AI_MASK) 6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_BADFLAGS); 6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (hints->ai_family) { 6261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case PF_UNSPEC: 6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case PF_INET: 6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case PF_INET6: 6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_FAMILY); 6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(pai, hints, sizeof(*pai)); 6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if both socktype/protocol are specified, check if they 6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are meaningful combination. 6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (ex = explore; ex->e_af >= 0; ex++) { 6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family != ex->e_af) 6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ex->e_socktype == ANY) 6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ex->e_protocol == ANY) 6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_socktype == ex->e_socktype 6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project && pai->ai_protocol != ex->e_protocol) { 6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_BADHINTS); 6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * check for special cases. (1) numeric servname is disallowed if 6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * socktype/protocol are left unspecified. (2) servname is disallowed 6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * for raw and other inet{,6} sockets. 6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef PF_INET6 6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ) { 6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai0 = *pai; /* backup *pai */ 6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family == PF_UNSPEC) { 6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef PF_INET6 6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family = PF_INET6; 6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family = PF_INET; 6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = get_portmatch(pai, servname); 6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error) 6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(error); 6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *pai = ai0; 6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai0 = *pai; 6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* NULL hostname, or numeric hostname */ 6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (ex = explore; ex->e_af >= 0; ex++) { 6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *pai = ai0; 6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* PF_UNSPEC entries are prepared for DNS queries only */ 6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ex->e_af == PF_UNSPEC) 6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family == PF_UNSPEC) 7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family = ex->e_af; 7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_socktype = ex->e_socktype; 7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_protocol = ex->e_protocol; 7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hostname == NULL) 7081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = explore_null(pai, servname, &cur->ai_next); 7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = explore_numeric_scope(pai, hostname, servname, 7111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project &cur->ai_next); 7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error) 7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur->ai_next) 7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * XXX 7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If numeric representation of AF1 can be interpreted as FQDN 7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * representation of AF2, we need to think again about the code below. 7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto good; 7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hostname == NULL) 7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_NODATA); 7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_flags & AI_NUMERICHOST) 7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_NONAME); 7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 733a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick /* 734a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick * BEGIN ANDROID CHANGES; proxying to the cache 735a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick */ 736a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (android_getaddrinfo_proxy(hostname, servname, hints, res) == 0) { 737a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return 0; 738a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 739a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 7401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 7411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * hostname as alphabetical name. 7421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * we would like to prefer AF_INET6 than AF_INET, so we'll make a 7431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * outer loop by AFs. 7441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (ex = explore; ex->e_af >= 0; ex++) { 7461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *pai = ai0; 7471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* require exact match for family field */ 7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family != ex->e_af) 7501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH(pai->ai_socktype, ex->e_socktype, 7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project WILD_SOCKTYPE(ex))) { 7541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH(pai->ai_protocol, ex->e_protocol, 7571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project WILD_PROTOCOL(ex))) { 7581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_socktype = ex->e_socktype; 7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 7641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_protocol = ex->e_protocol; 7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = explore_fqdn(pai, hostname, servname, 7671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project &cur->ai_next); 7681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 7701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 7711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX */ 7741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 7751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = 0; 7761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error) 7781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 7791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error == 0) { 7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) { 7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project good: 7821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = sentinel.ai_next; 7831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return SUCCESS; 7841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 7851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = EAI_FAIL; 7861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free: 7881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bad: 7891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 7901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(sentinel.ai_next); 7911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = NULL; 7921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 7931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 7941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 7961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FQDN hostname, DNS lookup 7971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 7991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexplore_fqdn(const struct addrinfo *pai, const char *hostname, 8001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *servname, struct addrinfo **res) 8011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 8021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *result; 8031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 8041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error = 0; 8051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project static const ns_dtab dtab[] = { 8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project NS_FILES_CB(_files_getaddrinfo, NULL) 8071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ 8081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project NS_NIS_CB(_yp_getaddrinfo, NULL) 8091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 0, 0, 0 } 8101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project }; 8111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 8131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hostname may be NULL */ 8141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 8151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 8161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = NULL; 8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 8201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if the servname does not match socktype/protocol, ignore it. 8211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_portmatch(pai, servname) != 0) 8231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 8241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", 8261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default_dns_files, hostname, pai)) { 8271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_TRYAGAIN: 8281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = EAI_AGAIN; 8291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 8301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_UNAVAIL: 8311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = EAI_FAIL; 8321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 8331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_NOTFOUND: 8341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = EAI_NODATA; 8351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 8361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_SUCCESS: 8371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = 0; 8381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cur = result; cur; cur = cur->ai_next) { 8391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur, servname); 8401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* canonname should be filled already */ 8411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 8421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 8431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 8441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = result; 8461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 8481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfree: 8501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (result) 8511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(result); 8521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 8531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 8541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 8561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * hostname == NULL. 8571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * passive socket -> anyaddr (0.0.0.0 or ::) 8581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * non-passive socket -> localhost (127.0.0.1 or ::1) 8591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 8611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexplore_null(const struct addrinfo *pai, const char *servname, 8621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo **res) 8631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 8641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int s; 8651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 8661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 8671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel; 8681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 8691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 8711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 8721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 8731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = NULL; 8751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sentinel.ai_next = NULL; 8761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 8771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 8791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * filter out AFs that are not supported by the kernel 8801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * XXX errno? 8811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project s = socket(pai->ai_family, SOCK_DGRAM, 0); 8831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (s < 0) { 8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno != EMFILE) 8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project close(s); 8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if the servname does not match socktype/protocol, ignore it. 8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_portmatch(pai, servname) != 0) 8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afd = find_afd(pai->ai_family); 8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd == NULL) 8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_flags & AI_PASSIVE) { 9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_AI(cur->ai_next, afd, afd->a_addrany); 9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* xxx meaningless? 9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * GET_CANONNAME(cur->ai_next, "anyaddr"); 9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur->ai_next, servname); 9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_AI(cur->ai_next, afd, afd->a_loopback); 9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* xxx meaningless? 9081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * GET_CANONNAME(cur->ai_next, "localhost"); 9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur->ai_next, servname); 9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = sentinel.ai_next; 9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfree: 9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(sentinel.ai_next); 9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 9241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * numeric hostname 9251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 9271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexplore_numeric(const struct addrinfo *pai, const char *hostname, 9281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *servname, struct addrinfo **res, const char *canonname) 9291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 9301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 9311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 9321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel; 9331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 9341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char pton[PTON_MAX]; 9351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 9371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hostname may be NULL */ 9381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 9391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 9401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = NULL; 9421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sentinel.ai_next = NULL; 9431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 9441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 9461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if the servname does not match socktype/protocol, ignore it. 9471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_portmatch(pai, servname) != 0) 9491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 9501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afd = find_afd(pai->ai_family); 9521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd == NULL) 9531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 9541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (afd->a_af) { 9561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 /*X/Open spec*/ 9571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 9581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (inet_aton(hostname, (struct in_addr *)pton) == 1) { 9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family == afd->a_af || 9601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family == PF_UNSPEC /*?*/) { 9611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_AI(cur->ai_next, afd, pton); 9621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur->ai_next, servname); 9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((pai->ai_flags & AI_CANONNAME)) { 9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 9651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Set the numeric address itself as 9661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the canonical name, based on a 9671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * clarification in rfc2553bis-03. 9681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_CANONNAME(cur->ai_next, canonname); 9701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 9721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 9731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 9741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_FAMILY); /*xxx*/ 9751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 9771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 9781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 9791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (inet_pton(afd->a_af, hostname, pton) == 1) { 9801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family == afd->a_af || 9811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family == PF_UNSPEC /*?*/) { 9821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_AI(cur->ai_next, afd, pton); 9831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur->ai_next, servname); 9841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((pai->ai_flags & AI_CANONNAME)) { 9851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 9861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Set the numeric address itself as 9871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the canonical name, based on a 9881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * clarification in rfc2553bis-03. 9891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_CANONNAME(cur->ai_next, canonname); 9911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur->ai_next) 9931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 9941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 9951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_FAMILY); /*xxx*/ 9961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 9981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = sentinel.ai_next; 10011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 10021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfree: 10041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectbad: 10051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 10061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(sentinel.ai_next); 10071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 10081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 10091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 10111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * numeric hostname with scope 10121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 10131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 10141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexplore_numeric_scope(const struct addrinfo *pai, const char *hostname, 10151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *servname, struct addrinfo **res) 10161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 10171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if !defined(SCOPE_DELIMITER) || !defined(INET6) 10181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return explore_numeric(pai, hostname, servname, res, hostname); 10191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 10201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 10211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 10221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 10231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *cp, *hostname2 = NULL, *scope, *addr; 10241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct sockaddr_in6 *sin6; 10251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 10271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hostname may be NULL */ 10281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 10291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 10301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 10321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if the servname does not match socktype/protocol, ignore it. 10331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 10341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_portmatch(pai, servname) != 0) 10351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 10361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afd = find_afd(pai->ai_family); 10381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd == NULL) 10391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 10401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!afd->a_scoped) 10421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return explore_numeric(pai, hostname, servname, res, hostname); 10431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = strchr(hostname, SCOPE_DELIMITER); 10451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cp == NULL) 10461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return explore_numeric(pai, hostname, servname, res, hostname); 10471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 10491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Handle special case of <scoped_address><delimiter><scope id> 10501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 10511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hostname2 = strdup(hostname); 10521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hostname2 == NULL) 10531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_MEMORY; 10541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* terminate at the delimiter */ 10551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hostname2[cp - hostname] = '\0'; 10561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project addr = hostname2; 10571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project scope = cp + 1; 10581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = explore_numeric(pai, addr, servname, res, hostname); 10601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error == 0) { 10611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int32_t scopeid; 10621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cur = *res; cur; cur = cur->ai_next) { 10641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cur->ai_family != AF_INET6) 10651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 10661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; 10671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { 10681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(hostname2); 10691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EAI_NODATA); /* XXX: is return OK? */ 10701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sin6->sin6_scope_id = scopeid; 10721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(hostname2); 10761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 10781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 10791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 10801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 10821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) 10831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 10841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 10861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(ai != NULL); 10871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(str != NULL); 10881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((pai->ai_flags & AI_CANONNAME) != 0) { 10901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_canonname = strdup(str); 10911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai->ai_canonname == NULL) 10921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_MEMORY; 10931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 10951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 10961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo * 10981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) 10991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 11001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *p; 11011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *ai; 11021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 11041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(afd != NULL); 11051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(addr != NULL); 11061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) 11081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project + (afd->a_socklen)); 11091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai == NULL) 11101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 11111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(ai, pai, sizeof(struct addrinfo)); 11131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); 11141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(ai->ai_addr, 0, (size_t)afd->a_socklen); 11151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAVE_SA_LEN 11171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr->sa_len = afd->a_socklen; 11181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 11191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addrlen = afd->a_socklen; 11211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if defined (__alpha__) || (defined(__i386__) && defined(_LP64)) || defined(__sparc64__) 11221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->__ai_pad0 = 0; 11231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 11241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 11251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p = (char *)(void *)(ai->ai_addr); 11261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); 11271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ai; 11281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 11311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_portmatch(const struct addrinfo *ai, const char *servname) 11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(ai != NULL); 11351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return get_port(ai, servname, 1); 11381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 11391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 11411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_port(const struct addrinfo *ai, const char *servname, int matchonly) 11421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *proto; 11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct servent *sp; 11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int port; 11461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int allownumeric; 11471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(ai != NULL); 11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 11501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (servname == NULL) 11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ai->ai_family) { 11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 11551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef AF_INET6 11561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 11571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 11591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 11601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 11611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ai->ai_socktype) { 11641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_RAW: 11651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SERVICE; 11661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_DGRAM: 11671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_STREAM: 11681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project allownumeric = 1; 11691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 11701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case ANY: 11719ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson#if 1 /* ANDROID-SPECIFIC CHANGE TO MATCH GLIBC */ 11725e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner allownumeric = 1; 11735e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner#else 11741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project allownumeric = 0; 11755e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner#endif 11761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 11771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 11781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SOCKTYPE; 11791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project port = str2number(servname); 11821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (port >= 0) { 11831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!allownumeric) 11841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SERVICE; 11851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (port < 0 || port > 65535) 11861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SERVICE; 11871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project port = htons(port); 11881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 11891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai->ai_flags & AI_NUMERICSERV) 11901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_NONAME; 11911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ai->ai_socktype) { 11931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_DGRAM: 11941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project proto = "udp"; 11951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 11961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_STREAM: 11971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project proto = "tcp"; 11981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 11991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 12001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project proto = NULL; 12011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 12021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((sp = getservbyname(servname, proto)) == NULL) 12051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SERVICE; 12061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project port = sp->s_port; 12071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!matchonly) { 12101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ai->ai_family) { 12111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 12121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((struct sockaddr_in *)(void *) 12131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr)->sin_port = port; 12141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 12151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 12161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 12171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((struct sockaddr_in6 *)(void *) 12181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr)->sin6_port = port; 12191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 12201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 12211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 12251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 12261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct afd * 12281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfind_afd(int af) 12291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 12301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 12311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (af == PF_UNSPEC) 12331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 12341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (afd = afdl; afd->a_af; afd++) { 12351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd->a_af == af) 12361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return afd; 12371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 12391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 12401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 12421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* convert a string to a scope identifier. XXX: IPv6 specific */ 12431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 12441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) 12451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 12461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_long lscopeid; 12471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct in6_addr *a6; 12481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *ep; 12491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(scope != NULL); 12511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(sin6 != NULL); 12521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(scopeid != NULL); 12531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project a6 = &sin6->sin6_addr; 12551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* empty scopeid portion is invalid */ 12571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*scope == '\0') 12581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 12591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { 12611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 12621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * We currently assume a one-to-one mapping between links 12631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * and interfaces, so we simply use interface indices for 12641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * like-local scopes. 12651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 12661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *scopeid = if_nametoindex(scope); 12671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*scopeid == 0) 12681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto trynumeric; 12691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 12701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* still unclear about literal, allow numeric only - placeholder */ 12731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) 12741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto trynumeric; 12751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) 12761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto trynumeric; 12771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 12781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto trynumeric; /* global */ 12791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* try to convert to a numeric id as a last resort */ 12811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project trynumeric: 12821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = 0; 12831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lscopeid = strtoul(scope, &ep, 10); 12841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); 12851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) 12861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 12871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 12881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 12891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 12901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 12911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* code duplicate with gethnamaddr.c */ 12931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char AskedForGot[] = 12951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 12961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo * 12981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectgetanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 12991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *pai) 13001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 13011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel, *cur; 13021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo ai; 13031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 13041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *canonname; 13051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const HEADER *hp; 13061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *cp; 13071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n; 13081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *eom; 13091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *bp, *ep; 13101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int type, class, ancount, qdcount; 13111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int haveanswer, had_error; 13121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char tbuf[MAXDNAME]; 13131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int (*name_ok) (const char *); 13141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char hostbuf[8*1024]; 13151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(answer != NULL); 13171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(qname != NULL); 13181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 13191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&sentinel, 0, sizeof(sentinel)); 13211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 13221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project canonname = NULL; 13241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eom = answer->buf + anslen; 13251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (qtype) { 13261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_A: 13271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_AAAA: 13281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ 13291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project name_ok = res_hnok; 13301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 13311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 13321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; /* XXX should be abort(); */ 13331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 13351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * find first satisfactory answer 13361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 13371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hp = &answer->hdr; 13381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ancount = ntohs(hp->ancount); 13391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project qdcount = ntohs(hp->qdcount); 13401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp = hostbuf; 13411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ep = hostbuf + sizeof hostbuf; 13421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = answer->buf + HFIXEDSZ; 13431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (qdcount != 1) { 13441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 13451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 13461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 13481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n < 0) || !(*name_ok)(bp)) { 13491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 13501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 13511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n + QFIXEDSZ; 13531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 13541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* res_send() has already verified that the query name is the 13551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * same as the one we sent; this just gets the expanded name 13561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (i.e., with the succeeding search-domain tacked on). 13571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 13581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = strlen(bp) + 1; /* for the \0 */ 13591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n >= MAXHOSTNAMELEN) { 13601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 13611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 13621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project canonname = bp; 13641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp += n; 13651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* The qname can be abbreviated, but h_name is now absolute. */ 13661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project qname = canonname; 13671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project haveanswer = 0; 13691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error = 0; 13701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (ancount-- > 0 && cp < eom && !had_error) { 13711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 13721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n < 0) || !(*name_ok)(bp)) { 13731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error++; 13741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 13751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; /* name */ 13771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project type = _getshort(cp); 1378b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti cp += INT16SZ; /* type */ 13791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project class = _getshort(cp); 1380b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti cp += INT16SZ + INT32SZ; /* class, TTL */ 13811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = _getshort(cp); 13821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += INT16SZ; /* len */ 13831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (class != C_IN) { 13841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX - debug? syslog? */ 13851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 13861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; /* XXX - had_error++ ? */ 13871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 13891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project type == T_CNAME) { 13901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 13911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n < 0) || !(*name_ok)(tbuf)) { 13921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error++; 13931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 13941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 13961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Get canonical name. */ 13971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = strlen(tbuf) + 1; /* for the \0 */ 13981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n > ep - bp || n >= MAXHOSTNAMELEN) { 13991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error++; 14001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strlcpy(bp, tbuf, (size_t)(ep - bp)); 14031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project canonname = bp; 14041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp += n; 14051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (qtype == T_ANY) { 14081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(type == T_A || type == T_AAAA)) { 14091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (type != qtype) { 14131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (type != T_KEY && type != T_SIG) 14141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project syslog(LOG_NOTICE|LOG_AUTH, 14151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 14161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project qname, p_class(C_IN), p_type(qtype), 14171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p_type(type)); 14181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; /* XXX - had_error++ ? */ 14201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (type) { 14221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_A: 14231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_AAAA: 14241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (strcasecmp(canonname, bp) != 0) { 14251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project syslog(LOG_NOTICE|LOG_AUTH, 14261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project AskedForGot, canonname, bp); 14271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; /* XXX - had_error++ ? */ 14291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (type == T_A && n != INADDRSZ) { 14311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (type == T_AAAA && n != IN6ADDRSZ) { 14351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (type == T_AAAA) { 14391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct in6_addr in6; 14401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(&in6, cp, IN6ADDRSZ); 14411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_V4MAPPED(&in6)) { 14421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!haveanswer) { 14471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int nn; 14481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project canonname = bp; 14501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project nn = strlen(bp) + 1; /* for the \0 */ 14511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp += nn; 14521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* don't overwrite pai */ 14551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = *pai; 14561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; 14571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afd = find_afd(ai.ai_family); 14581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd == NULL) { 14591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur->ai_next = get_ai(&ai, afd, (const char *)cp); 14631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cur->ai_next == NULL) 14641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error++; 14651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 14661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 14671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 14691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 14701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project abort(); 14711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!had_error) 14731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project haveanswer++; 14741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (haveanswer) { 14761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!canonname) 14771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)get_canonname(pai, sentinel.ai_next, qname); 14781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 14791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)get_canonname(pai, sentinel.ai_next, canonname); 14801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NETDB_SUCCESS; 14811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return sentinel.ai_next; 14821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 14851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 14861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 14871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14889ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstruct addrinfo_sort_elem { 14899ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson struct addrinfo *ai; 14909ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int has_src_addr; 149150ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner sockaddr_union src_addr; 14929ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int original_order; 14939ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson}; 14941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14959ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 14969ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 14979ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_get_scope(const struct sockaddr *addr) 14981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 14999ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (addr->sa_family == AF_INET6) { 15009ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; 15019ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) { 15029ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_MC_SCOPE(&addr6->sin6_addr); 15039ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) || 15049ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) { 15059ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 15069ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * RFC 4291 section 2.5.3 says loopback is to be treated as having 15079ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * link-local scope. 15089ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 15099ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_LINKLOCAL; 15109ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) { 15119ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_SITELOCAL; 15129ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 15139ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_GLOBAL; 15149ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15159ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (addr->sa_family == AF_INET) { 15169ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; 15179ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson unsigned long int na = ntohl(addr4->sin_addr.s_addr); 15189ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15199ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (IN_LOOPBACK(na) || /* 127.0.0.0/8 */ 15209ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson (na & 0xffff0000) == 0xa9fe0000) { /* 169.254.0.0/16 */ 15219ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_LINKLOCAL; 15229ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 1523d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson /* 1524d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson * According to draft-ietf-6man-rfc3484-revise-01 section 2.3, 1525d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson * it is best not to treat the private IPv4 ranges 1526d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson * (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) as being 1527d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson * in a special scope, so we don't. 1528d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson */ 15299ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_GLOBAL; 15309ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15319ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 15329ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 15339ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * This should never happen. 15349ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Return a scope with low priority as a last resort. 15359ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 15369ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_NODELOCAL; 15379ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15389ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 15399ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15409ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* These macros are modelled after the ones in <netinet/in6.h>. */ 15419ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15429ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* RFC 4380, section 2.6 */ 15439ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson#define IN6_IS_ADDR_TEREDO(a) \ 15449ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson ((*(const uint32_t *)(const void *)(&(a)->s6_addr[0]) == ntohl(0x20010000))) 15459ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15469ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* RFC 3056, section 2. */ 15479ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson#define IN6_IS_ADDR_6TO4(a) \ 15489ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson (((a)->s6_addr[0] == 0x20) && ((a)->s6_addr[1] == 0x02)) 15499ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15502e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson/* 6bone testing address area (3ffe::/16), deprecated in RFC 3701. */ 15512e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson#define IN6_IS_ADDR_6BONE(a) \ 15522e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson (((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe)) 15532e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson 15549ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 15559ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Get the label for a given IPv4/IPv6 address. 15562e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01. 15579ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 15589ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15599ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 15609ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 15619ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_get_label(const struct sockaddr *addr) 15629ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 15639ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (addr->sa_family == AF_INET) { 15642e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 3; 15659ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (addr->sa_family == AF_INET6) { 15669ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; 15679ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) { 15689ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 0; 15692e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) { 15702e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 1; 15712e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) { 15729ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 3; 15732e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) { 15742e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 4; 15759ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) { 15769ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 5; 15772e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) { 15782e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 10; 15792e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) { 15802e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 11; 15812e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) { 15822e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 12; 15839ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 15842e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 2; 15859ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15869ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 15879ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 15889ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * This should never happen. 15899ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Return a semi-random label as a last resort. 15909ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 15919ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 1; 15929ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15939ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 15949ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15959ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 15969ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Get the precedence for a given IPv4/IPv6 address. 15972e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01. 15989ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 15999ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16009ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 16019ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 16029ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_get_precedence(const struct sockaddr *addr) 16039ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 16049ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (addr->sa_family == AF_INET) { 16052e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 30; 16069ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (addr->sa_family == AF_INET6) { 16079ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; 16089ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) { 16092e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 60; 16102e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) { 16119ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 50; 16122e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) { 16132e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 30; 16142e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) { 16159ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 20; 16169ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) { 16172e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 10; 16182e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) || 1619b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) || 1620b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) { 16212e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 1; 16229ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 16239ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 40; 16249ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 16259ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 16262e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 1; 16279ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 16289ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 16299ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16309ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 16319ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Find number of matching initial bits between the two addresses a1 and a2. 16329ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 16339ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16349ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 16359ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 16369ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_common_prefix_len(const struct in6_addr *a1, const struct in6_addr *a2) 16379ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 16389ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const char *p1 = (const char *)a1; 16399ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const char *p2 = (const char *)a2; 16409ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson unsigned i; 16419ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16429ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson for (i = 0; i < sizeof(*a1); ++i) { 16439ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int x, j; 16449ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16459ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (p1[i] == p2[i]) { 16469ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson continue; 16479ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 16489ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson x = p1[i] ^ p2[i]; 16499ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson for (j = 0; j < CHAR_BIT; ++j) { 16509ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (x & (1 << (CHAR_BIT - 1))) { 16519ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return i * CHAR_BIT + j; 16521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 16539ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson x <<= 1; 16541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 16551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 16569ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return sizeof(*a1) * CHAR_BIT; 16579ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 16589ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16599ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 16609ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Compare two source/destination address pairs. 16619ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * RFC 3484, section 6. 16629ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 16639ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16649ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 16659ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 16669ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_rfc3484_compare(const void *ptr1, const void* ptr2) 16679ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 16689ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct addrinfo_sort_elem *a1 = (const struct addrinfo_sort_elem *)ptr1; 16699ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct addrinfo_sort_elem *a2 = (const struct addrinfo_sort_elem *)ptr2; 16709ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int scope_src1, scope_dst1, scope_match1; 16719ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int scope_src2, scope_dst2, scope_match2; 16729ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int label_src1, label_dst1, label_match1; 16739ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int label_src2, label_dst2, label_match2; 16749ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int precedence1, precedence2; 16759ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int prefixlen1, prefixlen2; 16769ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16779ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 1: Avoid unusable destinations. */ 16789ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (a1->has_src_addr != a2->has_src_addr) { 16799ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return a2->has_src_addr - a1->has_src_addr; 16809ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 16819ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16829ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 2: Prefer matching scope. */ 168350ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner scope_src1 = _get_scope(&a1->src_addr.generic); 16849ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson scope_dst1 = _get_scope(a1->ai->ai_addr); 16859ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson scope_match1 = (scope_src1 == scope_dst1); 16869ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 168750ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner scope_src2 = _get_scope(&a2->src_addr.generic); 16889ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson scope_dst2 = _get_scope(a2->ai->ai_addr); 16899ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson scope_match2 = (scope_src2 == scope_dst2); 16909ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16919ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (scope_match1 != scope_match2) { 16929ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return scope_match2 - scope_match1; 16939ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 16949ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16959ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 16969ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 3: Avoid deprecated addresses. 16979ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * TODO(sesse): We don't currently have a good way of finding this. 16989ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 16999ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17009ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 17019ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 4: Prefer home addresses. 17029ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * TODO(sesse): We don't currently have a good way of finding this. 17039ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17049ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17059ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 5: Prefer matching label. */ 170650ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner label_src1 = _get_label(&a1->src_addr.generic); 17079ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson label_dst1 = _get_label(a1->ai->ai_addr); 17089ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson label_match1 = (label_src1 == label_dst1); 17099ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 171050ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner label_src2 = _get_label(&a2->src_addr.generic); 17119ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson label_dst2 = _get_label(a2->ai->ai_addr); 17129ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson label_match2 = (label_src2 == label_dst2); 17139ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17149ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (label_match1 != label_match2) { 17159ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return label_match2 - label_match1; 17169ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17179ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17189ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 6: Prefer higher precedence. */ 17199ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson precedence1 = _get_precedence(a1->ai->ai_addr); 17209ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson precedence2 = _get_precedence(a2->ai->ai_addr); 17219ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (precedence1 != precedence2) { 17229ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return precedence2 - precedence1; 17239ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17249ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17259ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 17269ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 7: Prefer native transport. 17279ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * TODO(sesse): We don't currently have a good way of finding this. 17289ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17299ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17309ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 8: Prefer smaller scope. */ 17319ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (scope_dst1 != scope_dst2) { 17329ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return scope_dst1 - scope_dst2; 17339ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17349ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17359ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 17369ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 9: Use longest matching prefix. 17379ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * We implement this for IPv6 only, as the rules in RFC 3484 don't seem 17389ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * to work very well directly applied to IPv4. (glibc uses information from 17399ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * the routing table for a custom IPv4 implementation here.) 17409ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17419ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (a1->has_src_addr && a1->ai->ai_addr->sa_family == AF_INET6 && 17429ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson a2->has_src_addr && a2->ai->ai_addr->sa_family == AF_INET6) { 174350ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner const struct sockaddr_in6 *a1_src = &a1->src_addr.in6; 17449ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *a1_dst = (const struct sockaddr_in6 *)a1->ai->ai_addr; 174550ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner const struct sockaddr_in6 *a2_src = &a2->src_addr.in6; 17469ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *a2_dst = (const struct sockaddr_in6 *)a2->ai->ai_addr; 17479ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson prefixlen1 = _common_prefix_len(&a1_src->sin6_addr, &a1_dst->sin6_addr); 17487e0bfb511e85834d7c6cb9631206b62f82701d60Kenny Root prefixlen2 = _common_prefix_len(&a2_src->sin6_addr, &a2_dst->sin6_addr); 17499ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (prefixlen1 != prefixlen2) { 17509ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return prefixlen2 - prefixlen1; 17519ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17529ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17539ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17549ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 17559ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 10: Leave the order unchanged. 17569ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * We need this since qsort() is not necessarily stable. 17579ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17589ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return a1->original_order - a2->original_order; 17599ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 17609ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17619ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 17629ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Find the source address that will be used if trying to connect to the given 17639ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * address. src_addr must be large enough to hold a struct sockaddr_in6. 17649ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * 17659ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Returns 1 if a source address was found, 0 if the address is unreachable, 17669ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are 17679ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * undefined. 17689ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17699ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17709ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 17719ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 17729ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr) 17739ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 17749ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int sock; 17759ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int ret; 17769ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson socklen_t len; 17779ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17789ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson switch (addr->sa_family) { 17799ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson case AF_INET: 17809ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson len = sizeof(struct sockaddr_in); 17819ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson break; 17829ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson case AF_INET6: 17839ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson len = sizeof(struct sockaddr_in6); 17849ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson break; 17859ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson default: 17869ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* No known usable source address for non-INET families. */ 17879ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 0; 17889ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17899ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17909ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson sock = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); 17919ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (sock == -1) { 17929ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (errno == EAFNOSUPPORT) { 17939ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 0; 17949ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 17959ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return -1; 17969ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17979ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17989ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17999ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson do { 18009ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson ret = connect(sock, addr, len); 18019ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } while (ret == -1 && errno == EINTR); 18029ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18039ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (ret == -1) { 18049ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson close(sock); 18059ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 0; 18069ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18079ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18089ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (getsockname(sock, src_addr, &len) == -1) { 18099ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson close(sock); 18109ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return -1; 18119ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18129ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson close(sock); 18139ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 1; 18149ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 18159ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18169ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 18179ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Sort the linked list starting at sentinel->ai_next in RFC3484 order. 18189ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Will leave the list unchanged if an error occurs. 18199ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 18209ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18219ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 18229ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic void 18239ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_rfc3484_sort(struct addrinfo *list_sentinel) 18249ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 18259ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson struct addrinfo *cur; 18269ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int nelem = 0, i; 18279ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson struct addrinfo_sort_elem *elems; 18289ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18299ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson cur = list_sentinel->ai_next; 18309ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson while (cur) { 18319ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson ++nelem; 18329ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson cur = cur->ai_next; 18339ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18349ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18359ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems = (struct addrinfo_sort_elem *)malloc(nelem * sizeof(struct addrinfo_sort_elem)); 18369ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (elems == NULL) { 18379ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson goto error; 18389ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18399ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18409ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 18419ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Convert the linked list to an array that also contains the candidate 18429ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * source address for each destination address. 18439ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 18449ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson for (i = 0, cur = list_sentinel->ai_next; i < nelem; ++i, cur = cur->ai_next) { 18459ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int has_src_addr; 18469ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson assert(cur != NULL); 18479ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[i].ai = cur; 18489ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[i].original_order = i; 18499ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 185050ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic); 18519ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (has_src_addr == -1) { 18529ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson goto error; 18539ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18549ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[i].has_src_addr = has_src_addr; 18559ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18569ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18579ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Sort the addresses, and rearrange the linked list so it matches the sorted order. */ 18589ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson qsort((void *)elems, nelem, sizeof(struct addrinfo_sort_elem), _rfc3484_compare); 18599ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18609ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson list_sentinel->ai_next = elems[0].ai; 18619ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson for (i = 0; i < nelem - 1; ++i) { 18629ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[i].ai->ai_next = elems[i + 1].ai; 18639ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18649ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[nelem - 1].ai->ai_next = NULL; 18651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 18669ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonerror: 18679ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson free(elems); 18681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 18691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 18701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*ARGSUSED*/ 18711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 18721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_dns_getaddrinfo(void *rv, void *cb_data, va_list ap) 18731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 18741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *ai; 18751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project querybuf *buf, *buf2; 18761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *name; 18771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *pai; 18781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel, *cur; 18791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target q, q2; 18801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project res_state res; 18811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 18821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project name = va_arg(ap, char *); 18831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai = va_arg(ap, const struct addrinfo *); 18845e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner //fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name); 18851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 18861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&q, 0, sizeof(q)); 18871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&q2, 0, sizeof(q2)); 18881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&sentinel, 0, sizeof(sentinel)); 18891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 18901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 18911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project buf = malloc(sizeof(*buf)); 18921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (buf == NULL) { 18931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NETDB_INTERNAL; 18941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 18951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 18961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project buf2 = malloc(sizeof(*buf2)); 18971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (buf2 == NULL) { 18981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 18991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NETDB_INTERNAL; 19001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 19011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (pai->ai_family) { 19041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_UNSPEC: 19051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* prefer IPv6 */ 19061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.name = name; 19071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qclass = C_IN; 19081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.answer = buf->buf; 19091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.anslen = sizeof(buf->buf); 1910ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti int query_ipv6 = 1, query_ipv4 = 1; 1911ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti if (pai->ai_flags & AI_ADDRCONFIG) { 1912b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti query_ipv6 = _have_ipv6(); 1913b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti query_ipv4 = _have_ipv4(); 1914f432de2de7288c0589d1e50c2aa949a76c571794Lorenzo Colitti if (query_ipv6 == 0 && query_ipv4 == 0) { 1915f432de2de7288c0589d1e50c2aa949a76c571794Lorenzo Colitti // Both our IPv4 and IPv6 connectivity probes failed, which indicates 1916f432de2de7288c0589d1e50c2aa949a76c571794Lorenzo Colitti // that we have neither an IPv4 or an IPv6 default route (and thus no 1917f432de2de7288c0589d1e50c2aa949a76c571794Lorenzo Colitti // global IPv4 or IPv6 connectivity). We might be in a walled garden. 1918f432de2de7288c0589d1e50c2aa949a76c571794Lorenzo Colitti // Throw up our arms and ask for both A and AAAA. 1919f432de2de7288c0589d1e50c2aa949a76c571794Lorenzo Colitti query_ipv6 = query_ipv4 = 1; 1920f432de2de7288c0589d1e50c2aa949a76c571794Lorenzo Colitti } 1921ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti } 1922ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti if (query_ipv6) { 19233d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti q.qtype = T_AAAA; 1924ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti if (query_ipv4) { 1925ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q.next = &q2; 1926ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.name = name; 1927ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.qclass = C_IN; 1928ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.qtype = T_A; 1929ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.answer = buf2->buf; 1930ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.anslen = sizeof(buf2->buf); 1931ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti } 1932ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti } else if (query_ipv4) { 19333d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti q.qtype = T_A; 1934ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti } else { 1935ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti free(buf); 1936ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti free(buf2); 1937ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti return NS_NOTFOUND; 19383d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti } 19391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 19401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 19411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.name = name; 19421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qclass = C_IN; 19431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qtype = T_A; 19441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.answer = buf->buf; 19451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.anslen = sizeof(buf->buf); 19461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 19471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 19481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.name = name; 19491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qclass = C_IN; 19501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qtype = T_AAAA; 19511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.answer = buf->buf; 19521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.anslen = sizeof(buf->buf); 19531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 19541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 19551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 19561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf2); 19571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_UNAVAIL; 19581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project res = __res_get_state(); 19611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res == NULL) { 19621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 19631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf2); 19641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 19651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res_searchN(name, &q, res) < 0) { 19681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project __res_put_state(res); 19691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 19701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf2); 19711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 19721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = getanswer(buf, q.n, q.name, q.qtype, pai); 19741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai) { 19751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur->ai_next = ai; 19761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 19771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 19781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (q.next) { 19801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai); 19811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai) 19821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur->ai_next = ai; 19831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 19851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf2); 19861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next == NULL) { 19871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project __res_put_state(res); 19881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (h_errno) { 19891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case HOST_NOT_FOUND: 19901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 19911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case TRY_AGAIN: 19921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_TRYAGAIN; 19931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 19941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_UNAVAIL; 19951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19989ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson _rfc3484_sort(&sentinel); 19991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project __res_put_state(res); 20011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *((struct addrinfo **)rv) = sentinel.ai_next; 20031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_SUCCESS; 20041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 20051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 20071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_sethtent(FILE **hostf) 20081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 20091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!*hostf) 20111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *hostf = fopen(_PATH_HOSTS, "r" ); 20121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 20131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project rewind(*hostf); 20141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 20151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 20171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_endhtent(FILE **hostf) 20181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 20191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*hostf) { 20211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void) fclose(*hostf); 20221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *hostf = NULL; 20231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 20251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo * 20271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) 20281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 20291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *p; 20301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *cp, *tname, *cname; 20311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo hints, *res0, *res; 20321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 20331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *addr; 20341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char hostbuf[8*1024]; 20351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// fprintf(stderr, "_gethtent() name = '%s'\n", name); 20371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(name != NULL); 20381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 20391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" ))) 20411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 20421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project again: 20431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf))) 20441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 20451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*p == '#') 20461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(cp = strpbrk(p, "#\n"))) 20481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cp = '\0'; 20501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(cp = strpbrk(p, " \t"))) 20511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cp++ = '\0'; 20531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project addr = p; 20541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* if this is not something we're looking for, skip it. */ 20551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cname = NULL; 20561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cp && *cp) { 20571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*cp == ' ' || *cp == '\t') { 20581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp++; 20591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 20601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!cname) 20621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cname = cp; 20631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tname = cp; 20641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((cp = strpbrk(cp, " \t")) != NULL) 20651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cp++ = '\0'; 20661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// fprintf(stderr, "\ttname = '%s'", tname); 20671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (strcasecmp(name, tname) == 0) 20681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto found; 20691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfound: 20731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hints = *pai; 20741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hints.ai_flags = AI_NUMERICHOST; 20751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = getaddrinfo(addr, NULL, &hints, &res0); 20761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error) 20771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (res = res0; res; res = res->ai_next) { 20791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* cover it up */ 20801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project res->ai_flags = pai->ai_flags; 20811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_flags & AI_CANONNAME) { 20831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_canonname(pai, res, cname) != 0) { 20841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(res0); 20851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return res0; 20901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 20911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*ARGSUSED*/ 20931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 20941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_files_getaddrinfo(void *rv, void *cb_data, va_list ap) 20951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 20961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *name; 20971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *pai; 20981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel, *cur; 20991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *p; 21001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project FILE *hostf = NULL; 21011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project name = va_arg(ap, char *); 21031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai = va_arg(ap, struct addrinfo *); 21041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// fprintf(stderr, "_files_getaddrinfo() name = '%s'\n", name); 21061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&sentinel, 0, sizeof(sentinel)); 21071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 21081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project _sethtent(&hostf); 21101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((p = _gethtent(&hostf, name, pai)) != NULL) { 21111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur->ai_next = p; 21121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 21131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 21141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 21151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project _endhtent(&hostf); 21161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *((struct addrinfo **)rv) = sentinel.ai_next; 21181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next == NULL) 21191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 21201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_SUCCESS; 21211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 21221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* resolver logic */ 21241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 21261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Formulate a normal query, send, and await answer. 21271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Returned answer is placed in supplied buffer "answer". 21281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Perform preliminary check of answer, returning success only 21291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if no error is indicated and the answer count is nonzero. 21301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Return the size of the response on success, -1 on error. 21311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Error number is left in h_errno. 21321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 21331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Caller must parse answer and determine whether it answers the question. 21341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 21351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 21361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_queryN(const char *name, /* domain name */ struct res_target *target, 21371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project res_state res) 21381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 21391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char buf[MAXPACKET]; 21401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HEADER *hp; 21411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n; 21421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target *t; 21431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int rcode; 21441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int ancount; 21451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(name != NULL); 21471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX: target may be NULL??? */ 21481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project rcode = NOERROR; 21501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ancount = 0; 21511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (t = target; t; t = t->next) { 21531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int class, type; 21541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *answer; 21551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int anslen; 21561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hp = (HEADER *)(void *)t->answer; 21581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hp->rcode = NOERROR; /* default */ 21591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* make it easier... */ 21611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project class = t->qclass; 21621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project type = t->qtype; 21631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project answer = t->answer; 21641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project anslen = t->anslen; 21651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 21661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 21671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; res_nquery(%s, %d, %d)\n", name, class, type); 21681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 21691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, 21711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project buf, sizeof(buf)); 21721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef RES_USE_EDNS0 21731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n > 0 && (res->options & RES_USE_EDNS0) != 0) 21741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = res_nopt(res, n, buf, sizeof(buf), anslen); 21751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 21761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n <= 0) { 21771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 21781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 21791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; res_nquery: mkquery failed\n"); 21801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 21811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 21821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return n; 21831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 21841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = res_nsend(res, buf, n, answer, anslen); 21851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 21861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n < 0) { 21871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 21881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 21891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; res_query: send error\n"); 21901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 21911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = TRY_AGAIN; 21921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return n; 21931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 21941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 21951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 21971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project rcode = hp->rcode; /* record most recent error */ 21981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 21991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 22001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; rcode = %u, ancount=%u\n", hp->rcode, 22011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ntohs(hp->ancount)); 22021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 22031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 22041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ancount += ntohs(hp->ancount); 22071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t->n = n; 22091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ancount == 0) { 22121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (rcode) { 22131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NXDOMAIN: 22141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = HOST_NOT_FOUND; 22151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 22161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SERVFAIL: 22171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = TRY_AGAIN; 22181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 22191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NOERROR: 22201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_DATA; 22211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 22221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case FORMERR: 22231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NOTIMP: 22241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case REFUSED: 22251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 22261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 22271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 22281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 22301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ancount; 22321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 22331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 22351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Formulate a normal query, send, and retrieve answer in supplied buffer. 22361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Return the size of the response on success, -1 on error. 22371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If enabled, implement search rules until answer or unrecoverable failure 22381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is detected. Error code, if any, is left in h_errno. 22391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 22401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 22411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_searchN(const char *name, struct res_target *target, res_state res) 22421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 22431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *cp, * const *domain; 22441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HEADER *hp; 22451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int dots; 22461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int trailing_dot, ret, saved_herrno; 22471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 22481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(name != NULL); 22501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(target != NULL); 22511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hp = (HEADER *)(void *)target->answer; /*XXX*/ 22531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = 0; 22551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = HOST_NOT_FOUND; /* default, if we never query */ 22561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dots = 0; 22571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cp = name; *cp; cp++) 22581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dots += (*cp == '.'); 22591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project trailing_dot = 0; 22601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cp > name && *--cp == '.') 22611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project trailing_dot++; 22621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22645e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner //fprintf(stderr, "res_searchN() name = '%s'\n", name); 22651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 22671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if there aren't any dots, it could be a user-level alias 22681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 22691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!dots && (cp = __hostalias(name)) != NULL) { 22701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret = res_queryN(cp, target, res); 22711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ret; 22721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 22751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If there are dots in the name already, let's just give it a try 22761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 'as is'. The threshold can be set with the "ndots" option. 22771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 22781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project saved_herrno = -1; 22791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dots >= res->ndots) { 22801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret = res_querydomainN(name, NULL, target, res); 22811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ret > 0) 22821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ret); 22831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project saved_herrno = h_errno; 22841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tried_as_is++; 22851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 22881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * We do at least one level of search if 22891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - there is no dot and RES_DEFNAME is set, or 22901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - there is at least one dot, there is no trailing dot, 22911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * and RES_DNSRCH is set. 22921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 22931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((!dots && (res->options & RES_DEFNAMES)) || 22941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (dots && !trailing_dot && (res->options & RES_DNSRCH))) { 22951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int done = 0; 22961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (domain = (const char * const *)res->dnsrch; 22981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *domain && !done; 22991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project domain++) { 23001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret = res_querydomainN(name, *domain, target, res); 23021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ret > 0) 23031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ret; 23041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 23061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If no server present, give up. 23071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If name isn't found in this domain, 23081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * keep trying higher domains in the search list 23091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (if that's enabled). 23101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * On a NO_DATA error, keep trying, otherwise 23111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * a wildcard entry of another type could keep us 23121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * from finding this entry higher in the domain. 23131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If we get some other error (negative answer or 23141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * server failure), then stop searching up, 23151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * but try the input name below in case it's 23161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * fully-qualified. 23171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno == ECONNREFUSED) { 23191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = TRY_AGAIN; 23201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 23211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (h_errno) { 23241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NO_DATA: 23251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project got_nodata++; 23261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* FALLTHROUGH */ 23271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case HOST_NOT_FOUND: 23281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* keep trying */ 23291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 23301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case TRY_AGAIN: 23311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hp->rcode == SERVFAIL) { 23321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* try next search element, if any */ 23331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project got_servfail++; 23341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 23351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* FALLTHROUGH */ 23371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 23381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* anything else implies that we're done */ 23391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project done++; 23401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 23421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we got here for some reason other than DNSRCH, 23431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * we only wanted one iteration of the loop, so stop. 23441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(res->options & RES_DNSRCH)) 2346b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti done++; 23471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 23511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we have not already tried the name "as is", do that now. 23521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * note that we do this regardless of how many dots were in the 23531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * name or whether it ends with a dot. 23541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!tried_as_is) { 23561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret = res_querydomainN(name, NULL, target, res); 23571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ret > 0) 23581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ret; 23591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 23621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we got here, we didn't satisfy the search. 23631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we did an initial full query, return that query's h_errno 23641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (note that we wouldn't be here if that query had succeeded). 23651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * else if we ever got a nodata, send that back as the reason. 23661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * else send back meaningless h_errno, that being the one from 23671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the last DNSRCH we did. 23681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (saved_herrno != -1) 23701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = saved_herrno; 23711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if (got_nodata) 23721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_DATA; 23731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if (got_servfail) 23741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = TRY_AGAIN; 23751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 23761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 23771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 23791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Perform a call on res_query on the concatenation of name and domain, 23801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * removing a trailing dot from name if domain is NULL. 23811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 23831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_querydomainN(const char *name, const char *domain, 23841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target *target, res_state res) 23851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 23861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char nbuf[MAXDNAME]; 23871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *longname = nbuf; 23881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t n, d; 23891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(name != NULL); 23911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX: target may be NULL??? */ 23921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 23941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 23951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; res_querydomain(%s, %s)\n", 23961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project name, domain?domain:"<Nil>"); 23971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 23981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (domain == NULL) { 23991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 24001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Check for trailing '.'; 24011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copy without '.' if present. 24021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 24031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = strlen(name); 24041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n + 1 > sizeof(nbuf)) { 24051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 24061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 24071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 24081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n > 0 && name[--n] == '.') { 24091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strncpy(nbuf, name, n); 24101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project nbuf[n] = '\0'; 24111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 24121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project longname = name; 24131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 24141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = strlen(name); 24151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project d = strlen(domain); 24161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n + 1 + d + 1 > sizeof(nbuf)) { 24171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 24181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 24191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 24201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); 24211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 24221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return res_queryN(longname, target, res); 24231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2424