net.IPNet是否包含在其他net.IPNet中?

huangapple go评论78阅读模式
英文:

net.IPNet inside other net.IPNet?

问题

net.IPNet类型中,我们有Contains方法来检查一个net.IP是否在其中。但是我想知道的是一个net.IPNet是否在另一个net.IPNet中。我尝试了使用big.Int的解决方案,但它没有起作用(而且函数接口很糟糕)。有什么想法吗?

// ipnet2是否包含ipnet1?
func ContainsCIDR(ipnet1, ipnet2 net.IPNet) bool {
    var begin big.Int
    begin.SetBytes([]byte(ipnet1.IP))

    var mask big.Int
    mask.SetBytes([]byte(ipnet1.Mask))

    var diff big.Int
    diff.Xor(&begin, &mask)

    var end big.Int
    end.Add(&begin, &diff)

    ipBegin := net.IP(begin.Bytes())
    ipEnd := net.IP(end.Bytes())

    return ipnet2.Contains(ipBegin) && ipnet2.Contains(ipEnd)
}

以上是给出的代码,用于判断一个net.IPNet是否包含在另一个net.IPNet中。

英文:

In net.IPNet type we have the Contains method to check if a net.IP is inside it. But what I want is to know if a net.IPNet is inside another net.IPNet. I tried a solution working with big.Int but it didn't work (also, the function interface was terrible). Any ideas?

// ipnet2 contains ipnet1 ?
func ContainsCIDR(ipnet1, ipnet2 net.IPNet) bool {
	var begin big.Int
	begin.SetBytes([]byte(ipnet1.IP))

	var mask big.Int
	mask.SetBytes([]byte(ipnet1.Mask))

	var diff big.Int
	diff.Xor(&begin, &mask)

	var end big.Int
	end.Add(&begin, &diff)

	ipBegin := net.IP(begin.Bytes())
	ipEnd := net.IP(end.Bytes())

	return ipnet2.Contains(ipBegin) && ipnet2.Contains(ipEnd)
}

答案1

得分: 3

检查外部子网的掩码是否与内部子网的大小相同或更小,然后验证内部子网的起始地址是否包含在外部子网中:

func ContainsCIDR(ipnet1, ipnet2 *net.IPNet) bool {
    ones1, _ := ipnet1.Mask.Size()
    ones2, _ := ipnet2.Mask.Size()
    return ones1 <= ones2 && ipnet1.Contains(ipnet2.IP)
}

请注意,这是一个用Go语言编写的函数,用于检查两个CIDR(无类别域间路由)地址是否满足上述条件。

英文:

Check that the mask for the outer subnet is the same size or smaller than the inner, then verify that the starting address for the inner subnet is contained in the outer:

func ContainsCIDR(ipnet1, ipnet2 *net.IPNet) bool {
	ones1, _ := ipnet1.Mask.Size()
	ones2, _ := ipnet2.Mask.Size()
	return ones1 &lt;= ones2 &amp;&amp; ipnet1.Contains(ipnet2.IP)
}

答案2

得分: 0

你可以使用IPAddress Go库来完成这个任务,使用以下代码。请注意,IPAddress可以处理其他类型的子网,不仅仅是CIDR子网。相同的代码也适用于单个地址。免责声明:我是项目经理。

func testContains(containing, contained string) {
	containsIPAddress(containing, contained)
	containsNet(containing, contained)
	fmt.Println()
}

func containsIPAddress(containing, contained string) {
	containingAddr, containedAddr := ipaddr.NewIPAddressString(containing),
		ipaddr.NewIPAddressString(contained)
	fmt.Printf("ipaddress: %s contains %s %v\n", containingAddr, containedAddr,
		containingAddr.Contains(containedAddr))
}

func containsNet(containing, contained string) {
	_, ipNetContaining, err := net.ParseCIDR(containing)
	var ipNetContained *net.IPNet
	if err == nil {
		_, ipNetContained, err = net.ParseCIDR(contained)
	}
	if err != nil {
		fmt.Printf("net: %s not a CIDR subnet\n", contained)
		return
	}
	containingAddr, _ := ipaddr.NewIPAddressFromNetIPNet(ipNetContaining)
	containedAddr, _ := ipaddr.NewIPAddressFromNetIPNet(ipNetContained)
	fmt.Printf("net: %s contains %s %v\n", containingAddr, containedAddr,
		containingAddr.Contains(containedAddr))
}

