aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:30:19 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:45:27 -0400
commitd4c8741c431e07cfc66eb2b4c3a17b8d4975d9c0 (patch)
treef7639e6ffb4ca9c71c60df14733a78341453e65e /net/dccp
parent093e1f46cf162913d05e1d4eeb01baa3e297b683 (diff)
dccp: Mechanism to resolve CCID dependencies
This adds a hook to resolve features whose value depends on the choice of CCID. It is done at the server since it can only be done after the CCID values have been negotiated; i.e. the client will add its CCID preference list on the Change options sent in the Request, which will be reconciled with the local preference list of the server. The concept is documented on http://www.erg.abdn.ac.uk/users/gerrit/dccp/notes/feature_negotiation/\ implementation_notes.html#ccid_dependencies Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Diffstat (limited to 'net/dccp')
-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);