ipv6地址解析
/* ipv6 无符号整型数组转化为字符串 */
void ipv6_to_str(char *addr_str, unsigned int ipv6_addr[])
{
/* ipv6地址128位,数组ip维数默认为4 */
/* 输出格式为: A:B:C:D:E:F:G:H. */
int i;
unsigned short msw, lsw;
char *addr_str_end_ptr;
addr_str[0] = '\0';
addr_str_end_ptr = addr_str;
for (i = 0; i < 4; i++)
{
msw = ipv6_addr[i] >> 16;
lsw = ipv6_addr[i] & 0x0000ffff;
addr_str_end_ptr += sprintf(addr_str_end_ptr, "%X:%X:", msw, lsw);
}
*(addr_str_end_ptr - 1) = '\0';
}
char * string_white_space_trim(char *str)
{
/* 移除字符串中空格 */
int index;
int new_index;
int str_length;
str_length = strlen(str);
for (index = 0, new_index = 0; index < str_length; index++)
{
if (!isspace((unsigned char)str[index]))
{
str[new_index] = str[index];
new_index++;
}
}
str[new_index] = '\0';
return str;
}
int string_char_count(const char *string, char character)
{
/* 计算字符串中,给定字符的数量 */
int i;
int str_length;
int count = 0;
str_length = strlen(string);
for (i = 0; i < str_length; i++)
{
if (string[i] == character)
{
count++;
}
}
return count;
}
int ipv6_address_field_type_get(const char * field_str)
{
/* 判断ipv6地址域类型 */
int i = 0;
int length;
int type;
unsigned int ipv4_addr;
/* 通过长度判断 */
/* 16进制数字域: 1-4 */
/* "::"域:0 */
/* ipv4地址域: 7-15 */
length = strlen(field_str);
if (0 == length)
{
type = 1;
}
else if (length <= 4)
{
// 确保每个数字为16进制
for (i = 0; i < length; i++)
{
if (!isxdigit((unsigned char)field_str[i]))
{
return -1;
}
}
type = 0;
}
else if((length >= 7) && (length <= 15))
{
//确保是有效的ipv4地址
if (ipv4_to_i(field_str, &ipv4_addr))
{
type = 2;
}
else
{
type = -1;
}
}
else
{
type = -1;
}
return type;
}
int ipv6_to_i(const char *addr_str, int length, unsigned int ipv6_addr_ptr[])
{
/***************************************************************************/
/* 功能:解析ipv6地址字符串,转换为无符号整形,存入4个无符号整形的一维数组 */
/* ipv6地址 128位,prefix length: */
/* - 64 for EUI-64 addresses */
/* - 128 for non-EUI-64 addresses */
/* 输入:ipv6地址字符串,地址位数,默认为128位 */
/* 输出:返回解析成功或失败;指向4个无符号整形的一维数组的指针 */
/****************************************************************************/
char addr_str_copy[256];
int i, num_fields;
//unsigned int *ret_addr_ptr;
unsigned short int addr_field_arr[8];
int addr_index;
char *ith_field; // 指向地址当前域
int ith_field_type; // 地址域类型
char *next_field;
int double_colon_field_index = -1; // 字符串地址中"::"的位置
unsigned int ipv4_address; // ipv6地址中的ipv4部分
unsigned int msw, lsw;
int error = 0;
//复制一份,以便操作
strcpy(addr_str_copy, addr_str);
// 移除字符串中的空格字符
string_white_space_trim(addr_str_copy);
/* IPv6地址可能几种格式: */
/* 1) 2006:DB8:2A0:2F3B:34:E35:45:1 用16进制表示每个域的值(16位) */
/* 2) 2006:DB8::E34:1 , "::" 代表0,且只能出现一次 */
/* 3) 2002:9D36:1:2:0:5EFE:192.168.12.9 带有ipv4地址 */
// 计算字符串中冒号,字符串中地址域数比冒号多一个
num_fields = string_char_count(addr_str_copy, ':') + 1;
// 域最大数量为length/16 + 2
// 如 ::0:0:0:0:0:0:0:0.
if (num_fields > ((length >> 4) + 2))
{
ipv6_addr_ptr = NULL;
return 0;
}
// 初始化
ith_field = addr_str_copy;
for (i = 0, addr_index = 0; i < num_fields; i++)
{
// 获得下一个域的指针
next_field = strchr(ith_field, ':');
/* 若当前是最后一个域, next_field 是 NULL */
/* 否则,替换':'为'\0', 字符串可以结束,从而ith_field指向当前域 */
/* next_field指向下一个域头部 */
if (NULL != next_field)
{
*next_field = '\0';
++next_field;
}
// 发现这个域的类型
ith_field_type = ipv6_address_field_type_get(ith_field);
switch (ith_field_type)
{
case 0:
// 域类型为16进制表示
if (addr_index >= (length >> 4))
{
error = 1;
break;
}
// 字符串转换为16进制
addr_field_arr[addr_index] = (unsigned short)strtoul(ith_field, NULL, 16);
++addr_index;
break;
case 1:
// 域类型为 "::"
// 若出现在字符串的开头或结尾,忽略
if ((0 == i) || (i == num_fields - 1))
{
break;
}
// 若出现大于一次,错误
if (double_colon_field_index != -1)
{
error = 1;
break;
}
// 记下位置
double_colon_field_index = addr_index;
break;
case 2:
// 域类型为ipv4地址
// 确保在地址中还有两个未设置的域
if (addr_index >= 7)
{
error = 1;
break;
}
// ipv4地址解析
ipv4_to_i(ith_field, &ipv4_address);
// 存储高16位
addr_field_arr[addr_index] = (unsigned short)(ipv4_address >> 16);
// 存储低16位
addr_field_arr[addr_index + 1] = (unsigned short)(ipv4_address & 0x0000ffff);
addr_index += 2;
break;
default:
error = 1;
break;
}
if (error)
{
ipv6_addr_ptr = NULL;
return 0;
}
ith_field = next_field;
}
// 计算的域不是8,并且没有"::",错误
if ((addr_index != (length >> 4)) && (-1 == double_colon_field_index))
{
ipv6_addr_ptr = NULL;
return 0;
}
if ((addr_index != (length >> 4)) && (-1 != double_colon_field_index))
{
// 设置相应"::"对应addr_field_arr中位置为0
memmove(addr_field_arr + (double_colon_field_index + (length >> 4) - addr_index),
addr_field_arr + double_colon_field_index, (addr_index - double_colon_field_index) * 2);
memset(addr_field_arr + double_colon_field_index, 0, ((length >> 4) - addr_index) * 2);
}
for (i = 0; i < 4; i++)
{
msw = addr_field_arr[2 * i];
lsw = addr_field_arr[2 * i + 1];
(ipv6_addr_ptr)[i] = (msw << 16 | lsw);
}
return 1;
}
int main()
{
char addr[256];
unsigned int ip_v4 = 3356567252;
unsigned int ipv6[4] = {3356567252, 3356567253, 3356567254, 3356567255};
unsigned int ipv61[4] = {65538, 196612, 327686, 458760};
char *ipv6_str1 = "1:2:3:4:5:6:7:8";
char *ipv6_str2 = "1:2:3:4:5:6:7:8::";
char *ipv6_str3 = "::1:2:3:4:5:6:7:8";
char *ipv6_str4 = "1:2:3:4:5:6:192.168.1.100";
char *ipv6_str5 = "1:2::5:6:7:8";
char *ipv6_str6 = "1::3:4:5:6:7:8";
char *ipv6_str7 = "1::4:5:6:7:8";
char *ipv6_str8 = "1::8";
unsigned int ipv6_addr[4];
unsigned int ipv4_addr;
int flag;
int i;
// 192.168.1.100-----3232235876
// ipv4_to_str(addr, ip_v4);
// printf("ipv4: %s\n", addr);
ipv6_to_str(addr, ipv61);
printf("ipv6: %s\n", addr);
flag = ipv4_to_i("192.168.1.100", &ipv4_addr);
if (flag)
{
printf("ipv4_addr: %u\n", ipv4_addr);
}
flag = ipv6_to_i(ipv6_str8, 128, ipv6_addr);
if (flag)
{
for (i = 0; i < 4; i++)
{
printf("ipv6_addr: %u\n", ipv6_addr[i]);
}
}
return 0;
}