summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2010-02-17 08:49:28 +0100
committerStefan Metzmacher <metze@samba.org>2010-02-17 14:46:08 +0100
commit8a0949dfc8d2ecf577dfc5ef38496421101b734e (patch)
treed7b27af40979f9c8d0b2a6576059f47e6f45ac79
parent6637b2f4b06fcee1e8e1b1782dd96e3273f8caac (diff)
downloadsamba-8a0949dfc8d2ecf577dfc5ef38496421101b734e.tar.gz
samba-8a0949dfc8d2ecf577dfc5ef38496421101b734e.tar.bz2
samba-8a0949dfc8d2ecf577dfc5ef38496421101b734e.zip
tsocket/bsd: fix bug #7140 autodetect ipv4 and ipv6 based on the remote address if the local address is any
metze
-rw-r--r--lib/tsocket/tsocket_bsd.c55
1 files changed, 53 insertions, 2 deletions
diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c
index 8d1fe32083..2b0a24a58c 100644
--- a/lib/tsocket/tsocket_bsd.c
+++ b/lib/tsocket/tsocket_bsd.c
@@ -1142,6 +1142,8 @@ static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
int ret;
bool do_bind = false;
bool do_reuseaddr = false;
+ bool is_inet = false;
+ int sa_fam = lbsda->u.sa.sa_family;
socklen_t sa_socklen = sizeof(lbsda->u.ss);
if (remote) {
@@ -1173,6 +1175,8 @@ static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
if (lbsda->u.in.sin_addr.s_addr != INADDR_ANY) {
do_bind = true;
}
+ is_inet = true;
+ sa_socklen = sizeof(rbsda->u.in);
break;
#ifdef HAVE_IPV6
case AF_INET6:
@@ -1185,6 +1189,8 @@ static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
sizeof(in6addr_any)) != 0) {
do_bind = true;
}
+ is_inet = true;
+ sa_socklen = sizeof(rbsda->u.in6);
break;
#endif
default:
@@ -1192,7 +1198,21 @@ static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
return -1;
}
- fd = socket(lbsda->u.sa.sa_family, SOCK_DGRAM, 0);
+ if (!do_bind && is_inet && rbsda) {
+ sa_fam = rbsda->u.sa.sa_family;
+ switch (sa_fam) {
+ case AF_INET:
+ sa_socklen = sizeof(rbsda->u.in);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ sa_socklen = sizeof(rbsda->u.in6);
+ break;
+#endif
+ }
+ }
+
+ fd = socket(sa_fam, SOCK_DGRAM, 0);
if (fd < 0) {
return fd;
}
@@ -1254,6 +1274,12 @@ static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
}
if (rbsda) {
+ if (rbsda->u.sa.sa_family != sa_fam) {
+ talloc_free(dgram);
+ errno = EINVAL;
+ return -1;
+ }
+
ret = connect(fd, &rbsda->u.sa, sa_socklen);
if (ret == -1) {
int saved_errno = errno;
@@ -1944,6 +1970,8 @@ static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
bool retry;
bool do_bind = false;
bool do_reuseaddr = false;
+ bool is_inet = false;
+ int sa_fam = lbsda->u.sa.sa_family;
socklen_t sa_socklen = sizeof(rbsda->u.ss);
req = tevent_req_create(mem_ctx, &state,
@@ -1982,6 +2010,8 @@ static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
if (lbsda->u.in.sin_addr.s_addr != INADDR_ANY) {
do_bind = true;
}
+ is_inet = true;
+ sa_socklen = sizeof(rbsda->u.in);
break;
#ifdef HAVE_IPV6
case AF_INET6:
@@ -1994,6 +2024,8 @@ static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
sizeof(in6addr_any)) != 0) {
do_bind = true;
}
+ is_inet = true;
+ sa_socklen = sizeof(rbsda->u.in6);
break;
#endif
default:
@@ -2001,7 +2033,21 @@ static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
goto post;
}
- state->fd = socket(lbsda->u.sa.sa_family, SOCK_STREAM, 0);
+ if (!do_bind && is_inet) {
+ sa_fam = rbsda->u.sa.sa_family;
+ switch (sa_fam) {
+ case AF_INET:
+ sa_socklen = sizeof(rbsda->u.in);
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6:
+ sa_socklen = sizeof(rbsda->u.in6);
+ break;
+#endif
+ }
+ }
+
+ state->fd = socket(sa_fam, SOCK_STREAM, 0);
if (state->fd == -1) {
tevent_req_error(req, errno);
goto post;
@@ -2032,6 +2078,11 @@ static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
}
}
+ if (rbsda->u.sa.sa_family != sa_fam) {
+ tevent_req_error(req, EINVAL);
+ goto post;
+ }
+
ret = connect(state->fd, &rbsda->u.sa, sa_socklen);
err = tsocket_bsd_error_from_errno(ret, errno, &retry);
if (retry) {