Skip to content

Commit 01f7a64

Browse files
authored
add special handling for "2002:" ipv6 address (#252)
* add 2002 handling * add unittest * test error info * more * some fix * more fix * add unittest
1 parent e265e42 commit 01f7a64

File tree

3 files changed

+58
-5
lines changed

3 files changed

+58
-5
lines changed

handler/handler.go

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"net"
1212
"net/http"
1313
"strconv"
14+
"strings"
1415
"time"
1516

1617
"github.com/m-lab/go/logx"
@@ -140,7 +141,11 @@ func AnnotateLegacy(date time.Time, ips []api.RequestData) (map[string]*api.GeoD
140141
request := ips[i]
141142
metrics.TotalLookups.Inc()
142143
data := api.GeoData{}
143-
err := ann.Annotate(request.IP, &data)
144+
requestIP := request.IP
145+
if strings.HasPrefix(request.IP, "2002:") {
146+
requestIP = Ip6to4(request.IP)
147+
}
148+
err := ann.Annotate(requestIP, &data)
144149
if err != nil {
145150
// TODO need better error handling.
146151
continue
@@ -156,6 +161,20 @@ func AnnotateLegacy(date time.Time, ips []api.RequestData) (map[string]*api.GeoD
156161

157162
var v2errorLogger = logx.NewLogEvery(nil, time.Second)
158163

164+
// Ip6to4 converts "2002:" ipv6 address back to ipv4.
165+
func Ip6to4(ipv6 string) string {
166+
ipnet := &net.IPNet{
167+
Mask: net.CIDRMask(16, 128),
168+
IP: net.ParseIP("2002::"),
169+
}
170+
ip := net.ParseIP(ipv6)
171+
if ip == nil || !ipnet.Contains(ip) {
172+
return ""
173+
}
174+
175+
return fmt.Sprintf("%d.%d.%d.%d", ip[2], ip[3], ip[4], ip[5])
176+
}
177+
159178
// AnnotateV2 finds an appropriate Annotator based on the requested Date, and creates a
160179
// response with annotations for all parseable IPs.
161180
func AnnotateV2(date time.Time, ips []string, reqInfo string) (v2.Response, error) {
@@ -174,7 +193,12 @@ func AnnotateV2(date time.Time, ips []string, reqInfo string) (v2.Response, erro
174193
metrics.TotalLookups.Inc()
175194

176195
annotation := api.GeoData{}
177-
err := ann.Annotate(ips[i], &annotation)
196+
// special handling of "2002:" ip address
197+
requestIP := ips[i]
198+
if strings.HasPrefix(ips[i], "2002:") {
199+
requestIP = Ip6to4(ips[i])
200+
}
201+
err := ann.Annotate(requestIP, &annotation)
178202
if err != nil {
179203
switch err.Error {
180204
// TODO - enumerate interesting error types here...
@@ -331,7 +355,14 @@ func handleV2(w http.ResponseWriter, tStart time.Time, jsonBuffer []byte) {
331355
response := v2.Response{}
332356

333357
if len(request.IPs) > 0 {
334-
response, err = AnnotateV2(request.Date, request.IPs, request.RequestInfo)
358+
requestIPs := make([]string, len(request.IPs))
359+
for i := range request.IPs {
360+
requestIPs[i] = request.IPs[i]
361+
if strings.HasPrefix(request.IPs[i], "2002:") {
362+
requestIPs[i] = Ip6to4(request.IPs[i])
363+
}
364+
}
365+
response, err = AnnotateV2(request.Date, requestIPs, request.RequestInfo)
335366
if checkError(err, w, request.RequestInfo, len(request.IPs), "v2", tStart) {
336367
return
337368
}
@@ -410,7 +441,10 @@ func GetMetadataForSingleIP(request *api.RequestData) (result api.GeoData, err e
410441
if err != nil {
411442
return
412443
}
413-
414-
err = ann.Annotate(request.IP, &result)
444+
requestIP := request.IP
445+
if strings.HasPrefix(request.IP, "2002:") {
446+
requestIP = Ip6to4(request.IP)
447+
}
448+
err = ann.Annotate(requestIP, &result)
415449
return
416450
}

handler/handler_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@ func init() {
2828
log.SetFlags(log.LstdFlags | log.Lshortfile)
2929
}
3030

31+
func TestIp6to4(t *testing.T) {
32+
ss := handler.Ip6to4("2002:dced:117c::dced:117c")
33+
if ss != "220.237.17.124" {
34+
t.Errorf("ip6to4 not done correctly: expect 220.237.17.124 actually " + ss)
35+
}
36+
37+
es := handler.Ip6to4("2002:dced")
38+
if es != "" {
39+
t.Errorf("ip6to4 not done correctly: expect empty string actually " + es)
40+
}
41+
42+
cs := handler.Ip6to4("2002:dced::")
43+
if cs != "220.237.0.0" {
44+
t.Errorf("ip6to4 not done correctly: expect 220.237.0.0 actually " + cs)
45+
}
46+
}
47+
3148
func TestAnnotate(t *testing.T) {
3249
tests := []struct {
3350
ip string

manager/manager_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ func TestInitDataset(t *testing.T) {
5858
// This request needs the latest dataset in the memory.
5959
{"1.22.128.0", "1544400000",
6060
`{"Geo":{"continent_code":"AS","country_code":"IN","country_name":"India","region":"HR","city":"Faridabad","latitude":28.4333,"longitude":77.3167},"Network":{"Systems":[{"ASNs":[45528]}]}}`},
61+
{"2002:dced:117c::dced:117c", "1559227976",
62+
`{"Geo":{"continent_code":"OC","country_code":"AU","country_name":"Australia","region":"VIC","city":"East Malvern","postal_code":"3145","latitude":-37.8833,"longitude":145.05},"Network":{"Systems":[{"ASNs":[4804]}]}}`},
6163
}
6264
for n, test := range tests {
6365
w := httptest.NewRecorder()

0 commit comments

Comments
 (0)