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> 72290001Sglebius#ifdef HAVE_SYS_SOCKET_H 73132451Sroberto#include <sys/socket.h> 74290001Sglebius#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" 84290001Sglebius#include "ntp_debug.h" 85132451Sroberto 86290001Sglebius 87290001Sglebius/* 88290001Sglebius * copy_addrinfo() - copy a single addrinfo to malloc()'d block. 89290001Sglebius * copy_addrinfo_list() - copy an addrinfo list to malloc()'d block. 90290001Sglebius * 91290001Sglebius * Copies an addrinfo list and its associated data to a contiguous block 92290001Sglebius * of storage from emalloc(). Callback routines invoked via 93290001Sglebius * getaddrinfo_sometime() have access to the resulting addrinfo list 94290001Sglebius * only until they return. This routine provides an easy way to make a 95290001Sglebius * persistent copy. Although the list provided to gai_sometime_callback 96290001Sglebius * routines is similarly contiguous, to keep this code usable in any 97290001Sglebius * context where we might want to duplicate an addrinfo list, it does 98290001Sglebius * not require the input list be contiguous. 99290001Sglebius * 100290001Sglebius * The returned list head pointer is passed to free() to release the 101290001Sglebius * entire list. 102290001Sglebius * 103290001Sglebius * In keeping with the rest of the NTP distribution, sockaddr_u is used 104290001Sglebius * in preference to struct sockaddr_storage, which is a member of the 105290001Sglebius * former union and so compatible. 106290001Sglebius * 107290001Sglebius * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6 108290001Sglebius * not being defined, copy_addrinfo_*() are exceptions. 109290001Sglebius */ 110290001Sglebiusstruct addrinfo * copy_addrinfo_common(const struct addrinfo *, int 111290001Sglebius#ifdef EREALLOC_CALLSITE 112290001Sglebius , 113290001Sglebius const char *, int 114290001Sglebius#endif 115290001Sglebius ); 116290001Sglebius 117290001Sglebius 118290001Sglebiusstruct addrinfo * 119290001Sglebiuscopy_addrinfo_impl( 120290001Sglebius const struct addrinfo * src 121290001Sglebius#ifdef EREALLOC_CALLSITE 122290001Sglebius , 123290001Sglebius const char * caller_file, 124290001Sglebius int caller_line 125290001Sglebius#endif 126290001Sglebius ) 127290001Sglebius{ 128290001Sglebius return copy_addrinfo_common(src, TRUE 129290001Sglebius#ifdef EREALLOC_CALLSITE 130290001Sglebius , 131290001Sglebius caller_file, caller_line 132290001Sglebius#endif 133290001Sglebius ); 134290001Sglebius} 135290001Sglebius 136290001Sglebius 137290001Sglebiusstruct addrinfo * 138290001Sglebiuscopy_addrinfo_list_impl( 139290001Sglebius const struct addrinfo * src 140290001Sglebius#ifdef EREALLOC_CALLSITE 141290001Sglebius , 142290001Sglebius const char * caller_file, 143290001Sglebius int caller_line 144290001Sglebius#endif 145290001Sglebius ) 146290001Sglebius{ 147290001Sglebius return copy_addrinfo_common(src, FALSE 148290001Sglebius#ifdef EREALLOC_CALLSITE 149290001Sglebius , 150290001Sglebius caller_file, caller_line 151290001Sglebius#endif 152290001Sglebius ); 153290001Sglebius} 154290001Sglebius 155290001Sglebius 156290001Sglebiusstruct addrinfo * 157290001Sglebiuscopy_addrinfo_common( 158290001Sglebius const struct addrinfo * src, 159290001Sglebius int just_one 160290001Sglebius#ifdef EREALLOC_CALLSITE 161290001Sglebius , 162290001Sglebius const char * caller_file, 163290001Sglebius int caller_line 164290001Sglebius#endif 165290001Sglebius ) 166290001Sglebius{ 167290001Sglebius const struct addrinfo * ai_src; 168290001Sglebius const struct addrinfo * ai_nxt; 169290001Sglebius struct addrinfo * ai_cpy; 170290001Sglebius struct addrinfo * dst; 171290001Sglebius sockaddr_u * psau; 172290001Sglebius char * pcanon; 173290001Sglebius u_int elements; 174290001Sglebius size_t octets; 175290001Sglebius size_t canons_octets; 176290001Sglebius size_t str_octets; 177290001Sglebius 178290001Sglebius elements = 0; 179290001Sglebius canons_octets = 0; 180290001Sglebius 181290001Sglebius for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) { 182290001Sglebius if (just_one) 183290001Sglebius ai_nxt = NULL; 184290001Sglebius else 185290001Sglebius ai_nxt = ai_src->ai_next; 186290001Sglebius ++elements; 187290001Sglebius if (NULL != ai_src->ai_canonname) 188290001Sglebius canons_octets += 1 + strlen(ai_src->ai_canonname); 189290001Sglebius } 190290001Sglebius 191290001Sglebius octets = elements * (sizeof(*ai_cpy) + sizeof(*psau)); 192290001Sglebius octets += canons_octets; 193290001Sglebius 194290001Sglebius dst = erealloczsite(NULL, octets, 0, TRUE, caller_file, 195290001Sglebius caller_line); 196290001Sglebius ai_cpy = dst; 197290001Sglebius psau = (void *)(ai_cpy + elements); 198290001Sglebius pcanon = (void *)(psau + elements); 199290001Sglebius 200290001Sglebius for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) { 201290001Sglebius if (just_one) 202290001Sglebius ai_nxt = NULL; 203290001Sglebius else 204290001Sglebius ai_nxt = ai_src->ai_next; 205290001Sglebius *ai_cpy = *ai_src; 206293896Sglebius DEBUG_INSIST(ai_cpy->ai_canonname == ai_src->ai_canonname); 207293896Sglebius INSIST(ai_src->ai_addrlen <= sizeof(sockaddr_u)); 208290001Sglebius memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen); 209290001Sglebius ai_cpy->ai_addr = &psau->sa; 210290001Sglebius ++psau; 211293896Sglebius if (NULL != ai_src->ai_canonname) { 212290001Sglebius ai_cpy->ai_canonname = pcanon; 213290001Sglebius str_octets = 1 + strlen(ai_src->ai_canonname); 214290001Sglebius memcpy(pcanon, ai_src->ai_canonname, str_octets); 215290001Sglebius pcanon += str_octets; 216290001Sglebius } 217290001Sglebius if (NULL != ai_cpy->ai_next) { 218290001Sglebius if (just_one) 219290001Sglebius ai_cpy->ai_next = NULL; 220290001Sglebius else 221290001Sglebius ai_cpy->ai_next = ai_cpy + 1; 222290001Sglebius } 223290001Sglebius ++ai_cpy; 224290001Sglebius } 225290001Sglebius ENSURE(pcanon == ((char *)dst + octets)); 226290001Sglebius 227290001Sglebius return dst; 228290001Sglebius} 229290001Sglebius 230290001Sglebius 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 277290001Sglebiusstatic int do_nodename (const char *nodename, struct addrinfo *ai, 278290001Sglebius 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 } 450290001Sglebius if (host != NULL && hostlen > 0) 451290001Sglebius 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 { 486293896Sglebius 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 { 493293896Sglebius 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 } 504290001Sglebius#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; 570290001Sglebius#ifdef ISC_PLATFORM_HAVESALEN 571132451Sroberto ai->ai_addr->sa_len = sizeof(struct sockaddr); 572132451Sroberto#endif 573290001Sglebius if (hints != NULL && (hints->ai_flags & AI_CANONNAME)) 574290001Sglebius ai->ai_canonname = estrdup(hp->h_name); 575132451Sroberto return (0); 576132451Sroberto} 577132451Sroberto 578182007Sroberto#endif /* !ISC_PLATFORM_HAVEIPV6 */ 579