github.com/crowdsecurity/crowdsec@v1.6.1/pkg/types/ip.go (about) 1 package types 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "math" 7 "net" 8 "strings" 9 ) 10 11 // LastAddress returns the last address of a network 12 func LastAddress(n net.IPNet) net.IP { 13 // get the last address by ORing the hostmask and the IP 14 ip := n.IP.To4() 15 if ip == nil { 16 // IPv6 17 ip = n.IP 18 return net.IP{ 19 ip[0] | ^n.Mask[0], ip[1] | ^n.Mask[1], ip[2] | ^n.Mask[2], 20 ip[3] | ^n.Mask[3], ip[4] | ^n.Mask[4], ip[5] | ^n.Mask[5], 21 ip[6] | ^n.Mask[6], ip[7] | ^n.Mask[7], ip[8] | ^n.Mask[8], 22 ip[9] | ^n.Mask[9], ip[10] | ^n.Mask[10], ip[11] | ^n.Mask[11], 23 ip[12] | ^n.Mask[12], ip[13] | ^n.Mask[13], ip[14] | ^n.Mask[14], 24 ip[15] | ^n.Mask[15]} 25 } 26 27 return net.IPv4( 28 ip[0]|^n.Mask[0], 29 ip[1]|^n.Mask[1], 30 ip[2]|^n.Mask[2], 31 ip[3]|^n.Mask[3]) 32 } 33 34 /*returns a range for any ip or range*/ 35 func Addr2Ints(anyIP string) (int, int64, int64, int64, int64, error) { 36 if strings.Contains(anyIP, "/") { 37 _, net, err := net.ParseCIDR(anyIP) 38 if err != nil { 39 return -1, 0, 0, 0, 0, fmt.Errorf("while parsing range %s: %w", anyIP, err) 40 } 41 return Range2Ints(*net) 42 } 43 44 ip := net.ParseIP(anyIP) 45 if ip == nil { 46 return -1, 0, 0, 0, 0, fmt.Errorf("invalid address") 47 } 48 49 sz, start, end, err := IP2Ints(ip) 50 if err != nil { 51 return -1, 0, 0, 0, 0, fmt.Errorf("while parsing ip %s: %w", anyIP, err) 52 } 53 54 return sz, start, end, start, end, nil 55 } 56 57 /*size (16|4), nw_start, suffix_start, nw_end, suffix_end, error*/ 58 func Range2Ints(network net.IPNet) (int, int64, int64, int64, int64, error) { 59 60 szStart, nwStart, sfxStart, err := IP2Ints(network.IP) 61 if err != nil { 62 return -1, 0, 0, 0, 0, fmt.Errorf("converting first ip in range: %w", err) 63 } 64 lastAddr := LastAddress(network) 65 szEnd, nwEnd, sfxEnd, err := IP2Ints(lastAddr) 66 if err != nil { 67 return -1, 0, 0, 0, 0, fmt.Errorf("transforming last address of range: %w", err) 68 } 69 if szEnd != szStart { 70 return -1, 0, 0, 0, 0, fmt.Errorf("inconsistent size for range first(%d) and last(%d) ip", szStart, szEnd) 71 } 72 return szStart, nwStart, sfxStart, nwEnd, sfxEnd, nil 73 } 74 75 func uint2int(u uint64) int64 { 76 var ret int64 77 if u == math.MaxInt64 { 78 ret = 0 79 } else if u == math.MaxUint64 { 80 ret = math.MaxInt64 81 } else if u > math.MaxInt64 { 82 u -= math.MaxInt64 83 ret = int64(u) 84 } else { 85 ret = int64(u) 86 ret -= math.MaxInt64 87 } 88 return ret 89 } 90 91 /*size (16|4), network, suffix, error*/ 92 func IP2Ints(pip net.IP) (int, int64, int64, error) { 93 var ip_nw, ip_sfx uint64 94 95 pip4 := pip.To4() 96 pip16 := pip.To16() 97 98 if pip4 != nil { 99 ip_nw32 := binary.BigEndian.Uint32(pip4) 100 101 return 4, uint2int(uint64(ip_nw32)), uint2int(ip_sfx), nil 102 } else if pip16 != nil { 103 ip_nw = binary.BigEndian.Uint64(pip16[0:8]) 104 ip_sfx = binary.BigEndian.Uint64(pip16[8:16]) 105 return 16, uint2int(ip_nw), uint2int(ip_sfx), nil 106 } else { 107 return -1, 0, 0, fmt.Errorf("unexpected len %d for %s", len(pip), pip) 108 } 109 }