]>
The Tcpdump Group git mirrors - tcpdump/blob - missing/getaddrinfo.c
e37f9363860c5191b744cec1266ede52aa208891
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
33 * Issues to be discussed:
34 * - Thread safe-ness must be checked.
35 * - Return values. There are nonstandard return values defined and used
36 * in the source code. This is because RFC2553 is silent about which error
37 * code must be returned for which situation.
39 * - We use getipnodebyname() just for thread-safeness. There's no intent
40 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
42 * - The code filters out AFs that are not supported by the kernel,
43 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
44 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
52 #include "tcpdump-stdinc.h"
54 #include "interface.h"
58 static const char rcsid
[] =
59 "@(#) $Header: /tcpdump/master/tcpdump/missing/getaddrinfo.c,v 1.12 2003-11-15 00:39:47 guy Exp $";
62 #include <sys/types.h>
63 #include <sys/param.h>
65 #include <sys/sysctl.h>
67 #include <sys/socket.h>
69 #include <netinet/in.h>
70 #include <arpa/inet.h>
71 #include <arpa/nameser.h>
82 #ifndef HAVE_U_INT32_T
86 #ifndef HAVE_SOCKADDR_STORAGE
87 #include "sockstorage.h"
90 #ifdef NEED_ADDRINFO_H
94 #if defined(__KAME__) && defined(INET6)
104 static int translate
= NO
;
105 static struct in6_addr faith_prefix
= IN6ADDR_ANY_INIT
;
108 static const char in_addrany
[] = { 0, 0, 0, 0 };
109 static const char in6_addrany
[] = {
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
112 static const char in_loopback
[] = { 127, 0, 0, 1 };
113 static const char in6_loopback
[] = {
114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
121 u_int32_t si_scope_id
;
124 static const struct afd
{
129 const char *a_addrany
;
130 const char *a_loopback
;
134 {PF_INET6
, sizeof(struct in6_addr
),
135 sizeof(struct sockaddr_in6
),
136 offsetof(struct sockaddr_in6
, sin6_addr
),
137 in6_addrany
, in6_loopback
, 1},
139 {PF_INET
, sizeof(struct in_addr
),
140 sizeof(struct sockaddr_in
),
141 offsetof(struct sockaddr_in
, sin_addr
),
142 in_addrany
, in_loopback
, 0},
143 {0, 0, 0, 0, NULL
, NULL
, 0},
150 const char *e_protostr
;
152 #define WILD_AF(ex) ((ex)->e_wild & 0x01)
153 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
154 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
157 static const struct explore explore
[] = {
159 { PF_LOCAL
, 0, ANY
, ANY
, NULL
, 0x01 },
162 { PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
163 { PF_INET6
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
164 { PF_INET6
, SOCK_RAW
, ANY
, NULL
, 0x05 },
166 { PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
167 { PF_INET
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
168 { PF_INET
, SOCK_RAW
, ANY
, NULL
, 0x05 },
169 { -1, 0, 0, NULL
, 0 },
179 static int str_isnumber (const char *);
180 static int explore_fqdn (const struct addrinfo
*, const char *,
181 const char *, struct addrinfo
**);
182 static int explore_null (const struct addrinfo
*, const char *,
183 const char *, struct addrinfo
**);
184 static int explore_numeric (const struct addrinfo
*, const char *,
185 const char *, struct addrinfo
**);
186 static int explore_numeric_scope (const struct addrinfo
*, const char *,
187 const char *, struct addrinfo
**);
188 static int get_name (const char *, const struct afd
*, struct addrinfo
**,
189 char *, const struct addrinfo
*, const char *);
190 static int get_canonname (const struct addrinfo
*,
191 struct addrinfo
*, const char *);
192 static struct addrinfo
*get_ai (const struct addrinfo
*,
193 const struct afd
*, const char *);
194 static int get_portmatch (const struct addrinfo
*, const char *);
195 static int get_port (struct addrinfo
*, const char *, int);
196 static const struct afd
*find_afd (int);
198 static char *ai_errlist
[] = {
200 "Address family for hostname not supported", /* EAI_ADDRFAMILY */
201 "Temporary failure in name resolution", /* EAI_AGAIN */
202 "Invalid value for ai_flags", /* EAI_BADFLAGS */
203 "Non-recoverable failure in name resolution", /* EAI_FAIL */
204 "ai_family not supported", /* EAI_FAMILY */
205 "Memory allocation failure", /* EAI_MEMORY */
206 "No address associated with hostname", /* EAI_NODATA */
207 "hostname nor servname provided, or not known", /* EAI_NONAME */
208 "servname not supported for ai_socktype", /* EAI_SERVICE */
209 "ai_socktype not supported", /* EAI_SOCKTYPE */
210 "System error returned in errno", /* EAI_SYSTEM */
211 "Invalid value for hints", /* EAI_BADHINTS */
212 "Resolved protocol is unknown", /* EAI_PROTOCOL */
213 "Unknown error", /* EAI_MAX */
216 /* XXX macros that make external reference is BAD. */
218 #define GET_AI(ai, afd, addr) \
220 /* external reference: pai, error, and label free */ \
221 (ai) = get_ai(pai, (afd), (addr)); \
222 if ((ai) == NULL) { \
223 error = EAI_MEMORY; \
228 #define GET_PORT(ai, serv) \
230 /* external reference: error and label free */ \
231 error = get_port((ai), (serv), 0); \
236 #define GET_CANONNAME(ai, str) \
238 /* external reference: pai, error and label free */ \
239 error = get_canonname(pai, (ai), (str)); \
246 /* external reference: error, and label bad */ \
251 #define MATCH_FAMILY(x, y, w) \
252 ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
253 #define MATCH(x, y, w) \
254 ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
260 if (ecode
< 0 || ecode
> EAI_MAX
)
262 return ai_errlist
[ecode
];
269 struct addrinfo
*next
;
273 if (ai
->ai_canonname
)
274 free(ai
->ai_canonname
);
275 /* no need to free(ai->ai_addr) */
277 } while ((ai
= next
) != NULL
);
294 getaddrinfo(hostname
, servname
, hints
, res
)
295 const char *hostname
, *servname
;
296 const struct addrinfo
*hints
;
297 struct addrinfo
**res
;
299 struct addrinfo sentinel
;
300 struct addrinfo
*cur
;
304 struct addrinfo
*pai
;
305 const struct afd
*afd
;
306 const struct explore
*ex
;
309 static int firsttime
= 1;
312 /* translator hack */
313 char *q
= getenv("GAI");
314 if (q
&& inet_pton(AF_INET6
, q
, &faith_prefix
) == 1)
320 sentinel
.ai_next
= NULL
;
324 pai
->ai_family
= PF_UNSPEC
;
325 pai
->ai_socktype
= ANY
;
326 pai
->ai_protocol
= ANY
;
328 pai
->ai_canonname
= NULL
;
332 if (hostname
== NULL
&& servname
== NULL
)
335 /* error check for hints */
336 if (hints
->ai_addrlen
|| hints
->ai_canonname
||
337 hints
->ai_addr
|| hints
->ai_next
)
338 ERR(EAI_BADHINTS
); /* xxx */
339 if (hints
->ai_flags
& ~AI_MASK
)
341 switch (hints
->ai_family
) {
351 memcpy(pai
, hints
, sizeof(*pai
));
354 * if both socktype/protocol are specified, check if they
355 * are meaningful combination.
357 if (pai
->ai_socktype
!= ANY
&& pai
->ai_protocol
!= ANY
) {
358 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
359 if (pai
->ai_family
!= ex
->e_af
)
361 if (ex
->e_socktype
== ANY
)
363 if (ex
->e_protocol
== ANY
)
365 if (pai
->ai_socktype
== ex
->e_socktype
366 && pai
->ai_protocol
!= ex
->e_protocol
) {
374 * check for special cases. (1) numeric servname is disallowed if
375 * socktype/protocol are left unspecified. (2) servname is disallowed
376 * for raw and other inet{,6} sockets.
378 if (MATCH_FAMILY(pai
->ai_family
, PF_INET
, 1)
380 || MATCH_FAMILY(pai
->ai_family
, PF_INET6
, 1)
385 if (pai
->ai_family
== PF_UNSPEC
) {
387 pai
->ai_family
= PF_INET6
;
389 pai
->ai_family
= PF_INET
;
392 error
= get_portmatch(pai
, servname
);
401 /* NULL hostname, or numeric hostname */
402 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
405 if (!MATCH_FAMILY(pai
->ai_family
, ex
->e_af
, WILD_AF(ex
)))
407 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
, WILD_SOCKTYPE(ex
)))
409 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
, WILD_PROTOCOL(ex
)))
412 if (pai
->ai_family
== PF_UNSPEC
)
413 pai
->ai_family
= ex
->e_af
;
414 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
415 pai
->ai_socktype
= ex
->e_socktype
;
416 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
417 pai
->ai_protocol
= ex
->e_protocol
;
419 if (hostname
== NULL
)
420 error
= explore_null(pai
, hostname
, servname
, &cur
->ai_next
);
422 error
= explore_numeric_scope(pai
, hostname
, servname
, &cur
->ai_next
);
427 while (cur
&& cur
->ai_next
)
433 * If numreic representation of AF1 can be interpreted as FQDN
434 * representation of AF2, we need to think again about the code below.
436 if (sentinel
.ai_next
)
439 if (pai
->ai_flags
& AI_NUMERICHOST
)
441 if (hostname
== NULL
)
445 * hostname as alphabetical name.
446 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
449 for (afd
= afdl
; afd
->a_af
; afd
++) {
452 if (!MATCH_FAMILY(pai
->ai_family
, afd
->a_af
, 1))
455 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
458 if (pai
->ai_family
== PF_UNSPEC
)
459 pai
->ai_family
= afd
->a_af
;
461 if (!MATCH_FAMILY(pai
->ai_family
, ex
->e_af
, WILD_AF(ex
)))
463 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
,
464 WILD_SOCKTYPE(ex
))) {
467 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
,
468 WILD_PROTOCOL(ex
))) {
472 if (pai
->ai_family
== PF_UNSPEC
)
473 pai
->ai_family
= ex
->e_af
;
474 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
475 pai
->ai_socktype
= ex
->e_socktype
;
476 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
477 pai
->ai_protocol
= ex
->e_protocol
;
479 error
= explore_fqdn(pai
, hostname
, servname
,
482 while (cur
&& cur
->ai_next
)
488 if (sentinel
.ai_next
)
494 if (sentinel
.ai_next
) {
496 *res
= sentinel
.ai_next
;
503 if (sentinel
.ai_next
)
504 freeaddrinfo(sentinel
.ai_next
);
510 * FQDN hostname, DNS lookup
513 explore_fqdn(pai
, hostname
, servname
, res
)
514 const struct addrinfo
*pai
;
515 const char *hostname
;
516 const char *servname
;
517 struct addrinfo
**res
;
522 char **aplist
= NULL
, *apbuf
= NULL
;
524 struct addrinfo sentinel
, *cur
;
526 #ifndef USE_GETIPNODEBY
529 const struct afd
*afd
;
533 sentinel
.ai_next
= NULL
;
537 * Do not filter unsupported AFs here. We need to honor content of
538 * databases (/etc/hosts, DNS and others). Otherwise we cannot
539 * replace gethostbyname() by getaddrinfo().
543 * if the servname does not match socktype/protocol, ignore it.
545 if (get_portmatch(pai
, servname
) != 0)
548 afd
= find_afd(pai
->ai_family
);
551 * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG)
552 * rather than hardcoding it. we may need to add AI_ADDRCONFIG
553 * handling code by ourselves in case we don't have getipnodebyname().
555 #ifdef USE_GETIPNODEBY
556 hp
= getipnodebyname(hostname
, pai
->ai_family
, AI_ADDRCONFIG
, &h_error
);
558 #ifdef HAVE_GETHOSTBYNAME2
559 hp
= gethostbyname2(hostname
, pai
->ai_family
);
561 if (pai
->ai_family
!= AF_INET
)
563 hp
= gethostbyname(hostname
);
569 #endif /*HAVE_GETHOSTBYNAME2*/
570 #endif /*USE_GETIPNODEBY*/
587 } else if ((hp
->h_name
== NULL
) || (hp
->h_name
[0] == 0)
588 || (hp
->h_addr_list
[0] == NULL
)) {
589 #ifdef USE_GETIPNODEBY
599 #ifdef USE_GETIPNODEBY
600 aplist
= hp
->h_addr_list
;
603 * hp will be overwritten if we use gethostbyname2().
604 * always deep copy for simplification.
606 for (naddrs
= 0; hp
->h_addr_list
[naddrs
] != NULL
; naddrs
++)
609 aplist
= (char **)malloc(sizeof(aplist
[0]) * naddrs
);
610 apbuf
= (char *)malloc(hp
->h_length
* naddrs
);
611 if (aplist
== NULL
|| apbuf
== NULL
) {
615 memset(aplist
, 0, sizeof(aplist
[0]) * naddrs
);
616 for (i
= 0; i
< naddrs
; i
++) {
617 if (hp
->h_addr_list
[i
] == NULL
) {
621 memcpy(&apbuf
[i
* hp
->h_length
], hp
->h_addr_list
[i
],
623 aplist
[i
] = &apbuf
[i
* hp
->h_length
];
627 for (i
= 0; aplist
[i
] != NULL
; i
++) {
632 && IN6_IS_ADDR_V4MAPPED((struct in6_addr
*)ap
)) {
634 ap
= ap
+ sizeof(struct in6_addr
)
635 - sizeof(struct in_addr
);
639 if (af
!= pai
->ai_family
)
642 if ((pai
->ai_flags
& AI_CANONNAME
) == 0) {
643 GET_AI(cur
->ai_next
, afd
, ap
);
644 GET_PORT(cur
->ai_next
, servname
);
647 * if AI_CANONNAME and if reverse lookup
648 * fail, return ai anyway to pacify
649 * calling application.
651 * XXX getaddrinfo() is a name->address
652 * translation function, and it looks
653 * strange that we do addr->name
656 get_name(ap
, afd
, &cur
->ai_next
,
660 while (cur
&& cur
->ai_next
)
664 *res
= sentinel
.ai_next
;
668 #ifdef USE_GETIPNODEBY
676 if (sentinel
.ai_next
)
677 freeaddrinfo(sentinel
.ai_next
);
683 * passive socket -> anyaddr (0.0.0.0 or ::)
684 * non-passive socket -> localhost (127.0.0.1 or ::1)
687 explore_null(pai
, hostname
, servname
, res
)
688 const struct addrinfo
*pai
;
689 const char *hostname
;
690 const char *servname
;
691 struct addrinfo
**res
;
694 const struct afd
*afd
;
695 struct addrinfo
*cur
;
696 struct addrinfo sentinel
;
700 sentinel
.ai_next
= NULL
;
704 * filter out AFs that are not supported by the kernel
707 s
= socket(pai
->ai_family
, SOCK_DGRAM
, 0);
715 * if the servname does not match socktype/protocol, ignore it.
717 if (get_portmatch(pai
, servname
) != 0)
720 afd
= find_afd(pai
->ai_family
);
722 if (pai
->ai_flags
& AI_PASSIVE
) {
723 GET_AI(cur
->ai_next
, afd
, afd
->a_addrany
);
725 * GET_CANONNAME(cur->ai_next, "anyaddr");
727 GET_PORT(cur
->ai_next
, servname
);
729 GET_AI(cur
->ai_next
, afd
, afd
->a_loopback
);
731 * GET_CANONNAME(cur->ai_next, "localhost");
733 GET_PORT(cur
->ai_next
, servname
);
737 *res
= sentinel
.ai_next
;
741 if (sentinel
.ai_next
)
742 freeaddrinfo(sentinel
.ai_next
);
750 explore_numeric(pai
, hostname
, servname
, res
)
751 const struct addrinfo
*pai
;
752 const char *hostname
;
753 const char *servname
;
754 struct addrinfo
**res
;
756 const struct afd
*afd
;
757 struct addrinfo
*cur
;
758 struct addrinfo sentinel
;
764 sentinel
.ai_next
= NULL
;
768 * if the servname does not match socktype/protocol, ignore it.
770 if (get_portmatch(pai
, servname
) != 0)
773 afd
= find_afd(pai
->ai_family
);
774 flags
= pai
->ai_flags
;
776 if (inet_pton(afd
->a_af
, hostname
, pton
) == 1) {
784 v4a
= (u_int32_t
)ntohl(((struct in_addr
*)pton
)->s_addr
);
785 if (IN_MULTICAST(v4a
) || IN_EXPERIMENTAL(v4a
))
786 flags
&= ~AI_CANONNAME
;
787 v4a
>>= IN_CLASSA_NSHIFT
;
788 if (v4a
== 0 || v4a
== IN_LOOPBACKNET
)
789 flags
&= ~AI_CANONNAME
;
793 pfx
= ((struct in6_addr
*)pton
)->s6_addr
[0];
794 if (pfx
== 0 || pfx
== 0xfe || pfx
== 0xff)
795 flags
&= ~AI_CANONNAME
;
800 if (pai
->ai_family
== afd
->a_af
||
801 pai
->ai_family
== PF_UNSPEC
/*?*/) {
802 if ((flags
& AI_CANONNAME
) == 0) {
803 GET_AI(cur
->ai_next
, afd
, pton
);
804 GET_PORT(cur
->ai_next
, servname
);
807 * if AI_CANONNAME and if reverse lookup
808 * fail, return ai anyway to pacify
809 * calling application.
811 * XXX getaddrinfo() is a name->address
812 * translation function, and it looks
813 * strange that we do addr->name
816 get_name(pton
, afd
, &cur
->ai_next
,
817 pton
, pai
, servname
);
819 while (cur
&& cur
->ai_next
)
822 ERR(EAI_FAMILY
); /*xxx*/
825 *res
= sentinel
.ai_next
;
830 if (sentinel
.ai_next
)
831 freeaddrinfo(sentinel
.ai_next
);
836 * numeric hostname with scope
839 explore_numeric_scope(pai
, hostname
, servname
, res
)
840 const struct addrinfo
*pai
;
841 const char *hostname
;
842 const char *servname
;
843 struct addrinfo
**res
;
845 #ifndef SCOPE_DELIMITER
846 return explore_numeric(pai
, hostname
, servname
, res
);
848 const struct afd
*afd
;
849 struct addrinfo
*cur
;
851 char *cp
, *hostname2
= NULL
;
853 struct sockaddr_in6
*sin6
;
856 * if the servname does not match socktype/protocol, ignore it.
858 if (get_portmatch(pai
, servname
) != 0)
861 afd
= find_afd(pai
->ai_family
);
863 return explore_numeric(pai
, hostname
, servname
, res
);
865 cp
= strchr(hostname
, SCOPE_DELIMITER
);
867 return explore_numeric(pai
, hostname
, servname
, res
);
870 * Handle special case of <scoped_address><delimiter><scope id>
872 hostname2
= strdup(hostname
);
873 if (hostname2
== NULL
)
875 /* terminate at the delimiter */
876 hostname2
[cp
- hostname
] = '\0';
879 switch (pai
->ai_family
) {
882 scope
= if_nametoindex(cp
);
891 error
= explore_numeric(pai
, hostname2
, servname
, res
);
893 for (cur
= *res
; cur
; cur
= cur
->ai_next
) {
894 if (cur
->ai_family
!= AF_INET6
)
896 sin6
= (struct sockaddr_in6
*)cur
->ai_addr
;
897 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
) ||
898 IN6_IS_ADDR_MC_LINKLOCAL(&sin6
->sin6_addr
))
899 sin6
->sin6_scope_id
= scope
;
910 get_name(addr
, afd
, res
, numaddr
, pai
, servname
)
912 const struct afd
*afd
;
913 struct addrinfo
**res
;
915 const struct addrinfo
*pai
;
916 const char *servname
;
918 struct hostent
*hp
= NULL
;
919 struct addrinfo
*cur
= NULL
;
921 char *ap
= NULL
, *cn
= NULL
;
922 #ifdef USE_GETIPNODEBY
925 hp
= getipnodebyaddr(addr
, afd
->a_addrlen
, afd
->a_af
, &h_error
);
927 hp
= gethostbyaddr(addr
, afd
->a_addrlen
, afd
->a_af
);
929 if (hp
&& hp
->h_name
&& hp
->h_name
[0] && hp
->h_addr_list
[0]) {
930 #ifdef USE_GETIPNODEBY
931 GET_AI(cur
, afd
, hp
->h_addr_list
[0]);
932 GET_PORT(cur
, servname
);
933 GET_CANONNAME(cur
, hp
->h_name
);
935 /* hp will be damaged if we use gethostbyaddr() */
936 if ((ap
= (char *)malloc(hp
->h_length
)) == NULL
) {
940 memcpy(ap
, hp
->h_addr_list
[0], hp
->h_length
);
941 if ((cn
= strdup(hp
->h_name
)) == NULL
) {
946 GET_AI(cur
, afd
, ap
);
947 GET_PORT(cur
, servname
);
948 GET_CANONNAME(cur
, cn
);
953 GET_AI(cur
, afd
, numaddr
);
954 GET_PORT(cur
, servname
);
957 #ifdef USE_GETIPNODEBY
970 #ifdef USE_GETIPNODEBY
979 get_canonname(pai
, ai
, str
)
980 const struct addrinfo
*pai
;
984 if ((pai
->ai_flags
& AI_CANONNAME
) != 0) {
985 ai
->ai_canonname
= (char *)malloc(strlen(str
) + 1);
986 if (ai
->ai_canonname
== NULL
)
988 strcpy(ai
->ai_canonname
, str
);
993 static struct addrinfo
*
994 get_ai(pai
, afd
, addr
)
995 const struct addrinfo
*pai
;
996 const struct afd
*afd
;
1000 struct addrinfo
*ai
;
1002 ai
= (struct addrinfo
*)malloc(sizeof(struct addrinfo
)
1003 + (afd
->a_socklen
));
1007 memcpy(ai
, pai
, sizeof(struct addrinfo
));
1008 ai
->ai_addr
= (struct sockaddr
*)(ai
+ 1);
1009 memset(ai
->ai_addr
, 0, afd
->a_socklen
);
1010 #ifdef HAVE_SOCKADDR_SA_LEN
1011 ai
->ai_addr
->sa_len
= afd
->a_socklen
;
1013 ai
->ai_addrlen
= afd
->a_socklen
;
1014 ai
->ai_addr
->sa_family
= ai
->ai_family
= afd
->a_af
;
1015 p
= (char *)(ai
->ai_addr
);
1016 memcpy(p
+ afd
->a_off
, addr
, afd
->a_addrlen
);
1021 get_portmatch(ai
, servname
)
1022 const struct addrinfo
*ai
;
1023 const char *servname
;
1026 /* get_port does not touch first argument. when matchonly == 1. */
1027 return get_port((struct addrinfo
*)ai
, servname
, 1);
1031 get_port(ai
, servname
, matchonly
)
1032 struct addrinfo
*ai
;
1033 const char *servname
;
1041 if (servname
== NULL
)
1043 switch (ai
->ai_family
) {
1053 switch (ai
->ai_socktype
) {
1064 return EAI_SOCKTYPE
;
1067 if (str_isnumber(servname
)) {
1070 port
= htons(atoi(servname
));
1071 if (port
< 0 || port
> 65535)
1074 switch (ai
->ai_socktype
) {
1086 if ((sp
= getservbyname(servname
, proto
)) == NULL
)
1092 switch (ai
->ai_family
) {
1094 ((struct sockaddr_in
*)ai
->ai_addr
)->sin_port
= port
;
1098 ((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_port
= port
;
1107 static const struct afd
*
1111 const struct afd
*afd
;
1113 if (af
== PF_UNSPEC
)
1115 for (afd
= afdl
; afd
->a_af
; afd
++) {
1116 if (afd
->a_af
== af
)