getnameinfo.c revision d8213bb5738ac778fcb5d696d1294b0f8ddae7f3
1d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes/* $NetBSD: getnameinfo.c,v 1.53 2012/09/26 23:13:00 christos Exp $ */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* $KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $ */ 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 2000 Ben Harris. 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved. 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * documentation and/or other materials provided with the distribution. 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. Neither the name of the project nor the names of its contributors 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * may be used to endorse or promote products derived from this software 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * without specific prior written permission. 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Issues to be discussed: 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - Thread safe-ness must be checked 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - RFC2553 says that we should raise error on short buffer. X/Open says 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * we need to truncate the result. We obey RFC2553 (and X/Open should be 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modified). ipngwg rough consensus seems to follow RFC2553. 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - What is "local" in NI_FQDN? 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other. 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * sin6_scope_id is filled - standardization status? 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * XXX breaks backward compat for code that expects no scopeid. 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * beware on merge. 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h> 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if defined(LIBC_SCCS) && !defined(lint) 50d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes__RCSID("$NetBSD: getnameinfo.c,v 1.53 2012/09/26 23:13:00 christos Exp $"); 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* LIBC_SCCS and not lint */ 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h> 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h> 55d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes#include <sys/un.h> 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <net/if.h> 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <net/if_ieee1394.h> 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <net/if_types.h> 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h> 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <arpa/inet.h> 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <assert.h> 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <limits.h> 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netdb.h> 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef ANDROID_CHANGES 65d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes#include "arpa_nameser.h" 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h" 67149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk#include <sys/system_properties.h> 68149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk#include <stdlib.h> 69149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk#include <unistd.h> 70149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk#include <errno.h> 71d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes#define MIN(x,y) ((x) < (y) ? (x) : (y)) 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <resolv.h> 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stddef.h> 761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h> 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const struct afd { 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_af; 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project socklen_t a_addrlen; 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project socklen_t a_socklen; 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int a_off; 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} afdl [] = { 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project offsetof(struct sockaddr_in6, sin6_addr)}, 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project offsetof(struct sockaddr_in, sin_addr)}, 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project {0, 0, 0, 0}, 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct sockinet { 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char si_len; 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_char si_family; 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_short si_port; 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 99d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughesstatic int getnameinfo_inet(const struct sockaddr *, socklen_t, char *, 100d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes socklen_t, char *, socklen_t, int); 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 102d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughesstatic int ip6_parsenumeric(const struct sockaddr *, const char *, char *, 103d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes socklen_t, int); 104d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughesstatic int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int); 1055056f1fad1187cd67729bb04ba72397d78256f03Elliott Hughes#endif 106d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughesstatic int getnameinfo_local(const struct sockaddr *, socklen_t, char *, 107d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes socklen_t, char *, socklen_t, int); 10806e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Top-level getnameinfo() code. Look at the address family, and pick an 1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * appropriate function to call. 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags) 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (sa->sa_family) { 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return getnameinfo_inet(sa, salen, host, hostlen, 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project serv, servlen, flags); 120d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes case AF_LOCAL: 121d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes return getnameinfo_local(sa, salen, host, hostlen, 1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project serv, servlen, flags); 1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_FAMILY; 1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 128d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes/* 129d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes * getnameinfo_local(): 130d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes * Format an local address into a printable format. 131d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes */ 132d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes/* ARGSUSED */ 133d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughesstatic int 134d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughesgetnameinfo_local(const struct sockaddr *sa, socklen_t salen, 135d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes char *host, socklen_t hostlen, char *serv, socklen_t servlen, 136d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes int flags __attribute__((unused))) 137d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes{ 138d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes const struct sockaddr_un *sun = 139d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes (const struct sockaddr_un *)(const void *)sa; 140d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes 141d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes if (salen < (socklen_t) offsetof(struct sockaddr_un, sun_path)) { 142d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes return EAI_FAMILY; 143d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes } 144d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes 145d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes if (serv != NULL && servlen > 0) 146d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes serv[0] = '\0'; 147d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes 148d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes if (host && hostlen > 0) 149d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes strlcpy(host, sun->sun_path, 150d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes MIN((socklen_t) sizeof(sun->sun_path) + 1, hostlen)); 151d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes 152d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes return 0; 153d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes} 154d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes 155149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk#ifdef ANDROID_CHANGES 156149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk/* On success length of the host name is returned. A return 157149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk * value of 0 means there's no host name associated with 158149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk * the address. On failure -1 is returned in which case 159149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk * normal execution flow shall continue. */ 160149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falkstatic int 16106e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurunandroid_gethostbyaddr_proxy(char* nameBuf, size_t nameBufLen, const void *addr, socklen_t addrLen, int addrFamily) { 162149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 163149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk int sock; 164149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk const int one = 1; 165149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk struct sockaddr_un proxy_addr; 166149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk const char* cache_mode = getenv("ANDROID_DNS_MODE"); 167149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk FILE* proxy = NULL; 168149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk int result = -1; 169149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 170149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) { 171149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk // Don't use the proxy in local mode. This is used by the 172149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk // proxy itself. 173149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk return -1; 174149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 176149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk // Temporary cautious hack to disable the DNS proxy for processes 177149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk // requesting special treatment. Ideally the DNS proxy should 178149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk // accomodate these apps, though. 179149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk char propname[PROP_NAME_MAX]; 180149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk char propvalue[PROP_VALUE_MAX]; 181149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk snprintf(propname, sizeof(propname), "net.dns1.%d", getpid()); 182149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk if (__system_property_get(propname, propvalue) > 0) { 183149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk return -1; 184149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 185149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk // create socket 186149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk sock = socket(AF_UNIX, SOCK_STREAM, 0); 187149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk if (sock < 0) { 188149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk return -1; 189149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 190149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 191149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 192149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk memset(&proxy_addr, 0, sizeof(proxy_addr)); 193149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk proxy_addr.sun_family = AF_UNIX; 194149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", 195149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk sizeof(proxy_addr.sun_path)); 196c13fa640eea3285a586fc4bad0abf2fc1b902185Brian Carlstrom if (TEMP_FAILURE_RETRY(connect(sock, (const struct sockaddr*) (void*) &proxy_addr, 197149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk sizeof(proxy_addr))) != 0) { 198149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk close(sock); 199149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk return -1; 200149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 201149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 202149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk // send request to DnsProxyListener 203149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk proxy = fdopen(sock,"r+"); 204149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk if (proxy == NULL) { 205149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk goto exit; 206149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 207149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 208c13fa640eea3285a586fc4bad0abf2fc1b902185Brian Carlstrom char buf[INET6_ADDRSTRLEN]; // big enough for IPv4 and IPv6 20906e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun const char* addrStr = inet_ntop(addrFamily, addr, buf, sizeof(buf)); 210c13fa640eea3285a586fc4bad0abf2fc1b902185Brian Carlstrom if (addrStr == NULL) { 211c13fa640eea3285a586fc4bad0abf2fc1b902185Brian Carlstrom goto exit; 212c13fa640eea3285a586fc4bad0abf2fc1b902185Brian Carlstrom } 2131fb6662d1aa51eec54cfc133c40cacc0b15aad30Kenny Root if (fprintf(proxy, "gethostbyaddr %s %d %d", addrStr, addrLen, addrFamily) < 0) { 214149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk goto exit; 215149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 216149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 217149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk // literal NULL byte at end, required by FrameworkListener 218149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { 219149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk goto exit; 220149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 221149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 222149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk result = 0; 223c59ba4595be25a1213955233fcf9bcd1afe6438eRobert Greenwalt char msg_buf[4]; 22406e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun // read result code for gethostbyaddr 22506e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun if (fread(msg_buf, 1, sizeof(msg_buf), proxy) != sizeof(msg_buf)) { 22606e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun goto exit; 22706e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun } 22806e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun 22906e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun int result_code = (int)strtol(msg_buf, NULL, 10); 23006e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun // verify the code itself 231d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes // This should be synchronized to ResponseCode.h 232d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes static const int DnsProxyQueryResult = 222; 23306e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun if (result_code != DnsProxyQueryResult) { 23406e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun goto exit; 23506e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun } 23606e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun 237149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk uint32_t name_len; 238149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) { 239149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk goto exit; 240149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 241149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 242149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk name_len = ntohl(name_len); 24306e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun if (name_len <= 0 || name_len >= nameBufLen) { 244149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk goto exit; 245149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 246149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 24706e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun if (fread(nameBuf, name_len, 1, proxy) != 1) { 248149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk goto exit; 249149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 250149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 251149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk result = name_len; 252149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 253149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk exit: 254149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk if (proxy != NULL) { 255149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk fclose(proxy); 256149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 257149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 258149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk return result; 259149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk} 260149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk#endif 261d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * getnameinfo_inet(): 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Format an IPv4 or IPv6 sockaddr into a printable string. 2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 267d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughesgetnameinfo_inet(const struct sockaddr* sa, socklen_t salen, 268d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes char *host, socklen_t hostlen, 269d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes char *serv, socklen_t servlen, 270d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes int flags) 2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct afd *afd; 2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct servent *sp; 2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct hostent *hp; 2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project u_short port; 2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int family, i; 2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const char *addr; 278d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes uint32_t v4a; 2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char numserv[512]; 2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char numaddr[512]; 2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* sa is checked below */ 2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* host may be NULL */ 2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* serv may be NULL */ 2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sa == NULL) 2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_FAIL; 2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project family = sa->sa_family; 2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (i = 0; afdl[i].a_af; i++) 2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (afdl[i].a_af == family) { 2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project afd = &afdl[i]; 2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto found; 2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_FAMILY; 2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project found: 298d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes // http://b/1889275: callers should be allowed to provide too much 299d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes // space, but not too little. 300d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes if (salen < afd->a_socklen) { 301d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes return EAI_FAMILY; 302d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes } 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* network byte order */ 3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project port = ((const struct sockinet *)(const void *)sa)->si_port; 3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project addr = (const char *)(const void *)sa + afd->a_off; 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (serv == NULL || servlen == 0) { 3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * do nothing in this case. 3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * in case you are wondering if "&&" is more correct than 3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "||" here: rfc2553bis-03 says that serv == NULL OR 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * servlen == 0 means that the caller does not want the result. 3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (flags & NI_NUMERICSERV) 3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sp = NULL; 3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else { 3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sp = getservbyport(port, 3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (flags & NI_DGRAM) ? "udp" : "tcp"); 3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sp) { 3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (strlen(sp->s_name) + 1 > (size_t)servlen) 3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_MEMORY; 3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strlcpy(serv, sp->s_name, servlen); 3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project snprintf(numserv, sizeof(numserv), "%u", ntohs(port)); 3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (strlen(numserv) + 1 > (size_t)servlen) 3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_MEMORY; 3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strlcpy(serv, numserv, servlen); 3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (sa->sa_family) { 3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET: 336d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes v4a = (uint32_t) 3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ntohl(((const struct sockaddr_in *) 3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (const void *)sa)->sin_addr.s_addr); 3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) 3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project flags |= NI_NUMERICHOST; 3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v4a >>= IN_CLASSA_NSHIFT; 3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (v4a == 0) 3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project flags |= NI_NUMERICHOST; 3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct sockaddr_in6 *sin6; 3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sin6 = (const struct sockaddr_in6 *)(const void *)sa; 3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch (sin6->sin6_addr.s6_addr[0]) { 3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case 0x00: 3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) 3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ; 3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) 3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ; 3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project flags |= NI_NUMERICHOST; 3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project flags |= NI_NUMERICHOST; 3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project flags |= NI_NUMERICHOST; 3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (host == NULL || hostlen == 0) { 3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * do nothing in this case. 3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * in case you are wondering if "&&" is more correct than 3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "||" here: rfc2553bis-03 says that host == NULL or 3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * hostlen == 0 means that the caller does not want the result. 3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else if (flags & NI_NUMERICHOST) { 3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t numaddrlen; 3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* NUMERICHOST and NAMEREQD conflicts with each other */ 3821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (flags & NI_NAMEREQD) 3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_NONAME; 3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch(afd->a_af) { 3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 3881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 3891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((error = ip6_parsenumeric(sa, addr, host, 3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hostlen, flags)) != 0) 3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(error); 3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) 3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project == NULL) 4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SYSTEM; 4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project numaddrlen = strlen(numaddr); 4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (numaddrlen + 1 > (size_t)hostlen) /* don't forget terminator */ 4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_MEMORY; 4041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strlcpy(host, numaddr, hostlen); 4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 408149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk#ifdef ANDROID_CHANGES 409149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk struct hostent android_proxy_hostent; 410149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk char android_proxy_buf[MAXDNAME]; 411149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk 41206e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun int hostnamelen = android_gethostbyaddr_proxy(android_proxy_buf, 41306e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun MAXDNAME, addr, afd->a_addrlen, afd->a_af); 41406e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun if (hostnamelen > 0) { 41506e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun hp = &android_proxy_hostent; 41606e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun hp->h_name = android_proxy_buf; 41706e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun } else if (!hostnamelen) { 41806e1831f194389b6f56ac016ebb52ed5cd430bb2Selim Gurun hp = NULL; 419149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } else { 420149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); 421149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk } 422149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk#else 4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); 424149f7dfe0416f19a729d83bf5cfde44b5e28e0ecMattias Falk#endif 4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (hp) { 427d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes#if 0 4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * commented out, since "for local host" is not 4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * implemented here - see RFC2553 p30 4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (flags & NI_NOFQDN) { 4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *p; 4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p = strchr(hp->h_name, '.'); 4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (p) 4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *p = '\0'; 4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (strlen(hp->h_name) + 1 > (size_t)hostlen) { 4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_MEMORY; 4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strlcpy(host, hp->h_name, hostlen); 4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (flags & NI_NAMEREQD) 4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_NONAME; 4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project switch(afd->a_af) { 4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project case AF_INET6: 4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int error; 4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((error = ip6_parsenumeric(sa, addr, host, 4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hostlen, 4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project flags)) != 0) 4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(error); 4561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project default: 4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (inet_ntop(afd->a_af, addr, host, 4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project hostlen) == NULL) 4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SYSTEM; 4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(0); 4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef INET6 4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 472d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughesip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host, 473d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughes socklen_t hostlen, int flags) 4741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 4751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t numaddrlen; 4761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char numaddr[512]; 4771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(sa != NULL); 4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(addr != NULL); 4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(host != NULL); 4811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL) 4831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_SYSTEM; 4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project numaddrlen = strlen(numaddr); 48650ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner if (numaddrlen + 1 > (size_t)hostlen) /* don't forget terminator */ 4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_OVERFLOW; 4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project strlcpy(host, numaddr, hostlen); 4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (((const struct sockaddr_in6 *)(const void *)sa)->sin6_scope_id) { 4911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char zonebuf[MAXHOSTNAMELEN]; 4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int zonelen; 4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project zonelen = ip6_sa2str( 4951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (const struct sockaddr_in6 *)(const void *)sa, 4961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project zonebuf, sizeof(zonebuf), flags); 4971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (zonelen < 0) 4981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_OVERFLOW; 49950ace4fec5e8cb5afcbc656a4556fa528adfd760David 'Digit' Turner if ((size_t) zonelen + 1 + numaddrlen + 1 > (size_t)hostlen) 5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EAI_OVERFLOW; 5011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* construct <numeric-addr><delim><zoneid> */ 5021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project memcpy(host + numaddrlen + 1, zonebuf, 5031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (size_t)zonelen); 5041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project host[numaddrlen] = SCOPE_DELIMITER; 5051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project host[numaddrlen + 1 + zonelen] = '\0'; 5061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 5091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* ARGSUSED */ 5121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 513d8213bb5738ac778fcb5d696d1294b0f8ddae7f3Elliott Hughesip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags) 5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int ifindex; 5161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project const struct in6_addr *a6; 5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int n; 5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(sa6 != NULL); 5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project assert(buf != NULL); 5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ifindex = (unsigned int)sa6->sin6_scope_id; 5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project a6 = &sa6->sin6_addr; 5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef NI_NUMERICSCOPE 5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((flags & NI_NUMERICSCOPE) != 0) { 5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id); 5281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n < 0 || n >= bufsiz) 5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return n; 5321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 5341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* if_indextoname() does not take buffer size. not a good api... */ 5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) && 5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project bufsiz >= IF_NAMESIZE) { 5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project char *p = if_indextoname(ifindex, buf); 5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (p) { 5401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return(strlen(p)); 5411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 5441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* last resort */ 5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id); 5461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (n < 0 || (size_t) n >= bufsiz) 5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 5481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else 5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return n; 5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* INET6 */ 552