root/lib/socket_wrapper/socket_wrapper.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. swrap_ipv6
  2. sockaddr_dup
  3. set_port
  4. socket_length
  5. socket_wrapper_dir
  6. socket_wrapper_default_iface
  7. convert_un_in
  8. convert_in_un_remote
  9. convert_in_un_alloc
  10. find_socket_info
  11. sockaddr_convert_to_un
  12. sockaddr_convert_from_un
  13. socket_wrapper_pcap_file
  14. swrap_packet_init
  15. swrap_get_pcap_fd
  16. swrap_marshall_packet
  17. swrap_dump_packet
  18. swrap_socket
  19. swrap_accept
  20. swrap_auto_bind
  21. swrap_connect
  22. swrap_bind
  23. swrap_listen
  24. swrap_getpeername
  25. swrap_getsockname
  26. swrap_getsockopt
  27. swrap_setsockopt
  28. swrap_recvfrom
  29. swrap_sendto
  30. swrap_ioctl
  31. swrap_recv
  32. swrap_send
  33. swrap_readv
  34. swrap_writev
  35. swrap_close

   1 /*
   2  * Copyright (C) Jelmer Vernooij 2005,2008 <jelmer@samba.org>
   3  * Copyright (C) Stefan Metzmacher 2006-2009 <metze@samba.org>
   4  *
   5  * All rights reserved.
   6  * 
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  * 
  11  * 1. Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  * 
  14  * 2. Redistributions in binary form must reproduce the above copyright
  15  *    notice, this list of conditions and the following disclaimer in the
  16  *    documentation and/or other materials provided with the distribution.
  17  * 
  18  * 3. Neither the name of the author nor the names of its contributors
  19  *    may be used to endorse or promote products derived from this software
  20  *    without specific prior written permission.
  21  * 
  22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32  * SUCH DAMAGE.
  33  *
  34  */
  35 
  36 /*
  37    Socket wrapper library. Passes all socket communication over
  38    unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
  39    is set.
  40 */
  41 
  42 #ifdef _SAMBA_BUILD_
  43 
  44 #define SOCKET_WRAPPER_NOT_REPLACE
  45 #include "../replace/replace.h"
  46 #include "system/network.h"
  47 #include "system/filesys.h"
  48 #include "system/time.h"
  49 
  50 #else /* _SAMBA_BUILD_ */
  51 
  52 #include <sys/types.h>
  53 #include <sys/time.h>
  54 #include <sys/stat.h>
  55 #include <sys/socket.h>
  56 #include <sys/ioctl.h>
  57 #include <sys/filio.h>
  58 #include <errno.h>
  59 #include <sys/un.h>
  60 #include <netinet/in.h>
  61 #include <netinet/tcp.h>
  62 #include <fcntl.h>
  63 #include <stdlib.h>
  64 #include <unistd.h>
  65 #include <string.h>
  66 #include <stdio.h>
  67 #include <stdint.h>
  68 
  69 #endif
  70 
  71 #ifndef _PUBLIC_
  72 #define _PUBLIC_
  73 #endif
  74 
  75 #define SWRAP_DLIST_ADD(list,item) do { \
  76         if (!(list)) { \
  77                 (item)->prev    = NULL; \
  78                 (item)->next    = NULL; \
  79                 (list)          = (item); \
  80         } else { \
  81                 (item)->prev    = NULL; \
  82                 (item)->next    = (list); \
  83                 (list)->prev    = (item); \
  84                 (list)          = (item); \
  85         } \
  86 } while (0)
  87 
  88 #define SWRAP_DLIST_REMOVE(list,item) do { \
  89         if ((list) == (item)) { \
  90                 (list)          = (item)->next; \
  91                 if (list) { \
  92                         (list)->prev    = NULL; \
  93                 } \
  94         } else { \
  95                 if ((item)->prev) { \
  96                         (item)->prev->next      = (item)->next; \
  97                 } \
  98                 if ((item)->next) { \
  99                         (item)->next->prev      = (item)->prev; \
 100                 } \
 101         } \
 102         (item)->prev    = NULL; \
 103         (item)->next    = NULL; \
 104 } while (0)
 105 
 106 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
 107  * for now */
 108 #define REWRITE_CALLS 
 109 
 110 #ifdef REWRITE_CALLS
 111 #define real_accept accept
 112 #define real_connect connect
 113 #define real_bind bind
 114 #define real_listen listen
 115 #define real_getpeername getpeername
 116 #define real_getsockname getsockname
 117 #define real_getsockopt getsockopt
 118 #define real_setsockopt setsockopt
 119 #define real_recvfrom recvfrom
 120 #define real_sendto sendto
 121 #define real_ioctl ioctl
 122 #define real_recv recv
 123 #define real_send send
 124 #define real_readv readv
 125 #define real_writev writev
 126 #define real_socket socket
 127 #define real_close close
 128 #endif
 129 
 130 #ifdef HAVE_GETTIMEOFDAY_TZ
 131 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
 132 #else
 133 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
 134 #endif
 135 
 136 /* we need to use a very terse format here as IRIX 6.4 silently
 137    truncates names to 16 chars, so if we use a longer name then we
 138    can't tell which port a packet came from with recvfrom() 
 139    
 140    with this format we have 8 chars left for the directory name
 141 */
 142 #define SOCKET_FORMAT "%c%02X%04X"
 143 #define SOCKET_TYPE_CHAR_TCP            'T'
 144 #define SOCKET_TYPE_CHAR_UDP            'U'
 145 #define SOCKET_TYPE_CHAR_TCP_V6         'X'
 146 #define SOCKET_TYPE_CHAR_UDP_V6         'Y'
 147 
 148 #define MAX_WRAPPED_INTERFACES 16
 149 
 150 #ifdef HAVE_IPV6
 151 /*
 152  * FD00::5357:5FXX
 153  */
 154 static const struct in6_addr *swrap_ipv6(void)
     /* [<][>][^][v][top][bottom][index][help] */
 155 {
 156         static struct in6_addr v;
 157         static int initialized;
 158         int ret;
 159 
 160         if (initialized) {
 161                 return &v;
 162         }
 163         initialized = 1;
 164 
 165         ret = inet_pton(AF_INET6, "FD00::5357:5F00", &v);
 166         if (ret <= 0) {
 167                 abort();
 168         }
 169 
 170         return &v;
 171 }
 172 #endif
 173 
 174 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
     /* [<][>][^][v][top][bottom][index][help] */
 175 {
 176         struct sockaddr *ret = (struct sockaddr *)malloc(len);
 177         memcpy(ret, data, len);
 178         return ret;
 179 }
 180 
 181 static void set_port(int family, int prt, struct sockaddr *addr)
     /* [<][>][^][v][top][bottom][index][help] */
 182 {
 183         switch (family) {
 184         case AF_INET:
 185                 ((struct sockaddr_in *)addr)->sin_port = htons(prt);
 186                 break;
 187 #ifdef HAVE_IPV6
 188         case AF_INET6:
 189                 ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt);
 190                 break;
 191 #endif
 192         }
 193 }
 194 
 195 static size_t socket_length(int family)
     /* [<][>][^][v][top][bottom][index][help] */
 196 {
 197         switch (family) {
 198         case AF_INET:
 199                 return sizeof(struct sockaddr_in);
 200 #ifdef HAVE_IPV6
 201         case AF_INET6:
 202                 return sizeof(struct sockaddr_in6);
 203 #endif
 204         }
 205         return 0;
 206 }
 207 
 208 
 209 
 210 struct socket_info
 211 {
 212         int fd;
 213 
 214         int family;
 215         int type;
 216         int protocol;
 217         int bound;
 218         int bcast;
 219         int is_server;
 220         int connected;
 221 
 222         char *path;
 223         char *tmp_path;
 224 
 225         struct sockaddr *myname;
 226         socklen_t myname_len;
 227 
 228         struct sockaddr *peername;
 229         socklen_t peername_len;
 230 
 231         struct {
 232                 unsigned long pck_snd;
 233                 unsigned long pck_rcv;
 234         } io;
 235 
 236         struct socket_info *prev, *next;
 237 };
 238 
 239 static struct socket_info *sockets;
 240 
 241 const char *socket_wrapper_dir(void)
     /* [<][>][^][v][top][bottom][index][help] */
 242 {
 243         const char *s = getenv("SOCKET_WRAPPER_DIR");
 244         if (s == NULL) {
 245                 return NULL;
 246         }
 247         if (strncmp(s, "./", 2) == 0) {
 248                 s += 2;
 249         }
 250         return s;
 251 }
 252 
 253 unsigned int socket_wrapper_default_iface(void)
     /* [<][>][^][v][top][bottom][index][help] */
 254 {
 255         const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
 256         if (s) {
 257                 unsigned int iface;
 258                 if (sscanf(s, "%u", &iface) == 1) {
 259                         if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
 260                                 return iface;
 261                         }
 262                 }
 263         }
 264 
 265         return 1;/* 127.0.0.1 */
 266 }
 267 
 268 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len)
     /* [<][>][^][v][top][bottom][index][help] */
 269 {
 270         unsigned int iface;
 271         unsigned int prt;
 272         const char *p;
 273         char type;
 274 
 275         p = strrchr(un->sun_path, '/');
 276         if (p) p++; else p = un->sun_path;
 277 
 278         if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
 279                 errno = EINVAL;
 280                 return -1;
 281         }
 282 
 283         if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
 284                 errno = EINVAL;
 285                 return -1;
 286         }
 287 
 288         if (prt > 0xFFFF) {
 289                 errno = EINVAL;
 290                 return -1;
 291         }
 292 
 293         switch(type) {
 294         case SOCKET_TYPE_CHAR_TCP:
 295         case SOCKET_TYPE_CHAR_UDP: {
 296                 struct sockaddr_in *in2 = (struct sockaddr_in *)in;
 297                 
 298                 if ((*len) < sizeof(*in2)) {
 299                     errno = EINVAL;
 300                     return -1;
 301                 }
 302 
 303                 memset(in2, 0, sizeof(*in2));
 304                 in2->sin_family = AF_INET;
 305                 in2->sin_addr.s_addr = htonl((127<<24) | iface);
 306                 in2->sin_port = htons(prt);
 307 
 308                 *len = sizeof(*in2);
 309                 break;
 310         }
 311 #ifdef HAVE_IPV6
 312         case SOCKET_TYPE_CHAR_TCP_V6:
 313         case SOCKET_TYPE_CHAR_UDP_V6: {
 314                 struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in;
 315                 
 316                 if ((*len) < sizeof(*in2)) {
 317                         errno = EINVAL;
 318                         return -1;
 319                 }
 320 
 321                 memset(in2, 0, sizeof(*in2));
 322                 in2->sin6_family = AF_INET6;
 323                 in2->sin6_addr = *swrap_ipv6();
 324                 in2->sin6_addr.s6_addr[15] = iface;
 325                 in2->sin6_port = htons(prt);
 326 
 327                 *len = sizeof(*in2);
 328                 break;
 329         }
 330 #endif
 331         default:
 332                 errno = EINVAL;
 333                 return -1;
 334         }
 335 
 336         return 0;
 337 }
 338 
 339 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
     /* [<][>][^][v][top][bottom][index][help] */
 340                                 int *bcast)
 341 {
 342         char type = '\0';
 343         unsigned int prt;
 344         unsigned int iface;
 345         int is_bcast = 0;
 346 
 347         if (bcast) *bcast = 0;
 348 
 349         switch (si->family) {
 350         case AF_INET: {
 351                 const struct sockaddr_in *in = 
 352                     (const struct sockaddr_in *)inaddr;
 353                 unsigned int addr = ntohl(in->sin_addr.s_addr);
 354                 char u_type = '\0';
 355                 char b_type = '\0';
 356                 char a_type = '\0';
 357 
 358                 switch (si->type) {
 359                 case SOCK_STREAM:
 360                         u_type = SOCKET_TYPE_CHAR_TCP;
 361                         break;
 362                 case SOCK_DGRAM:
 363                         u_type = SOCKET_TYPE_CHAR_UDP;
 364                         a_type = SOCKET_TYPE_CHAR_UDP;
 365                         b_type = SOCKET_TYPE_CHAR_UDP;
 366                         break;
 367                 }
 368 
 369                 prt = ntohs(in->sin_port);
 370                 if (a_type && addr == 0xFFFFFFFF) {
 371                         /* 255.255.255.255 only udp */
 372                         is_bcast = 2;
 373                         type = a_type;
 374                         iface = socket_wrapper_default_iface();
 375                 } else if (b_type && addr == 0x7FFFFFFF) {
 376                         /* 127.255.255.255 only udp */
 377                         is_bcast = 1;
 378                         type = b_type;
 379                         iface = socket_wrapper_default_iface();
 380                 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
 381                         /* 127.0.0.X */
 382                         is_bcast = 0;
 383                         type = u_type;
 384                         iface = (addr & 0x000000FF);
 385                 } else {
 386                         errno = ENETUNREACH;
 387                         return -1;
 388                 }
 389                 if (bcast) *bcast = is_bcast;
 390                 break;
 391         }
 392 #ifdef HAVE_IPV6
 393         case AF_INET6: {
 394                 const struct sockaddr_in6 *in = 
 395                     (const struct sockaddr_in6 *)inaddr;
 396                 struct in6_addr cmp;
 397 
 398                 switch (si->type) {
 399                 case SOCK_STREAM:
 400                         type = SOCKET_TYPE_CHAR_TCP_V6;
 401                         break;
 402                 case SOCK_DGRAM:
 403                         type = SOCKET_TYPE_CHAR_UDP_V6;
 404                         break;
 405                 }
 406 
 407                 /* XXX no multicast/broadcast */
 408 
 409                 prt = ntohs(in->sin6_port);
 410 
 411                 cmp = in->sin6_addr;
 412                 cmp.s6_addr[15] = 0;
 413                 if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) {
 414                         iface = in->sin6_addr.s6_addr[15];
 415                 } else {
 416                         errno = ENETUNREACH;
 417                         return -1;
 418                 }
 419 
 420                 break;
 421         }
 422 #endif
 423         default:
 424                 errno = ENETUNREACH;
 425                 return -1;
 426         }
 427 
 428         if (prt == 0) {
 429                 errno = EINVAL;
 430                 return -1;
 431         }
 432 
 433         if (is_bcast) {
 434                 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", 
 435                          socket_wrapper_dir());
 436                 /* the caller need to do more processing */
 437                 return 0;
 438         }
 439 
 440         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
 441                  socket_wrapper_dir(), type, iface, prt);
 442 
 443         return 0;
 444 }
 445 
 446 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un,
     /* [<][>][^][v][top][bottom][index][help] */
 447                                int *bcast)
 448 {
 449         char type = '\0';
 450         unsigned int prt;
 451         unsigned int iface;
 452         struct stat st;
 453         int is_bcast = 0;
 454 
 455         if (bcast) *bcast = 0;
 456 
 457         switch (si->family) {
 458         case AF_INET: {
 459                 const struct sockaddr_in *in = 
 460                     (const struct sockaddr_in *)inaddr;
 461                 unsigned int addr = ntohl(in->sin_addr.s_addr);
 462                 char u_type = '\0';
 463                 char d_type = '\0';
 464                 char b_type = '\0';
 465                 char a_type = '\0';
 466 
 467                 prt = ntohs(in->sin_port);
 468 
 469                 switch (si->type) {
 470                 case SOCK_STREAM:
 471                         u_type = SOCKET_TYPE_CHAR_TCP;
 472                         d_type = SOCKET_TYPE_CHAR_TCP;
 473                         break;
 474                 case SOCK_DGRAM:
 475                         u_type = SOCKET_TYPE_CHAR_UDP;
 476                         d_type = SOCKET_TYPE_CHAR_UDP;
 477                         a_type = SOCKET_TYPE_CHAR_UDP;
 478                         b_type = SOCKET_TYPE_CHAR_UDP;
 479                         break;
 480                 }
 481 
 482                 if (addr == 0) {
 483                         /* 0.0.0.0 */
 484                         is_bcast = 0;
 485                         type = d_type;
 486                         iface = socket_wrapper_default_iface();
 487                 } else if (a_type && addr == 0xFFFFFFFF) {
 488                         /* 255.255.255.255 only udp */
 489                         is_bcast = 2;
 490                         type = a_type;
 491                         iface = socket_wrapper_default_iface();
 492                 } else if (b_type && addr == 0x7FFFFFFF) {
 493                         /* 127.255.255.255 only udp */
 494                         is_bcast = 1;
 495                         type = b_type;
 496                         iface = socket_wrapper_default_iface();
 497                 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
 498                         /* 127.0.0.X */
 499                         is_bcast = 0;
 500                         type = u_type;
 501                         iface = (addr & 0x000000FF);
 502                 } else {
 503                         errno = EADDRNOTAVAIL;
 504                         return -1;
 505                 }
 506                 break;
 507         }
 508 #ifdef HAVE_IPV6
 509         case AF_INET6: {
 510                 const struct sockaddr_in6 *in = 
 511                     (const struct sockaddr_in6 *)inaddr;
 512                 struct in6_addr cmp;
 513 
 514                 switch (si->type) {
 515                 case SOCK_STREAM:
 516                         type = SOCKET_TYPE_CHAR_TCP_V6;
 517                         break;
 518                 case SOCK_DGRAM:
 519                         type = SOCKET_TYPE_CHAR_UDP_V6;
 520                         break;
 521                 }
 522 
 523                 /* XXX no multicast/broadcast */
 524 
 525                 prt = ntohs(in->sin6_port);
 526 
 527                 cmp = in->sin6_addr;
 528                 cmp.s6_addr[15] = 0;
 529                 if (IN6_IS_ADDR_UNSPECIFIED(&in->sin6_addr)) {
 530                         iface = socket_wrapper_default_iface();
 531                 } else if (IN6_ARE_ADDR_EQUAL(swrap_ipv6(), &cmp)) {
 532                         iface = in->sin6_addr.s6_addr[15];
 533                 } else {
 534                         errno = EADDRNOTAVAIL;
 535                         return -1;
 536                 }
 537 
 538                 break;
 539         }
 540 #endif
 541         default:
 542                 errno = EADDRNOTAVAIL;
 543                 return -1;
 544         }
 545 
 546 
 547         if (bcast) *bcast = is_bcast;
 548 
 549         if (prt == 0) {
 550                 /* handle auto-allocation of ephemeral ports */
 551                 for (prt = 5001; prt < 10000; prt++) {
 552                         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
 553                                  socket_wrapper_dir(), type, iface, prt);
 554                         if (stat(un->sun_path, &st) == 0) continue;
 555 
 556                         set_port(si->family, prt, si->myname);
 557                         break;
 558                 }
 559                 if (prt == 10000) {
 560                         errno = ENFILE;
 561                         return -1;
 562                 }
 563         }
 564 
 565         snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 
 566                  socket_wrapper_dir(), type, iface, prt);
 567         return 0;
 568 }
 569 
 570 static struct socket_info *find_socket_info(int fd)
     /* [<][>][^][v][top][bottom][index][help] */
 571 {
 572         struct socket_info *i;
 573         for (i = sockets; i; i = i->next) {
 574                 if (i->fd == fd) 
 575                         return i;
 576         }
 577 
 578         return NULL;
 579 }
 580 
 581 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, 
     /* [<][>][^][v][top][bottom][index][help] */
 582                                   struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
 583 {
 584         if (!out_addr)
 585                 return 0;
 586 
 587         out_addr->sun_family = AF_UNIX;
 588 
 589         switch (in_addr->sa_family) {
 590         case AF_INET:
 591 #ifdef HAVE_IPV6
 592         case AF_INET6:
 593 #endif
 594                 switch (si->type) {
 595                 case SOCK_STREAM:
 596                 case SOCK_DGRAM:
 597                         break;
 598                 default:
 599                         errno = ESOCKTNOSUPPORT;
 600                         return -1;
 601                 }
 602                 if (alloc_sock) {
 603                         return convert_in_un_alloc(si, in_addr, out_addr, bcast);
 604                 } else {
 605                         return convert_in_un_remote(si, in_addr, out_addr, bcast);
 606                 }
 607         default:
 608                 break;
 609         }
 610         
 611         errno = EAFNOSUPPORT;
 612         return -1;
 613 }
 614 
 615 static int sockaddr_convert_from_un(const struct socket_info *si, 
     /* [<][>][^][v][top][bottom][index][help] */
 616                                     const struct sockaddr_un *in_addr, 
 617                                     socklen_t un_addrlen,
 618                                     int family,
 619                                     struct sockaddr *out_addr,
 620                                     socklen_t *out_addrlen)
 621 {
 622         if (out_addr == NULL || out_addrlen == NULL) 
 623                 return 0;
 624 
 625         if (un_addrlen == 0) {
 626                 *out_addrlen = 0;
 627                 return 0;
 628         }
 629 
 630         switch (family) {
 631         case AF_INET:
 632 #ifdef HAVE_IPV6
 633         case AF_INET6:
 634 #endif
 635                 switch (si->type) {
 636                 case SOCK_STREAM:
 637                 case SOCK_DGRAM:
 638                         break;
 639                 default:
 640                         errno = ESOCKTNOSUPPORT;
 641                         return -1;
 642                 }
 643                 return convert_un_in(in_addr, out_addr, out_addrlen);
 644         default:
 645                 break;
 646         }
 647 
 648         errno = EAFNOSUPPORT;
 649         return -1;
 650 }
 651 
 652 enum swrap_packet_type {
 653         SWRAP_CONNECT_SEND,
 654         SWRAP_CONNECT_UNREACH,
 655         SWRAP_CONNECT_RECV,
 656         SWRAP_CONNECT_ACK,
 657         SWRAP_ACCEPT_SEND,
 658         SWRAP_ACCEPT_RECV,
 659         SWRAP_ACCEPT_ACK,
 660         SWRAP_RECVFROM,
 661         SWRAP_SENDTO,
 662         SWRAP_SENDTO_UNREACH,
 663         SWRAP_PENDING_RST,
 664         SWRAP_RECV,
 665         SWRAP_RECV_RST,
 666         SWRAP_SEND,
 667         SWRAP_SEND_RST,
 668         SWRAP_CLOSE_SEND,
 669         SWRAP_CLOSE_RECV,
 670         SWRAP_CLOSE_ACK
 671 };
 672 
 673 struct swrap_file_hdr {
 674         uint32_t        magic;
 675         uint16_t        version_major;
 676         uint16_t        version_minor;
 677         int32_t         timezone;
 678         uint32_t        sigfigs;
 679         uint32_t        frame_max_len;
 680 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
 681         uint32_t        link_type;
 682 };
 683 #define SWRAP_FILE_HDR_SIZE 24
 684 
 685 struct swrap_packet_frame {
 686         uint32_t seconds;
 687         uint32_t micro_seconds;
 688         uint32_t recorded_length;
 689         uint32_t full_length;
 690 };
 691 #define SWRAP_PACKET_FRAME_SIZE 16
 692 
 693 union swrap_packet_ip {
 694         struct {
 695                 uint8_t         ver_hdrlen;
 696                 uint8_t         tos;
 697                 uint16_t        packet_length;
 698                 uint16_t        identification;
 699                 uint8_t         flags;
 700                 uint8_t         fragment;
 701                 uint8_t         ttl;
 702                 uint8_t         protocol;
 703                 uint16_t        hdr_checksum;
 704                 uint32_t        src_addr;
 705                 uint32_t        dest_addr;
 706         } v4;
 707 #define SWRAP_PACKET_IP_V4_SIZE 20
 708         struct {
 709                 uint8_t         ver_prio;
 710                 uint8_t         flow_label_high;
 711                 uint16_t        flow_label_low;
 712                 uint16_t        payload_length;
 713                 uint8_t         next_header;
 714                 uint8_t         hop_limit;
 715                 uint8_t         src_addr[16];
 716                 uint8_t         dest_addr[16];
 717         } v6;
 718 #define SWRAP_PACKET_IP_V6_SIZE 40
 719 };
 720 #define SWRAP_PACKET_IP_SIZE 40
 721 
 722 union swrap_packet_payload {
 723         struct {
 724                 uint16_t        source_port;
 725                 uint16_t        dest_port;
 726                 uint32_t        seq_num;
 727                 uint32_t        ack_num;
 728                 uint8_t         hdr_length;
 729                 uint8_t         control;
 730                 uint16_t        window;
 731                 uint16_t        checksum;
 732                 uint16_t        urg;
 733         } tcp;
 734 #define SWRAP_PACKET_PAYLOAD_TCP_SIZE 20
 735         struct {
 736                 uint16_t        source_port;
 737                 uint16_t        dest_port;
 738                 uint16_t        length;
 739                 uint16_t        checksum;
 740         } udp;
 741 #define SWRAP_PACKET_PAYLOAD_UDP_SIZE 8
 742         struct {
 743                 uint8_t         type;
 744                 uint8_t         code;
 745                 uint16_t        checksum;
 746                 uint32_t        unused;
 747         } icmp4;
 748 #define SWRAP_PACKET_PAYLOAD_ICMP4_SIZE 8
 749         struct {
 750                 uint8_t         type;
 751                 uint8_t         code;
 752                 uint16_t        checksum;
 753                 uint32_t        unused;
 754         } icmp6;
 755 #define SWRAP_PACKET_PAYLOAD_ICMP6_SIZE 8
 756 };
 757 #define SWRAP_PACKET_PAYLOAD_SIZE 20
 758 
 759 #define SWRAP_PACKET_MIN_ALLOC \
 760         (SWRAP_PACKET_FRAME_SIZE + \
 761          SWRAP_PACKET_IP_SIZE + \
 762          SWRAP_PACKET_PAYLOAD_SIZE)
 763 
 764 static const char *socket_wrapper_pcap_file(void)
     /* [<][>][^][v][top][bottom][index][help] */
 765 {
 766         static int initialized = 0;
 767         static const char *s = NULL;
 768         static const struct swrap_file_hdr h;
 769         static const struct swrap_packet_frame f;
 770         static const union swrap_packet_ip i;
 771         static const union swrap_packet_payload p;
 772 
 773         if (initialized == 1) {
 774                 return s;
 775         }
 776         initialized = 1;
 777 
 778         /*
 779          * TODO: don't use the structs use plain buffer offsets
 780          *       and PUSH_U8(), PUSH_U16() and PUSH_U32()
 781          * 
 782          * for now make sure we disable PCAP support
 783          * if the struct has alignment!
 784          */
 785         if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
 786                 return NULL;
 787         }
 788         if (sizeof(f) != SWRAP_PACKET_FRAME_SIZE) {
 789                 return NULL;
 790         }
 791         if (sizeof(i) != SWRAP_PACKET_IP_SIZE) {
 792                 return NULL;
 793         }
 794         if (sizeof(i.v4) != SWRAP_PACKET_IP_V4_SIZE) {
 795                 return NULL;
 796         }
 797         if (sizeof(i.v6) != SWRAP_PACKET_IP_V6_SIZE) {
 798                 return NULL;
 799         }
 800         if (sizeof(p) != SWRAP_PACKET_PAYLOAD_SIZE) {
 801                 return NULL;
 802         }
 803         if (sizeof(p.tcp) != SWRAP_PACKET_PAYLOAD_TCP_SIZE) {
 804                 return NULL;
 805         }
 806         if (sizeof(p.udp) != SWRAP_PACKET_PAYLOAD_UDP_SIZE) {
 807                 return NULL;
 808         }
 809         if (sizeof(p.icmp4) != SWRAP_PACKET_PAYLOAD_ICMP4_SIZE) {
 810                 return NULL;
 811         }
 812         if (sizeof(p.icmp6) != SWRAP_PACKET_PAYLOAD_ICMP6_SIZE) {
 813                 return NULL;
 814         }
 815 
 816         s = getenv("SOCKET_WRAPPER_PCAP_FILE");
 817         if (s == NULL) {
 818                 return NULL;
 819         }
 820         if (strncmp(s, "./", 2) == 0) {
 821                 s += 2;
 822         }
 823         return s;
 824 }
 825 
 826 static uint8_t *swrap_packet_init(struct timeval *tval,
     /* [<][>][^][v][top][bottom][index][help] */
 827                                   const struct sockaddr *src,
 828                                   const struct sockaddr *dest,
 829                                   int socket_type,
 830                                   const uint8_t *payload,
 831                                   size_t payload_len,
 832                                   unsigned long tcp_seqno,
 833                                   unsigned long tcp_ack,
 834                                   unsigned char tcp_ctl,
 835                                   int unreachable,
 836                                   size_t *_packet_len)
 837 {
 838         uint8_t *base;
 839         uint8_t *buf;
 840         struct swrap_packet_frame *frame;
 841         union swrap_packet_ip *ip;
 842         union swrap_packet_payload *pay;
 843         size_t packet_len;
 844         size_t alloc_len;
 845         size_t nonwire_len = sizeof(*frame);
 846         size_t wire_hdr_len = 0;
 847         size_t wire_len = 0;
 848         size_t ip_hdr_len = 0;
 849         size_t icmp_hdr_len = 0;
 850         size_t icmp_truncate_len = 0;
 851         uint8_t protocol = 0, icmp_protocol = 0;
 852         const struct sockaddr_in *src_in = NULL;
 853         const struct sockaddr_in *dest_in = NULL;
 854 #ifdef HAVE_IPV6
 855         const struct sockaddr_in6 *src_in6 = NULL;
 856         const struct sockaddr_in6 *dest_in6 = NULL;
 857 #endif
 858         uint16_t src_port;
 859         uint16_t dest_port;
 860 
 861         switch (src->sa_family) {
 862         case AF_INET:
 863                 src_in = (const struct sockaddr_in *)src;
 864                 dest_in = (const struct sockaddr_in *)dest;
 865                 src_port = src_in->sin_port;
 866                 dest_port = dest_in->sin_port;
 867                 ip_hdr_len = sizeof(ip->v4);
 868                 break;
 869 #ifdef HAVE_IPV6
 870         case AF_INET6:
 871                 src_in6 = (const struct sockaddr_in6 *)src;
 872                 dest_in6 = (const struct sockaddr_in6 *)dest;
 873                 src_port = src_in6->sin6_port;
 874                 dest_port = dest_in6->sin6_port;
 875                 ip_hdr_len = sizeof(ip->v6);
 876                 break;
 877 #endif
 878         default:
 879                 return NULL;
 880         }
 881 
 882         switch (socket_type) {
 883         case SOCK_STREAM:
 884                 protocol = 0x06; /* TCP */
 885                 wire_hdr_len = ip_hdr_len + sizeof(pay->tcp);
 886                 wire_len = wire_hdr_len + payload_len;
 887                 break;
 888 
 889         case SOCK_DGRAM:
 890                 protocol = 0x11; /* UDP */
 891                 wire_hdr_len = ip_hdr_len + sizeof(pay->udp);
 892                 wire_len = wire_hdr_len + payload_len;
 893                 break;
 894 
 895         default:
 896                 return NULL;
 897         }
 898 
 899         if (unreachable) {
 900                 icmp_protocol = protocol;
 901                 switch (src->sa_family) {
 902                 case AF_INET:
 903                         protocol = 0x01; /* ICMPv4 */
 904                         icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp4);
 905                         break;
 906 #ifdef HAVE_IPV6
 907                 case AF_INET6:
 908                         protocol = 0x3A; /* ICMPv6 */
 909                         icmp_hdr_len = ip_hdr_len + sizeof(pay->icmp6);
 910                         break;
 911 #endif
 912                 }
 913                 if (wire_len > 64 ) {
 914                         icmp_truncate_len = wire_len - 64;
 915                 }
 916                 wire_hdr_len += icmp_hdr_len;
 917                 wire_len += icmp_hdr_len;
 918         }
 919 
 920         packet_len = nonwire_len + wire_len;
 921         alloc_len = packet_len;
 922         if (alloc_len < SWRAP_PACKET_MIN_ALLOC) {
 923                 alloc_len = SWRAP_PACKET_MIN_ALLOC;
 924         }
 925 
 926         base = (uint8_t *)malloc(alloc_len);
 927         if (!base) return NULL;
 928 
 929         buf = base;
 930 
 931         frame = (struct swrap_packet_frame *)buf;
 932         frame->seconds          = tval->tv_sec;
 933         frame->micro_seconds    = tval->tv_usec;
 934         frame->recorded_length  = wire_len - icmp_truncate_len;
 935         frame->full_length      = wire_len - icmp_truncate_len;
 936         buf += SWRAP_PACKET_FRAME_SIZE;
 937 
 938         ip = (union swrap_packet_ip *)buf;
 939         switch (src->sa_family) {
 940         case AF_INET:
 941                 ip->v4.ver_hdrlen       = 0x45; /* version 4 and 5 * 32 bit words */
 942                 ip->v4.tos              = 0x00;
 943                 ip->v4.packet_length    = htons(wire_len - icmp_truncate_len);
 944                 ip->v4.identification   = htons(0xFFFF);
 945                 ip->v4.flags            = 0x40; /* BIT 1 set - means don't fraqment */
 946                 ip->v4.fragment         = htons(0x0000);
 947                 ip->v4.ttl              = 0xFF;
 948                 ip->v4.protocol         = protocol;
 949                 ip->v4.hdr_checksum     = htons(0x0000);
 950                 ip->v4.src_addr         = src_in->sin_addr.s_addr;
 951                 ip->v4.dest_addr        = dest_in->sin_addr.s_addr;
 952                 buf += SWRAP_PACKET_IP_V4_SIZE;
 953                 break;
 954 #ifdef HAVE_IPV6
 955         case AF_INET6:
 956                 ip->v6.ver_prio         = 0x60; /* version 4 and 5 * 32 bit words */
 957                 ip->v6.flow_label_high  = 0x00;
 958                 ip->v6.flow_label_low   = 0x0000;
 959                 ip->v6.payload_length   = htons(wire_len - icmp_truncate_len);//TODO
 960                 ip->v6.next_header      = protocol;
 961                 memcpy(ip->v6.src_addr, src_in6->sin6_addr.s6_addr, 16);
 962                 memcpy(ip->v6.dest_addr, dest_in6->sin6_addr.s6_addr, 16);
 963                 buf += SWRAP_PACKET_IP_V6_SIZE;
 964                 break;
 965 #endif
 966         }
 967 
 968         if (unreachable) {
 969                 pay = (union swrap_packet_payload *)buf;
 970                 switch (src->sa_family) {
 971                 case AF_INET:
 972                         pay->icmp4.type         = 0x03; /* destination unreachable */
 973                         pay->icmp4.code         = 0x01; /* host unreachable */
 974                         pay->icmp4.checksum     = htons(0x0000);
 975                         pay->icmp4.unused       = htonl(0x00000000);
 976                         buf += SWRAP_PACKET_PAYLOAD_ICMP4_SIZE;
 977 
 978                         /* set the ip header in the ICMP payload */
 979                         ip = (union swrap_packet_ip *)buf;
 980                         ip->v4.ver_hdrlen       = 0x45; /* version 4 and 5 * 32 bit words */
 981                         ip->v4.tos              = 0x00;
 982                         ip->v4.packet_length    = htons(wire_len - icmp_hdr_len);
 983                         ip->v4.identification   = htons(0xFFFF);
 984                         ip->v4.flags            = 0x40; /* BIT 1 set - means don't fraqment */
 985                         ip->v4.fragment         = htons(0x0000);
 986                         ip->v4.ttl              = 0xFF;
 987                         ip->v4.protocol         = icmp_protocol;
 988                         ip->v4.hdr_checksum     = htons(0x0000);
 989                         ip->v4.src_addr         = dest_in->sin_addr.s_addr;
 990                         ip->v4.dest_addr        = src_in->sin_addr.s_addr;
 991                         buf += SWRAP_PACKET_IP_V4_SIZE;
 992 
 993                         src_port = dest_in->sin_port;
 994                         dest_port = src_in->sin_port;
 995                         break;
 996 #ifdef HAVE_IPV6
 997                 case AF_INET6:
 998                         pay->icmp6.type         = 0x01; /* destination unreachable */
 999                         pay->icmp6.code         = 0x03; /* address unreachable */
1000                         pay->icmp6.checksum     = htons(0x0000);
1001                         pay->icmp6.unused       = htonl(0x00000000);
1002                         buf += SWRAP_PACKET_PAYLOAD_ICMP6_SIZE;
1003 
1004                         /* set the ip header in the ICMP payload */
1005                         ip = (union swrap_packet_ip *)buf;
1006                         ip->v6.ver_prio         = 0x60; /* version 4 and 5 * 32 bit words */
1007                         ip->v6.flow_label_high  = 0x00;
1008                         ip->v6.flow_label_low   = 0x0000;
1009                         ip->v6.payload_length   = htons(wire_len - icmp_truncate_len);//TODO
1010                         ip->v6.next_header      = protocol;
1011                         memcpy(ip->v6.src_addr, dest_in6->sin6_addr.s6_addr, 16);
1012                         memcpy(ip->v6.dest_addr, src_in6->sin6_addr.s6_addr, 16);
1013                         buf += SWRAP_PACKET_IP_V6_SIZE;
1014 
1015                         src_port = dest_in6->sin6_port;
1016                         dest_port = src_in6->sin6_port;
1017                         break;
1018 #endif
1019                 }
1020         }
1021 
1022         pay = (union swrap_packet_payload *)buf;
1023 
1024         switch (socket_type) {
1025         case SOCK_STREAM:
1026                 pay->tcp.source_port    = src_port;
1027                 pay->tcp.dest_port      = dest_port;
1028                 pay->tcp.seq_num        = htonl(tcp_seqno);
1029                 pay->tcp.ack_num        = htonl(tcp_ack);
1030                 pay->tcp.hdr_length     = 0x50; /* 5 * 32 bit words */
1031                 pay->tcp.control        = tcp_ctl;
1032                 pay->tcp.window         = htons(0x7FFF);
1033                 pay->tcp.checksum       = htons(0x0000);
1034                 pay->tcp.urg            = htons(0x0000);
1035                 buf += SWRAP_PACKET_PAYLOAD_TCP_SIZE;
1036 
1037                 break;
1038 
1039         case SOCK_DGRAM:
1040                 pay->udp.source_port    = src_port;
1041                 pay->udp.dest_port      = dest_port;
1042                 pay->udp.length         = htons(8 + payload_len);
1043                 pay->udp.checksum       = htons(0x0000);
1044                 buf += SWRAP_PACKET_PAYLOAD_UDP_SIZE;
1045 
1046                 break;
1047         }
1048 
1049         if (payload && payload_len > 0) {
1050                 memcpy(buf, payload, payload_len);
1051         }
1052 
1053         *_packet_len = packet_len - icmp_truncate_len;
1054         return base;
1055 }
1056 
1057 static int swrap_get_pcap_fd(const char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
1058 {
1059         static int fd = -1;
1060 
1061         if (fd != -1) return fd;
1062 
1063         fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
1064         if (fd != -1) {
1065                 struct swrap_file_hdr file_hdr;
1066                 file_hdr.magic          = 0xA1B2C3D4;
1067                 file_hdr.version_major  = 0x0002;       
1068                 file_hdr.version_minor  = 0x0004;
1069                 file_hdr.timezone       = 0x00000000;
1070                 file_hdr.sigfigs        = 0x00000000;
1071                 file_hdr.frame_max_len  = SWRAP_FRAME_LENGTH_MAX;
1072                 file_hdr.link_type      = 0x0065; /* 101 RAW IP */
1073 
1074                 if (write(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
1075                         close(fd);
1076                         fd = -1;
1077                 }
1078                 return fd;
1079         }
1080 
1081         fd = open(fname, O_WRONLY|O_APPEND, 0644);
1082 
1083         return fd;
1084 }
1085 
1086 static uint8_t *swrap_marshall_packet(struct socket_info *si,
     /* [<][>][^][v][top][bottom][index][help] */
1087                                       const struct sockaddr *addr,
1088                                       enum swrap_packet_type type,
1089                                       const void *buf, size_t len,
1090                                       size_t *packet_len)
1091 {
1092         const struct sockaddr *src_addr;
1093         const struct sockaddr *dest_addr;
1094         unsigned long tcp_seqno = 0;
1095         unsigned long tcp_ack = 0;
1096         unsigned char tcp_ctl = 0;
1097         int unreachable = 0;
1098 
1099         struct timeval tv;
1100 
1101         switch (si->family) {
1102         case AF_INET:
1103                 break;
1104 #ifdef HAVE_IPV6
1105         case AF_INET6:
1106                 break;
1107 #endif
1108         default:
1109                 return NULL;
1110         }
1111 
1112         switch (type) {
1113         case SWRAP_CONNECT_SEND:
1114                 if (si->type != SOCK_STREAM) return NULL;
1115 
1116                 src_addr = si->myname;
1117                 dest_addr = addr;
1118 
1119                 tcp_seqno = si->io.pck_snd;
1120                 tcp_ack = si->io.pck_rcv;
1121                 tcp_ctl = 0x02; /* SYN */
1122 
1123                 si->io.pck_snd += 1;
1124 
1125                 break;
1126 
1127         case SWRAP_CONNECT_RECV:
1128                 if (si->type != SOCK_STREAM) return NULL;
1129 
1130                 dest_addr = si->myname;
1131                 src_addr = addr;
1132 
1133                 tcp_seqno = si->io.pck_rcv;
1134                 tcp_ack = si->io.pck_snd;
1135                 tcp_ctl = 0x12; /** SYN,ACK */
1136 
1137                 si->io.pck_rcv += 1;
1138 
1139                 break;
1140 
1141         case SWRAP_CONNECT_UNREACH:
1142                 if (si->type != SOCK_STREAM) return NULL;
1143 
1144                 dest_addr = si->myname;
1145                 src_addr = addr;
1146 
1147                 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
1148                 tcp_seqno = si->io.pck_snd - 1;
1149                 tcp_ack = si->io.pck_rcv;
1150                 tcp_ctl = 0x02; /* SYN */
1151                 unreachable = 1;
1152 
1153                 break;
1154 
1155         case SWRAP_CONNECT_ACK:
1156                 if (si->type != SOCK_STREAM) return NULL;
1157 
1158                 src_addr = si->myname;
1159                 dest_addr = addr;
1160 
1161                 tcp_seqno = si->io.pck_snd;
1162                 tcp_ack = si->io.pck_rcv;
1163                 tcp_ctl = 0x10; /* ACK */
1164 
1165                 break;
1166 
1167         case SWRAP_ACCEPT_SEND:
1168                 if (si->type != SOCK_STREAM) return NULL;
1169 
1170                 dest_addr = si->myname;
1171                 src_addr = addr;
1172 
1173                 tcp_seqno = si->io.pck_rcv;
1174                 tcp_ack = si->io.pck_snd;
1175                 tcp_ctl = 0x02; /* SYN */
1176 
1177                 si->io.pck_rcv += 1;
1178 
1179                 break;
1180 
1181         case SWRAP_ACCEPT_RECV:
1182                 if (si->type != SOCK_STREAM) return NULL;
1183 
1184                 src_addr = si->myname;
1185                 dest_addr = addr;
1186 
1187                 tcp_seqno = si->io.pck_snd;
1188                 tcp_ack = si->io.pck_rcv;
1189                 tcp_ctl = 0x12; /* SYN,ACK */
1190 
1191                 si->io.pck_snd += 1;
1192 
1193                 break;
1194 
1195         case SWRAP_ACCEPT_ACK:
1196                 if (si->type != SOCK_STREAM) return NULL;
1197 
1198                 dest_addr = si->myname;
1199                 src_addr = addr;
1200 
1201                 tcp_seqno = si->io.pck_rcv;
1202                 tcp_ack = si->io.pck_snd;
1203                 tcp_ctl = 0x10; /* ACK */
1204 
1205                 break;
1206 
1207         case SWRAP_SEND:
1208                 src_addr = si->myname;
1209                 dest_addr = si->peername;
1210 
1211                 tcp_seqno = si->io.pck_snd;
1212                 tcp_ack = si->io.pck_rcv;
1213                 tcp_ctl = 0x18; /* PSH,ACK */
1214 
1215                 si->io.pck_snd += len;
1216 
1217                 break;
1218 
1219         case SWRAP_SEND_RST:
1220                 dest_addr = si->myname;
1221                 src_addr = si->peername;
1222 
1223                 if (si->type == SOCK_DGRAM) {
1224                         return swrap_marshall_packet(si, si->peername,
1225                                           SWRAP_SENDTO_UNREACH,
1226                                           buf, len, packet_len);
1227                 }
1228 
1229                 tcp_seqno = si->io.pck_rcv;
1230                 tcp_ack = si->io.pck_snd;
1231                 tcp_ctl = 0x14; /** RST,ACK */
1232 
1233                 break;
1234 
1235         case SWRAP_PENDING_RST:
1236                 dest_addr = si->myname;
1237                 src_addr = si->peername;
1238 
1239                 if (si->type == SOCK_DGRAM) {
1240                         return NULL;
1241                 }
1242 
1243                 tcp_seqno = si->io.pck_rcv;
1244                 tcp_ack = si->io.pck_snd;
1245                 tcp_ctl = 0x14; /* RST,ACK */
1246 
1247                 break;
1248 
1249         case SWRAP_RECV:
1250                 dest_addr = si->myname;
1251                 src_addr = si->peername;
1252 
1253                 tcp_seqno = si->io.pck_rcv;
1254                 tcp_ack = si->io.pck_snd;
1255                 tcp_ctl = 0x18; /* PSH,ACK */
1256 
1257                 si->io.pck_rcv += len;
1258 
1259                 break;
1260 
1261         case SWRAP_RECV_RST:
1262                 dest_addr = si->myname;
1263                 src_addr = si->peername;
1264 
1265                 if (si->type == SOCK_DGRAM) {
1266                         return NULL;
1267                 }
1268 
1269                 tcp_seqno = si->io.pck_rcv;
1270                 tcp_ack = si->io.pck_snd;
1271                 tcp_ctl = 0x14; /* RST,ACK */
1272 
1273                 break;
1274 
1275         case SWRAP_SENDTO:
1276                 src_addr = si->myname;
1277                 dest_addr = addr;
1278 
1279                 si->io.pck_snd += len;
1280 
1281                 break;
1282 
1283         case SWRAP_SENDTO_UNREACH:
1284                 dest_addr = si->myname;
1285                 src_addr = addr;
1286 
1287                 unreachable = 1;
1288 
1289                 break;
1290 
1291         case SWRAP_RECVFROM:
1292                 dest_addr = si->myname;
1293                 src_addr = addr;
1294 
1295                 si->io.pck_rcv += len;
1296 
1297                 break;
1298 
1299         case SWRAP_CLOSE_SEND:
1300                 if (si->type != SOCK_STREAM) return NULL;
1301 
1302                 src_addr = si->myname;
1303                 dest_addr = si->peername;
1304 
1305                 tcp_seqno = si->io.pck_snd;
1306                 tcp_ack = si->io.pck_rcv;
1307                 tcp_ctl = 0x11; /* FIN, ACK */
1308 
1309                 si->io.pck_snd += 1;
1310 
1311                 break;
1312 
1313         case SWRAP_CLOSE_RECV:
1314                 if (si->type != SOCK_STREAM) return NULL;
1315 
1316                 dest_addr = si->myname;
1317                 src_addr = si->peername;
1318 
1319                 tcp_seqno = si->io.pck_rcv;
1320                 tcp_ack = si->io.pck_snd;
1321                 tcp_ctl = 0x11; /* FIN,ACK */
1322 
1323                 si->io.pck_rcv += 1;
1324 
1325                 break;
1326 
1327         case SWRAP_CLOSE_ACK:
1328                 if (si->type != SOCK_STREAM) return NULL;
1329 
1330                 src_addr = si->myname;
1331                 dest_addr = si->peername;
1332 
1333                 tcp_seqno = si->io.pck_snd;
1334                 tcp_ack = si->io.pck_rcv;
1335                 tcp_ctl = 0x10; /* ACK */
1336 
1337                 break;
1338         default:
1339                 return NULL;
1340         }
1341 
1342         swrapGetTimeOfDay(&tv);
1343 
1344         return swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1345                                  (const uint8_t *)buf, len,
1346                                  tcp_seqno, tcp_ack, tcp_ctl, unreachable,
1347                                  packet_len);
1348 }
1349 
1350 static void swrap_dump_packet(struct socket_info *si,
     /* [<][>][^][v][top][bottom][index][help] */
1351                               const struct sockaddr *addr,
1352                               enum swrap_packet_type type,
1353                               const void *buf, size_t len)
1354 {
1355         const char *file_name;
1356         uint8_t *packet;
1357         size_t packet_len = 0;
1358         int fd;
1359 
1360         file_name = socket_wrapper_pcap_file();
1361         if (!file_name) {
1362                 return;
1363         }
1364 
1365         packet = swrap_marshall_packet(si, addr, type, buf, len, &packet_len);
1366         if (!packet) {
1367                 return;
1368         }
1369 
1370         fd = swrap_get_pcap_fd(file_name);
1371         if (fd != -1) {
1372                 if (write(fd, packet, packet_len) != packet_len) {
1373                         free(packet);
1374                         return;
1375                 }
1376         }
1377 
1378         free(packet);
1379 }
1380 
1381 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
     /* [<][>][^][v][top][bottom][index][help] */
1382 {
1383         struct socket_info *si;
1384         int fd;
1385 
1386         if (!socket_wrapper_dir()) {
1387                 return real_socket(family, type, protocol);
1388         }
1389 
1390         switch (family) {
1391         case AF_INET:
1392 #ifdef HAVE_IPV6
1393         case AF_INET6:
1394 #endif
1395                 break;
1396         case AF_UNIX:
1397                 return real_socket(family, type, protocol);
1398         default:
1399                 errno = EAFNOSUPPORT;
1400                 return -1;
1401         }
1402 
1403         switch (type) {
1404         case SOCK_STREAM:
1405                 break;
1406         case SOCK_DGRAM:
1407                 break;
1408         default:
1409                 errno = EPROTONOSUPPORT;
1410                 return -1;
1411         }
1412 
1413         switch (protocol) {
1414         case 0:
1415                 break;
1416         case 6:
1417                 if (type == SOCK_STREAM) {
1418                         break;
1419                 }
1420                 /*fall through*/
1421         case 17:
1422                 if (type == SOCK_DGRAM) {
1423                         break;
1424                 }
1425                 /*fall through*/
1426         default:
1427                 errno = EPROTONOSUPPORT;
1428                 return -1;
1429         }
1430 
1431         fd = real_socket(AF_UNIX, type, 0);
1432 
1433         if (fd == -1) return -1;
1434 
1435         si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1436 
1437         si->family = family;
1438         si->type = type;
1439         si->protocol = protocol;
1440         si->fd = fd;
1441 
1442         SWRAP_DLIST_ADD(sockets, si);
1443 
1444         return si->fd;
1445 }
1446 
1447 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
     /* [<][>][^][v][top][bottom][index][help] */
1448 {
1449         struct socket_info *parent_si, *child_si;
1450         int fd;
1451         struct sockaddr_un un_addr;
1452         socklen_t un_addrlen = sizeof(un_addr);
1453         struct sockaddr_un un_my_addr;
1454         socklen_t un_my_addrlen = sizeof(un_my_addr);
1455         struct sockaddr *my_addr;
1456         socklen_t my_addrlen, len;
1457         int ret;
1458 
1459         parent_si = find_socket_info(s);
1460         if (!parent_si) {
1461                 return real_accept(s, addr, addrlen);
1462         }
1463 
1464         /* 
1465          * assume out sockaddr have the same size as the in parent
1466          * socket family
1467          */
1468         my_addrlen = socket_length(parent_si->family);
1469         if (my_addrlen <= 0) {
1470                 errno = EINVAL;
1471                 return -1;
1472         }
1473 
1474         my_addr = (struct sockaddr *)malloc(my_addrlen);
1475         if (my_addr == NULL) {
1476                 return -1;
1477         }
1478 
1479         memset(&un_addr, 0, sizeof(un_addr));
1480         memset(&un_my_addr, 0, sizeof(un_my_addr));
1481 
1482         ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1483         if (ret == -1) {
1484                 free(my_addr);
1485                 return ret;
1486         }
1487 
1488         fd = ret;
1489 
1490         len = my_addrlen;
1491         ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1492                                        parent_si->family, my_addr, &len);
1493         if (ret == -1) {
1494                 free(my_addr);
1495                 close(fd);
1496                 return ret;
1497         }
1498 
1499         child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1500         memset(child_si, 0, sizeof(*child_si));
1501 
1502         child_si->fd = fd;
1503         child_si->family = parent_si->family;
1504         child_si->type = parent_si->type;
1505         child_si->protocol = parent_si->protocol;
1506         child_si->bound = 1;
1507         child_si->is_server = 1;
1508         child_si->connected = 1;
1509 
1510         child_si->peername_len = len;
1511         child_si->peername = sockaddr_dup(my_addr, len);
1512 
1513         if (addr != NULL && addrlen != NULL) {
1514             *addrlen = len;
1515             if (*addrlen >= len)
1516                 memcpy(addr, my_addr, len);
1517             *addrlen = 0;
1518         }
1519 
1520         ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1521         if (ret == -1) {
1522                 free(child_si);
1523                 close(fd);
1524                 return ret;
1525         }
1526 
1527         len = my_addrlen;
1528         ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1529                                        child_si->family, my_addr, &len);
1530         if (ret == -1) {
1531                 free(child_si);
1532                 free(my_addr);
1533                 close(fd);
1534                 return ret;
1535         }
1536 
1537         child_si->myname_len = len;
1538         child_si->myname = sockaddr_dup(my_addr, len);
1539         free(my_addr);
1540 
1541         SWRAP_DLIST_ADD(sockets, child_si);
1542 
1543         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1544         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1545         swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1546 
1547         return fd;
1548 }
1549 
1550 static int autobind_start_init;
1551 static int autobind_start;
1552 
1553 /* using sendto() or connect() on an unbound socket would give the
1554    recipient no way to reply, as unlike UDP and TCP, a unix domain
1555    socket can't auto-assign emphemeral port numbers, so we need to
1556    assign it here.
1557    Note: this might change the family from ipv6 to ipv4
1558 */
1559 static int swrap_auto_bind(struct socket_info *si, int family)
     /* [<][>][^][v][top][bottom][index][help] */
