1219820Sjeff/* 2219820Sjeff This software is available to you under a choice of one of two 3219820Sjeff licenses. You may choose to be licensed under the terms of the GNU 4219820Sjeff General Public License (GPL) Version 2, available at 5219820Sjeff <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD 6219820Sjeff license, available in the LICENSE.TXT file accompanying this 7219820Sjeff software. These details are also available at 8219820Sjeff <http://openib.org/license.html>. 9219820Sjeff 10219820Sjeff THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 11219820Sjeff EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 12219820Sjeff MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 13219820Sjeff NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 14219820Sjeff BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 15219820Sjeff ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16219820Sjeff CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17219820Sjeff SOFTWARE. 18219820Sjeff 19219820Sjeff Copyright (c) 2004 Topspin Communications. All rights reserved. 20219820Sjeff Copyright (c) 2005-2006 Mellanox Technologies Ltd. All rights reserved. 21219820Sjeff 22219820Sjeff $Id$ 23219820Sjeff*/ 24219820Sjeff 25219820Sjeff/* 26219820Sjeff * system includes 27219820Sjeff */ 28219820Sjeff#if HAVE_CONFIG_H 29219820Sjeff# include <config.h> 30219820Sjeff#endif /* HAVE_CONFIG_H */ 31219820Sjeff 32219820Sjeff#ifdef SOLARIS_BUILD 33219820Sjeff/* Our prototypes for ioctl, get*name and accept do not strictly 34219820Sjeff match the headers - we use the following lines to move the header 35219820Sjeff versions 'out of the way' temporarily. */ 36219820Sjeff#define ioctl __real_ioctl 37219820Sjeff#define getsockname __real_getsockname 38219820Sjeff#define getpeername __real_getpeername 39219820Sjeff#define accept __real_accept 40219820Sjeff#define FASYNC 0 41219820Sjeff#include <libgen.h> 42219820Sjeff#endif 43219820Sjeff#include <unistd.h> 44219820Sjeff#include <errno.h> 45219820Sjeff#include <stdio.h> 46219820Sjeff#include <stdlib.h> 47219820Sjeff#include <string.h> 48219820Sjeff#define __USE_GNU 49219820Sjeff#define _GNU_SOURCE /* define RTLD_NEXT */ 50219820Sjeff#include <dlfcn.h> 51219820Sjeff#include <sys/types.h> 52219820Sjeff#include <sys/socket.h> 53219820Sjeff#include <netinet/tcp.h> 54219820Sjeff#include <arpa/inet.h> 55219820Sjeff#include <netinet/in.h> 56219820Sjeff#include <stdarg.h> 57219820Sjeff#include <sys/time.h> 58219820Sjeff#include <sys/resource.h> 59219820Sjeff#include <sys/stat.h> 60219820Sjeff#include <fcntl.h> 61219820Sjeff#include <signal.h> 62219820Sjeff#include <sys/poll.h> 63219820Sjeff#ifdef __linux__ 64219820Sjeff#include <sys/epoll.h> 65219820Sjeff#endif 66219820Sjeff 67219820Sjeff#ifdef SOLARIS_BUILD 68219820Sjeff/* We're done protecting ourselves from the header prototypes */ 69219820Sjeff#undef ioctl 70219820Sjeff#undef getsockname 71219820Sjeff#undef getpeername 72219820Sjeff#undef accept 73219820Sjeff#endif 74219820Sjeff 75219820Sjeff/* 76219820Sjeff * SDP specific includes 77219820Sjeff */ 78219820Sjeff#include "libsdp.h" 79219820Sjeff 80219820Sjeff/* We can not use sizeof(sockaddr_in6) as the extra scope_id field is not a must have */ 81219820Sjeff#define IPV6_ADDR_IN_MIN_LEN 24 82219820Sjeff 83219820Sjeff/* setsockopt() level and optname declarations */ 84219820Sjeff#define SOL_SDP 1025 85219820Sjeff#define SDP_UNBIND 259 /* Unbind socket */ 86219820Sjeff 87219820Sjeff/* Solaris has two entry socket creation functions */ 88219820Sjeff#define SOCKET_SEMANTIC_DEFAULT 0 89219820Sjeff#define SOCKET_SEMANTIC_XNET 1 90219820Sjeff 91219820Sjeff/* HACK: filter ioctl errors for FIONREAD */ 92219820Sjeff#define FIONREAD 0x541B 93219820Sjeff 94219820Sjeffvoid __attribute__ ((constructor)) __sdp_init(void); 95219820Sjeffvoid __attribute__ ((destructor)) __sdp_fini(void); 96219820Sjeff 97219820Sjeff/* --------------------------------------------------------------------- */ 98219820Sjeff/* library type definitions. */ 99219820Sjeff/* --------------------------------------------------------------------- */ 100219820Sjeff 101219820Sjefftypedef int (*ioctl_func_t) (int fd, 102219820Sjeff int request, 103219820Sjeff void *arg0, 104219820Sjeff void *arg1, 105219820Sjeff void *arg2, 106219820Sjeff void *arg3, 107219820Sjeff void *arg4, void *arg5, void *arg6, void *arg7); 108219820Sjeff 109219820Sjefftypedef int (*fcntl_func_t) (int fd, int cmd, ...); 110219820Sjeff 111219820Sjefftypedef int (*socket_func_t) (int domain, int type, int protocol); 112219820Sjeff 113219820Sjefftypedef int (*setsockopt_func_t) (int s, 114219820Sjeff int level, 115219820Sjeff int optname, 116219820Sjeff const void *optval, socklen_t optlen); 117219820Sjeff 118219820Sjefftypedef int (*connect_func_t) (int sockfd, 119219820Sjeff const struct sockaddr * serv_addr, 120219820Sjeff socklen_t addrlen); 121219820Sjeff 122219820Sjefftypedef int (*listen_func_t) (int s, int backlog); 123219820Sjeff 124219820Sjefftypedef int (*bind_func_t) (int sockfd, 125219820Sjeff const struct sockaddr * my_addr, socklen_t addrlen); 126219820Sjeff 127219820Sjefftypedef int (*close_func_t) (int fd); 128219820Sjeff 129219820Sjefftypedef int (*dup_func_t) (int fd); 130219820Sjeff 131219820Sjefftypedef int (*dup2_func_t) (int oldfd, int newfd); 132219820Sjeff 133219820Sjefftypedef int (*getsockname_func_t) (int fd, 134219820Sjeff struct sockaddr * name, socklen_t * namelen); 135219820Sjeff 136219820Sjefftypedef int (*getpeername_func_t) (int fd, 137219820Sjeff struct sockaddr * name, socklen_t * namelen); 138219820Sjeff 139219820Sjefftypedef int (*accept_func_t) (int fd, 140219820Sjeff struct sockaddr * addr, socklen_t * addrlen); 141219820Sjeff 142219820Sjefftypedef int (*select_func_t) (int n, 143219820Sjeff fd_set * readfds, 144219820Sjeff fd_set * writefds, 145219820Sjeff fd_set * exceptfds, struct timeval * timeout); 146219820Sjeff 147219820Sjefftypedef int (*pselect_func_t) (int n, 148219820Sjeff fd_set * readfds, 149219820Sjeff fd_set * writefds, 150219820Sjeff fd_set * exceptfds, 151219820Sjeff const struct timespec * timeout, 152219820Sjeff const sigset_t * sigmask); 153219820Sjeff 154219820Sjefftypedef int (*poll_func_t) (struct pollfd * ufds, 155219820Sjeff unsigned long int nfds, int timeout); 156219820Sjeff 157219820Sjeff#ifdef __linux__ 158219820Sjefftypedef int (*epoll_create_func_t) (int size); 159219820Sjeff 160219820Sjefftypedef int (*epoll_ctl_func_t) (int epfd, 161219820Sjeff int op, int fd, struct epoll_event * event); 162219820Sjeff 163219820Sjefftypedef int (*epoll_wait_func_t) (int epfd, 164219820Sjeff struct epoll_event * events, 165219820Sjeff int maxevents, int timeout); 166219820Sjeff 167219820Sjefftypedef int (*epoll_pwait_func_t) (int epfd, 168219820Sjeff struct epoll_event * events, 169219820Sjeff int maxevents, 170219820Sjeff int timeout, const sigset_t * sigmask); 171219820Sjeff#endif 172219820Sjeff 173219820Sjeff 174219820Sjeffstruct socket_lib_funcs { 175219820Sjeff ioctl_func_t ioctl; 176219820Sjeff fcntl_func_t fcntl; 177219820Sjeff socket_func_t socket; 178219820Sjeff setsockopt_func_t setsockopt; 179219820Sjeff connect_func_t connect; 180219820Sjeff listen_func_t listen; 181219820Sjeff bind_func_t bind; 182219820Sjeff close_func_t close; 183219820Sjeff dup_func_t dup; 184219820Sjeff dup2_func_t dup2; 185219820Sjeff getpeername_func_t getpeername; 186219820Sjeff getsockname_func_t getsockname; 187219820Sjeff accept_func_t accept; 188219820Sjeff select_func_t select; 189219820Sjeff pselect_func_t pselect; 190219820Sjeff poll_func_t poll; 191219820Sjeff#ifdef __linux__ 192219820Sjeff epoll_create_func_t epoll_create; 193219820Sjeff epoll_ctl_func_t epoll_ctl; 194219820Sjeff epoll_wait_func_t epoll_wait; 195219820Sjeff epoll_pwait_func_t epoll_pwait; 196219820Sjeff#endif 197219820Sjeff}; /* socket_lib_funcs */ 198219820Sjeff 199219820Sjeff#ifdef SOLARIS_BUILD 200219820Sjeff/* Solaris has another interface to socket functions prefixed with __xnet_ */ 201219820Sjeffstruct socket_lib_xnet_funcs { 202219820Sjeff socket_func_t socket; 203219820Sjeff connect_func_t connect; 204219820Sjeff listen_func_t listen; 205219820Sjeff bind_func_t bind; 206219820Sjeff}; 207219820Sjeff#endif 208219820Sjeff 209219820Sjeffstatic int simple_sdp_library; 210219820Sjeffstatic int max_file_descriptors; 211219820Sjeffstatic int dev_null_fd; 212219820Sjeffvolatile static int init_status = 0; /* 0: idle, 1:during, 2:ready */ 213219820Sjeff 214219820Sjeff/* --------------------------------------------------------------------- */ 215219820Sjeff/* library static and global variables */ 216219820Sjeff/* --------------------------------------------------------------------- */ 217219820Sjeff 218219820Sjeff/* glibc provides these symbols - for Solaris builds we fake them 219219820Sjeff * until _init is called, at which point we quiz libdl.. */ 220219820Sjeff#ifdef SOLARIS_BUILD 221219820Sjeffchar *program_invocation_name = "[progname]", *program_invocation_short_name = 222219820Sjeff "[short_progname]"; 223219820Sjeff#else 224219820Sjeffextern char *program_invocation_name, *program_invocation_short_name; 225219820Sjeff#endif 226219820Sjeff 227219820Sjeff#ifdef RTLD_NEXT 228219820Sjeffstatic void *__libc_dl_handle = RTLD_NEXT; 229219820Sjeff#else 230219820Sjeffstatic void *__libc_dl_handle; 231219820Sjeff#endif 232219820Sjeff 233219820Sjeff/* extra fd attributes we need for our algorithms */ 234219820Sjeffstruct sdp_extra_fd_attributes { 235219820Sjeff int shadow_fd; /* file descriptor of shadow sdp socket */ 236219820Sjeff short last_accept_was_tcp; /* used by accept to alternate tcp and sdp */ 237219820Sjeff short is_sdp; /* 1 if the fd represents an sdp socket */ 238219820Sjeff}; /* sdp_extra_fd_attributes */ 239219820Sjeff 240219820Sjeff/* stores the extra attributes struct by fd */ 241219820Sjeffstatic struct sdp_extra_fd_attributes *libsdp_fd_attributes; 242219820Sjeff 243219820Sjeffstatic struct socket_lib_funcs _socket_funcs = { 244219820Sjeff .socket = NULL, 245219820Sjeff /* Automatically sets all other elements to NULL */ 246219820Sjeff}; /* _socket_funcs */ 247219820Sjeff 248219820Sjeff#ifdef SOLARIS_BUILD 249219820Sjeffstatic struct socket_lib_xnet_funcs _socket_xnet_funcs = { 250219820Sjeff .socket = NULL, 251219820Sjeff /* Automatically sets all other elements to NULL */ 252219820Sjeff}; 253219820Sjeff#endif 254219820Sjeff 255219820Sjeff/* --------------------------------------------------------------------- */ 256219820Sjeff/* Prototypes */ 257219820Sjeff/* --------------------------------------------------------------------- */ 258219820Sjeffvoid __sdp_init(void); 259219820Sjeff 260219820Sjeff/* --------------------------------------------------------------------- */ 261219820Sjeff/* */ 262219820Sjeff/* local static functions. */ 263219820Sjeff/* */ 264219820Sjeff/* --------------------------------------------------------------------- */ 265219820Sjeff 266219820Sjeff/* ========================================================================= */ 267219820Sjeff/*..init_extra_attribute -- initialize the set of extra attributes for a fd */ 268219820Sjeffstatic void init_extra_attribute(int fd) 269219820Sjeff{ 270219820Sjeff if ((0 <= fd) && (max_file_descriptors > fd)) { 271219820Sjeff libsdp_fd_attributes[fd].shadow_fd = -1; 272219820Sjeff libsdp_fd_attributes[fd].is_sdp = 0; 273219820Sjeff libsdp_fd_attributes[fd].last_accept_was_tcp = -1; 274219820Sjeff } 275219820Sjeff} 276219820Sjeff 277219820Sjeffstatic inline int is_valid_fd(int fd) 278219820Sjeff{ 279219820Sjeff return (0 <= fd) && (fd < max_file_descriptors); 280219820Sjeff} 281219820Sjeff 282219820Sjeff/* ========================================================================= */ 283219820Sjeff/*..get_shadow_fd_by_fd -- given an fd return its shadow fd if exists */ 284219820Sjeffstatic inline int get_shadow_fd_by_fd(int fd) 285219820Sjeff{ 286219820Sjeff if (is_valid_fd(fd)) 287219820Sjeff return libsdp_fd_attributes[fd].shadow_fd; 288219820Sjeff else 289219820Sjeff return -1; 290219820Sjeff} 291219820Sjeff 292219820Sjeff/* ========================================================================= */ 293219820Sjeff/*..set_shadow_for_fd -- */ 294219820Sjeffstatic inline void set_shadow_for_fd(int fd, int shadow_fd) 295219820Sjeff{ 296219820Sjeff if (is_valid_fd(fd)) 297219820Sjeff libsdp_fd_attributes[fd].shadow_fd = shadow_fd; 298219820Sjeff} 299219820Sjeff 300219820Sjeff/* ========================================================================= */ 301219820Sjeff/*..set_is_sdp_socket -- */ 302219820Sjeffstatic inline void set_is_sdp_socket(int fd, short is_sdp) 303219820Sjeff{ 304219820Sjeff if (is_valid_fd(fd)) 305219820Sjeff libsdp_fd_attributes[fd].is_sdp = is_sdp; 306219820Sjeff} 307219820Sjeff 308219820Sjeff/* ========================================================================= */ 309219820Sjeff/*..get_is_sdp_socket -- given an fd return 1 if it is an SDP socket */ 310219820Sjeffstatic inline int get_is_sdp_socket(int fd) 311219820Sjeff{ 312219820Sjeff if (is_valid_fd(fd)) 313219820Sjeff return libsdp_fd_attributes[fd].is_sdp; 314219820Sjeff else 315219820Sjeff return 0; 316219820Sjeff} 317219820Sjeff 318219820Sjeff/* ========================================================================= */ 319219820Sjeff/*..last_accept_was_tcp -- given an fd return 1 if last accept was tcp */ 320219820Sjeffstatic inline int last_accept_was_tcp(int fd) 321219820Sjeff{ 322219820Sjeff if (is_valid_fd(fd)) 323219820Sjeff return libsdp_fd_attributes[fd].last_accept_was_tcp; 324219820Sjeff else 325219820Sjeff return 0; 326219820Sjeff} 327219820Sjeff 328219820Sjeff/* ========================================================================= */ 329219820Sjeff/*..set_last_accept -- given an fd set last accept was tcp */ 330219820Sjeffstatic inline void set_last_accept(int fd, int was_tcp) 331219820Sjeff{ 332219820Sjeff if (is_valid_fd(fd)) 333219820Sjeff libsdp_fd_attributes[fd].last_accept_was_tcp = was_tcp; 334219820Sjeff} 335219820Sjeff 336219820Sjeff/* ========================================================================= */ 337219820Sjeff/*..cleanup_shadow -- an error occured on an SDP socket, cleanup */ 338219820Sjeffstatic int cleanup_shadow(int fd) 339219820Sjeff{ 340219820Sjeff int shadow_fd = get_shadow_fd_by_fd(fd); 341219820Sjeff 342219820Sjeff if (shadow_fd == -1) 343219820Sjeff return 0; 344219820Sjeff libsdp_fd_attributes[fd].shadow_fd = -1; 345219820Sjeff libsdp_fd_attributes[fd].last_accept_was_tcp = 0; 346219820Sjeff return (_socket_funcs.close(shadow_fd)); 347219820Sjeff} /* cleanup_shadow */ 348219820Sjeff 349219820Sjeff/* ========================================================================= */ 350219820Sjeff/*..replace_fd_with_its_shadow -- perform all required for such promotion */ 351219820Sjeffstatic int replace_fd_with_its_shadow(int fd) 352219820Sjeff{ 353219820Sjeff int shadow_fd = libsdp_fd_attributes[fd].shadow_fd; 354219820Sjeff 355219820Sjeff if (shadow_fd == -1) { 356219820Sjeff __sdp_log(9, "Error replace_fd_with_its_shadow: no shadow for fd:%d\n", 357219820Sjeff fd); 358219820Sjeff return EINVAL; 359219820Sjeff } 360219820Sjeff 361219820Sjeff /* copy the attributes of the shadow before we clean them up */ 362219820Sjeff libsdp_fd_attributes[fd] = libsdp_fd_attributes[shadow_fd]; 363219820Sjeff libsdp_fd_attributes[fd].shadow_fd = -1; 364219820Sjeff if (_socket_funcs.dup2(shadow_fd, fd) < 0) { 365219820Sjeff init_extra_attribute(fd); 366219820Sjeff _socket_funcs.close(shadow_fd); 367219820Sjeff return EINVAL; 368219820Sjeff } 369219820Sjeff _socket_funcs.close(shadow_fd); 370219820Sjeff return 0; 371219820Sjeff} 372219820Sjeff 373219820Sjeffstatic sa_family_t get_sdp_domain(int domain) 374219820Sjeff{ 375219820Sjeff if (AF_INET_SDP == domain || AF_INET6_SDP == domain) 376219820Sjeff return domain; 377219820Sjeff 378219820Sjeff if (AF_INET == domain) 379219820Sjeff return AF_INET_SDP; 380219820Sjeff else if (AF_INET6 == domain) 381219820Sjeff return AF_INET6_SDP; 382219820Sjeff 383219820Sjeff __sdp_log(9, "Error %s: unknown TCP domain: %d\n", __func__, domain); 384219820Sjeff 385219820Sjeff return -1; 386219820Sjeff} 387219820Sjeff 388219820Sjeffstatic int get_sock_domain(int sd) 389219820Sjeff{ 390219820Sjeff struct sockaddr_storage tmp_sin; 391219820Sjeff socklen_t tmp_sinlen = sizeof(tmp_sin); 392219820Sjeff 393219820Sjeff if (_socket_funcs.getsockname(sd, (struct sockaddr *) &tmp_sin, &tmp_sinlen) < 0) { 394219820Sjeff __sdp_log(9, "Error %s: getsockname return <%d> for socket\n", __func__, errno); 395219820Sjeff return -1; 396219820Sjeff } 397219820Sjeff 398219820Sjeff return ((struct sockaddr *)&tmp_sin)->sa_family; 399219820Sjeff} 400219820Sjeff 401219820Sjeff/* ========================================================================= */ 402219820Sjeff/*..is_filtered_unsuported_sockopt -- return 1 if to filter sockopt failure */ 403219820Sjeffstatic inline int is_filtered_unsuported_sockopt(int level, int optname) 404219820Sjeff{ 405219820Sjeff /* 406219820Sjeff * TODO: until we know exactly which unsupported opts are really 407219820Sjeff * a don't care we always pass the error 408219820Sjeff */ 409219820Sjeff return 0; 410219820Sjeff#if 0 411219820Sjeff /* these are the SOL_TCP OPTS we should consider filterring */ 412219820Sjeff TCP_NODELAY 1 /* Don't delay send to coalesce packets */ 413219820Sjeff TCP_MAXSEG 2 /* Set maximum segment size */ 414219820Sjeff TCP_CORK 3 /* Control sending of partial frames */ 415219820Sjeff TCP_KEEPIDLE 4 /* Start keeplives after this period */ 416219820Sjeff TCP_KEEPINTVL 5 /* Interval between keepalives */ 417219820Sjeff TCP_KEEPCNT 6 /* Number of keepalives before death */ 418219820Sjeff TCP_SYNCNT 7 /* Number of SYN retransmits */ 419219820Sjeff TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */ 420219820Sjeff TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */ 421219820Sjeff TCP_WINDOW_CLAMP 10 /* Bound advertised window */ 422219820Sjeff TCP_INFO 11 /* Information about this connection. */ 423219820Sjeff TCP_QUICKACK 12 /* Bock/reenable quick ACKs. */ 424219820Sjeff#endif 425219820Sjeff} 426219820Sjeff 427219820Sjeff/* ========================================================================= */ 428219820Sjeff/*..is_invalid_addr -- return 1 if given pointer is not valid */ 429219820Sjeff/* NOTE: invalidation of the size is going to happen during actual call */ 430219820Sjeffstatic inline int is_invalid_addr(const void *p) 431219820Sjeff{ 432219820Sjeff /* HACK: on some systems we can not write to check for pointer validity */ 433219820Sjeff size_t ret = fcntl(dev_null_fd, F_GETLK, p); 434219820Sjeff 435219820Sjeff ret = (errno == EFAULT); 436219820Sjeff errno = 0; 437219820Sjeff return ret; 438219820Sjeff} 439219820Sjeff 440219820Sjeff/* ========================================================================= */ 441219820Sjeff/*..get_addr_str -- fill in the given buffer with addr str or return 1 */ 442219820Sjeffstatic int get_addr_str(const struct sockaddr *addr, char *buf, size_t len) 443219820Sjeff{ 444219820Sjeff const struct sockaddr_in *sin = (struct sockaddr_in *) addr; 445219820Sjeff const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr; 446219820Sjeff char const *conv_res; 447219820Sjeff 448219820Sjeff if (sin->sin_family == AF_INET) { 449219820Sjeff conv_res = inet_ntop(AF_INET, (void *) &(sin->sin_addr), buf, len); 450219820Sjeff } else if (sin6->sin6_family == AF_INET6) { 451219820Sjeff conv_res = inet_ntop(AF_INET6, (void *) &sin6->sin6_addr, buf, len); 452219820Sjeff } else { 453219820Sjeff strncpy(buf, "unknown address family", len); 454219820Sjeff conv_res = (char *) 1; 455219820Sjeff } 456219820Sjeff return conv_res == NULL; 457219820Sjeff} 458219820Sjeff 459219820Sjeff/* --------------------------------------------------------------------- */ 460219820Sjeff/* */ 461219820Sjeff/* Socket library function overrides. */ 462219820Sjeff/* */ 463219820Sjeff/* --------------------------------------------------------------------- */ 464219820Sjeff 465219820Sjeff/* ========================================================================= */ 466219820Sjeff/*..ioctl -- replacement ioctl call. */ 467219820Sjeffint 468219820Sjeffioctl(int fd, 469219820Sjeff int request, 470219820Sjeff void *arg0, 471219820Sjeff void *arg1, 472219820Sjeff void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7) 473219820Sjeff{ 474219820Sjeff int shadow_fd; 475219820Sjeff int sret = 0; 476219820Sjeff int ret = 0; 477219820Sjeff 478219820Sjeff if (init_status == 0) 479219820Sjeff __sdp_init(); 480219820Sjeff 481219820Sjeff if (NULL == _socket_funcs.ioctl) { 482219820Sjeff __sdp_log(9, "Error ioctl: no implementation for ioctl found\n"); 483219820Sjeff return -1; 484219820Sjeff } 485219820Sjeff 486219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 487219820Sjeff 488219820Sjeff __sdp_log(2, "IOCTL: <%s:%d:%d> request <%d>\n", 489219820Sjeff program_invocation_short_name, fd, shadow_fd, request); 490219820Sjeff 491219820Sjeff ret = _socket_funcs.ioctl(fd, request, 492219820Sjeff arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); 493219820Sjeff 494219820Sjeff /* HACK: avoid failing on FIONREAD error as SDP does not support it at the moment */ 495219820Sjeff if ((ret < 0) && get_is_sdp_socket(fd) && (request == FIONREAD)) { 496219820Sjeff __sdp_log(8, "Warning ioctl: " 497219820Sjeff "Ignoring FIONREAD error for SDP socket.\n"); 498219820Sjeff ret = 0; 499219820Sjeff } 500219820Sjeff 501219820Sjeff /* if shadow and no error on tcp */ 502219820Sjeff if ((ret >= 0) && (-1 != shadow_fd)) { 503219820Sjeff sret = _socket_funcs.ioctl(shadow_fd, request, 504219820Sjeff arg0, arg1, arg2, arg3, arg4, arg5, arg6, 505219820Sjeff arg7); 506219820Sjeff /* HACK: avoid failing on FIONREAD error as SDP does not support it at the moment */ 507219820Sjeff if ((sret < 0) && (request == FIONREAD)) { 508219820Sjeff __sdp_log(8, "Warning ioctl: " 509219820Sjeff "Ignoring FIONREAD error for shadow SDP socket.\n"); 510219820Sjeff sret = 0; 511219820Sjeff } 512219820Sjeff 513219820Sjeff if (sret < 0) { 514219820Sjeff __sdp_log(9, "Error ioctl: " 515219820Sjeff "<%d> calling ioctl for SDP socket, closing it.\n", 516219820Sjeff errno); 517219820Sjeff cleanup_shadow(fd); 518219820Sjeff } 519219820Sjeff } 520219820Sjeff 521219820Sjeff __sdp_log(2, "IOCTL: <%s:%d:%d> result <%d:%d>\n", 522219820Sjeff program_invocation_short_name, fd, shadow_fd, ret, sret); 523219820Sjeff 524219820Sjeff return ret; 525219820Sjeff} /* ioctl */ 526219820Sjeff 527219820Sjeff/* ========================================================================= */ 528219820Sjeff/*..fcntl -- replacement fcntl call. */ 529219820Sjeffint fcntl(int fd, int cmd, ...) 530219820Sjeff{ 531219820Sjeff int shadow_fd; 532219820Sjeff int sret = 0; 533219820Sjeff int ret = 0; 534219820Sjeff 535219820Sjeff void *arg; 536219820Sjeff va_list ap; 537219820Sjeff 538219820Sjeff va_start(ap, cmd); 539219820Sjeff arg = va_arg(ap, void *); 540219820Sjeff va_end(ap); 541219820Sjeff 542219820Sjeff 543219820Sjeff if (init_status == 0) 544219820Sjeff __sdp_init(); 545219820Sjeff 546219820Sjeff if (NULL == _socket_funcs.fcntl) { 547219820Sjeff __sdp_log(9, "Error fcntl: no implementation for fcntl found\n"); 548219820Sjeff return -1; 549219820Sjeff } 550219820Sjeff 551219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 552219820Sjeff 553219820Sjeff __sdp_log(2, "FCNTL: <%s:%d:%d> command <%d> argument <%p>\n", 554219820Sjeff program_invocation_short_name, fd, shadow_fd, cmd, arg); 555219820Sjeff 556219820Sjeff ret = _socket_funcs.fcntl(fd, cmd, arg); 557219820Sjeff if ((ret >= 0) && (-1 != shadow_fd)) { 558219820Sjeff sret = _socket_funcs.fcntl(shadow_fd, cmd, arg); 559219820Sjeff if (sret < 0) { 560219820Sjeff __sdp_log(9, "Error fcntl:" 561219820Sjeff " <%d> calling fcntl(%d, %d, %p) for SDP socket. Closing it.\n", 562219820Sjeff shadow_fd, cmd, arg, errno); 563219820Sjeff cleanup_shadow(fd); 564219820Sjeff } 565219820Sjeff } 566219820Sjeff 567219820Sjeff __sdp_log(2, "FCNTL: <%s:%d:%d> result <%d:%d>\n", 568219820Sjeff program_invocation_short_name, fd, shadow_fd, ret, sret); 569219820Sjeff 570219820Sjeff return ret; 571219820Sjeff} /* fcntl */ 572219820Sjeff 573219820Sjeff/* ========================================================================= */ 574219820Sjeff/*..setsockopt -- replacement setsockopt call. */ 575219820Sjeffint 576219820Sjeffsetsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) 577219820Sjeff{ 578219820Sjeff int shadow_fd; 579219820Sjeff int sret = 0; 580219820Sjeff int ret = 0; 581219820Sjeff 582219820Sjeff if (init_status == 0) 583219820Sjeff __sdp_init(); 584219820Sjeff 585219820Sjeff if (NULL == _socket_funcs.setsockopt) { 586219820Sjeff __sdp_log(9, "Error setsockopt:" 587219820Sjeff " no implementation for setsockopt found\n"); 588219820Sjeff return -1; 589219820Sjeff } 590219820Sjeff 591219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 592219820Sjeff 593219820Sjeff __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> level <%d> name <%d>\n", 594219820Sjeff program_invocation_short_name, fd, shadow_fd, level, optname); 595219820Sjeff 596219820Sjeff if (level == SOL_SOCKET && optname == SO_KEEPALIVE && get_is_sdp_socket(fd)) { 597219820Sjeff level = AF_INET_SDP; 598219820Sjeff __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> substitute level %d\n", 599219820Sjeff program_invocation_short_name, fd, shadow_fd, level); 600219820Sjeff } 601219820Sjeff 602219820Sjeff ret = _socket_funcs.setsockopt(fd, level, optname, optval, optlen); 603219820Sjeff if ((ret >= 0) && (shadow_fd != -1)) { 604219820Sjeff if (level == SOL_SOCKET && optname == SO_KEEPALIVE && 605219820Sjeff get_is_sdp_socket(shadow_fd)) { 606219820Sjeff level = AF_INET_SDP; 607219820Sjeff __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> substitute level %d\n", 608219820Sjeff program_invocation_short_name, fd, shadow_fd, level); 609219820Sjeff } 610219820Sjeff 611219820Sjeff sret = _socket_funcs.setsockopt(shadow_fd, level, optname, optval, optlen); 612219820Sjeff if (sret < 0) { 613219820Sjeff __sdp_log(8, "Warning sockopts:" 614219820Sjeff " ignoring error on shadow SDP socket fd:<%d>\n", fd); 615219820Sjeff /* 616219820Sjeff * HACK: we should allow some errors as some sock opts are unsupported 617219820Sjeff * __sdp_log(9, "Error %d calling setsockopt for SDP socket, closing\n", errno); 618219820Sjeff * cleanup_shadow(fd); 619219820Sjeff */ 620219820Sjeff } 621219820Sjeff } 622219820Sjeff 623219820Sjeff /* Due to SDP limited implmentation of sockopts we ignore some errors */ 624219820Sjeff if ((ret < 0) && get_is_sdp_socket(fd) && 625219820Sjeff is_filtered_unsuported_sockopt(level, optname)) { 626219820Sjeff __sdp_log(8, "Warning sockopts: " 627219820Sjeff "ignoring error on non implemented sockopt on SDP socket" 628219820Sjeff " fd:<%d> level:<%d> opt:<%d>\n", fd, level, optval); 629219820Sjeff ret = 0; 630219820Sjeff } 631219820Sjeff 632219820Sjeff __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> result <%d:%d>\n", 633219820Sjeff program_invocation_short_name, fd, shadow_fd, ret, sret); 634219820Sjeff 635219820Sjeff return ret; 636219820Sjeff} /* setsockopt */ 637219820Sjeff 638219820Sjeff/* ========================================================================= */ 639219820Sjeff/*..socket -- replacement socket call. */ 640219820Sjeff 641219820Sjeffstatic inline int __create_socket_semantic(int domain, 642219820Sjeff int type, 643219820Sjeff int protocol, int semantics) 644219820Sjeff{ 645219820Sjeff return 646219820Sjeff#ifdef SOLARIS_BUILD 647219820Sjeff (semantics == SOCKET_SEMANTIC_XNET) ? 648219820Sjeff _socket_xnet_funcs.socket(domain, type, protocol) : 649219820Sjeff#endif 650219820Sjeff _socket_funcs.socket(domain, type, protocol); 651219820Sjeff} 652219820Sjeff 653219820Sjeff/* Contains the main logic for creating shadow SDP sockets */ 654219820Sjeffstatic int __create_socket(int domain, int type, int protocol, int semantics) 655219820Sjeff{ 656219820Sjeff int s = -1; 657219820Sjeff int shadow_fd = -1; 658219820Sjeff use_family_t family_by_prog; 659219820Sjeff int sdp_domain; 660219820Sjeff 661219820Sjeff if (init_status == 0) 662219820Sjeff __sdp_init(); 663219820Sjeff 664219820Sjeff if (NULL == _socket_funcs.socket) { 665219820Sjeff __sdp_log(9, "Error socket: no implementation for socket found\n"); 666219820Sjeff return -1; 667219820Sjeff } 668219820Sjeff 669219820Sjeff __sdp_log(2, "SOCKET: <%s> domain <%d> type <%d> protocol <%d>\n", 670219820Sjeff program_invocation_short_name, domain, type, protocol); 671219820Sjeff 672219820Sjeff sdp_domain = get_sdp_domain(domain); 673219820Sjeff if (sdp_domain < 0) { 674219820Sjeff errno = EAFNOSUPPORT; 675219820Sjeff s = -1; 676219820Sjeff goto done; 677219820Sjeff } 678219820Sjeff 679219820Sjeff /* check to see if we can skip the shadow */ 680219820Sjeff if ((AF_INET == domain || AF_INET6 == domain) && (SOCK_STREAM == type)) 681219820Sjeff if (simple_sdp_library) 682219820Sjeff family_by_prog = USE_SDP; 683219820Sjeff else 684219820Sjeff family_by_prog = __sdp_match_by_program(); 685219820Sjeff else if (AF_INET_SDP == domain || AF_INET6_SDP == domain) 686219820Sjeff family_by_prog = USE_SDP; 687219820Sjeff else 688219820Sjeff family_by_prog = USE_TCP; 689219820Sjeff 690219820Sjeff if (family_by_prog == USE_TCP) { 691219820Sjeff __sdp_log(1, "SOCKET: making TCP only socket (no shadow)\n"); 692219820Sjeff s = __create_socket_semantic(domain, type, protocol, semantics); 693219820Sjeff init_extra_attribute(s); 694219820Sjeff set_is_sdp_socket(s, 0); 695219820Sjeff goto done; 696219820Sjeff } 697219820Sjeff 698219820Sjeff if (family_by_prog == USE_SDP) { 699219820Sjeff /* HACK: convert the protocol if IPPROTO_IP */ 700219820Sjeff if (protocol == 0) 701219820Sjeff protocol = IPPROTO_TCP; 702219820Sjeff 703219820Sjeff __sdp_log(1, "SOCKET: making SDP socket type:%d proto:%d\n", 704219820Sjeff type, protocol); 705219820Sjeff s = __create_socket_semantic(sdp_domain, type, protocol, semantics); 706219820Sjeff init_extra_attribute(s); 707219820Sjeff set_is_sdp_socket(s, 1); 708219820Sjeff goto done; 709219820Sjeff } 710219820Sjeff 711219820Sjeff /* HACK: if we fail creating the TCP socket should we abort ? */ 712219820Sjeff __sdp_log(1, "SOCKET: making TCP socket\n"); 713219820Sjeff s = __create_socket_semantic(domain, type, protocol, semantics); 714219820Sjeff init_extra_attribute(s); 715219820Sjeff set_is_sdp_socket(s, 0); 716219820Sjeff if (is_valid_fd(s)) { 717219820Sjeff if (((AF_INET == domain) || (AF_INET6 == domain)) && 718219820Sjeff (SOCK_STREAM == type)) { 719219820Sjeff 720219820Sjeff if (protocol == 0) 721219820Sjeff protocol = IPPROTO_TCP; 722219820Sjeff __sdp_log(1, "SOCKET: making SDP shadow socket type:%d proto:%d\n", 723219820Sjeff type, protocol); 724219820Sjeff shadow_fd = 725219820Sjeff __create_socket_semantic(sdp_domain, type, protocol, 726219820Sjeff semantics); 727219820Sjeff if (is_valid_fd(shadow_fd)) { 728219820Sjeff init_extra_attribute(shadow_fd); 729219820Sjeff if (libsdp_fd_attributes[s].shadow_fd != -1) { 730219820Sjeff __sdp_log(8, "Warning socket: " 731219820Sjeff "overriding existing shadow fd:%d for fd:%d\n", 732219820Sjeff libsdp_fd_attributes[s].shadow_fd, s); 733219820Sjeff } 734219820Sjeff set_is_sdp_socket(shadow_fd, 1); 735219820Sjeff set_shadow_for_fd(s, shadow_fd); 736219820Sjeff } else { 737219820Sjeff __sdp_log(9, 738219820Sjeff "Error socket: <%d> calling socket for SDP socket\n", 739219820Sjeff errno); 740219820Sjeff /* fail if we did not make the SDP socket */ 741219820Sjeff __sdp_log(1, "SOCKET: closing TCP socket:<%d>\n", s); 742219820Sjeff _socket_funcs.close(s); 743219820Sjeff s = -1; 744219820Sjeff } 745219820Sjeff } 746219820Sjeff } else { 747219820Sjeff __sdp_log(9, "Error socket: " 748219820Sjeff "ignoring SDP socket since TCP fd:%d out of range\n", s); 749219820Sjeff } 750219820Sjeff 751219820Sjeffdone: 752219820Sjeff __sdp_log(2, "SOCKET: <%s:%d:%d>\n", 753219820Sjeff program_invocation_short_name, s, shadow_fd); 754219820Sjeff 755219820Sjeff return s; 756219820Sjeff} /* socket */ 757219820Sjeff 758219820Sjeffint socket(int domain, int type, int protocol) 759219820Sjeff{ 760219820Sjeff return __create_socket(domain, type, protocol, SOCKET_SEMANTIC_DEFAULT); 761219820Sjeff} 762219820Sjeff 763219820Sjeff#ifdef SOLARIS_BUILD 764219820Sjeffint __xnet_socket(int domain, int type, int protocol) 765219820Sjeff{ 766219820Sjeff return __create_socket(domain, type, protocol, SOCKET_SEMANTIC_XNET); 767219820Sjeff} 768219820Sjeff#endif 769219820Sjeff 770219820Sjeff/* ========================================================================= */ 771219820Sjeff/*..get_fd_addr_port_num - obtain the port the fd is attached to */ 772219820Sjeffstatic int get_fd_addr_port_num(int sd) 773219820Sjeff{ 774219820Sjeff struct sockaddr_storage addr; 775219820Sjeff int ret; 776219820Sjeff const struct sockaddr_in *sin; 777219820Sjeff socklen_t addrlen = sizeof(addr); 778219820Sjeff 779219820Sjeff ret = _socket_funcs.getsockname(sd, (struct sockaddr *) &addr, &addrlen); 780219820Sjeff 781219820Sjeff if (ret) { 782219820Sjeff __sdp_log(9, "Error: in get_fd_addr_port_num - Failed to get getsockname\n"); 783219820Sjeff return -1; 784219820Sjeff } 785219820Sjeff 786219820Sjeff /* port num is in same location for IPv4 and IPv6 */ 787219820Sjeff sin = (const struct sockaddr_in *) &addr; 788219820Sjeff return ntohs(sin->sin_port); 789219820Sjeff} 790219820Sjeff 791219820Sjeff/* ========================================================================= */ 792219820Sjeff/*..set_addr_port_num - sets the port in the given address */ 793219820Sjeffstatic int set_addr_port_num(const struct sockaddr *addr, int port) 794219820Sjeff{ 795219820Sjeff struct sockaddr_in *sin = (struct sockaddr_in *) addr; 796219820Sjeff 797219820Sjeff /* port num is in same location for IPv4 and IPv6 */ 798219820Sjeff sin->sin_port = htons(port); 799219820Sjeff return 0; 800219820Sjeff} 801219820Sjeff 802219820Sjeff/* ========================================================================= */ 803219820Sjeff/* perform a bind with the given socket semantics */ 804219820Sjeffstatic inline int 805219820Sjeff__bind_semantics(int fd, 806219820Sjeff const struct sockaddr *my_addr, 807219820Sjeff socklen_t addrlen, int semantics) 808219820Sjeff{ 809219820Sjeff return 810219820Sjeff#ifdef SOLARIS_BUILD 811219820Sjeff (semantics == SOCKET_SEMANTIC_XNET) ? 812219820Sjeff _socket_xnet_funcs.bind(fd, my_addr, addrlen) : 813219820Sjeff#endif 814219820Sjeff _socket_funcs.bind(fd, my_addr, addrlen); 815219820Sjeff} 816219820Sjeff 817219820Sjeff/* ========================================================================= */ 818219820Sjeff/*..find_free_port - find same free port on both TCP and SDP */ 819219820Sjeff#define MAX_BIND_ANY_PORT_TRIES 20000 820219820Sjeffstatic int 821219820Sjefffind_free_port(const struct sockaddr *sin_addr, 822219820Sjeff const socklen_t addrlen, 823219820Sjeff int orig_sd, 824219820Sjeff int *sdp_sd, int *tcp_sd, int semantics) 825219820Sjeff{ 826219820Sjeff static int tcp_turn = 1; 827219820Sjeff int tmp_turn = tcp_turn; 828219820Sjeff int num_of_loops = 0; 829219820Sjeff int port = -1; 830219820Sjeff int tmp_sd[2]; 831219820Sjeff unsigned int yes = 1; 832219820Sjeff int ret; 833219820Sjeff int domain, sdp_domain; 834219820Sjeff 835219820Sjeff __sdp_log(2, "find_free_port: starting search for common free port\n"); 836219820Sjeff 837219820Sjeff /* need to obtain the address family from the fd */ 838219820Sjeff domain = get_sock_domain(orig_sd); 839219820Sjeff if (domain == -1) { 840219820Sjeff errno = EFAULT; 841219820Sjeff goto done; 842219820Sjeff } 843219820Sjeff 844219820Sjeff sdp_domain = get_sdp_domain(domain); 845219820Sjeff if (sdp_domain < 0) { 846219820Sjeff errno = EFAULT; 847219820Sjeff goto done; 848219820Sjeff } 849219820Sjeff 850219820Sjeff do { 851219820Sjeff __sdp_log(1, "find_free_port: taking loop (%d)\n", ++num_of_loops); 852219820Sjeff 853219820Sjeff __sdp_log(1, "find_free_port: creating the two sockets\n"); 854219820Sjeff tmp_sd[0] = _socket_funcs.socket(sdp_domain, SOCK_STREAM, IPPROTO_TCP); 855219820Sjeff if (tmp_sd[0] < 0) { 856219820Sjeff __sdp_log(8, "Warning find_free_port: creating first socket failed\n"); 857219820Sjeff goto done; 858219820Sjeff } 859219820Sjeff 860219820Sjeff _socket_funcs.setsockopt(tmp_sd[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); 861219820Sjeff 862219820Sjeff tmp_sd[1] = _socket_funcs.socket(domain, SOCK_STREAM, IPPROTO_TCP); 863219820Sjeff if (tmp_sd[1] < 0) { 864219820Sjeff __sdp_log(8, "Warning find_free_port: creating second socket failed\n"); 865219820Sjeff _socket_funcs.close(tmp_sd[0]); 866219820Sjeff goto done; 867219820Sjeff } 868219820Sjeff 869219820Sjeff _socket_funcs.setsockopt(tmp_sd[1], SOL_SOCKET, SO_REUSEADDR, &yes, 870219820Sjeff sizeof(yes)); 871219820Sjeff 872219820Sjeff __sdp_log(1, "find_free_port: binding first %s socket\n", 873219820Sjeff tmp_turn ? "tcp" : "sdp"); 874219820Sjeff ret = __bind_semantics(tmp_sd[tmp_turn], sin_addr, addrlen, semantics); 875219820Sjeff if (ret < 0) { 876219820Sjeff __sdp_log(8, 877219820Sjeff "Warning find_free_port: binding first socket failed:%s\n", 878219820Sjeff strerror(errno)); 879219820Sjeff _socket_funcs.close(tmp_sd[0]); 880219820Sjeff _socket_funcs.close(tmp_sd[1]); 881219820Sjeff goto done; 882219820Sjeff } 883219820Sjeff 884219820Sjeff __sdp_log(1, "find_free_port: listening on first socket\n"); 885219820Sjeff ret = _socket_funcs.listen(tmp_sd[tmp_turn], 5); 886219820Sjeff if (ret < 0) { 887219820Sjeff __sdp_log(8, "Warning find_free_port: listening on first socket failed:%s\n", 888219820Sjeff strerror(errno)); 889219820Sjeff _socket_funcs.close(tmp_sd[0]); 890219820Sjeff _socket_funcs.close(tmp_sd[1]); 891219820Sjeff goto done; 892219820Sjeff } 893219820Sjeff 894219820Sjeff port = get_fd_addr_port_num(tmp_sd[tmp_turn]); 895219820Sjeff if (port < 0) { 896219820Sjeff __sdp_log(8, "Warning find_free_port: first socket port:%d < 0\n", 897219820Sjeff port); 898219820Sjeff _socket_funcs.close(tmp_sd[0]); 899219820Sjeff _socket_funcs.close(tmp_sd[1]); 900219820Sjeff goto done; 901219820Sjeff } 902219820Sjeff __sdp_log(1, "find_free_port: first socket port:%u\n", port); 903219820Sjeff 904219820Sjeff set_addr_port_num(sin_addr, port); 905219820Sjeff 906219820Sjeff __sdp_log(1, "find_free_port: binding second socket\n"); 907219820Sjeff ret = __bind_semantics(tmp_sd[1 - tmp_turn], sin_addr, addrlen, semantics); 908219820Sjeff if (ret < 0) { 909219820Sjeff /* bind() for sdp socket failed. It is acceptable only 910219820Sjeff * if the IP is not part of IB network. */ 911219820Sjeff 912219820Sjeff if (errno != EADDRINUSE) { 913219820Sjeff __sdp_log(8, "Warning find_free_port: " 914219820Sjeff "binding second socket failed with %s\n", 915219820Sjeff strerror(errno)); 916219820Sjeff goto close_and_mark; 917219820Sjeff } else { 918219820Sjeff int err; 919219820Sjeff#ifdef __linux__ 920219820Sjeff socklen_t len = sizeof(int); 921219820Sjeff 922219820Sjeff ret = getsockopt(tmp_sd[1 - tmp_turn], SOL_TCP, 923219820Sjeff SDP_LAST_BIND_ERR, &err, &len); 924219820Sjeff if (-1 == ret) { 925219820Sjeff __sdp_log(9, "Error %s:getsockopt: %s\n", 926219820Sjeff __func__, strerror(errno)); 927219820Sjeff goto close_and_mark; 928219820Sjeff } 929219820Sjeff#else 930219820Sjeff err = -errno; 931219820Sjeff#endif 932219820Sjeff if (-ENOENT == err || -EADDRINUSE != err) { 933219820Sjeff /* bind() failed due to either: 934219820Sjeff * 1. IP is ETH, not IB, so can't bind() to sdp socket. 935219820Sjeff * 2. real error. 936219820Sjeff * Continue only with TCP */ 937219820Sjeff goto close_and_mark; 938219820Sjeff } 939219820Sjeff __sdp_log(1, "find_free_port: %s port %u was busy\n", 940219820Sjeff 1 - tmp_turn ? "tcp" : "sdp", 941219820Sjeff ntohs(((const struct sockaddr_in *)sin_addr)->sin_port)); 942219820Sjeff } 943219820Sjeff 944219820Sjeff /* close the sockets - we will need new ones ... */ 945219820Sjeff __sdp_log(1, 946219820Sjeff "find_free_port: closing the two sockets before next loop\n"); 947219820Sjeff _socket_funcs.close(tmp_sd[0]); 948219820Sjeff _socket_funcs.close(tmp_sd[1]); 949219820Sjeff 950219820Sjeff port = -1; 951219820Sjeff /* we always start with tcp so we keep the original setting for now */ 952219820Sjeff /* tmp_turn = 1 - tmp_turn; */ 953219820Sjeff } 954219820Sjeff 955219820Sjeff } while ((port < 0) && (num_of_loops < MAX_BIND_ANY_PORT_TRIES)); 956219820Sjeff 957219820Sjeffsetfds: 958219820Sjeff tcp_turn = tmp_turn; 959219820Sjeff *sdp_sd = tmp_sd[0]; 960219820Sjeff *tcp_sd = tmp_sd[1]; 961219820Sjeff 962219820Sjeffdone: 963219820Sjeff __sdp_log(2, "find_free_port: return port:<%d>\n", port); 964219820Sjeff return port; 965219820Sjeff 966219820Sjeffclose_and_mark: 967219820Sjeff _socket_funcs.close(tmp_sd[0]); 968219820Sjeff tmp_sd[0] = -1; /* mark with error */ 969219820Sjeff goto setfds; 970219820Sjeff 971219820Sjeff} 972219820Sjeff 973219820Sjeff/* ========================================================================= */ 974219820Sjeff/*..check_legal_bind - check if given address is okay for both TCP and SDP */ 975219820Sjeffstatic int 976219820Sjeffcheck_legal_bind(const struct sockaddr *sin_addr, 977219820Sjeff const socklen_t addrlen, 978219820Sjeff int orig_sd, 979219820Sjeff int *sdp_sd, int *tcp_sd, int semantics) 980219820Sjeff{ 981219820Sjeff unsigned int yes = 1; 982219820Sjeff int ret = -1; 983219820Sjeff int sret = -1; 984219820Sjeff int domain, sdp_domain; 985219820Sjeff 986219820Sjeff /* need to obtain the address family from the fd */ 987219820Sjeff domain = get_sock_domain(orig_sd); 988219820Sjeff if (domain == -1) { 989219820Sjeff errno = EFAULT; 990219820Sjeff ret = -1; 991219820Sjeff goto done; 992219820Sjeff } 993219820Sjeff 994219820Sjeff sdp_domain = get_sdp_domain(domain); 995219820Sjeff if (sdp_domain < 0) { 996219820Sjeff errno = EFAULT; 997219820Sjeff goto done; 998219820Sjeff } 999219820Sjeff 1000219820Sjeff __sdp_log(2, "check_legal_bind: binding two temporary sockets\n"); 1001219820Sjeff *sdp_sd = _socket_funcs.socket(sdp_domain, SOCK_STREAM, IPPROTO_TCP); 1002219820Sjeff if (*sdp_sd < 0) { 1003219820Sjeff __sdp_log(9, "Error check_legal_bind: " "creating SDP socket failed\n"); 1004219820Sjeff goto done; 1005219820Sjeff } 1006219820Sjeff 1007219820Sjeff __sdp_log(2, "check_legal_bind: reusing <%d> \n", *sdp_sd); 1008219820Sjeff sret = 1009219820Sjeff _socket_funcs.setsockopt(*sdp_sd, SOL_SOCKET, SO_REUSEADDR, &yes, 1010219820Sjeff sizeof(yes)); 1011219820Sjeff if (sret < 0) { 1012219820Sjeff __sdp_log(9, "Error bind: Could not setsockopt sdp_sd\n"); 1013219820Sjeff } 1014219820Sjeff 1015219820Sjeff *tcp_sd = _socket_funcs.socket(domain, SOCK_STREAM, IPPROTO_TCP); 1016219820Sjeff if (*tcp_sd < 0) { 1017219820Sjeff __sdp_log(9, "Error check_legal_bind: " 1018219820Sjeff "creating second socket failed:%s\n", strerror(errno)); 1019219820Sjeff _socket_funcs.close(*sdp_sd); 1020219820Sjeff goto done; 1021219820Sjeff } 1022219820Sjeff 1023219820Sjeff __sdp_log(2, "check_legal_bind: reusing <%d> \n", *tcp_sd); 1024219820Sjeff sret = 1025219820Sjeff _socket_funcs.setsockopt(*tcp_sd, SOL_SOCKET, SO_REUSEADDR, &yes, 1026219820Sjeff sizeof(yes)); 1027219820Sjeff if (sret < 0) { 1028219820Sjeff __sdp_log(9, "Error bind: Could not setsockopt tcp_sd\n"); 1029219820Sjeff } 1030219820Sjeff 1031219820Sjeff __sdp_log(1, "check_legal_bind: binding SDP socket\n"); 1032219820Sjeff ret = __bind_semantics(*sdp_sd, sin_addr, addrlen, semantics); 1033219820Sjeff if (ret < 0) { 1034219820Sjeff /* bind() for sdp socket failed. It is acceptable only if 1035219820Sjeff * the IP is not part of IB network. */ 1036219820Sjeff int err; 1037219820Sjeff socklen_t len = sizeof(int); 1038219820Sjeff 1039219820Sjeff if (EADDRINUSE != errno) 1040219820Sjeff goto done; 1041219820Sjeff#ifdef __linux__ 1042219820Sjeff if (-1 == getsockopt(*sdp_sd, SOL_TCP, SDP_LAST_BIND_ERR, &err, &len)) { 1043219820Sjeff __sdp_log(9, "Error check_legal_bind:getsockopt: %s\n", 1044219820Sjeff strerror(errno)); 1045219820Sjeff goto done; 1046219820Sjeff } 1047219820Sjeff#else 1048219820Sjeff err = -errno; 1049219820Sjeff#endif 1050219820Sjeff if (-ENOENT != err) { 1051219820Sjeff /* bind() failed due to real error. Can't continue */ 1052219820Sjeff __sdp_log(9, "Error check_legal_bind: " 1053219820Sjeff "binding SDP socket failed:%s\n", strerror(errno)); 1054219820Sjeff _socket_funcs.close(*sdp_sd); 1055219820Sjeff _socket_funcs.close(*tcp_sd); 1056219820Sjeff 1057219820Sjeff /* TCP and SDP without library return EINVAL */ 1058219820Sjeff if (errno == EADDRINUSE) 1059219820Sjeff errno = EINVAL; 1060219820Sjeff 1061219820Sjeff goto done; 1062219820Sjeff } 1063219820Sjeff /* IP is ETH, not IB, so can't bind() to sdp socket */ 1064219820Sjeff /* Continue only with TCP */ 1065219820Sjeff _socket_funcs.close(*sdp_sd); 1066219820Sjeff *sdp_sd = -1; 1067219820Sjeff } 1068219820Sjeff 1069219820Sjeff __sdp_log(1, "check_legal_bind: binding TCP socket\n"); 1070219820Sjeff ret = __bind_semantics(*tcp_sd, sin_addr, addrlen, semantics); 1071219820Sjeff if (ret < 0) { 1072219820Sjeff __sdp_log(9, "Error check_legal_bind: " 1073219820Sjeff "binding TCP socket failed:%s\n", strerror(errno)); 1074219820Sjeff if (-1 != *sdp_sd) 1075219820Sjeff _socket_funcs.close(*sdp_sd); 1076219820Sjeff _socket_funcs.close(*tcp_sd); 1077219820Sjeff goto done; 1078219820Sjeff } 1079219820Sjeff ret = 0; 1080219820Sjeff __sdp_log(2, "check_legal_bind: result:<%d>\n", ret); 1081219820Sjeffdone: 1082219820Sjeff return ret; 1083219820Sjeff} 1084219820Sjeff 1085219820Sjeff/* ========================================================================= */ 1086219820Sjeff/*..close_and_bind - close an open fd and bind another one immediately */ 1087219820Sjeffstatic int 1088219820Sjeffclose_and_bind(int old_sd, 1089219820Sjeff int new_sd, 1090219820Sjeff const struct sockaddr *addr, socklen_t addrlen, int semantics) 1091219820Sjeff{ 1092219820Sjeff int ret; 1093219820Sjeff 1094219820Sjeff __sdp_log(2, "close_and_bind: closing <%d> binding <%d>\n", old_sd, new_sd); 1095219820Sjeff ret = _socket_funcs.close(old_sd); 1096219820Sjeff if (ret < 0) { 1097219820Sjeff __sdp_log(9, "Error bind: Could not close old_sd\n"); 1098219820Sjeff goto done; 1099219820Sjeff } 1100219820Sjeff 1101219820Sjeff ret = __bind_semantics(new_sd, addr, addrlen, semantics); 1102219820Sjeff if (ret < 0) 1103219820Sjeff __sdp_log(9, "Error bind: Could not bind new_sd\n"); 1104219820Sjeff 1105219820Sjeffdone: 1106219820Sjeff __sdp_log(2, "close_and_bind: returning <%d>\n", ret); 1107219820Sjeff return ret; 1108219820Sjeff} 1109219820Sjeff 1110219820Sjeff/* ========================================================================= */ 1111219820Sjeff/*..bind -- replacement bind call. */ 1112219820Sjeff/* 1113219820Sjeff As we do not know the role of this socket yet so we cannot choose AF. 1114219820Sjeff We need to be able to handle shadow too. 1115219820Sjeff SDP sockets (may be shadow or not) must be using converted address 1116219820Sjeff 1117219820Sjeff Since there is no way to "rebind" a socket we have to avoid "false" bind: 1118219820Sjeff 1. When the given address for the bind includes a port we need to 1119219820Sjeff guarantee the port is free on both address families. We do that 1120219820Sjeff by creating temporary sockets and biding them first. Then we close and 1121219820Sjeff re-use the address on the real sockets. 1122219820Sjeff 2. When ANY_PORT is requested we need to make sure the port we obtain from 1123219820Sjeff the first address family is also free on the second one. We use temporary 1124219820Sjeff sockets for that task too. We loop several times to find such common 1125219820Sjeff available socket 1126219820Sjeff*/ 1127219820Sjeffstatic int 1128219820Sjeff__perform_bind(int fd, 1129219820Sjeff const struct sockaddr *addr, socklen_t addrlen, int semantics) 1130219820Sjeff{ 1131219820Sjeff int shadow_fd; 1132219820Sjeff struct sockaddr_in *sin_addr = (struct sockaddr_in *) addr; 1133219820Sjeff int ret, sret = -1; 1134219820Sjeff char buf[MAX_ADDR_STR_LEN]; 1135219820Sjeff 1136219820Sjeff if (init_status == 0) 1137219820Sjeff __sdp_init(); 1138219820Sjeff 1139219820Sjeff if (NULL == _socket_funcs.bind) { 1140219820Sjeff __sdp_log(9, "Error bind: no implementation for bind found\n"); 1141219820Sjeff return -1; 1142219820Sjeff } 1143219820Sjeff 1144219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 1145219820Sjeff 1146219820Sjeff if ((addr == NULL) || is_invalid_addr(addr)) { 1147219820Sjeff errno = EFAULT; 1148219820Sjeff __sdp_log(9, "Error bind: illegal address provided\n"); 1149219820Sjeff return -1; 1150219820Sjeff } 1151219820Sjeff 1152219820Sjeff if (get_addr_str(addr, buf, MAX_ADDR_STR_LEN)) { 1153219820Sjeff __sdp_log(9, "Error bind: provided illegal address: %s\n", 1154219820Sjeff strerror(errno)); 1155219820Sjeff return -1; 1156219820Sjeff } 1157219820Sjeff 1158219820Sjeff __sdp_log(2, "BIND: <%s:%d:%d> type <%d> IP <%s> port <%d>\n", 1159219820Sjeff program_invocation_short_name, fd, shadow_fd, 1160219820Sjeff sin_addr->sin_family, buf, ntohs(sin_addr->sin_port)); 1161219820Sjeff 1162219820Sjeff if (get_is_sdp_socket(fd)) { 1163219820Sjeff __sdp_log(1, "BIND: binding SDP socket:<%d>\n", fd); 1164219820Sjeff ret = __bind_semantics(fd, addr, addrlen, semantics); 1165219820Sjeff goto done; 1166219820Sjeff } else if (shadow_fd != -1) { 1167219820Sjeff /* has shadow */ 1168219820Sjeff /* we need to validate the given address or find a common port 1169219820Sjeff * so we use the following tmp address and sockets */ 1170219820Sjeff struct sockaddr_storage tmp_addr; 1171219820Sjeff int sdp_sd = -1, tcp_sd = -1, port; 1172219820Sjeff 1173219820Sjeff memcpy(&tmp_addr, addr, addrlen); 1174219820Sjeff ret = 0; 1175219820Sjeff if (ntohs(sin_addr->sin_port) == 0) { 1176219820Sjeff /* When we get ANY_PORT we need to make sure that both TCP 1177219820Sjeff * and SDP sockets will use the same port */ 1178219820Sjeff 1179219820Sjeff port = find_free_port(addr, addrlen, fd, &sdp_sd, &tcp_sd, semantics); 1180219820Sjeff if (port < 0) { 1181219820Sjeff ret = -1; 1182219820Sjeff __sdp_log(9, "BIND: Failed to find common free port\n"); 1183219820Sjeff /* We cannot bind both tcp and sdp on the same port, we will close 1184219820Sjeff * the sdp and continue with tcp only */ 1185219820Sjeff goto done; 1186219820Sjeff } else { 1187219820Sjeff /* copy the port to the tmp address */ 1188219820Sjeff set_addr_port_num((struct sockaddr *) &tmp_addr, port); 1189219820Sjeff } 1190219820Sjeff } else { 1191219820Sjeff /* have a shadow but requested specific port - check that we 1192219820Sjeff * can actually bind the two addresses and then reuse */ 1193219820Sjeff ret = check_legal_bind(addr, addrlen, fd, &sdp_sd, &tcp_sd, semantics); 1194219820Sjeff if (ret < 0) { 1195219820Sjeff __sdp_log(9, "Error bind: " 1196219820Sjeff "Provided address can not bind on the two sockets\n"); 1197219820Sjeff } 1198219820Sjeff } 1199219820Sjeff 1200219820Sjeff /* if we fail to find a common port or given address can not be used 1201219820Sjeff * we return error */ 1202219820Sjeff if (ret < 0) { 1203219820Sjeff /* Temporary sockets already closed by check_legal_bind or 1204219820Sjeff * find_free_port */ 1205219820Sjeff errno = EADDRINUSE; 1206219820Sjeff goto done; 1207219820Sjeff } 1208219820Sjeff 1209219820Sjeff /* close temporary sockets and reuse their address */ 1210219820Sjeff /* HACK: close_and_bind might race with other applications. */ 1211219820Sjeff /* When the race occur we return EADDRINUSE */ 1212219820Sjeff ret = close_and_bind(tcp_sd, fd, (struct sockaddr *) &tmp_addr, 1213219820Sjeff addrlen, semantics); 1214219820Sjeff if (ret < 0) { 1215219820Sjeff __sdp_log(9, "Error bind: " "Could not close_and_bind TCP side\n"); 1216219820Sjeff if (-1 != sdp_sd) 1217219820Sjeff _socket_funcs.close(sdp_sd); 1218219820Sjeff goto done; 1219219820Sjeff } 1220219820Sjeff 1221219820Sjeff if (-1 != sdp_sd) { 1222219820Sjeff ret = close_and_bind(sdp_sd, shadow_fd, (struct sockaddr *) &tmp_addr, 1223219820Sjeff addrlen, semantics); 1224219820Sjeff 1225219820Sjeff if (ret < 0) { 1226219820Sjeff __sdp_log(9, 1227219820Sjeff "Error bind: " "Could not close_and_bind sdp side\n"); 1228219820Sjeff goto done; 1229219820Sjeff } 1230219820Sjeff } 1231219820Sjeff goto done; 1232219820Sjeff } 1233219820Sjeff 1234219820Sjeff /* we can only get here on single TCP socket */ 1235219820Sjeff __sdp_log(1, "BIND: binding TCP socket:<%d>\n", fd); 1236219820Sjeff ret = __bind_semantics(fd, addr, addrlen, semantics); 1237219820Sjeff 1238219820Sjeffdone: 1239219820Sjeff __sdp_log(2, "BIND: <%s:%d:%d> result <%d:%d>\n", 1240219820Sjeff program_invocation_short_name, fd, shadow_fd, ret, sret); 1241219820Sjeff 1242219820Sjeff return ret; 1243219820Sjeff} /* bind */ 1244219820Sjeff 1245219820Sjeff 1246219820Sjeffint bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen) 1247219820Sjeff{ 1248219820Sjeff return __perform_bind(fd, my_addr, addrlen, SOCKET_SEMANTIC_DEFAULT); 1249219820Sjeff} 1250219820Sjeff 1251219820Sjeff#ifdef SOLARIS_BUILD 1252219820Sjeffint __xnet_bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen) 1253219820Sjeff{ 1254219820Sjeff return __perform_bind(fd, my_addr, addrlen, SOCKET_SEMANTIC_XNET); 1255219820Sjeff} 1256219820Sjeff#endif 1257219820Sjeff 1258219820Sjeff 1259219820Sjeff/* ========================================================================= */ 1260219820Sjeff/*..connect -- replacement connect call. */ 1261219820Sjeff/* 1262219820Sjeff Given the connect address we can take out AF decision 1263219820Sjeff if target AF == both it means SDP and fall back to TCP 1264219820Sjeff if any connect worked we are fine 1265219820Sjeff*/ 1266219820Sjeffstatic inline int 1267219820Sjeff__connect_semantics(int fd, 1268219820Sjeff const struct sockaddr *serv_addr, 1269219820Sjeff socklen_t addrlen, int semantics) 1270219820Sjeff{ 1271219820Sjeff return 1272219820Sjeff#ifdef SOLARIS_BUILD 1273219820Sjeff (semantics == SOCKET_SEMANTIC_XNET) ? 1274219820Sjeff _socket_xnet_funcs.connect(fd, serv_addr, addrlen) : 1275219820Sjeff#endif 1276219820Sjeff _socket_funcs.connect(fd, serv_addr, addrlen); 1277219820Sjeff} 1278219820Sjeff 1279219820Sjeffstatic int 1280219820Sjeff__perform_connect(int fd, const struct sockaddr *serv_addr, 1281219820Sjeff socklen_t addrlen, int semantics) 1282219820Sjeff{ 1283219820Sjeff struct sockaddr_in *serv_sin = (struct sockaddr_in *) serv_addr; 1284219820Sjeff char buf[MAX_ADDR_STR_LEN]; 1285219820Sjeff int shadow_fd; 1286219820Sjeff int ret = -1, dup_ret; 1287219820Sjeff use_family_t target_family; 1288219820Sjeff int fopts; 1289219820Sjeff 1290219820Sjeff if (init_status == 0) 1291219820Sjeff __sdp_init(); 1292219820Sjeff 1293219820Sjeff if (NULL == _socket_funcs.connect) { 1294219820Sjeff __sdp_log(9, "Error connect: no implementation for connect found\n"); 1295219820Sjeff return -1; 1296219820Sjeff } 1297219820Sjeff 1298219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 1299219820Sjeff 1300219820Sjeff if ((serv_addr == NULL) || is_invalid_addr(serv_addr)) { 1301219820Sjeff errno = EFAULT; 1302219820Sjeff __sdp_log(9, "Error connect: illegal address provided\n"); 1303219820Sjeff return -1; 1304219820Sjeff } 1305219820Sjeff 1306219820Sjeff if (get_addr_str(serv_addr, buf, MAX_ADDR_STR_LEN)) { 1307219820Sjeff __sdp_log(9, "Error connect: provided illegal address: %s\n", 1308219820Sjeff strerror(errno)); 1309219820Sjeff return EADDRNOTAVAIL; 1310219820Sjeff } 1311219820Sjeff 1312219820Sjeff __sdp_log(2, "CONNECT: <%s:%d:%d> domain <%d> IP <%s> port <%d>\n", 1313219820Sjeff program_invocation_short_name, fd, shadow_fd, 1314219820Sjeff serv_sin->sin_family, buf, ntohs(serv_sin->sin_port)); 1315219820Sjeff 1316219820Sjeff 1317219820Sjeff /* obtain the target address family */ 1318219820Sjeff target_family = __sdp_match_connect(serv_addr, addrlen); 1319219820Sjeff 1320219820Sjeff /* if we do not have a shadow - just do the work */ 1321219820Sjeff if (shadow_fd == -1) { 1322219820Sjeff __sdp_log(1, "CONNECT: connectingthrough %s\n", 1323219820Sjeff get_is_sdp_socket(fd) ? "SDP" : "TCP"); 1324219820Sjeff ret = __connect_semantics(fd, serv_addr, addrlen, semantics); 1325219820Sjeff if ((ret == 0) || (errno == EINPROGRESS)) { 1326219820Sjeff __sdp_log(7, "CONNECT: connected SDP fd:%d to:%s port %d\n", 1327219820Sjeff fd, buf, ntohs(serv_sin->sin_port)); 1328219820Sjeff } 1329219820Sjeff goto done; 1330219820Sjeff } 1331219820Sjeff 1332219820Sjeff if ((target_family == USE_SDP) || (target_family == USE_BOTH)) { 1333219820Sjeff /* NOTE: the entire if sequence is negative logic */ 1334219820Sjeff __sdp_log(1, "CONNECT: connecting SDP fd:%d\n", shadow_fd); 1335219820Sjeff 1336219820Sjeff /* make the socket blocking on shadow SDP */ 1337219820Sjeff fopts = _socket_funcs.fcntl(shadow_fd, F_GETFL); 1338219820Sjeff if ((target_family == USE_BOTH) && (fopts & O_NONBLOCK)) { 1339219820Sjeff __sdp_log(1, 1340219820Sjeff "CONNECT: shadow_fd <%d> will be blocking during connect\n", 1341219820Sjeff shadow_fd); 1342219820Sjeff _socket_funcs.fcntl(shadow_fd, F_SETFL, fopts & (~O_NONBLOCK)); 1343219820Sjeff } 1344219820Sjeff 1345219820Sjeff ret = __connect_semantics(shadow_fd, serv_addr, addrlen, semantics); 1346219820Sjeff if ((ret < 0) && (errno != EINPROGRESS)) { 1347219820Sjeff __sdp_log(9, "Error connect: " 1348219820Sjeff "failed for SDP fd:%d with error:%m\n", shadow_fd); 1349219820Sjeff } else { 1350219820Sjeff __sdp_log(7, "CONNECT: connected SDP fd:%d to:%s port %d\n", 1351219820Sjeff fd, buf, ntohs(serv_sin->sin_port)); 1352219820Sjeff } 1353219820Sjeff 1354219820Sjeff /* restore socket options */ 1355219820Sjeff _socket_funcs.fcntl(shadow_fd, F_SETFL, fopts); 1356219820Sjeff 1357219820Sjeff /* if target is SDP or we succeeded we need to dup SDP fd into TCP fd */ 1358219820Sjeff if ((target_family == USE_SDP) || (ret >= 0)) { 1359219820Sjeff dup_ret = replace_fd_with_its_shadow(fd); 1360219820Sjeff if (dup_ret < 0) { 1361219820Sjeff __sdp_log(9, "Error connect: " 1362219820Sjeff "failed to dup2 shadow into orig fd:%d\n", fd); 1363219820Sjeff ret = dup_ret; 1364219820Sjeff } else { 1365219820Sjeff /* we can skip the TCP option if we are done */ 1366219820Sjeff __sdp_log(1, "CONNECT: " 1367219820Sjeff "matched SDP fd:%d so shadow dup into TCP\n", fd); 1368219820Sjeff goto done; 1369219820Sjeff } 1370219820Sjeff } 1371219820Sjeff } 1372219820Sjeff 1373219820Sjeff if ((target_family == USE_TCP) || (target_family == USE_BOTH)) { 1374219820Sjeff __sdp_log(1, "CONNECT: connecting TCP fd:%d\n", fd); 1375219820Sjeff ret = __connect_semantics(fd, serv_addr, addrlen, semantics); 1376219820Sjeff if ((ret < 0) && (errno != EINPROGRESS)) 1377219820Sjeff __sdp_log(9, "Error connect: for TCP fd:%d failed with error:%m\n", 1378219820Sjeff fd); 1379219820Sjeff else 1380219820Sjeff __sdp_log(7, "CONNECT: connected TCP fd:%d to:%s port %d\n", 1381219820Sjeff fd, buf, ntohs(serv_sin->sin_port)); 1382219820Sjeff 1383219820Sjeff if ((target_family == USE_TCP) || (ret >= 0) || (errno == EINPROGRESS)) { 1384219820Sjeff if (cleanup_shadow(fd) < 0) 1385219820Sjeff __sdp_log(9, 1386219820Sjeff "Error connect: failed to cleanup shadow for fd:%d\n", 1387219820Sjeff fd); 1388219820Sjeff } 1389219820Sjeff } 1390219820Sjeff 1391219820Sjeffdone: 1392219820Sjeff __sdp_log(2, "CONNECT: <%s:%d:%d> result <%d>\n", 1393219820Sjeff program_invocation_short_name, fd, shadow_fd, ret); 1394219820Sjeff 1395219820Sjeff return ret; 1396219820Sjeff} /* connect */ 1397219820Sjeff 1398219820Sjeffint connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen) 1399219820Sjeff{ 1400219820Sjeff return __perform_connect(fd, serv_addr, addrlen, SOCKET_SEMANTIC_DEFAULT); 1401219820Sjeff} 1402219820Sjeff 1403219820Sjeff#if defined( SOLARIS_BUILD ) 1404219820Sjeffint __xnet_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen) 1405219820Sjeff{ 1406219820Sjeff return __perform_connect(fd, serv_addr, addrlen, SOCKET_SEMANTIC_XNET); 1407219820Sjeff} 1408219820Sjeff#endif 1409219820Sjeff 1410219820Sjeff/* ========================================================================= */ 1411219820Sjeff/*..listen -- replacement listen call. */ 1412219820Sjeff/* 1413219820Sjeff Now we know our role (passive/server) and our address so we can get AF. 1414219820Sjeff If both we should try listening on both 1415219820Sjeff*/ 1416219820Sjeff 1417219820Sjeffstatic inline int __listen_semantics(int fd, int backlog, int semantics) 1418219820Sjeff{ 1419219820Sjeff return 1420219820Sjeff#ifdef SOLARIS_BUILD 1421219820Sjeff (semantics == SOCKET_SEMANTIC_XNET) ? 1422219820Sjeff _socket_xnet_funcs.listen(fd, backlog) : 1423219820Sjeff#endif 1424219820Sjeff _socket_funcs.listen(fd, backlog); 1425219820Sjeff} 1426219820Sjeff 1427219820Sjeffstatic int __perform_listen(int fd, int backlog, int semantics) 1428219820Sjeff{ 1429219820Sjeff use_family_t target_family; 1430219820Sjeff int shadow_fd; 1431219820Sjeff int ret = 0, sret = 0; 1432219820Sjeff struct sockaddr_storage tmp_sin; 1433219820Sjeff socklen_t tmp_sinlen = sizeof(tmp_sin); 1434219820Sjeff struct sockaddr_in *sin4 = (struct sockaddr_in *) &tmp_sin; 1435219820Sjeff char buf[MAX_ADDR_STR_LEN]; 1436219820Sjeff int actual_port; 1437219820Sjeff 1438219820Sjeff if (init_status == 0) 1439219820Sjeff __sdp_init(); 1440219820Sjeff 1441219820Sjeff if (NULL == _socket_funcs.listen) { 1442219820Sjeff __sdp_log(9, "Error listen: no implementation for listen found\n"); 1443219820Sjeff return -1; 1444219820Sjeff } 1445219820Sjeff 1446219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 1447219820Sjeff __sdp_log(2, "LISTEN: <%s:%d:%d>\n", 1448219820Sjeff program_invocation_short_name, fd, shadow_fd); 1449219820Sjeff 1450219820Sjeff /* if there is no shadow - simply call listen */ 1451219820Sjeff if (shadow_fd == -1) { 1452219820Sjeff __sdp_log(1, "LISTEN: calling listen on fd:%d\n", fd); 1453219820Sjeff ret = __listen_semantics(fd, backlog, semantics); 1454219820Sjeff goto done; 1455219820Sjeff } 1456219820Sjeff 1457219820Sjeff /* we need to obtain the address from the fd */ 1458219820Sjeff if (_socket_funcs.getsockname(fd, (struct sockaddr *) &tmp_sin, &tmp_sinlen) 1459219820Sjeff < 0) { 1460219820Sjeff __sdp_log(9, "Error listen: getsockname return <%d> for TCP socket\n", 1461219820Sjeff errno); 1462219820Sjeff errno = EADDRNOTAVAIL; 1463219820Sjeff sret = -1; 1464219820Sjeff goto done; 1465219820Sjeff } 1466219820Sjeff 1467219820Sjeff if (get_addr_str((struct sockaddr *) &tmp_sin, buf, MAX_ADDR_STR_LEN)) { 1468219820Sjeff __sdp_log(9, "Error listen: provided illegal address: %s\n", 1469219820Sjeff strerror(errno)); 1470219820Sjeff } 1471219820Sjeff 1472219820Sjeff __sdp_log(2, "LISTEN: <%s:%d:%d> domain <%d> IP <%s> port <%d>\n", 1473219820Sjeff program_invocation_short_name, fd, shadow_fd, 1474219820Sjeff sin4->sin_family, buf, ntohs(sin4->sin_port)); 1475219820Sjeff 1476219820Sjeff target_family = 1477219820Sjeff __sdp_match_listen((struct sockaddr *) &tmp_sin, sizeof(tmp_sin)); 1478219820Sjeff 1479219820Sjeff /* 1480219820Sjeff * in case of an implicit bind and "USE_BOTH" rule we need to first bind the 1481219820Sjeff * two sockets to the same port number 1482219820Sjeff */ 1483219820Sjeff actual_port = ntohs(sin4->sin_port); 1484219820Sjeff 1485219820Sjeff /* do we need to implicit bind both */ 1486219820Sjeff if ((actual_port == 0) && (target_family == USE_BOTH)) { 1487219820Sjeff int sdp_sd = -1, tcp_sd = -1; 1488219820Sjeff 1489219820Sjeff actual_port = find_free_port((struct sockaddr *) &tmp_sin, tmp_sinlen, 1490219820Sjeff fd, &sdp_sd, &tcp_sd, semantics); 1491219820Sjeff if (actual_port < 0) { 1492219820Sjeff ret = -1; 1493219820Sjeff __sdp_log(8, "LISTEN: Failed to find common free port. Only TCP will be used.\n"); 1494219820Sjeff target_family = USE_TCP; 1495219820Sjeff } else { 1496219820Sjeff /* copy the port to the tmp address */ 1497219820Sjeff set_addr_port_num((struct sockaddr *) sin4, actual_port); 1498219820Sjeff 1499219820Sjeff __sdp_log(2, "LISTEN: BOTH on IP <%s> port <%d>\n", 1500219820Sjeff buf, actual_port); 1501219820Sjeff /* perform the bind */ 1502219820Sjeff ret = close_and_bind(tcp_sd, fd, (struct sockaddr *) sin4, 1503219820Sjeff tmp_sinlen, semantics); 1504219820Sjeff if (ret < 0) { 1505219820Sjeff __sdp_log(9, "Error listen: " 1506219820Sjeff "Could not close_and_bind TCP side\n"); 1507219820Sjeff } 1508219820Sjeff 1509219820Sjeff ret = close_and_bind(sdp_sd, shadow_fd, (struct sockaddr *) sin4, 1510219820Sjeff tmp_sinlen, semantics); 1511219820Sjeff if (ret < 0) { 1512219820Sjeff __sdp_log(9, "Error listen: " 1513219820Sjeff "Could not close_and_bind SDP side\n"); 1514219820Sjeff } 1515219820Sjeff } 1516219820Sjeff } 1517219820Sjeff 1518219820Sjeff if ((target_family == USE_TCP) || (target_family == USE_BOTH)) { 1519219820Sjeff __sdp_log(1, "LISTEN: calling listen on TCP fd:%d\n", fd); 1520219820Sjeff ret = __listen_semantics(fd, backlog, semantics); 1521219820Sjeff if (ret < 0) { 1522219820Sjeff __sdp_log(9, "Error listen: failed with code <%d> on TCP fd:<%d>\n", 1523219820Sjeff errno, fd); 1524219820Sjeff } else { 1525219820Sjeff __sdp_log(7, "LISTEN: fd:%d listening on TCP bound to:%s port:%d\n", 1526219820Sjeff fd, buf, actual_port); 1527219820Sjeff } 1528219820Sjeff } 1529219820Sjeff 1530219820Sjeff if ((target_family == USE_SDP) || (target_family == USE_BOTH)) { 1531219820Sjeff __sdp_log(1, "LISTEN: calling listen on SDP fd:<%d>\n", shadow_fd); 1532219820Sjeff sret = __listen_semantics(shadow_fd, backlog, semantics); 1533219820Sjeff if (sret < 0) { 1534219820Sjeff __sdp_log(9, "Error listen: failed with code <%d> SDP fd:<%d>\n", 1535219820Sjeff errno, shadow_fd); 1536219820Sjeff } else { 1537219820Sjeff __sdp_log(7, "LISTEN: fd:%d listening on SDP bound to:%s port:%d\n", 1538219820Sjeff fd, buf, actual_port); 1539219820Sjeff } 1540219820Sjeff } 1541219820Sjeff 1542219820Sjeff /* cleanup the un-needed shadow if TCP and did not fail */ 1543219820Sjeff if ((target_family == USE_TCP) && (ret >= 0)) { 1544219820Sjeff __sdp_log(1, "LISTEN: cleaning up shadow SDP\n"); 1545219820Sjeff if (cleanup_shadow(fd) < 0) 1546219820Sjeff __sdp_log(9, "Error listen: failed to cleanup shadow for fd:%d\n", 1547219820Sjeff fd); 1548219820Sjeff } 1549219820Sjeff 1550219820Sjeff /* cleanup the TCP socket and replace with SDP */ 1551219820Sjeff if ((target_family == USE_SDP) && (sret >= 0)) { 1552219820Sjeff __sdp_log(1, "LISTEN: cleaning TCP socket and dup2 SDP into it\n"); 1553219820Sjeff if (0 > (sret = replace_fd_with_its_shadow(fd))) 1554219820Sjeff __sdp_log(9, "Error listen: " 1555219820Sjeff "failed to dup2 shadow into orig fd:%d\n", fd); 1556219820Sjeff } 1557219820Sjeff 1558219820Sjeffdone: 1559219820Sjeff __sdp_log(2, "LISTEN: <%s:%d:%d> result <%d>\n", 1560219820Sjeff program_invocation_short_name, fd, shadow_fd, ret); 1561219820Sjeff /* its a success only if both are ok */ 1562219820Sjeff if (ret < 0) 1563219820Sjeff return (ret); 1564219820Sjeff if (sret < 0) 1565219820Sjeff return (sret); 1566219820Sjeff return 0; 1567219820Sjeff} /* listen */ 1568219820Sjeff 1569219820Sjeffint listen(int fd, int backlog) 1570219820Sjeff{ 1571219820Sjeff return __perform_listen(fd, backlog, SOCKET_SEMANTIC_DEFAULT); 1572219820Sjeff} 1573219820Sjeff 1574219820Sjeff#ifdef SOLARIS_BUILD 1575219820Sjeffint __xnet_listen(int fd, int backlog) 1576219820Sjeff{ 1577219820Sjeff return __perform_listen(fd, backlog, SOCKET_SEMANTIC_XNET); 1578219820Sjeff} 1579219820Sjeff#endif 1580219820Sjeff 1581219820Sjeff/* ========================================================================= */ 1582219820Sjeff/*..close -- replacement close call. */ 1583219820Sjeffint close(int fd) 1584219820Sjeff{ 1585219820Sjeff int shadow_fd; 1586219820Sjeff int ret; 1587219820Sjeff 1588219820Sjeff if (init_status == 0) 1589219820Sjeff __sdp_init(); 1590219820Sjeff 1591219820Sjeff if (NULL == _socket_funcs.close) { 1592219820Sjeff __sdp_log(9, "Error close: no implementation for close found\n"); 1593219820Sjeff return -1; 1594219820Sjeff } 1595219820Sjeff 1596219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 1597219820Sjeff 1598219820Sjeff __sdp_log(2, "CLOSE: <%s:%d:%d>\n", 1599219820Sjeff program_invocation_short_name, fd, shadow_fd); 1600219820Sjeff 1601219820Sjeff if (shadow_fd != -1) { 1602219820Sjeff __sdp_log(1, "CLOSE: closing shadow fd:<%d>\n", shadow_fd); 1603219820Sjeff if (cleanup_shadow(fd) < 0) 1604219820Sjeff __sdp_log(9, "Error close: failed to cleanup shadow for fd:%d\n", 1605219820Sjeff fd); 1606219820Sjeff } 1607219820Sjeff 1608219820Sjeff init_extra_attribute(fd); 1609219820Sjeff ret = _socket_funcs.close(fd); 1610219820Sjeff __sdp_log(2, "CLOSE: <%s:%d:%d> result <%d>\n", 1611219820Sjeff program_invocation_short_name, fd, shadow_fd, ret); 1612219820Sjeff return ret; 1613219820Sjeff} /* close */ 1614219820Sjeff 1615219820Sjeff/* ========================================================================= */ 1616219820Sjeff/*..dup -- replacement dup call. */ 1617219820Sjeff/* we duplicate the fd and its shadow if exists - ok if the main worked */ 1618219820Sjeffint dup(int fd) 1619219820Sjeff{ 1620219820Sjeff int newfd, new_shadow_fd = -1; 1621219820Sjeff int shadow_fd; 1622219820Sjeff 1623219820Sjeff if (init_status == 0) 1624219820Sjeff __sdp_init(); 1625219820Sjeff 1626219820Sjeff if (NULL == _socket_funcs.dup) { 1627219820Sjeff __sdp_log(9, "Error dup: no implementation for dup found\n"); 1628219820Sjeff return -1; 1629219820Sjeff } 1630219820Sjeff 1631219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 1632219820Sjeff 1633219820Sjeff __sdp_log(2, "DUP: <%s:%d:%d>\n", 1634219820Sjeff program_invocation_short_name, fd, shadow_fd); 1635219820Sjeff 1636219820Sjeff __sdp_log(1, "DUP: duplication fd:<%d>\n", fd); 1637219820Sjeff newfd = _socket_funcs.dup(fd); 1638219820Sjeff 1639219820Sjeff if (newfd == fd) 1640219820Sjeff return (fd); 1641219820Sjeff 1642219820Sjeff if (!is_valid_fd(newfd)) { 1643219820Sjeff __sdp_log(9, "Error dup: new fd <%d> out of range.\n", newfd); 1644219820Sjeff } else { 1645219820Sjeff /* copy attributes from old fd */ 1646219820Sjeff libsdp_fd_attributes[newfd] = libsdp_fd_attributes[fd]; 1647219820Sjeff libsdp_fd_attributes[newfd].shadow_fd = -1; 1648219820Sjeff 1649219820Sjeff if (shadow_fd != -1) { 1650219820Sjeff __sdp_log(1, "DUP: duplication shadow fd:<%d>\n", shadow_fd); 1651219820Sjeff new_shadow_fd = _socket_funcs.dup(shadow_fd); 1652219820Sjeff if ((new_shadow_fd > max_file_descriptors) || (new_shadow_fd < 0)) { 1653219820Sjeff __sdp_log(9, "Error dup: new shadow fd <%d> out of range.\n", 1654219820Sjeff new_shadow_fd); 1655219820Sjeff } else { 1656219820Sjeff libsdp_fd_attributes[new_shadow_fd] = 1657219820Sjeff libsdp_fd_attributes[shadow_fd]; 1658219820Sjeff libsdp_fd_attributes[newfd].shadow_fd = new_shadow_fd; 1659219820Sjeff } 1660219820Sjeff } /* shadow exists */ 1661219820Sjeff } 1662219820Sjeff 1663219820Sjeff __sdp_log(2, "DUP: <%s:%d:%d> return <%d:%d>\n", 1664219820Sjeff program_invocation_short_name, fd, shadow_fd, newfd, 1665219820Sjeff new_shadow_fd); 1666219820Sjeff 1667219820Sjeff return newfd; 1668219820Sjeff} /* dup */ 1669219820Sjeff 1670219820Sjeff/* ========================================================================= */ 1671219820Sjeff/*..dup2 -- replacement dup2 call. */ 1672219820Sjeff/* since only the main new fd is given we only move the shadow if exists */ 1673219820Sjeffint dup2(int fd, int newfd) 1674219820Sjeff{ 1675219820Sjeff int shadow_fd; 1676219820Sjeff int shadow_newfd; 1677219820Sjeff int new_shadow_fd = -1; 1678219820Sjeff int ret = 0; 1679219820Sjeff 1680219820Sjeff if (init_status == 0) 1681219820Sjeff __sdp_init(); 1682219820Sjeff 1683219820Sjeff if (NULL == _socket_funcs.dup2) { 1684219820Sjeff __sdp_log(9, "Error dup2: no implementation for dup2 found\n"); 1685219820Sjeff return -1; 1686219820Sjeff } 1687219820Sjeff 1688219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 1689219820Sjeff shadow_newfd = get_shadow_fd_by_fd(newfd); 1690219820Sjeff 1691219820Sjeff __sdp_log(2, "DUP2: <%s:%d:%d>\n", 1692219820Sjeff program_invocation_short_name, fd, shadow_fd); 1693219820Sjeff 1694219820Sjeff if (newfd == fd) { 1695219820Sjeff __sdp_log(1, "DUP2: skip duplicating fd:<%d> into:<%d>\n", fd, newfd); 1696219820Sjeff goto done; 1697219820Sjeff } 1698219820Sjeff 1699219820Sjeff /* dup2 closes the target file desc if it is a valid fd */ 1700219820Sjeff if (shadow_newfd != -1) { 1701219820Sjeff __sdp_log(1, "DUP2: closing newfd:<%d> shadow:<%d>\n", newfd, 1702219820Sjeff shadow_newfd); 1703219820Sjeff ret = _socket_funcs.close(shadow_newfd); 1704219820Sjeff if (ret != 0) { 1705219820Sjeff __sdp_log(9, 1706219820Sjeff "DUP2: fail to close newfd:<%d> shadow:<%d> with: %d %s\n", 1707219820Sjeff newfd, shadow_newfd, ret, strerror(errno)); 1708219820Sjeff } 1709219820Sjeff } 1710219820Sjeff 1711219820Sjeff __sdp_log(1, "DUP2: duplicating fd:<%d> into:<%d>\n", fd, newfd); 1712219820Sjeff newfd = _socket_funcs.dup2(fd, newfd); 1713219820Sjeff if ((newfd > max_file_descriptors) || (newfd < 0)) { 1714219820Sjeff __sdp_log(9, "Error dup2: new fd <%d> out of range.\n", newfd); 1715219820Sjeff } else { 1716219820Sjeff /* copy attributes from old fd */ 1717219820Sjeff libsdp_fd_attributes[fd].shadow_fd = -1; 1718219820Sjeff libsdp_fd_attributes[newfd] = libsdp_fd_attributes[fd]; 1719219820Sjeff 1720219820Sjeff /* if it had a shadow create a new shadow */ 1721219820Sjeff if (shadow_fd != -1) { 1722219820Sjeff __sdp_log(1, "DUP2: duplication shadow fd:<%d>\n", shadow_fd); 1723219820Sjeff new_shadow_fd = _socket_funcs.dup(shadow_fd); 1724219820Sjeff if ((new_shadow_fd > max_file_descriptors) || (new_shadow_fd < 0)) { 1725219820Sjeff __sdp_log(9, "Error dup2: new shadow fd <%d> out of range.\n", 1726219820Sjeff new_shadow_fd); 1727219820Sjeff } else { 1728219820Sjeff libsdp_fd_attributes[new_shadow_fd] = 1729219820Sjeff libsdp_fd_attributes[shadow_fd]; 1730219820Sjeff libsdp_fd_attributes[newfd].shadow_fd = new_shadow_fd; 1731219820Sjeff } 1732219820Sjeff } /* newfd is ok */ 1733219820Sjeff } 1734219820Sjeff 1735219820Sjeffdone: 1736219820Sjeff __sdp_log(2, "DUP2: <%s:%d:%d> return <%d:%d>\n", 1737219820Sjeff program_invocation_short_name, fd, shadow_fd, newfd, 1738219820Sjeff new_shadow_fd); 1739219820Sjeff 1740219820Sjeff return newfd; 1741219820Sjeff} /* dup */ 1742219820Sjeff 1743219820Sjeff/* ========================================================================= */ 1744219820Sjeff/*..getsockname -- replacement getsocknanme call. */ 1745219820Sjeffint getsockname(int fd, struct sockaddr *name, socklen_t * namelen) 1746219820Sjeff{ 1747219820Sjeff int ret = 0; 1748219820Sjeff char buf[MAX_ADDR_STR_LEN]; 1749219820Sjeff 1750219820Sjeff if (init_status == 0) 1751219820Sjeff __sdp_init(); 1752219820Sjeff 1753219820Sjeff /* 1754219820Sjeff * ensure the SDP protocol family is not exposed to the user, since 1755219820Sjeff * this is meant to be a transparency layer. 1756219820Sjeff */ 1757219820Sjeff if (NULL == _socket_funcs.getsockname) { 1758219820Sjeff __sdp_log(9, 1759219820Sjeff "Error getsockname: no implementation for getsockname found\n"); 1760219820Sjeff return -1; 1761219820Sjeff } 1762219820Sjeff 1763219820Sjeff /* double check provided pointers */ 1764219820Sjeff if ((name == NULL) || is_invalid_addr(name)) { 1765219820Sjeff errno = EFAULT; 1766219820Sjeff __sdp_log(9, "Error getsockname: illegal address provided\n"); 1767219820Sjeff return -1; 1768219820Sjeff } 1769219820Sjeff 1770219820Sjeff if ((namelen != NULL) && is_invalid_addr(namelen)) { 1771219820Sjeff errno = EFAULT; 1772219820Sjeff __sdp_log(9, "Error getsockname: illegal address length pointer provided\n"); 1773219820Sjeff return -1; 1774219820Sjeff } 1775219820Sjeff 1776219820Sjeff __sdp_log(2, "GETSOCKNAME <%s:%d>\n", program_invocation_short_name, fd); 1777219820Sjeff 1778219820Sjeff ret = _socket_funcs.getsockname(fd, name, namelen); 1779219820Sjeff 1780219820Sjeff if (__sdp_log_get_level() <= 1) { 1781219820Sjeff if (get_addr_str(name, buf, MAX_ADDR_STR_LEN)) { 1782219820Sjeff __sdp_log(1, "GETSOCKNAME: " "address is illegal\n"); 1783219820Sjeff } else { 1784219820Sjeff __sdp_log(1, "GETSOCKNAME: address is:%s port:%d\n", buf, 1785219820Sjeff ntohs(((struct sockaddr_in *) name)->sin_port)); 1786219820Sjeff } 1787219820Sjeff } 1788219820Sjeff __sdp_log(2, "GETSOCKNAME <%s:%d> result <%d>\n", 1789219820Sjeff program_invocation_short_name, fd, ret); 1790219820Sjeff 1791219820Sjeff return ret; 1792219820Sjeff} /* getsockname */ 1793219820Sjeff 1794219820Sjeff/* ========================================================================= */ 1795219820Sjeff/*..getpeername -- replacement getpeername call. */ 1796219820Sjeffint getpeername(int fd, struct sockaddr *name, socklen_t * namelen) 1797219820Sjeff{ 1798219820Sjeff int ret = 0; 1799219820Sjeff 1800219820Sjeff if (init_status == 0) 1801219820Sjeff __sdp_init(); 1802219820Sjeff 1803219820Sjeff if (NULL == _socket_funcs.getpeername) { 1804219820Sjeff __sdp_log(9, "Error getpeername: " 1805219820Sjeff "no implementation for getpeername found\n"); 1806219820Sjeff return -1; 1807219820Sjeff } 1808219820Sjeff 1809219820Sjeff /* double check provided pointers */ 1810219820Sjeff if ((name == NULL) || is_invalid_addr(name)) { 1811219820Sjeff errno = EFAULT; 1812219820Sjeff __sdp_log(9, "Error getsockname: illegal address provided\n"); 1813219820Sjeff return -1; 1814219820Sjeff } 1815219820Sjeff 1816219820Sjeff if ((namelen != NULL) && is_invalid_addr(namelen)) { 1817219820Sjeff errno = EFAULT; 1818219820Sjeff __sdp_log(9, 1819219820Sjeff "Error getsockname: illegal address length pointer provided\n"); 1820219820Sjeff return -1; 1821219820Sjeff } 1822219820Sjeff 1823219820Sjeff __sdp_log(2, "GETPEERNAME <%s:%d>\n", program_invocation_short_name, fd); 1824219820Sjeff 1825219820Sjeff ret = _socket_funcs.getpeername(fd, name, namelen); 1826219820Sjeff 1827219820Sjeff __sdp_log(2, "GETPEERNAME <%s:%d> result <%d:%d> family=%d s_addr=%d\n", 1828219820Sjeff program_invocation_short_name, fd, ret, 1829219820Sjeff (!(0 > ret) ? 0 : -1), name->sa_family, 1830219820Sjeff ((struct sockaddr_in *) name)->sin_addr.s_addr); 1831219820Sjeff 1832219820Sjeff return ret; 1833219820Sjeff} /* getpeername */ 1834219820Sjeff 1835219820Sjeff 1836219820Sjeff 1837219820Sjeff/* ========================================================================= */ 1838219820Sjeff/*..accept -- replacement accept call. */ 1839219820Sjeff/* 1840219820Sjeff If we have a shadow we need to decide which socket we want to accept on 1841219820Sjeff so we select first and then give priority based on previous selection 1842219820Sjeff*/ 1843219820Sjeffint accept(int fd, struct sockaddr *addr, socklen_t * addrlen) 1844219820Sjeff{ 1845219820Sjeff int shadow_fd; 1846219820Sjeff int ret = 0; 1847219820Sjeff fd_set fds; 1848219820Sjeff socklen_t saved_addrlen = 0; 1849219820Sjeff int fopts; 1850219820Sjeff char buf[MAX_ADDR_STR_LEN]; 1851219820Sjeff 1852219820Sjeff if (init_status == 0) 1853219820Sjeff __sdp_init(); 1854219820Sjeff 1855219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 1856219820Sjeff 1857219820Sjeff /* 1858219820Sjeff * ensure the SDP protocol family is not exposed to the user, since 1859219820Sjeff * this is meant to be a transparency layer. 1860219820Sjeff */ 1861219820Sjeff if (NULL == _socket_funcs.accept) { 1862219820Sjeff __sdp_log(9, "Error accept: no implementation for accept found\n"); 1863219820Sjeff return -1; 1864219820Sjeff } 1865219820Sjeff 1866219820Sjeff /* double check provided pointers */ 1867219820Sjeff if ((addr != NULL) && is_invalid_addr(addr)) { 1868219820Sjeff errno = EINVAL; 1869219820Sjeff __sdp_log(9, "Error accept: illegal address provided\n"); 1870219820Sjeff return -1; 1871219820Sjeff } 1872219820Sjeff 1873219820Sjeff if ((addrlen != NULL) && is_invalid_addr(addrlen)) { 1874219820Sjeff errno = EINVAL; 1875219820Sjeff __sdp_log(9, "Error accept: illegal address length pointer provided\n"); 1876219820Sjeff return -1; 1877219820Sjeff } 1878219820Sjeff 1879219820Sjeff if (addr && addrlen) 1880219820Sjeff saved_addrlen = *addrlen; 1881219820Sjeff 1882219820Sjeff __sdp_log(2, "ACCEPT: <%s:%d>\n", program_invocation_short_name, fd); 1883219820Sjeff 1884219820Sjeff if (shadow_fd == -1) { 1885219820Sjeff fopts = _socket_funcs.fcntl(fd, F_GETFL); 1886219820Sjeff __sdp_log(1, "ACCEPT: fd <%d> opts are <0x%x>\n", fd, fopts); 1887219820Sjeff 1888219820Sjeff __sdp_log(7, "ACCEPT: accepting on single fd:<%d>\n", fd); 1889219820Sjeff ret = _socket_funcs.accept(fd, addr, addrlen); 1890219820Sjeff if (ret < 0) { 1891219820Sjeff if (!(fopts & O_NONBLOCK && errno == EWOULDBLOCK)) 1892219820Sjeff __sdp_log(9, "Error accept: accept returned :<%d> %s\n", 1893219820Sjeff ret, strerror(errno)); 1894219820Sjeff } else { 1895219820Sjeff set_is_sdp_socket(ret, get_is_sdp_socket(fd)); 1896219820Sjeff } 1897219820Sjeff } else { 1898219820Sjeff 1899219820Sjeff fopts = _socket_funcs.fcntl(shadow_fd, F_GETFL); 1900219820Sjeff __sdp_log(1, "ACCEPT: shadow_fd <%d> opts are <0x%x>\n", 1901219820Sjeff shadow_fd, fopts); 1902219820Sjeff 1903219820Sjeff /* we need different behavior for NONBLOCK or signal IO and BLOCK */ 1904219820Sjeff if ((fopts > 0) && (fopts & (O_NONBLOCK | FASYNC))) { 1905219820Sjeff __sdp_log(1, "ACCEPT: accepting (nonblock) on SDP fd:<%d>\n", shadow_fd); 1906219820Sjeff 1907219820Sjeff ret = _socket_funcs.accept(shadow_fd, addr, addrlen); 1908219820Sjeff if (ret >= 0) { 1909219820Sjeff set_is_sdp_socket(ret, 1); 1910219820Sjeff 1911219820Sjeff __sdp_log(7, "ACCEPT: accepted (nonblock) SDP fd:<%d>\n", 1912219820Sjeff shadow_fd); 1913219820Sjeff } else { 1914219820Sjeff __sdp_log(1, "ACCEPT: accept on SDP fd:<%d> return:%d errno:%d\n", 1915219820Sjeff shadow_fd, ret, errno); 1916219820Sjeff 1917219820Sjeff __sdp_log(1, "ACCEPT: accepting (nonblock) on TCP fd:<%d>\n", fd); 1918219820Sjeff ret = _socket_funcs.accept(fd, addr, addrlen); 1919219820Sjeff if (ret >= 0) { 1920219820Sjeff __sdp_log(7, "ACCEPT: accepted (nonblock) TCP fd:<%d>\n", 1921219820Sjeff shadow_fd); 1922219820Sjeff } else { 1923219820Sjeff __sdp_log(1, "ACCEPT: accept on TCP fd:<%d> " 1924219820Sjeff "return:%d errno:%d\n", fd, ret, errno); 1925219820Sjeff } 1926219820Sjeff } 1927219820Sjeff } else { 1928219820Sjeff __sdp_log(1, "ACCEPT: selecting both fd:<%d> and shadow:<%d>\n", 1929219820Sjeff fd, shadow_fd); 1930219820Sjeff FD_ZERO(&fds); 1931219820Sjeff FD_SET(fd, &fds); 1932219820Sjeff FD_SET(shadow_fd, &fds); 1933219820Sjeff ret = 1934219820Sjeff _socket_funcs.select(1 + ((fd > shadow_fd) ? fd : shadow_fd), 1935219820Sjeff &fds, NULL, NULL, NULL); 1936219820Sjeff if (ret >= 0) { 1937219820Sjeff if (last_accept_was_tcp(fd) == 0) { 1938219820Sjeff if (FD_ISSET(fd, &fds)) { 1939219820Sjeff set_last_accept(fd, 1); 1940219820Sjeff __sdp_log(7, "ACCEPT: accepting on TCP fd:<%d>\n", fd); 1941219820Sjeff ret = _socket_funcs.accept(fd, addr, addrlen); 1942219820Sjeff } else { 1943219820Sjeff __sdp_log(7, "ACCEPT: accepting on SDP fd:<%d>\n", 1944219820Sjeff shadow_fd); 1945219820Sjeff ret = _socket_funcs.accept(shadow_fd, addr, addrlen); 1946219820Sjeff if (ret >= 0) 1947219820Sjeff set_is_sdp_socket(ret, 1); 1948219820Sjeff } 1949219820Sjeff } else { 1950219820Sjeff if (FD_ISSET(shadow_fd, &fds)) { 1951219820Sjeff set_last_accept(fd, 1); 1952219820Sjeff __sdp_log(7, "ACCEPT: accepting on SDP fd:<%d>\n", 1953219820Sjeff shadow_fd); 1954219820Sjeff ret = _socket_funcs.accept(shadow_fd, addr, addrlen); 1955219820Sjeff if (ret >= 0) 1956219820Sjeff set_is_sdp_socket(ret, 1); 1957219820Sjeff } else { 1958219820Sjeff __sdp_log(7, "ACCEPT: accepting on TCP fd:<%d>\n", fd); 1959219820Sjeff ret = _socket_funcs.accept(fd, addr, addrlen); 1960219820Sjeff } 1961219820Sjeff } 1962219820Sjeff } else { 1963219820Sjeff if (errno != EINTR) { 1964219820Sjeff __sdp_log(9, 1965219820Sjeff "Error accept: select returned :<%d> (%d) %s\n", 1966219820Sjeff ret, errno, strerror(errno)); 1967219820Sjeff } else { 1968219820Sjeff __sdp_log(1, "ACCEPT: select returned :<%d> (%d) %s\n", 1969219820Sjeff ret, errno, strerror(errno)); 1970219820Sjeff } 1971219820Sjeff } 1972219820Sjeff } /* blocking mode */ 1973219820Sjeff } /* shadow fd */ 1974219820Sjeff 1975219820Sjeff if ((__sdp_log_get_level() <= 1) && (ret >= 0) && addr && addrlen) { 1976219820Sjeff get_addr_str(addr, buf, *addrlen); 1977219820Sjeff __sdp_log(1, "ACCEPT: accepted from:%s port:%d into fd:%d\n", 1978219820Sjeff buf, ntohs(((struct sockaddr_in *) addr)->sin_port), ret); 1979219820Sjeff } 1980219820Sjeff __sdp_log(2, "ACCEPT: <%s:%d> return <%d>\n", 1981219820Sjeff program_invocation_short_name, fd, ret); 1982219820Sjeff 1983219820Sjeff return ret; 1984219820Sjeff} /* accept */ 1985219820Sjeff 1986219820Sjeff/* ========================================================================= */ 1987219820Sjeff/*..select -- replacement socket call. */ 1988219820Sjeff/* 1989219820Sjeff if we have shadow we must select on it too - which requires a hack back 1990219820Sjeff and forth 1991219820Sjeff*/ 1992219820Sjeffint 1993219820Sjeffselect(int n, 1994219820Sjeff fd_set * readfds, 1995219820Sjeff fd_set * writefds, fd_set * exceptfds, struct timeval *timeout) 1996219820Sjeff{ 1997219820Sjeff int shadow_fd; 1998219820Sjeff int ret; 1999219820Sjeff int current; 2000219820Sjeff int maxi = 0; 2001219820Sjeff fd_set new_fds; 2002219820Sjeff 2003219820Sjeff if (init_status == 0) 2004219820Sjeff __sdp_init(); 2005219820Sjeff 2006219820Sjeff if (NULL == _socket_funcs.select) { 2007219820Sjeff __sdp_log(9, "Error select: no implementation for select found\n"); 2008219820Sjeff return -1; 2009219820Sjeff } 2010219820Sjeff 2011219820Sjeff __sdp_log(2, "SELECT: <%s:%d>\n", program_invocation_short_name, n); 2012219820Sjeff 2013219820Sjeff /* if we do not read - nothing to do */ 2014219820Sjeff if (readfds == NULL) { 2015219820Sjeff ret = _socket_funcs.select(n, readfds, writefds, exceptfds, timeout); 2016219820Sjeff goto done; 2017219820Sjeff } 2018219820Sjeff 2019219820Sjeff FD_ZERO(&new_fds); 2020219820Sjeff if (n > 0) { 2021219820Sjeff maxi = n - 1; 2022219820Sjeff } 2023219820Sjeff 2024219820Sjeff /* add shadow bits */ 2025219820Sjeff for (current = 0; current < n; current++) { 2026219820Sjeff if (FD_ISSET(current, readfds)) { 2027219820Sjeff FD_SET(current, &new_fds); 2028219820Sjeff if (current > maxi) { 2029219820Sjeff maxi = current; 2030219820Sjeff } 2031219820Sjeff shadow_fd = get_shadow_fd_by_fd(current); 2032219820Sjeff if (shadow_fd != -1) { 2033219820Sjeff __sdp_log(1, 2034219820Sjeff "SELECT: adding fd:<%d> shadow_fd:<%d> to readfs\n", 2035219820Sjeff current, shadow_fd); 2036219820Sjeff FD_SET(shadow_fd, &new_fds); 2037219820Sjeff if (shadow_fd > maxi) { 2038219820Sjeff maxi = shadow_fd; 2039219820Sjeff } 2040219820Sjeff } 2041219820Sjeff } 2042219820Sjeff } 2043219820Sjeff 2044219820Sjeff __sdp_log(1, "SELECT: invoking select n=<%d>\n", 1 + maxi); 2045219820Sjeff ret = _socket_funcs.select(1 + maxi, 2046219820Sjeff &new_fds, writefds, exceptfds, timeout); 2047219820Sjeff 2048219820Sjeff /* remove the count and bits of the shadows */ 2049219820Sjeff if (ret >= 0) { 2050219820Sjeff for (current = 0; current < n; current++) { 2051219820Sjeff shadow_fd = get_shadow_fd_by_fd(current); 2052219820Sjeff if (shadow_fd == -1) { 2053219820Sjeff if (FD_ISSET(current, readfds) && 2054219820Sjeff FD_ISSET(current, &new_fds) == 0) { 2055219820Sjeff FD_CLR(current, readfds); 2056219820Sjeff } 2057219820Sjeff } else { 2058219820Sjeff if (FD_ISSET(current, readfds) && FD_ISSET(current, &new_fds) 2059219820Sjeff && FD_ISSET(shadow_fd, &new_fds)) { 2060219820Sjeff ret -= 1; 2061219820Sjeff } 2062219820Sjeff if (FD_ISSET(current, readfds) && 2063219820Sjeff FD_ISSET(current, &new_fds) == 0 && 2064219820Sjeff FD_ISSET(shadow_fd, &new_fds) == 0) { 2065219820Sjeff FD_CLR(current, readfds); 2066219820Sjeff } 2067219820Sjeff } 2068219820Sjeff } 2069219820Sjeff } 2070219820Sjeff 2071219820Sjeffdone: 2072219820Sjeff 2073219820Sjeff __sdp_log(2, "SELECT: <%s:%d> return <%d>\n", 2074219820Sjeff program_invocation_short_name, n, ret); 2075219820Sjeff return ret; 2076219820Sjeff} /* select */ 2077219820Sjeff 2078219820Sjeff/* ========================================================================= */ 2079219820Sjeff/*..pselect -- replacement socket call. */ 2080219820Sjeff/* 2081219820Sjeff if we have shadow we must pselect on it too - which requires a hack back 2082219820Sjeff and forth 2083219820Sjeff*/ 2084219820Sjeffint 2085219820Sjeffpselect(int n, 2086219820Sjeff fd_set * readfds, 2087219820Sjeff fd_set * writefds, 2088219820Sjeff fd_set * exceptfds, 2089219820Sjeff const struct timespec *timeout, const sigset_t * sigmask) 2090219820Sjeff{ 2091219820Sjeff int shadow_fd; 2092219820Sjeff int ret; 2093219820Sjeff int current; 2094219820Sjeff int maxi = 0; 2095219820Sjeff fd_set new_fds; 2096219820Sjeff 2097219820Sjeff if (init_status == 0) 2098219820Sjeff __sdp_init(); 2099219820Sjeff 2100219820Sjeff if (NULL == _socket_funcs.pselect) { 2101219820Sjeff __sdp_log(9, "Error pselect: no implementation for pselect found\n"); 2102219820Sjeff return -1; 2103219820Sjeff } 2104219820Sjeff 2105219820Sjeff __sdp_log(2, "PSELECT: <%s:%d>\n", program_invocation_short_name, n); 2106219820Sjeff 2107219820Sjeff /* if we do not read - nothing to do */ 2108219820Sjeff if (readfds == NULL) { 2109219820Sjeff ret = 2110219820Sjeff _socket_funcs.pselect(n, readfds, writefds, exceptfds, timeout, 2111219820Sjeff sigmask); 2112219820Sjeff goto done; 2113219820Sjeff } 2114219820Sjeff 2115219820Sjeff FD_ZERO(&new_fds); 2116219820Sjeff if (n > 0) { 2117219820Sjeff maxi = n - 1; 2118219820Sjeff } 2119219820Sjeff 2120219820Sjeff /* add shadow bits */ 2121219820Sjeff for (current = 0; current < n; current++) { 2122219820Sjeff if (FD_ISSET(current, readfds)) { 2123219820Sjeff FD_SET(current, &new_fds); 2124219820Sjeff if (current > maxi) { 2125219820Sjeff maxi = current; 2126219820Sjeff } 2127219820Sjeff shadow_fd = get_shadow_fd_by_fd(current); 2128219820Sjeff if (shadow_fd != -1) { 2129219820Sjeff __sdp_log(1, 2130219820Sjeff "PSELECT: adding fd:<%d> shadow_fd:<%d> to readfs\n", 2131219820Sjeff current, shadow_fd); 2132219820Sjeff FD_SET(shadow_fd, &new_fds); 2133219820Sjeff if (shadow_fd > maxi) { 2134219820Sjeff maxi = shadow_fd; 2135219820Sjeff } 2136219820Sjeff } 2137219820Sjeff } 2138219820Sjeff } 2139219820Sjeff 2140219820Sjeff __sdp_log(1, "PSELECT: invoking pselect n=<%d>\n", 1 + maxi); 2141219820Sjeff ret = _socket_funcs.pselect(1 + maxi, 2142219820Sjeff &new_fds, writefds, exceptfds, 2143219820Sjeff timeout, sigmask); 2144219820Sjeff 2145219820Sjeff /* remove the count and bits of the shadows */ 2146219820Sjeff if (ret >= 0) { 2147219820Sjeff for (current = 0; current < n; current++) { 2148219820Sjeff shadow_fd = get_shadow_fd_by_fd(current); 2149219820Sjeff if (shadow_fd == -1) { 2150219820Sjeff if (FD_ISSET(current, readfds) && 2151219820Sjeff FD_ISSET(current, &new_fds) == 0) { 2152219820Sjeff FD_CLR(current, readfds); 2153219820Sjeff } 2154219820Sjeff } else { 2155219820Sjeff if (FD_ISSET(current, readfds) && FD_ISSET(current, &new_fds) 2156219820Sjeff && FD_ISSET(shadow_fd, &new_fds)) { 2157219820Sjeff ret -= 1; 2158219820Sjeff } 2159219820Sjeff if (FD_ISSET(current, readfds) && 2160219820Sjeff FD_ISSET(current, &new_fds) == 0 && 2161219820Sjeff FD_ISSET(shadow_fd, &new_fds) == 0) { 2162219820Sjeff FD_CLR(current, readfds); 2163219820Sjeff } 2164219820Sjeff } 2165219820Sjeff } 2166219820Sjeff } 2167219820Sjeff 2168219820Sjeffdone: 2169219820Sjeff 2170219820Sjeff __sdp_log(2, "PSELECT: <%s:%d> return <%d>\n", 2171219820Sjeff program_invocation_short_name, n, ret); 2172219820Sjeff return ret; 2173219820Sjeff} /* pselect */ 2174219820Sjeff 2175219820Sjeff/* ========================================================================= */ 2176219820Sjeff/*..poll -- replacement socket call. */ 2177219820Sjeff/* 2178219820Sjeff if we have shadow we must poll on it too - which requires a hack back 2179219820Sjeff and forth 2180219820Sjeff*/ 2181219820Sjeffint poll(struct pollfd *ufds, nfds_t nfds, int timeout) 2182219820Sjeff{ 2183219820Sjeff int ret; 2184219820Sjeff int shadow_fd; 2185219820Sjeff int current; 2186219820Sjeff int extra = 0; 2187219820Sjeff struct pollfd *poll_fds = NULL; 2188219820Sjeff struct pollfd *poll_fd_ptr = NULL; 2189219820Sjeff 2190219820Sjeff if (init_status == 0) 2191219820Sjeff __sdp_init(); 2192219820Sjeff 2193219820Sjeff if (NULL == _socket_funcs.poll) { 2194219820Sjeff __sdp_log(9, "Error poll: no implementation for poll found\n"); 2195219820Sjeff return -1; 2196219820Sjeff } 2197219820Sjeff 2198219820Sjeff __sdp_log(2, "POLL: <%s:%d>\n", program_invocation_short_name, nfds); 2199219820Sjeff 2200219820Sjeff /* if we do not have any file desc - nothing to do */ 2201219820Sjeff if (ufds == NULL) { 2202219820Sjeff ret = _socket_funcs.poll(ufds, nfds, timeout); 2203219820Sjeff goto done; 2204219820Sjeff } 2205219820Sjeff 2206219820Sjeff /* scan for how many extra fds are required */ 2207219820Sjeff for (current = 0; current < nfds; current++) { 2208219820Sjeff shadow_fd = get_shadow_fd_by_fd(ufds[current].fd); 2209219820Sjeff if (shadow_fd != -1) 2210219820Sjeff extra++; 2211219820Sjeff } 2212219820Sjeff 2213219820Sjeff if (!extra) { 2214219820Sjeff poll_fds = ufds; 2215219820Sjeff } else { 2216219820Sjeff poll_fds = 2217219820Sjeff (struct pollfd *) malloc((nfds + extra) * sizeof(struct pollfd)); 2218219820Sjeff if (!poll_fds) { 2219219820Sjeff __sdp_log(9, 2220219820Sjeff "Error poll: malloc of extended pollfd array failed\n"); 2221219820Sjeff ret = -1; 2222219820Sjeff errno = ENOMEM; 2223219820Sjeff goto done; 2224219820Sjeff } 2225219820Sjeff poll_fd_ptr = poll_fds; 2226219820Sjeff for (current = 0; current < nfds; current++) { 2227219820Sjeff *poll_fd_ptr = ufds[current]; 2228219820Sjeff poll_fd_ptr++; 2229219820Sjeff shadow_fd = get_shadow_fd_by_fd(ufds[current].fd); 2230219820Sjeff if (shadow_fd != -1) { 2231219820Sjeff __sdp_log(1, "POLL: adding fd:<%d> shadow_fd:<%d> to readfs\n", 2232219820Sjeff current, shadow_fd); 2233219820Sjeff *poll_fd_ptr = ufds[current]; 2234219820Sjeff poll_fd_ptr->fd = shadow_fd; 2235219820Sjeff poll_fd_ptr++; 2236219820Sjeff } 2237219820Sjeff } 2238219820Sjeff } 2239219820Sjeff 2240219820Sjeff __sdp_log(1, "POLL: invoking poll nfds=<%d>\n", nfds + extra); 2241219820Sjeff ret = _socket_funcs.poll(poll_fds, nfds + extra, timeout); 2242219820Sjeff 2243219820Sjeff /* refactor into original list if any events */ 2244219820Sjeff if ((ret > 0) && extra) { 2245219820Sjeff poll_fd_ptr = poll_fds; 2246219820Sjeff for (current = 0; current < nfds; current++) { 2247219820Sjeff shadow_fd = get_shadow_fd_by_fd(ufds[current].fd); 2248219820Sjeff if (shadow_fd == -1) { 2249219820Sjeff ufds[current] = *poll_fd_ptr; 2250219820Sjeff } else { 2251219820Sjeff ufds[current] = *poll_fd_ptr; 2252219820Sjeff poll_fd_ptr++; 2253219820Sjeff if (poll_fd_ptr->revents) { 2254219820Sjeff if (ufds[current].revents) 2255219820Sjeff ret--; 2256219820Sjeff ufds[current].revents |= poll_fd_ptr->revents; 2257219820Sjeff } 2258219820Sjeff } 2259219820Sjeff poll_fd_ptr++; 2260219820Sjeff } 2261219820Sjeff } 2262219820Sjeff 2263219820Sjeff if (extra) 2264219820Sjeff free(poll_fds); 2265219820Sjeffdone: 2266219820Sjeff 2267219820Sjeff __sdp_log(2, "POLL: <%s:%d> return <%d>\n", 2268219820Sjeff program_invocation_short_name, nfds, ret); 2269219820Sjeff return ret; 2270219820Sjeff} /* poll */ 2271219820Sjeff 2272219820Sjeff#ifdef __linux__ 2273219820Sjeff/* ========================================================================= */ 2274219820Sjeff/*..epoll_create -- replacement socket call. */ 2275219820Sjeff/* 2276219820Sjeff Need to make the size twice as large for shadow fds 2277219820Sjeff*/ 2278219820Sjeffint epoll_create(int size) 2279219820Sjeff{ 2280219820Sjeff int epfd; 2281219820Sjeff 2282219820Sjeff if (init_status == 0) 2283219820Sjeff __sdp_init(); 2284219820Sjeff 2285219820Sjeff if (NULL == _socket_funcs.epoll_create) { 2286219820Sjeff __sdp_log(9, 2287219820Sjeff "Error epoll_create: no implementation for epoll_create found\n"); 2288219820Sjeff return -1; 2289219820Sjeff } 2290219820Sjeff 2291219820Sjeff __sdp_log(2, "EPOLL_CREATE: <%s:%d>\n", program_invocation_short_name, 2292219820Sjeff size); 2293219820Sjeff 2294219820Sjeff epfd = _socket_funcs.epoll_create(size * 2); 2295219820Sjeff 2296219820Sjeff __sdp_log(2, "EPOLL_CREATE: <%s:%d> return %d\n", 2297219820Sjeff program_invocation_short_name, size, epfd); 2298219820Sjeff return epfd; 2299219820Sjeff} /* epoll_create */ 2300219820Sjeff 2301219820Sjeff/* ========================================================================= */ 2302219820Sjeff/*..epoll_ctl -- replacement socket call. */ 2303219820Sjeff/* 2304219820Sjeff Need to add/delete/modify shadow fds as well 2305219820Sjeff*/ 2306219820Sjeffint epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) 2307219820Sjeff{ 2308219820Sjeff int ret, shadow_fd, ret2; 2309219820Sjeff 2310219820Sjeff if (init_status == 0) 2311219820Sjeff __sdp_init(); 2312219820Sjeff 2313219820Sjeff if (NULL == _socket_funcs.epoll_ctl) { 2314219820Sjeff __sdp_log(9, 2315219820Sjeff "Error epoll_ctl: no implementation for epoll_ctl found\n"); 2316219820Sjeff return -1; 2317219820Sjeff } 2318219820Sjeff 2319219820Sjeff __sdp_log(2, "EPOLL_CTL: <%s:%d> op <%d:%d>\n", 2320219820Sjeff program_invocation_short_name, epfd, op, fd); 2321219820Sjeff 2322219820Sjeff ret = _socket_funcs.epoll_ctl(epfd, op, fd, event); 2323219820Sjeff 2324219820Sjeff shadow_fd = get_shadow_fd_by_fd(fd); 2325219820Sjeff if (shadow_fd != -1) { 2326219820Sjeff ret2 = _socket_funcs.epoll_ctl(epfd, op, shadow_fd, event); 2327219820Sjeff if (ret2 < 0) { 2328219820Sjeff __sdp_log(9, "Error epoll_ctl <%s:%d:%d>", 2329219820Sjeff program_invocation_short_name, fd, shadow_fd); 2330219820Sjeff return ret2; 2331219820Sjeff } 2332219820Sjeff } 2333219820Sjeff 2334219820Sjeff __sdp_log(2, "EPOLL_CTL: <%s:%d> return <%d>\n", 2335219820Sjeff program_invocation_short_name, epfd, ret); 2336219820Sjeff return ret; 2337219820Sjeff} /* epoll_ctl */ 2338219820Sjeff 2339219820Sjeff/* ========================================================================= */ 2340219820Sjeff/*..epoll_wait -- replacement socket call. */ 2341219820Sjeff/* 2342219820Sjeff We don't care who generated the event because all we get is user-context 2343219820Sjeff values. 2344219820Sjeff*/ 2345219820Sjeffint epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) 2346219820Sjeff{ 2347219820Sjeff int ret; 2348219820Sjeff 2349219820Sjeff if (init_status == 0) 2350219820Sjeff __sdp_init(); 2351219820Sjeff 2352219820Sjeff if (NULL == _socket_funcs.epoll_wait) { 2353219820Sjeff __sdp_log(9, 2354219820Sjeff "Error epoll_wait: no implementation for epoll_wait found\n"); 2355219820Sjeff return -1; 2356219820Sjeff } 2357219820Sjeff 2358219820Sjeff __sdp_log(2, "EPOLL_WAIT: <%s:%d>\n", program_invocation_short_name, epfd); 2359219820Sjeff 2360219820Sjeff ret = _socket_funcs.epoll_wait(epfd, events, maxevents, timeout); 2361219820Sjeff 2362219820Sjeff __sdp_log(2, "EPOLL_WAIT: <%s:%d> return <%d>\n", 2363219820Sjeff program_invocation_short_name, epfd, ret); 2364219820Sjeff return ret; 2365219820Sjeff} /* epoll_wait */ 2366219820Sjeff 2367219820Sjeff/* ========================================================================= */ 2368219820Sjeff/*..epoll_pwait -- replacement socket call. */ 2369219820Sjeff/* 2370219820Sjeff We don't care who generated the event because all we get is user-context 2371219820Sjeff values. 2372219820Sjeff*/ 2373219820Sjeffint 2374219820Sjeffepoll_pwait(int epfd, 2375219820Sjeff struct epoll_event *events, 2376219820Sjeff int maxevents, int timeout, const sigset_t * sigmask) 2377219820Sjeff{ 2378219820Sjeff int ret; 2379219820Sjeff 2380219820Sjeff if (init_status == 0) 2381219820Sjeff __sdp_init(); 2382219820Sjeff 2383219820Sjeff if (NULL == _socket_funcs.epoll_pwait) { 2384219820Sjeff __sdp_log(9, 2385219820Sjeff "Error epoll_pwait: no implementation for epoll_pwait found\n"); 2386219820Sjeff return -1; 2387219820Sjeff } 2388219820Sjeff 2389219820Sjeff __sdp_log(2, "EPOLL_PWAIT: <%s:%d>\n", program_invocation_short_name, epfd); 2390219820Sjeff 2391219820Sjeff ret = _socket_funcs.epoll_pwait(epfd, events, maxevents, timeout, sigmask); 2392219820Sjeff 2393219820Sjeff __sdp_log(2, "EPOLL_PWAIT: <%s:%d> return <%d>\n", 2394219820Sjeff program_invocation_short_name, epfd, ret); 2395219820Sjeff return ret; 2396219820Sjeff} /* epoll_pwait */ 2397219820Sjeff#endif 2398219820Sjeff 2399219820Sjeff/* ========================================================================= */ 2400219820Sjeff 2401219820Sjeff/* --------------------------------------------------------------------- */ 2402219820Sjeff/* */ 2403219820Sjeff/* Library load/unload initialization/cleanup */ 2404219820Sjeff/* */ 2405219820Sjeff/* --------------------------------------------------------------------- */ 2406219820Sjeff/* ========================================================================= */ 2407219820Sjeff/*..__sdp_init -- intialize the library */ 2408219820Sjeffvoid __sdp_init(void) 2409219820Sjeff{ 2410219820Sjeff char *config_file, *error_str; 2411219820Sjeff int fd; 2412219820Sjeff struct rlimit nofiles_limit; 2413219820Sjeff 2414219820Sjeff /* HACK: races might apply here: can we assume init is happening 2415219820Sjeff only within one thread ? */ 2416219820Sjeff if (init_status != 0) 2417219820Sjeff return; 2418219820Sjeff init_status = 1; 2419219820Sjeff 2420219820Sjeff dev_null_fd = open("/dev/null", O_WRONLY); 2421219820Sjeff 2422219820Sjeff /* figure out the max number of file descriptors */ 2423219820Sjeff if (getrlimit(RLIMIT_NOFILE, &nofiles_limit)) 2424219820Sjeff max_file_descriptors = 1024; 2425219820Sjeff else 2426219820Sjeff max_file_descriptors = nofiles_limit.rlim_cur; 2427219820Sjeff 2428219820Sjeff /* allocate and initialize the shadow sdp sockets array */ 2429219820Sjeff libsdp_fd_attributes = 2430219820Sjeff (struct sdp_extra_fd_attributes *) calloc(max_file_descriptors, 2431219820Sjeff sizeof(struct 2432219820Sjeff sdp_extra_fd_attributes)); 2433219820Sjeff for (fd = 0; fd < max_file_descriptors; fd++) 2434219820Sjeff init_extra_attribute(fd); 2435219820Sjeff 2436219820Sjeff#ifndef RTLD_NEXT 2437219820Sjeff /* 2438219820Sjeff * open libc for original socket call. 2439219820Sjeff * Solaris relies on RTLD next - since the socket calls are 2440219820Sjeff * actually in libsocket rather than libc. 2441219820Sjeff */ 2442219820Sjeff __libc_dl_handle = dlopen("/lib64/libc.so.6", RTLD_LAZY); 2443219820Sjeff if (NULL == __libc_dl_handle) { 2444219820Sjeff __libc_dl_handle = dlopen("/lib/libc.so.6", RTLD_LAZY); 2445219820Sjeff if (NULL == __libc_dl_handle) { 2446219820Sjeff fprintf(stderr, "%s\n", dlerror()); 2447219820Sjeff return; 2448219820Sjeff } 2449219820Sjeff } 2450219820Sjeff#endif 2451219820Sjeff 2452219820Sjeff /* 2453219820Sjeff * Get the original functions 2454219820Sjeff */ 2455219820Sjeff _socket_funcs.ioctl = dlsym(__libc_dl_handle, "ioctl"); 2456219820Sjeff if (NULL != (error_str = dlerror())) { 2457219820Sjeff fprintf(stderr, "%s\n", error_str); 2458219820Sjeff } 2459219820Sjeff 2460219820Sjeff _socket_funcs.fcntl = dlsym(__libc_dl_handle, "fcntl"); 2461219820Sjeff if (NULL != (error_str = dlerror())) { 2462219820Sjeff fprintf(stderr, "%s\n", error_str); 2463219820Sjeff } 2464219820Sjeff 2465219820Sjeff _socket_funcs.socket = dlsym(__libc_dl_handle, "socket"); 2466219820Sjeff if (NULL != (error_str = dlerror())) { 2467219820Sjeff fprintf(stderr, "%s\n", error_str); 2468219820Sjeff } 2469219820Sjeff 2470219820Sjeff _socket_funcs.setsockopt = dlsym(__libc_dl_handle, "setsockopt"); 2471219820Sjeff if (NULL != (error_str = dlerror())) { 2472219820Sjeff fprintf(stderr, "%s\n", error_str); 2473219820Sjeff } 2474219820Sjeff 2475219820Sjeff _socket_funcs.connect = dlsym(__libc_dl_handle, "connect"); 2476219820Sjeff if (NULL != (error_str = dlerror())) { 2477219820Sjeff fprintf(stderr, "%s\n", error_str); 2478219820Sjeff } 2479219820Sjeff 2480219820Sjeff _socket_funcs.listen = dlsym(__libc_dl_handle, "listen"); 2481219820Sjeff if (NULL != (error_str = dlerror())) { 2482219820Sjeff fprintf(stderr, "%s\n", error_str); 2483219820Sjeff } 2484219820Sjeff 2485219820Sjeff _socket_funcs.bind = dlsym(__libc_dl_handle, "bind"); 2486219820Sjeff if (NULL != (error_str = dlerror())) { 2487219820Sjeff fprintf(stderr, "%s\n", error_str); 2488219820Sjeff } 2489219820Sjeff 2490219820Sjeff _socket_funcs.close = dlsym(__libc_dl_handle, "close"); 2491219820Sjeff if (NULL != (error_str = dlerror())) { 2492219820Sjeff fprintf(stderr, "%s\n", error_str); 2493219820Sjeff } 2494219820Sjeff 2495219820Sjeff _socket_funcs.dup = dlsym(__libc_dl_handle, "dup"); 2496219820Sjeff if (NULL != (error_str = dlerror())) { 2497219820Sjeff fprintf(stderr, "%s\n", error_str); 2498219820Sjeff } 2499219820Sjeff 2500219820Sjeff _socket_funcs.dup2 = dlsym(__libc_dl_handle, "dup2"); 2501219820Sjeff if (NULL != (error_str = dlerror())) { 2502219820Sjeff fprintf(stderr, "%s\n", error_str); 2503219820Sjeff } 2504219820Sjeff 2505219820Sjeff _socket_funcs.getpeername = dlsym(__libc_dl_handle, "getpeername"); 2506219820Sjeff if (NULL != (error_str = dlerror())) { 2507219820Sjeff fprintf(stderr, "%s\n", error_str); 2508219820Sjeff } 2509219820Sjeff 2510219820Sjeff _socket_funcs.getsockname = dlsym(__libc_dl_handle, "getsockname"); 2511219820Sjeff if (NULL != (error_str = dlerror())) { 2512219820Sjeff fprintf(stderr, "%s\n", error_str); 2513219820Sjeff } 2514219820Sjeff 2515219820Sjeff _socket_funcs.accept = dlsym(__libc_dl_handle, "accept"); 2516219820Sjeff if (NULL != (error_str = dlerror())) { 2517219820Sjeff fprintf(stderr, "%s\n", error_str); 2518219820Sjeff } 2519219820Sjeff 2520219820Sjeff _socket_funcs.select = dlsym(__libc_dl_handle, "select"); 2521219820Sjeff if (NULL != (error_str = dlerror())) { 2522219820Sjeff fprintf(stderr, "%s\n", error_str); 2523219820Sjeff } 2524219820Sjeff 2525219820Sjeff _socket_funcs.pselect = dlsym(__libc_dl_handle, "pselect"); 2526219820Sjeff if (NULL != (error_str = dlerror())) { 2527219820Sjeff fprintf(stderr, "%s\n", error_str); 2528219820Sjeff } 2529219820Sjeff 2530219820Sjeff _socket_funcs.poll = dlsym(__libc_dl_handle, "poll"); 2531219820Sjeff if (NULL != (error_str = dlerror())) { 2532219820Sjeff fprintf(stderr, "%s\n", error_str); 2533219820Sjeff } 2534219820Sjeff 2535219820Sjeff#ifdef __linux__ 2536219820Sjeff _socket_funcs.epoll_create = dlsym(__libc_dl_handle, "epoll_create"); 2537219820Sjeff if (NULL != (error_str = dlerror())) { 2538219820Sjeff fprintf(stderr, "%s\n", error_str); 2539219820Sjeff } 2540219820Sjeff 2541219820Sjeff _socket_funcs.epoll_ctl = dlsym(__libc_dl_handle, "epoll_ctl"); 2542219820Sjeff if (NULL != (error_str = dlerror())) { 2543219820Sjeff fprintf(stderr, "%s\n", error_str); 2544219820Sjeff } 2545219820Sjeff 2546219820Sjeff _socket_funcs.epoll_wait = dlsym(__libc_dl_handle, "epoll_wait"); 2547219820Sjeff if (NULL != (error_str = dlerror())) { 2548219820Sjeff fprintf(stderr, "%s\n", error_str); 2549219820Sjeff } 2550219820Sjeff 2551219820Sjeff _socket_funcs.epoll_pwait = dlsym(__libc_dl_handle, "epoll_pwait"); 2552219820Sjeff if (NULL != (error_str = dlerror())) { 2553219820Sjeff fprintf(stderr, "%s\n", error_str); 2554219820Sjeff } 2555219820Sjeff#endif 2556219820Sjeff#ifdef SOLARIS_BUILD 2557219820Sjeff _socket_xnet_funcs.socket = dlsym(__libc_dl_handle, "__xnet_socket"); 2558219820Sjeff if (NULL != (error_str = dlerror())) { 2559219820Sjeff fprintf(stderr, "%s\n", error_str); 2560219820Sjeff } 2561219820Sjeff 2562219820Sjeff _socket_xnet_funcs.connect = dlsym(__libc_dl_handle, "__xnet_connect"); 2563219820Sjeff if (NULL != (error_str = dlerror())) { 2564219820Sjeff fprintf(stderr, "%s\n", error_str); 2565219820Sjeff } 2566219820Sjeff 2567219820Sjeff _socket_xnet_funcs.listen = dlsym(__libc_dl_handle, "__xnet_listen"); 2568219820Sjeff if (NULL != (error_str = dlerror())) { 2569219820Sjeff fprintf(stderr, "%s\n", error_str); 2570219820Sjeff } 2571219820Sjeff 2572219820Sjeff _socket_xnet_funcs.bind = dlsym(__libc_dl_handle, "__xnet_bind"); 2573219820Sjeff if (NULL != (error_str = dlerror())) { 2574219820Sjeff fprintf(stderr, "%s\n", error_str); 2575219820Sjeff } 2576219820Sjeff 2577219820Sjeff /* Determine program name by asking libdl */ 2578219820Sjeff Dl_argsinfo args_info; 2579219820Sjeff if (NULL != dlinfo(RTLD_SELF, RTLD_DI_ARGSINFO, &args_info)) { 2580219820Sjeff fprintf(stderr, "args_info: %s\n", dlerror()); 2581219820Sjeff } else { 2582219820Sjeff program_invocation_name = args_info.dla_argv[0]; 2583219820Sjeff program_invocation_short_name = basename(args_info.dla_argv[0]); 2584219820Sjeff } 2585219820Sjeff#endif 2586219820Sjeff 2587219820Sjeff if (getenv("SIMPLE_LIBSDP") != NULL) { 2588219820Sjeff simple_sdp_library = 1; 2589219820Sjeff } 2590219820Sjeff 2591219820Sjeff if (getenv("ALWAYS_USE_SDP") != NULL) { 2592219820Sjeff simple_sdp_library = 1; 2593219820Sjeff } 2594219820Sjeff#define LIBSDP_DEFAULT_CONFIG_FILE SYSCONFDIR "/libsdp.conf" 2595219820Sjeff if (!simple_sdp_library) { 2596219820Sjeff config_file = getenv("LIBSDP_CONFIG_FILE"); 2597219820Sjeff if (!config_file) 2598219820Sjeff config_file = LIBSDP_DEFAULT_CONFIG_FILE; 2599219820Sjeff 2600219820Sjeff if (__sdp_parse_config(config_file)) { 2601219820Sjeff fprintf(stderr, 2602219820Sjeff "libsdp Error: failed to parse config file:%s. Using defaults.\n", 2603219820Sjeff config_file); 2604219820Sjeff } 2605219820Sjeff } 2606219820Sjeff 2607219820Sjeff __sdp_log(1, "Max file descriptors:%d\n", max_file_descriptors); 2608219820Sjeff init_status = 2; 2609219820Sjeff 2610219820Sjeff} /* __sdp_init */ 2611219820Sjeff 2612219820Sjeff/* ========================================================================= */ 2613219820Sjeff/*..__sdp_fini -- when the library is unloaded this is called */ 2614219820Sjeffvoid __sdp_fini(void) 2615219820Sjeff{ 2616219820Sjeff struct use_family_rule *rule; 2617219820Sjeff for (rule = __sdp_clients_family_rules_head; rule != NULL; 2618219820Sjeff rule = rule->next) 2619219820Sjeff free(rule->prog_name_expr); 2620219820Sjeff for (rule = __sdp_servers_family_rules_head; rule != NULL; 2621219820Sjeff rule = rule->next) 2622219820Sjeff free(rule->prog_name_expr); 2623219820Sjeff 2624219820Sjeff free(libsdp_fd_attributes); 2625219820Sjeff 2626219820Sjeff#ifndef RTLD_NEXT 2627219820Sjeff dlclose(__libc_dl_handle); 2628219820Sjeff#endif 2629219820Sjeff} /* _fini */ 2630