Class Dnsruby::Update
In: lib/Dnsruby/update.rb
Parent: Message
Message Update ResolvError EncodeError OtherResolvError ServFail FormErr DecodeError NXRRSet YXDomain NotImp NXDomain VerifyError NotAuth YXRRSet NotZone Refused TsigError CodeMapper Types MetaTypes QTypes Nsec3HashAlgorithms Algorithms OpCode Classes ExtendedRCode Modes RCode Comparable Name RRSet TsigNotSignedResponseError Resolver SingleResolver StandardError TimeoutError ResolvTimeout DNS Dnssec Hosts RR\n[lib/Dnsruby/resource/A.rb\nlib/Dnsruby/resource/AAAA.rb\nlib/Dnsruby/resource/AFSDB.rb\nlib/Dnsruby/resource/CERT.rb\nlib/Dnsruby/resource/DHCID.rb\nlib/Dnsruby/resource/DLV.rb\nlib/Dnsruby/resource/DNSKEY.rb\nlib/Dnsruby/resource/DS.rb\nlib/Dnsruby/resource/HINFO.rb\nlib/Dnsruby/resource/HIP.rb\nlib/Dnsruby/resource/IN.rb\nlib/Dnsruby/resource/IPSECKEY.rb\nlib/Dnsruby/resource/ISDN.rb\nlib/Dnsruby/resource/KX.rb\nlib/Dnsruby/resource/LOC.rb\nlib/Dnsruby/resource/MINFO.rb\nlib/Dnsruby/resource/MX.rb\nlib/Dnsruby/resource/NAPTR.rb\nlib/Dnsruby/resource/NSAP.rb\nlib/Dnsruby/resource/NSEC.rb\nlib/Dnsruby/resource/NSEC3.rb\nlib/Dnsruby/resource/NSEC3PARAM.rb\nlib/Dnsruby/resource/OPT.rb\nlib/Dnsruby/resource/PX.rb\nlib/Dnsruby/resource/RP.rb\nlib/Dnsruby/resource/RRSIG.rb\nlib/Dnsruby/resource/RT.rb\nlib/Dnsruby/resource/SOA.rb\nlib/Dnsruby/resource/SPF.rb\nlib/Dnsruby/resource/SRV.rb\nlib/Dnsruby/resource/SSHFP.rb\nlib/Dnsruby/resource/TKEY.rb\nlib/Dnsruby/resource/TSIG.rb\nlib/Dnsruby/resource/TXT.rb\nlib/Dnsruby/resource/X25.rb\nlib/Dnsruby/resource/domain_name.rb\nlib/Dnsruby/resource/generic.rb\nlib/Dnsruby/resource/resource.rb] Recursor IPv6 IPv4 ZoneTransfer MessageDecoder MessageEncoder Question Header TheLog ValidatorThread PacketSender ResolverRuby Config KeyCache Cache SingleVerifier SelectThread Resolv ZoneReader lib/Dnsruby/DNS.rb lib/Dnsruby/dnssec.rb lib/Dnsruby/Hosts.rb lib/Dnsruby/resource/PX.rb lib/Dnsruby/Recursor.rb lib/Dnsruby/update.rb lib/Dnsruby/ipv6.rb lib/Dnsruby/ipv4.rb lib/Dnsruby/code_mapper.rb lib/Dnsruby/zone_transfer.rb lib/Dnsruby/message.rb lib/Dnsruby/TheLog.rb lib/Dnsruby/resource/resource.rb lib/Dnsruby/validator_thread.rb lib/Dnsruby/PacketSender.rb lib/Dnsruby/Resolver.rb lib/Dnsruby/Config.rb lib/Dnsruby/key_cache.rb lib/Dnsruby/Cache.rb lib/Dnsruby/single_verifier.rb lib/Dnsruby/SingleResolver.rb lib/Dnsruby/select_thread.rb lib/Dnsruby/name.rb lib/dnsruby.rb lib/Dnsruby/resource/TKEY.rb lib/Dnsruby/zone_reader.rb Dnsruby dot/m_61_0.png

The first example below shows a complete program; subsequent examples show only the creation of the update packet.

