Skip to content

Commit 05cfe98

Browse files
Julian AnastasovFlorian Westphal
authored andcommitted
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: 2906f66 ("ipvs: SCTP Trasport Loadbalancing Support") Fixes: 0bbdd42 ("IPVS: Extend protocol DNAT/SNAT and state handlers") Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Florian Westphal <fw@strlen.de>
1 parent 4edd4ba commit 05cfe98

3 files changed

Lines changed: 20 additions & 39 deletions

File tree

net/netfilter/ipvs/ip_vs_proto_sctp.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
#include <net/ip_vs.h>
1111

1212
static int
13-
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
13+
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
14+
unsigned int sctphoff);
1415

1516
static int
1617
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,
108109
int ret;
109110

110111
/* Some checks before mangling */
111-
if (!sctp_csum_check(cp->af, skb, pp))
112+
if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
112113
return 0;
113114

114115
/* Call application helper if needed */
@@ -156,7 +157,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
156157
int ret;
157158

158159
/* Some checks before mangling */
159-
if (!sctp_csum_check(cp->af, skb, pp))
160+
if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
160161
return 0;
161162

162163
/* Call application helper if needed */
@@ -185,19 +186,12 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
185186
}
186187

187188
static int
188-
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
189+
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
190+
unsigned int sctphoff)
189191
{
190-
unsigned int sctphoff;
191192
struct sctphdr *sh;
192193
__le32 cmp, val;
193194

194-
#ifdef CONFIG_IP_VS_IPV6
195-
if (af == AF_INET6)
196-
sctphoff = sizeof(struct ipv6hdr);
197-
else
198-
#endif
199-
sctphoff = ip_hdrlen(skb);
200-
201195
sh = (struct sctphdr *)(skb->data + sctphoff);
202196
cmp = sh->checksum;
203197
val = sctp_compute_cksum(skb, sctphoff);

net/netfilter/ipvs/ip_vs_proto_tcp.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
#include <net/ip_vs.h>
2929

3030
static int
31-
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
31+
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
32+
unsigned int tcphoff);
3233

3334
static int
3435
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,
165166
int ret;
166167

167168
/* Some checks before mangling */
168-
if (!tcp_csum_check(cp->af, skb, pp))
169+
if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
169170
return 0;
170171

171172
/* Call application helper if needed */
@@ -243,7 +244,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
243244
int ret;
244245

245246
/* Some checks before mangling */
246-
if (!tcp_csum_check(cp->af, skb, pp))
247+
if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
247248
return 0;
248249

249250
/*
@@ -300,17 +301,9 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
300301

301302

302303
static int
303-
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
304+
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
305+
unsigned int tcphoff)
304306
{
305-
unsigned int tcphoff;
306-
307-
#ifdef CONFIG_IP_VS_IPV6
308-
if (af == AF_INET6)
309-
tcphoff = sizeof(struct ipv6hdr);
310-
else
311-
#endif
312-
tcphoff = ip_hdrlen(skb);
313-
314307
switch (skb->ip_summed) {
315308
case CHECKSUM_NONE:
316309
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)
321314
if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
322315
&ipv6_hdr(skb)->daddr,
323316
skb->len - tcphoff,
324-
ipv6_hdr(skb)->nexthdr,
317+
IPPROTO_TCP,
325318
skb->csum)) {
326319
IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
327320
"Failed checksum for");

net/netfilter/ipvs/ip_vs_proto_udp.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#include <net/ip6_checksum.h>
2525

2626
static int
27-
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
27+
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
28+
unsigned int udphoff);
2829

2930
static int
3031
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,
154155
int ret;
155156

156157
/* Some checks before mangling */
157-
if (!udp_csum_check(cp->af, skb, pp))
158+
if (!udp_csum_check(cp->af, skb, pp, udphoff))
158159
return 0;
159160

160161
/*
@@ -237,7 +238,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
237238
int ret;
238239

239240
/* Some checks before mangling */
240-
if (!udp_csum_check(cp->af, skb, pp))
241+
if (!udp_csum_check(cp->af, skb, pp, udphoff))
241242
return 0;
242243

243244
/*
@@ -296,17 +297,10 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
296297

297298

298299
static int
299-
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
300+
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
301+
unsigned int udphoff)
300302
{
301303
struct udphdr _udph, *uh;
302-
unsigned int udphoff;
303-
304-
#ifdef CONFIG_IP_VS_IPV6
305-
if (af == AF_INET6)
306-
udphoff = sizeof(struct ipv6hdr);
307-
else
308-
#endif
309-
udphoff = ip_hdrlen(skb);
310304

311305
uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph);
312306
if (uh == NULL)
@@ -324,7 +318,7 @@ udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
324318
if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
325319
&ipv6_hdr(skb)->daddr,
326320
skb->len - udphoff,
327-
ipv6_hdr(skb)->nexthdr,
321+
IPPROTO_UDP,
328322
skb->csum)) {
329323
IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
330324
"Failed checksum for");

0 commit comments

Comments
 (0)