1560 {
1561         struct sockaddr_un un_addr;
1562         int i;
1563         char type;
1564         int ret;
1565         int port;
1566         struct stat st;
1567 
1568         if (autobind_start_init != 1) {
1569                 autobind_start_init = 1;
1570                 autobind_start = getpid();
1571                 autobind_start %= 50000;
1572                 autobind_start += 10000;
1573         }
1574 
1575         un_addr.sun_family = AF_UNIX;
1576 
1577         switch (family) {
1578         case AF_INET: {
1579                 struct sockaddr_in in;
1580 
1581                 switch (si->type) {
1582                 case SOCK_STREAM:
1583                         type = SOCKET_TYPE_CHAR_TCP;
1584                         break;
1585                 case SOCK_DGRAM:
1586                         type = SOCKET_TYPE_CHAR_UDP;
1587                         break;
1588                 default:
1589                     errno = ESOCKTNOSUPPORT;
1590                     return -1;
1591                 }
1592 
1593                 memset(&in, 0, sizeof(in));
1594                 in.sin_family = AF_INET;
1595                 in.sin_addr.s_addr = htonl(127<<24 | 
1596                                            socket_wrapper_default_iface());
1597 
1598                 si->myname_len = sizeof(in);
1599                 si->myname = sockaddr_dup(&in, si->myname_len);
1600                 break;
1601         }
1602 #ifdef HAVE_IPV6
1603         case AF_INET6: {
1604                 struct sockaddr_in6 in6;
1605 
1606                 if (si->family != family) {
1607                         errno = ENETUNREACH;
1608                         return -1;
1609                 }
1610 
1611                 switch (si->type) {
1612                 case SOCK_STREAM:
1613                         type = SOCKET_TYPE_CHAR_TCP_V6;
1614                         break;
1615                 case SOCK_DGRAM:
1616                         type = SOCKET_TYPE_CHAR_UDP_V6;
1617                         break;
1618                 default:
1619                         errno = ESOCKTNOSUPPORT;
1620                         return -1;
1621                 }
1622 
1623                 memset(&in6, 0, sizeof(in6));
1624                 in6.sin6_family = AF_INET6;
1625                 in6.sin6_addr = *swrap_ipv6();
1626                 in6.sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
1627                 si->myname_len = sizeof(in6);
1628                 si->myname = sockaddr_dup(&in6, si->myname_len);
1629                 break;
1630         }
1631 #endif
1632         default:
1633                 errno = ESOCKTNOSUPPORT;
1634                 return -1;
1635         }
1636 
1637         if (autobind_start > 60000) {
1638                 autobind_start = 10000;
1639         }
1640 
1641         for (i=0;i<1000;i++) {
1642                 port = autobind_start + i;
1643                 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), 
1644                          "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1645                          type, socket_wrapper_default_iface(), port);
1646                 if (stat(un_addr.sun_path, &st) == 0) continue;
1647                 
1648                 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1649                 if (ret == -1) return ret;
1650 
1651                 si->tmp_path = strdup(un_addr.sun_path);
1652                 si->bound = 1;
1653                 autobind_start = port + 1;
1654                 break;
1655         }
1656         if (i == 1000) {
1657                 errno = ENFILE;
1658                 return -1;
1659         }
1660 
1661         si->family = family;
1662         set_port(si->family, port, si->myname);
1663 
1664         return 0;
1665 }
1666 
1667 
1668 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
     /* [<][>][^][v][top][bottom][index][help] */
