diff options
author | Stef Walter <stef@thewalter.net> | 2010-11-11 16:38:05 +0000 |
---|---|---|
committer | Stef Walter <stef@thewalter.net> | 2011-01-23 15:47:45 -0600 |
commit | 002738e77ae6149c43a3d55b9364d365e1483578 (patch) | |
tree | d3f61147a8fdee72890a0f6fb7019114012fe80a | |
parent | 0238920875712b4e51f2d96f2146dc477b2de9d8 (diff) |
Don't force connections to come from same source port.
Also allow address reuse for connections in time wait state.
-rw-r--r-- | common/smtppass.c | 4 | ||||
-rw-r--r-- | common/sock_any.c | 25 | ||||
-rw-r--r-- | common/sock_any.h | 2 | ||||
-rw-r--r-- | common/spio.c | 3 |
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; |