I am learning the C interface to protocol-independent sockets, and I'm very confused. For example I keep reading in tutorials to not use sockaddr_in and sockaddr_in6 (since these are protocol-dependent structures), but I *need* to use them in order to use getaddrinfo(). So to start out: below is a function for a host name lookup. Is there any practical way to do this without using the nasty switch statements and the protocol-dependent structures?
Code:
vector<string> DnsLookup(const string& hostString, const int& IPproto=PROTO_UNDEF) // Perform a DNS lookup
{
struct addrinfo *res /* host information */, *p /* pointer to host information for iterating */;
struct addrinfo hints;
vector<string> ip_addrs; // list of IP addresses to be returned
// Set data in the hints struct
memset(&hints, 0, sizeof(hints));
// Set the protocol in the hints struct
hints.ai_socktype = SOCK_STREAM;
switch (IPproto)
{
case PROTO_UNDEF:
hints.ai_family = AF_UNSPEC;
break;
case IPV4:
hints.ai_family = AF_INET;
break;
case IPV6:
hints.ai_family = AF_INET6;
break;
}
// Perform the lookup
int lookup;
if ((lookup = getaddrinfo(hostString.c_str(), NULL, &hints, &res)) != 0)
{
throw SockErr::SocketError(SockErr::BAD_RESOLV);
}
// Get all the resulting addresses, convert them to a std::string, and add them to the list of addresses
for (p = res; p != NULL; p = p->ai_next)
{
char *ipver, ip_addr_buff[INET6_ADDRSTRLEN];
void *addr;
if (p->ai_family == AF_INET)
{ //IPv4
struct sockaddr_in *ipv4 = reinterpret_cast<struct sockaddr_in*>(p->ai_addr);
addr = &(ipv4->sin_addr);
ipver = "IPv4";
}
else
{ //IPv6
struct sockaddr_in6 *ipv6 = reinterpret_cast<struct sockaddr_in6*>(p->ai_addr);
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
inet_ntop(p->ai_family, addr, ip_addr_buff, sizeof(ip_addr_buff));
ip_addrs.push_back(static_cast<string>(ip_addr_buff));
}
freeaddrinfo(res);
return ip_addrs;
}