Beispiel #1
0
void
dns_dbtable_remove(dns_dbtable_t *dbtable, dns_db_t *db) {
	dns_db_t *stored_data = NULL;
	isc_result_t result;
	dns_name_t *name;

	REQUIRE(VALID_DBTABLE(dbtable));

	name = dns_db_origin(db);

	/*
	 * There is a requirement that the association of name with db
	 * be verified.  With the current rbt.c this is expensive to do,
	 * because effectively two find operations are being done, but
	 * deletion is relatively infrequent.
	 * XXXDCL ... this could be cheaper now with dns_rbt_deletenode.
	 */

	RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);

	result = dns_rbt_findname(dbtable->rbt, name, 0, NULL,
				  (void **) (void *)&stored_data);

	if (result == ISC_R_SUCCESS) {
		INSIST(stored_data == db);

		(void)dns_rbt_deletename(dbtable->rbt, name, ISC_FALSE);
	}

	RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
}
Beispiel #2
0
static void
remove_nodes(dns_rbt_t *mytree, char **names,
	     size_t *names_count, isc_uint32_t num_names)
{
	isc_uint32_t i;

	UNUSED(mytree);

	for (i = 0; i < num_names; i++) {
		isc_uint32_t node;
		dns_fixedname_t fname;
		dns_name_t *name;
		isc_result_t result;

		isc_random_get(&node);

		node %= *names_count;

		build_name_from_str(names[node], &fname);
		name = dns_fixedname_name(&fname);

		result = dns_rbt_deletename(mytree, name, ISC_FALSE);
		ATF_CHECK_EQ(result, ISC_R_SUCCESS);

		isc_mem_free(mctx, names[node]);
		if (*names_count > 0) {
			names[node] = names[*names_count - 1];
			names[*names_count - 1] = NULL;
			*names_count -= 1;
		}
	}
}
Beispiel #3
0
static void
remove_fromring(dns_tsigkey_t *tkey) {
	if (tkey->generated) {
		ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
		tkey->ring->generated--;
	}
	(void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
}
Beispiel #4
0
void
dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
	REQUIRE(VALID_TSIG_KEY(key));
	REQUIRE(key->ring != NULL);

	RWLOCK(&key->ring->lock, isc_rwlocktype_write);
	(void)dns_rbt_deletename(key->ring->keys, &key->name, ISC_FALSE);
	RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
}
Beispiel #5
0
isc_result_t
dns_fwdtable_delete(dns_fwdtable_t *fwdtable, 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, ISC_FALSE);
	RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);

	if (result == DNS_R_PARTIALMATCH)
		result = ISC_R_NOTFOUND;

	return (result);
}
Beispiel #6
0
isc_result_t
dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) {
	isc_result_t result;
	dns_name_t *name;

	REQUIRE(VALID_ZT(zt));

	name = dns_zone_getorigin(zone);

	RWLOCK(&zt->rwlock, isc_rwlocktype_write);

	result = dns_rbt_deletename(zt->table, name, ISC_FALSE);

	RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);

	return (result);
}
Beispiel #7
0
isc_result_t
dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
		 dns_name_t *algorithm, dns_tsig_keyring_t *ring)
{
	dns_tsigkey_t *key;
	isc_stdtime_t now;
	isc_result_t result;

	REQUIRE(tsigkey != NULL);
	REQUIRE(*tsigkey == NULL);
	REQUIRE(name != NULL);
	REQUIRE(ring != NULL);

	isc_stdtime_get(&now);
	RWLOCK(&ring->lock, isc_rwlocktype_read);
	key = NULL;
	result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
	if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
		RWUNLOCK(&ring->lock, isc_rwlocktype_read);
		return (ISC_R_NOTFOUND);
	}
	if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
		RWUNLOCK(&ring->lock, isc_rwlocktype_read);
		return (ISC_R_NOTFOUND);
	}
	if (key->inception != key->expire && key->expire < now) {
		/*
		 * The key has expired.
		 */
		RWUNLOCK(&ring->lock, isc_rwlocktype_read);
		RWLOCK(&ring->lock, isc_rwlocktype_write);
		(void) dns_rbt_deletename(ring->keys, name, ISC_FALSE);
		RWUNLOCK(&ring->lock, isc_rwlocktype_write);
		return (ISC_R_NOTFOUND);
	}

	isc_refcount_increment(&key->refs, NULL);
	RWUNLOCK(&ring->lock, isc_rwlocktype_read);
	*tsigkey = key;
	return (ISC_R_SUCCESS);
}
Beispiel #8
0
static int
t1_delete(char *name, dns_rbt_t *rbt, isc_mem_t *mctx,
	  isc_result_t *dns_result)
{
	int		nprobs;
	dns_name_t	*dns_name;

	nprobs = 0;
	if (name && dns_result) {
		if (create_name(name, mctx, &dns_name) == 0) {
			*dns_result = dns_rbt_deletename(rbt, dns_name,
							 ISC_FALSE);
			delete_name(dns_name, mctx);
		} else {
			++nprobs;
		}
	} else {
		++nprobs;
	}
	return(nprobs);
}
Beispiel #9
0
isc_result_t
discard_from_cache(ldap_cache_t *cache, dns_name_t *name)
{
	isc_result_t result;

	REQUIRE(cache != NULL);
	REQUIRE(name != NULL);

	if (cache->rbt == NULL) {
		result = ISC_R_SUCCESS;
	} else {
		LOCK(&cache->mutex);
		result = dns_rbt_deletename(cache->rbt, name, ISC_FALSE);
		UNLOCK(&cache->mutex);
	}

	if (result == ISC_R_NOTFOUND)
		result = ISC_R_SUCCESS;

	return result;
}
Beispiel #10
0
int
main(int argc, char **argv) {
	char *command, *arg, buffer[1024];
	const char *whitespace;
	dns_name_t *name, *foundname;
	dns_fixedname_t fixedname;
	dns_rbt_t *rbt = NULL;
	int length, ch;
	isc_boolean_t show_final_mem = ISC_FALSE;
	isc_result_t result;
	void *data;

	progname = strrchr(*argv, '/');
	if (progname != NULL)
		progname++;
	else
		progname = *argv;

	while ((ch = isc_commandline_parse(argc, argv, "m")) != -1) {
		switch (ch) {
		case 'm':
			show_final_mem = ISC_TRUE;
			break;
		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;
	POST(argv);

	if (argc > 1) {
		printf("Usage: %s [-m]\n", progname);
		exit(1);
	}

	setbuf(stdout, NULL);

	/*
	 * So isc_mem_stats() can report any allocation leaks.
	 */
	isc_mem_debugging = ISC_MEM_DEBUGRECORD;

	result = isc_mem_create(0, 0, &mctx);
	if (result != ISC_R_SUCCESS) {
		printf("isc_mem_create: %s: exiting\n",
		       dns_result_totext(result));
		exit(1);
	}

	result = dns_rbt_create(mctx, delete_name, NULL, &rbt);
	if (result != ISC_R_SUCCESS) {
		printf("dns_rbt_create: %s: exiting\n",
		       dns_result_totext(result));
		exit(1);
	}

	whitespace = " \t";

	while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
		length = strlen(buffer);

		if (buffer[length - 1] != '\n') {
			printf("line to long (%lu max), ignored\n",
			       (unsigned long)sizeof(buffer) - 2);
			continue;
		}

		buffer[length - 1] = '\0';

		command = buffer + strspn(buffer, whitespace);

		if (*command == '#')
			continue;

		arg = strpbrk(command, whitespace);
		if (arg != NULL) {
			*arg++ = '\0';
			arg += strspn(arg, whitespace);
		}

		length = strlen(command);
		if (*command != '\0') {
			if (CMDCHECK("add")) {
				name = create_name(arg);
				if (name != NULL) {
					printf("adding name %s\n", arg);
					result = dns_rbt_addname(rbt,
								 name, name);
					PRINTERR(result);
				}

			} else if (CMDCHECK("delete")) {
				name = create_name(arg);
				if (name != NULL) {
					printf("deleting name %s\n", arg);
					result = dns_rbt_deletename(rbt, name,
								    ISC_FALSE);
					PRINTERR(result);
					delete_name(name, NULL);
				}

			} else if (CMDCHECK("nuke")) {
				name = create_name(arg);
				if (name != NULL) {
					printf("nuking name %s "
					       "and its descendants\n", arg);
					result = dns_rbt_deletename(rbt, name,
								    ISC_TRUE);
					PRINTERR(result);
					delete_name(name, NULL);
				}

			} else if (CMDCHECK("search")) {
				name = create_name(arg);
				if (name != NULL) {
					printf("searching for name %s ... ",
					       arg);

					dns_fixedname_init(&fixedname);
					foundname =
						dns_fixedname_name(&fixedname);
					data = NULL;

					result = dns_rbt_findname(rbt, name, 0,
								  foundname,
								  &data);
					switch (result) {
					case ISC_R_SUCCESS:
						printf("found exact: ");
						print_name(data);
						putchar('\n');
						break;
					case DNS_R_PARTIALMATCH:
						printf("found parent: ");
						print_name(data);
						printf("\n\t(foundname: ");
						print_name(foundname);
						printf(")\n");
						break;
					case ISC_R_NOTFOUND:
						printf("NOT FOUND!\n");
						break;
					case ISC_R_NOMEMORY:
						printf("OUT OF MEMORY!\n");
						break;
					default:
						printf("UNEXPECTED RESULT\n");
					}

					delete_name(name, NULL);
				}

			} else if (CMDCHECK("check")) {
				/*
				 * Or "chain".  I know, I know.  Lame name.
				 * I was having a hard time thinking of a
				 * name (especially one that did not have
				 * a conflicting first letter with another
				 * command) that would differentiate this
				 * from the search command.
				 *
				 * But it is just a test program, eh?
				 */
				name = create_name(arg);
				if (name != NULL) {
					detail(rbt, name);

					delete_name(name, NULL);
				}

			} else if (CMDCHECK("forward")) {
				iterate(rbt, ISC_TRUE);

			} else if (CMDCHECK("backward")) {
				iterate(rbt, ISC_FALSE);

			} else if (CMDCHECK("print")) {
				if (arg == NULL || *arg == '\0')
					dns_rbt_printall(rbt, NULL);
				else
					printf("usage: print\n");

			} else if (CMDCHECK("quit")) {
				if (arg == NULL || *arg == '\0')
					break;
				else
					printf("usage: quit\n");
			} else {
				printf("a(dd) NAME, d(elete) NAME, "
				       "s(earch) NAME, p(rint), or q(uit)\n");

			}
		}

	}

	dns_rbt_destroy(&rbt);

	if (show_final_mem)
		isc_mem_stats(mctx, stderr);

	return (0);
}
Beispiel #11
0
ATF_TC_BODY(rbt_remove, tc) {
	/*
	 * This testcase checks that after node removal, the
	 * binary-search tree is valid and all nodes that are supposed
	 * to exist are present in the correct order. It mainly tests
	 * DomainTree as a BST, and not particularly as a red-black
	 * tree. This test checks node deletion when upper nodes have
	 * data.
	 */
	isc_result_t result;
	size_t j;

	UNUSED(tc);

	isc_mem_debugging = ISC_MEM_DEBUGRECORD;

	result = dns_test_begin(NULL, ISC_TRUE);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	/*
	 * Delete single nodes and check if the rest of the nodes exist.
	 */
	for (j = 0; j < ordered_names_count; j++) {
		dns_rbt_t *mytree = NULL;
		dns_rbtnode_t *node;
		size_t i;
		size_t *n;
		isc_boolean_t tree_ok;
		dns_rbtnodechain_t chain;
		size_t start_node;

		/* Create a tree. */
		result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
		ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

		/* Insert test data into the tree. */
		for (i = 0; i < domain_names_count; i++) {
			node = NULL;
			result = insert_helper(mytree, domain_names[i], &node);
			ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
		}

		/* Check that all names exist in order. */
		for (i = 0; i < ordered_names_count; i++) {
			dns_fixedname_t fname;
			dns_name_t *name;

			build_name_from_str(ordered_names[i], &fname);

			name = dns_fixedname_name(&fname);
			node = NULL;
			result = dns_rbt_findnode(mytree, name, NULL,
						  &node, NULL,
						  DNS_RBTFIND_EMPTYDATA,
						  NULL, NULL);
			ATF_CHECK_EQ(result, ISC_R_SUCCESS);

			/* Add node data */
			ATF_REQUIRE(node != NULL);
			ATF_REQUIRE_EQ(node->data, NULL);

			n = isc_mem_get(mctx, sizeof(size_t));
			*n = i;

			node->data = n;
		}

		/* Now, delete the j'th node from the tree. */
		{
			dns_fixedname_t fname;
			dns_name_t *name;

			build_name_from_str(ordered_names[j], &fname);

			name = dns_fixedname_name(&fname);

			result = dns_rbt_deletename(mytree, name, ISC_FALSE);
			ATF_CHECK_EQ(result, ISC_R_SUCCESS);
		}

		/* Check RB tree properties. */
		tree_ok = dns__rbt_checkproperties(mytree);
		ATF_CHECK_EQ(tree_ok, ISC_TRUE);

		dns_rbtnodechain_init(&chain, mctx);

		/* Now, walk through nodes in order. */
		if (j == 0) {
			/*
			 * Node for ordered_names[0] was already deleted
			 * above. We start from node 1.
			 */
			dns_fixedname_t fname;
			dns_name_t *name;

			build_name_from_str(ordered_names[0], &fname);
			name = dns_fixedname_name(&fname);
			node = NULL;
			result = dns_rbt_findnode(mytree, name, NULL,
						  &node, NULL,
						  0,
						  NULL, NULL);
			ATF_CHECK_EQ(result, ISC_R_NOTFOUND);

			build_name_from_str(ordered_names[1], &fname);
			name = dns_fixedname_name(&fname);
			node = NULL;
			result = dns_rbt_findnode(mytree, name, NULL,
						  &node, &chain,
						  0,
						  NULL, NULL);
			ATF_CHECK_EQ(result, ISC_R_SUCCESS);
			start_node = 1;
		} else {
			/* Start from node 0. */
			dns_fixedname_t fname;
			dns_name_t *name;

			build_name_from_str(ordered_names[0], &fname);
			name = dns_fixedname_name(&fname);
			node = NULL;
			result = dns_rbt_findnode(mytree, name, NULL,
						  &node, &chain,
						  0,
						  NULL, NULL);
			ATF_CHECK_EQ(result, ISC_R_SUCCESS);
			start_node = 0;
		}

		/*
		 * node and chain have been set by the code above at
		 * this point.
		 */
		for (i = start_node; i < ordered_names_count; i++) {
			dns_fixedname_t fname_j, fname_i;
			dns_name_t *name_j, *name_i;

			build_name_from_str(ordered_names[j], &fname_j);
			name_j = dns_fixedname_name(&fname_j);
			build_name_from_str(ordered_names[i], &fname_i);
			name_i = dns_fixedname_name(&fname_i);

			if (dns_name_equal(name_i, name_j)) {
				/*
				 * This may be true for the last node if
				 * we seek ahead in the loop using
				 * dns_rbtnodechain_next() below.
				 */
				if (node == NULL) {
					break;
				}

				/* All ordered nodes have data
				 * initially. If any node is empty, it
				 * means it was removed, but an empty
				 * node exists because it is a
				 * super-domain. Just skip it.
				 */
				if (node->data == NULL) {
					result = dns_rbtnodechain_next(&chain,
								       NULL,
								       NULL);
					if (result == ISC_R_NOMORE) {
						node = NULL;
					} else {
						dns_rbtnodechain_current(&chain,
									 NULL,
									 NULL,
									 &node);
					}
				}
				continue;
			}

			ATF_REQUIRE(node != NULL);

			n = (size_t *) node->data;
			if (n != NULL) {
				/* printf("n=%zu, i=%zu\n", *n, i); */
				ATF_CHECK_EQ(*n, i);
			}

			result = dns_rbtnodechain_next(&chain, NULL, NULL);
			if (result == ISC_R_NOMORE) {
				node = NULL;
			} else {
				dns_rbtnodechain_current(&chain, NULL, NULL,
							 &node);
			}
		}

		/* We should have reached the end of the tree. */
		ATF_REQUIRE_EQ(node, NULL);

		dns_rbt_destroy(&mytree);
	}

	dns_test_end();
}
Beispiel #12
0
isc_result_t
cached_ldap_rdatalist_get(isc_mem_t *mctx, ldap_cache_t *cache,
			  ldap_db_t *ldap_db, dns_name_t *name,
			  dns_name_t *origin, ldapdb_rdatalist_t *rdatalist)
{
	isc_result_t result;
	ldapdb_rdatalist_t rdlist;
	cache_node_t *node = NULL;
	int in_cache = 0;
	int is_locked = 0;

	REQUIRE(cache != NULL);

	if (cache->rbt == NULL)
		return ldapdb_rdatalist_get(mctx, ldap_db, name, origin,
					    rdatalist);

	CONTROLED_LOCK(&cache->mutex);
	result = dns_rbt_findname(cache->rbt, name, 0, NULL, (void *)&node);
	if (result == ISC_R_SUCCESS) {
		isc_time_t now;

		CHECK(isc_time_now(&now));

		/* Check if the record is still valid. */
		if (isc_time_compare(&now, &node->valid_until) > 0) {
			CHECK(dns_rbt_deletename(cache->rbt, name, ISC_FALSE));
			in_cache = 0;
		} else {
			rdlist = node->rdatalist;
			in_cache = 1;
		}
	} else if (result != ISC_R_NOTFOUND && result != DNS_R_PARTIALMATCH) {
		goto cleanup;
	}
	CONTROLED_UNLOCK(&cache->mutex);

	if (!in_cache) {
		INIT_LIST(rdlist);
		result = ldapdb_rdatalist_get(mctx, ldap_db, name, origin,
					      &rdlist);
		/* TODO: Cache entries that are not found. */
		if (result != ISC_R_SUCCESS)
			goto cleanup;
		CONTROLED_LOCK(&cache->mutex);
		/* Check again to make sure. */
		node = NULL;
		result = dns_rbt_findname(cache->rbt, name, 0, NULL,
					  (void *)&node);
		if (result == ISC_R_NOTFOUND || result == DNS_R_PARTIALMATCH) {
			node = NULL;
			CHECK(cache_node_create(cache, rdlist, &node));
			CHECK(dns_rbt_addname(cache->rbt, name, (void *)node));
		}
		CONTROLED_UNLOCK(&cache->mutex);
	}

	CHECK(ldap_rdatalist_copy(mctx, rdlist, rdatalist));

	if (EMPTY(*rdatalist))
		result = ISC_R_NOTFOUND;

cleanup:
	CONTROLED_UNLOCK(&cache->mutex);
	return result;
}