r21729: Some more tests
[Samba/ekacnet.git] / source4 / lib / socket_wrapper / socket_wrapper.c
blob3e3d384f85397bb8e6085f3b7faf491275248785
1 /*
2 * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org>
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:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
37 Socket wrapper library. Passes all socket communication over
38 unix domain sockets if the environment variable SOCKET_WRAPPER_DIR
39 is set.
42 #ifdef _SAMBA_BUILD_
44 #define SOCKET_WRAPPER_NOT_REPLACE
45 #include "includes.h"
46 #include "system/network.h"
47 #include "system/filesys.h"
49 #ifdef malloc
50 #undef malloc
51 #endif
52 #ifdef calloc
53 #undef calloc
54 #endif
55 #ifdef strdup
56 #undef strdup
57 #endif
59 #else /* _SAMBA_BUILD_ */
61 #include <sys/types.h>
62 #include <sys/time.h>
63 #include <sys/stat.h>
64 #include <sys/socket.h>
65 #include <sys/ioctl.h>
66 #include <sys/filio.h>
67 #include <errno.h>
68 #include <sys/un.h>
69 #include <netinet/in.h>
70 #include <netinet/tcp.h>
71 #include <fcntl.h>
72 #include <stdlib.h>
73 #include <unistd.h>
74 #include <string.h>
75 #include <stdio.h>
77 #define _PUBLIC_
79 #endif
81 #define SWRAP_DLIST_ADD(list,item) do { \
82 if (!(list)) { \
83 (item)->prev = NULL; \
84 (item)->next = NULL; \
85 (list) = (item); \
86 } else { \
87 (item)->prev = NULL; \
88 (item)->next = (list); \
89 (list)->prev = (item); \
90 (list) = (item); \
91 } \
92 } while (0)
94 #define SWRAP_DLIST_REMOVE(list,item) do { \
95 if ((list) == (item)) { \
96 (list) = (item)->next; \
97 if (list) { \
98 (list)->prev = NULL; \
99 } \
100 } else { \
101 if ((item)->prev) { \
102 (item)->prev->next = (item)->next; \
104 if ((item)->next) { \
105 (item)->next->prev = (item)->prev; \
108 (item)->prev = NULL; \
109 (item)->next = NULL; \
110 } while (0)
112 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
113 * for now */
114 #define REWRITE_CALLS
116 #ifdef REWRITE_CALLS
117 #define real_accept accept
118 #define real_connect connect
119 #define real_bind bind
120 #define real_listen listen
121 #define real_getpeername getpeername
122 #define real_getsockname getsockname
123 #define real_getsockopt getsockopt
124 #define real_setsockopt setsockopt
125 #define real_recvfrom recvfrom
126 #define real_sendto sendto
127 #define real_ioctl ioctl
128 #define real_recv recv
129 #define real_send send
130 #define real_socket socket
131 #define real_close close
132 #endif
134 #ifdef HAVE_GETTIMEOFDAY_TZ
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
136 #else
137 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
138 #endif
140 /* we need to use a very terse format here as IRIX 6.4 silently
141 truncates names to 16 chars, so if we use a longer name then we
142 can't tell which port a packet came from with recvfrom()
144 with this format we have 8 chars left for the directory name
146 #define SOCKET_FORMAT "%c%02X%04X"
147 #define SOCKET_TYPE_CHAR_TCP 'T'
148 #define SOCKET_TYPE_CHAR_UDP 'U'
150 #define MAX_WRAPPED_INTERFACES 16
152 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
154 struct sockaddr *ret = (struct sockaddr *)malloc(len);
155 memcpy(ret, data, len);
156 return ret;
159 struct socket_info
161 int fd;
163 int family;
164 int type;
165 int protocol;
166 int bound;
167 int bcast;
168 int is_server;
170 char *path;
171 char *tmp_path;
173 struct sockaddr *myname;
174 socklen_t myname_len;
176 struct sockaddr *peername;
177 socklen_t peername_len;
179 struct {
180 unsigned long pck_snd;
181 unsigned long pck_rcv;
182 } io;
184 struct socket_info *prev, *next;
187 static struct socket_info *sockets;
190 const char *socket_wrapper_dir(void)
192 const char *s = getenv("SOCKET_WRAPPER_DIR");
193 if (s == NULL) {
194 return NULL;
196 if (strncmp(s, "./", 2) == 0) {
197 s += 2;
199 return s;
202 unsigned int socket_wrapper_default_iface(void)
204 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
205 if (s) {
206 unsigned int iface;
207 iface = atoi(s);
208 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
209 return iface;
213 return 1;/* 127.0.0.1 */
216 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
218 unsigned int iface;
219 unsigned int prt;
220 const char *p;
221 char type;
223 if ((*len) < sizeof(struct sockaddr_in)) {
224 return 0;
227 p = strrchr(un->sun_path, '/');
228 if (p) p++; else p = un->sun_path;
230 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
231 errno = EINVAL;
232 return -1;
235 if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
236 errno = EINVAL;
237 return -1;
240 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
241 errno = EINVAL;
242 return -1;
245 if (prt > 0xFFFF) {
246 errno = EINVAL;
247 return -1;
250 in->sin_family = AF_INET;
251 in->sin_addr.s_addr = htonl((127<<24) | iface);
252 in->sin_port = htons(prt);
254 *len = sizeof(struct sockaddr_in);
255 return 0;
258 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
259 int *bcast)
261 char u_type = '\0';
262 char b_type = '\0';
263 char a_type = '\0';
264 char type = '\0';
265 unsigned int addr= ntohl(in->sin_addr.s_addr);
266 unsigned int prt = ntohs(in->sin_port);
267 unsigned int iface;
268 int is_bcast = 0;
270 if (bcast) *bcast = 0;
272 if (prt == 0) {
273 errno = EINVAL;
274 return -1;
277 switch (si->type) {
278 case SOCK_STREAM:
279 u_type = SOCKET_TYPE_CHAR_TCP;
280 break;
281 case SOCK_DGRAM:
282 u_type = SOCKET_TYPE_CHAR_UDP;
283 a_type = SOCKET_TYPE_CHAR_UDP;
284 b_type = SOCKET_TYPE_CHAR_UDP;
285 break;
288 if (a_type && addr == 0xFFFFFFFF) {
289 /* 255.255.255.255 only udp */
290 is_bcast = 2;
291 type = a_type;
292 iface = socket_wrapper_default_iface();
293 } else if (b_type && addr == 0x7FFFFFFF) {
294 /* 127.255.255.255 only udp */
295 is_bcast = 1;
296 type = b_type;
297 iface = socket_wrapper_default_iface();
298 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
299 /* 127.0.0.X */
300 is_bcast = 0;
301 type = u_type;
302 iface = (addr & 0x000000FF);
303 } else {
304 errno = ENETUNREACH;
305 return -1;
308 if (bcast) *bcast = is_bcast;
310 if (is_bcast) {
311 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
312 socket_wrapper_dir());
313 /* the caller need to do more processing */
314 return 0;
317 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
318 socket_wrapper_dir(), type, iface, prt);
320 return 0;
323 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
324 int *bcast)
326 char u_type = '\0';
327 char d_type = '\0';
328 char b_type = '\0';
329 char a_type = '\0';
330 char type = '\0';
331 unsigned int addr= ntohl(in->sin_addr.s_addr);
332 unsigned int prt = ntohs(in->sin_port);
333 unsigned int iface;
334 struct stat st;
335 int is_bcast = 0;
337 if (bcast) *bcast = 0;
339 switch (si->type) {
340 case SOCK_STREAM:
341 u_type = SOCKET_TYPE_CHAR_TCP;
342 d_type = SOCKET_TYPE_CHAR_TCP;
343 break;
344 case SOCK_DGRAM:
345 u_type = SOCKET_TYPE_CHAR_UDP;
346 d_type = SOCKET_TYPE_CHAR_UDP;
347 a_type = SOCKET_TYPE_CHAR_UDP;
348 b_type = SOCKET_TYPE_CHAR_UDP;
349 break;
352 if (addr == 0) {
353 /* 0.0.0.0 */
354 is_bcast = 0;
355 type = d_type;
356 iface = socket_wrapper_default_iface();
357 } else if (a_type && addr == 0xFFFFFFFF) {
358 /* 255.255.255.255 only udp */
359 is_bcast = 2;
360 type = a_type;
361 iface = socket_wrapper_default_iface();
362 } else if (b_type && addr == 0x7FFFFFFF) {
363 /* 127.255.255.255 only udp */
364 is_bcast = 1;
365 type = b_type;
366 iface = socket_wrapper_default_iface();
367 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
368 /* 127.0.0.X */
369 is_bcast = 0;
370 type = u_type;
371 iface = (addr & 0x000000FF);
372 } else {
373 errno = EADDRNOTAVAIL;
374 return -1;
377 if (bcast) *bcast = is_bcast;
379 if (prt == 0) {
380 /* handle auto-allocation of ephemeral ports */
381 for (prt = 5001; prt < 10000; prt++) {
382 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
383 socket_wrapper_dir(), type, iface, prt);
384 if (stat(un->sun_path, &st) == 0) continue;
386 ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
387 return 0;
389 errno = ENFILE;
390 return -1;
393 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
394 socket_wrapper_dir(), type, iface, prt);
395 return 0;
398 static struct socket_info *find_socket_info(int fd)
400 struct socket_info *i;
401 for (i = sockets; i; i = i->next) {
402 if (i->fd == fd)
403 return i;
406 return NULL;
409 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
410 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
412 if (!out_addr)
413 return 0;
415 out_addr->sun_family = AF_UNIX;
417 switch (in_addr->sa_family) {
418 case AF_INET:
419 switch (si->type) {
420 case SOCK_STREAM:
421 case SOCK_DGRAM:
422 break;
423 default:
424 errno = ESOCKTNOSUPPORT;
425 return -1;
427 if (alloc_sock) {
428 return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
429 } else {
430 return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
432 default:
433 break;
436 errno = EAFNOSUPPORT;
437 return -1;
440 static int sockaddr_convert_from_un(const struct socket_info *si,
441 const struct sockaddr_un *in_addr,
442 socklen_t un_addrlen,
443 int family,
444 struct sockaddr *out_addr,
445 socklen_t *_out_addrlen)
447 socklen_t out_addrlen;
449 if (out_addr == NULL || _out_addrlen == NULL)
450 return 0;
452 if (un_addrlen == 0) {
453 *_out_addrlen = 0;
454 return 0;
457 out_addrlen = *_out_addrlen;
458 if (out_addrlen > un_addrlen) {
459 out_addrlen = un_addrlen;
462 switch (family) {
463 case AF_INET:
464 switch (si->type) {
465 case SOCK_STREAM:
466 case SOCK_DGRAM:
467 break;
468 default:
469 errno = ESOCKTNOSUPPORT;
470 return -1;
472 return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
473 default:
474 break;
477 errno = EAFNOSUPPORT;
478 return -1;
481 enum swrap_packet_type {
482 SWRAP_CONNECT_SEND,
483 SWRAP_CONNECT_UNREACH,
484 SWRAP_CONNECT_RECV,
485 SWRAP_CONNECT_ACK,
486 SWRAP_ACCEPT_SEND,
487 SWRAP_ACCEPT_RECV,
488 SWRAP_ACCEPT_ACK,
489 SWRAP_RECVFROM,
490 SWRAP_SENDTO,
491 SWRAP_SENDTO_UNREACH,
492 SWRAP_PENDING_RST,
493 SWRAP_RECV,
494 SWRAP_RECV_RST,
495 SWRAP_SEND,
496 SWRAP_SEND_RST,
497 SWRAP_CLOSE_SEND,
498 SWRAP_CLOSE_RECV,
499 SWRAP_CLOSE_ACK
502 struct swrap_file_hdr {
503 unsigned long magic;
504 unsigned short version_major;
505 unsigned short version_minor;
506 long timezone;
507 unsigned long sigfigs;
508 unsigned long frame_max_len;
509 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
510 unsigned long link_type;
512 #define SWRAP_FILE_HDR_SIZE 24
514 struct swrap_packet {
515 struct {
516 unsigned long seconds;
517 unsigned long micro_seconds;
518 unsigned long recorded_length;
519 unsigned long full_length;
520 } frame;
521 #define SWRAP_PACKET__FRAME_SIZE 16
523 struct {
524 struct {
525 unsigned char ver_hdrlen;
526 unsigned char tos;
527 unsigned short packet_length;
528 unsigned short identification;
529 unsigned char flags;
530 unsigned char fragment;
531 unsigned char ttl;
532 unsigned char protocol;
533 unsigned short hdr_checksum;
534 unsigned long src_addr;
535 unsigned long dest_addr;
536 } hdr;
537 #define SWRAP_PACKET__IP_HDR_SIZE 20
539 union {
540 struct {
541 unsigned short source_port;
542 unsigned short dest_port;
543 unsigned long seq_num;
544 unsigned long ack_num;
545 unsigned char hdr_length;
546 unsigned char control;
547 unsigned short window;
548 unsigned short checksum;
549 unsigned short urg;
550 } tcp;
551 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
552 struct {
553 unsigned short source_port;
554 unsigned short dest_port;
555 unsigned short length;
556 unsigned short checksum;
557 } udp;
558 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
559 struct {
560 unsigned char type;
561 unsigned char code;
562 unsigned short checksum;
563 unsigned long unused;
564 } icmp;
565 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
566 } p;
567 } ip;
569 #define SWRAP_PACKET_SIZE 56
571 static const char *socket_wrapper_pcap_file(void)
573 static int initialized = 0;
574 static const char *s = NULL;
575 static const struct swrap_file_hdr h;
576 static const struct swrap_packet p;
578 if (initialized == 1) {
579 return s;
581 initialized = 1;
584 * TODO: don't use the structs use plain buffer offsets
585 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
587 * for now make sure we disable PCAP support
588 * if the struct has alignment!
590 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
591 return NULL;
593 if (sizeof(p) != SWRAP_PACKET_SIZE) {
594 return NULL;
596 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
597 return NULL;
599 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
600 return NULL;
602 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
603 return NULL;
605 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
606 return NULL;
608 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
609 return NULL;
612 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
613 if (s == NULL) {
614 return NULL;
616 if (strncmp(s, "./", 2) == 0) {
617 s += 2;
619 return s;
622 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
623 const struct sockaddr_in *src_addr,
624 const struct sockaddr_in *dest_addr,
625 int socket_type,
626 const unsigned char *payload,
627 size_t payload_len,
628 unsigned long tcp_seq,
629 unsigned long tcp_ack,
630 unsigned char tcp_ctl,
631 int unreachable,
632 size_t *_packet_len)
634 struct swrap_packet *ret;
635 struct swrap_packet *packet;
636 size_t packet_len;
637 size_t alloc_len;
638 size_t nonwire_len = sizeof(packet->frame);
639 size_t wire_hdr_len = 0;
640 size_t wire_len = 0;
641 size_t icmp_hdr_len = 0;
642 size_t icmp_truncate_len = 0;
643 unsigned char protocol = 0, icmp_protocol = 0;
644 unsigned short src_port = src_addr->sin_port;
645 unsigned short dest_port = dest_addr->sin_port;
647 switch (socket_type) {
648 case SOCK_STREAM:
649 protocol = 0x06; /* TCP */
650 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
651 wire_len = wire_hdr_len + payload_len;
652 break;
654 case SOCK_DGRAM:
655 protocol = 0x11; /* UDP */
656 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
657 wire_len = wire_hdr_len + payload_len;
658 break;
661 if (unreachable) {
662 icmp_protocol = protocol;
663 protocol = 0x01; /* ICMP */
664 if (wire_len > 64 ) {
665 icmp_truncate_len = wire_len - 64;
667 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
668 wire_hdr_len += icmp_hdr_len;
669 wire_len += icmp_hdr_len;
672 packet_len = nonwire_len + wire_len;
673 alloc_len = packet_len;
674 if (alloc_len < sizeof(struct swrap_packet)) {
675 alloc_len = sizeof(struct swrap_packet);
677 ret = (struct swrap_packet *)malloc(alloc_len);
678 if (!ret) return NULL;
680 packet = ret;
682 packet->frame.seconds = tval->tv_sec;
683 packet->frame.micro_seconds = tval->tv_usec;
684 packet->frame.recorded_length = wire_len - icmp_truncate_len;
685 packet->frame.full_length = wire_len - icmp_truncate_len;
687 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
688 packet->ip.hdr.tos = 0x00;
689 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
690 packet->ip.hdr.identification = htons(0xFFFF);
691 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
692 packet->ip.hdr.fragment = htons(0x0000);
693 packet->ip.hdr.ttl = 0xFF;
694 packet->ip.hdr.protocol = protocol;
695 packet->ip.hdr.hdr_checksum = htons(0x0000);
696 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
697 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
699 if (unreachable) {
700 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
701 packet->ip.p.icmp.code = 0x01; /* host unreachable */
702 packet->ip.p.icmp.checksum = htons(0x0000);
703 packet->ip.p.icmp.unused = htonl(0x00000000);
705 /* set the ip header in the ICMP payload */
706 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
707 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
708 packet->ip.hdr.tos = 0x00;
709 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
710 packet->ip.hdr.identification = htons(0xFFFF);
711 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
712 packet->ip.hdr.fragment = htons(0x0000);
713 packet->ip.hdr.ttl = 0xFF;
714 packet->ip.hdr.protocol = icmp_protocol;
715 packet->ip.hdr.hdr_checksum = htons(0x0000);
716 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
717 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
719 src_port = dest_addr->sin_port;
720 dest_port = src_addr->sin_port;
723 switch (socket_type) {
724 case SOCK_STREAM:
725 packet->ip.p.tcp.source_port = src_port;
726 packet->ip.p.tcp.dest_port = dest_port;
727 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
728 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
729 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
730 packet->ip.p.tcp.control = tcp_ctl;
731 packet->ip.p.tcp.window = htons(0x7FFF);
732 packet->ip.p.tcp.checksum = htons(0x0000);
733 packet->ip.p.tcp.urg = htons(0x0000);
735 break;
737 case SOCK_DGRAM:
738 packet->ip.p.udp.source_port = src_addr->sin_port;
739 packet->ip.p.udp.dest_port = dest_addr->sin_port;
740 packet->ip.p.udp.length = htons(8 + payload_len);
741 packet->ip.p.udp.checksum = htons(0x0000);
743 break;
746 if (payload && payload_len > 0) {
747 unsigned char *p = (unsigned char *)ret;
748 p += nonwire_len;
749 p += wire_hdr_len;
750 memcpy(p, payload, payload_len);
753 *_packet_len = packet_len - icmp_truncate_len;
754 return ret;
757 static int swrap_get_pcap_fd(const char *fname)
759 static int fd = -1;
761 if (fd != -1) return fd;
763 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
764 if (fd != -1) {
765 struct swrap_file_hdr file_hdr;
766 file_hdr.magic = 0xA1B2C3D4;
767 file_hdr.version_major = 0x0002;
768 file_hdr.version_minor = 0x0004;
769 file_hdr.timezone = 0x00000000;
770 file_hdr.sigfigs = 0x00000000;
771 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
772 file_hdr.link_type = 0x0065; /* 101 RAW IP */
774 write(fd, &file_hdr, sizeof(file_hdr));
775 return fd;
778 fd = open(fname, O_WRONLY|O_APPEND, 0644);
780 return fd;
783 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
784 enum swrap_packet_type type,
785 const void *buf, size_t len)
787 const struct sockaddr_in *src_addr;
788 const struct sockaddr_in *dest_addr;
789 const char *file_name;
790 unsigned long tcp_seq = 0;
791 unsigned long tcp_ack = 0;
792 unsigned char tcp_ctl = 0;
793 int unreachable = 0;
794 struct timeval tv;
795 struct swrap_packet *packet;
796 size_t packet_len = 0;
797 int fd;
799 file_name = socket_wrapper_pcap_file();
800 if (!file_name) {
801 return;
804 if (si->family != AF_INET) {
805 return;
808 switch (type) {
809 case SWRAP_CONNECT_SEND:
810 if (si->type != SOCK_STREAM) return;
812 src_addr = (const struct sockaddr_in *)si->myname;
813 dest_addr = (const struct sockaddr_in *)addr;
815 tcp_seq = si->io.pck_snd;
816 tcp_ack = si->io.pck_rcv;
817 tcp_ctl = 0x02; /* SYN */
819 si->io.pck_snd += 1;
821 break;
823 case SWRAP_CONNECT_RECV:
824 if (si->type != SOCK_STREAM) return;
826 dest_addr = (const struct sockaddr_in *)si->myname;
827 src_addr = (const struct sockaddr_in *)addr;
829 tcp_seq = si->io.pck_rcv;
830 tcp_ack = si->io.pck_snd;
831 tcp_ctl = 0x12; /** SYN,ACK */
833 si->io.pck_rcv += 1;
835 break;
837 case SWRAP_CONNECT_UNREACH:
838 if (si->type != SOCK_STREAM) return;
840 dest_addr = (const struct sockaddr_in *)si->myname;
841 src_addr = (const struct sockaddr_in *)addr;
843 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
844 tcp_seq = si->io.pck_snd - 1;
845 tcp_ack = si->io.pck_rcv;
846 tcp_ctl = 0x02; /* SYN */
847 unreachable = 1;
849 break;
851 case SWRAP_CONNECT_ACK:
852 if (si->type != SOCK_STREAM) return;
854 src_addr = (const struct sockaddr_in *)si->myname;
855 dest_addr = (const struct sockaddr_in *)addr;
857 tcp_seq = si->io.pck_snd;
858 tcp_ack = si->io.pck_rcv;
859 tcp_ctl = 0x10; /* ACK */
861 break;
863 case SWRAP_ACCEPT_SEND:
864 if (si->type != SOCK_STREAM) return;
866 dest_addr = (const struct sockaddr_in *)si->myname;
867 src_addr = (const struct sockaddr_in *)addr;
869 tcp_seq = si->io.pck_rcv;
870 tcp_ack = si->io.pck_snd;
871 tcp_ctl = 0x02; /* SYN */
873 si->io.pck_rcv += 1;
875 break;
877 case SWRAP_ACCEPT_RECV:
878 if (si->type != SOCK_STREAM) return;
880 src_addr = (const struct sockaddr_in *)si->myname;
881 dest_addr = (const struct sockaddr_in *)addr;
883 tcp_seq = si->io.pck_snd;
884 tcp_ack = si->io.pck_rcv;
885 tcp_ctl = 0x12; /* SYN,ACK */
887 si->io.pck_snd += 1;
889 break;
891 case SWRAP_ACCEPT_ACK:
892 if (si->type != SOCK_STREAM) return;
894 dest_addr = (const struct sockaddr_in *)si->myname;
895 src_addr = (const struct sockaddr_in *)addr;
897 tcp_seq = si->io.pck_rcv;
898 tcp_ack = si->io.pck_snd;
899 tcp_ctl = 0x10; /* ACK */
901 break;
903 case SWRAP_SEND:
904 src_addr = (const struct sockaddr_in *)si->myname;
905 dest_addr = (const struct sockaddr_in *)si->peername;
907 tcp_seq = si->io.pck_snd;
908 tcp_ack = si->io.pck_rcv;
909 tcp_ctl = 0x18; /* PSH,ACK */
911 si->io.pck_snd += len;
913 break;
915 case SWRAP_SEND_RST:
916 dest_addr = (const struct sockaddr_in *)si->myname;
917 src_addr = (const struct sockaddr_in *)si->peername;
919 if (si->type == SOCK_DGRAM) {
920 swrap_dump_packet(si, si->peername,
921 SWRAP_SENDTO_UNREACH,
922 buf, len);
923 return;
926 tcp_seq = si->io.pck_rcv;
927 tcp_ack = si->io.pck_snd;
928 tcp_ctl = 0x14; /** RST,ACK */
930 break;
932 case SWRAP_PENDING_RST:
933 dest_addr = (const struct sockaddr_in *)si->myname;
934 src_addr = (const struct sockaddr_in *)si->peername;
936 if (si->type == SOCK_DGRAM) {
937 return;
940 tcp_seq = si->io.pck_rcv;
941 tcp_ack = si->io.pck_snd;
942 tcp_ctl = 0x14; /* RST,ACK */
944 break;
946 case SWRAP_RECV:
947 dest_addr = (const struct sockaddr_in *)si->myname;
948 src_addr = (const struct sockaddr_in *)si->peername;
950 tcp_seq = si->io.pck_rcv;
951 tcp_ack = si->io.pck_snd;
952 tcp_ctl = 0x18; /* PSH,ACK */
954 si->io.pck_rcv += len;
956 break;
958 case SWRAP_RECV_RST:
959 dest_addr = (const struct sockaddr_in *)si->myname;
960 src_addr = (const struct sockaddr_in *)si->peername;
962 if (si->type == SOCK_DGRAM) {
963 return;
966 tcp_seq = si->io.pck_rcv;
967 tcp_ack = si->io.pck_snd;
968 tcp_ctl = 0x14; /* RST,ACK */
970 break;
972 case SWRAP_SENDTO:
973 src_addr = (const struct sockaddr_in *)si->myname;
974 dest_addr = (const struct sockaddr_in *)addr;
976 si->io.pck_snd += len;
978 break;
980 case SWRAP_SENDTO_UNREACH:
981 dest_addr = (const struct sockaddr_in *)si->myname;
982 src_addr = (const struct sockaddr_in *)addr;
984 unreachable = 1;
986 break;
988 case SWRAP_RECVFROM:
989 dest_addr = (const struct sockaddr_in *)si->myname;
990 src_addr = (const struct sockaddr_in *)addr;
992 si->io.pck_rcv += len;
994 break;
996 case SWRAP_CLOSE_SEND:
997 if (si->type != SOCK_STREAM) return;
999 src_addr = (const struct sockaddr_in *)si->myname;
1000 dest_addr = (const struct sockaddr_in *)si->peername;
1002 tcp_seq = si->io.pck_snd;
1003 tcp_ack = si->io.pck_rcv;
1004 tcp_ctl = 0x11; /* FIN, ACK */
1006 si->io.pck_snd += 1;
1008 break;
1010 case SWRAP_CLOSE_RECV:
1011 if (si->type != SOCK_STREAM) return;
1013 dest_addr = (const struct sockaddr_in *)si->myname;
1014 src_addr = (const struct sockaddr_in *)si->peername;
1016 tcp_seq = si->io.pck_rcv;
1017 tcp_ack = si->io.pck_snd;
1018 tcp_ctl = 0x11; /* FIN,ACK */
1020 si->io.pck_rcv += 1;
1022 break;
1024 case SWRAP_CLOSE_ACK:
1025 if (si->type != SOCK_STREAM) return;
1027 src_addr = (const struct sockaddr_in *)si->myname;
1028 dest_addr = (const struct sockaddr_in *)si->peername;
1030 tcp_seq = si->io.pck_snd;
1031 tcp_ack = si->io.pck_rcv;
1032 tcp_ctl = 0x10; /* ACK */
1034 break;
1035 default:
1036 return;
1039 swrapGetTimeOfDay(&tv);
1041 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1042 (const unsigned char *)buf, len,
1043 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1044 &packet_len);
1045 if (!packet) {
1046 return;
1049 fd = swrap_get_pcap_fd(file_name);
1050 if (fd != -1) {
1051 write(fd, packet, packet_len);
1054 free(packet);
1057 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1059 struct socket_info *si;
1060 int fd;
1062 if (!socket_wrapper_dir()) {
1063 return real_socket(family, type, protocol);
1066 switch (family) {
1067 case AF_INET:
1068 break;
1069 case AF_UNIX:
1070 return real_socket(family, type, protocol);
1071 default:
1072 errno = EAFNOSUPPORT;
1073 return -1;
1076 switch (type) {
1077 case SOCK_STREAM:
1078 break;
1079 case SOCK_DGRAM:
1080 break;
1081 default:
1082 errno = EPROTONOSUPPORT;
1083 return -1;
1086 switch (protocol) {
1087 case 0:
1088 break;
1089 default:
1090 errno = EPROTONOSUPPORT;
1091 return -1;
1094 fd = real_socket(AF_UNIX, type, 0);
1096 if (fd == -1) return -1;
1098 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1100 si->family = family;
1101 si->type = type;
1102 si->protocol = protocol;
1103 si->fd = fd;
1105 SWRAP_DLIST_ADD(sockets, si);
1107 return si->fd;
1110 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1112 struct socket_info *parent_si, *child_si;
1113 int fd;
1114 struct sockaddr_un un_addr;
1115 socklen_t un_addrlen = sizeof(un_addr);
1116 struct sockaddr_un un_my_addr;
1117 socklen_t un_my_addrlen = sizeof(un_my_addr);
1118 struct sockaddr my_addr;
1119 socklen_t my_addrlen = sizeof(my_addr);
1120 int ret;
1122 parent_si = find_socket_info(s);
1123 if (!parent_si) {
1124 return real_accept(s, addr, addrlen);
1127 memset(&un_addr, 0, sizeof(un_addr));
1128 memset(&un_my_addr, 0, sizeof(un_my_addr));
1129 memset(&my_addr, 0, sizeof(my_addr));
1131 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1132 if (ret == -1) return ret;
1134 fd = ret;
1136 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1137 parent_si->family, addr, addrlen);
1138 if (ret == -1) {
1139 close(fd);
1140 return ret;
1143 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1144 memset(child_si, 0, sizeof(*child_si));
1146 child_si->fd = fd;
1147 child_si->family = parent_si->family;
1148 child_si->type = parent_si->type;
1149 child_si->protocol = parent_si->protocol;
1150 child_si->bound = 1;
1151 child_si->is_server = 1;
1153 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1154 if (ret == -1) {
1155 free(child_si);
1156 close(fd);
1157 return ret;
1160 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1161 child_si->family, &my_addr, &my_addrlen);
1162 if (ret == -1) {
1163 free(child_si);
1164 close(fd);
1165 return ret;
1168 child_si->myname_len = my_addrlen;
1169 child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
1171 child_si->peername_len = *addrlen;
1172 child_si->peername = sockaddr_dup(addr, *addrlen);
1174 SWRAP_DLIST_ADD(sockets, child_si);
1176 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1177 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1178 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1180 return fd;
1183 static int autobind_start_init;
1184 static int autobind_start;
1186 /* using sendto() or connect() on an unbound socket would give the
1187 recipient no way to reply, as unlike UDP and TCP, a unix domain
1188 socket can't auto-assign emphemeral port numbers, so we need to
1189 assign it here */
1190 static int swrap_auto_bind(struct socket_info *si)
1192 struct sockaddr_un un_addr;
1193 struct sockaddr_in in;
1194 int i;
1195 char type;
1196 int ret;
1197 int port;
1198 struct stat st;
1200 if (autobind_start_init != 1) {
1201 autobind_start_init = 1;
1202 autobind_start = getpid();
1203 autobind_start %= 50000;
1204 autobind_start += 10000;
1207 un_addr.sun_family = AF_UNIX;
1209 switch (si->type) {
1210 case SOCK_STREAM:
1211 type = SOCKET_TYPE_CHAR_TCP;
1212 break;
1213 case SOCK_DGRAM:
1214 type = SOCKET_TYPE_CHAR_UDP;
1215 break;
1216 default:
1217 errno = ESOCKTNOSUPPORT;
1218 return -1;
1221 if (autobind_start > 60000) {
1222 autobind_start = 10000;
1225 for (i=0;i<1000;i++) {
1226 port = autobind_start + i;
1227 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1228 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1229 type, socket_wrapper_default_iface(), port);
1230 if (stat(un_addr.sun_path, &st) == 0) continue;
1232 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1233 if (ret == -1) return ret;
1235 si->tmp_path = strdup(un_addr.sun_path);
1236 si->bound = 1;
1237 autobind_start = port + 1;
1238 break;
1240 if (i == 1000) {
1241 errno = ENFILE;
1242 return -1;
1245 memset(&in, 0, sizeof(in));
1246 in.sin_family = AF_INET;
1247 in.sin_port = htons(port);
1248 in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
1250 si->myname_len = sizeof(in);
1251 si->myname = sockaddr_dup(&in, si->myname_len);
1252 return 0;
1256 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1258 int ret;
1259 struct sockaddr_un un_addr;
1260 struct socket_info *si = find_socket_info(s);
1262 if (!si) {
1263 return real_connect(s, serv_addr, addrlen);
1266 if (si->bound == 0) {
1267 ret = swrap_auto_bind(si);
1268 if (ret == -1) return -1;
1271 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1272 if (ret == -1) return -1;
1274 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1276 ret = real_connect(s, (struct sockaddr *)&un_addr,
1277 sizeof(struct sockaddr_un));
1279 /* to give better errors */
1280 if (ret == -1 && errno == ENOENT) {
1281 errno = EHOSTUNREACH;
1284 if (ret == 0) {
1285 si->peername_len = addrlen;
1286 si->peername = sockaddr_dup(serv_addr, addrlen);
1288 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1289 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1290 } else {
1291 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1294 return ret;
1297 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1299 int ret;
1300 struct sockaddr_un un_addr;
1301 struct socket_info *si = find_socket_info(s);
1303 if (!si) {
1304 return real_bind(s, myaddr, addrlen);
1307 si->myname_len = addrlen;
1308 si->myname = sockaddr_dup(myaddr, addrlen);
1310 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1311 if (ret == -1) return -1;
1313 unlink(un_addr.sun_path);
1315 ret = real_bind(s, (struct sockaddr *)&un_addr,
1316 sizeof(struct sockaddr_un));
1318 if (ret == 0) {
1319 si->bound = 1;
1322 return ret;
1325 _PUBLIC_ int swrap_listen(int s, int backlog)
1327 int ret;
1328 struct socket_info *si = find_socket_info(s);
1330 if (!si) {
1331 return real_listen(s, backlog);
1334 ret = real_listen(s, backlog);
1336 return ret;
1339 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1341 struct socket_info *si = find_socket_info(s);
1343 if (!si) {
1344 return real_getpeername(s, name, addrlen);
1347 if (!si->peername)
1349 errno = ENOTCONN;
1350 return -1;
1353 memcpy(name, si->peername, si->peername_len);
1354 *addrlen = si->peername_len;
1356 return 0;
1359 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1361 struct socket_info *si = find_socket_info(s);
1363 if (!si) {
1364 return real_getsockname(s, name, addrlen);
1367 memcpy(name, si->myname, si->myname_len);
1368 *addrlen = si->myname_len;
1370 return 0;
1373 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1375 struct socket_info *si = find_socket_info(s);
1377 if (!si) {
1378 return real_getsockopt(s, level, optname, optval, optlen);
1381 if (level == SOL_SOCKET) {
1382 return real_getsockopt(s, level, optname, optval, optlen);
1385 errno = ENOPROTOOPT;
1386 return -1;
1389 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1391 struct socket_info *si = find_socket_info(s);
1393 if (!si) {
1394 return real_setsockopt(s, level, optname, optval, optlen);
1397 if (level == SOL_SOCKET) {
1398 return real_setsockopt(s, level, optname, optval, optlen);
1401 switch (si->family) {
1402 case AF_INET:
1403 return 0;
1404 default:
1405 errno = ENOPROTOOPT;
1406 return -1;
1410 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1412 struct sockaddr_un un_addr;
1413 socklen_t un_addrlen = sizeof(un_addr);
1414 int ret;
1415 struct socket_info *si = find_socket_info(s);
1417 if (!si) {
1418 return real_recvfrom(s, buf, len, flags, from, fromlen);
1421 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1422 memset(&un_addr, 0, sizeof(un_addr));
1423 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1424 if (ret == -1)
1425 return ret;
1427 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1428 si->family, from, fromlen) == -1) {
1429 return -1;
1432 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1434 return ret;
1438 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1440 struct sockaddr_un un_addr;
1441 int ret;
1442 struct socket_info *si = find_socket_info(s);
1443 int bcast = 0;
1445 if (!si) {
1446 return real_sendto(s, buf, len, flags, to, tolen);
1449 if (si->bound == 0) {
1450 ret = swrap_auto_bind(si);
1451 if (ret == -1) return -1;
1454 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1455 if (ret == -1) return -1;
1457 if (bcast) {
1458 struct stat st;
1459 unsigned int iface;
1460 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1461 char type;
1463 type = SOCKET_TYPE_CHAR_UDP;
1465 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1466 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1467 socket_wrapper_dir(), type, iface, prt);
1468 if (stat(un_addr.sun_path, &st) != 0) continue;
1470 /* ignore the any errors in broadcast sends */
1471 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1474 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1476 return len;
1479 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1481 /* to give better errors */
1482 if (ret == -1 && errno == ENOENT) {
1483 errno = EHOSTUNREACH;
1486 if (ret == -1) {
1487 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1488 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1489 } else {
1490 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1493 return ret;
1496 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1498 int ret;
1499 struct socket_info *si = find_socket_info(s);
1500 int value;
1502 if (!si) {
1503 return real_ioctl(s, r, p);
1506 ret = real_ioctl(s, r, p);
1508 switch (r) {
1509 case FIONREAD:
1510 value = *((int *)p);
1511 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1512 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1513 } else if (value == 0) { /* END OF FILE */
1514 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1516 break;
1519 return ret;
1522 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1524 int ret;
1525 struct socket_info *si = find_socket_info(s);
1527 if (!si) {
1528 return real_recv(s, buf, len, flags);
1531 ret = real_recv(s, buf, len, flags);
1532 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1533 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1534 } else if (ret == 0) { /* END OF FILE */
1535 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1536 } else {
1537 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1540 return ret;
1544 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1546 int ret;
1547 struct socket_info *si = find_socket_info(s);
1549 if (!si) {
1550 return real_send(s, buf, len, flags);
1553 ret = real_send(s, buf, len, flags);
1555 if (ret == -1) {
1556 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1557 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1558 } else {
1559 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1562 return ret;
1565 _PUBLIC_ int swrap_close(int fd)
1567 struct socket_info *si = find_socket_info(fd);
1568 int ret;
1570 if (!si) {
1571 return real_close(fd);
1574 SWRAP_DLIST_REMOVE(sockets, si);
1576 if (si->myname && si->peername) {
1577 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1580 ret = real_close(fd);
1582 if (si->myname && si->peername) {
1583 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1584 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1587 if (si->path) free(si->path);
1588 if (si->myname) free(si->myname);
1589 if (si->peername) free(si->peername);
1590 if (si->tmp_path) {
1591 unlink(si->tmp_path);
1592 free(si->tmp_path);
1594 free(si);
1596 return ret;