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  }