Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipvs: inspect reply packets from DR/TUN real servers

Just like for MASQ, inspect the reply packets coming from DR/TUN
real servers and alter the connection's state and timeout
according to the protocol.

It's ipvs's duty to do traffic statistic if packets get hit,
no matter what mode it is.

Signed-off-by: longguang.yue <bigclouds@163.com>
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

longguang.yue and committed by
Pablo Neira Ayuso
073b04e7 bc081a69

+22 -15
+15 -3
net/netfilter/ipvs/ip_vs_conn.c
··· 402 402 { 403 403 unsigned int hash; 404 404 struct ip_vs_conn *cp, *ret=NULL; 405 + const union nf_inet_addr *saddr; 406 + __be16 sport; 405 407 406 408 /* 407 409 * Check for "full" addressed entries ··· 413 411 rcu_read_lock(); 414 412 415 413 hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) { 416 - if (p->vport == cp->cport && p->cport == cp->dport && 417 - cp->af == p->af && 414 + if (p->vport != cp->cport) 415 + continue; 416 + 417 + if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) { 418 + sport = cp->vport; 419 + saddr = &cp->vaddr; 420 + } else { 421 + sport = cp->dport; 422 + saddr = &cp->daddr; 423 + } 424 + 425 + if (p->cport == sport && cp->af == p->af && 418 426 ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) && 419 - ip_vs_addr_equal(p->af, p->caddr, &cp->daddr) && 427 + ip_vs_addr_equal(p->af, p->caddr, saddr) && 420 428 p->protocol == cp->protocol && 421 429 cp->ipvs == p->ipvs) { 422 430 if (!__ip_vs_conn_get(cp))
+7 -12
net/netfilter/ipvs/ip_vs_core.c
··· 875 875 unsigned int verdict = NF_DROP; 876 876 877 877 if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) 878 - goto ignore_cp; 878 + goto after_nat; 879 879 880 880 /* Ensure the checksum is correct */ 881 881 if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) { ··· 901 901 if (ip_vs_route_me_harder(cp->ipvs, af, skb, hooknum)) 902 902 goto out; 903 903 904 + after_nat: 904 905 /* do the statistics and put it back */ 905 906 ip_vs_out_stats(cp, skb); 906 907 ··· 910 909 ip_vs_notrack(skb); 911 910 else 912 911 ip_vs_update_conntrack(skb, cp, 0); 913 - 914 - ignore_cp: 915 912 verdict = NF_ACCEPT; 916 913 917 914 out: ··· 1275 1276 { 1276 1277 struct ip_vs_protocol *pp = pd->pp; 1277 1278 1279 + if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) 1280 + goto after_nat; 1281 + 1278 1282 IP_VS_DBG_PKT(11, af, pp, skb, iph->off, "Outgoing packet"); 1279 1283 1280 1284 if (skb_ensure_writable(skb, iph->len)) ··· 1318 1316 1319 1317 IP_VS_DBG_PKT(10, af, pp, skb, iph->off, "After SNAT"); 1320 1318 1319 + after_nat: 1321 1320 ip_vs_out_stats(cp, skb); 1322 1321 ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd); 1323 1322 skb->ipvs_property = 1; ··· 1415 1412 cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto, 1416 1413 ipvs, af, skb, &iph); 1417 1414 1418 - if (likely(cp)) { 1419 - if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) 1420 - goto ignore_cp; 1415 + if (likely(cp)) 1421 1416 return handle_response(af, skb, pd, cp, &iph, hooknum); 1422 - } 1423 1417 1424 1418 /* Check for real-server-started requests */ 1425 1419 if (atomic_read(&ipvs->conn_out_counter)) { ··· 1475 1475 } 1476 1476 } 1477 1477 1478 - out: 1479 1478 IP_VS_DBG_PKT(12, af, pp, skb, iph.off, 1480 1479 "ip_vs_out: packet continues traversal as normal"); 1481 1480 return NF_ACCEPT; 1482 - 1483 - ignore_cp: 1484 - __ip_vs_conn_put(cp); 1485 - goto out; 1486 1481 } 1487 1482 1488 1483 /*