+3434. [bug] Pass client info to the DLZ findzone() entry
+ point in addition to lookup(). This makes it
+ possible for a database to answer differently
+ whether it's authoritative for a name depending
+ on the address of the client. [RT #31775]
+
3433. [bug] dlz_findzone() did not correctly handle
ISC_R_NOMORE. [RT #31172]
if (zonelabels < namelabels &&
!ISC_LIST_EMPTY(client->view->dlz_searched))
{
- tresult = dns_dlzfindzone(client->view, name,
- zonelabels, &tdbp);
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+
+ dns_clientinfomethods_init(&cm, ns_client_sourceip);
+ dns_clientinfo_init(&ci, client);
+
+ tresult = dns_view_searchdlz(client->view, name,
+ zonelabels, &cm, &ci, &tdbp);
/* If we successful, we found a better match. */
if (tresult == ISC_R_SUCCESS) {
/*
}
static isc_result_t
-dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
+dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo)
{
dlopen_data_t *cd = (dlopen_data_t *) dbdata;
isc_result_t result;
UNUSED(driverarg);
MAYBE_LOCK(cd);
- result = cd->dlz_findzonedb(cd->dbdata, name);
+ result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo);
MAYBE_UNLOCK(cd);
return (result);
}
dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
if (cd->dlz_create == NULL ||
+ cd->dlz_version == NULL ||
cd->dlz_lookup == NULL ||
cd->dlz_findzonedb == NULL)
{
dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
if (cd->dlz_create == NULL ||
+ cd->dlz_version == NULL ||
cd->dlz_lookup == NULL ||
cd->dlz_findzonedb == NULL)
{
* See if we handle a given zone
*/
isc_result_t
-dlz_findzonedb(void *dbdata, const char *name) {
+dlz_findzonedb(void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo)
+{
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+ isc_sockaddr_t *src;
+ char addrbuf[100];
+
+ strcpy(addrbuf, "unknown");
+ if (methods != NULL &&
+ methods->sourceip != NULL &&
+ methods->version - methods->age >= DNS_CLIENTINFOMETHODS_VERSION)
+ {
+ methods->sourceip(clientinfo, &src);
+ fmt_address(src, addrbuf, sizeof(addrbuf));
+ }
+ fprintf(stderr, "findzonedb: connection from: %s\n", addrbuf);
state->log(ISC_LOG_INFO,
- "dlz_example: dlz_findzonedb called with name '%s'"
+ "dlz_example: dlz_findzonedb called with name '%s' "
"in zone DB '%s'", name, state->zone_name);
/*
if (strcasecmp(name, "test.example.com") == 0)
return (ISC_R_NOMORE);
+ /*
+ * For example.net, only return ISC_R_NOMORE when queried
+ * from 10.53.0.1.
+ */
+ if (strcasecmp(name, "test.example.net") == 0 &&
+ strncmp(addrbuf, "10.53.0.1", 9) == 0)
+ return (ISC_R_NOMORE);
+
if (strcasecmp(state->zone_name, name) == 0)
return (ISC_R_SUCCESS);
}
/*
- * Look up one record
+ * Look up one record in the sample database.
+ *
+ * If the queryname is "source-addr", we add a TXT record containing
+ * the address of the client, to test the use of 'methods' and 'clientinfo'
*/
isc_result_t
dlz_lookup(const char *zone, const char *name, void *dbdata,
char buf[100];
strcpy(buf, "unknown");
if (methods != NULL &&
+ methods->sourceip != NULL &&
methods->version - methods->age >=
DNS_CLIENTINFOMETHODS_VERSION)
{
fmt_address(src, buf, sizeof(buf));
}
- fprintf(stderr, "connection from: %s\n", buf);
+ fprintf(stderr, "lookup: connection from: %s\n", buf);
found = ISC_TRUE;
result = state->putrr(lookup, "TXT", 0, buf);
UNUSED(client);
/* Just say yes for all our zones */
- return (dlz_findzonedb(dbdata, name));
+ return (dlz_findzonedb(dbdata, name, NULL, NULL));
}
/*
echo "I:testing correct behavior with findzone returning ISC_R_NOMORE"
$DIG $DIGOPTS +noall a test.example.com > /dev/null 2>&1 || ret=1
# we should only find one logged lookup per searched DLZ database
-lines=`grep "dlz_findzonedb.*example\.com.*example.nil" ns1/named.run | wc -l`
+lines=`grep "dlz_findzonedb.*test\.example\.com.*example.nil" ns1/named.run | wc -l`
[ $lines -eq 1 ] || ret=1
-lines=`grep "dlz_findzonedb.*example\.com.*alternate.nil" ns1/named.run | wc -l`
+lines=`grep "dlz_findzonedb.*test\.example\.com.*alternate.nil" ns1/named.run | wc -l`
[ $lines -eq 1 ] || ret=1
[ "$ret" -eq 0 ] || echo "I:failed"
status=`expr $status + $ret`
+ret=0
+echo "I:testing findzone can return different results per client"
+$DIG $DIGOPTS -b 10.53.0.1 +noall a test.example.net > /dev/null 2>&1 || ret=1
+# we should only find one logged lookup per searched DLZ database
+lines=`grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l`
+[ $lines -eq 1 ] || ret=1
+lines=`grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l`
+[ $lines -eq 1 ] || ret=1
+$DIG $DIGOPTS -b 10.53.0.2 +noall a test.example.net > /dev/null 2>&1 || ret=1
+# we should find several logged lookups this time
+lines=`grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l`
+[ $lines -gt 2 ] || ret=1
+lines=`grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l`
+[ $lines -gt 2 ] || ret=1
+[ "$ret" -eq 0 ] || echo "I:failed"
+status=`expr $status + $ret`
+
exit $status
/* forward reference */
static isc_result_t
-bdb_findzone(void *driverarg, void *dbdata, const char *name);
+bdb_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo);
/*%
* Parses the DBT from the Berkeley DB into a parsed_data record
DBT key, data;
/* check to see if we are authoritative for the zone first. */
- result = bdb_findzone(driverarg, dbdata, name);
+ result = bdb_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
}
static isc_result_t
-bdb_findzone(void *driverarg, void *dbdata, const char *name)
+bdb_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
DBT key, data;
UNUSED(driverarg);
+ UNUSED(methods);
+ UNUSED(clientinfo);
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
/* forward reference */
static isc_result_t
-bdbhpt_findzone(void *driverarg, void *dbdata, const char *name);
+bdbhpt_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo);
/*%
* Reverses a string in place.
DBT key, data;
/* check to see if we are authoritative for the zone first. */
- result = bdbhpt_findzone(driverarg, dbdata, name);
+ result = bdbhpt_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
}
static isc_result_t
-bdbhpt_findzone(void *driverarg, void *dbdata, const char *name)
+bdbhpt_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
DBT key, data;
UNUSED(driverarg);
+ UNUSED(methods);
+ UNUSED(clientinfo);
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
}
static isc_result_t
-fs_findzone(void *driverarg, void *dbdata, const char *name)
+fs_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
path = NULL;
UNUSED(driverarg);
+ UNUSED(methods);
+ UNUSED(clientinfo);
if (create_path(name, NULL, NULL, (config_data_t *) dbdata,
&path) != ISC_R_SUCCESS) {
/* forward references */
static isc_result_t
-dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name);
+dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo);
static void
dlz_ldap_destroy(void *driverarg, void *dbdata);
UNUSED(driverarg);
/* check to see if we are authoritative for the zone first */
- result = dlz_ldap_findzone(driverarg, dbdata, name);
+ result = dlz_ldap_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS) {
return (result);
}
}
static isc_result_t
-dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name) {
+dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo)
+{
UNUSED(driverarg);
+ UNUSED(methods);
+ UNUSED(clientinfo);
return (ldap_get_results(name, NULL, NULL, FINDZONE, dbdata, NULL));
}
/*% determine if the zone is supported by (in) the database */
static isc_result_t
-mysql_findzone(void *driverarg, void *dbdata, const char *name)
+mysql_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
MYSQL_RES *rs = NULL;
my_ulonglong rows;
UNUSED(driverarg);
+ UNUSED(methods);
+ UNUSED(clientinfo);
/* run the query and get the result set from the database. */
result = mysql_get_resultset(name, NULL, NULL, FINDZONE, dbdata, &rs);
UNUSED(driverarg);
/* first check if the zone is supported by the database. */
- result = mysql_findzone(driverarg, dbdata, name);
+ result = mysql_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
/*% determine if the zone is supported by (in) the database */
static isc_result_t
-odbc_findzone(void *driverarg, void *dbdata, const char *name)
+odbc_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
dbinstance_t *dbi = NULL;
UNUSED(driverarg);
+ UNUSED(methods);
+ UNUSED(clientinfo);
/* run the query and get the result set from the database. */
/* if result != ISC_R_SUCCESS cursor and mutex already cleaned up. */
UNUSED(driverarg);
/* first check if the zone is supported by the database. */
- result = odbc_findzone(driverarg, dbdata, name);
+ result = odbc_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
/*% determine if the zone is supported by (in) the database */
static isc_result_t
-postgres_findzone(void *driverarg, void *dbdata, const char *name)
+postgres_findzone(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo)
{
isc_result_t result;
PGresult *rs = NULL;
unsigned int rows;
+
UNUSED(driverarg);
+ UNUSED(methods);
+ UNUSED(clientinfo);
/* run the query and get the result set from the database. */
result = postgres_get_resultset(name, NULL, NULL,
UNUSED(driverarg);
/* first check if the zone is supported by the database. */
- result = postgres_findzone(driverarg, dbdata, name);
+ result = postgres_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
}
static isc_result_t
-stub_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
+stub_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo)
{
config_data_t *cd;
UNUSED(driverarg);
+ UNUSED(methods);
+ UNUSED(clientinfo);
cd = (config_data_t *) dbdata;
#define STRTOK_R(a, b, c) strtok(a, b)
#endif
+#define CHECK(x) \
+ do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
/* For this simple example, use fixed sized strings */
struct record {
char name[100];
i = first_empty;
}
if (i == MAX_RECORDS) {
- state->log(ISC_LOG_ERROR, "dlz_example: out of record space");
+ if (state->log != NULL)
+ state->log(ISC_LOG_ERROR,
+ "dlz_example: out of record space");
return (ISC_R_FAILURE);
}
- strcpy(list[i].name, name);
- strcpy(list[i].type, type);
- strcpy(list[i].data, data);
+
+ if (strlen(name) >= sizeof(list[i].name) ||
+ strlen(type) >= sizeof(list[i].type) ||
+ strlen(data) >= sizeof(list[i].data))
+ return (ISC_R_NOSPACE);
+
+ strncpy(list[i].name, name, sizeof(list[i].name));
+ strncpy(list[i].type, type, sizeof(list[i].type));
+ strncpy(list[i].data, data, sizeof(list[i].data));
list[i].ttl = ttl;
+
return (ISC_R_SUCCESS);
}
state->writeable_zone = (dns_dlz_writeablezone_t *)ptr;
}
-
/*
* Called to initialize the driver
*/
va_list ap;
char soa_data[200];
const char *extra;
+ isc_result_t result;
+ int n;
UNUSED(dlzname);
/* Fill in the helper functions */
va_start(ap, dbdata);
while ((helper_name = va_arg(ap, const char *)) != NULL) {
- b9_add_helper(state, helper_name, va_arg(ap, void*));
+ b9_add_helper(state, helper_name, va_arg(ap, void *));
}
va_end(ap);
if (argc < 2) {
- state->log(ISC_LOG_ERROR,
- "dlz_example: please specify a zone name");
+ if (state->log != NULL)
+ state->log(ISC_LOG_ERROR,
+ "dlz_example: please specify a zone name");
+ dlz_destroy(state);
return (ISC_R_FAILURE);
}
state->zone_name = strdup(argv[1]);
+ if (state->zone_name == NULL) {
+ free(state);
+ return (ISC_R_NOMEMORY);
+ }
+
if (strcmp(state->zone_name, ".") == 0)
extra = ".root";
else
extra = ".";
- sprintf(soa_data, "%s hostmaster%s%s 123 900 600 86400 3600",
- state->zone_name, extra, state->zone_name);
+ n = sprintf(soa_data, "%s hostmaster%s%s 123 900 600 86400 3600",
+ state->zone_name, extra, state->zone_name);
+
+ if (n < 0)
+ CHECK(ISC_R_FAILURE);
+ if ((unsigned)n >= sizeof(soa_data))
+ CHECK(ISC_R_NOSPACE);
add_name(state, &state->current[0], state->zone_name,
"soa", 3600, soa_data);
add_name(state, &state->current[0], state->zone_name,
"a", 1800, "10.53.0.1");
- state->log(ISC_LOG_INFO,
- "dlz_example: started for zone %s",
- state->zone_name);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: started for zone %s",
+ state->zone_name);
*dbdata = state;
return (ISC_R_SUCCESS);
+
+ failure:
+ free(state);
+ return (result);
+
}
/*
dlz_destroy(void *dbdata) {
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
- state->log(ISC_LOG_INFO,
- "dlz_example: shutting down zone %s",
- state->zone_name);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO,
+ "dlz_example: shutting down zone %s",
+ state->zone_name);
free(state->zone_name);
free(state);
}
* See if we handle a given zone
*/
isc_result_t
-dlz_findzonedb(void *dbdata, const char *name) {
+dlz_findzonedb(void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo)
+{
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+ isc_sockaddr_t *src;
+ char addrbuf[100];
+
+ strcpy(addrbuf, "unknown");
+ if (methods != NULL &&
+ methods->sourceip != NULL &&
+ methods->version - methods->age >= DNS_CLIENTINFOMETHODS_VERSION)
+ {
+ methods->sourceip(clientinfo, &src);
+ fmt_address(src, addrbuf, sizeof(addrbuf));
+ }
+ fprintf(stderr, "findzonedb: connection from: %s\n", addrbuf);
+
+ state->log(ISC_LOG_INFO,
+ "dlz_example: dlz_findzonedb called with name '%s' "
+ "in zone DB '%s'", name, state->zone_name);
+
+ /*
+ * Returning ISC_R_NOTFOUND will cause the query logic to
+ * check the database for parent names, looking for zone cuts.
+ *
+ * Returning ISC_R_NOMORE prevents the query logic from doing
+ * this; it will move onto the next database after a single query.
+ */
+ if (strcasecmp(name, "test.example.com") == 0)
+ return (ISC_R_NOMORE);
+
+ /*
+ * For example.net, only return ISC_R_NOMORE when queried
+ * from 10.53.0.1.
+ */
+ if (strcasecmp(name, "test.example.net") == 0 &&
+ strncmp(addrbuf, "10.53.0.1", 9) == 0)
+ return (ISC_R_NOMORE);
if (strcasecmp(state->zone_name, name) == 0)
return (ISC_R_SUCCESS);
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
isc_boolean_t found = ISC_FALSE;
isc_sockaddr_t *src;
- char full_name[100];
+ char full_name[256];
int i;
UNUSED(zone);
- if (strcmp(name, "@") == 0)
- strcpy(full_name, state->zone_name);
- else
- sprintf(full_name, "%s.%s", name, state->zone_name);
+ if (state->putrr == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ if (strcmp(name, "@") == 0) {
+ strncpy(full_name, state->zone_name, 255);
+ full_name[255] = '\0';
+ } else
+ snprintf(full_name, 255, "%s.%s", name, state->zone_name);
if (strcmp(name, "source-addr") == 0) {
char buf[100];
strcpy(buf, "unknown");
if (methods != NULL &&
+ methods->sourceip != NULL &&
methods->version - methods->age >=
DNS_CLIENTINFOMETHODS_VERSION)
{
fmt_address(src, buf, sizeof(buf));
}
- fprintf(stderr, "connection from: %s\n", buf);
+ fprintf(stderr, "lookup: connection from: %s\n", buf);
found = ISC_TRUE;
result = state->putrr(lookup, "TXT", 0, buf);
UNUSED(client);
/* Just say yes for all our zones */
- return (dlz_findzonedb(dbdata, name));
+ return (dlz_findzonedb(dbdata, name, NULL, NULL));
}
/*
UNUSED(zone);
+ if (state->putnamedrr == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
for (i = 0; i < MAX_RECORDS; i++) {
isc_result_t result;
if (strlen(state->current[i].name) == 0U) {
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
if (state->transaction_started) {
- state->log(ISC_LOG_INFO,
- "dlz_example: transaction already "
- "started for zone %s", zone);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO,
+ "dlz_example: transaction already "
+ "started for zone %s", zone);
return (ISC_R_FAILURE);
}
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
if (!state->transaction_started) {
- state->log(ISC_LOG_INFO,
- "dlz_example: transaction not started for zone %s",
- zone);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: transaction not "
+ "started for zone %s", zone);
*versionp = NULL;
return;
}
if (commit) {
int i;
- state->log(ISC_LOG_INFO,
- "dlz_example: committing transaction on zone %s",
- zone);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: committing "
+ "transaction on zone %s", zone);
for (i = 0; i < MAX_RECORDS; i++) {
- if (strlen(state->adds[i].name) > 0U) {
- add_name(state, &state->current[0],
- state->adds[i].name,
- state->adds[i].type,
- state->adds[i].ttl,
- state->adds[i].data);
+ if (strlen(state->deletes[i].name) > 0U) {
+ (void)del_name(state, &state->current[0],
+ state->deletes[i].name,
+ state->deletes[i].type,
+ state->deletes[i].ttl,
+ state->deletes[i].data);
}
}
for (i = 0; i < MAX_RECORDS; i++) {
- if (strlen(state->deletes[i].name) > 0U) {
- del_name(state, &state->current[0],
- state->deletes[i].name,
- state->deletes[i].type,
- state->deletes[i].ttl,
- state->deletes[i].data);
+ if (strlen(state->adds[i].name) > 0U) {
+ (void)add_name(state, &state->current[0],
+ state->adds[i].name,
+ state->adds[i].type,
+ state->adds[i].ttl,
+ state->adds[i].data);
}
}
} else {
- state->log(ISC_LOG_INFO,
- "dlz_example: cancelling transaction on zone %s",
- zone);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: cancelling "
+ "transaction on zone %s", zone);
}
memset(state->adds, 0, sizeof(state->adds));
memset(state->deletes, 0, sizeof(state->deletes));
* Configure a writeable zone
*/
isc_result_t
-dlz_configure(dns_view_t *view, void *dbdata) {
+dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata) {
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
isc_result_t result;
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: starting configure");
- state->log(ISC_LOG_INFO, "dlz_example: starting configure");
if (state->writeable_zone == NULL) {
- state->log(ISC_LOG_INFO,
- "dlz_example: no writeable_zone method available");
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: no "
+ "writeable_zone method available");
return (ISC_R_FAILURE);
}
- result = state->writeable_zone(view, view->dlzdatabase,
- state->zone_name);
+ result = state->writeable_zone(view, dlzdb, state->zone_name);
if (result != ISC_R_SUCCESS) {
- state->log(ISC_LOG_ERROR,
- "dlz_example: failed to configure zone %s",
- state->zone_name);
+ if (state->log != NULL)
+ state->log(ISC_LOG_ERROR, "dlz_example: failed to "
+ "configure zone %s", state->zone_name);
return (result);
}
- state->log(ISC_LOG_INFO,
- "dlz_example: configured writeable zone %s",
- state->zone_name);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: configured writeable "
+ "zone %s", state->zone_name);
return (ISC_R_SUCCESS);
}
UNUSED(keydata);
if (strncmp(name, "deny.", 5) == 0) {
- state->log(ISC_LOG_INFO,
- "dlz_example: denying update of name=%s by %s",
- name, signer);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: denying update "
+ "of name=%s by %s", name, signer);
return (ISC_FALSE);
}
- state->log(ISC_LOG_INFO,
- "dlz_example: allowing update of name=%s by %s",
- name, signer);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: allowing update of "
+ "name=%s by %s", name, signer);
return (ISC_TRUE);
}
modrdataset(struct dlz_example_data *state, const char *name,
const char *rdatastr, struct record *list)
{
- char *full_name, *dclass, *type, *data, *ttlstr;
- char *buf = strdup(rdatastr);
+ char *full_name, *dclass, *type, *data, *ttlstr, *buf;
isc_result_t result;
#if defined(WIN32) || defined(_REENTRANT)
char *saveptr = NULL;
#endif
+ buf = strdup(rdatastr);
+ if (buf == NULL)
+ return (ISC_R_FAILURE);
+
/*
* The format is:
* FULLNAME\tTTL\tDCLASS\tTYPE\tDATA
full_name = STRTOK_R(buf, "\t", &saveptr);
if (full_name == NULL)
- return (ISC_R_FAILURE);
+ goto error;
ttlstr = STRTOK_R(NULL, "\t", &saveptr);
if (ttlstr == NULL)
- return (ISC_R_FAILURE);
+ goto error;
dclass = STRTOK_R(NULL, "\t", &saveptr);
if (dclass == NULL)
- return (ISC_R_FAILURE);
+ goto error;
type = STRTOK_R(NULL, "\t", &saveptr);
if (type == NULL)
- return (ISC_R_FAILURE);
+ goto error;
data = STRTOK_R(NULL, "\t", &saveptr);
if (data == NULL)
- return (ISC_R_FAILURE);
+ goto error;
result = add_name(state, list, name, type,
strtoul(ttlstr, NULL, 10), data);
free(buf);
return (result);
+
+ error:
+ free(buf);
+ return (ISC_R_FAILURE);
}
if (version != (void *) &state->transaction_started)
return (ISC_R_FAILURE);
- state->log(ISC_LOG_INFO,
- "dlz_example: adding rdataset %s '%s'",
- name, rdatastr);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: adding rdataset %s '%s'",
+ name, rdatastr);
return (modrdataset(state, name, rdatastr, &state->adds[0]));
}
if (version != (void *) &state->transaction_started)
return (ISC_R_FAILURE);
- state->log(ISC_LOG_INFO,
- "dlz_example: subtracting rdataset %s '%s'",
- name, rdatastr);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: subtracting rdataset "
+ "%s '%s'", name, rdatastr);
return (modrdataset(state, name, rdatastr, &state->deletes[0]));
}
if (version != (void *) &state->transaction_started)
return (ISC_R_FAILURE);
- state->log(ISC_LOG_INFO,
- "dlz_example: deleting rdataset %s of type %s",
- name, type);
+ if (state->log != NULL)
+ state->log(ISC_LOG_INFO, "dlz_example: deleting rdataset %s "
+ "of type %s", name, type);
return (ISC_R_SUCCESS);
}
typedef int isc_boolean_t;
typedef uint32_t dns_ttl_t;
-#define DLZ_DLOPEN_VERSION 2
+#define DLZ_DLOPEN_VERSION 3
/* return this in flags to dlz_version() if thread safe */
#define DNS_SDLZFLAG_THREADSAFE 0x00000001U
#define ISC_R_SUCCESS 0
#define ISC_R_NOMEMORY 1
#define ISC_R_NOPERM 6
+#define ISC_R_NOSPACE 19
#define ISC_R_NOTFOUND 23
#define ISC_R_FAILURE 25
+#define ISC_R_NOTIMPLEMENTED 27
#define ISC_R_NOMORE 29
/* boolean values */
typedef void *dns_sdlzlookup_t;
typedef void *dns_sdlzallnodes_t;
typedef void *dns_view_t;
+typedef void *dns_dlzdb_t;
/*
* Method and type definitions needed for retrieval of client info
const char *data);
typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view,
+ dns_dlzdb_t *dlzdb,
const char *zone_name);
-
/*
* prototypes for the functions you can include in your module
*/
* dlz_findzonedb is required for all DLZ external drivers
*/
isc_result_t
-dlz_findzonedb(void *dbdata, const char *name);
+dlz_findzonedb(void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo);
/*
* dlz_lookup is required for all DLZ external drivers
* dynamic updates
*/
isc_result_t
-dlz_configure(dns_view_t *view, void *dbdata);
+dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata);
/*
* dlz_ssumatch() is optional, but must be supplied if you want to support
*dbp = NULL;
}
-
-isc_result_t
-dns_dlzfindzone(dns_view_t *view, dns_name_t *name,
- unsigned int minlabels, dns_db_t **dbp)
-{
- dns_fixedname_t fname;
- dns_name_t *zonename;
- unsigned int namelabels;
- unsigned int i;
- isc_result_t result;
- dns_dlzfindzone_t findzone;
- dns_dlzdb_t *dlzdb;
- dns_db_t *db, *best = NULL;
-
- /*
- * Performs checks to make sure data is as we expect it to be.
- */
- REQUIRE(view != NULL);
- REQUIRE(name != NULL);
- REQUIRE(dbp != NULL && *dbp == NULL);
-
- /* setup a "fixed" dns name */
- dns_fixedname_init(&fname);
- zonename = dns_fixedname_name(&fname);
-
- /* count the number of labels in the name */
- namelabels = dns_name_countlabels(name);
-
- for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
- dlzdb != NULL;
- dlzdb = ISC_LIST_NEXT(dlzdb, link))
- {
- REQUIRE(DNS_DLZ_VALID(dlzdb));
-
- /*
- * loop through starting with the longest domain name and
- * trying shorter names portions of the name until we find a
- * match, have an error, or are below the 'minlabels'
- * threshold. minlabels is 0, if neither the standard
- * database nor any previous DLZ database had a zone name
- * match. Otherwise minlabels is the number of labels
- * in that name. We need to beat that for a "better"
- * match for this DLZ database to be authoritative.
- */
- for (i = namelabels; i > minlabels && i > 1; i--) {
- if (i == namelabels) {
- result = dns_name_copy(name, zonename, NULL);
- if (result != ISC_R_SUCCESS)
- return (result);
- } else
- dns_name_split(name, i, NULL, zonename);
-
- /* ask SDLZ driver if the zone is supported */
- db = NULL;
- findzone = dlzdb->implementation->methods->findzone;
- result = (*findzone)(dlzdb->implementation->driverarg,
- dlzdb->dbdata, dlzdb->mctx,
- view->rdclass, zonename, &db);
-
- if (result != ISC_R_NOTFOUND) {
- if (best != NULL)
- dns_db_detach(&best);
- if (result == ISC_R_SUCCESS) {
- INSIST(db != NULL);
- dns_db_attach(db, &best);
- dns_db_detach(&db);
- minlabels = i;
- } else {
- if (db != NULL)
- dns_db_detach(&db);
- break;
- }
- } else if (db != NULL)
- dns_db_detach(&db);
- }
- }
-
- if (best != NULL) {
- dns_db_attach(best, dbp);
- dns_db_detach(&best);
- return (ISC_R_SUCCESS);
- }
-
- return (ISC_R_NOTFOUND);
-}
-
/*%
* Registers a DLZ driver. This basically just adds the dlz
* driver to the list of available drivers in the dlz_implementations list.
***** Imports
*****/
+#include <dns/clientinfo.h>
#include <dns/name.h>
#include <dns/types.h>
#include <dns/view.h>
typedef isc_result_t
(*dns_dlzfindzone_t)(void *driverarg, void *dbdata, isc_mem_t *mctx,
dns_rdataclass_t rdclass, dns_name_t *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo,
dns_db_t **dbp);
/*%<
-
* Method prototype. Drivers implementing the DLZ interface MUST
* supply a find zone method. This method is called when the DNS
* server is performing a query. The find zone method will be called
* methods, this function will call it.
*/
-isc_result_t
-dns_dlzfindzone(dns_view_t *view, dns_name_t *name,
- unsigned int minlabels, dns_db_t **dbp);
-
-/*%<
- * This method is called when the DNS server is performing a query.
- * It will call the DLZ driver's find zone method.
- */
-
isc_result_t
dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
void *driverarg, isc_mem_t *mctx,
* for the entry points of an external DLZ module for bind9.
*/
-#define DLZ_DLOPEN_VERSION 2
+#define DLZ_DLOPEN_VERSION 3
/*
* dlz_dlopen_version() is required for all DLZ external drivers. It
* should return DLZ_DLOPEN_VERSION
*/
-typedef int dlz_dlopen_version_t (unsigned int *flags);
+typedef int dlz_dlopen_version_t(unsigned int *flags);
/*
* dlz_dlopen_create() is required for all DLZ external drivers.
*/
-typedef isc_result_t dlz_dlopen_create_t (const char *dlzname,
- unsigned int argc,
- char *argv[],
- void **dbdata,
- ...);
+typedef isc_result_t dlz_dlopen_create_t(const char *dlzname,
+ unsigned int argc,
+ char *argv[],
+ void **dbdata,
+ ...);
/*
* dlz_dlopen_destroy() is optional, and will be called when the
* driver is unloaded if supplied
*/
-typedef void dlz_dlopen_destroy_t (void *dbdata);
+typedef void dlz_dlopen_destroy_t(void *dbdata);
/*
* dlz_dlopen_findzonedb() is required for all DLZ external drivers
*/
-typedef isc_result_t dlz_dlopen_findzonedb_t (void *dbdata,
- const char *name);
+typedef isc_result_t dlz_dlopen_findzonedb_t(void *dbdata,
+ const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo);
/*
* dlz_dlopen_lookup() is required for all DLZ external drivers
*/
-typedef isc_result_t dlz_dlopen_lookup_t (const char *zone,
- const char *name,
- void *dbdata,
- dns_sdlzlookup_t *lookup,
- dns_clientinfomethods_t *methods,
- dns_clientinfo_t *clientinfo);
+typedef isc_result_t dlz_dlopen_lookup_t(const char *zone,
+ const char *name,
+ void *dbdata,
+ dns_sdlzlookup_t *lookup,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo);
/*
* dlz_dlopen_authority is optional() if dlz_dlopen_lookup()
* supplies authority information for the dns record
*/
-typedef isc_result_t dlz_dlopen_authority_t (const char *zone,
- void *dbdata,
- dns_sdlzlookup_t *lookup);
+typedef isc_result_t dlz_dlopen_authority_t(const char *zone,
+ void *dbdata,
+ dns_sdlzlookup_t *lookup);
/*
* dlz_dlopen_allowzonexfr() is optional, and should be supplied if
* you want to support zone transfers
*/
-typedef isc_result_t dlz_dlopen_allowzonexfr_t (void *dbdata,
- const char *name,
- const char *client);
+typedef isc_result_t dlz_dlopen_allowzonexfr_t(void *dbdata,
+ const char *name,
+ const char *client);
/*
* dlz_dlopen_allnodes() is optional, but must be supplied if supply a
* dlz_dlopen_allowzonexfr() function
*/
-typedef isc_result_t dlz_dlopen_allnodes_t (const char *zone,
- void *dbdata,
- dns_sdlzallnodes_t *allnodes);
+typedef isc_result_t dlz_dlopen_allnodes_t(const char *zone,
+ void *dbdata,
+ dns_sdlzallnodes_t *allnodes);
/*
* dlz_dlopen_newversion() is optional. It should be supplied if you
* want to support dynamic updates.
*/
-typedef isc_result_t dlz_dlopen_newversion_t (const char *zone,
- void *dbdata,
- void **versionp);
+typedef isc_result_t dlz_dlopen_newversion_t(const char *zone,
+ void *dbdata,
+ void **versionp);
/*
* dlz_closeversion() is optional, but must be supplied if you supply
* a dlz_newversion() function
*/
-typedef void dlz_dlopen_closeversion_t (const char *zone,
- isc_boolean_t commit,
- void *dbdata,
- void **versionp);
+typedef void dlz_dlopen_closeversion_t(const char *zone,
+ isc_boolean_t commit,
+ void *dbdata,
+ void **versionp);
/*
* dlz_dlopen_configure() is optional, but must be supplied if you
* want to support dynamic updates
*/
-typedef isc_result_t dlz_dlopen_configure_t (dns_view_t *view,
- dns_dlzdb_t *dlzdb,
- void *dbdata);
+typedef isc_result_t dlz_dlopen_configure_t(dns_view_t *view,
+ dns_dlzdb_t *dlzdb,
+ void *dbdata);
/*
* dlz_dlopen_setclientcallback() is optional, but must be supplied if you
* want to retrieve information about the client (e.g., source address)
* before sending a replay.
*/
-typedef isc_result_t dlz_dlopen_setclientcallback_t (dns_view_t *view,
- void *dbdata);
+typedef isc_result_t dlz_dlopen_setclientcallback_t(dns_view_t *view,
+ void *dbdata);
/*
* dlz_dlopen_ssumatch() is optional, but must be supplied if you want
* to support dynamic updates
*/
-typedef isc_boolean_t dlz_dlopen_ssumatch_t (const char *signer,
- const char *name,
- const char *tcpaddr,
- const char *type,
- const char *key,
- isc_uint32_t keydatalen,
- unsigned char *keydata,
- void *dbdata);
+typedef isc_boolean_t dlz_dlopen_ssumatch_t(const char *signer,
+ const char *name,
+ const char *tcpaddr,
+ const char *type,
+ const char *key,
+ isc_uint32_t keydatalen,
+ unsigned char *keydata,
+ void *dbdata);
/*
* dlz_dlopen_addrdataset() is optional, but must be supplied if you
* want to support dynamic updates
*/
-typedef isc_result_t dlz_dlopen_addrdataset_t (const char *name,
- const char *rdatastr,
- void *dbdata,
- void *version);
+typedef isc_result_t dlz_dlopen_addrdataset_t(const char *name,
+ const char *rdatastr,
+ void *dbdata,
+ void *version);
/*
* dlz_dlopen_subrdataset() is optional, but must be supplied if you
* want to support dynamic updates
*/
-typedef isc_result_t dlz_dlopen_subrdataset_t (const char *name,
- const char *rdatastr,
- void *dbdata,
- void *version);
+typedef isc_result_t dlz_dlopen_subrdataset_t(const char *name,
+ const char *rdatastr,
+ void *dbdata,
+ void *version);
/*
* dlz_dlopen_delrdataset() is optional, but must be supplied if you
* want to support dynamic updates
*/
-typedef isc_result_t dlz_dlopen_delrdataset_t (const char *name,
- const char *type,
- void *dbdata,
- void *version);
+typedef isc_result_t dlz_dlopen_delrdataset_t(const char *name,
+ const char *type,
+ void *dbdata,
+ void *version);
ISC_LANG_ENDDECLS
*/
typedef isc_result_t
-(*dns_sdlzfindzone_t)(void *driverarg, void *dbdata, const char *name);
-
+(*dns_sdlzfindzone_t)(void *driverarg, void *dbdata, const char *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo);
/*%<
* Method prototype. Drivers implementing the SDLZ interface MUST
* supply a find zone method. This method is called when the DNS
#include <isc/stdtime.h>
#include <dns/acl.h>
+#include <dns/clientinfo.h>
#include <dns/fixedname.h>
#include <dns/rdatastruct.h>
#include <dns/rpz.h>
void
dns_view_restorekeyring(dns_view_t *view);
+isc_result_t
+dns_view_searchdlz(dns_view_t *view, dns_name_t *name,
+ unsigned int minlabels,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo,
+ dns_db_t **dbp);
+
+/*%<
+ * Search through the DLZ database(s) in view->dlz_searched to find
+ * one that can answer a query for 'name', using the DLZ driver's
+ * findzone method. If successful, '*dbp' is set to point to the
+ * DLZ database.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOTFOUND
+ *
+ * Requires:
+ * \li 'view' is valid.
+ * \li 'name' is not NULL.
+ * \li 'dbp' is not NULL and *dbp is NULL.
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_VIEW_H */
static isc_result_t
dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
- dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp)
+ dns_rdataclass_t rdclass, dns_name_t *name,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo,
+ dns_db_t **dbp)
{
isc_buffer_t b;
char namestr[DNS_NAME_MAXTEXT + 1];
/* Call SDLZ driver's find zone method */
MAYBE_LOCK(imp);
- result = imp->methods->findzone(imp->driverarg, dbdata, namestr);
+ result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
+ methods, clientinfo);
MAYBE_UNLOCK(imp);
/*
UNUSED(cfg_destroy);
#endif
}
+
+isc_result_t
+dns_view_searchdlz(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
+ dns_clientinfomethods_t *methods,
+ dns_clientinfo_t *clientinfo,
+ dns_db_t **dbp)
+{
+ dns_fixedname_t fname;
+ dns_name_t *zonename;
+ unsigned int namelabels;
+ unsigned int i;
+ isc_result_t result;
+ dns_dlzfindzone_t findzone;
+ dns_dlzdb_t *dlzdb;
+ dns_db_t *db, *best = NULL;
+
+ /*
+ * Performs checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(name != NULL);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ /* setup a "fixed" dns name */
+ dns_fixedname_init(&fname);
+ zonename = dns_fixedname_name(&fname);
+
+ /* count the number of labels in the name */
+ namelabels = dns_name_countlabels(name);
+
+ for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
+ dlzdb != NULL;
+ dlzdb = ISC_LIST_NEXT(dlzdb, link))
+ {
+ REQUIRE(DNS_DLZ_VALID(dlzdb));
+
+ /*
+ * loop through starting with the longest domain name and
+ * trying shorter names portions of the name until we find a
+ * match, have an error, or are below the 'minlabels'
+ * threshold. minlabels is 0, if neither the standard
+ * database nor any previous DLZ database had a zone name
+ * match. Otherwise minlabels is the number of labels
+ * in that name. We need to beat that for a "better"
+ * match for this DLZ database to be authoritative.
+ */
+ for (i = namelabels; i > minlabels && i > 1; i--) {
+ if (i == namelabels) {
+ result = dns_name_copy(name, zonename, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else
+ dns_name_split(name, i, NULL, zonename);
+
+ /* ask SDLZ driver if the zone is supported */
+ db = NULL;
+ findzone = dlzdb->implementation->methods->findzone;
+ result = (*findzone)(dlzdb->implementation->driverarg,
+ dlzdb->dbdata, dlzdb->mctx,
+ view->rdclass, zonename,
+ methods, clientinfo, &db);
+
+ if (result != ISC_R_NOTFOUND) {
+ if (best != NULL)
+ dns_db_detach(&best);
+ if (result == ISC_R_SUCCESS) {
+ INSIST(db != NULL);
+ dns_db_attach(db, &best);
+ dns_db_detach(&db);
+ minlabels = i;
+ } else {
+ if (db != NULL)
+ dns_db_detach(&db);
+ break;
+ }
+ } else if (db != NULL)
+ dns_db_detach(&db);
+ }
+ }
+
+ if (best != NULL) {
+ dns_db_attach(best, dbp);
+ dns_db_detach(&best);
+ return (ISC_R_SUCCESS);
+ }
+
+ return (ISC_R_NOTFOUND);
+}
dns_dlzconfigure
dns_dlzcreate
dns_dlzdestroy
-dns_dlzfindzone
dns_dlzregister
dns_dlzstrtoargv
dns_dlzunregister
dns_view_load
dns_view_loadnew
dns_view_restorekeyring
+dns_view_searchdlz
dns_view_setcache
dns_view_setcache2
dns_view_setdstport
findzone = dlzdb->implementation->methods->findzone;
result = (*findzone)(dlzdb->implementation->driverarg,
dlzdb->dbdata, dlzdb->mctx,
- zone->view->rdclass, &zone->origin, &db);
+ zone->view->rdclass, &zone->origin,
+ NULL, NULL, &db);
if (result != ISC_R_NOTFOUND) {
if (zone->db != NULL)
zone_detachdb(zone);