1132451Sroberto/* 2132451Sroberto * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3132451Sroberto * All rights reserved. 4132451Sroberto * 5132451Sroberto * Redistribution and use in source and binary forms, with or without 6132451Sroberto * modification, are permitted provided that the following conditions 7132451Sroberto * are met: 8132451Sroberto * 1. Redistributions of source code must retain the above copyright 9132451Sroberto * notice, this list of conditions and the following disclaimer. 10132451Sroberto * 2. Redistributions in binary form must reproduce the above copyright 11132451Sroberto * notice, this list of conditions and the following disclaimer in the 12132451Sroberto * documentation and/or other materials provided with the distribution. 13132451Sroberto * 3. Neither the name of the project nor the names of its contributors 14132451Sroberto * may be used to endorse or promote products derived from this software 15132451Sroberto * without specific prior written permission. 16132451Sroberto * 17132451Sroberto * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18132451Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19132451Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20132451Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21132451Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22132451Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23132451Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24132451Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25132451Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26132451Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27132451Sroberto * SUCH DAMAGE. 28132451Sroberto */ 29132451Sroberto 30132451Sroberto/* 31132451Sroberto * Copyright (c) 1982, 1986, 1990, 1993 32132451Sroberto * The Regents of the University of California. All rights reserved. 33132451Sroberto * 34132451Sroberto * Redistribution and use in source and binary forms, with or without 35132451Sroberto * modification, are permitted provided that the following conditions 36132451Sroberto * are met: 37132451Sroberto * 1. Redistributions of source code must retain the above copyright 38132451Sroberto * notice, this list of conditions and the following disclaimer. 39132451Sroberto * 2. Redistributions in binary form must reproduce the above copyright 40132451Sroberto * notice, this list of conditions and the following disclaimer in the 41132451Sroberto * documentation and/or other materials provided with the distribution. 42132451Sroberto * 3. All advertising materials mentioning features or use of this software 43132451Sroberto * must display the following acknowledgement: 44132451Sroberto * This product includes software developed by the University of 45132451Sroberto * California, Berkeley and its contributors. 46132451Sroberto * 4. Neither the name of the University nor the names of its contributors 47132451Sroberto * may be used to endorse or promote products derived from this software 48132451Sroberto * without specific prior written permission. 49132451Sroberto * 50132451Sroberto * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 51132451Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52132451Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53132451Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 54132451Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55132451Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56132451Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57132451Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58132451Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59132451Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60132451Sroberto * SUCH DAMAGE. 61132451Sroberto * 62132451Sroberto */ 63132451Sroberto 64132451Sroberto/* 65132451Sroberto * Compatability shims with the rfc2553 API to simplify ntp. 66132451Sroberto */ 67132451Sroberto 68132451Sroberto#include <config.h> 69132451Sroberto 70132451Sroberto#include <sys/types.h> 71132451Sroberto#include <ctype.h> 72280849Scy#ifdef HAVE_SYS_SOCKET_H 73132451Sroberto#include <sys/socket.h> 74280849Scy#endif 75182007Sroberto#include <isc/net.h> 76132451Sroberto#ifdef HAVE_NETINET_IN_H 77132451Sroberto#include <netinet/in.h> 78132451Sroberto#endif 79182007Sroberto#include "ntp_rfc2553.h" 80132451Sroberto 81132451Sroberto#include "ntpd.h" 82132451Sroberto#include "ntp_malloc.h" 83132451Sroberto#include "ntp_string.h" 84280849Scy#include "ntp_debug.h" 85132451Sroberto 86280849Scy 87280849Scy/* 88280849Scy * copy_addrinfo() - copy a single addrinfo to malloc()'d block. 89280849Scy * copy_addrinfo_list() - copy an addrinfo list to malloc()'d block. 90280849Scy * 91280849Scy * Copies an addrinfo list and its associated data to a contiguous block 92280849Scy * of storage from emalloc(). Callback routines invoked via 93280849Scy * getaddrinfo_sometime() have access to the resulting addrinfo list 94280849Scy * only until they return. This routine provides an easy way to make a 95280849Scy * persistent copy. Although the list provided to gai_sometime_callback 96280849Scy * routines is similarly contiguous, to keep this code usable in any 97280849Scy * context where we might want to duplicate an addrinfo list, it does 98280849Scy * not require the input list be contiguous. 99280849Scy * 100280849Scy * The returned list head pointer is passed to free() to release the 101280849Scy * entire list. 102280849Scy * 103280849Scy * In keeping with the rest of the NTP distribution, sockaddr_u is used 104280849Scy * in preference to struct sockaddr_storage, which is a member of the 105280849Scy * former union and so compatible. 106280849Scy * 107280849Scy * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6 108280849Scy * not being defined, copy_addrinfo_*() are exceptions. 109280849Scy */ 110280849Scystruct addrinfo * copy_addrinfo_common(const struct addrinfo *, int 111280849Scy#ifdef EREALLOC_CALLSITE 112280849Scy , 113280849Scy const char *, int 114280849Scy#endif 115280849Scy ); 116280849Scy 117280849Scy 118280849Scystruct addrinfo * 119280849Scycopy_addrinfo_impl( 120280849Scy const struct addrinfo * src 121280849Scy#ifdef EREALLOC_CALLSITE 122280849Scy , 123280849Scy const char * caller_file, 124280849Scy int caller_line 125280849Scy#endif 126280849Scy ) 127280849Scy{ 128280849Scy return copy_addrinfo_common(src, TRUE 129280849Scy#ifdef EREALLOC_CALLSITE 130280849Scy , 131280849Scy caller_file, caller_line 132280849Scy#endif 133280849Scy ); 134280849Scy} 135280849Scy 136280849Scy 137280849Scystruct addrinfo * 138280849Scycopy_addrinfo_list_impl( 139280849Scy const struct addrinfo * src 140280849Scy#ifdef EREALLOC_CALLSITE 141280849Scy , 142280849Scy const char * caller_file, 143280849Scy int caller_line 144280849Scy#endif 145280849Scy ) 146280849Scy{ 147280849Scy return copy_addrinfo_common(src, FALSE 148280849Scy#ifdef EREALLOC_CALLSITE 149280849Scy , 150280849Scy caller_file, caller_line 151280849Scy#endif 152280849Scy ); 153280849Scy} 154280849Scy 155280849Scy 156280849Scystruct addrinfo * 157280849Scycopy_addrinfo_common( 158280849Scy const struct addrinfo * src, 159280849Scy int just_one 160280849Scy#ifdef EREALLOC_CALLSITE 161280849Scy , 162280849Scy const char * caller_file, 163280849Scy int caller_line 164280849Scy#endif 165280849Scy ) 166280849Scy{ 167280849Scy const struct addrinfo * ai_src; 168280849Scy const struct addrinfo * ai_nxt; 169280849Scy struct addrinfo * ai_cpy; 170280849Scy struct addrinfo * dst; 171280849Scy sockaddr_u * psau; 172280849Scy char * pcanon; 173280849Scy u_int elements; 174280849Scy size_t octets; 175280849Scy size_t canons_octets; 176280849Scy size_t str_octets; 177280849Scy 178280849Scy elements = 0; 179280849Scy canons_octets = 0; 180280849Scy 181280849Scy for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) { 182280849Scy if (just_one) 183280849Scy ai_nxt = NULL; 184280849Scy else 185280849Scy ai_nxt = ai_src->ai_next; 186280849Scy ++elements; 187280849Scy if (NULL != ai_src->ai_canonname) 188280849Scy canons_octets += 1 + strlen(ai_src->ai_canonname); 189280849Scy } 190280849Scy 191280849Scy octets = elements * (sizeof(*ai_cpy) + sizeof(*psau)); 192280849Scy octets += canons_octets; 193280849Scy 194280849Scy dst = erealloczsite(NULL, octets, 0, TRUE, caller_file, 195280849Scy caller_line); 196280849Scy ai_cpy = dst; 197280849Scy psau = (void *)(ai_cpy + elements); 198280849Scy pcanon = (void *)(psau + elements); 199280849Scy 200280849Scy for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) { 201280849Scy if (just_one) 202280849Scy ai_nxt = NULL; 203280849Scy else 204280849Scy ai_nxt = ai_src->ai_next; 205280849Scy *ai_cpy = *ai_src; 206293423Sdelphij DEBUG_INSIST(ai_cpy->ai_canonname == ai_src->ai_canonname); 207293423Sdelphij INSIST(ai_src->ai_addrlen <= sizeof(sockaddr_u)); 208280849Scy memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen); 209280849Scy ai_cpy->ai_addr = &psau->sa; 210280849Scy ++psau; 211293423Sdelphij if (NULL != ai_src->ai_canonname) { 212280849Scy ai_cpy->ai_canonname = pcanon; 213280849Scy str_octets = 1 + strlen(ai_src->ai_canonname); 214280849Scy memcpy(pcanon, ai_src->ai_canonname, str_octets); 215280849Scy pcanon += str_octets; 216280849Scy } 217280849Scy if (NULL != ai_cpy->ai_next) { 218280849Scy if (just_one) 219280849Scy ai_cpy->ai_next = NULL; 220280849Scy else 221280849Scy ai_cpy->ai_next = ai_cpy + 1; 222280849Scy } 223280849Scy ++ai_cpy; 224280849Scy } 225289764Sglebius ENSURE(pcanon == ((char *)dst + octets)); 226280849Scy 227280849Scy return dst; 228280849Scy} 229280849Scy 230280849Scy 231182007Sroberto#ifndef ISC_PLATFORM_HAVEIPV6 232132451Sroberto 233132451Srobertostatic char *ai_errlist[] = { 234132451Sroberto "Success", 235132451Sroberto "Address family for hostname not supported", /* EAI_ADDRFAMILY */ 236132451Sroberto "Temporary failure in name resolution", /* EAI_AGAIN */ 237132451Sroberto "Invalid value for ai_flags", /* EAI_BADFLAGS */ 238132451Sroberto "Non-recoverable failure in name resolution", /* EAI_FAIL */ 239132451Sroberto "ai_family not supported", /* EAI_FAMILY */ 240132451Sroberto "Memory allocation failure", /* EAI_MEMORY */ 241132451Sroberto "No address associated with hostname", /* EAI_NODATA */ 242132451Sroberto "hostname nor servname provided, or not known", /* EAI_NONAME */ 243132451Sroberto "servname not supported for ai_socktype", /* EAI_SERVICE */ 244132451Sroberto "ai_socktype not supported", /* EAI_SOCKTYPE */ 245132451Sroberto "System error returned in errno", /* EAI_SYSTEM */ 246132451Sroberto "Invalid value for hints", /* EAI_BADHINTS */ 247132451Sroberto "Resolved protocol is unknown", /* EAI_PROTOCOL */ 248132451Sroberto "Unknown error", /* EAI_MAX */ 249132451Sroberto}; 250132451Sroberto 251182007Sroberto/* 252182007Sroberto * Local declaration 253182007Sroberto */ 254182007Srobertoint 255182007SrobertoDNSlookup_name( 256182007Sroberto const char *name, 257182007Sroberto int ai_family, 258182007Sroberto struct hostent **Addresses 259182007Sroberto); 260182007Sroberto 261182007Sroberto#ifndef SYS_WINNT 262182007Sroberto/* 263182007Sroberto * Encapsulate gethostbyname to control the error code 264182007Sroberto */ 265182007Srobertoint 266182007SrobertoDNSlookup_name( 267182007Sroberto const char *name, 268182007Sroberto int ai_family, 269182007Sroberto struct hostent **Addresses 270182007Sroberto) 271182007Sroberto{ 272182007Sroberto *Addresses = gethostbyname(name); 273182007Sroberto return (h_errno); 274182007Sroberto} 275182007Sroberto#endif 276182007Sroberto 277280849Scystatic int do_nodename (const char *nodename, struct addrinfo *ai, 278280849Scy const struct addrinfo *hints); 279132451Sroberto 280132451Srobertoint 281132451Srobertogetaddrinfo (const char *nodename, const char *servname, 282132451Sroberto const struct addrinfo *hints, struct addrinfo **res) 283132451Sroberto{ 284132451Sroberto int rval; 285182007Sroberto struct servent *sp; 286182007Sroberto struct addrinfo *ai = NULL; 287182007Sroberto int port; 288182007Sroberto const char *proto = NULL; 289182007Sroberto int family, socktype, flags, protocol; 290132451Sroberto 291182007Sroberto 292182007Sroberto /* 293182007Sroberto * If no name is provide just return an error 294182007Sroberto */ 295182007Sroberto if (nodename == NULL && servname == NULL) 296182007Sroberto return (EAI_NONAME); 297182007Sroberto 298132451Sroberto ai = calloc(sizeof(struct addrinfo), 1); 299132451Sroberto if (ai == NULL) 300132451Sroberto return (EAI_MEMORY); 301132451Sroberto 302182007Sroberto /* 303182007Sroberto * Copy default values from hints, if available 304182007Sroberto */ 305182007Sroberto if (hints != NULL) { 306182007Sroberto ai->ai_flags = hints->ai_flags; 307182007Sroberto ai->ai_family = hints->ai_family; 308182007Sroberto ai->ai_socktype = hints->ai_socktype; 309182007Sroberto ai->ai_protocol = hints->ai_protocol; 310182007Sroberto 311182007Sroberto family = hints->ai_family; 312182007Sroberto socktype = hints->ai_socktype; 313182007Sroberto protocol = hints->ai_protocol; 314182007Sroberto flags = hints->ai_flags; 315182007Sroberto 316182007Sroberto switch (family) { 317182007Sroberto case AF_UNSPEC: 318182007Sroberto switch (hints->ai_socktype) { 319182007Sroberto case SOCK_STREAM: 320182007Sroberto proto = "tcp"; 321182007Sroberto break; 322182007Sroberto case SOCK_DGRAM: 323182007Sroberto proto = "udp"; 324182007Sroberto break; 325182007Sroberto } 326182007Sroberto break; 327182007Sroberto case AF_INET: 328182007Sroberto case AF_INET6: 329182007Sroberto switch (hints->ai_socktype) { 330182007Sroberto case 0: 331182007Sroberto break; 332182007Sroberto case SOCK_STREAM: 333182007Sroberto proto = "tcp"; 334182007Sroberto break; 335182007Sroberto case SOCK_DGRAM: 336182007Sroberto proto = "udp"; 337182007Sroberto break; 338182007Sroberto case SOCK_RAW: 339182007Sroberto break; 340182007Sroberto default: 341182007Sroberto return (EAI_SOCKTYPE); 342182007Sroberto } 343182007Sroberto break; 344182007Sroberto#ifdef AF_LOCAL 345182007Sroberto case AF_LOCAL: 346182007Sroberto switch (hints->ai_socktype) { 347182007Sroberto case 0: 348182007Sroberto break; 349182007Sroberto case SOCK_STREAM: 350182007Sroberto break; 351182007Sroberto case SOCK_DGRAM: 352182007Sroberto break; 353182007Sroberto default: 354182007Sroberto return (EAI_SOCKTYPE); 355182007Sroberto } 356182007Sroberto break; 357182007Sroberto#endif 358182007Sroberto default: 359182007Sroberto return (EAI_FAMILY); 360132451Sroberto } 361182007Sroberto } else { 362182007Sroberto protocol = 0; 363182007Sroberto family = 0; 364182007Sroberto socktype = 0; 365182007Sroberto flags = 0; 366132451Sroberto } 367182007Sroberto 368182007Sroberto rval = do_nodename(nodename, ai, hints); 369182007Sroberto if (rval != 0) { 370182007Sroberto freeaddrinfo(ai); 371182007Sroberto return (rval); 372132451Sroberto } 373182007Sroberto 374182007Sroberto /* 375182007Sroberto * First, look up the service name (port) if it was 376182007Sroberto * requested. If the socket type wasn't specified, then 377182007Sroberto * try and figure it out. 378182007Sroberto */ 379132451Sroberto if (servname != NULL) { 380182007Sroberto char *e; 381182007Sroberto 382182007Sroberto port = strtol(servname, &e, 10); 383182007Sroberto if (*e == '\0') { 384182007Sroberto if (socktype == 0) 385182007Sroberto return (EAI_SOCKTYPE); 386182007Sroberto if (port < 0 || port > 65535) 387182007Sroberto return (EAI_SERVICE); 388182007Sroberto port = htons((unsigned short) port); 389182007Sroberto } else { 390182007Sroberto sp = getservbyname(servname, proto); 391182007Sroberto if (sp == NULL) 392182007Sroberto return (EAI_SERVICE); 393182007Sroberto port = sp->s_port; 394182007Sroberto if (socktype == 0) { 395182007Sroberto if (strcmp(sp->s_proto, "tcp") == 0) 396182007Sroberto socktype = SOCK_STREAM; 397182007Sroberto else if (strcmp(sp->s_proto, "udp") == 0) 398182007Sroberto socktype = SOCK_DGRAM; 399182007Sroberto } 400132451Sroberto } 401182007Sroberto } else 402182007Sroberto port = 0; 403182007Sroberto 404182007Sroberto /* 405182007Sroberto * 406182007Sroberto * Set up the port number 407182007Sroberto */ 408182007Sroberto if (ai->ai_family == AF_INET) 409182007Sroberto ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port; 410182007Sroberto else if (ai->ai_family == AF_INET6) 411182007Sroberto ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port; 412132451Sroberto *res = ai; 413132451Sroberto return (0); 414132451Sroberto} 415132451Sroberto 416132451Srobertovoid 417132451Srobertofreeaddrinfo(struct addrinfo *ai) 418132451Sroberto{ 419132451Sroberto if (ai->ai_canonname != NULL) 420182007Sroberto { 421132451Sroberto free(ai->ai_canonname); 422182007Sroberto ai->ai_canonname = NULL; 423182007Sroberto } 424132451Sroberto if (ai->ai_addr != NULL) 425182007Sroberto { 426132451Sroberto free(ai->ai_addr); 427182007Sroberto ai->ai_addr = NULL; 428182007Sroberto } 429132451Sroberto free(ai); 430182007Sroberto ai = NULL; 431132451Sroberto} 432132451Sroberto 433132451Srobertoint 434132451Srobertogetnameinfo (const struct sockaddr *sa, u_int salen, char *host, 435132451Sroberto size_t hostlen, char *serv, size_t servlen, int flags) 436132451Sroberto{ 437132451Sroberto struct hostent *hp; 438132451Sroberto 439132451Sroberto if (sa->sa_family != AF_INET) 440132451Sroberto return (EAI_FAMILY); 441132451Sroberto hp = gethostbyaddr( 442132451Sroberto (const char *)&((const struct sockaddr_in *)sa)->sin_addr, 443132451Sroberto 4, AF_INET); 444132451Sroberto if (hp == NULL) { 445132451Sroberto if (h_errno == TRY_AGAIN) 446132451Sroberto return (EAI_AGAIN); 447132451Sroberto else 448132451Sroberto return (EAI_FAIL); 449132451Sroberto } 450280849Scy if (host != NULL && hostlen > 0) 451280849Scy strlcpy(host, hp->h_name, hostlen); 452132451Sroberto return (0); 453132451Sroberto} 454132451Sroberto 455132451Srobertochar * 456132451Srobertogai_strerror(int ecode) 457132451Sroberto{ 458132451Sroberto if (ecode < 0 || ecode > EAI_MAX) 459132451Sroberto ecode = EAI_MAX; 460132451Sroberto return ai_errlist[ecode]; 461132451Sroberto} 462132451Sroberto 463132451Srobertostatic int 464132451Srobertodo_nodename( 465132451Sroberto const char *nodename, 466132451Sroberto struct addrinfo *ai, 467132451Sroberto const struct addrinfo *hints) 468132451Sroberto{ 469182007Sroberto struct hostent *hp = NULL; 470132451Sroberto struct sockaddr_in *sockin; 471182007Sroberto struct sockaddr_in6 *sockin6; 472182007Sroberto int errval; 473132451Sroberto 474132451Sroberto ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1); 475132451Sroberto if (ai->ai_addr == NULL) 476132451Sroberto return (EAI_MEMORY); 477132451Sroberto 478182007Sroberto /* 479182007Sroberto * For an empty node name just use the wildcard. 480182007Sroberto * NOTE: We need to assume that the address family is 481182007Sroberto * set elsewhere so that we can set the appropriate wildcard 482182007Sroberto */ 483182007Sroberto if (nodename == NULL) { 484182007Sroberto if (ai->ai_family == AF_INET) 485182007Sroberto { 486293423Sdelphij ai->ai_addrlen = sizeof(struct sockaddr_in); 487182007Sroberto sockin = (struct sockaddr_in *)ai->ai_addr; 488182007Sroberto sockin->sin_family = (short) ai->ai_family; 489182007Sroberto sockin->sin_addr.s_addr = htonl(INADDR_ANY); 490182007Sroberto } 491182007Sroberto else 492182007Sroberto { 493293423Sdelphij ai->ai_addrlen = sizeof(struct sockaddr_in6); 494182007Sroberto sockin6 = (struct sockaddr_in6 *)ai->ai_addr; 495182007Sroberto sockin6->sin6_family = (short) ai->ai_family; 496182007Sroberto /* 497182007Sroberto * we have already zeroed out the address 498182007Sroberto * so we don't actually need to do this 499182007Sroberto * This assignment is causing problems so 500182007Sroberto * we don't do what this would do. 501182007Sroberto sockin6->sin6_addr = in6addr_any; 502182007Sroberto */ 503182007Sroberto } 504280849Scy#ifdef ISC_PLATFORM_HAVESALEN 505182007Sroberto ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr); 506182007Sroberto#endif 507182007Sroberto 508182007Sroberto return (0); 509182007Sroberto } 510182007Sroberto 511182007Sroberto /* 512182007Sroberto * See if we have an IPv6 address 513182007Sroberto */ 514182007Sroberto if(strchr(nodename, ':') != NULL) { 515182007Sroberto if (inet_pton(AF_INET6, nodename, 516182007Sroberto &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) { 517182007Sroberto ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6; 518182007Sroberto ai->ai_family = AF_INET6; 519182007Sroberto ai->ai_addrlen = sizeof(struct sockaddr_in6); 520132451Sroberto return (0); 521132451Sroberto } 522182007Sroberto } 523182007Sroberto 524182007Sroberto /* 525182007Sroberto * See if we have an IPv4 address 526182007Sroberto */ 527182007Sroberto if (inet_pton(AF_INET, nodename, 528182007Sroberto &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) { 529182007Sroberto ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET; 530182007Sroberto ai->ai_family = AF_INET; 531182007Sroberto ai->ai_addrlen = sizeof(struct sockaddr_in); 532182007Sroberto return (0); 533182007Sroberto } 534182007Sroberto 535182007Sroberto /* 536182007Sroberto * If the numeric host flag is set, don't attempt resolution 537182007Sroberto */ 538182007Sroberto if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST)) 539132451Sroberto return (EAI_NONAME); 540182007Sroberto 541182007Sroberto /* 542182007Sroberto * Look for a name 543182007Sroberto */ 544182007Sroberto 545182007Sroberto errval = DNSlookup_name(nodename, AF_INET, &hp); 546182007Sroberto 547132451Sroberto if (hp == NULL) { 548182007Sroberto if (errval == TRY_AGAIN || errval == EAI_AGAIN) 549132451Sroberto return (EAI_AGAIN); 550182007Sroberto else if (errval == EAI_NONAME) { 551182007Sroberto if (inet_pton(AF_INET, nodename, 552182007Sroberto &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) { 553182007Sroberto ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET; 554132451Sroberto ai->ai_family = AF_INET; 555132451Sroberto ai->ai_addrlen = sizeof(struct sockaddr_in); 556132451Sroberto return (0); 557132451Sroberto } 558182007Sroberto return (errval); 559132451Sroberto } 560182007Sroberto else 561182007Sroberto { 562182007Sroberto return (errval); 563182007Sroberto } 564132451Sroberto } 565132451Sroberto ai->ai_family = hp->h_addrtype; 566132451Sroberto ai->ai_addrlen = sizeof(struct sockaddr); 567132451Sroberto sockin = (struct sockaddr_in *)ai->ai_addr; 568132451Sroberto memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length); 569132451Sroberto ai->ai_addr->sa_family = hp->h_addrtype; 570280849Scy#ifdef ISC_PLATFORM_HAVESALEN 571132451Sroberto ai->ai_addr->sa_len = sizeof(struct sockaddr); 572132451Sroberto#endif 573280849Scy if (hints != NULL && (hints->ai_flags & AI_CANONNAME)) 574280849Scy ai->ai_canonname = estrdup(hp->h_name); 575132451Sroberto return (0); 576132451Sroberto} 577132451Sroberto 578182007Sroberto#endif /* !ISC_PLATFORM_HAVEIPV6 */ 579