iptoasn 0.6.0 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7d28863be637ca0ad4c3b7b7ac648828fb963f3fed53bc237e695c83876737f
4
- data.tar.gz: ac59b82846fcacd8e5d584ca7d10804dfe9097cd43d889bd53339c503686c011
3
+ metadata.gz: d832e981a75509b4b3d425c946c9acf45b8805bef9efa92d1261ec1331203f71
4
+ data.tar.gz: 455040daee6e754da6ffbb49cc53577bb5a5a8bb95b01e099ee14086dc322212
5
5
  SHA512:
6
- metadata.gz: 5bfdd00ff5e6d10bea42810af1861de3bcaf0eafebf933788ccac9b0056a5974bc9e457bd5cc3077b6b4d0952f9a46ed758512891beaa59c7fcec977a42f2ca1
7
- data.tar.gz: b0f0ad77ee6e089c3dfa0143523f8829ddf5fe25d3c38063fc383038a9a1350c8de00847925e3cff7a2c2c9439e797f93ac021bbb67f1904d10f5c62dbd1f7d7
6
+ metadata.gz: a02163999424c204244d864e311faba72e523f0ba07a30b60a726cc3f88cd35c6e9a82bccd37634a42cb91b7f9568ef1cb7c3104799bed92b869e588a8941956
7
+ data.tar.gz: 9b7f3740a6a3e51b1f4f04c21f07dbfbe70210c36199ef6f217408563a6f1b7073bb280214da67d60c717d97f8ba5274c71c29cde0682d88f49d71f3aeb77f98
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IpToAsn
4
+ DB_MAIN = 'ip2asn.dat'
5
+ DB_COUNTRIES = 'countries.dat'
6
+ DB_ASNAMES = 'asnames.dat'
7
+ end
8
+
9
+ module IpToAsn
10
+ class AsEntry
11
+ attr_accessor :range_start, :range_end, :number, :country, :name_offset, :name_length
12
+
13
+ def initialize(range_start, range_end, number, country, name_offset, name_length) # rubocop:disable Metrics/ParameterLists
14
+ @range_start = ip_to_int(range_start)
15
+ @range_end = ip_to_int(range_end)
16
+ @number = number
17
+ @country = country
18
+ @name_offset = name_offset
19
+ @name_length = name_length
20
+ end
21
+
22
+ def serialize
23
+ [@range_start, @range_end, @number, @country, @name_offset, @name_length].pack('L L L C L C')
24
+ end
25
+
26
+ def self.deserialize(binary_data)
27
+ range_start, range_end, number, country, name_offset, name_length = binary_data.unpack('L L L C L C')
28
+ new(int_to_ip(range_start), int_to_ip(range_end), number, country, name_offset, name_length)
29
+ end
30
+
31
+ def self.size
32
+ 18 # L + L + L + C + L + C = 18 bytes
33
+ end
34
+
35
+ def self.int_to_ip(int)
36
+ [24, 16, 8, 0].map { |b| (int >> b) & 0xFF }.join('.')
37
+ end
38
+
39
+ private
40
+
41
+ def ip_to_int(ip)
42
+ ip.split('.').map(&:to_i).inject(0) { |acc, num| (acc << 8) | num }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IpToAsn
4
+ class Lookup
5
+ def initialize(db_ip2asn: nil, db_country: nil, db_names: nil) # rubocop:disable Metrics/AbcSize
6
+ db_ip2asn ||= File.expand_path('../../data/ip2asn.dat', __dir__)
7
+ db_country ||= File.expand_path('../../data/countries.dat', __dir__)
8
+ db_names ||= File.expand_path('../../data/asnames.dat', __dir__)
9
+
10
+ @db_ip2asn = File.open(db_ip2asn, 'r')
11
+ @db_country = File.read(db_country)
12
+ @db_names = File.open(db_names, 'r')
13
+
14
+ @reserved_ranges = {
15
+ IPAddr.new('10.0.0.0/8') => 'RFC1918 Private',
16
+ IPAddr.new('172.16.0.0/12') => 'RFC1918 Private',
17
+ IPAddr.new('192.168.0.0/16') => 'RFC1918 Private',
18
+ IPAddr.new('0.0.0.0/8') => 'Current Network',
19
+ IPAddr.new('127.0.0.0/8') => 'Loopback',
20
+ IPAddr.new('169.254.0.0/16') => 'Link Local'
21
+ }
22
+
23
+ @entry_size = IpToAsn::AsEntry.size
24
+ @db_ip2asn.seek(0, IO::SEEK_END)
25
+ @db_total_entries = @db_ip2asn.size / @entry_size
26
+ @db_ip2asn.seek(0)
27
+ end
28
+
29
+ def ip_to_int(ip)
30
+ ip.split('.').map(&:to_i).inject(0) { |acc, num| (acc << 8) | num }
31
+ end
32
+
33
+ def as_name(name_offset, name_length)
34
+ @db_names.seek(name_offset, IO::SEEK_SET)
35
+ @db_names.read(name_length)
36
+ end
37
+
38
+ def country(country_index)
39
+ @db_country[country_index * 2, 2]
40
+ end
41
+
42
+ def lookup(ip)
43
+ reserved_range_name = find_range(
44
+ ranges: @reserved_ranges,
45
+ ip_address: ip
46
+ )
47
+
48
+ return { as_number: 0, country_code: 'XX', as_name: reserved_range_name } unless reserved_range_name.nil?
49
+
50
+ search_db(ip)
51
+ end
52
+
53
+ def search_db(ip) # rubocop:disable Metrics/AbcSize
54
+ ip_int = ip_to_int(ip)
55
+
56
+ left = 0
57
+ right = @db_total_entries - 1
58
+
59
+ while left <= right
60
+ mid = (left + right) / 2
61
+ @db_ip2asn.seek(mid * @entry_size, IO::SEEK_SET)
62
+ data = @db_ip2asn.read(@entry_size)
63
+ break if data.nil? || data.size < @entry_size
64
+
65
+ entry = IpToAsn::AsEntry.deserialize(data)
66
+
67
+ if entry.range_start.to_i <= ip_int && ip_int <= entry.range_end.to_i
68
+ return {
69
+ as_number: entry.number,
70
+ as_name: as_name(entry.name_offset, entry.name_length),
71
+ country_code: country(entry.country)
72
+ }
73
+ elsif ip_int < entry.range_start.to_i
74
+ right = mid - 1
75
+ else
76
+ left = mid + 1
77
+ end
78
+ end
79
+ end
80
+
81
+ def find_range(ranges:, ip_address:)
82
+ ranges.filter_map do |k, v|
83
+ v if k.include? ip_address
84
+ end.first
85
+ end
86
+ end
87
+ end
data/lib/iptoasn.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'main'
3
+ require_relative 'iptoasn/iptoasn'
4
+ require_relative 'iptoasn/asentry'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iptoasn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OMAR
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-12 00:00:00.000000000 Z
11
+ date: 2025-02-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This gem wraps the IP to ASN dataset. It uses lazy loading so it doesn't
14
14
  load the entire ~25M dataset all at once.
