@@ -237,6 +237,40 @@ static int dccp_feat_push_change(struct list_head *fn_list, u8 feat, u8 local,
237
237
return 0 ;
238
238
}
239
239
240
+ /**
241
+ * dccp_feat_push_confirm - Add a Confirm entry to the FN list
242
+ * @fn_list: feature-negotiation list to add to
243
+ * @feat: one of %dccp_feature_numbers
244
+ * @local: whether local (1) or remote (0) @feat_num is being confirmed
245
+ * @fval: pointer to NN/SP value to be inserted or NULL
246
+ * Returns 0 on success, a Reset code for further processing otherwise.
247
+ */
248
+ static int dccp_feat_push_confirm (struct list_head * fn_list , u8 feat , u8 local ,
249
+ dccp_feat_val * fval )
250
+ {
251
+ struct dccp_feat_entry * new = dccp_feat_entry_new (fn_list , feat , local );
252
+
253
+ if (new == NULL )
254
+ return DCCP_RESET_CODE_TOO_BUSY ;
255
+
256
+ new -> feat_num = feat ;
257
+ new -> is_local = local ;
258
+ new -> state = FEAT_STABLE ; /* transition in 6.6.2 */
259
+ new -> needs_confirm = 1 ;
260
+ new -> empty_confirm = (fval == NULL );
261
+ new -> val .nn = 0 ; /* zeroes the whole structure */
262
+ if (!new -> empty_confirm )
263
+ new -> val = * fval ;
264
+ new -> needs_mandatory = 0 ;
265
+
266
+ return 0 ;
267
+ }
268
+
269
+ static int dccp_push_empty_confirm (struct list_head * fn_list , u8 feat , u8 local )
270
+ {
271
+ return dccp_feat_push_confirm (fn_list , feat , local , NULL );
272
+ }
273
+
240
274
static inline void dccp_feat_list_pop (struct dccp_feat_entry * entry )
241
275
{
242
276
list_del (& entry -> node );
@@ -955,7 +989,6 @@ static int dccp_feat_nn(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
955
989
956
990
return 0 ;
957
991
}
958
- #endif /* (later) */
959
992
960
993
static void dccp_feat_empty_confirm (struct dccp_minisock * dmsk ,
961
994
u8 type , u8 feature )
@@ -1066,6 +1099,7 @@ int dccp_feat_change_recv(struct sock *sk, u8 type, u8 feature, u8 *val, u8 len)
1066
1099
}
1067
1100
1068
1101
EXPORT_SYMBOL_GPL (dccp_feat_change_recv );
1102
+ #endif /* (later) */
1069
1103
1070
1104
int dccp_feat_confirm_recv (struct sock * sk , u8 type , u8 feature ,
1071
1105
u8 * val , u8 len )
@@ -1206,6 +1240,150 @@ int dccp_feat_clone(struct sock *oldsk, struct sock *newsk)
1206
1240
1207
1241
EXPORT_SYMBOL_GPL (dccp_feat_clone );
1208
1242
1243
+ /**
1244
+ * dccp_feat_change_recv - Process incoming ChangeL/R options
1245
+ * @fn: feature-negotiation list to update
1246
+ * @is_mandatory: whether the Change was preceded by a Mandatory option
1247
+ * @opt: %DCCPO_CHANGE_L or %DCCPO_CHANGE_R
1248
+ * @feat: one of %dccp_feature_numbers
1249
+ * @val: NN value or SP value/preference list
1250
+ * @len: length of @val in bytes
1251
+ * @server: whether this node is the server (1) or the client (0)
1252
+ */
1253
+ static u8 dccp_feat_change_recv (struct list_head * fn , u8 is_mandatory , u8 opt ,
1254
+ u8 feat , u8 * val , u8 len , const bool server )
1255
+ {
1256
+ u8 defval , type = dccp_feat_type (feat );
1257
+ const bool local = (opt == DCCPO_CHANGE_R );
1258
+ struct dccp_feat_entry * entry ;
1259
+ dccp_feat_val fval ;
1260
+
1261
+ if (len == 0 || type == FEAT_UNKNOWN ) /* 6.1 and 6.6.8 */
1262
+ goto unknown_feature_or_value ;
1263
+
1264
+ /*
1265
+ * Negotiation of NN features: Change R is invalid, so there is no
1266
+ * simultaneous negotiation; hence we do not look up in the list.
1267
+ */
1268
+ if (type == FEAT_NN ) {
1269
+ if (local || len > sizeof (fval .nn ))
1270
+ goto unknown_feature_or_value ;
1271
+
1272
+ /* 6.3.2: "The feature remote MUST accept any valid value..." */
1273
+ fval .nn = dccp_decode_value_var (val , len );
1274
+ if (!dccp_feat_is_valid_nn_val (feat , fval .nn ))
1275
+ goto unknown_feature_or_value ;
1276
+
1277
+ return dccp_feat_push_confirm (fn , feat , local , & fval );
1278
+ }
1279
+
1280
+ /*
1281
+ * Unidirectional/simultaneous negotiation of SP features (6.3.1)
1282
+ */
1283
+ entry = dccp_feat_list_lookup (fn , feat , local );
1284
+ if (entry == NULL ) {
1285
+ /*
1286
+ * No particular preferences have been registered. We deal with
1287
+ * this situation by assuming that all valid values are equally
1288
+ * acceptable, and apply the following checks:
1289
+ * - if the peer's list is a singleton, we accept a valid value;
1290
+ * - if we are the server, we first try to see if the peer (the
1291
+ * client) advertises the default value. If yes, we use it,
1292
+ * otherwise we accept the preferred value;
1293
+ * - else if we are the client, we use the first list element.
1294
+ */
1295
+ if (dccp_feat_clone_sp_val (& fval , val , 1 ))
1296
+ return DCCP_RESET_CODE_TOO_BUSY ;
1297
+
1298
+ if (len > 1 && server ) {
1299
+ defval = dccp_feat_default_value (feat );
1300
+ if (dccp_feat_preflist_match (& defval , 1 , val , len ) > -1 )
1301
+ fval .sp .vec [0 ] = defval ;
1302
+ } else if (!dccp_feat_is_valid_sp_val (feat , fval .sp .vec [0 ])) {
1303
+ kfree (fval .sp .vec );
1304
+ goto unknown_feature_or_value ;
1305
+ }
1306
+
1307
+ /* Treat unsupported CCIDs like invalid values */
1308
+ if (feat == DCCPF_CCID && !ccid_support_check (fval .sp .vec , 1 )) {
1309
+ kfree (fval .sp .vec );
1310
+ goto not_valid_or_not_known ;
1311
+ }
1312
+
1313
+ return dccp_feat_push_confirm (fn , feat , local , & fval );
1314
+
1315
+ } else if (entry -> state == FEAT_UNSTABLE ) { /* 6.6.2 */
1316
+ return 0 ;
1317
+ }
1318
+
1319
+ if (dccp_feat_reconcile (& entry -> val , val , len , server , true)) {
1320
+ entry -> empty_confirm = 0 ;
1321
+ } else if (is_mandatory ) {
1322
+ return DCCP_RESET_CODE_MANDATORY_ERROR ;
1323
+ } else if (entry -> state == FEAT_INITIALISING ) {
1324
+ /*
1325
+ * Failed simultaneous negotiation (server only): try to `save'
1326
+ * the connection by checking whether entry contains the default
1327
+ * value for @feat. If yes, send an empty Confirm to signal that
1328
+ * the received Change was not understood - which implies using
1329
+ * the default value.
1330
+ * If this also fails, we use Reset as the last resort.
1331
+ */
1332
+ WARN_ON (!server );
1333
+ defval = dccp_feat_default_value (feat );
1334
+ if (!dccp_feat_reconcile (& entry -> val , & defval , 1 , server , true))
1335
+ return DCCP_RESET_CODE_OPTION_ERROR ;
1336
+ entry -> empty_confirm = 1 ;
1337
+ }
1338
+ entry -> needs_confirm = 1 ;
1339
+ entry -> needs_mandatory = 0 ;
1340
+ entry -> state = FEAT_STABLE ;
1341
+ return 0 ;
1342
+
1343
+ unknown_feature_or_value :
1344
+ if (!is_mandatory )
1345
+ return dccp_push_empty_confirm (fn , feat , local );
1346
+
1347
+ not_valid_or_not_known :
1348
+ return is_mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR
1349
+ : DCCP_RESET_CODE_OPTION_ERROR ;
1350
+ }
1351
+
1352
+ /**
1353
+ * dccp_feat_parse_options - Process Feature-Negotiation Options
1354
+ * @sk: for general use and used by the client during connection setup
1355
+ * @dreq: used by the server during connection setup
1356
+ * @mandatory: whether @opt was preceded by a Mandatory option
1357
+ * @opt: %DCCPO_CHANGE_L | %DCCPO_CHANGE_R | %DCCPO_CONFIRM_L | %DCCPO_CONFIRM_R
1358
+ * @feat: one of %dccp_feature_numbers
1359
+ * @val: value contents of @opt
1360
+ * @len: length of @val in bytes
1361
+ * Returns 0 on success, a Reset code for ending the connection otherwise.
1362
+ */
1363
+ int dccp_feat_parse_options (struct sock * sk , struct dccp_request_sock * dreq ,
1364
+ u8 mandatory , u8 opt , u8 feat , u8 * val , u8 len )
1365
+ {
1366
+ struct dccp_sock * dp = dccp_sk (sk );
1367
+ struct list_head * fn = dreq ? & dreq -> dreq_featneg : & dp -> dccps_featneg ;
1368
+ bool server = false;
1369
+
1370
+ switch (sk -> sk_state ) {
1371
+ /*
1372
+ * Negotiation during connection setup
1373
+ */
1374
+ case DCCP_LISTEN :
1375
+ server = true; /* fall through */
1376
+ case DCCP_REQUESTING :
1377
+ switch (opt ) {
1378
+ case DCCPO_CHANGE_L :
1379
+ case DCCPO_CHANGE_R :
1380
+ return dccp_feat_change_recv (fn , mandatory , opt , feat ,
1381
+ val , len , server );
1382
+ }
1383
+ }
1384
+ return 0 ; /* ignore FN options in all other states */
1385
+ }
1386
+
1209
1387
int dccp_feat_init (struct sock * sk )
1210
1388
{
1211
1389
struct dccp_sock * dp = dccp_sk (sk );
0 commit comments