1
1
package csnet
2
2
3
3
import (
4
- "github.com/crowdsecurity/crowdsec/pkg/types"
4
+ "encoding/binary"
5
+ "errors"
6
+ "math"
7
+ "net/netip"
8
+ "strings"
5
9
)
6
10
7
11
type IPAddrSize int
@@ -11,37 +15,98 @@ const (
11
15
IPv6Size IPAddrSize = 16
12
16
)
13
17
14
- type IP struct {
18
+ type IntIP struct {
15
19
size IPAddrSize
16
20
Addr int64
17
21
Sfx int64
18
22
}
19
23
20
24
type Range struct {
21
- Start IP
22
- End IP
25
+ Start IntIP
26
+ End IntIP
23
27
}
24
28
25
29
func (r Range ) Size () int {
26
30
return int (r .Start .size )
27
31
}
28
32
33
+ // NewIP converts a netip.Addr into an IntIP for storage and comparison.
34
+ func NewIP (addr netip.Addr ) IntIP {
35
+ if addr .Is4 () {
36
+ ipBytes := addr .As4 ()
37
+
38
+ return IntIP {
39
+ size : IPv4Size ,
40
+ Addr : uint2int (uint64 (binary .BigEndian .Uint32 (ipBytes [:]))),
41
+ Sfx : 0 ,
42
+ }
43
+ }
44
+
45
+ ipBytes := addr .As16 ()
46
+
47
+ return IntIP {
48
+ size : IPv6Size ,
49
+ Addr : uint2int (binary .BigEndian .Uint64 (ipBytes [0 :8 ])),
50
+ Sfx : uint2int (binary .BigEndian .Uint64 (ipBytes [8 :16 ])),
51
+ }
52
+ }
53
+
54
+ // NewRange parses an IP or CIDR string into a Range of IntIP addresses.
55
+ // If the input is a single IP (e.g. "1.2.3.4"), the start and end of the range are equal.
56
+ // If the input is a prefix (e.g. "1.2.3.0/24"), the function computes the first and last
57
+ // addresses covered by the prefix.
29
58
func NewRange (anyIP string ) (Range , error ) {
30
- size , start_ip , start_sfx , end_ip , end_sfx , err := types .Addr2Ints (anyIP )
59
+ if ! strings .Contains (anyIP , "/" ) {
60
+ addr , err := netip .ParseAddr (anyIP )
61
+ if err != nil {
62
+ return Range {}, err
63
+ }
64
+
65
+ ip := NewIP (addr )
66
+
67
+ return Range {Start : ip , End : ip }, nil
68
+ }
69
+
70
+ prefix , err := netip .ParsePrefix (anyIP )
31
71
if err != nil {
32
72
return Range {}, err
33
73
}
34
74
35
- return Range {
36
- Start : IP {
37
- size : IPAddrSize (size ),
38
- Addr : start_ip ,
39
- Sfx : start_sfx ,
40
- },
41
- End : IP {
42
- size : IPAddrSize (size ),
43
- Addr : end_ip ,
44
- Sfx : end_sfx ,
45
- },
46
- }, nil
75
+ start := prefix .Masked ().Addr ()
76
+ bits := prefix .Bits ()
77
+
78
+ if start .Is4In6 () && bits < 96 {
79
+ return Range {}, errors .New ("prefix with 4in6 address must have mask >= 96" )
80
+ }
81
+
82
+ a16 := start .As16 ()
83
+
84
+ if start .Is4 () {
85
+ bits += 96
86
+ }
87
+
88
+ // Fill host bits with 1s
89
+ for b := bits ; b < 128 ; b ++ {
90
+ a16 [b / 8 ] |= 1 << (7 - (b % 8 ))
91
+ }
92
+
93
+ end := netip .AddrFrom16 (a16 )
94
+ if start .Is4 () {
95
+ end = end .Unmap ()
96
+ }
97
+
98
+ return Range {Start : NewIP (start ), End : NewIP (end )}, nil
99
+ }
100
+
101
+ func uint2int (u uint64 ) int64 {
102
+ switch {
103
+ case u == math .MaxInt64 :
104
+ return 0
105
+ case u == math .MaxUint64 :
106
+ return math .MaxInt64
107
+ case u > math .MaxInt64 :
108
+ return int64 (u - math .MaxInt64 )
109
+ default :
110
+ return int64 (u ) - math .MaxInt64
111
+ }
47
112
}
0 commit comments