diff options
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/socket_wrapper/config.m4 | 22 | ||||
-rw-r--r-- | source3/lib/socket_wrapper/socket_wrapper.c (renamed from source3/lib/socket_wrapper.c) | 252 | ||||
-rw-r--r-- | source3/lib/socket_wrapper/socket_wrapper.h | 104 |
3 files changed, 301 insertions, 77 deletions
diff --git a/source3/lib/socket_wrapper/config.m4 b/source3/lib/socket_wrapper/config.m4 new file mode 100644 index 0000000000..42212abc7f --- /dev/null +++ b/source3/lib/socket_wrapper/config.m4 @@ -0,0 +1,22 @@ +AC_ARG_ENABLE(socket-wrapper, +[ --enable-socket-wrapper Turn on socket wrapper library (default=no)]) + +DEFAULT_TEST_TARGET=test-noswrap +HAVE_SOCKET_WRAPPER=no + +if eval "test x$developer = xyes"; then + enable_socket_wrapper=yes +fi + +if eval "test x$enable_socket_wrapper = xyes"; then + AC_DEFINE(SOCKET_WRAPPER,1,[Use socket wrapper library]) + DEFAULT_TEST_TARGET=test-swrap + HAVE_SOCKET_WRAPPER=yes + + # this is only used for samba3 + SOCKET_WRAPPER_OBJS="lib/socket_wrapper/socket_wrapper.o" +fi + +AC_SUBST(DEFAULT_TEST_TARGET) +AC_SUBST(HAVE_SOCKET_WRAPPER) +AC_SUBST(SOCKET_WRAPPER_OBJS) diff --git a/source3/lib/socket_wrapper.c b/source3/lib/socket_wrapper/socket_wrapper.c index 04c337267f..af774e1927 100644 --- a/source3/lib/socket_wrapper.c +++ b/source3/lib/socket_wrapper/socket_wrapper.c @@ -3,6 +3,7 @@ unix domain sockets if the environment variable SOCKET_WRAPPER_DIR is set. Copyright (C) Jelmer Vernooij 2005 + Copyright (C) Stefan Metzmacher 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,25 +20,44 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef _SAMBA_BUILD_ + +#define SOCKET_WRAPPER_NOT_REPLACE #include "includes.h" +/* +#include "system/network.h" +#include "system/filesys.h" +*/ +#ifndef _DLINKLIST_H +#include "lib/util/dlinklist.h" +#endif -#ifdef _PUBLIC_ -#undef _PUBLIC_ +#ifdef malloc +#undef malloc #endif -#define _PUBLIC_ - -#ifdef SOCKET_WRAPPER_REPLACE -#undef accept -#undef connect -#undef bind -#undef getpeername -#undef getsockname -#undef getsockopt -#undef setsockopt -#undef recvfrom -#undef sendto -#undef socket -#undef close +#ifdef calloc +#undef calloc +#endif +#ifdef strdup +#undef strdup +#endif + +#else /* _SAMBA_BUILD_ */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <errno.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#error "dlinklist.h missing" + #endif /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support @@ -54,13 +74,12 @@ #define real_setsockopt setsockopt #define real_recvfrom recvfrom #define real_sendto sendto +#define real_recv recv +#define real_send send #define real_socket socket #define real_close close #endif -#undef malloc -#undef calloc -#undef strdup /* we need to use a very terse format here as IRIX 6.4 silently truncates names to 16 chars, so if we use a longer name then we can't tell which port a packet came from with recvfrom() @@ -82,7 +101,7 @@ struct socket_info { int fd; - int domain; + int family; int type; int protocol; int bound; @@ -100,7 +119,7 @@ struct socket_info struct socket_info *prev, *next; }; -static struct socket_info *sockets = NULL; +static struct socket_info *sockets; static const char *socket_wrapper_dir(void) @@ -115,6 +134,23 @@ static const char *socket_wrapper_dir(void) return s; } +static const char *socket_wrapper_dump_dir(void) +{ + const char *s = getenv("SOCKET_WRAPPER_DUMP_DIR"); + + if (!socket_wrapper_dir()) { + return NULL; + } + + if (s == NULL) { + return NULL; + } + if (strncmp(s, "./", 2) == 0) { + s += 2; + } + return s; +} + static unsigned int socket_wrapper_default_iface(void) { const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE"); @@ -346,9 +382,6 @@ static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr } else { return convert_in_un_remote(si, (const struct sockaddr_in *)in_addr, out_addr, bcast); } - case AF_UNIX: - memcpy(out_addr, in_addr, sizeof(*out_addr)); - return 0; default: break; } @@ -390,10 +423,6 @@ static int sockaddr_convert_from_un(const struct socket_info *si, return -1; } return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, _out_addrlen); - case AF_UNIX: - memcpy(out_addr, in_addr, out_addrlen); - *_out_addrlen = out_addrlen; - return 0; default: break; } @@ -402,26 +431,52 @@ static int sockaddr_convert_from_un(const struct socket_info *si, return -1; } -_PUBLIC_ int swrap_socket(int domain, int type, int protocol) +enum swrap_packet_type { + SWRAP_CONNECT, + SWRAP_ACCEPT, + SWRAP_RECVFROM, + SWRAP_SENDTO, + SWRAP_RECV, + SWRAP_SEND, + SWRAP_CLOSE +}; + +static void swrap_dump_packet(struct socket_info *si, const struct sockaddr *addr, + enum swrap_packet_type type, + const void *buf, size_t len, ssize_t ret) +{ + if (!socket_wrapper_dump_dir()) { + return; + } + +} + +_PUBLIC_ int swrap_socket(int family, int type, int protocol) { struct socket_info *si; int fd; if (!socket_wrapper_dir()) { - return real_socket(domain, type, protocol); + return real_socket(family, type, protocol); } - - si = (struct socket_info *)calloc(1, sizeof(struct socket_info)); - if (si == NULL) { - errno = ENOMEM; + + switch (family) { + case AF_INET: + break; + case AF_UNIX: + return real_socket(family, type, protocol); + default: + errno = EAFNOSUPPORT; return -1; } - + fd = real_socket(AF_UNIX, type, 0); if (fd == -1) return -1; - si->domain = domain; + si = calloc(1, sizeof(struct socket_info)); + + si->family = family; si->type = type; si->protocol = protocol; si->fd = fd; @@ -458,29 +513,35 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) fd = ret; ret = sockaddr_convert_from_un(parent_si, &un_addr, un_addrlen, - parent_si->domain, addr, addrlen); - if (ret == -1) return ret; - - child_si = (struct socket_info *)malloc(sizeof(struct socket_info)); - if (child_si == NULL) { + parent_si->family, addr, addrlen); + if (ret == -1) { close(fd); - errno = ENOMEM; - return -1; + return ret; } + + child_si = malloc(sizeof(struct socket_info)); memset(child_si, 0, sizeof(*child_si)); child_si->fd = fd; - child_si->domain = parent_si->domain; + child_si->family = parent_si->family; child_si->type = parent_si->type; child_si->protocol = parent_si->protocol; child_si->bound = 1; ret = real_getsockname(fd, (struct sockaddr *)&un_my_addr, &un_my_addrlen); - if (ret == -1) return ret; + if (ret == -1) { + free(child_si); + close(fd); + return ret; + } ret = sockaddr_convert_from_un(child_si, &un_my_addr, un_my_addrlen, - child_si->domain, &my_addr, &my_addrlen); - if (ret == -1) return ret; + child_si->family, &my_addr, &my_addrlen); + if (ret == -1) { + free(child_si); + close(fd); + return ret; + } child_si->myname_len = my_addrlen; child_si->myname = sockaddr_dup(&my_addr, my_addrlen); @@ -490,6 +551,8 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) DLIST_ADD(sockets, child_si); + swrap_dump_packet(child_si, addr, SWRAP_ACCEPT, NULL, 0, 0); + return fd; } @@ -504,6 +567,7 @@ static int swrap_auto_bind(struct socket_info *si) int i; char type; int ret; + int port; struct stat st; un_addr.sun_family = AF_UNIX; @@ -521,9 +585,10 @@ static int swrap_auto_bind(struct socket_info *si) } for (i=0;i<1000;i++) { + port = 10000 + i; snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), - type, socket_wrapper_default_iface(), i + 10000); + type, socket_wrapper_default_iface(), port); if (stat(un_addr.sun_path, &st) == 0) continue; ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr)); @@ -540,7 +605,7 @@ static int swrap_auto_bind(struct socket_info *si) memset(&in, 0, sizeof(in)); in.sin_family = AF_INET; - in.sin_port = htons(i); + in.sin_port = htons(port); in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface()); si->myname_len = sizeof(in); @@ -560,7 +625,7 @@ _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t ad return real_connect(s, serv_addr, addrlen); } - if (si->bound == 0 && si->domain != AF_UNIX) { + if (si->bound == 0) { ret = swrap_auto_bind(si); if (ret == -1) return -1; } @@ -572,10 +637,8 @@ _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t ad sizeof(struct sockaddr_un)); /* to give better errors */ - if (serv_addr->sa_family == AF_INET) { - if (ret == -1 && errno == ENOENT) { - errno = EHOSTUNREACH; - } + if (ret == -1 && errno == ENOENT) { + errno = EHOSTUNREACH; } if (ret == 0) { @@ -583,6 +646,8 @@ _PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t ad si->peername = sockaddr_dup(serv_addr, addrlen); } + swrap_dump_packet(si, serv_addr, SWRAP_CONNECT, NULL, 0, ret); + return ret; } @@ -660,13 +725,8 @@ _PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, sockl return real_getsockopt(s, level, optname, optval, optlen); } - switch (si->domain) { - case AF_UNIX: - return real_getsockopt(s, level, optname, optval, optlen); - default: - errno = ENOPROTOOPT; - return -1; - } + errno = ENOPROTOOPT; + return -1; } _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) @@ -681,15 +741,9 @@ _PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *o return real_setsockopt(s, level, optname, optval, optlen); } - switch (si->domain) { - case AF_UNIX: - return real_setsockopt(s, level, optname, optval, optlen); + switch (si->family) { case AF_INET: - /* Silence some warnings */ -#ifdef TCP_NODELAY - if (optname == TCP_NODELAY) - return 0; -#endif + return 0; default: errno = ENOPROTOOPT; return -1; @@ -714,15 +768,17 @@ _PUBLIC_ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct return ret; if (sockaddr_convert_from_un(si, &un_addr, un_addrlen, - si->domain, from, fromlen) == -1) { + si->family, from, fromlen) == -1) { return -1; } - + + swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, len, ret); + return ret; } -_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) +_PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { struct sockaddr_un un_addr; int ret; @@ -733,7 +789,7 @@ _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, return real_sendto(s, buf, len, flags, to, tolen); } - if (si->bound == 0 && si->domain != AF_UNIX) { + if (si->bound == 0) { ret = swrap_auto_bind(si); if (ret == -1) return -1; } @@ -757,18 +813,58 @@ _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, /* ignore the any errors in broadcast sends */ real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); } + + swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len, len); + return len; } ret = real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr)); /* to give better errors */ - if (to->sa_family == AF_INET) { - if (ret == -1 && errno == ENOENT) { - errno = EHOSTUNREACH; - } + if (ret == -1 && errno == ENOENT) { + errno = EHOSTUNREACH; + } + + swrap_dump_packet(si, to, SWRAP_SENDTO, buf, len, ret); + + return ret; +} + +_PUBLIC_ ssize_t swrap_recv(int s, void *buf, size_t len, int flags) +{ + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_recv(s, buf, len, flags); } + ret = real_recv(s, buf, len, flags); + if (ret == -1) + return ret; + + swrap_dump_packet(si, NULL, SWRAP_RECV, buf, len, ret); + + return ret; +} + + +_PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags) +{ + int ret; + struct socket_info *si = find_socket_info(s); + + if (!si) { + return real_send(s, buf, len, flags); + } + + ret = real_send(s, buf, len, flags); + if (ret == -1) + return ret; + + swrap_dump_packet(si, NULL, SWRAP_SEND, buf, len, ret); + return ret; } @@ -779,6 +875,8 @@ _PUBLIC_ int swrap_close(int fd) if (si) { DLIST_REMOVE(sockets, si); + swrap_dump_packet(si, NULL, SWRAP_CLOSE, NULL, 0, 0); + free(si->path); free(si->myname); free(si->peername); diff --git a/source3/lib/socket_wrapper/socket_wrapper.h b/source3/lib/socket_wrapper/socket_wrapper.h new file mode 100644 index 0000000000..23a261faaf --- /dev/null +++ b/source3/lib/socket_wrapper/socket_wrapper.h @@ -0,0 +1,104 @@ +/* + Copyright (C) Jelmer Vernooij 2005 <jelmer@samba.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __SOCKET_WRAPPER_H__ +#define __SOCKET_WRAPPER_H__ + +int swrap_socket(int family, int type, int protocol); +int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen); +int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen); +int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen); +int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen); +int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); +int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); +ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); +ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); +ssize_t swrap_recv(int s, void *buf, size_t len, int flags); +ssize_t swrap_send(int s, const void *buf, size_t len, int flags); +int swrap_close(int); + +#ifdef SOCKET_WRAPPER_REPLACE + +#ifdef accept +#undef accept +#endif +#define accept(s,addr,addrlen) swrap_accept(s,addr,addrlen) + +#ifdef connect +#undef connect +#endif +#define connect(s,serv_addr,addrlen) swrap_connect(s,serv_addr,addrlen) + +#ifdef bind +#undef bind +#endif +#define bind(s,myaddr,addrlen) swrap_bind(s,myaddr,addrlen) + +#ifdef getpeername +#undef getpeername +#endif +#define getpeername(s,name,addrlen) swrap_getpeername(s,name,addrlen) + +#ifdef getsockname +#undef getsockname +#endif +#define getsockname(s,name,addrlen) swrap_getsockname(s,name,addrlen) + +#ifdef getsockopt +#undef getsockopt +#endif +#define getsockopt(s,level,optname,optval,optlen) swrap_getsockopt(s,level,optname,optval,optlen) + +#ifdef setsockopt +#undef setsockopt +#endif +#define setsockopt(s,level,optname,optval,optlen) swrap_setsockopt(s,level,optname,optval,optlen) + +#ifdef recvfrom +#undef recvfrom +#endif +#define recvfrom(s,buf,len,flags,from,fromlen) swrap_recvfrom(s,buf,len,flags,from,fromlen) + +#ifdef sendto +#undef sendto +#endif +#define sendto(s,buf,len,flags,to,tolen) swrap_sendto(s,buf,len,flags,to,tolen) + +#ifdef recv +#undef recv +#endif +#define recv(s,buf,len,flags) swrap_recv(s,buf,len,flags) + +#ifdef send +#undef send +#endif +#define send(s,buf,len,flags) swrap_send(s,buf,len,flags) + +#ifdef socket +#undef socket +#endif +#define socket(domain,type,protocol) swrap_socket(domain,type,protocol) + +#ifdef close +#undef close +#endif +#define close(s) swrap_close(s) +#endif + +#endif /* __SOCKET_WRAPPER_H__ */ |