BSD 4_4 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 7 Apr 1988 06:29:35 +0000 (22:29 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 7 Apr 1988 06:29:35 +0000 (22:29 -0800)
Work on file usr/src/contrib/bind-4.9/doc/DynamicUpdate

Synthesized-from: CSRG/cd3/4.4

usr/src/contrib/bind-4.9/doc/DynamicUpdate [new file with mode: 0644]

diff --git a/usr/src/contrib/bind-4.9/doc/DynamicUpdate b/usr/src/contrib/bind-4.9/doc/DynamicUpdate
new file mode 100644 (file)
index 0000000..fb4152c
--- /dev/null
@@ -0,0 +1,284 @@
+               Description of Dynamic Update and T_UNSPEC Code
+                         Added by Mike Schwartz
+          University of Washington Computer Science Department
+                                  11/86
+                       schwartz@cs.washington.edu
+I have incorporated 2 new features into BIND:
+       1. Code to allow (unauthenticated) dynamic updates: surrounded by
+          #ifdef ALLOW_UPDATES
+       2. Code to allow data of unspecified type: surrounded by
+          #ifdef ALLOW_T_UNSPEC
+Note that you can have one or the other or both (or neither) of these
+modifications running, by appropriately modifying the makefiles.  Also,
+the external interface isn't changed (other than being extended), i.e.,
+a BIND server that allows dynamic updates and/or T_UNSPEC data can
+still talk to a 'vanilla' server using the 'vanilla' operations.
+The description that follows is broken into 3 parts: a functional
+description of the dynamic update facility, a functional description of
+the T_UNSPEC facility, and a discussion of the implementation of
+dynamic updates.  The implementation description is mostly intended for
+those who want to make future enhancements (especially the addition of
+a good authentication mechanism).  If you make enhancements, I would be
+interested in hearing about them.
+                       1. Dynamic Update Facility
+I added this code in conjunction with my research into naming in large
+heterogeneous systems.  For the purposes of this research, I ignored
+security issues.  In other words, no authentication/authorization
+mechanism exists to control updates.  Authentication will hopefully be
+addressed at some future point (although probably not by me). In the
+mean time, BIND Internet name servers (as opposed to "private" name
+server networks operating with their own port numbers, as I use in my
+research) should be compiled *without* -DALLOW_UPDATES, so that the
+integrity of the Internet name database won't be compromised by this
+code.
+There are 5 different dynamic update interfaces:
+       UPDATEA  - add a resource record
+       UPDATED  - delete a specific resource record
+       UPDATEDA - delete all named resource records
+       UPDATEM  - modify a specific resource record
+       UPDATEMA - modify all named resource records
+These all work through the normal resolver interface, i.e., these
+interfaces are opcodes, and the data in the buffers passed to
+res_mkquery must conform to what is expected for the particular
+operation (see the #ifdef ALLOW_UPDATES extensions to nstest.c for
+example usage).
+UPDATEM is logically equivalent to an UPDATED followed by an UPDATEA,
+except that the updates occur atomically at the primary server (as
+usual with Domain servers, secondaries may become temporarily
+inconsistent).  The difference between UPDATED and UPDATEDA is that the
+latter allows you to delete all RRs associated with a name; similarly
+for UPDATEM and UPDATEMA.  The reason for the UPDATE{D,M}A interfaces
+is two-fold:
+       1. Sometimes you want to delete/modify some data, but you know you'll
+          only have a single RR for that data; in such a case, it's more
+          convenient to delete/modify the RR by just giving the name;
+          otherwise, you would have to first look it up, and then
+          delete/modify it.
+       2. It is sometimes useful to be able to delete/modify multiple RRs
+          this way, since one can then perform the operation atomically.
+          Otherwise, one would have to delete/modify the RRs one-by-one.
+One additional point to note about UPDATEMA is that it will return a
+success status if there were *zero* or more RRs associated with the given
+name (and the RR add succeeds), whereas UPDATEM, UPDATED, and UPDATEDA
+will return a success status if there were *one* or more RRs associated
+with the given name.  The reason for the difference is to handle the
+(probably common) case where what you want to do is set a particular
+name to contain a single RR, irrespective of whether or not it was
+already set.
+                       2. T_UNSPEC Facility
+Type T_UNSPEC allows you to store data whose layout BIND doesn't
+understand.  Data of this type is not marshalled (i.e., converted
+between host and network representation, as is done, for example, with
+Internet addresses) by BIND, so it is up to the client to make sure
+things work out ok w.r.t. heterogeneous data representations.  The way
+I use this type is to have the client marshal data, store it, retrieve
+it, and demarshal it.  This way I can store arbitrary data in BIND
+without having to add new code for each specific type.
+T_UNSPEC data is dumped in an ASCII-encoded, checksummed format so
+that, although it's not human-readable, it at least doesn't fill the
+dump file with unprintable characters.
+Type T_UNSPEC is important for my research environment, where
+potentially lots of people want to store data in the name service, and
+each person's data looks different.  Instead of having BIND understand
+the format of each of their data types, the clients define marshaling
+routines and pass buffers of marshalled data to BIND; BIND never tries
+to demarshal the data...it just holds on to it, and gives it back to
+the client when the client requests it, and the client must then
+demarshal it.
+The Xerox Network System's name service (the Clearinghouse) works this
+way.  The reason 'vanilla' BIND understands the format of all the data
+it holds is probably that BIND is tailored for a very specific
+application, and wants to make sure the data it holds makes sense (and,
+for some types, BIND needs to take additional action depending on the
+data's semantics).  For more general purpose name services (like the
+Clearinghouse and my usage of BIND), this approach is less tractable.
+See the #ifdef ALLOW_T_UNSPEC extensions to nstest.c for example usage of
+this type.
+               3. Dynamic Update Implementation Description
+This section is divided into 3 subsections: General Discussion,
+Miscellaneous Points, and Known Defects.
+               3.1 General Discussion
+The basic scheme is this: When an update message arrives, a call is
+made to InitDynUpdate, which first looks up the SOA record for the zone
+the update affects.  If this is the primary server for that zone, we do
+the update and then update the zone serial number (so that secondaries
+will refresh later).  If this is a secondary server, we forward the
+update to the primary, and if that's successful, we update our copy
+afterwards.  If it's neither, we refuse the update.  (One might think
+to try to propagate the update to an authoritative server; I figured
+that updates will probably be most likely within an administrative
+domain anyway; this could be changed if someone has strong feelings
+about it).
+Note that this mechanism disallows updates when the primary is
+down, preserving the Domain scheme's consistency requirements,
+but making the primary a critical point for updates.  This seemed
+reasonable to me because
+       1. Alternative schemes must deal with potentially complex
+          situations involving merging of inconsistent secondary
+          updates
+       2. Updates are presumed to be rare relative to read accesses,
+          so this increased restrictiveness for updates over reads is
+          probably not critical
+I have placed comments through out the code, so it shouldn't be
+too hard to see what I did.  The majority of the processing is in
+doupdate() and InitDynUpdate().  Also, I added a field to the zone
+struct, to keep track of when zones get updated, so that only changed
+zones get checkpointed.
+               3.2 Miscellaneous Points
+I use ns_maint to call zonedump() if the database changes, to
+provide a checkpointing mechanism.  I use the zone refresh times to
+set up ns_maint interrupts if there are either secondaries or
+primaries.  Hence, if there is a secondary, this interrupt can cause
+zoneref (as before), and if there is a primary, this interrupt can
+cause doadump.  I also checkpoint if needed before shutting down.
+You can force a server to checkpoint any changed zones by sending the
+maint signal (SIGALRM) to the process.  Otherwise it just checkpoints
+during maint. interrupts, or when being shutdown (with SIGTERM).
+Sending it the dump signal causes the database to be dumped into the
+(single) dump file, but doesn't checkpoint (i.e., update the boot
+files).  Note that the boot files will be overwritten with checkpoint
+files, so if you want to preserve the comments, you should keep copies
+of the original boot files separate from the versions that are actually
+used.
+I disallow T_SOA updates, for several reasons:
+       - T_SOA deletes at the primary wont be discovered by the secondaries
+         until they try to request them at maint time, which will cause
+         a failure
+       - the corresponding NS record would have to be deleted at the same
+         time (atomically) to avoid various problems
+       - T_SOA updates would have to be done in the right order, or else
+         the primary and secondaries will be out-of-sync for that zone.
+My feeling is that changing the zone topology is a weighty enough thing
+to do that it should involve changing the load file and reloading all
+affected servers.
+There are alot of places where bind exits due to catastrophic failures
+(mainly malloc failures).  I don't try to dump the database in these
+places because it's probably inconsistent anyway.  It's probably better
+to depend on the most recent dump.
+               3.2 Known Defects
+1. I put the following comment in nlookup (db_lookup.c):
+       Note: at this point, if np->n_data is NULL, we could be in one
+       of two situations: Either we have come across a name for which
+       all the RRs have been (dynamically) deleted, or else we have
+       come across a name which has no RRs associated with it because
+       it is just a place holder (e.g., EDU).  In the former case, we
+       would like to delete the namebuf, since it is no longer of use,
+       but in the latter case we need to hold on to it, so future
+       lookups that depend on it don't fail.  The only way I can see
+       of doing this is to always leave the namebufs around (although
+       then the memory usage continues to grow whenever names are
+       added, and can never shrink back down completely when all their
+       associated RRs are deleted).
+   Thus, there is a problem that the memory usage will keep growing for
+   the situation described.  You might just choose to ignore this
+   problem (since I don't see any good way out), since things probably
+   wont grow fast anyway (how many names are created and then deleted
+   during a single server incarnation, after all?)
+   The problem is that one can't delete old namebufs because one would
+   want to do it from db_update, but db_update calls nlookup to do the
+   actual work, and can't do it there, since we need to maintain place
+   holders.  One could make db_update not call nlookup, so we know it's
+   ok to delete the namebuf (since we know the call is part of a delete
+   call); but then there is code with alot of overlapping functionality
+   in the 2 routines.
+   This also causes another problem:  If you create a name and then do
+   UPDATEDA, all it's RRs get deleted, but the name remains; then, if you
+   do a lookup on that name later, the name is found in the hash table,
+   but no RRs are found for it.  It then forwards the query to itself (for
+   some reason), and then somehow decides there is no such domain, and then
+   returns (with the correct answer, but after going through extra work).
+   But the name remains, and each time it is looked up, we go through
+   these same steps.  This should be fixed, but I don't have time right
+   now (and the right answer seems to come back anyway, so it's good
+   enough for now).
+2. There are 2 problems that crop up when you store data (other than
+   T_SOA and T_NS records) in the root:
+   a. Can't get primary to doaxfr RRs other than SOA and NS to
+      secondary.
+   b. Upon checkpoint (zonedump), this data sometimes comes out after other
+      data in the root, so that (since the SOA and NS records have null
+      names), they will get interpreted as being records under the
+      other names upon the next boot up.  For example, if you have a
+      T_A record called ABC, the checkpoint may look like:
+        $ORIGIN .
+        ABC     IN      A       128.95.1.3
+        99999999        IN      NS      UW-BORNEO.
+        IN      SOA     UW-BORNEO. SCHWARTZ.CS.WASHINGTON.EDU.
+        ( 50 3600 300 3600000 3600 )
+      Then when booting up the next time, the SOA and NS records get
+      interpreted as being called "ABC" rather than the null root
+      name.
+3. The secondary server caches the T_A RR for the primary, and hence when
+   it tries to ns_forw an update, it won't find the address of the primary
+   using nslookup unless that T_A RR is *also* stored in the main hashtable
+   (by putting it in a named.db file as well as the named.ca file).