ipvs: Handle inverse and icmp headers in ip_vs_leave
Signed-off-by: Alex Gartrell <agartrell@fb.com> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
This commit is contained in:
parent
4fd9beef37
commit
0b72902120
@ -519,6 +519,17 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
|
||||
return cp;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
static inline int ip_vs_addr_is_unicast(struct net *net, int af,
|
||||
union nf_inet_addr *addr)
|
||||
{
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (af == AF_INET6)
|
||||
return ipv6_addr_type(&addr->in6) & IPV6_ADDR_UNICAST;
|
||||
#endif
|
||||
return (inet_addr_type(net, addr->ip) == RTN_UNICAST);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Pass or drop the packet.
|
||||
@ -528,33 +539,28 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
|
||||
int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
|
||||
struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph)
|
||||
{
|
||||
__be16 _ports[2], *pptr;
|
||||
__be16 _ports[2], *pptr, dport;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct net *net;
|
||||
struct netns_ipvs *ipvs;
|
||||
int unicast;
|
||||
#endif
|
||||
|
||||
pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
|
||||
if (pptr == NULL) {
|
||||
if (!pptr)
|
||||
return NF_DROP;
|
||||
}
|
||||
dport = likely(!ip_vs_iph_inverse(iph)) ? pptr[1] : pptr[0];
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
net = skb_net(skb);
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (svc->af == AF_INET6)
|
||||
unicast = ipv6_addr_type(&iph->daddr.in6) & IPV6_ADDR_UNICAST;
|
||||
else
|
||||
#endif
|
||||
unicast = (inet_addr_type(net, iph->daddr.ip) == RTN_UNICAST);
|
||||
|
||||
/* if it is fwmark-based service, the cache_bypass sysctl is up
|
||||
and the destination is a non-local unicast, then create
|
||||
a cache_bypass connection entry */
|
||||
ipvs = net_ipvs(net);
|
||||
if (ipvs->sysctl_cache_bypass && svc->fwmark && unicast) {
|
||||
if (ipvs->sysctl_cache_bypass && svc->fwmark &&
|
||||
!(iph->hdr_flags & (IP_VS_HDR_INVERSE | IP_VS_HDR_ICMP)) &&
|
||||
ip_vs_addr_is_unicast(net, svc->af, &iph->daddr)) {
|
||||
int ret;
|
||||
struct ip_vs_conn *cp;
|
||||
unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
|
||||
@ -598,9 +604,12 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
|
||||
* listed in the ipvs table), pass the packets, because it is
|
||||
* not ipvs job to decide to drop the packets.
|
||||
*/
|
||||
if ((svc->port == FTPPORT) && (pptr[1] != FTPPORT))
|
||||
if (svc->port == FTPPORT && dport != FTPPORT)
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (unlikely(ip_vs_iph_icmp(iph)))
|
||||
return NF_DROP;
|
||||
|
||||
/*
|
||||
* Notify the client that the destination is unreachable, and
|
||||
* release the socket buffer.
|
||||
|
Loading…
Reference in New Issue
Block a user