go.ligato.io/vpp-agent/v3@v3.5.0/plugins/netalloc/utils/netalloc_utils.go (about) 1 package utils 2 3 import ( 4 "fmt" 5 "net" 6 "strings" 7 8 "go.ligato.io/vpp-agent/v3/proto/ligato/netalloc" 9 ) 10 11 // ParseIPAddr parses IP address from string. 12 func ParseIPAddr(addr string, expNet *net.IPNet) (ipNet *net.IPNet, fromExpNet bool, err error) { 13 if expNet != nil { 14 expNet = &net.IPNet{IP: expNet.IP.Mask(expNet.Mask), Mask: expNet.Mask} 15 } 16 17 if strings.Contains(addr, "/") { 18 // IP with mask 19 ip, ipNet, err := net.ParseCIDR(addr) 20 if err != nil { 21 return nil, false, err 22 } 23 if ip.To4() != nil { 24 ip = ip.To4() 25 } 26 ipNet.IP = ip 27 if expNet != nil { 28 fromExpNet = expNet.Contains(ip) 29 } 30 return ipNet, fromExpNet, nil 31 } 32 33 // IP without mask 34 ip := net.ParseIP(addr) 35 if ip == nil { 36 return nil, false, fmt.Errorf("invalid IP address: %s", addr) 37 } 38 if ip.To4() != nil { 39 ip = ip.To4() 40 } 41 if expNet != nil { 42 if expNet.Contains(ip) { 43 // IP address from the expected network 44 return &net.IPNet{IP: ip, Mask: expNet.Mask}, true, nil 45 } 46 } 47 48 // use all-ones mask 49 defaultIpv4Mask := net.CIDRMask(32, 32) 50 defaultIpv6Mask := net.CIDRMask(128, 128) 51 52 if ip.To4() != nil { 53 // IPv4 address 54 return &net.IPNet{IP: ip.To4(), Mask: defaultIpv4Mask}, false, nil 55 } 56 57 // IPv6 address 58 return &net.IPNet{IP: ip, Mask: defaultIpv6Mask}, false, nil 59 } 60 61 // ParseAddrAllocRef parses reference to allocated address. 62 func ParseAddrAllocRef(addrAllocRef, expIface string) ( 63 network, iface string, isGW, isRef bool, err error) { 64 65 if !strings.HasPrefix(addrAllocRef, netalloc.AllocRefPrefix) { 66 isRef = false 67 return 68 } 69 70 isRef = true 71 addrAllocRef = strings.TrimPrefix(addrAllocRef, netalloc.AllocRefPrefix) 72 if strings.HasSuffix(addrAllocRef, netalloc.AllocRefGWSuffix) { 73 addrAllocRef = strings.TrimSuffix(addrAllocRef, netalloc.AllocRefGWSuffix) 74 isGW = true 75 } 76 77 // parse network name 78 parts := strings.SplitN(addrAllocRef, "/", 2) 79 network = parts[0] 80 if network == "" { 81 err = fmt.Errorf("address allocation reference with empty network name: %s", 82 addrAllocRef) 83 return 84 } 85 86 // parse interface name 87 if len(parts) == 2 { 88 iface = parts[1] 89 if expIface != "" && iface != expIface { 90 err = fmt.Errorf("expected different interface name in the address allocation "+ 91 "reference: %s (expected=%s vs. actual=%s)", addrAllocRef, expIface, iface) 92 return 93 } 94 } else { 95 if expIface == "" { 96 err = fmt.Errorf("missing interface name in the address allocation reference: %s", 97 addrAllocRef) 98 return 99 } else { 100 iface = expIface 101 } 102 } 103 return 104 } 105 106 // GetIPAddrInGivenForm returns IP address in the requested form. 107 func GetIPAddrInGivenForm(addr *net.IPNet, form netalloc.IPAddressForm) *net.IPNet { 108 switch form { 109 case netalloc.IPAddressForm_UNDEFINED_FORM: 110 return addr 111 case netalloc.IPAddressForm_ADDR_ONLY: 112 zeroMaskIpv4 := net.CIDRMask(0, 32) 113 zeroMaskIpv6 := net.CIDRMask(0, 128) 114 if addr.IP.To4() != nil { 115 return &net.IPNet{IP: addr.IP, Mask: zeroMaskIpv4} 116 } 117 return &net.IPNet{IP: addr.IP, Mask: zeroMaskIpv6} 118 case netalloc.IPAddressForm_ADDR_WITH_MASK: 119 return addr 120 case netalloc.IPAddressForm_ADDR_NET: 121 return &net.IPNet{IP: addr.IP.Mask(addr.Mask), Mask: addr.Mask} 122 case netalloc.IPAddressForm_SINGLE_ADDR_NET: 123 allOnesIpv4 := net.CIDRMask(32, 32) 124 allOnesIpv6 := net.CIDRMask(128, 128) 125 if addr.IP.To4() != nil { 126 return &net.IPNet{IP: addr.IP, Mask: allOnesIpv4} 127 } 128 return &net.IPNet{IP: addr.IP, Mask: allOnesIpv6} 129 } 130 return addr 131 }