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