123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- class Registry
- require 'logger'
- require 'ipaddr'
- MAX_LIMIT = 40_000
- IP_PATHS = %w[route route6 inetnum inet6num].freeze
- SEARCH_PATHS = %w[as-set aut-num dns key-cert mntner organisation person registry role route-set schema tinc-key].freeze
- DIRECT_NAME = 'direct'.freeze
- def initialize(args)
-
- raise ArgumentError, 'Wrong argument format' unless args.is_a? Hash
- raise ArgumentError, 'Directory must be a string' unless args[:dir].is_a? String
- raise ArgumentError, 'Logger must be a logger' unless args[:logger].is_a? Logger
-
- @data_dir = "#{args[:dir]}#{File::SEPARATOR}data#{File::SEPARATOR}"
- @logger = args[:logger]
- @registry_data = {}
-
- raise ArgumentError, 'Path does not exist' unless File.exist? @data_dir
- end
-
- def update
- limit_counter = 0
- registry_data = {}
- Dir["#{@data_dir}#{File::SEPARATOR}**#{File::SEPARATOR}*"].each do |file|
- if File.file? file
- if File.readable? file
-
- cnt = File.readlines file
-
- cnt.map!(&:chomp)
-
- cnt.reject!(&:empty?)
-
- val = cnt.join "\r\n"
-
- splited_dir = File.dirname(file).split(File::SEPARATOR)
- if splited_dir.empty?
- @logger.error "Invalid path for file #{file}"
- next
- elsif splited_dir[-1] == 'data'
-
- path = DIRECT_NAME
- else
- path = splited_dir[-1]
- end
-
- object_name = File.basename file
-
- registry_data[path] = {} unless registry_data.key? path
- if IP_PATHS.include? path
-
- ip_address_str = object_name.gsub('_', '/')
- begin
-
- ip_address = IPAddr.new ip_address_str
-
- registry_data[path][object_name] = [ip_address, val]
- rescue IPAddr::InvalidAddressError
- @logger.error "Failed to parse #{ip_address_str}"
- end
- else
-
- registry_data[path][object_name] = val
- end
- else
- @logger.error "File #{file} is not readable."
- end
- end
-
-
- limit_counter += 1
- if limit_counter > MAX_LIMIT
- @logger.error 'Reached file limit.'
- break
- end
- end
- @logger.info 'Save new registry data.'
- @registry_data = registry_data
- end
-
-
-
- def lookup_ipaddr(query)
- raise SuspiciousBehavior, 'Tried to lookup a IP address which is not a IP address' unless query.is_a? IPAddr
- if query.ipv4?
- route_path = 'route'
- inetnum_path = 'inetnum'
- elsif query.ipv6?
- route_path = 'route6'
- inetnum_path = 'inet6num'
- else
- raise SuspiciousBehavior, "Valid IP address is not IPv4 or IPv6: #{query}"
- end
- results = []
- results << lookup_ip_in_path(query, route_path)
- results[-1].map! do |value|
- [value[0], 2, value[1], value[2]]
- end
- results << lookup_ip_in_path(query, inetnum_path)
- results[-1].map! do |value|
- [value[0], 1, value[1], value[2]]
- end
- results.flatten!(1)
- results.reject!(&:empty?)
- results.sort! do |ip_a, ip_b|
- (ip_a[0] == ip_b[0] ? ip_a[1] <=> ip_b[1] : ip_a[0] <=> ip_b[0])
- end
-
- results.map! do |val|
- [val[2], val[3]]
- end
- return results
- end
-
-
-
- def lookup_ip_in_path(query, path)
- raise ArgumentError, 'Invalid IP path' unless IP_PATHS.include? path
- raise ArgumentError, 'IP address must be of type IP address' unless query.is_a? IPAddr
- results = []
- @registry_data[path].each do |key, value|
- ipaddr = value[0]
- data = value[1]
- if ipaddr.include? query
-
- results << [ipaddr, "#{path}/#{key}", data]
- end
- end
- return results
- end
-
-
-
- def lookup_direct(query)
- raise SuspiciousBehavior, 'Tried to lookup a string which is not a string' unless query.is_a? String
- query = query.sanitize.downcase
- return lookup_in_path(query, DIRECT_NAME)
- end
-
-
-
- def lookup_in_path(query, path)
- raise ArgumentError, 'Query must be a string' unless query.is_a? String
- raise ArgumentError, 'Path must be a string' unless path.is_a? String
- results = []
- @registry_data[path].each do |key, data|
- if key.downcase == query
-
- results << ["#{path}/#{key}", data]
- end
- end
- return results
- end
-
-
-
- def lookup(query)
- raise SuspiciousBehavior, 'Tried to lookup a string which is not a string' unless query.is_a? String
- query = query.sanitize.downcase
- results = []
- SEARCH_PATHS.each do |search_path|
- results << lookup_in_path(query, search_path)
- end
- results.flatten!(1)
- return results
- end
- end
|