1669 {
1670         int ret;
1671         struct sockaddr_un un_addr;
1672         struct socket_info *si = find_socket_info(s);
1673 
1674         if (!si) {
1675                 return real_connect(s, serv_addr, addrlen);
1676         }
1677 
1678         if (si->bound == 0) {
1679                 ret = swrap_auto_bind(si, serv_addr->sa_family);
1680                 if (ret == -1) return -1;
1681         }
1682 
1683         if (si->family != serv_addr->sa_family) {
1684                 errno = EINVAL;
1685                 return -1;
1686         }
1687 
1688         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1689         if (ret == -1) return -1;
1690 
1691         swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1692 
1693         ret = real_connect(s, (struct sockaddr *)&un_addr, 
1694                            sizeof(struct sockaddr_un));
1695 
1696         /* to give better errors */
1697         if (ret == -1 && errno == ENOENT) {
1698                 errno = EHOSTUNREACH;
1699         }
1700 
1701         if (ret == 0) {
1702                 si->peername_len = addrlen;
1703                 si->peername = sockaddr_dup(serv_addr, addrlen);
1704                 si->connected = 1;
1705 
1706                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1707                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1708         } else {
1709                 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1710         }
1711 
1712         return ret;
1713 }
1714 
1715 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
     /* [<][>][^][v][top][bottom][index][help] */
