BIND 10 #1212: Implement IXFR-in

BIND 10 Development do-not-reply at isc.org
Tue Sep 27 23:28:48 UTC 2011


#1212: Implement IXFR-in
-------------------------------------+-------------------------------------
                   Reporter:         |                 Owner:
  stephen                            |                Status:  new
                       Type:  task   |             Milestone:
                   Priority:  major  |  Sprint-20111011
                  Component:  xfrin  |            Resolution:
                   Keywords:         |             Sensitive:  0
            Defect Severity:  N/A    |           Sub-Project:  DNS
Feature Depending on Ticket:         |  Estimated Difficulty:  12
        Add Hours to Ticket:  0      |           Total Hours:  0
                  Internal?:  0      |
-------------------------------------+-------------------------------------

Comment (by jinmei):

 Replying to [comment:3 jelte]:
 > Whoever takes up this ticket should start out with reviewing the current
 code and RFC1995 and make a quick (and we mean quick) breakdown of the
 tasks involved, as discussed on the call today.

 I've read RFC1995 and BIND 9's xfrin implementation.

 First off, I propose a couple of simplifications toward the next
 release:
 - Don't support UDP.  In fact, if I understand it correctly even BIND
   9 doesn't support IXFR-in over UDP.
 - Don't support IXFR to AXFR fallback for now.  To help environment
   where IXFR doesn't work, introduce a (possibly short term)
   workaround of an option to disable IXFR (see below)

 Here's my proposed task breakdown:

 1. Add support for the "PRESERVE_ORDER" option in libdns++ (and
    pydnspp) Message::fromWire().
 2. A basic framework to handle RR diffs (add/delete).  This will
    eventually be used for dynamic update support.
 3. Main code logic for IXFR protocol: send IXFR query, receive
    response, and handle them (it would be nicer if we could break down
    this further, but I cannot think of any reasonable subtasking for
    this part)
 4. A small configuration extension: "disable-ixfr" option
    (preferably per zone basis)

 3 depends on 1, 2, and 4, but it should be possible to start work on 3
 without waiting for the others to be fully completed.  There should be
 no other dependencies.

 Some details:

 As for 1, see the DNS_MESSAGEPARSE_PRESERVEORDER option of BIND 9's
 dns_message_parse().  To quote the important part: "If
 DNS_MESSAGEPARSE_PRESERVEORDER is set, a separate dns_name_t object
 will be created for each RR in the message.".  This feature was
 necessary for AXFR, too, but we've worked around it with a heuristics
 hack so far.  It seems to be the time to address it.

 As for 2, I propose porting BIND 9's ixfr_putdata(), ixfr_apply(), and
 ixfr_commit() (implemented in lib/dns/xfrin.c), and
 dns_difftuple_create() and dns_diff_apply() (lib/dns/diff.c).  We
 introduce a notion of "RR diff", which (conceptually) consists of an
 operation mode (add or delete) and an RR (which would be an RRset
 object containing only one RDATA in our API).  dns_diff_apply()
 accepts a list of RR diffs, combining them into RRset diffs (for
 efficiency reasons), then make the corresponding changes on the zone
 DB.  ixfr_putdata() takes an operation (add or delete) and RR from the
 main IXFR logic, creates an RR diff object, and maintains it in a
 list.  For every 100 diffs, it calls ixfr_apply().  ixfr_apply()
 starts a new transaction (if it has already started transaction,
 continue it) and makes changes for the RR diff list accumulated so far
 under the transaction.  ixfr_commit() calls ixfr_apply() to apply any
 remaining diff and commit the transaction.

 As for 3, we'll update the do_xfrin() function of the current
 implementation:
 {{{
             if ret == XFRIN_OK:
                 logger.info(XFRIN_AXFR_TRANSFER_STARTED, self._zone_name)
                 self._send_query(RRType.AXFR())
                 isc.datasrc.sqlite3_ds.load(self._db_file,
 self._zone_name,
                                             self._handle_xfrin_response)
 }}}

 Unless IXFR is disabled, send IXFR query instead of AXFR, and instead
 of doing the sqlite3 specific stuff, implement and perform a
 completely separate code logic, where:
 - receive IXFR messages (until the xfrin process completes), parse it
   with PRESERVE_ORDER mode
 - handle each RR in the responses according to RFC1995.  call
   ixfr_putdata() for each RR, and ixfr_commit() for each
   "difference" (a single set of deletes and adds for one SOA change).
   I also suggest checking BIND 9's lib/dns/xfrin.c:xfr_rr() to know
   any corner cases and hints for tests.

 Some additional notes:
 - In our current API add/delete RRsets doesn't check data integrity.
   For example, "delete" doesn't check if the specified RRset exists.
   It shouldn't cause a problem as long as this ixfr context is the
   only writer to the zone and the remote primary server implementation
   behaves correctly, which wouldn't be unreasonable assumption in
   practice (in fact, even BIND 9 seems to rely on the accurate
   behavior of the primary server to some extent).  So at least at the
   moment I propose ignoring the error cases where given "delete" data
   doesn't exist, etc.
 - The above implementation logic uses a separate transaction for a
   single IXFR "diff".  So if the IXFR message consists of multiple
   diffs and there's another writer to the DB, the integrity may be
   broken.  We may want to discuss this point separately, but for now I
   propose implementing it this way.  Like the previous point, it will
   normally not be a problem in practice.  Also, BIND 9 seems to use
   the same logic here (using separate "transactions" for different
   diffs of a single IXFR message).

-- 
Ticket URL: <https://bind10.isc.org/ticket/1212#comment:4>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list