aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipvs/ip_vs_sync.c
diff options
context:
space:
mode:
authorJulian Anastasov <ja@ssi.bg>2005-09-15 00:08:51 -0400
committerDavid S. Miller <davem@davemloft.net>2005-09-15 00:08:51 -0400
commit87375ab47cd0ba04124c6d3fd80db5c368f5dcb6 (patch)
treec95f160e2b033b5f8d2fad58348400bab5f989f2 /net/ipv4/ipvs/ip_vs_sync.c
parentf5e229db9cdb27f83594712ca4bb98d9377eb6ed (diff)
[IPVS]: ip_vs_ftp breaks connections using persistence
ip_vs_ftp when loaded can create NAT connections with unknown client port for passive FTP. For such expectations we lookup with cport=0 on incoming packet but it matches the format of the persistence templates causing packets to other persistent virtual servers to be forwarded to real server without creating connection. Later the reply packets are treated as foreign and not SNAT-ed. This patch changes the connection lookup for packets from clients: * introduce IP_VS_CONN_F_TEMPLATE connection flag to mark the connection as template * create new connection lookup function just for templates - ip_vs_ct_in_get * make sure ip_vs_conn_in_get hits only connections with IP_VS_CONN_F_NO_CPORT flag set when s_port is 0. By this way we avoid returning template when looking for cport=0 (ftp) Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipvs/ip_vs_sync.c')
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 574d1f509b46..2e5ced3d8062 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -297,16 +297,24 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
297 297
298 p = (char *)buffer + sizeof(struct ip_vs_sync_mesg); 298 p = (char *)buffer + sizeof(struct ip_vs_sync_mesg);
299 for (i=0; i<m->nr_conns; i++) { 299 for (i=0; i<m->nr_conns; i++) {
300 unsigned flags;
301
300 s = (struct ip_vs_sync_conn *)p; 302 s = (struct ip_vs_sync_conn *)p;
301 cp = ip_vs_conn_in_get(s->protocol, 303 flags = ntohs(s->flags);
302 s->caddr, s->cport, 304 if (!(flags & IP_VS_CONN_F_TEMPLATE))
303 s->vaddr, s->vport); 305 cp = ip_vs_conn_in_get(s->protocol,
306 s->caddr, s->cport,
307 s->vaddr, s->vport);
308 else
309 cp = ip_vs_ct_in_get(s->protocol,
310 s->caddr, s->cport,
311 s->vaddr, s->vport);
304 if (!cp) { 312 if (!cp) {
305 cp = ip_vs_conn_new(s->protocol, 313 cp = ip_vs_conn_new(s->protocol,
306 s->caddr, s->cport, 314 s->caddr, s->cport,
307 s->vaddr, s->vport, 315 s->vaddr, s->vport,
308 s->daddr, s->dport, 316 s->daddr, s->dport,
309 ntohs(s->flags), NULL); 317 flags, NULL);
310 if (!cp) { 318 if (!cp) {
311 IP_VS_ERR("ip_vs_conn_new failed\n"); 319 IP_VS_ERR("ip_vs_conn_new failed\n");
312 return; 320 return;
@@ -315,11 +323,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
315 } else if (!cp->dest) { 323 } else if (!cp->dest) {
316 /* it is an entry created by the synchronization */ 324 /* it is an entry created by the synchronization */
317 cp->state = ntohs(s->state); 325 cp->state = ntohs(s->state);
318 cp->flags = ntohs(s->flags) | IP_VS_CONN_F_HASHED; 326 cp->flags = flags | IP_VS_CONN_F_HASHED;
319 } /* Note that we don't touch its state and flags 327 } /* Note that we don't touch its state and flags
320 if it is a normal entry. */ 328 if it is a normal entry. */
321 329
322 if (ntohs(s->flags) & IP_VS_CONN_F_SEQ_MASK) { 330 if (flags & IP_VS_CONN_F_SEQ_MASK) {
323 opt = (struct ip_vs_sync_conn_options *)&s[1]; 331 opt = (struct ip_vs_sync_conn_options *)&s[1];
324 memcpy(&cp->in_seq, opt, sizeof(*opt)); 332 memcpy(&cp->in_seq, opt, sizeof(*opt));
325 p += FULL_CONN_SIZE; 333 p += FULL_CONN_SIZE;