运行一些测试用例:

package main

import (
	"fmt"
	"github.com/seancfoley/ipaddress-go/ipaddr"
	"net"
)

func main() {
	testContains("172.17.0.0/16", "172.17.192.0/18")
	testContains("172.17.0.0/16", "172.17.191.0/18")
	testContains("10.10.20.0/30", "10.10.20.3/32")
	testContains("10.10.20.0/30", "10.10.20.3")
	testContains("10.10.20.0/30", "10.10.20.5")
	testContains("10.10.20.0/30", "10.10.20.0/31")
	testContains("10.10.20.0/30", "10.10.20.1-3")
	testContains("1::/64", "2::/72")
	testContains("1::/64", "1::/32")
	testContains("1::/64", "1::/112")
	testContains("1::3-4:5-6", "1::4:5-6")
	testContains("1::3-4:5-6", "1::3-4:5")
	testContains("1::3-4:5-6", "1::4:5-7")
	testContains("1-2::/64", "2::/64")
	testContains("bla", "foo")
}

输出结果:

ipaddress: 172.17.0.0/16 contains 172.17.192.0/18 true
net: 172.17.0.0/16 contains 172.17.192.0/18 true

ipaddress: 172.17.0.0/16 contains 172.17.191.0/18 true
net: 172.17.0.0/16 contains 172.17.128.0/18 true

ipaddress: 10.10.20.0/30 contains 10.10.20.3/32 true
net: 10.10.20.0/30 contains 10.10.20.3/32 true

ipaddress: 10.10.20.0/30 contains 10.10.20.3 true
net: 10.10.20.3 not a CIDR subnet

ipaddress: 10.10.20.0/30 contains 10.10.20.5 false
net: 10.10.20.5 not a CIDR subnet

ipaddress: 10.10.20.0/30 contains 10.10.20.0/31 true
net: 10.10.20.0/30 contains 10.10.20.0/31 true

ipaddress: 10.10.20.0/30 contains 10.10.20.1-3 true
net: 10.10.20.1-3 not a CIDR subnet

ipaddress: 1::/64 contains 2::/72 false
net: 1::/64 contains 2::/72 false

ipaddress: 1::/64 contains 1::/32 false
net: 1::/64 contains 1::/32 false

ipaddress: 1::/64 contains 1::/112 true
net: 1::/64 contains 1::/112 true

ipaddress: 1::3-4:5-6 contains 1::4:5-6 true
net: 1::4:5-6 not a CIDR subnet

ipaddress: 1::3-4:5-6 contains 1::3-4:5 true
net: 1::3-4:5 not a CIDR subnet

ipaddress: 1::3-4:5-6 contains 1::4:5-7 false
net: 1::4:5-7 not a CIDR subnet

ipaddress: 1-2::/64 contains 2::/64 true
net: 2::/64 not a CIDR subnet

ipaddress: bla contains foo false
net: foo not a CIDR subnet
英文:

You can do this with the IPAddress Go library using the following code. Note that IPAddress works with other types of subnets, not just CIDR subnets, as shown. The same code also works with individual addresses. Disclaimer: I am the project manager.

func testContains(containing, contained string) {
	containsIPAddress(containing, contained)
	containsNet(containing, contained)
	fmt.Println()
}

func containsIPAddress(containing, contained string) {
	containingAddr, containedAddr := ipaddr.NewIPAddressString(containing),
		ipaddr.NewIPAddressString(contained)
	fmt.Printf(&quot;ipaddress: %s contains %s %v\n&quot;, containingAddr, containedAddr,
		containingAddr.Contains(containedAddr))
}