Add a new host

 require 'Dnsruby'

 # Create the update packet.
 update = Dnsruby::Update.new('example.com')

 # Prerequisite is that no A records exist for the name.
 update.absent('foo.example.com.', 'A')

 # Add two A records for the name.
 update.add('foo.example.com.', 'A', 86400, '192.168.1.2')
 update.add('foo.example.com.', 'A', 86400, '172.16.3.4')

 # Send the update to the zone's primary master.
 res = Dnsruby::Resolver.new({:nameserver => 'primary-master.example.com'})

 begin
     reply = res.send_message(update)
     print "Update succeeded\n"
  rescue Exception => e
     print 'Update failed: #{e}\n'
  end

Add an MX record for a name that already exists

    update = Dnsruby::Update.new('example.com')
    update.present('example.com')
    update.add('example.com', Dnsruby::Types.MX, 10, 'mailhost.example.com')

Add a TXT record for a name that doesn‘t exist

    update = Dnsruby::Update.new('example.com')
    update.absent('info.example.com')
    update.add('info.example.com', Types.TXT, 86400, "yabba dabba doo"')

Delete all A records for a name

    update = Dnsruby::Update.new('example.com')
    update.present('foo.example.com', 'A')
    update.delete('foo.example.com', 'A')

Delete all RRs for a name

    update = Dnsruby::Update.new('example.com')
    update.present('byebye.example.com')
    update.delete('byebye.example.com')

Perform a signed update

    key_name = 'tsig-key'
    key      = 'awwLOtRfpGE+rRKF2+DEiw=='

    update = Dnsruby::Update.new('example.com')
    update.add('foo.example.com', 'A', 86400, 10.1.2.3'))
    update.add('bar.example.com', 'A', 86400, 10.4.5.6'))
    res.tsig=(key_name,key)

Methods

absent   add   delete   new   present  

Public Class methods

Returns a Dnsruby::Update object suitable for performing a DNS dynamic update. Specifically, it creates a message with the header opcode set to UPDATE and the zone record type to SOA (per RFC 2136, Section 2.3).

Programs must use the push method to add RRs to the prerequisite, update, and additional sections before performing the update.

Arguments are the zone name and the class. If the zone is omitted, the default domain will be taken from the resolver configuration. If the class is omitted, it defaults to IN.

    packet = Dnsruby::Update.new
    packet = Dnsruby::Update.new('example.com')
    packet = Dnsruby::Update.new('example.com', 'HS')

[Source]

     # File lib/Dnsruby/update.rb, line 98
 98:     def initialize(zone=nil, klass=nil)
 99:       
100:       # sort out the zone section (RFC2136, section 2.3)

101:       if (zone==nil)
102:         config = Config.new
103:         zone = (config.search)[0]
104:         return unless zone
105:       end
106:       
107:       type  = 'SOA'
108:       klass  ||= 'IN'
109:       
110:       super(zone, type, klass) || return
111:       
112:       @header.opcode=('UPDATE')
113:       @header.rd=(0)
114:     end

Public Instance methods

Ways to create the prerequisite records (exists, notexists, inuse, etc. - RFC2136, section 2.4) Can be called with one arg :

   update.absent(name)
      (5)  Name is not in use.  No RR of any type is owned by a
           specified NAME.  Note that this prerequisite IS satisfied by
           empty nonterminals.

Or with two :

   update.absent(name, type)
      (3)  RRset does not exist.  No RRs with a specified NAME and TYPE
          (in the zone and class denoted by the Zone Section) can exist.

[Source]

     # File lib/Dnsruby/update.rb, line 173
173:     def absent(*args)
174:       ttl = 0
175:       rdata = ""
176:       klass = Classes.NONE
177:       if (args.length>=1) # domain (RFC2136, Section 2.4.5)

178:         name = args[0]
179:         type = Types.ANY
180:         if (args.length==2) # RRSET (RFC2136, Section 2.4.3)

181:           type = args[1]
182:         end
183:         rec = RR.create("#{name} #{ttl} #{klass} #{type} #{rdata}")
184:         add_pre(rec)
185:         return rec
186:       else
187:         raise ArgumentError.new("Wrong number of arguments (#{args.length} for 1 or 2) for Update#absent")
188:       end
189:     end

Ways to create the update records (add, delete, RFC2136, section 2.5)

  " 2.5.1 - Add To An RRset

   RRs are added to the Update Section whose NAME, TYPE, TTL, RDLENGTH
   and RDATA are those being added, and CLASS is the same as the zone
   class.  Any duplicate RRs will be silently ignored by the primary
   master."

   update.add(rr)
   update.add([rr1, rr2])
   update.add(name, type, ttl, rdata)

[Source]

     # File lib/Dnsruby/update.rb, line 203
203:     def add(*args)
204:       zoneclass=zone()[0].zclass
205:       case args[0]
206:       when Array
207:         args[0].each do |resource|
208:           add(resource)
209:         end
210:       when RR
211:         # Make sure that the Class is the same as the zone

212:         resource = args[0]
213:         if (resource.klass != zoneclass)
214:           raise ArgumentError.new("Wrong class #{resource.klass} for update (should be #{zoneclass})!")
215:         end
216:         add_update(resource)
217:         return resource
218:       else
219:         name=args[0]
220:         type=args[1]
221:         ttl=args[2]
222:         rdata=args[3]
223:         resource = RR.create("#{name} #{ttl} #{zoneclass} #{type} #{rdata}")
224:         add_update(resource)
225:         return resource
226:       end
227:       # @TODO@ Should be able to take RRSet!

228:     end

Ways to create the update records (add, delete, RFC2136, section 2.5)

2.5.2 - Delete An RRset

   update.delete(name, type)

2.5.3 - Delete All RRsets From A Name

   update.delete(name)

2.5.4 - Delete An RR From An RRset

  update.delete(name, type, rdata)

[Source]

     # File lib/Dnsruby/update.rb, line 242
242:     def delete(*args)
243:       ttl = 0
244:       klass = Classes.ANY
245:       rdata=""
246:       resource = nil
247:       case args.length
248:       when 1 # name

249:         resource = RR.create("#{args[0]} #{ttl} #{klass} #{Types.ANY} #{rdata}")
250:         add_update(resource)      
251:       when 2 # name, type

252:         resource = RR.create("#{args[0]} #{ttl} #{klass} #{args[1]} #{rdata}")
253:         add_update(resource)      
254:       when 3 # name, type, rdata

255:         resource = RR.create("#{args[0]} #{ttl} IN #{args[1]} #{args[2]}")
256:         resource.klass = Classes.NONE
257:         add_update(resource)      
258:       end
259:       return resource
260:     end

Ways to create the prerequisite records (exists, notexists, inuse, etc. - RFC2136, section 2.4)

      (1)  RRset exists (value independent).  At least one RR with a
           specified NAME and TYPE (in the zone and class specified by
           the Zone Section) must exist.

           update.present(name, type)

      (2)  RRset exists (value dependent).  A set of RRs with a
           specified NAME and TYPE exists and has the same members
           with the same RDATAs as the RRset specified here in this
           Section.

           update.present(name, type, rdata)

      (4)  Name is in use.  At least one RR with a specified NAME (in
           the zone and class specified by the Zone Section) must exist.
           Note that this prerequisite is NOT satisfied by empty
           nonterminals.

           update.present(name)

[Source]

     # File lib/Dnsruby/update.rb, line 137
137:     def present(*args)
138:       ttl = 0
139:       rdata = ""
140:       klass = Classes.ANY
141:       if (args.length>=1) # domain (RFC2136, Section 2.4.4)

142:         name = args[0]
143:         type = Types.ANY
144:         if (args.length>=2) # RRSET (RFC2136, Section 2.4.1)

145:           type = args[1]
146:         end
147:         if (args.length > 2) # RRSET (RFC2136, Section 2.4.2)

148:           klass = zone()[0].zclass
149:           rdata=args[2]
150:         end
151:         rec = RR.create("#{name} #{ttl} #{klass} #{type} #{rdata}")
152:         add_pre(rec)
153:         return rec
154:       else
155:         raise ArgumentError.new("Wrong number of arguments (#{args.length} for 1 or 2) for Update#absent")
156:       end
157:     end

[Validate]