]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/libsdp/src/socket.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / libsdp / src / socket.c
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
79 extern char * program_invocation_name;
80 extern char * program_invocation_short_name;
81 extern char ** const environ;
82
83 /* ========================================================================= */
84 /*..socket -- replacment socket call. */
85 int 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 */