Example #1
0
File: rndc.c Project: OPSF/uClinux
static void
rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task) {
	isc_result_t result;
	int pf;
	isc_sockettype_t type;

	char socktext[ISC_SOCKADDR_FORMATSIZE];

	isc_sockaddr_format(addr, socktext, sizeof(socktext));

	notify("using server %s (%s)", servername, socktext);

	pf = isc_sockaddr_pf(addr);
	if (pf == AF_INET || pf == AF_INET6)
		type = isc_sockettype_tcp;
	else
		type = isc_sockettype_unix;
	DO("create socket", isc_socket_create(socketmgr, pf, type, &sock));
	switch (isc_sockaddr_pf(addr)) {
	case AF_INET:
		DO("bind socket", isc_socket_bind(sock, &local4));
		break;
	case AF_INET6:
		DO("bind socket", isc_socket_bind(sock, &local6));
		break;
	default:
		break;
	}
	DO("connect", isc_socket_connect(sock, addr, task, rndc_connected,
					 NULL));
	connects++;
}
Example #2
0
static isc_result_t
ns_interface_accepttcp(ns_interface_t *ifp) {
	isc_result_t result;

	/*
	 * Open a TCP socket.
	 */
	result = isc_socket_create(ifp->mgr->socketmgr,
				   isc_sockaddr_pf(&ifp->addr),
				   isc_sockettype_tcp,
				   &ifp->tcpsocket);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				 "creating TCP socket: %s",
				 isc_result_totext(result));
		goto tcp_socket_failure;
	}
	isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL);
#ifndef ISC_ALLOW_MAPPED
	isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
