aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/dccp/dccp.h1
-rw-r--r--net/dccp/feat.c57
2 files changed, 58 insertions, 0 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 94ae6d41d724..0a07b2e24e62 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -436,6 +436,7 @@ static inline int dccp_ack_pending(const struct sock *sk)
436 inet_csk_ack_scheduled(sk); 436 inet_csk_ack_scheduled(sk);
437} 437}
438 438
439extern int dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val);
439extern int dccp_feat_finalise_settings(struct dccp_sock *dp); 440extern int dccp_feat_finalise_settings(struct dccp_sock *dp);
440extern int dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq); 441extern int dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq);
441extern int dccp_feat_insert_opts(struct dccp_sock*, struct dccp_request_sock*, 442extern int dccp_feat_insert_opts(struct dccp_sock*, struct dccp_request_sock*,
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 3abacad0b224..5be8b85ac74b 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -13,6 +13,7 @@
13 * ----------- 13 * -----------
14 * o Feature negotiation is coordinated with connection setup (as in TCP), wild 14 * o Feature negotiation is coordinated with connection setup (as in TCP), wild
15 * changes of parameters of an established connection are not supported. 15 * changes of parameters of an established connection are not supported.
16 * o Changing NN values (Ack Ratio only) is supported in state OPEN/PARTOPEN.
16 * o All currently known SP features have 1-byte quantities. If in the future 17 * o All currently known SP features have 1-byte quantities. If in the future
17 * extensions of RFCs 4340..42 define features with item lengths larger than 18 * extensions of RFCs 4340..42 define features with item lengths larger than
18 * one byte, a feature-specific extension of the code will be required. 19 * one byte, a feature-specific extension of the code will be required.
@@ -337,6 +338,20 @@ static int __dccp_feat_activate(struct sock *sk, const int idx,
337 return dccp_feat_table[idx].activation_hdlr(sk, val, rx); 338 return dccp_feat_table[idx].activation_hdlr(sk, val, rx);
338} 339}
339 340
341/**
342 * dccp_feat_activate - Activate feature value on socket
343 * @sk: fully connected DCCP socket (after handshake is complete)
344 * @feat_num: feature to activate, one of %dccp_feature_numbers
345 * @local: whether local (1) or remote (0) @feat_num is meant
346 * @fval: the value (SP or NN) to activate, or NULL to use the default value
347 * For general use this function is preferable over __dccp_feat_activate().
348 */
349static int dccp_feat_activate(struct sock *sk, u8 feat_num, bool local,
350 dccp_feat_val const *fval)
351{
352 return __dccp_feat_activate(sk, dccp_feat_index(feat_num), local, fval);
353}
354
340/* Test for "Req'd" feature (RFC 4340, 6.4) */ 355/* Test for "Req'd" feature (RFC 4340, 6.4) */
341static inline int dccp_feat_must_be_understood(u8 feat_num) 356static inline int dccp_feat_must_be_understood(u8 feat_num)
342{ 357{
@@ -734,6 +749,48 @@ int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val)
734 return __feat_register_nn(&dccp_sk(sk)->dccps_featneg, feat, 0, val); 749 return __feat_register_nn(&dccp_sk(sk)->dccps_featneg, feat, 0, val);
735} 750}
736 751
752/**
753 * dccp_feat_signal_nn_change - Update NN values for an established connection
754 * @sk: DCCP socket of an established connection
755 * @feat: NN feature number from %dccp_feature_numbers
756 * @nn_val: the new value to use
757 * This function is used to communicate NN updates out-of-band. The difference
758 * to feature negotiation during connection setup is that values are activated
759 * immediately after validation, i.e. we don't wait for the Confirm: either the
760 * value is accepted by the peer (and then the waiting is futile), or it is not
761 * (Reset or empty Confirm). We don't accept empty Confirms - transmitted values
762 * are validated, and the peer "MUST accept any valid value" (RFC 4340, 6.3.2).
763 */
764int dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val)
765{
766 struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
767 dccp_feat_val fval = { .nn = nn_val };
768 struct dccp_feat_entry *entry;
769
770 if (sk->sk_state != DCCP_OPEN && sk->sk_state != DCCP_PARTOPEN)
771 return 0;
772
773 if (dccp_feat_type(feat) != FEAT_NN ||
774 !dccp_feat_is_valid_nn_val(feat, nn_val))
775 return -EINVAL;
776
777 entry = dccp_feat_list_lookup(fn, feat, 1);
778 if (entry != NULL) {
779 dccp_pr_debug("Ignoring %llu, entry %llu exists in state %s\n",
780 (unsigned long long)nn_val,
781 (unsigned long long)entry->val.nn,
782 dccp_feat_sname[entry->state]);
783 return 0;
784 }
785
786 if (dccp_feat_activate(sk, feat, 1, &fval))
787 return -EADV;
788
789 inet_csk_schedule_ack(sk);
790 return dccp_feat_push_change(fn, feat, 1, 0, &fval);
791}
792EXPORT_SYMBOL_GPL(dccp_feat_signal_nn_change);
793
737/* 794/*
738 * Tracking features whose value depend on the choice of CCID 795 * Tracking features whose value depend on the choice of CCID
739 * 796 *