-
Notifications
You must be signed in to change notification settings - Fork 107
/
brute.go
124 lines (113 loc) · 3.52 KB
/
brute.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package cidranger
import (
"net"
rnet "github.com/yl2chen/cidranger/net"
)
// bruteRanger is a brute force implementation of Ranger. Insertion and
// deletion of networks is performed on an internal storage in the form of
// map[string]net.IPNet (constant time operations). However, inclusion tests are
// always performed linearly at no guaranteed traversal order of recorded networks,
// so one can assume a worst case performance of O(N). The performance can be
// boosted many ways, e.g. changing usage of net.IPNet.Contains() to using masked
// bits equality checking, but the main purpose of this implementation is for
// testing because the correctness of this implementation can be easily guaranteed,
// and used as the ground truth when running a wider range of 'random' tests on
// other more sophisticated implementations.
type bruteRanger struct {
ipV4Entries map[string]RangerEntry
ipV6Entries map[string]RangerEntry
}
// newBruteRanger returns a new Ranger.
func newBruteRanger() Ranger {
return &bruteRanger{
ipV4Entries: make(map[string]RangerEntry),
ipV6Entries: make(map[string]RangerEntry),
}
}
// Insert inserts a RangerEntry into ranger.
func (b *bruteRanger) Insert(entry RangerEntry) error {
network := entry.Network()
key := network.String()
if _, found := b.ipV4Entries[key]; !found {
entries, err := b.getEntriesByVersion(entry.Network().IP)
if err != nil {
return err
}
entries[key] = entry
}
return nil
}
// Remove removes a RangerEntry identified by given network from ranger.
func (b *bruteRanger) Remove(network net.IPNet) (RangerEntry, error) {
networks, err := b.getEntriesByVersion(network.IP)
if err != nil {
return nil, err
}
key := network.String()
if networkToDelete, found := networks[key]; found {
delete(networks, key)
return networkToDelete, nil
}
return nil, nil
}
// Contains returns bool indicating whether given ip is contained by any
// network in ranger.
func (b *bruteRanger) Contains(ip net.IP) (bool, error) {
entries, err := b.getEntriesByVersion(ip)
if err != nil {
return false, err
}
for _, entry := range entries {
network := entry.Network()
if network.Contains(ip) {
return true, nil
}
}
return false, nil
}
// ContainingNetworks returns all RangerEntry(s) that given ip contained in.
func (b *bruteRanger) ContainingNetworks(ip net.IP) ([]RangerEntry, error) {
entries, err := b.getEntriesByVersion(ip)
if err != nil {
return nil, err
}
results := []RangerEntry{}
for _, entry := range entries {
network := entry.Network()
if network.Contains(ip) {
results = append(results, entry)
}
}
return results, nil
}
// CoveredNetworks returns the list of RangerEntry(s) the given ipnet
// covers. That is, the networks that are completely subsumed by the
// specified network.
func (b *bruteRanger) CoveredNetworks(network net.IPNet) ([]RangerEntry, error) {
entries, err := b.getEntriesByVersion(network.IP)
if err != nil {
return nil, err
}
var results []RangerEntry
testNetwork := rnet.NewNetwork(network)
for _, entry := range entries {
entryNetwork := rnet.NewNetwork(entry.Network())
if testNetwork.Covers(entryNetwork) {
results = append(results, entry)
}
}
return results, nil
}
// Len returns number of networks in ranger.
func (b *bruteRanger) Len() int {
return len(b.ipV4Entries) + len(b.ipV6Entries)
}
func (b *bruteRanger) getEntriesByVersion(ip net.IP) (map[string]RangerEntry, error) {
if ip.To4() != nil {
return b.ipV4Entries, nil
}
if ip.To16() != nil {
return b.ipV6Entries, nil
}
return nil, ErrInvalidNetworkInput
}