Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/proto/dns/cache.rb
Views: 11704
# -*- coding: binary -*-12require 'rex/socket'34module Rex5module Proto6module DNS7class Cache8attr_reader :records, :lock, :monitor_thread9include Rex::Proto::DNS::Constants10# class DNSRecordError < ::Exception11#12# Create DNS cache13#14def initialize15@records = {}16@lock = Mutex.new17end1819#20# Find entries in cache, substituting names for '*' in return21#22# @param search [String] Name or address to search for23# @param type [Dnsruby::Types] Record type to search for24#25# @return [Array] Records found26def find(search, type = Dnsruby::Types::A)27self.records.select do |record,expire|28record.type == type and (expire < 1 or expire > ::Time.now.to_i) and29(30record.name == '*' or31record.name.to_s == search.to_s or record.name.to_s[0..-2] == search.to_s or32( record.respond_to?(:address) and record.address.to_s == search.to_s )33)34end.keys.map do |record|35if search.to_s.match(MATCH_HOSTNAME) and record.name == '*'36record = Dnsruby::RR.create(name: name, type: type, address: address)37else38record39end40end41end4243#44# Add record to cache, only when "running"45#46# @param record [Dnsruby::RR] Record to cache47def cache_record(record)48return unless @monitor_thread49if record.is_a?(Dnsruby::RR) and50(!record.respond_to?(:address) or Rex::Socket.is_ip_addr?(record.address.to_s)) and51record.name.to_s.match(MATCH_HOSTNAME)52add(record, ::Time.now.to_i + record.ttl)53else54raise "Invalid record for cache entry - #{record.inspect}"55end56end5758#59# Delete all cache entries, this is different from pruning because the60# record's expiration is ignored61#62def flush63self.records.each {|rec, _| delete(rec)}64end6566#67# Prune cache entries68#69# @param before [Fixnum] Time in seconds before which records are evicted70def prune(before = ::Time.now.to_i)71self.records.select do |rec, expire|72expire > 0 and expire < before73end.each {|rec, exp| delete(rec)}74end7576#77# Start the cache monitor78#79def start80@monitor_thread = Rex::ThreadFactory.spawn("DNSServerCacheMonitor", false) {81while true82prune83Rex::ThreadSafe.sleep(0.5)84end85} unless @monitor_thread86end8788#89# Stop the cache monitor90#91# @param flush [TrueClass,FalseClass] Remove non-static entries92def stop(flush = false)93self.monitor_thread.kill unless @monitor_thread.nil?94@monitor_thread = nil95if flush96self.records.select do |rec, expire|97rec.ttl > 098end.each {|rec| delete(rec)}99end100end101102protected103104#105# Add a record to the cache with thread safety106#107# @param record [Dnsruby::RR] Record to add108# @param expire [Fixnum] Time in seconds when record becomes stale109def add(record, expire = 0)110self.lock.synchronize do111self.records[record] = expire112end113end114115#116# Delete a record from the cache with thread safety117#118# @param record [Dnsruby::RR] Record to delete119def delete(record)120self.lock.synchronize do121self.records.delete(record)122end123end124end # Cache125end126end127end128129130