187 #include <sys/types.h>
188 #include <sys/socket.h>
189 #include <netinet/in.h>
190 #include <arpa/inet.h>
226 #define MAI_SOCKTYPE SOCK_STREAM
228 #ifdef EMULATE_IPV4_ADDRINFO
238 ip->
info.ai_addr = (
struct sockaddr *) &(ip->
sin);
244 static void init_ipv4addrinfo(
struct ipv4addrinfo * ip,
int socktype)
251 memset((
void *) ip, 0,
sizeof(*ip));
252 ip->
info.ai_family = PF_INET;
253 ip->
info.ai_socktype = socktype;
254 ip->
info.ai_protocol = 0;
255 ip->
info.ai_addrlen =
sizeof(ip->
sin);
256 ip->
info.ai_canonname = 0;
257 ip->
info.ai_addr = (
struct sockaddr *) &(ip->
sin);
258 ip->
info.ai_next = 0;
259 ip->
sin.sin_family = AF_INET;
261 ip->
sin.sin_len =
sizeof(ip->
sin);
267 static int find_service(
const char *service,
int socktype)
274 port = atoi(service);
275 return (port < 65536 ? htons(port) : -1);
277 if (socktype == SOCK_STREAM) {
279 }
else if (socktype == SOCK_DGRAM) {
284 if ((sp = getservbyname(service, proto)) != 0) {
296 const char *service,
int socktype,
297 struct addrinfo ** res)
299 #ifdef EMULATE_IPV4_ADDRINFO
316 if ((port = find_service(service, socktype)) < 0)
317 return (EAI_SERVICE);
328 init_ipv4addrinfo(ip, socktype);
329 ip->
sin.sin_addr.s_addr = INADDR_ANY;
330 ip->
sin.sin_port = port;
338 if (
inet_pton(AF_INET, hostname, (
void *) &addr) == 1) {
340 init_ipv4addrinfo(ip, socktype);
341 ip->
sin.sin_addr = addr;
342 ip->
sin.sin_port = port;
350 if ((hp = gethostbyname(hostname)) == 0)
351 return (h_errno == TRY_AGAIN ? EAI_AGAIN : EAI_NODATA);
352 if (hp->h_addrtype != AF_INET
353 || hp->h_length !=
sizeof(
template.sin.sin_addr))
359 if (
template.
info.ai_addrlen == 0)
360 init_ipv4addrinfo(&
template, socktype);
366 for (name_list = hp->h_addr_list; name_list[0]; name_list++) {
367 ip = clone_ipv4addrinfo(prev);
369 ip->
sin.sin_port = port;
370 if (prev == &
template)
424 struct addrinfo hints;
427 memset((
void *) &hints, 0,
sizeof(hints));
428 hints.ai_family = (pf != PF_UNSPEC) ? pf :
inet_proto_info()->ai_family;
431 hints.ai_flags = AI_PASSIVE;
432 #if !defined(IPV6_V6ONLY) || defined(BROKEN_AI_PASSIVE_NULL_HOST)
433 switch (hints.ai_family) {
435 hints.ai_family = PF_INET6;
436 #ifdef BROKEN_AI_PASSIVE_NULL_HOST
441 hostname =
"0.0.0.0";
447 err = getaddrinfo(hostname, service, &hints, res);
448 #if defined(BROKEN_AI_NULL_SERVICE)
449 if (service == 0 && err == 0) {
451 unsigned short *portp;
453 for (r = *res; r != 0; r = r->ai_next)
465 int socktype,
struct addrinfo ** res)
467 #ifdef EMULATE_IPV4_ADDRINFO
480 if ((port = find_service(service, socktype)) < 0)
481 return (EAI_SERVICE);
492 init_ipv4addrinfo(ip, socktype);
493 ip->
sin.sin_addr.s_addr = INADDR_ANY;
494 ip->
sin.sin_port = port;
502 switch (
inet_pton(AF_INET, hostaddr, (
void *) &addr)) {
515 init_ipv4addrinfo(ip, socktype);
520 ip->
sin.sin_addr = addr;
521 ip->
sin.sin_port = port;
539 struct addrinfo hints;
542 memset(&hints, 0,
sizeof(hints));
545 hints.ai_flags = AI_NUMERICHOST;
547 hints.ai_flags |= AI_PASSIVE;
548 #if !defined(IPV6_V6ONLY) || defined(BROKEN_AI_PASSIVE_NULL_HOST)
549 switch (hints.ai_family) {
551 hints.ai_family = PF_INET6;
552 #ifdef BROKEN_AI_PASSIVE_NULL_HOST
557 hostaddr =
"0.0.0.0";
563 err = getaddrinfo(hostaddr, service, &hints, res);
564 #if defined(BROKEN_AI_NULL_SERVICE)
565 if (service == 0 && err == 0) {
567 unsigned short *portp;
569 for (r = *res; r != 0; r = r->ai_next)
585 #ifdef EMULATE_IPV4_ADDRINFO
586 char portbuf[
sizeof(
"65535")];
593 if (sa->sa_family != AF_INET) {
594 errno = EAFNOSUPPORT;
599 hostaddr->
buf,
sizeof(hostaddr->
buf)) == 0)
604 if ((len = strlen(portbuf)) >=
sizeof(portnum->
buf)) {
608 memcpy(portnum->
buf, portbuf, len + 1);
617 ret = getnameinfo(sa, salen,
618 hostaddr ? hostaddr->
buf : (
char *) 0,
619 hostaddr ?
sizeof(hostaddr->
buf) : 0,
620 portnum ? portnum->
buf : (
char *) 0,
621 portnum ?
sizeof(portnum->
buf) : 0,
622 NI_NUMERICHOST | NI_NUMERICSERV);
623 if (hostaddr != 0 && ret == 0 && sa->sa_family == AF_INET6)
636 #ifdef EMULATE_IPV4_ADDRINFO
648 if (sa->sa_family != AF_INET)
658 return (h_errno == TRY_AGAIN ? EAI_AGAIN : EAI_NONAME);
665 if ((len = strlen(hp->h_name)) >=
sizeof(hostname->
buf)) {
669 memcpy(hostname->
buf, hp->h_name, len + 1);
677 socktype == SOCK_DGRAM ?
"udp" :
"tcp")) == 0)
684 if ((len = strlen(sp->s_name)) >=
sizeof(service->
buf)) {
688 memcpy(service->
buf, sp->s_name, len + 1);
697 err = getnameinfo(sa, salen,
698 hostname ? hostname->
buf : (
char *) 0,
699 hostname ?
sizeof(hostname->
buf) : 0,
700 service ? service->
buf : (
char *) 0,
701 service ?
sizeof(service->
buf) : 0,
702 socktype == SOCK_DGRAM ?
703 NI_NAMEREQD | NI_DGRAM : NI_NAMEREQD);
726 const char *myname =
"myaddrinfo_control";
729 for (va_start(ap, name); name != 0; name = va_arg(ap,
int)) {
732 msg_panic(
"%s: bad name %d", myname, name);
738 #ifdef EMULATE_IPV4_ADDRINFO
745 struct addrinfo *next;
750 for (ap = ai; ap != 0; ap = next) {
752 if (ap->ai_canonname)
759 static char *ai_errlist[] = {
761 "Address family for hostname not supported",
762 "Temporary failure in name resolution",
763 "Invalid value for ai_flags",
764 "Non-recoverable failure in name resolution",
765 "ai_family not supported",
766 "Memory allocation failure",
767 "No address associated with hostname",
768 "hostname nor servname provided, or not known",
769 "service name not supported for ai_socktype",
770 "ai_socktype not supported",
771 "System error returned in errno",
772 "Invalid value for hints",
773 "Resolved protocol is unknown",
786 if (ecode < 0 || ecode > EAI_MAX)
788 return (ai_errlist[ecode]);
804 static int compare_family(
const void *a,
const void *b)
806 struct addrinfo *resa = *(
struct addrinfo **) a;
807 struct addrinfo *resb = *(
struct addrinfo **) b;
809 return (resa->ai_family - resb->ai_family);
812 int main(
int argc,
char **argv)
814 struct addrinfo *
info;
816 struct addrinfo **resv;
825 msg_fatal(
"usage: %s protocols hostname hostaddress", argv[0]);
829 msg_info(
"=== hostname %s ===", argv[2]);
832 msg_info(
"hostname_to_sockaddr(%s): %s",
833 argv[2], err == EAI_SYSTEM ? strerror(errno) :
gai_strerror(err));
835 for (len = 0, ip = info; ip != 0; ip = ip->ai_next)
837 resv = (
struct addrinfo **)
mymalloc(len *
sizeof(*resv));
838 for (len = 0, ip = info; ip != 0; ip = ip->ai_next)
840 qsort((
void *) resv, len,
sizeof(*resv), compare_family);
841 for (n = 0; n < len; n++) {
845 msg_info(
"sockaddr_to_hostaddr: %s",
846 err == EAI_SYSTEM ? strerror(errno) :
gai_strerror(err));
849 msg_info(
"%s -> family=%d sock=%d proto=%d %s", argv[2],
850 ip->ai_family, ip->ai_socktype, ip->ai_protocol, addr.
buf);
853 msg_info(
"sockaddr_to_hostname: %s",
854 err == EAI_SYSTEM ? strerror(errno) :
gai_strerror(err));
863 msg_info(
"=== host address %s ===", argv[3]);
866 msg_info(
"hostaddr_to_sockaddr(%s): %s",
867 argv[3], err == EAI_SYSTEM ? strerror(errno) :
gai_strerror(err));
871 msg_info(
"sockaddr_to_hostaddr: %s",
872 err == EAI_SYSTEM ? strerror(errno) :
gai_strerror(err));
874 msg_info(
"%s -> family=%d sock=%d proto=%d %s", argv[3],
875 ip->ai_family, ip->ai_socktype, ip->ai_protocol, addr.
buf);
878 msg_info(
"sockaddr_to_hostname: %s",
879 err == EAI_SYSTEM ? strerror(errno) :
gai_strerror(err));
int valid_hostaddr(const char *addr, int gripe)
#define SOCK_ADDR_PORTP(sa)
void freeaddrinfo(struct addrinfo *ai)
NORETURN msg_panic(const char *fmt,...)
#define inet_proto_info()
int main(int argc, char **argv)
INET_PROTO_INFO * inet_proto_init(const char *context, const char *protocols)
#define hostname_to_sockaddr(host, serv, sock, res)
int alldig(const char *string)
int hostaddr_to_sockaddr(const char *hostaddr, const char *service, int socktype, struct addrinfo **res)
int sockaddr_to_hostaddr(const struct sockaddr *sa, SOCKADDR_SIZE salen, MAI_HOSTADDR_STR *hostaddr, MAI_SERVPORT_STR *portnum, int unused_socktype)
int valid_hostname(const char *name, int gripe)
char buf[MAI_HOSTADDR_STRSIZE]
char buf[MAI_SERVNAME_STRSIZE]
const char * inet_ntop(int af, const void *src, char *dst, SOCKADDR_SIZE size)
int hostname_to_sockaddr_pf(const char *hostname, int pf, const char *service, int socktype, struct addrinfo **res)
void msg_warn(const char *fmt,...)
int inet_pton(int af, const char *src, void *dst)
NORETURN msg_fatal(const char *fmt,...)
char buf[MAI_HOSTNAME_STRSIZE]
char * split_at(char *string, int delimiter)
void msg_vstream_init(const char *name, VSTREAM *vp)
char buf[MAI_SERVPORT_STRSIZE]
#define SOCK_ADDR_IN_ADDR(sa)
int sockaddr_to_hostname(const struct sockaddr *sa, SOCKADDR_SIZE salen, MAI_HOSTNAME_STR *hostname, MAI_SERVNAME_STR *service, int socktype)
#define SOCK_ADDR_IN_PORT(sa)
char * gai_strerror(int ecode)
void myaddrinfo_control(int name,...)
void * mymalloc(ssize_t len)
void msg_info(const char *fmt,...)