1178825Sdfr/* 2178825Sdfr * Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org> 3178825Sdfr * Copyright (C) Stefan Metzmacher 2006 <metze@samba.org> 4178825Sdfr * 5178825Sdfr * All rights reserved. 6233294Sstas * 7178825Sdfr * Redistribution and use in source and binary forms, with or without 8178825Sdfr * modification, are permitted provided that the following conditions 9178825Sdfr * are met: 10233294Sstas * 11178825Sdfr * 1. Redistributions of source code must retain the above copyright 12178825Sdfr * notice, this list of conditions and the following disclaimer. 13233294Sstas * 14178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 15178825Sdfr * notice, this list of conditions and the following disclaimer in the 16178825Sdfr * documentation and/or other materials provided with the distribution. 17233294Sstas * 18178825Sdfr * 3. Neither the name of the author nor the names of its contributors 19178825Sdfr * may be used to endorse or promote products derived from this software 20178825Sdfr * without specific prior written permission. 21233294Sstas * 22178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32178825Sdfr * SUCH DAMAGE. 33178825Sdfr * 34178825Sdfr */ 35178825Sdfr 36178825Sdfr/* 37178825Sdfr Socket wrapper library. Passes all socket communication over 38178825Sdfr unix domain sockets if the environment variable SOCKET_WRAPPER_DIR 39178825Sdfr is set. 40178825Sdfr*/ 41178825Sdfr 42178825Sdfr#define SOCKET_WRAPPER_NOT_REPLACE 43178825Sdfr 44178825Sdfr#ifdef _SAMBA_BUILD_ 45178825Sdfr 46178825Sdfr#include "includes.h" 47178825Sdfr#include "system/network.h" 48178825Sdfr#include "system/filesys.h" 49178825Sdfr 50178825Sdfr#ifdef malloc 51178825Sdfr#undef malloc 52178825Sdfr#endif 53178825Sdfr#ifdef calloc 54178825Sdfr#undef calloc 55178825Sdfr#endif 56178825Sdfr#ifdef strdup 57178825Sdfr#undef strdup 58178825Sdfr#endif 59178825Sdfr 60178825Sdfr#else /* _SAMBA_BUILD_ */ 61178825Sdfr 62178825Sdfr#include <config.h> 63178825Sdfr#undef SOCKET_WRAPPER_REPLACE 64178825Sdfr 65178825Sdfr#include <sys/types.h> 66178825Sdfr#ifdef TIME_WITH_SYS_TIME 67178825Sdfr#include <sys/time.h> 68178825Sdfr#include <time.h> 69178825Sdfr#elif defined(HAVE_SYS_TIME_H) 70178825Sdfr#include <sys/time.h> 71178825Sdfr#else 72178825Sdfr#include <time.h> 73178825Sdfr#endif 74178825Sdfr#include <sys/stat.h> 75178825Sdfr#include <sys/socket.h> 76178825Sdfr#include <sys/ioctl.h> 77178825Sdfr#ifdef HAVE_SYS_FILIO_H 78178825Sdfr#include <sys/filio.h> 79178825Sdfr#endif 80178825Sdfr#include <errno.h> 81178825Sdfr#include <sys/un.h> 82178825Sdfr#include <netinet/in.h> 83178825Sdfr#include <netinet/tcp.h> 84178825Sdfr#include <fcntl.h> 85178825Sdfr#include <stdlib.h> 86178825Sdfr#include <unistd.h> 87178825Sdfr#include <string.h> 88178825Sdfr#include <stdio.h> 89178825Sdfr#include "roken.h" 90178825Sdfr 91178825Sdfr#include "socket_wrapper.h" 92178825Sdfr 93178825Sdfr#define HAVE_GETTIMEOFDAY_TZ 1 94178825Sdfr 95178825Sdfr#define _PUBLIC_ 96178825Sdfr 97178825Sdfr#endif 98178825Sdfr 99178825Sdfr#define SWRAP_DLIST_ADD(list,item) do { \ 100178825Sdfr if (!(list)) { \ 101178825Sdfr (item)->prev = NULL; \ 102178825Sdfr (item)->next = NULL; \ 103178825Sdfr (list) = (item); \ 104178825Sdfr } else { \ 105178825Sdfr (item)->prev = NULL; \ 106178825Sdfr (item)->next = (list); \ 107178825Sdfr (list)->prev = (item); \ 108178825Sdfr (list) = (item); \ 109178825Sdfr } \ 110178825Sdfr} while (0) 111178825Sdfr 112178825Sdfr#define SWRAP_DLIST_REMOVE(list,item) do { \ 113178825Sdfr if ((list) == (item)) { \ 114178825Sdfr (list) = (item)->next; \ 115178825Sdfr if (list) { \ 116178825Sdfr (list)->prev = NULL; \ 117178825Sdfr } \ 118178825Sdfr } else { \ 119178825Sdfr if ((item)->prev) { \ 120178825Sdfr (item)->prev->next = (item)->next; \ 121178825Sdfr } \ 122178825Sdfr if ((item)->next) { \ 123178825Sdfr (item)->next->prev = (item)->prev; \ 124178825Sdfr } \ 125178825Sdfr } \ 126178825Sdfr (item)->prev = NULL; \ 127178825Sdfr (item)->next = NULL; \ 128178825Sdfr} while (0) 129178825Sdfr 130178825Sdfr/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support 131178825Sdfr * for now */ 132233294Sstas#define REWRITE_CALLS 133178825Sdfr 134178825Sdfr#ifdef REWRITE_CALLS 135178825Sdfr#define real_accept accept 136178825Sdfr#define real_connect connect 137178825Sdfr#define real_bind bind 138178825Sdfr#define real_listen listen 139178825Sdfr#define real_getpeername getpeername 140178825Sdfr#define real_getsockname getsockname 141178825Sdfr#define real_getsockopt getsockopt 142178825Sdfr#define real_setsockopt setsockopt 143178825Sdfr#define real_recvfrom recvfrom 144178825Sdfr#define real_sendto sendto 145178825Sdfr#define real_ioctl ioctl 146178825Sdfr#define real_recv recv 147178825Sdfr#define real_send send 148178825Sdfr#define real_socket socket 149178825Sdfr#define real_close close 150178825Sdfr#define real_dup dup 151178825Sdfr#define real_dup2 dup2 152178825Sdfr#endif 153178825Sdfr 154178825Sdfr#ifdef HAVE_GETTIMEOFDAY_TZ 155178825Sdfr#define swrapGetTimeOfDay(tval) gettimeofday(tval,NULL) 156178825Sdfr#else 157178825Sdfr#define swrapGetTimeOfDay(tval) gettimeofday(tval) 158178825Sdfr#endif 159178825Sdfr 160178825Sdfr/* we need to use a very terse format here as IRIX 6.4 silently 161178825Sdfr truncates names to 16 chars, so if we use a longer name then we 162233294Sstas can't tell which port a packet came from with recvfrom() 163233294Sstas 164178825Sdfr with this format we have 8 chars left for the directory name 165178825Sdfr*/ 166178825Sdfr#define SOCKET_FORMAT "%c%02X%04X" 167178825Sdfr#define SOCKET_TYPE_CHAR_TCP 'T' 168178825Sdfr#define SOCKET_TYPE_CHAR_UDP 'U' 169178825Sdfr#define SOCKET_TYPE_CHAR_TCP_V6 'X' 170178825Sdfr#define SOCKET_TYPE_CHAR_UDP_V6 'Y' 171178825Sdfr 172178825Sdfr#define MAX_WRAPPED_INTERFACES 16 173178825Sdfr 174178825Sdfr#define SW_IPV6_ADDRESS 1 175178825Sdfr 176178825Sdfrstatic struct sockaddr *sockaddr_dup(const void *data, socklen_t len) 177178825Sdfr{ 178178825Sdfr struct sockaddr *ret = (struct sockaddr *)malloc(len); 179178825Sdfr memcpy(ret, data, len); 180178825Sdfr return ret; 181178825Sdfr} 182178825Sdfr 183178825Sdfrstatic void set_port(int family, int prt, struct sockaddr *addr) 184178825Sdfr{ 185178825Sdfr switch (family) { 186178825Sdfr case AF_INET: 187178825Sdfr ((struct sockaddr_in *)addr)->sin_port = htons(prt); 188178825Sdfr break; 189178825Sdfr#ifdef HAVE_IPV6 190178825Sdfr case AF_INET6: 191178825Sdfr ((struct sockaddr_in6 *)addr)->sin6_port = htons(prt); 192178825Sdfr break; 193178825Sdfr#endif 194178825Sdfr } 195178825Sdfr} 196178825Sdfr 197178825Sdfrstatic int socket_length(int family) 198178825Sdfr{ 199178825Sdfr switch (family) { 200178825Sdfr case AF_INET: 201178825Sdfr return sizeof(struct sockaddr_in); 202178825Sdfr#ifdef HAVE_IPV6 203178825Sdfr case AF_INET6: 204178825Sdfr return sizeof(struct sockaddr_in6); 205178825Sdfr#endif 206178825Sdfr } 207178825Sdfr return -1; 208178825Sdfr} 209178825Sdfr 210178825Sdfr 211178825Sdfr 212178825Sdfrstruct socket_info 213178825Sdfr{ 214178825Sdfr int fd; 215178825Sdfr 216178825Sdfr int family; 217178825Sdfr int type; 218178825Sdfr int protocol; 219178825Sdfr int bound; 220178825Sdfr int bcast; 221178825Sdfr int is_server; 222178825Sdfr 223178825Sdfr char *path; 224178825Sdfr char *tmp_path; 225178825Sdfr 226178825Sdfr struct sockaddr *myname; 227178825Sdfr socklen_t myname_len; 228178825Sdfr 229178825Sdfr struct sockaddr *peername; 230178825Sdfr socklen_t peername_len; 231178825Sdfr 232178825Sdfr struct { 233178825Sdfr unsigned long pck_snd; 234178825Sdfr unsigned long pck_rcv; 235178825Sdfr } io; 236178825Sdfr 237178825Sdfr struct socket_info *prev, *next; 238178825Sdfr}; 239178825Sdfr 240178825Sdfrstatic struct socket_info *sockets; 241178825Sdfr 242178825Sdfr 243178825Sdfrstatic const char *socket_wrapper_dir(void) 244178825Sdfr{ 245178825Sdfr const char *s = getenv("SOCKET_WRAPPER_DIR"); 246178825Sdfr if (s == NULL) { 247178825Sdfr return NULL; 248178825Sdfr } 249178825Sdfr if (strncmp(s, "./", 2) == 0) { 250178825Sdfr s += 2; 251178825Sdfr } 252178825Sdfr return s; 253178825Sdfr} 254178825Sdfr 255178825Sdfrstatic unsigned int socket_wrapper_default_iface(void) 256178825Sdfr{ 257178825Sdfr const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE"); 258178825Sdfr if (s) { 259178825Sdfr unsigned int iface; 260178825Sdfr if (sscanf(s, "%u", &iface) == 1) { 261178825Sdfr if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) { 262178825Sdfr return iface; 263178825Sdfr } 264178825Sdfr } 265178825Sdfr } 266178825Sdfr 267178825Sdfr return 1;/* 127.0.0.1 */ 268178825Sdfr} 269178825Sdfr 270178825Sdfrstatic int convert_un_in(const struct sockaddr_un *un, struct sockaddr *in, socklen_t *len) 271178825Sdfr{ 272178825Sdfr unsigned int iface; 273178825Sdfr unsigned int prt; 274178825Sdfr const char *p; 275178825Sdfr char type; 276178825Sdfr 277178825Sdfr p = strrchr(un->sun_path, '/'); 278178825Sdfr if (p) p++; else p = un->sun_path; 279178825Sdfr 280178825Sdfr if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) { 281178825Sdfr errno = EINVAL; 282178825Sdfr return -1; 283178825Sdfr } 284178825Sdfr 285178825Sdfr if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) { 286178825Sdfr errno = EINVAL; 287178825Sdfr return -1; 288178825Sdfr } 289178825Sdfr 290178825Sdfr if (prt > 0xFFFF) { 291178825Sdfr errno = EINVAL; 292178825Sdfr return -1; 293178825Sdfr } 294178825Sdfr 295178825Sdfr switch(type) { 296178825Sdfr case SOCKET_TYPE_CHAR_TCP: 297178825Sdfr case SOCKET_TYPE_CHAR_UDP: { 298178825Sdfr struct sockaddr_in *in2 = (struct sockaddr_in *)in; 299233294Sstas 300178825Sdfr if ((*len) < sizeof(*in2)) { 301178825Sdfr errno = EINVAL; 302178825Sdfr return -1; 303178825Sdfr } 304178825Sdfr 305178825Sdfr memset(in2, 0, sizeof(*in2)); 306178825Sdfr in2->sin_family = AF_INET; 307178825Sdfr in2->sin_addr.s_addr = htonl((127<<24) | iface); 308178825Sdfr in2->sin_port = htons(prt); 309178825Sdfr 310178825Sdfr *len = sizeof(*in2); 311178825Sdfr break; 312178825Sdfr } 313178825Sdfr#ifdef HAVE_IPV6 314178825Sdfr case SOCKET_TYPE_CHAR_TCP_V6: 315178825Sdfr case SOCKET_TYPE_CHAR_UDP_V6: { 316178825Sdfr struct sockaddr_in6 *in2 = (struct sockaddr_in6 *)in; 317233294Sstas 318178825Sdfr if ((*len) < sizeof(*in2)) { 319178825Sdfr errno = EINVAL; 320178825Sdfr return -1; 321178825Sdfr } 322178825Sdfr 323178825Sdfr memset(in2, 0, sizeof(*in2)); 324178825Sdfr in2->sin6_family = AF_INET6; 325178825Sdfr in2->sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS; 326178825Sdfr in2->sin6_port = htons(prt); 327178825Sdfr 328178825Sdfr *len = sizeof(*in2); 329178825Sdfr break; 330178825Sdfr } 331178825Sdfr#endif 332178825Sdfr default: 333178825Sdfr errno = EINVAL; 334178825Sdfr return -1; 335178825Sdfr } 336178825Sdfr 337178825Sdfr return 0; 338178825Sdfr} 339178825Sdfr 340178825Sdfrstatic int convert_in_un_remote(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un, 341178825Sdfr int *bcast) 342178825Sdfr{ 343178825Sdfr char type = '\0'; 344178825Sdfr unsigned int prt; 345178825Sdfr unsigned int iface; 346178825Sdfr int is_bcast = 0; 347178825Sdfr 348178825Sdfr if (bcast) *bcast = 0; 349178825Sdfr 350178825Sdfr switch (si->family) { 351178825Sdfr case AF_INET: { 352233294Sstas const struct sockaddr_in *in = 353178825Sdfr (const struct sockaddr_in *)inaddr; 354178825Sdfr unsigned int addr = ntohl(in->sin_addr.s_addr); 355178825Sdfr char u_type = '\0'; 356178825Sdfr char b_type = '\0'; 357178825Sdfr char a_type = '\0'; 358178825Sdfr 359178825Sdfr switch (si->type) { 360178825Sdfr case SOCK_STREAM: 361178825Sdfr u_type = SOCKET_TYPE_CHAR_TCP; 362178825Sdfr break; 363178825Sdfr case SOCK_DGRAM: 364178825Sdfr u_type = SOCKET_TYPE_CHAR_UDP; 365178825Sdfr a_type = SOCKET_TYPE_CHAR_UDP; 366178825Sdfr b_type = SOCKET_TYPE_CHAR_UDP; 367178825Sdfr break; 368178825Sdfr } 369178825Sdfr 370178825Sdfr prt = ntohs(in->sin_port); 371178825Sdfr if (a_type && addr == 0xFFFFFFFF) { 372178825Sdfr /* 255.255.255.255 only udp */ 373178825Sdfr is_bcast = 2; 374178825Sdfr type = a_type; 375178825Sdfr iface = socket_wrapper_default_iface(); 376178825Sdfr } else if (b_type && addr == 0x7FFFFFFF) { 377178825Sdfr /* 127.255.255.255 only udp */ 378178825Sdfr is_bcast = 1; 379178825Sdfr type = b_type; 380178825Sdfr iface = socket_wrapper_default_iface(); 381178825Sdfr } else if ((addr & 0xFFFFFF00) == 0x7F000000) { 382178825Sdfr /* 127.0.0.X */ 383178825Sdfr is_bcast = 0; 384178825Sdfr type = u_type; 385178825Sdfr iface = (addr & 0x000000FF); 386178825Sdfr } else { 387178825Sdfr errno = ENETUNREACH; 388178825Sdfr return -1; 389178825Sdfr } 390178825Sdfr if (bcast) *bcast = is_bcast; 391178825Sdfr break; 392178825Sdfr } 393178825Sdfr#ifdef HAVE_IPV6 394178825Sdfr case AF_INET6: { 395233294Sstas const struct sockaddr_in6 *in = 396178825Sdfr (const struct sockaddr_in6 *)inaddr; 397178825Sdfr 398178825Sdfr switch (si->type) { 399178825Sdfr case SOCK_STREAM: 400178825Sdfr type = SOCKET_TYPE_CHAR_TCP_V6; 401178825Sdfr break; 402178825Sdfr case SOCK_DGRAM: 403178825Sdfr type = SOCKET_TYPE_CHAR_UDP_V6; 404178825Sdfr break; 405178825Sdfr } 406178825Sdfr 407178825Sdfr /* XXX no multicast/broadcast */ 408178825Sdfr 409178825Sdfr prt = ntohs(in->sin6_port); 410178825Sdfr iface = SW_IPV6_ADDRESS; 411233294Sstas 412178825Sdfr break; 413178825Sdfr } 414178825Sdfr#endif 415178825Sdfr default: 416178825Sdfr errno = ENETUNREACH; 417178825Sdfr return -1; 418178825Sdfr } 419178825Sdfr 420178825Sdfr if (prt == 0) { 421178825Sdfr errno = EINVAL; 422178825Sdfr return -1; 423178825Sdfr } 424178825Sdfr 425178825Sdfr if (is_bcast) { 426233294Sstas snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL", 427178825Sdfr socket_wrapper_dir()); 428178825Sdfr /* the caller need to do more processing */ 429178825Sdfr return 0; 430178825Sdfr } 431178825Sdfr 432233294Sstas snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 433178825Sdfr socket_wrapper_dir(), type, iface, prt); 434178825Sdfr 435178825Sdfr return 0; 436178825Sdfr} 437178825Sdfr 438178825Sdfrstatic int convert_in_un_alloc(struct socket_info *si, const struct sockaddr *inaddr, struct sockaddr_un *un, 439178825Sdfr int *bcast) 440178825Sdfr{ 441178825Sdfr char type = '\0'; 442178825Sdfr unsigned int prt; 443178825Sdfr unsigned int iface; 444178825Sdfr struct stat st; 445178825Sdfr int is_bcast = 0; 446178825Sdfr 447178825Sdfr if (bcast) *bcast = 0; 448178825Sdfr 449178825Sdfr switch (si->family) { 450178825Sdfr case AF_INET: { 451233294Sstas const struct sockaddr_in *in = 452178825Sdfr (const struct sockaddr_in *)inaddr; 453178825Sdfr unsigned int addr = ntohl(in->sin_addr.s_addr); 454178825Sdfr char u_type = '\0'; 455178825Sdfr char d_type = '\0'; 456178825Sdfr char b_type = '\0'; 457178825Sdfr char a_type = '\0'; 458178825Sdfr 459178825Sdfr prt = ntohs(in->sin_port); 460178825Sdfr 461178825Sdfr switch (si->type) { 462178825Sdfr case SOCK_STREAM: 463178825Sdfr u_type = SOCKET_TYPE_CHAR_TCP; 464178825Sdfr d_type = SOCKET_TYPE_CHAR_TCP; 465178825Sdfr break; 466178825Sdfr case SOCK_DGRAM: 467178825Sdfr u_type = SOCKET_TYPE_CHAR_UDP; 468178825Sdfr d_type = SOCKET_TYPE_CHAR_UDP; 469178825Sdfr a_type = SOCKET_TYPE_CHAR_UDP; 470178825Sdfr b_type = SOCKET_TYPE_CHAR_UDP; 471178825Sdfr break; 472178825Sdfr } 473178825Sdfr 474178825Sdfr if (addr == 0) { 475178825Sdfr /* 0.0.0.0 */ 476178825Sdfr is_bcast = 0; 477178825Sdfr type = d_type; 478178825Sdfr iface = socket_wrapper_default_iface(); 479178825Sdfr } else if (a_type && addr == 0xFFFFFFFF) { 480178825Sdfr /* 255.255.255.255 only udp */ 481178825Sdfr is_bcast = 2; 482178825Sdfr type = a_type; 483178825Sdfr iface = socket_wrapper_default_iface(); 484178825Sdfr } else if (b_type && addr == 0x7FFFFFFF) { 485178825Sdfr /* 127.255.255.255 only udp */ 486178825Sdfr is_bcast = 1; 487178825Sdfr type = b_type; 488178825Sdfr iface = socket_wrapper_default_iface(); 489178825Sdfr } else if ((addr & 0xFFFFFF00) == 0x7F000000) { 490178825Sdfr /* 127.0.0.X */ 491178825Sdfr is_bcast = 0; 492178825Sdfr type = u_type; 493178825Sdfr iface = (addr & 0x000000FF); 494178825Sdfr } else { 495178825Sdfr errno = EADDRNOTAVAIL; 496178825Sdfr return -1; 497178825Sdfr } 498178825Sdfr break; 499178825Sdfr } 500178825Sdfr#ifdef HAVE_IPV6 501178825Sdfr case AF_INET6: { 502233294Sstas const struct sockaddr_in6 *in = 503178825Sdfr (const struct sockaddr_in6 *)inaddr; 504178825Sdfr 505178825Sdfr switch (si->type) { 506178825Sdfr case SOCK_STREAM: 507178825Sdfr type = SOCKET_TYPE_CHAR_TCP_V6; 508178825Sdfr break; 509178825Sdfr case SOCK_DGRAM: 510178825Sdfr type = SOCKET_TYPE_CHAR_UDP_V6; 511178825Sdfr break; 512178825Sdfr } 513178825Sdfr 514178825Sdfr /* XXX no multicast/broadcast */ 515178825Sdfr 516178825Sdfr prt = ntohs(in->sin6_port); 517178825Sdfr iface = SW_IPV6_ADDRESS; 518233294Sstas 519178825Sdfr break; 520178825Sdfr } 521178825Sdfr#endif 522178825Sdfr default: 523178825Sdfr errno = ENETUNREACH; 524178825Sdfr return -1; 525178825Sdfr } 526178825Sdfr 527178825Sdfr 528178825Sdfr if (bcast) *bcast = is_bcast; 529178825Sdfr 530178825Sdfr if (prt == 0) { 531178825Sdfr /* handle auto-allocation of ephemeral ports */ 532178825Sdfr for (prt = 5001; prt < 10000; prt++) { 533233294Sstas snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 534178825Sdfr socket_wrapper_dir(), type, iface, prt); 535178825Sdfr if (stat(un->sun_path, &st) == 0) continue; 536178825Sdfr 537178825Sdfr set_port(si->family, prt, si->myname); 538178825Sdfr } 539178825Sdfr } 540178825Sdfr 541233294Sstas snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT, 542178825Sdfr socket_wrapper_dir(), type, iface, prt); 543178825Sdfr return 0; 544178825Sdfr} 545178825Sdfr 546178825Sdfrstatic struct socket_info *find_socket_info(int fd) 547178825Sdfr{ 548178825Sdfr struct socket_info *i; 549178825Sdfr for (i = sockets; i; i = i->next) { 550233294Sstas if (i->fd == fd) 551178825Sdfr return i; 552178825Sdfr } 553178825Sdfr 554178825Sdfr return NULL; 555178825Sdfr} 556178825Sdfr 557233294Sstasstatic int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, 558178825Sdfr struct sockaddr_un *out_addr, int alloc_sock, int *bcast) 559178825Sdfr{ 560178825Sdfr if (!out_addr) 561178825Sdfr return 0; 562178825Sdfr 563178825Sdfr out_addr->sun_family = AF_UNIX; 564178825Sdfr 565178825Sdfr switch (in_addr->sa_family) { 566178825Sdfr case AF_INET: 567178825Sdfr#ifdef HAVE_IPV6 568178825Sdfr case AF_INET6: 569178825Sdfr#endif 570178825Sdfr switch (si->type) { 571178825Sdfr case SOCK_STREAM: 572178825Sdfr case SOCK_DGRAM: 573178825Sdfr break; 574178825Sdfr default: 575178825Sdfr errno = ESOCKTNOSUPPORT; 576178825Sdfr return -1; 577178825Sdfr } 578178825Sdfr if (alloc_sock) { 579178825Sdfr return convert_in_un_alloc(si, in_addr, out_addr, bcast); 580178825Sdfr } else { 581178825Sdfr return convert_in_un_remote(si, in_addr, out_addr, bcast); 582178825Sdfr } 583178825Sdfr default: 584178825Sdfr break; 585178825Sdfr } 586233294Sstas 587178825Sdfr errno = EAFNOSUPPORT; 588178825Sdfr return -1; 589178825Sdfr} 590178825Sdfr 591233294Sstasstatic int sockaddr_convert_from_un(const struct socket_info *si, 592233294Sstas const struct sockaddr_un *in_addr, 593178825Sdfr socklen_t un_addrlen, 594178825Sdfr int family, 595178825Sdfr struct sockaddr *out_addr, 596178825Sdfr socklen_t *out_addrlen) 597178825Sdfr{ 598233294Sstas if (out_addr == NULL || out_addrlen == NULL) 599178825Sdfr return 0; 600178825Sdfr 601178825Sdfr if (un_addrlen == 0) { 602178825Sdfr *out_addrlen = 0; 603178825Sdfr return 0; 604178825Sdfr } 605178825Sdfr 606178825Sdfr switch (family) { 607178825Sdfr case AF_INET: 608178825Sdfr#ifdef HAVE_IPV6 609178825Sdfr case AF_INET6: 610178825Sdfr#endif 611178825Sdfr switch (si->type) { 612178825Sdfr case SOCK_STREAM: 613178825Sdfr case SOCK_DGRAM: 614178825Sdfr break; 615178825Sdfr default: 616178825Sdfr errno = ESOCKTNOSUPPORT; 617178825Sdfr return -1; 618178825Sdfr } 619178825Sdfr return convert_un_in(in_addr, out_addr, out_addrlen); 620178825Sdfr default: 621178825Sdfr break; 622178825Sdfr } 623178825Sdfr 624178825Sdfr errno = EAFNOSUPPORT; 625178825Sdfr return -1; 626178825Sdfr} 627178825Sdfr 628178825Sdfrenum swrap_packet_type { 629178825Sdfr SWRAP_CONNECT_SEND, 630178825Sdfr SWRAP_CONNECT_UNREACH, 631178825Sdfr SWRAP_CONNECT_RECV, 632178825Sdfr SWRAP_CONNECT_ACK, 633178825Sdfr SWRAP_ACCEPT_SEND, 634178825Sdfr SWRAP_ACCEPT_RECV, 635178825Sdfr SWRAP_ACCEPT_ACK, 636178825Sdfr SWRAP_RECVFROM, 637178825Sdfr SWRAP_SENDTO, 638178825Sdfr SWRAP_SENDTO_UNREACH, 639178825Sdfr SWRAP_PENDING_RST, 640178825Sdfr SWRAP_RECV, 641178825Sdfr SWRAP_RECV_RST, 642178825Sdfr SWRAP_SEND, 643178825Sdfr SWRAP_SEND_RST, 644178825Sdfr SWRAP_CLOSE_SEND, 645178825Sdfr SWRAP_CLOSE_RECV, 646178825Sdfr SWRAP_CLOSE_ACK 647178825Sdfr}; 648178825Sdfr 649178825Sdfrstruct swrap_file_hdr { 650178825Sdfr unsigned long magic; 651233294Sstas unsigned short version_major; 652178825Sdfr unsigned short version_minor; 653178825Sdfr long timezone; 654178825Sdfr unsigned long sigfigs; 655178825Sdfr unsigned long frame_max_len; 656178825Sdfr#define SWRAP_FRAME_LENGTH_MAX 0xFFFF 657178825Sdfr unsigned long link_type; 658178825Sdfr}; 659178825Sdfr#define SWRAP_FILE_HDR_SIZE 24 660178825Sdfr 661178825Sdfrstruct swrap_packet { 662178825Sdfr struct { 663178825Sdfr unsigned long seconds; 664178825Sdfr unsigned long micro_seconds; 665178825Sdfr unsigned long recorded_length; 666178825Sdfr unsigned long full_length; 667178825Sdfr } frame; 668178825Sdfr#define SWRAP_PACKET__FRAME_SIZE 16 669178825Sdfr 670178825Sdfr struct { 671178825Sdfr struct { 672178825Sdfr unsigned char ver_hdrlen; 673178825Sdfr unsigned char tos; 674178825Sdfr unsigned short packet_length; 675178825Sdfr unsigned short identification; 676178825Sdfr unsigned char flags; 677178825Sdfr unsigned char fragment; 678178825Sdfr unsigned char ttl; 679178825Sdfr unsigned char protocol; 680178825Sdfr unsigned short hdr_checksum; 681178825Sdfr unsigned long src_addr; 682178825Sdfr unsigned long dest_addr; 683178825Sdfr } hdr; 684178825Sdfr#define SWRAP_PACKET__IP_HDR_SIZE 20 685178825Sdfr 686178825Sdfr union { 687178825Sdfr struct { 688178825Sdfr unsigned short source_port; 689178825Sdfr unsigned short dest_port; 690178825Sdfr unsigned long seq_num; 691178825Sdfr unsigned long ack_num; 692178825Sdfr unsigned char hdr_length; 693178825Sdfr unsigned char control; 694178825Sdfr unsigned short window; 695178825Sdfr unsigned short checksum; 696178825Sdfr unsigned short urg; 697178825Sdfr } tcp; 698178825Sdfr#define SWRAP_PACKET__IP_P_TCP_SIZE 20 699178825Sdfr struct { 700178825Sdfr unsigned short source_port; 701178825Sdfr unsigned short dest_port; 702178825Sdfr unsigned short length; 703178825Sdfr unsigned short checksum; 704178825Sdfr } udp; 705178825Sdfr#define SWRAP_PACKET__IP_P_UDP_SIZE 8 706178825Sdfr struct { 707178825Sdfr unsigned char type; 708178825Sdfr unsigned char code; 709178825Sdfr unsigned short checksum; 710178825Sdfr unsigned long unused; 711178825Sdfr } icmp; 712178825Sdfr#define SWRAP_PACKET__IP_P_ICMP_SIZE 8 713178825Sdfr } p; 714178825Sdfr } ip; 715178825Sdfr}; 716178825Sdfr#define SWRAP_PACKET_SIZE 56 717178825Sdfr 718178825Sdfrstatic const char *socket_wrapper_pcap_file(void) 719178825Sdfr{ 720178825Sdfr static int initialized = 0; 721178825Sdfr static const char *s = NULL; 722178825Sdfr static const struct swrap_file_hdr h; 723178825Sdfr static const struct swrap_packet p; 724178825Sdfr 725178825Sdfr if (initialized == 1) { 726178825Sdfr return s; 727178825Sdfr } 728178825Sdfr initialized = 1; 729178825Sdfr 730178825Sdfr /* 731178825Sdfr * TODO: don't use the structs use plain buffer offsets 732178825Sdfr * and PUSH_U8(), PUSH_U16() and PUSH_U32() 733233294Sstas * 734178825Sdfr * for now make sure we disable PCAP support 735178825Sdfr * if the struct has alignment! 736178825Sdfr */ 737178825Sdfr if (sizeof(h) != SWRAP_FILE_HDR_SIZE) { 738178825Sdfr return NULL; 739178825Sdfr } 740178825Sdfr if (sizeof(p) != SWRAP_PACKET_SIZE) { 741178825Sdfr return NULL; 742178825Sdfr } 743178825Sdfr if (sizeof(p.frame) != SWRAP_PACKET__FRAME_SIZE) { 744178825Sdfr return NULL; 745178825Sdfr } 746178825Sdfr if (sizeof(p.ip.hdr) != SWRAP_PACKET__IP_HDR_SIZE) { 747178825Sdfr return NULL; 748178825Sdfr } 749178825Sdfr if (sizeof(p.ip.p.tcp) != SWRAP_PACKET__IP_P_TCP_SIZE) { 750178825Sdfr return NULL; 751178825Sdfr } 752178825Sdfr if (sizeof(p.ip.p.udp) != SWRAP_PACKET__IP_P_UDP_SIZE) { 753178825Sdfr return NULL; 754178825Sdfr } 755178825Sdfr if (sizeof(p.ip.p.icmp) != SWRAP_PACKET__IP_P_ICMP_SIZE) { 756178825Sdfr return NULL; 757178825Sdfr } 758178825Sdfr 759178825Sdfr s = getenv("SOCKET_WRAPPER_PCAP_FILE"); 760178825Sdfr if (s == NULL) { 761178825Sdfr return NULL; 762178825Sdfr } 763178825Sdfr if (strncmp(s, "./", 2) == 0) { 764178825Sdfr s += 2; 765178825Sdfr } 766178825Sdfr return s; 767178825Sdfr} 768178825Sdfr 769178825Sdfrstatic struct swrap_packet *swrap_packet_init(struct timeval *tval, 770178825Sdfr const struct sockaddr_in *src_addr, 771178825Sdfr const struct sockaddr_in *dest_addr, 772178825Sdfr int socket_type, 773178825Sdfr const unsigned char *payload, 774178825Sdfr size_t payload_len, 775178825Sdfr unsigned long tcp_seq, 776178825Sdfr unsigned long tcp_ack, 777178825Sdfr unsigned char tcp_ctl, 778178825Sdfr int unreachable, 779178825Sdfr size_t *_packet_len) 780178825Sdfr{ 781178825Sdfr struct swrap_packet *ret; 782178825Sdfr struct swrap_packet *packet; 783178825Sdfr size_t packet_len; 784178825Sdfr size_t alloc_len; 785178825Sdfr size_t nonwire_len = sizeof(packet->frame); 786178825Sdfr size_t wire_hdr_len = 0; 787178825Sdfr size_t wire_len = 0; 788178825Sdfr size_t icmp_hdr_len = 0; 789178825Sdfr size_t icmp_truncate_len = 0; 790178825Sdfr unsigned char protocol = 0, icmp_protocol = 0; 791178825Sdfr unsigned short src_port = src_addr->sin_port; 792178825Sdfr unsigned short dest_port = dest_addr->sin_port; 793178825Sdfr 794178825Sdfr switch (socket_type) { 795178825Sdfr case SOCK_STREAM: 796178825Sdfr protocol = 0x06; /* TCP */ 797178825Sdfr wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.tcp); 798178825Sdfr wire_len = wire_hdr_len + payload_len; 799178825Sdfr break; 800178825Sdfr 801178825Sdfr case SOCK_DGRAM: 802178825Sdfr protocol = 0x11; /* UDP */ 803178825Sdfr wire_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.udp); 804178825Sdfr wire_len = wire_hdr_len + payload_len; 805178825Sdfr break; 806178825Sdfr } 807178825Sdfr 808178825Sdfr if (unreachable) { 809178825Sdfr icmp_protocol = protocol; 810178825Sdfr protocol = 0x01; /* ICMP */ 811178825Sdfr if (wire_len > 64 ) { 812178825Sdfr icmp_truncate_len = wire_len - 64; 813178825Sdfr } 814178825Sdfr icmp_hdr_len = sizeof(packet->ip.hdr) + sizeof(packet->ip.p.icmp); 815178825Sdfr wire_hdr_len += icmp_hdr_len; 816178825Sdfr wire_len += icmp_hdr_len; 817178825Sdfr } 818178825Sdfr 819178825Sdfr packet_len = nonwire_len + wire_len; 820178825Sdfr alloc_len = packet_len; 821178825Sdfr if (alloc_len < sizeof(struct swrap_packet)) { 822178825Sdfr alloc_len = sizeof(struct swrap_packet); 823178825Sdfr } 824178825Sdfr ret = (struct swrap_packet *)malloc(alloc_len); 825178825Sdfr if (!ret) return NULL; 826178825Sdfr 827178825Sdfr packet = ret; 828178825Sdfr 829178825Sdfr packet->frame.seconds = tval->tv_sec; 830178825Sdfr packet->frame.micro_seconds = tval->tv_usec; 831178825Sdfr packet->frame.recorded_length = wire_len - icmp_truncate_len; 832178825Sdfr packet->frame.full_length = wire_len - icmp_truncate_len; 833178825Sdfr 834178825Sdfr packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */ 835178825Sdfr packet->ip.hdr.tos = 0x00; 836178825Sdfr packet->ip.hdr.packet_length = htons(wire_len - icmp_truncate_len); 837178825Sdfr packet->ip.hdr.identification = htons(0xFFFF); 838178825Sdfr packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */ 839178825Sdfr packet->ip.hdr.fragment = htons(0x0000); 840178825Sdfr packet->ip.hdr.ttl = 0xFF; 841178825Sdfr packet->ip.hdr.protocol = protocol; 842178825Sdfr packet->ip.hdr.hdr_checksum = htons(0x0000); 843178825Sdfr packet->ip.hdr.src_addr = src_addr->sin_addr.s_addr; 844178825Sdfr packet->ip.hdr.dest_addr = dest_addr->sin_addr.s_addr; 845178825Sdfr 846178825Sdfr if (unreachable) { 847178825Sdfr packet->ip.p.icmp.type = 0x03; /* destination unreachable */ 848178825Sdfr packet->ip.p.icmp.code = 0x01; /* host unreachable */ 849178825Sdfr packet->ip.p.icmp.checksum = htons(0x0000); 850178825Sdfr packet->ip.p.icmp.unused = htonl(0x00000000); 851178825Sdfr 852178825Sdfr /* set the ip header in the ICMP payload */ 853178825Sdfr packet = (struct swrap_packet *)(((unsigned char *)ret) + icmp_hdr_len); 854178825Sdfr packet->ip.hdr.ver_hdrlen = 0x45; /* version 4 and 5 * 32 bit words */ 855178825Sdfr packet->ip.hdr.tos = 0x00; 856178825Sdfr packet->ip.hdr.packet_length = htons(wire_len - icmp_hdr_len); 857178825Sdfr packet->ip.hdr.identification = htons(0xFFFF); 858178825Sdfr packet->ip.hdr.flags = 0x40; /* BIT 1 set - means don't fraqment */ 859178825Sdfr packet->ip.hdr.fragment = htons(0x0000); 860178825Sdfr packet->ip.hdr.ttl = 0xFF; 861178825Sdfr packet->ip.hdr.protocol = icmp_protocol; 862178825Sdfr packet->ip.hdr.hdr_checksum = htons(0x0000); 863178825Sdfr packet->ip.hdr.src_addr = dest_addr->sin_addr.s_addr; 864178825Sdfr packet->ip.hdr.dest_addr = src_addr->sin_addr.s_addr; 865178825Sdfr 866178825Sdfr src_port = dest_addr->sin_port; 867178825Sdfr dest_port = src_addr->sin_port; 868178825Sdfr } 869178825Sdfr 870178825Sdfr switch (socket_type) { 871178825Sdfr case SOCK_STREAM: 872178825Sdfr packet->ip.p.tcp.source_port = src_port; 873178825Sdfr packet->ip.p.tcp.dest_port = dest_port; 874178825Sdfr packet->ip.p.tcp.seq_num = htonl(tcp_seq); 875178825Sdfr packet->ip.p.tcp.ack_num = htonl(tcp_ack); 876178825Sdfr packet->ip.p.tcp.hdr_length = 0x50; /* 5 * 32 bit words */ 877178825Sdfr packet->ip.p.tcp.control = tcp_ctl; 878178825Sdfr packet->ip.p.tcp.window = htons(0x7FFF); 879178825Sdfr packet->ip.p.tcp.checksum = htons(0x0000); 880178825Sdfr packet->ip.p.tcp.urg = htons(0x0000); 881178825Sdfr 882178825Sdfr break; 883178825Sdfr 884178825Sdfr case SOCK_DGRAM: 885178825Sdfr packet->ip.p.udp.source_port = src_addr->sin_port; 886178825Sdfr packet->ip.p.udp.dest_port = dest_addr->sin_port; 887178825Sdfr packet->ip.p.udp.length = htons(8 + payload_len); 888178825Sdfr packet->ip.p.udp.checksum = htons(0x0000); 889178825Sdfr 890178825Sdfr break; 891178825Sdfr } 892178825Sdfr 893178825Sdfr if (payload && payload_len > 0) { 894178825Sdfr unsigned char *p = (unsigned char *)ret; 895178825Sdfr p += nonwire_len; 896178825Sdfr p += wire_hdr_len; 897178825Sdfr memcpy(p, payload, payload_len); 898178825Sdfr } 899178825Sdfr 900178825Sdfr *_packet_len = packet_len - icmp_truncate_len; 901178825Sdfr return ret; 902178825Sdfr} 903178825Sdfr 904178825Sdfrstatic int swrap_get_pcap_fd(const char *fname) 905178825Sdfr{ 906178825Sdfr static int fd = -1; 907178825Sdfr 908178825Sdfr if (fd != -1) return fd; 909178825Sdfr 910178825Sdfr fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0644); 911178825Sdfr if (fd != -1) { 912178825Sdfr struct swrap_file_hdr file_hdr; 913178825Sdfr file_hdr.magic = 0xA1B2C3D4; 914233294Sstas file_hdr.version_major = 0x0002; 915178825Sdfr file_hdr.version_minor = 0x0004; 916178825Sdfr file_hdr.timezone = 0x00000000; 917178825Sdfr file_hdr.sigfigs = 0x00000000; 918178825Sdfr file_hdr.frame_max_len = SWRAP_FRAME_LENGTH_MAX; 919178825Sdfr file_hdr.link_type = 0x0065; /* 101 RAW IP */ 920178825Sdfr 921178825Sdfr write(fd, &file_hdr, sizeof(file_hdr)); 922178825Sdfr return fd; 923178825Sdfr } 924178825Sdfr 925178825Sdfr fd = open(fname, O_WRONLY|O_APPEND, 0644); 926178825Sdfr 927178825Sdfr return fd; 928178825Sdfr} 929178825Sdfr 930178825Sdfrstatic void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr, 931178825Sdfr enum swrap_packet_type type, 932178825Sdfr const void *buf, size_t len) 933178825Sdfr{ 934178825Sdfr const struct sockaddr_in *src_addr; 935178825Sdfr const struct sockaddr_in *dest_addr; 936178825Sdfr const char *file_name; 937178825Sdfr unsigned long tcp_seq = 0; 938178825Sdfr unsigned long tcp_ack = 0; 939178825Sdfr unsigned char tcp_ctl = 0; 940178825Sdfr int unreachable = 0; 941178825Sdfr struct timeval tv; 942178825Sdfr struct swrap_packet *packet; 943178825Sdfr size_t packet_len = 0; 944178825Sdfr int fd; 945178825Sdfr 946178825Sdfr file_name = socket_wrapper_pcap_file(); 947178825Sdfr if (!file_name) { 948178825Sdfr return; 949178825Sdfr } 950178825Sdfr 951178825Sdfr switch (si->family) { 952178825Sdfr case AF_INET: 953178825Sdfr#ifdef HAVE_IPV6 954178825Sdfr case AF_INET6: 955178825Sdfr#endif 956178825Sdfr break; 957178825Sdfr default: 958178825Sdfr return; 959178825Sdfr } 960178825Sdfr 961178825Sdfr switch (type) { 962178825Sdfr case SWRAP_CONNECT_SEND: 963178825Sdfr if (si->type != SOCK_STREAM) return; 964178825Sdfr 965178825Sdfr src_addr = (const struct sockaddr_in *)si->myname; 966178825Sdfr dest_addr = (const struct sockaddr_in *)addr; 967178825Sdfr 968178825Sdfr tcp_seq = si->io.pck_snd; 969178825Sdfr tcp_ack = si->io.pck_rcv; 970178825Sdfr tcp_ctl = 0x02; /* SYN */ 971178825Sdfr 972178825Sdfr si->io.pck_snd += 1; 973178825Sdfr 974178825Sdfr break; 975178825Sdfr 976178825Sdfr case SWRAP_CONNECT_RECV: 977178825Sdfr if (si->type != SOCK_STREAM) return; 978178825Sdfr 979178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 980178825Sdfr src_addr = (const struct sockaddr_in *)addr; 981178825Sdfr 982178825Sdfr tcp_seq = si->io.pck_rcv; 983178825Sdfr tcp_ack = si->io.pck_snd; 984178825Sdfr tcp_ctl = 0x12; /** SYN,ACK */ 985178825Sdfr 986178825Sdfr si->io.pck_rcv += 1; 987178825Sdfr 988178825Sdfr break; 989178825Sdfr 990178825Sdfr case SWRAP_CONNECT_UNREACH: 991178825Sdfr if (si->type != SOCK_STREAM) return; 992178825Sdfr 993178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 994178825Sdfr src_addr = (const struct sockaddr_in *)addr; 995178825Sdfr 996178825Sdfr /* Unreachable: resend the data of SWRAP_CONNECT_SEND */ 997178825Sdfr tcp_seq = si->io.pck_snd - 1; 998178825Sdfr tcp_ack = si->io.pck_rcv; 999178825Sdfr tcp_ctl = 0x02; /* SYN */ 1000178825Sdfr unreachable = 1; 1001178825Sdfr 1002178825Sdfr break; 1003178825Sdfr 1004178825Sdfr case SWRAP_CONNECT_ACK: 1005178825Sdfr if (si->type != SOCK_STREAM) return; 1006178825Sdfr 1007178825Sdfr src_addr = (const struct sockaddr_in *)si->myname; 1008178825Sdfr dest_addr = (const struct sockaddr_in *)addr; 1009178825Sdfr 1010178825Sdfr tcp_seq = si->io.pck_snd; 1011178825Sdfr tcp_ack = si->io.pck_rcv; 1012178825Sdfr tcp_ctl = 0x10; /* ACK */ 1013178825Sdfr 1014178825Sdfr break; 1015178825Sdfr 1016178825Sdfr case SWRAP_ACCEPT_SEND: 1017178825Sdfr if (si->type != SOCK_STREAM) return; 1018178825Sdfr 1019178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 1020178825Sdfr src_addr = (const struct sockaddr_in *)addr; 1021178825Sdfr 1022178825Sdfr tcp_seq = si->io.pck_rcv; 1023178825Sdfr tcp_ack = si->io.pck_snd; 1024178825Sdfr tcp_ctl = 0x02; /* SYN */ 1025178825Sdfr 1026178825Sdfr si->io.pck_rcv += 1; 1027178825Sdfr 1028178825Sdfr break; 1029178825Sdfr 1030178825Sdfr case SWRAP_ACCEPT_RECV: 1031178825Sdfr if (si->type != SOCK_STREAM) return; 1032178825Sdfr 1033178825Sdfr src_addr = (const struct sockaddr_in *)si->myname; 1034178825Sdfr dest_addr = (const struct sockaddr_in *)addr; 1035178825Sdfr 1036178825Sdfr tcp_seq = si->io.pck_snd; 1037178825Sdfr tcp_ack = si->io.pck_rcv; 1038178825Sdfr tcp_ctl = 0x12; /* SYN,ACK */ 1039178825Sdfr 1040178825Sdfr si->io.pck_snd += 1; 1041178825Sdfr 1042178825Sdfr break; 1043178825Sdfr 1044178825Sdfr case SWRAP_ACCEPT_ACK: 1045178825Sdfr if (si->type != SOCK_STREAM) return; 1046178825Sdfr 1047178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 1048178825Sdfr src_addr = (const struct sockaddr_in *)addr; 1049178825Sdfr 1050178825Sdfr tcp_seq = si->io.pck_rcv; 1051178825Sdfr tcp_ack = si->io.pck_snd; 1052178825Sdfr tcp_ctl = 0x10; /* ACK */ 1053178825Sdfr 1054178825Sdfr break; 1055178825Sdfr 1056178825Sdfr case SWRAP_SEND: 1057178825Sdfr src_addr = (const struct sockaddr_in *)si->myname; 1058178825Sdfr dest_addr = (const struct sockaddr_in *)si->peername; 1059178825Sdfr 1060178825Sdfr tcp_seq = si->io.pck_snd; 1061178825Sdfr tcp_ack = si->io.pck_rcv; 1062178825Sdfr tcp_ctl = 0x18; /* PSH,ACK */ 1063178825Sdfr 1064178825Sdfr si->io.pck_snd += len; 1065178825Sdfr 1066178825Sdfr break; 1067178825Sdfr 1068178825Sdfr case SWRAP_SEND_RST: 1069178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 1070178825Sdfr src_addr = (const struct sockaddr_in *)si->peername; 1071178825Sdfr 1072178825Sdfr if (si->type == SOCK_DGRAM) { 1073178825Sdfr swrap_dump_packet(si, si->peername, 1074178825Sdfr SWRAP_SENDTO_UNREACH, 1075178825Sdfr buf, len); 1076178825Sdfr return; 1077178825Sdfr } 1078178825Sdfr 1079178825Sdfr tcp_seq = si->io.pck_rcv; 1080178825Sdfr tcp_ack = si->io.pck_snd; 1081178825Sdfr tcp_ctl = 0x14; /** RST,ACK */ 1082178825Sdfr 1083178825Sdfr break; 1084178825Sdfr 1085178825Sdfr case SWRAP_PENDING_RST: 1086178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 1087178825Sdfr src_addr = (const struct sockaddr_in *)si->peername; 1088178825Sdfr 1089178825Sdfr if (si->type == SOCK_DGRAM) { 1090178825Sdfr return; 1091178825Sdfr } 1092178825Sdfr 1093178825Sdfr tcp_seq = si->io.pck_rcv; 1094178825Sdfr tcp_ack = si->io.pck_snd; 1095178825Sdfr tcp_ctl = 0x14; /* RST,ACK */ 1096178825Sdfr 1097178825Sdfr break; 1098178825Sdfr 1099178825Sdfr case SWRAP_RECV: 1100178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 1101178825Sdfr src_addr = (const struct sockaddr_in *)si->peername; 1102178825Sdfr 1103178825Sdfr tcp_seq = si->io.pck_rcv; 1104178825Sdfr tcp_ack = si->io.pck_snd; 1105178825Sdfr tcp_ctl = 0x18; /* PSH,ACK */ 1106178825Sdfr 1107178825Sdfr si->io.pck_rcv += len; 1108178825Sdfr 1109178825Sdfr break; 1110178825Sdfr 1111178825Sdfr case SWRAP_RECV_RST: 1112178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 1113178825Sdfr src_addr = (const struct sockaddr_in *)si->peername; 1114178825Sdfr 1115178825Sdfr if (si->type == SOCK_DGRAM) { 1116178825Sdfr return; 1117178825Sdfr } 1118178825Sdfr 1119178825Sdfr tcp_seq = si->io.pck_rcv; 1120178825Sdfr tcp_ack = si->io.pck_snd; 1121178825Sdfr tcp_ctl = 0x14; /* RST,ACK */ 1122178825Sdfr 1123178825Sdfr break; 1124178825Sdfr 1125178825Sdfr case SWRAP_SENDTO: 1126178825Sdfr src_addr = (const struct sockaddr_in *)si->myname; 1127178825Sdfr dest_addr = (const struct sockaddr_in *)addr; 1128178825Sdfr 1129178825Sdfr si->io.pck_snd += len; 1130178825Sdfr 1131178825Sdfr break; 1132178825Sdfr 1133178825Sdfr case SWRAP_SENDTO_UNREACH: 1134178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 1135178825Sdfr src_addr = (const struct sockaddr_in *)addr; 1136178825Sdfr 1137178825Sdfr unreachable = 1; 1138178825Sdfr 1139178825Sdfr break; 1140178825Sdfr 1141178825Sdfr case SWRAP_RECVFROM: 1142178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 1143178825Sdfr src_addr = (const struct sockaddr_in *)addr; 1144178825Sdfr 1145178825Sdfr si->io.pck_rcv += len; 1146178825Sdfr 1147178825Sdfr break; 1148178825Sdfr 1149178825Sdfr case SWRAP_CLOSE_SEND: 1150178825Sdfr if (si->type != SOCK_STREAM) return; 1151178825Sdfr 1152178825Sdfr src_addr = (const struct sockaddr_in *)si->myname; 1153178825Sdfr dest_addr = (const struct sockaddr_in *)si->peername; 1154178825Sdfr 1155178825Sdfr tcp_seq = si->io.pck_snd; 1156178825Sdfr tcp_ack = si->io.pck_rcv; 1157178825Sdfr tcp_ctl = 0x11; /* FIN, ACK */ 1158178825Sdfr 1159178825Sdfr si->io.pck_snd += 1; 1160178825Sdfr 1161178825Sdfr break; 1162178825Sdfr 1163178825Sdfr case SWRAP_CLOSE_RECV: 1164178825Sdfr if (si->type != SOCK_STREAM) return; 1165178825Sdfr 1166178825Sdfr dest_addr = (const struct sockaddr_in *)si->myname; 1167178825Sdfr src_addr = (const struct sockaddr_in *)si->peername; 1168178825Sdfr 1169178825Sdfr tcp_seq = si->io.pck_rcv; 1170178825Sdfr tcp_ack = si->io.pck_snd; 1171178825Sdfr tcp_ctl = 0x11; /* FIN,ACK */ 1172178825Sdfr 1173178825Sdfr si->io.pck_rcv += 1; 1174178825Sdfr 1175178825Sdfr break; 1176178825Sdfr 1177178825Sdfr case SWRAP_CLOSE_ACK: 1178178825Sdfr if (si->type != SOCK_STREAM) return; 1179178825Sdfr 1180178825Sdfr src_addr = (const struct sockaddr_in *)si->myname; 1181178825Sdfr dest_addr = (const struct sockaddr_in *)si->peername; 1182178825Sdfr 1183178825Sdfr tcp_seq = si->io.pck_snd; 1184178825Sdfr tcp_ack = si->io.pck_rcv; 1185178825Sdfr tcp_ctl = 0x10; /* ACK */ 1186178825Sdfr 1187178825Sdfr break; 1188178825Sdfr default: 1189178825Sdfr return; 1190178825Sdfr } 1191178825Sdfr 1192178825Sdfr swrapGetTimeOfDay(&tv); 1193178825Sdfr 1194178825Sdfr packet = swrap_packet_init(&tv, src_addr, dest_addr, si->type, 1195178825Sdfr (const unsigned char *)buf, len, 1196178825Sdfr tcp_seq, tcp_ack, tcp_ctl, unreachable, 1197178825Sdfr &packet_len); 1198178825Sdfr if (!packet) { 1199178825Sdfr return; 1200178825Sdfr } 1201178825Sdfr 1202178825Sdfr fd = swrap_get_pcap_fd(file_name); 1203178825Sdfr if (fd != -1) { 1204178825Sdfr write(fd, packet, packet_len); 1205178825Sdfr } 1206178825Sdfr 1207178825Sdfr free(packet); 1208178825Sdfr} 1209178825Sdfr 1210178825Sdfr_PUBLIC_ int swrap_socket(int family, int type, int protocol) 1211178825Sdfr{ 1212178825Sdfr struct socket_info *si; 1213178825Sdfr int fd; 1214178825Sdfr 1215178825Sdfr if (!socket_wrapper_dir()) { 1216178825Sdfr return real_socket(family, type, protocol); 1217178825Sdfr } 1218178825Sdfr 1219178825Sdfr switch (family) { 1220178825Sdfr case AF_INET: 1221178825Sdfr#ifdef HAVE_IPV6 1222178825Sdfr case AF_INET6: 1223178825Sdfr#endif 1224178825Sdfr break; 1225178825Sdfr case AF_UNIX: 1226178825Sdfr return real_socket(family, type, protocol); 1227178825Sdfr default: 1228178825Sdfr errno = EAFNOSUPPORT; 1229178825Sdfr return -1; 1230178825Sdfr } 1231178825Sdfr 1232178825Sdfr switch (type) { 1233178825Sdfr case SOCK_STREAM: 1234178825Sdfr break; 1235178825Sdfr case SOCK_DGRAM: 1236178825Sdfr break; 1237178825Sdfr default: 1238178825Sdfr errno = EPROTONOSUPPORT; 1239178825Sdfr return -1; 1240178825Sdfr } 1241178825Sdfr 1242178825Sdfr#if 0 1243178825Sdfr switch (protocol) { 1244178825Sdfr case 0: 1245178825Sdfr break; 1246178825Sdfr default: 1247178825Sdfr errno = EPROTONOSUPPORT; 1248178825Sdfr return -1; 1249178825Sdfr } 1250178825Sdfr#endif 1251178825Sdfr 1252178825Sdfr fd = real_socket(AF_UNIX, type, 0); 1253178825Sdfr 1254178825Sdfr if (fd == -1) return -1; 1255178825Sdfr 1256178825Sdfr si = (struct socket_info *)calloc(1, sizeof(struct socket_info)); 1257178825Sdfr 1258178825Sdfr si->family = family; 1259178825Sdfr si->type = type; 1260178825Sdfr si->protocol = protocol; 1261178825Sdfr si->fd = fd; 1262178825Sdfr 1263178825Sdfr SWRAP_DLIST_ADD(sockets, si); 1264178825Sdfr 1265178825Sdfr return si->fd; 1266178825Sdfr} 1267178825Sdfr 1268178825Sdfr_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) 1269178825Sdfr{ 1270178825Sdfr struct socket_info *parent_si, *child_si; 1271178825Sdfr int fd; 1272178825Sdfr struct sockaddr_un un_addr; 1273178825Sdfr socklen_t un_addrlen = sizeof(un_addr); 1274178825Sdfr struct sockaddr_un un_my_addr; 1275178825Sdfr socklen_t un_my_addrlen = sizeof(un_my_addr); 1276178825Sdfr struct sockaddr *my_addr; 1277178825Sdfr socklen_t my_addrlen, len; 1278178825Sdfr int ret; 1279178825Sdfr 1280178825Sdfr parent_si = find_socket_info(s); 1281178825Sdfr if (!parent_si) { 1282178825Sdfr return real_accept(s, addr, addrlen); 1283178825Sdfr } 1284178825Sdfr 1285233294Sstas /* 1286178825Sdfr * assume out sockaddr have the same size as the in parent 1287178825Sdfr * socket family 1288178825Sdfr */ 1289178825Sdfr my_addrlen = socket_length(parent_si->family); 1290178825Sdfr if (my_addrlen < 0) { 1291178825Sdfr errno = EINVAL; 1292178825Sdfr return -1; 1293178825Sdfr } 1294178825Sdfr 1295178825Sdfr my_addr = malloc(my_addrlen); 1296178825Sdfr if (my_addr == NULL) { 1297178825Sdfr return -1; 1298178825Sdfr } 1299178825Sdfr 1300178825Sdfr memset(&un_addr, 0, sizeof(un_addr)); 1301178825Sdfr memset(&un_my_addr, 0, sizeof(un_my_addr)); 1302178825Sdfr 1303178825Sdfr ret = real_accept(s, (struct sockaddr *)&un_addr, &un_addrlen); 1304178825Sdfr if (ret == -1) { 1305178825Sdfr free(my_addr); 1306178825Sdfr return ret; 1307178825Sdfr } 1308178825Sdfr 1309178825Sdfr fd = ret; 1310178825Sdfr 1311178825Sdfr len = my_addrlen; 1312178825Sdfr ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen, 1313178825Sdfr parent_si->family, my_addr, &len); 1314178825Sdfr if (ret == -1) { 1315178825Sdfr free(my_addr); 1316178825Sdfr close(fd); 1317178825Sdfr return ret; 1318178825Sdfr } 1319178825Sdfr 1320178825Sdfr child_si = (struct socket_info *)malloc(sizeof(struct socket_info)); 1321178825Sdfr memset(child_si, 0, sizeof(*child_si)); 1322178825Sdfr 1323178825Sdfr child_si->fd = fd; 1324178825Sdfr child_si->family = parent_si->family; 1325178825Sdfr child_si->type = parent_si->type; 1326178825Sdfr child_si->protocol = parent_si->protocol; 1327178825Sdfr child_si->bound = 1; 1328178825Sdfr child_si->is_server = 1; 1329178825Sdfr 1330178825Sdfr child_si->peername_len = len; 1331178825Sdfr child_si->peername = sockaddr_dup(my_addr, len); 1332178825Sdfr 1333178825Sdfr if (addr != NULL && addrlen != NULL) { 1334178825Sdfr *addrlen = len; 1335178825Sdfr if (*addrlen >= len) 1336178825Sdfr memcpy(addr, my_addr, len); 1337178825Sdfr *addrlen = 0; 1338178825Sdfr } 1339178825Sdfr 1340178825Sdfr ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen); 1341178825Sdfr if (ret == -1) { 1342178825Sdfr free(child_si); 1343178825Sdfr close(fd); 1344178825Sdfr return ret; 1345178825Sdfr } 1346178825Sdfr 1347178825Sdfr len = my_addrlen; 1348178825Sdfr ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen, 1349178825Sdfr child_si->family, my_addr, &len); 1350178825Sdfr if (ret == -1) { 1351178825Sdfr free(child_si); 1352178825Sdfr free(my_addr); 1353178825Sdfr close(fd); 1354178825Sdfr return ret; 1355178825Sdfr } 1356178825Sdfr 1357178825Sdfr child_si->myname_len = len; 1358178825Sdfr child_si->myname = sockaddr_dup(my_addr, len); 1359178825Sdfr free(my_addr); 1360178825Sdfr 1361178825Sdfr SWRAP_DLIST_ADD(sockets, child_si); 1362178825Sdfr 1363178825Sdfr swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_SEND, NULL, 0); 1364178825Sdfr swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_RECV, NULL, 0); 1365178825Sdfr swrap_dump_packet(child_si, addr, SWRAP_ACCEPT_ACK, NULL, 0); 1366178825Sdfr 1367178825Sdfr return fd; 1368178825Sdfr} 1369178825Sdfr 1370178825Sdfrstatic int autobind_start_init; 1371178825Sdfrstatic int autobind_start; 1372178825Sdfr 1373178825Sdfr/* using sendto() or connect() on an unbound socket would give the 1374178825Sdfr recipient no way to reply, as unlike UDP and TCP, a unix domain 1375178825Sdfr socket can't auto-assign emphemeral port numbers, so we need to 1376178825Sdfr assign it here */ 1377178825Sdfrstatic int swrap_auto_bind(struct socket_info *si) 1378178825Sdfr{ 1379178825Sdfr struct sockaddr_un un_addr; 1380178825Sdfr int i; 1381178825Sdfr char type; 1382178825Sdfr int ret; 1383178825Sdfr int port; 1384178825Sdfr struct stat st; 1385178825Sdfr 1386178825Sdfr if (autobind_start_init != 1) { 1387178825Sdfr autobind_start_init = 1; 1388178825Sdfr autobind_start = getpid(); 1389178825Sdfr autobind_start %= 50000; 1390178825Sdfr autobind_start += 10000; 1391178825Sdfr } 1392178825Sdfr 1393178825Sdfr un_addr.sun_family = AF_UNIX; 1394178825Sdfr 1395178825Sdfr switch (si->family) { 1396178825Sdfr case AF_INET: { 1397178825Sdfr struct sockaddr_in in; 1398178825Sdfr 1399178825Sdfr switch (si->type) { 1400178825Sdfr case SOCK_STREAM: 1401178825Sdfr type = SOCKET_TYPE_CHAR_TCP; 1402178825Sdfr break; 1403178825Sdfr case SOCK_DGRAM: 1404178825Sdfr type = SOCKET_TYPE_CHAR_UDP; 1405178825Sdfr break; 1406178825Sdfr default: 1407178825Sdfr errno = ESOCKTNOSUPPORT; 1408178825Sdfr return -1; 1409178825Sdfr } 1410178825Sdfr 1411178825Sdfr memset(&in, 0, sizeof(in)); 1412178825Sdfr in.sin_family = AF_INET; 1413233294Sstas in.sin_addr.s_addr = htonl(127<<24 | 1414178825Sdfr socket_wrapper_default_iface()); 1415178825Sdfr 1416178825Sdfr si->myname_len = sizeof(in); 1417178825Sdfr si->myname = sockaddr_dup(&in, si->myname_len); 1418178825Sdfr break; 1419178825Sdfr } 1420178825Sdfr#ifdef HAVE_IPV6 1421178825Sdfr case AF_INET6: { 1422178825Sdfr struct sockaddr_in6 in6; 1423178825Sdfr 1424178825Sdfr switch (si->type) { 1425178825Sdfr case SOCK_STREAM: 1426178825Sdfr type = SOCKET_TYPE_CHAR_TCP_V6; 1427178825Sdfr break; 1428178825Sdfr case SOCK_DGRAM: 1429178825Sdfr type = SOCKET_TYPE_CHAR_UDP_V6; 1430178825Sdfr break; 1431178825Sdfr default: 1432178825Sdfr errno = ESOCKTNOSUPPORT; 1433178825Sdfr return -1; 1434178825Sdfr } 1435178825Sdfr 1436178825Sdfr memset(&in6, 0, sizeof(in6)); 1437178825Sdfr in6.sin6_family = AF_INET6; 1438178825Sdfr in6.sin6_addr.s6_addr[0] = SW_IPV6_ADDRESS; 1439178825Sdfr si->myname_len = sizeof(in6); 1440178825Sdfr si->myname = sockaddr_dup(&in6, si->myname_len); 1441178825Sdfr break; 1442178825Sdfr } 1443178825Sdfr#endif 1444178825Sdfr default: 1445178825Sdfr errno = ESOCKTNOSUPPORT; 1446178825Sdfr return -1; 1447178825Sdfr } 1448178825Sdfr 1449178825Sdfr if (autobind_start > 60000) { 1450178825Sdfr autobind_start = 10000; 1451178825Sdfr } 1452178825Sdfr 1453178825Sdfr for (i=0;i<1000;i++) { 1454178825Sdfr port = autobind_start + i; 1455233294Sstas snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), 1456178825Sdfr "%s/"SOCKET_FORMAT, socket_wrapper_dir(), 1457178825Sdfr type, socket_wrapper_default_iface(), port); 1458178825Sdfr if (stat(un_addr.sun_path, &st) == 0) continue; 1459233294Sstas 1460178825Sdfr ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr)); 1461178825Sdfr if (ret == -1) return ret; 1462178825Sdfr 1463178825Sdfr si->tmp_path = strdup(un_addr.sun_path); 1464178825Sdfr si->bound = 1; 1465178825Sdfr autobind_start = port + 1; 1466178825Sdfr break; 1467178825Sdfr } 1468178825Sdfr if (i == 1000) { 1469178825Sdfr errno = ENFILE; 1470178825Sdfr return -1; 1471178825Sdfr } 1472178825Sdfr 1473178825Sdfr set_port(si->family, port, si->myname); 1474178825Sdfr 1475178825Sdfr return 0; 1476178825Sdfr} 1477178825Sdfr 1478178825Sdfr 1479178825Sdfr_PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen) 1480178825Sdfr{ 1481178825Sdfr int ret; 1482178825Sdfr struct sockaddr_un un_addr; 1483178825Sdfr struct socket_info *si = find_socket_info(s); 1484178825Sdfr 1485178825Sdfr if (!si) { 1486178825Sdfr return real_connect(s, serv_addr, addrlen); 1487178825Sdfr } 1488178825Sdfr 1489178825Sdfr if (si->bound == 0) { 1490178825Sdfr ret = swrap_auto_bind(si); 1491178825Sdfr if (ret == -1) return -1; 1492178825Sdfr } 1493178825Sdfr 1494178825Sdfr if (si->family != serv_addr->sa_family) { 1495178825Sdfr errno = EINVAL; 1496178825Sdfr return -1; 1497178825Sdfr } 1498178825Sdfr 1499178825Sdfr ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL); 1500178825Sdfr if (ret == -1) return -1; 1501178825Sdfr 1502178825Sdfr swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_SEND, NULL, 0); 1503178825Sdfr 1504233294Sstas ret = real_connect(s, (struct sockaddr *)&un_addr, 1505178825Sdfr sizeof(struct sockaddr_un)); 1506178825Sdfr 1507178825Sdfr /* to give better errors */ 1508178825Sdfr if (ret == -1 && errno == ENOENT) { 1509178825Sdfr errno = EHOSTUNREACH; 1510178825Sdfr } 1511178825Sdfr 1512178825Sdfr if (ret == 0) { 1513178825Sdfr si->peername_len = addrlen; 1514178825Sdfr si->peername = sockaddr_dup(serv_addr, addrlen); 1515178825Sdfr 1516178825Sdfr swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0); 1517178825Sdfr swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0); 1518178825Sdfr } else { 1519178825Sdfr swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0); 1520178825Sdfr } 1521178825Sdfr 1522178825Sdfr return ret; 1523178825Sdfr} 1524178825Sdfr 1525178825Sdfr_PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen) 1526178825Sdfr{ 1527178825Sdfr int ret; 1528178825Sdfr struct sockaddr_un un_addr; 1529178825Sdfr struct socket_info *si = find_socket_info(s); 1530178825Sdfr 1531178825Sdfr if (!si) { 1532178825Sdfr return real_bind(s, myaddr, addrlen); 1533178825Sdfr } 1534178825Sdfr 1535178825Sdfr si->myname_len = addrlen; 1536178825Sdfr si->myname = sockaddr_dup(myaddr, addrlen); 1537178825Sdfr 1538178825Sdfr ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast); 1539178825Sdfr if (ret == -1) return -1; 1540178825Sdfr 1541178825Sdfr unlink(un_addr.sun_path); 1542178825Sdfr 1543178825Sdfr ret = real_bind(s, (struct sockaddr *)&un_addr, 1544178825Sdfr sizeof(struct sockaddr_un)); 1545178825Sdfr 1546178825Sdfr if (ret == 0) { 1547178825Sdfr si->bound = 1; 1548178825Sdfr } 1549178825Sdfr 1550178825Sdfr return ret; 1551178825Sdfr} 1552178825Sdfr 1553178825Sdfr_PUBLIC_ int swrap_listen(int s, int backlog) 1554178825Sdfr{ 1555178825Sdfr int ret; 1556178825Sdfr struct socket_info *si = find_socket_info(s); 1557178825Sdfr 1558178825Sdfr if (!si) { 1559178825Sdfr return real_listen(s, backlog); 1560178825Sdfr } 1561178825Sdfr 1562178825Sdfr ret = real_listen(s, backlog); 1563178825Sdfr 1564178825Sdfr return ret; 1565178825Sdfr} 1566178825Sdfr 1567178825Sdfr_PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen) 1568178825Sdfr{ 1569178825Sdfr struct socket_info *si = find_socket_info(s); 1570178825Sdfr 1571178825Sdfr if (!si) { 1572178825Sdfr return real_getpeername(s, name, addrlen); 1573178825Sdfr } 1574178825Sdfr 1575178825Sdfr if (!si->peername) 1576178825Sdfr { 1577178825Sdfr errno = ENOTCONN; 1578178825Sdfr return -1; 1579178825Sdfr } 1580178825Sdfr 1581178825Sdfr memcpy(name, si->peername, si->peername_len); 1582178825Sdfr *addrlen = si->peername_len; 1583178825Sdfr 1584178825Sdfr return 0; 1585178825Sdfr} 1586178825Sdfr 1587178825Sdfr_PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen) 1588178825Sdfr{ 1589178825Sdfr struct socket_info *si = find_socket_info(s); 1590178825Sdfr 1591178825Sdfr if (!si) { 1592178825Sdfr return real_getsockname(s, name, addrlen); 1593178825Sdfr } 1594178825Sdfr 1595178825Sdfr memcpy(name, si->myname, si->myname_len); 1596178825Sdfr *addrlen = si->myname_len; 1597178825Sdfr 1598178825Sdfr return 0; 1599178825Sdfr} 1600178825Sdfr 1601178825Sdfr_PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) 1602178825Sdfr{ 1603178825Sdfr struct socket_info *si = find_socket_info(s); 1604178825Sdfr 1605178825Sdfr if (!si) { 1606178825Sdfr return real_getsockopt(s, level, optname, optval, optlen); 1607178825Sdfr } 1608178825Sdfr 1609178825Sdfr if (level == SOL_SOCKET) { 1610178825Sdfr return real_getsockopt(s, level, optname, optval, optlen); 1611233294Sstas } 1612178825Sdfr 1613178825Sdfr errno = ENOPROTOOPT; 1614178825Sdfr return -1; 1615178825Sdfr} 1616178825Sdfr 1617178825Sdfr_PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) 1618178825Sdfr{ 1619178825Sdfr struct socket_info *si = find_socket_info(s); 1620178825Sdfr 1621178825Sdfr if (!si) { 1622178825Sdfr return real_setsockopt(s, level, optname, optval, optlen); 1623178825Sdfr } 1624178825Sdfr 1625178825Sdfr if (level == SOL_SOCKET) { 1626178825Sdfr return real_setsockopt(s, level, optname, optval, optlen); 1627178825Sdfr } 1628178825Sdfr 1629178825Sdfr switch (si->family) { 1630178825Sdfr case AF_INET: 1631178825Sdfr return 0; 1632178825Sdfr default: 1633178825Sdfr errno = ENOPROTOOPT; 1634178825Sdfr return -1; 1635178825Sdfr } 1636178825Sdfr} 1637178825Sdfr 1638178825Sdfr_PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) 1639178825Sdfr{ 1640178825Sdfr struct sockaddr_un un_addr; 1641178825Sdfr socklen_t un_addrlen = sizeof(un_addr); 1642178825Sdfr int ret; 1643178825Sdfr struct socket_info *si = find_socket_info(s); 1644178825Sdfr 1645178825Sdfr if (!si) { 1646178825Sdfr return real_recvfrom(s, buf, len, flags, from, fromlen); 1647178825Sdfr } 1648178825Sdfr 1649178825Sdfr /* irix 6.4 forgets to null terminate the sun_path string :-( */ 1650178825Sdfr memset(&un_addr, 0, sizeof(un_addr)); 1651178825Sdfr ret = real_recvfrom(s, buf, len, flags, (struct sockaddr *)&un_addr, &un_addrlen); 1652233294Sstas if (ret == -1) 1653178825Sdfr return ret; 1654178825Sdfr 1655178825Sdfr if (sockaddr_convert_from_un(si, &un_addr, un_addrlen, 1656178825Sdfr si->family, from, fromlen) == -1) { 1657178825Sdfr return -1; 1658178825Sdfr } 1659178825Sdfr 1660178825Sdfr swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret); 1661178825Sdfr 1662178825Sdfr return ret; 1663178825Sdfr} 1664178825Sdfr 1665178825Sdfr 1666178825Sdfr_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) 1667178825Sdfr{ 1668178825Sdfr struct sockaddr_un un_addr; 1669178825Sdfr int ret; 1670178825Sdfr struct socket_info *si = find_socket_info(s); 1671178825Sdfr int bcast = 0; 1672178825Sdfr 1673178825Sdfr if (!si) { 1674178825Sdfr return real_sendto(s, buf, len, flags, to, tolen); 1675178825Sdfr } 1676178825Sdfr 1677178825Sdfr switch (si->type) { 1678178825Sdfr case SOCK_STREAM: 1679178825Sdfr ret = real_send(s, buf, len, flags); 1680178825Sdfr break; 1681178825Sdfr case SOCK_DGRAM: 1682178825Sdfr if (si->bound == 0) { 1683178825Sdfr ret = swrap_auto_bind(si); 1684178825Sdfr if (ret == -1) return -1; 1685178825Sdfr } 1686233294Sstas 1687178825Sdfr ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast); 1688178825Sdfr if (ret == -1) return -1; 1689233294Sstas 1690178825Sdfr if (bcast) { 1691178825Sdfr struct stat st; 1692178825Sdfr unsigned int iface; 1693178825Sdfr unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port); 1694178825Sdfr char type; 1695233294Sstas 1696178825Sdfr type = SOCKET_TYPE_CHAR_UDP; 1697233294Sstas 1698178825Sdfr for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) { 1699233294Sstas snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, 1700178825Sdfr socket_wrapper_dir(), type, iface, prt); 1701178825Sdfr if (stat(un_addr.sun_path, &st) != 0) continue; 1702233294Sstas 1703178825Sdfr /* ignore the any errors in broadcast sends */ 1704178825Sdfr real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); 1705178825Sdfr } 1706233294Sstas 1707178825Sdfr swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); 1708233294Sstas 1709178825Sdfr return len; 1710178825Sdfr } 1711233294Sstas 1712178825Sdfr ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); 1713178825Sdfr break; 1714178825Sdfr default: 1715178825Sdfr ret = -1; 1716178825Sdfr errno = EHOSTUNREACH; 1717178825Sdfr break; 1718178825Sdfr } 1719233294Sstas 1720178825Sdfr /* to give better errors */ 1721178825Sdfr if (ret == -1 && errno == ENOENT) { 1722178825Sdfr errno = EHOSTUNREACH; 1723178825Sdfr } 1724178825Sdfr 1725178825Sdfr if (ret == -1) { 1726178825Sdfr swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len); 1727178825Sdfr swrap_dump_packet(si, to, SWRAP_SENDTO_UNREACH, buf, len); 1728178825Sdfr } else { 1729178825Sdfr swrap_dump_packet(si, to, SWRAP_SENDTO, buf, ret); 1730178825Sdfr } 1731178825Sdfr 1732178825Sdfr return ret; 1733178825Sdfr} 1734178825Sdfr 1735178825Sdfr_PUBLIC_ int swrap_ioctl(int s, int r, void *p) 1736178825Sdfr{ 1737178825Sdfr int ret; 1738178825Sdfr struct socket_info *si = find_socket_info(s); 1739178825Sdfr int value; 1740178825Sdfr 1741178825Sdfr if (!si) { 1742178825Sdfr return real_ioctl(s, r, p); 1743178825Sdfr } 1744178825Sdfr 1745178825Sdfr ret = real_ioctl(s, r, p); 1746178825Sdfr 1747178825Sdfr switch (r) { 1748178825Sdfr case FIONREAD: 1749178825Sdfr value = *((int *)p); 1750178825Sdfr if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) { 1751178825Sdfr swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0); 1752178825Sdfr } else if (value == 0) { /* END OF FILE */ 1753178825Sdfr swrap_dump_packet(si, NULL, SWRAP_PENDING_RST, NULL, 0); 1754178825Sdfr } 1755178825Sdfr break; 1756178825Sdfr } 1757178825Sdfr 1758178825Sdfr return ret; 1759178825Sdfr} 1760178825Sdfr 1761178825Sdfr_PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags) 1762178825Sdfr{ 1763178825Sdfr int ret; 1764178825Sdfr struct socket_info *si = find_socket_info(s); 1765178825Sdfr 1766178825Sdfr if (!si) { 1767178825Sdfr return real_recv(s, buf, len, flags); 1768178825Sdfr } 1769178825Sdfr 1770178825Sdfr ret = real_recv(s, buf, len, flags); 1771178825Sdfr if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) { 1772178825Sdfr swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0); 1773178825Sdfr } else if (ret == 0) { /* END OF FILE */ 1774178825Sdfr swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0); 1775178825Sdfr } else { 1776178825Sdfr swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret); 1777178825Sdfr } 1778178825Sdfr 1779178825Sdfr return ret; 1780178825Sdfr} 1781178825Sdfr 1782178825Sdfr 1783178825Sdfr_PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags) 1784178825Sdfr{ 1785178825Sdfr int ret; 1786178825Sdfr struct socket_info *si = find_socket_info(s); 1787178825Sdfr 1788178825Sdfr if (!si) { 1789178825Sdfr return real_send(s, buf, len, flags); 1790178825Sdfr } 1791178825Sdfr 1792178825Sdfr ret = real_send(s, buf, len, flags); 1793178825Sdfr 1794178825Sdfr if (ret == -1) { 1795178825Sdfr swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len); 1796178825Sdfr swrap_dump_packet(si, NULL, SWRAP_SEND_RST, NULL, 0); 1797178825Sdfr } else { 1798178825Sdfr swrap_dump_packet(si, NULL, SWRAP_SEND, buf, ret); 1799178825Sdfr } 1800178825Sdfr 1801178825Sdfr return ret; 1802178825Sdfr} 1803178825Sdfr 1804178825Sdfr_PUBLIC_ int swrap_close(int fd) 1805178825Sdfr{ 1806178825Sdfr struct socket_info *si = find_socket_info(fd); 1807178825Sdfr int ret; 1808178825Sdfr 1809178825Sdfr if (!si) { 1810178825Sdfr return real_close(fd); 1811178825Sdfr } 1812178825Sdfr 1813178825Sdfr SWRAP_DLIST_REMOVE(sockets, si); 1814178825Sdfr 1815178825Sdfr if (si->myname && si->peername) { 1816178825Sdfr swrap_dump_packet(si, NULL, SWRAP_CLOSE_SEND, NULL, 0); 1817178825Sdfr } 1818178825Sdfr 1819178825Sdfr ret = real_close(fd); 1820178825Sdfr 1821178825Sdfr if (si->myname && si->peername) { 1822178825Sdfr swrap_dump_packet(si, NULL, SWRAP_CLOSE_RECV, NULL, 0); 1823178825Sdfr swrap_dump_packet(si, NULL, SWRAP_CLOSE_ACK, NULL, 0); 1824178825Sdfr } 1825178825Sdfr 1826178825Sdfr if (si->path) free(si->path); 1827178825Sdfr if (si->myname) free(si->myname); 1828178825Sdfr if (si->peername) free(si->peername); 1829178825Sdfr if (si->tmp_path) { 1830178825Sdfr unlink(si->tmp_path); 1831178825Sdfr free(si->tmp_path); 1832178825Sdfr } 1833178825Sdfr free(si); 1834178825Sdfr 1835178825Sdfr return ret; 1836178825Sdfr} 1837178825Sdfr 1838178825Sdfrstatic int 1839178825Sdfrdup_internal(const struct socket_info *si_oldd, int fd) 1840178825Sdfr{ 1841178825Sdfr struct socket_info *si_newd; 1842178825Sdfr 1843178825Sdfr si_newd = (struct socket_info *)calloc(1, sizeof(struct socket_info)); 1844178825Sdfr 1845178825Sdfr si_newd->fd = fd; 1846178825Sdfr 1847178825Sdfr si_newd->family = si_oldd->family; 1848178825Sdfr si_newd->type = si_oldd->type; 1849178825Sdfr si_newd->protocol = si_oldd->protocol; 1850178825Sdfr si_newd->bound = si_oldd->bound; 1851178825Sdfr si_newd->bcast = si_oldd->bcast; 1852178825Sdfr if (si_oldd->path) 1853178825Sdfr si_newd->path = strdup(si_oldd->path); 1854178825Sdfr if (si_oldd->tmp_path) 1855178825Sdfr si_newd->tmp_path = strdup(si_oldd->tmp_path); 1856178825Sdfr si_newd->myname = 1857178825Sdfr sockaddr_dup(si_oldd->myname, si_oldd->myname_len); 1858178825Sdfr si_newd->myname_len = si_oldd->myname_len; 1859233294Sstas si_newd->peername = 1860178825Sdfr sockaddr_dup(si_oldd->peername, si_oldd->peername_len); 1861178825Sdfr si_newd->peername_len = si_oldd->peername_len; 1862178825Sdfr 1863178825Sdfr si_newd->io = si_oldd->io; 1864178825Sdfr 1865178825Sdfr SWRAP_DLIST_ADD(sockets, si_newd); 1866178825Sdfr 1867178825Sdfr return fd; 1868178825Sdfr} 1869178825Sdfr 1870178825Sdfr 1871178825Sdfr_PUBLIC_ int swrap_dup(int oldd) 1872178825Sdfr{ 1873178825Sdfr struct socket_info *si; 1874178825Sdfr int fd; 1875178825Sdfr 1876178825Sdfr si = find_socket_info(oldd); 1877178825Sdfr if (si == NULL) 1878178825Sdfr return real_dup(oldd); 1879178825Sdfr 1880178825Sdfr fd = real_dup(si->fd); 1881178825Sdfr if (fd < 0) 1882178825Sdfr return fd; 1883178825Sdfr 1884178825Sdfr return dup_internal(si, fd); 1885178825Sdfr} 1886178825Sdfr 1887178825Sdfr 1888178825Sdfr_PUBLIC_ int swrap_dup2(int oldd, int newd) 1889178825Sdfr{ 1890178825Sdfr struct socket_info *si_newd, *si_oldd; 1891178825Sdfr int fd; 1892178825Sdfr 1893178825Sdfr if (newd == oldd) 1894178825Sdfr return newd; 1895178825Sdfr 1896178825Sdfr si_oldd = find_socket_info(oldd); 1897178825Sdfr si_newd = find_socket_info(newd); 1898178825Sdfr 1899178825Sdfr if (si_oldd == NULL && si_newd == NULL) 1900178825Sdfr return real_dup2(oldd, newd); 1901178825Sdfr 1902178825Sdfr fd = real_dup2(si_oldd->fd, newd); 1903178825Sdfr if (fd < 0) 1904178825Sdfr return fd; 1905178825Sdfr 1906178825Sdfr /* close new socket first */ 1907178825Sdfr if (si_newd) 1908178825Sdfr swrap_close(newd); 1909178825Sdfr 1910178825Sdfr return dup_internal(si_oldd, fd); 1911178825Sdfr} 1912