dov11020
2016-01-11 19:08
浏览 161
已采纳

如何检测两个Golang net.IPNet对象是否相交?

How to detect if there is intersection between two Golang net.IPNet objects?

That is, how to check both if the first network is subnet of the second one OR if the second network is subnet of the first one.

Does Go provide any utility function ready for this specific task?

See test code below.

package main

import (
    "fmt"
    "net"
)

func main() {
    _, net1, _ := net.ParseCIDR("1.1.1.1/24")
    _, net2, _ := net.ParseCIDR("1.1.0.2/16")
    _, net3, _ := net.ParseCIDR("1.1.1.3/25")
    _, net4, _ := net.ParseCIDR("1.2.0.4/16")

    test(net1, net2, true)
    test(net2, net1, true)
    test(net1, net3, true)
    test(net3, net1, true)
    test(net1, net4, false)
    test(net4, net1, false)
}

func test(n1, n2 *net.IPNet, expect bool) {
    result := intersect(n1, n2)
    var label string
    if result == expect {
        label = "good"
    } else {
        label = "FAIL"
    }
    fmt.Printf("test intersect(%v,%v)=%v expected=%v => %s
", n1, n2, result, expect, label)
}

func intersect(n1, n2 *net.IPNet) bool {
    return false // FIXME WRITEME
}

Run it on Go Playground

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • doufu1504 2016-01-11 19:53
    已采纳

    If (as your test cases seem to imply) you don't care about which side contains which, but just that there's overlap, this should be sufficient.

    func intersect(n1, n2 *net.IPNet) bool {
        return n2.Contains(n1.IP) || n1.Contains(n2.IP)
    }
    
    已采纳该答案
    打赏 评论
  • doutuo1908 2016-01-11 19:58

    You can use the fact that IP addresses (net.IP) and netmasks (net.IPMask) are simply byte slices ([]byte) that contain the binary IP addresses. You can use the usual bitwise-operators on the network addresses and their masks to determine if one network is a subnet of another:

    func intersect(n1, n2 *net.IPNet) bool {
        for i := range n1.IP {
            if n1.IP[i] & n1.Mask[i] != n2.IP[i] & n2.Mask[i] & n1.Mask[i] {
                return false
            }
        }
        return true
    }
    

    This function is missing some basic sanity checks (for example, it would break when passed one IPv4 and one IPv6 address), but the example should be sufficient to get the gist of it.

    It succeeds in all test cases from your question, except the first one. But after all, 1.1.0.2/16 is not really a subnet of 1.1.1.1/24 (it's the other way around).

    https://play.golang.org/p/Kur5n2hfLg

    打赏 评论

相关推荐 更多相似问题