func containsNet(containing, contained string) {
	_, ipNetContaining, err := net.ParseCIDR(containing)
	var ipNetContained *net.IPNet
	if err == nil {
		_, ipNetContained, err = net.ParseCIDR(contained)
	}
	if err != nil {
		fmt.Printf(&quot;net: %s not a CIDR subnet\n&quot;, contained)
		return
	}
	containingAddr, _ := ipaddr.NewIPAddressFromNetIPNet(ipNetContaining)
	containedAddr, _ := ipaddr.NewIPAddressFromNetIPNet(ipNetContained)
	fmt.Printf(&quot;net: %s contains %s %v\n&quot;, containingAddr, containedAddr,
		containingAddr.Contains(containedAddr))
}

Running some test cases:

package main

import (
	&quot;fmt&quot;
	&quot;github.com/seancfoley/ipaddress-go/ipaddr&quot;
	&quot;net&quot;
)

func main() {
	testContains(&quot;172.17.0.0/16&quot;, &quot;172.17.192.0/18&quot;)
	testContains(&quot;172.17.0.0/16&quot;, &quot;172.17.191.0/18&quot;)
	testContains(&quot;10.10.20.0/30&quot;, &quot;10.10.20.3/32&quot;)
	testContains(&quot;10.10.20.0/30&quot;, &quot;10.10.20.3&quot;)
	testContains(&quot;10.10.20.0/30&quot;, &quot;10.10.20.5&quot;)
	testContains(&quot;10.10.20.0/30&quot;, &quot;10.10.20.0/31&quot;)
	testContains(&quot;10.10.20.0/30&quot;, &quot;10.10.20.1-3&quot;)
	testContains(&quot;1::/64&quot;, &quot;2::/72&quot;)
	testContains(&quot;1::/64&quot;, &quot;1::/32&quot;)
	testContains(&quot;1::/64&quot;, &quot;1::/112&quot;)
	testContains(&quot;1::3-4:5-6&quot;, &quot;1::4:5-6&quot;)
	testContains(&quot;1::3-4:5-6&quot;, &quot;1::3-4:5&quot;)
	testContains(&quot;1::3-4:5-6&quot;, &quot;1::4:5-7&quot;)
	testContains(&quot;1-2::/64&quot;, &quot;2::/64&quot;)
	testContains(&quot;bla&quot;, &quot;foo&quot;)
}

Output:

ipaddress: 172.17.0.0/16 contains 172.17.192.0/18 true
net: 172.17.0.0/16 contains 172.17.192.0/18 true

ipaddress: 172.17.0.0/16 contains 172.17.191.0/18 true
net: 172.17.0.0/16 contains 172.17.128.0/18 true

ipaddress: 10.10.20.0/30 contains 10.10.20.3/32 true
net: 10.10.20.0/30 contains 10.10.20.3/32 true

ipaddress: 10.10.20.0/30 contains 10.10.20.3 true
net: 10.10.20.3 not a CIDR subnet

ipaddress: 10.10.20.0/30 contains 10.10.20.5 false
net: 10.10.20.5 not a CIDR subnet

ipaddress: 10.10.20.0/30 contains 10.10.20.0/31 true
net: 10.10.20.0/30 contains 10.10.20.0/31 true

ipaddress: 10.10.20.0/30 contains 10.10.20.1-3 true
net: 10.10.20.1-3 not a CIDR subnet

ipaddress: 1::/64 contains 2::/72 false
net: 1::/64 contains 2::/72 false

ipaddress: 1::/64 contains 1::/32 false
net: 1::/64 contains 1::/32 false

ipaddress: 1::/64 contains 1::/112 true
net: 1::/64 contains 1::/112 true

ipaddress: 1::3-4:5-6 contains 1::4:5-6 true
net: 1::4:5-6 not a CIDR subnet

ipaddress: 1::3-4:5-6 contains 1::3-4:5 true
net: 1::3-4:5 not a CIDR subnet

ipaddress: 1::3-4:5-6 contains 1::4:5-7 false
net: 1::4:5-7 not a CIDR subnet

ipaddress: 1-2::/64 contains 2::/64 true
net: 2::/64 not a CIDR subnet

ipaddress: bla contains foo false
net: foo not a CIDR subnet

huangapple
  • 本文由 发表于 2016年11月4日 00:03:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/40406230.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定