diff options
Diffstat (limited to 'source3/lib/socket_wrapper')
-rw-r--r-- | source3/lib/socket_wrapper/socket_wrapper.c | 79 |
1 files changed, 58 insertions, 21 deletions
diff --git a/source3/lib/socket_wrapper/socket_wrapper.c b/source3/lib/socket_wrapper/socket_wrapper.c index 331e23aa48..224d521b30 100644 --- a/source3/lib/socket_wrapper/socket_wrapper.c +++ b/source3/lib/socket_wrapper/socket_wrapper.c @@ -89,6 +89,8 @@ #define SOCKET_TYPE_CHAR_TCP 'T' #define SOCKET_TYPE_CHAR_UDP 'U' +#define MAX_WRAPPED_INTERFACES 16 + static struct sockaddr *sockaddr_dup(const void *data, socklen_t len) { struct sockaddr *ret = (struct sockaddr *)malloc(len); @@ -156,7 +158,7 @@ static unsigned int socket_wrapper_default_iface(void) if (s) { unsigned int iface; if (sscanf(s, "%u", &iface) == 1) { - if (iface >= 1 && iface <= 0xFF) { + if (iface >= 1 && iface <= MAX_WRAPPED_INTERFACES) { return iface; } } @@ -189,7 +191,7 @@ static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, s return -1; } - if (iface == 0 || iface > 0xFF) { + if (iface == 0 || iface > MAX_WRAPPED_INTERFACES) { errno = EINVAL; return -1; } @@ -468,7 +470,25 @@ _PUBLIC_ int swrap_socket(int family, int type, int protocol) errno = EAFNOSUPPORT; return -1; } - + + switch (type) { + case SOCK_STREAM: + break; + case SOCK_DGRAM: + break; + default: + errno = EPROTONOSUPPORT; + return -1; + } + + switch (protocol) { + case 0: + break; + default: + errno = EPROTONOSUPPORT; + return -1; + } + fd = real_socket(AF_UNIX, type, 0); if (fd == -1) return -1; @@ -555,6 +575,9 @@ _PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen) return fd; } +static int autobind_start_init; +static int autobind_start; + /* using sendto() or connect() on an unbound socket would give the recipient no way to reply, as unlike UDP and TCP, a unix domain socket can't auto-assign emphemeral port numbers, so we need to @@ -568,7 +591,14 @@ static int swrap_auto_bind(struct socket_info *si) int ret; int port; struct stat st; - + + if (autobind_start_init != 1) { + autobind_start_init = 1; + autobind_start = getpid(); + autobind_start %= 50000; + autobind_start += 10000; + } + un_addr.sun_family = AF_UNIX; switch (si->type) { @@ -582,9 +612,13 @@ static int swrap_auto_bind(struct socket_info *si) errno = ESOCKTNOSUPPORT; return -1; } - + + if (autobind_start > 60000) { + autobind_start = 10000; + } + for (i=0;i<1000;i++) { - port = 10000 + i; + port = autobind_start + i; snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, socket_wrapper_default_iface(), port); @@ -595,13 +629,14 @@ static int swrap_auto_bind(struct socket_info *si) si->tmp_path = strdup(un_addr.sun_path); si->bound = 1; + autobind_start = port + 1; break; } if (i == 1000) { errno = ENFILE; return -1; } - + memset(&in, 0, sizeof(in)); in.sin_family = AF_INET; in.sin_port = htons(port); @@ -609,7 +644,6 @@ static int swrap_auto_bind(struct socket_info *si) si->myname_len = sizeof(in); si->myname = sockaddr_dup(&in, si->myname_len); - si->bound = 1; return 0; } @@ -804,7 +838,7 @@ _PUBLIC_ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, con type = SOCKET_TYPE_CHAR_UDP; - for(iface=0; iface <= 0xFF; iface++) { + for(iface=0; iface <= MAX_WRAPPED_INTERFACES; iface++) { snprintf(un_addr.sun_path, sizeof(un_addr.sun_path), "%s/"SOCKET_FORMAT, socket_wrapper_dir(), type, iface, prt); if (stat(un_addr.sun_path, &st) != 0) continue; @@ -870,21 +904,24 @@ _PUBLIC_ ssize_t swrap_send(int s, const void *buf, size_t len, int flags) _PUBLIC_ int swrap_close(int fd) { struct socket_info *si = find_socket_info(fd); + int ret; + + if (!si) { + return real_close(fd); + } - if (si) { - DLIST_REMOVE(sockets, si); + DLIST_REMOVE(sockets, si); - swrap_dump_packet(si, NULL, SWRAP_CLOSE, NULL, 0, 0); + ret = real_close(fd); - free(si->path); - free(si->myname); - free(si->peername); - if (si->tmp_path) { - unlink(si->tmp_path); - free(si->tmp_path); - } - free(si); + free(si->path); + free(si->myname); + free(si->peername); + if (si->tmp_path) { + unlink(si->tmp_path); + free(si->tmp_path); } + free(si); - return real_close(fd); + return ret; } |