aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/feat.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/feat.c')
-rw-r--r--net/dccp/feat.c65
1 files changed, 56 insertions, 9 deletions
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 4152308958a..67ffac9905f 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -1115,23 +1115,70 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
1115 return 0; /* ignore FN options in all other states */ 1115 return 0; /* ignore FN options in all other states */
1116} 1116}
1117 1117
1118/**
1119 * dccp_feat_init - Seed feature negotiation with host-specific defaults
1120 * This initialises global defaults, depending on the value of the sysctls.
1121 * These can later be overridden by registering changes via setsockopt calls.
1122 * The last link in the chain is finalise_settings, to make sure that between
1123 * here and the start of actual feature negotiation no inconsistencies enter.
1124 *
1125 * All features not appearing below use either defaults or are otherwise
1126 * later adjusted through dccp_feat_finalise_settings().
1127 */
1118int dccp_feat_init(struct sock *sk) 1128int dccp_feat_init(struct sock *sk)
1119{ 1129{
1120 struct dccp_sock *dp = dccp_sk(sk); 1130 struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
1121 struct dccp_minisock *dmsk = dccp_msk(sk); 1131 u8 on = 1, off = 0;
1122 int rc; 1132 int rc;
1133 struct {
1134 u8 *val;
1135 u8 len;
1136 } tx, rx;
1137
1138 /* Non-negotiable (NN) features */
1139 rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0,
1140 sysctl_dccp_feat_sequence_window);
1141 if (rc)
1142 return rc;
1143
1144 /* Server-priority (SP) features */
1145
1146 /* Advertise that short seqnos are not supported (7.6.1) */
1147 rc = __feat_register_sp(fn, DCCPF_SHORT_SEQNOS, true, true, &off, 1);
1148 if (rc)
1149 return rc;
1123 1150
1124 INIT_LIST_HEAD(&dmsk->dccpms_pending); /* XXX no longer used */ 1151 /* RFC 4340 12.1: "If a DCCP is not ECN capable, ..." */
1125 INIT_LIST_HEAD(&dmsk->dccpms_conf); /* XXX no longer used */ 1152 rc = __feat_register_sp(fn, DCCPF_ECN_INCAPABLE, true, true, &on, 1);
1153 if (rc)
1154 return rc;
1155
1156 /*
1157 * We advertise the available list of CCIDs and reorder according to
1158 * preferences, to avoid failure resulting from negotiating different
1159 * singleton values (which always leads to failure).
1160 * These settings can still (later) be overridden via sockopts.
1161 */
1162 if (ccid_get_builtin_ccids(&tx.val, &tx.len) ||
1163 ccid_get_builtin_ccids(&rx.val, &rx.len))
1164 return -ENOBUFS;
1126 1165
1127 /* Ack ratio */ 1166 if (!dccp_feat_prefer(sysctl_dccp_feat_tx_ccid, tx.val, tx.len) ||
1128 rc = __feat_register_nn(&dp->dccps_featneg, DCCPF_ACK_RATIO, 0, 1167 !dccp_feat_prefer(sysctl_dccp_feat_rx_ccid, rx.val, rx.len))
1129 dp->dccps_l_ack_ratio); 1168 goto free_ccid_lists;
1169
1170 rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len);
1171 if (rc)
1172 goto free_ccid_lists;
1173
1174 rc = __feat_register_sp(fn, DCCPF_CCID, false, false, rx.val, rx.len);
1175
1176free_ccid_lists:
1177 kfree(tx.val);
1178 kfree(rx.val);
1130 return rc; 1179 return rc;
1131} 1180}
1132 1181
1133EXPORT_SYMBOL_GPL(dccp_feat_init);
1134
1135int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) 1182int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)
1136{ 1183{
1137 struct dccp_sock *dp = dccp_sk(sk); 1184 struct dccp_sock *dp = dccp_sk(sk);