#endif
	result = isc_socket_bind(ifp->tcpsocket, &ifp->addr);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				 "binding TCP socket: %s",
				 isc_result_totext(result));
		goto tcp_bind_failure;
	}
	result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				 "listening on TCP socket: %s",
				 isc_result_totext(result));
		goto tcp_listen_failure;
	}

	/* 
	 * If/when there a multiple filters listen to the
	 * result.
	 */
	(void)isc_socket_filter(ifp->tcpsocket, "dataready");

	result = ns_clientmgr_createclients(ifp->clientmgr,
					    ifp->ntcptarget, ifp,
					    ISC_TRUE);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "TCP ns_clientmgr_createclients(): %s",
				 isc_result_totext(result));
		goto accepttcp_failure;
	}
	return (ISC_R_SUCCESS);

 accepttcp_failure:
 tcp_listen_failure:
 tcp_bind_failure:
	isc_socket_detach(&ifp->tcpsocket);
 tcp_socket_failure:
	return (ISC_R_SUCCESS);
}
Example #3
0
static isc_result_t
listener_bind(ns_lwreslistener_t *listener, isc_sockaddr_t *address) {
	isc_socket_t *sock = NULL;
	isc_result_t result = ISC_R_SUCCESS;
	int pf;

	pf = isc_sockaddr_pf(address);
	if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
	    (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
		return (ISC_R_FAMILYNOSUPPORT);

	listener->address = *address;

	if (isc_sockaddr_getport(&listener->address) == 0) {
		in_port_t port;
		port = lwresd_g_listenport;
		if (port == 0)
			port = LWRES_UDP_PORT;
		isc_sockaddr_setport(&listener->address, port);
	}

	sock = NULL;
	result = isc_socket_create(ns_g_socketmgr, pf,
				   isc_sockettype_udp, &sock);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
			      "failed to create lwres socket: %s",
			      isc_result_totext(result));
		return (result);
	}

	result = isc_socket_bind(sock, &listener->address,
				 ISC_SOCKET_REUSEADDRESS);
	if (result != ISC_R_SUCCESS) {
		char socktext[ISC_SOCKADDR_FORMATSIZE];
		isc_sockaddr_format(&listener->address, socktext,
				    sizeof(socktext));
		isc_socket_detach(&sock);
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
			      "failed to add lwres socket: %s: %s",
			      socktext, isc_result_totext(result));
		return (result);
	}
	listener->sock = sock;
	return (ISC_R_SUCCESS);
}
Example #4
0
static void
add_listener(ns_controls_t *cp, controllistener_t **listenerp,
	     const cfg_obj_t *control, const cfg_obj_t *config,
	     isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
	     const char *socktext, isc_sockettype_t type)
{
	isc_mem_t *mctx = cp->server->mctx;
	controllistener_t *listener;
	const cfg_obj_t *allow;
	const cfg_obj_t *global_keylist = NULL;
	const cfg_obj_t *control_keylist = NULL;
	dns_acl_t *new_acl = NULL;
	isc_result_t result = ISC_R_SUCCESS;

	listener = isc_mem_get(mctx, sizeof(*listener));
	if (listener == NULL)
		result = ISC_R_NOMEMORY;

	if (result == ISC_R_SUCCESS) {
		listener->mctx = NULL;
		isc_mem_attach(mctx, &listener->mctx);
		listener->controls = cp;
		listener->task = cp->server->task;
		listener->address = *addr;
		listener->sock = NULL;
		listener->listening = ISC_FALSE;
		listener->exiting = ISC_FALSE;
		listener->acl = NULL;
		listener->type = type;
		listener->perm = 0;
		listener->owner = 0;
		listener->group = 0;
		ISC_LINK_INIT(listener, link);
		ISC_LIST_INIT(listener->keys);
		ISC_LIST_INIT(listener->connections);

		/*
		 * Make the acl.
		 */
		if (control != NULL && type == isc_sockettype_tcp) {
			allow = cfg_tuple_get(control, "allow");
			result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
						    aclconfctx, mctx, 0,
						    &new_acl);
		} else {
			result = dns_acl_any(mctx, &new_acl);
		}
	}

	if (result == ISC_R_SUCCESS) {
		dns_acl_attach(new_acl, &listener->acl);
		dns_acl_detach(&new_acl);

		if (config != NULL)
			get_key_info(config, control, &global_keylist,
				     &control_keylist);

		if (control_keylist != NULL) {
			result = controlkeylist_fromcfg(control_keylist,
							listener->mctx,
							&listener->keys);
			if (result == ISC_R_SUCCESS)
				register_keys(control, global_keylist,
					      &listener->keys,
					      listener->mctx, socktext);
		} else
			result = get_rndckey(mctx, &listener->keys);

		if (result != ISC_R_SUCCESS && control != NULL)
			cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
				    "couldn't install keys for "
				    "command channel %s: %s",
				    socktext, isc_result_totext(result));
	}

	if (result == ISC_R_SUCCESS) {
		int pf = isc_sockaddr_pf(&listener->address);
		if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
#ifdef ISC_PLATFORM_HAVESYSUNH
		    (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) ||
#endif
		    (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
			result = ISC_R_FAMILYNOSUPPORT;
	}

	if (result == ISC_R_SUCCESS && type == isc_sockettype_unix)
		isc_socket_cleanunix(&listener->address, ISC_FALSE);

	if (result == ISC_R_SUCCESS)
		result = isc_socket_create(ns_g_socketmgr,
					   isc_sockaddr_pf(&listener->address),
					   type, &listener->sock);
	if (result == ISC_R_SUCCESS)
		isc_socket_setname(listener->sock, "control", NULL);

#ifndef ISC_ALLOW_MAPPED
	if (result == ISC_R_SUCCESS)
		isc_socket_ipv6only(listener->sock, ISC_TRUE);
#endif

	if (result == ISC_R_SUCCESS)
		result = isc_socket_bind(listener->sock, &listener->address,
					 ISC_SOCKET_REUSEADDRESS);

	if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
		listener->perm = cfg_obj_asuint32(cfg_tuple_get(control,
								"perm"));
		listener->owner = cfg_obj_asuint32(cfg_tuple_get(control,
								 "owner"));
		listener->group = cfg_obj_asuint32(cfg_tuple_get(control,
								 "group"));
		result = isc_socket_permunix(&listener->address, listener->perm,
					     listener->owner, listener->group);
	}
	if (result == ISC_R_SUCCESS)
		result = control_listen(listener);

	if (result == ISC_R_SUCCESS)
		result = control_accept(listener);

	if (result == ISC_R_SUCCESS) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
			      "command channel listening on %s", socktext);
		*listenerp = listener;

	} else {
		if (listener != NULL) {
			listener->exiting = ISC_TRUE;
			free_listener(listener);
		}

		if (control != NULL)
			cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
				    "couldn't add command channel %s: %s",
				    socktext, isc_result_totext(result));
		else
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
				      "couldn't add command channel %s: %s",
				      socktext, isc_result_totext(result));

		*listenerp = NULL;
	}

	/* XXXDCL return error results? fail hard? */
}
Example #5
0
static void
buildquery(void) {
	isc_result_t result;
	dns_rdataset_t *question = NULL;
	dns_name_t *qname = NULL;
	isc_region_t r, inr;
	dns_message_t *query;
	char nametext[] = "host.example";
	isc_buffer_t namesrc, namedst;
	unsigned char namedata[256];
	isc_sockaddr_t sa;
	dns_compress_t cctx;

	query = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
	CHECK("dns_message_create", result);
	result = dns_message_setsig0key(query, key);
	CHECK("dns_message_setsig0key", result);

	result = dns_message_gettemprdataset(query, &question);
	CHECK("dns_message_gettemprdataset", result);
	dns_rdataset_init(question);
	dns_rdataset_makequestion(question, dns_rdataclass_in,
				  dns_rdatatype_a);
	result = dns_message_gettempname(query, &qname);
	CHECK("dns_message_gettempname", result);
	isc_buffer_init(&namesrc, nametext, strlen(nametext));
	isc_buffer_add(&namesrc, strlen(nametext));
	isc_buffer_init(&namedst, namedata, sizeof(namedata));
	dns_name_init(qname, NULL);
	result = dns_name_fromtext(qname, &namesrc, dns_rootname, ISC_FALSE,
				   &namedst);
	CHECK("dns_name_fromtext", result);
	ISC_LIST_APPEND(qname->list, question, link);
	dns_message_addname(query, qname, DNS_SECTION_QUESTION);

	isc_buffer_init(&qbuffer, qdata, sizeof(qdata));

	result = dns_compress_init(&cctx, -1, mctx);
	CHECK("dns_compress_init", result);
	result = dns_message_renderbegin(query, &cctx, &qbuffer);
	CHECK("dns_message_renderbegin", result);
	result = dns_message_rendersection(query, DNS_SECTION_QUESTION, 0);
	CHECK("dns_message_rendersection(question)", result);
	result = dns_message_rendersection(query, DNS_SECTION_ANSWER, 0);
	CHECK("dns_message_rendersection(answer)", result);
	result = dns_message_rendersection(query, DNS_SECTION_AUTHORITY, 0);
	CHECK("dns_message_rendersection(auth)", result);
	result = dns_message_rendersection(query, DNS_SECTION_ADDITIONAL, 0);
	CHECK("dns_message_rendersection(add)", result);
	result = dns_message_renderend(query);
	CHECK("dns_message_renderend", result);
	dns_compress_invalidate(&cctx);

	isc_buffer_init(&outbuf, output, sizeof(output));
	result = dns_message_totext(query, style, 0, &outbuf);
	CHECK("dns_message_totext", result);
	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
	       (char *)isc_buffer_base(&outbuf));

	isc_buffer_usedregion(&qbuffer, &r);
	isc_sockaddr_any(&sa);
	result = isc_socket_bind(s, &sa);
	CHECK("isc_socket_bind", result);
	result = isc_socket_sendto(s, &r, task1, senddone, NULL, &address,
				   NULL);
	CHECK("isc_socket_sendto", result);

	inr.base = rdata;
	inr.length = sizeof(rdata);
	result = isc_socket_recv(s, &inr, 1, task1, recvdone, NULL);
	CHECK("isc_socket_recv", result);
	dns_message_destroy(&query);
}
Example #6
0
int
main(int argc, char *argv[]) {
	isc_task_t *t1, *t2;
	isc_timermgr_t *timgr;
	isc_time_t expires;
	isc_interval_t interval;
	isc_timer_t *ti1;
	unsigned int workers;
	isc_socketmgr_t *socketmgr;
	isc_socket_t *so1, *so2;
	isc_sockaddr_t sockaddr;
	struct in_addr ina;
	struct in6_addr in6a;
	isc_result_t result;
	int pf;

	if (argc > 1)
		workers = atoi(argv[1]);
	else
		workers = 2;
	printf("%d workers\n", workers);

	if (isc_net_probeipv6() == ISC_R_SUCCESS)
		pf = PF_INET6;
	else
		pf = PF_INET;

	/*
	 * EVERYTHING needs a memory context.
	 */
	mctx = NULL;
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);

	/*
	 * The task manager is independent (other than memory context)
	 */
	manager = NULL;
	RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &manager) ==
		      ISC_R_SUCCESS);

	/*
	 * Timer manager depends only on the memory context as well.
	 */
	timgr = NULL;
	RUNTIME_CHECK(isc_timermgr_create(mctx, &timgr) == ISC_R_SUCCESS);

	t1 = NULL;
	RUNTIME_CHECK(isc_task_create(manager, 0, &t1) == ISC_R_SUCCESS);
	t2 = NULL;
	RUNTIME_CHECK(isc_task_create(manager, 0, &t2) == ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_task_onshutdown(t1, my_shutdown, "1") ==
		      ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_task_onshutdown(t2, my_shutdown, "2") ==
		      ISC_R_SUCCESS);

	printf("task 1 = %p\n", t1);
	printf("task 2 = %p\n", t2);

	socketmgr = NULL;
	RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);

	/*
	 * Open up a listener socket.
	 */
	so1 = NULL;

	if (pf == PF_INET6) {
		in6a = in6addr_any;
		isc_sockaddr_fromin6(&sockaddr, &in6a, 5544);
	} else {
		ina.s_addr = INADDR_ANY;
		isc_sockaddr_fromin(&sockaddr, &ina, 5544);
	}
	RUNTIME_CHECK(isc_socket_create(socketmgr, pf, isc_sockettype_tcp,
					&so1) == ISC_R_SUCCESS);
	result = isc_socket_bind(so1, &sockaddr, ISC_SOCKET_REUSEADDRESS);
	RUNTIME_CHECK(result == ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_socket_listen(so1, 0) == ISC_R_SUCCESS);

	/*
	 * Queue up the first accept event.
	 */
	RUNTIME_CHECK(isc_socket_accept(so1, t1, my_listen, "so1")
		      == ISC_R_SUCCESS);
	isc_time_settoepoch(&expires);
	isc_interval_set(&interval, 10, 0);
	ti1 = NULL;
	RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, &expires,
				       &interval, t1, timeout, so1, &ti1) ==
		      ISC_R_SUCCESS);

	/*
	 * Open up a socket that will connect to www.flame.org, port 80.
	 * Why not.  :)
	 */
	so2 = NULL;
	ina.s_addr = inet_addr("204.152.184.97");
	if (0 && pf == PF_INET6)
		isc_sockaddr_v6fromin(&sockaddr, &ina, 80);
	else
		isc_sockaddr_fromin(&sockaddr, &ina, 80);
	RUNTIME_CHECK(isc_socket_create(socketmgr, isc_sockaddr_pf(&sockaddr),
					isc_sockettype_tcp,
					&so2) == ISC_R_SUCCESS);

	RUNTIME_CHECK(isc_socket_connect(so2, &sockaddr, t2,
					 my_connect, "so2") == ISC_R_SUCCESS);

	/*
	 * Detaching these is safe, since the socket will attach to the
	 * task for any outstanding requests.
	 */
	isc_task_detach(&t1);
	isc_task_detach(&t2);

	/*
	 * Wait a short while.
	 */
	sleep(10);

	fprintf(stderr, "Destroying socket manager\n");
	isc_socketmgr_destroy(&socketmgr);

	fprintf(stderr, "Destroying timer manager\n");
	isc_timermgr_destroy(&timgr);

	fprintf(stderr, "Destroying task manager\n");
	isc_taskmgr_destroy(&manager);

	isc_mem_stats(mctx, stdout);
	isc_mem_destroy(&mctx);

	return (0);
}
Example #7
0
static isc_result_t
add_listener(ns_server_t *server, ns_statschannel_t **listenerp,
	     const cfg_obj_t *listen_params, const cfg_obj_t *config,
	     isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
	     const char *socktext)
{
	isc_result_t result;
	ns_statschannel_t *listener;
	isc_task_t *task = NULL;
	isc_socket_t *sock = NULL;
	const cfg_obj_t *allow;
	dns_acl_t *new_acl = NULL;

	listener = isc_mem_get(server->mctx, sizeof(*listener));
	if (listener == NULL)
		return (ISC_R_NOMEMORY);

	listener->httpdmgr = NULL;
	listener->address = *addr;
	listener->acl = NULL;
	listener->mctx = NULL;
	ISC_LINK_INIT(listener, link);

	result = isc_mutex_init(&listener->lock);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(server->mctx, listener, sizeof(*listener));
		return (ISC_R_FAILURE);
	}

	isc_mem_attach(server->mctx, &listener->mctx);

	allow = cfg_tuple_get(listen_params, "allow");
	if (allow != NULL && cfg_obj_islist(allow)) {
		result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
					    aclconfctx, listener->mctx, 0,
					    &new_acl);
	} else
		result = dns_acl_any(listener->mctx, &new_acl);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	dns_acl_attach(new_acl, &listener->acl);
	dns_acl_detach(&new_acl);

	result = isc_task_create(ns_g_taskmgr, 0, &task);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	isc_task_setname(task, "statchannel", NULL);

	result = isc_socket_create(ns_g_socketmgr, isc_sockaddr_pf(addr),
				   isc_sockettype_tcp, &sock);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	isc_socket_setname(sock, "statchannel", NULL);