1716 {
1717         int ret;
1718         struct sockaddr_un un_addr;
1719         struct socket_info *si = find_socket_info(s);
1720 
1721         if (!si) {
1722                 return real_bind(s, myaddr, addrlen);
1723         }
1724 
1725         si->myname_len = addrlen;
1726         si->myname = sockaddr_dup(myaddr, addrlen);
1727 
1728         ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1729         if (ret == -1) return -1;
1730 
1731         unlink(un_addr.sun_path);
1732 
1733         ret = real_bind(s, (struct sockaddr *)&un_addr,
1734                         sizeof(struct sockaddr_un));
1735 
1736         if (ret == 0) {
1737                 si->bound = 1;
1738         }
1739 
1740         return ret;
1741 }
1742 
1743 _PUBLIC_ int swrap_listen(int s, int backlog)
     /* [<][>][^][v][top][bottom][index][help] */
1744 {
1745         int ret;
1746         struct socket_info *si = find_socket_info(s);
1747 
1748         if (!si) {
1749                 return real_listen(s, backlog);
1750         }
1751 
1752         ret = real_listen(s, backlog);
1753 
1754         return ret;
1755 }
1756 
1757 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
     /* [<][>][^][v][top][bottom][index][help] */
1758 {
1759         struct socket_info *si = find_socket_info(s);
1760 
1761         if (!si) {
1762                 return real_getpeername(s, name, addrlen);
1763         }
1764 
1765         if (!si->peername)
1766         {
1767                 errno = ENOTCONN;
1768                 return -1;
1769         }
1770 
1771         memcpy(name, si->peername, si->peername_len);
1772         *addrlen = si->peername_len;
1773 
1774         return 0;
1775 }
1776 
1777 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
     /* [<][>][^][v][top][bottom][index][help] */
