Example #1
0
int main(int argc, char *argv[])
{
	plan(TESTS_COUNT + 1);

	mm_ctx_t mm;
	mm_ctx_mempool(&mm, MM_DEFAULT_BLKSIZE);

	conf_remote_t remote;
	memset(&remote, 0, sizeof(conf_remote_t));
	sockaddr_set(&remote.addr, AF_INET, "127.0.0.1", 0);
	sockaddr_set(&remote.via, AF_INET, "127.0.0.1", 0);

	/* Create fake server environment. */
	server_t server;
	int ret = create_fake_server(&server, &mm);
	ok(ret == KNOT_EOK, "requestor: initialize fake server");

	/* Initialize requestor. */
	struct knot_requestor requestor;
	knot_requestor_init(&requestor, &mm);
	knot_requestor_overlay(&requestor, &dummy_module, NULL);

	/* Test requestor in disconnected environment. */
	test_disconnected(&requestor, &remote);

	/* Bind to random port. */
	int origin_fd = net_bound_socket(SOCK_STREAM, &remote.addr, 0);
	assert(origin_fd > 0);
	socklen_t addr_len = sockaddr_len((struct sockaddr *)&remote.addr);
	getsockname(origin_fd, (struct sockaddr *)&remote.addr, &addr_len);
	ret = listen(origin_fd, 10);
	assert(ret == 0);

	/* Responder thread. */
	pthread_t thread;
	pthread_create(&thread, 0, responder_thread, &origin_fd);

	/* Test requestor in connected environment. */
	test_connected(&requestor, &remote);

	/*! \todo #243 TSIG secured requests test should be implemented. */

	/* Terminate responder. */
	int responder = net_connected_socket(SOCK_STREAM, &remote.addr, NULL, 0);
	assert(responder > 0);
	tcp_send_msg(responder, (const uint8_t *)"", 1, NULL);
	(void) pthread_join(thread, 0);
	close(responder);

	/* Close requestor. */
	knot_requestor_clear(&requestor);
	close(origin_fd);

	/* Cleanup. */
	mp_delete((struct mempool *)mm.ctx);
	server_deinit(&server);
	conf_free(conf(), false);

	return 0;
}
Example #2
0
static int dnsproxy_fwd(int state, knot_pkt_t *pkt, struct query_data *qdata, void *ctx)
{
	if (pkt == NULL || qdata == NULL || ctx == NULL) {
		return KNOT_STATE_FAIL;
	}

	/* If not already satisfied. */
	if (state == KNOT_STATE_DONE) {
		return state;
	}

	struct dnsproxy *proxy = ctx;

	/* Create a forwarding request. */
	struct knot_requestor re;
	knot_requestor_init(&re, qdata->mm);
	struct capture_param param;
	param.sink = pkt;
	int ret = knot_requestor_overlay(&re, LAYER_CAPTURE, &param);
	if (ret != KNOT_EOK) {
		return KNOT_STATE_FAIL;
	}

	bool is_tcp = net_is_connected(qdata->param->socket);
	struct knot_request *req;
	req = knot_request_make(re.mm, (const struct sockaddr *)&proxy->remote,
	                        NULL, qdata->query, is_tcp ? 0 : KNOT_RQ_UDP);
	if (req == NULL) {
		return state; /* Ignore, not enough memory. */
	}

	/* Forward request. */
	ret = knot_requestor_enqueue(&re, req);
	if (ret == KNOT_EOK) {
		conf_val_t val = conf_get(conf(), C_SRV, C_TCP_HSHAKE_TIMEOUT);
		struct timeval tv = { conf_int(&val), 0 };
		ret = knot_requestor_exec(&re, &tv);
	} else {
		knot_request_free(re.mm, req);
	}

	knot_requestor_clear(&re);

	/* Check result. */
	if (ret != KNOT_EOK) {
		qdata->rcode = KNOT_RCODE_SERVFAIL;
		return KNOT_STATE_FAIL; /* Forwarding failed, SERVFAIL. */
	}

	return KNOT_STATE_DONE;
}
Example #3
0
/*! \brief Process query using requestor. */
static int zone_query_request(knot_pkt_t *query, const conf_remote_t *remote,
                              struct process_answer_param *param, knot_mm_t *mm)
{
	/* Create requestor instance. */
	struct knot_requestor re;
	int ret = knot_requestor_init(&re, mm);
	if (ret != KNOT_EOK) {
		return ret;
	}
	ret = knot_requestor_overlay(&re, KNOT_STATE_ANSWER, param);
	if (ret != KNOT_EOK) {
		knot_requestor_clear(&re);
		return ret;
	}

	/* Create a request. */
	const struct sockaddr *dst = (const struct sockaddr *)&remote->addr;
	const struct sockaddr *src = (const struct sockaddr *)&remote->via;
	struct knot_request *req = knot_request_make(re.mm, dst, src, query, 0);
	if (req == NULL) {
		knot_requestor_clear(&re);
		return KNOT_ENOMEM;
	}

	/* Send the queries and process responses. */
	ret = knot_requestor_enqueue(&re, req);
	if (ret == KNOT_EOK) {
		conf_val_t *val = &param->conf->cache.srv_tcp_reply_timeout;
		int timeout = conf_int(val) * 1000;
		ret = knot_requestor_exec(&re, timeout);
	} else {
		knot_request_free(req, re.mm);
	}

	/* Cleanup. */
	knot_requestor_clear(&re);

	return ret;
}