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 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/* 33 For non-i386 systems, we pass socket() through to library code using 34 dlsym() instead of trying to make the system call directly. This 35 may cause problems if this library is LD_PRELOADed before the real C 36 library is available. Eventually we may want to add the same type 37 of system call assembly code as i386 has for IA64 and AMD64, but for 38 now.... 39*/ 40#ifndef i386 41#define _GNU_SOURCE /* Get RTLD_NEXT */ 42#include <dlfcn.h> 43#else 44#include <sys/syscall.h> 45#endif 46 47#include <errno.h> 48#include <stdio.h> 49#include <stdlib.h> 50#include <sys/socket.h> 51#include <string.h> 52/* 53 * SDP specific includes 54 */ 55#include "linux/sdp_inet.h" 56 57#if 0 58#define _SDP_VERBOSE_PRELOAD 59#endif 60 61#define SOCKOP_socket 1 62#define SOCKOP_bind 2 63#define SOCKOP_connect 3 64#define SOCKOP_listen 4 65#define SOCKOP_accept 5 66#define SOCKOP_getsockname 6 67#define SOCKOP_getpeername 7 68#define SOCKOP_socketpair 8 69#define SOCKOP_send 9 70#define SOCKOP_recv 10 71#define SOCKOP_sendto 11 72#define SOCKOP_recvfrom 12 73#define SOCKOP_shutdown 13 74#define SOCKOP_setsockopt 14 75#define SOCKOP_getsockopt 15 76#define SOCKOP_sendmsg 16 77#define SOCKOP_recvmsg 17 78 79extern char * program_invocation_name; 80extern char * program_invocation_short_name; 81extern char ** const environ; 82 83/* ========================================================================= */ 84/*..socket -- replacment socket call. */ 85int socket 86( 87 int domain, 88 int type, 89 int protocol 90) 91{ 92#ifdef i386 93 long __ret; 94 void *__scratch; 95 int call[3]; 96#endif 97 char *test; 98 char *inet; 99 char **tenviron; 100 101#ifdef _SDP_VERBOSE_PRELOAD 102 FILE *fd; 103#endif 104 /* 105 * check for magic enviroment variable 106 */ 107 if ((AF_INET == domain || AF_INET6 == domain) && 108 SOCK_STREAM == type) { 109 110 if (environ) { 111 tenviron = environ; 112 for (test = *tenviron; NULL != test; test = *++tenviron) { 113 114 inet = AF_INET_STR; 115 116 while (*inet == *test && '\0' != *inet) { 117 118 inet++; 119 test++; 120 } /* while */ 121 122 if ('\0' == *inet && '=' == *test) { 123 124 domain = AF_INET_SDP; 125 break; 126 } /* if */ 127 } /* for */ 128 } /* if */ 129 } /* if */ 130 131#ifdef _SDP_VERBOSE_PRELOAD 132 fd = fopen("/tmp/libsdp.log.txt", "a+"); 133 134 fprintf(fd, "SOCKET: <%s> domain <%d> type <%d> protocol <%d>\n", 135 program_invocation_short_name, domain, type, protocol); 136 137 fclose(fd); 138#endif 139 140#ifdef i386 141 /* Make the socket() system call directly, as described above */ 142 call[0] = domain; 143 call[1] = type; 144 call[2] = protocol; 145 146 __asm__ __volatile__("movl %%ebx, %1\n" /* save %ebx */ 147 "movl %3, %%ebx\n" /* put sockopt in %ebx as arg */ 148 "int $0x80\n" /* do syscall */ 149 "movl %1, %%ebx\n" /* restore %ebx */ 150 : "=a" (__ret), "=r" (__scratch) 151 : "0" (__NR_socketcall), 152 "g" (SOCKOP_socket), 153 "c" (call)); 154 return __ret; 155#else /* i386 */ 156 /* Use the standard library socket() to pass through the call */ 157 { 158 static int (*orig_socket)(int, int, int); 159 160 if (!orig_socket) { 161 orig_socket = dlsym(RTLD_NEXT, "socket"); 162 } 163 164 return orig_socket(domain, type, protocol); 165 } 166#endif /* i386 */ 167} /* socket */ 168