ipvs: skip ipv6 extension headers for csum checks
Protocol checksum validation fails for IPv6 if there are extension headers before the protocol header. iph->len already contains its offset, so use it to fix the problem. Fixes:2906f66a56("ipvs: SCTP Trasport Loadbalancing Support") Fixes:0bbdd42b7e("IPVS: Extend protocol DNAT/SNAT and state handlers") Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Florian Westphal <fw@strlen.de>
This commit is contained in:
parent
4edd4ba71c
commit
05cfe9863e
|
|
@ -10,7 +10,8 @@
|
|||
#include <net/ip_vs.h>
|
||||
|
||||
static int
|
||||
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
|
||||
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int sctphoff);
|
||||
|
||||
static int
|
||||
sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
|
||||
|
|
@ -108,7 +109,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!sctp_csum_check(cp->af, skb, pp))
|
||||
if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
|
||||
return 0;
|
||||
|
||||
/* Call application helper if needed */
|
||||
|
|
@ -156,7 +157,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!sctp_csum_check(cp->af, skb, pp))
|
||||
if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
|
||||
return 0;
|
||||
|
||||
/* Call application helper if needed */
|
||||
|
|
@ -185,19 +186,12 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
}
|
||||
|
||||
static int
|
||||
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
||||
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int sctphoff)
|
||||
{
|
||||
unsigned int sctphoff;
|
||||
struct sctphdr *sh;
|
||||
__le32 cmp, val;
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (af == AF_INET6)
|
||||
sctphoff = sizeof(struct ipv6hdr);
|
||||
else
|
||||
#endif
|
||||
sctphoff = ip_hdrlen(skb);
|
||||
|
||||
sh = (struct sctphdr *)(skb->data + sctphoff);
|
||||
cmp = sh->checksum;
|
||||
val = sctp_compute_cksum(skb, sctphoff);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
#include <net/ip_vs.h>
|
||||
|
||||
static int
|
||||
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
|
||||
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int tcphoff);
|
||||
|
||||
static int
|
||||
tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
|
||||
|
|
@ -165,7 +166,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!tcp_csum_check(cp->af, skb, pp))
|
||||
if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
|
||||
return 0;
|
||||
|
||||
/* Call application helper if needed */
|
||||
|
|
@ -243,7 +244,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!tcp_csum_check(cp->af, skb, pp))
|
||||
if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
@ -300,17 +301,9 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
|
||||
|
||||
static int
|
||||
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
||||
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int tcphoff)
|
||||
{
|
||||
unsigned int tcphoff;
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (af == AF_INET6)
|
||||
tcphoff = sizeof(struct ipv6hdr);
|
||||
else
|
||||
#endif
|
||||
tcphoff = ip_hdrlen(skb);
|
||||
|
||||
switch (skb->ip_summed) {
|
||||
case CHECKSUM_NONE:
|
||||
skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
|
||||
|
|
@ -321,7 +314,7 @@ tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
|||
if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
|
||||
&ipv6_hdr(skb)->daddr,
|
||||
skb->len - tcphoff,
|
||||
ipv6_hdr(skb)->nexthdr,
|
||||
IPPROTO_TCP,
|
||||
skb->csum)) {
|
||||
IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
|
||||
"Failed checksum for");
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@
|
|||
#include <net/ip6_checksum.h>
|
||||
|
||||
static int
|
||||
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
|
||||
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int udphoff);
|
||||
|
||||
static int
|
||||
udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
|
||||
|
|
@ -154,7 +155,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!udp_csum_check(cp->af, skb, pp))
|
||||
if (!udp_csum_check(cp->af, skb, pp, udphoff))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
@ -237,7 +238,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!udp_csum_check(cp->af, skb, pp))
|
||||
if (!udp_csum_check(cp->af, skb, pp, udphoff))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
@ -296,17 +297,10 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
|
||||
|
||||
static int
|
||||
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
||||
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int udphoff)
|
||||
{
|
||||
struct udphdr _udph, *uh;
|
||||
unsigned int udphoff;
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (af == AF_INET6)
|
||||
udphoff = sizeof(struct ipv6hdr);
|
||||
else
|
||||
#endif
|
||||
udphoff = ip_hdrlen(skb);
|
||||
|
||||
uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph);
|
||||
if (uh == NULL)
|
||||
|
|
@ -324,7 +318,7 @@ udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
|||
if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
|
||||
&ipv6_hdr(skb)->daddr,
|
||||
skb->len - udphoff,
|
||||
ipv6_hdr(skb)->nexthdr,
|
||||
IPPROTO_UDP,
|
||||
skb->csum)) {
|
||||
IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
|
||||
"Failed checksum for");
|
||||
|
|
|
|||
Loading…
Reference in New Issue