#ifndef _IPV6_H_
#define _IPV6_H_
#define HEX_BASE 16
#define IP_CIDR_DELIMITER "/"
#define IPV4_DELIMITER "."
#define IPV6_DELIMITER ":"
#define IPV6_DELIMITER_CHAR ':'
#include "split.h"
#include "utils.h"
bool is_ipv6(char *ipv6_addr);
bool is_ipv6_cidr(char *ipv6_addr_cidr);
[docs]/**
* Returns ``true`` if given string is a IPv6 otherwise ``false``.
*
* Args:
* ipv6_addr(char *): target string to be validated
*
* Returns:
* ``true`` if given address is a IPv6 address
*/
bool is_ipv6(char *ipv6_addr) {
struct split_t ipv6_groups;
struct split_t ipv4_groups;
char *ipv4_part;
int blankctr, number;
bool is_freed_ipv4;
ipv6_groups = split(ipv6_addr, IPV6_DELIMITER);
blankctr = blanks(ipv6_addr, IPV6_DELIMITER_CHAR);
if (!ipv6_groups.length || ipv6_groups.length + blankctr <= 1)
return free_split_r(&ipv6_groups, false);
ipv4_part = ipv6_groups.tokens[ipv6_groups.length - 1];
ipv4_groups = split(ipv4_part, IPV4_DELIMITER);
is_freed_ipv4 = false;
if (ipv4_groups.length > 1) {
if (!is_ipv4(ipv4_part))
return free_split_r(&ipv4_groups, free_split_r(&ipv6_groups, false));
free(ipv4_part);
ipv4_part = NULL;
ipv6_groups.length--;
} else {
free_split(&ipv4_groups);
is_freed_ipv4 = true;
}
size_t max_groups = ipv4_groups.tokens ? 6 : 8;
if (ipv6_groups.length + blankctr > max_groups) {
if (!is_freed_ipv4)
free_split(&ipv4_groups);
return free_split_r(&ipv6_groups, false);
}
for (size_t i = 0; i < ipv6_groups.length; i++) {
char *part = ipv6_groups.tokens[i];
if (!is_xdigit(part)) {
if (!is_freed_ipv4)
free_split(&ipv4_groups);
return free_split_r(&ipv6_groups, false);
}
number = (int)strtol(part, NULL, HEX_BASE);
if (!(0 <= number && number <= 65536)) {
if (!is_freed_ipv4)
free_split(&ipv4_groups);
return free_split_r(&ipv6_groups, false);
}
}
if (blankctr <= 2) {
if (!is_freed_ipv4)
free_split(&ipv4_groups);
return free_split_r(&ipv6_groups, true);
}
if (!is_freed_ipv4)
free_split(&ipv4_groups);
return free_split_r(&ipv6_groups, false);
}
[docs]/**
* Returns ``true`` if given string is a IPv6CIDR otherwise ``false``.
*
* Args:
* ipv6_addr_cidr(char *): target string to be validated
*
* Returns:
* ``true`` if given address is a IPv6CIDR
*/
bool is_ipv6_cidr(char *ipv6_addr_cidr) {
struct split_t splitted = split(ipv6_addr_cidr, IP_CIDR_DELIMITER);
if (splitted.length != 2)
return free_split_r(&splitted, false);
char *prefix = splitted.tokens[0];
char *suffix = splitted.tokens[1];
if (!is_ipv6(prefix) || !is_digit(suffix))
return free_split_r(&splitted, false);
if (!(0 <= atoi(suffix) && atoi(suffix) <= 128))
return free_split_r(&splitted, false);
return free_split_r(&splitted, true);
}
#endif