1 /*
2 * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org>
3 * Copyright (C) Stefan Metzmacher 2006 <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 "includes.h"
46 #include "system/network.h"
47 #include "system/filesys.h"
48
49 #ifdef malloc
50 #undef malloc
51 #endif
52 #ifdef calloc
53 #undef calloc
54 #endif
55 #ifdef strdup
56 #undef strdup
57 #endif
58
59 #else /* _SAMBA_BUILD_ */
60
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>
76
77 #define _PUBLIC_
78
79 #endif
80
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)
93
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; \
103 } \
104 if ((item)->next) { \
105 (item)->next->prev = (item)->prev; \
106 } \
107 } \
108 (item)->prev = NULL; \
109 (item)->next = NULL; \
110 } while (0)
111
112 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
113 * for now */
114 #define REWRITE_CALLS
115
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
133
134 #ifdef HAVE_GETTIMEOFDAY_TZ
135 #define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL)
136 #else
137 #define swrapGetTimeOfDay(tval) gettimeofday(tval)
138 #endif
139
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()
143
144 with this format we have 8 chars left for the directory name
145 */
146 #define SOCKET_FORMAT "%c%02X%04X"
147 #define SOCKET_TYPE_CHAR_TCP 'T'
148 #define SOCKET_TYPE_CHAR_UDP 'U'
149
150 #define MAX_WRAPPED_INTERFACES 16
151
sockaddr_dup(const void * data,socklen_t len)152 static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
153 {
154 struct sockaddr *ret = (struct sockaddr *)malloc(len);
155 memcpy(ret, data, len);
156 return ret;
157 }
158
159 struct socket_info
160 {
161 int fd;
162
163 int family;
164 int type;
165 int protocol;
166 int bound;
167 int bcast;
168 int is_server;
169
170 char *path;
171 char *tmp_path;
172
173 struct sockaddr *myname;
174 socklen_t myname_len;
175
176 struct sockaddr *peername;
177 socklen_t peername_len;
178
179 struct {
180 unsigned long pck_snd;
181 unsigned long pck_rcv;
182 } io;
183
184 struct socket_info *prev, *next;
185 };
186
187 static struct socket_info *sockets;
188
189
socket_wrapper_dir(void)190 static const char *socket_wrapper_dir(void)
191 {
192 const char *s = getenv("SOCKET_WRAPPER_DIR");
193 if (s == NULL) {
194 return NULL;
195 }
196 if (strncmp(s, "./", 2) == 0) {
197 s += 2;
198 }
199 return s;
200 }
201
socket_wrapper_default_iface(void)202 static unsigned int socket_wrapper_default_iface(void)
203 {
204 const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
205 if (s) {
206 unsigned int iface;
207 if (sscanf(s, "%u", &iface) == 1) {
208 if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) {
209 return iface;
210 }
211 }
212 }
213
214 return 1;/* 127.0.0.1 */
215 }
216
convert_un_in(const struct sockaddr_un * un,struct sockaddr_in * in,socklen_t * len)217 static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
218 {
219 unsigned int iface;
220 unsigned int prt;
221 const char *p;
222 char type;
223
224 if ((*len) < sizeof(struct sockaddr_in)) {
225 return 0;
226 }
227
228 p = strrchr(un->sun_path, '/');
229 if (p) p++; else p = un->sun_path;
230
231 if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
232 errno = EINVAL;
233 return -1;
234 }
235
236 if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
237 errno = EINVAL;
238 return -1;
239 }
240
241 if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) {
242 errno = EINVAL;
243 return -1;
244 }
245
246 if (prt > 0xFFFF) {
247 errno = EINVAL;
248 return -1;
249 }
250
251 in->sin_family = AF_INET;
252 in->sin_addr.s_addr = htonl((127<<24) | iface);
253 in->sin_port = htons(prt);
254
255 *len = sizeof(struct sockaddr_in);
256 return 0;
257 }
258
convert_in_un_remote(struct socket_info * si,const struct sockaddr_in * in,struct sockaddr_un * un,int * bcast)259 static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
260 int *bcast)
261 {
262 char u_type = '\0';
263 char b_type = '\0';
264 char a_type = '\0';
265 char type = '\0';
266 unsigned int addr= ntohl(in->sin_addr.s_addr);
267 unsigned int prt = ntohs(in->sin_port);
268 unsigned int iface;
269 int is_bcast = 0;
270
271 if (bcast) *bcast = 0;
272
273 if (prt == 0) {
274 errno = EINVAL;
275 return -1;
276 }
277
278 switch (si->type) {
279 case SOCK_STREAM:
280 u_type = SOCKET_TYPE_CHAR_TCP;
281 break;
282 case SOCK_DGRAM:
283 u_type = SOCKET_TYPE_CHAR_UDP;
284 a_type = SOCKET_TYPE_CHAR_UDP;
285 b_type = SOCKET_TYPE_CHAR_UDP;
286 break;
287 }
288
289 if (a_type && addr == 0xFFFFFFFF) {
290 /* 255.255.255.255 only udp */
291 is_bcast = 2;
292 type = a_type;
293 iface = socket_wrapper_default_iface();
294 } else if (b_type && addr == 0x7FFFFFFF) {
295 /* 127.255.255.255 only udp */
296 is_bcast = 1;
297 type = b_type;
298 iface = socket_wrapper_default_iface();
299 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
300 /* 127.0.0.X */
301 is_bcast = 0;
302 type = u_type;
303 iface = (addr & 0x000000FF);
304 } else {
305 errno = ENETUNREACH;
306 return -1;
307 }
308
309 if (bcast) *bcast = is_bcast;
310
311 if (is_bcast) {
312 snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
313 socket_wrapper_dir());
314 /* the caller need to do more processing */
315 return 0;
316 }
317
318 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
319 socket_wrapper_dir(), type, iface, prt);
320
321 return 0;
322 }
323
convert_in_un_alloc(struct socket_info * si,const struct sockaddr_in * in,struct sockaddr_un * un,int * bcast)324 static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
325 int *bcast)
326 {
327 char u_type = '\0';
328 char d_type = '\0';
329 char b_type = '\0';
330 char a_type = '\0';
331 char type = '\0';
332 unsigned int addr= ntohl(in->sin_addr.s_addr);
333 unsigned int prt = ntohs(in->sin_port);
334 unsigned int iface;
335 struct stat st;
336 int is_bcast = 0;
337
338 if (bcast) *bcast = 0;
339
340 switch (si->type) {
341 case SOCK_STREAM:
342 u_type = SOCKET_TYPE_CHAR_TCP;
343 d_type = SOCKET_TYPE_CHAR_TCP;
344 break;
345 case SOCK_DGRAM:
346 u_type = SOCKET_TYPE_CHAR_UDP;
347 d_type = SOCKET_TYPE_CHAR_UDP;
348 a_type = SOCKET_TYPE_CHAR_UDP;
349 b_type = SOCKET_TYPE_CHAR_UDP;
350 break;
351 }
352
353 if (addr == 0) {
354 /* 0.0.0.0 */
355 is_bcast = 0;
356 type = d_type;
357 iface = socket_wrapper_default_iface();
358 } else if (a_type && addr == 0xFFFFFFFF) {
359 /* 255.255.255.255 only udp */
360 is_bcast = 2;
361 type = a_type;
362 iface = socket_wrapper_default_iface();
363 } else if (b_type && addr == 0x7FFFFFFF) {
364 /* 127.255.255.255 only udp */
365 is_bcast = 1;
366 type = b_type;
367 iface = socket_wrapper_default_iface();
368 } else if ((addr & 0xFFFFFF00) == 0x7F000000) {
369 /* 127.0.0.X */
370 is_bcast = 0;
371 type = u_type;
372 iface = (addr & 0x000000FF);
373 } else {
374 errno = EADDRNOTAVAIL;
375 return -1;
376 }
377
378 if (bcast) *bcast = is_bcast;
379
380 if (prt == 0) {
381 /* handle auto-allocation of ephemeral ports */
382 for (prt = 5001; prt < 10000; prt++) {
383 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
384 socket_wrapper_dir(), type, iface, prt);
385 if (stat(un->sun_path, &st) == 0) continue;
386
387 ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
388 return 0;
389 }
390 errno = ENFILE;
391 return -1;
392 }
393
394 snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
395 socket_wrapper_dir(), type, iface, prt);
396 return 0;
397 }
398
find_socket_info(int fd)399 static struct socket_info *find_socket_info(int fd)
400 {
401 struct socket_info *i;
402 for (i = sockets; i; i = i->next) {
403 if (i->fd == fd)
404 return i;
405 }
406
407 return NULL;
408 }
409
sockaddr_convert_to_un(struct socket_info * si,const struct sockaddr * in_addr,socklen_t in_len,struct sockaddr_un * out_addr,int alloc_sock,int * bcast)410 static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
411 struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
412 {
413 if (!out_addr)
414 return 0;
415
416 out_addr->sun_family = AF_UNIX;
417
418 switch (in_addr->sa_family) {
419 case AF_INET:
420 switch (si->type) {
421 case SOCK_STREAM:
422 case SOCK_DGRAM:
423 break;
424 default:
425 errno = ESOCKTNOSUPPORT;
426 return -1;
427 }
428 if (alloc_sock) {
429 return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
430 } else {
431 return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
432 }
433 default:
434 break;
435 }
436
437 errno = EAFNOSUPPORT;
438 return -1;
439 }
440
sockaddr_convert_from_un(const struct socket_info * si,const struct sockaddr_un * in_addr,socklen_t un_addrlen,int family,struct sockaddr * out_addr,socklen_t * _out_addrlen)441 static int sockaddr_convert_from_un(const struct socket_info *si,
442 const struct sockaddr_un *in_addr,
443 socklen_t un_addrlen,
444 int family,
445 struct sockaddr *out_addr,
446 socklen_t *_out_addrlen)
447 {
448 socklen_t out_addrlen;
449
450 if (out_addr == NULL || _out_addrlen == NULL)
451 return 0;
452
453 if (un_addrlen == 0) {
454 *_out_addrlen = 0;
455 return 0;
456 }
457
458 out_addrlen = *_out_addrlen;
459 if (out_addrlen > un_addrlen) {
460 out_addrlen = un_addrlen;
461 }
462
463 switch (family) {
464 case AF_INET:
465 switch (si->type) {
466 case SOCK_STREAM:
467 case SOCK_DGRAM:
468 break;
469 default:
470 errno = ESOCKTNOSUPPORT;
471 return -1;
472 }
473 return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen);
474 default:
475 break;
476 }
477
478 errno = EAFNOSUPPORT;
479 return -1;
480 }
481
482 enum swrap_packet_type {
483 SWRAP_CONNECT_SEND,
484 SWRAP_CONNECT_UNREACH,
485 SWRAP_CONNECT_RECV,
486 SWRAP_CONNECT_ACK,
487 SWRAP_ACCEPT_SEND,
488 SWRAP_ACCEPT_RECV,
489 SWRAP_ACCEPT_ACK,
490 SWRAP_RECVFROM,
491 SWRAP_SENDTO,
492 SWRAP_SENDTO_UNREACH,
493 SWRAP_PENDING_RST,
494 SWRAP_RECV,
495 SWRAP_RECV_RST,
496 SWRAP_SEND,
497 SWRAP_SEND_RST,
498 SWRAP_CLOSE_SEND,
499 SWRAP_CLOSE_RECV,
500 SWRAP_CLOSE_ACK
501 };
502
503 struct swrap_file_hdr {
504 unsigned long magic;
505 unsigned short version_major;
506 unsigned short version_minor;
507 long timezone;
508 unsigned long sigfigs;
509 unsigned long frame_max_len;
510 #define SWRAP_FRAME_LENGTH_MAX 0xFFFF
511 unsigned long link_type;
512 };
513 #define SWRAP_FILE_HDR_SIZE 24
514
515 struct swrap_packet {
516 struct {
517 unsigned long seconds;
518 unsigned long micro_seconds;
519 unsigned long recorded_length;
520 unsigned long full_length;
521 } frame;
522 #define SWRAP_PACKET__FRAME_SIZE 16
523
524 struct {
525 struct {
526 unsigned char ver_hdrlen;
527 unsigned char tos;
528 unsigned short packet_length;
529 unsigned short identification;
530 unsigned char flags;
531 unsigned char fragment;
532 unsigned char ttl;
533 unsigned char protocol;
534 unsigned short hdr_checksum;
535 unsigned long src_addr;
536 unsigned long dest_addr;
537 } hdr;
538 #define SWRAP_PACKET__IP_HDR_SIZE 20
539
540 union {
541 struct {
542 unsigned short source_port;
543 unsigned short dest_port;
544 unsigned long seq_num;
545 unsigned long ack_num;
546 unsigned char hdr_length;
547 unsigned char control;
548 unsigned short window;
549 unsigned short checksum;
550 unsigned short urg;
551 } tcp;
552 #define SWRAP_PACKET__IP_P_TCP_SIZE 20
553 struct {
554 unsigned short source_port;
555 unsigned short dest_port;
556 unsigned short length;
557 unsigned short checksum;
558 } udp;
559 #define SWRAP_PACKET__IP_P_UDP_SIZE 8
560 struct {
561 unsigned char type;
562 unsigned char code;
563 unsigned short checksum;
564 unsigned long unused;
565 } icmp;
566 #define SWRAP_PACKET__IP_P_ICMP_SIZE 8
567 } p;
568 } ip;
569 };
570 #define SWRAP_PACKET_SIZE 56
571
socket_wrapper_pcap_file(void)572 static const char *socket_wrapper_pcap_file(void)
573 {
574 static int initialized = 0;
575 static const char *s = NULL;
576 static const struct swrap_file_hdr h;
577 static const struct swrap_packet p;
578
579 if (initialized == 1) {
580 return s;
581 }
582 initialized = 1;
583
584 /*
585 * TODO: don't use the structs use plain buffer offsets
586 * and PUSH_U8(), PUSH_U16() and PUSH_U32()
587 *
588 * for now make sure we disable PCAP support
589 * if the struct has alignment!
590 */
591 if (sizeof(h) != SWRAP_FILE_HDR_SIZE) {
592 return NULL;
593 }
594 if (sizeof(p) != SWRAP_PACKET_SIZE) {
595 return NULL;
596 }
597 if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) {
598 return NULL;
599 }
600 if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) {
601 return NULL;
602 }
603 if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) {
604 return NULL;
605 }
606 if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) {
607 return NULL;
608 }
609 if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) {
610 return NULL;
611 }
612
613 s = getenv("SOCKET_WRAPPER_PCAP_FILE");
614 if (s == NULL) {
615 return NULL;
616 }
617 if (strncmp(s, "./", 2) == 0) {
618 s += 2;
619 }
620 return s;
621 }
622
swrap_packet_init(struct timeval * tval,const struct sockaddr_in * src_addr,const struct sockaddr_in * dest_addr,int socket_type,const unsigned char * payload,size_t payload_len,unsigned long tcp_seq,unsigned long tcp_ack,unsigned char tcp_ctl,int unreachable,size_t * _packet_len)623 static struct swrap_packet *swrap_packet_init(struct timeval *tval,
624 const struct sockaddr_in *src_addr,
625 const struct sockaddr_in *dest_addr,
626 int socket_type,
627 const unsigned char *payload,
628 size_t payload_len,
629 unsigned long tcp_seq,
630 unsigned long tcp_ack,
631 unsigned char tcp_ctl,
632 int unreachable,
633 size_t *_packet_len)
634 {
635 struct swrap_packet *ret;
636 struct swrap_packet *packet;
637 size_t packet_len;
638 size_t alloc_len;
639 size_t nonwire_len = sizeof(packet->frame);
640 size_t wire_hdr_len = 0;
641 size_t wire_len = 0;
642 size_t icmp_hdr_len = 0;
643 size_t icmp_truncate_len = 0;
644 unsigned char protocol = 0, icmp_protocol = 0;
645 unsigned short src_port = src_addr->sin_port;
646 unsigned short dest_port = dest_addr->sin_port;
647
648 switch (socket_type) {
649 case SOCK_STREAM:
650 protocol = 0x06; /* TCP */
651 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp);
652 wire_len = wire_hdr_len + payload_len;
653 break;
654
655 case SOCK_DGRAM:
656 protocol = 0x11; /* UDP */
657 wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp);
658 wire_len = wire_hdr_len + payload_len;
659 break;
660 }
661
662 if (unreachable) {
663 icmp_protocol = protocol;
664 protocol = 0x01; /* ICMP */
665 if (wire_len > 64 ) {
666 icmp_truncate_len = wire_len - 64;
667 }
668 icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp);
669 wire_hdr_len += icmp_hdr_len;
670 wire_len += icmp_hdr_len;
671 }
672
673 packet_len = nonwire_len + wire_len;
674 alloc_len = packet_len;
675 if (alloc_len < sizeof(struct swrap_packet)) {
676 alloc_len = sizeof(struct swrap_packet);
677 }
678 ret = (struct swrap_packet *)malloc(alloc_len);
679 if (!ret) return NULL;
680
681 packet = ret;
682
683 packet->frame.seconds = tval->tv_sec;
684 packet->frame.micro_seconds = tval->tv_usec;
685 packet->frame.recorded_length = wire_len - icmp_truncate_len;
686 packet->frame.full_length = wire_len - icmp_truncate_len;
687
688 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
689 packet->ip.hdr.tos = 0x00;
690 packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len);
691 packet->ip.hdr.identification = htons(0xFFFF);
692 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
693 packet->ip.hdr.fragment = htons(0x0000);
694 packet->ip.hdr.ttl = 0xFF;
695 packet->ip.hdr.protocol = protocol;
696 packet->ip.hdr.hdr_checksum = htons(0x0000);
697 packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr;
698 packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr;
699
700 if (unreachable) {
701 packet->ip.p.icmp.type = 0x03; /* destination unreachable */
702 packet->ip.p.icmp.code = 0x01; /* host unreachable */
703 packet->ip.p.icmp.checksum = htons(0x0000);
704 packet->ip.p.icmp.unused = htonl(0x00000000);
705
706 /* set the ip header in the ICMP payload */
707 packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len);
708 packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */
709 packet->ip.hdr.tos = 0x00;
710 packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len);
711 packet->ip.hdr.identification = htons(0xFFFF);
712 packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */
713 packet->ip.hdr.fragment = htons(0x0000);
714 packet->ip.hdr.ttl = 0xFF;
715 packet->ip.hdr.protocol = icmp_protocol;
716 packet->ip.hdr.hdr_checksum = htons(0x0000);
717 packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr;
718 packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr;
719
720 src_port = dest_addr->sin_port;
721 dest_port = src_addr->sin_port;
722 }
723
724 switch (socket_type) {
725 case SOCK_STREAM:
726 packet->ip.p.tcp.source_port = src_port;
727 packet->ip.p.tcp.dest_port = dest_port;
728 packet->ip.p.tcp.seq_num = htonl(tcp_seq);
729 packet->ip.p.tcp.ack_num = htonl(tcp_ack);
730 packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */
731 packet->ip.p.tcp.control = tcp_ctl;
732 packet->ip.p.tcp.window = htons(0x7FFF);
733 packet->ip.p.tcp.checksum = htons(0x0000);
734 packet->ip.p.tcp.urg = htons(0x0000);
735
736 break;
737
738 case SOCK_DGRAM:
739 packet->ip.p.udp.source_port = src_addr->sin_port;
740 packet->ip.p.udp.dest_port = dest_addr->sin_port;
741 packet->ip.p.udp.length = htons(8 + payload_len);
742 packet->ip.p.udp.checksum = htons(0x0000);
743
744 break;
745 }
746
747 if (payload && payload_len > 0) {
748 unsigned char *p = (unsigned char *)ret;
749 p += nonwire_len;
750 p += wire_hdr_len;
751 memcpy(p, payload, payload_len);
752 }
753
754 *_packet_len = packet_len - icmp_truncate_len;
755 return ret;
756 }
757
swrap_get_pcap_fd(const char * fname)758 static int swrap_get_pcap_fd(const char *fname)
759 {
760 static int fd = -1;
761
762 if (fd != -1) return fd;
763
764 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644);
765 if (fd != -1) {
766 struct swrap_file_hdr file_hdr;
767 file_hdr.magic = 0xA1B2C3D4;
768 file_hdr.version_major = 0x0002;
769 file_hdr.version_minor = 0x0004;
770 file_hdr.timezone = 0x00000000;
771 file_hdr.sigfigs = 0x00000000;
772 file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX;
773 file_hdr.link_type = 0x0065; /* 101 RAW IP */
774
775 write(fd, &file_hdr, sizeof(file_hdr));
776 return fd;
777 }
778
779 fd = open(fname, O_WRONLY|O_APPEND, 0644);
780
781 return fd;
782 }
783
swrap_dump_packet(struct socket_info * si,const struct sockaddr * addr,enum swrap_packet_type type,const void * buf,size_t len)784 static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr,
785 enum swrap_packet_type type,
786 const void *buf, size_t len)
787 {
788 const struct sockaddr_in *src_addr;
789 const struct sockaddr_in *dest_addr;
790 const char *file_name;
791 unsigned long tcp_seq = 0;
792 unsigned long tcp_ack = 0;
793 unsigned char tcp_ctl = 0;
794 int unreachable = 0;
795 struct timeval tv;
796 struct swrap_packet *packet;
797 size_t packet_len = 0;
798 int fd;
799
800 file_name = socket_wrapper_pcap_file();
801 if (!file_name) {
802 return;
803 }
804
805 if (si->family != AF_INET) {
806 return;
807 }
808
809 switch (type) {
810 case SWRAP_CONNECT_SEND:
811 if (si->type != SOCK_STREAM) return;
812
813 src_addr = (const struct sockaddr_in *)si->myname;
814 dest_addr = (const struct sockaddr_in *)addr;
815
816 tcp_seq = si->io.pck_snd;
817 tcp_ack = si->io.pck_rcv;
818 tcp_ctl = 0x02; /* SYN */
819
820 si->io.pck_snd += 1;
821
822 break;
823
824 case SWRAP_CONNECT_RECV:
825 if (si->type != SOCK_STREAM) return;
826
827 dest_addr = (const struct sockaddr_in *)si->myname;
828 src_addr = (const struct sockaddr_in *)addr;
829
830 tcp_seq = si->io.pck_rcv;
831 tcp_ack = si->io.pck_snd;
832 tcp_ctl = 0x12; /** SYN,ACK */
833
834 si->io.pck_rcv += 1;
835
836 break;
837
838 case SWRAP_CONNECT_UNREACH:
839 if (si->type != SOCK_STREAM) return;
840
841 dest_addr = (const struct sockaddr_in *)si->myname;
842 src_addr = (const struct sockaddr_in *)addr;
843
844 /* Unreachable: resend the data of SWRAP_CONNECT_SEND */
845 tcp_seq = si->io.pck_snd - 1;
846 tcp_ack = si->io.pck_rcv;
847 tcp_ctl = 0x02; /* SYN */
848 unreachable = 1;
849
850 break;
851
852 case SWRAP_CONNECT_ACK:
853 if (si->type != SOCK_STREAM) return;
854
855 src_addr = (const struct sockaddr_in *)si->myname;
856 dest_addr = (const struct sockaddr_in *)addr;
857
858 tcp_seq = si->io.pck_snd;
859 tcp_ack = si->io.pck_rcv;
860 tcp_ctl = 0x10; /* ACK */
861
862 break;
863
864 case SWRAP_ACCEPT_SEND:
865 if (si->type != SOCK_STREAM) return;
866
867 dest_addr = (const struct sockaddr_in *)si->myname;
868 src_addr = (const struct sockaddr_in *)addr;
869
870 tcp_seq = si->io.pck_rcv;
871 tcp_ack = si->io.pck_snd;
872 tcp_ctl = 0x02; /* SYN */
873
874 si->io.pck_rcv += 1;
875
876 break;
877
878 case SWRAP_ACCEPT_RECV:
879 if (si->type != SOCK_STREAM) return;
880
881 src_addr = (const struct sockaddr_in *)si->myname;
882 dest_addr = (const struct sockaddr_in *)addr;
883
884 tcp_seq = si->io.pck_snd;
885 tcp_ack = si->io.pck_rcv;
886 tcp_ctl = 0x12; /* SYN,ACK */
887
888 si->io.pck_snd += 1;
889
890 break;
891
892 case SWRAP_ACCEPT_ACK:
893 if (si->type != SOCK_STREAM) return;
894
895 dest_addr = (const struct sockaddr_in *)si->myname;
896 src_addr = (const struct sockaddr_in *)addr;
897
898 tcp_seq = si->io.pck_rcv;
899 tcp_ack = si->io.pck_snd;
900 tcp_ctl = 0x10; /* ACK */
901
902 break;
903
904 case SWRAP_SEND:
905 src_addr = (const struct sockaddr_in *)si->myname;
906 dest_addr = (const struct sockaddr_in *)si->peername;
907
908 tcp_seq = si->io.pck_snd;
909 tcp_ack = si->io.pck_rcv;
910 tcp_ctl = 0x18; /* PSH,ACK */
911
912 si->io.pck_snd += len;
913
914 break;
915
916 case SWRAP_SEND_RST:
917 dest_addr = (const struct sockaddr_in *)si->myname;
918 src_addr = (const struct sockaddr_in *)si->peername;
919
920 if (si->type == SOCK_DGRAM) {
921 swrap_dump_packet(si, si->peername,
922 SWRAP_SENDTO_UNREACH,
923 buf, len);
924 return;
925 }
926
927 tcp_seq = si->io.pck_rcv;
928 tcp_ack = si->io.pck_snd;
929 tcp_ctl = 0x14; /** RST,ACK */
930
931 break;
932
933 case SWRAP_PENDING_RST:
934 dest_addr = (const struct sockaddr_in *)si->myname;
935 src_addr = (const struct sockaddr_in *)si->peername;
936
937 if (si->type == SOCK_DGRAM) {
938 return;
939 }
940
941 tcp_seq = si->io.pck_rcv;
942 tcp_ack = si->io.pck_snd;
943 tcp_ctl = 0x14; /* RST,ACK */
944
945 break;
946
947 case SWRAP_RECV:
948 dest_addr = (const struct sockaddr_in *)si->myname;
949 src_addr = (const struct sockaddr_in *)si->peername;
950
951 tcp_seq = si->io.pck_rcv;
952 tcp_ack = si->io.pck_snd;
953 tcp_ctl = 0x18; /* PSH,ACK */
954
955 si->io.pck_rcv += len;
956
957 break;
958
959 case SWRAP_RECV_RST:
960 dest_addr = (const struct sockaddr_in *)si->myname;
961 src_addr = (const struct sockaddr_in *)si->peername;
962
963 if (si->type == SOCK_DGRAM) {
964 return;
965 }
966
967 tcp_seq = si->io.pck_rcv;
968 tcp_ack = si->io.pck_snd;
969 tcp_ctl = 0x14; /* RST,ACK */
970
971 break;
972
973 case SWRAP_SENDTO:
974 src_addr = (const struct sockaddr_in *)si->myname;
975 dest_addr = (const struct sockaddr_in *)addr;
976
977 si->io.pck_snd += len;
978
979 break;
980
981 case SWRAP_SENDTO_UNREACH:
982 dest_addr = (const struct sockaddr_in *)si->myname;
983 src_addr = (const struct sockaddr_in *)addr;
984
985 unreachable = 1;
986
987 break;
988
989 case SWRAP_RECVFROM:
990 dest_addr = (const struct sockaddr_in *)si->myname;
991 src_addr = (const struct sockaddr_in *)addr;
992
993 si->io.pck_rcv += len;
994
995 break;
996
997 case SWRAP_CLOSE_SEND:
998 if (si->type != SOCK_STREAM) return;
999
1000 src_addr = (const struct sockaddr_in *)si->myname;
1001 dest_addr = (const struct sockaddr_in *)si->peername;
1002
1003 tcp_seq = si->io.pck_snd;
1004 tcp_ack = si->io.pck_rcv;
1005 tcp_ctl = 0x11; /* FIN, ACK */
1006
1007 si->io.pck_snd += 1;
1008
1009 break;
1010
1011 case SWRAP_CLOSE_RECV:
1012 if (si->type != SOCK_STREAM) return;
1013
1014 dest_addr = (const struct sockaddr_in *)si->myname;
1015 src_addr = (const struct sockaddr_in *)si->peername;
1016
1017 tcp_seq = si->io.pck_rcv;
1018 tcp_ack = si->io.pck_snd;
1019 tcp_ctl = 0x11; /* FIN,ACK */
1020
1021 si->io.pck_rcv += 1;
1022
1023 break;
1024
1025 case SWRAP_CLOSE_ACK:
1026 if (si->type != SOCK_STREAM) return;
1027
1028 src_addr = (const struct sockaddr_in *)si->myname;
1029 dest_addr = (const struct sockaddr_in *)si->peername;
1030
1031 tcp_seq = si->io.pck_snd;
1032 tcp_ack = si->io.pck_rcv;
1033 tcp_ctl = 0x10; /* ACK */
1034
1035 break;
1036 default:
1037 return;
1038 }
1039
1040 swrapGetTimeOfDay(&tv);
1041
1042 packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type,
1043 (const unsigned char *)buf, len,
1044 tcp_seq, tcp_ack, tcp_ctl, unreachable,
1045 &packet_len);
1046 if (!packet) {
1047 return;
1048 }
1049
1050 fd = swrap_get_pcap_fd(file_name);
1051 if (fd != -1) {
1052 write(fd, packet, packet_len);
1053 }
1054
1055 free(packet);
1056 }
1057
swrap_socket(int family,int type,int protocol)1058 _PUBLIC_ int swrap_socket(int family, int type, int protocol)
1059 {
1060 struct socket_info *si;
1061 int fd;
1062
1063 if (!socket_wrapper_dir()) {
1064 return real_socket(family, type, protocol);
1065 }
1066
1067 switch (family) {
1068 case AF_INET:
1069 break;
1070 case AF_UNIX:
1071 return real_socket(family, type, protocol);
1072 default:
1073 errno = EAFNOSUPPORT;
1074 return -1;
1075 }
1076
1077 switch (type) {
1078 case SOCK_STREAM:
1079 break;
1080 case SOCK_DGRAM:
1081 break;
1082 default:
1083 errno = EPROTONOSUPPORT;
1084 return -1;
1085 }
1086
1087 switch (protocol) {
1088 case 0:
1089 break;
1090 default:
1091 errno = EPROTONOSUPPORT;
1092 return -1;
1093 }
1094
1095 fd = real_socket(AF_UNIX, type, 0);
1096
1097 if (fd == -1) return -1;
1098
1099 si = (struct socket_info *)calloc(1, sizeof(struct socket_info));
1100
1101 si->family = family;
1102 si->type = type;
1103 si->protocol = protocol;
1104 si->fd = fd;
1105
1106 SWRAP_DLIST_ADD(sockets, si);
1107
1108 return si->fd;
1109 }
1110
swrap_accept(int s,struct sockaddr * addr,socklen_t * addrlen)1111 _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1112 {
1113 struct socket_info *parent_si, *child_si;
1114 int fd;
1115 struct sockaddr_un un_addr;
1116 socklen_t un_addrlen = sizeof(un_addr);
1117 struct sockaddr_un un_my_addr;
1118 socklen_t un_my_addrlen = sizeof(un_my_addr);
1119 struct sockaddr my_addr;
1120 socklen_t my_addrlen = sizeof(my_addr);
1121 int ret;
1122
1123 parent_si = find_socket_info(s);
1124 if (!parent_si) {
1125 return real_accept(s, addr, addrlen);
1126 }
1127
1128 memset(&un_addr, 0, sizeof(un_addr));
1129 memset(&un_my_addr, 0, sizeof(un_my_addr));
1130 memset(&my_addr, 0, sizeof(my_addr));
1131
1132 ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen);
1133 if (ret == -1) return ret;
1134
1135 fd = ret;
1136
1137 ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen,
1138 parent_si->family, addr, addrlen);
1139 if (ret == -1) {
1140 close(fd);
1141 return ret;
1142 }
1143
1144 child_si = (struct socket_info *)malloc(sizeof(struct socket_info));
1145 memset(child_si, 0, sizeof(*child_si));
1146
1147 child_si->fd = fd;
1148 child_si->family = parent_si->family;
1149 child_si->type = parent_si->type;
1150 child_si->protocol = parent_si->protocol;
1151 child_si->bound = 1;
1152 child_si->is_server = 1;
1153
1154 ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen);
1155 if (ret == -1) {
1156 free(child_si);
1157 close(fd);
1158 return ret;
1159 }
1160
1161 ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen,
1162 child_si->family, &my_addr, &my_addrlen);
1163 if (ret == -1) {
1164 free(child_si);
1165 close(fd);
1166 return ret;
1167 }
1168
1169 child_si->myname_len = my_addrlen;
1170 child_si->myname = sockaddr_dup(&my_addr, my_addrlen);
1171
1172 child_si->peername_len = *addrlen;
1173 child_si->peername = sockaddr_dup(addr, *addrlen);
1174
1175 SWRAP_DLIST_ADD(sockets, child_si);
1176
1177 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0);
1178 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0);
1179 swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0);
1180
1181 return fd;
1182 }
1183
1184 static int autobind_start_init;
1185 static int autobind_start;
1186
1187 /* using sendto() or connect() on an unbound socket would give the
1188 recipient no way to reply, as unlike UDP and TCP, a unix domain
1189 socket can't auto-assign emphemeral port numbers, so we need to
1190 assign it here */
swrap_auto_bind(struct socket_info * si)1191 static int swrap_auto_bind(struct socket_info *si)
1192 {
1193 struct sockaddr_un un_addr;
1194 struct sockaddr_in in;
1195 int i;
1196 char type;
1197 int ret;
1198 int port;
1199 struct stat st;
1200
1201 if (autobind_start_init != 1) {
1202 autobind_start_init = 1;
1203 autobind_start = getpid();
1204 autobind_start %= 50000;
1205 autobind_start += 10000;
1206 }
1207
1208 un_addr.sun_family = AF_UNIX;
1209
1210 switch (si->type) {
1211 case SOCK_STREAM:
1212 type = SOCKET_TYPE_CHAR_TCP;
1213 break;
1214 case SOCK_DGRAM:
1215 type = SOCKET_TYPE_CHAR_UDP;
1216 break;
1217 default:
1218 errno = ESOCKTNOSUPPORT;
1219 return -1;
1220 }
1221
1222 if (autobind_start > 60000) {
1223 autobind_start = 10000;
1224 }
1225
1226 for (i=0;i<1000;i++) {
1227 port = autobind_start + i;
1228 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
1229 "%s/"SOCKET_FORMAT, socket_wrapper_dir(),
1230 type, socket_wrapper_default_iface(), port);
1231 if (stat(un_addr.sun_path, &st) == 0) continue;
1232
1233 ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
1234 if (ret == -1) return ret;
1235
1236 si->tmp_path = strdup(un_addr.sun_path);
1237 si->bound = 1;
1238 autobind_start = port + 1;
1239 break;
1240 }
1241 if (i == 1000) {
1242 errno = ENFILE;
1243 return -1;
1244 }
1245
1246 memset(&in, 0, sizeof(in));
1247 in.sin_family = AF_INET;
1248 in.sin_port = htons(port);
1249 in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
1250
1251 si->myname_len = sizeof(in);
1252 si->myname = sockaddr_dup(&in, si->myname_len);
1253 return 0;
1254 }
1255
1256
swrap_connect(int s,const struct sockaddr * serv_addr,socklen_t addrlen)1257 _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
1258 {
1259 int ret;
1260 struct sockaddr_un un_addr;
1261 struct socket_info *si = find_socket_info(s);
1262
1263 if (!si) {
1264 return real_connect(s, serv_addr, addrlen);
1265 }
1266
1267 if (si->bound == 0) {
1268 ret = swrap_auto_bind(si);
1269 if (ret == -1) return -1;
1270 }
1271
1272 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
1273 if (ret == -1) return -1;
1274
1275 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0);
1276
1277 ret = real_connect(s, (struct sockaddr *)&un_addr,
1278 sizeof(struct sockaddr_un));
1279
1280 /* to give better errors */
1281 if (ret == -1 && errno == ENOENT) {
1282 errno = EHOSTUNREACH;
1283 }
1284
1285 if (ret == 0) {
1286 si->peername_len = addrlen;
1287 si->peername = sockaddr_dup(serv_addr, addrlen);
1288
1289 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
1290 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
1291 } else {
1292 swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
1293 }
1294
1295 return ret;
1296 }
1297
swrap_bind(int s,const struct sockaddr * myaddr,socklen_t addrlen)1298 _PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
1299 {
1300 int ret;
1301 struct sockaddr_un un_addr;
1302 struct socket_info *si = find_socket_info(s);
1303
1304 if (!si) {
1305 return real_bind(s, myaddr, addrlen);
1306 }
1307
1308 si->myname_len = addrlen;
1309 si->myname = sockaddr_dup(myaddr, addrlen);
1310
1311 ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
1312 if (ret == -1) return -1;
1313
1314 unlink(un_addr.sun_path);
1315
1316 ret = real_bind(s, (struct sockaddr *)&un_addr,
1317 sizeof(struct sockaddr_un));
1318
1319 if (ret == 0) {
1320 si->bound = 1;
1321 }
1322
1323 return ret;
1324 }
1325
swrap_listen(int s,int backlog)1326 _PUBLIC_ int swrap_listen(int s, int backlog)
1327 {
1328 int ret;
1329 struct socket_info *si = find_socket_info(s);
1330
1331 if (!si) {
1332 return real_listen(s, backlog);
1333 }
1334
1335 ret = real_listen(s, backlog);
1336
1337 return ret;
1338 }
1339
swrap_getpeername(int s,struct sockaddr * name,socklen_t * addrlen)1340 _PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
1341 {
1342 struct socket_info *si = find_socket_info(s);
1343
1344 if (!si) {
1345 return real_getpeername(s, name, addrlen);
1346 }
1347
1348 if (!si->peername)
1349 {
1350 errno = ENOTCONN;
1351 return -1;
1352 }
1353
1354 memcpy(name, si->peername, si->peername_len);
1355 *addrlen = si->peername_len;
1356
1357 return 0;
1358 }
1359
swrap_getsockname(int s,struct sockaddr * name,socklen_t * addrlen)1360 _PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
1361 {
1362 struct socket_info *si = find_socket_info(s);
1363
1364 if (!si) {
1365 return real_getsockname(s, name, addrlen);
1366 }
1367
1368 memcpy(name, si->myname, si->myname_len);
1369 *addrlen = si->myname_len;
1370
1371 return 0;
1372 }
1373
swrap_getsockopt(int s,int level,int optname,void * optval,socklen_t * optlen)1374 _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1375 {
1376 struct socket_info *si = find_socket_info(s);
1377
1378 if (!si) {
1379 return real_getsockopt(s, level, optname, optval, optlen);
1380 }
1381
1382 if (level == SOL_SOCKET) {
1383 return real_getsockopt(s, level, optname, optval, optlen);
1384 }
1385
1386 errno = ENOPROTOOPT;
1387 return -1;
1388 }
1389
swrap_setsockopt(int s,int level,int optname,const void * optval,socklen_t optlen)1390 _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1391 {
1392 struct socket_info *si = find_socket_info(s);
1393
1394 if (!si) {
1395 return real_setsockopt(s, level, optname, optval, optlen);
1396 }
1397
1398 if (level == SOL_SOCKET) {
1399 return real_setsockopt(s, level, optname, optval, optlen);
1400 }
1401
1402 switch (si->family) {
1403 case AF_INET:
1404 return 0;
1405 default:
1406 errno = ENOPROTOOPT;
1407 return -1;
1408 }
1409 }
1410
swrap_recvfrom(int s,void * buf,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)1411 _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
1412 {
1413 struct sockaddr_un un_addr;
1414 socklen_t un_addrlen = sizeof(un_addr);
1415 int ret;
1416 struct socket_info *si = find_socket_info(s);
1417
1418 if (!si) {
1419 return real_recvfrom(s, buf, len, flags, from, fromlen);
1420 }
1421
1422 /* irix 6.4 forgets to null terminate the sun_path string :-( */
1423 memset(&un_addr, 0, sizeof(un_addr));
1424 ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen);
1425 if (ret == -1)
1426 return ret;
1427
1428 if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
1429 si->family, from, fromlen) == -1) {
1430 return -1;
1431 }
1432
1433 swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
1434
1435 return ret;
1436 }
1437
1438
swrap_sendto(int s,const void * buf,size_t len,int flags,const struct sockaddr * to,socklen_t tolen)1439 _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
1440 {
1441 struct sockaddr_un un_addr;
1442 int ret;
1443 struct socket_info *si = find_socket_info(s);
1444 int bcast = 0;
1445
1446 if (!si) {
1447 return real_sendto(s, buf, len, flags, to, tolen);
1448 }
1449
1450 if (si->bound == 0) {
1451 ret = swrap_auto_bind(si);
1452 if (ret == -1) return -1;
1453 }
1454
1455 ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
1456 if (ret == -1) return -1;
1457
1458 if (bcast) {
1459 struct stat st;
1460 unsigned int iface;
1461 unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
1462 char type;
1463
1464 type = SOCKET_TYPE_CHAR_UDP;
1465
1466 for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) {
1467 snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT,
1468 socket_wrapper_dir(), type, iface, prt);
1469 if (stat(un_addr.sun_path, &st) != 0) continue;
1470
1471 /* ignore the any errors in broadcast sends */
1472 real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1473 }
1474
1475 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1476
1477 return len;
1478 }
1479
1480 ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
1481
1482 /* to give better errors */
1483 if (ret == -1 && errno == ENOENT) {
1484 errno = EHOSTUNREACH;
1485 }
1486
1487 if (ret == -1) {
1488 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len);
1489 swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len);
1490 } else {
1491 swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret);
1492 }
1493
1494 return ret;
1495 }
1496
swrap_ioctl(int s,int r,void * p)1497 _PUBLIC_ int swrap_ioctl(int s, int r, void *p)
1498 {
1499 int ret;
1500 struct socket_info *si = find_socket_info(s);
1501 int value;
1502
1503 if (!si) {
1504 return real_ioctl(s, r, p);
1505 }
1506
1507 ret = real_ioctl(s, r, p);
1508
1509 switch (r) {
1510 case FIONREAD:
1511 value = *((int *)p);
1512 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1513 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1514 } else if (value == 0) { /* END OF FILE */
1515 swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0);
1516 }
1517 break;
1518 }
1519
1520 return ret;
1521 }
1522
swrap_recv(int s,void * buf,size_t len,int flags)1523 _PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
1524 {
1525 int ret;
1526 struct socket_info *si = find_socket_info(s);
1527
1528 if (!si) {
1529 return real_recv(s, buf, len, flags);
1530 }
1531
1532 ret = real_recv(s, buf, len, flags);
1533 if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
1534 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1535 } else if (ret == 0) { /* END OF FILE */
1536 swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
1537 } else {
1538 swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
1539 }
1540
1541 return ret;
1542 }
1543
1544
swrap_send(int s,const void * buf,size_t len,int flags)1545 _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags)
1546 {
1547 int ret;
1548 struct socket_info *si = find_socket_info(s);
1549
1550 if (!si) {
1551 return real_send(s, buf, len, flags);
1552 }
1553
1554 ret = real_send(s, buf, len, flags);
1555
1556 if (ret == -1) {
1557 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len);
1558 swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0);
1559 } else {
1560 swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret);
1561 }
1562
1563 return ret;
1564 }
1565
swrap_close(int fd)1566 _PUBLIC_ int swrap_close(int fd)
1567 {
1568 struct socket_info *si = find_socket_info(fd);
1569 int ret;
1570
1571 if (!si) {
1572 return real_close(fd);
1573 }
1574
1575 SWRAP_DLIST_REMOVE(sockets, si);
1576
1577 if (si->myname && si->peername) {
1578 swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0);
1579 }
1580
1581 ret = real_close(fd);
1582
1583 if (si->myname && si->peername) {
1584 swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0);
1585 swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0);
1586 }
1587
1588 if (si->path) free(si->path);
1589 if (si->myname) free(si->myname);
1590 if (si->peername) free(si->peername);
1591 if (si->tmp_path) {
1592 unlink(si->tmp_path);
1593 free(si->tmp_path);
1594 }
1595 free(si);
1596
1597 return ret;
1598 }
1599