lib/socket_wrapper/socket_wrapper.c

説明を見る。
00001 /*
00002  * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
00003  * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
00004  *
00005  * All rights reserved.
00006  * 
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  * 
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  * 
00018  * 3. Neither the name of the author nor the names of its contributors
00019  *    may be used to endorse or promote products derived from this software
00020  *    without specific prior written permission.
00021  * 
00022  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  */
00035 
00036 /*
00037    Socket wrapper library. Passes all socket communication over
00038    unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
00039    is set.
00040 */
00041 
00042 #ifdef _SAMBA_BUILD_
00043 
00044 #define SOCKET_WRAPPER_NOT_REPLACE
00045 #include "includes.h"
00046 #include "system/network.h"
00047 #include "system/filesys.h"
00048 
00049 #ifdef malloc
00050 #undef malloc
00051 #endif
00052 #ifdef calloc
00053 #undef calloc
00054 #endif
00055 #ifdef strdup
00056 #undef strdup
00057 #endif
00058 
00059 #else /* _SAMBA_BUILD_ */
00060 
00061 #include <sys/types.h>
00062 #include <sys/stat.h>
00063 #include <sys/socket.h>
00064 #include <sys/ioctl.h>
00065 #include <errno.h>
00066 #include <sys/un.h>
00067 #include <netinet/in.h>
00068 #include <netinet/tcp.h>
00069 #include <fcntl.h>
00070 #include <stdlib.h>
00071 #include <unistd.h>
00072 #include <string.h>
00073 #include <stdio.h>
00074 
00075 #define _PUBLIC_
00076 
00077 #endif
00078 
00079 #define SWRAP_DLIST_ADD(list,item) do { \
00080         if (!(list)) { \
00081                 (item)->prev    = NULL; \
00082                 (item)->next    = NULL; \
00083                 (list)          = (item); \
00084         } else { \
00085                 (item)->prev    = NULL; \
00086                 (item)->next    = (list); \
00087                 (list)->prev    = (item); \
00088                 (list)          = (item); \
00089         } \
00090 } while (0)
00091 
00092 #define SWRAP_DLIST_REMOVE(list,item) do { \
00093         if ((list) == (item)) { \
00094                 (list)          = (item)->next; \
00095                 if (list) { \
00096                         (list)->prev    = NULL; \
00097                 } \
00098         } else { \
00099                 if ((item)->prev) { \
00100                         (item)->prev->next      = (item)->next; \
00101                 } \
00102                 if ((item)->next) { \
00103                         (item)->next->prev      = (item)->prev; \
00104                 } \
00105         } \
00106         (item)->prev    = NULL; \
00107         (item)->next    = NULL; \
00108 } while (0)
00109 
00110 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
00111  * for now */
00112 #define REWRITE_CALLS 
00113 
00114 #ifdef REWRITE_CALLS
00115 #define real_accept accept
00116 #define real_connect connect
00117 #define real_bind bind
00118 #define real_listen listen
00119 #define real_getpeername getpeername
00120 #define real_getsockname getsockname
00121 #define real_getsockopt getsockopt
00122 #define real_setsockopt setsockopt
00123 #define real_recvfrom recvfrom
00124 #define real_sendto sendto
00125 #define real_ioctl ioctl
00126 #define real_recv recv
00127 #define real_send send
00128 #define real_socket socket
00129 #define real_close close
00130 #endif
00131 
00132 #ifdef HAVE_GETTIMEOFDAY_TZ
00133 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
00134 #else
00135 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
00136 #endif
00137 
00138 /* we need to use a very terse format here as IRIX 6.4 silently
00139    truncates names to 16 chars, so if we use a longer name then we
00140    can't tell which port a packet came from with recvfrom() 
00141    
00142    with this format we have 8 chars left for the directory name
00143 */
00144 #define SOCKET_FORMAT "%c%02X%04X"
00145 #define SOCKET_TYPE_CHAR_TCP            'T'
00146 #define SOCKET_TYPE_CHAR_UDP            'U'
00147 
00148 #define MAX_WRAPPED_INTERFACES 16
00149 
00150 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
00151 {
00152         struct sockaddr *ret = (struct sockaddr *)malloc(len);
00153         memcpy(ret, data, len);
00154         return ret;
00155 }
00156 
00157 struct socket_info
00158 {
00159         int fd;
00160 
00161         int family;
00162         int type;
00163         int protocol;
00164         int bound;
00165         int bcast;
00166         int is_server;
00167 
00168         char *path;
00169         char *tmp_path;
00170 
00171         struct sockaddr *myname;
00172         socklen_t myname_len;
00173 
00174         struct sockaddr *peername;
00175         socklen_t peername_len;
00176 
00177         struct {
00178                 unsigned long pck_snd;
00179                 unsigned long pck_rcv;
00180         } io;
00181 
00182         struct socket_info *prev, *next;
00183 };
00184 
00185 static struct socket_info *sockets;
00186 
00187 
00188 static const char *socket_wrapper_dir(void)
00189 {
00190         const char *s = getenv("SOCKET_WRAPPER_DIR");
00191         if (s == NULL) {
00192                 return NULL;
00193         }
00194         if (strncmp(s, "./", 2) == 0) {
00195                 s += 2;
00196         }
00197         return s;
00198 }
00199 
00200 static unsigned int socket_wrapper_default_iface(void)
00201 {
00202         const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
00203         if (s) {
00204                 unsigned int iface;
00205                 if (sscanf(s, "%u", &iface) == 1) {
00206                         if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
00207                                 return iface;
00208                         }
00209                 }
00210         }
00211 
00212         return 1;/* 127.0.0.1 */
00213 }
00214 
00215 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
00216 {
00217         unsigned int iface;
00218         unsigned int prt;
00219         const char *p;
00220         char type;
00221 
00222         if ((*len) < sizeof(struct sockaddr_in)) {
00223                 return 0;
00224         }
00225 
00226         p = strrchr(un->sun_path, '/');
00227         if (p) p++; else p = un->sun_path;
00228 
00229         if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
00230                 errno = EINVAL;
00231                 return -1;
00232         }
00233 
00234         if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
00235                 errno = EINVAL;
00236                 return -1;
00237         }
00238 
00239         if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
00240                 errno = EINVAL;
00241                 return -1;
00242         }
00243 
00244         if (prt > 0xFFFF) {
00245                 errno = EINVAL;
00246                 return -1;
00247         }
00248 
00249         in->sin_family = AF_INET;
00250         in->sin_addr.s_addr = htonl((127<<24) | iface);
00251         in->sin_port = htons(prt);
00252 
00253         *len = sizeof(struct sockaddr_in);
00254         return 0;
00255 }
00256 
00257 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
00258                                 int *bcast)
00259 {
00260         char u_type = '\0';
00261         char b_type = '\0';
00262         char a_type = '\0';
00263         char type = '\0';
00264         unsigned int addr= ntohl(in->sin_addr.s_addr);
00265         unsigned int prt = ntohs(in->sin_port);
00266         unsigned int iface;
00267         int is_bcast = 0;
00268 
00269         if (bcast) *bcast = 0;
00270 
00271         if (prt == 0) {
00272                 errno = EINVAL;
00273                 return -1;
00274         }
00275 
00276         switch (si->type) {
00277         case SOCK_STREAM:
00278                 u_type = SOCKET_TYPE_CHAR_TCP;
00279                 break;
00280         case SOCK_DGRAM:
00281                 u_type = SOCKET_TYPE_CHAR_UDP;
00282                 a_type = SOCKET_TYPE_CHAR_UDP;
00283                 b_type = SOCKET_TYPE_CHAR_UDP;
00284                 break;
00285         }
00286 
00287         if (a_type && addr == 0xFFFFFFFF) {
00288                 /* 255.255.255.255 only udp */
00289                 is_bcast = 2;
00290                 type = a_type;
00291                 iface = socket_wrapper_default_iface();
00292         } else if (b_type && addr == 0x7FFFFFFF) {
00293                 /* 127.255.255.255 only udp */
00294                 is_bcast = 1;
00295                 type = b_type;
00296                 iface = socket_wrapper_default_iface();
00297         } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
00298                 /* 127.0.0.X */
00299                 is_bcast = 0;
00300                 type = u_type;
00301                 iface = (addr & 0x000000FF);
00302         } else {
00303                 errno = ENETUNREACH;
00304                 return -1;
00305         }
00306 
00307         if (bcast) *bcast = is_bcast;
00308 
00309         if (is_bcast) {
00310                 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", 
00311                          socket_wrapper_dir());
00312                 /* the caller need to do more processing */
00313                 return 0;
00314         }
00315 
00316         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
00317                  socket_wrapper_dir(), type, iface, prt);
00318 
00319         return 0;
00320 }
00321 
00322 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
00323                                int *bcast)
00324 {
00325         char u_type = '\0';
00326         char d_type = '\0';
00327         char b_type = '\0';
00328         char a_type = '\0';
00329         char type = '\0';
00330         unsigned int addr= ntohl(in->sin_addr.s_addr);
00331         unsigned int prt = ntohs(in->sin_port);
00332         unsigned int iface;
00333         struct stat st;
00334         int is_bcast = 0;
00335 
00336         if (bcast) *bcast = 0;
00337 
00338         switch (si->type) {
00339         case SOCK_STREAM:
00340                 u_type = SOCKET_TYPE_CHAR_TCP;
00341                 d_type = SOCKET_TYPE_CHAR_TCP;
00342                 break;
00343         case SOCK_DGRAM:
00344                 u_type = SOCKET_TYPE_CHAR_UDP;
00345                 d_type = SOCKET_TYPE_CHAR_UDP;
00346                 a_type = SOCKET_TYPE_CHAR_UDP;
00347                 b_type = SOCKET_TYPE_CHAR_UDP;
00348                 break;
00349         }
00350 
00351         if (addr == 0) {
00352                 /* 0.0.0.0 */
00353                 is_bcast = 0;
00354                 type = d_type;
00355                 iface = socket_wrapper_default_iface();
00356         } else if (a_type && addr == 0xFFFFFFFF) {
00357                 /* 255.255.255.255 only udp */
00358                 is_bcast = 2;
00359                 type = a_type;
00360                 iface = socket_wrapper_default_iface();
00361         } else if (b_type && addr == 0x7FFFFFFF) {
00362                 /* 127.255.255.255 only udp */
00363                 is_bcast = 1;
00364                 type = b_type;
00365                 iface = socket_wrapper_default_iface();
00366         } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
00367                 /* 127.0.0.X */
00368                 is_bcast = 0;
00369                 type = u_type;
00370                 iface = (addr & 0x000000FF);
00371         } else {
00372                 errno = EADDRNOTAVAIL;
00373                 return -1;
00374         }
00375 
00376         if (bcast) *bcast = is_bcast;
00377 
00378         if (prt == 0) {
00379                 /* handle auto-allocation of ephemeral ports */
00380                 for (prt = 5001; prt < 10000; prt++) {
00381                         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
00382                                  socket_wrapper_dir(), type, iface, prt);
00383                         if (stat(un->sun_path, &st) == 0) continue;
00384 
00385                         ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
00386                         return 0;
00387                 }
00388                 errno = ENFILE;
00389                 return -1;
00390         }
00391 
00392         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
00393                  socket_wrapper_dir(), type, iface, prt);
00394         return 0;
00395 }
00396 
00397 static struct socket_info *find_socket_info(int fd)
00398 {
00399         struct socket_info *i;
00400         for (i = sockets; i; i = i->next) {
00401                 if (i->fd == fd) 
00402                         return i;
00403         }
00404 
00405         return NULL;
00406 }
00407 
00408 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, 
00409                                   struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
00410 {
00411         if (!out_addr)
00412                 return 0;
00413 
00414         out_addr->sun_family = AF_UNIX;
00415 
00416         switch (in_addr->sa_family) {
00417         case AF_INET:
00418                 switch (si->type) {
00419                 case SOCK_STREAM:
00420                 case SOCK_DGRAM:
00421                         break;
00422                 default:
00423                         errno = ESOCKTNOSUPPORT;
00424                         return -1;
00425                 }
00426                 if (alloc_sock) {
00427                         return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
00428                 } else {
00429                         return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
00430                 }
00431         default:
00432                 break;
00433         }
00434         
00435         errno = EAFNOSUPPORT;
00436         return -1;
00437 }
00438 
00439 static int sockaddr_convert_from_un(const struct socket_info *si, 
00440                                     const struct sockaddr_un *in_addr, 
00441                                     socklen_t un_addrlen,
00442                                     int family,
00443                                     struct sockaddr *out_addr,
00444                                     socklen_t *_out_addrlen)
00445 {
00446         socklen_t out_addrlen;
00447 
00448         if (out_addr == NULL || _out_addrlen == NULL) 
00449                 return 0;
00450 
00451         if (un_addrlen == 0) {
00452                 *_out_addrlen = 0;
00453                 return 0;
00454         }
00455 
00456         out_addrlen = *_out_addrlen;
00457         if (out_addrlen > un_addrlen) {
00458                 out_addrlen = un_addrlen;
00459         }
00460 
00461         switch (family) {
00462         case AF_INET:
00463                 switch (si->type) {
00464                 case SOCK_STREAM:
00465                 case SOCK_DGRAM:
00466                         break;
00467                 default:
00468                         errno = ESOCKTNOSUPPORT;
00469                         return -1;
00470                 }
00471                 return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
00472         default:
00473                 break;
00474         }
00475 
00476         errno = EAFNOSUPPORT;
00477         return -1;
00478 }
00479 
00480 enum swrap_packet_type {
00481         SWRAP_CONNECT_SEND,
00482         SWRAP_CONNECT_UNREACH,
00483         SWRAP_CONNECT_RECV,
00484         SWRAP_CONNECT_ACK,
00485         SWRAP_ACCEPT_SEND,
00486         SWRAP_ACCEPT_RECV,
00487         SWRAP_ACCEPT_ACK,
00488         SWRAP_RECVFROM,
00489         SWRAP_SENDTO,
00490         SWRAP_SENDTO_UNREACH,
00491         SWRAP_PENDING_RST,
00492         SWRAP_RECV,
00493         SWRAP_RECV_RST,
00494         SWRAP_SEND,
00495         SWRAP_SEND_RST,
00496         SWRAP_CLOSE_SEND,
00497         SWRAP_CLOSE_RECV,
00498         SWRAP_CLOSE_ACK
00499 };
00500 
00501 struct swrap_file_hdr {
00502         unsigned long   magic;
00503         unsigned short  version_major;  
00504         unsigned short  version_minor;
00505         long            timezone;
00506         unsigned long   sigfigs;
00507         unsigned long   frame_max_len;
00508 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
00509         unsigned long   link_type;
00510 };
00511 #define SWRAP_FILE_HDR_SIZE 24
00512 
00513 struct swrap_packet {
00514         struct {
00515                 unsigned long seconds;
00516                 unsigned long micro_seconds;
00517                 unsigned long recorded_length;
00518                 unsigned long full_length;
00519         } frame;
00520 #define SWRAP_PACKET__FRAME_SIZE 16
00521 
00522         struct {
00523                 struct {
00524                         unsigned char   ver_hdrlen;
00525                         unsigned char   tos;
00526                         unsigned short  packet_length;
00527                         unsigned short  identification;
00528                         unsigned char   flags;
00529                         unsigned char   fragment;
00530                         unsigned char   ttl;
00531                         unsigned char   protocol;
00532                         unsigned short  hdr_checksum;
00533                         unsigned long   src_addr;
00534                         unsigned long   dest_addr;
00535                 } hdr;
00536 #define SWRAP_PACKET__IP_HDR_SIZE 20
00537 
00538                 union {
00539                         struct {
00540                                 unsigned short  source_port;
00541                                 unsigned short  dest_port;
00542                                 unsigned long   seq_num;
00543                                 unsigned long   ack_num;
00544                                 unsigned char   hdr_length;
00545                                 unsigned char   control;
00546                                 unsigned short  window;
00547                                 unsigned short  checksum;
00548                                 unsigned short  urg;
00549                         } tcp;
00550 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
00551                         struct {
00552                                 unsigned short  source_port;
00553                                 unsigned short  dest_port;
00554                                 unsigned short  length;
00555                                 unsigned short  checksum;
00556                         } udp;
00557 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
00558                         struct {
00559                                 unsigned char   type;
00560                                 unsigned char   code;
00561                                 unsigned short  checksum;
00562                                 unsigned long   unused;
00563                         } icmp;
00564 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
00565                 } p;
00566         } ip;
00567 };
00568 #define SWRAP_PACKET_SIZE 56
00569 
00570 static const char *socket_wrapper_pcap_file(void)
00571 {
00572         static int initialized = 0;
00573         static const char *s = NULL;
00574         static const struct swrap_file_hdr h;
00575         static const struct swrap_packet p;
00576 
00577         if (initialized == 1) {
00578                 return s;
00579         }
00580         initialized = 1;
00581 
00582         /*
00583          * TODO: don't use the structs use plain buffer offsets
00584          *       and PUSH_U8(), PUSH_U16() and PUSH_U32()
00585          * 
00586          * for now make sure we disable PCAP support
00587          * if the struct has alignment!
00588          */
00589         if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
00590                 return NULL;
00591         }
00592         if (sizeof(p) != SWRAP_PACKET_SIZE) {
00593                 return NULL;
00594         }
00595         if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
00596                 return NULL;
00597         }
00598         if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
00599                 return NULL;
00600         }
00601         if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
00602                 return NULL;
00603         }
00604         if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
00605                 return NULL;
00606         }
00607         if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
00608                 return NULL;
00609         }
00610 
00611         s = getenv("SOCKET_WRAPPER_PCAP_FILE");
00612         if (s == NULL) {
00613                 return NULL;
00614         }
00615         if (strncmp(s, "./", 2) == 0) {
00616                 s += 2;
00617         }
00618         return s;
00619 }
00620 
00621 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
00622                                               const struct sockaddr_in *src_addr,
00623                                               const struct sockaddr_in *dest_addr,
00624                                               int socket_type,
00625                                               const unsigned char *payload,
00626                                               size_t payload_len,
00627                                               unsigned long tcp_seq,
00628                                               unsigned long tcp_ack,
00629                                               unsigned char tcp_ctl,
00630                                               int unreachable,
00631                                               size_t *_packet_len)
00632 {
00633         struct swrap_packet *ret;
00634         struct swrap_packet *packet;
00635         size_t packet_len;
00636         size_t alloc_len;
00637         size_t nonwire_len = sizeof(packet->frame);
00638         size_t wire_hdr_len = 0;
00639         size_t wire_len = 0;
00640         size_t icmp_hdr_len = 0;
00641         size_t icmp_truncate_len = 0;
00642         unsigned char protocol = 0, icmp_protocol = 0;
00643         unsigned short src_port = src_addr->sin_port;
00644         unsigned short dest_port = dest_addr->sin_port;
00645 
00646         switch (socket_type) {
00647         case SOCK_STREAM:
00648                 protocol = 0x06; /* TCP */
00649                 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
00650                 wire_len = wire_hdr_len + payload_len;
00651                 break;
00652 
00653         case SOCK_DGRAM:
00654                 protocol = 0x11; /* UDP */
00655                 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
00656                 wire_len = wire_hdr_len + payload_len;
00657                 break;
00658         }
00659 
00660         if (unreachable) {
00661                 icmp_protocol = protocol;
00662                 protocol = 0x01; /* ICMP */
00663                 if (wire_len > 64 ) {
00664                         icmp_truncate_len = wire_len - 64;
00665                 }
00666                 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
00667                 wire_hdr_len += icmp_hdr_len;
00668                 wire_len += icmp_hdr_len;
00669         }
00670 
00671         packet_len = nonwire_len + wire_len;
00672         alloc_len = packet_len;
00673         if (alloc_len < sizeof(struct swrap_packet)) {
00674                 alloc_len = sizeof(struct swrap_packet);
00675         }
00676         ret = (struct swrap_packet *)malloc(alloc_len);
00677         if (!ret) return NULL;
00678 
00679         packet = ret;
00680 
00681         packet->frame.seconds           = tval->tv_sec;
00682         packet->frame.micro_seconds     = tval->tv_usec;
00683         packet->frame.recorded_length   = wire_len - icmp_truncate_len;
00684         packet->frame.full_length       = wire_len - icmp_truncate_len;
00685 
00686         packet->ip.hdr.ver_hdrlen       = 0x45; /* version 4 and 5 * 32 bit words */
00687         packet->ip.hdr.tos              = 0x00;
00688         packet->ip.hdr.packet_length    = htons(wire_len - icmp_truncate_len);
00689         packet->ip.hdr.identification   = htons(0xFFFF);
00690         packet->ip.hdr.flags            = 0x40; /* BIT 1 set - means don't fraqment */
00691         packet->ip.hdr.fragment         = htons(0x0000);
00692         packet->ip.hdr.ttl              = 0xFF;
00693         packet->ip.hdr.protocol         = protocol;
00694         packet->ip.hdr.hdr_checksum     = htons(0x0000);
00695         packet->ip.hdr.src_addr         = src_addr->sin_addr.s_addr;
00696         packet->ip.hdr.dest_addr        = dest_addr->sin_addr.s_addr;
00697 
00698         if (unreachable) {
00699                 packet->ip.p.icmp.type          = 0x03; /* destination unreachable */
00700                 packet->ip.p.icmp.code          = 0x01; /* host unreachable */
00701                 packet->ip.p.icmp.checksum      = htons(0x0000);
00702                 packet->ip.p.icmp.unused        = htonl(0x00000000);
00703 
00704                 /* set the ip header in the ICMP payload */
00705                 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
00706                 packet->ip.hdr.ver_hdrlen       = 0x45; /* version 4 and 5 * 32 bit words */
00707                 packet->ip.hdr.tos              = 0x00;
00708                 packet->ip.hdr.packet_length    = htons(wire_len - icmp_hdr_len);
00709                 packet->ip.hdr.identification   = htons(0xFFFF);
00710                 packet->ip.hdr.flags            = 0x40; /* BIT 1 set - means don't fraqment */
00711                 packet->ip.hdr.fragment         = htons(0x0000);
00712                 packet->ip.hdr.ttl              = 0xFF;
00713                 packet->ip.hdr.protocol         = icmp_protocol;
00714                 packet->ip.hdr.hdr_checksum     = htons(0x0000);
00715                 packet->ip.hdr.src_addr         = dest_addr->sin_addr.s_addr;
00716                 packet->ip.hdr.dest_addr        = src_addr->sin_addr.s_addr;
00717 
00718                 src_port = dest_addr->sin_port;
00719                 dest_port = src_addr->sin_port;
00720         }
00721 
00722         switch (socket_type) {
00723         case SOCK_STREAM:
00724                 packet->ip.p.tcp.source_port    = src_port;
00725                 packet->ip.p.tcp.dest_port      = dest_port;
00726                 packet->ip.p.tcp.seq_num        = htonl(tcp_seq);
00727                 packet->ip.p.tcp.ack_num        = htonl(tcp_ack);
00728                 packet->ip.p.tcp.hdr_length     = 0x50; /* 5 * 32 bit words */
00729                 packet->ip.p.tcp.control        = tcp_ctl;
00730                 packet->ip.p.tcp.window         = htons(0x7FFF);
00731                 packet->ip.p.tcp.checksum       = htons(0x0000);
00732                 packet->ip.p.tcp.urg            = htons(0x0000);
00733 
00734                 break;
00735 
00736         case SOCK_DGRAM:
00737                 packet->ip.p.udp.source_port    = src_addr->sin_port;
00738                 packet->ip.p.udp.dest_port      = dest_addr->sin_port;
00739                 packet->ip.p.udp.length         = htons(8 + payload_len);
00740                 packet->ip.p.udp.checksum       = htons(0x0000);
00741 
00742                 break;
00743         }
00744 
00745         if (payload && payload_len > 0) {
00746                 unsigned char *p = (unsigned char *)ret;
00747                 p += nonwire_len;
00748                 p += wire_hdr_len;
00749                 memcpy(p, payload, payload_len);
00750         }
00751 
00752         *_packet_len = packet_len - icmp_truncate_len;
00753         return ret;
00754 }
00755 
00756 static int swrap_get_pcap_fd(const char *fname)
00757 {
00758         static int fd = -1;
00759 
00760         if (fd != -1) return fd;
00761 
00762         fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
00763         if (fd != -1) {
00764                 struct swrap_file_hdr file_hdr;
00765                 file_hdr.magic          = 0xA1B2C3D4;
00766                 file_hdr.version_major  = 0x0002;       
00767                 file_hdr.version_minor  = 0x0004;
00768                 file_hdr.timezone       = 0x00000000;
00769                 file_hdr.sigfigs        = 0x00000000;
00770                 file_hdr.frame_max_len  = SWRAP_FRAME_LENGTH_MAX;
00771                 file_hdr.link_type      = 0x0065; /* 101 RAW IP */
00772 
00773                 write(fd, &file_hdr, sizeof(file_hdr));
00774                 return fd;
00775         }
00776 
00777         fd = open(fname, O_WRONLY|O_APPEND, 0644);
00778 
00779         return fd;
00780 }
00781 
00782 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
00783                               enum swrap_packet_type type,
00784                               const void *buf, size_t len)
00785 {
00786         const struct sockaddr_in *src_addr;
00787         const struct sockaddr_in *dest_addr;
00788         const char *file_name;
00789         unsigned long tcp_seq = 0;
00790         unsigned long tcp_ack = 0;
00791         unsigned char tcp_ctl = 0;
00792         int unreachable = 0;
00793         struct timeval tv;
00794         struct swrap_packet *packet;
00795         size_t packet_len = 0;
00796         int fd;
00797 
00798         file_name = socket_wrapper_pcap_file();
00799         if (!file_name) {
00800                 return;
00801         }
00802 
00803         if (si->family != AF_INET) {
00804                 return;
00805         }
00806 
00807         switch (type) {
00808         case SWRAP_CONNECT_SEND:
00809                 if (si->type != SOCK_STREAM) return;
00810 
00811                 src_addr = (const struct sockaddr_in *)si->myname;
00812                 dest_addr = (const struct sockaddr_in *)addr;
00813 
00814                 tcp_seq = si->io.pck_snd;
00815                 tcp_ack = si->io.pck_rcv;
00816                 tcp_ctl = 0x02; /* SYN */
00817 
00818                 si->io.pck_snd += 1;
00819 
00820                 break;
00821 
00822         case SWRAP_CONNECT_RECV:
00823                 if (si->type != SOCK_STREAM) return;
00824 
00825                 dest_addr = (const struct sockaddr_in *)si->myname;
00826                 src_addr = (const struct sockaddr_in *)addr;
00827 
00828                 tcp_seq = si->io.pck_rcv;
00829                 tcp_ack = si->io.pck_snd;
00830                 tcp_ctl = 0x12; /** SYN,ACK */
00831 
00832                 si->io.pck_rcv += 1;
00833 
00834                 break;
00835 
00836         case SWRAP_CONNECT_UNREACH:
00837                 if (si->type != SOCK_STREAM) return;
00838 
00839                 dest_addr = (const struct sockaddr_in *)si->myname;
00840                 src_addr = (const struct sockaddr_in *)addr;
00841 
00842                 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
00843                 tcp_seq = si->io.pck_snd - 1;
00844                 tcp_ack = si->io.pck_rcv;
00845                 tcp_ctl = 0x02; /* SYN */
00846                 unreachable = 1;
00847 
00848                 break;
00849 
00850         case SWRAP_CONNECT_ACK:
00851                 if (si->type != SOCK_STREAM) return;
00852 
00853                 src_addr = (const struct sockaddr_in *)si->myname;
00854                 dest_addr = (const struct sockaddr_in *)addr;
00855 
00856                 tcp_seq = si->io.pck_snd;
00857                 tcp_ack = si->io.pck_rcv;
00858                 tcp_ctl = 0x10; /* ACK */
00859 
00860                 break;
00861 
00862         case SWRAP_ACCEPT_SEND:
00863                 if (si->type != SOCK_STREAM) return;
00864 
00865                 dest_addr = (const struct sockaddr_in *)si->myname;
00866                 src_addr = (const struct sockaddr_in *)addr;
00867 
00868                 tcp_seq = si->io.pck_rcv;
00869                 tcp_ack = si->io.pck_snd;
00870                 tcp_ctl = 0x02; /* SYN */
00871 
00872                 si->io.pck_rcv += 1;
00873 
00874                 break;
00875 
00876         case SWRAP_ACCEPT_RECV:
00877                 if (si->type != SOCK_STREAM) return;
00878 
00879                 src_addr = (const struct sockaddr_in *)si->myname;
00880                 dest_addr = (const struct sockaddr_in *)addr;
00881 
00882                 tcp_seq = si->io.pck_snd;
00883                 tcp_ack = si->io.pck_rcv;
00884                 tcp_ctl = 0x12; /* SYN,ACK */
00885 
00886                 si->io.pck_snd += 1;
00887 
00888                 break;
00889 
00890         case SWRAP_ACCEPT_ACK:
00891                 if (si->type != SOCK_STREAM) return;
00892 
00893                 dest_addr = (const struct sockaddr_in *)si->myname;
00894                 src_addr = (const struct sockaddr_in *)addr;
00895 
00896                 tcp_seq = si->io.pck_rcv;
00897                 tcp_ack = si->io.pck_snd;
00898                 tcp_ctl = 0x10; /* ACK */
00899 
00900                 break;
00901 
00902         case SWRAP_SEND:
00903                 src_addr = (const struct sockaddr_in *)si->myname;
00904                 dest_addr = (const struct sockaddr_in *)si->peername;
00905 
00906                 tcp_seq = si->io.pck_snd;
00907                 tcp_ack = si->io.pck_rcv;
00908                 tcp_ctl = 0x18; /* PSH,ACK */
00909 
00910                 si->io.pck_snd += len;
00911 
00912                 break;
00913 
00914         case SWRAP_SEND_RST:
00915                 dest_addr = (const struct sockaddr_in *)si->myname;
00916                 src_addr = (const struct sockaddr_in *)si->peername;
00917 
00918                 if (si->type == SOCK_DGRAM) {
00919                         swrap_dump_packet(si, si->peername,
00920                                           SWRAP_SENDTO_UNREACH,
00921                                           buf, len);
00922                         return;
00923                 }
00924 
00925                 tcp_seq = si->io.pck_rcv;
00926                 tcp_ack = si->io.pck_snd;
00927                 tcp_ctl = 0x14; /** RST,ACK */
00928 
00929                 break;
00930 
00931         case SWRAP_PENDING_RST:
00932                 dest_addr = (const struct sockaddr_in *)si->myname;
00933                 src_addr = (const struct sockaddr_in *)si->peername;
00934 
00935                 if (si->type == SOCK_DGRAM) {
00936                         return;
00937                 }
00938 
00939                 tcp_seq = si->io.pck_rcv;
00940                 tcp_ack = si->io.pck_snd;
00941                 tcp_ctl = 0x14; /* RST,ACK */
00942 
00943                 break;
00944 
00945         case SWRAP_RECV:
00946                 dest_addr = (const struct sockaddr_in *)si->myname;
00947                 src_addr = (const struct sockaddr_in *)si->peername;
00948 
00949                 tcp_seq = si->io.pck_rcv;
00950                 tcp_ack = si->io.pck_snd;
00951                 tcp_ctl = 0x18; /* PSH,ACK */
00952 
00953                 si->io.pck_rcv += len;
00954 
00955                 break;
00956 
00957         case SWRAP_RECV_RST:
00958                 dest_addr = (const struct sockaddr_in *)si->myname;
00959                 src_addr = (const struct sockaddr_in *)si->peername;
00960 
00961                 if (si->type == SOCK_DGRAM) {
00962                         return;
00963                 }
00964 
00965                 tcp_seq = si->io.pck_rcv;
00966                 tcp_ack = si->io.pck_snd;
00967                 tcp_ctl = 0x14; /* RST,ACK */
00968 
00969                 break;
00970 
00971         case SWRAP_SENDTO:
00972                 src_addr = (const struct sockaddr_in *)si->myname;
00973                 dest_addr = (const struct sockaddr_in *)addr;
00974 
00975                 si->io.pck_snd += len;
00976 
00977                 break;
00978 
00979         case SWRAP_SENDTO_UNREACH:
00980                 dest_addr = (const struct sockaddr_in *)si->myname;
00981                 src_addr = (const struct sockaddr_in *)addr;
00982 
00983                 unreachable = 1;
00984 
00985                 break;
00986 
00987         case SWRAP_RECVFROM:
00988                 dest_addr = (const struct sockaddr_in *)si->myname;
00989                 src_addr = (const struct sockaddr_in *)addr;
00990 
00991                 si->io.pck_rcv += len;
00992 
00993                 break;
00994 
00995         case SWRAP_CLOSE_SEND:
00996                 if (si->type != SOCK_STREAM) return;
00997 
00998                 src_addr = (const struct sockaddr_in *)si->myname;
00999                 dest_addr = (const struct sockaddr_in *)si->peername;
01000 
01001                 tcp_seq = si->io.pck_snd;
01002                 tcp_ack = si->io.pck_rcv;
01003                 tcp_ctl = 0x11; /* FIN, ACK */
01004 
01005                 si->io.pck_snd += 1;
01006 
01007                 break;
01008 
01009         case SWRAP_CLOSE_RECV:
01010                 if (si->type != SOCK_STREAM) return;
01011 
01012                 dest_addr = (const struct sockaddr_in *)si->myname;
01013                 src_addr = (const struct sockaddr_in *)si->peername;
01014 
01015                 tcp_seq = si->io.pck_rcv;
01016                 tcp_ack = si->io.pck_snd;
01017                 tcp_ctl = 0x11; /* FIN,ACK */
01018 
01019                 si->io.pck_rcv += 1;
01020 
01021                 break;
01022 
01023         case SWRAP_CLOSE_ACK:
01024                 if (si->type != SOCK_STREAM) return;
01025 
01026                 src_addr = (const struct sockaddr_in *)si->myname;
01027                 dest_addr = (const struct sockaddr_in *)si->peername;
01028 
01029                 tcp_seq = si->io.pck_snd;
01030                 tcp_ack = si->io.pck_rcv;
01031                 tcp_ctl = 0x10; /* ACK */
01032 
01033                 break;
01034         default:
01035                 return;
01036         }
01037 
01038         swrapGetTimeOfDay(&tv);
01039 
01040         packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
01041                                    (const unsigned char *)buf, len,
01042                                    tcp_seq, tcp_ack, tcp_ctl, unreachable,
01043                                    &packet_len);
01044         if (!packet) {
01045                 return;
01046         }
01047 
01048         fd = swrap_get_pcap_fd(file_name);
01049         if (fd != -1) {
01050                 write(fd, packet, packet_len);
01051         }
01052 
01053         free(packet);
01054 }
01055 
01056 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
01057 {
01058         struct socket_info *si;
01059         int fd;
01060 
01061         if (!socket_wrapper_dir()) {
01062                 return real_socket(family, type, protocol);
01063         }
01064 
01065         switch (family) {
01066         case AF_INET:
01067                 break;
01068         case AF_UNIX:
01069                 return real_socket(family, type, protocol);
01070         default:
01071                 errno = EAFNOSUPPORT;
01072                 return -1;
01073         }
01074 
01075         switch (type) {
01076         case SOCK_STREAM:
01077                 break;
01078         case SOCK_DGRAM:
01079                 break;
01080         default:
01081                 errno = EPROTONOSUPPORT;
01082                 return -1;
01083         }
01084 
01085         switch (protocol) {
01086         case 0:
01087                 break;
01088         default:
01089                 errno = EPROTONOSUPPORT;
01090                 return -1;
01091         }
01092 
01093         fd = real_socket(AF_UNIX, type, 0);
01094 
01095         if (fd == -1) return -1;
01096 
01097         si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
01098 
01099         si->family = family;
01100         si->type = type;
01101         si->protocol = protocol;
01102         si->fd = fd;
01103 
01104         SWRAP_DLIST_ADD(sockets, si);
01105 
01106         return si->fd;
01107 }
01108 
01109 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
01110 {
01111         struct socket_info *parent_si, *child_si;
01112         int fd;
01113         struct sockaddr_un un_addr;
01114         socklen_t un_addrlen = sizeof(un_addr);
01115         struct sockaddr_un un_my_addr;
01116         socklen_t un_my_addrlen = sizeof(un_my_addr);
01117         struct sockaddr my_addr;
01118         socklen_t my_addrlen = sizeof(my_addr);
01119         int ret;
01120 
01121         parent_si = find_socket_info(s);
01122         if (!parent_si) {
01123                 return real_accept(s, addr, addrlen);
01124         }
01125 
01126         memset(&un_addr, 0, sizeof(un_addr));
01127         memset(&un_my_addr, 0, sizeof(un_my_addr));
01128         memset(&my_addr, 0, sizeof(my_addr));
01129 
01130         ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
01131         if (ret == -1) return ret;
01132 
01133         fd = ret;
01134 
01135         ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
01136                                        parent_si->family, addr, addrlen);
01137         if (ret == -1) {
01138                 close(fd);
01139                 return ret;
01140         }
01141 
01142         child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
01143         memset(child_si, 0, sizeof(*child_si));
01144 
01145         child_si->fd = fd;
01146         child_si->family = parent_si->family;
01147         child_si->type = parent_si->type;
01148         child_si->protocol = parent_si->protocol;
01149         child_si->bound = 1;
01150         child_si->is_server = 1;
01151 
01152         ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
01153         if (ret == -1) {
01154                 free(child_si);
01155                 close(fd);
01156                 return ret;
01157         }
01158 
01159         ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
01160                                        child_si->family, &my_addr, &my_addrlen);
01161         if (ret == -1) {
01162                 free(child_si);
01163                 close(fd);
01164                 return ret;
01165         }
01166 
01167         child_si->myname_len = my_addrlen;
01168         child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
01169 
01170         child_si->peername_len = *addrlen;
01171         child_si->peername = sockaddr_dup(addr, *addrlen);
01172 
01173         SWRAP_DLIST_ADD(sockets, child_si);
01174 
01175         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
01176         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
01177         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
01178 
01179         return fd;
01180 }
01181 
01182 static int autobind_start_init;
01183 static int autobind_start;
01184 
01185 /* using sendto() or connect() on an unbound socket would give the
01186    recipient no way to reply, as unlike UDP and TCP, a unix domain
01187    socket can't auto-assign emphemeral port numbers, so we need to
01188    assign it here */
01189 static int swrap_auto_bind(struct socket_info *si)
01190 {
01191         struct sockaddr_un un_addr;
01192         struct sockaddr_in in;
01193         int i;
01194         char type;
01195         int ret;
01196         int port;
01197         struct stat st;
01198 
01199         if (autobind_start_init != 1) {
01200                 autobind_start_init = 1;
01201                 autobind_start = getpid();
01202                 autobind_start %= 50000;
01203                 autobind_start += 10000;
01204         }
01205 
01206         un_addr.sun_family = AF_UNIX;
01207 
01208         switch (si->type) {
01209         case SOCK_STREAM:
01210                 type = SOCKET_TYPE_CHAR_TCP;
01211                 break;
01212         case SOCK_DGRAM:
01213                 type = SOCKET_TYPE_CHAR_UDP;
01214                 break;
01215         default:
01216                 errno = ESOCKTNOSUPPORT;
01217                 return -1;
01218         }
01219 
01220         if (autobind_start > 60000) {
01221                 autobind_start = 10000;
01222         }
01223 
01224         for (i=0;i<1000;i++) {
01225                 port = autobind_start + i;
01226                 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), 
01227                          "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
01228                          type, socket_wrapper_default_iface(), port);
01229                 if (stat(un_addr.sun_path, &st) == 0) continue;
01230                 
01231                 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
01232                 if (ret == -1) return ret;
01233 
01234                 si->tmp_path = strdup(un_addr.sun_path);
01235                 si->bound = 1;
01236                 autobind_start = port + 1;
01237                 break;
01238         }
01239         if (i == 1000) {
01240                 errno = ENFILE;
01241                 return -1;
01242         }
01243 
01244         memset(&in, 0, sizeof(in));
01245         in.sin_family = AF_INET;
01246         in.sin_port   = htons(port);
01247         in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
01248         
01249         si->myname_len = sizeof(in);
01250         si->myname = sockaddr_dup(&in, si->myname_len);
01251         return 0;
01252 }
01253 
01254 
01255 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
01256 {
01257         int ret;
01258         struct sockaddr_un un_addr;
01259         struct socket_info *si = find_socket_info(s);
01260 
01261         if (!si) {
01262                 return real_connect(s, serv_addr, addrlen);
01263         }
01264 
01265         if (si->bound == 0) {
01266                 ret = swrap_auto_bind(si);
01267                 if (ret == -1) return -1;
01268         }
01269 
01270         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
01271         if (ret == -1) return -1;
01272 
01273         swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
01274 
01275         ret = real_connect(s, (struct sockaddr *)&un_addr, 
01276                            sizeof(struct sockaddr_un));
01277 
01278         /* to give better errors */
01279         if (ret == -1 && errno == ENOENT) {
01280                 errno = EHOSTUNREACH;
01281         }
01282 
01283         if (ret == 0) {
01284                 si->peername_len = addrlen;
01285                 si->peername = sockaddr_dup(serv_addr, addrlen);
01286 
01287                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
01288                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
01289         } else {
01290                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
01291         }
01292 
01293         return ret;
01294 }
01295 
01296 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
01297 {
01298         int ret;
01299         struct sockaddr_un un_addr;
01300         struct socket_info *si = find_socket_info(s);
01301 
01302         if (!si) {
01303                 return real_bind(s, myaddr, addrlen);
01304         }
01305 
01306         si->myname_len = addrlen;
01307         si->myname = sockaddr_dup(myaddr, addrlen);
01308 
01309         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
01310         if (ret == -1) return -1;
01311 
01312         unlink(un_addr.sun_path);
01313 
01314         ret = real_bind(s, (struct sockaddr *)&un_addr,
01315                         sizeof(struct sockaddr_un));
01316 
01317         if (ret == 0) {
01318                 si->bound = 1;
01319         }
01320 
01321         return ret;
01322 }
01323 
01324 _PUBLIC_ int swrap_listen(int s, int backlog)
01325 {
01326         int ret;
01327         struct socket_info *si = find_socket_info(s);
01328 
01329         if (!si) {
01330                 return real_listen(s, backlog);
01331         }
01332 
01333         ret = real_listen(s, backlog);
01334 
01335         return ret;
01336 }
01337 
01338 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
01339 {
01340         struct socket_info *si = find_socket_info(s);
01341 
01342         if (!si) {
01343                 return real_getpeername(s, name, addrlen);
01344         }
01345 
01346         if (!si->peername)
01347         {
01348                 errno = ENOTCONN;
01349                 return -1;
01350         }
01351 
01352         memcpy(name, si->peername, si->peername_len);
01353         *addrlen = si->peername_len;
01354 
01355         return 0;
01356 }
01357 
01358 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
01359 {
01360         struct socket_info *si = find_socket_info(s);
01361 
01362         if (!si) {
01363                 return real_getsockname(s, name, addrlen);
01364         }
01365 
01366         memcpy(name, si->myname, si->myname_len);
01367         *addrlen = si->myname_len;
01368 
01369         return 0;
01370 }
01371 
01372 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
01373 {
01374         struct socket_info *si = find_socket_info(s);
01375 
01376         if (!si) {
01377                 return real_getsockopt(s, level, optname, optval, optlen);
01378         }
01379 
01380         if (level == SOL_SOCKET) {
01381                 return real_getsockopt(s, level, optname, optval, optlen);
01382         } 
01383 
01384         errno = ENOPROTOOPT;
01385         return -1;
01386 }
01387 
01388 _PUBLIC_ int swrap_setsockopt(int s, int  level,  int  optname,  const  void  *optval, socklen_t optlen)
01389 {
01390         struct socket_info *si = find_socket_info(s);
01391 
01392         if (!si) {
01393                 return real_setsockopt(s, level, optname, optval, optlen);
01394         }
01395 
01396         if (level == SOL_SOCKET) {
01397                 return real_setsockopt(s, level, optname, optval, optlen);
01398         }
01399 
01400         switch (si->family) {
01401         case AF_INET:
01402                 return 0;
01403         default:
01404                 errno = ENOPROTOOPT;
01405                 return -1;
01406         }
01407 }
01408 
01409 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
01410 {
01411         struct sockaddr_un un_addr;
01412         socklen_t un_addrlen = sizeof(un_addr);
01413         int ret;
01414         struct socket_info *si = find_socket_info(s);
01415 
01416         if (!si) {
01417                 return real_recvfrom(s, buf, len, flags, from, fromlen);
01418         }
01419 
01420         /* irix 6.4 forgets to null terminate the sun_path string :-( */
01421         memset(&un_addr, 0, sizeof(un_addr));
01422         ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
01423         if (ret == -1) 
01424                 return ret;
01425 
01426         if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
01427                                      si->family, from, fromlen) == -1) {
01428                 return -1;
01429         }
01430 
01431         swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
01432 
01433         return ret;
01434 }
01435 
01436 
01437 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
01438 {
01439         struct sockaddr_un un_addr;
01440         int ret;
01441         struct socket_info *si = find_socket_info(s);
01442         int bcast = 0;
01443 
01444         if (!si) {
01445                 return real_sendto(s, buf, len, flags, to, tolen);
01446         }
01447 
01448         if (si->bound == 0) {
01449                 ret = swrap_auto_bind(si);
01450                 if (ret == -1) return -1;
01451         }
01452 
01453         ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
01454         if (ret == -1) return -1;
01455 
01456         if (bcast) {
01457                 struct stat st;
01458                 unsigned int iface;
01459                 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
01460                 char type;
01461 
01462                 type = SOCKET_TYPE_CHAR_UDP;
01463 
01464                 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
01465                         snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, 
01466                                  socket_wrapper_dir(), type, iface, prt);
01467                         if (stat(un_addr.sun_path, &st) != 0) continue;
01468 
01469                         /* ignore the any errors in broadcast sends */
01470                         real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
01471                 }
01472 
01473                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
01474 
01475                 return len;
01476         }
01477 
01478         ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
01479 
01480         /* to give better errors */
01481         if (ret == -1 && errno == ENOENT) {
01482                 errno = EHOSTUNREACH;
01483         }
01484 
01485         if (ret == -1) {
01486                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
01487                 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
01488         } else {
01489                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
01490         }
01491 
01492         return ret;
01493 }
01494 
01495 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
01496 {
01497         int ret;
01498         struct socket_info *si = find_socket_info(s);
01499         int value;
01500 
01501         if (!si) {
01502                 return real_ioctl(s, r, p);
01503         }
01504 
01505         ret = real_ioctl(s, r, p);
01506 
01507         switch (r) {
01508         case FIONREAD:
01509                 value = *((int *)p);
01510                 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
01511                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
01512                 } else if (value == 0) { /* END OF FILE */
01513                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
01514                 }
01515                 break;
01516         }
01517 
01518         return ret;
01519 }
01520 
01521 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
01522 {
01523         int ret;
01524         struct socket_info *si = find_socket_info(s);
01525 
01526         if (!si) {
01527                 return real_recv(s, buf, len, flags);
01528         }
01529 
01530         ret = real_recv(s, buf, len, flags);
01531         if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
01532                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
01533         } else if (ret == 0) { /* END OF FILE */
01534                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
01535         } else {
01536                 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
01537         }
01538 
01539         return ret;
01540 }
01541 
01542 
01543 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
01544 {
01545         int ret;
01546         struct socket_info *si = find_socket_info(s);
01547 
01548         if (!si) {
01549                 return real_send(s, buf, len, flags);
01550         }
01551 
01552         ret = real_send(s, buf, len, flags);
01553 
01554         if (ret == -1) {
01555                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
01556                 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
01557         } else {
01558                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
01559         }
01560 
01561         return ret;
01562 }
01563 
01564 _PUBLIC_ int swrap_close(int fd)
01565 {
01566         struct socket_info *si = find_socket_info(fd);
01567         int ret;
01568 
01569         if (!si) {
01570                 return real_close(fd);
01571         }
01572 
01573         SWRAP_DLIST_REMOVE(sockets, si);
01574 
01575         if (si->myname && si->peername) {
01576                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
01577         }
01578 
01579         ret = real_close(fd);
01580 
01581         if (si->myname && si->peername) {
01582                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
01583                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
01584         }
01585 
01586         if (si->path) free(si->path);
01587         if (si->myname) free(si->myname);
01588         if (si->peername) free(si->peername);
01589         if (si->tmp_path) {
01590                 unlink(si->tmp_path);
01591                 free(si->tmp_path);
01592         }
01593         free(si);
01594 
01595         return ret;
01596 }

Sambaに対してSat Aug 29 21:22:59 2009に生成されました。  doxygen 1.4.7