天天看點

判斷兩個CIDR是否有IP沖突

1.校驗網段是否合法

1.1函數

import (
    "fmt"
    "net"
)
func IsNetWorkOk(network string ) bool{
    _, _, err := net.ParseCIDR(network)
    if err != nil {
        return false
    }
    return true
}      
判斷兩個CIDR是否有IP沖突

1.2分析

第一步就是先split變成ip跟子網路遮罩

主要原理就是變成二進制以後再進行判斷

ipv4跟ipv6都可以校驗,如果隻想校驗ipv4可以調用parseIPv4方法

1.3主函數運作測試

func main() {
    ip := "100.4.11.3/24"
    result := IsNetWorkOk(ip)
    fmt.Println(result)
}      

2.校驗ip是否合法

2.1函數

func IsIpOk(ip string ) bool{
    address := net.ParseIP(ip)
    if address == nil {
        return false
    }
    return true
}      

2.2分析

判斷兩個CIDR是否有IP沖突

點分十進制換成2進制,判斷是否合法

判斷兩個CIDR是否有IP沖突

2.3主函數運作測試

func main() {
    ip := "100.4.11.34"
    result := IsIpOk(ip)
    fmt.Println(result)
}      

3.判斷兩個網段,一個是否是另一個的子網

3.1函數

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

//最好提前做好網段是否合法校驗
func ContainsCIDRString(a,b string)(bool,error){
    _, net1, err := net.ParseCIDR(a)
    if err != nil {
        return false,err
    }
    _, net2, err := net.ParseCIDR(b)
    if err != nil {
        return false,err
    }
    result := ContainsCIDR(net1,net2)
    return result,err
}      

3.2分析

判斷兩個CIDR是否有IP沖突

調用了ip包含的方法

3.3運作測試

func main() {
    net1 := "100.64.0.0/16"
    net2 := "100.64.0.0/20"
    _, a, err := net.ParseCIDR(net1)
    _, b, err := net.ParseCIDR(net2)
    if err != nil {
        return
    }
    result := ContainsCIDR(a,b)
    fmt.Println(result)
}      

4.判斷兩個網段是否沖突

4.1函數

package main

import (
    "fmt"
    "strconv"
    "strings"
)

func main() {
    s1:="192.168.0.0/24"
    s2:="192.168.15.0/20"
    b:=IsCIDROverlay(s1,s2)
    fmt.Println(b)
}
//判斷CIDR是否相交
//true代表相交
func IsCIDROverlay(s1, s2 string) bool {
    minIp1, maxIp1 := getCidrIpRange(s1)
    minIp2, maxIp2 := getCidrIpRange(s2)
    if compareIp(maxIp1, minIp2) == -1 ||
        compareIp(minIp1, maxIp2) == 1 {
        return false
    }
    return true
}

//傳回1代表大于s1>s2,
//傳回-1代表大于s1<s2,
//傳回0代表大于s1=s2,
func compareIp(s1, s2 string) int {
    ip1 := strings.Split(s1, ".")
    ip2 := strings.Split(s2, ".")
    for i := 0; i < 4; i++ {
        ipInt1, _ := strconv.Atoi(ip1[i])
        ipInt2, _ := strconv.Atoi(ip2[i])
        if ipInt1 < ipInt2 {
            return -1
        } else if ipInt1 > ipInt2 {
            return 1
        }
    }
    return 0
}

func getCidrIpRange(cidr string) (string, string) {
    ip := strings.Split(cidr, "/")[0]
    ipSegs := strings.Split(ip, ".")
    maskLen, _ := strconv.Atoi(strings.Split(cidr, "/")[1])
    seg1MinIp, seg1MaxIp := getIpSeg1Range(ipSegs, maskLen)
    seg2MinIp, seg2MaxIp := getIpSeg2Range(ipSegs, maskLen)
    seg3MinIp, seg3MaxIp := getIpSeg3Range(ipSegs, maskLen)
    seg4MinIp, seg4MaxIp := getIpSeg4Range(ipSegs, maskLen)
    return strconv.Itoa(seg1MinIp) + "." + strconv.Itoa(seg2MinIp)+ "." + strconv.Itoa(seg3MinIp) + "." + strconv.Itoa(seg4MinIp),
        strconv.Itoa(seg1MaxIp) + "." + strconv.Itoa(seg2MaxIp)+ "." + strconv.Itoa(seg3MaxIp) + "." + strconv.Itoa(seg4MaxIp)
}

