1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-10 01:18:15 +03:00

r11555: - change socket_wrapper to support multiple IP's

- SOCKET_WRAPPER_DEFAULT_IFACE=X specifies the default interface
  for 127.0.0.X
- we now use multiple interfaces for smbtorture in make test
  127.0.0.26-127.0.0.31
- and 127.0.0.1 only for smbd

the are more work needed for better support for broacast messages...
but this is enough for the winsrepl tests

metze
(This used to be commit dbd01110d1)
This commit is contained in:
Stefan Metzmacher 2005-11-07 15:36:51 +00:00 committed by Gerald (Jerry) Carter
parent a8d741b4f7
commit 14b59bcbec
3 changed files with 279 additions and 63 deletions

View File

@ -63,7 +63,9 @@
with this format we have 8 chars left for the directory name
*/
#define SOCKET_FORMAT "%u_%05u"
#define SOCKET_FORMAT "%c%02X%04X"
#define SOCKET_TYPE_CHAR_TCP 'T'
#define SOCKET_TYPE_CHAR_UDP 'U'
static struct sockaddr *sockaddr_dup(const void *data, socklen_t len)
{
@ -80,6 +82,7 @@ struct socket_info
int type;
int protocol;
int bound;
int bcast;
char *path;
char *tmp_path;
@ -108,45 +111,199 @@ static const char *socket_wrapper_dir(void)
return s;
}
static unsigned int socket_wrapper_default_iface(void)
{
const char *s = getenv("SOCKET_WRAPPER_DEFAULT_IFACE");
if (s) {
unsigned int iface;
if (sscanf(s, "%u", &iface) == 1) {
if (iface >= 1 && iface <= 0xFF) {
return iface;
}
}
}
return 1;/* 127.0.0.1 */
}
static int convert_un_in(const struct sockaddr_un *un, struct sockaddr_in *in, socklen_t *len)
{
unsigned int iface;
unsigned int prt;
const char *p;
int type;
char type;
if ((*len) < sizeof(struct sockaddr_in)) {
return 0;
}
in->sin_family = AF_INET;
in->sin_port = htons(1025); /* Default to 1025 */
p = strrchr(un->sun_path, '/');
if (p) p++; else p = un->sun_path;
if (sscanf(p, SOCKET_FORMAT, &type, &prt) == 2) {
in->sin_port = htons(prt);
if (sscanf(p, SOCKET_FORMAT, &type, &iface, &prt) != 3) {
errno = EINVAL;
return -1;
}
in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (type != SOCKET_TYPE_CHAR_TCP && type != SOCKET_TYPE_CHAR_UDP) {
errno = EINVAL;
return -1;
}
if (iface == 0 || iface > 0xFF) {
errno = EINVAL;
return -1;
}
if (prt > 0xFFFF) {
errno = EINVAL;
return -1;
}
in->sin_addr.s_addr = htonl((127<<24) | iface);
in->sin_port = htons(prt);
*len = sizeof(struct sockaddr_in);
return 0;
}
static int convert_in_un(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un)
static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
int *bcast)
{
int type = si->type;
uint16_t prt = ntohs(in->sin_port);
char u_type = '\0';
char b_type = '\0';
char a_type = '\0';
char type = '\0';
unsigned int addr= ntohl(in->sin_addr.s_addr);
unsigned int prt = ntohs(in->sin_port);
unsigned int iface;
int is_bcast = 0;
if (bcast) *bcast = 0;
if (prt == 0) {
struct stat st;
/* handle auto-allocation of ephemeral ports */
prt = 5000;
do {
snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
socket_wrapper_dir(), type, ++prt);
} while (stat(un->sun_path, &st) == 0 && prt < 10000);
((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
}
errno = EINVAL;
return -1;
}
switch (si->type) {
case SOCK_STREAM:
u_type = SOCKET_TYPE_CHAR_TCP;
break;
case SOCK_DGRAM:
u_type = SOCKET_TYPE_CHAR_UDP;
a_type = SOCKET_TYPE_CHAR_UDP;
b_type = SOCKET_TYPE_CHAR_UDP;
break;
}
if (a_type && addr == 0xFFFFFFFF) {
/* 255.255.255.255 only udp */
is_bcast = 2;
type = a_type;
iface = socket_wrapper_default_iface();
} else if (b_type && addr == 0x7FFFFFFF) {
/* 127.255.255.255 only udp */
is_bcast = 1;
type = b_type;
iface = socket_wrapper_default_iface();
} else if ((addr & 0xFFFFFF00) == 0x7F000000) {
/* 127.0.0.X */
is_bcast = 0;
type = u_type;
iface = (addr & 0x000000FF);
} else {
errno = ENETUNREACH;
return -1;
}
if (bcast) *bcast = is_bcast;
if (is_bcast) {
snprintf(un->sun_path, sizeof(un->sun_path), "%s/EINVAL",
socket_wrapper_dir());
/* the caller need to do more processing */
return 0;
}
snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
socket_wrapper_dir(), type, prt);
socket_wrapper_dir(), type, iface, prt);
return 0;
}
static int convert_in_un_alloc(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
int *bcast)
{
char u_type = '\0';
char d_type = '\0';
char b_type = '\0';
char a_type = '\0';
char type = '\0';
unsigned int addr= ntohl(in->sin_addr.s_addr);
unsigned int prt = ntohs(in->sin_port);
unsigned int iface;
struct stat st;
int is_bcast = 0;
if (bcast) *bcast = 0;
switch (si->type) {
case SOCK_STREAM:
u_type = SOCKET_TYPE_CHAR_TCP;
d_type = SOCKET_TYPE_CHAR_TCP;
break;
case SOCK_DGRAM:
u_type = SOCKET_TYPE_CHAR_UDP;
d_type = SOCKET_TYPE_CHAR_UDP;
a_type = SOCKET_TYPE_CHAR_UDP;
b_type = SOCKET_TYPE_CHAR_UDP;
break;
}
if (addr == 0) {
/* 0.0.0.0 */
is_bcast = 0;
type = d_type;
iface = socket_wrapper_default_iface();
} else if (a_type && addr == 0xFFFFFFFF) {
/* 255.255.255.255 only udp */
is_bcast = 2;
type = a_type;
iface = socket_wrapper_default_iface();
} else if (b_type && addr == 0x7FFFFFFF) {
/* 127.255.255.255 only udp */
is_bcast = 1;
type = b_type;
iface = socket_wrapper_default_iface();
} else if ((addr & 0xFFFFFF00) == 0x7F000000) {
/* 127.0.0.X */
is_bcast = 0;
type = u_type;
iface = (addr & 0x000000FF);
} else {
errno = EADDRNOTAVAIL;
return -1;
}
if (bcast) *bcast = is_bcast;
if (prt == 0) {
/* handle auto-allocation of ephemeral ports */
for (prt = 5001; prt < 10000; prt++) {
snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
socket_wrapper_dir(), type, iface, prt);
if (stat(un->sun_path, &st) == 0) continue;
((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
return 0;
}
errno = ENFILE;
return -1;
}
snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
socket_wrapper_dir(), type, iface, prt);
return 0;
}
@ -162,7 +319,7 @@ static struct socket_info *find_socket_info(int fd)
}
static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
struct sockaddr_un *out_addr)
struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
{
if (!out_addr)
return 0;
@ -171,7 +328,19 @@ static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr
switch (in_addr->sa_family) {
case AF_INET:
return convert_in_un(si, (const struct sockaddr_in *)in_addr, out_addr);
switch (si->type) {
case SOCK_STREAM:
case SOCK_DGRAM:
break;
default:
errno = ESOCKTNOSUPPORT;
return -1;
}
if (alloc_sock) {
return convert_in_un_alloc(si, (const struct sockaddr_in *)in_addr, out_addr, bcast);
} 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;
@ -200,6 +369,14 @@ static int sockaddr_convert_from_un(const struct socket_info *si,
switch (family) {
case AF_INET:
switch (si->type) {
case SOCK_STREAM:
case SOCK_DGRAM:
break;
default:
errno = ESOCKTNOSUPPORT;
return -1;
}
return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, out_len);
case AF_UNIX:
memcpy(out_addr, in_addr, sizeof(*in_addr));
@ -288,28 +465,46 @@ static int swrap_auto_bind(struct socket_info *si)
struct sockaddr_un un_addr;
struct sockaddr_in in;
int i;
char type;
int ret;
struct stat st;
un_addr.sun_family = AF_UNIX;
switch (si->type) {
case SOCK_STREAM:
type = SOCKET_TYPE_CHAR_TCP;
break;
case SOCK_DGRAM:
type = SOCKET_TYPE_CHAR_UDP;
break;
default:
errno = ESOCKTNOSUPPORT;
return -1;
}
for (i=0;i<1000;i++) {
snprintf(un_addr.sun_path, sizeof(un_addr.sun_path),
"%s/"SOCKET_FORMAT, socket_wrapper_dir(),
SOCK_DGRAM, i + 10000);
if (bind(si->fd, (struct sockaddr *)&un_addr,
sizeof(un_addr)) == 0) {
si->tmp_path = strdup(un_addr.sun_path);
si->bound = 1;
break;
}
type, socket_wrapper_default_iface(), i + 10000);
if (stat(un_addr.sun_path, &st) == 0) continue;
ret = real_bind(si->fd, (struct sockaddr *)&un_addr, sizeof(un_addr));
if (ret == -1) return ret;
si->tmp_path = strdup(un_addr.sun_path);
si->bound = 1;
break;
}
if (i == 1000) {
errno = ENFILE;
return -1;
}
memset(&in, 0, sizeof(in));
in.sin_family = AF_INET;
in.sin_port = htons(i);
in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
in.sin_addr.s_addr = htonl(127<<24 | socket_wrapper_default_iface());
si->myname_len = sizeof(in);
si->myname = sockaddr_dup(&in, si->myname_len);
@ -328,25 +523,24 @@ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
return real_connect(s, serv_addr, addrlen);
}
/* only allow pseudo loopback connections */
if (serv_addr->sa_family == AF_INET &&
((const struct sockaddr_in *)serv_addr)->sin_addr.s_addr !=
htonl(INADDR_LOOPBACK)) {
errno = ENETUNREACH;
return -1;
}
if (si->bound == 0 && si->domain != AF_UNIX) {
ret = swrap_auto_bind(si);
if (ret == -1) return -1;
}
ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr);
ret = sockaddr_convert_to_un(si, (const struct sockaddr *)serv_addr, addrlen, &un_addr, 0, NULL);
if (ret == -1) return -1;
ret = real_connect(s, (struct sockaddr *)&un_addr,
sizeof(struct sockaddr_un));
/* to give better errors */
if (serv_addr->sa_family == AF_INET) {
if (ret == -1 && errno == ENOENT) {
errno = EHOSTUNREACH;
}
}
if (ret == 0) {
si->peername_len = addrlen;
si->peername = sockaddr_dup(serv_addr, addrlen);
@ -368,12 +562,7 @@ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
si->myname_len = addrlen;
si->myname = sockaddr_dup(myaddr, addrlen);
if (myaddr->sa_family == AF_INET &&
((const struct sockaddr_in *)myaddr)->sin_addr.s_addr == 0) {
((struct sockaddr_in *)si->myname)->sin_addr.s_addr =
htonl(INADDR_LOOPBACK);
}
ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr);
ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr, 1, &si->bcast);
if (ret == -1) return -1;
unlink(un_addr.sun_path);
@ -501,6 +690,7 @@ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const str
struct sockaddr_un un_addr;
int ret;
struct socket_info *si = find_socket_info(s);
int bcast = 0;
if (!si) {
return real_sendto(s, buf, len, flags, to, tolen);
@ -511,11 +701,37 @@ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const str
if (ret == -1) return -1;
}
ret = sockaddr_convert_to_un(si, to, tolen, &un_addr);
ret = sockaddr_convert_to_un(si, to, tolen, &un_addr, 0, &bcast);
if (ret == -1) return -1;
if (bcast) {
struct stat st;
unsigned int iface;
unsigned int prt = ntohs(((const struct sockaddr_in *)to)->sin_port);
char type;
type = SOCKET_TYPE_CHAR_UDP;
for(iface=0; iface <= 0xFF; 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;
/* ignore the any errors in broadcast sends */
real_sendto(s, buf, len, flags, (struct sockaddr *)&un_addr, sizeof(un_addr));
}
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;
}
}
return ret;
}