1778 {
1779         struct socket_info *si = find_socket_info(s);
1780 
1781         if (!si) {
1782                 return real_getsockname(s, name, addrlen);
1783         }
1784 
1785         memcpy(name, si->myname, si->myname_len);
1786         *addrlen = si->myname_len;
1787 
1788         return 0;
1789 }
1790 
1791 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
     /* [<][>][^][v][top][bottom][index][help] */
1792 {
1793         struct socket_info *si = find_socket_info(s);
1794 
1795         if (!si) {
1796                 return real_getsockopt(s, level, optname, optval, optlen);
1797         }
1798 
1799         if (level == SOL_SOCKET) {
1800                 return real_getsockopt(s, level, optname, optval, optlen);
1801         } 
1802 
1803         errno = ENOPROTOOPT;
1804         return -1;
1805 }
1806 
1807 _PUBLIC_ int swrap_setsockopt(int s, int  level,  int  optname,  const  void  *optval, socklen_t optlen)
     /* [<][>][^][v][top][bottom][index][help] */
1808 {
1809         struct socket_info *si = find_socket_info(s);
1810 
1811         if (!si) {
1812                 return real_setsockopt(s, level, optname, optval, optlen);
1813         }
1814 
1815         if (level == SOL_SOCKET) {
1816                 return real_setsockopt(s, level, optname, optval, optlen);
1817         }
1818 
1819         switch (si->family) {
1820         case AF_INET:
1821                 return 0;
1822         default:
1823                 errno = ENOPROTOOPT;
1824                 return -1;
1825         }
1826 }
1827 
1828 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
     /* [<][>][^][v][top][bottom][index][help] */