//計算得到CIDR位址範圍内可擁有的主機數量
func getCidrHostNum(maskLen int) uint {
    cidrIpNum := uint(0)
    var i uint = uint(32 - maskLen - 1)
    for ; i >= 1; i-- {
        cidrIpNum += 1 << i
    }
    return cidrIpNum
}

//擷取Cidr的掩碼
func getCidrIpMask(maskLen int) string {
    // ^uint32(0)二進制為32個比特1,通過向左位移,得到CIDR掩碼的二進制
    cidrMask := ^uint32(0) << uint(32-maskLen)
    fmt.Println(fmt.Sprintf("%b \n", cidrMask))
    //計算CIDR掩碼的四個片段,将想要得到的片段移動到記憶體最低8位後,将其強轉為8位整型,進而得到
    cidrMaskSeg1 := uint8(cidrMask >> 24)
    cidrMaskSeg2 := uint8(cidrMask >> 16)
    cidrMaskSeg3 := uint8(cidrMask >> 8)
    cidrMaskSeg4 := uint8(cidrMask & uint32(255))

    return fmt.Sprint(cidrMaskSeg1) + "." + fmt.Sprint(cidrMaskSeg2) + "." + fmt.Sprint(cidrMaskSeg3) + "." + fmt.Sprint(cidrMaskSeg4)
}



func getIpSeg1Range(ipSegs []string, maskLen int) (int, int) {
    if maskLen > 8 {
        segIp, _ := strconv.Atoi(ipSegs[0])
        return segIp, segIp
    }
    ipSeg, _ := strconv.Atoi(ipSegs[0])
    return getIpSegRange(uint8(ipSeg), uint8(8-maskLen))
}

func getIpSeg2Range(ipSegs []string, maskLen int) (int, int) {
    if maskLen > 16 {
        segIp, _ := strconv.Atoi(ipSegs[1])
        return segIp, segIp
    }
    ipSeg, _ := strconv.Atoi(ipSegs[1])
    return getIpSegRange(uint8(ipSeg), uint8(16-maskLen))
}


//得到第三段IP的區間(第一片段.第二片段.第三片段.第四片段)
func getIpSeg3Range(ipSegs []string, maskLen int) (int, int) {
    if maskLen > 24 {
        segIp, _ := strconv.Atoi(ipSegs[2])
        return segIp, segIp
    }
    ipSeg, _ := strconv.Atoi(ipSegs[2])
    return getIpSegRange(uint8(ipSeg), uint8(24-maskLen))
}

//得到第四段IP的區間(第一片段.第二片段.第三片段.第四片段)
func getIpSeg4Range(ipSegs []string, maskLen int) (int, int) {
    ipSeg, _ := strconv.Atoi(ipSegs[3])
    segMinIp, segMaxIp := getIpSegRange(uint8(ipSeg), uint8(32-maskLen))
    return segMinIp + 1, segMaxIp
}
//根據使用者輸入的基礎IP位址和CIDR掩碼計算一個IP片段的區間
//或是加法 ^是異或
func getIpSegRange(userSegIp, offset uint8) (int, int) {
    var ipSegMax uint8 = 255
    netSegIp := ipSegMax << offset
    segMinIp := netSegIp & userSegIp
    segMaxIp := segMinIp | ^(ipSegMax << offset)
    return int(segMinIp), int(segMaxIp)
}      

4.2分析

判斷兩個CIDR是否有IP沖突
判斷兩個CIDR是否有IP沖突

A網段最小值大于B網段最大值,或者A網段最大值小于B網段最小值代表兩個網段沒有重疊部分

4.3運作測試

func main() {
    s1:="192.168.14.0/20"
    s2:="192.168.15.0/20"
    b:=IsCIDROverlay(s1,s2)
    fmt.Println(b)
}