@@ -21,11 +21,12 @@ var metadataStartMarker = []byte("\xAB\xCD\xEFMaxMind.com")
2121// Reader holds the data corresponding to the MaxMind DB file. Its only public
2222// field is Metadata, which contains the metadata from the MaxMind DB file.
2323type 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
2930}
3031
3132// Metadata holds the metadata decoded from the MaxMind DB file. In particular
@@ -81,27 +82,30 @@ func FromBytes(buffer []byte) (*Reader, error) {
8182 ipv4Start : 0 ,
8283 }
8384
84- reader . ipv4Start , err = reader .startNode ()
85+ err = reader .setIPv4Start ()
8586
8687 return reader , err
8788}
8889
89- func (r * Reader ) startNode () ( uint , error ) {
90+ func (r * Reader ) setIPv4Start () error {
9091 if r .Metadata .IPVersion != 6 {
91- return 0 , nil
92+ return nil
9293 }
9394
9495 nodeCount := r .Metadata .NodeCount
9596
9697 node := uint (0 )
9798 var err error
98- for i := 0 ; i < 96 && node < nodeCount ; i ++ {
99+ i := 0
100+ for ; i < 96 && node < nodeCount ; i ++ {
99101 node , err = r .readNode (node , 0 )
100102 if err != nil {
101- return 0 , err
103+ return err
102104 }
103105 }
104- return node , err
106+ r .ipv4Start = node
107+ r .ipv4StartBitDepth = i
108+ return err
105109}
106110
107111// 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) {
161165}
162166
163167func (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+ }
166176
177+ mask := net .CIDRMask (prefixLength , len (ip )* 8 )
167178 return & net.IPNet {IP : ip .Mask (mask ), Mask : mask }
168179}
169180
0 commit comments