2 This software is available to you under a choice of one of two
3 licenses. You may choose to be licensed under the terms of the GNU
4 General Public License (GPL) Version 2, available at
5 <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD
6 license, available in the LICENSE.TXT file accompanying this
7 software. These details are also available at
8 <http://openib.org/license.html>.
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 Copyright (c) 2004 Topspin Communications. All rights reserved.
20 Copyright (c) 2005-2006 Mellanox Technologies Ltd. All rights reserved.
30 #endif /* HAVE_CONFIG_H */
33 /* Our prototypes for ioctl, get*name and accept do not strictly
34 match the headers - we use the following lines to move the header
35 versions 'out of the way' temporarily. */
36 #define ioctl __real_ioctl
37 #define getsockname __real_getsockname
38 #define getpeername __real_getpeername
39 #define accept __real_accept
49 #define _GNU_SOURCE /* define RTLD_NEXT */
51 #include <sys/types.h>
52 #include <sys/socket.h>
53 #include <netinet/tcp.h>
54 #include <arpa/inet.h>
55 #include <netinet/in.h>
58 #include <sys/resource.h>
64 #include <sys/epoll.h>
68 /* We're done protecting ourselves from the header prototypes */
76 * SDP specific includes
80 /* We can not use sizeof(sockaddr_in6) as the extra scope_id field is not a must have */
81 #define IPV6_ADDR_IN_MIN_LEN 24
83 /* setsockopt() level and optname declarations */
85 #define SDP_UNBIND 259 /* Unbind socket */
87 /* Solaris has two entry socket creation functions */
88 #define SOCKET_SEMANTIC_DEFAULT 0
89 #define SOCKET_SEMANTIC_XNET 1
91 /* HACK: filter ioctl errors for FIONREAD */
92 #define FIONREAD 0x541B
94 void __attribute__ ((constructor)) __sdp_init(void);
95 void __attribute__ ((destructor)) __sdp_fini(void);
97 /* --------------------------------------------------------------------- */
98 /* library type definitions. */
99 /* --------------------------------------------------------------------- */
101 typedef int (*ioctl_func_t) (int fd,
107 void *arg4, void *arg5, void *arg6, void *arg7);
109 typedef int (*fcntl_func_t) (int fd, int cmd, ...);
111 typedef int (*socket_func_t) (int domain, int type, int protocol);
113 typedef int (*setsockopt_func_t) (int s,
116 const void *optval, socklen_t optlen);
118 typedef int (*connect_func_t) (int sockfd,
119 const struct sockaddr * serv_addr,
122 typedef int (*listen_func_t) (int s, int backlog);
124 typedef int (*bind_func_t) (int sockfd,
125 const struct sockaddr * my_addr, socklen_t addrlen);
127 typedef int (*close_func_t) (int fd);
129 typedef int (*dup_func_t) (int fd);
131 typedef int (*dup2_func_t) (int oldfd, int newfd);
133 typedef int (*getsockname_func_t) (int fd,
134 struct sockaddr * name, socklen_t * namelen);
136 typedef int (*getpeername_func_t) (int fd,
137 struct sockaddr * name, socklen_t * namelen);
139 typedef int (*accept_func_t) (int fd,
140 struct sockaddr * addr, socklen_t * addrlen);
142 typedef int (*select_func_t) (int n,
145 fd_set * exceptfds, struct timeval * timeout);
147 typedef int (*pselect_func_t) (int n,
151 const struct timespec * timeout,
152 const sigset_t * sigmask);
154 typedef int (*poll_func_t) (struct pollfd * ufds,
155 unsigned long int nfds, int timeout);
158 typedef int (*epoll_create_func_t) (int size);
160 typedef int (*epoll_ctl_func_t) (int epfd,
161 int op, int fd, struct epoll_event * event);
163 typedef int (*epoll_wait_func_t) (int epfd,
164 struct epoll_event * events,
165 int maxevents, int timeout);
167 typedef int (*epoll_pwait_func_t) (int epfd,
168 struct epoll_event * events,
170 int timeout, const sigset_t * sigmask);
174 struct socket_lib_funcs {
177 socket_func_t socket;
178 setsockopt_func_t setsockopt;
179 connect_func_t connect;
180 listen_func_t listen;
185 getpeername_func_t getpeername;
186 getsockname_func_t getsockname;
187 accept_func_t accept;
188 select_func_t select;
189 pselect_func_t pselect;
192 epoll_create_func_t epoll_create;
193 epoll_ctl_func_t epoll_ctl;
194 epoll_wait_func_t epoll_wait;
195 epoll_pwait_func_t epoll_pwait;
197 }; /* socket_lib_funcs */
200 /* Solaris has another interface to socket functions prefixed with __xnet_ */
201 struct socket_lib_xnet_funcs {
202 socket_func_t socket;
203 connect_func_t connect;
204 listen_func_t listen;
209 static int simple_sdp_library;
210 static int max_file_descriptors;
211 static int dev_null_fd;
212 volatile static int init_status = 0; /* 0: idle, 1:during, 2:ready */
214 /* --------------------------------------------------------------------- */
215 /* library static and global variables */
216 /* --------------------------------------------------------------------- */
218 /* glibc provides these symbols - for Solaris builds we fake them
219 * until _init is called, at which point we quiz libdl.. */
221 char *program_invocation_name = "[progname]", *program_invocation_short_name =
224 extern char *program_invocation_name, *program_invocation_short_name;
228 static void *__libc_dl_handle = RTLD_NEXT;
230 static void *__libc_dl_handle;
233 /* extra fd attributes we need for our algorithms */
234 struct sdp_extra_fd_attributes {
235 int shadow_fd; /* file descriptor of shadow sdp socket */
236 short last_accept_was_tcp; /* used by accept to alternate tcp and sdp */
237 short is_sdp; /* 1 if the fd represents an sdp socket */
238 }; /* sdp_extra_fd_attributes */
240 /* stores the extra attributes struct by fd */
241 static struct sdp_extra_fd_attributes *libsdp_fd_attributes;
243 static struct socket_lib_funcs _socket_funcs = {
245 /* Automatically sets all other elements to NULL */
246 }; /* _socket_funcs */
249 static struct socket_lib_xnet_funcs _socket_xnet_funcs = {
251 /* Automatically sets all other elements to NULL */
255 /* --------------------------------------------------------------------- */
257 /* --------------------------------------------------------------------- */
258 void __sdp_init(void);
260 /* --------------------------------------------------------------------- */
262 /* local static functions. */
264 /* --------------------------------------------------------------------- */
266 /* ========================================================================= */
267 /*..init_extra_attribute -- initialize the set of extra attributes for a fd */
268 static void init_extra_attribute(int fd)
270 if ((0 <= fd) && (max_file_descriptors > fd)) {
271 libsdp_fd_attributes[fd].shadow_fd = -1;
272 libsdp_fd_attributes[fd].is_sdp = 0;
273 libsdp_fd_attributes[fd].last_accept_was_tcp = -1;
277 static inline int is_valid_fd(int fd)
279 return (0 <= fd) && (fd < max_file_descriptors);
282 /* ========================================================================= */
283 /*..get_shadow_fd_by_fd -- given an fd return its shadow fd if exists */
284 static inline int get_shadow_fd_by_fd(int fd)
287 return libsdp_fd_attributes[fd].shadow_fd;
292 /* ========================================================================= */
293 /*..set_shadow_for_fd -- */
294 static inline void set_shadow_for_fd(int fd, int shadow_fd)
297 libsdp_fd_attributes[fd].shadow_fd = shadow_fd;
300 /* ========================================================================= */
301 /*..set_is_sdp_socket -- */
302 static inline void set_is_sdp_socket(int fd, short is_sdp)
305 libsdp_fd_attributes[fd].is_sdp = is_sdp;
308 /* ========================================================================= */
309 /*..get_is_sdp_socket -- given an fd return 1 if it is an SDP socket */
310 static inline int get_is_sdp_socket(int fd)
313 return libsdp_fd_attributes[fd].is_sdp;
318 /* ========================================================================= */
319 /*..last_accept_was_tcp -- given an fd return 1 if last accept was tcp */
320 static inline int last_accept_was_tcp(int fd)
323 return libsdp_fd_attributes[fd].last_accept_was_tcp;
328 /* ========================================================================= */
329 /*..set_last_accept -- given an fd set last accept was tcp */
330 static inline void set_last_accept(int fd, int was_tcp)
333 libsdp_fd_attributes[fd].last_accept_was_tcp = was_tcp;
336 /* ========================================================================= */
337 /*..cleanup_shadow -- an error occured on an SDP socket, cleanup */
338 static int cleanup_shadow(int fd)
340 int shadow_fd = get_shadow_fd_by_fd(fd);
344 libsdp_fd_attributes[fd].shadow_fd = -1;
345 libsdp_fd_attributes[fd].last_accept_was_tcp = 0;
346 return (_socket_funcs.close(shadow_fd));
347 } /* cleanup_shadow */
349 /* ========================================================================= */
350 /*..replace_fd_with_its_shadow -- perform all required for such promotion */
351 static int replace_fd_with_its_shadow(int fd)
353 int shadow_fd = libsdp_fd_attributes[fd].shadow_fd;
355 if (shadow_fd == -1) {
356 __sdp_log(9, "Error replace_fd_with_its_shadow: no shadow for fd:%d\n",
361 /* copy the attributes of the shadow before we clean them up */
362 libsdp_fd_attributes[fd] = libsdp_fd_attributes[shadow_fd];
363 libsdp_fd_attributes[fd].shadow_fd = -1;
364 if (_socket_funcs.dup2(shadow_fd, fd) < 0) {
365 init_extra_attribute(fd);
366 _socket_funcs.close(shadow_fd);
369 _socket_funcs.close(shadow_fd);
373 static sa_family_t get_sdp_domain(int domain)
375 if (AF_INET_SDP == domain || AF_INET6_SDP == domain)
378 if (AF_INET == domain)
380 else if (AF_INET6 == domain)
383 __sdp_log(9, "Error %s: unknown TCP domain: %d\n", __func__, domain);
388 static int get_sock_domain(int sd)
390 struct sockaddr_storage tmp_sin;
391 socklen_t tmp_sinlen = sizeof(tmp_sin);
393 if (_socket_funcs.getsockname(sd, (struct sockaddr *) &tmp_sin, &tmp_sinlen) < 0) {
394 __sdp_log(9, "Error %s: getsockname return <%d> for socket\n", __func__, errno);
398 return ((struct sockaddr *)&tmp_sin)->sa_family;
401 /* ========================================================================= */
402 /*..is_filtered_unsuported_sockopt -- return 1 if to filter sockopt failure */
403 static inline int is_filtered_unsuported_sockopt(int level, int optname)
406 * TODO: until we know exactly which unsupported opts are really
407 * a don't care we always pass the error
411 /* these are the SOL_TCP OPTS we should consider filterring */
412 TCP_NODELAY 1 /* Don't delay send to coalesce packets */
413 TCP_MAXSEG 2 /* Set maximum segment size */
414 TCP_CORK 3 /* Control sending of partial frames */
415 TCP_KEEPIDLE 4 /* Start keeplives after this period */
416 TCP_KEEPINTVL 5 /* Interval between keepalives */
417 TCP_KEEPCNT 6 /* Number of keepalives before death */
418 TCP_SYNCNT 7 /* Number of SYN retransmits */
419 TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */
420 TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */
421 TCP_WINDOW_CLAMP 10 /* Bound advertised window */
422 TCP_INFO 11 /* Information about this connection. */
423 TCP_QUICKACK 12 /* Bock/reenable quick ACKs. */
427 /* ========================================================================= */
428 /*..is_invalid_addr -- return 1 if given pointer is not valid */
429 /* NOTE: invalidation of the size is going to happen during actual call */
430 static inline int is_invalid_addr(const void *p)
432 /* HACK: on some systems we can not write to check for pointer validity */
433 size_t ret = fcntl(dev_null_fd, F_GETLK, p);
435 ret = (errno == EFAULT);
440 /* ========================================================================= */
441 /*..get_addr_str -- fill in the given buffer with addr str or return 1 */
442 static int get_addr_str(const struct sockaddr *addr, char *buf, size_t len)
444 const struct sockaddr_in *sin = (struct sockaddr_in *) addr;
445 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
446 char const *conv_res;
448 if (sin->sin_family == AF_INET) {
449 conv_res = inet_ntop(AF_INET, (void *) &(sin->sin_addr), buf, len);
450 } else if (sin6->sin6_family == AF_INET6) {
451 conv_res = inet_ntop(AF_INET6, (void *) &sin6->sin6_addr, buf, len);
453 strncpy(buf, "unknown address family", len);
454 conv_res = (char *) 1;
456 return conv_res == NULL;
459 /* --------------------------------------------------------------------- */
461 /* Socket library function overrides. */
463 /* --------------------------------------------------------------------- */
465 /* ========================================================================= */
466 /*..ioctl -- replacement ioctl call. */
472 void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7)
478 if (init_status == 0)
481 if (NULL == _socket_funcs.ioctl) {
482 __sdp_log(9, "Error ioctl: no implementation for ioctl found\n");
486 shadow_fd = get_shadow_fd_by_fd(fd);
488 __sdp_log(2, "IOCTL: <%s:%d:%d> request <%d>\n",
489 program_invocation_short_name, fd, shadow_fd, request);
491 ret = _socket_funcs.ioctl(fd, request,
492 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
494 /* HACK: avoid failing on FIONREAD error as SDP does not support it at the moment */
495 if ((ret < 0) && get_is_sdp_socket(fd) && (request == FIONREAD)) {
496 __sdp_log(8, "Warning ioctl: "
497 "Ignoring FIONREAD error for SDP socket.\n");
501 /* if shadow and no error on tcp */
502 if ((ret >= 0) && (-1 != shadow_fd)) {
503 sret = _socket_funcs.ioctl(shadow_fd, request,
504 arg0, arg1, arg2, arg3, arg4, arg5, arg6,
506 /* HACK: avoid failing on FIONREAD error as SDP does not support it at the moment */
507 if ((sret < 0) && (request == FIONREAD)) {
508 __sdp_log(8, "Warning ioctl: "
509 "Ignoring FIONREAD error for shadow SDP socket.\n");
514 __sdp_log(9, "Error ioctl: "
515 "<%d> calling ioctl for SDP socket, closing it.\n",
521 __sdp_log(2, "IOCTL: <%s:%d:%d> result <%d:%d>\n",
522 program_invocation_short_name, fd, shadow_fd, ret, sret);
527 /* ========================================================================= */
528 /*..fcntl -- replacement fcntl call. */
529 int fcntl(int fd, int cmd, ...)
539 arg = va_arg(ap, void *);
543 if (init_status == 0)
546 if (NULL == _socket_funcs.fcntl) {
547 __sdp_log(9, "Error fcntl: no implementation for fcntl found\n");
551 shadow_fd = get_shadow_fd_by_fd(fd);
553 __sdp_log(2, "FCNTL: <%s:%d:%d> command <%d> argument <%p>\n",
554 program_invocation_short_name, fd, shadow_fd, cmd, arg);
556 ret = _socket_funcs.fcntl(fd, cmd, arg);
557 if ((ret >= 0) && (-1 != shadow_fd)) {
558 sret = _socket_funcs.fcntl(shadow_fd, cmd, arg);
560 __sdp_log(9, "Error fcntl:"
561 " <%d> calling fcntl(%d, %d, %p) for SDP socket. Closing it.\n",
562 shadow_fd, cmd, arg, errno);
567 __sdp_log(2, "FCNTL: <%s:%d:%d> result <%d:%d>\n",
568 program_invocation_short_name, fd, shadow_fd, ret, sret);
573 /* ========================================================================= */
574 /*..setsockopt -- replacement setsockopt call. */
576 setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
582 if (init_status == 0)
585 if (NULL == _socket_funcs.setsockopt) {
586 __sdp_log(9, "Error setsockopt:"
587 " no implementation for setsockopt found\n");
591 shadow_fd = get_shadow_fd_by_fd(fd);
593 __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> level <%d> name <%d>\n",
594 program_invocation_short_name, fd, shadow_fd, level, optname);
596 if (level == SOL_SOCKET && optname == SO_KEEPALIVE && get_is_sdp_socket(fd)) {
598 __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> substitute level %d\n",
599 program_invocation_short_name, fd, shadow_fd, level);
602 ret = _socket_funcs.setsockopt(fd, level, optname, optval, optlen);
603 if ((ret >= 0) && (shadow_fd != -1)) {
604 if (level == SOL_SOCKET && optname == SO_KEEPALIVE &&
605 get_is_sdp_socket(shadow_fd)) {
607 __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> substitute level %d\n",
608 program_invocation_short_name, fd, shadow_fd, level);
611 sret = _socket_funcs.setsockopt(shadow_fd, level, optname, optval, optlen);
613 __sdp_log(8, "Warning sockopts:"
614 " ignoring error on shadow SDP socket fd:<%d>\n", fd);
616 * HACK: we should allow some errors as some sock opts are unsupported
617 * __sdp_log(9, "Error %d calling setsockopt for SDP socket, closing\n", errno);
618 * cleanup_shadow(fd);
623 /* Due to SDP limited implmentation of sockopts we ignore some errors */
624 if ((ret < 0) && get_is_sdp_socket(fd) &&
625 is_filtered_unsuported_sockopt(level, optname)) {
626 __sdp_log(8, "Warning sockopts: "
627 "ignoring error on non implemented sockopt on SDP socket"
628 " fd:<%d> level:<%d> opt:<%d>\n", fd, level, optval);
632 __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> result <%d:%d>\n",
633 program_invocation_short_name, fd, shadow_fd, ret, sret);
638 /* ========================================================================= */
639 /*..socket -- replacement socket call. */
641 static inline int __create_socket_semantic(int domain,
643 int protocol, int semantics)
647 (semantics == SOCKET_SEMANTIC_XNET) ?
648 _socket_xnet_funcs.socket(domain, type, protocol) :
650 _socket_funcs.socket(domain, type, protocol);
653 /* Contains the main logic for creating shadow SDP sockets */
654 static int __create_socket(int domain, int type, int protocol, int semantics)
658 use_family_t family_by_prog;
661 if (init_status == 0)
664 if (NULL == _socket_funcs.socket) {
665 __sdp_log(9, "Error socket: no implementation for socket found\n");
669 __sdp_log(2, "SOCKET: <%s> domain <%d> type <%d> protocol <%d>\n",
670 program_invocation_short_name, domain, type, protocol);
672 sdp_domain = get_sdp_domain(domain);
673 if (sdp_domain < 0) {
674 errno = EAFNOSUPPORT;
679 /* check to see if we can skip the shadow */
680 if ((AF_INET == domain || AF_INET6 == domain) && (SOCK_STREAM == type))
681 if (simple_sdp_library)
682 family_by_prog = USE_SDP;
684 family_by_prog = __sdp_match_by_program();
685 else if (AF_INET_SDP == domain || AF_INET6_SDP == domain)
686 family_by_prog = USE_SDP;
688 family_by_prog = USE_TCP;
690 if (family_by_prog == USE_TCP) {
691 __sdp_log(1, "SOCKET: making TCP only socket (no shadow)\n");
692 s = __create_socket_semantic(domain, type, protocol, semantics);
693 init_extra_attribute(s);
694 set_is_sdp_socket(s, 0);
698 if (family_by_prog == USE_SDP) {
699 /* HACK: convert the protocol if IPPROTO_IP */
701 protocol = IPPROTO_TCP;
703 __sdp_log(1, "SOCKET: making SDP socket type:%d proto:%d\n",
705 s = __create_socket_semantic(sdp_domain, type, protocol, semantics);
706 init_extra_attribute(s);
707 set_is_sdp_socket(s, 1);
711 /* HACK: if we fail creating the TCP socket should we abort ? */
712 __sdp_log(1, "SOCKET: making TCP socket\n");
713 s = __create_socket_semantic(domain, type, protocol, semantics);
714 init_extra_attribute(s);
715 set_is_sdp_socket(s, 0);
716 if (is_valid_fd(s)) {
717 if (((AF_INET == domain) || (AF_INET6 == domain)) &&
718 (SOCK_STREAM == type)) {
721 protocol = IPPROTO_TCP;
722 __sdp_log(1, "SOCKET: making SDP shadow socket type:%d proto:%d\n",
725 __create_socket_semantic(sdp_domain, type, protocol,
727 if (is_valid_fd(shadow_fd)) {
728 init_extra_attribute(shadow_fd);
729 if (libsdp_fd_attributes[s].shadow_fd != -1) {
730 __sdp_log(8, "Warning socket: "
731 "overriding existing shadow fd:%d for fd:%d\n",
732 libsdp_fd_attributes[s].shadow_fd, s);
734 set_is_sdp_socket(shadow_fd, 1);
735 set_shadow_for_fd(s, shadow_fd);
738 "Error socket: <%d> calling socket for SDP socket\n",
740 /* fail if we did not make the SDP socket */
741 __sdp_log(1, "SOCKET: closing TCP socket:<%d>\n", s);
742 _socket_funcs.close(s);
747 __sdp_log(9, "Error socket: "
748 "ignoring SDP socket since TCP fd:%d out of range\n", s);
752 __sdp_log(2, "SOCKET: <%s:%d:%d>\n",
753 program_invocation_short_name, s, shadow_fd);
758 int socket(int domain, int type, int protocol)
760 return __create_socket(domain, type, protocol, SOCKET_SEMANTIC_DEFAULT);
764 int __xnet_socket(int domain, int type, int protocol)
766 return __create_socket(domain, type, protocol, SOCKET_SEMANTIC_XNET);
770 /* ========================================================================= */
771 /*..get_fd_addr_port_num - obtain the port the fd is attached to */
772 static int get_fd_addr_port_num(int sd)
774 struct sockaddr_storage addr;
776 const struct sockaddr_in *sin;
777 socklen_t addrlen = sizeof(addr);
779 ret = _socket_funcs.getsockname(sd, (struct sockaddr *) &addr, &addrlen);
782 __sdp_log(9, "Error: in get_fd_addr_port_num - Failed to get getsockname\n");
786 /* port num is in same location for IPv4 and IPv6 */
787 sin = (const struct sockaddr_in *) &addr;
788 return ntohs(sin->sin_port);
791 /* ========================================================================= */
792 /*..set_addr_port_num - sets the port in the given address */
793 static int set_addr_port_num(const struct sockaddr *addr, int port)
795 struct sockaddr_in *sin = (struct sockaddr_in *) addr;
797 /* port num is in same location for IPv4 and IPv6 */
798 sin->sin_port = htons(port);
802 /* ========================================================================= */
803 /* perform a bind with the given socket semantics */
805 __bind_semantics(int fd,
806 const struct sockaddr *my_addr,
807 socklen_t addrlen, int semantics)
811 (semantics == SOCKET_SEMANTIC_XNET) ?
812 _socket_xnet_funcs.bind(fd, my_addr, addrlen) :
814 _socket_funcs.bind(fd, my_addr, addrlen);
817 /* ========================================================================= */
818 /*..find_free_port - find same free port on both TCP and SDP */
819 #define MAX_BIND_ANY_PORT_TRIES 20000
821 find_free_port(const struct sockaddr *sin_addr,
822 const socklen_t addrlen,
824 int *sdp_sd, int *tcp_sd, int semantics)
826 static int tcp_turn = 1;
827 int tmp_turn = tcp_turn;
828 int num_of_loops = 0;
831 unsigned int yes = 1;
833 int domain, sdp_domain;
835 __sdp_log(2, "find_free_port: starting search for common free port\n");
837 /* need to obtain the address family from the fd */
838 domain = get_sock_domain(orig_sd);
844 sdp_domain = get_sdp_domain(domain);
845 if (sdp_domain < 0) {
851 __sdp_log(1, "find_free_port: taking loop (%d)\n", ++num_of_loops);
853 __sdp_log(1, "find_free_port: creating the two sockets\n");
854 tmp_sd[0] = _socket_funcs.socket(sdp_domain, SOCK_STREAM, IPPROTO_TCP);
856 __sdp_log(8, "Warning find_free_port: creating first socket failed\n");
860 _socket_funcs.setsockopt(tmp_sd[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
862 tmp_sd[1] = _socket_funcs.socket(domain, SOCK_STREAM, IPPROTO_TCP);
864 __sdp_log(8, "Warning find_free_port: creating second socket failed\n");
865 _socket_funcs.close(tmp_sd[0]);
869 _socket_funcs.setsockopt(tmp_sd[1], SOL_SOCKET, SO_REUSEADDR, &yes,
872 __sdp_log(1, "find_free_port: binding first %s socket\n",
873 tmp_turn ? "tcp" : "sdp");
874 ret = __bind_semantics(tmp_sd[tmp_turn], sin_addr, addrlen, semantics);
877 "Warning find_free_port: binding first socket failed:%s\n",
879 _socket_funcs.close(tmp_sd[0]);
880 _socket_funcs.close(tmp_sd[1]);
884 __sdp_log(1, "find_free_port: listening on first socket\n");
885 ret = _socket_funcs.listen(tmp_sd[tmp_turn], 5);
887 __sdp_log(8, "Warning find_free_port: listening on first socket failed:%s\n",
889 _socket_funcs.close(tmp_sd[0]);
890 _socket_funcs.close(tmp_sd[1]);
894 port = get_fd_addr_port_num(tmp_sd[tmp_turn]);
896 __sdp_log(8, "Warning find_free_port: first socket port:%d < 0\n",
898 _socket_funcs.close(tmp_sd[0]);
899 _socket_funcs.close(tmp_sd[1]);
902 __sdp_log(1, "find_free_port: first socket port:%u\n", port);
904 set_addr_port_num(sin_addr, port);
906 __sdp_log(1, "find_free_port: binding second socket\n");
907 ret = __bind_semantics(tmp_sd[1 - tmp_turn], sin_addr, addrlen, semantics);
909 /* bind() for sdp socket failed. It is acceptable only
910 * if the IP is not part of IB network. */
912 if (errno != EADDRINUSE) {
913 __sdp_log(8, "Warning find_free_port: "
914 "binding second socket failed with %s\n",
920 socklen_t len = sizeof(int);
922 ret = getsockopt(tmp_sd[1 - tmp_turn], SOL_TCP,
923 SDP_LAST_BIND_ERR, &err, &len);
925 __sdp_log(9, "Error %s:getsockopt: %s\n",
926 __func__, strerror(errno));
932 if (-ENOENT == err || -EADDRINUSE != err) {
933 /* bind() failed due to either:
934 * 1. IP is ETH, not IB, so can't bind() to sdp socket.
936 * Continue only with TCP */
939 __sdp_log(1, "find_free_port: %s port %u was busy\n",
940 1 - tmp_turn ? "tcp" : "sdp",
941 ntohs(((const struct sockaddr_in *)sin_addr)->sin_port));
944 /* close the sockets - we will need new ones ... */
946 "find_free_port: closing the two sockets before next loop\n");
947 _socket_funcs.close(tmp_sd[0]);
948 _socket_funcs.close(tmp_sd[1]);
951 /* we always start with tcp so we keep the original setting for now */
952 /* tmp_turn = 1 - tmp_turn; */
955 } while ((port < 0) && (num_of_loops < MAX_BIND_ANY_PORT_TRIES));
963 __sdp_log(2, "find_free_port: return port:<%d>\n", port);
967 _socket_funcs.close(tmp_sd[0]);
968 tmp_sd[0] = -1; /* mark with error */
973 /* ========================================================================= */
974 /*..check_legal_bind - check if given address is okay for both TCP and SDP */
976 check_legal_bind(const struct sockaddr *sin_addr,
977 const socklen_t addrlen,
979 int *sdp_sd, int *tcp_sd, int semantics)
981 unsigned int yes = 1;
984 int domain, sdp_domain;
986 /* need to obtain the address family from the fd */
987 domain = get_sock_domain(orig_sd);
994 sdp_domain = get_sdp_domain(domain);
995 if (sdp_domain < 0) {
1000 __sdp_log(2, "check_legal_bind: binding two temporary sockets\n");
1001 *sdp_sd = _socket_funcs.socket(sdp_domain, SOCK_STREAM, IPPROTO_TCP);
1003 __sdp_log(9, "Error check_legal_bind: " "creating SDP socket failed\n");
1007 __sdp_log(2, "check_legal_bind: reusing <%d> \n", *sdp_sd);
1009 _socket_funcs.setsockopt(*sdp_sd, SOL_SOCKET, SO_REUSEADDR, &yes,
1012 __sdp_log(9, "Error bind: Could not setsockopt sdp_sd\n");
1015 *tcp_sd = _socket_funcs.socket(domain, SOCK_STREAM, IPPROTO_TCP);
1017 __sdp_log(9, "Error check_legal_bind: "
1018 "creating second socket failed:%s\n", strerror(errno));
1019 _socket_funcs.close(*sdp_sd);
1023 __sdp_log(2, "check_legal_bind: reusing <%d> \n", *tcp_sd);
1025 _socket_funcs.setsockopt(*tcp_sd, SOL_SOCKET, SO_REUSEADDR, &yes,
1028 __sdp_log(9, "Error bind: Could not setsockopt tcp_sd\n");
1031 __sdp_log(1, "check_legal_bind: binding SDP socket\n");
1032 ret = __bind_semantics(*sdp_sd, sin_addr, addrlen, semantics);
1034 /* bind() for sdp socket failed. It is acceptable only if
1035 * the IP is not part of IB network. */
1037 socklen_t len = sizeof(int);
1039 if (EADDRINUSE != errno)
1042 if (-1 == getsockopt(*sdp_sd, SOL_TCP, SDP_LAST_BIND_ERR, &err, &len)) {
1043 __sdp_log(9, "Error check_legal_bind:getsockopt: %s\n",
1050 if (-ENOENT != err) {
1051 /* bind() failed due to real error. Can't continue */
1052 __sdp_log(9, "Error check_legal_bind: "
1053 "binding SDP socket failed:%s\n", strerror(errno));
1054 _socket_funcs.close(*sdp_sd);
1055 _socket_funcs.close(*tcp_sd);
1057 /* TCP and SDP without library return EINVAL */
1058 if (errno == EADDRINUSE)
1063 /* IP is ETH, not IB, so can't bind() to sdp socket */
1064 /* Continue only with TCP */
1065 _socket_funcs.close(*sdp_sd);
1069 __sdp_log(1, "check_legal_bind: binding TCP socket\n");
1070 ret = __bind_semantics(*tcp_sd, sin_addr, addrlen, semantics);
1072 __sdp_log(9, "Error check_legal_bind: "
1073 "binding TCP socket failed:%s\n", strerror(errno));
1075 _socket_funcs.close(*sdp_sd);
1076 _socket_funcs.close(*tcp_sd);
1080 __sdp_log(2, "check_legal_bind: result:<%d>\n", ret);
1085 /* ========================================================================= */
1086 /*..close_and_bind - close an open fd and bind another one immediately */
1088 close_and_bind(int old_sd,
1090 const struct sockaddr *addr, socklen_t addrlen, int semantics)
1094 __sdp_log(2, "close_and_bind: closing <%d> binding <%d>\n", old_sd, new_sd);
1095 ret = _socket_funcs.close(old_sd);
1097 __sdp_log(9, "Error bind: Could not close old_sd\n");
1101 ret = __bind_semantics(new_sd, addr, addrlen, semantics);
1103 __sdp_log(9, "Error bind: Could not bind new_sd\n");
1106 __sdp_log(2, "close_and_bind: returning <%d>\n", ret);
1110 /* ========================================================================= */
1111 /*..bind -- replacement bind call. */
1113 As we do not know the role of this socket yet so we cannot choose AF.
1114 We need to be able to handle shadow too.
1115 SDP sockets (may be shadow or not) must be using converted address
1117 Since there is no way to "rebind" a socket we have to avoid "false" bind:
1118 1. When the given address for the bind includes a port we need to
1119 guarantee the port is free on both address families. We do that
1120 by creating temporary sockets and biding them first. Then we close and
1121 re-use the address on the real sockets.
1122 2. When ANY_PORT is requested we need to make sure the port we obtain from
1123 the first address family is also free on the second one. We use temporary
1124 sockets for that task too. We loop several times to find such common
1128 __perform_bind(int fd,
1129 const struct sockaddr *addr, socklen_t addrlen, int semantics)
1132 struct sockaddr_in *sin_addr = (struct sockaddr_in *) addr;
1134 char buf[MAX_ADDR_STR_LEN];
1136 if (init_status == 0)
1139 if (NULL == _socket_funcs.bind) {
1140 __sdp_log(9, "Error bind: no implementation for bind found\n");
1144 shadow_fd = get_shadow_fd_by_fd(fd);
1146 if ((addr == NULL) || is_invalid_addr(addr)) {
1148 __sdp_log(9, "Error bind: illegal address provided\n");
1152 if (get_addr_str(addr, buf, MAX_ADDR_STR_LEN)) {
1153 __sdp_log(9, "Error bind: provided illegal address: %s\n",
1158 __sdp_log(2, "BIND: <%s:%d:%d> type <%d> IP <%s> port <%d>\n",
1159 program_invocation_short_name, fd, shadow_fd,
1160 sin_addr->sin_family, buf, ntohs(sin_addr->sin_port));
1162 if (get_is_sdp_socket(fd)) {
1163 __sdp_log(1, "BIND: binding SDP socket:<%d>\n", fd);
1164 ret = __bind_semantics(fd, addr, addrlen, semantics);
1166 } else if (shadow_fd != -1) {
1168 /* we need to validate the given address or find a common port
1169 * so we use the following tmp address and sockets */
1170 struct sockaddr_storage tmp_addr;
1171 int sdp_sd = -1, tcp_sd = -1, port;
1173 memcpy(&tmp_addr, addr, addrlen);
1175 if (ntohs(sin_addr->sin_port) == 0) {
1176 /* When we get ANY_PORT we need to make sure that both TCP
1177 * and SDP sockets will use the same port */
1179 port = find_free_port(addr, addrlen, fd, &sdp_sd, &tcp_sd, semantics);
1182 __sdp_log(9, "BIND: Failed to find common free port\n");
1183 /* We cannot bind both tcp and sdp on the same port, we will close
1184 * the sdp and continue with tcp only */
1187 /* copy the port to the tmp address */
1188 set_addr_port_num((struct sockaddr *) &tmp_addr, port);
1191 /* have a shadow but requested specific port - check that we
1192 * can actually bind the two addresses and then reuse */
1193 ret = check_legal_bind(addr, addrlen, fd, &sdp_sd, &tcp_sd, semantics);
1195 __sdp_log(9, "Error bind: "
1196 "Provided address can not bind on the two sockets\n");
1200 /* if we fail to find a common port or given address can not be used
1201 * we return error */
1203 /* Temporary sockets already closed by check_legal_bind or
1209 /* close temporary sockets and reuse their address */
1210 /* HACK: close_and_bind might race with other applications. */
1211 /* When the race occur we return EADDRINUSE */
1212 ret = close_and_bind(tcp_sd, fd, (struct sockaddr *) &tmp_addr,
1213 addrlen, semantics);
1215 __sdp_log(9, "Error bind: " "Could not close_and_bind TCP side\n");
1217 _socket_funcs.close(sdp_sd);
1222 ret = close_and_bind(sdp_sd, shadow_fd, (struct sockaddr *) &tmp_addr,
1223 addrlen, semantics);
1227 "Error bind: " "Could not close_and_bind sdp side\n");
1234 /* we can only get here on single TCP socket */
1235 __sdp_log(1, "BIND: binding TCP socket:<%d>\n", fd);
1236 ret = __bind_semantics(fd, addr, addrlen, semantics);
1239 __sdp_log(2, "BIND: <%s:%d:%d> result <%d:%d>\n",
1240 program_invocation_short_name, fd, shadow_fd, ret, sret);
1246 int bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen)
1248 return __perform_bind(fd, my_addr, addrlen, SOCKET_SEMANTIC_DEFAULT);
1251 #ifdef SOLARIS_BUILD
1252 int __xnet_bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen)
1254 return __perform_bind(fd, my_addr, addrlen, SOCKET_SEMANTIC_XNET);
1259 /* ========================================================================= */
1260 /*..connect -- replacement connect call. */
1262 Given the connect address we can take out AF decision
1263 if target AF == both it means SDP and fall back to TCP
1264 if any connect worked we are fine
1267 __connect_semantics(int fd,
1268 const struct sockaddr *serv_addr,
1269 socklen_t addrlen, int semantics)
1272 #ifdef SOLARIS_BUILD
1273 (semantics == SOCKET_SEMANTIC_XNET) ?
1274 _socket_xnet_funcs.connect(fd, serv_addr, addrlen) :
1276 _socket_funcs.connect(fd, serv_addr, addrlen);
1280 __perform_connect(int fd, const struct sockaddr *serv_addr,
1281 socklen_t addrlen, int semantics)
1283 struct sockaddr_in *serv_sin = (struct sockaddr_in *) serv_addr;
1284 char buf[MAX_ADDR_STR_LEN];
1286 int ret = -1, dup_ret;
1287 use_family_t target_family;
1290 if (init_status == 0)
1293 if (NULL == _socket_funcs.connect) {
1294 __sdp_log(9, "Error connect: no implementation for connect found\n");
1298 shadow_fd = get_shadow_fd_by_fd(fd);
1300 if ((serv_addr == NULL) || is_invalid_addr(serv_addr)) {
1302 __sdp_log(9, "Error connect: illegal address provided\n");
1306 if (get_addr_str(serv_addr, buf, MAX_ADDR_STR_LEN)) {
1307 __sdp_log(9, "Error connect: provided illegal address: %s\n",
1309 return EADDRNOTAVAIL;
1312 __sdp_log(2, "CONNECT: <%s:%d:%d> domain <%d> IP <%s> port <%d>\n",
1313 program_invocation_short_name, fd, shadow_fd,
1314 serv_sin->sin_family, buf, ntohs(serv_sin->sin_port));
1317 /* obtain the target address family */
1318 target_family = __sdp_match_connect(serv_addr, addrlen);
1320 /* if we do not have a shadow - just do the work */
1321 if (shadow_fd == -1) {
1322 __sdp_log(1, "CONNECT: connectingthrough %s\n",
1323 get_is_sdp_socket(fd) ? "SDP" : "TCP");
1324 ret = __connect_semantics(fd, serv_addr, addrlen, semantics);
1325 if ((ret == 0) || (errno == EINPROGRESS)) {
1326 __sdp_log(7, "CONNECT: connected SDP fd:%d to:%s port %d\n",
1327 fd, buf, ntohs(serv_sin->sin_port));
1332 if ((target_family == USE_SDP) || (target_family == USE_BOTH)) {
1333 /* NOTE: the entire if sequence is negative logic */
1334 __sdp_log(1, "CONNECT: connecting SDP fd:%d\n", shadow_fd);
1336 /* make the socket blocking on shadow SDP */
1337 fopts = _socket_funcs.fcntl(shadow_fd, F_GETFL);
1338 if ((target_family == USE_BOTH) && (fopts & O_NONBLOCK)) {
1340 "CONNECT: shadow_fd <%d> will be blocking during connect\n",
1342 _socket_funcs.fcntl(shadow_fd, F_SETFL, fopts & (~O_NONBLOCK));
1345 ret = __connect_semantics(shadow_fd, serv_addr, addrlen, semantics);
1346 if ((ret < 0) && (errno != EINPROGRESS)) {
1347 __sdp_log(9, "Error connect: "
1348 "failed for SDP fd:%d with error:%m\n", shadow_fd);
1350 __sdp_log(7, "CONNECT: connected SDP fd:%d to:%s port %d\n",
1351 fd, buf, ntohs(serv_sin->sin_port));
1354 /* restore socket options */
1355 _socket_funcs.fcntl(shadow_fd, F_SETFL, fopts);
1357 /* if target is SDP or we succeeded we need to dup SDP fd into TCP fd */
1358 if ((target_family == USE_SDP) || (ret >= 0)) {
1359 dup_ret = replace_fd_with_its_shadow(fd);
1361 __sdp_log(9, "Error connect: "
1362 "failed to dup2 shadow into orig fd:%d\n", fd);
1365 /* we can skip the TCP option if we are done */
1366 __sdp_log(1, "CONNECT: "
1367 "matched SDP fd:%d so shadow dup into TCP\n", fd);
1373 if ((target_family == USE_TCP) || (target_family == USE_BOTH)) {
1374 __sdp_log(1, "CONNECT: connecting TCP fd:%d\n", fd);
1375 ret = __connect_semantics(fd, serv_addr, addrlen, semantics);
1376 if ((ret < 0) && (errno != EINPROGRESS))
1377 __sdp_log(9, "Error connect: for TCP fd:%d failed with error:%m\n",
1380 __sdp_log(7, "CONNECT: connected TCP fd:%d to:%s port %d\n",
1381 fd, buf, ntohs(serv_sin->sin_port));
1383 if ((target_family == USE_TCP) || (ret >= 0) || (errno == EINPROGRESS)) {
1384 if (cleanup_shadow(fd) < 0)
1386 "Error connect: failed to cleanup shadow for fd:%d\n",
1392 __sdp_log(2, "CONNECT: <%s:%d:%d> result <%d>\n",
1393 program_invocation_short_name, fd, shadow_fd, ret);
1398 int connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen)
1400 return __perform_connect(fd, serv_addr, addrlen, SOCKET_SEMANTIC_DEFAULT);
1403 #if defined( SOLARIS_BUILD )
1404 int __xnet_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen)
1406 return __perform_connect(fd, serv_addr, addrlen, SOCKET_SEMANTIC_XNET);
1410 /* ========================================================================= */
1411 /*..listen -- replacement listen call. */
1413 Now we know our role (passive/server) and our address so we can get AF.
1414 If both we should try listening on both
1417 static inline int __listen_semantics(int fd, int backlog, int semantics)
1420 #ifdef SOLARIS_BUILD
1421 (semantics == SOCKET_SEMANTIC_XNET) ?
1422 _socket_xnet_funcs.listen(fd, backlog) :
1424 _socket_funcs.listen(fd, backlog);
1427 static int __perform_listen(int fd, int backlog, int semantics)
1429 use_family_t target_family;
1431 int ret = 0, sret = 0;
1432 struct sockaddr_storage tmp_sin;
1433 socklen_t tmp_sinlen = sizeof(tmp_sin);
1434 struct sockaddr_in *sin4 = (struct sockaddr_in *) &tmp_sin;
1435 char buf[MAX_ADDR_STR_LEN];
1438 if (init_status == 0)
1441 if (NULL == _socket_funcs.listen) {
1442 __sdp_log(9, "Error listen: no implementation for listen found\n");
1446 shadow_fd = get_shadow_fd_by_fd(fd);
1447 __sdp_log(2, "LISTEN: <%s:%d:%d>\n",
1448 program_invocation_short_name, fd, shadow_fd);
1450 /* if there is no shadow - simply call listen */
1451 if (shadow_fd == -1) {
1452 __sdp_log(1, "LISTEN: calling listen on fd:%d\n", fd);
1453 ret = __listen_semantics(fd, backlog, semantics);
1457 /* we need to obtain the address from the fd */
1458 if (_socket_funcs.getsockname(fd, (struct sockaddr *) &tmp_sin, &tmp_sinlen)
1460 __sdp_log(9, "Error listen: getsockname return <%d> for TCP socket\n",
1462 errno = EADDRNOTAVAIL;
1467 if (get_addr_str((struct sockaddr *) &tmp_sin, buf, MAX_ADDR_STR_LEN)) {
1468 __sdp_log(9, "Error listen: provided illegal address: %s\n",
1472 __sdp_log(2, "LISTEN: <%s:%d:%d> domain <%d> IP <%s> port <%d>\n",
1473 program_invocation_short_name, fd, shadow_fd,
1474 sin4->sin_family, buf, ntohs(sin4->sin_port));
1477 __sdp_match_listen((struct sockaddr *) &tmp_sin, sizeof(tmp_sin));
1480 * in case of an implicit bind and "USE_BOTH" rule we need to first bind the
1481 * two sockets to the same port number
1483 actual_port = ntohs(sin4->sin_port);
1485 /* do we need to implicit bind both */
1486 if ((actual_port == 0) && (target_family == USE_BOTH)) {
1487 int sdp_sd = -1, tcp_sd = -1;
1489 actual_port = find_free_port((struct sockaddr *) &tmp_sin, tmp_sinlen,
1490 fd, &sdp_sd, &tcp_sd, semantics);
1491 if (actual_port < 0) {
1493 __sdp_log(8, "LISTEN: Failed to find common free port. Only TCP will be used.\n");
1494 target_family = USE_TCP;
1496 /* copy the port to the tmp address */
1497 set_addr_port_num((struct sockaddr *) sin4, actual_port);
1499 __sdp_log(2, "LISTEN: BOTH on IP <%s> port <%d>\n",
1501 /* perform the bind */
1502 ret = close_and_bind(tcp_sd, fd, (struct sockaddr *) sin4,
1503 tmp_sinlen, semantics);
1505 __sdp_log(9, "Error listen: "
1506 "Could not close_and_bind TCP side\n");
1509 ret = close_and_bind(sdp_sd, shadow_fd, (struct sockaddr *) sin4,
1510 tmp_sinlen, semantics);
1512 __sdp_log(9, "Error listen: "
1513 "Could not close_and_bind SDP side\n");
1518 if ((target_family == USE_TCP) || (target_family == USE_BOTH)) {
1519 __sdp_log(1, "LISTEN: calling listen on TCP fd:%d\n", fd);
1520 ret = __listen_semantics(fd, backlog, semantics);
1522 __sdp_log(9, "Error listen: failed with code <%d> on TCP fd:<%d>\n",
1525 __sdp_log(7, "LISTEN: fd:%d listening on TCP bound to:%s port:%d\n",
1526 fd, buf, actual_port);
1530 if ((target_family == USE_SDP) || (target_family == USE_BOTH)) {
1531 __sdp_log(1, "LISTEN: calling listen on SDP fd:<%d>\n", shadow_fd);
1532 sret = __listen_semantics(shadow_fd, backlog, semantics);
1534 __sdp_log(9, "Error listen: failed with code <%d> SDP fd:<%d>\n",
1537 __sdp_log(7, "LISTEN: fd:%d listening on SDP bound to:%s port:%d\n",
1538 fd, buf, actual_port);
1542 /* cleanup the un-needed shadow if TCP and did not fail */
1543 if ((target_family == USE_TCP) && (ret >= 0)) {
1544 __sdp_log(1, "LISTEN: cleaning up shadow SDP\n");
1545 if (cleanup_shadow(fd) < 0)
1546 __sdp_log(9, "Error listen: failed to cleanup shadow for fd:%d\n",
1550 /* cleanup the TCP socket and replace with SDP */
1551 if ((target_family == USE_SDP) && (sret >= 0)) {
1552 __sdp_log(1, "LISTEN: cleaning TCP socket and dup2 SDP into it\n");
1553 if (0 > (sret = replace_fd_with_its_shadow(fd)))
1554 __sdp_log(9, "Error listen: "
1555 "failed to dup2 shadow into orig fd:%d\n", fd);
1559 __sdp_log(2, "LISTEN: <%s:%d:%d> result <%d>\n",
1560 program_invocation_short_name, fd, shadow_fd, ret);
1561 /* its a success only if both are ok */
1569 int listen(int fd, int backlog)
1571 return __perform_listen(fd, backlog, SOCKET_SEMANTIC_DEFAULT);
1574 #ifdef SOLARIS_BUILD
1575 int __xnet_listen(int fd, int backlog)
1577 return __perform_listen(fd, backlog, SOCKET_SEMANTIC_XNET);
1581 /* ========================================================================= */
1582 /*..close -- replacement close call. */
1588 if (init_status == 0)
1591 if (NULL == _socket_funcs.close) {
1592 __sdp_log(9, "Error close: no implementation for close found\n");
1596 shadow_fd = get_shadow_fd_by_fd(fd);
1598 __sdp_log(2, "CLOSE: <%s:%d:%d>\n",
1599 program_invocation_short_name, fd, shadow_fd);
1601 if (shadow_fd != -1) {
1602 __sdp_log(1, "CLOSE: closing shadow fd:<%d>\n", shadow_fd);
1603 if (cleanup_shadow(fd) < 0)
1604 __sdp_log(9, "Error close: failed to cleanup shadow for fd:%d\n",
1608 init_extra_attribute(fd);
1609 ret = _socket_funcs.close(fd);
1610 __sdp_log(2, "CLOSE: <%s:%d:%d> result <%d>\n",
1611 program_invocation_short_name, fd, shadow_fd, ret);
1615 /* ========================================================================= */
1616 /*..dup -- replacement dup call. */
1617 /* we duplicate the fd and its shadow if exists - ok if the main worked */
1620 int newfd, new_shadow_fd = -1;
1623 if (init_status == 0)
1626 if (NULL == _socket_funcs.dup) {
1627 __sdp_log(9, "Error dup: no implementation for dup found\n");
1631 shadow_fd = get_shadow_fd_by_fd(fd);
1633 __sdp_log(2, "DUP: <%s:%d:%d>\n",
1634 program_invocation_short_name, fd, shadow_fd);
1636 __sdp_log(1, "DUP: duplication fd:<%d>\n", fd);
1637 newfd = _socket_funcs.dup(fd);
1642 if (!is_valid_fd(newfd)) {
1643 __sdp_log(9, "Error dup: new fd <%d> out of range.\n", newfd);
1645 /* copy attributes from old fd */
1646 libsdp_fd_attributes[newfd] = libsdp_fd_attributes[fd];
1647 libsdp_fd_attributes[newfd].shadow_fd = -1;
1649 if (shadow_fd != -1) {
1650 __sdp_log(1, "DUP: duplication shadow fd:<%d>\n", shadow_fd);
1651 new_shadow_fd = _socket_funcs.dup(shadow_fd);
1652 if ((new_shadow_fd > max_file_descriptors) || (new_shadow_fd < 0)) {
1653 __sdp_log(9, "Error dup: new shadow fd <%d> out of range.\n",
1656 libsdp_fd_attributes[new_shadow_fd] =
1657 libsdp_fd_attributes[shadow_fd];
1658 libsdp_fd_attributes[newfd].shadow_fd = new_shadow_fd;
1660 } /* shadow exists */
1663 __sdp_log(2, "DUP: <%s:%d:%d> return <%d:%d>\n",
1664 program_invocation_short_name, fd, shadow_fd, newfd,
1670 /* ========================================================================= */
1671 /*..dup2 -- replacement dup2 call. */
1672 /* since only the main new fd is given we only move the shadow if exists */
1673 int dup2(int fd, int newfd)
1677 int new_shadow_fd = -1;
1680 if (init_status == 0)
1683 if (NULL == _socket_funcs.dup2) {
1684 __sdp_log(9, "Error dup2: no implementation for dup2 found\n");
1688 shadow_fd = get_shadow_fd_by_fd(fd);
1689 shadow_newfd = get_shadow_fd_by_fd(newfd);
1691 __sdp_log(2, "DUP2: <%s:%d:%d>\n",
1692 program_invocation_short_name, fd, shadow_fd);
1695 __sdp_log(1, "DUP2: skip duplicating fd:<%d> into:<%d>\n", fd, newfd);
1699 /* dup2 closes the target file desc if it is a valid fd */
1700 if (shadow_newfd != -1) {
1701 __sdp_log(1, "DUP2: closing newfd:<%d> shadow:<%d>\n", newfd,
1703 ret = _socket_funcs.close(shadow_newfd);
1706 "DUP2: fail to close newfd:<%d> shadow:<%d> with: %d %s\n",
1707 newfd, shadow_newfd, ret, strerror(errno));
1711 __sdp_log(1, "DUP2: duplicating fd:<%d> into:<%d>\n", fd, newfd);
1712 newfd = _socket_funcs.dup2(fd, newfd);
1713 if ((newfd > max_file_descriptors) || (newfd < 0)) {
1714 __sdp_log(9, "Error dup2: new fd <%d> out of range.\n", newfd);
1716 /* copy attributes from old fd */
1717 libsdp_fd_attributes[fd].shadow_fd = -1;
1718 libsdp_fd_attributes[newfd] = libsdp_fd_attributes[fd];
1720 /* if it had a shadow create a new shadow */
1721 if (shadow_fd != -1) {
1722 __sdp_log(1, "DUP2: duplication shadow fd:<%d>\n", shadow_fd);
1723 new_shadow_fd = _socket_funcs.dup(shadow_fd);
1724 if ((new_shadow_fd > max_file_descriptors) || (new_shadow_fd < 0)) {
1725 __sdp_log(9, "Error dup2: new shadow fd <%d> out of range.\n",
1728 libsdp_fd_attributes[new_shadow_fd] =
1729 libsdp_fd_attributes[shadow_fd];
1730 libsdp_fd_attributes[newfd].shadow_fd = new_shadow_fd;
1736 __sdp_log(2, "DUP2: <%s:%d:%d> return <%d:%d>\n",
1737 program_invocation_short_name, fd, shadow_fd, newfd,
1743 /* ========================================================================= */
1744 /*..getsockname -- replacement getsocknanme call. */
1745 int getsockname(int fd, struct sockaddr *name, socklen_t * namelen)
1748 char buf[MAX_ADDR_STR_LEN];
1750 if (init_status == 0)
1754 * ensure the SDP protocol family is not exposed to the user, since
1755 * this is meant to be a transparency layer.
1757 if (NULL == _socket_funcs.getsockname) {
1759 "Error getsockname: no implementation for getsockname found\n");
1763 /* double check provided pointers */
1764 if ((name == NULL) || is_invalid_addr(name)) {
1766 __sdp_log(9, "Error getsockname: illegal address provided\n");
1770 if ((namelen != NULL) && is_invalid_addr(namelen)) {
1772 __sdp_log(9, "Error getsockname: illegal address length pointer provided\n");
1776 __sdp_log(2, "GETSOCKNAME <%s:%d>\n", program_invocation_short_name, fd);
1778 ret = _socket_funcs.getsockname(fd, name, namelen);
1780 if (__sdp_log_get_level() <= 1) {
1781 if (get_addr_str(name, buf, MAX_ADDR_STR_LEN)) {
1782 __sdp_log(1, "GETSOCKNAME: " "address is illegal\n");
1784 __sdp_log(1, "GETSOCKNAME: address is:%s port:%d\n", buf,
1785 ntohs(((struct sockaddr_in *) name)->sin_port));
1788 __sdp_log(2, "GETSOCKNAME <%s:%d> result <%d>\n",
1789 program_invocation_short_name, fd, ret);
1794 /* ========================================================================= */
1795 /*..getpeername -- replacement getpeername call. */
1796 int getpeername(int fd, struct sockaddr *name, socklen_t * namelen)
1800 if (init_status == 0)
1803 if (NULL == _socket_funcs.getpeername) {
1804 __sdp_log(9, "Error getpeername: "
1805 "no implementation for getpeername found\n");
1809 /* double check provided pointers */
1810 if ((name == NULL) || is_invalid_addr(name)) {
1812 __sdp_log(9, "Error getsockname: illegal address provided\n");
1816 if ((namelen != NULL) && is_invalid_addr(namelen)) {
1819 "Error getsockname: illegal address length pointer provided\n");
1823 __sdp_log(2, "GETPEERNAME <%s:%d>\n", program_invocation_short_name, fd);
1825 ret = _socket_funcs.getpeername(fd, name, namelen);
1827 __sdp_log(2, "GETPEERNAME <%s:%d> result <%d:%d> family=%d s_addr=%d\n",
1828 program_invocation_short_name, fd, ret,
1829 (!(0 > ret) ? 0 : -1), name->sa_family,
1830 ((struct sockaddr_in *) name)->sin_addr.s_addr);
1837 /* ========================================================================= */
1838 /*..accept -- replacement accept call. */
1840 If we have a shadow we need to decide which socket we want to accept on
1841 so we select first and then give priority based on previous selection
1843 int accept(int fd, struct sockaddr *addr, socklen_t * addrlen)
1848 socklen_t saved_addrlen = 0;
1850 char buf[MAX_ADDR_STR_LEN];
1852 if (init_status == 0)
1855 shadow_fd = get_shadow_fd_by_fd(fd);
1858 * ensure the SDP protocol family is not exposed to the user, since
1859 * this is meant to be a transparency layer.
1861 if (NULL == _socket_funcs.accept) {
1862 __sdp_log(9, "Error accept: no implementation for accept found\n");
1866 /* double check provided pointers */
1867 if ((addr != NULL) && is_invalid_addr(addr)) {
1869 __sdp_log(9, "Error accept: illegal address provided\n");
1873 if ((addrlen != NULL) && is_invalid_addr(addrlen)) {
1875 __sdp_log(9, "Error accept: illegal address length pointer provided\n");
1879 if (addr && addrlen)
1880 saved_addrlen = *addrlen;
1882 __sdp_log(2, "ACCEPT: <%s:%d>\n", program_invocation_short_name, fd);
1884 if (shadow_fd == -1) {
1885 fopts = _socket_funcs.fcntl(fd, F_GETFL);
1886 __sdp_log(1, "ACCEPT: fd <%d> opts are <0x%x>\n", fd, fopts);
1888 __sdp_log(7, "ACCEPT: accepting on single fd:<%d>\n", fd);
1889 ret = _socket_funcs.accept(fd, addr, addrlen);
1891 if (!(fopts & O_NONBLOCK && errno == EWOULDBLOCK))
1892 __sdp_log(9, "Error accept: accept returned :<%d> %s\n",
1893 ret, strerror(errno));
1895 set_is_sdp_socket(ret, get_is_sdp_socket(fd));
1899 fopts = _socket_funcs.fcntl(shadow_fd, F_GETFL);
1900 __sdp_log(1, "ACCEPT: shadow_fd <%d> opts are <0x%x>\n",
1903 /* we need different behavior for NONBLOCK or signal IO and BLOCK */
1904 if ((fopts > 0) && (fopts & (O_NONBLOCK | FASYNC))) {
1905 __sdp_log(1, "ACCEPT: accepting (nonblock) on SDP fd:<%d>\n", shadow_fd);
1907 ret = _socket_funcs.accept(shadow_fd, addr, addrlen);
1909 set_is_sdp_socket(ret, 1);
1911 __sdp_log(7, "ACCEPT: accepted (nonblock) SDP fd:<%d>\n",
1914 __sdp_log(1, "ACCEPT: accept on SDP fd:<%d> return:%d errno:%d\n",
1915 shadow_fd, ret, errno);
1917 __sdp_log(1, "ACCEPT: accepting (nonblock) on TCP fd:<%d>\n", fd);
1918 ret = _socket_funcs.accept(fd, addr, addrlen);
1920 __sdp_log(7, "ACCEPT: accepted (nonblock) TCP fd:<%d>\n",
1923 __sdp_log(1, "ACCEPT: accept on TCP fd:<%d> "
1924 "return:%d errno:%d\n", fd, ret, errno);
1928 __sdp_log(1, "ACCEPT: selecting both fd:<%d> and shadow:<%d>\n",
1932 FD_SET(shadow_fd, &fds);
1934 _socket_funcs.select(1 + ((fd > shadow_fd) ? fd : shadow_fd),
1935 &fds, NULL, NULL, NULL);
1937 if (last_accept_was_tcp(fd) == 0) {
1938 if (FD_ISSET(fd, &fds)) {
1939 set_last_accept(fd, 1);
1940 __sdp_log(7, "ACCEPT: accepting on TCP fd:<%d>\n", fd);
1941 ret = _socket_funcs.accept(fd, addr, addrlen);
1943 __sdp_log(7, "ACCEPT: accepting on SDP fd:<%d>\n",
1945 ret = _socket_funcs.accept(shadow_fd, addr, addrlen);
1947 set_is_sdp_socket(ret, 1);
1950 if (FD_ISSET(shadow_fd, &fds)) {
1951 set_last_accept(fd, 1);
1952 __sdp_log(7, "ACCEPT: accepting on SDP fd:<%d>\n",
1954 ret = _socket_funcs.accept(shadow_fd, addr, addrlen);
1956 set_is_sdp_socket(ret, 1);
1958 __sdp_log(7, "ACCEPT: accepting on TCP fd:<%d>\n", fd);
1959 ret = _socket_funcs.accept(fd, addr, addrlen);
1963 if (errno != EINTR) {
1965 "Error accept: select returned :<%d> (%d) %s\n",
1966 ret, errno, strerror(errno));
1968 __sdp_log(1, "ACCEPT: select returned :<%d> (%d) %s\n",
1969 ret, errno, strerror(errno));
1972 } /* blocking mode */
1975 if ((__sdp_log_get_level() <= 1) && (ret >= 0) && addr && addrlen) {
1976 get_addr_str(addr, buf, *addrlen);
1977 __sdp_log(1, "ACCEPT: accepted from:%s port:%d into fd:%d\n",
1978 buf, ntohs(((struct sockaddr_in *) addr)->sin_port), ret);
1980 __sdp_log(2, "ACCEPT: <%s:%d> return <%d>\n",
1981 program_invocation_short_name, fd, ret);
1986 /* ========================================================================= */
1987 /*..select -- replacement socket call. */
1989 if we have shadow we must select on it too - which requires a hack back
1995 fd_set * writefds, fd_set * exceptfds, struct timeval *timeout)
2003 if (init_status == 0)
2006 if (NULL == _socket_funcs.select) {
2007 __sdp_log(9, "Error select: no implementation for select found\n");
2011 __sdp_log(2, "SELECT: <%s:%d>\n", program_invocation_short_name, n);
2013 /* if we do not read - nothing to do */
2014 if (readfds == NULL) {
2015 ret = _socket_funcs.select(n, readfds, writefds, exceptfds, timeout);
2024 /* add shadow bits */
2025 for (current = 0; current < n; current++) {
2026 if (FD_ISSET(current, readfds)) {
2027 FD_SET(current, &new_fds);
2028 if (current > maxi) {
2031 shadow_fd = get_shadow_fd_by_fd(current);
2032 if (shadow_fd != -1) {
2034 "SELECT: adding fd:<%d> shadow_fd:<%d> to readfs\n",
2035 current, shadow_fd);
2036 FD_SET(shadow_fd, &new_fds);
2037 if (shadow_fd > maxi) {
2044 __sdp_log(1, "SELECT: invoking select n=<%d>\n", 1 + maxi);
2045 ret = _socket_funcs.select(1 + maxi,
2046 &new_fds, writefds, exceptfds, timeout);
2048 /* remove the count and bits of the shadows */
2050 for (current = 0; current < n; current++) {
2051 shadow_fd = get_shadow_fd_by_fd(current);
2052 if (shadow_fd == -1) {
2053 if (FD_ISSET(current, readfds) &&
2054 FD_ISSET(current, &new_fds) == 0) {
2055 FD_CLR(current, readfds);
2058 if (FD_ISSET(current, readfds) && FD_ISSET(current, &new_fds)
2059 && FD_ISSET(shadow_fd, &new_fds)) {
2062 if (FD_ISSET(current, readfds) &&
2063 FD_ISSET(current, &new_fds) == 0 &&
2064 FD_ISSET(shadow_fd, &new_fds) == 0) {
2065 FD_CLR(current, readfds);
2073 __sdp_log(2, "SELECT: <%s:%d> return <%d>\n",
2074 program_invocation_short_name, n, ret);
2078 /* ========================================================================= */
2079 /*..pselect -- replacement socket call. */
2081 if we have shadow we must pselect on it too - which requires a hack back
2089 const struct timespec *timeout, const sigset_t * sigmask)
2097 if (init_status == 0)
2100 if (NULL == _socket_funcs.pselect) {
2101 __sdp_log(9, "Error pselect: no implementation for pselect found\n");
2105 __sdp_log(2, "PSELECT: <%s:%d>\n", program_invocation_short_name, n);
2107 /* if we do not read - nothing to do */
2108 if (readfds == NULL) {
2110 _socket_funcs.pselect(n, readfds, writefds, exceptfds, timeout,
2120 /* add shadow bits */
2121 for (current = 0; current < n; current++) {
2122 if (FD_ISSET(current, readfds)) {
2123 FD_SET(current, &new_fds);
2124 if (current > maxi) {
2127 shadow_fd = get_shadow_fd_by_fd(current);
2128 if (shadow_fd != -1) {
2130 "PSELECT: adding fd:<%d> shadow_fd:<%d> to readfs\n",
2131 current, shadow_fd);
2132 FD_SET(shadow_fd, &new_fds);
2133 if (shadow_fd > maxi) {
2140 __sdp_log(1, "PSELECT: invoking pselect n=<%d>\n", 1 + maxi);
2141 ret = _socket_funcs.pselect(1 + maxi,
2142 &new_fds, writefds, exceptfds,
2145 /* remove the count and bits of the shadows */
2147 for (current = 0; current < n; current++) {
2148 shadow_fd = get_shadow_fd_by_fd(current);
2149 if (shadow_fd == -1) {
2150 if (FD_ISSET(current, readfds) &&
2151 FD_ISSET(current, &new_fds) == 0) {
2152 FD_CLR(current, readfds);
2155 if (FD_ISSET(current, readfds) && FD_ISSET(current, &new_fds)
2156 && FD_ISSET(shadow_fd, &new_fds)) {
2159 if (FD_ISSET(current, readfds) &&
2160 FD_ISSET(current, &new_fds) == 0 &&
2161 FD_ISSET(shadow_fd, &new_fds) == 0) {
2162 FD_CLR(current, readfds);
2170 __sdp_log(2, "PSELECT: <%s:%d> return <%d>\n",
2171 program_invocation_short_name, n, ret);
2175 /* ========================================================================= */
2176 /*..poll -- replacement socket call. */
2178 if we have shadow we must poll on it too - which requires a hack back
2181 int poll(struct pollfd *ufds, nfds_t nfds, int timeout)
2187 struct pollfd *poll_fds = NULL;
2188 struct pollfd *poll_fd_ptr = NULL;
2190 if (init_status == 0)
2193 if (NULL == _socket_funcs.poll) {
2194 __sdp_log(9, "Error poll: no implementation for poll found\n");
2198 __sdp_log(2, "POLL: <%s:%d>\n", program_invocation_short_name, nfds);
2200 /* if we do not have any file desc - nothing to do */
2202 ret = _socket_funcs.poll(ufds, nfds, timeout);
2206 /* scan for how many extra fds are required */
2207 for (current = 0; current < nfds; current++) {
2208 shadow_fd = get_shadow_fd_by_fd(ufds[current].fd);
2209 if (shadow_fd != -1)
2217 (struct pollfd *) malloc((nfds + extra) * sizeof(struct pollfd));
2220 "Error poll: malloc of extended pollfd array failed\n");
2225 poll_fd_ptr = poll_fds;
2226 for (current = 0; current < nfds; current++) {
2227 *poll_fd_ptr = ufds[current];
2229 shadow_fd = get_shadow_fd_by_fd(ufds[current].fd);
2230 if (shadow_fd != -1) {
2231 __sdp_log(1, "POLL: adding fd:<%d> shadow_fd:<%d> to readfs\n",
2232 current, shadow_fd);
2233 *poll_fd_ptr = ufds[current];
2234 poll_fd_ptr->fd = shadow_fd;
2240 __sdp_log(1, "POLL: invoking poll nfds=<%d>\n", nfds + extra);
2241 ret = _socket_funcs.poll(poll_fds, nfds + extra, timeout);
2243 /* refactor into original list if any events */
2244 if ((ret > 0) && extra) {
2245 poll_fd_ptr = poll_fds;
2246 for (current = 0; current < nfds; current++) {
2247 shadow_fd = get_shadow_fd_by_fd(ufds[current].fd);
2248 if (shadow_fd == -1) {
2249 ufds[current] = *poll_fd_ptr;
2251 ufds[current] = *poll_fd_ptr;
2253 if (poll_fd_ptr->revents) {
2254 if (ufds[current].revents)
2256 ufds[current].revents |= poll_fd_ptr->revents;
2267 __sdp_log(2, "POLL: <%s:%d> return <%d>\n",
2268 program_invocation_short_name, nfds, ret);
2273 /* ========================================================================= */
2274 /*..epoll_create -- replacement socket call. */
2276 Need to make the size twice as large for shadow fds
2278 int epoll_create(int size)
2282 if (init_status == 0)
2285 if (NULL == _socket_funcs.epoll_create) {
2287 "Error epoll_create: no implementation for epoll_create found\n");
2291 __sdp_log(2, "EPOLL_CREATE: <%s:%d>\n", program_invocation_short_name,
2294 epfd = _socket_funcs.epoll_create(size * 2);
2296 __sdp_log(2, "EPOLL_CREATE: <%s:%d> return %d\n",
2297 program_invocation_short_name, size, epfd);
2299 } /* epoll_create */
2301 /* ========================================================================= */
2302 /*..epoll_ctl -- replacement socket call. */
2304 Need to add/delete/modify shadow fds as well
2306 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
2308 int ret, shadow_fd, ret2;
2310 if (init_status == 0)
2313 if (NULL == _socket_funcs.epoll_ctl) {
2315 "Error epoll_ctl: no implementation for epoll_ctl found\n");
2319 __sdp_log(2, "EPOLL_CTL: <%s:%d> op <%d:%d>\n",
2320 program_invocation_short_name, epfd, op, fd);
2322 ret = _socket_funcs.epoll_ctl(epfd, op, fd, event);
2324 shadow_fd = get_shadow_fd_by_fd(fd);
2325 if (shadow_fd != -1) {
2326 ret2 = _socket_funcs.epoll_ctl(epfd, op, shadow_fd, event);
2328 __sdp_log(9, "Error epoll_ctl <%s:%d:%d>",
2329 program_invocation_short_name, fd, shadow_fd);
2334 __sdp_log(2, "EPOLL_CTL: <%s:%d> return <%d>\n",
2335 program_invocation_short_name, epfd, ret);
2339 /* ========================================================================= */
2340 /*..epoll_wait -- replacement socket call. */
2342 We don't care who generated the event because all we get is user-context
2345 int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
2349 if (init_status == 0)
2352 if (NULL == _socket_funcs.epoll_wait) {
2354 "Error epoll_wait: no implementation for epoll_wait found\n");
2358 __sdp_log(2, "EPOLL_WAIT: <%s:%d>\n", program_invocation_short_name, epfd);
2360 ret = _socket_funcs.epoll_wait(epfd, events, maxevents, timeout);
2362 __sdp_log(2, "EPOLL_WAIT: <%s:%d> return <%d>\n",
2363 program_invocation_short_name, epfd, ret);
2367 /* ========================================================================= */
2368 /*..epoll_pwait -- replacement socket call. */
2370 We don't care who generated the event because all we get is user-context
2374 epoll_pwait(int epfd,
2375 struct epoll_event *events,
2376 int maxevents, int timeout, const sigset_t * sigmask)
2380 if (init_status == 0)
2383 if (NULL == _socket_funcs.epoll_pwait) {
2385 "Error epoll_pwait: no implementation for epoll_pwait found\n");
2389 __sdp_log(2, "EPOLL_PWAIT: <%s:%d>\n", program_invocation_short_name, epfd);
2391 ret = _socket_funcs.epoll_pwait(epfd, events, maxevents, timeout, sigmask);
2393 __sdp_log(2, "EPOLL_PWAIT: <%s:%d> return <%d>\n",
2394 program_invocation_short_name, epfd, ret);
2399 /* ========================================================================= */
2401 /* --------------------------------------------------------------------- */
2403 /* Library load/unload initialization/cleanup */
2405 /* --------------------------------------------------------------------- */
2406 /* ========================================================================= */
2407 /*..__sdp_init -- intialize the library */
2408 void __sdp_init(void)
2410 char *config_file, *error_str;
2412 struct rlimit nofiles_limit;
2414 /* HACK: races might apply here: can we assume init is happening
2415 only within one thread ? */
2416 if (init_status != 0)
2420 dev_null_fd = open("/dev/null", O_WRONLY);
2422 /* figure out the max number of file descriptors */
2423 if (getrlimit(RLIMIT_NOFILE, &nofiles_limit))
2424 max_file_descriptors = 1024;
2426 max_file_descriptors = nofiles_limit.rlim_cur;
2428 /* allocate and initialize the shadow sdp sockets array */
2429 libsdp_fd_attributes =
2430 (struct sdp_extra_fd_attributes *) calloc(max_file_descriptors,
2432 sdp_extra_fd_attributes));
2433 for (fd = 0; fd < max_file_descriptors; fd++)
2434 init_extra_attribute(fd);
2438 * open libc for original socket call.
2439 * Solaris relies on RTLD next - since the socket calls are
2440 * actually in libsocket rather than libc.
2442 __libc_dl_handle = dlopen("/lib64/libc.so.6", RTLD_LAZY);
2443 if (NULL == __libc_dl_handle) {
2444 __libc_dl_handle = dlopen("/lib/libc.so.6", RTLD_LAZY);
2445 if (NULL == __libc_dl_handle) {
2446 fprintf(stderr, "%s\n", dlerror());
2453 * Get the original functions
2455 _socket_funcs.ioctl = dlsym(__libc_dl_handle, "ioctl");
2456 if (NULL != (error_str = dlerror())) {
2457 fprintf(stderr, "%s\n", error_str);
2460 _socket_funcs.fcntl = dlsym(__libc_dl_handle, "fcntl");
2461 if (NULL != (error_str = dlerror())) {
2462 fprintf(stderr, "%s\n", error_str);
2465 _socket_funcs.socket = dlsym(__libc_dl_handle, "socket");
2466 if (NULL != (error_str = dlerror())) {
2467 fprintf(stderr, "%s\n", error_str);
2470 _socket_funcs.setsockopt = dlsym(__libc_dl_handle, "setsockopt");
2471 if (NULL != (error_str = dlerror())) {
2472 fprintf(stderr, "%s\n", error_str);
2475 _socket_funcs.connect = dlsym(__libc_dl_handle, "connect");
2476 if (NULL != (error_str = dlerror())) {
2477 fprintf(stderr, "%s\n", error_str);
2480 _socket_funcs.listen = dlsym(__libc_dl_handle, "listen");
2481 if (NULL != (error_str = dlerror())) {
2482 fprintf(stderr, "%s\n", error_str);
2485 _socket_funcs.bind = dlsym(__libc_dl_handle, "bind");
2486 if (NULL != (error_str = dlerror())) {
2487 fprintf(stderr, "%s\n", error_str);
2490 _socket_funcs.close = dlsym(__libc_dl_handle, "close");
2491 if (NULL != (error_str = dlerror())) {
2492 fprintf(stderr, "%s\n", error_str);
2495 _socket_funcs.dup = dlsym(__libc_dl_handle, "dup");
2496 if (NULL != (error_str = dlerror())) {
2497 fprintf(stderr, "%s\n", error_str);
2500 _socket_funcs.dup2 = dlsym(__libc_dl_handle, "dup2");
2501 if (NULL != (error_str = dlerror())) {
2502 fprintf(stderr, "%s\n", error_str);
2505 _socket_funcs.getpeername = dlsym(__libc_dl_handle, "getpeername");
2506 if (NULL != (error_str = dlerror())) {
2507 fprintf(stderr, "%s\n", error_str);
2510 _socket_funcs.getsockname = dlsym(__libc_dl_handle, "getsockname");
2511 if (NULL != (error_str = dlerror())) {
2512 fprintf(stderr, "%s\n", error_str);
2515 _socket_funcs.accept = dlsym(__libc_dl_handle, "accept");
2516 if (NULL != (error_str = dlerror())) {
2517 fprintf(stderr, "%s\n", error_str);
2520 _socket_funcs.select = dlsym(__libc_dl_handle, "select");
2521 if (NULL != (error_str = dlerror())) {
2522 fprintf(stderr, "%s\n", error_str);
2525 _socket_funcs.pselect = dlsym(__libc_dl_handle, "pselect");
2526 if (NULL != (error_str = dlerror())) {
2527 fprintf(stderr, "%s\n", error_str);
2530 _socket_funcs.poll = dlsym(__libc_dl_handle, "poll");
2531 if (NULL != (error_str = dlerror())) {
2532 fprintf(stderr, "%s\n", error_str);
2536 _socket_funcs.epoll_create = dlsym(__libc_dl_handle, "epoll_create");
2537 if (NULL != (error_str = dlerror())) {
2538 fprintf(stderr, "%s\n", error_str);
2541 _socket_funcs.epoll_ctl = dlsym(__libc_dl_handle, "epoll_ctl");
2542 if (NULL != (error_str = dlerror())) {
2543 fprintf(stderr, "%s\n", error_str);
2546 _socket_funcs.epoll_wait = dlsym(__libc_dl_handle, "epoll_wait");
2547 if (NULL != (error_str = dlerror())) {
2548 fprintf(stderr, "%s\n", error_str);
2551 _socket_funcs.epoll_pwait = dlsym(__libc_dl_handle, "epoll_pwait");
2552 if (NULL != (error_str = dlerror())) {
2553 fprintf(stderr, "%s\n", error_str);
2556 #ifdef SOLARIS_BUILD
2557 _socket_xnet_funcs.socket = dlsym(__libc_dl_handle, "__xnet_socket");
2558 if (NULL != (error_str = dlerror())) {
2559 fprintf(stderr, "%s\n", error_str);
2562 _socket_xnet_funcs.connect = dlsym(__libc_dl_handle, "__xnet_connect");
2563 if (NULL != (error_str = dlerror())) {
2564 fprintf(stderr, "%s\n", error_str);
2567 _socket_xnet_funcs.listen = dlsym(__libc_dl_handle, "__xnet_listen");
2568 if (NULL != (error_str = dlerror())) {
2569 fprintf(stderr, "%s\n", error_str);
2572 _socket_xnet_funcs.bind = dlsym(__libc_dl_handle, "__xnet_bind");
2573 if (NULL != (error_str = dlerror())) {
2574 fprintf(stderr, "%s\n", error_str);
2577 /* Determine program name by asking libdl */
2578 Dl_argsinfo args_info;
2579 if (NULL != dlinfo(RTLD_SELF, RTLD_DI_ARGSINFO, &args_info)) {
2580 fprintf(stderr, "args_info: %s\n", dlerror());
2582 program_invocation_name = args_info.dla_argv[0];
2583 program_invocation_short_name = basename(args_info.dla_argv[0]);
2587 if (getenv("SIMPLE_LIBSDP") != NULL) {
2588 simple_sdp_library = 1;
2591 if (getenv("ALWAYS_USE_SDP") != NULL) {
2592 simple_sdp_library = 1;
2594 #define LIBSDP_DEFAULT_CONFIG_FILE SYSCONFDIR "/libsdp.conf"
2595 if (!simple_sdp_library) {
2596 config_file = getenv("LIBSDP_CONFIG_FILE");
2598 config_file = LIBSDP_DEFAULT_CONFIG_FILE;
2600 if (__sdp_parse_config(config_file)) {
2602 "libsdp Error: failed to parse config file:%s. Using defaults.\n",
2607 __sdp_log(1, "Max file descriptors:%d\n", max_file_descriptors);
2612 /* ========================================================================= */
2613 /*..__sdp_fini -- when the library is unloaded this is called */
2614 void __sdp_fini(void)
2616 struct use_family_rule *rule;
2617 for (rule = __sdp_clients_family_rules_head; rule != NULL;
2619 free(rule->prog_name_expr);
2620 for (rule = __sdp_servers_family_rules_head; rule != NULL;
2622 free(rule->prog_name_expr);
2624 free(libsdp_fd_attributes);
2627 dlclose(__libc_dl_handle);