C Protocol-Independent Sockets

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Xx r3negade
    New Member
    • Apr 2008
    • 39

    C Protocol-Independent Sockets

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