^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * net/dccp/feat.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Feature negotiation for the DCCP protocol (RFC 4340, section 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2008 Gerrit Renker <gerrit@erg.abdn.ac.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Rewrote from scratch, some bits from earlier code by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * ASSUMPTIONS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * -----------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * o Feature negotiation is coordinated with connection setup (as in TCP), wild
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * changes of parameters of an established connection are not supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * o Changing non-negotiable (NN) values is supported in state OPEN/PARTOPEN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * o All currently known SP features have 1-byte quantities. If in the future
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * extensions of RFCs 4340..42 define features with item lengths larger than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * one byte, a feature-specific extension of the code will be required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "ccid.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "feat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* feature-specific sysctls - initialised to the defaults from RFC 4340, 6.4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned long sysctl_dccp_sequence_window __read_mostly = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int sysctl_dccp_rx_ccid __read_mostly = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) sysctl_dccp_tx_ccid __read_mostly = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Feature activation handlers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * These all use an u64 argument, to provide enough room for NN/SP features. At
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * this stage the negotiated values have been checked to be within their range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int dccp_hdlr_ccid(struct sock *sk, u64 ccid, bool rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct ccid *new_ccid = ccid_new(ccid, sk, rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (new_ccid == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) dp->dccps_hc_rx_ccid = new_ccid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) dp->dccps_hc_tx_ccid = new_ccid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int dccp_hdlr_seq_win(struct sock *sk, u64 seq_win, bool rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) dp->dccps_r_seq_win = seq_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* propagate changes to update SWL/SWH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) dccp_update_gsr(sk, dp->dccps_gsr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) dp->dccps_l_seq_win = seq_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* propagate changes to update AWL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) dccp_update_gss(sk, dp->dccps_gss);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int dccp_hdlr_ack_ratio(struct sock *sk, u64 ratio, bool rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) dccp_sk(sk)->dccps_r_ack_ratio = ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) dccp_sk(sk)->dccps_l_ack_ratio = ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int dccp_hdlr_ackvec(struct sock *sk, u64 enable, bool rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (enable && dp->dccps_hc_rx_ackvec == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(gfp_any());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (dp->dccps_hc_rx_ackvec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) } else if (!enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) dp->dccps_hc_rx_ackvec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static int dccp_hdlr_ndp(struct sock *sk, u64 enable, bool rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (!rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dccp_sk(sk)->dccps_send_ndp_count = (enable > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * Minimum Checksum Coverage is located at the RX side (9.2.1). This means that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * `rx' holds when the sending peer informs about his partial coverage via a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * ChangeR() option. In the other case, we are the sender and the receiver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * announces its coverage via ChangeL() options. The policy here is to honour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * such communication by enabling the corresponding partial coverage - but only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * if it has not been set manually before; the warning here means that all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * packets will be dropped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int dccp_hdlr_min_cscov(struct sock *sk, u64 cscov, bool rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (rx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) dp->dccps_pcrlen = cscov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (dp->dccps_pcslen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dp->dccps_pcslen = cscov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) else if (cscov > dp->dccps_pcslen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) DCCP_WARN("CsCov %u too small, peer requires >= %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dp->dccps_pcslen, (u8)cscov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u8 feat_num; /* DCCPF_xxx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) enum dccp_feat_type rxtx; /* RX or TX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) enum dccp_feat_type reconciliation; /* SP or NN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) u8 default_value; /* as in 6.4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int (*activation_hdlr)(struct sock *sk, u64 val, bool rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * Lookup table for location and type of features (from RFC 4340/4342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * +--------------------------+----+-----+----+----+---------+-----------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * | Feature | Location | Reconc. | Initial | Section |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * | | RX | TX | SP | NN | Value | Reference |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * +--------------------------+----+-----+----+----+---------+-----------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * | DCCPF_CCID | | X | X | | 2 | 10 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * | DCCPF_SHORT_SEQNOS | | X | X | | 0 | 7.6.1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * | DCCPF_SEQUENCE_WINDOW | | X | | X | 100 | 7.5.2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * | DCCPF_ECN_INCAPABLE | X | | X | | 0 | 12.1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * | DCCPF_ACK_RATIO | | X | | X | 2 | 11.3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * | DCCPF_SEND_ACK_VECTOR | X | | X | | 0 | 11.5 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * | DCCPF_SEND_NDP_COUNT | | X | X | | 0 | 7.7.2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * | DCCPF_MIN_CSUM_COVER | X | | X | | 0 | 9.2.1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * | DCCPF_DATA_CHECKSUM | X | | X | | 0 | 9.3.1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * | DCCPF_SEND_LEV_RATE | X | | X | | 0 | 4342/8.4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * +--------------------------+----+-----+----+----+---------+-----------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) } dccp_feat_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { DCCPF_CCID, FEAT_AT_TX, FEAT_SP, 2, dccp_hdlr_ccid },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) { DCCPF_SHORT_SEQNOS, FEAT_AT_TX, FEAT_SP, 0, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) { DCCPF_SEQUENCE_WINDOW, FEAT_AT_TX, FEAT_NN, 100, dccp_hdlr_seq_win },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) { DCCPF_ECN_INCAPABLE, FEAT_AT_RX, FEAT_SP, 0, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) { DCCPF_ACK_RATIO, FEAT_AT_TX, FEAT_NN, 2, dccp_hdlr_ack_ratio},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) { DCCPF_SEND_ACK_VECTOR, FEAT_AT_RX, FEAT_SP, 0, dccp_hdlr_ackvec },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) { DCCPF_SEND_NDP_COUNT, FEAT_AT_TX, FEAT_SP, 0, dccp_hdlr_ndp },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { DCCPF_MIN_CSUM_COVER, FEAT_AT_RX, FEAT_SP, 0, dccp_hdlr_min_cscov},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) { DCCPF_DATA_CHECKSUM, FEAT_AT_RX, FEAT_SP, 0, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) { DCCPF_SEND_LEV_RATE, FEAT_AT_RX, FEAT_SP, 0, NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define DCCP_FEAT_SUPPORTED_MAX ARRAY_SIZE(dccp_feat_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * dccp_feat_index - Hash function to map feature number into array position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @feat_num: feature to hash, one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Returns consecutive array index or -1 if the feature is not understood.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static int dccp_feat_index(u8 feat_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* The first 9 entries are occupied by the types from RFC 4340, 6.4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (feat_num > DCCPF_RESERVED && feat_num <= DCCPF_DATA_CHECKSUM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return feat_num - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * Other features: add cases for new feature types here after adding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * them to the above table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) switch (feat_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) case DCCPF_SEND_LEV_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return DCCP_FEAT_SUPPORTED_MAX - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static u8 dccp_feat_type(u8 feat_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int idx = dccp_feat_index(feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (idx < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return FEAT_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return dccp_feat_table[idx].reconciliation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int dccp_feat_default_value(u8 feat_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int idx = dccp_feat_index(feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * There are no default values for unknown features, so encountering a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * negative index here indicates a serious problem somewhere else.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) DCCP_BUG_ON(idx < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return idx < 0 ? 0 : dccp_feat_table[idx].default_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * Debugging and verbose-printing section
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static const char *dccp_feat_fname(const u8 feat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static const char *const feature_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) [DCCPF_RESERVED] = "Reserved",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) [DCCPF_CCID] = "CCID",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) [DCCPF_SHORT_SEQNOS] = "Allow Short Seqnos",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) [DCCPF_SEQUENCE_WINDOW] = "Sequence Window",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) [DCCPF_ECN_INCAPABLE] = "ECN Incapable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) [DCCPF_ACK_RATIO] = "Ack Ratio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) [DCCPF_SEND_ACK_VECTOR] = "Send ACK Vector",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) [DCCPF_SEND_NDP_COUNT] = "Send NDP Count",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) [DCCPF_MIN_CSUM_COVER] = "Min. Csum Coverage",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) [DCCPF_DATA_CHECKSUM] = "Send Data Checksum",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (feat > DCCPF_DATA_CHECKSUM && feat < DCCPF_MIN_CCID_SPECIFIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return feature_names[DCCPF_RESERVED];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (feat == DCCPF_SEND_LEV_RATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return "Send Loss Event Rate";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (feat >= DCCPF_MIN_CCID_SPECIFIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return "CCID-specific";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return feature_names[feat];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static const char *const dccp_feat_sname[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) "DEFAULT", "INITIALISING", "CHANGING", "UNSTABLE", "STABLE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #ifdef CONFIG_IP_DCCP_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static const char *dccp_feat_oname(const u8 opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) switch (opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case DCCPO_CHANGE_L: return "Change_L";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) case DCCPO_CONFIRM_L: return "Confirm_L";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case DCCPO_CHANGE_R: return "Change_R";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) case DCCPO_CONFIRM_R: return "Confirm_R";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static void dccp_feat_printval(u8 feat_num, dccp_feat_val const *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) u8 i, type = dccp_feat_type(feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (val == NULL || (type == FEAT_SP && val->sp.vec == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) dccp_pr_debug_cat("(NULL)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) else if (type == FEAT_SP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) for (i = 0; i < val->sp.len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) dccp_pr_debug_cat("%s%u", i ? " " : "", val->sp.vec[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) else if (type == FEAT_NN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dccp_pr_debug_cat("%llu", (unsigned long long)val->nn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dccp_pr_debug_cat("unknown type %u", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static void dccp_feat_printvals(u8 feat_num, u8 *list, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) u8 type = dccp_feat_type(feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) dccp_feat_val fval = { .sp.vec = list, .sp.len = len };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (type == FEAT_NN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) fval.nn = dccp_decode_value_var(list, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dccp_feat_printval(feat_num, &fval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static void dccp_feat_print_entry(struct dccp_feat_entry const *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) dccp_debug(" * %s %s = ", entry->is_local ? "local" : "remote",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) dccp_feat_fname(entry->feat_num));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) dccp_feat_printval(entry->feat_num, &entry->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) dccp_pr_debug_cat(", state=%s %s\n", dccp_feat_sname[entry->state],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) entry->needs_confirm ? "(Confirm pending)" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #define dccp_feat_print_opt(opt, feat, val, len, mandatory) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) dccp_pr_debug("%s(%s, ", dccp_feat_oname(opt), dccp_feat_fname(feat));\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dccp_feat_printvals(feat, val, len); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) dccp_pr_debug_cat(") %s\n", mandatory ? "!" : ""); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #define dccp_feat_print_fnlist(fn_list) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) const struct dccp_feat_entry *___entry; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) dccp_pr_debug("List Dump:\n"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) list_for_each_entry(___entry, fn_list, node) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) dccp_feat_print_entry(___entry); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) #else /* ! CONFIG_IP_DCCP_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #define dccp_feat_print_opt(opt, feat, val, len, mandatory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) #define dccp_feat_print_fnlist(fn_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int __dccp_feat_activate(struct sock *sk, const int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) const bool is_local, dccp_feat_val const *fval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) bool rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (idx < 0 || idx >= DCCP_FEAT_SUPPORTED_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (dccp_feat_table[idx].activation_hdlr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (fval == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) val = dccp_feat_table[idx].default_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) } else if (dccp_feat_table[idx].reconciliation == FEAT_SP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (fval->sp.vec == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * This can happen when an empty Confirm is sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * for an SP (i.e. known) feature. In this case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * we would be using the default anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) DCCP_CRIT("Feature #%d undefined: using default", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) val = dccp_feat_table[idx].default_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) val = fval->sp.vec[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) val = fval->nn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* Location is RX if this is a local-RX or remote-TX feature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) rx = (is_local == (dccp_feat_table[idx].rxtx == FEAT_AT_RX));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) dccp_debug(" -> activating %s %s, %sval=%llu\n", rx ? "RX" : "TX",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) dccp_feat_fname(dccp_feat_table[idx].feat_num),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) fval ? "" : "default ", (unsigned long long)val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return dccp_feat_table[idx].activation_hdlr(sk, val, rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * dccp_feat_activate - Activate feature value on socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * @sk: fully connected DCCP socket (after handshake is complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * @feat_num: feature to activate, one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * @local: whether local (1) or remote (0) @feat_num is meant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * @fval: the value (SP or NN) to activate, or NULL to use the default value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * For general use this function is preferable over __dccp_feat_activate().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static int dccp_feat_activate(struct sock *sk, u8 feat_num, bool local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) dccp_feat_val const *fval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return __dccp_feat_activate(sk, dccp_feat_index(feat_num), local, fval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* Test for "Req'd" feature (RFC 4340, 6.4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static inline int dccp_feat_must_be_understood(u8 feat_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return feat_num == DCCPF_CCID || feat_num == DCCPF_SHORT_SEQNOS ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) feat_num == DCCPF_SEQUENCE_WINDOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* copy constructor, fval must not already contain allocated memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static int dccp_feat_clone_sp_val(dccp_feat_val *fval, u8 const *val, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) fval->sp.len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (fval->sp.len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) fval->sp.vec = kmemdup(val, len, gfp_any());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (fval->sp.vec == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) fval->sp.len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (unlikely(val == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (dccp_feat_type(feat_num) == FEAT_SP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) kfree(val->sp.vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) memset(val, 0, sizeof(*val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static struct dccp_feat_entry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) dccp_feat_clone_entry(struct dccp_feat_entry const *original)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) struct dccp_feat_entry *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) u8 type = dccp_feat_type(original->feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (type == FEAT_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) new = kmemdup(original, sizeof(struct dccp_feat_entry), gfp_any());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (new == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (type == FEAT_SP && dccp_feat_clone_sp_val(&new->val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) original->val.sp.vec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) original->val.sp.len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) kfree(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (entry != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dccp_feat_val_destructor(entry->feat_num, &entry->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * List management functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * Feature negotiation lists rely on and maintain the following invariants:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * - each feat_num in the list is known, i.e. we know its type and default value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * - each feat_num/is_local combination is unique (old entries are overwritten)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * - SP values are always freshly allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * - list is sorted in increasing order of feature number (faster lookup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static struct dccp_feat_entry *dccp_feat_list_lookup(struct list_head *fn_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) u8 feat_num, bool is_local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct dccp_feat_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) list_for_each_entry(entry, fn_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (entry->feat_num == feat_num && entry->is_local == is_local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) else if (entry->feat_num > feat_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * dccp_feat_entry_new - Central list update routine (called by all others)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * @head: list to add to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * @feat: feature number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * @local: whether the local (1) or remote feature with number @feat is meant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * This is the only constructor and serves to ensure the above invariants.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static struct dccp_feat_entry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) dccp_feat_entry_new(struct list_head *head, u8 feat, bool local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct dccp_feat_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) list_for_each_entry(entry, head, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (entry->feat_num == feat && entry->is_local == local) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) dccp_feat_val_destructor(entry->feat_num, &entry->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) } else if (entry->feat_num > feat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) head = &entry->node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) entry = kmalloc(sizeof(*entry), gfp_any());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (entry != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) entry->feat_num = feat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) entry->is_local = local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) list_add_tail(&entry->node, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * dccp_feat_push_change - Add/overwrite a Change option in the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * @fn_list: feature-negotiation list to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * @feat: one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * @local: whether local (1) or remote (0) @feat_num is meant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * @mandatory: whether to use Mandatory feature negotiation options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * @fval: pointer to NN/SP value to be inserted (will be copied)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int dccp_feat_push_change(struct list_head *fn_list, u8 feat, u8 local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) u8 mandatory, dccp_feat_val *fval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct dccp_feat_entry *new = dccp_feat_entry_new(fn_list, feat, local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (new == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) new->feat_num = feat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) new->is_local = local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) new->state = FEAT_INITIALISING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) new->needs_confirm = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) new->empty_confirm = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) new->val = *fval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) new->needs_mandatory = mandatory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * dccp_feat_push_confirm - Add a Confirm entry to the FN list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * @fn_list: feature-negotiation list to add to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * @feat: one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * @local: whether local (1) or remote (0) @feat_num is being confirmed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * @fval: pointer to NN/SP value to be inserted or NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * Returns 0 on success, a Reset code for further processing otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static int dccp_feat_push_confirm(struct list_head *fn_list, u8 feat, u8 local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) dccp_feat_val *fval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct dccp_feat_entry *new = dccp_feat_entry_new(fn_list, feat, local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (new == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return DCCP_RESET_CODE_TOO_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) new->feat_num = feat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) new->is_local = local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) new->state = FEAT_STABLE; /* transition in 6.6.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) new->needs_confirm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) new->empty_confirm = (fval == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) new->val.nn = 0; /* zeroes the whole structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (!new->empty_confirm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) new->val = *fval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) new->needs_mandatory = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int dccp_push_empty_confirm(struct list_head *fn_list, u8 feat, u8 local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return dccp_feat_push_confirm(fn_list, feat, local, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static inline void dccp_feat_list_pop(struct dccp_feat_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) list_del(&entry->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) dccp_feat_entry_destructor(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) void dccp_feat_list_purge(struct list_head *fn_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct dccp_feat_entry *entry, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) list_for_each_entry_safe(entry, next, fn_list, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) dccp_feat_entry_destructor(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) INIT_LIST_HEAD(fn_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) EXPORT_SYMBOL_GPL(dccp_feat_list_purge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /* generate @to as full clone of @from - @to must not contain any nodes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) int dccp_feat_clone_list(struct list_head const *from, struct list_head *to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct dccp_feat_entry *entry, *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) INIT_LIST_HEAD(to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) list_for_each_entry(entry, from, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) new = dccp_feat_clone_entry(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (new == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) goto cloning_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) list_add_tail(&new->node, to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) cloning_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) dccp_feat_list_purge(to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * dccp_feat_valid_nn_length - Enforce length constraints on NN options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * @feat_num: feature to return length of, one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * Length is between 0 and %DCCP_OPTVAL_MAXLEN. Used for outgoing packets only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * incoming options are accepted as long as their values are valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) static u8 dccp_feat_valid_nn_length(u8 feat_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (feat_num == DCCPF_ACK_RATIO) /* RFC 4340, 11.3 and 6.6.8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (feat_num == DCCPF_SEQUENCE_WINDOW) /* RFC 4340, 7.5.2 and 6.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static u8 dccp_feat_is_valid_nn_val(u8 feat_num, u64 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) switch (feat_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) case DCCPF_ACK_RATIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return val <= DCCPF_ACK_RATIO_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) case DCCPF_SEQUENCE_WINDOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return val >= DCCPF_SEQ_WMIN && val <= DCCPF_SEQ_WMAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return 0; /* feature unknown - so we can't tell */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* check that SP values are within the ranges defined in RFC 4340 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static u8 dccp_feat_is_valid_sp_val(u8 feat_num, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) switch (feat_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) case DCCPF_CCID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return val == DCCPC_CCID2 || val == DCCPC_CCID3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) /* Type-check Boolean feature values: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) case DCCPF_SHORT_SEQNOS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case DCCPF_ECN_INCAPABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) case DCCPF_SEND_ACK_VECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) case DCCPF_SEND_NDP_COUNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) case DCCPF_DATA_CHECKSUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) case DCCPF_SEND_LEV_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return val < 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) case DCCPF_MIN_CSUM_COVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return val < 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return 0; /* feature unknown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static u8 dccp_feat_sp_list_ok(u8 feat_num, u8 const *sp_list, u8 sp_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (sp_list == NULL || sp_len < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) while (sp_len--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (!dccp_feat_is_valid_sp_val(feat_num, *sp_list++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * dccp_feat_insert_opts - Generate FN options from current list state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * @skb: next sk_buff to be sent to the peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * @dp: for client during handshake and general negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * @dreq: used by the server only (all Changes/Confirms in LISTEN/RESPOND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int dccp_feat_insert_opts(struct dccp_sock *dp, struct dccp_request_sock *dreq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct list_head *fn = dreq ? &dreq->dreq_featneg : &dp->dccps_featneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct dccp_feat_entry *pos, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) u8 opt, type, len, *ptr, nn_in_nbo[DCCP_OPTVAL_MAXLEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) bool rpt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /* put entries into @skb in the order they appear in the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) list_for_each_entry_safe_reverse(pos, next, fn, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) opt = dccp_feat_genopt(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) type = dccp_feat_type(pos->feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) rpt = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (pos->empty_confirm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (type == FEAT_SP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) len = pos->val.sp.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ptr = pos->val.sp.vec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) rpt = pos->needs_confirm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) } else if (type == FEAT_NN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) len = dccp_feat_valid_nn_length(pos->feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ptr = nn_in_nbo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) dccp_encode_value_var(pos->val.nn, ptr, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) DCCP_BUG("unknown feature %u", pos->feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) dccp_feat_print_opt(opt, pos->feat_num, ptr, len, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (dccp_insert_fn_opt(skb, opt, pos->feat_num, ptr, len, rpt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (pos->needs_mandatory && dccp_insert_option_mandatory(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (skb->sk->sk_state == DCCP_OPEN &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) (opt == DCCPO_CONFIRM_R || opt == DCCPO_CONFIRM_L)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * Confirms don't get retransmitted (6.6.3) once the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * connection is in state OPEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) dccp_feat_list_pop(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * Enter CHANGING after transmitting the Change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * option (6.6.2).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (pos->state == FEAT_INITIALISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) pos->state = FEAT_CHANGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * __feat_register_nn - Register new NN value on socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * @fn: feature-negotiation list to register with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * @feat: an NN feature from %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * @mandatory: use Mandatory option if 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * @nn_val: value to register (restricted to 4 bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * Note that NN features are local by definition (RFC 4340, 6.3.2).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static int __feat_register_nn(struct list_head *fn, u8 feat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) u8 mandatory, u64 nn_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) dccp_feat_val fval = { .nn = nn_val };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (dccp_feat_type(feat) != FEAT_NN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) !dccp_feat_is_valid_nn_val(feat, nn_val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) /* Don't bother with default values, they will be activated anyway. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (nn_val - (u64)dccp_feat_default_value(feat) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return dccp_feat_push_change(fn, feat, 1, mandatory, &fval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * __feat_register_sp - Register new SP value/list on socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * @fn: feature-negotiation list to register with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * @feat: an SP feature from %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * @is_local: whether the local (1) or the remote (0) @feat is meant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * @mandatory: use Mandatory option if 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * @sp_val: SP value followed by optional preference list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * @sp_len: length of @sp_val in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static int __feat_register_sp(struct list_head *fn, u8 feat, u8 is_local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) u8 mandatory, u8 const *sp_val, u8 sp_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) dccp_feat_val fval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (dccp_feat_type(feat) != FEAT_SP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) !dccp_feat_sp_list_ok(feat, sp_val, sp_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) /* Avoid negotiating alien CCIDs by only advertising supported ones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (feat == DCCPF_CCID && !ccid_support_check(sp_val, sp_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (dccp_feat_clone_sp_val(&fval, sp_val, sp_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (dccp_feat_push_change(fn, feat, is_local, mandatory, &fval)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) kfree(fval.sp.vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * dccp_feat_register_sp - Register requests to change SP feature values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * @sk: client or listening socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * @feat: one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * @is_local: whether the local (1) or remote (0) @feat is meant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * @list: array of preferred values, in descending order of preference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * @len: length of @list in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) u8 const *list, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) { /* any changes must be registered before establishing the connection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (sk->sk_state != DCCP_CLOSED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return -EISCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (dccp_feat_type(feat) != FEAT_SP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return __feat_register_sp(&dccp_sk(sk)->dccps_featneg, feat, is_local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 0, list, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * dccp_feat_nn_get - Query current/pending value of NN feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * @sk: DCCP socket of an established connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * @feat: NN feature number from %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * For a known NN feature, returns value currently being negotiated, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * current (confirmed) value if no negotiation is going on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) u64 dccp_feat_nn_get(struct sock *sk, u8 feat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (dccp_feat_type(feat) == FEAT_NN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) struct dccp_feat_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) entry = dccp_feat_list_lookup(&dp->dccps_featneg, feat, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (entry != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return entry->val.nn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) switch (feat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) case DCCPF_ACK_RATIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return dp->dccps_l_ack_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) case DCCPF_SEQUENCE_WINDOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return dp->dccps_l_seq_win;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) DCCP_BUG("attempt to look up unsupported feature %u", feat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) EXPORT_SYMBOL_GPL(dccp_feat_nn_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * dccp_feat_signal_nn_change - Update NN values for an established connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * @sk: DCCP socket of an established connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * @feat: NN feature number from %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * @nn_val: the new value to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * This function is used to communicate NN updates out-of-band.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) int dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) dccp_feat_val fval = { .nn = nn_val };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) struct dccp_feat_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (sk->sk_state != DCCP_OPEN && sk->sk_state != DCCP_PARTOPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (dccp_feat_type(feat) != FEAT_NN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) !dccp_feat_is_valid_nn_val(feat, nn_val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) if (nn_val == dccp_feat_nn_get(sk, feat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return 0; /* already set or negotiation under way */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) entry = dccp_feat_list_lookup(fn, feat, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (entry != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) dccp_pr_debug("Clobbering existing NN entry %llu -> %llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) (unsigned long long)entry->val.nn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) (unsigned long long)nn_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) dccp_feat_list_pop(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) inet_csk_schedule_ack(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return dccp_feat_push_change(fn, feat, 1, 0, &fval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) EXPORT_SYMBOL_GPL(dccp_feat_signal_nn_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * Tracking features whose value depend on the choice of CCID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * This is designed with an extension in mind so that a list walk could be done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * before activating any features. However, the existing framework was found to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) * work satisfactorily up until now, the automatic verification is left open.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * When adding new CCIDs, add a corresponding dependency table here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static const struct ccid_dependency *dccp_feat_ccid_deps(u8 ccid, bool is_local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static const struct ccid_dependency ccid2_dependencies[2][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * CCID2 mandates Ack Vectors (RFC 4341, 4.): as CCID is a TX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * feature and Send Ack Vector is an RX feature, `is_local'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * needs to be reversed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) { /* Dependencies of the receiver-side (remote) CCID2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) .dependent_feat = DCCPF_SEND_ACK_VECTOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) .is_local = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .is_mandatory = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .val = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) { 0, 0, 0, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) { /* Dependencies of the sender-side (local) CCID2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .dependent_feat = DCCPF_SEND_ACK_VECTOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) .is_local = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) .is_mandatory = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) .val = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) { 0, 0, 0, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static const struct ccid_dependency ccid3_dependencies[2][5] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) { /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * Dependencies of the receiver-side CCID3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) { /* locally disable Ack Vectors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .dependent_feat = DCCPF_SEND_ACK_VECTOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .is_local = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .is_mandatory = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .val = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) { /* see below why Send Loss Event Rate is on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) .dependent_feat = DCCPF_SEND_LEV_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) .is_local = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) .is_mandatory = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) .val = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) { /* NDP Count is needed as per RFC 4342, 6.1.1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) .dependent_feat = DCCPF_SEND_NDP_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) .is_local = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) .is_mandatory = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) .val = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) { 0, 0, 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) { /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) * CCID3 at the TX side: we request that the HC-receiver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * will not send Ack Vectors (they will be ignored, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * Mandatory is not set); we enable Send Loss Event Rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * (Mandatory since the implementation does not support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * the Loss Intervals option of RFC 4342, 8.6).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * The last two options are for peer's information only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) .dependent_feat = DCCPF_SEND_ACK_VECTOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .is_local = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) .is_mandatory = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) .val = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) .dependent_feat = DCCPF_SEND_LEV_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) .is_local = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) .is_mandatory = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) .val = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) { /* this CCID does not support Ack Ratio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .dependent_feat = DCCPF_ACK_RATIO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .is_local = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .is_mandatory = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) .val = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) { /* tell receiver we are sending NDP counts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .dependent_feat = DCCPF_SEND_NDP_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .is_local = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .is_mandatory = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .val = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) { 0, 0, 0, 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) switch (ccid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) case DCCPC_CCID2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return ccid2_dependencies[is_local];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) case DCCPC_CCID3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return ccid3_dependencies[is_local];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * dccp_feat_propagate_ccid - Resolve dependencies of features on choice of CCID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * @fn: feature-negotiation list to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) * @id: CCID number to track
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * @is_local: whether TX CCID (1) or RX CCID (0) is meant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * This function needs to be called after registering all other features.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) static int dccp_feat_propagate_ccid(struct list_head *fn, u8 id, bool is_local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) const struct ccid_dependency *table = dccp_feat_ccid_deps(id, is_local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) int i, rc = (table == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) for (i = 0; rc == 0 && table[i].dependent_feat != DCCPF_RESERVED; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (dccp_feat_type(table[i].dependent_feat) == FEAT_SP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) rc = __feat_register_sp(fn, table[i].dependent_feat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) table[i].is_local,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) table[i].is_mandatory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) &table[i].val, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) rc = __feat_register_nn(fn, table[i].dependent_feat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) table[i].is_mandatory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) table[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * dccp_feat_finalise_settings - Finalise settings before starting negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * @dp: client or listening socket (settings will be inherited)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * This is called after all registrations (socket initialisation, sysctls, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * sockopt calls), and before sending the first packet containing Change options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * (ie. client-Request or server-Response), to ensure internal consistency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) int dccp_feat_finalise_settings(struct dccp_sock *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) struct list_head *fn = &dp->dccps_featneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct dccp_feat_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) int i = 2, ccids[2] = { -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * Propagating CCIDs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * 1) not useful to propagate CCID settings if this host advertises more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * than one CCID: the choice of CCID may still change - if this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) * the client, or if this is the server and the client sends
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) * singleton CCID values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) * 2) since is that propagate_ccid changes the list, we defer changing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * the sorted list until after the traversal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) list_for_each_entry(entry, fn, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (entry->feat_num == DCCPF_CCID && entry->val.sp.len == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) ccids[entry->is_local] = entry->val.sp.vec[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) while (i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (ccids[i] > 0 && dccp_feat_propagate_ccid(fn, ccids[i], i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) dccp_feat_print_fnlist(fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) * dccp_feat_server_ccid_dependencies - Resolve CCID-dependent features
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * It is the server which resolves the dependencies once the CCID has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) * fully negotiated. If no CCID has been negotiated, it uses the default CCID.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) int dccp_feat_server_ccid_dependencies(struct dccp_request_sock *dreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct list_head *fn = &dreq->dreq_featneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct dccp_feat_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) u8 is_local, ccid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) for (is_local = 0; is_local <= 1; is_local++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) entry = dccp_feat_list_lookup(fn, DCCPF_CCID, is_local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (entry != NULL && !entry->empty_confirm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) ccid = entry->val.sp.vec[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) ccid = dccp_feat_default_value(DCCPF_CCID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (dccp_feat_propagate_ccid(fn, ccid, is_local))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* Select the first entry in @servlist that also occurs in @clilist (6.3.1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) static int dccp_feat_preflist_match(u8 *servlist, u8 slen, u8 *clilist, u8 clen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) u8 c, s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) for (s = 0; s < slen; s++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) for (c = 0; c < clen; c++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (servlist[s] == clilist[c])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return servlist[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) * dccp_feat_prefer - Move preferred entry to the start of array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) * Reorder the @array_len elements in @array so that @preferred_value comes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * first. Returns >0 to indicate that @preferred_value does occur in @array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static u8 dccp_feat_prefer(u8 preferred_value, u8 *array, u8 array_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) u8 i, does_occur = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (array != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) for (i = 0; i < array_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (array[i] == preferred_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) array[i] = array[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) does_occur++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (does_occur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) array[0] = preferred_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return does_occur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * dccp_feat_reconcile - Reconcile SP preference lists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * @fv: SP list to reconcile into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * @arr: received SP preference list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * @len: length of @arr in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * @is_server: whether this side is the server (and @fv is the server's list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) * @reorder: whether to reorder the list in @fv after reconciling with @arr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * When successful, > 0 is returned and the reconciled list is in @fval.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) * A value of 0 means that negotiation failed (no shared entry).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static int dccp_feat_reconcile(dccp_feat_val *fv, u8 *arr, u8 len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) bool is_server, bool reorder)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (!fv->sp.vec || !arr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) DCCP_CRIT("NULL feature value or array");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (is_server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) rc = dccp_feat_preflist_match(fv->sp.vec, fv->sp.len, arr, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) rc = dccp_feat_preflist_match(arr, len, fv->sp.vec, fv->sp.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (!reorder)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) * Reorder list: used for activating features and in dccp_insert_fn_opt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return dccp_feat_prefer(rc, fv->sp.vec, fv->sp.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) * dccp_feat_change_recv - Process incoming ChangeL/R options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * @fn: feature-negotiation list to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) * @is_mandatory: whether the Change was preceded by a Mandatory option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) * @opt: %DCCPO_CHANGE_L or %DCCPO_CHANGE_R
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) * @feat: one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) * @val: NN value or SP value/preference list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * @len: length of @val in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * @server: whether this node is the server (1) or the client (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) u8 feat, u8 *val, u8 len, const bool server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) u8 defval, type = dccp_feat_type(feat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) const bool local = (opt == DCCPO_CHANGE_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) struct dccp_feat_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) dccp_feat_val fval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (len == 0 || type == FEAT_UNKNOWN) /* 6.1 and 6.6.8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) goto unknown_feature_or_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) dccp_feat_print_opt(opt, feat, val, len, is_mandatory);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) * Negotiation of NN features: Change R is invalid, so there is no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) * simultaneous negotiation; hence we do not look up in the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (type == FEAT_NN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (local || len > sizeof(fval.nn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) goto unknown_feature_or_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /* 6.3.2: "The feature remote MUST accept any valid value..." */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) fval.nn = dccp_decode_value_var(val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (!dccp_feat_is_valid_nn_val(feat, fval.nn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) goto unknown_feature_or_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) return dccp_feat_push_confirm(fn, feat, local, &fval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) * Unidirectional/simultaneous negotiation of SP features (6.3.1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) entry = dccp_feat_list_lookup(fn, feat, local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (entry == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) * No particular preferences have been registered. We deal with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) * this situation by assuming that all valid values are equally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) * acceptable, and apply the following checks:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) * - if the peer's list is a singleton, we accept a valid value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) * - if we are the server, we first try to see if the peer (the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) * client) advertises the default value. If yes, we use it,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) * otherwise we accept the preferred value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * - else if we are the client, we use the first list element.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (dccp_feat_clone_sp_val(&fval, val, 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) return DCCP_RESET_CODE_TOO_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (len > 1 && server) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) defval = dccp_feat_default_value(feat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if (dccp_feat_preflist_match(&defval, 1, val, len) > -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) fval.sp.vec[0] = defval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) } else if (!dccp_feat_is_valid_sp_val(feat, fval.sp.vec[0])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) kfree(fval.sp.vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) goto unknown_feature_or_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) /* Treat unsupported CCIDs like invalid values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (feat == DCCPF_CCID && !ccid_support_check(fval.sp.vec, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) kfree(fval.sp.vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) goto not_valid_or_not_known;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) return dccp_feat_push_confirm(fn, feat, local, &fval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) } else if (entry->state == FEAT_UNSTABLE) { /* 6.6.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (dccp_feat_reconcile(&entry->val, val, len, server, true)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) entry->empty_confirm = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) } else if (is_mandatory) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return DCCP_RESET_CODE_MANDATORY_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) } else if (entry->state == FEAT_INITIALISING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * Failed simultaneous negotiation (server only): try to `save'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * the connection by checking whether entry contains the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) * value for @feat. If yes, send an empty Confirm to signal that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * the received Change was not understood - which implies using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) * the default value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) * If this also fails, we use Reset as the last resort.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) WARN_ON(!server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) defval = dccp_feat_default_value(feat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (!dccp_feat_reconcile(&entry->val, &defval, 1, server, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return DCCP_RESET_CODE_OPTION_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) entry->empty_confirm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) entry->needs_confirm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) entry->needs_mandatory = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) entry->state = FEAT_STABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) unknown_feature_or_value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (!is_mandatory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) return dccp_push_empty_confirm(fn, feat, local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) not_valid_or_not_known:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) return is_mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) : DCCP_RESET_CODE_OPTION_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) * dccp_feat_confirm_recv - Process received Confirm options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) * @fn: feature-negotiation list to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) * @is_mandatory: whether @opt was preceded by a Mandatory option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) * @opt: %DCCPO_CONFIRM_L or %DCCPO_CONFIRM_R
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) * @feat: one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) * @val: NN value or SP value/preference list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) * @len: length of @val in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) * @server: whether this node is server (1) or client (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) u8 feat, u8 *val, u8 len, const bool server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) u8 *plist, plen, type = dccp_feat_type(feat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) const bool local = (opt == DCCPO_CONFIRM_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) struct dccp_feat_entry *entry = dccp_feat_list_lookup(fn, feat, local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) dccp_feat_print_opt(opt, feat, val, len, is_mandatory);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (entry == NULL) { /* nothing queued: ignore or handle error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (is_mandatory && type == FEAT_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) return DCCP_RESET_CODE_MANDATORY_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (!local && type == FEAT_NN) /* 6.3.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) goto confirmation_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (entry->state != FEAT_CHANGING) /* 6.6.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) if (len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (dccp_feat_must_be_understood(feat)) /* 6.6.7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) goto confirmation_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) * Empty Confirm during connection setup: this means reverting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) * to the `old' value, which in this case is the default. Since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * we handle default values automatically when no other values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) * have been set, we revert to the old value by removing this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) * entry from the list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) dccp_feat_list_pop(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if (type == FEAT_NN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (len > sizeof(entry->val.nn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) goto confirmation_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (entry->val.nn == dccp_decode_value_var(val, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) goto confirmation_succeeded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) DCCP_WARN("Bogus Confirm for non-existing value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) goto confirmation_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) * Parsing SP Confirms: the first element of @val is the preferred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * SP value which the peer confirms, the remainder depends on @len.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) * Note that only the confirmed value need to be a valid SP value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (!dccp_feat_is_valid_sp_val(feat, *val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) goto confirmation_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (len == 1) { /* peer didn't supply a preference list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) plist = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) plen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) } else { /* preferred value + preference list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) plist = val + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) plen = len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) /* Check whether the peer got the reconciliation right (6.6.8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) if (dccp_feat_reconcile(&entry->val, plist, plen, server, 0) != *val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) DCCP_WARN("Confirm selected the wrong value %u\n", *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) return DCCP_RESET_CODE_OPTION_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) entry->val.sp.vec[0] = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) confirmation_succeeded:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) entry->state = FEAT_STABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) confirmation_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) DCCP_WARN("Confirmation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) return is_mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) : DCCP_RESET_CODE_OPTION_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) * dccp_feat_handle_nn_established - Fast-path reception of NN options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) * @sk: socket of an established DCCP connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) * @mandatory: whether @opt was preceded by a Mandatory option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) * @opt: %DCCPO_CHANGE_L | %DCCPO_CONFIRM_R (NN only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) * @feat: NN number, one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) * @val: NN value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) * @len: length of @val in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) * This function combines the functionality of change_recv/confirm_recv, with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * the following differences (reset codes are the same):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) * - cleanup after receiving the Confirm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) * - values are directly activated after successful parsing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) * - deliberately restricted to NN features.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) * The restriction to NN features is essential since SP features can have non-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) * predictable outcomes (depending on the remote configuration), and are inter-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) * dependent (CCIDs for instance cause further dependencies).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) static u8 dccp_feat_handle_nn_established(struct sock *sk, u8 mandatory, u8 opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) u8 feat, u8 *val, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) const bool local = (opt == DCCPO_CONFIRM_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) struct dccp_feat_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) u8 type = dccp_feat_type(feat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) dccp_feat_val fval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) dccp_feat_print_opt(opt, feat, val, len, mandatory);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) /* Ignore non-mandatory unknown and non-NN features */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (type == FEAT_UNKNOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (local && !mandatory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) goto fast_path_unknown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) } else if (type != FEAT_NN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * We don't accept empty Confirms, since in fast-path feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) * negotiation the values are enabled immediately after sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) * the Change option.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * Empty Changes on the other hand are invalid (RFC 4340, 6.1).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (len == 0 || len > sizeof(fval.nn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) goto fast_path_unknown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) if (opt == DCCPO_CHANGE_L) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) fval.nn = dccp_decode_value_var(val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) if (!dccp_feat_is_valid_nn_val(feat, fval.nn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) goto fast_path_unknown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (dccp_feat_push_confirm(fn, feat, local, &fval) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) dccp_feat_activate(sk, feat, local, &fval))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) return DCCP_RESET_CODE_TOO_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) /* set the `Ack Pending' flag to piggyback a Confirm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) inet_csk_schedule_ack(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) } else if (opt == DCCPO_CONFIRM_R) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) entry = dccp_feat_list_lookup(fn, feat, local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (entry == NULL || entry->state != FEAT_CHANGING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) fval.nn = dccp_decode_value_var(val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) * Just ignore a value that doesn't match our current value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) * If the option changes twice within two RTTs, then at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * one CONFIRM will be received for the old value after a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * new CHANGE was sent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (fval.nn != entry->val.nn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) /* Only activate after receiving the Confirm option (6.6.1). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) dccp_feat_activate(sk, feat, local, &fval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) /* It has been confirmed - so remove the entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) dccp_feat_list_pop(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) DCCP_WARN("Received illegal option %u\n", opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) goto fast_path_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) fast_path_unknown:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (!mandatory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) return dccp_push_empty_confirm(fn, feat, local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) fast_path_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) return mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) : DCCP_RESET_CODE_OPTION_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * dccp_feat_parse_options - Process Feature-Negotiation Options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) * @sk: for general use and used by the client during connection setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) * @dreq: used by the server during connection setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) * @mandatory: whether @opt was preceded by a Mandatory option
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * @opt: %DCCPO_CHANGE_L | %DCCPO_CHANGE_R | %DCCPO_CONFIRM_L | %DCCPO_CONFIRM_R
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * @feat: one of %dccp_feature_numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) * @val: value contents of @opt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) * @len: length of @val in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * Returns 0 on success, a Reset code for ending the connection otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) u8 mandatory, u8 opt, u8 feat, u8 *val, u8 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) struct list_head *fn = dreq ? &dreq->dreq_featneg : &dp->dccps_featneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) bool server = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) switch (sk->sk_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) * Negotiation during connection setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) case DCCP_LISTEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) server = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) case DCCP_REQUESTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) switch (opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) case DCCPO_CHANGE_L:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) case DCCPO_CHANGE_R:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) return dccp_feat_change_recv(fn, mandatory, opt, feat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) val, len, server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) case DCCPO_CONFIRM_R:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) case DCCPO_CONFIRM_L:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) return dccp_feat_confirm_recv(fn, mandatory, opt, feat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) val, len, server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) * Support for exchanging NN options on an established connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) case DCCP_OPEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) case DCCP_PARTOPEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) return dccp_feat_handle_nn_established(sk, mandatory, opt, feat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) return 0; /* ignore FN options in all other states */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) * dccp_feat_init - Seed feature negotiation with host-specific defaults
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) * @sk: Socket to initialize.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) * This initialises global defaults, depending on the value of the sysctls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) * These can later be overridden by registering changes via setsockopt calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) * The last link in the chain is finalise_settings, to make sure that between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) * here and the start of actual feature negotiation no inconsistencies enter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) * All features not appearing below use either defaults or are otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) * later adjusted through dccp_feat_finalise_settings().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) int dccp_feat_init(struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) u8 on = 1, off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) u8 *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) u8 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) } tx, rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) /* Non-negotiable (NN) features */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) sysctl_dccp_sequence_window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) /* Server-priority (SP) features */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) /* Advertise that short seqnos are not supported (7.6.1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) rc = __feat_register_sp(fn, DCCPF_SHORT_SEQNOS, true, true, &off, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /* RFC 4340 12.1: "If a DCCP is not ECN capable, ..." */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) rc = __feat_register_sp(fn, DCCPF_ECN_INCAPABLE, true, true, &on, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) * We advertise the available list of CCIDs and reorder according to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) * preferences, to avoid failure resulting from negotiating different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) * singleton values (which always leads to failure).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) * These settings can still (later) be overridden via sockopts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (ccid_get_builtin_ccids(&tx.val, &tx.len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (ccid_get_builtin_ccids(&rx.val, &rx.len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) kfree(tx.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (!dccp_feat_prefer(sysctl_dccp_tx_ccid, tx.val, tx.len) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) !dccp_feat_prefer(sysctl_dccp_rx_ccid, rx.val, rx.len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) goto free_ccid_lists;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) goto free_ccid_lists;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) rc = __feat_register_sp(fn, DCCPF_CCID, false, false, rx.val, rx.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) free_ccid_lists:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) kfree(tx.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) kfree(rx.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) struct dccp_sock *dp = dccp_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) struct dccp_feat_entry *cur, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) dccp_feat_val *fvals[DCCP_FEAT_SUPPORTED_MAX][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) [0 ... DCCP_FEAT_SUPPORTED_MAX-1] = { NULL, NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) list_for_each_entry(cur, fn_list, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * An empty Confirm means that either an unknown feature type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) * or an invalid value was present. In the first case there is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) * nothing to activate, in the other the default value is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) if (cur->empty_confirm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) idx = dccp_feat_index(cur->feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) if (idx < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) DCCP_BUG("Unknown feature %u", cur->feat_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) goto activation_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) if (cur->state != FEAT_STABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) DCCP_CRIT("Negotiation of %s %s failed in state %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) cur->is_local ? "local" : "remote",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) dccp_feat_fname(cur->feat_num),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) dccp_feat_sname[cur->state]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) goto activation_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) fvals[idx][cur->is_local] = &cur->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * Activate in decreasing order of index, so that the CCIDs are always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) * activated as the last feature. This avoids the case where a CCID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) * relies on the initialisation of one or more features that it depends
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) * on (e.g. Send NDP Count, Send Ack Vector, and Ack Ratio features).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) for (idx = DCCP_FEAT_SUPPORTED_MAX; --idx >= 0;)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) if (__dccp_feat_activate(sk, idx, 0, fvals[idx][0]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) __dccp_feat_activate(sk, idx, 1, fvals[idx][1])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) DCCP_CRIT("Could not activate %d", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) goto activation_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) /* Clean up Change options which have been confirmed already */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) list_for_each_entry_safe(cur, next, fn_list, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (!cur->needs_confirm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) dccp_feat_list_pop(cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) dccp_pr_debug("Activation OK\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) activation_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) * We clean up everything that may have been allocated, since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) * it is difficult to track at which stage negotiation failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) * This is ok, since all allocation functions below are robust
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) * against NULL arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) dp->dccps_hc_rx_ackvec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) }