Class: Rex::Proto::DNS::Cache

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/rex/proto/dns/cache.rb

Constant Summary

Constants included from Constants

Rex::Proto::DNS::Constants::MATCH_FQDN, Rex::Proto::DNS::Constants::MATCH_HOSTNAME

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCache

class DNSRecordError < ::Exception

Create DNS cache



15
16
17
18
# File 'lib/rex/proto/dns/cache.rb', line 15

def initialize
  @records = {}
  @lock = Mutex.new
end

Instance Attribute Details

#lockObject (readonly)

Returns the value of attribute lock.



9
10
11
# File 'lib/rex/proto/dns/cache.rb', line 9

def lock
  @lock
end

#monitor_threadObject (readonly)

Returns the value of attribute monitor_thread.



9
10
11
# File 'lib/rex/proto/dns/cache.rb', line 9

def monitor_thread
  @monitor_thread
end

#recordsObject (readonly)

Returns the value of attribute records.



9
10
11
# File 'lib/rex/proto/dns/cache.rb', line 9

def records
  @records
end

Instance Method Details

#add(record, expire = 0) ⇒ Object (protected)

Add a record to the cache with thread safety

Parameters:

  • record (Dnsruby::RR)

    Record to add

  • expire (Fixnum) (defaults to: 0)

    Time in seconds when record becomes stale



110
111
112
113
114
# File 'lib/rex/proto/dns/cache.rb', line 110

def add(record, expire = 0)
  self.lock.synchronize do
    self.records[record] = expire
  end
end

#cache_record(record) ⇒ Object

Add record to cache, only when “running”

Parameters:

  • record (Dnsruby::RR)

    Record to cache



48
49
50
51
52
53
54
55
56
57
# File 'lib/rex/proto/dns/cache.rb', line 48

def cache_record(record)
  return unless @monitor_thread
  if record.is_a?(Dnsruby::RR) and
  (!record.respond_to?(:address) or Rex::Socket.is_ip_addr?(record.address.to_s)) and
  record.name.to_s.match(MATCH_HOSTNAME)
    add(record, ::Time.now.to_i + record.ttl)
  else
    raise "Invalid record for cache entry - #{record.inspect}"
  end
end

#delete(record) ⇒ Object (protected)

Delete a record from the cache with thread safety

Parameters:

  • record (Dnsruby::RR)

    Record to delete



120
121
122
123
124
# File 'lib/rex/proto/dns/cache.rb', line 120

def delete(record)
  self.lock.synchronize do
    self.records.delete(record)
  end
end

#find(search, type = Dnsruby::Types::A) ⇒ Array

Find entries in cache, substituting names for ‘*’ in return

Parameters:

  • search (String)

    Name or address to search for

  • type (Dnsruby::Types) (defaults to: Dnsruby::Types::A)

    Record type to search for

Returns:

  • (Array)

    Records found



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rex/proto/dns/cache.rb', line 27

def find(search, type = Dnsruby::Types::A)
  self.records.select do |record,expire|
    record.type == type and (expire < 1 or expire > ::Time.now.to_i) and
    (
      record.name == '*' or
      record.name.to_s == search.to_s or record.name.to_s[0..-2] == search.to_s or
      ( record.respond_to?(:address) and record.address.to_s == search.to_s )
    )
  end.keys.map do |record|
    if search.to_s.match(MATCH_HOSTNAME) and record.name == '*'
      record = Dnsruby::RR.create(name: name, type: type, address: address)
    else
      record
    end
  end
end

#flushObject

Delete all cache entries, this is different from pruning because the record’s expiration is ignored



63
64
65
# File 'lib/rex/proto/dns/cache.rb', line 63

def flush
  self.records.each {|rec, _| delete(rec)}
end

#prune(before = ::Time.now.to_i) ⇒ Object

Prune cache entries

Parameters:

  • before (Fixnum) (defaults to: ::Time.now.to_i)

    Time in seconds before which records are evicted



71
72
73
74
75
# File 'lib/rex/proto/dns/cache.rb', line 71

def prune(before = ::Time.now.to_i)
  self.records.select do |rec, expire|
    expire > 0 and expire < before
  end.each {|rec, exp| delete(rec)}
end

#startObject

Start the cache monitor



80
81
82
83
84
85
86
87
# File 'lib/rex/proto/dns/cache.rb', line 80

def start
  @monitor_thread = Rex::ThreadFactory.spawn("DNSServerCacheMonitor", false) {
    while true
      prune
      Rex::ThreadSafe.sleep(0.5)
    end
  } unless @monitor_thread
end

#stop(flush = false) ⇒ Object

Stop the cache monitor

Parameters:

  • flush (TrueClass, FalseClass) (defaults to: false)

    Remove non-static entries



93
94
95
96
97
98
99
100
101
# File 'lib/rex/proto/dns/cache.rb', line 93

def stop(flush = false)
  self.monitor_thread.kill unless @monitor_thread.nil?
  @monitor_thread = nil
  if flush
    self.records.select do |rec, expire|
      rec.ttl > 0
    end.each {|rec| delete(rec)}
  end
end