aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/ipv6.c')
-rw-r--r--net/dccp/ipv6.c74
1 files changed, 47 insertions, 27 deletions
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 201801e1532d..193b946fd039 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -58,12 +58,22 @@ static void dccp_v6_hash(struct sock *sk)
58 } 58 }
59} 59}
60 60
61static inline u16 dccp_v6_check(struct dccp_hdr *dh, int len, 61/* add pseudo-header to DCCP checksum stored in skb->csum */
62 struct in6_addr *saddr, 62static inline u16 dccp_v6_csum_finish(struct sk_buff *skb,
63 struct in6_addr *daddr, 63 struct in6_addr *saddr,
64 unsigned long base) 64 struct in6_addr *daddr)
65{ 65{
66 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_DCCP, base); 66 return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum);
67}
68
69static inline void dccp_v6_send_check(struct sock *sk, int unused_value,
70 struct sk_buff *skb)
71{
72 struct ipv6_pinfo *np = inet6_sk(sk);
73 struct dccp_hdr *dh = dccp_hdr(skb);
74
75 dccp_csum_outgoing(skb);
76 dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
67} 77}
68 78
69static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) 79static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
@@ -280,12 +290,9 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
280 if (skb != NULL) { 290 if (skb != NULL) {
281 struct dccp_hdr *dh = dccp_hdr(skb); 291 struct dccp_hdr *dh = dccp_hdr(skb);
282 292
283 dh->dccph_checksum = dccp_v6_check(dh, skb->len, 293 dh->dccph_checksum = dccp_v6_csum_finish(skb,
284 &ireq6->loc_addr, 294 &ireq6->loc_addr,
285 &ireq6->rmt_addr, 295 &ireq6->rmt_addr);
286 csum_partial((char *)dh,
287 skb->len,
288 skb->csum));
289 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); 296 ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
290 err = ip6_xmit(sk, skb, &fl, opt, 0); 297 err = ip6_xmit(sk, skb, &fl, opt, 0);
291 if (err == NET_XMIT_CN) 298 if (err == NET_XMIT_CN)
@@ -305,18 +312,6 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req)
305 kfree_skb(inet6_rsk(req)->pktopts); 312 kfree_skb(inet6_rsk(req)->pktopts);
306} 313}
307 314
308static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
309{
310 struct ipv6_pinfo *np = inet6_sk(sk);
311 struct dccp_hdr *dh = dccp_hdr(skb);
312
313 dh->dccph_checksum = csum_ipv6_magic(&np->saddr, &np->daddr,
314 len, IPPROTO_DCCP,
315 csum_partial((char *)dh,
316 dh->dccph_doff << 2,
317 skb->csum));
318}
319
320static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) 315static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
321{ 316{
322 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; 317 struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
@@ -360,12 +355,14 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
360 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), 355 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
361 DCCP_SKB_CB(rxskb)->dccpd_seq); 356 DCCP_SKB_CB(rxskb)->dccpd_seq);
362 357
358 dccp_csum_outgoing(skb);
359 dh->dccph_checksum = dccp_v6_csum_finish(skb, &rxskb->nh.ipv6h->saddr,
360 &rxskb->nh.ipv6h->daddr);
361
363 memset(&fl, 0, sizeof(fl)); 362 memset(&fl, 0, sizeof(fl));
364 ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr); 363 ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
365 ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr); 364 ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr);
366 dh->dccph_checksum = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, 365
367 sizeof(*dh), IPPROTO_DCCP,
368 skb->csum);
369 fl.proto = IPPROTO_DCCP; 366 fl.proto = IPPROTO_DCCP;
370 fl.oif = inet6_iif(rxskb); 367 fl.oif = inet6_iif(rxskb);
371 fl.fl_ip_dport = dh->dccph_dport; 368 fl.fl_ip_dport = dh->dccph_dport;
@@ -825,12 +822,22 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
825 const struct dccp_hdr *dh; 822 const struct dccp_hdr *dh;
826 struct sk_buff *skb = *pskb; 823 struct sk_buff *skb = *pskb;
827 struct sock *sk; 824 struct sock *sk;
825 int min_cov;
828 826
829 /* Step 1: Check header basics: */ 827 /* Step 1: Check header basics */
830 828
831 if (dccp_invalid_packet(skb)) 829 if (dccp_invalid_packet(skb))
832 goto discard_it; 830 goto discard_it;
833 831
832 /* Step 1: If header checksum is incorrect, drop packet and return. */
833 if (dccp_v6_csum_finish(skb, &skb->nh.ipv6h->saddr,
834 &skb->nh.ipv6h->daddr)) {
835 LIMIT_NETDEBUG(KERN_WARNING
836 "%s: dropped packet with invalid checksum\n",
837 __FUNCTION__);
838 goto discard_it;
839 }
840
834 dh = dccp_hdr(skb); 841 dh = dccp_hdr(skb);
835 842
836 DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); 843 DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
@@ -869,6 +876,19 @@ static int dccp_v6_rcv(struct sk_buff **pskb)
869 goto no_dccp_socket; 876 goto no_dccp_socket;
870 } 877 }
871 878
879 /*
880 * RFC 4340, sec. 9.2.1: Minimum Checksum Coverage
881 * o if MinCsCov = 0, only packets with CsCov = 0 are accepted
882 * o if MinCsCov > 0, also accept packets with CsCov >= MinCsCov
883 */
884 min_cov = dccp_sk(sk)->dccps_pcrlen;
885 if (dh->dccph_cscov && (min_cov == 0 || dh->dccph_cscov < min_cov)) {
886 dccp_pr_debug("Packet CsCov %d does not satisfy MinCsCov %d\n",
887 dh->dccph_cscov, min_cov);
888 /* FIXME: send Data Dropped option (see also dccp_v4_rcv) */
889 goto discard_and_relse;
890 }
891
872 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) 892 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
873 goto discard_and_relse; 893 goto discard_and_relse;
874 894