aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/output.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2006-11-10 14:43:06 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:22:09 -0500
commit6f4e5fff1e4d46714ea554fd83e44eab534e8b11 (patch)
tree4b14344fd825bbcefb6e8514e98e3e796b2dc1bd /net/dccp/output.c
parenta11d206d0f88e092419877c7f706cafb5e1c2e57 (diff)
[DCCP]: Support for partial checksums (RFC 4340, sec. 9.2)
This patch does the following: a) introduces variable-length checksums as specified in [RFC 4340, sec. 9.2] b) provides necessary socket options and documentation as to how to use them c) basic support and infrastructure for the Minimum Checksum Coverage feature [RFC 4340, sec. 9.2.1]: acceptability tests, user notification and user interface In addition, it (1) fixes two bugs in the DCCPv4 checksum computation: * pseudo-header used checksum_len instead of skb->len * incorrect checksum coverage calculation based on dccph_x (2) removes dccp_v4_verify_checksum() since it reduplicates code of the checksum computation; code calling this function is updated accordingly. (3) now uses skb_checksum(), which is safer than checksum_partial() if the sk_buff has is a non-linear buffer (has pages attached to it). (4) fixes an outstanding TODO item: * If P.CsCov is too large for the packet size, drop packet and return. The code has been tested with applications, the latest version of tcpdump now comes with support for partial DCCP checksums. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Diffstat (limited to 'net/dccp/output.c')
-rw-r--r--net/dccp/output.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 51654975e8ea..992caedd7725 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -96,6 +96,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
96 dh->dccph_dport = inet->dport; 96 dh->dccph_dport = inet->dport;
97 dh->dccph_doff = (dccp_header_size + dcb->dccpd_opt_len) / 4; 97 dh->dccph_doff = (dccp_header_size + dcb->dccpd_opt_len) / 4;
98 dh->dccph_ccval = dcb->dccpd_ccval; 98 dh->dccph_ccval = dcb->dccpd_ccval;
99 dh->dccph_cscov = dp->dccps_pcslen;
99 /* XXX For now we're using only 48 bits sequence numbers */ 100 /* XXX For now we're using only 48 bits sequence numbers */
100 dh->dccph_x = 1; 101 dh->dccph_x = 1;
101 102
@@ -115,7 +116,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
115 break; 116 break;
116 } 117 }
117 118
118 icsk->icsk_af_ops->send_check(sk, skb->len, skb); 119 icsk->icsk_af_ops->send_check(sk, 0, skb);
119 120
120 if (set_ack) 121 if (set_ack)
121 dccp_event_ack_sent(sk); 122 dccp_event_ack_sent(sk);
@@ -329,7 +330,6 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
329 skb_reserve(skb, sk->sk_prot->max_header); 330 skb_reserve(skb, sk->sk_prot->max_header);
330 331
331 skb->dst = dst_clone(dst); 332 skb->dst = dst_clone(dst);
332 skb->csum = 0;
333 333
334 dreq = dccp_rsk(req); 334 dreq = dccp_rsk(req);
335 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; 335 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
@@ -352,6 +352,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
352 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr); 352 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr);
353 dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service; 353 dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
354 354
355 dccp_csum_outgoing(skb);
356
355 DCCP_INC_STATS(DCCP_MIB_OUTSEGS); 357 DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
356 return skb; 358 return skb;
357} 359}
@@ -376,7 +378,6 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
376 skb_reserve(skb, sk->sk_prot->max_header); 378 skb_reserve(skb, sk->sk_prot->max_header);
377 379
378 skb->dst = dst_clone(dst); 380 skb->dst = dst_clone(dst);
379 skb->csum = 0;
380 381
381 dccp_inc_seqno(&dp->dccps_gss); 382 dccp_inc_seqno(&dp->dccps_gss);
382 383
@@ -401,7 +402,7 @@ static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
401 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr); 402 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr);
402 403
403 dccp_hdr_reset(skb)->dccph_reset_code = code; 404 dccp_hdr_reset(skb)->dccph_reset_code = code;
404 inet_csk(sk)->icsk_af_ops->send_check(sk, skb->len, skb); 405 inet_csk(sk)->icsk_af_ops->send_check(sk, 0, skb);
405 406
406 DCCP_INC_STATS(DCCP_MIB_OUTSEGS); 407 DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
407 return skb; 408 return skb;
@@ -475,7 +476,6 @@ int dccp_connect(struct sock *sk)
475 skb_reserve(skb, sk->sk_prot->max_header); 476 skb_reserve(skb, sk->sk_prot->max_header);
476 477
477 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; 478 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
478 skb->csum = 0;
479 479
480 dccp_skb_entail(sk, skb); 480 dccp_skb_entail(sk, skb);
481 dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL)); 481 dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
@@ -507,7 +507,6 @@ void dccp_send_ack(struct sock *sk)
507 507
508 /* Reserve space for headers */ 508 /* Reserve space for headers */
509 skb_reserve(skb, sk->sk_prot->max_header); 509 skb_reserve(skb, sk->sk_prot->max_header);
510 skb->csum = 0;
511 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK; 510 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK;
512 dccp_transmit_skb(sk, skb); 511 dccp_transmit_skb(sk, skb);
513 } 512 }
@@ -561,7 +560,6 @@ void dccp_send_sync(struct sock *sk, const u64 seq,
561 560
562 /* Reserve space for headers and prepare control bits. */ 561 /* Reserve space for headers and prepare control bits. */
563 skb_reserve(skb, sk->sk_prot->max_header); 562 skb_reserve(skb, sk->sk_prot->max_header);
564 skb->csum = 0;
565 DCCP_SKB_CB(skb)->dccpd_type = pkt_type; 563 DCCP_SKB_CB(skb)->dccpd_type = pkt_type;
566 DCCP_SKB_CB(skb)->dccpd_seq = seq; 564 DCCP_SKB_CB(skb)->dccpd_seq = seq;
567 565
@@ -587,7 +585,6 @@ void dccp_send_close(struct sock *sk, const int active)
587 585
588 /* Reserve space for headers and prepare control bits. */ 586 /* Reserve space for headers and prepare control bits. */
589 skb_reserve(skb, sk->sk_prot->max_header); 587 skb_reserve(skb, sk->sk_prot->max_header);
590 skb->csum = 0;
591 DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ? 588 DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ?
592 DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; 589 DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ;
593 590