/* * i host = 0 mean INADDR_ANY only ipv4 */ dlist *bnet_host2ipaddrs(const char *host, int family, const char **errstr) { struct in_addr inaddr; IPADDR *addr = 0; const char *errmsg; #ifdef HAVE_IPV6 struct in6_addr inaddr6; #endif dlist *addr_list = New(dlist(addr, &addr->link)); if (!host || host[0] == '\0') { if (family != 0) { addr_list->append(add_any(family)); } else { addr_list->append(add_any(AF_INET)); #ifdef HAVE_IPV6 addr_list->append(add_any(AF_INET6)); #endif } } else if (inet_aton(host, &inaddr)) { /* MA Bug 4 */ addr = New(IPADDR(AF_INET)); addr->set_type(IPADDR::R_MULTIPLE); addr->set_addr4(&inaddr); addr_list->append(addr); #ifdef HAVE_IPV6 } else if (inet_pton(AF_INET6, host, &inaddr6) == 1) { addr = New(IPADDR(AF_INET6)); addr->set_type(IPADDR::R_MULTIPLE); addr->set_addr6(&inaddr6); addr_list->append(addr); #endif } else { if (family != 0) { errmsg = resolv_host(family, host, addr_list); if (errmsg) { *errstr = errmsg; free_addresses(addr_list); return 0; } } else { #ifdef HAVE_IPV6 /* We try to resolv host for ipv6 and ipv4, the connection procedure * will try to reach the host for each protocols. We report only "Host * not found" ipv4 message (no need to have ipv6 and ipv4 messages). */ resolv_host(AF_INET6, host, addr_list); #endif errmsg = resolv_host(AF_INET, host, addr_list); if (addr_list->size() == 0) { *errstr = errmsg; free_addresses(addr_list); return 0; } } } return addr_list; }
const char *resolv_host(int family, const char *host, dlist *addr_list) { int res; struct addrinfo hints; struct addrinfo *ai, *rp; IPADDR *addr; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = 0; res = getaddrinfo(host, NULL, &hints, &ai); if (res != 0) { return gai_strerror(res); } for (rp = ai; rp != NULL; rp = rp->ai_next) { switch (rp->ai_addr->sa_family) { case AF_INET: addr = New(IPADDR(rp->ai_addr->sa_family)); addr->set_type(IPADDR::R_MULTIPLE); /* * Some serious casting to get the struct in_addr * * rp->ai_addr == struct sockaddr * as this is AF_INET family we can cast that * to struct_sockaddr_in. Of that we need the * address of the sin_addr member which contains a * struct in_addr */ addr->set_addr4(&(((struct sockaddr_in *)rp->ai_addr)->sin_addr)); break; #ifdef HAVE_IPV6 case AF_INET6: addr = New(IPADDR(rp->ai_addr->sa_family)); addr->set_type(IPADDR::R_MULTIPLE); /* * Some serious casting to get the struct in6_addr * * rp->ai_addr == struct sockaddr * as this is AF_INET6 family we can cast that * to struct_sockaddr_in6. Of that we need the * address of the sin6_addr member which contains a * struct in6_addr */ addr->set_addr6(&(((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr)); break; #endif default: continue; } addr_list->append(addr); } freeaddrinfo(ai); return NULL; }
/* * Note: this is the old way of resolving a host * that does not use the new getaddrinfo() above. */ static const char *resolv_host(int family, const char *host, dlist * addr_list) { struct hostent *hp; const char *errmsg; P(ip_mutex); /* gethostbyname() is not thread safe */ #ifdef HAVE_GETHOSTBYNAME2 if ((hp = gethostbyname2(host, family)) == NULL) { #else if ((hp = gethostbyname(host)) == NULL) { #endif /* may be the strerror give not the right result -:( */ errmsg = gethost_strerror(); V(ip_mutex); return errmsg; } else { char **p; for (p = hp->h_addr_list; *p != 0; p++) { IPADDR *addr = New(IPADDR(hp->h_addrtype)); addr->set_type(IPADDR::R_MULTIPLE); if (addr->get_family() == AF_INET) { addr->set_addr4((struct in_addr*)*p); addr_list->append(addr); } #ifdef HAVE_IPV6 else if (addr->get_family() == AF_INET6) { addr->set_addr6((struct in6_addr*)*p); addr_list->append(addr); } #endif } V(ip_mutex); } return NULL; } #endif static IPADDR *add_any(int family) { IPADDR *addr = New(IPADDR(family)); addr->set_type(IPADDR::R_MULTIPLE); addr->set_addr_any(); return addr; }