#ifndef ISC_ALLOW_MAPPED
	isc_socket_ipv6only(sock, ISC_TRUE);
#endif

	result = isc_socket_bind(sock, addr, ISC_SOCKET_REUSEADDRESS);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	result = isc_httpdmgr_create(server->mctx, sock, task, client_ok,
				     destroy_listener, listener, ns_g_timermgr,
				     &listener->httpdmgr);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

#ifdef HAVE_LIBXML2
	isc_httpdmgr_addurl(listener->httpdmgr, "/", render_index, server);
#endif
	isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.xsl", render_xsl,
			    server);

	*listenerp = listener;
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
		      NS_LOGMODULE_SERVER, ISC_LOG_NOTICE,
		      "statistics channel listening on %s", socktext);

cleanup:
	if (result != ISC_R_SUCCESS) {
		if (listener->acl != NULL)
			dns_acl_detach(&listener->acl);
		DESTROYLOCK(&listener->lock);
		isc_mem_putanddetach(&listener->mctx, listener,
				     sizeof(*listener));
	}
	if (task != NULL)
		isc_task_detach(&task);
	if (sock != NULL)
		isc_socket_detach(&sock);

	return (result);
}
Example #8
0
ATF_TC_BODY(udp_sendto, tc) {
	isc_result_t result;
	isc_sockaddr_t addr1, addr2;
	struct in_addr in;
	isc_socket_t *s1 = NULL, *s2 = NULL;
	isc_task_t *task = NULL;
	char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
	completion_t completion;
	isc_region_t r;

	UNUSED(tc);

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

	/*
	 * Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to
	 * each other.
	 */
	in.s_addr = inet_addr("127.0.0.1");
	isc_sockaddr_fromin(&addr1, &in, 5444);
	isc_sockaddr_fromin(&addr2, &in, 5445);

	result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	result = isc_task_create(taskmgr, 0, &task);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	strcpy(sendbuf, "Hello");
	r.base = (void *) sendbuf;
	r.length = strlen(sendbuf) + 1;

	completion_init(&completion);
	result = isc_socket_sendto(s1, &r, task, event_done, &completion,
				   &addr2, NULL);
	ATF_CHECK_EQ(result, ISC_R_SUCCESS);
	waitfor(&completion);
	ATF_CHECK(completion.done);
	ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);

	r.base = (void *) recvbuf;
	r.length = BUFSIZ;
	completion_init(&completion);
	result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
	ATF_CHECK_EQ(result, ISC_R_SUCCESS);
	waitfor(&completion);
	ATF_CHECK(completion.done);
	ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
	ATF_CHECK_STREQ(recvbuf, "Hello");

	isc_task_detach(&task);

	isc_socket_detach(&s1);
	isc_socket_detach(&s2);

	isc_test_end();
}