mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 05:00:00 -04:00
move slab rdataset implementation to rdataslab.c
ultimately we want the slab implementation of dns_rdataset to be usable by more database implementaions than just rbtdb. this commit moves rdataset_methods to rdataslab.c, renamed dns_rdataslab_rdatasetmethods. new database methods have been added: locknode, unlocknode, addglue, expiredata, and deletedata, allowing external functions to perform functions that previously required internal access to the database implementation. database and heap pointers are now stored in the dns_slabheader object so that header is the only thing that needs to be passed to some functions; this will simplify moving functions that process slabheaders out of rbtdb.c so they can be used by other database implementations.
This commit is contained in:
parent
17f85f6c93
commit
445ef1d033
11 changed files with 1337 additions and 1456 deletions
44
lib/dns/db.c
44
lib/dns/db.c
|
|
@ -1061,3 +1061,47 @@ dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
|
|||
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_db_addglue(dns_db_t *db, dns_dbversion_t *version, dns_rdataset_t *rdataset,
|
||||
dns_message_t *msg) {
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
REQUIRE(rdataset->type == dns_rdatatype_ns);
|
||||
|
||||
if (db->methods->addglue != NULL) {
|
||||
return ((db->methods->addglue)(db, version, rdataset, msg));
|
||||
}
|
||||
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_locknode(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t type) {
|
||||
if (db->methods->locknode != NULL) {
|
||||
(db->methods->locknode)(db, node, type);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_unlocknode(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t type) {
|
||||
if (db->methods->unlocknode != NULL) {
|
||||
(db->methods->unlocknode)(db, node, type);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_expiredata(dns_db_t *db, dns_dbnode_t *node, void *data) {
|
||||
if (db->methods->expiredata != NULL) {
|
||||
(db->methods->expiredata)(db, node, data);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_deletedata(dns_db_t *db, dns_dbnode_t *node, void *data) {
|
||||
if (db->methods->deletedata != NULL) {
|
||||
(db->methods->deletedata)(db, node, data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/rwlock.h>
|
||||
#include <isc/stats.h>
|
||||
#include <isc/stdtime.h>
|
||||
|
||||
|
|
@ -171,6 +172,13 @@ typedef struct dns_dbmethods {
|
|||
isc_result_t (*setservestalerefresh)(dns_db_t *db, uint32_t interval);
|
||||
isc_result_t (*getservestalerefresh)(dns_db_t *db, uint32_t *interval);
|
||||
isc_result_t (*setgluecachestats)(dns_db_t *db, isc_stats_t *stats);
|
||||
void (*locknode)(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t t);
|
||||
void (*unlocknode)(dns_db_t *db, dns_dbnode_t *node,
|
||||
isc_rwlocktype_t t);
|
||||
isc_result_t (*addglue)(dns_db_t *db, dns_dbversion_t *version,
|
||||
dns_rdataset_t *rdataset, dns_message_t *msg);
|
||||
void (*expiredata)(dns_db_t *db, dns_dbnode_t *node, void *data);
|
||||
void (*deletedata)(dns_db_t *db, dns_dbnode_t *node, void *data);
|
||||
} dns_dbmethods_t;
|
||||
|
||||
typedef isc_result_t (*dns_dbcreatefunc_t)(isc_mem_t *mctx,
|
||||
|
|
@ -1715,4 +1723,50 @@ dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats);
|
|||
* dns_rdatasetstats_create(); otherwise NULL.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_db_locknode(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t type);
|
||||
void
|
||||
dns_db_unlocknode(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t type);
|
||||
/*%<
|
||||
* Lock/unlock a single node within a database so that data stored
|
||||
* there can be manipulated directly.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_db_addglue(dns_db_t *db, dns_dbversion_t *version, dns_rdataset_t *rdataset,
|
||||
dns_message_t *msg);
|
||||
/*%<
|
||||
* Add glue records for rdataset to the additional section of message in
|
||||
* 'msg'. 'rdataset' must be of type NS.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'db' is a database with 'zone' semantics.
|
||||
* \li 'version' is the DB version.
|
||||
* \li 'rdataset' is a valid NS rdataset.
|
||||
* \li 'msg' is the DNS message to which the glue should be added.
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_SUCCESS
|
||||
*\li #ISC_R_NOTIMPLEMENTED
|
||||
*\li #ISC_R_FAILURE
|
||||
*\li Any error that dns_rdata_additionaldata() can return.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_db_expiredata(dns_db_t *db, dns_dbnode_t *node, void *data);
|
||||
/*%<
|
||||
* Tell the database 'db' to mark a block of data 'data' stored at
|
||||
* node 'node' as expired.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_db_deletedata(dns_db_t *db, dns_dbnode_t *node, void *data);
|
||||
/*%<
|
||||
* Tell the database 'db' to prepare to delete the block of data 'data'
|
||||
* stored at node 'node. This may include, for example, removing the
|
||||
* data from an LRU list or a heap.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_db_expiredata(dns_db_t *db, dns_dbnode_t *node, void *data);
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -54,6 +54,18 @@
|
|||
#include <dns/rdatastruct.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
/* Fixed RRSet helper macros */
|
||||
|
||||
#define DNS_RDATASET_LENGTH 2;
|
||||
|
||||
#if DNS_RDATASET_FIXED
|
||||
#define DNS_RDATASET_ORDER 2
|
||||
#define DNS_RDATASET_COUNT (count * 4)
|
||||
#else /* !DNS_RDATASET_FIXED */
|
||||
#define DNS_RDATASET_ORDER 0
|
||||
#define DNS_RDATASET_COUNT 0
|
||||
#endif /* DNS_RDATASET_FIXED */
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -648,28 +660,6 @@ dns_rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name);
|
|||
* according to it. If CASESET is not set, do nothing.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version,
|
||||
dns_message_t *msg);
|
||||
/*%<
|
||||
* Add glue records for rdataset to the additional section of message in
|
||||
* 'msg'. 'rdataset' must be of type NS.
|
||||
*
|
||||
* In case a successful result is not returned, the caller should try to
|
||||
* add glue directly to the message by iterating for additional data.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'rdataset' is a valid NS rdataset.
|
||||
* \li 'version' is the DB version.
|
||||
* \li 'msg' is the DNS message to which the glue should be added.
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_SUCCESS
|
||||
*\li #ISC_R_NOTIMPLEMENTED
|
||||
*\li #ISC_R_FAILURE
|
||||
*\li Any error that dns_rdata_additionaldata() can return.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
|
||||
dns_rdata_rrsig_t *rrsig, isc_stdtime_t now,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/heap.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/urcu.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
|
||||
|
|
@ -54,6 +56,109 @@ ISC_LANG_BEGINDECLS
|
|||
|
||||
#define DNS_RDATASLAB_OFFLINE 0x01 /* RRSIG is for offline DNSKEY */
|
||||
|
||||
struct dns_proof {
|
||||
dns_name_t name;
|
||||
void *neg;
|
||||
void *negsig;
|
||||
dns_rdatatype_t type;
|
||||
};
|
||||
|
||||
struct dns_slabheader {
|
||||
/*%
|
||||
* Locked by the owning node's lock.
|
||||
*/
|
||||
uint32_t serial;
|
||||
dns_ttl_t ttl;
|
||||
dns_typepair_t type;
|
||||
atomic_uint_least16_t attributes;
|
||||
dns_trust_t trust;
|
||||
|
||||
unsigned int heap_index;
|
||||
/*%<
|
||||
* Used for TTL-based cache cleaning.
|
||||
*/
|
||||
|
||||
isc_stdtime_t resign;
|
||||
unsigned int resign_lsb : 1;
|
||||
|
||||
atomic_uint_fast16_t count;
|
||||
/*%<
|
||||
* Monotonically increased every time this rdataset is bound so that
|
||||
* it is used as the base of the starting point in DNS responses
|
||||
* when the "cyclic" rrset-order is required.
|
||||
*/
|
||||
|
||||
atomic_uint_fast32_t last_refresh_fail_ts;
|
||||
|
||||
dns_proof_t *noqname;
|
||||
dns_proof_t *closest;
|
||||
/*%<
|
||||
* We don't use the LIST macros, because the LIST structure has
|
||||
* both head and tail pointers, and is doubly linked.
|
||||
*/
|
||||
|
||||
struct dns_slabheader *next;
|
||||
/*%<
|
||||
* If this is the top header for an rdataset, 'next' points
|
||||
* to the top header for the next rdataset (i.e., the next type).
|
||||
* Otherwise, it points up to the header whose down pointer points
|
||||
* at this header.
|
||||
*/
|
||||
|
||||
struct dns_slabheader *down;
|
||||
/*%<
|
||||
* Points to the header for the next older version of
|
||||
* this rdataset.
|
||||
*/
|
||||
|
||||
dns_db_t *db;
|
||||
dns_dbnode_t *node;
|
||||
/*%<
|
||||
* The database and database node objects containing
|
||||
* this rdataset, if any.
|
||||
*/
|
||||
|
||||
isc_stdtime_t last_used;
|
||||
ISC_LINK(struct dns_slabheader) link;
|
||||
|
||||
/*%
|
||||
* Case vector. If the bit is set then the corresponding
|
||||
* character in the owner name needs to be AND'd with 0x20,
|
||||
* rendering that character upper case.
|
||||
*/
|
||||
unsigned char upper[32];
|
||||
|
||||
isc_heap_t *heap;
|
||||
dns_glue_t *glue_list;
|
||||
struct cds_wfs_node wfs_node;
|
||||
};
|
||||
|
||||
enum {
|
||||
DNS_SLABHEADERATTR_NONEXISTENT = 1 << 0,
|
||||
DNS_SLABHEADERATTR_STALE = 1 << 1,
|
||||
DNS_SLABHEADERATTR_IGNORE = 1 << 2,
|
||||
DNS_SLABHEADERATTR_NXDOMAIN = 1 << 3,
|
||||
DNS_SLABHEADERATTR_RESIGN = 1 << 4,
|
||||
DNS_SLABHEADERATTR_STATCOUNT = 1 << 5,
|
||||
DNS_SLABHEADERATTR_OPTOUT = 1 << 6,
|
||||
DNS_SLABHEADERATTR_NEGATIVE = 1 << 7,
|
||||
DNS_SLABHEADERATTR_PREFETCH = 1 << 8,
|
||||
DNS_SLABHEADERATTR_CASESET = 1 << 9,
|
||||
DNS_SLABHEADERATTR_ZEROTTL = 1 << 10,
|
||||
DNS_SLABHEADERATTR_CASEFULLYLOWER = 1 << 11,
|
||||
DNS_SLABHEADERATTR_ANCIENT = 1 << 12,
|
||||
DNS_SLABHEADERATTR_STALE_WINDOW = 1 << 13,
|
||||
};
|
||||
|
||||
#define DNS_SLABHEADER_GETATTR(header, attribute) \
|
||||
(atomic_load_acquire(&(header)->attributes) & attribute)
|
||||
#define DNS_SLABHEADER_SETATTR(header, attribute) \
|
||||
atomic_fetch_or_release(&(header)->attributes, attribute)
|
||||
#define DNS_SLABHEADER_CLRATTR(header, attribute) \
|
||||
atomic_fetch_and_release(&(header)->attributes, ~(attribute))
|
||||
|
||||
extern dns_rdatasetmethods_t dns_rdataslab_rdatasetmethods;
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
|
@ -161,4 +266,47 @@ dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
|
|||
*\li true if the slabs are equal, #false otherwise.
|
||||
*/
|
||||
|
||||
dns_slabheader_t *
|
||||
dns_slabheader_fromrdataset(const dns_rdataset_t *rdataset);
|
||||
/*%
|
||||
* Returns the address of the slab header for a slab-type rdataset.
|
||||
*/
|
||||
|
||||
void *
|
||||
dns_slabheader_raw(dns_slabheader_t *header);
|
||||
/*%
|
||||
* Returns the address of the raw memory following a dns_slabheader.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_slabheader_setownercase(dns_slabheader_t *header, const dns_name_t *name);
|
||||
/*%<
|
||||
* Store the casing of 'name', into a bitfield in 'header'.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_slabheader_copycase(dns_slabheader_t *dest, dns_slabheader_t *src);
|
||||
/*%<
|
||||
* Copy the casing of 'src', into 'dest'.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_slabheader_reset(dns_slabheader_t *h, dns_db_t *db, dns_dbnode_t *node);
|
||||
/*%<
|
||||
* Reset an rdataslab header 'h' so it can be used to store data in
|
||||
* database 'db' and node 'node'.
|
||||
*/
|
||||
|
||||
dns_slabheader_t *
|
||||
dns_slabheader_new(dns_db_t *db, dns_dbnode_t *node);
|
||||
/*%<
|
||||
* Allocate memory for an rdataslab header and initialize it for use
|
||||
* in database 'db'/node 'node'.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_slabheader_destroy(dns_slabheader_t **headerp);
|
||||
/*%<
|
||||
* Free all memory associated with '*headerp'.
|
||||
*/
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ typedef struct dns_forwarders dns_forwarders_t;
|
|||
typedef struct dns_forwarder dns_forwarder_t;
|
||||
typedef struct dns_fwdtable dns_fwdtable_t;
|
||||
typedef struct dns_geoip_databases dns_geoip_databases_t;
|
||||
typedef struct dns_glue dns_glue_t;
|
||||
typedef struct dns_iptable dns_iptable_t;
|
||||
typedef uint32_t dns_iterations_t;
|
||||
typedef struct dns_kasp dns_kasp_t;
|
||||
|
|
|
|||
1742
lib/dns/rbtdb.c
1742
lib/dns/rbtdb.c
File diff suppressed because it is too large
Load diff
|
|
@ -13,8 +13,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <isc/heap.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/urcu.h>
|
||||
|
||||
#include <dns/nsec3.h>
|
||||
#include <dns/rbt.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
/*%
|
||||
|
|
@ -135,6 +139,15 @@
|
|||
TREE_UNLOCK(l, tp); \
|
||||
TREE_WRLOCK(l, tp); \
|
||||
}
|
||||
|
||||
#define RDATASET_RBTDB(r) ((dns_rbtdb_t *)(r)->slab.db)
|
||||
#define RDATASET_DBNODE(r) ((dns_rbtnode_t *)(r)->slab.node)
|
||||
|
||||
#define HEADER_NODE(h) ((dns_rbtnode_t *)((h)->node))
|
||||
|
||||
#define IS_STUB(rbtdb) (((rbtdb)->common.attributes & DNS_DBATTR_STUB) != 0)
|
||||
#define IS_CACHE(rbtdb) (((rbtdb)->common.attributes & DNS_DBATTR_CACHE) != 0)
|
||||
|
||||
/*****
|
||||
***** Module Info
|
||||
*****/
|
||||
|
|
@ -146,6 +159,179 @@
|
|||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
typedef struct {
|
||||
isc_rwlock_t lock;
|
||||
/* Protected in the refcount routines. */
|
||||
isc_refcount_t references;
|
||||
/* Locked by lock. */
|
||||
bool exiting;
|
||||
} rbtdb_nodelock_t;
|
||||
|
||||
typedef struct rbtdb_changed {
|
||||
dns_rbtnode_t *node;
|
||||
bool dirty;
|
||||
ISC_LINK(struct rbtdb_changed) link;
|
||||
} rbtdb_changed_t;
|
||||
|
||||
typedef ISC_LIST(rbtdb_changed_t) rbtdb_changedlist_t;
|
||||
|
||||
struct dns_glue {
|
||||
struct dns_glue *next;
|
||||
dns_fixedname_t fixedname;
|
||||
dns_rdataset_t rdataset_a;
|
||||
dns_rdataset_t sigrdataset_a;
|
||||
dns_rdataset_t rdataset_aaaa;
|
||||
dns_rdataset_t sigrdataset_aaaa;
|
||||
|
||||
isc_mem_t *mctx;
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
dns_glue_t *glue_list;
|
||||
dns_rbtdb_t *rbtdb;
|
||||
dns_rbtdb_version_t *rbtversion;
|
||||
dns_name_t *nodename;
|
||||
} dns_glue_additionaldata_ctx_t;
|
||||
|
||||
struct dns_rbtdb_version {
|
||||
/* Not locked */
|
||||
uint32_t serial;
|
||||
dns_rbtdb_t *rbtdb;
|
||||
/*
|
||||
* Protected in the refcount routines.
|
||||
* XXXJT: should we change the lock policy based on the refcount
|
||||
* performance?
|
||||
*/
|
||||
isc_refcount_t references;
|
||||
/* Locked by database lock. */
|
||||
bool writer;
|
||||
bool commit_ok;
|
||||
rbtdb_changedlist_t changed_list;
|
||||
dns_slabheaderlist_t resigned_list;
|
||||
ISC_LINK(dns_rbtdb_version_t) link;
|
||||
bool secure;
|
||||
bool havensec3;
|
||||
/* NSEC3 parameters */
|
||||
dns_hash_t hash;
|
||||
uint8_t flags;
|
||||
uint16_t iterations;
|
||||
uint8_t salt_length;
|
||||
unsigned char salt[DNS_NSEC3_SALTSIZE];
|
||||
|
||||
/*
|
||||
* records and xfrsize are covered by rwlock.
|
||||
*/
|
||||
isc_rwlock_t rwlock;
|
||||
uint64_t records;
|
||||
uint64_t xfrsize;
|
||||
|
||||
struct cds_wfs_stack glue_stack;
|
||||
};
|
||||
|
||||
typedef ISC_LIST(dns_rbtdb_version_t) rbtdb_versionlist_t;
|
||||
|
||||
struct dns_rbtdb {
|
||||
/* Unlocked. */
|
||||
dns_db_t common;
|
||||
/* Locks the data in this struct */
|
||||
isc_rwlock_t lock;
|
||||
/* Locks the tree structure (prevents nodes appearing/disappearing) */
|
||||
isc_rwlock_t tree_lock;
|
||||
/* Locks for individual tree nodes */
|
||||
unsigned int node_lock_count;
|
||||
rbtdb_nodelock_t *node_locks;
|
||||
dns_rbtnode_t *origin_node;
|
||||
dns_rbtnode_t *nsec3_origin_node;
|
||||
dns_stats_t *rrsetstats; /* cache DB only */
|
||||
isc_stats_t *cachestats; /* cache DB only */
|
||||
isc_stats_t *gluecachestats; /* zone DB only */
|
||||
/* Locked by lock. */
|
||||
unsigned int active;
|
||||
unsigned int attributes;
|
||||
uint32_t current_serial;
|
||||
uint32_t least_serial;
|
||||
uint32_t next_serial;
|
||||
dns_rbtdb_version_t *current_version;
|
||||
dns_rbtdb_version_t *future_version;
|
||||
rbtdb_versionlist_t open_versions;
|
||||
isc_loop_t *loop;
|
||||
dns_dbnode_t *soanode;
|
||||
dns_dbnode_t *nsnode;
|
||||
|
||||
/*
|
||||
* The time after a failed lookup, where stale answers from cache
|
||||
* may be used directly in a DNS response without attempting a
|
||||
* new iterative lookup.
|
||||
*/
|
||||
uint32_t serve_stale_refresh;
|
||||
|
||||
/*
|
||||
* This is a linked list used to implement the LRU cache. There will
|
||||
* be node_lock_count linked lists here. Nodes in bucket 1 will be
|
||||
* placed on the linked list lru[1].
|
||||
*/
|
||||
dns_slabheaderlist_t *lru;
|
||||
|
||||
/*%
|
||||
* Temporary storage for stale cache nodes and dynamically deleted
|
||||
* nodes that await being cleaned up.
|
||||
*/
|
||||
dns_rbtnodelist_t *deadnodes;
|
||||
|
||||
/*
|
||||
* Heaps. These are used for TTL based expiry in a cache,
|
||||
* or for zone resigning in a zone DB. hmctx is the memory
|
||||
* context to use for the heap (which differs from the main
|
||||
* database memory context in the case of a cache).
|
||||
*/
|
||||
isc_mem_t *hmctx;
|
||||
isc_heap_t **heaps;
|
||||
|
||||
/* Locked by tree_lock. */
|
||||
dns_rbt_t *tree;
|
||||
dns_rbt_t *nsec;
|
||||
dns_rbt_t *nsec3;
|
||||
|
||||
/* Unlocked */
|
||||
unsigned int quantum;
|
||||
};
|
||||
|
||||
/*%
|
||||
* Search Context
|
||||
*/
|
||||
typedef struct {
|
||||
dns_rbtdb_t *rbtdb;
|
||||
dns_rbtdb_version_t *rbtversion;
|
||||
uint32_t serial;
|
||||
unsigned int options;
|
||||
dns_rbtnodechain_t chain;
|
||||
bool copy_name;
|
||||
bool need_cleanup;
|
||||
bool wild;
|
||||
dns_rbtnode_t *zonecut;
|
||||
dns_slabheader_t *zonecut_header;
|
||||
dns_slabheader_t *zonecut_sigheader;
|
||||
dns_fixedname_t zonecut_name;
|
||||
isc_stdtime_t now;
|
||||
} rbtdb_search_t;
|
||||
|
||||
/*%
|
||||
* Load Context
|
||||
*/
|
||||
typedef struct {
|
||||
dns_rbtdb_t *rbtdb;
|
||||
isc_stdtime_t now;
|
||||
} rbtdb_load_t;
|
||||
|
||||
/*%
|
||||
* Prune context
|
||||
*/
|
||||
typedef struct {
|
||||
dns_db_t *db;
|
||||
dns_rbtnode_t *node;
|
||||
} prune_t;
|
||||
|
||||
extern dns_dbmethods_t dns__rbtdb_zonemethods;
|
||||
extern dns_dbmethods_t dns__rbtdb_cachemethods;
|
||||
|
||||
|
|
@ -187,7 +373,10 @@ dns__rbtdb_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
|
|||
isc_result_t
|
||||
dns__rbtdb_findnode(dns_db_t *db, const dns_name_t *name, bool create,
|
||||
dns_dbnode_t **nodep DNS__DB_FLARG);
|
||||
|
||||
isc_result_t
|
||||
dns__rbtdb_findnodeintree(dns_rbtdb_t *rbtdb, dns_rbt_t *tree,
|
||||
const dns_name_t *name, bool create,
|
||||
dns_dbnode_t **nodep DNS__DB_FLARG);
|
||||
void
|
||||
dns__rbtdb_attachnode(dns_db_t *db, dns_dbnode_t *source,
|
||||
dns_dbnode_t **targetp DNS__DB_FLARG);
|
||||
|
|
@ -237,8 +426,33 @@ dns__rbtdb_bindrdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
|||
dns_rdataset_t *rdataset DNS__DB_FLARG);
|
||||
|
||||
void
|
||||
dns__rbtdb_expireheader(dns_rbtdb_t *rbtdb, dns_slabheader_t *header,
|
||||
isc_rwlocktype_t *nlocktypep,
|
||||
isc_rwlocktype_t *tlocktypep,
|
||||
dns__rbtdb_expireheader(dns_slabheader_t *header, isc_rwlocktype_t *tlocktypep,
|
||||
dns_expire_t reason DNS__DB_FLARG);
|
||||
|
||||
void
|
||||
dns__rbtdb_locknode(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t type);
|
||||
void
|
||||
dns__rbtdb_unlocknode(dns_db_t *db, dns_dbnode_t *node, isc_rwlocktype_t type);
|
||||
|
||||
isc_result_t
|
||||
dns__rbtdb_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name);
|
||||
void
|
||||
dns__rbtdb_freeglue(dns_glue_t *glue_list);
|
||||
bool
|
||||
dns__rbtdb_decref(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
uint32_t least_serial, isc_rwlocktype_t *nlocktypep,
|
||||
isc_rwlocktype_t *tlocktypep, bool tryupgrade,
|
||||
bool pruning DNS__DB_FLARG);
|
||||
void
|
||||
dns__rbtdb_resigninsert(dns_rbtdb_t *rbtdb, int idx,
|
||||
dns_slabheader_t *newheader);
|
||||
void
|
||||
dns__rbtdb_resigndelete(dns_rbtdb_t *rbtdb, dns_rbtdb_version_t *version,
|
||||
dns_slabheader_t *header DNS__DB_FLARG);
|
||||
isc_result_t
|
||||
dns__rbtdb_add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
||||
const dns_name_t *nodename, dns_rbtdb_version_t *rbtversion,
|
||||
dns_slabheader_t *newheader, unsigned int options,
|
||||
bool loading, dns_rdataset_t *addedrdataset,
|
||||
isc_stdtime_t now DNS__DB_FLARG);
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -671,17 +671,3 @@ dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
|
|||
rdataset->ttl = ttl;
|
||||
sigrdataset->ttl = ttl;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version,
|
||||
dns_message_t *msg) {
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
REQUIRE(rdataset->type == dns_rdatatype_ns);
|
||||
|
||||
if (rdataset->methods->addglue == NULL) {
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
return ((rdataset->methods->addglue)(rdataset, version, msg));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,18 +13,32 @@
|
|||
|
||||
/*! \file */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <isc/ascii.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/region.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/rdataslab.h>
|
||||
#include <dns/stats.h>
|
||||
|
||||
#define CASESET(header) \
|
||||
((atomic_load_acquire(&(header)->attributes) & \
|
||||
DNS_SLABHEADERATTR_CASESET) != 0)
|
||||
#define CASEFULLYLOWER(header) \
|
||||
((atomic_load_acquire(&(header)->attributes) & \
|
||||
DNS_SLABHEADERATTR_CASEFULLYLOWER) != 0)
|
||||
#define NONEXISTENT(header) \
|
||||
((atomic_load_acquire(&(header)->attributes) & \
|
||||
DNS_SLABHEADERATTR_NONEXISTENT) != 0)
|
||||
|
||||
/*
|
||||
* The rdataslab structure allows iteration to occur in both load order
|
||||
|
|
@ -75,6 +89,52 @@ struct xrdata {
|
|||
#endif /* if DNS_RDATASET_FIXED */
|
||||
};
|
||||
|
||||
struct dns_glue {
|
||||
struct dns_glue *next;
|
||||
dns_fixedname_t fixedname;
|
||||
dns_rdataset_t rdataset_a;
|
||||
dns_rdataset_t sigrdataset_a;
|
||||
dns_rdataset_t rdataset_aaaa;
|
||||
dns_rdataset_t sigrdataset_aaaa;
|
||||
struct cds_wfs_node wfs_node;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
dns_glue_t *glue_list;
|
||||
dns_rbtdb_t *rbtdb;
|
||||
dns_rbtdb_version_t *rbtversion;
|
||||
dns_name_t *nodename;
|
||||
} dns_glue_additionaldata_ctx_t;
|
||||
|
||||
static void
|
||||
rdataset_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG);
|
||||
static isc_result_t
|
||||
rdataset_first(dns_rdataset_t *rdataset);
|
||||
static isc_result_t
|
||||
rdataset_next(dns_rdataset_t *rdataset);
|
||||
static void
|
||||
rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
|
||||
static void
|
||||
rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG);
|
||||
static unsigned int
|
||||
rdataset_count(dns_rdataset_t *rdataset);
|
||||
static isc_result_t
|
||||
rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
|
||||
dns_rdataset_t *neg, dns_rdataset_t *negsig DNS__DB_FLARG);
|
||||
static isc_result_t
|
||||
rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
|
||||
dns_rdataset_t *neg, dns_rdataset_t *negsig DNS__DB_FLARG);
|
||||
static void
|
||||
rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
|
||||
static void
|
||||
rdataset_expire(dns_rdataset_t *rdataset DNS__DB_FLARG);
|
||||
static void
|
||||
rdataset_clearprefetch(dns_rdataset_t *rdataset);
|
||||
static void
|
||||
rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name);
|
||||
static void
|
||||
rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name);
|
||||
|
||||
/*% Note: the "const void *" are just to make qsort happy. */
|
||||
static int
|
||||
compare_rdata(const void *p1, const void *p2) {
|
||||
|
|
@ -919,7 +979,7 @@ dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
|
|||
bool
|
||||
dns_rdataslab_equal(unsigned char *slab1, unsigned char *slab2,
|
||||
unsigned int reservelen) {
|
||||
unsigned char *current1, *current2;
|
||||
unsigned char *current1 = NULL, *current2 = NULL;
|
||||
unsigned int count1, count2;
|
||||
unsigned int length1, length2;
|
||||
|
||||
|
|
@ -970,7 +1030,7 @@ bool
|
|||
dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
|
||||
unsigned int reservelen, dns_rdataclass_t rdclass,
|
||||
dns_rdatatype_t type) {
|
||||
unsigned char *current1, *current2;
|
||||
unsigned char *current1 = NULL, *current2 = NULL;
|
||||
unsigned int count1, count2;
|
||||
dns_rdata_t rdata1 = DNS_RDATA_INIT;
|
||||
dns_rdata_t rdata2 = DNS_RDATA_INIT;
|
||||
|
|
@ -1003,3 +1063,441 @@ dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
|
|||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
dns_slabheader_t *
|
||||
dns_slabheader_fromrdataset(const dns_rdataset_t *rdataset) {
|
||||
dns_slabheader_t *header = (dns_slabheader_t *)rdataset->slab.raw;
|
||||
return (header - 1);
|
||||
}
|
||||
|
||||
void *
|
||||
dns_slabheader_raw(dns_slabheader_t *header) {
|
||||
return (header + 1);
|
||||
}
|
||||
|
||||
void
|
||||
dns_slabheader_setownercase(dns_slabheader_t *header, const dns_name_t *name) {
|
||||
unsigned int i;
|
||||
bool fully_lower;
|
||||
|
||||
/*
|
||||
* We do not need to worry about label lengths as they are all
|
||||
* less than or equal to 63.
|
||||
*/
|
||||
memset(header->upper, 0, sizeof(header->upper));
|
||||
fully_lower = true;
|
||||
for (i = 0; i < name->length; i++) {
|
||||
if (isupper(name->ndata[i])) {
|
||||
header->upper[i / 8] |= 1 << (i % 8);
|
||||
fully_lower = false;
|
||||
}
|
||||
}
|
||||
DNS_SLABHEADER_SETATTR(header, DNS_SLABHEADERATTR_CASESET);
|
||||
if (fully_lower) {
|
||||
DNS_SLABHEADER_SETATTR(header,
|
||||
DNS_SLABHEADERATTR_CASEFULLYLOWER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_slabheader_copycase(dns_slabheader_t *dest, dns_slabheader_t *src) {
|
||||
if (CASESET(src)) {
|
||||
uint_least16_t attr = DNS_SLABHEADER_GETATTR(
|
||||
src, (DNS_SLABHEADERATTR_CASESET |
|
||||
DNS_SLABHEADERATTR_CASEFULLYLOWER));
|
||||
DNS_SLABHEADER_SETATTR(dest, attr);
|
||||
memmove(dest->upper, src->upper, sizeof(src->upper));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_slabheader_reset(dns_slabheader_t *h, dns_db_t *db, dns_dbnode_t *node) {
|
||||
ISC_LINK_INIT(h, link);
|
||||
h->heap_index = 0;
|
||||
h->heap = NULL;
|
||||
h->glue_list = NULL;
|
||||
h->db = db;
|
||||
h->node = node;
|
||||
|
||||
atomic_init(&h->attributes, 0);
|
||||
atomic_init(&h->last_refresh_fail_ts, 0);
|
||||
|
||||
cds_wfs_node_init(&h->wfs_node);
|
||||
|
||||
STATIC_ASSERT((sizeof(h->attributes) == 2),
|
||||
"The .attributes field of dns_slabheader_t needs to be "
|
||||
"16-bit int type exactly.");
|
||||
}
|
||||
|
||||
dns_slabheader_t *
|
||||
dns_slabheader_new(dns_db_t *db, dns_dbnode_t *node) {
|
||||
dns_slabheader_t *h = NULL;
|
||||
|
||||
h = isc_mem_get(db->mctx, sizeof(*h));
|
||||
*h = (dns_slabheader_t){
|
||||
.link = ISC_LINK_INITIALIZER,
|
||||
};
|
||||
dns_slabheader_reset(h, db, node);
|
||||
return (h);
|
||||
}
|
||||
|
||||
void
|
||||
dns_slabheader_destroy(dns_slabheader_t **headerp) {
|
||||
unsigned int size;
|
||||
dns_slabheader_t *header = *headerp;
|
||||
|
||||
*headerp = NULL;
|
||||
|
||||
isc_mem_t *mctx = header->db->mctx;
|
||||
|
||||
dns_db_deletedata(header->db, header->node, header);
|
||||
|
||||
if (NONEXISTENT(header)) {
|
||||
size = sizeof(*header);
|
||||
} else {
|
||||
size = dns_rdataslab_size((unsigned char *)header,
|
||||
sizeof(*header));
|
||||
}
|
||||
|
||||
isc_mem_put(mctx, header, size);
|
||||
}
|
||||
|
||||
dns_rdatasetmethods_t dns_rdataslab_rdatasetmethods = {
|
||||
.disassociate = rdataset_disassociate,
|
||||
.first = rdataset_first,
|
||||
.next = rdataset_next,
|
||||
.current = rdataset_current,
|
||||
.clone = rdataset_clone,
|
||||
.count = rdataset_count,
|
||||
.getnoqname = rdataset_getnoqname,
|
||||
.getclosest = rdataset_getclosest,
|
||||
.settrust = rdataset_settrust,
|
||||
.expire = rdataset_expire,
|
||||
.clearprefetch = rdataset_clearprefetch,
|
||||
.setownercase = rdataset_setownercase,
|
||||
.getownercase = rdataset_getownercase,
|
||||
};
|
||||
|
||||
/* Fixed RRSet helper macros */
|
||||
|
||||
#define DNS_RDATASET_LENGTH 2;
|
||||
|
||||
#if DNS_RDATASET_FIXED
|
||||
#define DNS_RDATASET_ORDER 2
|
||||
#define DNS_RDATASET_COUNT (count * 4)
|
||||
#else /* !DNS_RDATASET_FIXED */
|
||||
#define DNS_RDATASET_ORDER 0
|
||||
#define DNS_RDATASET_COUNT 0
|
||||
#endif /* DNS_RDATASET_FIXED */
|
||||
|
||||
static void
|
||||
rdataset_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) {
|
||||
dns_db_t *db = rdataset->slab.db;
|
||||
dns_dbnode_t *node = rdataset->slab.node;
|
||||
|
||||
dns__db_detachnode(db, &node DNS__DB_FLARG_PASS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rdataset_first(dns_rdataset_t *rdataset) {
|
||||
unsigned char *raw = NULL;
|
||||
unsigned int count;
|
||||
|
||||
raw = rdataset->slab.raw;
|
||||
count = raw[0] * 256 + raw[1];
|
||||
if (count == 0) {
|
||||
rdataset->slab.iter_pos = NULL;
|
||||
rdataset->slab.iter_count = 0;
|
||||
return (ISC_R_NOMORE);
|
||||
}
|
||||
|
||||
if ((rdataset->attributes & DNS_RDATASETATTR_LOADORDER) == 0) {
|
||||
raw += DNS_RDATASET_COUNT;
|
||||
}
|
||||
|
||||
/*
|
||||
* iter_count is the number of rdata beyond the cursor
|
||||
* position, so we decrement the total count by one before
|
||||
* storing it.
|
||||
*
|
||||
* If DNS_RDATASETATTR_LOADORDER is not set 'raw' points to the
|
||||
* first record. If DNS_RDATASETATTR_LOADORDER is set 'raw' points
|
||||
* to the first entry in the offset table.
|
||||
*/
|
||||
rdataset->slab.iter_pos = raw + DNS_RDATASET_LENGTH;
|
||||
rdataset->slab.iter_count = count - 1;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rdataset_next(dns_rdataset_t *rdataset) {
|
||||
unsigned int count;
|
||||
unsigned int length;
|
||||
unsigned char *raw = NULL;
|
||||
|
||||
count = rdataset->slab.iter_count;
|
||||
if (count == 0) {
|
||||
rdataset->slab.iter_pos = NULL;
|
||||
return (ISC_R_NOMORE);
|
||||
}
|
||||
rdataset->slab.iter_count = count - 1;
|
||||
|
||||
/*
|
||||
* Skip forward one record (length + 4) or one offset (4).
|
||||
*/
|
||||
raw = rdataset->slab.iter_pos;
|
||||
#if DNS_RDATASET_FIXED
|
||||
if ((rdataset->attributes & DNS_RDATASETATTR_LOADORDER) == 0)
|
||||
#endif /* DNS_RDATASET_FIXED */
|
||||
{
|
||||
length = raw[0] * 256 + raw[1];
|
||||
raw += length;
|
||||
}
|
||||
rdataset->slab.iter_pos = raw + DNS_RDATASET_ORDER +
|
||||
DNS_RDATASET_LENGTH;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
|
||||
unsigned char *raw = NULL;
|
||||
unsigned int length;
|
||||
isc_region_t r;
|
||||
unsigned int flags = 0;
|
||||
|
||||
raw = rdataset->slab.iter_pos;
|
||||
REQUIRE(raw != NULL);
|
||||
|
||||
/*
|
||||
* Find the start of the record if not already in iter_pos
|
||||
* then skip the length and order fields.
|
||||
*/
|
||||
#if DNS_RDATASET_FIXED
|
||||
if ((rdataset->attributes & DNS_RDATASETATTR_LOADORDER) != 0) {
|
||||
unsigned int offset;
|
||||
offset = ((unsigned int)raw[0] << 24) +
|
||||
((unsigned int)raw[1] << 16) +
|
||||
((unsigned int)raw[2] << 8) + (unsigned int)raw[3];
|
||||
raw = rdataset->slab.raw + offset;
|
||||
}
|
||||
#endif /* if DNS_RDATASET_FIXED */
|
||||
|
||||
length = raw[0] * 256 + raw[1];
|
||||
|
||||
raw += DNS_RDATASET_ORDER + DNS_RDATASET_LENGTH;
|
||||
|
||||
if (rdataset->type == dns_rdatatype_rrsig) {
|
||||
if (*raw & DNS_RDATASLAB_OFFLINE) {
|
||||
flags |= DNS_RDATA_OFFLINE;
|
||||
}
|
||||
length--;
|
||||
raw++;
|
||||
}
|
||||
r.length = length;
|
||||
r.base = raw;
|
||||
dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
|
||||
rdata->flags |= flags;
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) {
|
||||
dns_db_t *db = source->slab.db;
|
||||
dns_dbnode_t *node = source->slab.node;
|
||||
dns_dbnode_t *cloned_node = NULL;
|
||||
|
||||
dns__db_attachnode(db, node, &cloned_node DNS__DB_FLARG_PASS);
|
||||
INSIST(!ISC_LINK_LINKED(target, link));
|
||||
*target = *source;
|
||||
ISC_LINK_INIT(target, link);
|
||||
|
||||
target->slab.iter_pos = NULL;
|
||||
target->slab.iter_count = 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
rdataset_count(dns_rdataset_t *rdataset) {
|
||||
unsigned char *raw = NULL;
|
||||
unsigned int count;
|
||||
|
||||
raw = rdataset->slab.raw;
|
||||
count = raw[0] * 256 + raw[1];
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
|
||||
dns_rdataset_t *nsec,
|
||||
dns_rdataset_t *nsecsig DNS__DB_FLARG) {
|
||||
dns_db_t *db = rdataset->slab.db;
|
||||
dns_dbnode_t *node = rdataset->slab.node;
|
||||
const dns_proof_t *noqname = rdataset->slab.noqname;
|
||||
|
||||
/*
|
||||
* Usually, rdataset->slab.raw refers the data following a
|
||||
* dns_slabheader, but in this case it points to a bare
|
||||
* rdataslab belonging to the dns_slabheader's `noqname` field.
|
||||
* The DNS_RDATASETATTR_KEEPCASE attribute is set to prevent
|
||||
* setownercase and getownercase methods from affecting the
|
||||
* case of NSEC/NSEC3 owner names.
|
||||
*/
|
||||
dns__db_attachnode(db, node,
|
||||
&(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
|
||||
*nsec = (dns_rdataset_t){
|
||||
.methods = &dns_rdataslab_rdatasetmethods,
|
||||
.rdclass = db->rdclass,
|
||||
.type = noqname->type,
|
||||
.ttl = rdataset->ttl,
|
||||
.trust = rdataset->trust,
|
||||
.slab.db = db,
|
||||
.slab.node = node,
|
||||
.slab.raw = noqname->neg,
|
||||
.link = nsec->link,
|
||||
.count = nsec->count,
|
||||
.attributes = nsec->attributes | DNS_RDATASETATTR_KEEPCASE,
|
||||
.magic = nsec->magic,
|
||||
};
|
||||
|
||||
dns__db_attachnode(db, node,
|
||||
&(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
|
||||
*nsecsig = (dns_rdataset_t){
|
||||
.methods = &dns_rdataslab_rdatasetmethods,
|
||||
.rdclass = db->rdclass,
|
||||
.type = dns_rdatatype_rrsig,
|
||||
.covers = noqname->type,
|
||||
.ttl = rdataset->ttl,
|
||||
.trust = rdataset->trust,
|
||||
.slab.db = db,
|
||||
.slab.node = node,
|
||||
.slab.raw = noqname->negsig,
|
||||
.link = nsecsig->link,
|
||||
.count = nsecsig->count,
|
||||
.attributes = nsecsig->attributes | DNS_RDATASETATTR_KEEPCASE,
|
||||
.magic = nsecsig->magic,
|
||||
};
|
||||
|
||||
dns_name_clone(&noqname->name, name);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
|
||||
dns_rdataset_t *nsec,
|
||||
dns_rdataset_t *nsecsig DNS__DB_FLARG) {
|
||||
dns_db_t *db = rdataset->slab.db;
|
||||
dns_dbnode_t *node = rdataset->slab.node;
|
||||
const dns_proof_t *closest = rdataset->slab.closest;
|
||||
|
||||
/*
|
||||
* As mentioned above, rdataset->slab.raw usually refers the data
|
||||
* following an dns_slabheader, but in this case it points to a bare
|
||||
* rdataslab belonging to the dns_slabheader's `closest` field.
|
||||
*/
|
||||
dns__db_attachnode(db, node,
|
||||
&(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
|
||||
*nsec = (dns_rdataset_t){
|
||||
.methods = &dns_rdataslab_rdatasetmethods,
|
||||
.rdclass = db->rdclass,
|
||||
.type = closest->type,
|
||||
.ttl = rdataset->ttl,
|
||||
.trust = rdataset->trust,
|
||||
.slab.db = db,
|
||||
.slab.node = node,
|
||||
.slab.raw = closest->neg,
|
||||
.link = nsec->link,
|
||||
.count = nsec->count,
|
||||
.attributes = nsec->attributes | DNS_RDATASETATTR_KEEPCASE,
|
||||
.magic = nsec->magic,
|
||||
};
|
||||
|
||||
dns__db_attachnode(db, node,
|
||||
&(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
|
||||
*nsecsig = (dns_rdataset_t){
|
||||
.methods = &dns_rdataslab_rdatasetmethods,
|
||||
.rdclass = db->rdclass,
|
||||
.type = dns_rdatatype_rrsig,
|
||||
.covers = closest->type,
|
||||
.ttl = rdataset->ttl,
|
||||
.trust = rdataset->trust,
|
||||
.slab.db = db,
|
||||
.slab.node = node,
|
||||
.slab.raw = closest->negsig,
|
||||
.link = nsecsig->link,
|
||||
.count = nsecsig->count,
|
||||
.attributes = nsecsig->attributes | DNS_RDATASETATTR_KEEPCASE,
|
||||
.magic = nsecsig->magic,
|
||||
};
|
||||
|
||||
dns_name_clone(&closest->name, name);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
|
||||
dns_db_locknode(header->db, header->node, isc_rwlocktype_write);
|
||||
header->trust = rdataset->trust = trust;
|
||||
dns_db_unlocknode(header->db, header->node, isc_rwlocktype_write);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_expire(dns_rdataset_t *rdataset DNS__DB_FLARG) {
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
|
||||
dns_db_expiredata(header->db, header->node, header);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_clearprefetch(dns_rdataset_t *rdataset) {
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
|
||||
dns_db_locknode(header->db, header->node, isc_rwlocktype_write);
|
||||
DNS_SLABHEADER_CLRATTR(header, DNS_SLABHEADERATTR_PREFETCH);
|
||||
dns_db_unlocknode(header->db, header->node, isc_rwlocktype_write);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) {
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
|
||||
dns_db_locknode(header->db, header->node, isc_rwlocktype_write);
|
||||
dns_slabheader_setownercase(header, name);
|
||||
dns_db_unlocknode(header->db, header->node, isc_rwlocktype_write);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
|
||||
dns_slabheader_t *header = dns_slabheader_fromrdataset(rdataset);
|
||||
uint8_t mask = (1 << 7);
|
||||
uint8_t bits = 0;
|
||||
|
||||
dns_db_locknode(header->db, header->node, isc_rwlocktype_write);
|
||||
|
||||
if (!CASESET(header)) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (CASEFULLYLOWER(header)) {
|
||||
isc_ascii_lowercopy(name->ndata, name->ndata, name->length);
|
||||
} else {
|
||||
uint8_t *nd = name->ndata;
|
||||
for (size_t i = 0; i < name->length; i++) {
|
||||
if (mask == (1 << 7)) {
|
||||
bits = header->upper[i / 8];
|
||||
mask = 1;
|
||||
} else {
|
||||
mask <<= 1;
|
||||
}
|
||||
nd[i] = (bits & mask) ? isc_ascii_toupper(nd[i])
|
||||
: isc_ascii_tolower(nd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
dns_db_unlocknode(header->db, header->node, isc_rwlocktype_write);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2140,15 +2140,15 @@ query_additional(query_ctx_t *qctx, dns_name_t *name,
|
|||
if (rdataset->type == dns_rdatatype_ns &&
|
||||
client->query.gluedb != NULL && dns_db_iszone(client->query.gluedb))
|
||||
{
|
||||
ns_dbversion_t *dbversion;
|
||||
ns_dbversion_t *dbversion = NULL;
|
||||
|
||||
dbversion = ns_client_findversion(client, client->query.gluedb);
|
||||
if (dbversion == NULL) {
|
||||
goto regular;
|
||||
}
|
||||
|
||||
result = dns_rdataset_addglue(rdataset, dbversion->version,
|
||||
client->message);
|
||||
result = dns_db_addglue(qctx->db, dbversion->version, rdataset,
|
||||
client->message);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,16 +96,23 @@ static bool
|
|||
ownercase_test_one(const char *str1, const char *str2) {
|
||||
isc_result_t result;
|
||||
rbtdb_nodelock_t node_locks[1];
|
||||
dns_rbtdb_t rbtdb = { .node_locks = node_locks };
|
||||
dns_rbtdb_t rbtdb = {
|
||||
.common.methods = &dns__rbtdb_zonemethods,
|
||||
.common.mctx = mctx,
|
||||
.node_locks = node_locks,
|
||||
};
|
||||
dns_rbtnode_t rbtnode = { .locknum = 0 };
|
||||
dns_slabheader_t header = { 0 };
|
||||
dns_slabheader_t header = {
|
||||
.node = &rbtnode,
|
||||
.db = (dns_db_t *)&rbtdb,
|
||||
};
|
||||
unsigned char *raw = (unsigned char *)(&header) + sizeof(header);
|
||||
dns_rdataset_t rdataset = {
|
||||
.magic = DNS_RDATASET_MAGIC,
|
||||
.slab = { .db = (dns_db_t *)&rbtdb,
|
||||
.node = &rbtnode,
|
||||
.raw = raw },
|
||||
.methods = &rdataset_methods,
|
||||
.methods = &dns_rdataslab_rdatasetmethods,
|
||||
};
|
||||
isc_buffer_t b;
|
||||
dns_fixedname_t fname1, fname2;
|
||||
|
|
@ -156,16 +163,23 @@ ISC_RUN_TEST_IMPL(ownercase) {
|
|||
ISC_RUN_TEST_IMPL(setownercase) {
|
||||
isc_result_t result;
|
||||
rbtdb_nodelock_t node_locks[1];
|
||||
dns_rbtdb_t rbtdb = { .node_locks = node_locks };
|
||||
dns_rbtdb_t rbtdb = {
|
||||
.common.methods = &dns__rbtdb_zonemethods,
|
||||
.common.mctx = mctx,
|
||||
.node_locks = node_locks,
|
||||
};
|
||||
dns_rbtnode_t rbtnode = { .locknum = 0 };
|
||||
dns_slabheader_t header = { 0 };
|
||||
dns_slabheader_t header = {
|
||||
.node = &rbtnode,
|
||||
.db = (dns_db_t *)&rbtdb,
|
||||
};
|
||||
unsigned char *raw = (unsigned char *)(&header) + sizeof(header);
|
||||
dns_rdataset_t rdataset = {
|
||||
.magic = DNS_RDATASET_MAGIC,
|
||||
.slab = { .db = (dns_db_t *)&rbtdb,
|
||||
.node = &rbtnode,
|
||||
.raw = raw },
|
||||
.methods = &rdataset_methods,
|
||||
.methods = &dns_rdataslab_rdatasetmethods,
|
||||
};
|
||||
const char *str1 =
|
||||
"AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
|
||||
|
|
|
|||
Loading…
Reference in a new issue