diff --git a/README.md b/README.md index 55490de..55f5a7a 100644 --- a/README.md +++ b/README.md @@ -28,34 +28,38 @@ __Step 3: Build your MMDBs__ ========== building My IPv4 GeoIP DB - database options set: IncludeReservedNetworks=true IPVersion=4 RecordSize=24 + database options set: IPVersion=4 RecordSize=24 (IncludeReservedNetworks=true DisableIPv4Aliasing=true) + database types: autonomous_system_number, autonomous_system_organization, country.iso_code optimizations set: FloatDecimals=2 ForceIPVersion=true MaxPrefix=0 + conditional resets: [{IfChanged:[country] Reset:[location]}] --- - processing input/asn-ipv4.csv... - inserted 100000 entries - batch in 314ms (3µs/op) - inserted 200000 entries - batch in 287ms (3µs/op) - inserted 300000 entries - batch in 281ms (3µs/op) - inserted 368765 entries - batch in 206ms (2µs/op) + processing input/iptoasn-asn-ipv4.csv... + inserted 100000 entries - batch in 356ms (4µs/op) + inserted 200000 entries - batch in 327ms (3µs/op) + inserted 300000 entries - batch in 322ms (3µs/op) + inserted 360970 entries - batch in 224ms (2µs/op) --- processing input/geo-whois-asn-country-ipv4.csv... - inserted 100000 entries - batch in 931ms (9µs/op) - inserted 200000 entries - batch in 684ms (7µs/op) - inserted 238714 entries - batch in 353ms (4µs/op) + inserted 100000 entries - batch in 1.012s (10µs/op) + inserted 200000 entries - batch in 889ms (9µs/op) + inserted 238756 entries - batch in 418ms (4µs/op) --- - My IPv4 GeoIP DB finished: inserted 607479 entries in 3s, resulting in 7MB + My IPv4 GeoIP DB finished: inserted 599726 entries in 4s, resulting in 7.67 MB written to output/geoip-v4.mmdb ========== building My IPv6 GeoIP DB - database options set: IncludeReservedNetworks=true IPVersion=6 RecordSize=24 + database options set: IPVersion=6 RecordSize=24 (IncludeReservedNetworks=true DisableIPv4Aliasing=true) + database types: autonomous_system_number, autonomous_system_organization, country.iso_code optimizations set: FloatDecimals=2 ForceIPVersion=true MaxPrefix=0 + conditional resets: [{IfChanged:[country] Reset:[location]}] --- - processing input/asn-ipv6.csv... - inserted 86473 entries - batch in 382ms (4µs/op) + processing input/iptoasn-asn-ipv6.csv... + inserted 81939 entries - batch in 352ms (4µs/op) --- processing input/geo-whois-asn-country-ipv6.csv... - inserted 82381 entries - batch in 1.389s (14µs/op) + inserted 82321 entries - batch in 1.609s (16µs/op) --- - My IPv6 GeoIP DB finished: inserted 168854 entries in 2s, resulting in 5MB + My IPv6 GeoIP DB finished: inserted 164260 entries in 2s, resulting in 5.42 MB written to output/geoip-v6.mmdb __Step 4: Check your MMDBs__ @@ -64,43 +68,43 @@ __Step 4: Check your MMDBs__ [...] - loading output/geoip-v4.mmdb with 7.85 MB + loading output/geoip-v4.mmdb with 7.67 MB Running all checks: Probing: ..............................................................................................................................................................................................................................................................:: analyzed with 0 lookup errors - Total= 14462461 Country=99.57% Coords=0.00% ASN=87.04% ASOrg=87.04% AC=0.00% SP=0.00% AP=0.00% + Total= 14462461 Country=99.57% Coords=0.00% ASN=82.40% ASOrg=82.40% AC=0.00% SP=0.00% AP=0.00% Network Mask Stats: - Total= 770040 Country=99.94% Coords=0.00% ASN=89.10% ASOrg=89.10% AC=0.00% SP=0.00% AP=0.00% + Total= 800822 Country=99.93% Coords=0.00% ASN=85.24% ASOrg=85.24% AC=0.00% SP=0.00% AP=0.00% CIDR=/ 7 Total= 1 Country=100.00% Coords=0.00% ASN=100.00% ASOrg=100.00% AC=0.00% SP=0.00% AP=0.00% CIDR=/ 8 Total= 6 Country=100.00% Coords=0.00% ASN=100.00% ASOrg=100.00% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 9 Total= 9 Country=100.00% Coords=0.00% ASN=88.89% ASOrg=88.89% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 10 Total= 35 Country=100.00% Coords=0.00% ASN=88.57% ASOrg=88.57% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 11 Total= 90 Country=100.00% Coords=0.00% ASN=88.89% ASOrg=88.89% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 12 Total= 273 Country=100.00% Coords=0.00% ASN=89.74% ASOrg=89.74% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 13 Total= 561 Country=100.00% Coords=0.00% ASN=90.02% ASOrg=90.02% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 14 Total= 1321 Country=100.00% Coords=0.00% ASN=87.06% ASOrg=87.06% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 15 Total= 2743 Country=100.00% Coords=0.00% ASN=83.81% ASOrg=83.81% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 16 Total= 10414 Country=99.96% Coords=0.00% ASN=83.52% ASOrg=83.52% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 17 Total= 7469 Country=100.00% Coords=0.00% ASN=87.36% ASOrg=87.36% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 18 Total= 13200 Country=99.97% Coords=0.00% ASN=87.29% ASOrg=87.29% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 19 Total= 24993 Country=99.98% Coords=0.00% ASN=88.65% ASOrg=88.65% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 20 Total= 38550 Country=99.96% Coords=0.00% ASN=88.21% ASOrg=88.21% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 21 Total= 53388 Country=99.95% Coords=0.00% ASN=86.92% ASOrg=86.92% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 22 Total= 115769 Country=99.92% Coords=0.00% ASN=88.42% ASOrg=88.42% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 23 Total= 118221 Country=99.93% Coords=0.00% ASN=84.43% ASOrg=84.43% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 24 Total= 228493 Country=99.90% Coords=0.00% ASN=86.77% ASOrg=86.77% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 25 Total= 10503 Country=100.00% Coords=0.00% ASN=96.15% ASOrg=96.15% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 26 Total= 15323 Country=100.00% Coords=0.00% ASN=96.80% ASOrg=96.80% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 27 Total= 21747 Country=100.00% Coords=0.00% ASN=97.20% ASOrg=97.20% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 28 Total= 28184 Country=100.00% Coords=0.00% ASN=98.64% ASOrg=98.64% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 29 Total= 30933 Country=100.00% Coords=0.00% ASN=98.97% ASOrg=98.97% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 30 Total= 23054 Country=100.00% Coords=0.00% ASN=99.51% ASOrg=99.51% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 31 Total= 7488 Country=100.00% Coords=0.00% ASN=99.49% ASOrg=99.49% AC=0.00% SP=0.00% AP=0.00% - CIDR=/ 32 Total= 17272 Country=100.00% Coords=0.00% ASN=99.58% ASOrg=99.58% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 9 Total= 8 Country=100.00% Coords=0.00% ASN=62.50% ASOrg=62.50% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 10 Total= 35 Country=100.00% Coords=0.00% ASN=71.43% ASOrg=71.43% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 11 Total= 85 Country=100.00% Coords=0.00% ASN=78.82% ASOrg=78.82% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 12 Total= 278 Country=100.00% Coords=0.00% ASN=83.45% ASOrg=83.45% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 13 Total= 569 Country=100.00% Coords=0.00% ASN=87.17% ASOrg=87.17% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 14 Total= 1327 Country=100.00% Coords=0.00% ASN=84.78% ASOrg=84.78% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 15 Total= 2760 Country=100.00% Coords=0.00% ASN=82.14% ASOrg=82.14% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 16 Total= 10167 Country=99.95% Coords=0.00% ASN=80.14% ASOrg=80.14% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 17 Total= 7563 Country=100.00% Coords=0.00% ASN=83.49% ASOrg=83.49% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 18 Total= 13354 Country=99.97% Coords=0.00% ASN=83.91% ASOrg=83.91% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 19 Total= 25354 Country=99.98% Coords=0.00% ASN=84.98% ASOrg=84.98% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 20 Total= 39116 Country=99.96% Coords=0.00% ASN=84.53% ASOrg=84.53% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 21 Total= 54874 Country=99.95% Coords=0.00% ASN=82.60% ASOrg=82.60% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 22 Total= 117368 Country=99.94% Coords=0.00% ASN=83.46% ASOrg=83.46% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 23 Total= 124541 Country=99.94% Coords=0.00% ASN=79.46% ASOrg=79.46% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 24 Total= 240113 Country=99.92% Coords=0.00% ASN=81.46% ASOrg=81.46% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 25 Total= 10581 Country=99.94% Coords=0.00% ASN=95.53% ASOrg=95.53% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 26 Total= 15500 Country=99.95% Coords=0.00% ASN=96.35% ASOrg=96.35% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 27 Total= 22059 Country=99.91% Coords=0.00% ASN=96.78% ASOrg=96.78% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 28 Total= 30393 Country=99.91% Coords=0.00% ASN=98.38% ASOrg=98.38% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 29 Total= 34128 Country=99.89% Coords=0.00% ASN=98.76% ASOrg=98.76% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 30 Total= 24836 Country=99.81% Coords=0.00% ASN=99.44% ASOrg=99.44% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 31 Total= 7847 Country=99.86% Coords=0.00% ASN=98.89% ASOrg=98.89% AC=0.00% SP=0.00% AP=0.00% + CIDR=/ 32 Total= 17959 Country=99.96% Coords=0.00% ASN=99.20% ASOrg=99.20% AC=0.00% SP=0.00% AP=0.00% This check queries the following fields: @@ -159,26 +163,60 @@ There are three special fields which are not defined in the types: These are used to derive the IP ranges the data (row, entry) is applicable for. -### CSV +##### CSV Define columns with `fields`, which must match a field defined in the `types`: - fields: ["from", "to", "autonomous_system_number", "autonomous_system_organization"] + databases: + ... + fields: ["from", "to", "autonomous_system_number", "autonomous_system_organization"] All rows must have exactly the specified amount of columns. Use `-` to define a column you are not using, eg.: - fields: ["from", "to", "country.iso_code", "-", "-", "-", "-", "location.latitude", "location.longitude", "-"] + databases: + ... + fields: ["from", "to", "country.iso_code", "-", "-", "-", "-", "location.latitude", "location.longitude", "-"] -### IPFire +##### IPFire The [IPFire Firewall](https://www.ipfire.org/) maintains a [geoip database in a custom format](https://git.ipfire.org/?p=location/location-database.git;a=summary), which notably includes IP categorization, such as `is-anycast`. Define fields with `fieldMap`, mapping IPFire database keys to `types`: - fieldMap: - "aut-num": "autonomous_system_number" - "name": "autonomous_system_organization" - "country": "country.iso_code" - "is-anycast": "is_anycast" - "is-satellite-provider": "is_satellite_provider" - "is-anonymous-proxy": "is_anonymous_proxy" + databases: + ... + fieldMap: + "aut-num": "autonomous_system_number" + "name": "autonomous_system_organization" + "country": "country.iso_code" + "is-anycast": "is_anycast" + "is-satellite-provider": "is_satellite_provider" + "is-anonymous-proxy": "is_anonymous_proxy" + +### Defaults + +If you are building more than one mmdb file, you can use defaults to apply certain configuration to all databases. +A common case is when you build an IPv4 and IPv6 database separately. + +When using defaults, always check if they are applied correctly by checking the logs when building the databases. + + defaults: + types: # Entries are merged. + # Databases inherit defaults types, if not yet set. + # You can define a type with a "-" type string to ignore a default in a database config. + "country.iso_code": string + "location.latitude": float32 + "location.longitude": float32 + "autonomous_system_organization": string + "autonomous_system_number": uint32 + "is_anycast": bool + "is_satellite_provider": bool + "is_anonymous_proxy": bool + optimize: # Entries are used as default separately. + floatDecimals: 2 # Default is used when database value is 0. + forceIPVersion: true # Default is used when database value is not defined. + maxPrefix: 24 # Default is used when database value is 0. + merge: # Entries are used as default separately. + conditionalResets: # Default is used when not defined or empty in database config. + - ifChanged: ["country"] + reset: ["location"] diff --git a/cmd/mmdbmeld/main.go b/cmd/mmdbmeld/main.go index 9a8cc83..762a7d3 100644 --- a/cmd/mmdbmeld/main.go +++ b/cmd/mmdbmeld/main.go @@ -23,6 +23,11 @@ func main() { for _, db := range c.Databases { fmt.Printf("\n==========\nbuilding %s\n", db.Name) + // Apply defaults. + dbP := &db //nolint:gosec,scopelint // Only used within loop. + c.Defaults.ApplyTo(dbP) + + // Load sources for database. sources, err := mmdbmeld.LoadSources(db) if err != nil { fmt.Println(err) @@ -42,6 +47,7 @@ func main() { } }() + // Read all sources and write to mmdb. err = mmdbmeld.WriteMMDB(db, sources, updates) if err != nil { fmt.Println(err) diff --git a/config.go b/config.go index 16ab799..064b928 100644 --- a/config.go +++ b/config.go @@ -9,6 +9,7 @@ import ( // Config is the geoip build config. type Config struct { Databases []DatabaseConfig `yaml:"databases"` + Defaults DefaultConfig `yaml:"defaults"` } // DatabaseConfig holds the config for building one database. @@ -22,6 +23,13 @@ type DatabaseConfig struct { Merge MergeConfig `yaml:"merge"` } +// DefaultConfig holds a subset of DatabaseConfig fields to be used as a default config. +type DefaultConfig struct { + Types map[string]string `yaml:"types"` + Optimize Optimizations `yaml:"optimize"` + Merge MergeConfig `yaml:"merge"` +} + // MMDBConfig holds mmdb specific config. type MMDBConfig struct { IPVersion int `yaml:"ipVersion"` @@ -37,9 +45,14 @@ type DatabaseInput struct { // Optimizations holds optimization config. type Optimizations struct { - FloatDecimals int `yaml:"floatDecimals"` - ForceIPVersion bool `yaml:"forceIPVersion"` - MaxPrefix int `yaml:"maxPrefix"` + FloatDecimals int `yaml:"floatDecimals"` + ForceIPVersion *bool `yaml:"forceIPVersion"` + MaxPrefix int `yaml:"maxPrefix"` +} + +// ForceIPVersionEnabled reports whether ForceIPVersion is set and true. +func (o Optimizations) ForceIPVersionEnabled() bool { + return o.ForceIPVersion != nil && *o.ForceIPVersion } // MergeConfig holds merge configuration. @@ -62,3 +75,33 @@ func LoadConfig(filePath string) (*Config, error) { config := &Config{} return config, yaml.Unmarshal(data, config) } + +// ApplyTo applies the default config to the given database config. +func (d DefaultConfig) ApplyTo(c *DatabaseConfig) { + // Add all missing default types. + if c.Types == nil { + c.Types = make(map[string]string) + } + for k, v := range d.Types { + _, ok := c.Types[k] + if !ok { + c.Types[k] = v + } + } + + // Apply Optimizations. + if c.Optimize.FloatDecimals == 0 && d.Optimize.FloatDecimals != 0 { + c.Optimize.FloatDecimals = d.Optimize.FloatDecimals + } + if c.Optimize.ForceIPVersion == nil && d.Optimize.ForceIPVersion != nil { + c.Optimize.ForceIPVersion = d.Optimize.ForceIPVersion + } + if c.Optimize.MaxPrefix == 0 && d.Optimize.MaxPrefix != 0 { + c.Optimize.MaxPrefix = d.Optimize.MaxPrefix + } + + // Apply Merge Config. + if len(c.Merge.ConditionalResets) == 0 && len(d.Merge.ConditionalResets) != 0 { + c.Merge.ConditionalResets = d.Merge.ConditionalResets + } +} diff --git a/source_csv.go b/source_csv.go index 0ba2b06..24dad58 100644 --- a/source_csv.go +++ b/source_csv.go @@ -83,12 +83,15 @@ func (csv *CSVSource) NextEntry() (*SourceEntry, error) { if v4 := se.To.To4(); v4 != nil { se.To = v4 } - case "-": + case "", "-": // Ignore default: - se.Values[fieldName] = SourceValue{ - Type: csv.types[fieldName], - Value: row[i], + fieldType, ok := csv.types[fieldName] + if ok && fieldType != "" && fieldType != "-" { + se.Values[fieldName] = SourceValue{ + Type: csv.types[fieldName], + Value: row[i], + } } } } diff --git a/source_ipfire.go b/source_ipfire.go index 131a4cd..3c0d9c9 100644 --- a/source_ipfire.go +++ b/source_ipfire.go @@ -152,9 +152,12 @@ func (ipf *IPFireSource) SourceEntryFromMimeHeader(data textproto.MIMEHeader) (* if fieldName, ok := ipf.fieldMap["aut-num"]; ok { if asNum := data.Get("aut-num"); asNum != "" { asNum := strings.TrimPrefix(asNum, "AS") - se.Values[fieldName] = SourceValue{ - Type: ipf.types[fieldName], - Value: asNum, + fieldType, ok := ipf.types[fieldName] + if ok && fieldType != "" && fieldType != "-" { + se.Values[fieldName] = SourceValue{ + Type: fieldType, + Value: asNum, + } } } } @@ -162,9 +165,12 @@ func (ipf *IPFireSource) SourceEntryFromMimeHeader(data textproto.MIMEHeader) (* // Parse AS Org. if fieldName, ok := ipf.fieldMap["name"]; ok { if asOrg := data.Get("name"); asOrg != "" { - se.Values[fieldName] = SourceValue{ - Type: ipf.types[fieldName], - Value: asOrg, + fieldType, ok := ipf.types[fieldName] + if ok && fieldType != "" && fieldType != "-" { + se.Values[fieldName] = SourceValue{ + Type: fieldType, + Value: asOrg, + } } } } @@ -172,9 +178,12 @@ func (ipf *IPFireSource) SourceEntryFromMimeHeader(data textproto.MIMEHeader) (* // Parse country. if fieldName, ok := ipf.fieldMap["country"]; ok { if country := data.Get("country"); len(country) == 2 { - se.Values[fieldName] = SourceValue{ - Type: ipf.types[fieldName], - Value: country, + fieldType, ok := ipf.types[fieldName] + if ok && fieldType != "" && fieldType != "-" { + se.Values[fieldName] = SourceValue{ + Type: fieldType, + Value: country, + } } } } @@ -182,33 +191,45 @@ func (ipf *IPFireSource) SourceEntryFromMimeHeader(data textproto.MIMEHeader) (* // Parse flags. if fieldName, ok := ipf.fieldMap["is-anycast"]; ok { if flag := data.Get("is-anycast"); flag != "" { - se.Values[fieldName] = SourceValue{ - Type: ipf.types[fieldName], - Value: "true", + fieldType, ok := ipf.types[fieldName] + if ok && fieldType != "" && fieldType != "-" { + se.Values[fieldName] = SourceValue{ + Type: fieldType, + Value: "true", + } } } } if fieldName, ok := ipf.fieldMap["is-satellite-provider"]; ok { if flag := data.Get("is-satellite-provider"); flag != "" { - se.Values[fieldName] = SourceValue{ - Type: ipf.types[fieldName], - Value: "true", + fieldType, ok := ipf.types[fieldName] + if ok && fieldType != "" && fieldType != "-" { + se.Values[fieldName] = SourceValue{ + Type: fieldType, + Value: "true", + } } } } if fieldName, ok := ipf.fieldMap["is-anonymous-proxy"]; ok { if flag := data.Get("is-anonymous-proxy"); flag != "" { - se.Values[fieldName] = SourceValue{ - Type: ipf.types[fieldName], - Value: "true", + fieldType, ok := ipf.types[fieldName] + if ok && fieldType != "" && fieldType != "-" { + se.Values[fieldName] = SourceValue{ + Type: fieldType, + Value: "true", + } } } } if fieldName, ok := ipf.fieldMap["drop"]; ok { if flag := data.Get("drop"); flag != "" { - se.Values[fieldName] = SourceValue{ - Type: ipf.types[fieldName], - Value: "true", + fieldType, ok := ipf.types[fieldName] + if ok && fieldType != "" && fieldType != "-" { + se.Values[fieldName] = SourceValue{ + Type: fieldType, + Value: "true", + } } } } diff --git a/writer.go b/writer.go index d3f83b1..f974c07 100644 --- a/writer.go +++ b/writer.go @@ -5,6 +5,8 @@ import ( "net" "net/netip" "os" + "slices" + "strings" "time" "github.com/maxmind/mmdbwriter" @@ -31,15 +33,27 @@ func WriteMMDB(dbConfig DatabaseConfig, sources []Source, updates chan string) e return fmt.Errorf("failed to create mmdb writer for %s: %w", dbConfig.Name, err) } sendUpdate(updates, fmt.Sprintf( - "database options set: IncludeReservedNetworks=%v IPVersion=%d RecordSize=%d", - opts.IncludeReservedNetworks, + "database options set: IPVersion=%d RecordSize=%d (IncludeReservedNetworks=%v DisableIPv4Aliasing=%v)", opts.IPVersion, opts.RecordSize, + opts.IncludeReservedNetworks, + opts.DisableIPv4Aliasing, + )) + typeKeys := make([]string, 0, len(dbConfig.Types)) + for k, v := range dbConfig.Types { + if v != "-" && v != "" { + typeKeys = append(typeKeys, k) + } + } + slices.Sort[[]string, string](typeKeys) + sendUpdate(updates, fmt.Sprintf( + "database types: %s", + strings.Join(typeKeys, ", "), )) sendUpdate(updates, fmt.Sprintf( "optimizations set: FloatDecimals=%d ForceIPVersion=%v MaxPrefix=%d", dbConfig.Optimize.FloatDecimals, - dbConfig.Optimize.ForceIPVersion, + dbConfig.Optimize.ForceIPVersionEnabled(), dbConfig.Optimize.MaxPrefix, )) sendUpdate(updates, fmt.Sprintf( @@ -88,7 +102,7 @@ func WriteMMDB(dbConfig DatabaseConfig, sources []Source, updates chan string) e // Handle Network/Prefix Format. // Ignore entry if the IP version is forced and it does not match the mmdb DB. - if dbConfig.Optimize.ForceIPVersion && ipVersion(entry.Net.IP) != opts.IPVersion { + if dbConfig.Optimize.ForceIPVersionEnabled() && ipVersion(entry.Net.IP) != opts.IPVersion { continue } @@ -109,7 +123,7 @@ func WriteMMDB(dbConfig DatabaseConfig, sources []Source, updates chan string) e // Handle From-To IP Format. // Ignore entry if the IP version is forced and it does not match the mmdb DB. - if dbConfig.Optimize.ForceIPVersion && ipVersion(entry.From) != opts.IPVersion { + if dbConfig.Optimize.ForceIPVersionEnabled() && ipVersion(entry.From) != opts.IPVersion { continue }