1968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 2968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Copyright 2005 by Dominick Meglio 3968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * 4968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Permission to use, copy, modify, and distribute this 5968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software and its documentation for any purpose and without 6968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * fee is hereby granted, provided that the above copyright 7968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice appear in all copies and that both that copyright 8968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice and this permission notice appear in supporting 9968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * documentation, and that the name of M.I.T. not be used in 10968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * advertising or publicity pertaining to distribution of the 11968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software without specific, written prior permission. 12968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * M.I.T. makes no representations about the suitability of 13968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * this software for any purpose. It is provided "as is" 14968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * without express or implied warranty. 15968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 16968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_setup.h" 17968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 18968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_GETSERVBYPORT_R 19968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# if !defined(GETSERVBYPORT_R_ARGS) || \ 20968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (GETSERVBYPORT_R_ARGS < 4) || (GETSERVBYPORT_R_ARGS > 6) 21968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# error "you MUST specifiy a valid number of arguments for getservbyport_r" 22968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# endif 23968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 24968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 25968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_SOCKET_H 26968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <sys/socket.h> 27968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 28968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETINET_IN_H 29968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <netinet/in.h> 30968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 31968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETDB_H 32968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <netdb.h> 33968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 34968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_INET_H 35968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/inet.h> 36968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 37968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_H 38968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/nameser.h> 39968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 40968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include "nameser.h" 41968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 42968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_COMPAT_H 43968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/nameser_compat.h> 44968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 45968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 46968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NET_IF_H 47968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <net/if.h> 48968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 49968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 50968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_UNISTD_H 51968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <unistd.h> 52968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 53968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 54968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <stdio.h> 55968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <stdlib.h> 56968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <string.h> 57968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 58968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares.h" 59968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_ipv6.h" 60968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "inet_ntop.h" 61968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_nowarn.h" 62968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_private.h" 63968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 64968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstruct nameinfo_query { 65968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_nameinfo_callback callback; 66968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold void *arg; 67968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold union { 68968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in addr4; 69968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in6 addr6; 70968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } addr; 71968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int family; 72968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int flags; 73968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int timeouts; 74968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold}; 75968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 76968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 77968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#define IPBUFSIZ \ 78968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + IF_NAMESIZE) 79968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 80968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#define IPBUFSIZ \ 81968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")) 82968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 83968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 84968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void nameinfo_callback(void *arg, int status, int timeouts, 85968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct hostent *host); 86968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic char *lookup_service(unsigned short port, int flags, 87968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *buf, size_t buflen); 88968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 89968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void append_scopeid(struct sockaddr_in6 *addr6, unsigned int scopeid, 90968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *buf, size_t buflen); 91968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 92968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic char *ares_striendstr(const char *s1, const char *s2); 93968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 94968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, 95968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socklen_t salen, 96968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int flags, ares_nameinfo_callback callback, void *arg) 97968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 98968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in *addr = NULL; 99968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in6 *addr6 = NULL; 100968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct nameinfo_query *niquery; 101968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold unsigned int port = 0; 102968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 103968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Validate socket address family and length */ 104968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((sa->sa_family == AF_INET) && 105968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (salen == sizeof(struct sockaddr_in))) 106968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 107968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold addr = (struct sockaddr_in *)sa; 108968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold port = addr->sin_port; 109968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 110968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else if ((sa->sa_family == AF_INET6) && 111968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (salen == sizeof(struct sockaddr_in6))) 112968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 113968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold addr6 = (struct sockaddr_in6 *)sa; 114968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold port = addr6->sin6_port; 115968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 116968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 117968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 118968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold callback(arg, ARES_ENOTIMP, 0, NULL, NULL); 119968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 120968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 121968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 122968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If neither, assume they want a host */ 123968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!(flags & ARES_NI_LOOKUPSERVICE) && !(flags & ARES_NI_LOOKUPHOST)) 124968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold flags |= ARES_NI_LOOKUPHOST; 125968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 126968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* All they want is a service, no need for DNS */ 127968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((flags & ARES_NI_LOOKUPSERVICE) && !(flags & ARES_NI_LOOKUPHOST)) 128968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 129968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char buf[33], *service; 130968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 131968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold service = lookup_service((unsigned short)(port & 0xffff), 132968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold flags, buf, sizeof(buf)); 133968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold callback(arg, ARES_SUCCESS, 0, NULL, service); 134968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 135968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 136968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 137968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* They want a host lookup */ 138968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((flags & ARES_NI_LOOKUPHOST)) 139968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 140968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* A numeric host can be handled without DNS */ 141968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((flags & ARES_NI_NUMERICHOST)) 142968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 143968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char ipbuf[IPBUFSIZ]; 144968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char srvbuf[33]; 145968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *service = NULL; 146968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ipbuf[0] = 0; 147968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 148968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Specifying not to lookup a host, but then saying a host 149968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * is required has to be illegal. 150968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 151968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (flags & ARES_NI_NAMEREQD) 152968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 153968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold callback(arg, ARES_EBADFLAGS, 0, NULL, NULL); 154968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 155968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 156968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (salen == sizeof(struct sockaddr_in6)) 157968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 158968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_inet_ntop(AF_INET6, &addr6->sin6_addr, ipbuf, IPBUFSIZ); 159968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If the system supports scope IDs, use it */ 160968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 161968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold append_scopeid(addr6, flags, ipbuf, sizeof(ipbuf)); 162968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 163968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 164968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 165968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 166968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_inet_ntop(AF_INET, &addr->sin_addr, ipbuf, IPBUFSIZ); 167968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 168968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* They also want a service */ 169968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (flags & ARES_NI_LOOKUPSERVICE) 170968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold service = lookup_service((unsigned short)(port & 0xffff), 171968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold flags, srvbuf, sizeof(srvbuf)); 172968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold callback(arg, ARES_SUCCESS, 0, ipbuf, service); 173968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 174968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 175968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* This is where a DNS lookup becomes necessary */ 176968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 177968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 178968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery = malloc(sizeof(struct nameinfo_query)); 179968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!niquery) 180968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 181968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold callback(arg, ARES_ENOMEM, 0, NULL, NULL); 182968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 183968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 184968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->callback = callback; 185968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->arg = arg; 186968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->flags = flags; 187968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->timeouts = 0; 188968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (sa->sa_family == AF_INET) 189968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 190968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->family = AF_INET; 191968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memcpy(&niquery->addr.addr4, addr, sizeof(struct in_addr)); 192968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_gethostbyaddr(channel, &addr->sin_addr, 193968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(struct in_addr), AF_INET, 194968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold nameinfo_callback, niquery); 195968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 196968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 197968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 198968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->family = AF_INET6; 199968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memcpy(&niquery->addr.addr6, addr6, sizeof(struct ares_in6_addr)); 200968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_gethostbyaddr(channel, &addr6->sin6_addr, 201968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(struct ares_in6_addr), AF_INET6, 202968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold nameinfo_callback, niquery); 203968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 204968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 205968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 206968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 207968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 208968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void nameinfo_callback(void *arg, int status, int timeouts, 209968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct hostent *host) 210968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 211968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct nameinfo_query *niquery = (struct nameinfo_query *) arg; 212968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char srvbuf[33]; 213968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *service = NULL; 214968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 215968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->timeouts += timeouts; 216968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (status == ARES_SUCCESS) 217968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 218968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* They want a service too */ 219968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (niquery->flags & ARES_NI_LOOKUPSERVICE) 220968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 221968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (niquery->family == AF_INET) 222968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold service = lookup_service(niquery->addr.addr4.sin_port, 223968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->flags, srvbuf, sizeof(srvbuf)); 224968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 225968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold service = lookup_service(niquery->addr.addr6.sin6_port, 226968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->flags, srvbuf, sizeof(srvbuf)); 227968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 228968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* NOFQDN means we have to strip off the domain name portion. We do 229968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold this by determining our own domain name, then searching the string 230968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for this domain name and removing it. 231968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 232968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_GETHOSTNAME 233968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (niquery->flags & ARES_NI_NOFQDN) 234968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 235968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char buf[255]; 236968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *domain; 237968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold gethostname(buf, 255); 238968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((domain = strchr(buf, '.')) != NULL) 239968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 240968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *end = ares_striendstr(host->h_name, domain); 241968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (end) 242968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold *end = 0; 243968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 244968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 245968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 246968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->callback(niquery->arg, ARES_SUCCESS, niquery->timeouts, 247968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (char *)(host->h_name), 248968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold service); 249968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(niquery); 250968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 251968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 252968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* We couldn't find the host, but it's OK, we can use the IP */ 253968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else if (status == ARES_ENOTFOUND && !(niquery->flags & ARES_NI_NAMEREQD)) 254968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 255968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char ipbuf[IPBUFSIZ]; 256968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (niquery->family == AF_INET) 257968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_inet_ntop(AF_INET, &niquery->addr.addr4.sin_addr, ipbuf, 258968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold IPBUFSIZ); 259968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 260968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 261968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_inet_ntop(AF_INET6, &niquery->addr.addr6.sin6_addr, ipbuf, 262968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold IPBUFSIZ); 263968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 264968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold append_scopeid(&niquery->addr.addr6, niquery->flags, ipbuf, 265968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(ipbuf)); 266968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 267968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 268968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* They want a service too */ 269968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (niquery->flags & ARES_NI_LOOKUPSERVICE) 270968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 271968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (niquery->family == AF_INET) 272968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold service = lookup_service(niquery->addr.addr4.sin_port, 273968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->flags, srvbuf, sizeof(srvbuf)); 274968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 275968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold service = lookup_service(niquery->addr.addr6.sin6_port, 276968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->flags, srvbuf, sizeof(srvbuf)); 277968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 278968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->callback(niquery->arg, ARES_SUCCESS, niquery->timeouts, ipbuf, 279968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold service); 280968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(niquery); 281968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 282968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 283968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold niquery->callback(niquery->arg, status, niquery->timeouts, NULL, NULL); 284968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(niquery); 285968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 286968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 287968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic char *lookup_service(unsigned short port, int flags, 288968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *buf, size_t buflen) 289968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 290968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold const char *proto; 291968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct servent *sep; 292968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_GETSERVBYPORT_R 293968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct servent se; 294968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 295968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char tmpbuf[4096]; 296968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 297968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (port) 298968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 299968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (flags & ARES_NI_NUMERICSERV) 300968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sep = NULL; 301968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 302968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 303968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (flags & ARES_NI_UDP) 304968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold proto = "udp"; 305968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else if (flags & ARES_NI_SCTP) 306968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold proto = "sctp"; 307968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else if (flags & ARES_NI_DCCP) 308968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold proto = "dccp"; 309968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 310968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold proto = "tcp"; 311968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_GETSERVBYPORT_R 312968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sep = &se; 313968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memset(tmpbuf, 0, sizeof(tmpbuf)); 314968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if GETSERVBYPORT_R_ARGS == 6 315968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (getservbyport_r(port, proto, &se, (void *)tmpbuf, 316968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(tmpbuf), &sep) != 0) 317968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sep = NULL; 318968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif GETSERVBYPORT_R_ARGS == 5 319968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sep = getservbyport_r(port, proto, &se, (void *)tmpbuf, 320968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(tmpbuf)); 321968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif GETSERVBYPORT_R_ARGS == 4 322968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (getservbyport_r(port, proto, &se, (void *)tmpbuf) != 0) 323968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sep = NULL; 324968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 325968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Lets just hope the OS uses TLS! */ 326968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sep = getservbyport(port, proto); 327968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 328968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 329968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Lets just hope the OS uses TLS! */ 330968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) 331968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sep = getservbyport(port, (char*)proto); 332968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 333968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sep = getservbyport(port, proto); 334968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 335968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 336968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 337968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (sep && sep->s_name) 338968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* get service name */ 339968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold strcpy(tmpbuf, sep->s_name); 340968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 341968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* get port as a string */ 342968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sprintf(tmpbuf, "%u", (unsigned int)ntohs(port)); 343968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (strlen(tmpbuf) < buflen) 344968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* return it if buffer big enough */ 345968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold strcpy(buf, tmpbuf); 346968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 347968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* avoid reusing previous one */ 348968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold buf[0] = '\0'; 349968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return buf; 350968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 351968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold buf[0] = '\0'; 352968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return NULL; 353968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 354968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 355968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 356968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void append_scopeid(struct sockaddr_in6 *addr6, unsigned int flags, 357968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *buf, size_t buflen) 358968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 359968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_IF_INDEXTONAME 360968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int is_ll, is_mcll; 361968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 362968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold static const char fmt_u[] = "%u"; 363968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold static const char fmt_lu[] = "%lu"; 364968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char tmpbuf[IF_NAMESIZE + 2]; 365968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold size_t bufl; 366968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold const char *fmt = (sizeof(addr6->sin6_scope_id) > sizeof(unsigned int))? 367968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold fmt_lu:fmt_u; 368968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 369968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold tmpbuf[0] = '%'; 370968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 371968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_IF_INDEXTONAME 372968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold is_ll = IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr); 373968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold is_mcll = IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr); 374968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((flags & ARES_NI_NUMERICSCOPE) || 375968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (!is_ll && !is_mcll)) 376968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 377968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sprintf(&tmpbuf[1], fmt, addr6->sin6_scope_id); 378968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 379968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 380968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 381968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (if_indextoname(addr6->sin6_scope_id, &tmpbuf[1]) == NULL) 382968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sprintf(&tmpbuf[1], fmt, addr6->sin6_scope_id); 383968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 384968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 385968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sprintf(&tmpbuf[1], fmt, addr6->sin6_scope_id); 386968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (void) flags; 387968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 388968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold tmpbuf[IF_NAMESIZE + 1] = '\0'; 389968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold bufl = strlen(buf); 390968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 391968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(bufl + strlen(tmpbuf) < buflen) 392968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* only append the scopeid string if it fits in the target buffer */ 393968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold strcpy(&buf[bufl], tmpbuf); 394968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 395968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 396968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 397968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Determines if s1 ends with the string in s2 (case-insensitive) */ 398968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic char *ares_striendstr(const char *s1, const char *s2) 399968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 400968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold const char *c1, *c2, *c1_begin; 401968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int lo1, lo2; 402968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold size_t s1_len = strlen(s1), s2_len = strlen(s2); 403968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 404968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If the substr is longer than the full str, it can't match */ 405968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (s2_len > s1_len) 406968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return NULL; 407968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 408968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Jump to the end of s1 minus the length of s2 */ 409968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold c1_begin = s1+s1_len-s2_len; 410968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold c1 = (const char *)c1_begin; 411968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold c2 = s2; 412968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold while (c2 < s2+s2_len) 413968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 414968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold lo1 = TOLOWER(*c1); 415968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold lo2 = TOLOWER(*c2); 416968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (lo1 != lo2) 417968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return NULL; 418968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 419968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 420968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold c1++; 421968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold c2++; 422968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 423968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 424968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (c2 == c1 && c2 == NULL) 425968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return (char *)c1_begin; 426968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return NULL; 427968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 428