diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2009-01-16 18:36:30 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-21 17:34:04 -0500 |
commit | f90f92eed74251034f251e3cdf4fa5c4c1f09df0 (patch) | |
tree | 85ed44fee79d91d7bf1ebc6624a90e50af46063f /net/dccp/feat.c | |
parent | 5cda9364f1fbc330f0d82f534505a8e375d0a66c (diff) |
dccp: Initialisation framework for feature negotiation
This initialises feature negotiation from two tables, which are in
turn are initialised from sysctls.
As a novel feature, specifics of the implementation (e.g. that short
seqnos and ECN are not yet available) are advertised for robustness.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/feat.c')
-rw-r--r-- | net/dccp/feat.c | 65 |
1 files changed, 56 insertions, 9 deletions
diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 4152308958ab..67ffac9905f8 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 | */ | ||
1118 | int dccp_feat_init(struct sock *sk) | 1128 | int 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 | |||
1176 | free_ccid_lists: | ||
1177 | kfree(tx.val); | ||
1178 | kfree(rx.val); | ||
1130 | return rc; | 1179 | return rc; |
1131 | } | 1180 | } |
1132 | 1181 | ||
1133 | EXPORT_SYMBOL_GPL(dccp_feat_init); | ||
1134 | |||
1135 | int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) | 1182 | int 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); |