@@ -18,33 +18,9 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - README.md
21
- - lib/chunks/chunk_aa.rb
22
- - lib/chunks/chunk_ab.rb
23
- - lib/chunks/chunk_ac.rb
24
- - lib/chunks/chunk_ad.rb
25
- - lib/chunks/chunk_ae.rb
26
- - lib/chunks/chunk_af.rb
27
- - lib/chunks/chunk_ag.rb
28
- - lib/chunks/chunk_ah.rb
29
- - lib/chunks/chunk_ai.rb
30
- - lib/chunks/chunk_aj.rb
31
- - lib/chunks/chunk_ak.rb
32
- - lib/chunks/chunk_al.rb
33
- - lib/chunks/chunk_am.rb
34
- - lib/chunks/chunk_an.rb
35
- - lib/chunks/chunk_ao.rb
36
- - lib/chunks/chunk_ap.rb
37
- - lib/chunks/chunk_aq.rb
38
- - lib/chunks/chunk_ar.rb
39
- - lib/chunks/chunk_as.rb
40
- - lib/chunks/chunk_at.rb
41
- - lib/chunks/chunk_au.rb
42
- - lib/chunks/chunk_av.rb
43
- - lib/chunks/chunk_aw.rb
44
- - lib/chunks/chunk_ax.rb
45
- - lib/index.rb
46
21
  - lib/iptoasn.rb
47
- - lib/main.rb
22
+ - lib/iptoasn/asentry.rb
23
+ - lib/iptoasn/iptoasn.rb
48
24
  homepage: https://github.com/ancat/iptoasn
49
25
  licenses:
50
26
  - MIT