diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:30:19 -0400 |
---|---|---|
committer | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:45:31 -0400 |
commit | 5d3dac267a7fd0811ec777e76a81f97f5cdcb395 (patch) | |
tree | ef57f539a5be1c7776c73a4bcffe2d840e6883f5 /net/dccp/feat.c | |
parent | b235dc4abbc1356284bd0dc730efa711f394e0e2 (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.c | 66 |
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 | */ | ||
1113 | int dccp_feat_init(struct sock *sk) | 1123 | int 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; |
1125 | out: | 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 | |||
1171 | free_ccid_lists: | ||
1172 | kfree(tx.val); | ||
1173 | kfree(rx.val); | ||
1126 | return rc; | 1174 | return rc; |
1127 | } | 1175 | } |
1128 | 1176 | ||
1129 | EXPORT_SYMBOL_GPL(dccp_feat_init); | ||
1130 | |||
1131 | int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) | 1177 | int 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); |