maxmind-geoip2 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile.lock +5 -3
  4. data/README.md +69 -0
  5. data/lib/maxmind/geoip2.rb +0 -13
  6. data/lib/maxmind/geoip2/model/abstract.rb +27 -0
  7. data/lib/maxmind/geoip2/model/anonymous_ip.rb +63 -0
  8. data/lib/maxmind/geoip2/model/asn.rb +39 -0
  9. data/lib/maxmind/geoip2/model/city.rb +28 -13
  10. data/lib/maxmind/geoip2/model/connection_type.rb +32 -0
  11. data/lib/maxmind/geoip2/model/country.rb +17 -9
  12. data/lib/maxmind/geoip2/model/domain.rb +32 -0
  13. data/lib/maxmind/geoip2/model/enterprise.rb +1 -1
  14. data/lib/maxmind/geoip2/model/isp.rb +53 -0
  15. data/lib/maxmind/geoip2/reader.rb +176 -59
  16. data/lib/maxmind/geoip2/record/abstract.rb +2 -1
  17. data/lib/maxmind/geoip2/record/city.rb +11 -6
  18. data/lib/maxmind/geoip2/record/continent.rb +11 -6
  19. data/lib/maxmind/geoip2/record/country.rb +17 -8
  20. data/lib/maxmind/geoip2/record/location.rb +18 -8
  21. data/lib/maxmind/geoip2/record/place.rb +5 -3
  22. data/lib/maxmind/geoip2/record/postal.rb +6 -2
  23. data/lib/maxmind/geoip2/record/represented_country.rb +4 -2
  24. data/lib/maxmind/geoip2/record/subdivision.rb +14 -10
  25. data/lib/maxmind/geoip2/record/traits.rb +52 -21
  26. data/maxmind-geoip2.gemspec +3 -1
  27. data/test/data/LICENSE +4 -0
  28. data/test/data/MaxMind-DB-spec.md +570 -0
  29. data/test/data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  30. data/test/data/README.md +4 -0
  31. data/test/data/bad-data/README.md +7 -0
  32. data/test/data/bad-data/libmaxminddb/libmaxminddb-offset-integer-overflow.mmdb +0 -0
  33. data/test/data/bad-data/maxminddb-golang/cyclic-data-structure.mmdb +0 -0
  34. data/test/data/bad-data/maxminddb-golang/invalid-bytes-length.mmdb +1 -0
  35. data/test/data/bad-data/maxminddb-golang/invalid-data-record-offset.mmdb +0 -0
  36. data/test/data/bad-data/maxminddb-golang/invalid-map-key-length.mmdb +0 -0
  37. data/test/data/bad-data/maxminddb-golang/invalid-string-length.mmdb +1 -0
  38. data/test/data/bad-data/maxminddb-golang/metadata-is-an-uint128.mmdb +1 -0
  39. data/test/data/bad-data/maxminddb-golang/unexpected-bytes.mmdb +0 -0
  40. data/test/data/perltidyrc +12 -0
  41. data/test/data/source-data/GeoIP2-Anonymous-IP-Test.json +48 -0
  42. data/test/data/source-data/GeoIP2-City-Test.json +12852 -0
  43. data/test/data/source-data/GeoIP2-Connection-Type-Test.json +102 -0
  44. data/test/data/source-data/GeoIP2-Country-Test.json +15916 -0
  45. data/test/data/source-data/GeoIP2-DensityIncome-Test.json +14 -0
  46. data/test/data/source-data/GeoIP2-Domain-Test.json +452 -0
  47. data/test/data/source-data/GeoIP2-Enterprise-Test.json +687 -0
  48. data/test/data/source-data/GeoIP2-ISP-Test.json +12593 -0
  49. data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +2061 -0
  50. data/test/data/source-data/GeoIP2-Static-IP-Score-Test.json +2132 -0
  51. data/test/data/source-data/GeoIP2-User-Count-Test.json +2837 -0
  52. data/test/data/source-data/GeoLite2-ASN-Test.json +37 -0
  53. data/test/data/source-data/README +15 -0
  54. data/test/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb +0 -0
  55. data/test/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb +0 -0
  56. data/test/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb +0 -0
  57. data/test/data/test-data/GeoIP2-City-Test.mmdb +0 -0
  58. data/test/data/test-data/GeoIP2-Connection-Type-Test.mmdb +0 -0
  59. data/test/data/test-data/GeoIP2-Country-Test.mmdb +0 -0
  60. data/test/data/test-data/GeoIP2-DensityIncome-Test.mmdb +0 -0
  61. data/test/data/test-data/GeoIP2-Domain-Test.mmdb +0 -0
  62. data/test/data/test-data/GeoIP2-Enterprise-Test.mmdb +0 -0
  63. data/test/data/test-data/GeoIP2-ISP-Test.mmdb +0 -0
  64. data/test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
  65. data/test/data/test-data/GeoIP2-Static-IP-Score-Test.mmdb +0 -0
  66. data/test/data/test-data/GeoIP2-User-Count-Test.mmdb +0 -0
  67. data/test/data/test-data/GeoLite2-ASN-Test.mmdb +0 -0
  68. data/test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
  69. data/test/data/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
  70. data/test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
  71. data/test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
  72. data/test/data/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
  73. data/test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
  74. data/test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
  75. data/test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
  76. data/test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
  77. data/test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
  78. data/test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
  79. data/test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  80. data/test/data/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
  81. data/test/data/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
  82. data/test/data/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
  83. data/test/data/test-data/MaxMind-DB-test-nested.mmdb +0 -0
  84. data/test/data/test-data/README.md +26 -0
  85. data/test/data/test-data/maps-with-pointers.raw +0 -0
  86. data/test/data/test-data/write-test-data.pl +641 -0
  87. data/test/data/tidyall.ini +5 -0
  88. data/test/test_model_country.rb +1 -1
  89. data/test/test_model_names.rb +1 -1
  90. data/test/test_reader.rb +79 -1
  91. metadata +85 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1a002f3e88bfdcee342f01131f73efbb7d22263e
