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 13306e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun// This should be synchronized to ResponseCode.h 13406e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurunstatic const int DnsProxyQueryResult = 222; 13506e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun 1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct afd { 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_af; 1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_addrlen; 1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_socklen; 1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_off; 1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *a_addrany; 1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *a_loopback; 1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_scoped; 1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} afdl [] = { 1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {PF_INET6, sizeof(struct in6_addr), 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sizeof(struct sockaddr_in6), 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project offsetof(struct sockaddr_in6, sin6_addr), 1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project in6_addrany, in6_loopback, 1}, 1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {PF_INET, sizeof(struct in_addr), 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sizeof(struct sockaddr_in), 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project offsetof(struct sockaddr_in, sin_addr), 1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project in_addrany, in_loopback, 0}, 1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {0, 0, 0, 0, NULL, NULL, 0}, 1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct explore { 1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int e_af; 1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int e_socktype; 1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int e_protocol; 1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *e_protostr; 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int e_wild; 1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define WILD_AF(ex) ((ex)->e_wild & 0x01) 1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) 1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct explore explore[] = { 1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, 1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, 1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, 1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, 1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, 1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 }, 1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { -1, 0, 0, NULL, 0 }, 1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define PTON_MAX 16 1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define PTON_MAX 4 1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const ns_src default_dns_files[] = { 194b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti { NSSRC_FILES, NS_SUCCESS }, 195b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti { NSSRC_DNS, NS_SUCCESS }, 1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 0, 0 } 1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define MAXPACKET (64*1024) 2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef union { 2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HEADER hdr; 2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char buf[MAXPACKET]; 2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} querybuf; 2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct res_target { 2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target *next; 2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *name; /* domain name */ 2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int qclass, qtype; /* class and type of query */ 2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *answer; /* buffer to put answer */ 2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int anslen; /* size of answer buffer */ 2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n; /* result length */ 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int str2number(const char *); 2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int explore_fqdn(const struct addrinfo *, const char *, 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *, struct addrinfo **); 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int explore_null(const struct addrinfo *, 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *, struct addrinfo **); 2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int explore_numeric(const struct addrinfo *, const char *, 2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *, struct addrinfo **, const char *); 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int explore_numeric_scope(const struct addrinfo *, const char *, 2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *, struct addrinfo **); 2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int get_canonname(const struct addrinfo *, 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *, const char *); 2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo *get_ai(const struct addrinfo *, 2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *, const char *); 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int get_portmatch(const struct addrinfo *, const char *); 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int get_port(const struct addrinfo *, const char *, int); 2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct afd *find_afd(int); 2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); 2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo *getanswer(const querybuf *, int, const char *, int, 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *); 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int _dns_getaddrinfo(void *, void *, va_list); 2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void _sethtent(FILE **); 2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void _endhtent(FILE **); 2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo *_gethtent(FILE **, const char *, 2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *); 2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int _files_getaddrinfo(void *, void *, va_list); 2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int res_queryN(const char *, struct res_target *, res_state); 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int res_searchN(const char *, struct res_target *, res_state); 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int res_querydomainN(const char *, const char *, 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target *, res_state); 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char * const ai_errlist[] = { 2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Success", 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Temporary failure in name resolution", /* EAI_AGAIN */ 253b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "Invalid value for ai_flags", /* EAI_BADFLAGS */ 254b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "Non-recoverable failure in name resolution", /* EAI_FAIL */ 2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "ai_family not supported", /* EAI_FAMILY */ 256b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "Memory allocation failure", /* EAI_MEMORY */ 257b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "No address associated with hostname", /* EAI_NODATA */ 2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "hostname nor servname provided, or not known", /* EAI_NONAME */ 2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "servname not supported for ai_socktype", /* EAI_SERVICE */ 260b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "ai_socktype not supported", /* EAI_SOCKTYPE */ 261b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "System error returned in errno", /* EAI_SYSTEM */ 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Invalid value for hints", /* EAI_BADHINTS */ 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Resolved protocol is unknown", /* EAI_PROTOCOL */ 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "Argument buffer overflow", /* EAI_OVERFLOW */ 265b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti "Unknown error", /* EAI_MAX */ 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* XXX macros that make external reference is BAD. */ 2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 270b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define GET_AI(ai, afd, addr) \ 271b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colittido { \ 272b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /* external reference: pai, error, and label free */ \ 273b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti (ai) = get_ai(pai, (afd), (addr)); \ 274b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti if ((ai) == NULL) { \ 275b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti error = EAI_MEMORY; \ 276b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti goto free; \ 277b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti } \ 2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (/*CONSTCOND*/0) 2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 280b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define GET_PORT(ai, serv) \ 281b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colittido { \ 282b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /* external reference: error and label free */ \ 283b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti error = get_port((ai), (serv), 0); \ 284b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti if (error != 0) \ 285b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti goto free; \ 2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (/*CONSTCOND*/0) 2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 288b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define GET_CANONNAME(ai, str) \ 289b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colittido { \ 290b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /* external reference: pai, error and label free */ \ 291b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti error = get_canonname(pai, (ai), (str)); \ 292b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti if (error != 0) \ 293b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti goto free; \ 2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (/*CONSTCOND*/0) 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 296b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define ERR(err) \ 297b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colittido { \ 298b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /* external reference: error, and label bad */ \ 299b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti error = (err); \ 300b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti goto bad; \ 301b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti /*NOTREACHED*/ \ 3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (/*CONSTCOND*/0) 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 304b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define MATCH_FAMILY(x, y, w) \ 305b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \ 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (y) == PF_UNSPEC))) 307b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti#define MATCH(x, y, w) \ 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) 3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectconst char * 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectgai_strerror(int ecode) 3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ecode < 0 || ecode > EAI_MAX) 3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ecode = EAI_MAX; 3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ai_errlist[ecode]; 3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid 3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfreeaddrinfo(struct addrinfo *ai) 3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *next; 3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(ai != NULL); 3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { 3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project next = ai->ai_next; 3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai->ai_canonname) 3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(ai->ai_canonname); 3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* no need to free(ai->ai_addr) */ 3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(ai); 3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = next; 3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } while (ai); 3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstr2number(const char *p) 3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *ep; 3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned long v; 3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(p != NULL); 3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*p == '\0') 3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ep = NULL; 3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = 0; 3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v = strtoul(p, &ep, 10); 3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) 3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return v; 3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 354ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti/* 355ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * Connect a UDP socket to a given unicast address. This will cause no network 356ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * traffic, but will fail fast if the system has no or limited reachability to 357ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * the destination (e.g., no IPv4 address, no IPv6 default route, ...). 358ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti */ 3593d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colittistatic int 360ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti_test_connect(int pf, struct sockaddr *addr, size_t addrlen) { 361ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti int s = socket(pf, SOCK_DGRAM, IPPROTO_UDP); 3623d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti if (s < 0) 3633d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti return 0; 3643d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti int ret; 3653d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti do { 366ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti ret = connect(s, addr, addrlen); 3673d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti } while (ret < 0 && errno == EINTR); 368ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti int success = (ret == 0); 3693d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti do { 3703d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti ret = close(s); 3713d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti } while (ret < 0 && errno == EINTR); 372ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti return success; 373ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti} 374ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti 375ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti/* 376ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * The following functions determine whether IPv4 or IPv6 connectivity is 377ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * available in order to implement AI_ADDRCONFIG. 378ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * 379ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * Strictly speaking, AI_ADDRCONFIG should not look at whether connectivity is 380ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * available, but whether addresses of the specified family are "configured 381ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * on the local system". However, bionic doesn't currently support getifaddrs, 382ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti * so checking for connectivity is the next best thing. 383ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti */ 384ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colittistatic int 385b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti_have_ipv6() { 386b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti static const struct sockaddr_in6 sin6_test = { 387b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti .sin6_family = AF_INET6, 388b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti .sin6_addr.s6_addr = { // 2000:: 389b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 390b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti }; 391b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti sockaddr_union addr = { .in6 = sin6_test }; 392b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6)); 393ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti} 394ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti 395ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colittistatic int 396b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti_have_ipv4() { 397b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti static const struct sockaddr_in sin_test = { 398b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti .sin_family = AF_INET, 399b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti .sin_addr.s_addr = __constant_htonl(0x08080808L) // 8.8.8.8 400b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti }; 401b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti sockaddr_union addr = { .in = sin_test }; 402b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti return _test_connect(PF_INET, &addr.generic, sizeof(addr.in)); 4033d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti} 4043d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti 405a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick// Returns 0 on success, else returns non-zero on error (in which case 406a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick// getaddrinfo should continue as normal) 407a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrickstatic int 408a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrickandroid_getaddrinfo_proxy( 409a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick const char *hostname, const char *servname, 410a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick const struct addrinfo *hints, struct addrinfo **res) 411a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick{ 412a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick int sock; 413a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick const int one = 1; 414a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct sockaddr_un proxy_addr; 415a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick const char* cache_mode = getenv("ANDROID_DNS_MODE"); 416a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick FILE* proxy = NULL; 417a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick int success = 0; 418a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 419a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Clear this at start, as we use its non-NULLness later (in the 420a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // error path) to decide if we have to free up any memory we 421a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // allocated in the process (before failing). 422a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick *res = NULL; 423a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 424a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) { 425a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Don't use the proxy in local mode. This is used by the 426a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // proxy itself. 427a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 428a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 429a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 4307858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick // Temporary cautious hack to disable the DNS proxy for processes 4317858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick // requesting special treatment. Ideally the DNS proxy should 4327858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick // accomodate these apps, though. 4337858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick char propname[PROP_NAME_MAX]; 4347858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick char propvalue[PROP_VALUE_MAX]; 4357858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick snprintf(propname, sizeof(propname), "net.dns1.%d", getpid()); 4367858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick if (__system_property_get(propname, propvalue) > 0) { 4377858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick return -1; 4387858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick } 4397858564582ca134bd0101ffc725c0d0b1d29d645Brad Fitzpatrick 440a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Bogus things we can't serialize. Don't use the proxy. 441a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if ((hostname != NULL && 442a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick strcspn(hostname, " \n\r\t^'\"") != strlen(hostname)) || 443a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick (servname != NULL && 444a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick strcspn(servname, " \n\r\t^'\"") != strlen(servname))) { 445a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 446a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 447a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 448a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick sock = socket(AF_UNIX, SOCK_STREAM, 0); 449a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (sock < 0) { 450a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 451a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 452a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 453a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 454a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick memset(&proxy_addr, 0, sizeof(proxy_addr)); 455a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick proxy_addr.sun_family = AF_UNIX; 456a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", 457a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick sizeof(proxy_addr.sun_path)); 458a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (TEMP_FAILURE_RETRY(connect(sock, 459a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick (const struct sockaddr*) &proxy_addr, 460a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick sizeof(proxy_addr))) != 0) { 461a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick close(sock); 462a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 463a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 464a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 465a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Send the request. 466a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick proxy = fdopen(sock, "r+"); 4671fb6662d1aa51eec54cfc133c40cacc0b15aad30Kenny Root if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d", 468a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hostname == NULL ? "^" : hostname, 469a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick servname == NULL ? "^" : servname, 470a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hints == NULL ? -1 : hints->ai_flags, 471a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hints == NULL ? -1 : hints->ai_family, 472a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hints == NULL ? -1 : hints->ai_socktype, 473a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick hints == NULL ? -1 : hints->ai_protocol) < 0) { 474a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick goto exit; 475a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 476a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // literal NULL byte at end, required by FrameworkListener 477a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fputc(0, proxy) == EOF || 478a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick fflush(proxy) != 0) { 479a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick goto exit; 480a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 481a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 482c59ba4595be25a1213955233fcf9bcd1afe6438eRobert Greenwalt char buf[4]; 48306e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun // read result code for gethostbyaddr 48406e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) { 485a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick goto exit; 486a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 487a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 48806e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun int result_code = (int)strtol(buf, NULL, 10); 48906e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun // verify the code itself 49006e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun if (result_code != DnsProxyQueryResult ) { 491a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick goto exit; 492a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 493a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 494a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct addrinfo* ai = NULL; 495a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct addrinfo** nextres = res; 496a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick while (1) { 497a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick uint32_t addrinfo_len; 498a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(&addrinfo_len, sizeof(addrinfo_len), 499a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 1, proxy) != 1) { 500a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 501a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 502a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick addrinfo_len = ntohl(addrinfo_len); 503a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (addrinfo_len == 0) { 504a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick success = 1; 505a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 506a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 507a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 508a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (addrinfo_len < sizeof(struct addrinfo)) { 509a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 510a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 511a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct addrinfo* ai = calloc(1, addrinfo_len + 512a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick sizeof(struct sockaddr_storage)); 513a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (ai == NULL) { 514a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 515a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 516a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 517a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(ai, addrinfo_len, 1, proxy) != 1) { 518a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Error; fall through. 519a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 520a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 521a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 522a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Zero out the pointer fields we copied which aren't 523a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // valid in this address space. 524a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_addr = NULL; 525a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_canonname = NULL; 526a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_next = NULL; 527a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 528a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // struct sockaddr 529a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick uint32_t addr_len; 530a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(&addr_len, sizeof(addr_len), 1, proxy) != 1) { 531a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 532a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 533a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick addr_len = ntohl(addr_len); 534a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (addr_len != 0) { 535a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (addr_len > sizeof(struct sockaddr_storage)) { 536a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Bogus; too big. 537a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 538a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 539a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick struct sockaddr* addr = (struct sockaddr*)(ai + 1); 540a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(addr, addr_len, 1, proxy) != 1) { 541a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 542a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 543a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_addr = addr; 544a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 545a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 546a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // cannonname 547a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick uint32_t name_len; 548a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) { 549a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 550a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 5510ee092fb23318bc479de8e6514fbf2e05e0ce646Mattias Falk name_len = ntohl(name_len); 552a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (name_len != 0) { 553a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai->ai_canonname = (char*) malloc(name_len); 554a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (fread(ai->ai_canonname, name_len, 1, proxy) != 1) { 555a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 556a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 557a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (ai->ai_canonname[name_len - 1] != '\0') { 558a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // The proxy should be returning this 559a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // NULL-terminated. 560a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick break; 561a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 562a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 563a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 564a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick *nextres = ai; 565a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick nextres = &ai->ai_next; 566a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick ai = NULL; 567a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 568a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 569a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (ai != NULL) { 570a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Clean up partially-built addrinfo that we never ended up 571a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // attaching to the response. 572a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick freeaddrinfo(ai); 573a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 574a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrickexit: 575a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (proxy != NULL) { 576a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick fclose(proxy); 577a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 578a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 579a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (success) { 580a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return 0; 581a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 582a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 583a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // Proxy failed; fall through to local 584a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // resolver case. But first clean up any 585a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick // memory we might've allocated. 586a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (*res) { 587a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick freeaddrinfo(*res); 588a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick *res = NULL; 589a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 590a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return -1; 591a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick} 592a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint 5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectgetaddrinfo(const char *hostname, const char *servname, 5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *hints, struct addrinfo **res) 5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel; 5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error = 0; 6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo ai; 6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo ai0; 6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *pai; 6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct explore *ex; 6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hostname is allowed to be NULL */ 6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname is allowed to be NULL */ 6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hints is allowed to be NULL */ 6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&sentinel, 0, sizeof(sentinel)); 6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai = &ai; 6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_flags = 0; 6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family = PF_UNSPEC; 6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_socktype = ANY; 6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_protocol = ANY; 6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_addrlen = 0; 6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_canonname = NULL; 6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_addr = NULL; 6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_next = NULL; 6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hostname == NULL && servname == NULL) 6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_NONAME; 6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hints) { 6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* error check for hints */ 6261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hints->ai_addrlen || hints->ai_canonname || 6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hints->ai_addr || hints->ai_next) 6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_BADHINTS); /* xxx */ 6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hints->ai_flags & ~AI_MASK) 6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_BADFLAGS); 6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (hints->ai_family) { 6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case PF_UNSPEC: 6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case PF_INET: 6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case PF_INET6: 6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_FAMILY); 6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(pai, hints, sizeof(*pai)); 6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if both socktype/protocol are specified, check if they 6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are meaningful combination. 6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { 6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (ex = explore; ex->e_af >= 0; ex++) { 6491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family != ex->e_af) 6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ex->e_socktype == ANY) 6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ex->e_protocol == ANY) 6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_socktype == ex->e_socktype 6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project && pai->ai_protocol != ex->e_protocol) { 6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_BADHINTS); 6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * check for special cases. (1) numeric servname is disallowed if 6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * socktype/protocol are left unspecified. (2) servname is disallowed 6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * for raw and other inet{,6} sockets. 6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) 6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef PF_INET6 6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) 6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ) { 6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai0 = *pai; /* backup *pai */ 6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family == PF_UNSPEC) { 6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef PF_INET6 6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family = PF_INET6; 6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family = PF_INET; 6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = get_portmatch(pai, servname); 6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error) 6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(error); 6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *pai = ai0; 6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai0 = *pai; 6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* NULL hostname, or numeric hostname */ 6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (ex = explore; ex->e_af >= 0; ex++) { 6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *pai = ai0; 6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* PF_UNSPEC entries are prepared for DNS queries only */ 6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ex->e_af == PF_UNSPEC) 6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) 7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) 7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) 7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family == PF_UNSPEC) 7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family = ex->e_af; 7081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_socktype = ex->e_socktype; 7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 7111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_protocol = ex->e_protocol; 7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hostname == NULL) 7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = explore_null(pai, servname, &cur->ai_next); 7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = explore_numeric_scope(pai, hostname, servname, 7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project &cur->ai_next); 7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error) 7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur->ai_next) 7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * XXX 7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If numeric representation of AF1 can be interpreted as FQDN 7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * representation of AF2, we need to think again about the code below. 7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto good; 7331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hostname == NULL) 7351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_NODATA); 7361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_flags & AI_NUMERICHOST) 7371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_NONAME); 7381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 739a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick /* 740a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick * BEGIN ANDROID CHANGES; proxying to the cache 741a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick */ 742a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick if (android_getaddrinfo_proxy(hostname, servname, hints, res) == 0) { 743a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick return 0; 744a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick } 745a1dbf0b453801620565e5911f354f82706b0200dBrad Fitzpatrick 7461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 7471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * hostname as alphabetical name. 7481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * we would like to prefer AF_INET6 than AF_INET, so we'll make a 7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * outer loop by AFs. 7501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (ex = explore; ex->e_af >= 0; ex++) { 7521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *pai = ai0; 7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* require exact match for family field */ 7551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family != ex->e_af) 7561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH(pai->ai_socktype, ex->e_socktype, 7591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project WILD_SOCKTYPE(ex))) { 7601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!MATCH(pai->ai_protocol, ex->e_protocol, 7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project WILD_PROTOCOL(ex))) { 7641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_socktype == ANY && ex->e_socktype != ANY) 7681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_socktype = ex->e_socktype; 7691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_protocol == ANY && ex->e_protocol != ANY) 7701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_protocol = ex->e_protocol; 7711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = explore_fqdn(pai, hostname, servname, 7731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project &cur->ai_next); 7741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 7761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX */ 7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = 0; 7821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error) 7841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 7851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error == 0) { 7861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) { 7871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project good: 7881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = sentinel.ai_next; 7891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return SUCCESS; 7901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 7911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = EAI_FAIL; 7921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 7931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free: 7941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bad: 7951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 7961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(sentinel.ai_next); 7971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = NULL; 7981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 7991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 8001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 8021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FQDN hostname, DNS lookup 8031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 8051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexplore_fqdn(const struct addrinfo *pai, const char *hostname, 8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *servname, struct addrinfo **res) 8071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 8081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *result; 8091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 8101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error = 0; 8111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project static const ns_dtab dtab[] = { 8121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project NS_FILES_CB(_files_getaddrinfo, NULL) 8131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ 8141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project NS_NIS_CB(_yp_getaddrinfo, NULL) 8151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 0, 0, 0 } 8161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project }; 8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 8191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hostname may be NULL */ 8201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 8211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 8221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = NULL; 8241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 8261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if the servname does not match socktype/protocol, ignore it. 8271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_portmatch(pai, servname) != 0) 8291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 8301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", 8321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default_dns_files, hostname, pai)) { 8331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_TRYAGAIN: 8341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = EAI_AGAIN; 8351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 8361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_UNAVAIL: 8371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = EAI_FAIL; 8381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 8391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_NOTFOUND: 8401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = EAI_NODATA; 8411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto free; 8421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NS_SUCCESS: 8431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = 0; 8441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cur = result; cur; cur = cur->ai_next) { 8451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur, servname); 8461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* canonname should be filled already */ 8471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 8481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 8491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 8501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = result; 8521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 8541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfree: 8561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (result) 8571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(result); 8581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 8591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 8601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 8621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * hostname == NULL. 8631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * passive socket -> anyaddr (0.0.0.0 or ::) 8641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * non-passive socket -> localhost (127.0.0.1 or ::1) 8651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 8671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexplore_null(const struct addrinfo *pai, const char *servname, 8681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo **res) 8691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 8701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int s; 8711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 8721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 8731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel; 8741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 8751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 8771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 8791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = NULL; 8811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sentinel.ai_next = NULL; 8821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 8831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * filter out AFs that are not supported by the kernel 8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * XXX errno? 8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project s = socket(pai->ai_family, SOCK_DGRAM, 0); 8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (s < 0) { 8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno != EMFILE) 8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project close(s); 8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if the servname does not match socktype/protocol, ignore it. 8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_portmatch(pai, servname) != 0) 8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afd = find_afd(pai->ai_family); 9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd == NULL) 9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_flags & AI_PASSIVE) { 9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_AI(cur->ai_next, afd, afd->a_addrany); 9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* xxx meaningless? 9081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * GET_CANONNAME(cur->ai_next, "anyaddr"); 9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur->ai_next, servname); 9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_AI(cur->ai_next, afd, afd->a_loopback); 9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* xxx meaningless? 9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * GET_CANONNAME(cur->ai_next, "localhost"); 9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur->ai_next, servname); 9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = sentinel.ai_next; 9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfree: 9241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 9251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(sentinel.ai_next); 9261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 9271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 9281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 9301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * numeric hostname 9311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 9331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexplore_numeric(const struct addrinfo *pai, const char *hostname, 9341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *servname, struct addrinfo **res, const char *canonname) 9351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 9361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 9371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 9381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel; 9391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 9401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char pton[PTON_MAX]; 9411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 9431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hostname may be NULL */ 9441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 9451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 9461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = NULL; 9481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sentinel.ai_next = NULL; 9491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 9501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 9521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if the servname does not match socktype/protocol, ignore it. 9531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_portmatch(pai, servname) != 0) 9551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 9561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afd = find_afd(pai->ai_family); 9581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd == NULL) 9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 9601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (afd->a_af) { 9621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 /*X/Open spec*/ 9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (inet_aton(hostname, (struct in_addr *)pton) == 1) { 9651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family == afd->a_af || 9661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family == PF_UNSPEC /*?*/) { 9671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_AI(cur->ai_next, afd, pton); 9681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur->ai_next, servname); 9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((pai->ai_flags & AI_CANONNAME)) { 9701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 9711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Set the numeric address itself as 9721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the canonical name, based on a 9731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * clarification in rfc2553bis-03. 9741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_CANONNAME(cur->ai_next, canonname); 9761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 9781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 9791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 9801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_FAMILY); /*xxx*/ 9811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 9831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 9841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 9851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (inet_pton(afd->a_af, hostname, pton) == 1) { 9861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_family == afd->a_af || 9871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai->ai_family == PF_UNSPEC /*?*/) { 9881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_AI(cur->ai_next, afd, pton); 9891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_PORT(cur->ai_next, servname); 9901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((pai->ai_flags & AI_CANONNAME)) { 9911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 9921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Set the numeric address itself as 9931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the canonical name, based on a 9941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * clarification in rfc2553bis-03. 9951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 9961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project GET_CANONNAME(cur->ai_next, canonname); 9971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 9981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur->ai_next) 9991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 10001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 10011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ERR(EAI_FAMILY); /*xxx*/ 10021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 10041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *res = sentinel.ai_next; 10071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 10081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfree: 10101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectbad: 10111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next) 10121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(sentinel.ai_next); 10131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 10141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 10151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 10171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * numeric hostname with scope 10181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 10191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 10201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexplore_numeric_scope(const struct addrinfo *pai, const char *hostname, 10211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *servname, struct addrinfo **res) 10221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 10231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if !defined(SCOPE_DELIMITER) || !defined(INET6) 10241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return explore_numeric(pai, hostname, servname, res, hostname); 10251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 10261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 10271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *cur; 10281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 10291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *cp, *hostname2 = NULL, *scope, *addr; 10301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct sockaddr_in6 *sin6; 10311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 10331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* hostname may be NULL */ 10341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 10351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(res != NULL); 10361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 10381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if the servname does not match socktype/protocol, ignore it. 10391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 10401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_portmatch(pai, servname) != 0) 10411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 10421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afd = find_afd(pai->ai_family); 10441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd == NULL) 10451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 10461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!afd->a_scoped) 10481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return explore_numeric(pai, hostname, servname, res, hostname); 10491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = strchr(hostname, SCOPE_DELIMITER); 10511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cp == NULL) 10521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return explore_numeric(pai, hostname, servname, res, hostname); 10531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 10551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Handle special case of <scoped_address><delimiter><scope id> 10561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 10571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hostname2 = strdup(hostname); 10581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hostname2 == NULL) 10591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_MEMORY; 10601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* terminate at the delimiter */ 10611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hostname2[cp - hostname] = '\0'; 10621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project addr = hostname2; 10631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project scope = cp + 1; 10641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = explore_numeric(pai, addr, servname, res, hostname); 10661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error == 0) { 10671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int32_t scopeid; 10681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cur = *res; cur; cur = cur->ai_next) { 10701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cur->ai_family != AF_INET6) 10711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 10721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; 10731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { 10741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(hostname2); 10751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(EAI_NODATA); /* XXX: is return OK? */ 10761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sin6->sin6_scope_id = scopeid; 10781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 10801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(hostname2); 10821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return error; 10841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 10851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 10861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 10881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) 10891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 10901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 10921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(ai != NULL); 10931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(str != NULL); 10941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((pai->ai_flags & AI_CANONNAME) != 0) { 10961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_canonname = strdup(str); 10971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai->ai_canonname == NULL) 10981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_MEMORY; 10991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 11011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 11021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo * 11041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) 11051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 11061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *p; 11071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *ai; 11081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 11101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(afd != NULL); 11111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(addr != NULL); 11121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) 11141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project + (afd->a_socklen)); 11151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai == NULL) 11161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 11171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(ai, pai, sizeof(struct addrinfo)); 11191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); 11201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(ai->ai_addr, 0, (size_t)afd->a_socklen); 11211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef HAVE_SA_LEN 11231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr->sa_len = afd->a_socklen; 11241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 11251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addrlen = afd->a_socklen; 11271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if defined (__alpha__) || (defined(__i386__) && defined(_LP64)) || defined(__sparc64__) 11281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->__ai_pad0 = 0; 11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 11301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr->sa_family = ai->ai_family = afd->a_af; 11311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p = (char *)(void *)(ai->ai_addr); 11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); 11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ai; 11341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 11351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_portmatch(const struct addrinfo *ai, const char *servname) 11381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 11391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(ai != NULL); 11411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 11421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return get_port(ai, servname, 1); 11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 11471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectget_port(const struct addrinfo *ai, const char *servname, int matchonly) 11481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *proto; 11501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct servent *sp; 11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int port; 11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int allownumeric; 11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(ai != NULL); 11551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* servname may be NULL */ 11561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (servname == NULL) 11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 11591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ai->ai_family) { 11601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 11611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef AF_INET6 11621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 11631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 11641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 11651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 11661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 11671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ai->ai_socktype) { 11701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_RAW: 11711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SERVICE; 11721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_DGRAM: 11731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_STREAM: 11741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project allownumeric = 1; 11751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 11761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case ANY: 11779ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson#if 1 /* ANDROID-SPECIFIC CHANGE TO MATCH GLIBC */ 11785e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner allownumeric = 1; 11795e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner#else 11801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project allownumeric = 0; 11815e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner#endif 11821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 11831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 11841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SOCKTYPE; 11851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 11861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project port = str2number(servname); 11881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (port >= 0) { 11891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!allownumeric) 11901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SERVICE; 11911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (port < 0 || port > 65535) 11921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SERVICE; 11931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project port = htons(port); 11941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 11951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai->ai_flags & AI_NUMERICSERV) 11961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_NONAME; 11971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ai->ai_socktype) { 11991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_DGRAM: 12001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project proto = "udp"; 12011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 12021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SOCK_STREAM: 12031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project proto = "tcp"; 12041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 12051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 12061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project proto = NULL; 12071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 12081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((sp = getservbyname(servname, proto)) == NULL) 12111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SERVICE; 12121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project port = sp->s_port; 12131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!matchonly) { 12161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (ai->ai_family) { 12171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 12181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((struct sockaddr_in *)(void *) 12191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr)->sin_port = port; 12201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 12211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 12221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 12231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((struct sockaddr_in6 *)(void *) 12241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai->ai_addr)->sin6_port = port; 12251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 12261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 12271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 12311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 12321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct afd * 12341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfind_afd(int af) 12351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 12361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 12371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (af == PF_UNSPEC) 12391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 12401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (afd = afdl; afd->a_af; afd++) { 12411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd->a_af == af) 12421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return afd; 12431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 12451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 12461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 12481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* convert a string to a scope identifier. XXX: IPv6 specific */ 12491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 12501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) 12511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 12521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_long lscopeid; 12531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct in6_addr *a6; 12541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *ep; 12551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(scope != NULL); 12571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(sin6 != NULL); 12581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(scopeid != NULL); 12591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project a6 = &sin6->sin6_addr; 12611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* empty scopeid portion is invalid */ 12631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*scope == '\0') 12641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 12651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { 12671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 12681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * We currently assume a one-to-one mapping between links 12691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * and interfaces, so we simply use interface indices for 12701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * like-local scopes. 12711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 12721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *scopeid = if_nametoindex(scope); 12731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*scopeid == 0) 12741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto trynumeric; 12751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 12761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 12771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* still unclear about literal, allow numeric only - placeholder */ 12791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) 12801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto trynumeric; 12811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) 12821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto trynumeric; 12831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 12841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto trynumeric; /* global */ 12851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* try to convert to a numeric id as a last resort */ 12871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project trynumeric: 12881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = 0; 12891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project lscopeid = strtoul(scope, &ep, 10); 12901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); 12911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) 12921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 12931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 12941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 12951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 12961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 12971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* code duplicate with gethnamaddr.c */ 12991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char AskedForGot[] = 13011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 13021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo * 13041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectgetanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 13051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *pai) 13061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 13071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel, *cur; 13081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo ai; 13091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 13101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *canonname; 13111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const HEADER *hp; 13121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *cp; 13131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n; 13141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const u_char *eom; 13151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *bp, *ep; 13161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int type, class, ancount, qdcount; 13171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int haveanswer, had_error; 13181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char tbuf[MAXDNAME]; 13191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int (*name_ok) (const char *); 13201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char hostbuf[8*1024]; 13211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(answer != NULL); 13231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(qname != NULL); 13241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 13251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&sentinel, 0, sizeof(sentinel)); 13271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 13281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project canonname = NULL; 13301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project eom = answer->buf + anslen; 13311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (qtype) { 13321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_A: 13331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_AAAA: 13341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ 13351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project name_ok = res_hnok; 13361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 13371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 13381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; /* XXX should be abort(); */ 13391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 13411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * find first satisfactory answer 13421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 13431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hp = &answer->hdr; 13441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ancount = ntohs(hp->ancount); 13451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project qdcount = ntohs(hp->qdcount); 13461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp = hostbuf; 13471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ep = hostbuf + sizeof hostbuf; 13481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp = answer->buf + HFIXEDSZ; 13491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (qdcount != 1) { 13501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 13511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 13521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 13541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n < 0) || !(*name_ok)(bp)) { 13551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 13561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 13571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n + QFIXEDSZ; 13591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { 13601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* res_send() has already verified that the query name is the 13611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * same as the one we sent; this just gets the expanded name 13621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (i.e., with the succeeding search-domain tacked on). 13631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 13641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = strlen(bp) + 1; /* for the \0 */ 13651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n >= MAXHOSTNAMELEN) { 13661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 13671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 13681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project canonname = bp; 13701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp += n; 13711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* The qname can be abbreviated, but h_name is now absolute. */ 13721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project qname = canonname; 13731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project haveanswer = 0; 13751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error = 0; 13761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (ancount-- > 0 && cp < eom && !had_error) { 13771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 13781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n < 0) || !(*name_ok)(bp)) { 13791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error++; 13801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 13811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; /* name */ 13831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project type = _getshort(cp); 1384b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti cp += INT16SZ; /* type */ 13851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project class = _getshort(cp); 1386b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti cp += INT16SZ + INT32SZ; /* class, TTL */ 13871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = _getshort(cp); 13881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += INT16SZ; /* len */ 13891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (class != C_IN) { 13901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX - debug? syslog? */ 13911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 13921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; /* XXX - had_error++ ? */ 13931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 13941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && 13951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project type == T_CNAME) { 13961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 13971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((n < 0) || !(*name_ok)(tbuf)) { 13981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error++; 13991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Get canonical name. */ 14031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = strlen(tbuf) + 1; /* for the \0 */ 14041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n > ep - bp || n >= MAXHOSTNAMELEN) { 14051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error++; 14061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strlcpy(bp, tbuf, (size_t)(ep - bp)); 14091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project canonname = bp; 14101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp += n; 14111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (qtype == T_ANY) { 14141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(type == T_A || type == T_AAAA)) { 14151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (type != qtype) { 14191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (type != T_KEY && type != T_SIG) 14201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project syslog(LOG_NOTICE|LOG_AUTH, 14211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 14221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project qname, p_class(C_IN), p_type(qtype), 14231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p_type(type)); 14241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; /* XXX - had_error++ ? */ 14261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (type) { 14281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_A: 14291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case T_AAAA: 14301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (strcasecmp(canonname, bp) != 0) { 14311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project syslog(LOG_NOTICE|LOG_AUTH, 14321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project AskedForGot, canonname, bp); 14331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; /* XXX - had_error++ ? */ 14351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (type == T_A && n != INADDRSZ) { 14371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (type == T_AAAA && n != IN6ADDRSZ) { 14411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (type == T_AAAA) { 14451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct in6_addr in6; 14461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(&in6, cp, IN6ADDRSZ); 14471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_V4MAPPED(&in6)) { 14481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!haveanswer) { 14531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int nn; 14541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project canonname = bp; 14561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project nn = strlen(bp) + 1; /* for the \0 */ 14571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bp += nn; 14581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* don't overwrite pai */ 14611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = *pai; 14621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; 14631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afd = find_afd(ai.ai_family); 14641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afd == NULL) { 14651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 14671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur->ai_next = get_ai(&ai, afd, (const char *)cp); 14691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cur->ai_next == NULL) 14701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project had_error++; 14711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 14721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 14731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp += n; 14741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 14751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 14761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project abort(); 14771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!had_error) 14791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project haveanswer++; 14801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (haveanswer) { 14821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!canonname) 14831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)get_canonname(pai, sentinel.ai_next, qname); 14841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 14851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)get_canonname(pai, sentinel.ai_next, canonname); 14861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NETDB_SUCCESS; 14871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return sentinel.ai_next; 14881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 14891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 14911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NULL; 14921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 14931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14949ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstruct addrinfo_sort_elem { 14959ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson struct addrinfo *ai; 14969ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int has_src_addr; 149750ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner sockaddr_union src_addr; 14989ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int original_order; 14999ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson}; 15001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 15019ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 15029ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 15039ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_get_scope(const struct sockaddr *addr) 15041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 15059ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (addr->sa_family == AF_INET6) { 15069ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; 15079ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) { 15089ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_MC_SCOPE(&addr6->sin6_addr); 15099ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) || 15109ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) { 15119ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 15129ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * RFC 4291 section 2.5.3 says loopback is to be treated as having 15139ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * link-local scope. 15149ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 15159ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_LINKLOCAL; 15169ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) { 15179ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_SITELOCAL; 15189ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 15199ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_GLOBAL; 15209ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15219ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (addr->sa_family == AF_INET) { 15229ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr; 15239ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson unsigned long int na = ntohl(addr4->sin_addr.s_addr); 15249ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15259ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (IN_LOOPBACK(na) || /* 127.0.0.0/8 */ 15269ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson (na & 0xffff0000) == 0xa9fe0000) { /* 169.254.0.0/16 */ 15279ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_LINKLOCAL; 15289ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 1529d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson /* 1530d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson * According to draft-ietf-6man-rfc3484-revise-01 section 2.3, 1531d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson * it is best not to treat the private IPv4 ranges 1532d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson * (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) as being 1533d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson * in a special scope, so we don't. 1534d1624add2b73ce8ff7826ce27b1d6d6e35bb83a6Steinar H. Gunderson */ 15359ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_GLOBAL; 15369ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15379ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 15389ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 15399ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * This should never happen. 15409ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Return a scope with low priority as a last resort. 15419ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 15429ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return IPV6_ADDR_SCOPE_NODELOCAL; 15439ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15449ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 15459ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15469ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* These macros are modelled after the ones in <netinet/in6.h>. */ 15479ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15489ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* RFC 4380, section 2.6 */ 15499ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson#define IN6_IS_ADDR_TEREDO(a) \ 15509ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson ((*(const uint32_t *)(const void *)(&(a)->s6_addr[0]) == ntohl(0x20010000))) 15519ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15529ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* RFC 3056, section 2. */ 15539ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson#define IN6_IS_ADDR_6TO4(a) \ 15549ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson (((a)->s6_addr[0] == 0x20) && ((a)->s6_addr[1] == 0x02)) 15559ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15562e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson/* 6bone testing address area (3ffe::/16), deprecated in RFC 3701. */ 15572e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson#define IN6_IS_ADDR_6BONE(a) \ 15582e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson (((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe)) 15592e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson 15609ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 15619ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Get the label for a given IPv4/IPv6 address. 15622e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01. 15639ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 15649ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 15659ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 15669ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 15679ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_get_label(const struct sockaddr *addr) 15689ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 15699ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (addr->sa_family == AF_INET) { 15702e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 3; 15719ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (addr->sa_family == AF_INET6) { 15729ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; 15739ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) { 15749ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 0; 15752e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) { 15762e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 1; 15772e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) { 15789ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 3; 15792e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) { 15802e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 4; 15819ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) { 15829ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 5; 15832e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) { 15842e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 10; 15852e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) { 15862e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 11; 15872e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) { 15882e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 12; 15899ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 15902e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 2; 15919ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15929ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 15939ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 15949ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * This should never happen. 15959ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Return a semi-random label as a last resort. 15969ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 15979ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 1; 15989ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 15999ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 16009ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16019ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 16029ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Get the precedence for a given IPv4/IPv6 address. 16032e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01. 16049ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 16059ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16069ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 16079ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 16089ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_get_precedence(const struct sockaddr *addr) 16099ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 16109ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (addr->sa_family == AF_INET) { 16112e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 30; 16129ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (addr->sa_family == AF_INET6) { 16139ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr; 16149ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) { 16152e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 60; 16162e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) { 16179ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 50; 16182e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) { 16192e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 30; 16202e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) { 16219ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 20; 16229ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) { 16232e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 10; 16242e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) || 1625b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) || 1626b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) { 16272e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 1; 16289ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 16299ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 40; 16309ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 16319ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 16322e23e29245aa42d0f9419187c94e72dba3888eefSteinar H. Gunderson return 1; 16339ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 16349ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 16359ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16369ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 16379ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Find number of matching initial bits between the two addresses a1 and a2. 16389ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 16399ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16409ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 16419ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 16429ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_common_prefix_len(const struct in6_addr *a1, const struct in6_addr *a2) 16439ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 16449ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const char *p1 = (const char *)a1; 16459ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const char *p2 = (const char *)a2; 16469ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson unsigned i; 16479ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16489ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson for (i = 0; i < sizeof(*a1); ++i) { 16499ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int x, j; 16509ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16519ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (p1[i] == p2[i]) { 16529ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson continue; 16539ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 16549ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson x = p1[i] ^ p2[i]; 16559ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson for (j = 0; j < CHAR_BIT; ++j) { 16569ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (x & (1 << (CHAR_BIT - 1))) { 16579ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return i * CHAR_BIT + j; 16581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 16599ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson x <<= 1; 16601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 16611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 16629ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return sizeof(*a1) * CHAR_BIT; 16639ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 16649ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16659ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 16669ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Compare two source/destination address pairs. 16679ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * RFC 3484, section 6. 16689ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 16699ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16709ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 16719ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 16729ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_rfc3484_compare(const void *ptr1, const void* ptr2) 16739ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 16749ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct addrinfo_sort_elem *a1 = (const struct addrinfo_sort_elem *)ptr1; 16759ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct addrinfo_sort_elem *a2 = (const struct addrinfo_sort_elem *)ptr2; 16769ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int scope_src1, scope_dst1, scope_match1; 16779ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int scope_src2, scope_dst2, scope_match2; 16789ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int label_src1, label_dst1, label_match1; 16799ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int label_src2, label_dst2, label_match2; 16809ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int precedence1, precedence2; 16819ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int prefixlen1, prefixlen2; 16829ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16839ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 1: Avoid unusable destinations. */ 16849ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (a1->has_src_addr != a2->has_src_addr) { 16859ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return a2->has_src_addr - a1->has_src_addr; 16869ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 16879ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16889ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 2: Prefer matching scope. */ 168950ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner scope_src1 = _get_scope(&a1->src_addr.generic); 16909ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson scope_dst1 = _get_scope(a1->ai->ai_addr); 16919ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson scope_match1 = (scope_src1 == scope_dst1); 16929ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 169350ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner scope_src2 = _get_scope(&a2->src_addr.generic); 16949ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson scope_dst2 = _get_scope(a2->ai->ai_addr); 16959ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson scope_match2 = (scope_src2 == scope_dst2); 16969ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 16979ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (scope_match1 != scope_match2) { 16989ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return scope_match2 - scope_match1; 16999ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17009ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17019ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 17029ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 3: Avoid deprecated addresses. 17039ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * TODO(sesse): We don't currently have a good way of finding this. 17049ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17059ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17069ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 17079ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 4: Prefer home addresses. 17089ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * TODO(sesse): We don't currently have a good way of finding this. 17099ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17109ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17119ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 5: Prefer matching label. */ 171250ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner label_src1 = _get_label(&a1->src_addr.generic); 17139ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson label_dst1 = _get_label(a1->ai->ai_addr); 17149ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson label_match1 = (label_src1 == label_dst1); 17159ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 171650ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner label_src2 = _get_label(&a2->src_addr.generic); 17179ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson label_dst2 = _get_label(a2->ai->ai_addr); 17189ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson label_match2 = (label_src2 == label_dst2); 17199ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17209ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (label_match1 != label_match2) { 17219ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return label_match2 - label_match1; 17229ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17239ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17249ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 6: Prefer higher precedence. */ 17259ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson precedence1 = _get_precedence(a1->ai->ai_addr); 17269ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson precedence2 = _get_precedence(a2->ai->ai_addr); 17279ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (precedence1 != precedence2) { 17289ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return precedence2 - precedence1; 17299ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17309ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17319ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 17329ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 7: Prefer native transport. 17339ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * TODO(sesse): We don't currently have a good way of finding this. 17349ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17359ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17369ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Rule 8: Prefer smaller scope. */ 17379ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (scope_dst1 != scope_dst2) { 17389ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return scope_dst1 - scope_dst2; 17399ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17409ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17419ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 17429ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 9: Use longest matching prefix. 17439ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * We implement this for IPv6 only, as the rules in RFC 3484 don't seem 17449ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * to work very well directly applied to IPv4. (glibc uses information from 17459ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * the routing table for a custom IPv4 implementation here.) 17469ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17479ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (a1->has_src_addr && a1->ai->ai_addr->sa_family == AF_INET6 && 17489ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson a2->has_src_addr && a2->ai->ai_addr->sa_family == AF_INET6) { 174950ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner const struct sockaddr_in6 *a1_src = &a1->src_addr.in6; 17509ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *a1_dst = (const struct sockaddr_in6 *)a1->ai->ai_addr; 175150ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner const struct sockaddr_in6 *a2_src = &a2->src_addr.in6; 17529ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson const struct sockaddr_in6 *a2_dst = (const struct sockaddr_in6 *)a2->ai->ai_addr; 17539ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson prefixlen1 = _common_prefix_len(&a1_src->sin6_addr, &a1_dst->sin6_addr); 17547e0bfb511e85834d7c6cb9631206b62f82701d60Kenny Root prefixlen2 = _common_prefix_len(&a2_src->sin6_addr, &a2_dst->sin6_addr); 17559ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (prefixlen1 != prefixlen2) { 17569ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return prefixlen2 - prefixlen1; 17579ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17589ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17599ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17609ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 17619ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Rule 10: Leave the order unchanged. 17629ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * We need this since qsort() is not necessarily stable. 17639ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17649ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return a1->original_order - a2->original_order; 17659ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 17669ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17679ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 17689ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Find the source address that will be used if trying to connect to the given 17699ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * address. src_addr must be large enough to hold a struct sockaddr_in6. 17709ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * 17719ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Returns 1 if a source address was found, 0 if the address is unreachable, 17729ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are 17739ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * undefined. 17749ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 17759ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17769ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 17779ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic int 17789ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr) 17799ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 17809ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int sock; 17819ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int ret; 17829ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson socklen_t len; 17839ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17849ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson switch (addr->sa_family) { 17859ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson case AF_INET: 17869ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson len = sizeof(struct sockaddr_in); 17879ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson break; 17889ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson case AF_INET6: 17899ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson len = sizeof(struct sockaddr_in6); 17909ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson break; 17919ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson default: 17929ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* No known usable source address for non-INET families. */ 17939ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 0; 17949ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 17959ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 17969ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson sock = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); 17979ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (sock == -1) { 17989ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (errno == EAFNOSUPPORT) { 17999ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 0; 18009ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } else { 18019ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return -1; 18029ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18039ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18049ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18059ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson do { 18069ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson ret = connect(sock, addr, len); 18079ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } while (ret == -1 && errno == EINTR); 18089ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18099ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (ret == -1) { 18109ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson close(sock); 18119ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 0; 18129ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18139ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18149ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (getsockname(sock, src_addr, &len) == -1) { 18159ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson close(sock); 18169ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return -1; 18179ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18189ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson close(sock); 18199ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson return 1; 18209ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson} 18219ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18229ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/* 18239ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Sort the linked list starting at sentinel->ai_next in RFC3484 order. 18249ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Will leave the list unchanged if an error occurs. 18259ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 18269ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18279ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson/*ARGSUSED*/ 18289ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonstatic void 18299ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson_rfc3484_sort(struct addrinfo *list_sentinel) 18309ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson{ 18319ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson struct addrinfo *cur; 18329ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int nelem = 0, i; 18339ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson struct addrinfo_sort_elem *elems; 18349ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18359ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson cur = list_sentinel->ai_next; 18369ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson while (cur) { 18379ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson ++nelem; 18389ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson cur = cur->ai_next; 18399ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18409ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18419ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems = (struct addrinfo_sort_elem *)malloc(nelem * sizeof(struct addrinfo_sort_elem)); 18429ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (elems == NULL) { 18439ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson goto error; 18449ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18459ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18469ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* 18479ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * Convert the linked list to an array that also contains the candidate 18489ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson * source address for each destination address. 18499ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson */ 18509ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson for (i = 0, cur = list_sentinel->ai_next; i < nelem; ++i, cur = cur->ai_next) { 18519ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson int has_src_addr; 18529ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson assert(cur != NULL); 18539ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[i].ai = cur; 18549ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[i].original_order = i; 18559ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 185650ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic); 18579ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson if (has_src_addr == -1) { 18589ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson goto error; 18599ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18609ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[i].has_src_addr = has_src_addr; 18619ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18629ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18639ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson /* Sort the addresses, and rearrange the linked list so it matches the sorted order. */ 18649ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson qsort((void *)elems, nelem, sizeof(struct addrinfo_sort_elem), _rfc3484_compare); 18659ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson 18669ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson list_sentinel->ai_next = elems[0].ai; 18679ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson for (i = 0; i < nelem - 1; ++i) { 18689ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[i].ai->ai_next = elems[i + 1].ai; 18699ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson } 18709ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson elems[nelem - 1].ai->ai_next = NULL; 18711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 18729ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gundersonerror: 18739ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson free(elems); 18741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 18751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1876ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwaltstatic int _using_alt_dns() 1877ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt{ 1878ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt char propname[PROP_NAME_MAX]; 1879ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt char propvalue[PROP_VALUE_MAX]; 1880ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt 1881ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt propvalue[0] = 0; 1882ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt snprintf(propname, sizeof(propname), "net.dns1.%d", getpid()); 1883ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt if (__system_property_get(propname, propvalue) > 0 ) { 1884ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt return 1; 1885ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt } 1886ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt return 0; 1887ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt} 1888ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt 18891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*ARGSUSED*/ 18901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 18911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_dns_getaddrinfo(void *rv, void *cb_data, va_list ap) 18921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 18931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *ai; 18941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project querybuf *buf, *buf2; 18951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *name; 18961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *pai; 18971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel, *cur; 18981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target q, q2; 18991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project res_state res; 19001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project name = va_arg(ap, char *); 19021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai = va_arg(ap, const struct addrinfo *); 19035e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner //fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name); 19041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&q, 0, sizeof(q)); 19061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&q2, 0, sizeof(q2)); 19071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&sentinel, 0, sizeof(sentinel)); 19081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 19091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project buf = malloc(sizeof(*buf)); 19111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (buf == NULL) { 19121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NETDB_INTERNAL; 19131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 19141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project buf2 = malloc(sizeof(*buf2)); 19161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (buf2 == NULL) { 19171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 19181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NETDB_INTERNAL; 19191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 19201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (pai->ai_family) { 19231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_UNSPEC: 19241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* prefer IPv6 */ 19251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.name = name; 19261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qclass = C_IN; 19271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.answer = buf->buf; 19281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.anslen = sizeof(buf->buf); 1929ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti int query_ipv6 = 1, query_ipv4 = 1; 1930ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti if (pai->ai_flags & AI_ADDRCONFIG) { 1931ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt // Only implement AI_ADDRCONFIG if the application is not 1932ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt // using its own DNS servers, since our implementation 1933ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt // only works on the default connection. 1934ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt if (!_using_alt_dns()) { 1935ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt query_ipv6 = _have_ipv6(); 1936ca6fe7bebe3cc6ed7e2db5a3ede2de0fcddf411dRobert Greenwalt query_ipv4 = _have_ipv4(); 1937f432de2de7288c0589d1e50c2aa949a76c571794Lorenzo Colitti } 1938ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti } 1939ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti if (query_ipv6) { 19403d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti q.qtype = T_AAAA; 1941ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti if (query_ipv4) { 1942ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q.next = &q2; 1943ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.name = name; 1944ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.qclass = C_IN; 1945ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.qtype = T_A; 1946ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.answer = buf2->buf; 1947ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti q2.anslen = sizeof(buf2->buf); 1948ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti } 1949ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti } else if (query_ipv4) { 19503d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti q.qtype = T_A; 1951ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti } else { 1952ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti free(buf); 1953ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti free(buf2); 1954ba96e30fa08212e48ec1ff9c1d545b2d05e787b0Lorenzo Colitti return NS_NOTFOUND; 19553d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07Lorenzo Colitti } 19561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 19571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 19581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.name = name; 19591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qclass = C_IN; 19601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qtype = T_A; 19611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.answer = buf->buf; 19621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.anslen = sizeof(buf->buf); 19631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 19641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 19651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.name = name; 19661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qclass = C_IN; 19671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.qtype = T_AAAA; 19681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.answer = buf->buf; 19691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project q.anslen = sizeof(buf->buf); 19701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 19711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 19721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 19731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf2); 19741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_UNAVAIL; 19751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project res = __res_get_state(); 19781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res == NULL) { 19791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 19801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf2); 19811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 19821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 19841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res_searchN(name, &q, res) < 0) { 19851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project __res_put_state(res); 19861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 19871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf2); 19881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 19891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = getanswer(buf, q.n, q.name, q.qtype, pai); 19911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai) { 19921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur->ai_next = ai; 19931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 19941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 19951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 19961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (q.next) { 19971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai); 19981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ai) 19991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur->ai_next = ai; 20001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf); 20021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project free(buf2); 20031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next == NULL) { 20041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project __res_put_state(res); 20051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (h_errno) { 20061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case HOST_NOT_FOUND: 20071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 20081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case TRY_AGAIN: 20091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_TRYAGAIN; 20101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 20111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_UNAVAIL; 20121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20159ab75d4cc803e91b7f1b656ffbe2ad32c52a86f9Steinar H. Gunderson _rfc3484_sort(&sentinel); 20161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project __res_put_state(res); 20181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *((struct addrinfo **)rv) = sentinel.ai_next; 20201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_SUCCESS; 20211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 20221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 20241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_sethtent(FILE **hostf) 20251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 20261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!*hostf) 20281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *hostf = fopen(_PATH_HOSTS, "r" ); 20291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 20301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project rewind(*hostf); 20311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 20321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void 20341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_endhtent(FILE **hostf) 20351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 20361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*hostf) { 20381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void) fclose(*hostf); 20391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *hostf = NULL; 20401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 20421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct addrinfo * 20441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) 20451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 20461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *p; 20471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *cp, *tname, *cname; 20481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo hints, *res0, *res; 20491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 20501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *addr; 20511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char hostbuf[8*1024]; 20521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// fprintf(stderr, "_gethtent() name = '%s'\n", name); 20541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(name != NULL); 20551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(pai != NULL); 20561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" ))) 20581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 20591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project again: 20601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf))) 20611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (NULL); 20621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*p == '#') 20631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(cp = strpbrk(p, "#\n"))) 20651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cp = '\0'; 20671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(cp = strpbrk(p, " \t"))) 20681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cp++ = '\0'; 20701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project addr = p; 20711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* if this is not something we're looking for, skip it. */ 20721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cname = NULL; 20731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cp && *cp) { 20741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (*cp == ' ' || *cp == '\t') { 20751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cp++; 20761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 20771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!cname) 20791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cname = cp; 20801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tname = cp; 20811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((cp = strpbrk(cp, " \t")) != NULL) 20821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *cp++ = '\0'; 20831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// fprintf(stderr, "\ttname = '%s'", tname); 20841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (strcasecmp(name, tname) == 0) 20851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto found; 20861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 20871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfound: 20901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hints = *pai; 20911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hints.ai_flags = AI_NUMERICHOST; 20921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project error = getaddrinfo(addr, NULL, &hints, &res0); 20931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (error) 20941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 20951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (res = res0; res; res = res->ai_next) { 20961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* cover it up */ 20971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project res->ai_flags = pai->ai_flags; 20981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 20991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (pai->ai_flags & AI_CANONNAME) { 21001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (get_canonname(pai, res, cname) != 0) { 21011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project freeaddrinfo(res0); 21021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto again; 21031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 21041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 21051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 21061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return res0; 21071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 21081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*ARGSUSED*/ 21101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 21111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_files_getaddrinfo(void *rv, void *cb_data, va_list ap) 21121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 21131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *name; 21141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct addrinfo *pai; 21151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo sentinel, *cur; 21161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct addrinfo *p; 21171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project FILE *hostf = NULL; 21181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project name = va_arg(ap, char *); 21201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project pai = va_arg(ap, struct addrinfo *); 21211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project// fprintf(stderr, "_files_getaddrinfo() name = '%s'\n", name); 21231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memset(&sentinel, 0, sizeof(sentinel)); 21241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = &sentinel; 21251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project _sethtent(&hostf); 21271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while ((p = _gethtent(&hostf, name, pai)) != NULL) { 21281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur->ai_next = p; 21291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while (cur && cur->ai_next) 21301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project cur = cur->ai_next; 21311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 21321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project _endhtent(&hostf); 21331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *((struct addrinfo **)rv) = sentinel.ai_next; 21351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sentinel.ai_next == NULL) 21361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_NOTFOUND; 21371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return NS_SUCCESS; 21381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 21391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* resolver logic */ 21411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 21431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Formulate a normal query, send, and await answer. 21441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Returned answer is placed in supplied buffer "answer". 21451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Perform preliminary check of answer, returning success only 21461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if no error is indicated and the answer count is nonzero. 21471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Return the size of the response on success, -1 on error. 21481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Error number is left in h_errno. 21491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 21501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Caller must parse answer and determine whether it answers the question. 21511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 21521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 21531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_queryN(const char *name, /* domain name */ struct res_target *target, 21541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project res_state res) 21551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 21561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char buf[MAXPACKET]; 21571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HEADER *hp; 21581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n; 21591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target *t; 21601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int rcode; 21611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int ancount; 21621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(name != NULL); 21641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX: target may be NULL??? */ 21651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project rcode = NOERROR; 21671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ancount = 0; 21681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (t = target; t; t = t->next) { 21701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int class, type; 21711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char *answer; 21721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int anslen; 21731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hp = (HEADER *)(void *)t->answer; 21751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hp->rcode = NOERROR; /* default */ 21761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* make it easier... */ 21781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project class = t->qclass; 21791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project type = t->qtype; 21801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project answer = t->answer; 21811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project anslen = t->anslen; 21821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 21831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 21841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; res_nquery(%s, %d, %d)\n", name, class, type); 21851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 21861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 21871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, 21881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project buf, sizeof(buf)); 21891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef RES_USE_EDNS0 21901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n > 0 && (res->options & RES_USE_EDNS0) != 0) 21911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = res_nopt(res, n, buf, sizeof(buf), anslen); 21921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 21931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n <= 0) { 21941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 21951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 21961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; res_nquery: mkquery failed\n"); 21971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 21981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 21991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return n; 22001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = res_nsend(res, buf, n, answer, anslen); 22021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 22031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n < 0) { 22041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 22051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 22061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; res_query: send error\n"); 22071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 22081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = TRY_AGAIN; 22091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return n; 22101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 22121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 22141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project rcode = hp->rcode; /* record most recent error */ 22151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 22161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 22171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; rcode = %u, ancount=%u\n", hp->rcode, 22181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ntohs(hp->ancount)); 22191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 22201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 22211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ancount += ntohs(hp->ancount); 22241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project t->n = n; 22261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ancount == 0) { 22291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (rcode) { 22301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NXDOMAIN: 22311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = HOST_NOT_FOUND; 22321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 22331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case SERVFAIL: 22341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = TRY_AGAIN; 22351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 22361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NOERROR: 22371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_DATA; 22381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 22391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case FORMERR: 22401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NOTIMP: 22411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case REFUSED: 22421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 22431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 22441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 22451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 22471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ancount; 22491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 22501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 22521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Formulate a normal query, send, and retrieve answer in supplied buffer. 22531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Return the size of the response on success, -1 on error. 22541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If enabled, implement search rules until answer or unrecoverable failure 22551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is detected. Error code, if any, is left in h_errno. 22561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 22571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 22581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_searchN(const char *name, struct res_target *target, res_state res) 22591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 22601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *cp, * const *domain; 22611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project HEADER *hp; 22621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_int dots; 22631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int trailing_dot, ret, saved_herrno; 22641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 22651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(name != NULL); 22671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(target != NULL); 22681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hp = (HEADER *)(void *)target->answer; /*XXX*/ 22701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = 0; 22721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = HOST_NOT_FOUND; /* default, if we never query */ 22731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dots = 0; 22741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (cp = name; *cp; cp++) 22751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project dots += (*cp == '.'); 22761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project trailing_dot = 0; 22771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (cp > name && *--cp == '.') 22781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project trailing_dot++; 22791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22815e563700380eade647f347669ea61dbb0ede9814David 'Digit' Turner //fprintf(stderr, "res_searchN() name = '%s'\n", name); 22821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 22841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if there aren't any dots, it could be a user-level alias 22851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 22861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!dots && (cp = __hostalias(name)) != NULL) { 22871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret = res_queryN(cp, target, res); 22881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ret; 22891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 22901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 22911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 22921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If there are dots in the name already, let's just give it a try 22931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 'as is'. The threshold can be set with the "ndots" option. 22941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 22951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project saved_herrno = -1; 22961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (dots >= res->ndots) { 22971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret = res_querydomainN(name, NULL, target, res); 22981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ret > 0) 22991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ret); 23001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project saved_herrno = h_errno; 23011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tried_as_is++; 23021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 23051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * We do at least one level of search if 23061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - there is no dot and RES_DEFNAME is set, or 23071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - there is at least one dot, there is no trailing dot, 23081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * and RES_DNSRCH is set. 23091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((!dots && (res->options & RES_DEFNAMES)) || 23111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (dots && !trailing_dot && (res->options & RES_DNSRCH))) { 23121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int done = 0; 23131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (domain = (const char * const *)res->dnsrch; 23151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *domain && !done; 23161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project domain++) { 23171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret = res_querydomainN(name, *domain, target, res); 23191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ret > 0) 23201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ret; 23211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 23231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If no server present, give up. 23241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If name isn't found in this domain, 23251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * keep trying higher domains in the search list 23261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (if that's enabled). 23271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * On a NO_DATA error, keep trying, otherwise 23281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * a wildcard entry of another type could keep us 23291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * from finding this entry higher in the domain. 23301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * If we get some other error (negative answer or 23311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * server failure), then stop searching up, 23321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * but try the input name below in case it's 23331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * fully-qualified. 23341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (errno == ECONNREFUSED) { 23361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = TRY_AGAIN; 23371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 23381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (h_errno) { 23411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case NO_DATA: 23421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project got_nodata++; 23431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* FALLTHROUGH */ 23441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case HOST_NOT_FOUND: 23451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* keep trying */ 23461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 23471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case TRY_AGAIN: 23481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hp->rcode == SERVFAIL) { 23491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* try next search element, if any */ 23501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project got_servfail++; 23511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 23521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* FALLTHROUGH */ 23541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 23551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* anything else implies that we're done */ 23561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project done++; 23571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 23591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we got here for some reason other than DNSRCH, 23601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * we only wanted one iteration of the loop, so stop. 23611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!(res->options & RES_DNSRCH)) 2363b82532d11a301370c14f77f2e56dee11f8bfa971Lorenzo Colitti done++; 23641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 23681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we have not already tried the name "as is", do that now. 23691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * note that we do this regardless of how many dots were in the 23701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * name or whether it ends with a dot. 23711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (!tried_as_is) { 23731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret = res_querydomainN(name, NULL, target, res); 23741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ret > 0) 23751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ret; 23761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 23771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 23791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we got here, we didn't satisfy the search. 23801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * if we did an initial full query, return that query's h_errno 23811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (note that we wouldn't be here if that query had succeeded). 23821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * else if we ever got a nodata, send that back as the reason. 23831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * else send back meaningless h_errno, that being the one from 23841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the last DNSRCH we did. 23851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (saved_herrno != -1) 23871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = saved_herrno; 23881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if (got_nodata) 23891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_DATA; 23901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if (got_servfail) 23911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = TRY_AGAIN; 23921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 23931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 23941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 23951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 23961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Perform a call on res_query on the concatenation of name and domain, 23971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * removing a trailing dot from name if domain is NULL. 23981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 23991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 24001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectres_querydomainN(const char *name, const char *domain, 24011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct res_target *target, res_state res) 24021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 24031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char nbuf[MAXDNAME]; 24041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *longname = nbuf; 24051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t n, d; 24061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 24071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(name != NULL); 24081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* XXX: target may be NULL??? */ 24091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 24101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG 24111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (res->options & RES_DEBUG) 24121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project printf(";; res_querydomain(%s, %s)\n", 24131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project name, domain?domain:"<Nil>"); 24141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 24151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (domain == NULL) { 24161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 24171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Check for trailing '.'; 24181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copy without '.' if present. 24191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 24201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = strlen(name); 24211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n + 1 > sizeof(nbuf)) { 24221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 24231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 24241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 24251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n > 0 && name[--n] == '.') { 24261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strncpy(nbuf, name, n); 24271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project nbuf[n] = '\0'; 24281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else 24291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project longname = name; 24301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 24311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = strlen(name); 24321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project d = strlen(domain); 24331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n + 1 + d + 1 > sizeof(nbuf)) { 24341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project h_errno = NO_RECOVERY; 24351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 24361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 24371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); 24381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 24391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return res_queryN(longname, target, res); 24401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2441