1 /* $NetBSD: socket_api.c,v 1.10 2014/12/10 04:37:59 christos Exp $ */
2
3 /*
4 * Copyright (C) 2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /* Id */
20
21 #include <config.h>
22
23 #include <isc/app.h>
24 #include <isc/magic.h>
25 #include <isc/mutex.h>
26 #include <isc/once.h>
27 #include <isc/socket.h>
28 #include <isc/util.h>
29
30 static isc_mutex_t createlock;
31 static isc_once_t once = ISC_ONCE_INIT;
32 static isc_socketmgrcreatefunc_t socketmgr_createfunc = NULL;
33
34 static void
initialize(void)35 initialize(void) {
36 RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
37 }
38
39 isc_result_t
isc_socket_register(isc_socketmgrcreatefunc_t createfunc)40 isc_socket_register(isc_socketmgrcreatefunc_t createfunc) {
41 isc_result_t result = ISC_R_SUCCESS;
42
43 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
44
45 LOCK(&createlock);
46 if (socketmgr_createfunc == NULL)
47 socketmgr_createfunc = createfunc;
48 else
49 result = ISC_R_EXISTS;
50 UNLOCK(&createlock);
51
52 return (result);
53 }
54
55 isc_result_t
isc_socketmgr_createinctx(isc_mem_t * mctx,isc_appctx_t * actx,isc_socketmgr_t ** managerp)56 isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
57 isc_socketmgr_t **managerp)
58 {
59 isc_result_t result;
60
61 LOCK(&createlock);
62
63 REQUIRE(socketmgr_createfunc != NULL);
64 result = (*socketmgr_createfunc)(mctx, managerp);
65
66 UNLOCK(&createlock);
67
68 if (result == ISC_R_SUCCESS)
69 isc_appctx_setsocketmgr(actx, *managerp);
70
71 return (result);
72 }
73
74 isc_result_t
isc_socketmgr_create(isc_mem_t * mctx,isc_socketmgr_t ** managerp)75 isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
76 isc_result_t result;
77
78 if (isc_bind9)
79 return (isc__socketmgr_create(mctx, managerp));
80
81 LOCK(&createlock);
82
83 REQUIRE(socketmgr_createfunc != NULL);
84 result = (*socketmgr_createfunc)(mctx, managerp);
85
86 UNLOCK(&createlock);
87
88 return (result);
89 }
90
91 void
isc_socketmgr_destroy(isc_socketmgr_t ** managerp)92 isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
93 REQUIRE(managerp != NULL && ISCAPI_SOCKETMGR_VALID(*managerp));
94
95 if (isc_bind9)
96 isc__socketmgr_destroy(managerp);
97 else
98 (*managerp)->methods->destroy(managerp);
99
100 ENSURE(*managerp == NULL);
101 }
102
103 isc_result_t
isc_socket_create(isc_socketmgr_t * manager,int pf,isc_sockettype_t type,isc_socket_t ** socketp)104 isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
105 isc_socket_t **socketp)
106 {
107 REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
108
109 if (isc_bind9)
110 return (isc__socket_create(manager, pf, type, socketp));
111
112 return (manager->methods->socketcreate(manager, pf, type, socketp));
113 }
114
115 void
isc_socket_attach(isc_socket_t * sock,isc_socket_t ** socketp)116 isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
117 REQUIRE(ISCAPI_SOCKET_VALID(sock));
118 REQUIRE(socketp != NULL && *socketp == NULL);
119
120 if (isc_bind9)
121 isc__socket_attach(sock, socketp);
122 else
123 sock->methods->attach(sock, socketp);
124
125 ENSURE(*socketp == sock);
126 }
127
128 void
isc_socket_detach(isc_socket_t ** socketp)129 isc_socket_detach(isc_socket_t **socketp) {
130 REQUIRE(socketp != NULL && ISCAPI_SOCKET_VALID(*socketp));
131
132 if (isc_bind9)
133 isc__socket_detach(socketp);
134 else
135 (*socketp)->methods->detach(socketp);
136
137 ENSURE(*socketp == NULL);
138 }
139
140 isc_result_t
isc_socket_bind(isc_socket_t * sock,isc_sockaddr_t * sockaddr,unsigned int options)141 isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
142 unsigned int options)
143 {
144 REQUIRE(ISCAPI_SOCKET_VALID(sock));
145
146 if (isc_bind9)
147 return (isc__socket_bind(sock, sockaddr, options));
148
149 return (sock->methods->bind(sock, sockaddr, options));
150 }
151
152 isc_result_t
isc_socket_sendto(isc_socket_t * sock,isc_region_t * region,isc_task_t * task,isc_taskaction_t action,void * arg,isc_sockaddr_t * address,struct in6_pktinfo * pktinfo)153 isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
154 isc_taskaction_t action, void *arg,
155 isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
156 {
157 REQUIRE(ISCAPI_SOCKET_VALID(sock));
158
159 if (isc_bind9)
160 return (isc__socket_sendto(sock, region, task,
161 action, arg, address, pktinfo));
162
163 return (sock->methods->sendto(sock, region, task, action, arg, address,
164 pktinfo));
165 }
166
167 isc_result_t
isc_socket_connect(isc_socket_t * sock,isc_sockaddr_t * addr,isc_task_t * task,isc_taskaction_t action,void * arg)168 isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task,
169 isc_taskaction_t action, void *arg)
170 {
171 REQUIRE(ISCAPI_SOCKET_VALID(sock));
172
173 if (isc_bind9)
174 return (isc__socket_connect(sock, addr, task, action, arg));
175
176 return (sock->methods->connect(sock, addr, task, action, arg));
177 }
178
179 isc_result_t
isc_socket_recv(isc_socket_t * sock,isc_region_t * region,unsigned int minimum,isc_task_t * task,isc_taskaction_t action,void * arg)180 isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
181 isc_task_t *task, isc_taskaction_t action, void *arg)
182 {
183 REQUIRE(ISCAPI_SOCKET_VALID(sock));
184
185 if (isc_bind9)
186 return (isc__socket_recv(sock, region, minimum,
187 task, action, arg));
188
189 return (sock->methods->recv(sock, region, minimum, task, action, arg));
190 }
191
192 void
isc_socket_cancel(isc_socket_t * sock,isc_task_t * task,unsigned int how)193 isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
194 REQUIRE(ISCAPI_SOCKET_VALID(sock));
195
196 if (isc_bind9)
197 isc__socket_cancel(sock, task, how);
198 else
199 sock->methods->cancel(sock, task, how);
200 }
201
202 isc_result_t
isc_socket_getsockname(isc_socket_t * sock,isc_sockaddr_t * addressp)203 isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
204 REQUIRE(ISCAPI_SOCKET_VALID(sock));
205
206 if (isc_bind9)
207 return (isc__socket_getsockname(sock, addressp));
208
209 return (sock->methods->getsockname(sock, addressp));
210 }
211
212 void
isc_socket_ipv6only(isc_socket_t * sock,isc_boolean_t yes)213 isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
214 REQUIRE(ISCAPI_SOCKET_VALID(sock));
215
216 if (isc_bind9)
217 isc__socket_ipv6only(sock, yes);
218 else
219 sock->methods->ipv6only(sock, yes);
220 }
221
222 void
isc_socket_dscp(isc_socket_t * sock,isc_dscp_t dscp)223 isc_socket_dscp(isc_socket_t *sock, isc_dscp_t dscp) {
224 REQUIRE(ISCAPI_SOCKET_VALID(sock));
225
226 sock->methods->dscp(sock, dscp);
227 }
228
229 isc_sockettype_t
isc_socket_gettype(isc_socket_t * sock)230 isc_socket_gettype(isc_socket_t *sock) {
231 REQUIRE(ISCAPI_SOCKET_VALID(sock));
232
233 if (isc_bind9)
234 return (isc__socket_gettype(sock));
235
236 return (sock->methods->gettype(sock));
237 }
238
239 void
isc_socket_setname(isc_socket_t * socket,const char * name,void * tag)240 isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
241 REQUIRE(ISCAPI_SOCKET_VALID(socket));
242
243 UNUSED(socket); /* in case REQUIRE() is empty */
244 UNUSED(name);
245 UNUSED(tag);
246 }
247
248 isc_result_t
isc_socket_fdwatchcreate(isc_socketmgr_t * manager,int fd,int flags,isc_sockfdwatch_t callback,void * cbarg,isc_task_t * task,isc_socket_t ** socketp)249 isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
250 isc_sockfdwatch_t callback, void *cbarg,
251 isc_task_t *task, isc_socket_t **socketp)
252 {
253 REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
254
255 if (isc_bind9)
256 return (isc__socket_fdwatchcreate(manager, fd, flags,
257 callback, cbarg,
258 task, socketp));
259
260 return (manager->methods->fdwatchcreate(manager, fd, flags,
261 callback, cbarg, task,
262 socketp));
263 }
264
265 isc_result_t
isc_socket_fdwatchpoke(isc_socket_t * sock,int flags)266 isc_socket_fdwatchpoke(isc_socket_t *sock, int flags)
267 {
268 REQUIRE(ISCAPI_SOCKET_VALID(sock));
269
270 if (isc_bind9)
271 return (isc__socket_fdwatchpoke(sock, flags));
272
273 return (sock->methods->fdwatchpoke(sock, flags));
274 }
275
276 isc_result_t
isc_socket_dup(isc_socket_t * sock,isc_socket_t ** socketp)277 isc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
278 REQUIRE(ISCAPI_SOCKET_VALID(sock));
279 REQUIRE(socketp != NULL && *socketp == NULL);
280
281 if (isc_bind9)
282 return (isc__socket_dup(sock, socketp));
283
284 return (sock->methods->dup(sock, socketp));
285 }
286
287 int
isc_socket_getfd(isc_socket_t * sock)288 isc_socket_getfd(isc_socket_t *sock) {
289 REQUIRE(ISCAPI_SOCKET_VALID(sock));
290
291 if (isc_bind9)
292 return (isc__socket_getfd(sock));
293
294 return (sock->methods->getfd(sock));
295 }
296
297 isc_result_t
isc_socket_open(isc_socket_t * sock)298 isc_socket_open(isc_socket_t *sock) {
299 return (isc__socket_open(sock));
300 }
301
302 isc_result_t
isc_socket_close(isc_socket_t * sock)303 isc_socket_close(isc_socket_t *sock) {
304 return (isc__socket_close(sock));
305 }
306
307 isc_result_t
isc_socketmgr_create2(isc_mem_t * mctx,isc_socketmgr_t ** managerp,unsigned int maxsocks)308 isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
309 unsigned int maxsocks)
310 {
311 return (isc__socketmgr_create2(mctx, managerp, maxsocks));
312 }
313
314 isc_result_t
isc_socket_recvv(isc_socket_t * sock,isc_bufferlist_t * buflist,unsigned int minimum,isc_task_t * task,isc_taskaction_t action,void * arg)315 isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
316 unsigned int minimum, isc_task_t *task,
317 isc_taskaction_t action, void *arg)
318 {
319 return (isc__socket_recvv(sock, buflist, minimum, task, action, arg));
320 }
321
322 isc_result_t
isc_socket_recv2(isc_socket_t * sock,isc_region_t * region,unsigned int minimum,isc_task_t * task,isc_socketevent_t * event,unsigned int flags)323 isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
324 unsigned int minimum, isc_task_t *task,
325 isc_socketevent_t *event, unsigned int flags)
326 {
327 return (isc__socket_recv2(sock, region, minimum, task, event, flags));
328 }
329
330 isc_result_t
isc_socket_send(isc_socket_t * sock,isc_region_t * region,isc_task_t * task,isc_taskaction_t action,void * arg)331 isc_socket_send(isc_socket_t *sock, isc_region_t *region,
332 isc_task_t *task, isc_taskaction_t action, void *arg)
333 {
334 return (isc__socket_send(sock, region, task, action, arg));
335 }
336
337 isc_result_t
isc_socket_sendv(isc_socket_t * sock,isc_bufferlist_t * buflist,isc_task_t * task,isc_taskaction_t action,void * arg)338 isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
339 isc_task_t *task, isc_taskaction_t action, void *arg)
340 {
341 return (isc__socket_sendv(sock, buflist, task, action, arg));
342 }
343
344 isc_result_t
isc_socket_sendtov(isc_socket_t * sock,isc_bufferlist_t * buflist,isc_task_t * task,isc_taskaction_t action,void * arg,isc_sockaddr_t * address,struct in6_pktinfo * pktinfo)345 isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
346 isc_task_t *task, isc_taskaction_t action, void *arg,
347 isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
348 {
349 return (isc__socket_sendtov(sock, buflist, task, action, arg,
350 address, pktinfo));
351 }
352
353 isc_result_t
isc_socket_sendtov2(isc_socket_t * sock,isc_bufferlist_t * buflist,isc_task_t * task,isc_taskaction_t action,void * arg,isc_sockaddr_t * address,struct in6_pktinfo * pktinfo,unsigned int flags)354 isc_socket_sendtov2(isc_socket_t *sock, isc_bufferlist_t *buflist,
355 isc_task_t *task, isc_taskaction_t action, void *arg,
356 isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
357 unsigned int flags)
358 {
359 return (isc__socket_sendtov2(sock, buflist, task, action, arg,
360 address, pktinfo, flags));
361 }
362
363 isc_result_t
isc_socket_sendto2(isc_socket_t * sock,isc_region_t * region,isc_task_t * task,isc_sockaddr_t * address,struct in6_pktinfo * pktinfo,isc_socketevent_t * event,unsigned int flags)364 isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
365 isc_task_t *task,
366 isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
367 isc_socketevent_t *event, unsigned int flags)
368 {
369 return (isc__socket_sendto2(sock, region, task, address, pktinfo,
370 event, flags));
371 }
372
373 void
isc_socket_cleanunix(isc_sockaddr_t * sockaddr,isc_boolean_t active)374 isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) {
375 isc__socket_cleanunix(sockaddr, active);
376 }
377
378 isc_result_t
isc_socket_permunix(isc_sockaddr_t * sockaddr,isc_uint32_t perm,isc_uint32_t owner,isc_uint32_t group)379 isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
380 isc_uint32_t owner, isc_uint32_t group)
381 {
382 return (isc__socket_permunix(sockaddr, perm, owner, group));
383 }
384
385 isc_result_t
isc_socket_filter(isc_socket_t * sock,const char * filter)386 isc_socket_filter(isc_socket_t *sock, const char *filter) {
387 return (isc__socket_filter(sock, filter));
388 }
389
390 isc_result_t
isc_socket_listen(isc_socket_t * sock,unsigned int backlog)391 isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
392 return (isc__socket_listen(sock, backlog));
393 }
394
395 isc_result_t
isc_socket_accept(isc_socket_t * sock,isc_task_t * task,isc_taskaction_t action,void * arg)396 isc_socket_accept(isc_socket_t *sock, isc_task_t *task,
397 isc_taskaction_t action, void *arg)
398 {
399 return (isc__socket_accept(sock, task, action, arg));
400 }
401
402 isc_result_t
isc_socket_getpeername(isc_socket_t * sock,isc_sockaddr_t * addressp)403 isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
404 return (isc__socket_getpeername(sock, addressp));
405 }
406