Commit 073b04e7 authored by longguang.yue's avatar longguang.yue Committed by Pablo Neira Ayuso

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: default avatarlongguang.yue <bigclouds@163.com>
Signed-off-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent bc081a69
...@@ -402,6 +402,8 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p) ...@@ -402,6 +402,8 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
{ {
unsigned int hash; unsigned int hash;
struct ip_vs_conn *cp, *ret=NULL; struct ip_vs_conn *cp, *ret=NULL;
const union nf_inet_addr *saddr;
__be16 sport;
/* /*
* Check for "full" addressed entries * Check for "full" addressed entries
...@@ -411,10 +413,20 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p) ...@@ -411,10 +413,20 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
rcu_read_lock(); rcu_read_lock();
hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) { hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) {
if (p->vport == cp->cport && p->cport == cp->dport && if (p->vport != cp->cport)
cp->af == p->af && continue;
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
sport = cp->vport;
saddr = &cp->vaddr;
} else {
sport = cp->dport;
saddr = &cp->daddr;
}
if (p->cport == sport && cp->af == p->af &&
ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) && ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) &&
ip_vs_addr_equal(p->af, p->caddr, &cp->daddr) && ip_vs_addr_equal(p->af, p->caddr, saddr) &&
p->protocol == cp->protocol && p->protocol == cp->protocol &&
cp->ipvs == p->ipvs) { cp->ipvs == p->ipvs) {
if (!__ip_vs_conn_get(cp)) if (!__ip_vs_conn_get(cp))
......
...@@ -875,7 +875,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb, ...@@ -875,7 +875,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
unsigned int verdict = NF_DROP; unsigned int verdict = NF_DROP;
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
goto ignore_cp; goto after_nat;
/* Ensure the checksum is correct */ /* Ensure the checksum is correct */
if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) { if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
...@@ -901,6 +901,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb, ...@@ -901,6 +901,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
if (ip_vs_route_me_harder(cp->ipvs, af, skb, hooknum)) if (ip_vs_route_me_harder(cp->ipvs, af, skb, hooknum))
goto out; goto out;
after_nat:
/* do the statistics and put it back */ /* do the statistics and put it back */
ip_vs_out_stats(cp, skb); ip_vs_out_stats(cp, skb);
...@@ -909,8 +910,6 @@ static int handle_response_icmp(int af, struct sk_buff *skb, ...@@ -909,8 +910,6 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
ip_vs_notrack(skb); ip_vs_notrack(skb);
else else
ip_vs_update_conntrack(skb, cp, 0); ip_vs_update_conntrack(skb, cp, 0);
ignore_cp:
verdict = NF_ACCEPT; verdict = NF_ACCEPT;
out: out:
...@@ -1276,6 +1275,9 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, ...@@ -1276,6 +1275,9 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
{ {
struct ip_vs_protocol *pp = pd->pp; struct ip_vs_protocol *pp = pd->pp;
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
goto after_nat;
IP_VS_DBG_PKT(11, af, pp, skb, iph->off, "Outgoing packet"); IP_VS_DBG_PKT(11, af, pp, skb, iph->off, "Outgoing packet");
if (skb_ensure_writable(skb, iph->len)) if (skb_ensure_writable(skb, iph->len))
...@@ -1316,6 +1318,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, ...@@ -1316,6 +1318,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
IP_VS_DBG_PKT(10, af, pp, skb, iph->off, "After SNAT"); IP_VS_DBG_PKT(10, af, pp, skb, iph->off, "After SNAT");
after_nat:
ip_vs_out_stats(cp, skb); ip_vs_out_stats(cp, skb);
ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd); ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd);
skb->ipvs_property = 1; skb->ipvs_property = 1;
...@@ -1412,11 +1415,8 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in ...@@ -1412,11 +1415,8 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto, cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
ipvs, af, skb, &iph); ipvs, af, skb, &iph);
if (likely(cp)) { if (likely(cp))
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
goto ignore_cp;
return handle_response(af, skb, pd, cp, &iph, hooknum); return handle_response(af, skb, pd, cp, &iph, hooknum);
}
/* Check for real-server-started requests */ /* Check for real-server-started requests */
if (atomic_read(&ipvs->conn_out_counter)) { if (atomic_read(&ipvs->conn_out_counter)) {
...@@ -1475,14 +1475,9 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in ...@@ -1475,14 +1475,9 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
} }
} }
out:
IP_VS_DBG_PKT(12, af, pp, skb, iph.off, IP_VS_DBG_PKT(12, af, pp, skb, iph.off,
"ip_vs_out: packet continues traversal as normal"); "ip_vs_out: packet continues traversal as normal");
return NF_ACCEPT; return NF_ACCEPT;
ignore_cp:
__ip_vs_conn_put(cp);
goto out;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment