标准/安全的方法来检查IP地址是否在范围/子网中

Clo*_*oud 1 c sockets ip-address netmask subnet

我有一小段代码将32位无符号整数(即:)uint32_t转换为一组四个8位字段,将其视为IP地址,然后向客户端报告它是否在预定的范围内IP地址.

我已经在C中找到了几个不同的代码示例,它们向我展示了如何从struct sockaddr_in包含它的客户端获取IP地址以及C#答案.但是,我想进一步细分地址,保持纯C,并想知道一些简单的事情:

  1. 内部表示在系统之间是否一致,或者我是否需要在s_addr现场进行Endian-ness检查/更正?
  2. 是否有标准宏沿的线CLASS_C_NETMASK,CLASS_B_NETMASK等等,这将是比使用人工生成的掩模更合适的(即:0xFF000000,0x00FF0000,等等).
  3. 套接字库中是否存在任何现有函数,如果IP地址在IP地址范围内或与子网掩码匹配,它们将进行检查?

谢谢.

Rem*_*eau 10

内部表示在系统之间是否一致,或者我是否需要对s_addr字段进行Endian-ness检查/更正?

s_addr 在所有平台上始终处于网络(大端)字节顺序.

是否存在CLASS_C_NETMASK,CLASS_B_NETMASK等行的标准宏,这比使用手动生成的掩码(即:0xFF000000,0x00FF0000等)更合适.

不,使用这样的宏也没有意义,因为子网掩码不是从一个网络固定到另一个网络.您需要为代码提供实际的网络IP及其子网掩码(提示用户,查询操作系统等).然后,您可以计算子网的起始IP和结束IP,以与目标IP进行比较:

uint32_t ip = ...; // value to check
uint32_t netip = ...; // network ip to compare with
uint32_t netmask = ...; // network ip subnet mask
uint32_t netstart = (netip & netmask); // first ip in subnet
uint32_t netend = (netstart | ~netmask); // last ip in subnet
if ((ip >= netstart) && (ip <= netend))
    // is in subnet range...
else
    // not in subnet range...
Run Code Online (Sandbox Code Playgroud)

或者更简单,使用子网掩码屏蔽网络IP和目标IP,并查看结果值是否相同(即,它们是否是同一子网):

uint32_t ip = ...; // value to check
uint32_t netip = ...; // network ip to compare with
uint32_t netmask = ...; // network ip subnet mask
if ((netip & netmask) == (ip & netmask))
    // is on same subnet...
else
    // not on same subnet...
Run Code Online (Sandbox Code Playgroud)

套接字库中是否存在任何现有函数,如果IP地址在IP地址范围内或与子网掩码匹配,它们将进行检查?

不.但是手动实现是微不足道的,它只需要几行代码,如上所示.

  • 非常有用的解决方案,谢谢 我可能会建议从netend中减去1来获取子网上的最后一个地址. (2认同)
  • 子网上的最后一个地址是子网的广播IP.使用子网掩码屏蔽网络IP会产生广播IP,这在技术上仍然是子网的一部分.如果您不想在比较中允许广播IP,您可以从`netend`中减去1,或者您可以将`<= netend`改为`<netend`,或者您可以使用反向屏蔽目标IP.子网掩码并查看结果是否与掩码相同(如果是,则目标是广播IP). (2认同)