]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/libsdp/src/port.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 / port.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-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
94 void __attribute__ ((constructor)) __sdp_init(void);
95 void __attribute__ ((destructor)) __sdp_fini(void);
96
97 /* --------------------------------------------------------------------- */
98 /* library type definitions.                                             */
99 /* --------------------------------------------------------------------- */
100
101 typedef 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
109 typedef int (*fcntl_func_t) (int fd, int cmd, ...);
110
111 typedef int (*socket_func_t) (int domain, int type, int protocol);
112
113 typedef int (*setsockopt_func_t) (int s,
114                                                                   int level,
115                                                                   int optname,
116                                                                   const void *optval, socklen_t optlen);
117
118 typedef int (*connect_func_t) (int sockfd,
119                                                            const struct sockaddr * serv_addr,
120                                                            socklen_t addrlen);
121
122 typedef int (*listen_func_t) (int s, int backlog);
123
124 typedef int (*bind_func_t) (int sockfd,
125                                                         const struct sockaddr * my_addr, socklen_t addrlen);
126
127 typedef int (*close_func_t) (int fd);
128
129 typedef int (*dup_func_t) (int fd);
130
131 typedef int (*dup2_func_t) (int oldfd, int newfd);
132
133 typedef int (*getsockname_func_t) (int fd,
134                                                                    struct sockaddr * name, socklen_t * namelen);
135
136 typedef int (*getpeername_func_t) (int fd,
137                                                                    struct sockaddr * name, socklen_t * namelen);
138
139 typedef int (*accept_func_t) (int fd,
140                                                           struct sockaddr * addr, socklen_t * addrlen);
141
142 typedef int (*select_func_t) (int n,
143                                                           fd_set * readfds,
144                                                           fd_set * writefds,
145                                                           fd_set * exceptfds, struct timeval * timeout);
146
147 typedef 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
154 typedef int (*poll_func_t) (struct pollfd * ufds,
155                                                         unsigned long int nfds, int timeout);
156
157 #ifdef __linux__
158 typedef int (*epoll_create_func_t) (int size);
159
160 typedef int (*epoll_ctl_func_t) (int epfd,
161                                                                  int op, int fd, struct epoll_event * event);
162
163 typedef int (*epoll_wait_func_t) (int epfd,
164                                                                   struct epoll_event * events,
165                                                                   int maxevents, int timeout);
166
167 typedef 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
174 struct 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_ */
201 struct 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
209 static int simple_sdp_library;
210 static int max_file_descriptors;
211 static int dev_null_fd;
212 volatile 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
221 char *program_invocation_name = "[progname]", *program_invocation_short_name =
222         "[short_progname]";
223 #else
224 extern char *program_invocation_name, *program_invocation_short_name;
225 #endif
226
227 #ifdef RTLD_NEXT
228 static void *__libc_dl_handle = RTLD_NEXT;
229 #else
230 static void *__libc_dl_handle;
231 #endif
232
233 /* extra fd attributes we need for our algorithms */
234 struct 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 */
241 static struct sdp_extra_fd_attributes *libsdp_fd_attributes;
242
243 static 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
249 static 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 /* --------------------------------------------------------------------- */
258 void __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 */
268 static 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
277 static 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        */
284 static 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 --                                                     */
294 static 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 --                                                     */
302 static 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         */
310 static 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       */
320 static 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                   */
330 static 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             */
338 static 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    */
351 static 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
373 static 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
388 static 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  */
403 static 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      */
430 static 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       */
442 static 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. */
467 int
468 ioctl(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.                                         */
529 int 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.                               */
575 int
576 setsockopt(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
641 static 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 */
654 static 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
751 done:
752         __sdp_log(2, "SOCKET: <%s:%d:%d>\n",
753                           program_invocation_short_name, s, shadow_fd);
754
755         return s;
756 }                                                               /* socket */
757
758 int socket(int domain, int type, int protocol)
759 {
760         return __create_socket(domain, type, protocol, SOCKET_SEMANTIC_DEFAULT);
761 }
762
763 #ifdef SOLARIS_BUILD
764 int __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             */
772 static 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                   */
793 static 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                           */
804 static 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
820 static int
821 find_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
957 setfds:
958         tcp_turn = tmp_turn;
959         *sdp_sd = tmp_sd[0];
960         *tcp_sd = tmp_sd[1];
961
962 done:
963         __sdp_log(2, "find_free_port: return port:<%d>\n", port);
964         return port;
965
966 close_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   */
975 static int
976 check_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);
1081 done:
1082         return ret;
1083 }
1084
1085 /* ========================================================================= */
1086 /*..close_and_bind - close an open fd and bind another one immediately       */
1087 static int
1088 close_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
1105 done:
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 */
1127 static 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
1238 done:
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
1246 int 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
1252 int __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 */
1266 static 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
1279 static 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
1391 done:
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
1398 int 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 )
1404 int __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
1417 static 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
1427 static 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
1558 done:
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
1569 int listen(int fd, int backlog)
1570 {
1571         return __perform_listen(fd, backlog, SOCKET_SEMANTIC_DEFAULT);
1572 }
1573
1574 #ifdef SOLARIS_BUILD
1575 int __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. */
1583 int 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      */
1618 int 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     */
1673 int 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
1735 done:
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.                            */
1745 int 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. */
1796 int 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 */
1843 int 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 */
1992 int
1993 select(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
2071 done:
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 */
2084 int
2085 pselect(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
2168 done:
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 */
2181 int 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);
2265 done:
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 */
2278 int 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 */
2306 int 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 */
2345 int 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 */
2373 int
2374 epoll_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 */
2408 void __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 */
2614 void __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 */