aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/feat.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:30:19 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:45:31 -0400
commit5d3dac267a7fd0811ec777e76a81f97f5cdcb395 (patch)
treeef57f539a5be1c7776c73a4bcffe2d840e6883f5 /net/dccp/feat.c
parentb235dc4abbc1356284bd0dc730efa711f394e0e2 (diff)
dccp: Initialisation framework for feature negotiation
This initialises feature negotiation from two tables, which are initialised from sysctls. As a novel feature, specifics of the implementation (e.g. currently short seqnos and ECN are not supported) are advertised for robustness. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Diffstat (limited to 'net/dccp/feat.c')
-rw-r--r--net/dccp/feat.c66
1 files changed, 56 insertions, 10 deletions
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 35a57ab3bb1e..a687740e4420 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -1110,24 +1110,70 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
1110 return 0; /* ignore FN options in all other states */ 1110 return 0; /* ignore FN options in all other states */
1111} 1111}
1112 1112
1113/**
1114 * dccp_feat_init - Seed feature negotiation with host-specific defaults
1115 * This initialises global defaults, depending on the value of the sysctls.
1116 * These can later be overridden by registering changes via setsockopt calls.
1117 * The last link in the chain is finalise_settings, to make sure that between
1118 * here and the start of actual feature negotiation no inconsistencies enter.
1119 *
1120 * All features not appearing below use either defaults or are otherwise
1121 * later adjusted through dccp_feat_finalise_settings().
1122 */
1113int dccp_feat_init(struct sock *sk) 1123int dccp_feat_init(struct sock *sk)
1114{ 1124{
1115 struct dccp_sock *dp = dccp_sk(sk); 1125 struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
1116 struct dccp_minisock *dmsk = dccp_msk(sk); 1126 u8 on = 1, off = 0;
1117 int rc; 1127 int rc;
1128 struct {
1129 u8 *val;
1130 u8 len;
1131 } tx, rx;
1132
1133 /* Non-negotiable (NN) features */
1134 rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0,
1135 sysctl_dccp_feat_sequence_window);
1136 if (rc)
1137 return rc;
1138
1139 /* Server-priority (SP) features */
1140
1141 /* Advertise that short seqnos are not supported (7.6.1) */
1142 rc = __feat_register_sp(fn, DCCPF_SHORT_SEQNOS, true, true, &off, 1);
1143 if (rc)
1144 return rc;
1118 1145
1119 INIT_LIST_HEAD(&dmsk->dccpms_pending); /* XXX no longer used */ 1146 /* RFC 4340 12.1: "If a DCCP is not ECN capable, ..." */
1120 INIT_LIST_HEAD(&dmsk->dccpms_conf); /* XXX no longer used */ 1147 rc = __feat_register_sp(fn, DCCPF_ECN_INCAPABLE, true, true, &on, 1);
1148 if (rc)
1149 return rc;
1150
1151 /*
1152 * We advertise the available list of CCIDs and reorder according to
1153 * preferences, to avoid failure resulting from negotiating different
1154 * singleton values (which always leads to failure).
1155 * These settings can still (later) be overridden via sockopts.
1156 */
1157 if (ccid_get_builtin_ccids(&tx.val, &tx.len) ||
1158 ccid_get_builtin_ccids(&rx.val, &rx.len))
1159 return -ENOBUFS;
1121 1160
1122 /* Ack ratio */ 1161 if (!dccp_feat_prefer(sysctl_dccp_feat_tx_ccid, tx.val, tx.len) ||
1123 rc = __feat_register_nn(&dp->dccps_featneg, DCCPF_ACK_RATIO, 0, 1162 !dccp_feat_prefer(sysctl_dccp_feat_rx_ccid, rx.val, rx.len))
1124 dp->dccps_l_ack_ratio); 1163 goto free_ccid_lists;
1125out: 1164
1165 rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len);
1166 if (rc)
1167 goto free_ccid_lists;
1168
1169 rc = __feat_register_sp(fn, DCCPF_CCID, false, false, rx.val, rx.len);
1170
1171free_ccid_lists:
1172 kfree(tx.val);
1173 kfree(rx.val);
1126 return rc; 1174 return rc;
1127} 1175}
1128 1176
1129EXPORT_SYMBOL_GPL(dccp_feat_init);
1130
1131int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) 1177int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)
1132{ 1178{
1133 struct dccp_sock *dp = dccp_sk(sk); 1179 struct dccp_sock *dp = dccp_sk(sk);