1/* 2 This software is available to you under a choice of one of two 3 licenses. You may choose to be licensed under the terms of the GNU 4 General Public License (GPL) Version 2, available at 5 <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD 6 license, available in the LICENSE.TXT file accompanying this 7 software. These details are also available at 8 <http://openib.org/license.html>. 9 10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 11 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 12 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 13 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 14 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 15 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 SOFTWARE. 18 19 Copyright (c) 2004 Topspin Communications. All rights reserved. 20 Copyright (c) 2005-2006 Mellanox Technologies Ltd. All rights reserved. 21 22 $Id$ 23*/ 24 25/* 26 * system includes 27 */ 28#if HAVE_CONFIG_H 29# include <config.h> 30#endif /* HAVE_CONFIG_H */ 31 32#ifdef SOLARIS_BUILD 33/* Our prototypes for ioctl, get*name and accept do not strictly 34 match the headers - we use the following lines to move the header 35 versions 'out of the way' temporarily. */ 36#define ioctl __real_ioctl 37#define getsockname __real_getsockname 38#define getpeername __real_getpeername 39#define accept __real_accept 40#define FASYNC 0 41#include <libgen.h> 42#endif 43#include <unistd.h> 44#include <errno.h> 45#include <stdio.h> 46#include <stdlib.h> 47#include <string.h> 48#define __USE_GNU 49#define _GNU_SOURCE /* define RTLD_NEXT */ 50#include <dlfcn.h> 51#include <sys/types.h> 52#include <sys/socket.h> 53#include <netinet/tcp.h> 54#include <arpa/inet.h> 55#include <netinet/in.h> 56#include <stdarg.h> 57#include <sys/time.h> 58#include <sys/resource.h> 59#include <sys/stat.h> 60#include <fcntl.h> 61#include <signal.h> 62#include <sys/poll.h> 63#ifdef __linux__ 64#include <sys/epoll.h> 65#endif 66 67#ifdef SOLARIS_BUILD 68/* We're done protecting ourselves from the header prototypes */ 69#undef ioctl 70#undef getsockname 71#undef getpeername 72#undef accept 73#endif 74 75/* 76 * SDP specific includes 77 */ 78#include "libsdp.h" 79 80/* We can not use sizeof(sockaddr_in6) as the extra scope_id field is not a must have */ 81#define IPV6_ADDR_IN_MIN_LEN 24 82 83/* setsockopt() level and optname declarations */ 84#define SOL_SDP 1025 85#define SDP_UNBIND 259 /* Unbind socket */ 86 87/* Solaris has two entry socket creation functions */ 88#define SOCKET_SEMANTIC_DEFAULT 0 89#define SOCKET_SEMANTIC_XNET 1 90 91/* HACK: filter ioctl errors for FIONREAD */ 92#define FIONREAD 0x541B 93 94void __attribute__ ((constructor)) __sdp_init(void); 95void __attribute__ ((destructor)) __sdp_fini(void); 96 97/* --------------------------------------------------------------------- */ 98/* library type definitions. */ 99/* --------------------------------------------------------------------- */ 100 101typedef int (*ioctl_func_t) (int fd, 102 int request, 103 void *arg0, 104 void *arg1, 105 void *arg2, 106 void *arg3, 107 void *arg4, void *arg5, void *arg6, void *arg7); 108 109typedef int (*fcntl_func_t) (int fd, int cmd, ...); 110 111typedef int (*socket_func_t) (int domain, int type, int protocol); 112 113typedef int (*setsockopt_func_t) (int s, 114 int level, 115 int optname, 116 const void *optval, socklen_t optlen); 117 118typedef int (*connect_func_t) (int sockfd, 119 const struct sockaddr * serv_addr, 120 socklen_t addrlen); 121 122typedef int (*listen_func_t) (int s, int backlog); 123 124typedef int (*bind_func_t) (int sockfd, 125 const struct sockaddr * my_addr, socklen_t addrlen); 126 127typedef int (*close_func_t) (int fd); 128 129typedef int (*dup_func_t) (int fd); 130 131typedef int (*dup2_func_t) (int oldfd, int newfd); 132 133typedef int (*getsockname_func_t) (int fd, 134 struct sockaddr * name, socklen_t * namelen); 135 136typedef int (*getpeername_func_t) (int fd, 137 struct sockaddr * name, socklen_t * namelen); 138 139typedef int (*accept_func_t) (int fd, 140 struct sockaddr * addr, socklen_t * addrlen); 141 142typedef int (*select_func_t) (int n, 143 fd_set * readfds, 144 fd_set * writefds, 145 fd_set * exceptfds, struct timeval * timeout); 146 147typedef int (*pselect_func_t) (int n, 148 fd_set * readfds, 149 fd_set * writefds, 150 fd_set * exceptfds, 151 const struct timespec * timeout, 152 const sigset_t * sigmask); 153 154typedef int (*poll_func_t) (struct pollfd * ufds, 155 unsigned long int nfds, int timeout); 156 157#ifdef __linux__ 158typedef int (*epoll_create_func_t) (int size); 159 160typedef int (*epoll_ctl_func_t) (int epfd, 161 int op, int fd, struct epoll_event * event); 162 163typedef int (*epoll_wait_func_t) (int epfd, 164 struct epoll_event * events, 165 int maxevents, int timeout); 166 167typedef int (*epoll_pwait_func_t) (int epfd, 168 struct epoll_event * events, 169 int maxevents, 170 int timeout, const sigset_t * sigmask); 171#endif 172 173 174struct socket_lib_funcs { 175 ioctl_func_t ioctl; 176 fcntl_func_t fcntl; 177 socket_func_t socket; 178 setsockopt_func_t setsockopt; 179 connect_func_t connect; 180 listen_func_t listen; 181 bind_func_t bind; 182 close_func_t close; 183 dup_func_t dup; 184 dup2_func_t dup2; 185 getpeername_func_t getpeername; 186 getsockname_func_t getsockname; 187 accept_func_t accept; 188 select_func_t select; 189 pselect_func_t pselect; 190 poll_func_t poll; 191#ifdef __linux__ 192 epoll_create_func_t epoll_create; 193 epoll_ctl_func_t epoll_ctl; 194 epoll_wait_func_t epoll_wait; 195 epoll_pwait_func_t epoll_pwait; 196#endif 197}; /* socket_lib_funcs */ 198 199#ifdef SOLARIS_BUILD 200/* Solaris has another interface to socket functions prefixed with __xnet_ */ 201struct socket_lib_xnet_funcs { 202 socket_func_t socket; 203 connect_func_t connect; 204 listen_func_t listen; 205 bind_func_t bind; 206}; 207#endif 208 209static int simple_sdp_library; 210static int max_file_descriptors; 211static int dev_null_fd; 212volatile static int init_status = 0; /* 0: idle, 1:during, 2:ready */ 213 214/* --------------------------------------------------------------------- */ 215/* library static and global variables */ 216/* --------------------------------------------------------------------- */ 217 218/* glibc provides these symbols - for Solaris builds we fake them 219 * until _init is called, at which point we quiz libdl.. */ 220#ifdef SOLARIS_BUILD 221char *program_invocation_name = "[progname]", *program_invocation_short_name = 222 "[short_progname]"; 223#else 224extern char *program_invocation_name, *program_invocation_short_name; 225#endif 226 227#ifdef RTLD_NEXT 228static void *__libc_dl_handle = RTLD_NEXT; 229#else 230static void *__libc_dl_handle; 231#endif 232 233/* extra fd attributes we need for our algorithms */ 234struct sdp_extra_fd_attributes { 235 int shadow_fd; /* file descriptor of shadow sdp socket */ 236 short last_accept_was_tcp; /* used by accept to alternate tcp and sdp */ 237 short is_sdp; /* 1 if the fd represents an sdp socket */ 238}; /* sdp_extra_fd_attributes */ 239 240/* stores the extra attributes struct by fd */ 241static struct sdp_extra_fd_attributes *libsdp_fd_attributes; 242 243static struct socket_lib_funcs _socket_funcs = { 244 .socket = NULL, 245 /* Automatically sets all other elements to NULL */ 246}; /* _socket_funcs */ 247 248#ifdef SOLARIS_BUILD 249static struct socket_lib_xnet_funcs _socket_xnet_funcs = { 250 .socket = NULL, 251 /* Automatically sets all other elements to NULL */ 252}; 253#endif 254 255/* --------------------------------------------------------------------- */ 256/* Prototypes */ 257/* --------------------------------------------------------------------- */ 258void __sdp_init(void); 259 260/* --------------------------------------------------------------------- */ 261/* */ 262/* local static functions. */ 263/* */ 264/* --------------------------------------------------------------------- */ 265 266/* ========================================================================= */ 267/*..init_extra_attribute -- initialize the set of extra attributes for a fd */ 268static void init_extra_attribute(int fd) 269{ 270 if ((0 <= fd) && (max_file_descriptors > fd)) { 271 libsdp_fd_attributes[fd].shadow_fd = -1; 272 libsdp_fd_attributes[fd].is_sdp = 0; 273 libsdp_fd_attributes[fd].last_accept_was_tcp = -1; 274 } 275} 276 277static inline int is_valid_fd(int fd) 278{ 279 return (0 <= fd) && (fd < max_file_descriptors); 280} 281 282/* ========================================================================= */ 283/*..get_shadow_fd_by_fd -- given an fd return its shadow fd if exists */ 284static inline int get_shadow_fd_by_fd(int fd) 285{ 286 if (is_valid_fd(fd)) 287 return libsdp_fd_attributes[fd].shadow_fd; 288 else 289 return -1; 290} 291 292/* ========================================================================= */ 293/*..set_shadow_for_fd -- */ 294static inline void set_shadow_for_fd(int fd, int shadow_fd) 295{ 296 if (is_valid_fd(fd)) 297 libsdp_fd_attributes[fd].shadow_fd = shadow_fd; 298} 299 300/* ========================================================================= */ 301/*..set_is_sdp_socket -- */ 302static inline void set_is_sdp_socket(int fd, short is_sdp) 303{ 304 if (is_valid_fd(fd)) 305 libsdp_fd_attributes[fd].is_sdp = is_sdp; 306} 307 308/* ========================================================================= */ 309/*..get_is_sdp_socket -- given an fd return 1 if it is an SDP socket */ 310static inline int get_is_sdp_socket(int fd) 311{ 312 if (is_valid_fd(fd)) 313 return libsdp_fd_attributes[fd].is_sdp; 314 else 315 return 0; 316} 317 318/* ========================================================================= */ 319/*..last_accept_was_tcp -- given an fd return 1 if last accept was tcp */ 320static inline int last_accept_was_tcp(int fd) 321{ 322 if (is_valid_fd(fd)) 323 return libsdp_fd_attributes[fd].last_accept_was_tcp; 324 else 325 return 0; 326} 327 328/* ========================================================================= */ 329/*..set_last_accept -- given an fd set last accept was tcp */ 330static inline void set_last_accept(int fd, int was_tcp) 331{ 332 if (is_valid_fd(fd)) 333 libsdp_fd_attributes[fd].last_accept_was_tcp = was_tcp; 334} 335 336/* ========================================================================= */ 337/*..cleanup_shadow -- an error occured on an SDP socket, cleanup */ 338static int cleanup_shadow(int fd) 339{ 340 int shadow_fd = get_shadow_fd_by_fd(fd); 341 342 if (shadow_fd == -1) 343 return 0; 344 libsdp_fd_attributes[fd].shadow_fd = -1; 345 libsdp_fd_attributes[fd].last_accept_was_tcp = 0; 346 return (_socket_funcs.close(shadow_fd)); 347} /* cleanup_shadow */ 348 349/* ========================================================================= */ 350/*..replace_fd_with_its_shadow -- perform all required for such promotion */ 351static int replace_fd_with_its_shadow(int fd) 352{ 353 int shadow_fd = libsdp_fd_attributes[fd].shadow_fd; 354 355 if (shadow_fd == -1) { 356 __sdp_log(9, "Error replace_fd_with_its_shadow: no shadow for fd:%d\n", 357 fd); 358 return EINVAL; 359 } 360 361 /* copy the attributes of the shadow before we clean them up */ 362 libsdp_fd_attributes[fd] = libsdp_fd_attributes[shadow_fd]; 363 libsdp_fd_attributes[fd].shadow_fd = -1; 364 if (_socket_funcs.dup2(shadow_fd, fd) < 0) { 365 init_extra_attribute(fd); 366 _socket_funcs.close(shadow_fd); 367 return EINVAL; 368 } 369 _socket_funcs.close(shadow_fd); 370 return 0; 371} 372 373static sa_family_t get_sdp_domain(int domain) 374{ 375 if (AF_INET_SDP == domain || AF_INET6_SDP == domain) 376 return domain; 377 378 if (AF_INET == domain) 379 return AF_INET_SDP; 380 else if (AF_INET6 == domain) 381 return AF_INET6_SDP; 382 383 __sdp_log(9, "Error %s: unknown TCP domain: %d\n", __func__, domain); 384 385 return -1; 386} 387 388static int get_sock_domain(int sd) 389{ 390 struct sockaddr_storage tmp_sin; 391 socklen_t tmp_sinlen = sizeof(tmp_sin); 392 393 if (_socket_funcs.getsockname(sd, (struct sockaddr *) &tmp_sin, &tmp_sinlen) < 0) { 394 __sdp_log(9, "Error %s: getsockname return <%d> for socket\n", __func__, errno); 395 return -1; 396 } 397 398 return ((struct sockaddr *)&tmp_sin)->sa_family; 399} 400 401/* ========================================================================= */ 402/*..is_filtered_unsuported_sockopt -- return 1 if to filter sockopt failure */ 403static inline int is_filtered_unsuported_sockopt(int level, int optname) 404{ 405 /* 406 * TODO: until we know exactly which unsupported opts are really 407 * a don't care we always pass the error 408 */ 409 return 0; 410#if 0 411 /* these are the SOL_TCP OPTS we should consider filterring */ 412 TCP_NODELAY 1 /* Don't delay send to coalesce packets */ 413 TCP_MAXSEG 2 /* Set maximum segment size */ 414 TCP_CORK 3 /* Control sending of partial frames */ 415 TCP_KEEPIDLE 4 /* Start keeplives after this period */ 416 TCP_KEEPINTVL 5 /* Interval between keepalives */ 417 TCP_KEEPCNT 6 /* Number of keepalives before death */ 418 TCP_SYNCNT 7 /* Number of SYN retransmits */ 419 TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */ 420 TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */ 421 TCP_WINDOW_CLAMP 10 /* Bound advertised window */ 422 TCP_INFO 11 /* Information about this connection. */ 423 TCP_QUICKACK 12 /* Bock/reenable quick ACKs. */ 424#endif 425} 426 427/* ========================================================================= */ 428/*..is_invalid_addr -- return 1 if given pointer is not valid */ 429/* NOTE: invalidation of the size is going to happen during actual call */ 430static inline int is_invalid_addr(const void *p) 431{ 432 /* HACK: on some systems we can not write to check for pointer validity */ 433 size_t ret = fcntl(dev_null_fd, F_GETLK, p); 434 435 ret = (errno == EFAULT); 436 errno = 0; 437 return ret; 438} 439 440/* ========================================================================= */ 441/*..get_addr_str -- fill in the given buffer with addr str or return 1 */ 442static int get_addr_str(const struct sockaddr *addr, char *buf, size_t len) 443{ 444 const struct sockaddr_in *sin = (struct sockaddr_in *) addr; 445 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr; 446 char const *conv_res; 447 448 if (sin->sin_family == AF_INET) { 449 conv_res = inet_ntop(AF_INET, (void *) &(sin->sin_addr), buf, len); 450 } else if (sin6->sin6_family == AF_INET6) { 451 conv_res = inet_ntop(AF_INET6, (void *) &sin6->sin6_addr, buf, len); 452 } else { 453 strncpy(buf, "unknown address family", len); 454 conv_res = (char *) 1; 455 } 456 return conv_res == NULL; 457} 458 459/* --------------------------------------------------------------------- */ 460/* */ 461/* Socket library function overrides. */ 462/* */ 463/* --------------------------------------------------------------------- */ 464 465/* ========================================================================= */ 466/*..ioctl -- replacement ioctl call. */ 467int 468ioctl(int fd, 469 int request, 470 void *arg0, 471 void *arg1, 472 void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7) 473{ 474 int shadow_fd; 475 int sret = 0; 476 int ret = 0; 477 478 if (init_status == 0) 479 __sdp_init(); 480 481 if (NULL == _socket_funcs.ioctl) { 482 __sdp_log(9, "Error ioctl: no implementation for ioctl found\n"); 483 return -1; 484 } 485 486 shadow_fd = get_shadow_fd_by_fd(fd); 487 488 __sdp_log(2, "IOCTL: <%s:%d:%d> request <%d>\n", 489 program_invocation_short_name, fd, shadow_fd, request); 490 491 ret = _socket_funcs.ioctl(fd, request, 492 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); 493 494 /* HACK: avoid failing on FIONREAD error as SDP does not support it at the moment */ 495 if ((ret < 0) && get_is_sdp_socket(fd) && (request == FIONREAD)) { 496 __sdp_log(8, "Warning ioctl: " 497 "Ignoring FIONREAD error for SDP socket.\n"); 498 ret = 0; 499 } 500 501 /* if shadow and no error on tcp */ 502 if ((ret >= 0) && (-1 != shadow_fd)) { 503 sret = _socket_funcs.ioctl(shadow_fd, request, 504 arg0, arg1, arg2, arg3, arg4, arg5, arg6, 505 arg7); 506 /* HACK: avoid failing on FIONREAD error as SDP does not support it at the moment */ 507 if ((sret < 0) && (request == FIONREAD)) { 508 __sdp_log(8, "Warning ioctl: " 509 "Ignoring FIONREAD error for shadow SDP socket.\n"); 510 sret = 0; 511 } 512 513 if (sret < 0) { 514 __sdp_log(9, "Error ioctl: " 515 "<%d> calling ioctl for SDP socket, closing it.\n", 516 errno); 517 cleanup_shadow(fd); 518 } 519 } 520 521 __sdp_log(2, "IOCTL: <%s:%d:%d> result <%d:%d>\n", 522 program_invocation_short_name, fd, shadow_fd, ret, sret); 523 524 return ret; 525} /* ioctl */ 526 527/* ========================================================================= */ 528/*..fcntl -- replacement fcntl call. */ 529int fcntl(int fd, int cmd, ...) 530{ 531 int shadow_fd; 532 int sret = 0; 533 int ret = 0; 534 535 void *arg; 536 va_list ap; 537 538 va_start(ap, cmd); 539 arg = va_arg(ap, void *); 540 va_end(ap); 541 542 543 if (init_status == 0) 544 __sdp_init(); 545 546 if (NULL == _socket_funcs.fcntl) { 547 __sdp_log(9, "Error fcntl: no implementation for fcntl found\n"); 548 return -1; 549 } 550 551 shadow_fd = get_shadow_fd_by_fd(fd); 552 553 __sdp_log(2, "FCNTL: <%s:%d:%d> command <%d> argument <%p>\n", 554 program_invocation_short_name, fd, shadow_fd, cmd, arg); 555 556 ret = _socket_funcs.fcntl(fd, cmd, arg); 557 if ((ret >= 0) && (-1 != shadow_fd)) { 558 sret = _socket_funcs.fcntl(shadow_fd, cmd, arg); 559 if (sret < 0) { 560 __sdp_log(9, "Error fcntl:" 561 " <%d> calling fcntl(%d, %d, %p) for SDP socket. Closing it.\n", 562 shadow_fd, cmd, arg, errno); 563 cleanup_shadow(fd); 564 } 565 } 566 567 __sdp_log(2, "FCNTL: <%s:%d:%d> result <%d:%d>\n", 568 program_invocation_short_name, fd, shadow_fd, ret, sret); 569 570 return ret; 571} /* fcntl */ 572 573/* ========================================================================= */ 574/*..setsockopt -- replacement setsockopt call. */ 575int 576setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) 577{ 578 int shadow_fd; 579 int sret = 0; 580 int ret = 0; 581 582 if (init_status == 0) 583 __sdp_init(); 584 585 if (NULL == _socket_funcs.setsockopt) { 586 __sdp_log(9, "Error setsockopt:" 587 " no implementation for setsockopt found\n"); 588 return -1; 589 } 590 591 shadow_fd = get_shadow_fd_by_fd(fd); 592 593 __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> level <%d> name <%d>\n", 594 program_invocation_short_name, fd, shadow_fd, level, optname); 595 596 if (level == SOL_SOCKET && optname == SO_KEEPALIVE && get_is_sdp_socket(fd)) { 597 level = AF_INET_SDP; 598 __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> substitute level %d\n", 599 program_invocation_short_name, fd, shadow_fd, level); 600 } 601 602 ret = _socket_funcs.setsockopt(fd, level, optname, optval, optlen); 603 if ((ret >= 0) && (shadow_fd != -1)) { 604 if (level == SOL_SOCKET && optname == SO_KEEPALIVE && 605 get_is_sdp_socket(shadow_fd)) { 606 level = AF_INET_SDP; 607 __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> substitute level %d\n", 608 program_invocation_short_name, fd, shadow_fd, level); 609 } 610 611 sret = _socket_funcs.setsockopt(shadow_fd, level, optname, optval, optlen); 612 if (sret < 0) { 613 __sdp_log(8, "Warning sockopts:" 614 " ignoring error on shadow SDP socket fd:<%d>\n", fd); 615 /* 616 * HACK: we should allow some errors as some sock opts are unsupported 617 * __sdp_log(9, "Error %d calling setsockopt for SDP socket, closing\n", errno); 618 * cleanup_shadow(fd); 619 */ 620 } 621 } 622 623 /* Due to SDP limited implmentation of sockopts we ignore some errors */ 624 if ((ret < 0) && get_is_sdp_socket(fd) && 625 is_filtered_unsuported_sockopt(level, optname)) { 626 __sdp_log(8, "Warning sockopts: " 627 "ignoring error on non implemented sockopt on SDP socket" 628 " fd:<%d> level:<%d> opt:<%d>\n", fd, level, optval); 629 ret = 0; 630 } 631 632 __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> result <%d:%d>\n", 633 program_invocation_short_name, fd, shadow_fd, ret, sret); 634 635 return ret; 636} /* setsockopt */ 637 638/* ========================================================================= */ 639/*..socket -- replacement socket call. */ 640 641static inline int __create_socket_semantic(int domain, 642 int type, 643 int protocol, int semantics) 644{ 645 return 646#ifdef SOLARIS_BUILD 647 (semantics == SOCKET_SEMANTIC_XNET) ? 648 _socket_xnet_funcs.socket(domain, type, protocol) : 649#endif 650 _socket_funcs.socket(domain, type, protocol); 651} 652 653/* Contains the main logic for creating shadow SDP sockets */ 654static int __create_socket(int domain, int type, int protocol, int semantics) 655{ 656 int s = -1; 657 int shadow_fd = -1; 658 use_family_t family_by_prog; 659 int sdp_domain; 660 661 if (init_status == 0) 662 __sdp_init(); 663 664 if (NULL == _socket_funcs.socket) { 665 __sdp_log(9, "Error socket: no implementation for socket found\n"); 666 return -1; 667 } 668 669 __sdp_log(2, "SOCKET: <%s> domain <%d> type <%d> protocol <%d>\n", 670 program_invocation_short_name, domain, type, protocol); 671 672 sdp_domain = get_sdp_domain(domain); 673 if (sdp_domain < 0) { 674 errno = EAFNOSUPPORT; 675 s = -1; 676 goto done; 677 } 678 679 /* check to see if we can skip the shadow */ 680 if ((AF_INET == domain || AF_INET6 == domain) && (SOCK_STREAM == type)) 681 if (simple_sdp_library) 682 family_by_prog = USE_SDP; 683 else 684 family_by_prog = __sdp_match_by_program(); 685 else if (AF_INET_SDP == domain || AF_INET6_SDP == domain) 686 family_by_prog = USE_SDP; 687 else 688 family_by_prog = USE_TCP; 689 690 if (family_by_prog == USE_TCP) { 691 __sdp_log(1, "SOCKET: making TCP only socket (no shadow)\n"); 692 s = __create_socket_semantic(domain, type, protocol, semantics); 693 init_extra_attribute(s); 694 set_is_sdp_socket(s, 0); 695 goto done; 696 } 697 698 if (family_by_prog == USE_SDP) { 699 /* HACK: convert the protocol if IPPROTO_IP */ 700 if (protocol == 0) 701 protocol = IPPROTO_TCP; 702 703 __sdp_log(1, "SOCKET: making SDP socket type:%d proto:%d\n", 704 type, protocol); 705 s = __create_socket_semantic(sdp_domain, type, protocol, semantics); 706 init_extra_attribute(s); 707 set_is_sdp_socket(s, 1); 708 goto done; 709 } 710 711 /* HACK: if we fail creating the TCP socket should we abort ? */ 712 __sdp_log(1, "SOCKET: making TCP socket\n"); 713 s = __create_socket_semantic(domain, type, protocol, semantics); 714 init_extra_attribute(s); 715 set_is_sdp_socket(s, 0); 716 if (is_valid_fd(s)) { 717 if (((AF_INET == domain) || (AF_INET6 == domain)) && 718 (SOCK_STREAM == type)) { 719 720 if (protocol == 0) 721 protocol = IPPROTO_TCP; 722 __sdp_log(1, "SOCKET: making SDP shadow socket type:%d proto:%d\n", 723 type, protocol); 724 shadow_fd = 725 __create_socket_semantic(sdp_domain, type, protocol, 726 semantics); 727 if (is_valid_fd(shadow_fd)) { 728 init_extra_attribute(shadow_fd); 729 if (libsdp_fd_attributes[s].shadow_fd != -1) { 730 __sdp_log(8, "Warning socket: " 731 "overriding existing shadow fd:%d for fd:%d\n", 732 libsdp_fd_attributes[s].shadow_fd, s); 733 } 734 set_is_sdp_socket(shadow_fd, 1); 735 set_shadow_for_fd(s, shadow_fd); 736 } else { 737 __sdp_log(9, 738 "Error socket: <%d> calling socket for SDP socket\n", 739 errno); 740 /* fail if we did not make the SDP socket */ 741 __sdp_log(1, "SOCKET: closing TCP socket:<%d>\n", s); 742 _socket_funcs.close(s); 743 s = -1; 744 } 745 } 746 } else { 747 __sdp_log(9, "Error socket: " 748 "ignoring SDP socket since TCP fd:%d out of range\n", s); 749 } 750 751done: 752 __sdp_log(2, "SOCKET: <%s:%d:%d>\n", 753 program_invocation_short_name, s, shadow_fd); 754 755 return s; 756} /* socket */ 757 758int socket(int domain, int type, int protocol) 759{ 760 return __create_socket(domain, type, protocol, SOCKET_SEMANTIC_DEFAULT); 761} 762 763#ifdef SOLARIS_BUILD 764int __xnet_socket(int domain, int type, int protocol) 765{ 766 return __create_socket(domain, type, protocol, SOCKET_SEMANTIC_XNET); 767} 768#endif 769 770/* ========================================================================= */ 771/*..get_fd_addr_port_num - obtain the port the fd is attached to */ 772static int get_fd_addr_port_num(int sd) 773{ 774 struct sockaddr_storage addr; 775 int ret; 776 const struct sockaddr_in *sin; 777 socklen_t addrlen = sizeof(addr); 778 779 ret = _socket_funcs.getsockname(sd, (struct sockaddr *) &addr, &addrlen); 780 781 if (ret) { 782 __sdp_log(9, "Error: in get_fd_addr_port_num - Failed to get getsockname\n"); 783 return -1; 784 } 785 786 /* port num is in same location for IPv4 and IPv6 */ 787 sin = (const struct sockaddr_in *) &addr; 788 return ntohs(sin->sin_port); 789} 790 791/* ========================================================================= */ 792/*..set_addr_port_num - sets the port in the given address */ 793static int set_addr_port_num(const struct sockaddr *addr, int port) 794{ 795 struct sockaddr_in *sin = (struct sockaddr_in *) addr; 796 797 /* port num is in same location for IPv4 and IPv6 */ 798 sin->sin_port = htons(port); 799 return 0; 800} 801 802/* ========================================================================= */ 803/* perform a bind with the given socket semantics */ 804static inline int 805__bind_semantics(int fd, 806 const struct sockaddr *my_addr, 807 socklen_t addrlen, int semantics) 808{ 809 return 810#ifdef SOLARIS_BUILD 811 (semantics == SOCKET_SEMANTIC_XNET) ? 812 _socket_xnet_funcs.bind(fd, my_addr, addrlen) : 813#endif 814 _socket_funcs.bind(fd, my_addr, addrlen); 815} 816 817/* ========================================================================= */ 818/*..find_free_port - find same free port on both TCP and SDP */ 819#define MAX_BIND_ANY_PORT_TRIES 20000 820static int 821find_free_port(const struct sockaddr *sin_addr, 822 const socklen_t addrlen, 823 int orig_sd, 824 int *sdp_sd, int *tcp_sd, int semantics) 825{ 826 static int tcp_turn = 1; 827 int tmp_turn = tcp_turn; 828 int num_of_loops = 0; 829 int port = -1; 830 int tmp_sd[2]; 831 unsigned int yes = 1; 832 int ret; 833 int domain, sdp_domain; 834 835 __sdp_log(2, "find_free_port: starting search for common free port\n"); 836 837 /* need to obtain the address family from the fd */ 838 domain = get_sock_domain(orig_sd); 839 if (domain == -1) { 840 errno = EFAULT; 841 goto done; 842 } 843 844 sdp_domain = get_sdp_domain(domain); 845 if (sdp_domain < 0) { 846 errno = EFAULT; 847 goto done; 848 } 849 850 do { 851 __sdp_log(1, "find_free_port: taking loop (%d)\n", ++num_of_loops); 852 853 __sdp_log(1, "find_free_port: creating the two sockets\n"); 854 tmp_sd[0] = _socket_funcs.socket(sdp_domain, SOCK_STREAM, IPPROTO_TCP); 855 if (tmp_sd[0] < 0) { 856 __sdp_log(8, "Warning find_free_port: creating first socket failed\n"); 857 goto done; 858 } 859 860 _socket_funcs.setsockopt(tmp_sd[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); 861 862 tmp_sd[1] = _socket_funcs.socket(domain, SOCK_STREAM, IPPROTO_TCP); 863 if (tmp_sd[1] < 0) { 864 __sdp_log(8, "Warning find_free_port: creating second socket failed\n"); 865 _socket_funcs.close(tmp_sd[0]); 866 goto done; 867 } 868 869 _socket_funcs.setsockopt(tmp_sd[1], SOL_SOCKET, SO_REUSEADDR, &yes, 870 sizeof(yes)); 871 872 __sdp_log(1, "find_free_port: binding first %s socket\n", 873 tmp_turn ? "tcp" : "sdp"); 874 ret = __bind_semantics(tmp_sd[tmp_turn], sin_addr, addrlen, semantics); 875 if (ret < 0) { 876 __sdp_log(8, 877 "Warning find_free_port: binding first socket failed:%s\n", 878 strerror(errno)); 879 _socket_funcs.close(tmp_sd[0]); 880 _socket_funcs.close(tmp_sd[1]); 881 goto done; 882 } 883 884 __sdp_log(1, "find_free_port: listening on first socket\n"); 885 ret = _socket_funcs.listen(tmp_sd[tmp_turn], 5); 886 if (ret < 0) { 887 __sdp_log(8, "Warning find_free_port: listening on first socket failed:%s\n", 888 strerror(errno)); 889 _socket_funcs.close(tmp_sd[0]); 890 _socket_funcs.close(tmp_sd[1]); 891 goto done; 892 } 893 894 port = get_fd_addr_port_num(tmp_sd[tmp_turn]); 895 if (port < 0) { 896 __sdp_log(8, "Warning find_free_port: first socket port:%d < 0\n", 897 port); 898 _socket_funcs.close(tmp_sd[0]); 899 _socket_funcs.close(tmp_sd[1]); 900 goto done; 901 } 902 __sdp_log(1, "find_free_port: first socket port:%u\n", port); 903 904 set_addr_port_num(sin_addr, port); 905 906 __sdp_log(1, "find_free_port: binding second socket\n"); 907 ret = __bind_semantics(tmp_sd[1 - tmp_turn], sin_addr, addrlen, semantics); 908 if (ret < 0) { 909 /* bind() for sdp socket failed. It is acceptable only 910 * if the IP is not part of IB network. */ 911 912 if (errno != EADDRINUSE) { 913 __sdp_log(8, "Warning find_free_port: " 914 "binding second socket failed with %s\n", 915 strerror(errno)); 916 goto close_and_mark; 917 } else { 918 int err; 919#ifdef __linux__ 920 socklen_t len = sizeof(int); 921 922 ret = getsockopt(tmp_sd[1 - tmp_turn], SOL_TCP, 923 SDP_LAST_BIND_ERR, &err, &len); 924 if (-1 == ret) { 925 __sdp_log(9, "Error %s:getsockopt: %s\n", 926 __func__, strerror(errno)); 927 goto close_and_mark; 928 } 929#else 930 err = -errno; 931#endif 932 if (-ENOENT == err || -EADDRINUSE != err) { 933 /* bind() failed due to either: 934 * 1. IP is ETH, not IB, so can't bind() to sdp socket. 935 * 2. real error. 936 * Continue only with TCP */ 937 goto close_and_mark; 938 } 939 __sdp_log(1, "find_free_port: %s port %u was busy\n", 940 1 - tmp_turn ? "tcp" : "sdp", 941 ntohs(((const struct sockaddr_in *)sin_addr)->sin_port)); 942 } 943 944 /* close the sockets - we will need new ones ... */ 945 __sdp_log(1, 946 "find_free_port: closing the two sockets before next loop\n"); 947 _socket_funcs.close(tmp_sd[0]); 948 _socket_funcs.close(tmp_sd[1]); 949 950 port = -1; 951 /* we always start with tcp so we keep the original setting for now */ 952 /* tmp_turn = 1 - tmp_turn; */ 953 } 954 955 } while ((port < 0) && (num_of_loops < MAX_BIND_ANY_PORT_TRIES)); 956 957setfds: 958 tcp_turn = tmp_turn; 959 *sdp_sd = tmp_sd[0]; 960 *tcp_sd = tmp_sd[1]; 961 962done: 963 __sdp_log(2, "find_free_port: return port:<%d>\n", port); 964 return port; 965 966close_and_mark: 967 _socket_funcs.close(tmp_sd[0]); 968 tmp_sd[0] = -1; /* mark with error */ 969 goto setfds; 970 971} 972 973/* ========================================================================= */ 974/*..check_legal_bind - check if given address is okay for both TCP and SDP */ 975static int 976check_legal_bind(const struct sockaddr *sin_addr, 977 const socklen_t addrlen, 978 int orig_sd, 979 int *sdp_sd, int *tcp_sd, int semantics) 980{ 981 unsigned int yes = 1; 982 int ret = -1; 983 int sret = -1; 984 int domain, sdp_domain; 985 986 /* need to obtain the address family from the fd */ 987 domain = get_sock_domain(orig_sd); 988 if (domain == -1) { 989 errno = EFAULT; 990 ret = -1; 991 goto done; 992 } 993 994 sdp_domain = get_sdp_domain(domain); 995 if (sdp_domain < 0) { 996 errno = EFAULT; 997 goto done; 998 } 999 1000 __sdp_log(2, "check_legal_bind: binding two temporary sockets\n"); 1001 *sdp_sd = _socket_funcs.socket(sdp_domain, SOCK_STREAM, IPPROTO_TCP); 1002 if (*sdp_sd < 0) { 1003 __sdp_log(9, "Error check_legal_bind: " "creating SDP socket failed\n"); 1004 goto done; 1005 } 1006 1007 __sdp_log(2, "check_legal_bind: reusing <%d> \n", *sdp_sd); 1008 sret = 1009 _socket_funcs.setsockopt(*sdp_sd, SOL_SOCKET, SO_REUSEADDR, &yes, 1010 sizeof(yes)); 1011 if (sret < 0) { 1012 __sdp_log(9, "Error bind: Could not setsockopt sdp_sd\n"); 1013 } 1014 1015 *tcp_sd = _socket_funcs.socket(domain, SOCK_STREAM, IPPROTO_TCP); 1016 if (*tcp_sd < 0) { 1017 __sdp_log(9, "Error check_legal_bind: " 1018 "creating second socket failed:%s\n", strerror(errno)); 1019 _socket_funcs.close(*sdp_sd); 1020 goto done; 1021 } 1022 1023 __sdp_log(2, "check_legal_bind: reusing <%d> \n", *tcp_sd); 1024 sret = 1025 _socket_funcs.setsockopt(*tcp_sd, SOL_SOCKET, SO_REUSEADDR, &yes, 1026 sizeof(yes)); 1027 if (sret < 0) { 1028 __sdp_log(9, "Error bind: Could not setsockopt tcp_sd\n"); 1029 } 1030 1031 __sdp_log(1, "check_legal_bind: binding SDP socket\n"); 1032 ret = __bind_semantics(*sdp_sd, sin_addr, addrlen, semantics); 1033 if (ret < 0) { 1034 /* bind() for sdp socket failed. It is acceptable only if 1035 * the IP is not part of IB network. */ 1036 int err; 1037 socklen_t len = sizeof(int); 1038 1039 if (EADDRINUSE != errno) 1040 goto done; 1041#ifdef __linux__ 1042 if (-1 == getsockopt(*sdp_sd, SOL_TCP, SDP_LAST_BIND_ERR, &err, &len)) { 1043 __sdp_log(9, "Error check_legal_bind:getsockopt: %s\n", 1044 strerror(errno)); 1045 goto done; 1046 } 1047#else 1048 err = -errno; 1049#endif 1050 if (-ENOENT != err) { 1051 /* bind() failed due to real error. Can't continue */ 1052 __sdp_log(9, "Error check_legal_bind: " 1053 "binding SDP socket failed:%s\n", strerror(errno)); 1054 _socket_funcs.close(*sdp_sd); 1055 _socket_funcs.close(*tcp_sd); 1056 1057 /* TCP and SDP without library return EINVAL */ 1058 if (errno == EADDRINUSE) 1059 errno = EINVAL; 1060 1061 goto done; 1062 } 1063 /* IP is ETH, not IB, so can't bind() to sdp socket */ 1064 /* Continue only with TCP */ 1065 _socket_funcs.close(*sdp_sd); 1066 *sdp_sd = -1; 1067 } 1068 1069 __sdp_log(1, "check_legal_bind: binding TCP socket\n"); 1070 ret = __bind_semantics(*tcp_sd, sin_addr, addrlen, semantics); 1071 if (ret < 0) { 1072 __sdp_log(9, "Error check_legal_bind: " 1073 "binding TCP socket failed:%s\n", strerror(errno)); 1074 if (-1 != *sdp_sd) 1075 _socket_funcs.close(*sdp_sd); 1076 _socket_funcs.close(*tcp_sd); 1077 goto done; 1078 } 1079 ret = 0; 1080 __sdp_log(2, "check_legal_bind: result:<%d>\n", ret); 1081done: 1082 return ret; 1083} 1084 1085/* ========================================================================= */ 1086/*..close_and_bind - close an open fd and bind another one immediately */ 1087static int 1088close_and_bind(int old_sd, 1089 int new_sd, 1090 const struct sockaddr *addr, socklen_t addrlen, int semantics) 1091{ 1092 int ret; 1093 1094 __sdp_log(2, "close_and_bind: closing <%d> binding <%d>\n", old_sd, new_sd); 1095 ret = _socket_funcs.close(old_sd); 1096 if (ret < 0) { 1097 __sdp_log(9, "Error bind: Could not close old_sd\n"); 1098 goto done; 1099 } 1100 1101 ret = __bind_semantics(new_sd, addr, addrlen, semantics); 1102 if (ret < 0) 1103 __sdp_log(9, "Error bind: Could not bind new_sd\n"); 1104 1105done: 1106 __sdp_log(2, "close_and_bind: returning <%d>\n", ret); 1107 return ret; 1108} 1109 1110/* ========================================================================= */ 1111/*..bind -- replacement bind call. */ 1112/* 1113 As we do not know the role of this socket yet so we cannot choose AF. 1114 We need to be able to handle shadow too. 1115 SDP sockets (may be shadow or not) must be using converted address 1116 1117 Since there is no way to "rebind" a socket we have to avoid "false" bind: 1118 1. When the given address for the bind includes a port we need to 1119 guarantee the port is free on both address families. We do that 1120 by creating temporary sockets and biding them first. Then we close and 1121 re-use the address on the real sockets. 1122 2. When ANY_PORT is requested we need to make sure the port we obtain from 1123 the first address family is also free on the second one. We use temporary 1124 sockets for that task too. We loop several times to find such common 1125 available socket 1126*/ 1127static int 1128__perform_bind(int fd, 1129 const struct sockaddr *addr, socklen_t addrlen, int semantics) 1130{ 1131 int shadow_fd; 1132 struct sockaddr_in *sin_addr = (struct sockaddr_in *) addr; 1133 int ret, sret = -1; 1134 char buf[MAX_ADDR_STR_LEN]; 1135 1136 if (init_status == 0) 1137 __sdp_init(); 1138 1139 if (NULL == _socket_funcs.bind) { 1140 __sdp_log(9, "Error bind: no implementation for bind found\n"); 1141 return -1; 1142 } 1143 1144 shadow_fd = get_shadow_fd_by_fd(fd); 1145 1146 if ((addr == NULL) || is_invalid_addr(addr)) { 1147 errno = EFAULT; 1148 __sdp_log(9, "Error bind: illegal address provided\n"); 1149 return -1; 1150 } 1151 1152 if (get_addr_str(addr, buf, MAX_ADDR_STR_LEN)) { 1153 __sdp_log(9, "Error bind: provided illegal address: %s\n", 1154 strerror(errno)); 1155 return -1; 1156 } 1157 1158 __sdp_log(2, "BIND: <%s:%d:%d> type <%d> IP <%s> port <%d>\n", 1159 program_invocation_short_name, fd, shadow_fd, 1160 sin_addr->sin_family, buf, ntohs(sin_addr->sin_port)); 1161 1162 if (get_is_sdp_socket(fd)) { 1163 __sdp_log(1, "BIND: binding SDP socket:<%d>\n", fd); 1164 ret = __bind_semantics(fd, addr, addrlen, semantics); 1165 goto done; 1166 } else if (shadow_fd != -1) { 1167 /* has shadow */ 1168 /* we need to validate the given address or find a common port 1169 * so we use the following tmp address and sockets */ 1170 struct sockaddr_storage tmp_addr; 1171 int sdp_sd = -1, tcp_sd = -1, port; 1172 1173 memcpy(&tmp_addr, addr, addrlen); 1174 ret = 0; 1175 if (ntohs(sin_addr->sin_port) == 0) { 1176 /* When we get ANY_PORT we need to make sure that both TCP 1177 * and SDP sockets will use the same port */ 1178 1179 port = find_free_port(addr, addrlen, fd, &sdp_sd, &tcp_sd, semantics); 1180 if (port < 0) { 1181 ret = -1; 1182 __sdp_log(9, "BIND: Failed to find common free port\n"); 1183 /* We cannot bind both tcp and sdp on the same port, we will close 1184 * the sdp and continue with tcp only */ 1185 goto done; 1186 } else { 1187 /* copy the port to the tmp address */ 1188 set_addr_port_num((struct sockaddr *) &tmp_addr, port); 1189 } 1190 } else { 1191 /* have a shadow but requested specific port - check that we 1192 * can actually bind the two addresses and then reuse */ 1193 ret = check_legal_bind(addr, addrlen, fd, &sdp_sd, &tcp_sd, semantics); 1194 if (ret < 0) { 1195 __sdp_log(9, "Error bind: " 1196 "Provided address can not bind on the two sockets\n"); 1197 } 1198 } 1199 1200 /* if we fail to find a common port or given address can not be used 1201 * we return error */ 1202 if (ret < 0) { 1203 /* Temporary sockets already closed by check_legal_bind or 1204 * find_free_port */ 1205 errno = EADDRINUSE; 1206 goto done; 1207 } 1208 1209 /* close temporary sockets and reuse their address */ 1210 /* HACK: close_and_bind might race with other applications. */ 1211 /* When the race occur we return EADDRINUSE */ 1212 ret = close_and_bind(tcp_sd, fd, (struct sockaddr *) &tmp_addr, 1213 addrlen, semantics); 1214 if (ret < 0) { 1215 __sdp_log(9, "Error bind: " "Could not close_and_bind TCP side\n"); 1216 if (-1 != sdp_sd) 1217 _socket_funcs.close(sdp_sd); 1218 goto done; 1219 } 1220 1221 if (-1 != sdp_sd) { 1222 ret = close_and_bind(sdp_sd, shadow_fd, (struct sockaddr *) &tmp_addr, 1223 addrlen, semantics); 1224 1225 if (ret < 0) { 1226 __sdp_log(9, 1227 "Error bind: " "Could not close_and_bind sdp side\n"); 1228 goto done; 1229 } 1230 } 1231 goto done; 1232 } 1233 1234 /* we can only get here on single TCP socket */ 1235 __sdp_log(1, "BIND: binding TCP socket:<%d>\n", fd); 1236 ret = __bind_semantics(fd, addr, addrlen, semantics); 1237 1238done: 1239 __sdp_log(2, "BIND: <%s:%d:%d> result <%d:%d>\n", 1240 program_invocation_short_name, fd, shadow_fd, ret, sret); 1241 1242 return ret; 1243} /* bind */ 1244 1245 1246int bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen) 1247{ 1248 return __perform_bind(fd, my_addr, addrlen, SOCKET_SEMANTIC_DEFAULT); 1249} 1250 1251#ifdef SOLARIS_BUILD 1252int __xnet_bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen) 1253{ 1254 return __perform_bind(fd, my_addr, addrlen, SOCKET_SEMANTIC_XNET); 1255} 1256#endif 1257 1258 1259/* ========================================================================= */ 1260/*..connect -- replacement connect call. */ 1261/* 1262 Given the connect address we can take out AF decision 1263 if target AF == both it means SDP and fall back to TCP 1264 if any connect worked we are fine 1265*/ 1266static inline int 1267__connect_semantics(int fd, 1268 const struct sockaddr *serv_addr, 1269 socklen_t addrlen, int semantics) 1270{ 1271 return 1272#ifdef SOLARIS_BUILD 1273 (semantics == SOCKET_SEMANTIC_XNET) ? 1274 _socket_xnet_funcs.connect(fd, serv_addr, addrlen) : 1275#endif 1276 _socket_funcs.connect(fd, serv_addr, addrlen); 1277} 1278 1279static int 1280__perform_connect(int fd, const struct sockaddr *serv_addr, 1281 socklen_t addrlen, int semantics) 1282{ 1283 struct sockaddr_in *serv_sin = (struct sockaddr_in *) serv_addr; 1284 char buf[MAX_ADDR_STR_LEN]; 1285 int shadow_fd; 1286 int ret = -1, dup_ret; 1287 use_family_t target_family; 1288 int fopts; 1289 1290 if (init_status == 0) 1291 __sdp_init(); 1292 1293 if (NULL == _socket_funcs.connect) { 1294 __sdp_log(9, "Error connect: no implementation for connect found\n"); 1295 return -1; 1296 } 1297 1298 shadow_fd = get_shadow_fd_by_fd(fd); 1299 1300 if ((serv_addr == NULL) || is_invalid_addr(serv_addr)) { 1301 errno = EFAULT; 1302 __sdp_log(9, "Error connect: illegal address provided\n"); 1303 return -1; 1304 } 1305 1306 if (get_addr_str(serv_addr, buf, MAX_ADDR_STR_LEN)) { 1307 __sdp_log(9, "Error connect: provided illegal address: %s\n", 1308 strerror(errno)); 1309 return EADDRNOTAVAIL; 1310 } 1311 1312 __sdp_log(2, "CONNECT: <%s:%d:%d> domain <%d> IP <%s> port <%d>\n", 1313 program_invocation_short_name, fd, shadow_fd, 1314 serv_sin->sin_family, buf, ntohs(serv_sin->sin_port)); 1315 1316 1317 /* obtain the target address family */ 1318 target_family = __sdp_match_connect(serv_addr, addrlen); 1319 1320 /* if we do not have a shadow - just do the work */ 1321 if (shadow_fd == -1) { 1322 __sdp_log(1, "CONNECT: connectingthrough %s\n", 1323 get_is_sdp_socket(fd) ? "SDP" : "TCP"); 1324 ret = __connect_semantics(fd, serv_addr, addrlen, semantics); 1325 if ((ret == 0) || (errno == EINPROGRESS)) { 1326 __sdp_log(7, "CONNECT: connected SDP fd:%d to:%s port %d\n", 1327 fd, buf, ntohs(serv_sin->sin_port)); 1328 } 1329 goto done; 1330 } 1331 1332 if ((target_family == USE_SDP) || (target_family == USE_BOTH)) { 1333 /* NOTE: the entire if sequence is negative logic */ 1334 __sdp_log(1, "CONNECT: connecting SDP fd:%d\n", shadow_fd); 1335 1336 /* make the socket blocking on shadow SDP */ 1337 fopts = _socket_funcs.fcntl(shadow_fd, F_GETFL); 1338 if ((target_family == USE_BOTH) && (fopts & O_NONBLOCK)) { 1339 __sdp_log(1, 1340 "CONNECT: shadow_fd <%d> will be blocking during connect\n", 1341 shadow_fd); 1342 _socket_funcs.fcntl(shadow_fd, F_SETFL, fopts & (~O_NONBLOCK)); 1343 } 1344 1345 ret = __connect_semantics(shadow_fd, serv_addr, addrlen, semantics); 1346 if ((ret < 0) && (errno != EINPROGRESS)) { 1347 __sdp_log(9, "Error connect: " 1348 "failed for SDP fd:%d with error:%m\n", shadow_fd); 1349 } else { 1350 __sdp_log(7, "CONNECT: connected SDP fd:%d to:%s port %d\n", 1351 fd, buf, ntohs(serv_sin->sin_port)); 1352 } 1353 1354 /* restore socket options */ 1355 _socket_funcs.fcntl(shadow_fd, F_SETFL, fopts); 1356 1357 /* if target is SDP or we succeeded we need to dup SDP fd into TCP fd */ 1358 if ((target_family == USE_SDP) || (ret >= 0)) { 1359 dup_ret = replace_fd_with_its_shadow(fd); 1360 if (dup_ret < 0) { 1361 __sdp_log(9, "Error connect: " 1362 "failed to dup2 shadow into orig fd:%d\n", fd); 1363 ret = dup_ret; 1364 } else { 1365 /* we can skip the TCP option if we are done */ 1366 __sdp_log(1, "CONNECT: " 1367 "matched SDP fd:%d so shadow dup into TCP\n", fd); 1368 goto done; 1369 } 1370 } 1371 } 1372 1373 if ((target_family == USE_TCP) || (target_family == USE_BOTH)) { 1374 __sdp_log(1, "CONNECT: connecting TCP fd:%d\n", fd); 1375 ret = __connect_semantics(fd, serv_addr, addrlen, semantics); 1376 if ((ret < 0) && (errno != EINPROGRESS)) 1377 __sdp_log(9, "Error connect: for TCP fd:%d failed with error:%m\n", 1378 fd); 1379 else 1380 __sdp_log(7, "CONNECT: connected TCP fd:%d to:%s port %d\n", 1381 fd, buf, ntohs(serv_sin->sin_port)); 1382 1383 if ((target_family == USE_TCP) || (ret >= 0) || (errno == EINPROGRESS)) { 1384 if (cleanup_shadow(fd) < 0) 1385 __sdp_log(9, 1386 "Error connect: failed to cleanup shadow for fd:%d\n", 1387 fd); 1388 } 1389 } 1390 1391done: 1392 __sdp_log(2, "CONNECT: <%s:%d:%d> result <%d>\n", 1393 program_invocation_short_name, fd, shadow_fd, ret); 1394 1395 return ret; 1396} /* connect */ 1397 1398int connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen) 1399{ 1400 return __perform_connect(fd, serv_addr, addrlen, SOCKET_SEMANTIC_DEFAULT); 1401} 1402 1403#if defined( SOLARIS_BUILD ) 1404int __xnet_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen) 1405{ 1406 return __perform_connect(fd, serv_addr, addrlen, SOCKET_SEMANTIC_XNET); 1407} 1408#endif 1409 1410/* ========================================================================= */ 1411/*..listen -- replacement listen call. */ 1412/* 1413 Now we know our role (passive/server) and our address so we can get AF. 1414 If both we should try listening on both 1415*/ 1416 1417static inline int __listen_semantics(int fd, int backlog, int semantics) 1418{ 1419 return 1420#ifdef SOLARIS_BUILD 1421 (semantics == SOCKET_SEMANTIC_XNET) ? 1422 _socket_xnet_funcs.listen(fd, backlog) : 1423#endif 1424 _socket_funcs.listen(fd, backlog); 1425} 1426 1427static int __perform_listen(int fd, int backlog, int semantics) 1428{ 1429 use_family_t target_family; 1430 int shadow_fd; 1431 int ret = 0, sret = 0; 1432 struct sockaddr_storage tmp_sin; 1433 socklen_t tmp_sinlen = sizeof(tmp_sin); 1434 struct sockaddr_in *sin4 = (struct sockaddr_in *) &tmp_sin; 1435 char buf[MAX_ADDR_STR_LEN]; 1436 int actual_port; 1437 1438 if (init_status == 0) 1439 __sdp_init(); 1440 1441 if (NULL == _socket_funcs.listen) { 1442 __sdp_log(9, "Error listen: no implementation for listen found\n"); 1443 return -1; 1444 } 1445 1446 shadow_fd = get_shadow_fd_by_fd(fd); 1447 __sdp_log(2, "LISTEN: <%s:%d:%d>\n", 1448 program_invocation_short_name, fd, shadow_fd); 1449 1450 /* if there is no shadow - simply call listen */ 1451 if (shadow_fd == -1) { 1452 __sdp_log(1, "LISTEN: calling listen on fd:%d\n", fd); 1453 ret = __listen_semantics(fd, backlog, semantics); 1454 goto done; 1455 } 1456 1457 /* we need to obtain the address from the fd */ 1458 if (_socket_funcs.getsockname(fd, (struct sockaddr *) &tmp_sin, &tmp_sinlen) 1459 < 0) { 1460 __sdp_log(9, "Error listen: getsockname return <%d> for TCP socket\n", 1461 errno); 1462 errno = EADDRNOTAVAIL; 1463 sret = -1; 1464 goto done; 1465 } 1466 1467 if (get_addr_str((struct sockaddr *) &tmp_sin, buf, MAX_ADDR_STR_LEN)) { 1468 __sdp_log(9, "Error listen: provided illegal address: %s\n", 1469 strerror(errno)); 1470 } 1471 1472 __sdp_log(2, "LISTEN: <%s:%d:%d> domain <%d> IP <%s> port <%d>\n", 1473 program_invocation_short_name, fd, shadow_fd, 1474 sin4->sin_family, buf, ntohs(sin4->sin_port)); 1475 1476 target_family = 1477 __sdp_match_listen((struct sockaddr *) &tmp_sin, sizeof(tmp_sin)); 1478 1479 /* 1480 * in case of an implicit bind and "USE_BOTH" rule we need to first bind the 1481 * two sockets to the same port number 1482 */ 1483 actual_port = ntohs(sin4->sin_port); 1484 1485 /* do we need to implicit bind both */ 1486 if ((actual_port == 0) && (target_family == USE_BOTH)) { 1487 int sdp_sd = -1, tcp_sd = -1; 1488 1489 actual_port = find_free_port((struct sockaddr *) &tmp_sin, tmp_sinlen, 1490 fd, &sdp_sd, &tcp_sd, semantics); 1491 if (actual_port < 0) { 1492 ret = -1; 1493 __sdp_log(8, "LISTEN: Failed to find common free port. Only TCP will be used.\n"); 1494 target_family = USE_TCP; 1495 } else { 1496 /* copy the port to the tmp address */ 1497 set_addr_port_num((struct sockaddr *) sin4, actual_port); 1498 1499 __sdp_log(2, "LISTEN: BOTH on IP <%s> port <%d>\n", 1500 buf, actual_port); 1501 /* perform the bind */ 1502 ret = close_and_bind(tcp_sd, fd, (struct sockaddr *) sin4, 1503 tmp_sinlen, semantics); 1504 if (ret < 0) { 1505 __sdp_log(9, "Error listen: " 1506 "Could not close_and_bind TCP side\n"); 1507 } 1508 1509 ret = close_and_bind(sdp_sd, shadow_fd, (struct sockaddr *) sin4, 1510 tmp_sinlen, semantics); 1511 if (ret < 0) { 1512 __sdp_log(9, "Error listen: " 1513 "Could not close_and_bind SDP side\n"); 1514 } 1515 } 1516 } 1517 1518 if ((target_family == USE_TCP) || (target_family == USE_BOTH)) { 1519 __sdp_log(1, "LISTEN: calling listen on TCP fd:%d\n", fd); 1520 ret = __listen_semantics(fd, backlog, semantics); 1521 if (ret < 0) { 1522 __sdp_log(9, "Error listen: failed with code <%d> on TCP fd:<%d>\n", 1523 errno, fd); 1524 } else { 1525 __sdp_log(7, "LISTEN: fd:%d listening on TCP bound to:%s port:%d\n", 1526 fd, buf, actual_port); 1527 } 1528 } 1529 1530 if ((target_family == USE_SDP) || (target_family == USE_BOTH)) { 1531 __sdp_log(1, "LISTEN: calling listen on SDP fd:<%d>\n", shadow_fd); 1532 sret = __listen_semantics(shadow_fd, backlog, semantics); 1533 if (sret < 0) { 1534 __sdp_log(9, "Error listen: failed with code <%d> SDP fd:<%d>\n", 1535 errno, shadow_fd); 1536 } else { 1537 __sdp_log(7, "LISTEN: fd:%d listening on SDP bound to:%s port:%d\n", 1538 fd, buf, actual_port); 1539 } 1540 } 1541 1542 /* cleanup the un-needed shadow if TCP and did not fail */ 1543 if ((target_family == USE_TCP) && (ret >= 0)) { 1544 __sdp_log(1, "LISTEN: cleaning up shadow SDP\n"); 1545 if (cleanup_shadow(fd) < 0) 1546 __sdp_log(9, "Error listen: failed to cleanup shadow for fd:%d\n", 1547 fd); 1548 } 1549 1550 /* cleanup the TCP socket and replace with SDP */ 1551 if ((target_family == USE_SDP) && (sret >= 0)) { 1552 __sdp_log(1, "LISTEN: cleaning TCP socket and dup2 SDP into it\n"); 1553 if (0 > (sret = replace_fd_with_its_shadow(fd))) 1554 __sdp_log(9, "Error listen: " 1555 "failed to dup2 shadow into orig fd:%d\n", fd); 1556 } 1557 1558done: 1559 __sdp_log(2, "LISTEN: <%s:%d:%d> result <%d>\n", 1560 program_invocation_short_name, fd, shadow_fd, ret); 1561 /* its a success only if both are ok */ 1562 if (ret < 0) 1563 return (ret); 1564 if (sret < 0) 1565 return (sret); 1566 return 0; 1567} /* listen */ 1568 1569int listen(int fd, int backlog) 1570{ 1571 return __perform_listen(fd, backlog, SOCKET_SEMANTIC_DEFAULT); 1572} 1573 1574#ifdef SOLARIS_BUILD 1575int __xnet_listen(int fd, int backlog) 1576{ 1577 return __perform_listen(fd, backlog, SOCKET_SEMANTIC_XNET); 1578} 1579#endif 1580 1581/* ========================================================================= */ 1582/*..close -- replacement close call. */ 1583int close(int fd) 1584{ 1585 int shadow_fd; 1586 int ret; 1587 1588 if (init_status == 0) 1589 __sdp_init(); 1590 1591 if (NULL == _socket_funcs.close) { 1592 __sdp_log(9, "Error close: no implementation for close found\n"); 1593 return -1; 1594 } 1595 1596 shadow_fd = get_shadow_fd_by_fd(fd); 1597 1598 __sdp_log(2, "CLOSE: <%s:%d:%d>\n", 1599 program_invocation_short_name, fd, shadow_fd); 1600 1601 if (shadow_fd != -1) { 1602 __sdp_log(1, "CLOSE: closing shadow fd:<%d>\n", shadow_fd); 1603 if (cleanup_shadow(fd) < 0) 1604 __sdp_log(9, "Error close: failed to cleanup shadow for fd:%d\n", 1605 fd); 1606 } 1607 1608 init_extra_attribute(fd); 1609 ret = _socket_funcs.close(fd); 1610 __sdp_log(2, "CLOSE: <%s:%d:%d> result <%d>\n", 1611 program_invocation_short_name, fd, shadow_fd, ret); 1612 return ret; 1613} /* close */ 1614 1615/* ========================================================================= */ 1616/*..dup -- replacement dup call. */ 1617/* we duplicate the fd and its shadow if exists - ok if the main worked */ 1618int dup(int fd) 1619{ 1620 int newfd, new_shadow_fd = -1; 1621 int shadow_fd; 1622 1623 if (init_status == 0) 1624 __sdp_init(); 1625 1626 if (NULL == _socket_funcs.dup) { 1627 __sdp_log(9, "Error dup: no implementation for dup found\n"); 1628 return -1; 1629 } 1630 1631 shadow_fd = get_shadow_fd_by_fd(fd); 1632 1633 __sdp_log(2, "DUP: <%s:%d:%d>\n", 1634 program_invocation_short_name, fd, shadow_fd); 1635 1636 __sdp_log(1, "DUP: duplication fd:<%d>\n", fd); 1637 newfd = _socket_funcs.dup(fd); 1638 1639 if (newfd == fd) 1640 return (fd); 1641 1642 if (!is_valid_fd(newfd)) { 1643 __sdp_log(9, "Error dup: new fd <%d> out of range.\n", newfd); 1644 } else { 1645 /* copy attributes from old fd */ 1646 libsdp_fd_attributes[newfd] = libsdp_fd_attributes[fd]; 1647 libsdp_fd_attributes[newfd].shadow_fd = -1; 1648 1649 if (shadow_fd != -1) { 1650 __sdp_log(1, "DUP: duplication shadow fd:<%d>\n", shadow_fd); 1651 new_shadow_fd = _socket_funcs.dup(shadow_fd); 1652 if ((new_shadow_fd > max_file_descriptors) || (new_shadow_fd < 0)) { 1653 __sdp_log(9, "Error dup: new shadow fd <%d> out of range.\n", 1654 new_shadow_fd); 1655 } else { 1656 libsdp_fd_attributes[new_shadow_fd] = 1657 libsdp_fd_attributes[shadow_fd]; 1658 libsdp_fd_attributes[newfd].shadow_fd = new_shadow_fd; 1659 } 1660 } /* shadow exists */ 1661 } 1662 1663 __sdp_log(2, "DUP: <%s:%d:%d> return <%d:%d>\n", 1664 program_invocation_short_name, fd, shadow_fd, newfd, 1665 new_shadow_fd); 1666 1667 return newfd; 1668} /* dup */ 1669 1670/* ========================================================================= */ 1671/*..dup2 -- replacement dup2 call. */ 1672/* since only the main new fd is given we only move the shadow if exists */ 1673int dup2(int fd, int newfd) 1674{ 1675 int shadow_fd; 1676 int shadow_newfd; 1677 int new_shadow_fd = -1; 1678 int ret = 0; 1679 1680 if (init_status == 0) 1681 __sdp_init(); 1682 1683 if (NULL == _socket_funcs.dup2) { 1684 __sdp_log(9, "Error dup2: no implementation for dup2 found\n"); 1685 return -1; 1686 } 1687 1688 shadow_fd = get_shadow_fd_by_fd(fd); 1689 shadow_newfd = get_shadow_fd_by_fd(newfd); 1690 1691 __sdp_log(2, "DUP2: <%s:%d:%d>\n", 1692 program_invocation_short_name, fd, shadow_fd); 1693 1694 if (newfd == fd) { 1695 __sdp_log(1, "DUP2: skip duplicating fd:<%d> into:<%d>\n", fd, newfd); 1696 goto done; 1697 } 1698 1699 /* dup2 closes the target file desc if it is a valid fd */ 1700 if (shadow_newfd != -1) { 1701 __sdp_log(1, "DUP2: closing newfd:<%d> shadow:<%d>\n", newfd, 1702 shadow_newfd); 1703 ret = _socket_funcs.close(shadow_newfd); 1704 if (ret != 0) { 1705 __sdp_log(9, 1706 "DUP2: fail to close newfd:<%d> shadow:<%d> with: %d %s\n", 1707 newfd, shadow_newfd, ret, strerror(errno)); 1708 } 1709 } 1710 1711 __sdp_log(1, "DUP2: duplicating fd:<%d> into:<%d>\n", fd, newfd); 1712 newfd = _socket_funcs.dup2(fd, newfd); 1713 if ((newfd > max_file_descriptors) || (newfd < 0)) { 1714 __sdp_log(9, "Error dup2: new fd <%d> out of range.\n", newfd); 1715 } else { 1716 /* copy attributes from old fd */ 1717 libsdp_fd_attributes[fd].shadow_fd = -1; 1718 libsdp_fd_attributes[newfd] = libsdp_fd_attributes[fd]; 1719 1720 /* if it had a shadow create a new shadow */ 1721 if (shadow_fd != -1) { 1722 __sdp_log(1, "DUP2: duplication shadow fd:<%d>\n", shadow_fd); 1723 new_shadow_fd = _socket_funcs.dup(shadow_fd); 1724 if ((new_shadow_fd > max_file_descriptors) || (new_shadow_fd < 0)) { 1725 __sdp_log(9, "Error dup2: new shadow fd <%d> out of range.\n", 1726 new_shadow_fd); 1727 } else { 1728 libsdp_fd_attributes[new_shadow_fd] = 1729 libsdp_fd_attributes[shadow_fd]; 1730 libsdp_fd_attributes[newfd].shadow_fd = new_shadow_fd; 1731 } 1732 } /* newfd is ok */ 1733 } 1734 1735done: 1736 __sdp_log(2, "DUP2: <%s:%d:%d> return <%d:%d>\n", 1737 program_invocation_short_name, fd, shadow_fd, newfd, 1738 new_shadow_fd); 1739 1740 return newfd; 1741} /* dup */ 1742 1743/* ========================================================================= */ 1744/*..getsockname -- replacement getsocknanme call. */ 1745int getsockname(int fd, struct sockaddr *name, socklen_t * namelen) 1746{ 1747 int ret = 0; 1748 char buf[MAX_ADDR_STR_LEN]; 1749 1750 if (init_status == 0) 1751 __sdp_init(); 1752 1753 /* 1754 * ensure the SDP protocol family is not exposed to the user, since 1755 * this is meant to be a transparency layer. 1756 */ 1757 if (NULL == _socket_funcs.getsockname) { 1758 __sdp_log(9, 1759 "Error getsockname: no implementation for getsockname found\n"); 1760 return -1; 1761 } 1762 1763 /* double check provided pointers */ 1764 if ((name == NULL) || is_invalid_addr(name)) { 1765 errno = EFAULT; 1766 __sdp_log(9, "Error getsockname: illegal address provided\n"); 1767 return -1; 1768 } 1769 1770 if ((namelen != NULL) && is_invalid_addr(namelen)) { 1771 errno = EFAULT; 1772 __sdp_log(9, "Error getsockname: illegal address length pointer provided\n"); 1773 return -1; 1774 } 1775 1776 __sdp_log(2, "GETSOCKNAME <%s:%d>\n", program_invocation_short_name, fd); 1777 1778 ret = _socket_funcs.getsockname(fd, name, namelen); 1779 1780 if (__sdp_log_get_level() <= 1) { 1781 if (get_addr_str(name, buf, MAX_ADDR_STR_LEN)) { 1782 __sdp_log(1, "GETSOCKNAME: " "address is illegal\n"); 1783 } else { 1784 __sdp_log(1, "GETSOCKNAME: address is:%s port:%d\n", buf, 1785 ntohs(((struct sockaddr_in *) name)->sin_port)); 1786 } 1787 } 1788 __sdp_log(2, "GETSOCKNAME <%s:%d> result <%d>\n", 1789 program_invocation_short_name, fd, ret); 1790 1791 return ret; 1792} /* getsockname */ 1793 1794/* ========================================================================= */ 1795/*..getpeername -- replacement getpeername call. */ 1796int getpeername(int fd, struct sockaddr *name, socklen_t * namelen) 1797{ 1798 int ret = 0; 1799 1800 if (init_status == 0) 1801 __sdp_init(); 1802 1803 if (NULL == _socket_funcs.getpeername) { 1804 __sdp_log(9, "Error getpeername: " 1805 "no implementation for getpeername found\n"); 1806 return -1; 1807 } 1808 1809 /* double check provided pointers */ 1810 if ((name == NULL) || is_invalid_addr(name)) { 1811 errno = EFAULT; 1812 __sdp_log(9, "Error getsockname: illegal address provided\n"); 1813 return -1; 1814 } 1815 1816 if ((namelen != NULL) && is_invalid_addr(namelen)) { 1817 errno = EFAULT; 1818 __sdp_log(9, 1819 "Error getsockname: illegal address length pointer provided\n"); 1820 return -1; 1821 } 1822 1823 __sdp_log(2, "GETPEERNAME <%s:%d>\n", program_invocation_short_name, fd); 1824 1825 ret = _socket_funcs.getpeername(fd, name, namelen); 1826 1827 __sdp_log(2, "GETPEERNAME <%s:%d> result <%d:%d> family=%d s_addr=%d\n", 1828 program_invocation_short_name, fd, ret, 1829 (!(0 > ret) ? 0 : -1), name->sa_family, 1830 ((struct sockaddr_in *) name)->sin_addr.s_addr); 1831 1832 return ret; 1833} /* getpeername */ 1834 1835 1836 1837/* ========================================================================= */ 1838/*..accept -- replacement accept call. */ 1839/* 1840 If we have a shadow we need to decide which socket we want to accept on 1841 so we select first and then give priority based on previous selection 1842*/ 1843int accept(int fd, struct sockaddr *addr, socklen_t * addrlen) 1844{ 1845 int shadow_fd; 1846 int ret = 0; 1847 fd_set fds; 1848 socklen_t saved_addrlen = 0; 1849 int fopts; 1850 char buf[MAX_ADDR_STR_LEN]; 1851 1852 if (init_status == 0) 1853 __sdp_init(); 1854 1855 shadow_fd = get_shadow_fd_by_fd(fd); 1856 1857 /* 1858 * ensure the SDP protocol family is not exposed to the user, since 1859 * this is meant to be a transparency layer. 1860 */ 1861 if (NULL == _socket_funcs.accept) { 1862 __sdp_log(9, "Error accept: no implementation for accept found\n"); 1863 return -1; 1864 } 1865 1866 /* double check provided pointers */ 1867 if ((addr != NULL) && is_invalid_addr(addr)) { 1868 errno = EINVAL; 1869 __sdp_log(9, "Error accept: illegal address provided\n"); 1870 return -1; 1871 } 1872 1873 if ((addrlen != NULL) && is_invalid_addr(addrlen)) { 1874 errno = EINVAL; 1875 __sdp_log(9, "Error accept: illegal address length pointer provided\n"); 1876 return -1; 1877 } 1878 1879 if (addr && addrlen) 1880 saved_addrlen = *addrlen; 1881 1882 __sdp_log(2, "ACCEPT: <%s:%d>\n", program_invocation_short_name, fd); 1883 1884 if (shadow_fd == -1) { 1885 fopts = _socket_funcs.fcntl(fd, F_GETFL); 1886 __sdp_log(1, "ACCEPT: fd <%d> opts are <0x%x>\n", fd, fopts); 1887 1888 __sdp_log(7, "ACCEPT: accepting on single fd:<%d>\n", fd); 1889 ret = _socket_funcs.accept(fd, addr, addrlen); 1890 if (ret < 0) { 1891 if (!(fopts & O_NONBLOCK && errno == EWOULDBLOCK)) 1892 __sdp_log(9, "Error accept: accept returned :<%d> %s\n", 1893 ret, strerror(errno)); 1894 } else { 1895 set_is_sdp_socket(ret, get_is_sdp_socket(fd)); 1896 } 1897 } else { 1898 1899 fopts = _socket_funcs.fcntl(shadow_fd, F_GETFL); 1900 __sdp_log(1, "ACCEPT: shadow_fd <%d> opts are <0x%x>\n", 1901 shadow_fd, fopts); 1902 1903 /* we need different behavior for NONBLOCK or signal IO and BLOCK */ 1904 if ((fopts > 0) && (fopts & (O_NONBLOCK | FASYNC))) { 1905 __sdp_log(1, "ACCEPT: accepting (nonblock) on SDP fd:<%d>\n", shadow_fd); 1906 1907 ret = _socket_funcs.accept(shadow_fd, addr, addrlen); 1908 if (ret >= 0) { 1909 set_is_sdp_socket(ret, 1); 1910 1911 __sdp_log(7, "ACCEPT: accepted (nonblock) SDP fd:<%d>\n", 1912 shadow_fd); 1913 } else { 1914 __sdp_log(1, "ACCEPT: accept on SDP fd:<%d> return:%d errno:%d\n", 1915 shadow_fd, ret, errno); 1916 1917 __sdp_log(1, "ACCEPT: accepting (nonblock) on TCP fd:<%d>\n", fd); 1918 ret = _socket_funcs.accept(fd, addr, addrlen); 1919 if (ret >= 0) { 1920 __sdp_log(7, "ACCEPT: accepted (nonblock) TCP fd:<%d>\n", 1921 shadow_fd); 1922 } else { 1923 __sdp_log(1, "ACCEPT: accept on TCP fd:<%d> " 1924 "return:%d errno:%d\n", fd, ret, errno); 1925 } 1926 } 1927 } else { 1928 __sdp_log(1, "ACCEPT: selecting both fd:<%d> and shadow:<%d>\n", 1929 fd, shadow_fd); 1930 FD_ZERO(&fds); 1931 FD_SET(fd, &fds); 1932 FD_SET(shadow_fd, &fds); 1933 ret = 1934 _socket_funcs.select(1 + ((fd > shadow_fd) ? fd : shadow_fd), 1935 &fds, NULL, NULL, NULL); 1936 if (ret >= 0) { 1937 if (last_accept_was_tcp(fd) == 0) { 1938 if (FD_ISSET(fd, &fds)) { 1939 set_last_accept(fd, 1); 1940 __sdp_log(7, "ACCEPT: accepting on TCP fd:<%d>\n", fd); 1941 ret = _socket_funcs.accept(fd, addr, addrlen); 1942 } else { 1943 __sdp_log(7, "ACCEPT: accepting on SDP fd:<%d>\n", 1944 shadow_fd); 1945 ret = _socket_funcs.accept(shadow_fd, addr, addrlen); 1946 if (ret >= 0) 1947 set_is_sdp_socket(ret, 1); 1948 } 1949 } else { 1950 if (FD_ISSET(shadow_fd, &fds)) { 1951 set_last_accept(fd, 1); 1952 __sdp_log(7, "ACCEPT: accepting on SDP fd:<%d>\n", 1953 shadow_fd); 1954 ret = _socket_funcs.accept(shadow_fd, addr, addrlen); 1955 if (ret >= 0) 1956 set_is_sdp_socket(ret, 1); 1957 } else { 1958 __sdp_log(7, "ACCEPT: accepting on TCP fd:<%d>\n", fd); 1959 ret = _socket_funcs.accept(fd, addr, addrlen); 1960 } 1961 } 1962 } else { 1963 if (errno != EINTR) { 1964 __sdp_log(9, 1965 "Error accept: select returned :<%d> (%d) %s\n", 1966 ret, errno, strerror(errno)); 1967 } else { 1968 __sdp_log(1, "ACCEPT: select returned :<%d> (%d) %s\n", 1969 ret, errno, strerror(errno)); 1970 } 1971 } 1972 } /* blocking mode */ 1973 } /* shadow fd */ 1974 1975 if ((__sdp_log_get_level() <= 1) && (ret >= 0) && addr && addrlen) { 1976 get_addr_str(addr, buf, *addrlen); 1977 __sdp_log(1, "ACCEPT: accepted from:%s port:%d into fd:%d\n", 1978 buf, ntohs(((struct sockaddr_in *) addr)->sin_port), ret); 1979 } 1980 __sdp_log(2, "ACCEPT: <%s:%d> return <%d>\n", 1981 program_invocation_short_name, fd, ret); 1982 1983 return ret; 1984} /* accept */ 1985 1986/* ========================================================================= */ 1987/*..select -- replacement socket call. */ 1988/* 1989 if we have shadow we must select on it too - which requires a hack back 1990 and forth 1991*/ 1992int 1993select(int n, 1994 fd_set * readfds, 1995 fd_set * writefds, fd_set * exceptfds, struct timeval *timeout) 1996{ 1997 int shadow_fd; 1998 int ret; 1999 int current; 2000 int maxi = 0; 2001 fd_set new_fds; 2002 2003 if (init_status == 0) 2004 __sdp_init(); 2005 2006 if (NULL == _socket_funcs.select) { 2007 __sdp_log(9, "Error select: no implementation for select found\n"); 2008 return -1; 2009 } 2010 2011 __sdp_log(2, "SELECT: <%s:%d>\n", program_invocation_short_name, n); 2012 2013 /* if we do not read - nothing to do */ 2014 if (readfds == NULL) { 2015 ret = _socket_funcs.select(n, readfds, writefds, exceptfds, timeout); 2016 goto done; 2017 } 2018 2019 FD_ZERO(&new_fds); 2020 if (n > 0) { 2021 maxi = n - 1; 2022 } 2023 2024 /* add shadow bits */ 2025 for (current = 0; current < n; current++) { 2026 if (FD_ISSET(current, readfds)) { 2027 FD_SET(current, &new_fds); 2028 if (current > maxi) { 2029 maxi = current; 2030 } 2031 shadow_fd = get_shadow_fd_by_fd(current); 2032 if (shadow_fd != -1) { 2033 __sdp_log(1, 2034 "SELECT: adding fd:<%d> shadow_fd:<%d> to readfs\n", 2035 current, shadow_fd); 2036 FD_SET(shadow_fd, &new_fds); 2037 if (shadow_fd > maxi) { 2038 maxi = shadow_fd; 2039 } 2040 } 2041 } 2042 } 2043 2044 __sdp_log(1, "SELECT: invoking select n=<%d>\n", 1 + maxi); 2045 ret = _socket_funcs.select(1 + maxi, 2046 &new_fds, writefds, exceptfds, timeout); 2047 2048 /* remove the count and bits of the shadows */ 2049 if (ret >= 0) { 2050 for (current = 0; current < n; current++) { 2051 shadow_fd = get_shadow_fd_by_fd(current); 2052 if (shadow_fd == -1) { 2053 if (FD_ISSET(current, readfds) && 2054 FD_ISSET(current, &new_fds) == 0) { 2055 FD_CLR(current, readfds); 2056 } 2057 } else { 2058 if (FD_ISSET(current, readfds) && FD_ISSET(current, &new_fds) 2059 && FD_ISSET(shadow_fd, &new_fds)) { 2060 ret -= 1; 2061 } 2062 if (FD_ISSET(current, readfds) && 2063 FD_ISSET(current, &new_fds) == 0 && 2064 FD_ISSET(shadow_fd, &new_fds) == 0) { 2065 FD_CLR(current, readfds); 2066 } 2067 } 2068 } 2069 } 2070 2071done: 2072 2073 __sdp_log(2, "SELECT: <%s:%d> return <%d>\n", 2074 program_invocation_short_name, n, ret); 2075 return ret; 2076} /* select */ 2077 2078/* ========================================================================= */ 2079/*..pselect -- replacement socket call. */ 2080/* 2081 if we have shadow we must pselect on it too - which requires a hack back 2082 and forth 2083*/ 2084int 2085pselect(int n, 2086 fd_set * readfds, 2087 fd_set * writefds, 2088 fd_set * exceptfds, 2089 const struct timespec *timeout, const sigset_t * sigmask) 2090{ 2091 int shadow_fd; 2092 int ret; 2093 int current; 2094 int maxi = 0; 2095 fd_set new_fds; 2096 2097 if (init_status == 0) 2098 __sdp_init(); 2099 2100 if (NULL == _socket_funcs.pselect) { 2101 __sdp_log(9, "Error pselect: no implementation for pselect found\n"); 2102 return -1; 2103 } 2104 2105 __sdp_log(2, "PSELECT: <%s:%d>\n", program_invocation_short_name, n); 2106 2107 /* if we do not read - nothing to do */ 2108 if (readfds == NULL) { 2109 ret = 2110 _socket_funcs.pselect(n, readfds, writefds, exceptfds, timeout, 2111 sigmask); 2112 goto done; 2113 } 2114 2115 FD_ZERO(&new_fds); 2116 if (n > 0) { 2117 maxi = n - 1; 2118 } 2119 2120 /* add shadow bits */ 2121 for (current = 0; current < n; current++) { 2122 if (FD_ISSET(current, readfds)) { 2123 FD_SET(current, &new_fds); 2124 if (current > maxi) { 2125 maxi = current; 2126 } 2127 shadow_fd = get_shadow_fd_by_fd(current); 2128 if (shadow_fd != -1) { 2129 __sdp_log(1, 2130 "PSELECT: adding fd:<%d> shadow_fd:<%d> to readfs\n", 2131 current, shadow_fd); 2132 FD_SET(shadow_fd, &new_fds); 2133 if (shadow_fd > maxi) { 2134 maxi = shadow_fd; 2135 } 2136 } 2137 } 2138 } 2139 2140 __sdp_log(1, "PSELECT: invoking pselect n=<%d>\n", 1 + maxi); 2141 ret = _socket_funcs.pselect(1 + maxi, 2142 &new_fds, writefds, exceptfds, 2143 timeout, sigmask); 2144 2145 /* remove the count and bits of the shadows */ 2146 if (ret >= 0) { 2147 for (current = 0; current < n; current++) { 2148 shadow_fd = get_shadow_fd_by_fd(current); 2149 if (shadow_fd == -1) { 2150 if (FD_ISSET(current, readfds) && 2151 FD_ISSET(current, &new_fds) == 0) { 2152 FD_CLR(current, readfds); 2153 } 2154 } else { 2155 if (FD_ISSET(current, readfds) && FD_ISSET(current, &new_fds) 2156 && FD_ISSET(shadow_fd, &new_fds)) { 2157 ret -= 1; 2158 } 2159 if (FD_ISSET(current, readfds) && 2160 FD_ISSET(current, &new_fds) == 0 && 2161 FD_ISSET(shadow_fd, &new_fds) == 0) { 2162 FD_CLR(current, readfds); 2163 } 2164 } 2165 } 2166 } 2167 2168done: 2169 2170 __sdp_log(2, "PSELECT: <%s:%d> return <%d>\n", 2171 program_invocation_short_name, n, ret); 2172 return ret; 2173} /* pselect */ 2174 2175/* ========================================================================= */ 2176/*..poll -- replacement socket call. */ 2177/* 2178 if we have shadow we must poll on it too - which requires a hack back 2179 and forth 2180*/ 2181int poll(struct pollfd *ufds, nfds_t nfds, int timeout) 2182{ 2183 int ret; 2184 int shadow_fd; 2185 int current; 2186 int extra = 0; 2187 struct pollfd *poll_fds = NULL; 2188 struct pollfd *poll_fd_ptr = NULL; 2189 2190 if (init_status == 0) 2191 __sdp_init(); 2192 2193 if (NULL == _socket_funcs.poll) { 2194 __sdp_log(9, "Error poll: no implementation for poll found\n"); 2195 return -1; 2196 } 2197 2198 __sdp_log(2, "POLL: <%s:%d>\n", program_invocation_short_name, nfds); 2199 2200 /* if we do not have any file desc - nothing to do */ 2201 if (ufds == NULL) { 2202 ret = _socket_funcs.poll(ufds, nfds, timeout); 2203 goto done; 2204 } 2205 2206 /* scan for how many extra fds are required */ 2207 for (current = 0; current < nfds; current++) { 2208 shadow_fd = get_shadow_fd_by_fd(ufds[current].fd); 2209 if (shadow_fd != -1) 2210 extra++; 2211 } 2212 2213 if (!extra) { 2214 poll_fds = ufds; 2215 } else { 2216 poll_fds = 2217 (struct pollfd *) malloc((nfds + extra) * sizeof(struct pollfd)); 2218 if (!poll_fds) { 2219 __sdp_log(9, 2220 "Error poll: malloc of extended pollfd array failed\n"); 2221 ret = -1; 2222 errno = ENOMEM; 2223 goto done; 2224 } 2225 poll_fd_ptr = poll_fds; 2226 for (current = 0; current < nfds; current++) { 2227 *poll_fd_ptr = ufds[current]; 2228 poll_fd_ptr++; 2229 shadow_fd = get_shadow_fd_by_fd(ufds[current].fd); 2230 if (shadow_fd != -1) { 2231 __sdp_log(1, "POLL: adding fd:<%d> shadow_fd:<%d> to readfs\n", 2232 current, shadow_fd); 2233 *poll_fd_ptr = ufds[current]; 2234 poll_fd_ptr->fd = shadow_fd; 2235 poll_fd_ptr++; 2236 } 2237 } 2238 } 2239 2240 __sdp_log(1, "POLL: invoking poll nfds=<%d>\n", nfds + extra); 2241 ret = _socket_funcs.poll(poll_fds, nfds + extra, timeout); 2242 2243 /* refactor into original list if any events */ 2244 if ((ret > 0) && extra) { 2245 poll_fd_ptr = poll_fds; 2246 for (current = 0; current < nfds; current++) { 2247 shadow_fd = get_shadow_fd_by_fd(ufds[current].fd); 2248 if (shadow_fd == -1) { 2249 ufds[current] = *poll_fd_ptr; 2250 } else { 2251 ufds[current] = *poll_fd_ptr; 2252 poll_fd_ptr++; 2253 if (poll_fd_ptr->revents) { 2254 if (ufds[current].revents) 2255 ret--; 2256 ufds[current].revents |= poll_fd_ptr->revents; 2257 } 2258 } 2259 poll_fd_ptr++; 2260 } 2261 } 2262 2263 if (extra) 2264 free(poll_fds); 2265done: 2266 2267 __sdp_log(2, "POLL: <%s:%d> return <%d>\n", 2268 program_invocation_short_name, nfds, ret); 2269 return ret; 2270} /* poll */ 2271 2272#ifdef __linux__ 2273/* ========================================================================= */ 2274/*..epoll_create -- replacement socket call. */ 2275/* 2276 Need to make the size twice as large for shadow fds 2277*/ 2278int epoll_create(int size) 2279{ 2280 int epfd; 2281 2282 if (init_status == 0) 2283 __sdp_init(); 2284 2285 if (NULL == _socket_funcs.epoll_create) { 2286 __sdp_log(9, 2287 "Error epoll_create: no implementation for epoll_create found\n"); 2288 return -1; 2289 } 2290 2291 __sdp_log(2, "EPOLL_CREATE: <%s:%d>\n", program_invocation_short_name, 2292 size); 2293 2294 epfd = _socket_funcs.epoll_create(size * 2); 2295 2296 __sdp_log(2, "EPOLL_CREATE: <%s:%d> return %d\n", 2297 program_invocation_short_name, size, epfd); 2298 return epfd; 2299} /* epoll_create */ 2300 2301/* ========================================================================= */ 2302/*..epoll_ctl -- replacement socket call. */ 2303/* 2304 Need to add/delete/modify shadow fds as well 2305*/ 2306int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) 2307{ 2308 int ret, shadow_fd, ret2; 2309 2310 if (init_status == 0) 2311 __sdp_init(); 2312 2313 if (NULL == _socket_funcs.epoll_ctl) { 2314 __sdp_log(9, 2315 "Error epoll_ctl: no implementation for epoll_ctl found\n"); 2316 return -1; 2317 } 2318 2319 __sdp_log(2, "EPOLL_CTL: <%s:%d> op <%d:%d>\n", 2320 program_invocation_short_name, epfd, op, fd); 2321 2322 ret = _socket_funcs.epoll_ctl(epfd, op, fd, event); 2323 2324 shadow_fd = get_shadow_fd_by_fd(fd); 2325 if (shadow_fd != -1) { 2326 ret2 = _socket_funcs.epoll_ctl(epfd, op, shadow_fd, event); 2327 if (ret2 < 0) { 2328 __sdp_log(9, "Error epoll_ctl <%s:%d:%d>", 2329 program_invocation_short_name, fd, shadow_fd); 2330 return ret2; 2331 } 2332 } 2333 2334 __sdp_log(2, "EPOLL_CTL: <%s:%d> return <%d>\n", 2335 program_invocation_short_name, epfd, ret); 2336 return ret; 2337} /* epoll_ctl */ 2338 2339/* ========================================================================= */ 2340/*..epoll_wait -- replacement socket call. */ 2341/* 2342 We don't care who generated the event because all we get is user-context 2343 values. 2344*/ 2345int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) 2346{ 2347 int ret; 2348 2349 if (init_status == 0) 2350 __sdp_init(); 2351 2352 if (NULL == _socket_funcs.epoll_wait) { 2353 __sdp_log(9, 2354 "Error epoll_wait: no implementation for epoll_wait found\n"); 2355 return -1; 2356 } 2357 2358 __sdp_log(2, "EPOLL_WAIT: <%s:%d>\n", program_invocation_short_name, epfd); 2359 2360 ret = _socket_funcs.epoll_wait(epfd, events, maxevents, timeout); 2361 2362 __sdp_log(2, "EPOLL_WAIT: <%s:%d> return <%d>\n", 2363 program_invocation_short_name, epfd, ret); 2364 return ret; 2365} /* epoll_wait */ 2366 2367/* ========================================================================= */ 2368/*..epoll_pwait -- replacement socket call. */ 2369/* 2370 We don't care who generated the event because all we get is user-context 2371 values. 2372*/ 2373int 2374epoll_pwait(int epfd, 2375 struct epoll_event *events, 2376 int maxevents, int timeout, const sigset_t * sigmask) 2377{ 2378 int ret; 2379 2380 if (init_status == 0) 2381 __sdp_init(); 2382 2383 if (NULL == _socket_funcs.epoll_pwait) { 2384 __sdp_log(9, 2385 "Error epoll_pwait: no implementation for epoll_pwait found\n"); 2386 return -1; 2387 } 2388 2389 __sdp_log(2, "EPOLL_PWAIT: <%s:%d>\n", program_invocation_short_name, epfd); 2390 2391 ret = _socket_funcs.epoll_pwait(epfd, events, maxevents, timeout, sigmask); 2392 2393 __sdp_log(2, "EPOLL_PWAIT: <%s:%d> return <%d>\n", 2394 program_invocation_short_name, epfd, ret); 2395 return ret; 2396} /* epoll_pwait */ 2397#endif 2398 2399/* ========================================================================= */ 2400 2401/* --------------------------------------------------------------------- */ 2402/* */ 2403/* Library load/unload initialization/cleanup */ 2404/* */ 2405/* --------------------------------------------------------------------- */ 2406/* ========================================================================= */ 2407/*..__sdp_init -- intialize the library */ 2408void __sdp_init(void) 2409{ 2410 char *config_file, *error_str; 2411 int fd; 2412 struct rlimit nofiles_limit; 2413 2414 /* HACK: races might apply here: can we assume init is happening 2415 only within one thread ? */ 2416 if (init_status != 0) 2417 return; 2418 init_status = 1; 2419 2420 dev_null_fd = open("/dev/null", O_WRONLY); 2421 2422 /* figure out the max number of file descriptors */ 2423 if (getrlimit(RLIMIT_NOFILE, &nofiles_limit)) 2424 max_file_descriptors = 1024; 2425 else 2426 max_file_descriptors = nofiles_limit.rlim_cur; 2427 2428 /* allocate and initialize the shadow sdp sockets array */ 2429 libsdp_fd_attributes = 2430 (struct sdp_extra_fd_attributes *) calloc(max_file_descriptors, 2431 sizeof(struct 2432 sdp_extra_fd_attributes)); 2433 for (fd = 0; fd < max_file_descriptors; fd++) 2434 init_extra_attribute(fd); 2435 2436#ifndef RTLD_NEXT 2437 /* 2438 * open libc for original socket call. 2439 * Solaris relies on RTLD next - since the socket calls are 2440 * actually in libsocket rather than libc. 2441 */ 2442 __libc_dl_handle = dlopen("/lib64/libc.so.6", RTLD_LAZY); 2443 if (NULL == __libc_dl_handle) { 2444 __libc_dl_handle = dlopen("/lib/libc.so.6", RTLD_LAZY); 2445 if (NULL == __libc_dl_handle) { 2446 fprintf(stderr, "%s\n", dlerror()); 2447 return; 2448 } 2449 } 2450#endif 2451 2452 /* 2453 * Get the original functions 2454 */ 2455 _socket_funcs.ioctl = dlsym(__libc_dl_handle, "ioctl"); 2456 if (NULL != (error_str = dlerror())) { 2457 fprintf(stderr, "%s\n", error_str); 2458 } 2459 2460 _socket_funcs.fcntl = dlsym(__libc_dl_handle, "fcntl"); 2461 if (NULL != (error_str = dlerror())) { 2462 fprintf(stderr, "%s\n", error_str); 2463 } 2464 2465 _socket_funcs.socket = dlsym(__libc_dl_handle, "socket"); 2466 if (NULL != (error_str = dlerror())) { 2467 fprintf(stderr, "%s\n", error_str); 2468 } 2469 2470 _socket_funcs.setsockopt = dlsym(__libc_dl_handle, "setsockopt"); 2471 if (NULL != (error_str = dlerror())) { 2472 fprintf(stderr, "%s\n", error_str); 2473 } 2474 2475 _socket_funcs.connect = dlsym(__libc_dl_handle, "connect"); 2476 if (NULL != (error_str = dlerror())) { 2477 fprintf(stderr, "%s\n", error_str); 2478 } 2479 2480 _socket_funcs.listen = dlsym(__libc_dl_handle, "listen"); 2481 if (NULL != (error_str = dlerror())) { 2482 fprintf(stderr, "%s\n", error_str); 2483 } 2484 2485 _socket_funcs.bind = dlsym(__libc_dl_handle, "bind"); 2486 if (NULL != (error_str = dlerror())) { 2487 fprintf(stderr, "%s\n", error_str); 2488 } 2489 2490 _socket_funcs.close = dlsym(__libc_dl_handle, "close"); 2491 if (NULL != (error_str = dlerror())) { 2492 fprintf(stderr, "%s\n", error_str); 2493 } 2494 2495 _socket_funcs.dup = dlsym(__libc_dl_handle, "dup"); 2496 if (NULL != (error_str = dlerror())) { 2497 fprintf(stderr, "%s\n", error_str); 2498 } 2499 2500 _socket_funcs.dup2 = dlsym(__libc_dl_handle, "dup2"); 2501 if (NULL != (error_str = dlerror())) { 2502 fprintf(stderr, "%s\n", error_str); 2503 } 2504 2505 _socket_funcs.getpeername = dlsym(__libc_dl_handle, "getpeername"); 2506 if (NULL != (error_str = dlerror())) { 2507 fprintf(stderr, "%s\n", error_str); 2508 } 2509 2510 _socket_funcs.getsockname = dlsym(__libc_dl_handle, "getsockname"); 2511 if (NULL != (error_str = dlerror())) { 2512 fprintf(stderr, "%s\n", error_str); 2513 } 2514 2515 _socket_funcs.accept = dlsym(__libc_dl_handle, "accept"); 2516 if (NULL != (error_str = dlerror())) { 2517 fprintf(stderr, "%s\n", error_str); 2518 } 2519 2520 _socket_funcs.select = dlsym(__libc_dl_handle, "select"); 2521 if (NULL != (error_str = dlerror())) { 2522 fprintf(stderr, "%s\n", error_str); 2523 } 2524 2525 _socket_funcs.pselect = dlsym(__libc_dl_handle, "pselect"); 2526 if (NULL != (error_str = dlerror())) { 2527 fprintf(stderr, "%s\n", error_str); 2528 } 2529 2530 _socket_funcs.poll = dlsym(__libc_dl_handle, "poll"); 2531 if (NULL != (error_str = dlerror())) { 2532 fprintf(stderr, "%s\n", error_str); 2533 } 2534 2535#ifdef __linux__ 2536 _socket_funcs.epoll_create = dlsym(__libc_dl_handle, "epoll_create"); 2537 if (NULL != (error_str = dlerror())) { 2538 fprintf(stderr, "%s\n", error_str); 2539 } 2540 2541 _socket_funcs.epoll_ctl = dlsym(__libc_dl_handle, "epoll_ctl"); 2542 if (NULL != (error_str = dlerror())) { 2543 fprintf(stderr, "%s\n", error_str); 2544 } 2545 2546 _socket_funcs.epoll_wait = dlsym(__libc_dl_handle, "epoll_wait"); 2547 if (NULL != (error_str = dlerror())) { 2548 fprintf(stderr, "%s\n", error_str); 2549 } 2550 2551 _socket_funcs.epoll_pwait = dlsym(__libc_dl_handle, "epoll_pwait"); 2552 if (NULL != (error_str = dlerror())) { 2553 fprintf(stderr, "%s\n", error_str); 2554 } 2555#endif 2556#ifdef SOLARIS_BUILD 2557 _socket_xnet_funcs.socket = dlsym(__libc_dl_handle, "__xnet_socket"); 2558 if (NULL != (error_str = dlerror())) { 2559 fprintf(stderr, "%s\n", error_str); 2560 } 2561 2562 _socket_xnet_funcs.connect = dlsym(__libc_dl_handle, "__xnet_connect"); 2563 if (NULL != (error_str = dlerror())) { 2564 fprintf(stderr, "%s\n", error_str); 2565 } 2566 2567 _socket_xnet_funcs.listen = dlsym(__libc_dl_handle, "__xnet_listen"); 2568 if (NULL != (error_str = dlerror())) { 2569 fprintf(stderr, "%s\n", error_str); 2570 } 2571 2572 _socket_xnet_funcs.bind = dlsym(__libc_dl_handle, "__xnet_bind"); 2573 if (NULL != (error_str = dlerror())) { 2574 fprintf(stderr, "%s\n", error_str); 2575 } 2576 2577 /* Determine program name by asking libdl */ 2578 Dl_argsinfo args_info; 2579 if (NULL != dlinfo(RTLD_SELF, RTLD_DI_ARGSINFO, &args_info)) { 2580 fprintf(stderr, "args_info: %s\n", dlerror()); 2581 } else { 2582 program_invocation_name = args_info.dla_argv[0]; 2583 program_invocation_short_name = basename(args_info.dla_argv[0]); 2584 } 2585#endif 2586 2587 if (getenv("SIMPLE_LIBSDP") != NULL) { 2588 simple_sdp_library = 1; 2589 } 2590 2591 if (getenv("ALWAYS_USE_SDP") != NULL) { 2592 simple_sdp_library = 1; 2593 } 2594#define LIBSDP_DEFAULT_CONFIG_FILE SYSCONFDIR "/libsdp.conf" 2595 if (!simple_sdp_library) { 2596 config_file = getenv("LIBSDP_CONFIG_FILE"); 2597 if (!config_file) 2598 config_file = LIBSDP_DEFAULT_CONFIG_FILE; 2599 2600 if (__sdp_parse_config(config_file)) { 2601 fprintf(stderr, 2602 "libsdp Error: failed to parse config file:%s. Using defaults.\n", 2603 config_file); 2604 } 2605 } 2606 2607 __sdp_log(1, "Max file descriptors:%d\n", max_file_descriptors); 2608 init_status = 2; 2609 2610} /* __sdp_init */ 2611 2612/* ========================================================================= */ 2613/*..__sdp_fini -- when the library is unloaded this is called */ 2614void __sdp_fini(void) 2615{ 2616 struct use_family_rule *rule; 2617 for (rule = __sdp_clients_family_rules_head; rule != NULL; 2618 rule = rule->next) 2619 free(rule->prog_name_expr); 2620 for (rule = __sdp_servers_family_rules_head; rule != NULL; 2621 rule = rule->next) 2622 free(rule->prog_name_expr); 2623 2624 free(libsdp_fd_attributes); 2625 2626#ifndef RTLD_NEXT 2627 dlclose(__libc_dl_handle); 2628#endif 2629} /* _fini */ 2630