Skip to content

Commit 7abc676

Browse files
committed
Convert ipv4 address to ipv6 when searching on an ipv6 db
1 parent d1c282d commit 7abc676

File tree

2 files changed

+215
-19
lines changed

2 files changed

+215
-19
lines changed

traverse.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package maxminddb
22

3-
import "net"
3+
import (
4+
"net"
5+
)
46

57
// Internal structure used to keep track of nodes we still need to visit.
68
type netNode struct {
@@ -38,13 +40,20 @@ func (r *Reader) Networks() *Networks {
3840
}
3941

4042
func (r *Reader) NetworksWithin(network *net.IPNet) *Networks {
43+
ip := network.IP
4144
prefixLength, _ := network.Mask.Size()
42-
pointer, bit := r.traverseTree(network.IP, 0, uint(prefixLength))
45+
46+
if r.Metadata.IPVersion == 6 && len(ip) == net.IPv4len {
47+
ip = net.IP.To16(ip)
48+
prefixLength += 96
49+
}
50+
51+
pointer, bit := r.traverseTree(ip, 0, uint(prefixLength))
4352
return &Networks{
4453
reader: r,
4554
nodes: []netNode{
4655
{
47-
ip: network.IP,
56+
ip: ip,
4857
bit: uint(bit),
4958
pointer: pointer,
5059
},

traverse_test.go

Lines changed: 203 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,9 @@ func TestNetworksWithInvalidSearchTree(t *testing.T) {
4747
assert.NotNil(t, n.Err(), "no error received when traversing an broken search tree")
4848
assert.Equal(t, n.Err().Error(), "invalid search tree at 128.128.128.128/32")
4949
}
50-
func TestNetworksWithin(t *testing.T) {
51-
_, network, error := net.ParseCIDR("1.1.1.0/24")
5250

53-
assert.Nil(t, error)
51+
func TestNetworksWithinV4SearchInV4Db(t *testing.T) {
52+
var network = &net.IPNet{IP: make(net.IP, 4), Mask: net.CIDRMask(0, 32)}
5453

5554
for _, recordSize := range []uint{24, 28, 32} {
5655
fileName := testFile(fmt.Sprintf("MaxMind-DB-test-ipv4-%d.mmdb", recordSize))
@@ -70,27 +69,26 @@ func TestNetworksWithin(t *testing.T) {
7069
assert.Equal(t, record.IP, network.IP.String(),
7170
"expected %s got %s", record.IP, network.IP.String(),
7271
)
73-
innerIPs = append(innerIPs, record.IP)
72+
innerIPs = append(innerIPs, network.String())
7473
}
7574

7675
expectedIPs := []string{
77-
"1.1.1.1",
78-
"1.1.1.2",
79-
"1.1.1.4",
80-
"1.1.1.8",
81-
"1.1.1.16",
82-
"1.1.1.32",
76+
"1.1.1.1/32",
77+
"1.1.1.2/31",
78+
"1.1.1.4/30",
79+
"1.1.1.8/29",
80+
"1.1.1.16/28",
81+
"1.1.1.32/32",
8382
}
8483

8584
assert.Equal(t, expectedIPs, innerIPs)
8685
assert.Nil(t, n.Err())
8786
}
8887
}
8988

90-
func TestNetworksWithinSlash32(t *testing.T) {
91-
_, network, error := net.ParseCIDR("1.1.1.32/32")
92-
93-
assert.Nil(t, error)
89+
func TestNetworksWithinSlash32V4SearchInV4Db(t *testing.T) {
90+
_, network, err := net.ParseCIDR("1.1.1.1/32")
91+
assert.Nil(t, err)
9492

9593
for _, recordSize := range []uint{24, 28, 32} {
9694
fileName := testFile(fmt.Sprintf("MaxMind-DB-test-ipv4-%d.mmdb", recordSize))
@@ -110,12 +108,201 @@ func TestNetworksWithinSlash32(t *testing.T) {
110108
assert.Equal(t, record.IP, network.IP.String(),
111109
"expected %s got %s", record.IP, network.IP.String(),
112110
)
113-
innerIPs = append(innerIPs, record.IP)
111+
innerIPs = append(innerIPs, network.String())
112+
}
113+
114+
expectedIPs := []string{
115+
"1.1.1.1/32",
116+
}
117+
118+
assert.Equal(t, expectedIPs, innerIPs)
119+
assert.Nil(t, n.Err())
120+
}
121+
}
122+
123+
func TestNetworksWithinSlash32V4SearchInV6Db(t *testing.T) {
124+
_, network, err := net.ParseCIDR("1.1.1.1/32")
125+
assert.Nil(t, err)
126+
127+
for _, recordSize := range []uint{24, 28, 32} {
128+
fileName := testFile(fmt.Sprintf("MaxMind-DB-test-mixed-%d.mmdb", recordSize))
129+
reader, err := Open(fileName)
130+
require.Nil(t, err, "unexpected error while opening database: %v", err)
131+
defer reader.Close()
132+
133+
n := reader.NetworksWithin(network)
134+
var innerIPs []string
135+
136+
for n.Next() {
137+
record := struct {
138+
IP string `maxminddb:"ip"`
139+
}{}
140+
network, err := n.Network(&record)
141+
assert.Nil(t, err)
142+
innerIPs = append(innerIPs, network.String())
143+
}
144+
145+
expectedIPs := []string{
146+
"1.1.1.1/32",
147+
}
148+
149+
assert.Equal(t, expectedIPs, innerIPs)
150+
assert.Nil(t, n.Err())
151+
}
152+
153+
}
154+
func TestNetworksWithinSlash128V6SearchInV6Db(t *testing.T) {
155+
_, network, err := net.ParseCIDR("::1:ffff:ffff/128")
156+
assert.Nil(t, err)
157+
158+
for _, recordSize := range []uint{24, 28, 32} {
159+
fileName := testFile(fmt.Sprintf("MaxMind-DB-test-ipv6-%d.mmdb", recordSize))
160+
reader, err := Open(fileName)
161+
require.Nil(t, err, "unexpected error while opening database: %v", err)
162+
defer reader.Close()
163+
164+
n := reader.NetworksWithin(network)
165+
var innerIPs []string
166+
167+
for n.Next() {
168+
record := struct {
169+
IP string `maxminddb:"ip"`
170+
}{}
171+
network, err := n.Network(&record)
172+
assert.Nil(t, err)
173+
assert.Equal(t, record.IP, network.IP.String(),
174+
"expected %s got %s", record.IP, network.IP.String(),
175+
)
176+
innerIPs = append(innerIPs, network.String())
114177
}
115178

116-
expectedIPs := []string([]string{"1.1.1.32"})
179+
expectedIPs := []string{
180+
"::1:ffff:ffff/128",
181+
}
117182

118183
assert.Equal(t, expectedIPs, innerIPs)
119184
assert.Nil(t, n.Err())
120185
}
121186
}
187+
188+
func TestNetworksWithinV6SearchInV6Db(t *testing.T) {
189+
var network = &net.IPNet{IP: make(net.IP, 16), Mask: net.CIDRMask(0, 128)}
190+
191+
for _, recordSize := range []uint{24, 28, 32} {
192+
fileName := testFile(fmt.Sprintf("MaxMind-DB-test-ipv6-%d.mmdb", recordSize))
193+
reader, err := Open(fileName)
194+
require.Nil(t, err, "unexpected error while opening database: %v", err)
195+
defer reader.Close()
196+
197+
n := reader.NetworksWithin(network)
198+
var innerIPs []string
199+
200+
for n.Next() {
201+
record := struct {
202+
IP string `maxminddb:"ip"`
203+
}{}
204+
network, err := n.Network(&record)
205+
assert.Nil(t, err)
206+
assert.Equal(t, record.IP, network.IP.String(),
207+
"expected %s got %s", record.IP, network.IP.String(),
208+
)
209+
innerIPs = append(innerIPs, network.String())
210+
}
211+
212+
expectedIPs := []string{
213+
"::1:ffff:ffff/128",
214+
"::2:0:0/122",
215+
"::2:0:40/124",
216+
"::2:0:50/125",
217+
"::2:0:58/127",
218+
}
219+
220+
assert.Equal(
221+
t,
222+
expectedIPs,
223+
innerIPs,
224+
fmt.Sprintf("inner IPs for %v", fileName),
225+
)
226+
assert.Nil(t, n.Err())
227+
}
228+
}
229+
230+
func TestNetworksWithinV4SearchInV6Db(t *testing.T) {
231+
var network = &net.IPNet{IP: make(net.IP, 4), Mask: net.CIDRMask(0, 32)}
232+
233+
for _, recordSize := range []uint{24, 28, 32} {
234+
fileName := testFile(fmt.Sprintf("MaxMind-DB-test-mixed-%d.mmdb", recordSize))
235+
reader, err := Open(fileName)
236+
require.Nil(t, err, "unexpected error while opening database: %v", err)
237+
defer reader.Close()
238+
239+
n := reader.NetworksWithin(network)
240+
var innerIPs []string
241+
242+
for n.Next() {
243+
record := struct {
244+
IP string `maxminddb:"ip"`
245+
}{}
246+
network, err := n.Network(&record)
247+
assert.Nil(t, err)
248+
innerIPs = append(innerIPs, network.String())
249+
}
250+
251+
expectedIPs := []string{
252+
"1.1.1.1/32",
253+
"1.1.1.2/31",
254+
"1.1.1.4/30",
255+
"1.1.1.8/29",
256+
"1.1.1.16/28",
257+
"1.1.1.32/32",
258+
}
259+
260+
assert.Equal(
261+
t,
262+
expectedIPs,
263+
innerIPs,
264+
fmt.Sprintf("inner IPs for %v", fileName),
265+
)
266+
assert.Nil(t, n.Err())
267+
}
268+
}
269+
270+
func TestNetworksWithinV6SearchInV4Db(t *testing.T) {
271+
var network = &net.IPNet{IP: make(net.IP, 16), Mask: net.CIDRMask(0, 128)}
272+
273+
for _, recordSize := range []uint{24, 28, 32} {
274+
fileName := testFile(fmt.Sprintf("MaxMind-DB-test-ipv4-%d.mmdb", recordSize))
275+
reader, err := Open(fileName)
276+
require.Nil(t, err, "unexpected error while opening database: %v", err)
277+
defer reader.Close()
278+
279+
n := reader.NetworksWithin(network)
280+
var innerIPs []string
281+
282+
for n.Next() {
283+
record := struct {
284+
IP string `maxminddb:"ip"`
285+
}{}
286+
network, err := n.Network(&record)
287+
assert.Nil(t, err)
288+
innerIPs = append(innerIPs, network.String())
289+
}
290+
291+
expectedIPs := []string{
292+
"101:101::/32",
293+
"101:102::/31",
294+
"101:104::/30",
295+
"101:108::/29",
296+
"101:110::/28",
297+
"101:120::/32",
298+
}
299+
300+
assert.Equal(
301+
t,
302+
expectedIPs,
303+
innerIPs,
304+
fmt.Sprintf("inner IPs for %v", fileName),
305+
)
306+
assert.Nil(t, n.Err())
307+
}
308+
}

0 commit comments

Comments
 (0)