aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
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:32 -0400
commit4861a354430d2ea36847ef88086c7449b4f385b6 (patch)
tree53a40f7f81c6f683b5c998f7a295de4bef2b5abf /net/dccp
parent624a965a93610152b10c73d050ed44812efa8abe (diff)
dccp: Support for exchanging of NN options in established state
This patch provides support for the reception of NN options in (PART)OPEN state. It is a combination of change_recv() and confirm_recv(), specifically geared towards receiving the `fast-path' NN options. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/feat.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 5be8b85ac74b..c847c80d1b97 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -1247,6 +1247,93 @@ confirmation_failed:
1247} 1247}
1248 1248
1249/** 1249/**
1250 * dccp_feat_handle_nn_established - Fast-path reception of NN options
1251 * @sk: socket of an established DCCP connection
1252 * @mandatory: whether @opt was preceded by a Mandatory option
1253 * @opt: %DCCPO_CHANGE_L | %DCCPO_CONFIRM_R (NN only)
1254 * @feat: NN number, one of %dccp_feature_numbers
1255 * @val: NN value
1256 * @len: length of @val in bytes
1257 * This function combines the functionality of change_recv/confirm_recv, with
1258 * the following differences (reset codes are the same):
1259 * - cleanup after receiving the Confirm;
1260 * - values are directly activated after successful parsing;
1261 * - deliberately restricted to NN features.
1262 * The restriction to NN features is essential since SP features can have non-
1263 * predictable outcomes (depending on the remote configuration), and are inter-
1264 * dependent (CCIDs for instance cause further dependencies).
1265 */
1266static u8 dccp_feat_handle_nn_established(struct sock *sk, u8 mandatory, u8 opt,
1267 u8 feat, u8 *val, u8 len)
1268{
1269 struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
1270 const bool local = (opt == DCCPO_CONFIRM_R);
1271 struct dccp_feat_entry *entry;
1272 u8 type = dccp_feat_type(feat);
1273 dccp_feat_val fval;
1274
1275 dccp_feat_print_opt(opt, feat, val, len, mandatory);
1276
1277 /* Ignore non-mandatory unknown and non-NN features */
1278 if (type == FEAT_UNKNOWN) {
1279 if (local && !mandatory)
1280 return 0;
1281 goto fast_path_unknown;
1282 } else if (type != FEAT_NN) {
1283 return 0;
1284 }
1285
1286 /*
1287 * We don't accept empty Confirms, since in fast-path feature
1288 * negotiation the values are enabled immediately after sending
1289 * the Change option.
1290 * Empty Changes on the other hand are invalid (RFC 4340, 6.1).
1291 */
1292 if (len == 0 || len > sizeof(fval.nn))
1293 goto fast_path_unknown;
1294
1295 if (opt == DCCPO_CHANGE_L) {
1296 fval.nn = dccp_decode_value_var(val, len);
1297 if (!dccp_feat_is_valid_nn_val(feat, fval.nn))
1298 goto fast_path_unknown;
1299
1300 if (dccp_feat_push_confirm(fn, feat, local, &fval) ||
1301 dccp_feat_activate(sk, feat, local, &fval))
1302 return DCCP_RESET_CODE_TOO_BUSY;
1303
1304 /* set the `Ack Pending' flag to piggyback a Confirm */
1305 inet_csk_schedule_ack(sk);
1306
1307 } else if (opt == DCCPO_CONFIRM_R) {
1308 entry = dccp_feat_list_lookup(fn, feat, local);
1309 if (entry == NULL || entry->state != FEAT_CHANGING)
1310 return 0;
1311
1312 fval.nn = dccp_decode_value_var(val, len);
1313 if (fval.nn != entry->val.nn) {
1314 DCCP_WARN("Bogus Confirm for non-existing value\n");
1315 goto fast_path_failed;
1316 }
1317
1318 /* It has been confirmed - so remove the entry */
1319 dccp_feat_list_pop(entry);
1320
1321 } else {
1322 DCCP_WARN("Received illegal option %u\n", opt);
1323 goto fast_path_failed;
1324 }
1325 return 0;
1326
1327fast_path_unknown:
1328 if (!mandatory)
1329 return dccp_push_empty_confirm(fn, feat, local);
1330
1331fast_path_failed:
1332 return mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR
1333 : DCCP_RESET_CODE_OPTION_ERROR;
1334}
1335
1336/**
1250 * dccp_feat_parse_options - Process Feature-Negotiation Options 1337 * dccp_feat_parse_options - Process Feature-Negotiation Options
1251 * @sk: for general use and used by the client during connection setup 1338 * @sk: for general use and used by the client during connection setup
1252 * @dreq: used by the server during connection setup 1339 * @dreq: used by the server during connection setup
@@ -1281,6 +1368,15 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
1281 return dccp_feat_confirm_recv(fn, mandatory, opt, feat, 1368 return dccp_feat_confirm_recv(fn, mandatory, opt, feat,
1282 val, len, server); 1369 val, len, server);
1283 } 1370 }
1371 break;
1372 /*
1373 * Support for exchanging NN options on an established connection
1374 * This is currently restricted to Ack Ratio (RFC 4341, 6.1.2)
1375 */
1376 case DCCP_OPEN:
1377 case DCCP_PARTOPEN:
1378 return dccp_feat_handle_nn_established(sk, mandatory, opt, feat,
1379 val, len);
1284 } 1380 }
1285 return 0; /* ignore FN options in all other states */ 1381 return 0; /* ignore FN options in all other states */
1286} 1382}