Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IPv6 parsing in C

Tags:

c

parsing

ipv6

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 converted to its 128 bit equivalent binary. The problem is the IP address could be of the type ::2 and its variant since they are valid IPv6 address.

The input is from the keyboard and hence is in ASCII format.

like image 654
The Stig Avatar asked Jun 03 '10 00:06

The Stig


People also ask

Is IPv6 32 or 64 bit?

An Ipv6 address uses 128 bits as opposed to 32 bits in IPv4.

Does IPv6 use binary or hexadecimal?

Hexadecimal (the Base16 numbering system), rather than decimal (the Base10 numbering system), is used for IPv6 because it is easier to convert between hexadecimal and binary than it is to convert between decimal and binary. Each hexadecimal digit represents four binary digits.

Does IPv6 use hexadecimal?

In contrast, IPv6 addresses are 128 bits divided along 16-bit boundaries. Each 16-bit block is converted to a 4-digit hexadecimal number and separated by colons. The resulting representation is called colon-hexadecimal.


6 Answers

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?
}
like image 127
dreamlax Avatar answered Sep 30 '22 14:09

dreamlax


getaddrinfo() can understand IPv6 addresses. Pass AF_INET6 to it in the hints, as well as AI_NUMERICHOST (to prevent a DNS lookup). Linux has it, Windows has it as of Windows XP.

like image 32
Thanatos Avatar answered Sep 30 '22 15:09

Thanatos


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
}
like image 37
Ales Teska Avatar answered Sep 30 '22 15:09

Ales Teska


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)
like image 28
YeenFei Avatar answered Sep 30 '22 15:09

YeenFei


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

like image 37
Ken Bloom Avatar answered Sep 30 '22 16:09

Ken Bloom


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

like image 30
Fernando Gonzalez Sanchez Avatar answered Sep 30 '22 15:09

Fernando Gonzalez Sanchez