diff --git a/.gitignore b/.gitignore index 415479f..dd6e8fd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.code-workspace *.mmdb node_modules/ +vendor/ diff --git a/.golangci.yaml b/.golangci.yaml index 84eb946..e05d4ad 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,78 +1,89 @@ -run: - timeout: 3m - skip-files: [] - skip-dirs: [] - -linters-settings: - govet: - enable-all: true - disable: - - fieldalignment - golint: - min-confidence: 0 - gocyclo: - min-complexity: 12 - goconst: - min-len: 5 - min-occurrences: 4 - misspell: - locale: US - funlen: - lines: -1 - statements: 50 - godox: - keywords: - - FIXME - gofumpt: - extra-rules: true - +version: "2" linters: - enable-all: true + default: all disable: - - deadcode # deprecated - - exhaustivestruct # deprecated - - golint # deprecated - - ifshort # deprecated - - interfacer # deprecated - - maligned # deprecated - - nosnakecase # deprecated - - scopelint # deprecated - - scopelint # deprecated - - structcheck # deprecated - - varcheck # deprecated - - sqlclosecheck # not relevant (SQL) - - rowserrcheck # not relevant (SQL) - - execinquery # not relevant (SQL) - - cyclop # duplicate of gocyclo - - bodyclose # Too many false positives: https://github.com/timakin/bodyclose/issues/30 + - bodyclose + - cyclop - dupl - - testpackage - - tparallel - - paralleltest - - nlreturn - - wsl + - err113 - exhaustive - exhaustruct - - goerr113 - - wrapcheck - - ifshort - - noctx - - lll - - gomnd - forbidigo + - lll + - mnd + - nlreturn + - noctx + - paralleltest + - rowserrcheck + - sqlclosecheck + - testpackage + - tparallel - varnamelen + - wrapcheck + - wsl + settings: + funlen: + lines: -1 + statements: 50 + goconst: + min-len: 5 + min-occurrences: 4 + gocyclo: + min-complexity: 15 + godox: + keywords: + - FIXME + govet: + disable: + - fieldalignment + enable-all: true + misspell: + locale: US + depguard: + rules: + main: + files: + - $all + - "!$test" + allow: + - $gostd + - github.com/IncSW/geoip2 + test: + files: + - "$test" + allow: + - $gostd + - github.com/traefik-plugins/traefikgeoip2 + exclusions: + generated: lax + rules: + - linters: + - gochecknoglobals + path: middleware.go + - linters: + - funlen + - goconst + - godot + path: (.+)_test.go + paths: + - third_party$ + - builtin$ + - examples$ issues: - exclude-use-default: false - max-per-linter: 0 max-same-issues: 0 - exclude: [] - exclude-rules: - - path: middleware.go - linters: - - gochecknoglobals - - path: (.+)_test.go - linters: - - goconst - - funlen - - godot +formatters: + enable: + - gci + - gofmt + - gofumpt + - goimports + settings: + gofumpt: + extra-rules: true + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..80b3a6f --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +.PHONY: prepare lint test vendor + +export GO111MODULE=on + +default: prepare lint test + +prepare: + tar -zxvf geolite2.tgz + +lint: + golangci-lint run + +test: + go test -v -cover ./... + +vendor: + go mod vendor + +yaegi: + yaegi run middleware.go + +clean: + rm -rf ./vendor *.mmdb || exit 0 diff --git a/go.mod b/go.mod index 8822e97..eeb5722 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/traefik-plugins/traefikgeoip2 -go 1.19 +go 1.25 -require github.com/IncSW/geoip2 v0.1.1 +require github.com/IncSW/geoip2 v0.1.4 diff --git a/go.sum b/go.sum index 6823772..7bebd47 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -github.com/IncSW/geoip2 v0.1.1 h1:afzzYF7n9JbdcPy8aiBSgBJuXi4mTWXZ3z6V3o6Vg34= -github.com/IncSW/geoip2 v0.1.1/go.mod h1:adcasR40vXiUBjtzdaTTKL/6wSf+fgO4M8Gve/XzPUk= +github.com/IncSW/geoip2 v0.1.4 h1:nkZz/E6POGDjnHsOda0CpBzwiH+FoDRQ1LhlAlBxOC8= +github.com/IncSW/geoip2 v0.1.4/go.mod h1:P2giYcBGG9oBqvgkLy2DZGM+thol50fXF5+8j+VIdm8= diff --git a/middleware.go b/middleware.go index e9e55ab..f0a257a 100644 --- a/middleware.go +++ b/middleware.go @@ -41,8 +41,10 @@ type TraefikGeoIP2 struct { // New created a new TraefikGeoIP2 plugin. func New(_ context.Context, next http.Handler, cfg *Config, name string) (http.Handler, error) { - if _, err := os.Stat(cfg.DBPath); err != nil { + _, err := os.Stat(cfg.DBPath) + if err != nil { log.Printf("[geoip2] DB not found: db=%s, name=%s, err=%v", cfg.DBPath, name, err) + return &TraefikGeoIP2{ next: next, name: name, @@ -83,14 +85,17 @@ func (mw *TraefikGeoIP2) ServeHTTP(reqWr http.ResponseWriter, req *http.Request) req.Header.Set(RegionHeader, Unknown) req.Header.Set(CityHeader, Unknown) req.Header.Set(IPAddressHeader, Unknown) + mw.next.ServeHTTP(reqWr, req) + return } ipStr := getClientIP(req, mw.preferXForwardedForHeader) + res, err := lookup(net.ParseIP(ipStr)) if err != nil { - log.Printf("[geoip2] Unable to find: ip=%s, err=%v", ipStr, err) + // log.Printf("[geoip2] Unable to find: ip=%s, err=%v", ipStr, err) res = &GeoIPResult{ country: Unknown, region: Unknown, @@ -118,9 +123,11 @@ func getClientIP(req *http.Request, preferXForwardedForHeader bool) string { // If X-Forwarded-For is not present or retrieval is not enabled, fallback to RemoteAddr remoteAddr := req.RemoteAddr + tmp, _, err := net.SplitHostPort(remoteAddr) if err == nil { remoteAddr = tmp } + return remoteAddr } diff --git a/middleware_test.go b/middleware_test.go index 544244c..53f4187 100644 --- a/middleware_test.go +++ b/middleware_test.go @@ -2,7 +2,6 @@ package traefikgeoip2_test import ( "context" - "fmt" "net/http" "net/http/httptest" "testing" @@ -23,13 +22,16 @@ func TestGeoIPConfig(t *testing.T) { } mwCfg.DBPath = "./non-existing" + mw.ResetLookup() + _, err := mw.New(context.TODO(), nil, mwCfg, "") if err != nil { t.Fatalf("Must not fail on missing DB") } mwCfg.DBPath = "justfile" + _, err = mw.New(context.TODO(), nil, mwCfg, "") if err != nil { t.Fatalf("Must not fail on invalid DB format") @@ -41,9 +43,10 @@ func TestGeoIPBasic(t *testing.T) { mwCfg.DBPath = "./GeoLite2-City.mmdb" called := false - next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { called = true }) + next := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { called = true }) mw.ResetLookup() + instance, err := mw.New(context.TODO(), next, mwCfg, "traefik-geoip2") if err != nil { t.Fatalf("Error creating %v", err) @@ -53,9 +56,11 @@ func TestGeoIPBasic(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "http://localhost", nil) instance.ServeHTTP(recorder, req) + if recorder.Result().StatusCode != http.StatusOK { t.Fatalf("Invalid return code") } + if called != true { t.Fatalf("next handler was not called") } @@ -66,9 +71,10 @@ func TestMissingGeoIPDB(t *testing.T) { mwCfg.DBPath = "./missing" called := false - next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { called = true }) + next := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { called = true }) mw.ResetLookup() + instance, err := mw.New(context.TODO(), next, mwCfg, "traefik-geoip2") if err != nil { t.Fatalf("Error creating %v", err) @@ -79,12 +85,15 @@ func TestMissingGeoIPDB(t *testing.T) { req.RemoteAddr = "1.2.3.4" instance.ServeHTTP(recorder, req) + if recorder.Result().StatusCode != http.StatusOK { t.Fatalf("Invalid return code") } + if called != true { t.Fatalf("next handler was not called") } + assertHeader(t, req, mw.CountryHeader, mw.Unknown) assertHeader(t, req, mw.RegionHeader, mw.Unknown) assertHeader(t, req, mw.CityHeader, mw.Unknown) @@ -95,12 +104,14 @@ func TestGeoIPFromRemoteAddr(t *testing.T) { mwCfg := mw.CreateConfig() mwCfg.DBPath = "./GeoLite2-City.mmdb" - next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}) + next := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}) + mw.ResetLookup() + instance, _ := mw.New(context.TODO(), next, mwCfg, "traefik-geoip2") req := httptest.NewRequest(http.MethodGet, "http://localhost", nil) - req.RemoteAddr = fmt.Sprintf("%s:9999", ValidIP) + req.RemoteAddr = ValidIP + ":9999" instance.ServeHTTP(httptest.NewRecorder(), req) assertHeader(t, req, mw.CountryHeader, "DE") assertHeader(t, req, mw.RegionHeader, "BY") @@ -108,7 +119,7 @@ func TestGeoIPFromRemoteAddr(t *testing.T) { assertHeader(t, req, mw.IPAddressHeader, ValidIP) req = httptest.NewRequest(http.MethodGet, "http://localhost", nil) - req.RemoteAddr = fmt.Sprintf("%s:9999", ValidIPNoCity) + req.RemoteAddr = ValidIPNoCity + ":9999" instance.ServeHTTP(httptest.NewRecorder(), req) assertHeader(t, req, mw.CountryHeader, "US") assertHeader(t, req, mw.RegionHeader, mw.Unknown) @@ -129,12 +140,14 @@ func TestGeoIPFromXForwardedFor(t *testing.T) { mwCfg.DBPath = "./GeoLite2-City.mmdb" mwCfg.PreferXForwardedForHeader = true - next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}) + next := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}) + mw.ResetLookup() + instance, _ := mw.New(context.TODO(), next, mwCfg, "traefik-geoip2") req := httptest.NewRequest(http.MethodGet, "http://localhost", nil) - req.RemoteAddr = fmt.Sprintf("%s:9999", ValidIP) + req.RemoteAddr = ValidIP + ":9999" req.Header.Set("X-Forwarded-For", ValidAlternateIP) instance.ServeHTTP(httptest.NewRecorder(), req) assertHeader(t, req, mw.CountryHeader, "DE") @@ -143,7 +156,7 @@ func TestGeoIPFromXForwardedFor(t *testing.T) { assertHeader(t, req, mw.IPAddressHeader, ValidAlternateIP) req = httptest.NewRequest(http.MethodGet, "http://localhost", nil) - req.RemoteAddr = fmt.Sprintf("%s:9999", ValidIP) + req.RemoteAddr = ValidIP + ":9999" req.Header.Set("X-Forwarded-For", ValidAlternateIP+",188.193.88.100") instance.ServeHTTP(httptest.NewRecorder(), req) assertHeader(t, req, mw.CountryHeader, "DE") @@ -165,12 +178,14 @@ func TestGeoIPCountryDBFromRemoteAddr(t *testing.T) { mwCfg := mw.CreateConfig() mwCfg.DBPath = "./GeoLite2-Country.mmdb" - next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {}) + next := http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {}) + mw.ResetLookup() + instance, _ := mw.New(context.TODO(), next, mwCfg, "traefik-geoip2") req := httptest.NewRequest(http.MethodGet, "http://localhost", nil) - req.RemoteAddr = fmt.Sprintf("%s:9999", ValidIP) + req.RemoteAddr = ValidIP + ":9999" instance.ServeHTTP(httptest.NewRecorder(), req) assertHeader(t, req, mw.CountryHeader, "DE") @@ -181,6 +196,7 @@ func TestGeoIPCountryDBFromRemoteAddr(t *testing.T) { func assertHeader(t *testing.T, req *http.Request, key, expected string) { t.Helper() + if req.Header.Get(key) != expected { t.Fatalf("invalid value of header [%s] != %s", key, req.Header.Get(key)) } diff --git a/types.go b/types.go index c0c77f0..0e7836f 100644 --- a/types.go +++ b/types.go @@ -10,18 +10,18 @@ import ( // Unknown constant for undefined data. const Unknown = "XX" -// DefaultDBPath default GeoIP2 database path. +// DefaultDBPath default Geoip2 database path. const DefaultDBPath = "GeoLite2-Country.mmdb" const ( // CountryHeader country header name. - CountryHeader = "X-GeoIP2-Country" + CountryHeader = "X-Geoip2-Country" // RegionHeader region header name. - RegionHeader = "X-GeoIP2-Region" + RegionHeader = "X-Geoip2-Region" // CityHeader city header name. - CityHeader = "X-GeoIP2-City" + CityHeader = "X-Geoip2-City" // IPAddressHeader city header name. - IPAddressHeader = "X-GeoIP2-IPAddress" + IPAddressHeader = "X-Geoip2-Ipaddress" ) // GeoIPResult GeoIPResult. @@ -41,17 +41,21 @@ func CreateCityDBLookup(rdr *geoip2.CityReader) LookupGeoIP2 { if err != nil { return nil, fmt.Errorf("%w", err) } + retval := GeoIPResult{ country: rec.Country.ISOCode, region: Unknown, city: Unknown, } + if city, ok := rec.City.Names["en"]; ok { retval.city = city } + if rec.Subdivisions != nil { retval.region = rec.Subdivisions[0].ISOCode } + return &retval, nil } } @@ -63,11 +67,13 @@ func CreateCountryDBLookup(rdr *geoip2.CountryReader) LookupGeoIP2 { if err != nil { return nil, fmt.Errorf("%w", err) } + retval := GeoIPResult{ country: rec.Country.ISOCode, region: Unknown, city: Unknown, } + return &retval, nil } } diff --git a/vendor/github.com/IncSW/geoip2/.gitignore b/vendor/github.com/IncSW/geoip2/.gitignore index 59b9502..d383c56 100644 --- a/vendor/github.com/IncSW/geoip2/.gitignore +++ b/vendor/github.com/IncSW/geoip2/.gitignore @@ -1,16 +1 @@ -testdata/GeoIP2-City.mmdb -testdata/GeoIP2-Connection-Type.mmdb -testdata/GeoIP2-Country.mmdb -testdata/GeoIP2-ISP.mmdb -testdata/GeoLite2-ASN.mmdb -testdata/GeoLite2-City.mmdb -testdata/GeoLite2-Country.mmdb - -testdata/GeoIP2-Anonymous-IP-Test.mmdb -testdata/GeoIP2-City-Test.mmdb -testdata/GeoIP2-Connection-Type-Test.mmdb -testdata/GeoIP2-Country-Test.mmdb -testdata/GeoIP2-Domain-Test.mmdb -testdata/GeoIP2-Enterprise-Test.mmdb -testdata/GeoIP2-ISP-Test.mmdb -testdata/GeoLite2-ASN-Test.mmdb +testdata diff --git a/vendor/github.com/IncSW/geoip2/.gitmodules b/vendor/github.com/IncSW/geoip2/.gitmodules new file mode 100644 index 0000000..8aeaa08 --- /dev/null +++ b/vendor/github.com/IncSW/geoip2/.gitmodules @@ -0,0 +1,3 @@ +[submodule "testdata/maxmind"] + path = testdata/maxmind + url = https://github.com/maxmind/MaxMind-DB diff --git a/vendor/github.com/IncSW/geoip2/LICENSE b/vendor/github.com/IncSW/geoip2/LICENSE deleted file mode 100644 index c0dfe01..0000000 --- a/vendor/github.com/IncSW/geoip2/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 Aleksey Lin (https://incsw.in) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/IncSW/geoip2/README.md b/vendor/github.com/IncSW/geoip2/README.md index d8bda1e..6afd195 100644 --- a/vendor/github.com/IncSW/geoip2/README.md +++ b/vendor/github.com/IncSW/geoip2/README.md @@ -58,6 +58,54 @@ connection_type-24 3883234 305 ns/op 32 B/op 2 allocs/o connection_type_parallel-24 34284831 32.1 ns/op 32 B/op 2 allocs/op ``` +## Supported databases types + +### Country +- GeoIP2-Country +- GeoLite2-Country +- DBIP-Country +- DBIP-Country-Lite + +### City +- GeoIP2-City +- GeoLite2-City +- GeoIP2-Enterprise +- DBIP-City-Lite + +### ISP +- GeoIP2-ISP + +### ASN +- GeoLite2-ASN +- DBIP-ASN-Lite +- DBIP-ASN-Lite (compat=GeoLite2-ASN) + +### Connection Type +- GeoIP2-Connection-Type + +### Anonymous IP +- GeoIP2-Anonymous-IP + +### Domain +- GeoIP2-Domain + +## MMDB files for tests + +MMDB files for tests are organised in their respective directories based on the source within the `testdata` repository root directory. + +### MaxMind + +These are obtained using a submodule into a `testdata/maxmind` directory. + +``` +git submodule init +git submodule update +``` + +### DB-IP + +You must obtain these files manually and place them into the `testdata/dbip` directory. + ## License [MIT License](LICENSE). diff --git a/vendor/github.com/IncSW/geoip2/anonymous_ip.go b/vendor/github.com/IncSW/geoip2/anonymous_ip.go index 0a43711..dbb15fe 100644 --- a/vendor/github.com/IncSW/geoip2/anonymous_ip.go +++ b/vendor/github.com/IncSW/geoip2/anonymous_ip.go @@ -5,7 +5,7 @@ import "errors" func readAnonymousIPMap(result *AnonymousIP, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err @@ -42,7 +42,7 @@ func readAnonymousIPMap(result *AnonymousIP, buffer []byte, mapSize uint, offset return 0, err } default: - return 0, errors.New("unknown isp key: " + string(key)) + return 0, errors.New("unknown anonymous ip key: " + string(key)) } } return offset, nil diff --git a/vendor/github.com/IncSW/geoip2/asn.go b/vendor/github.com/IncSW/geoip2/asn.go index f54aed6..c698bc6 100644 --- a/vendor/github.com/IncSW/geoip2/asn.go +++ b/vendor/github.com/IncSW/geoip2/asn.go @@ -5,7 +5,7 @@ import "errors" func readASNMap(result *ASN, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err @@ -22,7 +22,7 @@ func readASNMap(result *ASN, buffer []byte, mapSize uint, offset uint) (uint, er return 0, err } default: - return 0, errors.New("unknown isp key: " + string(key)) + return 0, errors.New("unknown asn key: " + string(key)) } } return offset, nil diff --git a/vendor/github.com/IncSW/geoip2/city.go b/vendor/github.com/IncSW/geoip2/city.go index 2c0acf9..2d1fa37 100644 --- a/vendor/github.com/IncSW/geoip2/city.go +++ b/vendor/github.com/IncSW/geoip2/city.go @@ -38,7 +38,7 @@ func readCity(city *City, buffer []byte, offset uint) (uint, error) { func readCityMap(city *City, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err diff --git a/vendor/github.com/IncSW/geoip2/common.go b/vendor/github.com/IncSW/geoip2/common.go index 17a3a1d..70ae1c9 100644 --- a/vendor/github.com/IncSW/geoip2/common.go +++ b/vendor/github.com/IncSW/geoip2/common.go @@ -4,9 +4,28 @@ import ( "encoding/binary" "errors" "math" + "net" "strconv" ) +func getNetworkString(ip net.IP, mask uint) string { + bitLen := 128 + for i := range ip { + if ip[i] != 0 { + if i == 10 { + bitLen = 32 + } + break + } + } + cidrMask := net.CIDRMask(int(mask), bitLen) + ipNet := net.IPNet{ + IP: ip.Mask(cidrMask), + Mask: cidrMask, + } + return ipNet.String() +} + func readControl(buffer []byte, offset uint) (byte, uint, uint, error) { controlByte := buffer[offset] offset++ @@ -229,7 +248,7 @@ func readStringMapMap(buffer []byte, mapSize uint, offset uint) (map[string]stri var dataType byte var size uint result := map[string]string{} - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return nil, 0, err @@ -298,7 +317,7 @@ func readStringSlice(buffer []byte, sliceSize uint, offset uint) ([]string, uint var err error var value string result := make([]string, sliceSize) - for i := uint(0); i < sliceSize; i++ { + for i := range sliceSize { value, offset, err = readString(buffer, offset) if err != nil { return nil, 0, err diff --git a/vendor/github.com/IncSW/geoip2/connection_type.go b/vendor/github.com/IncSW/geoip2/connection_type.go index eb5cf9a..9965a90 100644 --- a/vendor/github.com/IncSW/geoip2/connection_type.go +++ b/vendor/github.com/IncSW/geoip2/connection_type.go @@ -5,7 +5,7 @@ import "errors" func readConnectionTypeMap(result *ConnectionType, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err diff --git a/vendor/github.com/IncSW/geoip2/continent.go b/vendor/github.com/IncSW/geoip2/continent.go index 024a02d..431c9ed 100644 --- a/vendor/github.com/IncSW/geoip2/continent.go +++ b/vendor/github.com/IncSW/geoip2/continent.go @@ -38,7 +38,7 @@ func readContinent(continent *Continent, buffer []byte, offset uint) (uint, erro func readContinentMap(continent *Continent, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err diff --git a/vendor/github.com/IncSW/geoip2/country.go b/vendor/github.com/IncSW/geoip2/country.go index e615efa..451897c 100644 --- a/vendor/github.com/IncSW/geoip2/country.go +++ b/vendor/github.com/IncSW/geoip2/country.go @@ -38,7 +38,7 @@ func readCountry(country *Country, buffer []byte, offset uint) (uint, error) { func readCountryMap(country *Country, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err diff --git a/vendor/github.com/IncSW/geoip2/domain.go b/vendor/github.com/IncSW/geoip2/domain.go index 022ff6d..6486978 100644 --- a/vendor/github.com/IncSW/geoip2/domain.go +++ b/vendor/github.com/IncSW/geoip2/domain.go @@ -5,7 +5,7 @@ import "errors" func readDomainMap(result *Domain, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err diff --git a/vendor/github.com/IncSW/geoip2/isp.go b/vendor/github.com/IncSW/geoip2/isp.go index bc3cfbd..e93bc44 100644 --- a/vendor/github.com/IncSW/geoip2/isp.go +++ b/vendor/github.com/IncSW/geoip2/isp.go @@ -5,7 +5,7 @@ import "errors" func readISPMap(result *ISP, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err @@ -31,6 +31,16 @@ func readISPMap(result *ISP, buffer []byte, mapSize uint, offset uint) (uint, er if err != nil { return 0, err } + case "mobile_country_code": + result.MobileCountryCode, offset, err = readString(buffer, offset) + if err != nil { + return 0, err + } + case "mobile_network_code": + result.MobileNetworkCode, offset, err = readString(buffer, offset) + if err != nil { + return 0, err + } default: return 0, errors.New("unknown isp key: " + string(key)) } diff --git a/vendor/github.com/IncSW/geoip2/location.go b/vendor/github.com/IncSW/geoip2/location.go index 8fed055..c5134c3 100644 --- a/vendor/github.com/IncSW/geoip2/location.go +++ b/vendor/github.com/IncSW/geoip2/location.go @@ -38,7 +38,7 @@ func readLocation(location *Location, buffer []byte, offset uint) (uint, error) func readLocationMap(location *Location, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err diff --git a/vendor/github.com/IncSW/geoip2/metadata.go b/vendor/github.com/IncSW/geoip2/metadata.go index 3b22210..381621c 100644 --- a/vendor/github.com/IncSW/geoip2/metadata.go +++ b/vendor/github.com/IncSW/geoip2/metadata.go @@ -29,7 +29,7 @@ func readMetadata(buffer []byte) (*Metadata, error) { } var key []byte metadata := &Metadata{} - for i := uint(0); i < metadataSize; i++ { + for range metadataSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return nil, err diff --git a/vendor/github.com/IncSW/geoip2/postal.go b/vendor/github.com/IncSW/geoip2/postal.go index 4e496ec..6b5d952 100644 --- a/vendor/github.com/IncSW/geoip2/postal.go +++ b/vendor/github.com/IncSW/geoip2/postal.go @@ -38,7 +38,7 @@ func readPostal(postal *Postal, buffer []byte, offset uint) (uint, error) { func readPostalMap(postal *Postal, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err diff --git a/vendor/github.com/IncSW/geoip2/reader.go b/vendor/github.com/IncSW/geoip2/reader.go index 918b0bf..75d5275 100644 --- a/vendor/github.com/IncSW/geoip2/reader.go +++ b/vendor/github.com/IncSW/geoip2/reader.go @@ -19,28 +19,36 @@ type reader struct { nodeOffsetMult uint } -func (r *reader) getOffset(ip net.IP) (uint, error) { - pointer, err := r.lookupPointer(ip) +func (r *reader) getOffsetWithPrefix(ip net.IP) (uint, uint, error) { + pointer, prefix, err := r.lookupPointer(ip) if err != nil { - return 0, err + return 0, 0, err } offset := pointer - uint(r.metadata.NodeCount) - uint(dataSectionSeparatorSize) if offset >= uint(len(r.buffer)) { - return 0, errors.New("the MaxMind DB search tree is corrupt: " + strconv.Itoa(int(pointer))) + return 0, 0, errors.New("the MaxMind DB search tree is corrupt: " + strconv.Itoa(int(pointer))) + } + return offset, prefix, nil +} + +func (r *reader) getOffset(ip net.IP) (uint, error) { + offset, _, err := r.getOffsetWithPrefix(ip) + if err != nil { + return 0, err } return offset, nil } -func (r *reader) lookupPointer(ip net.IP) (uint, error) { +func (r *reader) lookupPointer(ip net.IP) (uint, uint, error) { if ip == nil { - return 0, errors.New("IP cannot be nil") + return 0, 0, errors.New("IP cannot be nil") } ipV4 := ip.To4() if ipV4 != nil { ip = ipV4 } if len(ip) == 16 && r.metadata.IPVersion == 4 { - return 0, errors.New("cannot look up an IPv6 address in an IPv4-only database") + return 0, 0, errors.New("cannot look up an IPv6 address in an IPv4-only database") } bitCount := uint(len(ip)) * 8 node := uint(0) @@ -59,11 +67,11 @@ func (r *reader) lookupPointer(ip net.IP) (uint, error) { } } if node == nodeCount { - return 0, ErrNotFound + return 0, 0, ErrNotFound } else if node > nodeCount { - return node, nil + return node, i, nil } - return 0, errors.New("invalid node in search tree") + return 0, 0, errors.New("invalid node in search tree") } func (r *reader) readLeft(nodeNumber uint) uint { diff --git a/vendor/github.com/IncSW/geoip2/reader_anonymous_ip.go b/vendor/github.com/IncSW/geoip2/reader_anonymous_ip.go index 1768aff..fe24fe5 100644 --- a/vendor/github.com/IncSW/geoip2/reader_anonymous_ip.go +++ b/vendor/github.com/IncSW/geoip2/reader_anonymous_ip.go @@ -2,8 +2,8 @@ package geoip2 import ( "errors" - "io/ioutil" "net" + "os" "strconv" ) @@ -63,7 +63,7 @@ func NewAnonymousIPReader(buffer []byte) (*AnonymousIPReader, error) { } func NewAnonymousIPReaderFromFile(filename string) (*AnonymousIPReader, error) { - buffer, err := ioutil.ReadFile(filename) + buffer, err := os.ReadFile(filename) if err != nil { return nil, err } diff --git a/vendor/github.com/IncSW/geoip2/reader_asn.go b/vendor/github.com/IncSW/geoip2/reader_asn.go index 44b7470..6ac8b44 100644 --- a/vendor/github.com/IncSW/geoip2/reader_asn.go +++ b/vendor/github.com/IncSW/geoip2/reader_asn.go @@ -2,8 +2,8 @@ package geoip2 import ( "errors" - "io/ioutil" "net" + "os" "strconv" ) @@ -12,7 +12,7 @@ type ASNReader struct { } func (r *ASNReader) Lookup(ip net.IP) (*ASN, error) { - offset, err := r.getOffset(ip) + offset, prefix, err := r.getOffsetWithPrefix(ip) if err != nil { return nil, err } @@ -21,6 +21,7 @@ func (r *ASNReader) Lookup(ip net.IP) (*ASN, error) { return nil, err } result := &ASN{} + result.Network = getNetworkString(ip, prefix) switch dataType { case dataTypeMap: _, err = readASNMap(result, r.decoderBuffer, size, offset) @@ -54,7 +55,9 @@ func NewASNReader(buffer []byte) (*ASNReader, error) { if err != nil { return nil, err } - if reader.metadata.DatabaseType != "GeoLite2-ASN" { + if reader.metadata.DatabaseType != "GeoLite2-ASN" && + reader.metadata.DatabaseType != "DBIP-ASN-Lite" && + reader.metadata.DatabaseType != "DBIP-ASN-Lite (compat=GeoLite2-ASN)" { return nil, errors.New("wrong MaxMind DB ASN type: " + reader.metadata.DatabaseType) } return &ASNReader{ @@ -63,7 +66,7 @@ func NewASNReader(buffer []byte) (*ASNReader, error) { } func NewASNReaderFromFile(filename string) (*ASNReader, error) { - buffer, err := ioutil.ReadFile(filename) + buffer, err := os.ReadFile(filename) if err != nil { return nil, err } diff --git a/vendor/github.com/IncSW/geoip2/reader_city.go b/vendor/github.com/IncSW/geoip2/reader_city.go index 6ccd8ce..1eabbe0 100644 --- a/vendor/github.com/IncSW/geoip2/reader_city.go +++ b/vendor/github.com/IncSW/geoip2/reader_city.go @@ -2,8 +2,8 @@ package geoip2 import ( "errors" - "io/ioutil" "net" + "os" "strconv" ) @@ -25,7 +25,7 @@ func (r *CityReader) Lookup(ip net.IP) (*CityResult, error) { } var key []byte result := &CityResult{} - for i := uint(0); i < size; i++ { + for range size { key, offset, err = readMapKey(r.decoderBuffer, offset) if err != nil { return nil, err @@ -90,7 +90,8 @@ func NewCityReader(buffer []byte) (*CityReader, error) { } if reader.metadata.DatabaseType != "GeoIP2-City" && reader.metadata.DatabaseType != "GeoLite2-City" && - reader.metadata.DatabaseType != "GeoIP2-Enterprise" { + reader.metadata.DatabaseType != "GeoIP2-Enterprise" && + reader.metadata.DatabaseType != "DBIP-City-Lite" { return nil, errors.New("wrong MaxMind DB City type: " + reader.metadata.DatabaseType) } return &CityReader{ @@ -99,7 +100,7 @@ func NewCityReader(buffer []byte) (*CityReader, error) { } func NewCityReaderFromFile(filename string) (*CityReader, error) { - buffer, err := ioutil.ReadFile(filename) + buffer, err := os.ReadFile(filename) if err != nil { return nil, err } diff --git a/vendor/github.com/IncSW/geoip2/reader_connection_type.go b/vendor/github.com/IncSW/geoip2/reader_connection_type.go index cb0e748..e27c61c 100644 --- a/vendor/github.com/IncSW/geoip2/reader_connection_type.go +++ b/vendor/github.com/IncSW/geoip2/reader_connection_type.go @@ -2,8 +2,8 @@ package geoip2 import ( "errors" - "io/ioutil" "net" + "os" "strconv" ) @@ -63,7 +63,7 @@ func NewConnectionTypeReader(buffer []byte) (*ConnectionTypeReader, error) { } func NewConnectionTypeReaderFromFile(filename string) (*ConnectionTypeReader, error) { - buffer, err := ioutil.ReadFile(filename) + buffer, err := os.ReadFile(filename) if err != nil { return nil, err } diff --git a/vendor/github.com/IncSW/geoip2/reader_country.go b/vendor/github.com/IncSW/geoip2/reader_country.go index e1e804b..a378616 100644 --- a/vendor/github.com/IncSW/geoip2/reader_country.go +++ b/vendor/github.com/IncSW/geoip2/reader_country.go @@ -2,8 +2,8 @@ package geoip2 import ( "errors" - "io/ioutil" "net" + "os" "strconv" ) @@ -25,7 +25,7 @@ func (r *CountryReader) Lookup(ip net.IP) (*CountryResult, error) { } var key []byte result := &CountryResult{} - for i := uint(0); i < size; i++ { + for range size { key, offset, err = readMapKey(r.decoderBuffer, offset) if err != nil { return nil, err @@ -69,7 +69,9 @@ func NewCountryReader(buffer []byte) (*CountryReader, error) { return nil, err } if reader.metadata.DatabaseType != "GeoIP2-Country" && - reader.metadata.DatabaseType != "GeoLite2-Country" { + reader.metadata.DatabaseType != "GeoLite2-Country" && + reader.metadata.DatabaseType != "DBIP-Country" && + reader.metadata.DatabaseType != "DBIP-Country-Lite" { return nil, errors.New("wrong MaxMind DB Country type: " + reader.metadata.DatabaseType) } return &CountryReader{ @@ -78,7 +80,7 @@ func NewCountryReader(buffer []byte) (*CountryReader, error) { } func NewCountryReaderFromFile(filename string) (*CountryReader, error) { - buffer, err := ioutil.ReadFile(filename) + buffer, err := os.ReadFile(filename) if err != nil { return nil, err } diff --git a/vendor/github.com/IncSW/geoip2/reader_domain.go b/vendor/github.com/IncSW/geoip2/reader_domain.go index 12ac07e..1c1eb40 100644 --- a/vendor/github.com/IncSW/geoip2/reader_domain.go +++ b/vendor/github.com/IncSW/geoip2/reader_domain.go @@ -2,8 +2,8 @@ package geoip2 import ( "errors" - "io/ioutil" "net" + "os" "strconv" ) @@ -63,7 +63,7 @@ func NewDomainReader(buffer []byte) (*DomainReader, error) { } func NewDomainReaderFromFile(filename string) (*DomainReader, error) { - buffer, err := ioutil.ReadFile(filename) + buffer, err := os.ReadFile(filename) if err != nil { return nil, err } diff --git a/vendor/github.com/IncSW/geoip2/reader_isp.go b/vendor/github.com/IncSW/geoip2/reader_isp.go index 068c13d..6c24155 100644 --- a/vendor/github.com/IncSW/geoip2/reader_isp.go +++ b/vendor/github.com/IncSW/geoip2/reader_isp.go @@ -2,8 +2,8 @@ package geoip2 import ( "errors" - "io/ioutil" "net" + "os" "strconv" ) @@ -63,7 +63,7 @@ func NewISPReader(buffer []byte) (*ISPReader, error) { } func NewISPReaderFromFile(filename string) (*ISPReader, error) { - buffer, err := ioutil.ReadFile(filename) + buffer, err := os.ReadFile(filename) if err != nil { return nil, err } diff --git a/vendor/github.com/IncSW/geoip2/subdivision.go b/vendor/github.com/IncSW/geoip2/subdivision.go index 26f034b..95eb916 100644 --- a/vendor/github.com/IncSW/geoip2/subdivision.go +++ b/vendor/github.com/IncSW/geoip2/subdivision.go @@ -38,7 +38,7 @@ func readSubdivisions(buffer []byte, offset uint) ([]Subdivision, uint, error) { func readSubdivisionsSlice(buffer []byte, subdivisionsSize uint, offset uint) ([]Subdivision, uint, error) { var err error subdivisions := make([]Subdivision, subdivisionsSize) - for i := uint(0); i < subdivisionsSize; i++ { + for i := range subdivisionsSize { offset, err = readSubdivision(&subdivisions[i], buffer, offset) if err != nil { return nil, 0, err @@ -80,7 +80,7 @@ func readSubdivision(subdivision *Subdivision, buffer []byte, offset uint) (uint func readSubdivisionMap(subdivision *Subdivision, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err diff --git a/vendor/github.com/IncSW/geoip2/traits.go b/vendor/github.com/IncSW/geoip2/traits.go index 9ad70f2..264607a 100644 --- a/vendor/github.com/IncSW/geoip2/traits.go +++ b/vendor/github.com/IncSW/geoip2/traits.go @@ -38,7 +38,7 @@ func readTraits(traits *Traits, buffer []byte, offset uint) (uint, error) { func readTraitsMap(traits *Traits, buffer []byte, mapSize uint, offset uint) (uint, error) { var key []byte var err error - for i := uint(0); i < mapSize; i++ { + for range mapSize { key, offset, err = readMapKey(buffer, offset) if err != nil { return 0, err @@ -99,6 +99,21 @@ func readTraitsMap(traits *Traits, buffer []byte, mapSize uint, offset uint) (ui if err != nil { return 0, err } + case "mobile_country_code": + traits.MobileCountryCode, offset, err = readString(buffer, offset) + if err != nil { + return 0, err + } + case "mobile_network_code": + traits.MobileNetworkCode, offset, err = readString(buffer, offset) + if err != nil { + return 0, err + } + case "is_anycast": + traits.IsAnycast, offset, err = readBool(buffer, offset) + if err != nil { + return 0, err + } default: return 0, errors.New("unknown traits key: " + string(key)) } diff --git a/vendor/github.com/IncSW/geoip2/types.go b/vendor/github.com/IncSW/geoip2/types.go index ff080a9..70559a2 100644 --- a/vendor/github.com/IncSW/geoip2/types.go +++ b/vendor/github.com/IncSW/geoip2/types.go @@ -21,106 +21,114 @@ const ( dataSectionSeparatorSize = 16 ) -type Continent struct { - GeoNameID uint32 - Code string - Names map[string]string -} - -type Country struct { - ISOCode string - Names map[string]string - Type string // [RepresentedCountry] - GeoNameID uint32 - Confidence uint16 // Enterprise [Country, RegisteredCountry] - IsInEuropeanUnion bool -} - -type Subdivision struct { - ISOCode string - Names map[string]string - GeoNameID uint32 - Confidence uint16 // Enterprise -} - -type City struct { - Names map[string]string - GeoNameID uint32 - Confidence uint16 // Enterprise -} - -type Location struct { - Latitude float64 - Longitude float64 - TimeZone string - AccuracyRadius uint16 - MetroCode uint16 -} - -type Postal struct { - Code string - Confidence uint16 // Enterprise -} - -type Traits struct { - StaticIPScore float64 // Enterprise - ISP string // Enterprise - Organization string // Enterprise - ConnectionType string // Enterprise - Domain string // Enterprise - UserType string // Enterprise - AutonomousSystemOrganization string // Enterprise - AutonomousSystemNumber uint32 // Enterprise - IsLegitimateProxy bool // Enterprise - IsAnonymousProxy bool - IsSatelliteProvider bool -} - -type CountryResult struct { - Continent Continent - Country Country - RegisteredCountry Country - RepresentedCountry Country - Traits Traits -} - -type CityResult struct { - Continent Continent - Country Country - Subdivisions []Subdivision - City City - Location Location - Postal Postal - RegisteredCountry Country - RepresentedCountry Country - Traits Traits -} - -type ISP struct { - AutonomousSystemNumber uint32 - AutonomousSystemOrganization string - ISP string - Organization string -} - -type ConnectionType struct { - ConnectionType string -} - -type AnonymousIP struct { - IsAnonymous bool - IsAnonymousVPN bool - IsHostingProvider bool - IsPublicProxy bool - IsTorExitNode bool - IsResidentialProxy bool -} - -type ASN struct { - AutonomousSystemNumber uint32 - AutonomousSystemOrganization string -} - -type Domain struct { - Domain string -} +type ( + Continent struct { + GeoNameID uint32 + Code string + Names map[string]string + } + + Country struct { + ISOCode string + Names map[string]string + Type string // [RepresentedCountry] + GeoNameID uint32 + Confidence uint16 // Enterprise [Country, RegisteredCountry] + IsInEuropeanUnion bool + } + + Subdivision struct { + ISOCode string + Names map[string]string + GeoNameID uint32 + Confidence uint16 // Enterprise + } + + City struct { + Names map[string]string + GeoNameID uint32 + Confidence uint16 // Enterprise + } + + Location struct { + Latitude float64 + Longitude float64 + TimeZone string + AccuracyRadius uint16 + MetroCode uint16 + } + + Postal struct { + Code string + Confidence uint16 // Enterprise + } + + Traits struct { + StaticIPScore float64 // Enterprise + ISP string // Enterprise + Organization string // Enterprise + ConnectionType string // Enterprise + Domain string // Enterprise + UserType string // Enterprise + AutonomousSystemOrganization string // Enterprise + AutonomousSystemNumber uint32 // Enterprise + IsLegitimateProxy bool // Enterprise + MobileCountryCode string // Enterprise + MobileNetworkCode string // Enterprise + IsAnonymousProxy bool + IsSatelliteProvider bool + IsAnycast bool + } + + CountryResult struct { + Continent Continent + Country Country + RegisteredCountry Country + RepresentedCountry Country + Traits Traits + } + + CityResult struct { + Continent Continent + Country Country + Subdivisions []Subdivision + City City + Location Location + Postal Postal + RegisteredCountry Country + RepresentedCountry Country + Traits Traits + } + + ISP struct { + AutonomousSystemNumber uint32 + AutonomousSystemOrganization string + ISP string + Organization string + MobileCountryCode string + MobileNetworkCode string + } + + ConnectionType struct { + ConnectionType string + } + + AnonymousIP struct { + IsAnonymous bool + IsAnonymousVPN bool + IsHostingProvider bool + IsPublicProxy bool + IsTorExitNode bool + IsResidentialProxy bool + } + + ASN struct { + AutonomousSystemNumber uint32 + AutonomousSystemOrganization string + Network string + } + + Domain struct { + Domain string + } +) diff --git a/vendor/modules.txt b/vendor/modules.txt index b44aa2e..34a90e3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,3 +1,3 @@ -# github.com/IncSW/geoip2 v0.1.1 -## explicit; go 1.14 +# github.com/IncSW/geoip2 v0.1.4 +## explicit; go 1.25 github.com/IncSW/geoip2