【Linux】Linux C判断两个IPv6地址是否有包含关系
功能说明
要判断两个 IPv6 地址是否具有包含关系,包括前缀的比较,可以通过以下步骤实现:
- 解析 IPv6 地址和前缀:将两个 IPv6 地址和它们的前缀长度解析为二进制形式。
- 生成掩码:根据前缀长度生成掩码。
- 按位比较:使用掩码对两个 IPv6 地址进行按位与操作,判断它们是否匹配。
代码实现
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
// 判断两个 IPv6 地址是否具有包含关系(包括前缀)
int is_ipv6_prefix_contained(const char *ip1_str, int prefix1_len, const char *ip2_str, int prefix2_len)
{
struct in6_addr ip1, ip2;
unsigned char mask[16] = {0};
int common_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
// 将字符串形式的 IPv6 地址转换为 in6_addr 结构
if (inet_pton(AF_INET6, ip1_str, &ip1) != 1)
{
fprintf(stderr, "Invalid IPv6 address: %s\n", ip1_str);
return -1;
}
if (inet_pton(AF_INET6, ip2_str, &ip2) != 1)
{
fprintf(stderr, "Invalid IPv6 address: %s\n", ip2_str);
return -1;
}
// 生成掩码,使用较短的公共前缀长度
for (int i = 0; i < common_prefix_len / 8; i++)
{
mask[i] = 0xFF; // 每个完整字节设置为 0xFF
}
if (common_prefix_len % 8 != 0)
{
mask[common_prefix_len / 8] = (0xFF << (8 - (common_prefix_len % 8))) & 0xFF; // 部分字节掩码
}
// 比较地址和前缀
for (int i = 0; i < 16; i++)
{
if ((ip1.s6_addr[i] & mask[i]) != (ip2.s6_addr[i] & mask[i]))
{
return 0; // 不包含
}
}
return 1; // 包含
}
int main()
{
const char *ip1 = "2001:db8::1";
int prefix1_len = 32;
const char *ip2 = "2001:db8::";
int prefix2_len = 48;
int result = is_ipv6_prefix_contained(ip1, prefix1_len, ip2, prefix2_len);
if (result == 1)
{
printf("IPv6 address %s/%d is contained within %s/%d\n", ip1, prefix1_len, ip2, prefix2_len);
}
else if (result == 0)
{
printf("IPv6 address %s/%d is NOT contained within %s/%d\n", ip1, prefix1_len, ip2, prefix2_len);
}
else
{
printf("An error occurred.\n");
}
return 0;
}
代码说明
inet_pton
函数
- 将字符串形式的 IPv6 地址转换为
struct in6_addr
结构。 - 如果转换失败,返回值为
0
或-1
。
掩码生成
- 根据两个前缀长度的较小值生成掩码。
- 每个完整字节设置为
0xFF
,部分字节根据前缀长度生成部分掩码。
按位比较
- 使用掩码对两个 IPv6 地址进行按位与操作。
- 如果结果相同,则说明一个地址的前缀包含另一个地址。
返回值
- 返回
1
表示 IPv6 地址ip1/prefix1_len
包含或被包含于ip2/prefix2_len
。 - 返回
0
表示两者没有包含关系。 - 返回
-1
表示输入无效。
测试用例
测试 1:IPv6 地址包含关系
输入:
- IPv6 地址 1:
2001:db8::1/32
- IPv6 地址 2:
2001:db8::/48
输出:
IPv6 address 2001:db8::1/32 is contained within 2001:db8::/48
测试 2:IPv6 地址不包含关系
输入:
- IPv6 地址 1:
2001:db9::1/32
- IPv6 地址 2:
2001:db8::/48
输出:
IPv6 address 2001:db9::1/32 is NOT contained within 2001:db8::/48
测试 3:无效输入
输入:
- IPv6 地址 1:
invalid_ip/32
- IPv6 地址 2:
2001:db8::/48
输出:
Invalid IPv6 address: invalid_ip
An error occurred.