From: Stefan Metzmacher Date: Wed, 17 Feb 2010 07:49:28 +0000 (+0100) Subject: tsocket/bsd: fix bug #7140 autodetect ipv4 and ipv6 based on the remote address if... X-Git-Url: http://git.samba.org/?p=abartlet%2Fsamba.git%2F.git;a=commitdiff_plain;h=8a0949dfc8d2ecf577dfc5ef38496421101b734e tsocket/bsd: fix bug #7140 autodetect ipv4 and ipv6 based on the remote address if the local address is any metze --- diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c index 8d1fe320834..2b0a24a58ce 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) {