2 * Copyright (c) 2016-2019 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 * Copyright (c) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
18 * Copyright (C) 2006-2014 Stefan Metzmacher <metze@samba.org>
19 * Copyright (C) 2013-2014 Andreas Schneider <asn@samba.org>
21 * All rights reserved.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution.
34 * 3. Neither the name of the author nor the names of its contributors
35 * may be used to endorse or promote products derived from this software
36 * without specific prior written permission.
38 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 Socket wrapper library. Passes all socket communication over
54 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
66 #include <vcl/ldp_socket_wrapper.h>
78 /* Macros for accessing mutexes */
79 #define SWRAP_LOCK(m) do { \
80 pthread_mutex_lock(&(m ## _mutex)); \
83 #define SWRAP_UNLOCK(m) do { \
84 pthread_mutex_unlock(&(m ## _mutex)); \
87 /* Add new global locks here please */
88 #define SWRAP_LOCK_ALL \
89 SWRAP_LOCK(libc_symbol_binding); \
91 #define SWRAP_UNLOCK_ALL \
92 SWRAP_UNLOCK(libc_symbol_binding); \
96 /* The mutex for accessing the global libc.symbols */
97 static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER;
99 /* Function prototypes */
102 #define SWRAP_LOG(...)
104 static unsigned int swrap_log_lvl = SWRAP_LOG_WARN;
107 swrap_log (enum swrap_dbglvl_e dbglvl, const char *func,
108 const char *format, ...)
109 PRINTF_ATTRIBUTE (3, 4);
110 #define SWRAP_LOG(dbglvl, ...) swrap_log((dbglvl), __func__, __VA_ARGS__)
113 swrap_log (enum swrap_dbglvl_e dbglvl,
114 const char *func, const char *format, ...)
119 va_start (va, format);
120 vsnprintf (buffer, sizeof (buffer), format, va);
123 if (dbglvl <= swrap_log_lvl)
127 case SWRAP_LOG_ERROR:
129 "SWRAP_ERROR(%d) - %s: %s\n",
130 (int) getpid (), func, buffer);
134 "SWRAP_WARN(%d) - %s: %s\n",
135 (int) getpid (), func, buffer);
137 case SWRAP_LOG_DEBUG:
139 "SWRAP_DEBUG(%d) - %s: %s\n",
140 (int) getpid (), func, buffer);
142 case SWRAP_LOG_TRACE:
144 "SWRAP_TRACE(%d) - %s: %s\n",
145 (int) getpid (), func, buffer);
153 /*********************************************************
154 * SWRAP LOADING LIBC FUNCTIONS
155 *********************************************************/
157 typedef int (*__libc_accept4) (int sockfd,
158 struct sockaddr * addr,
159 socklen_t * addrlen, int flags);
160 typedef int (*__libc_accept) (int sockfd,
161 struct sockaddr * addr, socklen_t * addrlen);
162 typedef int (*__libc_bind) (int sockfd,
163 const struct sockaddr * addr, socklen_t addrlen);
164 typedef int (*__libc_close) (int fd);
165 typedef int (*__libc_connect) (int sockfd,
166 const struct sockaddr * addr,
170 /* TBD: dup and dup2 to be implemented later */
171 typedef int (*__libc_dup) (int fd);
172 typedef int (*__libc_dup2) (int oldfd, int newfd);
175 typedef int (*__libc_fcntl) (int fd, int cmd, ...);
177 typedef int (*__libc_fcntl64) (int fd, int cmd, ...);
179 typedef FILE *(*__libc_fopen) (const char *name, const char *mode);
181 typedef FILE *(*__libc_fopen64) (const char *name, const char *mode);
184 typedef int (*__libc_eventfd) (int count, int flags);
186 typedef int (*__libc_getpeername) (int sockfd,
187 struct sockaddr * addr,
188 socklen_t * addrlen);
189 typedef int (*__libc_getsockname) (int sockfd,
190 struct sockaddr * addr,
191 socklen_t * addrlen);
192 typedef int (*__libc_getsockopt) (int sockfd,
195 void *optval, socklen_t * optlen);
196 typedef int (*__libc_ioctl) (int d, unsigned long int request, ...);
197 typedef int (*__libc_listen) (int sockfd, int backlog);
198 typedef int (*__libc_open) (const char *pathname, int flags, mode_t mode);
200 typedef int (*__libc_open64) (const char *pathname, int flags, mode_t mode);
201 #endif /* HAVE_OPEN64 */
202 typedef int (*__libc_openat) (int dirfd, const char *path, int flags, ...);
203 typedef int (*__libc_pipe) (int pipefd[2]);
204 typedef int (*__libc_read) (int fd, void *buf, size_t count);
205 typedef ssize_t (*__libc_readv) (int fd, const struct iovec * iov,
207 typedef int (*__libc_recv) (int sockfd, void *buf, size_t len, int flags);
208 typedef int (*__libc_recvfrom) (int sockfd,
212 struct sockaddr * src_addr,
213 socklen_t * addrlen);
214 typedef int (*__libc_recvmsg) (int sockfd, const struct msghdr * msg,
216 typedef int (*__libc_send) (int sockfd, const void *buf, size_t len,
218 typedef ssize_t (*__libc_sendfile) (int out_fd, int in_fd, off_t * offset,
220 typedef int (*__libc_sendmsg) (int sockfd, const struct msghdr * msg,
222 typedef int (*__libc_sendto) (int sockfd, const void *buf, size_t len,
223 int flags, const struct sockaddr * dst_addr,
225 typedef int (*__libc_setsockopt) (int sockfd, int level, int optname,
226 const void *optval, socklen_t optlen);
228 typedef int (*__libc_signalfd) (int fd, const sigset_t * mask, int flags);
230 typedef int (*__libc_socket) (int domain, int type, int protocol);
231 typedef int (*__libc_socketpair) (int domain, int type, int protocol,
233 #ifdef HAVE_TIMERFD_CREATE
234 typedef int (*__libc_timerfd_create) (int clockid, int flags);
236 typedef ssize_t (*__libc_write) (int fd, const void *buf, size_t count);
237 typedef ssize_t (*__libc_writev) (int fd, const struct iovec * iov,
240 typedef int (*__libc_shutdown) (int fd, int how);
242 typedef int (*__libc_select) (int __nfds, fd_set * __restrict __readfds,
243 fd_set * __restrict __writefds,
244 fd_set * __restrict __exceptfds,
245 struct timeval * __restrict __timeout);
248 typedef int (*__libc_pselect) (int __nfds, fd_set * __restrict __readfds,
249 fd_set * __restrict __writefds,
250 fd_set * __restrict __exceptfds,
251 const struct timespec * __restrict __timeout,
252 const __sigset_t * __restrict __sigmask);
255 typedef int (*__libc_epoll_create) (int __size);
257 typedef int (*__libc_epoll_create1) (int __flags);
259 typedef int (*__libc_epoll_ctl) (int __epfd, int __op, int __fd,
260 struct epoll_event * __event);
262 typedef int (*__libc_epoll_wait) (int __epfd, struct epoll_event * __events,
263 int __maxevents, int __timeout);
265 typedef int (*__libc_epoll_pwait) (int __epfd, struct epoll_event * __events,
266 int __maxevents, int __timeout,
267 const __sigset_t * __ss);
269 typedef int (*__libc_poll) (struct pollfd * __fds, nfds_t __nfds,
273 typedef int (*__libc_ppoll) (struct pollfd * __fds, nfds_t __nfds,
274 const struct timespec * __timeout,
275 const __sigset_t * __ss);
279 #define SWRAP_SYMBOL_ENTRY(i) \
285 struct swrap_libc_symbols
287 SWRAP_SYMBOL_ENTRY (accept4);
288 SWRAP_SYMBOL_ENTRY (accept);
289 SWRAP_SYMBOL_ENTRY (bind);
290 SWRAP_SYMBOL_ENTRY (close);
291 SWRAP_SYMBOL_ENTRY (connect);
293 /* TBD: dup and dup2 to be implemented later */
294 SWRAP_SYMBOL_ENTRY (dup);
295 SWRAP_SYMBOL_ENTRY (dup2);
297 SWRAP_SYMBOL_ENTRY (fcntl);
299 SWRAP_SYMBOL_ENTRY (fcntl64);
301 SWRAP_SYMBOL_ENTRY (fopen);
303 SWRAP_SYMBOL_ENTRY (fopen64);
306 SWRAP_SYMBOL_ENTRY (eventfd);
308 SWRAP_SYMBOL_ENTRY (getpeername);
309 SWRAP_SYMBOL_ENTRY (getsockname);
310 SWRAP_SYMBOL_ENTRY (getsockopt);
311 SWRAP_SYMBOL_ENTRY (ioctl);
312 SWRAP_SYMBOL_ENTRY (listen);
313 SWRAP_SYMBOL_ENTRY (open);
315 SWRAP_SYMBOL_ENTRY (open64);
317 SWRAP_SYMBOL_ENTRY (openat);
318 SWRAP_SYMBOL_ENTRY (pipe);
319 SWRAP_SYMBOL_ENTRY (read);
320 SWRAP_SYMBOL_ENTRY (readv);
321 SWRAP_SYMBOL_ENTRY (recv);
322 SWRAP_SYMBOL_ENTRY (recvfrom);
323 SWRAP_SYMBOL_ENTRY (recvmsg);
324 SWRAP_SYMBOL_ENTRY (send);
325 SWRAP_SYMBOL_ENTRY (sendfile);
326 SWRAP_SYMBOL_ENTRY (sendmsg);
327 SWRAP_SYMBOL_ENTRY (sendto);
328 SWRAP_SYMBOL_ENTRY (setsockopt);
330 SWRAP_SYMBOL_ENTRY (signalfd);
332 SWRAP_SYMBOL_ENTRY (socket);
333 SWRAP_SYMBOL_ENTRY (socketpair);
334 #ifdef HAVE_TIMERFD_CREATE
335 SWRAP_SYMBOL_ENTRY (timerfd_create);
337 SWRAP_SYMBOL_ENTRY (write);
338 SWRAP_SYMBOL_ENTRY (writev);
340 SWRAP_SYMBOL_ENTRY (shutdown);
341 SWRAP_SYMBOL_ENTRY (select);
343 SWRAP_SYMBOL_ENTRY (pselect);
345 SWRAP_SYMBOL_ENTRY (epoll_create);
346 SWRAP_SYMBOL_ENTRY (epoll_create1);
347 SWRAP_SYMBOL_ENTRY (epoll_ctl);
348 SWRAP_SYMBOL_ENTRY (epoll_wait);
349 SWRAP_SYMBOL_ENTRY (epoll_pwait);
350 SWRAP_SYMBOL_ENTRY (poll);
352 SWRAP_SYMBOL_ENTRY (ppoll);
362 struct swrap_libc_symbols symbols;
366 static struct swrap swrap;
368 #define LIBC_NAME "libc.so"
377 swrap_str_lib (enum swrap_lib lib)
385 /* Compiler would warn us about unhandled enum value if we get here */
391 swrap_load_lib_handle (enum swrap_lib lib)
393 int flags = RTLD_LAZY;
397 #if defined(RTLD_DEEPBIND) && !defined(CLIB_SANITIZE_ADDR)
398 flags |= RTLD_DEEPBIND;
404 handle = swrap.libc.handle;
408 handle = dlopen (LIBC_SO, flags);
410 swrap.libc.handle = handle;
415 for (i = 10; i >= 0; i--)
417 char soname[256] = { 0 };
419 snprintf (soname, sizeof (soname), "libc.so.%d", i);
420 handle = dlopen (soname, flags);
427 swrap.libc.handle = handle;
434 SWRAP_LOG (SWRAP_LOG_ERROR,
435 "Failed to dlopen library: %s\n", dlerror ());
443 _swrap_bind_symbol (enum swrap_lib lib, const char *fn_name)
448 handle = swrap_load_lib_handle (lib);
450 func = dlsym (handle, fn_name);
453 SWRAP_LOG (SWRAP_LOG_ERROR,
454 "Failed to find %s: %s\n", fn_name, dlerror ());
458 SWRAP_LOG (SWRAP_LOG_TRACE,
459 "Loaded %s from %s", fn_name, swrap_str_lib (lib));
464 #define swrap_bind_symbol_libc(sym_name) \
465 SWRAP_LOCK(libc_symbol_binding); \
466 if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
467 swrap.libc.symbols._libc_##sym_name.obj = \
468 _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
470 SWRAP_UNLOCK(libc_symbol_binding)
475 * Functions especially from libc need to be loaded individually, you can't load
476 * all at once or gdb will segfault at startup. The same applies to valgrind and
477 * has probably something todo with with the linker.
478 * So we need load each function at the point it is called the first time.
481 libc_accept4 (int sockfd,
482 struct sockaddr *addr, socklen_t * addrlen, int flags)
484 swrap_bind_symbol_libc (accept4);
486 return swrap.libc.symbols._libc_accept4.f (sockfd, addr, addrlen, flags);
490 libc_accept (int sockfd, struct sockaddr *addr, socklen_t * addrlen)
492 swrap_bind_symbol_libc (accept);
494 return swrap.libc.symbols._libc_accept.f (sockfd, addr, addrlen);
498 libc_bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
500 swrap_bind_symbol_libc (bind);
502 return swrap.libc.symbols._libc_bind.f (sockfd, addr, addrlen);
508 swrap_bind_symbol_libc (close);
510 return swrap.libc.symbols._libc_close.f (fd);
514 libc_connect (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
516 swrap_bind_symbol_libc (connect);
518 return swrap.libc.symbols._libc_connect.f (sockfd, addr, addrlen);
522 /* TBD: dup and dup2 to be implemented later */
526 swrap_bind_symbol_libc (dup);
528 return swrap.libc.symbols._libc_dup.f (fd);
532 libc_dup2 (int oldfd, int newfd)
534 swrap_bind_symbol_libc (dup2);
536 return swrap.libc.symbols._libc_dup2.f (oldfd, newfd);
542 libc_eventfd (int count, int flags)
544 swrap_bind_symbol_libc (eventfd);
546 return swrap.libc.symbols._libc_eventfd.f (count, flags);
551 libc_vfcntl (int fd, int cmd, va_list ap)
553 swrap_bind_symbol_libc (fcntl);
554 return swrap.libc.symbols._libc_fcntl.f (fd, cmd, va_arg (ap, long int));
559 libc_vfcntl64 (int fd, int cmd, va_list ap)
561 swrap_bind_symbol_libc (fcntl64);
562 return swrap.libc.symbols._libc_fcntl64.f (fd, cmd, va_arg (ap, long int));
567 libc_vioctl (int fd, int cmd, va_list ap)
573 swrap_bind_symbol_libc (ioctl);
575 for (i = 0; i < 4; i++)
577 args[i] = va_arg (ap, long int);
580 rc = swrap.libc.symbols._libc_ioctl.f (fd,
582 args[0], args[1], args[2], args[3]);
588 libc_getpeername (int sockfd, struct sockaddr *addr, socklen_t * addrlen)
590 swrap_bind_symbol_libc (getpeername);
592 return swrap.libc.symbols._libc_getpeername.f (sockfd, addr, addrlen);
596 libc_getsockname (int sockfd, struct sockaddr *addr, socklen_t * addrlen)
598 swrap_bind_symbol_libc (getsockname);
600 return swrap.libc.symbols._libc_getsockname.f (sockfd, addr, addrlen);
604 libc_getsockopt (int sockfd,
605 int level, int optname, void *optval, socklen_t * optlen)
607 swrap_bind_symbol_libc (getsockopt);
609 return swrap.libc.symbols._libc_getsockopt.f (sockfd,
611 optname, optval, optlen);
615 libc_listen (int sockfd, int backlog)
617 swrap_bind_symbol_libc (listen);
619 return swrap.libc.symbols._libc_listen.f (sockfd, backlog);
622 /* TBD: libc_read() should return ssize_t not an int */
624 libc_read (int fd, void *buf, size_t count)
626 swrap_bind_symbol_libc (read);
628 return swrap.libc.symbols._libc_read.f (fd, buf, count);
632 libc_readv (int fd, const struct iovec * iov, int iovcnt)
634 swrap_bind_symbol_libc (readv);
636 return swrap.libc.symbols._libc_readv.f (fd, iov, iovcnt);
640 libc_recv (int sockfd, void *buf, size_t len, int flags)
642 swrap_bind_symbol_libc (recv);
644 return swrap.libc.symbols._libc_recv.f (sockfd, buf, len, flags);
648 libc_recvfrom (int sockfd,
651 int flags, struct sockaddr *src_addr, socklen_t * addrlen)
653 swrap_bind_symbol_libc (recvfrom);
655 return swrap.libc.symbols._libc_recvfrom.f (sockfd,
657 len, flags, src_addr, addrlen);
661 libc_recvmsg (int sockfd, struct msghdr *msg, int flags)
663 swrap_bind_symbol_libc (recvmsg);
665 return swrap.libc.symbols._libc_recvmsg.f (sockfd, msg, flags);
669 libc_send (int sockfd, const void *buf, size_t len, int flags)
671 swrap_bind_symbol_libc (send);
673 return swrap.libc.symbols._libc_send.f (sockfd, buf, len, flags);
677 libc_sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
679 swrap_bind_symbol_libc (sendfile);
681 return swrap.libc.symbols._libc_sendfile.f (out_fd, in_fd, offset, len);
685 libc_sendmsg (int sockfd, const struct msghdr *msg, int flags)
687 swrap_bind_symbol_libc (sendmsg);
689 return swrap.libc.symbols._libc_sendmsg.f (sockfd, msg, flags);
693 libc_sendto (int sockfd,
696 int flags, const struct sockaddr *dst_addr, socklen_t addrlen)
698 swrap_bind_symbol_libc (sendto);
700 return swrap.libc.symbols._libc_sendto.f (sockfd,
702 len, flags, dst_addr, addrlen);
706 libc_setsockopt (int sockfd,
707 int level, int optname, const void *optval, socklen_t optlen)
709 swrap_bind_symbol_libc (setsockopt);
711 return swrap.libc.symbols._libc_setsockopt.f (sockfd,
713 optname, optval, optlen);
717 libc_socket (int domain, int type, int protocol)
719 swrap_bind_symbol_libc (socket);
721 return swrap.libc.symbols._libc_socket.f (domain, type, protocol);
725 libc_socketpair (int domain, int type, int protocol, int sv[2])
727 swrap_bind_symbol_libc (socketpair);
729 return swrap.libc.symbols._libc_socketpair.f (domain, type, protocol, sv);
733 libc_write (int fd, const void *buf, size_t count)
735 swrap_bind_symbol_libc (write);
737 return swrap.libc.symbols._libc_write.f (fd, buf, count);
741 libc_writev (int fd, const struct iovec * iov, int iovcnt)
743 swrap_bind_symbol_libc (writev);
745 return swrap.libc.symbols._libc_writev.f (fd, iov, iovcnt);
749 libc_shutdown (int fd, int how)
751 swrap_bind_symbol_libc (shutdown);
753 return swrap.libc.symbols._libc_shutdown.f (fd, how);
757 libc_select (int __nfds, fd_set * __restrict __readfds,
758 fd_set * __restrict __writefds,
759 fd_set * __restrict __exceptfds,
760 struct timeval *__restrict __timeout)
762 swrap_bind_symbol_libc (select);
764 return swrap.libc.symbols._libc_select.f (__nfds, __readfds,
766 __exceptfds, __timeout);
771 libc_pselect (int __nfds, fd_set * __restrict __readfds,
772 fd_set * __restrict __writefds,
773 fd_set * __restrict __exceptfds,
774 const struct timespec *__restrict __timeout,
775 const __sigset_t * __restrict __sigmask)
777 swrap_bind_symbol_libc (pselect);
779 return swrap.libc.symbols._libc_pselect.f (__nfds, __readfds,
782 __timeout, __sigmask);
787 libc_epoll_create (int __size)
789 swrap_bind_symbol_libc (epoll_create);
791 return swrap.libc.symbols._libc_epoll_create.f (__size);
795 libc_epoll_create1 (int __flags)
797 swrap_bind_symbol_libc (epoll_create1);
799 return swrap.libc.symbols._libc_epoll_create1.f (__flags);
803 libc_epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event)
805 swrap_bind_symbol_libc (epoll_ctl);
807 return swrap.libc.symbols._libc_epoll_ctl.f (__epfd, __op, __fd, __event);
811 libc_epoll_wait (int __epfd, struct epoll_event *__events,
812 int __maxevents, int __timeout)
814 swrap_bind_symbol_libc (epoll_wait);
816 return swrap.libc.symbols._libc_epoll_wait.f (__epfd, __events,
817 __maxevents, __timeout);
821 libc_epoll_pwait (int __epfd, struct epoll_event *__events,
822 int __maxevents, int __timeout, const __sigset_t * __ss)
824 swrap_bind_symbol_libc (epoll_pwait);
826 return swrap.libc.symbols._libc_epoll_pwait.f (__epfd, __events,
827 __maxevents, __timeout,
832 libc_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
834 swrap_bind_symbol_libc (poll);
836 return swrap.libc.symbols._libc_poll.f (__fds, __nfds, __timeout);
841 libc_ppoll (struct pollfd *__fds, nfds_t __nfds,
842 const struct timespec *__timeout, const __sigset_t * __ss)
844 swrap_bind_symbol_libc (ppoll);
846 return swrap.libc.symbols._libc_ppoll.f (__fds, __nfds, __timeout, __ss);
851 swrap_thread_prepare (void)
857 swrap_thread_parent (void)
863 swrap_thread_child (void)
868 /****************************
870 ***************************/
872 swrap_constructor (void)
875 * If we hold a lock and the application forks, then the child
876 * is not able to unlock the mutex and we are in a deadlock.
877 * This should prevent such deadlocks.
879 pthread_atfork (&swrap_thread_prepare,
880 &swrap_thread_parent, &swrap_thread_child);
883 /****************************
885 ***************************/
888 * This function is called when the library is unloaded and makes sure that
889 * sockets get closed and the unix file for the socket are unlinked.
892 swrap_destructor (void)
894 if (swrap.libc.handle != NULL)
896 dlclose (swrap.libc.handle);
898 if (swrap.libc.socket_handle)
900 dlclose (swrap.libc.socket_handle);
905 * fd.io coding-style-patch-verification: ON
908 * eval: (c-set-style "gnu")