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 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/* 33219820Sjeff For non-i386 systems, we pass socket() through to library code using 34219820Sjeff dlsym() instead of trying to make the system call directly. This 35219820Sjeff may cause problems if this library is LD_PRELOADed before the real C 36219820Sjeff library is available. Eventually we may want to add the same type 37219820Sjeff of system call assembly code as i386 has for IA64 and AMD64, but for 38219820Sjeff now.... 39219820Sjeff*/ 40219820Sjeff#ifndef i386 41219820Sjeff#define _GNU_SOURCE /* Get RTLD_NEXT */ 42219820Sjeff#include <dlfcn.h> 43219820Sjeff#else 44219820Sjeff#include <sys/syscall.h> 45219820Sjeff#endif 46219820Sjeff 47219820Sjeff#include <errno.h> 48219820Sjeff#include <stdio.h> 49219820Sjeff#include <stdlib.h> 50219820Sjeff#include <sys/socket.h> 51219820Sjeff#include <string.h> 52219820Sjeff/* 53219820Sjeff * SDP specific includes 54219820Sjeff */ 55219820Sjeff#include "linux/sdp_inet.h" 56219820Sjeff 57219820Sjeff#if 0 58219820Sjeff#define _SDP_VERBOSE_PRELOAD 59219820Sjeff#endif 60219820Sjeff 61219820Sjeff#define SOCKOP_socket 1 62219820Sjeff#define SOCKOP_bind 2 63219820Sjeff#define SOCKOP_connect 3 64219820Sjeff#define SOCKOP_listen 4 65219820Sjeff#define SOCKOP_accept 5 66219820Sjeff#define SOCKOP_getsockname 6 67219820Sjeff#define SOCKOP_getpeername 7 68219820Sjeff#define SOCKOP_socketpair 8 69219820Sjeff#define SOCKOP_send 9 70219820Sjeff#define SOCKOP_recv 10 71219820Sjeff#define SOCKOP_sendto 11 72219820Sjeff#define SOCKOP_recvfrom 12 73219820Sjeff#define SOCKOP_shutdown 13 74219820Sjeff#define SOCKOP_setsockopt 14 75219820Sjeff#define SOCKOP_getsockopt 15 76219820Sjeff#define SOCKOP_sendmsg 16 77219820Sjeff#define SOCKOP_recvmsg 17 78219820Sjeff 79219820Sjeffextern char * program_invocation_name; 80219820Sjeffextern char * program_invocation_short_name; 81219820Sjeffextern char ** const environ; 82219820Sjeff 83219820Sjeff/* ========================================================================= */ 84219820Sjeff/*..socket -- replacment socket call. */ 85219820Sjeffint socket 86219820Sjeff( 87219820Sjeff int domain, 88219820Sjeff int type, 89219820Sjeff int protocol 90219820Sjeff) 91219820Sjeff{ 92219820Sjeff#ifdef i386 93219820Sjeff long __ret; 94219820Sjeff void *__scratch; 95219820Sjeff int call[3]; 96219820Sjeff#endif 97219820Sjeff char *test; 98219820Sjeff char *inet; 99219820Sjeff char **tenviron; 100219820Sjeff 101219820Sjeff#ifdef _SDP_VERBOSE_PRELOAD 102219820Sjeff FILE *fd; 103219820Sjeff#endif 104219820Sjeff /* 105219820Sjeff * check for magic enviroment variable 106219820Sjeff */ 107219820Sjeff if ((AF_INET == domain || AF_INET6 == domain) && 108219820Sjeff SOCK_STREAM == type) { 109219820Sjeff 110219820Sjeff if (environ) { 111219820Sjeff tenviron = environ; 112219820Sjeff for (test = *tenviron; NULL != test; test = *++tenviron) { 113219820Sjeff 114219820Sjeff inet = AF_INET_STR; 115219820Sjeff 116219820Sjeff while (*inet == *test && '\0' != *inet) { 117219820Sjeff 118219820Sjeff inet++; 119219820Sjeff test++; 120219820Sjeff } /* while */ 121219820Sjeff 122219820Sjeff if ('\0' == *inet && '=' == *test) { 123219820Sjeff 124219820Sjeff domain = AF_INET_SDP; 125219820Sjeff break; 126219820Sjeff } /* if */ 127219820Sjeff } /* for */ 128219820Sjeff } /* if */ 129219820Sjeff } /* if */ 130219820Sjeff 131219820Sjeff#ifdef _SDP_VERBOSE_PRELOAD 132219820Sjeff fd = fopen("/tmp/libsdp.log.txt", "a+"); 133219820Sjeff 134219820Sjeff fprintf(fd, "SOCKET: <%s> domain <%d> type <%d> protocol <%d>\n", 135219820Sjeff program_invocation_short_name, domain, type, protocol); 136219820Sjeff 137219820Sjeff fclose(fd); 138219820Sjeff#endif 139219820Sjeff 140219820Sjeff#ifdef i386 141219820Sjeff /* Make the socket() system call directly, as described above */ 142219820Sjeff call[0] = domain; 143219820Sjeff call[1] = type; 144219820Sjeff call[2] = protocol; 145219820Sjeff 146219820Sjeff __asm__ __volatile__("movl %%ebx, %1\n" /* save %ebx */ 147219820Sjeff "movl %3, %%ebx\n" /* put sockopt in %ebx as arg */ 148219820Sjeff "int $0x80\n" /* do syscall */ 149219820Sjeff "movl %1, %%ebx\n" /* restore %ebx */ 150219820Sjeff : "=a" (__ret), "=r" (__scratch) 151219820Sjeff : "0" (__NR_socketcall), 152219820Sjeff "g" (SOCKOP_socket), 153219820Sjeff "c" (call)); 154219820Sjeff return __ret; 155219820Sjeff#else /* i386 */ 156219820Sjeff /* Use the standard library socket() to pass through the call */ 157219820Sjeff { 158219820Sjeff static int (*orig_socket)(int, int, int); 159219820Sjeff 160219820Sjeff if (!orig_socket) { 161219820Sjeff orig_socket = dlsym(RTLD_NEXT, "socket"); 162219820Sjeff } 163219820Sjeff 164219820Sjeff return orig_socket(domain, type, protocol); 165219820Sjeff } 166219820Sjeff#endif /* i386 */ 167219820Sjeff} /* socket */ 168