Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module github.com/ipinfo/mmdbctl

go 1.20
go 1.24.0

require (
github.com/edsrzf/mmap-go v1.1.0
github.com/fatih/color v1.16.0
github.com/ipinfo/cli v0.0.0-20240814004006-a9ca4b1d939d
github.com/maxmind/mmdbwriter v1.0.1-0.20231024181307-469cd9b959b4
github.com/oschwald/maxminddb-golang v1.12.0
github.com/oschwald/maxminddb-golang/v2 v2.1.1
github.com/spf13/pflag v1.0.5
)

Expand All @@ -16,8 +16,9 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/oschwald/maxminddb-golang v1.12.0 // indirect
github.com/posener/script v1.2.0 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/sys v0.38.0 // indirect
)
12 changes: 9 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
Expand All @@ -19,18 +20,23 @@ github.com/maxmind/mmdbwriter v1.0.1-0.20231024181307-469cd9b959b4 h1:rF6qXloekm
github.com/maxmind/mmdbwriter v1.0.1-0.20231024181307-469cd9b959b4/go.mod h1:6F/4tSDsJ8Y9UFVnehdZEIS220Uz62E7lbo8ZS0DehI=
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
github.com/oschwald/maxminddb-golang/v2 v2.1.1 h1:lA8FH0oOrM4u7mLvowq8IT6a3Q/qEnqRzLQn9eH5ojc=
github.com/oschwald/maxminddb-golang/v2 v2.1.1/go.mod h1:PLdx6PR+siSIoXqqy7C7r3SB3KZnhxWr1Dp6g0Hacl8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/script v1.2.0 h1:DrZz0qFT8lCLkYNi1PleLDANFnKxJ2VmlNPJbAkVLsE=
github.com/posener/script v1.2.0/go.mod h1:s4sVvRXtdc/1aK6otTSeW2BVXndO8MsoOVUwK74zcg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4=
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
34 changes: 13 additions & 21 deletions lib/cmd_diff.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package lib

import (
"bytes"
"errors"
"fmt"
"net"
"net/netip"
"reflect"

"github.com/oschwald/maxminddb-golang"
"github.com/oschwald/maxminddb-golang/v2"
"github.com/spf13/pflag"
)

