IPv6 parsing in C

前端 未结 7 1103
猫巷女王i
猫巷女王i 2020-12-15 08:35

I wanted to know how I can parse an IPv6 address in C and convert it to a 128 bit value?

So a hex address like 1:22:333:aaaa:b:c:d:e needs to be convert

相关标签:
7条回答
  • 2020-12-15 08:58

    You can use getaddrinfo() POSIX function. It is more flexible than inet_pton(), for example it automatically detects IPv4 and IPv6 address formats, it can resolve even hostnames (using DNS resolving) and port/service names (using /etc/services).

    #include <sys/types.h>
    #include <netdb.h>
    #include <netdb.h>
    
    ....
    
    const char *ip6str = "::2";
    
    struct sockaddr_storage result;
    socklen_t result_len;
    
    struct addrinfo *res = NULL;
    struct addrinfo hints;
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_DEFAULT | AI_NUMERICHOST | AI_NUMERICSERV;
    
    rc = getaddrinfo(ip6str, NULL, &hints, &res);
    if (rc != 0)
    {
        fprintf(stderr, "Failure to parse host '%s': %s (%d)", ip6str, gai_strerror(rc), rc);
        return -1;
    }
    
    if (res == NULL)
    {
        // Failure to resolve 'ip6str'
        fprintf(stderr, "No host found for '%s'", ip6str);
        return -1;
    }
    
    // We use the first returned entry
    result_len = res->ai_addrlen;
    memcpy(&result, res->ai_addr, res->ai_addrlen);
    
    freeaddrinfo(res);
    

    The IPv6 address is stored in the struct sockaddr_storage result variable.

    if (result.ss_family == AF_INET6) // Ensure that we deal with IPv6
    {
        struct sockaddr_in6 * sa6 = (struct sockaddr_in6 *) &result;
        struct in6_addr * in6 = &sa6->sin6_addr;
        in6->s6_addr[0]; // This is a first byte of the IPv6
        in6->s6_addr[15]; // This is a last byte of the IPv6
    }
    
    0 讨论(0)
  • 2020-12-15 08:58

    if you can use boost, something like this should work:

    #include<boost/asio.hpp>
    
    using boost::asio::ip;
    
    bool parseIpv6String(std::string ipv6_string, char* dest){
        try{
            address_v6 addr = address_v6::from_string(ipv6_string);
            memcpy(dest,addr.to_bytes().data(), 16);
        }catch(...){
            return false;
        }
        return true;
    }
    

    It is a bit more portable than for example POSIX specific functions.

    0 讨论(0)
  • 2020-12-15 09:00

    To parse IPv6 in C, you need to build yourself a utility function, which tokenized string (colon for hex blocks, and forward-slash for subnet bits).

    1. Tokenize raw IPv6 string into smaller substring.
    2. Convert non-empty substring into hex blocks. (ASCII to decimal conversion)
    3. Expand hex block into 2-bytes by padding zero in front. (only leading zeroes get trimmed)
    4. Complete IPv6 should have 8 hex blocks, calculate missing hex-block(s). (zeroes grouping can happen only once)
    5. Reinsert missing hex-block. (use index of the empty substring)
    0 讨论(0)
  • 2020-12-15 09:03

    In Windows, you can use WSAStringToAddress, which is available since Windows 2000.

    0 讨论(0)
  • 2020-12-15 09:19

    You can use POSIX inet_pton to convert a string to a struct in6_addr.

    #include <arpa/inet.h>
    
      ...
    
    const char *ip6str = "::2";
    struct in6_addr result;
    
    if (inet_pton(AF_INET6, ip6str, &result) == 1) // success!
    {
        //successfully parsed string into "result"
    }
    else
    {
        //failed, perhaps not a valid representation of IPv6?
    }
    
    0 讨论(0)
  • 2020-12-15 09:19

    Rosetta has samples in several languages: https://rosettacode.org/wiki/Parse_an_IP_Address

    0 讨论(0)
提交回复
热议问题