1829 {
1830         struct sockaddr_un un_addr;
1831         socklen_t un_addrlen = sizeof(un_addr);
1832         int ret;
1833         struct socket_info *si = find_socket_info(s);
1834         struct sockaddr_storage ss;
1835         socklen_t ss_len = sizeof(ss);
1836 
1837         if (!si) {
1838                 return real_recvfrom(s, buf, len, flags, from, fromlen);
1839         }
1840 
1841         if (!from) {
1842                 from = (struct sockaddr *)&ss;
1843                 fromlen = &ss_len;
1844         }
1845 
1846         len = MIN(len, 1500);
1847 
1848         /* irix 6.4 forgets to null terminate the sun_path string :-( */
1849         memset(&un_addr, 0, sizeof(un_addr));
1850         ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1851         if (ret == -1) 
1852                 return ret;
1853 
1854         if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1855                                      si->family, from, fromlen) == -1) {
1856                 return -1;
1857         }
1858 
1859         swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1860 
1861         return ret;
1862 }
1863 
1864 
1865 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
     /* [<][>][^][v][top][bottom][index][help] */
1866 {
1867         struct sockaddr_un un_addr;
1868         int ret;
1869         struct socket_info *si = find_socket_info(s);
1870         int bcast = 0;
1871 
1872         if (!si) {
1873                 return real_sendto(s, buf, len, flags, to, tolen);
1874         }
1875 
1876         if (si->connected) {
1877                 if (to) {
1878                         errno = EISCONN;
1879                         return -1;
1880                 }
1881 
1882                 to = si->peername;
1883                 tolen = si->peername_len;
1884         }
1885 
1886         len = MIN(len, 1500);
1887 
1888         switch (si->type) {
1889         case SOCK_STREAM:
1890                 ret = real_send(s, buf, len, flags);
1891                 break;
1892         case SOCK_DGRAM:
1893                 if (si->bound == 0) {
1894                         ret = swrap_auto_bind(si, si->family);
1895                         if (ret == -1) return -1;
1896                 }
1897                 
1898                 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1899                 if (ret == -1) return -1;
1900                 
1901                 if (bcast) {
1902                         struct stat st;
1903                         unsigned int iface;
1904                         unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1905                         char type;
1906                         
1907                         type = SOCKET_TYPE_CHAR_UDP;
1908                         
1909                         for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1910                                 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, 
1911                                          socket_wrapper_dir(), type, iface, prt);
1912                                 if (stat(un_addr.sun_path, &st) != 0) continue;
1913                                 
1914                                 /* ignore the any errors in broadcast sends */
1915                                 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1916                         }
1917                         
1918                         swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1919                         
1920                         return len;
1921                 }
1922                 
1923                 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1924                 break;
1925         default:
1926                 ret = -1;
1927                 errno = EHOSTUNREACH;
1928                 break;
1929         }
1930                 
1931         /* to give better errors */
1932         if (ret == -1 && errno == ENOENT) {
1933                 errno = EHOSTUNREACH;
1934         }
1935 
1936         if (ret == -1) {
1937                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1938                 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1939         } else {
1940                 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1941         }
1942 
1943         return ret;
1944 }
1945 
1946 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
     /* [<][>][^][v][top][bottom][index][help] */
