github.com/slackhq/nebula@v1.9.0/iputil/util.go (about)

     1  package iputil
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"net"
     7  	"net/netip"
     8  )
     9  
    10  type VpnIp uint32
    11  
    12  const maxIPv4StringLen = len("255.255.255.255")
    13  
    14  func (ip VpnIp) String() string {
    15  	b := make([]byte, maxIPv4StringLen)
    16  
    17  	n := ubtoa(b, 0, byte(ip>>24))
    18  	b[n] = '.'
    19  	n++
    20  
    21  	n += ubtoa(b, n, byte(ip>>16&255))
    22  	b[n] = '.'
    23  	n++
    24  
    25  	n += ubtoa(b, n, byte(ip>>8&255))
    26  	b[n] = '.'
    27  	n++
    28  
    29  	n += ubtoa(b, n, byte(ip&255))
    30  	return string(b[:n])
    31  }
    32  
    33  func (ip VpnIp) MarshalJSON() ([]byte, error) {
    34  	return []byte(fmt.Sprintf("\"%s\"", ip.String())), nil
    35  }
    36  
    37  func (ip VpnIp) ToIP() net.IP {
    38  	nip := make(net.IP, 4)
    39  	binary.BigEndian.PutUint32(nip, uint32(ip))
    40  	return nip
    41  }
    42  
    43  func (ip VpnIp) ToNetIpAddr() netip.Addr {
    44  	var nip [4]byte
    45  	binary.BigEndian.PutUint32(nip[:], uint32(ip))
    46  	return netip.AddrFrom4(nip)
    47  }
    48  
    49  func Ip2VpnIp(ip []byte) VpnIp {
    50  	if len(ip) == 16 {
    51  		return VpnIp(binary.BigEndian.Uint32(ip[12:16]))
    52  	}
    53  	return VpnIp(binary.BigEndian.Uint32(ip))
    54  }
    55  
    56  func ToNetIpAddr(ip net.IP) (netip.Addr, error) {
    57  	addr, ok := netip.AddrFromSlice(ip)
    58  	if !ok {
    59  		return netip.Addr{}, fmt.Errorf("invalid net.IP: %v", ip)
    60  	}
    61  	return addr, nil
    62  }
    63  
    64  func ToNetIpPrefix(ipNet net.IPNet) (netip.Prefix, error) {
    65  	addr, err := ToNetIpAddr(ipNet.IP)
    66  	if err != nil {
    67  		return netip.Prefix{}, err
    68  	}
    69  	ones, bits := ipNet.Mask.Size()
    70  	if ones == 0 && bits == 0 {
    71  		return netip.Prefix{}, fmt.Errorf("invalid net.IP: %v", ipNet)
    72  	}
    73  	return netip.PrefixFrom(addr, ones), nil
    74  }
    75  
    76  // ubtoa encodes the string form of the integer v to dst[start:] and
    77  // returns the number of bytes written to dst. The caller must ensure
    78  // that dst has sufficient length.
    79  func ubtoa(dst []byte, start int, v byte) int {
    80  	if v < 10 {
    81  		dst[start] = v + '0'
    82  		return 1
    83  	} else if v < 100 {
    84  		dst[start+1] = v%10 + '0'
    85  		dst[start] = v/10 + '0'
    86  		return 2
    87  	}
    88  
    89  	dst[start+2] = v%10 + '0'
    90  	dst[start+1] = (v/10)%10 + '0'
    91  	dst[start] = v/100 + '0'
    92  	return 3
    93  }