C中实现判断ipv4或ipv6地址是单播、组播、广播地址
在 C 中我们需要实现输入一个字符集(单播、组播、广播地址类型),来判断某 ipv4
或 ipv6
地址的类型是否在指定的类型集内。
为方便用户输入,类型的字符集我们定义为:
1:单播地址
2:组播地址
3:广播地址
可以输入多个类型,以英文逗号分隔,如:1,2,3
首先定义处理字符串类型匹配的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
bool pp_in_string(int target, char *data) { bool found = false; if (data == NULL) goto end;
char str[128]; strncpy(str, data, sizeof(data) - 1); str[sizeof(str) - 1] = '\0';
char *token = strtok(str, ","); while (token != NULL) { if (atoi(token) == target) { found = true; break; } token = strtok(NULL, ","); }
end: return found; }
|
定义地址类型判断方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
bool address_check_range_type(int family, unsigned int *ip, char *range_type) { if (range_type[0] == '\0') { return true; }
int result = 1;
if (family == AF_INET) { if (ntohl(ip[0]) == 0xFFFFFFFF) { result = 3; } else if ((ntohl(ip[0]) & 0xF0000000) == ((uint32_t)(0xE0 << 24))) { result = 2; } } else if (family == AF_INET6) { struct in6_addr *addr_v6 = (struct in6_addr *)ip; if (addr_v6->s6_addr[0] == 0xFF) { result = 2; if (pp_in_string(3, range_type)) { result = 3; } } }
return pp_in_string(result, range_type); }
|
上面的在 ipv6
格式下比较,需要转换一下再去判断。
ipv6
的地址结构体为:
1 2 3 4 5 6 7
| struct in6_addr { union { uint8_t s6_addr[16]; uint16_t s6_addr16[8]; uint32_t s6_addr32[4]; } __u6_addr; }
|
所以我们需要使用 in6_addr
结构体中的 s6_addr
去判断,正好是 128
位的 ipv6
地址表示值,而且分了 16
个数组,所以每组即 8
位,正使满足我们比较前 8
位需要全是 1
的条件。而如果我们使用的 s6_addr32
,那么每组是 32
位,共 4
组,不能满足判断前 8
位的条件。
ipv6
的地址数据格式为:AA22:BB11:1122:CDED:1234:AA99:7654:7410
致力于网站建设与Web开发。喜欢新事物,关注前后端动态,对新的技术有追求, 做一个优秀的web全栈工程师。