1947 {
1948         int ret;
1949         struct socket_info *si = find_socket_info(s);
1950         int value;
1951 
1952         if (!si) {
1953                 return real_ioctl(s, r, p);
1954         }
1955 
1956         ret = real_ioctl(s, r, p);
1957 
1958         switch (r) {
1959         case FIONREAD:
1960                 value = *((int *)p);
1961                 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1962                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1963                 } else if (value == 0) { /* END OF FILE */
1964                         swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1965                 }
1966                 break;
1967         }
1968 
1969         return ret;
1970 }
1971 
1972 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
1973 {
1974         int ret;
1975         struct socket_info *si = find_socket_info(s);
1976 
1977         if (!si) {
1978                 return real_recv(s, buf, len, flags);
1979         }
1980 
1981         len = MIN(len, 1500);
1982 
1983         ret = real_recv(s, buf, len, flags);
1984         if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1985                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1986         } else if (ret == 0) { /* END OF FILE */
1987                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1988         } else if (ret > 0) {
1989                 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1990         }
1991 
1992         return ret;
1993 }
1994 
1995 
1996 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
1997 {
1998         int ret;
1999         struct socket_info *si = find_socket_info(s);
2000 
2001         if (!si) {
2002                 return real_send(s, buf, len, flags);
2003         }
2004 
2005         len = MIN(len, 1500);
2006 
2007         ret = real_send(s, buf, len, flags);
2008 
2009         if (ret == -1) {
2010                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
2011                 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2012         } else {
2013                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
2014         }
2015 
2016         return ret;
2017 }
2018 
2019 int swrap_readv(int s, const struct iovec *vector, size_t count)
     /* [<][>][^][v][top][bottom][index][help] */
