@@ -21,11 +21,12 @@ var metadataStartMarker = []byte("\xAB\xCD\xEFMaxMind.com")
21
21
// Reader holds the data corresponding to the MaxMind DB file. Its only public
22
22
// field is Metadata, which contains the metadata from the MaxMind DB file.
23
23
type Reader struct {
24
- hasMappedFile bool
25
- buffer []byte
26
- decoder decoder
27
- Metadata Metadata
28
- ipv4Start uint
24
+ hasMappedFile bool
25
+ buffer []byte
26
+ decoder decoder
27
+ Metadata Metadata
28
+ ipv4Start uint
29
+ ipv4StartBitDepth int
29
30
}
30
31
31
32
// Metadata holds the metadata decoded from the MaxMind DB file. In particular
@@ -81,27 +82,30 @@ func FromBytes(buffer []byte) (*Reader, error) {
81
82
ipv4Start : 0 ,
82
83
}
83
84
84
- reader . ipv4Start , err = reader .startNode ()
85
+ err = reader .setIPv4Start ()
85
86
86
87
return reader , err
87
88
}
88
89
89
- func (r * Reader ) startNode () ( uint , error ) {
90
+ func (r * Reader ) setIPv4Start () error {
90
91
if r .Metadata .IPVersion != 6 {
91
- return 0 , nil
92
+ return nil
92
93
}
93
94
94
95
nodeCount := r .Metadata .NodeCount
95
96
96
97
node := uint (0 )
97
98
var err error
98
- for i := 0 ; i < 96 && node < nodeCount ; i ++ {
99
+ i := 0
100
+ for ; i < 96 && node < nodeCount ; i ++ {
99
101
node , err = r .readNode (node , 0 )
100
102
if err != nil {
101
- return 0 , err
103
+ return err
102
104
}
103
105
}
104
- return node , err
106
+ r .ipv4Start = node
107
+ r .ipv4StartBitDepth = i
108
+ return err
105
109
}
106
110
107
111
// Lookup retrieves the database record for ip and stores it in the value
@@ -161,9 +165,16 @@ func (r *Reader) LookupOffset(ip net.IP) (uintptr, error) {
161
165
}
162
166
163
167
func (r * Reader ) cidr (ip net.IP , prefixLength int ) * net.IPNet {
164
- ipBitLength := len (ip ) * 8
165
- mask := net .CIDRMask (prefixLength , ipBitLength )
168
+ // This is necessary as the node that the IPv4 start is at may
169
+ // be at a bit depth that is less that 96, i.e., ipv4Start points
170
+ // to a leaf node.
171
+ if r .Metadata .IPVersion == 6 &&
172
+ len (ip ) == net .IPv4len &&
173
+ r .ipv4StartBitDepth != 96 {
174
+ return & net.IPNet {IP : net .ParseIP ("::" ), Mask : net .CIDRMask (r .ipv4StartBitDepth , 128 )}
175
+ }
166
176
177
+ mask := net .CIDRMask (prefixLength , len (ip )* 8 )
167
178
return & net.IPNet {IP : ip .Mask (mask ), Mask : mask }
168
179
}
169
180
0 commit comments