2021-01-14 15:27:45 +00:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
|
|
|
"math"
|
|
|
|
"net"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2023-06-29 09:34:59 +00:00
|
|
|
// LastAddress returns the last address of a network
|
2021-01-14 15:27:45 +00:00
|
|
|
func LastAddress(n net.IPNet) net.IP {
|
2023-06-29 09:34:59 +00:00
|
|
|
// get the last address by ORing the hostmask and the IP
|
2021-01-14 15:27:45 +00:00
|
|
|
ip := n.IP.To4()
|
|
|
|
if ip == nil {
|
2023-06-29 09:34:59 +00:00
|
|
|
// IPv6
|
2021-01-14 15:27:45 +00:00
|
|
|
ip = n.IP
|
|
|
|
return net.IP{
|
|
|
|
ip[0] | ^n.Mask[0], ip[1] | ^n.Mask[1], ip[2] | ^n.Mask[2],
|
|
|
|
ip[3] | ^n.Mask[3], ip[4] | ^n.Mask[4], ip[5] | ^n.Mask[5],
|
|
|
|
ip[6] | ^n.Mask[6], ip[7] | ^n.Mask[7], ip[8] | ^n.Mask[8],
|
|
|
|
ip[9] | ^n.Mask[9], ip[10] | ^n.Mask[10], ip[11] | ^n.Mask[11],
|
|
|
|
ip[12] | ^n.Mask[12], ip[13] | ^n.Mask[13], ip[14] | ^n.Mask[14],
|
|
|
|
ip[15] | ^n.Mask[15]}
|
|
|
|
}
|
|
|
|
|
|
|
|
return net.IPv4(
|
|
|
|
ip[0]|^n.Mask[0],
|
|
|
|
ip[1]|^n.Mask[1],
|
|
|
|
ip[2]|^n.Mask[2],
|
|
|
|
ip[3]|^n.Mask[3])
|
|
|
|
}
|
|
|
|
|
|
|
|
/*returns a range for any ip or range*/
|
2022-06-16 12:41:54 +00:00
|
|
|
func Addr2Ints(anyIP string) (int, int64, int64, int64, int64, error) {
|
|
|
|
if strings.Contains(anyIP, "/") {
|
|
|
|
_, net, err := net.ParseCIDR(anyIP)
|
2021-01-14 15:27:45 +00:00
|
|
|
if err != nil {
|
2023-06-29 09:34:59 +00:00
|
|
|
return -1, 0, 0, 0, 0, fmt.Errorf("while parsing range %s: %w", anyIP, err)
|
2021-01-14 15:27:45 +00:00
|
|
|
}
|
|
|
|
return Range2Ints(*net)
|
|
|
|
}
|
2022-02-01 21:08:06 +00:00
|
|
|
|
2022-06-16 12:41:54 +00:00
|
|
|
ip := net.ParseIP(anyIP)
|
2022-02-01 21:08:06 +00:00
|
|
|
if ip == nil {
|
|
|
|
return -1, 0, 0, 0, 0, fmt.Errorf("invalid address")
|
|
|
|
}
|
|
|
|
|
|
|
|
sz, start, end, err := IP2Ints(ip)
|
|
|
|
if err != nil {
|
2023-06-29 09:34:59 +00:00
|
|
|
return -1, 0, 0, 0, 0, fmt.Errorf("while parsing ip %s: %w", anyIP, err)
|
2022-02-01 21:08:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return sz, start, end, start, end, nil
|
2021-01-14 15:27:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*size (16|4), nw_start, suffix_start, nw_end, suffix_end, error*/
|
|
|
|
func Range2Ints(network net.IPNet) (int, int64, int64, int64, int64, error) {
|
|
|
|
|
|
|
|
szStart, nwStart, sfxStart, err := IP2Ints(network.IP)
|
|
|
|
if err != nil {
|
2023-06-29 09:34:59 +00:00
|
|
|
return -1, 0, 0, 0, 0, fmt.Errorf("converting first ip in range: %w", err)
|
2021-01-14 15:27:45 +00:00
|
|
|
}
|
|
|
|
lastAddr := LastAddress(network)
|
|
|
|
szEnd, nwEnd, sfxEnd, err := IP2Ints(lastAddr)
|
|
|
|
if err != nil {
|
2023-06-29 09:34:59 +00:00
|
|
|
return -1, 0, 0, 0, 0, fmt.Errorf("transforming last address of range: %w", err)
|
2021-01-14 15:27:45 +00:00
|
|
|
}
|
|
|
|
if szEnd != szStart {
|
|
|
|
return -1, 0, 0, 0, 0, fmt.Errorf("inconsistent size for range first(%d) and last(%d) ip", szStart, szEnd)
|
|
|
|
}
|
|
|
|
return szStart, nwStart, sfxStart, nwEnd, sfxEnd, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func uint2int(u uint64) int64 {
|
|
|
|
var ret int64
|
|
|
|
if u == math.MaxInt64 {
|
|
|
|
ret = 0
|
|
|
|
} else if u == math.MaxUint64 {
|
|
|
|
ret = math.MaxInt64
|
|
|
|
} else if u > math.MaxInt64 {
|
|
|
|
u -= math.MaxInt64
|
|
|
|
ret = int64(u)
|
|
|
|
} else {
|
|
|
|
ret = int64(u)
|
|
|
|
ret -= math.MaxInt64
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
/*size (16|4), network, suffix, error*/
|
|
|
|
func IP2Ints(pip net.IP) (int, int64, int64, error) {
|
|
|
|
var ip_nw, ip_sfx uint64
|
|
|
|
|
|
|
|
pip4 := pip.To4()
|
|
|
|
pip16 := pip.To16()
|
|
|
|
|
|
|
|
if pip4 != nil {
|
|
|
|
ip_nw32 := binary.BigEndian.Uint32(pip4)
|
|
|
|
|
|
|
|
return 4, uint2int(uint64(ip_nw32)), uint2int(ip_sfx), nil
|
|
|
|
} else if pip16 != nil {
|
|
|
|
ip_nw = binary.BigEndian.Uint64(pip16[0:8])
|
|
|
|
ip_sfx = binary.BigEndian.Uint64(pip16[8:16])
|
|
|
|
return 16, uint2int(ip_nw), uint2int(ip_sfx), nil
|
|
|
|
} else {
|
|
|
|
return -1, 0, 0, fmt.Errorf("unexpected len %d for %s", len(pip), pip)
|
|
|
|
}
|
|
|
|
}
|