Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifdef SAMBA_MAJOR_VERSION
+#ifdef _SAMBA_BUILD
#include "includes.h"
#include "system/network.h"
#else
#include <errno.h>
#include <sys/un.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define real_close close
#endif
-static struct sockaddr *memdup(const void *data, socklen_t len)
+static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
{
struct sockaddr *ret = (struct sockaddr *)malloc(len);
memcpy(ret, data, len);
{
unsigned int prt;
const char *p;
+ int type;
if ((*len) < sizeof(struct sockaddr_in)) {
return 0;
p = strchr(un->sun_path, '/');
if (p) p++; else p = un->sun_path;
- if(sscanf(p, "sock_ip_%u", &prt) == 1)
+ if(sscanf(p, "sock_ip_%d_%u", &type, &prt) == 1)
{
in->sin_port = htons(prt);
}
return 0;
}
-static int convert_in_un(const struct sockaddr_in *in, struct sockaddr_un *un)
+static int convert_in_un(int type, const struct sockaddr_in *in, struct sockaddr_un *un)
{
uint16_t prt = ntohs(in->sin_port);
/* FIXME: ENETUNREACH if in->sin_addr is not loopback */
- un->sun_family = AF_LOCAL;
- snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%u", getenv("SOCKET_WRAPPER_DIR"), prt);
+ snprintf(un->sun_path, sizeof(un->sun_path), "%s/sock_ip_%d_%u", getenv("SOCKET_WRAPPER_DIR"), type, prt);
return 0;
}
return NULL;
}
-static int sockaddr_convert_to_un(const struct sockaddr *in_addr, socklen_t in_len,
+static int sockaddr_convert_to_un(const struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
struct sockaddr_un *out_addr)
{
if (!out_addr)
return 0;
+ out_addr->sun_family = AF_LOCAL;
+
switch (in_addr->sa_family) {
case AF_INET:
- return convert_in_un((const struct sockaddr_in *)in_addr, out_addr);
+ return convert_in_un(si->type, (const struct sockaddr_in *)in_addr, out_addr);
case AF_LOCAL:
memcpy(out_addr, in_addr, sizeof(*out_addr));
return 0;
return -1;
}
-static int sockaddr_convert_from_un(const struct sockaddr_un *in_addr,
+static int sockaddr_convert_from_un(const struct socket_info *si,
+ const struct sockaddr_un *in_addr,
int family,
struct sockaddr *out_addr,
socklen_t *out_len)
fd = ret;
- ret = sockaddr_convert_from_un(&un_addr, parent_si->domain, addr, addrlen);
+ ret = sockaddr_convert_from_un(parent_si, &un_addr, parent_si->domain, addr, addrlen);
if (ret < 0) return ret;
if (addr && addrlen) {
child_si->myname_len = *addrlen;
- child_si->myname = memdup(addr, *addrlen);
+ child_si->myname = sockaddr_dup(addr, *addrlen);
}
return fd;
return real_connect(s, serv_addr, addrlen);
}
- ret = sockaddr_convert_to_un((const struct sockaddr *)serv_addr, addrlen, &un_addr);
+ ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr);
if (ret < 0) return ret;
ret = real_connect(s,
if (ret >= 0) {
si->peername_len = addrlen;
- si->peername = memdup(serv_addr, addrlen);
+ si->peername = sockaddr_dup(serv_addr, addrlen);
}
return ret;
return real_bind(s, myaddr, addrlen);
}
- ret = sockaddr_convert_to_un((const struct sockaddr *)myaddr, addrlen, &un_addr);
+ ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr);
if (ret < 0) return ret;
unlink(un_addr.sun_path);
if (ret >= 0) {
si->myname_len = addrlen;
- si->myname = memdup(myaddr, addrlen);
+ si->myname = sockaddr_dup(myaddr, addrlen);
}
return ret;
return real_getsockopt(s, level, optname, optval, optlen);
}
- if (level != SOL_SOCKET) {
+ if (level == SOL_SOCKET) {
+ return real_getsockopt(s, level, optname, optval, optlen);
+ }
+
+ switch (si->domain) {
+ case AF_LOCAL:
+ return real_getsockopt(s, level, optname, optval, optlen);
+ default:
errno = ENOPROTOOPT;
return -1;
}
-
- return real_getsockopt(s, level, optname, optval, optlen);
}
int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
return real_setsockopt(s, level, optname, optval, optlen);
}
- if (level != SOL_SOCKET) {
+ if (level == SOL_SOCKET) {
+ return real_setsockopt(s, level, optname, optval, optlen);
+ }
+
+ switch (si->domain) {
+ case AF_LOCAL:
+ return real_setsockopt(s, level, optname, optval, optlen);
+ case AF_INET:
+ /* Silence some warnings */
+#ifdef TCP_NODELAY
+ if (optname == TCP_NODELAY)
+ return 0;
+#endif
+ default:
errno = ENOPROTOOPT;
return -1;
}
-
- return real_setsockopt(s, level, optname, optval, optlen);
}
ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
if (ret < 0)
return ret;
- ret = sockaddr_convert_from_un(&un_addr, si->domain, from, fromlen);
+ ret = sockaddr_convert_from_un(si, &un_addr, si->domain, from, fromlen);
return ret;
}
return real_sendto(s, buf, len, flags, to, tolen);
}
- ret = sockaddr_convert_to_un(to, tolen, &un_addr);
+ ret = sockaddr_convert_to_un(si, to, tolen, &un_addr);
if (ret < 0)
return ret;