1275970Scy/*
2275970Scy * Copyright (C) 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
3275970Scy *
4275970Scy * Permission to use, copy, modify, and/or distribute this software for any
5275970Scy * purpose with or without fee is hereby granted, provided that the above
6275970Scy * copyright notice and this permission notice appear in all copies.
7275970Scy *
8275970Scy * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9275970Scy * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10275970Scy * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11275970Scy * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12275970Scy * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13275970Scy * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14275970Scy * PERFORMANCE OF THIS SOFTWARE.
15275970Scy */
16275970Scy
17275970Scy/* $Id$ */
18275970Scy
19275970Scy#include <config.h>
20275970Scy
21275970Scy#include <isc/app.h>
22275970Scy#include <isc/magic.h>
23275970Scy#include <isc/mutex.h>
24275970Scy#include <isc/once.h>
25275970Scy#include <isc/socket.h>
26275970Scy#include <isc/util.h>
27275970Scy
28275970Scystatic isc_mutex_t createlock;
29275970Scystatic isc_once_t once = ISC_ONCE_INIT;
30275970Scystatic isc_socketmgrcreatefunc_t socketmgr_createfunc = NULL;
31275970Scy
32275970Scystatic void
33275970Scyinitialize(void) {
34275970Scy	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
35275970Scy}
36275970Scy
37275970Scyisc_result_t
38275970Scyisc_socket_register(isc_socketmgrcreatefunc_t createfunc) {
39275970Scy	isc_result_t result = ISC_R_SUCCESS;
40275970Scy
41275970Scy	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
42275970Scy
43275970Scy	LOCK(&createlock);
44275970Scy	if (socketmgr_createfunc == NULL)
45275970Scy		socketmgr_createfunc = createfunc;
46275970Scy	else
47275970Scy		result = ISC_R_EXISTS;
48275970Scy	UNLOCK(&createlock);
49275970Scy
50275970Scy	return (result);
51275970Scy}
52275970Scy
53275970Scyisc_result_t
54275970Scyisc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
55275970Scy			  isc_socketmgr_t **managerp)
56275970Scy{
57275970Scy	isc_result_t result;
58275970Scy
59275970Scy	LOCK(&createlock);
60275970Scy
61275970Scy	REQUIRE(socketmgr_createfunc != NULL);
62275970Scy	result = (*socketmgr_createfunc)(mctx, managerp);
63275970Scy
64275970Scy	UNLOCK(&createlock);
65275970Scy
66275970Scy	if (result == ISC_R_SUCCESS)
67275970Scy		isc_appctx_setsocketmgr(actx, *managerp);
68275970Scy
69275970Scy	return (result);
70275970Scy}
71275970Scy
72275970Scyisc_result_t
73275970Scyisc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
74275970Scy	isc_result_t result;
75275970Scy
76275970Scy	LOCK(&createlock);
77275970Scy
78275970Scy	REQUIRE(socketmgr_createfunc != NULL);
79275970Scy	result = (*socketmgr_createfunc)(mctx, managerp);
80275970Scy
81275970Scy	UNLOCK(&createlock);
82275970Scy
83275970Scy	return (result);
84275970Scy}
85275970Scy
86275970Scyvoid
87275970Scyisc_socketmgr_destroy(isc_socketmgr_t **managerp) {
88275970Scy	REQUIRE(managerp != NULL && ISCAPI_SOCKETMGR_VALID(*managerp));
89275970Scy
90275970Scy	(*managerp)->methods->destroy(managerp);
91275970Scy
92275970Scy	ENSURE(*managerp == NULL);
93275970Scy}
94275970Scy
95275970Scyisc_result_t
96275970Scyisc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
97275970Scy		  isc_socket_t **socketp)
98275970Scy{
99275970Scy	REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
100275970Scy
101275970Scy	return (manager->methods->socketcreate(manager, pf, type, socketp));
102275970Scy}
103275970Scy
104275970Scyvoid
105275970Scyisc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
106275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
107275970Scy	REQUIRE(socketp != NULL && *socketp == NULL);
108275970Scy
109275970Scy	sock->methods->attach(sock, socketp);
110275970Scy
111275970Scy	ENSURE(*socketp == sock);
112275970Scy}
113275970Scy
114275970Scyvoid
115275970Scyisc_socket_detach(isc_socket_t **socketp) {
116275970Scy	REQUIRE(socketp != NULL && ISCAPI_SOCKET_VALID(*socketp));
117275970Scy
118275970Scy	(*socketp)->methods->detach(socketp);
119275970Scy
120275970Scy	ENSURE(*socketp == NULL);
121275970Scy}
122275970Scy
123275970Scyisc_result_t
124275970Scyisc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
125275970Scy		unsigned int options)
126275970Scy{
127275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
128275970Scy
129275970Scy	return (sock->methods->bind(sock, sockaddr, options));
130275970Scy}
131275970Scy
132275970Scyisc_result_t
133275970Scyisc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
134275970Scy		  isc_taskaction_t action, const void *arg,
135275970Scy		  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
136275970Scy{
137275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
138275970Scy
139275970Scy	return (sock->methods->sendto(sock, region, task, action, arg, address,
140275970Scy				      pktinfo));
141275970Scy}
142275970Scy
143275970Scyisc_result_t
144275970Scyisc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task,
145275970Scy		   isc_taskaction_t action, const void *arg)
146275970Scy{
147275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
148275970Scy
149275970Scy	return (sock->methods->connect(sock, addr, task, action, arg));
150275970Scy}
151275970Scy
152275970Scyisc_result_t
153275970Scyisc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
154275970Scy		isc_task_t *task, isc_taskaction_t action, const void *arg)
155275970Scy{
156275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
157275970Scy
158275970Scy	return (sock->methods->recv(sock, region, minimum, task, action, arg));
159275970Scy}
160275970Scy
161275970Scyvoid
162275970Scyisc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
163275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
164275970Scy
165275970Scy	sock->methods->cancel(sock, task, how);
166275970Scy}
167275970Scy
168275970Scyisc_result_t
169275970Scyisc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
170275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
171275970Scy
172275970Scy	return (sock->methods->getsockname(sock, addressp));
173275970Scy}
174275970Scy
175275970Scyvoid
176275970Scyisc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
177275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
178275970Scy
179275970Scy	sock->methods->ipv6only(sock, yes);
180275970Scy}
181275970Scy
182275970Scyisc_sockettype_t
183275970Scyisc_socket_gettype(isc_socket_t *sock) {
184275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
185275970Scy
186275970Scy	return (sock->methods->gettype(sock));
187275970Scy}
188275970Scy
189275970Scyvoid
190275970Scyisc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
191275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(socket));
192275970Scy
193275970Scy	UNUSED(socket);		/* in case REQUIRE() is empty */
194275970Scy	UNUSED(name);
195275970Scy	UNUSED(tag);
196275970Scy}
197275970Scy
198275970Scyisc_result_t
199275970Scyisc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
200275970Scy			 isc_sockfdwatch_t callback, void *cbarg,
201275970Scy			 isc_task_t *task, isc_socket_t **socketp)
202275970Scy{
203275970Scy	REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
204275970Scy
205275970Scy	return (manager->methods->fdwatchcreate(manager, fd, flags,
206275970Scy						callback, cbarg, task,
207275970Scy						socketp));
208275970Scy}
209275970Scy
210275970Scyisc_result_t
211275970Scyisc_socket_fdwatchpoke(isc_socket_t *sock, int flags)
212275970Scy{
213275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
214275970Scy
215275970Scy	return(sock->methods->fdwatchpoke(sock, flags));
216275970Scy}
217275970Scy
218275970Scyisc_result_t
219275970Scyisc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
220275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
221275970Scy	REQUIRE(socketp != NULL && *socketp == NULL);
222275970Scy
223275970Scy	return(sock->methods->dup(sock, socketp));
224275970Scy}
225275970Scy
226275970Scyint
227275970Scyisc_socket_getfd(isc_socket_t *sock) {
228275970Scy	REQUIRE(ISCAPI_SOCKET_VALID(sock));
229275970Scy
230275970Scy	return(sock->methods->getfd(sock));
231275970Scy}
232