Module: DDNSUpdate

Defined in:
lib/ddnsupdate.rb

Defined Under Namespace

Classes: UpdateError

Class Method Summary collapse

Class Method Details

.determine_current_ip(zone, soa = nil) ⇒ Object



37
38
39
40
# File 'lib/ddnsupdate.rb', line 37

def self.determine_current_ip(zone, soa=nil)
  soa = determine_soa(zone) unless !soa.nil?
  %x{dig @#{soa} #{zone} A +short }
end

.determine_local_ipObject



42
43
44
45
46
47
48
49
50
51
# File 'lib/ddnsupdate.rb', line 42

def self.determine_local_ip
  orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true  # turn off reverse DNS resolution temporarily

  UDPSocket.open do |s|
    s.connect '64.233.187.99', 1
    s.addr.last
  end
ensure
    Socket.do_not_reverse_lookup = orig
end

.determine_remote_ipObject



53
54
55
# File 'lib/ddnsupdate.rb', line 53

def self.determine_remote_ip
  Net::HTTP.get(URI.parse('http://www.whatismyip.org/'))
end

.determine_soa(zone) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/ddnsupdate.rb', line 15

def self.determine_soa(zone)
  current = zone.gsub(/\.$/, "")
  soa = nil
  while soa.nil? and not current.match /\.*\..*/
    soa = %x{dig -t SOA #{current} +noquestion +nostats +nocmd +noqr +nocomments +noadditional +nottlid}
    if not soa.nil?
      #Split lines into an array, filtering out comments and blanks
      soa = soa.split("\n").delete_if { |el| el.start_with?(";") || el.empty? }
      #Split remaining line into whitespace delimited fields
      if not soa.empty?
        soa = soa[0].split(/\s/)
        #Find the field we actually want, stripping the trailing dot
        soa = soa[soa.index("SOA") + 1].gsub(/\.$/, "")
      else
        soa = nil
      end
    end
    current.sub! /^.*?\./, ""
  end
  return soa
end

.keygen(input) ⇒ Object



11
12
13
# File 'lib/ddnsupdate.rb', line 11

def self.keygen(input)
  Base64.encode64(Digest::MD5.hexdigest(input.downcase))
end

.update(zone, ip, key, wild = false, soa = nil) ⇒ Object

Raises:



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
85
86
87
88
89
90
91
# File 'lib/ddnsupdate.rb', line 57

def self.update(zone, ip, key, wild = false, soa = nil)
  soa         = determine_soa(zone) if soa.nil?
  raise UpdateError, "can't find SOA for #{zone}" if soa.nil?
  curip       = determine_current_ip(zone, soa)

  if curip != ip
    delete_seq  = "                  server \#{soa}\n                  key \#{zone}. \#{key}\n                  prereq yxdomain \#{zone}.\n                  update delete \#{zone}. A\n                  ;\n    delete_seq += \"                    update delete *.\#{zone}. A\\n\" if wild\n    delete_seq += \"                    send\\n\"\n\n    create_seq  = <<-\";\"\n                  server \#{soa}\n                  key \#{zone}. \#{key}\n                  prereq nxdomain \#{zone}.\n                  update add \#{zone}. 300 A \#{ip}\n                  ;\n    create_seq += \"                    update add *.\#{zone}. 300 A \#{ip}\\n\" if wild\n    create_seq += \"                    send\\n\"\n\n    Open3.popen3(\"nsupdate\") do |stdin, stdout, stderr|\n      stdin << delete_seq << create_seq\n      stdin.close_write\n      err = stderr.read\n      raise UpdateError, err unless err.empty?\n    end\n    true\n  else\n    false\n  end\nend\n"