87 lines
1.7 KiB
Go
87 lines
1.7 KiB
Go
|
|
package network
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"net"
|
||
|
|
)
|
||
|
|
|
||
|
|
type SubnetOverlap struct {
|
||
|
|
Interface string `json:"interface"`
|
||
|
|
Subnet string `json:"subnet"`
|
||
|
|
Label string `json:"label,omitempty"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func parseIPNet(ipStr, maskStr string) (*net.IPNet, error) {
|
||
|
|
ip := net.ParseIP(ipStr)
|
||
|
|
if ip == nil {
|
||
|
|
return nil, fmt.Errorf("invalid IP: %s", ipStr)
|
||
|
|
}
|
||
|
|
ip = ip.To4()
|
||
|
|
if ip == nil {
|
||
|
|
return nil, fmt.Errorf("invalid IPv4: %s", ipStr)
|
||
|
|
}
|
||
|
|
|
||
|
|
mask := ipMaskFromString(maskStr)
|
||
|
|
if mask == nil {
|
||
|
|
return nil, fmt.Errorf("invalid netmask: %s", maskStr)
|
||
|
|
}
|
||
|
|
|
||
|
|
return &net.IPNet{IP: ip.Mask(mask), Mask: mask}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func ipMaskFromString(maskStr string) net.IPMask {
|
||
|
|
m := net.ParseIP(maskStr)
|
||
|
|
if m != nil {
|
||
|
|
if m4 := m.To4(); m4 != nil {
|
||
|
|
return net.IPMask(m4)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func subnetsOverlap(a, b *net.IPNet) bool {
|
||
|
|
return a.Contains(b.IP) || b.Contains(a.IP)
|
||
|
|
}
|
||
|
|
|
||
|
|
func CheckOverlap(newIP, newMask, excludeIface string, existing []SubnetOverlap) []SubnetOverlap {
|
||
|
|
newNet, err := parseIPNet(newIP, newMask)
|
||
|
|
if err != nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
var result []SubnetOverlap
|
||
|
|
for _, s := range existing {
|
||
|
|
if s.Interface == excludeIface {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
parts, err := parseSubnetStr(s.Subnet)
|
||
|
|
if err != nil {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
existingNet, err := parseIPNet(parts[0], parts[1])
|
||
|
|
if err != nil {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if subnetsOverlap(newNet, existingNet) {
|
||
|
|
result = append(result, s)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
func ParseSubnet(ipStr, maskStr string) (string, error) {
|
||
|
|
n, err := parseIPNet(ipStr, maskStr)
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
return n.String(), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func parseSubnetStr(s string) ([2]string, error) {
|
||
|
|
for i := len(s) - 1; i >= 0; i-- {
|
||
|
|
if s[i] == '/' {
|
||
|
|
return [2]string{s[:i], s[i+1:]}, nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return [2]string{}, fmt.Errorf("invalid subnet format: %s", s)
|
||
|
|
}
|