Exemple #1
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;
		}
	}
}
Exemple #2
0
isc_result_t
isc_file_openunique(char *templet, FILE **fp) {
	int fd;
	FILE *f;
	isc_result_t result = ISC_R_SUCCESS;
	char *x;
	char *cp;
	isc_uint32_t which;
	int mode;

	REQUIRE(templet != NULL);
	REQUIRE(fp != NULL && *fp == NULL);

	cp = templet;
	while (*cp != '\0')
		cp++;
	if (cp == templet)
		return (ISC_R_FAILURE);

	x = cp--;
	while (cp >= templet && *cp == 'X') {
		isc_random_get(&which);
		*cp = alphnum[which % (sizeof(alphnum) - 1)];
		x = cp--;
	}

	mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;

	while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) {
		if (errno != EEXIST)
			return (isc__errno2result(errno));
		for (cp = x;;) {
			char *t;
			if (*cp == '\0')
				return (ISC_R_FAILURE);
			t = strchr(alphnum, *cp);
			if (t == NULL || *++t == '\0')
				*cp++ = alphnum[0];
			else {
				*cp = *t;
				break;
			}
		}
	}
	f = fdopen(fd, "w+");
	if (f == NULL) {
		result = isc__errno2result(errno);
		if (remove(templet) < 0) {
			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
				      ISC_LOGMODULE_FILE, ISC_LOG_ERROR,
				      "remove '%s': failed", templet);
		}
		(void)close(fd);
	} else
		*fp = f;

	return (result);
}
Exemple #3
0
isc_result_t
isc_file_renameunique(const char *file, char *templet) {
	char *x;
	char *cp;

	REQUIRE(file != NULL);
	REQUIRE(templet != NULL);

	cp = templet;
	while (*cp != '\0')
		cp++;
	if (cp == templet)
		return (ISC_R_FAILURE);

	x = cp--;
	while (cp >= templet && *cp == 'X') {
		isc_uint32_t which;

		isc_random_get(&which);
		*cp = alphnum[which % (sizeof(alphnum) - 1)];
		x = cp--;
	}
	while (link(file, templet) == -1) {
		if (errno != EEXIST)
			return (isc__errno2result(errno));
		for (cp = x;;) {
			const char *t;
			if (*cp == '\0')
				return (ISC_R_FAILURE);
			t = strchr(alphnum, *cp);
			if (t == NULL || *++t == '\0')
				*cp++ = alphnum[0];
			else {
				*cp = *t;
				break;
			}
		}
	}
	if (unlink(file) < 0)
		if (errno != ENOENT)
			return (isc__errno2result(errno));
	return (ISC_R_SUCCESS);
}
Exemple #4
0
void
isc_hash_ctxinit(isc_hash_t *hctx) {
	LOCK(&hctx->lock);

	if (hctx->initialized == ISC_TRUE)
		goto out;

	if (hctx->entropy) {
#ifdef BIND9
		isc_result_t result;

		result = isc_entropy_getdata(hctx->entropy,
					     hctx->rndvector, hctx->vectorlen,
					     NULL, 0);
		INSIST(result == ISC_R_SUCCESS);
#else
		INSIST(0);
#endif
	} else {
		isc_uint32_t pr;
		unsigned int i, copylen;
		unsigned char *p;

		p = (unsigned char *)hctx->rndvector;
		for (i = 0; i < hctx->vectorlen; i += copylen, p += copylen) {
			isc_random_get(&pr);
			if (i + sizeof(pr) <= hctx->vectorlen)
				copylen = sizeof(pr);
			else
				copylen = hctx->vectorlen - i;

			memcpy(p, &pr, copylen);
		}
		INSIST(p == (unsigned char *)hctx->rndvector +
		       hctx->vectorlen);
	}

	hctx->initialized = ISC_TRUE;

 out:
	UNLOCK(&hctx->lock);
}
Exemple #5
0
static void
insert_nodes(dns_rbt_t *mytree, char **names,
	     size_t *names_count, isc_uint32_t num_names)
{
	isc_uint32_t i;

	for (i = 0; i < num_names; i++) {
		size_t *n;
		char namebuf[34];

		n = isc_mem_get(mctx, sizeof(size_t));
		ATF_REQUIRE(n != NULL);

		*n = i; /* Unused value */

		while (1) {
			int j;
			dns_fixedname_t fname;
			dns_name_t *name;
			isc_result_t result;

			for (j = 0; j < 32; j++) {
				isc_uint32_t v;
				isc_random_get(&v);
				namebuf[j] = 'a' + (v % 26);
			}
			namebuf[32] = '.';
			namebuf[33] = 0;

			build_name_from_str(namebuf, &fname);
			name = dns_fixedname_name(&fname);

			result = dns_rbt_addname(mytree, name, n);
			if (result == ISC_R_SUCCESS) {
				names[*names_count] = isc_mem_strdup(mctx,
								     namebuf);
				*names_count += 1;
				break;
			}
		}
	}
}
Exemple #6
0
static void
control_recvmessage(isc_task_t *task, isc_event_t *event) {
	controlconnection_t *conn;
	controllistener_t *listener;
	controlkey_t *key;
	isccc_sexpr_t *request = NULL;
	isccc_sexpr_t *response = NULL;
	isc_uint32_t algorithm;
	isccc_region_t secret;
	isc_stdtime_t now;
	isc_buffer_t b;
	isc_region_t r;
	isc_buffer_t *text;
	isc_result_t result;
	isc_result_t eresult;
	isccc_sexpr_t *_ctrl;
	isccc_time_t sent;
	isccc_time_t exp;
	isc_uint32_t nonce;
	isccc_sexpr_t *data;

	REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG);

	conn = event->ev_arg;
	listener = conn->listener;
	algorithm = DST_ALG_UNKNOWN;
	secret.rstart = NULL;
	text = NULL;

	/* Is the server shutting down? */
	if (listener->controls->shuttingdown)
		goto cleanup;

	if (conn->ccmsg.result != ISC_R_SUCCESS) {
		if (conn->ccmsg.result != ISC_R_CANCELED &&
		    conn->ccmsg.result != ISC_R_EOF)
			log_invalid(&conn->ccmsg, conn->ccmsg.result);
		goto cleanup;
	}

	request = NULL;

	for (key = ISC_LIST_HEAD(listener->keys);
	     key != NULL;
	     key = ISC_LIST_NEXT(key, link))
	{
		isccc_region_t ccregion;

		ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer);
		ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer);
		secret.rstart = isc_mem_get(listener->mctx, key->secret.length);
		if (secret.rstart == NULL)
			goto cleanup;
		memmove(secret.rstart, key->secret.base, key->secret.length);
		secret.rend = secret.rstart + key->secret.length;
		algorithm = key->algorithm;
		result = isccc_cc_fromwire(&ccregion, &request,
					   algorithm, &secret);
		if (result == ISC_R_SUCCESS)
			break;
		isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
		if (result != ISCCC_R_BADAUTH) {
			log_invalid(&conn->ccmsg, result);
			goto cleanup;
		}
	}

	if (key == NULL) {
		log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
		goto cleanup;
	}

	/* We shouldn't be getting a reply. */
	if (isccc_cc_isreply(request)) {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	isc_stdtime_get(&now);

	/*
	 * Limit exposure to replay attacks.
	 */
	_ctrl = isccc_alist_lookup(request, "_ctrl");
	if (_ctrl == NULL) {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	if (isccc_cc_lookupuint32(_ctrl, "_tim", &sent) == ISC_R_SUCCESS) {
		if ((sent + CLOCKSKEW) < now || (sent - CLOCKSKEW) > now) {
			log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW);
			goto cleanup_request;
		}
	} else {
		log_invalid(&conn->ccmsg, ISC_R_FAILURE);
		goto cleanup_request;
	}

	/*
	 * Expire messages that are too old.
	 */
	if (isccc_cc_lookupuint32(_ctrl, "_exp", &exp) == ISC_R_SUCCESS &&
	    now > exp) {
		log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED);
		goto cleanup_request;
	}

	/*
	 * Duplicate suppression (required for UDP).
	 */
	isccc_cc_cleansymtab(listener->controls->symtab, now);
	result = isccc_cc_checkdup(listener->controls->symtab, request, now);
	if (result != ISC_R_SUCCESS) {
		if (result == ISC_R_EXISTS)
			result = ISCCC_R_DUPLICATE;
		log_invalid(&conn->ccmsg, result);
		goto cleanup_request;
	}

	if (conn->nonce != 0 &&
	    (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS ||
	     conn->nonce != nonce)) {
		log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
		goto cleanup_request;
	}

	result = isc_buffer_allocate(listener->mctx, &text, 2 * 2048);
	if (result != ISC_R_SUCCESS)
		goto cleanup_request;

	/*
	 * Establish nonce.
	 */
	if (conn->nonce == 0) {
		while (conn->nonce == 0)
			isc_random_get(&conn->nonce);
		eresult = ISC_R_SUCCESS;
	} else
		eresult = ns_control_docommand(request, &text);

	result = isccc_cc_createresponse(request, now, now + 60, &response);
	if (result != ISC_R_SUCCESS)
		goto cleanup_request;

	data = isccc_alist_lookup(response, "_data");
	if (data != NULL) {
		if (isccc_cc_defineuint32(data, "result", eresult) == NULL)
			goto cleanup_response;
	}

	if (eresult != ISC_R_SUCCESS) {
		if (data != NULL) {
			const char *estr = isc_result_totext(eresult);
			if (isccc_cc_definestring(data, "err", estr) == NULL)
				goto cleanup_response;
		}
	}

	if (isc_buffer_usedlength(text) > 0) {
		if (data != NULL) {
			char *str = (char *)isc_buffer_base(text);
			if (isccc_cc_definestring(data, "text", str) == NULL)
				goto cleanup_response;
		}
	}

	_ctrl = isccc_alist_lookup(response, "_ctrl");
	if (_ctrl == NULL ||
	    isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL)
		goto cleanup_response;

	if (conn->buffer == NULL) {
		result = isc_buffer_allocate(listener->mctx,
					     &conn->buffer, 2 * 2048);
		if (result != ISC_R_SUCCESS)
			goto cleanup_response;
	}

	isc_buffer_clear(conn->buffer);
	/* Skip the length field (4 bytes) */
	isc_buffer_add(conn->buffer, 4);

	result = isccc_cc_towire(response, &conn->buffer, algorithm, &secret);
	if (result != ISC_R_SUCCESS)
		goto cleanup_response;

	isc_buffer_init(&b, conn->buffer->base, 4);
	isc_buffer_putuint32(&b, conn->buffer->used - 4);

	r.base = conn->buffer->base;
	r.length = conn->buffer->used;

	result = isc_socket_send(conn->sock, &r, task, control_senddone, conn);
	if (result != ISC_R_SUCCESS)
		goto cleanup_response;
	conn->sending = ISC_TRUE;

	isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
	isccc_sexpr_free(&request);
	isccc_sexpr_free(&response);
	isc_buffer_free(&text);
	return;

 cleanup_response:
	isccc_sexpr_free(&response);

 cleanup_request:
	isccc_sexpr_free(&request);
	isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
	if (text != NULL)
		isc_buffer_free(&text);

 cleanup:
	isc_socket_detach(&conn->sock);
	isccc_ccmsg_invalidate(&conn->ccmsg);
	conn->ccmsg_valid = ISC_FALSE;
	maybe_free_connection(conn);
	maybe_free_listener(listener);
}
Exemple #7
0
static isc_result_t
towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
	     dns_compress_t *cctx, isc_buffer_t *target,
	     dns_rdatasetorderfunc_t order, const void *order_arg,
	     isc_boolean_t partial, unsigned int options,
	     unsigned int *countp, void **state)
{
	dns_rdata_t rdata = DNS_RDATA_INIT;
	isc_region_t r;
	isc_result_t result;
	unsigned int i, count = 0, added, choice;
	isc_buffer_t savedbuffer, rdlen, rrbuffer;
	unsigned int headlen;
	isc_boolean_t question = ISC_FALSE;
	isc_boolean_t shuffle = ISC_FALSE;
	dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
	struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];

	/* count processed auswer ips */
	int answer_count = 0;
	int is_no_auth_answer    = 0;
	/* tmp count for record */
	int tmp_count = 0;

	UNUSED(state);

	/*
	 * Convert 'rdataset' to wire format, compressing names as specified
	 * in cctx, and storing the result in 'target'.
	 */

	REQUIRE(DNS_RDATASET_VALID(rdataset));
	REQUIRE(countp != NULL);
	REQUIRE((order == NULL) == (order_arg == NULL));
	REQUIRE(cctx != NULL && cctx->mctx != NULL);

	if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
		question = ISC_TRUE;
		count = 1;
		result = dns_rdataset_first(rdataset);
		INSIST(result == ISC_R_NOMORE);
	} else if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
		/*
		 * This is a negative caching rdataset.
		 */
		unsigned int ncache_opts = 0;
		if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0)
			ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC;
		return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
					  countp));
	} else {
		count = (rdataset->methods->count)(rdataset);
		result = dns_rdataset_first(rdataset);
		if (result == ISC_R_NOMORE)
			return (ISC_R_SUCCESS);
		if (result != ISC_R_SUCCESS)
			return (result);
	}

	/*
	 * Do we want to shuffle this answer?
	 */
	if (!question && count > 1 &&
	    (!WANT_FIXED(rdataset) || order != NULL) &&
	    rdataset->type != dns_rdatatype_rrsig)
		shuffle = ISC_TRUE;

	if (shuffle && count > MAX_SHUFFLE) {
		shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
		sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
		if (shuffled == NULL || sorted == NULL)
			shuffle = ISC_FALSE;
	} else {
		shuffled = shuffled_fixed;
		sorted = sorted_fixed;
	}

	if (shuffle) {
		/*
		 * First we get handles to all of the rdata.
		 */
		i = 0;
		do {
			INSIST(i < count);
			dns_rdata_init(&shuffled[i]);
			dns_rdataset_current(rdataset, &shuffled[i]);
			i++;
			result = dns_rdataset_next(rdataset);
		} while (result == ISC_R_SUCCESS);
		if (result != ISC_R_NOMORE)
			goto cleanup;
		INSIST(i == count);

		/*
		 * Now we shuffle.
		 */
		if (WANT_FIXED(rdataset)) {
			/*
			 * 'Fixed' order.
			 */
			INSIST(order != NULL);
			for (i = 0; i < count; i++) {
				sorted[i].key = (*order)(&shuffled[i],
							 order_arg);
				sorted[i].rdata = &shuffled[i];
			}
		} else if (WANT_RANDOM(rdataset)) {
			/*
			 * 'Random' order.
			 */
			for (i = 0; i < count; i++) {
				dns_rdata_t rdata;
				isc_uint32_t val;

				isc_random_get(&val);
				choice = i + (val % (count - i));
				rdata = shuffled[i];
				shuffled[i] = shuffled[choice];
				shuffled[choice] = rdata;
				if (order != NULL)
					sorted[i].key = (*order)(&shuffled[i],
								 order_arg);
				else
					sorted[i].key = 0; /* Unused */
				sorted[i].rdata = &shuffled[i];
			}
		} else {
			/*
			 * "Cyclic" order.
			 */
			isc_uint32_t val;
			unsigned int j;

			val = rdataset->count;
			if (val == ISC_UINT32_MAX)
				isc_random_get(&val);
			j = val % count;
			for (i = 0; i < count; i++) {
				if (order != NULL)
					sorted[i].key = (*order)(&shuffled[j],
								 order_arg);
				else
					sorted[i].key = 0; /* Unused */
				sorted[i].rdata = &shuffled[j];
				j++;
				if (j == count)
					j = 0; /* Wrap around. */
			}
		}

		/*
		 * Sorted order.
		 */
		if (order != NULL)
			qsort(sorted, count, sizeof(sorted[0]),
			      towire_compare);
	}

	savedbuffer = *target;
	i = 0;
	added = 0;

	// save the count here
	tmp_count = count;

	do {
		/*
		 * Copy out the name, type, class, ttl.
		 */
			/* mark if is answer data. */
			is_no_auth_answer = 0;
			/* Answer from a non-authoritative server,we set the ttl fixed as 500. */
			if(rdataset->attributes == DNS_RDATASETATTR_LOADORDER && 
					rdataset->type == dns_rdatatype_a){
				/* Answer from a non-authoritative server,we set the ttl fixed as 500. */
				if(rdataset->trust == dns_trust_answer ){
					is_no_auth_answer = 1;
				}

				/* for all multi-ip answer,if set DNS_ANSWER_ONLY_ONE_IP flag, return only 1 ip. */
				if(answer_count == 0){
					answer_count ++;
				}else{
					if( DNS_ANSWER_ONLY_ONE_IP ){
						//fprintf(stderr,"DNS_ANSWER_ONLY_ONE_IP set,skip. \n");
						if (shuffle) {
							tmp_count--;
							if (i == tmp_count)
								result = ISC_R_NOMORE;
							else
								result = ISC_R_SUCCESS;
						} else {
							result = dns_rdataset_next(rdataset);
						}
						continue;
					}
				}
			}


			rrbuffer = *target;
		dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
		result = dns_name_towire(owner_name, cctx, target);
		if (result != ISC_R_SUCCESS)
			goto rollback;
		headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
		if (!question)
			headlen += sizeof(dns_ttl_t)
				+ 2;  /* XXX 2 for rdata len */
		isc_buffer_availableregion(target, &r);
		if (r.length < headlen) {
			result = ISC_R_NOSPACE;
			goto rollback;
		}

		isc_buffer_putuint16(target, rdataset->type);
		isc_buffer_putuint16(target, rdataset->rdclass);
		if (!question) {
			
			if( is_no_auth_answer ){
					isc_buffer_putuint32(target, DNS_DEFAULT_TTL_FOR_NO_AUTH_NAME);
			}else{
					isc_buffer_putuint32(target, rdataset->ttl);
			}
			//fprintf(stderr,"xxxxxxxxx:trust : %d artr: %d ttl:%d  cover: %d type: %d count: %d class: %d\n", rdataset->trust,rdataset->attributes,rdataset->ttl, rdataset->covers,rdataset->type, rdataset->count, rdataset->rdclass);

			/*
			 * Save space for rdlen.
			 */
			rdlen = *target;
			isc_buffer_add(target, 2);

			/*
			 * Copy out the rdata
			 */
			if (shuffle)
				rdata = *(sorted[i].rdata);
			else {
				dns_rdata_reset(&rdata);
				dns_rdataset_current(rdataset, &rdata);
			}
			result = dns_rdata_towire(&rdata, cctx, target);
			if (result != ISC_R_SUCCESS)
				goto rollback;
			INSIST((target->used >= rdlen.used + 2) &&
			       (target->used - rdlen.used - 2 < 65536));
			isc_buffer_putuint16(&rdlen,
					     (isc_uint16_t)(target->used -
							    rdlen.used - 2));
			added++;
		}

		if (shuffle) {
			i++;
			if (i == tmp_count)
				result = ISC_R_NOMORE;
			else
				result = ISC_R_SUCCESS;
		} else {
			result = dns_rdataset_next(rdataset);
		}
	} while (result == ISC_R_SUCCESS);

	if (result != ISC_R_NOMORE)
		goto rollback;

	*countp += tmp_count;

	result = ISC_R_SUCCESS;
	goto cleanup;

 rollback:
	if (partial && result == ISC_R_NOSPACE) {
		INSIST(rrbuffer.used < 65536);
		dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used);
		*countp += added;
		*target = rrbuffer;
		goto cleanup;
	}
	INSIST(savedbuffer.used < 65536);
	dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
	*countp = 0;
	*target = savedbuffer;

 cleanup:
	if (sorted != NULL && sorted != sorted_fixed)
		isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
	if (shuffled != NULL && shuffled != shuffled_fixed)
		isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
	return (result);
}
Exemple #8
0
int
main(int argc, char **argv) {
	isc_boolean_t show_final_mem = ISC_FALSE;
	isc_result_t result = ISC_R_SUCCESS;
	isc_taskmgr_t *taskmgr = NULL;
	isc_task_t *task = NULL;
	isc_log_t *log = NULL;
	isc_logconfig_t *logconfig = NULL;
	isc_logdestination_t logdest;
	cfg_parser_t *pctx = NULL;
	cfg_obj_t *config = NULL;
	const char *keyname = NULL;
	char *p;
	size_t argslen;
	int ch;
	int i;

	result = isc_file_progname(*argv, program, sizeof(program));
	if (result != ISC_R_SUCCESS)
		memcpy(program, "rndc", 5);
	progname = program;

	admin_conffile = RNDC_CONFFILE;
	admin_keyfile = RNDC_KEYFILE;

	result = isc_app_start();
	if (result != ISC_R_SUCCESS)
		fatal("isc_app_start() failed: %s", isc_result_totext(result));

	while ((ch = isc_commandline_parse(argc, argv, "c:k:Mmp:s:Vy:"))
	       != -1) {
		switch (ch) {
		case 'c':
			admin_conffile = isc_commandline_argument;
			break;

		case 'k':
			admin_keyfile = isc_commandline_argument;
			break;

		case 'M':
			isc_mem_debugging = ISC_MEM_DEBUGTRACE;
			break;

		case 'm':
			show_final_mem = ISC_TRUE;
			break;

		case 'p':
			remoteport = atoi(isc_commandline_argument);
			if (remoteport > 65535 || remoteport == 0)
				fatal("port '%s' out of range",
				      isc_commandline_argument);
			break;

		case 's':
			servername = isc_commandline_argument;
			break;
		case 'V':
			verbose = ISC_TRUE;
			break;
		case 'y':
			keyname = isc_commandline_argument;
			break;
		case '?':
			usage(0);
			break;
		default:
			fatal("unexpected error parsing command arguments: "
			      "got %c\n", ch);
			break;
		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;

	if (argc < 1)
		usage(1);

	isc_random_get(&serial);

	DO("create memory context", isc_mem_create(0, 0, &mctx));
	DO("create socket manager", isc_socketmgr_create(mctx, &socketmgr));
	DO("create task manager", isc_taskmgr_create(mctx, 1, 0, &taskmgr));
	DO("create task", isc_task_create(taskmgr, 0, &task));

	DO("create logging context", isc_log_create(mctx, &log, &logconfig));
	isc_log_setcontext(log);
	DO("setting log tag", isc_log_settag(logconfig, progname));
	logdest.file.stream = stderr;
	logdest.file.name = NULL;
	logdest.file.versions = ISC_LOG_ROLLNEVER;
	logdest.file.maximum_size = 0;
	DO("creating log channel",
	   isc_log_createchannel(logconfig, "stderr",
		   		 ISC_LOG_TOFILEDESC, ISC_LOG_INFO, &logdest,
				 ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL));
	DO("enabling log channel", isc_log_usechannel(logconfig, "stderr",
						      NULL, NULL));

	parse_config(mctx, log, keyname, &pctx, &config);

	isccc_result_register();

	command = *argv;

	/*
	 * Convert argc/argv into a space-delimited command string
	 * similar to what the user might enter in interactive mode
	 * (if that were implemented).
	 */
	argslen = 0;
	for (i = 0; i < argc; i++)
		argslen += strlen(argv[i]) + 1;

	args = isc_mem_get(mctx, argslen);
	if (args == NULL)
		DO("isc_mem_get", ISC_R_NOMEMORY);

	p = args;
	for (i = 0; i < argc; i++) {
		size_t len = strlen(argv[i]);
		memcpy(p, argv[i], len);
		p += len;
		*p++ = ' ';
	}

	p--;
	*p++ = '\0';
	INSIST(p == args + argslen);

	notify("%s", command);

	if (strcmp(command, "restart") == 0)
		fatal("'%s' is not implemented", command);

	DO("post event", isc_app_onrun(mctx, task, rndc_start, NULL));

	result = isc_app_run();
	if (result != ISC_R_SUCCESS)
		fatal("isc_app_run() failed: %s", isc_result_totext(result));

	if (connects > 0 || sends > 0 || recvs > 0)
		isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);

	isc_task_detach(&task);
	isc_taskmgr_destroy(&taskmgr);
	isc_socketmgr_destroy(&socketmgr);
	isc_log_destroy(&log);
	isc_log_setcontext(NULL);

	cfg_obj_destroy(pctx, &config);
	cfg_parser_destroy(&pctx);

	isc_mem_put(mctx, args, argslen);
	isccc_ccmsg_invalidate(&ccmsg);

	if (show_final_mem)
		isc_mem_stats(mctx, stderr);

	isc_mem_destroy(&mctx);

	if (failed)
		return (1);

	return (0);
}
Exemple #9
0
void *
isc_pool_get(isc_pool_t *pool) {
	isc_uint32_t i;
	isc_random_get(&i);
	return (pool->pool[i % pool->count]);
}
ATF_TC_BODY(deserialize_corrupt, tc) {
	dns_rbt_t *rbt = NULL;
	isc_result_t result;
	FILE *rbtfile = NULL;
	off_t offset;
	int fd;
	off_t filesize = 0;
	char *base, *p, *q;
	isc_uint32_t r;
	int i;

	UNUSED(tc);

	isc_mem_debugging = ISC_MEM_DEBUGRECORD;

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

	/* Set up map file */
	result = dns_rbt_create(mctx, delete_data, NULL, &rbt);
	ATF_CHECK_EQ(result, ISC_R_SUCCESS);

	add_test_data(mctx, rbt);
	rbtfile = fopen("./zone.bin", "w+b");
	ATF_REQUIRE(rbtfile != NULL);
	result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL,
					&offset);
	ATF_REQUIRE(result == ISC_R_SUCCESS);
	dns_rbt_destroy(&rbt);

	/* Read back with random fuzzing */
	for (i = 0; i < 256; i++) {
		dns_rbt_t *rbt_deserialized = NULL;

		fd = open("zone.bin", O_RDWR);
		isc_file_getsizefd(fd, &filesize);
		base = mmap(NULL, filesize,
			    PROT_READ|PROT_WRITE,
			    MAP_FILE|MAP_PRIVATE, fd, 0);
		ATF_REQUIRE(base != NULL && base != MAP_FAILED);
		close(fd);

		/* Randomly fuzz a portion of the memory */
		isc_random_get(&r);
		p = base + (r % filesize);
		q = base + filesize;
		isc_random_get(&r);
		q -= (r % (q - p));
		while (p++ < q) {
			isc_random_get(&r);
			*p = r & 0xff;
		}

		result = dns_rbt_deserialize_tree(base, filesize, 0, mctx,
						  delete_data, NULL,
						  fix_data, NULL,
						  NULL, &rbt_deserialized);
		printf("%d: %s\n", i, isc_result_totext(result));

		/* Test to make sure we have a valid tree */
		ATF_REQUIRE(result == ISC_R_SUCCESS ||
			    result == ISC_R_INVALIDFILE);
		if (result != ISC_R_SUCCESS)
			ATF_REQUIRE(rbt_deserialized == NULL);

		if (rbt_deserialized != NULL)
			dns_rbt_destroy(&rbt_deserialized);

		munmap(base, filesize);
	}

	unlink("zone.bin");
	dns_test_end();
}
Exemple #11
0
void
isc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp) {
	isc_uint32_t i;
	isc_random_get(&i);
	isc_task_attach(pool->tasks[i % pool->ntasks], targetp);
}
Exemple #12
0
int
main(int argc, char **argv) {
	isc_result_t result = ISC_R_SUCCESS;
	isc_boolean_t show_final_mem = ISC_FALSE;
	isc_taskmgr_t *taskmgr = NULL;
	isc_task_t *task = NULL;
	isc_log_t *log = NULL;
	isc_logconfig_t *logconfig = NULL;
	isc_logdestination_t logdest;
	cfg_parser_t *pctx = NULL;
	cfg_obj_t *config = NULL;
	const char *keyname = NULL;
	struct in_addr in;
	struct in6_addr in6;
	char *p;
	size_t argslen;
	int ch;
	int i;

	result = isc_file_progname(*argv, program, sizeof(program));
	if (result != ISC_R_SUCCESS)
		memmove(program, "rndc", 5);
	progname = program;

	admin_conffile = RNDC_CONFFILE;
	admin_keyfile = RNDC_KEYFILE;

	isc_sockaddr_any(&local4);
	isc_sockaddr_any6(&local6);

	result = isc_app_start();
	if (result != ISC_R_SUCCESS)
		fatal("isc_app_start() failed: %s", isc_result_totext(result));

	isc_commandline_errprint = ISC_FALSE;

	while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:qrs:Vy:"))
	       != -1) {
		switch (ch) {
		case 'b':
			if (inet_pton(AF_INET, isc_commandline_argument,
				      &in) == 1) {
				isc_sockaddr_fromin(&local4, &in, 0);
				local4set = ISC_TRUE;
			} else if (inet_pton(AF_INET6, isc_commandline_argument,
					     &in6) == 1) {
				isc_sockaddr_fromin6(&local6, &in6, 0);
				local6set = ISC_TRUE;
			}
			break;

		case 'c':
			admin_conffile = isc_commandline_argument;
			c_flag = ISC_TRUE;
			break;

		case 'k':
			admin_keyfile = isc_commandline_argument;
			break;

		case 'M':
			isc_mem_debugging = ISC_MEM_DEBUGTRACE;
			break;

		case 'm':
			show_final_mem = ISC_TRUE;
			break;

		case 'p':
			remoteport = atoi(isc_commandline_argument);
			if (remoteport > 65535 || remoteport == 0)
				fatal("port '%s' out of range",
				      isc_commandline_argument);
			break;

		case 'q':
			quiet = ISC_TRUE;
			break;

		case 'r':
			showresult = ISC_TRUE;
			break;

		case 's':
			servername = isc_commandline_argument;
			break;

		case 'V':
			verbose = ISC_TRUE;
			break;

		case 'y':
			keyname = isc_commandline_argument;
			break;

		case '?':
			if (isc_commandline_option != '?') {
				fprintf(stderr, "%s: invalid argument -%c\n",
					program, isc_commandline_option);
				usage(1);
			}
			/* FALLTHROUGH */
		case 'h':
			usage(0);
			break;
		default:
			fprintf(stderr, "%s: unhandled option -%c\n",
				program, isc_commandline_option);
			exit(1);
		}
	}

	argc -= isc_commandline_index;
	argv += isc_commandline_index;

	if (argc < 1)
		usage(1);

	isc_random_get(&serial);

	DO("create memory context", isc_mem_create(0, 0, &rndc_mctx));
	DO("create socket manager", isc_socketmgr_create(rndc_mctx, &socketmgr));
	DO("create task manager", isc_taskmgr_create(rndc_mctx, 1, 0, &taskmgr));
	DO("create task", isc_task_create(taskmgr, 0, &task));

	DO("create logging context", isc_log_create(rndc_mctx, &log, &logconfig));
	isc_log_setcontext(log);
	DO("setting log tag", isc_log_settag(logconfig, progname));
	logdest.file.stream = stderr;
	logdest.file.name = NULL;
	logdest.file.versions = ISC_LOG_ROLLNEVER;
	logdest.file.maximum_size = 0;
	DO("creating log channel",
	   isc_log_createchannel(logconfig, "stderr",
				 ISC_LOG_TOFILEDESC, ISC_LOG_INFO, &logdest,
				 ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL));
	DO("enabling log channel", isc_log_usechannel(logconfig, "stderr",
						      NULL, NULL));

	parse_config(rndc_mctx, log, keyname, &pctx, &config);

	isccc_result_register();

	command = *argv;

	DO("allocate data buffer",
	   isc_buffer_allocate(rndc_mctx, &databuf, 2048));

	/*
	 * Convert argc/argv into a space-delimited command string
	 * similar to what the user might enter in interactive mode
	 * (if that were implemented).
	 */
	argslen = 0;
	for (i = 0; i < argc; i++)
		argslen += strlen(argv[i]) + 1;

	args = isc_mem_get(rndc_mctx, argslen);
	if (args == NULL)
		DO("isc_mem_get", ISC_R_NOMEMORY);

	p = args;
	for (i = 0; i < argc; i++) {
		size_t len = strlen(argv[i]);
		memmove(p, argv[i], len);
		p += len;
		*p++ = ' ';
	}

	p--;
	*p++ = '\0';
	INSIST(p == args + argslen);

	notify("%s", command);

	if (strcmp(command, "restart") == 0)
		fatal("'%s' is not implemented", command);

	if (nserveraddrs == 0)
		get_addresses(servername, (in_port_t) remoteport);

	DO("post event", isc_app_onrun(rndc_mctx, task, rndc_start, NULL));

	result = isc_app_run();
	if (result != ISC_R_SUCCESS)
		fatal("isc_app_run() failed: %s", isc_result_totext(result));

	if (connects > 0 || sends > 0 || recvs > 0)
		isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);

	isc_task_detach(&task);
	isc_taskmgr_destroy(&taskmgr);
	isc_socketmgr_destroy(&socketmgr);
	isc_log_destroy(&log);
	isc_log_setcontext(NULL);

	cfg_obj_destroy(pctx, &config);
	cfg_parser_destroy(&pctx);

	isc_mem_put(rndc_mctx, args, argslen);
	isccc_ccmsg_invalidate(&ccmsg);

	dns_name_destroy();

	isc_buffer_free(&databuf);

	if (show_final_mem)
		isc_mem_stats(rndc_mctx, stderr);

	isc_mem_destroy(&rndc_mctx);

	if (failed)
		return (1);

	return (0);
}
Exemple #13
0
ATF_TC_BODY(rbt_check_distance_random, tc) {
	/* This test checks an important performance-related property of
	 * the red-black tree, which is important for us: the longest
	 * path from a sub-tree's root to a node is no more than
	 * 2log(n). This check verifies that the tree is balanced.
	 */
	dns_rbt_t *mytree = NULL;
	const unsigned int log_num_nodes = 16;

	int i;
	isc_result_t result;
	isc_boolean_t tree_ok;

	UNUSED(tc);

	isc_mem_debugging = ISC_MEM_DEBUGRECORD;

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

	result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	/* Names are inserted in random order. */

	/* Make a large 65536 node top-level domain tree, i.e., the
	 * following code inserts names such as:
	 *
	 * savoucnsrkrqzpkqypbygwoiliawpbmz.
	 * wkadamcbbpjtundbxcmuayuycposvngx.
	 * wzbpznemtooxdpjecdxynsfztvnuyfao.
	 * yueojmhyffslpvfmgyfwioxegfhepnqq.
	 */
	for (i = 0; i < (1 << log_num_nodes); i++) {
		size_t *n;
		char namebuf[34];

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

		while (1) {
			int j;
			dns_fixedname_t fname;
			dns_name_t *name;

			for (j = 0; j < 32; j++) {
				isc_uint32_t v;
				isc_random_get(&v);
				namebuf[j] = 'a' + (v % 26);
			}
			namebuf[32] = '.';
			namebuf[33] = 0;

			build_name_from_str(namebuf, &fname);
			name = dns_fixedname_name(&fname);

			result = dns_rbt_addname(mytree, name, n);
			if (result == ISC_R_SUCCESS)
				break;
		}
	}

	/* 1 (root . node) + (1 << log_num_nodes) */
	ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree));

	/* The distance from each node to its sub-tree root must be less
	 * than 2 * log(n).
	 */
	ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree));

	/* Also check RB tree properties */
	tree_ok = dns__rbt_checkproperties(mytree);
	ATF_CHECK_EQ(tree_ok, ISC_TRUE);

	dns_rbt_destroy(&mytree);

	dns_test_end();
}
Exemple #14
0
ATF_TC_BODY(rbt_insert_and_remove, tc) {
	/*
	 * What is the best way to test our red-black tree code? It is
	 * not a good method to test every case handled in the actual
	 * code itself. This is because our approach itself may be
	 * incorrect.
	 *
	 * We test our code at the interface level here by exercising the
	 * tree randomly multiple times, checking that red-black tree
	 * properties are valid, and all the nodes that are supposed to be
	 * in the tree exist and are in order.
	 *
	 * NOTE: These tests are run within a single tree level in the
	 * forest. The number of nodes in the tree level doesn't grow
	 * over 1024.
	 */
	isc_result_t result;
	dns_rbt_t *mytree = NULL;
	/*
	 * We use an array for storing names instead of a set
	 * structure. It's slow, but works and is good enough for tests.
	 */
	char *names[1024];
	size_t names_count;
	int i;

	UNUSED(tc);

	isc_mem_debugging = ISC_MEM_DEBUGRECORD;

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

	result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	memset(names, 0, sizeof(names));
	names_count = 0;

	/* Repeat the insert/remove test some 4096 times */
	for (i = 0; i < 4096; i++) {
		isc_uint32_t num_names;
		isc_random_get(&num_names);

		if (names_count < 1024) {
			num_names %= 1024 - names_count;
			num_names++;
		} else {
			num_names = 0;
		}

		insert_nodes(mytree, names, &names_count, num_names);
		check_tree(mytree, names, names_count);

		isc_random_get(&num_names);
		if (names_count > 0) {
			num_names %= names_count;
			num_names++;
		} else {
			num_names = 0;
		}

		remove_nodes(mytree, names, &names_count, num_names);
		check_tree(mytree, names, names_count);
	}

	/* Remove the rest of the nodes */
	remove_nodes(mytree, names, &names_count, names_count);
	check_tree(mytree, names, names_count);

	for (i = 0; i < 1024; i++) {
		if (names[i] != NULL) {
			isc_mem_free(mctx, names[i]);
		}
	}

	dns_rbt_destroy(&mytree);

	dns_test_end();
}