mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 10:10:06 +00:00
Also disable the semantic patch as the code needs tweaks here and there because some destroy functions might not destroy the object and return early if the object is still in use.
232 lines
5.7 KiB
C
232 lines
5.7 KiB
C
/*
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
* information regarding copyright ownership.
|
|
*/
|
|
|
|
/*! \file */
|
|
|
|
#include <isc/magic.h>
|
|
#include <isc/mem.h>
|
|
#include <isc/rwlock.h>
|
|
#include <isc/util.h>
|
|
|
|
#include <dns/forward.h>
|
|
#include <dns/rbt.h>
|
|
#include <dns/result.h>
|
|
#include <dns/types.h>
|
|
|
|
struct dns_fwdtable {
|
|
/* Unlocked. */
|
|
unsigned int magic;
|
|
isc_mem_t *mctx;
|
|
isc_rwlock_t rwlock;
|
|
/* Locked by lock. */
|
|
dns_rbt_t *table;
|
|
};
|
|
|
|
#define FWDTABLEMAGIC ISC_MAGIC('F', 'w', 'd', 'T')
|
|
#define VALID_FWDTABLE(ft) ISC_MAGIC_VALID(ft, FWDTABLEMAGIC)
|
|
|
|
static void
|
|
auto_detach(void *, void *);
|
|
|
|
isc_result_t
|
|
dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep) {
|
|
dns_fwdtable_t *fwdtable;
|
|
isc_result_t result;
|
|
|
|
REQUIRE(fwdtablep != NULL && *fwdtablep == NULL);
|
|
|
|
fwdtable = isc_mem_get(mctx, sizeof(dns_fwdtable_t));
|
|
|
|
fwdtable->table = NULL;
|
|
result = dns_rbt_create(mctx, auto_detach, fwdtable, &fwdtable->table);
|
|
if (result != ISC_R_SUCCESS)
|
|
goto cleanup_fwdtable;
|
|
|
|
result = isc_rwlock_init(&fwdtable->rwlock, 0, 0);
|
|
if (result != ISC_R_SUCCESS)
|
|
goto cleanup_rbt;
|
|
|
|
fwdtable->mctx = NULL;
|
|
isc_mem_attach(mctx, &fwdtable->mctx);
|
|
fwdtable->magic = FWDTABLEMAGIC;
|
|
*fwdtablep = fwdtable;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
cleanup_rbt:
|
|
dns_rbt_destroy(&fwdtable->table);
|
|
|
|
cleanup_fwdtable:
|
|
isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));
|
|
|
|
return (result);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_fwdtable_addfwd(dns_fwdtable_t *fwdtable, const dns_name_t *name,
|
|
dns_forwarderlist_t *fwdrs, dns_fwdpolicy_t fwdpolicy)
|
|
{
|
|
isc_result_t result;
|
|
dns_forwarders_t *forwarders;
|
|
dns_forwarder_t *fwd, *nfwd;
|
|
|
|
REQUIRE(VALID_FWDTABLE(fwdtable));
|
|
|
|
forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t));
|
|
|
|
ISC_LIST_INIT(forwarders->fwdrs);
|
|
for (fwd = ISC_LIST_HEAD(*fwdrs);
|
|
fwd != NULL;
|
|
fwd = ISC_LIST_NEXT(fwd, link))
|
|
{
|
|
nfwd = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarder_t));
|
|
*nfwd = *fwd;
|
|
ISC_LINK_INIT(nfwd, link);
|
|
ISC_LIST_APPEND(forwarders->fwdrs, nfwd, link);
|
|
}
|
|
forwarders->fwdpolicy = fwdpolicy;
|
|
|
|
RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
|
|
result = dns_rbt_addname(fwdtable->table, name, forwarders);
|
|
RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
goto cleanup;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
cleanup:
|
|
while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
|
|
fwd = ISC_LIST_HEAD(forwarders->fwdrs);
|
|
ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
|
|
isc_mem_put(fwdtable->mctx, fwd, sizeof(isc_sockaddr_t));
|
|
}
|
|
isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
|
|
return (result);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_fwdtable_add(dns_fwdtable_t *fwdtable, const dns_name_t *name,
|
|
isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy)
|
|
{
|
|
isc_result_t result;
|
|
dns_forwarders_t *forwarders;
|
|
dns_forwarder_t *fwd;
|
|
isc_sockaddr_t *sa;
|
|
|
|
REQUIRE(VALID_FWDTABLE(fwdtable));
|
|
|
|
forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t));
|
|
|
|
ISC_LIST_INIT(forwarders->fwdrs);
|
|
for (sa = ISC_LIST_HEAD(*addrs);
|
|
sa != NULL;
|
|
sa = ISC_LIST_NEXT(sa, link))
|
|
{
|
|
fwd = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarder_t));
|
|
fwd->addr = *sa;
|
|
fwd->dscp = -1;
|
|
ISC_LINK_INIT(fwd, link);
|
|
ISC_LIST_APPEND(forwarders->fwdrs, fwd, link);
|
|
}
|
|
forwarders->fwdpolicy = fwdpolicy;
|
|
|
|
RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
|
|
result = dns_rbt_addname(fwdtable->table, name, forwarders);
|
|
RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
goto cleanup;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
cleanup:
|
|
while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
|
|
fwd = ISC_LIST_HEAD(forwarders->fwdrs);
|
|
ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
|
|
isc_mem_put(fwdtable->mctx, fwd, sizeof(dns_forwarder_t));
|
|
}
|
|
isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
|
|
return (result);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_fwdtable_delete(dns_fwdtable_t *fwdtable, const dns_name_t *name) {
|
|
isc_result_t result;
|
|
|
|
REQUIRE(VALID_FWDTABLE(fwdtable));
|
|
|
|
RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
|
|
result = dns_rbt_deletename(fwdtable->table, name, false);
|
|
RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
|
|
|
|
if (result == DNS_R_PARTIALMATCH)
|
|
result = ISC_R_NOTFOUND;
|
|
|
|
return (result);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_fwdtable_find(dns_fwdtable_t *fwdtable, const dns_name_t *name,
|
|
dns_name_t *foundname, dns_forwarders_t **forwardersp)
|
|
{
|
|
isc_result_t result;
|
|
|
|
REQUIRE(VALID_FWDTABLE(fwdtable));
|
|
|
|
RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
|
|
|
|
result = dns_rbt_findname(fwdtable->table, name, 0, foundname,
|
|
(void **)forwardersp);
|
|
if (result == DNS_R_PARTIALMATCH)
|
|
result = ISC_R_SUCCESS;
|
|
|
|
RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
|
|
|
|
return (result);
|
|
}
|
|
|
|
void
|
|
dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep) {
|
|
dns_fwdtable_t *fwdtable;
|
|
|
|
REQUIRE(fwdtablep != NULL && VALID_FWDTABLE(*fwdtablep));
|
|
|
|
fwdtable = *fwdtablep;
|
|
*fwdtablep = NULL;
|
|
|
|
dns_rbt_destroy(&fwdtable->table);
|
|
isc_rwlock_destroy(&fwdtable->rwlock);
|
|
fwdtable->magic = 0;
|
|
|
|
isc_mem_putanddetach(&fwdtable->mctx, fwdtable, sizeof(dns_fwdtable_t));
|
|
}
|
|
|
|
/***
|
|
*** Private
|
|
***/
|
|
|
|
static void
|
|
auto_detach(void *data, void *arg) {
|
|
dns_forwarders_t *forwarders = data;
|
|
dns_fwdtable_t *fwdtable = arg;
|
|
dns_forwarder_t *fwd;
|
|
|
|
UNUSED(arg);
|
|
|
|
while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
|
|
fwd = ISC_LIST_HEAD(forwarders->fwdrs);
|
|
ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
|
|
isc_mem_put(fwdtable->mctx, fwd, sizeof(dns_forwarder_t));
|
|
}
|
|
isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
|
|
}
|