4
- data.tar.gz: c84ca6ebd6460ff4e9e5a449198be9bd4a6cfe1e
2
+ SHA256:
3
+ metadata.gz: 59a52bbdfb71c9b0ebe0104616db7425e90f166940aa14a04aef3baa60adce7e
4
+ data.tar.gz: 51a5b6921967659ac3ee2a874b7625065b71102ce8fc5ee05b0ea7b94f34f233
5
5
  SHA512:
6
- metadata.gz: 67ef5b0bbef11189d028619f8f9543eefd270e0a4d09ce9b5c7447ccd1987438e034bf0b0394cef815dbc3ae919cfa7fa54829bbba45351a897c6828df9547cb
7
- data.tar.gz: 4f4fef06fa1d74c670e562aeca1a01eb41786af8130519270d500c72ebd93afb84038ed54e34ead1ea08e6b98828b62f3aeb1a5cffa40170db3a523d651647b5
6
+ metadata.gz: 3a75b0ac6a4da68a4c79b9a8b3a61d45c458279189edb5dc98a5366c4dbac567d6834528c6060ad3dbb759316614649b0d8d9bdf571516ca5d33d639dbf7f76c
7
+ data.tar.gz: dfa9fb9b9d1f0a10194ee80b4860cd2b83398fbdc86f042a3e9bcf0c90bd4d7621323524167f19467d46faf94bd790283d5ffdb14d8ba66841615dea4d64c37e
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0 (2020-02-20)
4
+
5
+ * Added support for the Anonymous IP, ASN, Connection Type, Domain, and ISP
6
+ databases.
7
+ * Added missing dependency on maxmind-db to the gemspec. Reported by Sean
8
+ Dilda. GitHub #4.
9
+
3
10
  ## 0.0.1 (2020-01-09)
4
11
 
5
12
  * Initial implementation with support for location databases.
@@ -4,23 +4,25 @@ GEM
4
4
  ast (2.4.0)
5
5
  jaro_winkler (1.5.4)
6
6
  maxmind-db (1.1.0)
7
- minitest (5.13.0)
7
+ minitest (5.14.0)
8
8
  parallel (1.19.1)
9
9
  parser (2.7.0.2)
10
10
  ast (~> 2.4.0)
11
11
  rainbow (3.0.0)
12
12
  rake (13.0.1)
13
- rubocop (0.79.0)
13
+ rexml (3.2.4)
14
+ rubocop (0.80.0)
14
15
  jaro_winkler (~> 1.5.1)
15
16
  parallel (~> 1.10)
16
17
  parser (>= 2.7.0.1)
17
18
  rainbow (>= 2.2.2, < 4.0)
19
+ rexml
18
20
  ruby-progressbar (~> 1.7)
19
21
  unicode-display_width (>= 1.4.0, < 1.7)
20
22
  rubocop-performance (1.5.2)
21
23
  rubocop (>= 0.71.0)
22
24
  ruby-progressbar (1.10.1)
23
- unicode-display_width (1.6.0)
25
+ unicode-display_width (1.6.1)
24
26
 
25
27
  PLATFORMS
26
28
  ruby
