我正在编写一个程序,我需要在其中迭代从用户给定的 cidr(例如 75.24.64.0/24 )派生的地址列表。我查看了一些 code ,但这似乎过于复杂。最后我决定使用一个看起来像这样的结构:struct ip_iterator { unsigned int netmask; int bitcount; long long num_total; long long num_left; int current_ip[4];};然后我可以定义 ip_iterator_init ip_iterator_next 和 ip_iterator_is_finished 函数。但是,我被困在如何从 cidr 获得第一个 IP 的问题上。不久前我学习了网络数学,但自从我获得认证以来,我一直在使用在线计算器。 最佳答案 假设你有一个字符串中的 CIDR,这样的事情可能会为你做。首先,一个将 CIDR 转换为 IP 和掩码的函数:int cidr_to_ip_and_mask(const char *cidr, uint32_t *ip, uint32_t *mask){ uint8_t a, b, c, d, bits; if (sscanf(cidr, "%hhu.%hhu.%hhu.%hhu/%hhu", a, b, c, d, bits) < 5) { return -1; /* didn't convert enough of CIDR */ } if (bits > 32) { return -1; /* Invalid bit count */ } *ip = (a << 24UL) | (b << 16UL) | (c << 8UL) | (d); *mask = (0xFFFFFFFFUL << (32 - bits)) & 0xFFFFFFFFUL;}接下来,获取第一个 IP 的片段:uint32_t ip;uint32_t mask;uint32_t first_ip;if (cidr_to_ip_and_mask(cidr, &ip, &mask) < 0) { /* return some failure */}first_ip = ip & mask;首先,我假设 C99 或 stdint.h 可用的环境,这样我就可以使用显式位宽数据类型(最大可移植性,因为您没有指定架构)。我还假设 IPv4,因为那是您的示例字符串。接下来我使用 sscanf 将字符串转换为地址的组成部分。将字节组合成完整的 32 位值应该很简单。我将我的文字标记为 unsigned long 以确保结果在分配之前不会被截断,如果我们在一个小位宽机器上。用于设置 mask 的表达式背后的想法是 CIDR 中的位计数指定了表示网络的最高有效位的数量,因此如果我们从 32 中减去它,那就是我们需要上移一组完整位以获得该掩码的数量(截断后)。例如,掩码 32 将是所有位,而 32-32 = 0 所以我们根本不会移位,给出所有 32 位。比特数为 24(如您的示例)将给出 32-24=8,并且 0xFFFFFFFF 最后,为了获得初始 IP,我只需使用按位 AND 将掩码应用于 IP 地址。简单的!由于您的标题问题讨论了整个列表,您可以通过将掩码的补码与基数进行 ORing 来获得最终地址:uint32_t finalIP = first_ip | ~mask;这也应该等于广播地址。然后,您可以按顺序从 firstIP 迭代到 finalIP,包括或排除 finalIP 取决于您是否需要广播地址(如果您需要网络地址,则包括或排除 firstIP)。关于C CIDR 到地址列表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28532688/
10-11 02:05