summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorStef Walter <stef@thewalter.net>2010-11-11 16:38:05 +0000
committerStef Walter <stef@thewalter.net>2011-01-23 15:47:45 -0600
commit002738e77ae6149c43a3d55b9364d365e1483578 (patch)
treed3f61147a8fdee72890a0f6fb7019114012fe80a /common
parent0238920875712b4e51f2d96f2146dc477b2de9d8 (diff)
Don't force connections to come from same source port.
Also allow address reuse for connections in time wait state.
Diffstat (limited to 'common')
-rw-r--r--common/smtppass.c4
-rw-r--r--common/sock_any.c25
-rw-r--r--common/sock_any.h2
-rw-r--r--common/spio.c3
4 files changed, 30 insertions, 4 deletions
diff --git a/common/smtppass.c b/common/smtppass.c
index 9a6b347..aff8811 100644
--- a/common/smtppass.c
+++ b/common/smtppass.c
@@ -792,6 +792,7 @@ cleanup:
static int make_connections(spctx_t* ctx, int client)
{
struct sockaddr_any peeraddr;
+ struct sockaddr_any peersrc;
struct sockaddr_any addr;
struct sockaddr_any* dstaddr;
struct sockaddr_any* srcaddr;
@@ -839,7 +840,8 @@ static int make_connections(spctx_t* ctx, int client)
if (g_state.transparent == TRANSPARENT_FULL) {
#ifdef HAVE_IP_TRANSPARENT
- srcaddr = &peeraddr;
+ sock_any_cpy (&peersrc, &peeraddr, SANY_OPT_NOPORT);
+ srcaddr = &peersrc;
srcname = ctx->client.peername;
#endif
}
diff --git a/common/sock_any.c b/common/sock_any.c
index 9a03f09..3ca68a3 100644
--- a/common/sock_any.c
+++ b/common/sock_any.c
@@ -367,14 +367,14 @@ int sock_any_cmp(const struct sockaddr_any* a1, const struct sockaddr_any* a2, i
case AF_INET:
if(memcmp(&(a1->s.in.sin_addr), &(a2->s.in.sin_addr), sizeof(a2->s.in.sin_addr)) != 0)
return -1;
- if(!(opts && SANY_OPT_NOPORT) && a1->s.in.sin_port != a2->s.in.sin_port)
+ if(!(opts & SANY_OPT_NOPORT) && a1->s.in.sin_port != a2->s.in.sin_port)
return -1;
return 0;
#ifdef HAVE_INET6
case AF_INET6:
if(memcmp(&(a1->s.in6.sin6_addr), &(a2->s.in6.sin6_addr), sizeof(a2->s.in6.sin6_addr)) != 0)
return -1;
- if(!(opts && SANY_OPT_NOPORT) && a1->s.in6.sin6_port != a2->s.in6.sin6_port)
+ if(!(opts & SANY_OPT_NOPORT) && a1->s.in6.sin6_port != a2->s.in6.sin6_port)
return -1;
return 0;
#endif
@@ -383,3 +383,24 @@ int sock_any_cmp(const struct sockaddr_any* a1, const struct sockaddr_any* a2, i
return -1;
}
}
+
+void
+sock_any_cpy(struct sockaddr_any* dst, const struct sockaddr_any* src, int opts)
+{
+ memcpy(dst, src, sizeof(struct sockaddr_any));
+ switch(src->s.a.sa_family)
+ {
+ case AF_INET:
+ if(opts & SANY_OPT_NOPORT)
+ dst->s.in.sin_port = 0;
+ break;
+#ifdef HAVE_INET6
+ case AF_INET6:
+ if(opts & SANY_OPT_NOPORT)
+ dst->s.in6.sin_port = 0;
+ break;
+#endif
+ default:
+ break;
+ }
+}
diff --git a/common/sock_any.h b/common/sock_any.h
index 9282e36..c8fe63f 100644
--- a/common/sock_any.h
+++ b/common/sock_any.h
@@ -87,4 +87,6 @@ int sock_any_ntop(const struct sockaddr_any* any, char* addr, size_t addrlen, in
int sock_any_cmp(const struct sockaddr_any* a1, const struct sockaddr_any* a2, int opts);
+void sock_any_cpy(struct sockaddr_any* src, const struct sockaddr_any* dst, int opts);
+
#endif /* __SOCK_ANY_H__ */
diff --git a/common/spio.c b/common/spio.c
index f8f2ef1..e9a22e0 100644
--- a/common/spio.c
+++ b/common/spio.c
@@ -180,7 +180,8 @@ int spio_connect(spctx_t* ctx, spio_t* io, const struct sockaddr_any* sdst,
if (ssrc != NULL) {
#ifdef HAVE_IP_TRANSPARENT
int value = 1;
- if(setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value)) < 0) {
+ if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) < 0 ||
+ setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value)) < 0) {
sp_message(ctx, LOG_DEBUG, "%s: couldn't set transparent mode on connection",
GET_IO_NAME(io));
ssrc = NULL;