Skip to content

Commit 8875528

Browse files
committed
net.ip -> netip part 2
1 parent 5fb5d32 commit 8875528

File tree

7 files changed

+188
-511
lines changed

7 files changed

+188
-511
lines changed

pkg/apiserver/alerts_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ func TestAlertListFilters(t *testing.T) {
304304

305305
w = lapi.RecordResponse(t, ctx, "GET", "/v1/alerts?ip=gruueq", emptyBody, "password")
306306
assert.Equal(t, http.StatusInternalServerError, w.Code)
307-
assert.JSONEq(t, `{"message":"invalid ip address 'gruueq'"}`, w.Body.String())
307+
assert.JSONEq(t, `{"message":"ParseAddr(\"gruueq\"): unable to parse IP"}`, w.Body.String())
308308

309309
// test range (ok)
310310

@@ -323,7 +323,7 @@ func TestAlertListFilters(t *testing.T) {
323323

324324
w = lapi.RecordResponse(t, ctx, "GET", "/v1/alerts?range=ratata", emptyBody, "password")
325325
assert.Equal(t, http.StatusInternalServerError, w.Code)
326-
assert.JSONEq(t, `{"message":"invalid ip address 'ratata'"}`, w.Body.String())
326+
assert.JSONEq(t, `{"message":"ParseAddr(\"ratata\"): unable to parse IP"}`, w.Body.String())
327327

328328
// test since (ok)
329329

pkg/csnet/ip.go

Lines changed: 82 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package csnet
22

33
import (
4-
"github.com/crowdsecurity/crowdsec/pkg/types"
4+
"encoding/binary"
5+
"errors"
6+
"math"
7+
"net/netip"
8+
"strings"
59
)
610

711
type IPAddrSize int
@@ -11,37 +15,98 @@ const (
1115
IPv6Size IPAddrSize = 16
1216
)
1317

14-
type IP struct {
18+
type IntIP struct {
1519
size IPAddrSize
1620
Addr int64
1721
Sfx int64
1822
}
1923

2024
type Range struct {
21-
Start IP
22-
End IP
25+
Start IntIP
26+
End IntIP
2327
}
2428

2529
func (r Range) Size() int {
2630
return int(r.Start.size)
2731
}
2832

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.
2958
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)
3171
if err != nil {
3272
return Range{}, err
3373
}
3474

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+
}
47112
}

0 commit comments

Comments
 (0)