2 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001 Internet Software Consortium.
5 * This code is derived from software contributed to ISC by
6 * Berkeley Software Design, Inc.
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND BERKELEY SOFTWARE DESIGN, INC.
13 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
15 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
18 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 /* $Id: getaddrinfo.c,v 1.43.18.8 2007/09/13 23:46:26 tbox Exp $ */
26 * lwres_getaddrinfo() is used to get a list of IP addresses and port
27 * numbers for host hostname and service servname. The function is the
28 * lightweight resolver's implementation of getaddrinfo() as defined in
29 * RFC2133. hostname and servname are pointers to null-terminated strings
30 * or NULL. hostname is either a host name or a numeric host address
31 * string: a dotted decimal IPv4 address or an IPv6 address. servname is
32 * either a decimal port number or a service name as listed in
35 * If the operating system does not provide a struct addrinfo, the
36 * following structure is used:
40 * int ai_flags; // AI_PASSIVE, AI_CANONNAME
41 * int ai_family; // PF_xxx
42 * int ai_socktype; // SOCK_xxx
43 * int ai_protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6
44 * size_t ai_addrlen; // length of ai_addr
45 * char *ai_canonname; // canonical name for hostname
46 * struct sockaddr *ai_addr; // binary address
47 * struct addrinfo *ai_next; // next structure in linked list
52 * hints is an optional pointer to a struct addrinfo. This structure can
53 * be used to provide hints concerning the type of socket that the caller
54 * supports or wishes to use. The caller can supply the following
55 * structure elements in *hints:
59 * The protocol family that should be used. When ai_family is set
60 * to PF_UNSPEC, it means the caller will accept any protocol
61 * family supported by the operating system.</li>
64 * denotes the type of socket -- SOCK_STREAM, SOCK_DGRAM or
65 * SOCK_RAW -- that is wanted. When ai_socktype is zero the caller
66 * will accept any socket type.</li>
69 * indicates which transport protocol is wanted: IPPROTO_UDP or
70 * IPPROTO_TCP. If ai_protocol is zero the caller will accept any
74 * Flag bits. If the AI_CANONNAME bit is set, a successful call to
75 * lwres_getaddrinfo() will return a null-terminated string
76 * containing the canonical name of the specified hostname in
77 * ai_canonname of the first addrinfo structure returned. Setting
78 * the AI_PASSIVE bit indicates that the returned socket address
79 * structure is intended for used in a call to bind(2). In this
80 * case, if the hostname argument is a NULL pointer, then the IP
81 * address portion of the socket address structure will be set to
82 * INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6
83 * address.<br /><br />
85 * When ai_flags does not set the AI_PASSIVE bit, the returned
86 * socket address structure will be ready for use in a call to
87 * connect(2) for a connection-oriented protocol or connect(2),
88 * sendto(2), or sendmsg(2) if a connectionless protocol was
89 * chosen. The IP address portion of the socket address structure
90 * will be set to the loopback address if hostname is a NULL
91 * pointer and AI_PASSIVE is not set in ai_flags.<br /><br />
93 * If ai_flags is set to AI_NUMERICHOST it indicates that hostname
94 * should be treated as a numeric string defining an IPv4 or IPv6
95 * address and no name resolution should be attempted.
98 * All other elements of the struct addrinfo passed via hints must be
101 * A hints of NULL is treated as if the caller provided a struct addrinfo
102 * initialized to zero with ai_familyset to PF_UNSPEC.
104 * After a successful call to lwres_getaddrinfo(), *res is a pointer to a
105 * linked list of one or more addrinfo structures. Each struct addrinfo
106 * in this list cn be processed by following the ai_next pointer, until a
107 * NULL pointer is encountered. The three members ai_family, ai_socktype,
108 * and ai_protocol in each returned addrinfo structure contain the
109 * corresponding arguments for a call to socket(2). For each addrinfo
110 * structure in the list, the ai_addr member points to a filled-in socket
111 * address structure of length ai_addrlen.
113 * All of the information returned by lwres_getaddrinfo() is dynamically
114 * allocated: the addrinfo structures, and the socket address structures
115 * and canonical host name strings pointed to by the addrinfostructures.
116 * Memory allocated for the dynamically allocated structures created by a
117 * successful call to lwres_getaddrinfo() is released by
118 * lwres_freeaddrinfo(). ai is a pointer to a struct addrinfo created by
119 * a call to lwres_getaddrinfo().
121 * \section lwresreturn RETURN VALUES
123 * lwres_getaddrinfo() returns zero on success or one of the error codes
124 * listed in gai_strerror() if an error occurs. If both hostname and
125 * servname are NULL lwres_getaddrinfo() returns #EAI_NONAME.
127 * \section lwressee SEE ALSO
129 * lwres(3), lwres_getaddrinfo(), lwres_freeaddrinfo(),
130 * lwres_gai_strerror(), RFC2133, getservbyname(3), connect(2),
131 * sendto(2), sendmsg(2), socket(2).
138 #include <isc/string.h>
140 #include <lwres/lwres.h>
141 #include <lwres/net.h>
142 #include <lwres/netdb.h>
143 #include <lwres/stdlib.h>
145 #define SA(addr) ((struct sockaddr *)(addr))
146 #define SIN(addr) ((struct sockaddr_in *)(addr))
147 #define SIN6(addr) ((struct sockaddr_in6 *)(addr))
148 #define SUN(addr) ((struct sockaddr_un *)(addr))
152 static struct addrinfo
153 *ai_reverse(struct addrinfo *oai),
154 *ai_clone(struct addrinfo *oai, int family),
155 *ai_alloc(int family, int addrlen);
157 static int get_local(const char *name, int socktype, struct addrinfo **res);
160 static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip,
161 int socktype, int port);
162 static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip,
163 int socktype, int port);
164 static void set_order(int, int (**)(const char *, int, struct addrinfo **,
167 #define FOUND_IPV4 0x1
168 #define FOUND_IPV6 0x2
171 #define ISC_AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST)
172 /*% Get a list of IP addresses and port numbers for host hostname and service servname. */
174 lwres_getaddrinfo(const char *hostname, const char *servname,
175 const struct addrinfo *hints, struct addrinfo **res)
179 int family, socktype, flags, protocol;
180 struct addrinfo *ai, *ai_list;
182 int (*net_order[FOUND_MAX+1])(const char *, int, struct addrinfo **,
185 if (hostname == NULL && servname == NULL)
190 if ((hints->ai_flags & ~(ISC_AI_MASK)) != 0)
191 return (EAI_BADFLAGS);
192 if (hints->ai_addrlen || hints->ai_canonname ||
193 hints->ai_addr || hints->ai_next) {
197 family = hints->ai_family;
198 socktype = hints->ai_socktype;
199 protocol = hints->ai_protocol;
200 flags = hints->ai_flags;
203 switch (hints->ai_socktype) {
214 switch (hints->ai_socktype) {
226 return (EAI_SOCKTYPE);
231 switch (hints->ai_socktype) {
239 return (EAI_SOCKTYPE);
255 * First, deal with AF_LOCAL. If the family was not set,
256 * then assume AF_LOCAL if the first character of the
257 * hostname/servname is '/'.
260 if (hostname != NULL &&
261 (family == AF_LOCAL || (family == 0 && *hostname == '/')))
262 return (get_local(hostname, socktype, res));
264 if (servname != NULL &&
265 (family == AF_LOCAL || (family == 0 && *servname == '/')))
266 return (get_local(servname, socktype, res));
270 * Ok, only AF_INET and AF_INET6 left.
275 * First, look up the service name (port) if it was
276 * requested. If the socket type wasn't specified, then
277 * try and figure it out.
279 if (servname != NULL) {
282 port = strtol(servname, &e, 10);
285 return (EAI_SOCKTYPE);
286 if (port < 0 || port > 65535)
287 return (EAI_SERVICE);
288 port = htons((unsigned short) port);
290 sp = getservbyname(servname, proto);
292 return (EAI_SERVICE);
295 if (strcmp(sp->s_proto, "tcp") == 0)
296 socktype = SOCK_STREAM;
297 else if (strcmp(sp->s_proto, "udp") == 0)
298 socktype = SOCK_DGRAM;
305 * Next, deal with just a service name, and no hostname.
306 * (we verified that one of them was non-null up above).
308 if (hostname == NULL && (flags & AI_PASSIVE) != 0) {
309 if (family == AF_INET || family == 0) {
310 ai = ai_alloc(AF_INET, sizeof(struct sockaddr_in));
313 ai->ai_socktype = socktype;
314 ai->ai_protocol = protocol;
315 SIN(ai->ai_addr)->sin_port = port;
316 ai->ai_next = ai_list;
320 if (family == AF_INET6 || family == 0) {
321 ai = ai_alloc(AF_INET6, sizeof(struct sockaddr_in6));
323 lwres_freeaddrinfo(ai_list);
326 ai->ai_socktype = socktype;
327 ai->ai_protocol = protocol;
328 SIN6(ai->ai_addr)->sin6_port = port;
329 ai->ai_next = ai_list;
338 * If the family isn't specified or AI_NUMERICHOST specified,
339 * check first to see if it is a numeric address.
340 * Though the gethostbyname2() routine
341 * will recognize numeric addresses, it will only recognize
342 * the format that it is being called for. Thus, a numeric
343 * AF_INET address will be treated by the AF_INET6 call as
344 * a domain name, and vice versa. Checking for both numerics
347 if (hostname != NULL &&
348 (family == 0 || (flags & AI_NUMERICHOST) != 0)) {
349 char abuf[sizeof(struct in6_addr)];
350 char nbuf[NI_MAXHOST];
351 int addrsize, addroff;
352 #ifdef LWRES_HAVE_SIN6_SCOPE_ID
354 char ntmp[NI_MAXHOST];
355 lwres_uint32_t scopeid;
358 #ifdef LWRES_HAVE_SIN6_SCOPE_ID
360 * Scope identifier portion.
363 if (strchr(hostname, '%') != NULL) {
364 strncpy(ntmp, hostname, sizeof(ntmp) - 1);
365 ntmp[sizeof(ntmp) - 1] = '\0';
366 p = strchr(ntmp, '%');
370 * Vendors may want to support non-numeric
371 * scopeid around here.
375 scopeid = (lwres_uint32_t)strtoul(p + 1,
377 if (p != NULL && ep != NULL && ep[0] == '\0')
387 if (lwres_net_pton(AF_INET, hostname, (struct in_addr *)abuf)
390 if (family == AF_INET6) {
392 * Convert to a V4 mapped address.
394 struct in6_addr *a6 = (struct in6_addr *)abuf;
395 memcpy(&a6->s6_addr[12], &a6->s6_addr[0], 4);
396 memset(&a6->s6_addr[10], 0xff, 2);
397 memset(&a6->s6_addr[0], 0, 10);
400 addrsize = sizeof(struct in_addr);
401 addroff = (char *)(&SIN(0)->sin_addr) - (char *)0;
404 #ifdef LWRES_HAVE_SIN6_SCOPE_ID
405 } else if (ntmp[0] != '\0' &&
406 lwres_net_pton(AF_INET6, ntmp, abuf) == 1)
408 if (family && family != AF_INET6)
410 addrsize = sizeof(struct in6_addr);
411 addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0;
415 } else if (lwres_net_pton(AF_INET6, hostname, abuf) == 1) {
416 if (family != 0 && family != AF_INET6)
419 addrsize = sizeof(struct in6_addr);
420 addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0;
424 ai = ai_clone(ai_list, family);
428 ai->ai_socktype = socktype;
429 SIN(ai->ai_addr)->sin_port = port;
430 memcpy((char *)ai->ai_addr + addroff, abuf, addrsize);
431 if (flags & AI_CANONNAME) {
432 #if defined(LWRES_HAVE_SIN6_SCOPE_ID)
433 if (ai->ai_family == AF_INET6)
434 SIN6(ai->ai_addr)->sin6_scope_id =
437 if (lwres_getnameinfo(ai->ai_addr,
438 ai->ai_addrlen, nbuf, sizeof(nbuf),
440 NI_NUMERICHOST) == 0) {
441 ai->ai_canonname = strdup(nbuf);
442 if (ai->ai_canonname == NULL) {
443 lwres_freeaddrinfo(ai_list);
447 /* XXX raise error? */
448 ai->ai_canonname = NULL;
452 } else if ((flags & AI_NUMERICHOST) != 0) {
457 set_order(family, net_order);
458 for (i = 0; i < FOUND_MAX; i++) {
459 if (net_order[i] == NULL)
461 err = (net_order[i])(hostname, flags, &ai_list,
471 ai_list = ai_reverse(ai_list);
478 lwres_strsep(char **stringp, const char *delim) {
479 char *string = *stringp;
487 for (s = string; *s != '\0'; s++) {
489 for (d = delim; (dc = *d) != '\0'; d++)
501 set_order(int family, int (**net_order)(const char *, int, struct addrinfo **,
510 *net_order++ = add_ipv4;
513 *net_order++ = add_ipv6;
517 order = getenv("NET_ORDER");
519 while (order != NULL) {
521 * We ignore any unknown names.
523 tok = lwres_strsep(&order, ":");
524 if (strcasecmp(tok, "inet6") == 0) {
525 if ((found & FOUND_IPV6) == 0)
526 *net_order++ = add_ipv6;
528 } else if (strcasecmp(tok, "inet") == 0 ||
529 strcasecmp(tok, "inet4") == 0) {
530 if ((found & FOUND_IPV4) == 0)
531 *net_order++ = add_ipv4;
537 * Add in anything that we didn't find.
539 if ((found & FOUND_IPV4) == 0)
540 *net_order++ = add_ipv4;
541 if ((found & FOUND_IPV6) == 0)
542 *net_order++ = add_ipv6;
548 static char v4_loop[4] = { 127, 0, 0, 1 };
551 * The test against 0 is there to keep the Solaris compiler
552 * from complaining about "end-of-loop code not reached".
554 #define SETERROR(code) \
555 do { result = (code); \
556 if (result != 0) goto cleanup; \
560 add_ipv4(const char *hostname, int flags, struct addrinfo **aip,
561 int socktype, int port)
564 lwres_context_t *lwrctx = NULL;
565 lwres_gabnresponse_t *by = NULL;
567 lwres_result_t lwres;
570 lwres = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
571 if (lwres != LWRES_R_SUCCESS)
573 (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
574 if (hostname == NULL && (flags & AI_PASSIVE) == 0) {
575 ai = ai_clone(*aip, AF_INET);
577 lwres_freeaddrinfo(*aip);
578 SETERROR(EAI_MEMORY);
582 ai->ai_socktype = socktype;
583 SIN(ai->ai_addr)->sin_port = port;
584 memcpy(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4);
586 lwres = lwres_getaddrsbyname(lwrctx, hostname,
587 LWRES_ADDRTYPE_V4, &by);
588 if (lwres != LWRES_R_SUCCESS) {
589 if (lwres == LWRES_R_NOTFOUND)
594 addr = LWRES_LIST_HEAD(by->addrs);
595 while (addr != NULL) {
596 ai = ai_clone(*aip, AF_INET);
598 lwres_freeaddrinfo(*aip);
599 SETERROR(EAI_MEMORY);
602 ai->ai_socktype = socktype;
603 SIN(ai->ai_addr)->sin_port = port;
604 memcpy(&SIN(ai->ai_addr)->sin_addr,
606 if (flags & AI_CANONNAME) {
607 ai->ai_canonname = strdup(by->realname);
608 if (ai->ai_canonname == NULL)
609 SETERROR(EAI_MEMORY);
611 addr = LWRES_LIST_NEXT(addr, link);
616 lwres_gabnresponse_free(lwrctx, &by);
617 if (lwrctx != NULL) {
618 lwres_conf_clear(lwrctx);
619 lwres_context_destroy(&lwrctx);
624 static char v6_loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
627 add_ipv6(const char *hostname, int flags, struct addrinfo **aip,
628 int socktype, int port)
631 lwres_context_t *lwrctx = NULL;
632 lwres_gabnresponse_t *by = NULL;
634 lwres_result_t lwres;
637 lwres = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
638 if (lwres != LWRES_R_SUCCESS)
640 (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
642 if (hostname == NULL && (flags & AI_PASSIVE) == 0) {
643 ai = ai_clone(*aip, AF_INET6);
645 lwres_freeaddrinfo(*aip);
646 SETERROR(EAI_MEMORY);
650 ai->ai_socktype = socktype;
651 SIN6(ai->ai_addr)->sin6_port = port;
652 memcpy(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16);
654 lwres = lwres_getaddrsbyname(lwrctx, hostname,
655 LWRES_ADDRTYPE_V6, &by);
656 if (lwres != LWRES_R_SUCCESS) {
657 if (lwres == LWRES_R_NOTFOUND)
662 addr = LWRES_LIST_HEAD(by->addrs);
663 while (addr != NULL) {
664 ai = ai_clone(*aip, AF_INET6);
666 lwres_freeaddrinfo(*aip);
667 SETERROR(EAI_MEMORY);
670 ai->ai_socktype = socktype;
671 SIN6(ai->ai_addr)->sin6_port = port;
672 memcpy(&SIN6(ai->ai_addr)->sin6_addr,
674 if (flags & AI_CANONNAME) {
675 ai->ai_canonname = strdup(by->realname);
676 if (ai->ai_canonname == NULL)
677 SETERROR(EAI_MEMORY);
679 addr = LWRES_LIST_NEXT(addr, link);
684 lwres_gabnresponse_free(lwrctx, &by);
685 if (lwrctx != NULL) {
686 lwres_conf_clear(lwrctx);
687 lwres_context_destroy(&lwrctx);
692 /*% Free address info. */
694 lwres_freeaddrinfo(struct addrinfo *ai) {
695 struct addrinfo *ai_next;
698 ai_next = ai->ai_next;
699 if (ai->ai_addr != NULL)
701 if (ai->ai_canonname)
702 free(ai->ai_canonname);
710 get_local(const char *name, int socktype, struct addrinfo **res) {
712 struct sockaddr_un *sun;
715 return (EAI_SOCKTYPE);
717 ai = ai_alloc(AF_LOCAL, sizeof(*sun));
721 sun = SUN(ai->ai_addr);
722 strncpy(sun->sun_path, name, sizeof(sun->sun_path));
724 ai->ai_socktype = socktype;
726 * ai->ai_flags, ai->ai_protocol, ai->ai_canonname,
727 * and ai->ai_next were initialized to zero.
736 * Allocate an addrinfo structure, and a sockaddr structure
737 * of the specificed length. We initialize:
742 * ai_addr->sa_len (LWRES_PLATFORM_HAVESALEN)
743 * and everything else is initialized to zero.
745 static struct addrinfo *
746 ai_alloc(int family, int addrlen) {
749 ai = (struct addrinfo *)calloc(1, sizeof(*ai));
753 ai->ai_addr = SA(calloc(1, addrlen));
754 if (ai->ai_addr == NULL) {
758 ai->ai_addrlen = addrlen;
759 ai->ai_family = family;
760 ai->ai_addr->sa_family = family;
761 #ifdef LWRES_PLATFORM_HAVESALEN
762 ai->ai_addr->sa_len = addrlen;
767 static struct addrinfo *
768 ai_clone(struct addrinfo *oai, int family) {
771 ai = ai_alloc(family, ((family == AF_INET6) ?
772 sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)));
775 lwres_freeaddrinfo(oai);
781 ai->ai_flags = oai->ai_flags;
782 ai->ai_socktype = oai->ai_socktype;
783 ai->ai_protocol = oai->ai_protocol;
784 ai->ai_canonname = NULL;
789 static struct addrinfo *
790 ai_reverse(struct addrinfo *oai) {
791 struct addrinfo *nai, *tai;
795 while (oai != NULL) {
797 * Grab one off the old list.
802 * Put it on the front of the new list.