跳至主要内容

cidrsubnet 函数

cidrsubnet 计算给定 IP 网络地址前缀内的子网地址。

代码块
cidrsubnet(prefix, newbits, netnum)

prefix 必须使用 CIDR 表示法给出,如 RFC 4632 第 3.1 节 中所定义。

newbits 是用于扩展前缀的额外位数。例如,如果给定一个以 /16 结尾的前缀和一个 newbits 值为 4,则生成的子网地址的长度将为 /20

netnum 是一个整数,可以用不超过 newbits 个二进制位表示的二进制整数表示,它将用于填充添加到前缀中的额外位。

此函数接受 IPv6 和 IPv4 前缀,结果始终使用与给定前缀相同的寻址方案。

与相关的函数 cidrsubnets 不同,cidrsubnet 允许您指定要使用的特定网络编号。cidrsubnets 可以一次分配多个网络地址,但会自动从零开始编号它们。

示例

代码块
> cidrsubnet("172.16.0.0/12", 4, 2)
172.18.0.0/16
> cidrsubnet("10.1.2.0/24", 4, 15)
10.1.2.240/28
> cidrsubnet("fd00:fd12:3456:7890::/56", 16, 162)
fd00:fd12:3456:7800:a200::/72

网络掩码和子网

使用 cidrsubnet 需要熟悉一些网络寻址概念。

最重要的概念是,IP 地址(无论是 IPv4 还是 IPv6)从根本上是由二进制数字构成的,即使我们通常将其表示为四个十进制八位字节(对于 IPv4)或十六进制数字序列(对于 IPv6)。

以我们上面提到的 cidrsubnet("10.1.2.0/24", 4, 15) 为例,该函数首先会将给定的 IP 地址字符串转换为等效的二进制表示形式。

代码块
      10 .        1 .        2 .        0
00001010 00000001 00000010 | 00000000
network | host

前缀字符串末尾的 /24 指定前 24 位(或前三个八位字节)标识网络,而其余位(在本例中为 32 - 24 = 8 位)标识网络中的主机。

CLI 工具 ipcalc 可用于将 CIDR 前缀可视化为二进制数。我们可以通过向 ipcalc 提供相同的 前缀字符串来确认上述转换。

代码块
$ ipcalc 10.1.2.0/24
Address: 10.1.2.0 00001010.00000001.00000010. 00000000
Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000
Wildcard: 0.0.0.255 00000000.00000000.00000000. 11111111
=>
Network: 10.1.2.0/24 00001010.00000001.00000010. 00000000
HostMin: 10.1.2.1 00001010.00000001.00000010. 00000001
HostMax: 10.1.2.254 00001010.00000001.00000010. 11111110
Broadcast: 10.1.2.255 00001010.00000001.00000010. 11111111
Hosts/Net: 254 Class A, Private Internet

这提供了一些额外的信息,但也确认了(使用略微不同的表示法)从十进制到二进制的转换,并显示了此网络中可能的主机地址范围。

虽然 cidrhost 允许计算单个主机 IP 地址,但另一方面,cidrsubnet 在给定网络前缀内部创建新的网络前缀。换句话说,它创建了一个子网。

当我们调用 cidrsubnet 时,我们还会传递两个额外的参数:newbitsnetnumnewbits 决定结果前缀在位数上将延长多少;在我们这里的示例中,我们指定了 4,这意味着结果子网的前缀长度将为 24 + 4 = 28 位。我们可以想象这些位按如下方式分解:

代码块
      10 .        1 .        2 .    ?        0
00001010 00000001 00000010 | XXXX | 0000
parent network | netnum | host

最初是“主机号”的八位中的四位现在被重新用作子网号。网络前缀不再落在精确的八位字节边界上,因此实际上我们现在将 IP 地址中的最后一个十进制数字分成两部分,使用其中的一半来表示子网号,另一半来表示主机号。

然后,netnum 参数决定将什么数值编码到这四个新的子网位中。在我们当前的示例中,我们传递了 15,它在二进制中表示为 1111,使我们能够填充上述 XXXX 段。

代码块
      10 .        1 .        2 .    15       0
00001010 00000001 00000010 | 1111 | 0000
parent network | netnum | host

要将其转换回正常的十进制表示法,我们需要重新组合最后一个八位字节的两个部分。将 11110000 从二进制转换为十进制得到 240,然后可以将其与我们新的 28 位前缀长度组合以生成结果 10.1.2.240/28。同样,我们可以将此前缀字符串传递给 ipcalc 来将其可视化。

代码块
$ ipcalc 10.1.2.240/28
Address: 10.1.2.240 00001010.00000001.00000010.1111 0000
Netmask: 255.255.255.240 = 28 11111111.11111111.11111111.1111 0000
Wildcard: 0.0.0.15 00000000.00000000.00000000.0000 1111
=>
Network: 10.1.2.240/28 00001010.00000001.00000010.1111 0000
HostMin: 10.1.2.241 00001010.00000001.00000010.1111 0001
HostMax: 10.1.2.254 00001010.00000001.00000010.1111 1110
Broadcast: 10.1.2.255 00001010.00000001.00000010.1111 1111
Hosts/Net: 14 Class A, Private Internet

新子网有四位可用于主机编号,这意味着在减去网络自己的地址和广播地址后,有 14 个主机地址可供分配。因此,您可以使用 cidrhost 函数通过向其提供 1 到 14 之间的值来计算这些主机地址。

代码块
> cidrhost("10.1.2.240/28", 1)
10.1.2.241
> cidrhost("10.1.2.240/28", 14)
10.1.2.254

有关 CIDR 表示法和子网划分的更多信息,请参阅 无类别域间路由

  • cidrhost 计算给定网络地址前缀内单个主机的 IP 地址。
  • cidrnetmask 将 CIDR 表示法中的 IPv4 网络前缀转换为网络掩码表示法。
  • cidrsubnets 可以一次在某个前缀下分配多个连续地址,并自动为其编号。