data/README.md CHANGED
@@ -114,6 +114,75 @@ puts record.location.longitude # -93.2323
114
114
  puts record.traits.network # 128.101.101.101/32
115
115
  ```
116
116
 
117
+ ### Anonymous IP Example
118
+
119
+ ```ruby
120
+ require 'maxmind/geoip2'
121
+
122
+ # This creates the Reader object which should be reused across lookups.
123
+ reader = MaxMind::GeoIP2::Reader.new('/usr/share/GeoIP/GeoIP2-Anonymous-IP.mmdb')
124
+
125
+ record = reader.anonymous_ip('128.101.101.101')
126
+
127
+ puts "Anonymous" if record.is_anonymous
128
+ ```
129
+
130
+ ### ASN Example
131
+
132
+ ```ruby
133
+ require 'maxmind/geoip2'
134
+
135
+ # This creates the Reader object which should be reused across lookups.
136
+ reader = MaxMind::GeoIP2::Reader.new('/usr/share/GeoIP/GeoLite2-ASN.mmdb')
137
+
138
+ record = reader.asn('128.101.101.101')
139
+
140
+ puts record.autonomous_system_number # 1234
141
+ puts record.autonomous_system_organization # Example Ltd
142
+ ```
143
+
144
+ ### Connection Type Example
145
+
146
+ ```ruby
147
+ require 'maxmind/geoip2'
148
+
149
+ # This creates the Reader object which should be reused across lookups.
150
+ reader = MaxMind::GeoIP2::Reader.new('/usr/share/GeoIP/GeoIP2-Connection-Type.mmdb')
151
+
152
+ record = reader.connection_type('128.101.101.101')
153
+
154
+ puts record.connection_type # Cable/DSL
155
+ ```
156
+
157
+ ### Domain Example
158
+
159
+ ```ruby
160
+ require 'maxmind/geoip2'
161
+
162
+ # This creates the Reader object which should be reused across lookups.
163
+ reader = MaxMind::GeoIP2::Reader.new('/usr/share/GeoIP/GeoIP2-Domain.mmdb')
164
+
165
+ record = reader.domain('128.101.101.101')
166
+
167
+ puts record.domain # example.com
168
+ ```
169
+
170
+ ### ISP Example
171
+
172
+ ```ruby
173
+ require 'maxmind/geoip2'
174
+
175
+ # This creates the Reader object which should be reused across lookups.
176
+ reader = MaxMind::GeoIP2::Reader.new('/usr/share/GeoIP/GeoIP2-ISP.mmdb')
177
+
178
+ record = reader.isp('128.101.101.101')
179
+
180
+ puts record.autonomous_system_number # 217
181
+ puts record.autonomous_system_organization # University of Minnesota
182
+ puts record.isp # University of Minnesota
183
+ puts record.organization # University of Minnesota
184
+ ```
185
+
117
186
  ## Values to use for Database or Array Keys
118
187
 
119
188
  **We strongly discourage you from using a value from any `names` property
@@ -1,16 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'maxmind/geoip2/reader'
4
-
5
- # rubocop:disable Style/ClassAndModuleChildren
6
- # :nodoc: all
7
- module MaxMind
8
- module GeoIP2
9
- module Record # :nodoc:
10
- end
11
-
12
- module Model # :nodoc:
13
- end
14
- end
15
- end
16
- # rubocop:enable Style/ClassAndModuleChildren
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ipaddr'
4
+
5
+ module MaxMind::GeoIP2::Model
6
+ # @!visibility private
7
+ class Abstract
8
+ def initialize(record)
9
+ @record = record
10
+
11
+ ip = IPAddr.new(record['ip_address']).mask(record['prefix_length'])
12
+ record['network'] = format('%s/%d', ip.to_s, record['prefix_length'])
13
+ end
14
+
15
+ protected
16
+
17
+ def get(key)
18
+ if @record.nil? || !@record.key?(key)
19
+ return false if key.start_with?('is_')
20
+
21
+ return nil
22
+ end
23
+
24
+ @record[key]
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/abstract'
4
+
5
+ module MaxMind::GeoIP2::Model
6
+ # Model class for the Anonymous IP database.
7
+ class AnonymousIP < Abstract
8
+ # This is true if the IP address belongs to any sort of anonymous network.
9
+ #
10
+ # @return [Boolean]
11
+ def anonymous?
12
+ get('is_anonymous')
13
+ end
14
+
15
+ # This is true if the IP address is registered to an anonymous VPN
16
+ # provider. If a VPN provider does not register subnets under names
17
+ # associated with them, we will likely only flag their IP ranges using the
18
+ # is_hosting_provider attribute.
19
+ #
20
+ # @return [Boolean]
21
+ def anonymous_vpn?
22
+ get('is_anonymous_vpn')
23
+ end
24
+
25
+ # This is true if the IP address belongs to a hosting or VPN provider (see
26
+ # description of the is_anonymous_vpn attribute).
27
+ #
28
+ # @return [Boolean]
29
+ def hosting_provider?
30
+ get('is_hosting_provider')
31
+ end
32
+
33
+ # The IP address that the data in the model is for.
34
+ #
35
+ # @return [String]
36
+ def ip_address
37
+ get('ip_address')
38
+ end
39
+
40
+ # The network in CIDR notation associated with the record. In particular,
41
+ # this is the largest network where all of the fields besides ip_address
42
+ # have the same value.
43
+ #
44
+ # @return [String]
45
+ def network
46
+ get('network')
47
+ end
48
+
49
+ # This is true if the IP address belongs to a public proxy.
50
+ #
51
+ # @return [Boolean]
52
+ def public_proxy?
53
+ get('is_public_proxy')
54
+ end
55
+
56
+ # This is true if the IP address is a Tor exit node.
57
+ #
58
+ # @return [Boolean]
59
+ def tor_exit_node?
60
+ get('is_tor_exit_node')
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/abstract'
4
+
5
+ module MaxMind::GeoIP2::Model
6
+ # Model class for the GeoLite2 ASN database.
7
+ class ASN < Abstract
8
+ # The autonomous system number associated with the IP address.
9
+ #
10
+ # @return [Integer, nil]
11
+ def autonomous_system_number
12
+ get('autonomous_system_number')
13
+ end
14
+
15
+ # The organization associated with the registered autonomous system number
16
+ # for the IP address.
17
+ #
18
+ # @return [String, nil]
19
+ def autonomous_system_organization
20
+ get('autonomous_system_organization')
21
+ end
22
+
23
+ # The IP address that the data in the model is for.
24
+ #
25
+ # @return [String]
26
+ def ip_address
27
+ get('ip_address')
28
+ end
29
+
30
+ # The network in CIDR notation associated with the record. In particular,
31
+ # this is the largest network where all of the fields besides ip_address
32
+ # have the same value.
33
+ #
34
+ # @return [String]
35
+ def network
36
+ get('network')
37
+ end
38
+ end
39
+ end
@@ -14,26 +14,37 @@ module MaxMind::GeoIP2::Model
14
14
  # fields in each record may be populated. See
15
15
  # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
16
16
  #
17
- # See Country for inherited methods.
17
+ # See {MaxMind::GeoIP2::Model::Country} for inherited methods.
18
18
  class City < Country
19
- # City data for the IP address. See MaxMind::GeoIP2::Record::City.
19
+ # City data for the IP address.
20
+ #
21
+ # @return [MaxMind::GeoIP2::Record::City]
20
22
  attr_reader :city
21
23
 
22
- # Location data for the IP address. See MaxMind::GeoIP2::Record::Location.
24
+ # Location data for the IP address.
25
+ #
26
+ # @return [MaxMind::GeoIP2::Record::Location]
23
27
  attr_reader :location
24
28
 
25
- # Postal data for the IP address. See MaxMind::GeoIP2::Record::Postal.
29
+ # Postal data for the IP address.
30
+ #
31
+ # @return [MaxMind::GeoIP2::Record::Postal]
26
32
  attr_reader :postal
27
33
 
28
- # An array of MaxMind::GeoIP2::Record::Subdivision objects representing the
29
- # country subdivisions for the IP address. The number and type of
30
- # subdivisions varies by country, but a subdivision is typically a state,
31
- # province, country, etc. Subdivisions are ordered from most general
32
- # (largest) to most specific (smallest). If the response did not contain
33
- # any subdivisions, this attribute will be an empty array.
34
+ # The country subdivisions for the IP address.
35
+ #
36
+ # The number and type of subdivisions varies by country, but a subdivision
37
+ # is typically a state, province, country, etc. Subdivisions are ordered
38
+ # from most general (largest) to most specific (smallest).
39
+ #
40
+ # If the response did not contain any subdivisions, this attribute will be
41
+ # an empty array.
42
+ #
43
+ # @return [Array<MaxMind::GeoIP2::Record::Subdivision>]
34
44
  attr_reader :subdivisions
35
45
 
36
- def initialize(record, locales) # :nodoc:
46
+ # @!visibility private
47
+ def initialize(record, locales)
37
48
  super(record, locales)
38
49
  @city = MaxMind::GeoIP2::Record::City.new(record['city'], locales)
39
50
  @location = MaxMind::GeoIP2::Record::Location.new(record['location'])
@@ -41,8 +52,12 @@ module MaxMind::GeoIP2::Model
41
52
  @subdivisions = create_subdivisions(record['subdivisions'], locales)
42
53
  end
43
54
 
44
- # Return an object representing the most specific subdivision returned. If
45
- # the response did not contain any subdivisions, this method returns nil.
55
+ # The most specific subdivision returned.
56
+ #
57
+ # If the response did not contain any subdivisions, this method returns
58
+ # nil.
59
+ #
60
+ # @return [MaxMind::GeoIP2::Record::Subdivision, nil]
46
61
  def most_specific_subdivision
47
62
  @subdivisions.last
48
63
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/abstract'
4
+
5
+ module MaxMind::GeoIP2::Model
6
+ # Model class for the GeoIP2 Connection Type database.
7
+ class ConnectionType < Abstract
8
+ # The connection type may take the following values: "Dialup", "Cable/DSL",
9
+ # "Corporate", "Cellular". Additional values may be added in the future.
10
+ #
11
+ # @return [String, nil]
12
+ def connection_type
13
+ get('connection_type')
14
+ end
15
+
16
+ # The IP address that the data in the model is for.
17
+ #
18
+ # @return [String]
19
+ def ip_address
20
+ get('ip_address')
21
+ end
22
+
23
+ # The network in CIDR notation associated with the record. In particular,
24
+ # this is the largest network where all of the fields besides ip_address
25
+ # have the same value.
26
+ #
27
+ # @return [String]
28
+ def network
29
+ get('network')
30
+ end
31
+ end
32
+ end
@@ -9,30 +9,38 @@ module MaxMind::GeoIP2::Model
9
9
  # Model class for the data returned by the GeoIP2 Country web service and
10
10
  # database. It is also used for GeoLite2 Country lookups.
11
11
  class Country
12
- # Continent data for the IP address. See MaxMind::GeoIP2::Record::Continent.
12
+ # Continent data for the IP address.
13
+ #
14
+ # @return [MaxMind::GeoIP2::Record::Continent]
13
15
  attr_reader :continent
14
16
 
15
17
  # Country data for the IP address. This object represents the country where
16
- # MaxMind believes the end user is located. See
17
- # MaxMind::GeoIP2::Record::Country.
18
+ # MaxMind believes the end user is located.
19
+ #
20
+ # @return [MaxMind::GeoIP2::Record::Country]
18
21
  attr_reader :country
19
22
 
20
23
  # Registered country data for the IP address. This record represents the
21
24
  # country where the ISP has registered a given IP block and may differ from
22
- # the user's country. See MaxMind::GeoIP2::Record::Country.
25
+ # the user's country.
26
+ #
27
+ # @return [MaxMind::GeoIP2::Record::Country]
23
28
  attr_reader :registered_country
24
29
 
25
30
  # Represented country data for the IP address. The represented country is
26
31
  # used for things like military bases. It is only present when the
27
- # represented country differs from the country. See
28
- # MaxMind::GeoIP2::Record::RepresentedCountry.
32
+ # represented country differs from the country.
33
+ #
34
+ # @return [MaxMind::GeoIP2::Record::RepresentedCountry]
29
35
  attr_reader :represented_country
30
36
 
31
- # Data for the traits of the IP address. See
32
- # MaxMind::GeoIP2::Record::Traits.
37
+ # Data for the traits of the IP address.
38
+ #
39
+ # @return [MaxMind::GeoIP2::Record::Traits]
33
40
  attr_reader :traits
34
41
 
35
- def initialize(record, locales) # :nodoc:
42
+ # @!visibility private
43
+ def initialize(record, locales)
36
44
  @continent = MaxMind::GeoIP2::Record::Continent.new(
37
45
  record['continent'],
38
46
  locales,
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/abstract'
4
+
5
+ module MaxMind::GeoIP2::Model
6
+ # Model class for the GeoIP2 Domain database.
7
+ class Domain < Abstract
8
+ # The second level domain associated with the IP address. This will be
9
+ # something like "example.com" or "example.co.uk", not "foo.example.com".
10
+ #
11
+ # @return [String, nil]
12
+ def domain
13
+ get('domain')
14
+ end
15
+
16
+ # The IP address that the data in the model is for.
17
+ #
18
+ # @return [String]
19
+ def ip_address
20
+ get('ip_address')
21
+ end
22
+
23
+ # The network in CIDR notation associated with the record. In particular,
24
+ # this is the largest network where all of the fields besides ip_address
25
+ # have the same value.
26
+ #
27
+ # @return [String]
28
+ def network
29
+ get('network')
30
+ end
31
+ end
32
+ end