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; }