Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tell whether a text string is an IPv6 address or IPv4 address using standard C sockets API

I have a program where an external component passes me a string which contains an IP address. I then need to turn it into a URI. For IPv4 this is easy; I prepend http:// and append /. However, for IPv6 I need to also surround it in brackets [].

Is there a standard sockets API call to determine the address family of the address?

like image 497
Nathan Avatar asked Sep 17 '10 14:09

Nathan


People also ask

How do you check IP address is IPv4 or IPv6 in C?

Given a string S consisting of N characters, the task is to check if the given string S is IPv4 or IPv6 or Invalid. If the given string S is a valid IPv4, then print “IPv4”, if the string S is a valid IPv6, then print “IPv4”. Otherwise, print “-1”. A valid IPv4 address is an IP in the form “x1.

How do I know if a packet is IPv4 or IPv6?

One of the differences between IPv4 and IPv6 is the appearance of the IP addresses. IPv4 uses four 1 byte decimal numbers, separated by a dot (i.e. 192.168. 1.1), while IPv6 uses hexadecimal numbers that are separated by colons (i.e. fe80::d4a8:6435:d2d8:d9f3b11).


2 Answers

Kind of. You could use inet_pton() to try parsing the string first as an IPv4 (AF_INET) then IPv6 (AF_INET6). The return code will let you know if the function succeeded, and the string thus contains an address of the attempted type.

For example:

#include <arpa/inet.h>
#include <stdio.h>

static int
ip_version(const char *src) {
    char buf[16];
    if (inet_pton(AF_INET, src, buf)) {
        return 4;
    } else if (inet_pton(AF_INET6, src, buf)) {
        return 6;
    }
    return -1;
}

int
main(int argc, char *argv[]) {
    for (int i = 1; i < argc; ++i) {
        printf("%s\t%d\n", argv[i], ip_version(argv[i]));
    }

    return 0;
}
like image 146
llasram Avatar answered Sep 28 '22 01:09

llasram


Use getaddrinfo() and set the hint flag AI_NUMERICHOST, family to AF_UNSPEC, upon successfull return from getaddrinfo, the resulting struct addrinfo .ai_family member will be either AF_INET or AF_INET6.

EDIT, small example

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>

int main(int argc, char *argv[])
{
    struct addrinfo hint, *res = NULL;
    int ret;

    memset(&hint, '\0', sizeof hint);

    hint.ai_family = PF_UNSPEC;
    hint.ai_flags = AI_NUMERICHOST;

    ret = getaddrinfo(argv[1], NULL, &hint, &res);
    if (ret) {
        puts("Invalid address");
        puts(gai_strerror(ret));
        return 1;
    }
    if(res->ai_family == AF_INET) {
        printf("%s is an ipv4 address\n",argv[1]);
    } else if (res->ai_family == AF_INET6) {
        printf("%s is an ipv6 address\n",argv[1]);
    } else {
        printf("%s is an is unknown address format %d\n",argv[1],res->ai_family);
    }

   freeaddrinfo(res);
   return 0;
}

$ ./a.out 127.0.0.1
127.0.0.1 is an ipv4 address
$ ./a.out ff01::01
ff01::01 is an ipv6 address
like image 40
nos Avatar answered Sep 27 '22 23:09

nos