2020 {
2021         int ret;
2022         struct socket_info *si = find_socket_info(s);
2023         struct iovec v;
2024 
2025         if (!si) {
2026                 return real_readv(s, vector, count);
2027         }
2028 
2029         /* we read 1500 bytes as maximum */
2030         if (count > 0) {
2031                 size_t i, len = 0;
2032 
2033                 for (i=0; i < count; i++) {
2034                         size_t nlen;
2035                         nlen = len + vector[i].iov_len;
2036                         if (nlen > 1500) {
2037                                 break;
2038                         }
2039                 }
2040                 count = i;
2041                 if (count == 0) {
2042                         v = vector[0];
2043                         v.iov_len = MIN(v.iov_len, 1500);
2044                         vector = &v;
2045                         count = 1;
2046                 }
2047         }
2048 
2049         ret = real_readv(s, vector, count);
2050         if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
2051                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2052         } else if (ret == 0) { /* END OF FILE */
2053                 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
2054         } else if (ret > 0) {
2055                 uint8_t *buf;
2056                 off_t ofs = 0;
2057                 size_t i;
2058                 size_t remain = ret;
2059 
2060                 /* we capture it as one single packet */
2061                 buf = (uint8_t *)malloc(ret);
2062                 if (!buf) {
2063                         /* we just not capture the packet */
2064                         errno = 0;
2065                         return ret;
2066                 }
2067 
2068                 for (i=0; i < count; i++) {
2069                         size_t this_time = MIN(remain, vector[i].iov_len);
2070                         memcpy(buf + ofs,
2071                                vector[i].iov_base,
2072                                this_time);
2073                         ofs += this_time;
2074                         remain -= this_time;
2075                 }
2076 
2077                 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
2078                 free(buf);
2079         }
2080 
2081         return ret;
2082 }
2083 
2084 int swrap_writev(int s, const struct iovec *vector, size_t count)
     /* [<][>][^][v][top][bottom][index][help] */
2085 {
2086         int ret;
2087         struct socket_info *si = find_socket_info(s);
2088         struct iovec v;
2089 
2090         if (!si) {
2091                 return real_writev(s, vector, count);
2092         }
2093 
2094         /* we write 1500 bytes as maximum */
2095         if (count > 0) {
2096                 size_t i, len = 0;
2097 
2098                 for (i=0; i < count; i++) {
2099                         size_t nlen;
2100                         nlen = len + vector[i].iov_len;
2101                         if (nlen > 1500) {
2102                                 break;
2103                         }
2104                 }
2105                 count = i;
2106                 if (count == 0) {
2107                         v = vector[0];
2108                         v.iov_len = MIN(v.iov_len, 1500);
2109                         vector = &v;
2110                         count = 1;
2111                 }
2112         }
2113 
2114         ret = real_writev(s, vector, count);
2115         if (ret == -1) {
2116                 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
2117         } else {
2118                 uint8_t *buf;
2119                 off_t ofs = 0;
2120                 size_t i;
2121                 size_t remain = ret;
2122 
2123                 /* we capture it as one single packet */
2124                 buf = (uint8_t *)malloc(ret);
2125                 if (!buf) {
2126                         /* we just not capture the packet */
2127                         errno = 0;
2128                         return ret;
2129                 }
2130 
2131                 for (i=0; i < count; i++) {
2132                         size_t this_time = MIN(remain, vector[i].iov_len);
2133                         memcpy(buf + ofs,
2134                                vector[i].iov_base,
2135                                this_time);
2136                         ofs += this_time;
2137                         remain -= this_time;
2138                 }
2139 
2140                 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
2141                 free(buf);
2142         }
2143 
2144         return ret;
2145 }
2146 
2147 _PUBLIC_ int swrap_close(int fd)
     /* [<][>][^][v][top][bottom][index][help] */
2148 {
2149         struct socket_info *si = find_socket_info(fd);
2150         int ret;
2151 
2152         if (!si) {
2153                 return real_close(fd);
2154         }
2155 
2156         SWRAP_DLIST_REMOVE(sockets, si);
2157 
2158         if (si->myname && si->peername) {
2159                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
2160         }
2161 
2162         ret = real_close(fd);
2163 
2164         if (si->myname && si->peername) {
2165                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
2166                 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
2167         }
2168 
2169         if (si->path) free(si->path);
2170         if (si->myname) free(si->myname);
2171         if (si->peername) free(si->peername);
2172         if (si->tmp_path) {
2173                 unlink(si->tmp_path);
2174                 free(si->tmp_path);
2175         }
2176         free(si);
2177 
2178         return ret;
2179 }

/* [<][>][^][v][top][bottom][index][help] */