Expand Down Expand Up @@ -51,33 +50,32 @@ func doDiff(
newDbStr string,
oldDb *maxminddb.Reader,
oldDbStr string,
) (map[interface{}]*net.IPNet, map[interface{}]cmdDiffRecord, error) {
modifiedSubnets := map[interface{}]*net.IPNet{}
modifiedRecords := map[interface{}]cmdDiffRecord{}
networksA := newDb.Networks(maxminddb.SkipAliasedNetworks)
for networksA.Next() {
) (map[netip.Prefix]netip.Prefix, map[netip.Prefix]cmdDiffRecord, error) {
modifiedSubnets := map[netip.Prefix]netip.Prefix{}
modifiedRecords := map[netip.Prefix]cmdDiffRecord{}
for result := range newDb.Networks() {
var recordA interface{}
var recordB interface{}

subnetA, err := networksA.Network(&recordA)
if err != nil {
if err := result.Decode(&recordA); err != nil {
return nil, nil, fmt.Errorf(
"failed to get record for subnet from %v: %w",
newDbStr, err,
)
}
subnetA := result.Prefix()

subnetB, _, err := oldDb.LookupNetwork(subnetA.IP, &recordB)
if err != nil {
lookupResult := oldDb.Lookup(subnetA.Addr())
if err := lookupResult.Decode(&recordB); err != nil {
return nil, nil, fmt.Errorf(
"failed to get record for IP %v from %v: %w",
subnetA.IP, oldDbStr, err,
subnetA.Addr(), oldDbStr, err,
)
}
subnetB := lookupResult.Prefix()

// unequal subnets?
if bytes.Compare(subnetA.IP, subnetB.IP) != 0 ||
bytes.Compare(subnetA.Mask, subnetB.Mask) != 0 {
if subnetA != subnetB {
modifiedSubnets[subnetA] = subnetB
continue
}
Expand All @@ -90,12 +88,6 @@ func doDiff(
}
}
}
if networksA.Err() != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No sure if you need similar handling still

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed anymore, the error is now embedded in the result struct. If there is an error it will raise at decode time.

return nil, nil, fmt.Errorf(
"failed traversing networks of %v: %w",
newDbStr, networksA.Err(),
)
}

return modifiedSubnets, modifiedRecords, nil
}
Expand Down
26 changes: 8 additions & 18 deletions lib/cmd_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"os"
"strings"

"github.com/oschwald/maxminddb-golang"
"github.com/oschwald/maxminddb-golang/v2"
"github.com/spf13/pflag"
)

Expand Down Expand Up @@ -112,13 +112,12 @@ func CmdExport(f CmdExportFlags, args []string, printHelp func()) error {
tsvwr := NewTsvWriter(outFile)
wr = tsvwr
}
record := make(map[string]interface{})
networks := db.Networks(maxminddb.SkipAliasedNetworks)
for networks.Next() {
subnet, err := networks.Network(&record)
if err != nil {
for result := range db.Networks() {
record := make(map[string]interface{})
if err := result.Decode(&record); err != nil {
return fmt.Errorf("failed to get record for next subnet: %w", err)
}
subnet := result.Prefix()

recordStr := mapInterfaceToStr(record)
if !hdrWritten {
Expand Down Expand Up @@ -147,25 +146,16 @@ func CmdExport(f CmdExportFlags, args []string, printHelp func()) error {
if err := wr.Error(); err != nil {
return fmt.Errorf("writer had failure: %w", err)
}
if err := networks.Err(); err != nil {
return fmt.Errorf("failed networks traversal: %w", err)
}
} else if f.Format == "json" {
networks := db.Networks(maxminddb.SkipAliasedNetworks)
enc := json.NewEncoder(outFile)
for networks.Next() {
for result := range db.Networks() {
record := make(map[string]interface{})

subnet, err := networks.Network(&record)
if err != nil {
if err := result.Decode(&record); err != nil {
return fmt.Errorf("failed to get record for next subnet: %w", err)
}
record["range"] = subnet.String()
record["range"] = result.Prefix().String()
enc.Encode(record)
}
if err := networks.Err(); err != nil {
return fmt.Errorf("failed networks traversal: %w", err)
}
}
return nil
}
10 changes: 5 additions & 5 deletions lib/cmd_import_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package lib

import (
"net"
"net/netip"
"os"
"path/filepath"
"strings"
"testing"

"github.com/oschwald/maxminddb-golang"
"github.com/oschwald/maxminddb-golang/v2"
)

// verifyMMDBContent is a test helper that verifies MMDB file contains expected entries
Expand All @@ -29,14 +29,14 @@ func verifyMMDBContent(t *testing.T, mmdbPath string, testCases []struct {
defer db.Close()

for _, tc := range testCases {
ip := net.ParseIP(tc.ip)
if ip == nil {
addr, err := netip.ParseAddr(tc.ip)
if err != nil {
t.Errorf("failed to parse IP: %s", tc.ip)
continue
}

var record map[string]interface{}
err := db.Lookup(ip, &record)
err = db.Lookup(addr).Decode(&record)
if err != nil {
t.Errorf("failed to lookup IP %s: %s", tc.ip, err.Error())
continue
Expand Down
2 changes: 1 addition & 1 deletion lib/cmd_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"strings"

"github.com/fatih/color"
"github.com/oschwald/maxminddb-golang"
"github.com/oschwald/maxminddb-golang/v2"
"github.com/spf13/pflag"
)

Expand Down
15 changes: 13 additions & 2 deletions lib/cmd_read.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import (
"encoding/csv"
"encoding/json"
"fmt"
"net/netip"
"os"

"github.com/fatih/color"
"github.com/ipinfo/cli/lib/iputil"
"github.com/oschwald/maxminddb-golang"
"github.com/oschwald/maxminddb-golang/v2"
"github.com/spf13/pflag"
)

Expand Down Expand Up @@ -102,7 +103,17 @@ func CmdRead(f CmdReadFlags, args []string, printHelp func()) error {
}
for _, ip := range ips {
record := make(map[string]interface{})
if err := db.Lookup(ip, &record); err != nil || len(record) == 0 {
addr, ok := netip.AddrFromSlice(ip)
if !ok {
if !requiresHdr {
fmt.Fprintf(os.Stderr,
"err: invalid IP address %s\n",
ip.String(),
)
}
continue
}
if err := db.Lookup(addr).Decode(&record); err != nil || len(record) == 0 {
if !requiresHdr {
fmt.Fprintf(os.Stderr,
"err: couldn't get data for %s\n",
Expand Down
2 changes: 1 addition & 1 deletion lib/cmd_verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"errors"
"fmt"

"github.com/oschwald/maxminddb-golang"
"github.com/oschwald/maxminddb-golang/v2"
"github.com/spf13/pflag"
)

Expand Down