aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/dccp/dccp.h1
-rw-r--r--net/dccp/feat.c25
-rw-r--r--net/dccp/output.c13
3 files changed, 35 insertions, 4 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 1881527bdcd7..e656dafb5d96 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -443,6 +443,7 @@ static inline int dccp_ack_pending(const struct sock *sk)
443} 443}
444 444
445extern int dccp_feat_finalise_settings(struct dccp_sock *dp); 445extern int dccp_feat_finalise_settings(struct dccp_sock *dp);
446extern int dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq);
446extern void dccp_feat_list_purge(struct list_head *fn_list); 447extern void dccp_feat_list_purge(struct list_head *fn_list);
447 448
448extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb); 449extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index ed9f50b1c34a..6852960bb0a9 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -601,6 +601,31 @@ int dccp_feat_finalise_settings(struct dccp_sock *dp)
601 return 0; 601 return 0;
602} 602}
603 603
604/**
605 * dccp_feat_server_ccid_dependencies - Resolve CCID-dependent features
606 * It is the server which resolves the dependencies once the CCID has been
607 * fully negotiated. If no CCID has been negotiated, it uses the default CCID.
608 */
609int dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq)
610{
611 struct list_head *fn = &dreq->dreq_featneg;
612 struct dccp_feat_entry *entry;
613 u8 is_local, ccid;
614
615 for (is_local = 0; is_local <= 1; is_local++) {
616 entry = dccp_feat_list_lookup(fn, DCCPF_CCID, is_local);
617
618 if (entry != NULL && !entry->empty_confirm)
619 ccid = entry->val.sp.vec[0];
620 else
621 ccid = dccp_feat_default_value(DCCPF_CCID);
622
623 if (dccp_feat_propagate_ccid(fn, ccid, is_local))
624 return -1;
625 }
626 return 0;
627}
628
604static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr) 629static int dccp_feat_update_ccid(struct sock *sk, u8 type, u8 new_ccid_nr)
605{ 630{
606 struct dccp_sock *dp = dccp_sk(sk); 631 struct dccp_sock *dp = dccp_sk(sk);
diff --git a/net/dccp/output.c b/net/dccp/output.c
index dc96ecfbe6e8..19a93d5433a7 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -339,10 +339,12 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
339 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; 339 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
340 DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; 340 DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss;
341 341
342 if (dccp_insert_options_rsk(dreq, skb)) { 342 /* Resolve feature dependencies resulting from choice of CCID */
343 kfree_skb(skb); 343 if (dccp_feat_server_ccid_dependencies(dreq))
344 return NULL; 344 goto response_failed;
345 } 345
346 if (dccp_insert_options_rsk(dreq, skb))
347 goto response_failed;
346 348
347 /* Build and checksum header */ 349 /* Build and checksum header */
348 dh = dccp_zeroed_hdr(skb, dccp_header_size); 350 dh = dccp_zeroed_hdr(skb, dccp_header_size);
@@ -363,6 +365,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
363 inet_rsk(req)->acked = 1; 365 inet_rsk(req)->acked = 1;
364 DCCP_INC_STATS(DCCP_MIB_OUTSEGS); 366 DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
365 return skb; 367 return skb;
368response_failed:
369 kfree_skb(skb);
370 return NULL;
366} 371}
367 372
368EXPORT_SYMBOL_GPL(dccp_make_response); 373EXPORT_SYMBOL_GPL(dccp_make_response);