View File

@ -82,18 +82,15 @@ rm -rf $PREFIX/*
mkdir -p $PRIVATEDIR $LIBDIR $PIDDIR $NCALRPCDIR $LOCKDIR $TMPDIR $TLSDIR
cat >$PRIVATEDIR/wins.ldif<<EOF
dn: name=127.0.0.1,CN=PARTNERS
dn: name=TORTURE_26,CN=PARTNERS
objectClass: wreplPartner
name: 127.0.0.1
address: 127.0.0.1
pullRetryInterval: 100
pullInterval: 200
type: 0x2
name: TORTURE_26
address: 127.0.0.26
pullInterval: 0
pushChangeCount: 0
type: 0x3
EOF
WREPL_TORTURE_OPTIONS=
export WREPL_TORTURE_OPTIONS
cat >$CONFFILE<<EOF
[global]
netbios name = $SERVER
@ -106,7 +103,7 @@ cat >$CONFFILE<<EOF
setup directory = $SRCDIR/setup
js include = $SRCDIR/scripting/libjs
name resolve order = bcast
interfaces = lo*
interfaces = 127.0.0.1/8
tls enabled = $TLS_ENABLED
panic action = $SRCDIR/script/gdb_backtrace %PID% %PROG%
wins support = yes
@ -163,13 +160,17 @@ if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
CONFIGURATION="$CONFIGURATION --option=\"torture:progress=no\""
fi
SOCKET_WRAPPER_DEFAULT_IFACE=1
export SOCKET_WRAPPER_DEFAULT_IFACE
smbd_check_or_start
# ensure any one smbtorture call doesn't run too long
TORTURE_OPTIONS="--maximum-runtime=300 $CONFIGURATION"
SOCKET_WRAPPER_DEFAULT_IFACE=26
export SOCKET_WRAPPER_DEFAULT_IFACE
TORTURE_INTERFACES='127.0.0.26/8,127.0.0.27/8,127.0.0.28/8,127.0.0.29/8,127.0.0.30/8,127.0.0.31/8'
TORTURE_OPTIONS="--maximum-runtime=300 --option=interfaces=$TORTURE_INTERFACES $CONFIGURATION"
export TORTURE_OPTIONS
START=`date`
(
# give time for nbt server to register its names

View File

@ -18,12 +18,11 @@ SCRIPTDIR=../testprogs/ejs
PATH=bin:$PATH
export PATH
for f in NBT-REGISTER NBT-WINS; do
testit "nmblookup -U $SERVER $SERVER" bin/nmblookup $TORTURE_OPTIONS -U $SERVER $SERVER || failed=`expr $failed + 1`
testit "nmblookup $SERVER" bin/nmblookup $TORTURE_OPTIONS $SERVER || failed=`expr $failed + 1`
for f in NBT-REGISTER NBT-WINS NBT-WINSREPLICATION-QUICK; do
testit "$f" bin/smbtorture $TORTURE_OPTIONS //$SERVER/_none_ $f || failed=`expr $failed + 1`
done
for f in NBT-WINSREPLICATION-QUICK; do
testit "$f" bin/smbtorture $TORTURE_OPTIONS $WREPL_TORTURE_OPTIONS //$SERVER/_none_ $f || failed=`expr $failed + 1`
done
testok $0 $failed