aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/dccp/dccp.h1
-rw-r--r--net/dccp/options.c32
-rw-r--r--net/dccp/output.c2
3 files changed, 24 insertions, 11 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 3af3320194f0..b138e2019d78 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -428,6 +428,7 @@ static inline int dccp_ack_pending(const struct sock *sk)
428} 428}
429 429
430extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb); 430extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
431extern int dccp_insert_options_rsk(struct dccp_request_sock*, struct sk_buff*);
431extern int dccp_insert_option_elapsed_time(struct sock *sk, 432extern int dccp_insert_option_elapsed_time(struct sock *sk,
432 struct sk_buff *skb, 433 struct sk_buff *skb,
433 u32 elapsed_time); 434 u32 elapsed_time);
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 0c996d8c79a3..bedb5daaa3c5 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -537,6 +537,18 @@ static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)
537 return 0; 537 return 0;
538} 538}
539 539
540/* The length of all options needs to be a multiple of 4 (5.8) */
541static void dccp_insert_option_padding(struct sk_buff *skb)
542{
543 int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4;
544
545 if (padding != 0) {
546 padding = 4 - padding;
547 memset(skb_push(skb, padding), 0, padding);
548 DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
549 }
550}
551
540int dccp_insert_options(struct sock *sk, struct sk_buff *skb) 552int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
541{ 553{
542 struct dccp_sock *dp = dccp_sk(sk); 554 struct dccp_sock *dp = dccp_sk(sk);
@@ -580,18 +592,18 @@ int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
580 dccp_insert_option_timestamp_echo(dp, NULL, skb)) 592 dccp_insert_option_timestamp_echo(dp, NULL, skb))
581 return -1; 593 return -1;
582 594
583 /* XXX: insert other options when appropriate */ 595 dccp_insert_option_padding(skb);
596 return 0;
597}
584 598
585 if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) { 599int dccp_insert_options_rsk(struct dccp_request_sock *dreq, struct sk_buff *skb)
586 /* The length of all options has to be a multiple of 4 */ 600{
587 int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4; 601 DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
588 602
589 if (padding != 0) { 603 if (dreq->dreq_timestamp_echo != 0 &&
590 padding = 4 - padding; 604 dccp_insert_option_timestamp_echo(NULL, dreq, skb))
591 memset(skb_push(skb, padding), 0, padding); 605 return -1;
592 DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
593 }
594 }
595 606
607 dccp_insert_option_padding(skb);
596 return 0; 608 return 0;
597} 609}
diff --git a/net/dccp/output.c b/net/dccp/output.c
index b2e17910930d..5589a5e581f4 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -303,7 +303,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
303 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; 303 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
304 DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; 304 DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss;
305 305
306 if (dccp_insert_options(sk, skb)) { 306 if (dccp_insert_options_rsk(dreq, skb)) {
307 kfree_skb(skb); 307 kfree_skb(skb);
308 return NULL; 308 return NULL;
309 } 309 }