Class: Dyndnsd::Updater::ZoneTransferServer

Inherits:
Object
  • Object
show all
Defined in:
lib/dyndnsd/updater/zone_transfer_server.rb

Constant Summary collapse

DEFAULT_SERVER_LISTENS =
['0.0.0.0@53'].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(domain, updater_params) ⇒ ZoneTransferServer

Returns a new instance of ZoneTransferServer.

Parameters:

  • domain (String)
  • updater_params (Hash{String => Object})


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/dyndnsd/updater/zone_transfer_server.rb', line 15

def initialize(domain, updater_params)
  @domain = domain

  @server_listens = self.class.parse_endpoints(updater_params['server_listens'] || DEFAULT_SERVER_LISTENS)
  @notify_targets = (updater_params['send_notifies'] || []).map { |e| self.class.parse_endpoints([e]) }

  @zone_rr_ttl = updater_params['zone_ttl']
  @zone_nameservers = updater_params['zone_nameservers'].map { |n| Resolv::DNS::Name.create(n) }
  @zone_email_address = Resolv::DNS::Name.create(updater_params['zone_email_address'])
  @zone_additional_ips = updater_params['zone_additional_ips'] || []

  @server = ZoneTransferServerHelper.new(@server_listens, @domain)

  # run Async::DNS server in background thread
  Thread.new do
    @server.run
  end
end

Class Method Details

.parse_endpoints(endpoint_list) ⇒ Array{Array{Object}}

converts into suitable parameter form for Async::DNS::Resolver or Async::DNS::Server

Parameters:

  • endpoint_list (Array<String>)

Returns:

  • (Array{Array{Object}})


90
91
92
93
94
95
# File 'lib/dyndnsd/updater/zone_transfer_server.rb', line 90

def self.parse_endpoints(endpoint_list)
  endpoint_list.map { |addr_string| addr_string.split('@') }
               .map { |addr_parts| [addr_parts[0], addr_parts[1].to_i || 53] }
               .map { |addr| [:tcp, :udp].map { |type| [type] + addr } }
               .flatten(1)
end

Instance Method Details

#update(db) ⇒ void

This method returns an undefined value.

Parameters:



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/dyndnsd/updater/zone_transfer_server.rb', line 36

def update(db)
  Helper.span('updater_update') do |span|
    span.set_attribute('dyndnsd.updater.name', self.class.name&.split('::')&.last || 'None')

    soa_rr = Resolv::DNS::Resource::IN::SOA.new(
      @zone_nameservers[0], @zone_email_address,
      db['serial'],
      10_800,  # 3h
      300,     # 5m
      604_800, # 1w
      3_600    # 1h
    )

    default_options = {ttl: @zone_rr_ttl}

    # array containing all resource records for an AXFR request in the right order
    rrs = []
    # AXFR responses need to start with zone's SOA RR
    rrs << [soa_rr, default_options]

    # return RRs for all of the zone's nameservers
    @zone_nameservers.each do |ns|
      rrs << [Resolv::DNS::Resource::IN::NS.new(ns), default_options]
    end

    # return A/AAAA RRs for all additional IPv4s/IPv6s for the domain itself
    @zone_additional_ips.each do |ip|
      rrs << [create_addr_rr_for_ip(ip), default_options]
    end

    # return A/AAAA RRs for the dyndns hostnames
    db['hosts'].each do |hostname, ips|
      ips.each do |ip|
        rrs << [create_addr_rr_for_ip(ip), default_options.merge({name: hostname})]
      end
    end

    # AXFR responses need to end with zone's SOA RR again
    rrs << [soa_rr, default_options]

    # point Async::DNS server thread's variable to this new RR array
    @server.axfr_rrs = rrs

    # only send DNS NOTIFY if there really was a change
    if db.changed?
      send_dns_notify
    end
  end
end