search revision 816e576f77e2c46df3e3d97d65822aa8aded7c4b
10139N/ACopyright (C) 1999, 2000 Internet Software Consortium.
10139N/ASee COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
10139N/A
12282N/A$Id: search,v 1.8 2000/08/09 04:37:26 tale Exp $
10139N/A
10139N/AWhat follows is pseudocode for the zone and cache lookup algorithms, as they
10139N/Awill work in the RBT DB.
17185N/A
10139N/ANote: These algorithms differ in some respects from those discussed in
17178N/Athe RFCs and drafts. I believe these algorithms provide better
17178N/Aanswers in some cases.
17178N/A
10139N/A
15322N/APreliminary Stuff
17008N/A
12282N/ABIND 9 zone databases are versioned, and every search is done in the
10139N/Acontext of some version. There are a number of ways of implementing
10139N/Aversioning. The method that's going to be used in the RBT DB is to
10139N/Astore a serial number with every rdataset. All rdatasets added as the
10139N/Aresult of a single database update have the same serial number. This
10139N/Aserial number is not related to the SOA serial, since the SOA serial
10139N/Ais under user control and can do weird things. The database serial
12773N/Anumber is a monotonically increasing value. When you go to retrieve
15694N/Aan rdataset, you may encounter many rdatasets of that type at any
12773N/Agiven node. The correct one to return, called the "active rdataset",
13483N/Ahas the greatest serial number less than or equal to the serial number
10139N/Aused for the search. The version whose serial number is being used in
10139N/Athe search is the "target version".
10139N/A
10139N/ACache databases are not versioned. A search will always return the
10139N/Amost recent value.
10139N/A
10139N/ADKZC == Deepest Known Zone Cut. This is the zone cut closest to the
10139N/Adesired name. In a zone, it's either a delegation out of authoritative
10139N/Adata, or it's the top of the zone.
10139N/A
10139N/AZC == "zone cut", a node not at the zone top which has an active NS
10139N/Ardataset, or a node (including the zone top) with an active DNAME
10139N/Ardataset.
10139N/A
10139N/A
10139N/AZone Search Algorithm
10139N/A
10139N/A Inputs:
10139N/A Search name
10139N/A Search rdata type (including ANY)
10139N/A Search options
10139N/A
10139N/A The search options parameter is a flags variable. Current
10139N/A flags are
10139N/A
10139N/A Glue OK If set, then the caller is
10139N/A wants best match results for
10139N/A the search name, even if it's
10139N/A glue. If not set, the caller
10139N/A will get a delegation if the
10139N/A search name is glue.
10139N/A
10139N/A Glue Validation Section 7.18 of RFC 2136
10139N/A requires that certain data that
10139N/A is not in the zone and is not
10139N/A glue remain stored in the zone.
10139N/A A search can never return this
10139N/A data, but there might be glue
10139N/A mixed in with it. Telling glue
10139N/A from non glue involves some
10139N/A work, especially since the
10139N/A database is versioned. Often,
10139N/A however, the caller will know
10139N/A the name it's looking for is
10139N/A glue, so validation isn't
10139N/A required.
10139N/A
10139N/A Outputs:
10139N/A result code
10139N/A a node
10139N/A the name of the node
10139N/A rdataset (not bound if querying for ANY)
10139N/A
10139N/A Note: The node, name, and rdataset are optional. If the
10139N/A caller doesn't care about them, they won't be set.
10139N/A
10139N/A Note: there is no EDNS1 "longest match" support in the algorithm yet,
10139N/A though I know how to do it.
10139N/A
10139N/A
10139N/A cname_ok = yes
10165N/A search_must_succeed = no
15713N/A
12773N/A Search down from the root of the tree. If, while going down, we
12773N/A encounter a zone cut node, then search the rdatasets at the zone
12773N/A cut for active DNAME or NS rdatasets. Note that if we find both
12773N/A an active DNAME rdataset and an active NS rdataset, then the DNAME
12773N/A rdataset has precedence.
10139N/A
10139N/A If we found an active DNAME rdataset, the search ends here.
10139N/A result = DNS_R_DNAME
13468N/A foundname = name of this node
13468N/A *nodep = this node
13468N/A rdataset is the DNAME
13468N/A return
10139N/A
10139N/A If we found an active NS rdataset
10139N/A If finding glue is not OK, or we're not searching for
10139N/A a glue type, then the search ends here.
10139N/A result = DNS_R_DELEGATION
15544N/A foundname = name of this node
13468N/A *nodep = this node
13468N/A rdataset = NS
10139N/A return
10139N/A Else
10139N/A We remember that this node is the ZC.
10139N/A We remember this node's name.
10139N/A We'll ignore any zone cuts found further down
10139N/A the tree.
10139N/A Continue the search down.
10139N/A
10139N/A Partial_Match:
10139N/A If we don't have an exact match to the name
10139N/A If we're below a zone cut, then we need to return a referral.
10139N/A result = DNS_R_DELEGATION;
10139N/A foundname = ZC name
10139N/A *nodep = ZC
10139N/A rdataset = NS
10139N/A return
10139N/A Else If this zone has any wildcards, then
10139N/A Go looking for a wildcard match for this name.
10139N/A If we found one,
10139N/A result = DNS_R_WILDCARD
10139N/A foundname = wildcard node name
10139N/A Fall through to searching the wildcard node
10139N/A for the desired type.
10139N/A Else
10139N/A NXDOMAIN (finally!)
10139N/A If this is a secure zone then
10139N/A Find the greatest predecessor to this node
10139N/A that has at least one active rdataset.
10139N/A Change the type we're search for to NXT
10139N/A cname_ok = no
10139N/A search_must_succeed = yes
10139N/A Else
10139N/A result = DNS_R_NXDOMAIN
10139N/A foundname = <empty>
10139N/A rdataset = <unbound>
10139N/A *nodep = NULL
10139N/A return
10139N/A
10139N/A If we're here, then we've got a node and are now trying to find
10139N/A an active rdataset of the desired type, or, in the case of an ANY
10139N/A query, any active rdataset.
10139N/A
17008N/A If we're beneath a zone cut
17008N/A cname_ok = no
16697N/A If the caller wants us to validate glue, then see if the
16697N/A current name is a valid glue name for the ZC.
16697N/A If not,
16496N/A result = DNS_R_DELEGATION;
16496N/A foundname = ZC name
16076N/A *nodep = ZC
16076N/A rdataset = NS
16076N/A return
15694N/A
15694N/A If the desired type is KEY, SIG, or NXT, then
15205N/A cname_ok = no
15205N/A
13468N/A foundname = current node name
13468N/A *nodep = current node;
13468N/A
13468N/A Search the rdataset list for the desired type. If cname_ok, also
13445N/A look for a CNAME rdataset. While searching, remember the active NXT
13445N/A rdataset if we come across it. We must also determine if there are
12793N/A any active rdatasets at the node.
12793N/A
12628N/A If there are no active rdatasets at the node, then we've got an
12628N/A exact name match, but the name doesn't exist in the desired version.
12436N/A This means we really have a partial match. Goto Partial_Match.
12436N/A
12304N/A If we didn't find the type we were looking for (including a failed
12304N/A ANY search)
12282N/A If (search_must_succeed), then
12282N/A The database is bad, e.g. missing NXT records.
11951N/A result = DNS_R_BADDB
11951N/A *nodep = NULL
11010N/A foundname = <empty>
11010N/A Else if we're beneath a zone cut
10818N/A result = DNS_R_DELEGATION
10818N/A foundname = ZC name
10802N/A *nodep = ZC
10802N/A rdataset = NS
10802N/A Else
10344N/A result = DNS_R_NXRDATASET
10344N/A If this is a secure zone then
10344N/A If we found an active NXT rdataset
10232N/A rdataset = NXT rdataset
10233N/A Else
10165N/A result = DNS_R_BADDB
10165N/A *nodep = NULL
10139N/A foundname = <empty>
10139N/A Else
10139N/A rdataset = <unbound>
10139N/A return
10139N/A
10139N/A We have found the type we were looking for or we've found a CNAME.
10139N/A
10139N/A If we're not doing any ANY query, didn't find the type we were looking
10139N/A for, but did find a CNAME
10139N/A result = DNS_R_CNAME
10139N/A rdataset = CNAME
10139N/A Else If we're beneath a zone cut
10139N/A result = DNS_R_GLUE
10139N/A Else
10139N/A result = DNS_R_SUCCESS
10139N/A
10139N/A If type is ANY
10139N/A rdataset = <unbound>
10139N/A else
10139N/A rdataset = the type we were looking for
10139N/A
10139N/A
10139N/A
10139N/AXXX This is now old XXX
10139N/A
10139N/ANow for the cache lookup algorithm, which is a little different. The
10139N/Acache algorithm takes an optional "zone DKZC". Say a server is
10139N/Aauthoritative for vix.com but not rc.vix.com. When it looks up
10139N/Abb.rc.vix.com it will search vix.com and discover the delegation to
10139N/Arc.vix.com. We then want to look in the cache for bb.rc.vix.com, and
10139N/Aif we don't find it, the authoritative delegation might be the best
10139N/ADKZC (since there might not be anything for rc.vix.com in the cache),
10139N/Aso that's why we allow it to be an argument to the cache search
10139N/Aalgorithm. Of course, the cache might have data for rc.vix.com
10139N/Acached, in which case we should use it and not the DKZC.
10139N/A
10139N/ADKZC A is "better" than DKZC B if DKZC A is a proper subdomain of DKZC
10139N/AB.
10139N/A
10139N/A
10139N/ACache Search Algorithm:
10139N/A
10139N/A Go down as far as possible remembering every parent node.
10139N/A Remember the predecessor too.
10139N/A
10139N/A If some rdataset for name exists
10139N/A
10139N/A Look for desired type or CNAME
10139N/A
10139N/A If found
10139N/A If negative cache entry
10139N/A Indicate this and return.
10139N/A If CNAME?
10139N/A Indicate it and return.
10139N/A Return.
10139N/A Else
10139N/A Indicate we know nothing about this type at this
10139N/A node.
10139N/A Return.
10139N/A
10139N/A Else
10139N/A (Peek at predecessor to see if it has an NXT for the same
10139N/A zone and which covers the QNAME. If so, return it.)
10139N/A
10139N/A Go up until we find a node with a DNAME or a zone cut.
10139N/A XXX DNAME draft says go up until you prove that there are no
10139N/A ancestor DNAMEs at all XXX
10139N/A
10139N/A If there's a DNAME
10139N/A Return a DNAME result with the dname node and node name
10139N/A XXX what if the zone DKZC is better (i.e. deeper)? XXX
10139N/A
10139N/A We know nothing about this name.
10139N/A
10139N/A XXX DNAME draft says that if we have a zone DKZC, we should
10139N/A use it now. I say use the best DKZC you've got. XXX
10139N/A
10139N/A If we get all the way to '.' and we don't even have the
10139N/A root NS records
10139N/A If we have a DKZC from authoritative data
10139N/A Return it.
10139N/A Else
10139N/A Return NO_KNOWN_AUTHORITY
10139N/A (this will cause priming of root servers or,
10139N/A perhaps, forwarding)
10139N/A
10139N/A If we have a zone DKZC and it's better than the one we found
10139N/A in the cache
10139N/A Return it (node and name).
10139N/A
10139N/A Return the cache DKZC (node and name).
10139N/A