@@ -16,6 +16,7 @@ type netNode struct {
16
16
17
17
type networkOptions struct {
18
18
includeAliasedNetworks bool
19
+ includeEmptyNetworks bool
19
20
}
20
21
21
22
var (
@@ -33,30 +34,42 @@ func IncludeAliasedNetworks(networks *networkOptions) {
33
34
networks .includeAliasedNetworks = true
34
35
}
35
36
36
- // Networks returns an iterator that can be used to traverse all networks in
37
+ // IncludeEmptyNetworks is an option for Networks and NetworksWithin
38
+ // that makes them include networks without any data in the iteration.
39
+ func IncludeEmptyNetworks (networks * networkOptions ) {
40
+ networks .includeEmptyNetworks = true
41
+ }
42
+
43
+ // Networks returns an iterator that can be used to traverse the networks in
37
44
// the database.
38
45
//
39
46
// Please note that a MaxMind DB may map IPv4 networks into several locations
40
47
// in an IPv6 database. This iterator will only iterate over these once by
41
48
// default. To iterate over all the IPv4 network locations, use the
42
- // IncludeAliasedNetworks option.
49
+ // [IncludeAliasedNetworks] option.
50
+ //
51
+ // Networks without data are excluded by default. To include them, use
52
+ // [IncludeEmptyNetworks].
43
53
func (r * Reader ) Networks (options ... NetworksOption ) iter.Seq [Result ] {
44
54
if r .Metadata .IPVersion == 6 {
45
55
return r .NetworksWithin (allIPv6 , options ... )
46
56
}
47
57
return r .NetworksWithin (allIPv4 , options ... )
48
58
}
49
59
50
- // NetworksWithin returns an iterator that can be used to traverse all networks
60
+ // NetworksWithin returns an iterator that can be used to traverse the networks
51
61
// in the database which are contained in a given prefix.
52
62
//
53
63
// Please note that a MaxMind DB may map IPv4 networks into several locations
54
- // in an IPv6 database. This iterator will iterate over all of these locations
55
- // separately . To only iterate over the IPv4 networks once , use the
56
- // SkipAliasedNetworks option.
64
+ // in an IPv6 database. This iterator will only iterate over these once by
65
+ // default . To iterate over all the IPv4 network locations , use the
66
+ // [IncludeAliasedNetworks] option.
57
67
//
58
68
// If the provided prefix is contained within a network in the database, the
59
69
// iterator will iterate over exactly one network, the containing network.
70
+ //
71
+ // Networks without data are excluded by default. To include them, use
72
+ // [IncludeEmptyNetworks].
60
73
func (r * Reader ) NetworksWithin (prefix netip.Prefix , options ... NetworksOption ) iter.Seq [Result ] {
61
74
return func (yield func (Result ) bool ) {
62
75
if r .Metadata .IPVersion == 4 && prefix .Addr ().Is6 () {
@@ -106,7 +119,20 @@ func (r *Reader) NetworksWithin(prefix netip.Prefix, options ...NetworksOption)
106
119
node := nodes [len (nodes )- 1 ]
107
120
nodes = nodes [:len (nodes )- 1 ]
108
121
109
- for node .pointer != r .Metadata .NodeCount {
122
+ for {
123
+ if node .pointer == r .Metadata .NodeCount {
124
+ if n .includeEmptyNetworks {
125
+ ok := yield (Result {
126
+ ip : mappedIP (node .ip ),
127
+ offset : notFound ,
128
+ prefixLen : uint8 (node .bit ),
129
+ })
130
+ if ! ok {
131
+ return
132
+ }
133
+ }
134
+ break
135
+ }
110
136
// This skips IPv4 aliases without hardcoding the networks that the writer
111
137
// currently aliases.
112
138
if ! n .includeAliasedNetworks && r .ipv4Start != 0 &&
@@ -115,15 +141,10 @@ func (r *Reader) NetworksWithin(prefix netip.Prefix, options ...NetworksOption)
115
141
}
116
142
117
143
if node .pointer > r .Metadata .NodeCount {
118
- ip := node .ip
119
- if isInIPv4Subtree (ip ) {
120
- ip = v6ToV4 (ip )
121
- }
122
-
123
144
offset , err := r .resolveDataPointer (node .pointer )
124
145
ok := yield (Result {
125
146
decoder : r .decoder ,
126
- ip : ip ,
147
+ ip : mappedIP ( node . ip ) ,
127
148
offset : uint (offset ),
128
149
prefixLen : uint8 (node .bit ),
129
150
err : err ,
@@ -171,6 +192,13 @@ func (r *Reader) NetworksWithin(prefix netip.Prefix, options ...NetworksOption)
171
192
172
193
var ipv4SubtreeBoundary = netip .MustParseAddr ("::255.255.255.255" ).Next ()
173
194
195
+ func mappedIP (ip netip.Addr ) netip.Addr {
196
+ if isInIPv4Subtree (ip ) {
197
+ return v6ToV4 (ip )
198
+ }
199
+ return ip
200
+ }
201
+
174
202
// isInIPv4Subtree returns true if the IP is in the database's IPv4 subtree.
175
203
func isInIPv4Subtree (ip netip.Addr ) bool {
176
204
return ip .Is4 () || ip .Less (ipv4SubtreeBoundary )
0 commit comments