feat.c (7483d45f0aee3afc0646d185cabd4af9f6cab58c) feat.c (2c53040f018b6c36a46eec75b9b937aaa5f78e6d)
1/*
2 * net/dccp/feat.c
3 *
4 * Feature negotiation for the DCCP protocol (RFC 4340, section 6)
5 *
6 * Copyright (c) 2008 Gerrit Renker <gerrit@erg.abdn.ac.uk>
7 * Rewrote from scratch, some bits from earlier code by
8 * Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk>

--- 336 unchanged lines hidden (view full) ---

345}
346
347/**
348 * dccp_feat_activate - Activate feature value on socket
349 * @sk: fully connected DCCP socket (after handshake is complete)
350 * @feat_num: feature to activate, one of %dccp_feature_numbers
351 * @local: whether local (1) or remote (0) @feat_num is meant
352 * @fval: the value (SP or NN) to activate, or NULL to use the default value
1/*
2 * net/dccp/feat.c
3 *
4 * Feature negotiation for the DCCP protocol (RFC 4340, section 6)
5 *
6 * Copyright (c) 2008 Gerrit Renker <gerrit@erg.abdn.ac.uk>
7 * Rewrote from scratch, some bits from earlier code by
8 * Copyright (c) 2005 Andrea Bittau <a.bittau@cs.ucl.ac.uk>

--- 336 unchanged lines hidden (view full) ---

345}
346
347/**
348 * dccp_feat_activate - Activate feature value on socket
349 * @sk: fully connected DCCP socket (after handshake is complete)
350 * @feat_num: feature to activate, one of %dccp_feature_numbers
351 * @local: whether local (1) or remote (0) @feat_num is meant
352 * @fval: the value (SP or NN) to activate, or NULL to use the default value
353 *
353 * For general use this function is preferable over __dccp_feat_activate().
354 */
355static int dccp_feat_activate(struct sock *sk, u8 feat_num, bool local,
356 dccp_feat_val const *fval)
357{
358 return __dccp_feat_activate(sk, dccp_feat_index(feat_num), local, fval);
359}
360

--- 80 unchanged lines hidden (view full) ---

441 return NULL;
442}
443
444/**
445 * dccp_feat_entry_new - Central list update routine (called by all others)
446 * @head: list to add to
447 * @feat: feature number
448 * @local: whether the local (1) or remote feature with number @feat is meant
354 * For general use this function is preferable over __dccp_feat_activate().
355 */
356static int dccp_feat_activate(struct sock *sk, u8 feat_num, bool local,
357 dccp_feat_val const *fval)
358{
359 return __dccp_feat_activate(sk, dccp_feat_index(feat_num), local, fval);
360}
361

--- 80 unchanged lines hidden (view full) ---

442 return NULL;
443}
444
445/**
446 * dccp_feat_entry_new - Central list update routine (called by all others)
447 * @head: list to add to
448 * @feat: feature number
449 * @local: whether the local (1) or remote feature with number @feat is meant
450 *
449 * This is the only constructor and serves to ensure the above invariants.
450 */
451static struct dccp_feat_entry *
452 dccp_feat_entry_new(struct list_head *head, u8 feat, bool local)
453{
454 struct dccp_feat_entry *entry;
455
456 list_for_each_entry(entry, head, node)

--- 42 unchanged lines hidden (view full) ---

499}
500
501/**
502 * dccp_feat_push_confirm - Add a Confirm entry to the FN list
503 * @fn_list: feature-negotiation list to add to
504 * @feat: one of %dccp_feature_numbers
505 * @local: whether local (1) or remote (0) @feat_num is being confirmed
506 * @fval: pointer to NN/SP value to be inserted or NULL
451 * This is the only constructor and serves to ensure the above invariants.
452 */
453static struct dccp_feat_entry *
454 dccp_feat_entry_new(struct list_head *head, u8 feat, bool local)
455{
456 struct dccp_feat_entry *entry;
457
458 list_for_each_entry(entry, head, node)

--- 42 unchanged lines hidden (view full) ---

501}
502
503/**
504 * dccp_feat_push_confirm - Add a Confirm entry to the FN list
505 * @fn_list: feature-negotiation list to add to
506 * @feat: one of %dccp_feature_numbers
507 * @local: whether local (1) or remote (0) @feat_num is being confirmed
508 * @fval: pointer to NN/SP value to be inserted or NULL
509 *
507 * Returns 0 on success, a Reset code for further processing otherwise.
508 */
509static int dccp_feat_push_confirm(struct list_head *fn_list, u8 feat, u8 local,
510 dccp_feat_val *fval)
511{
512 struct dccp_feat_entry *new = dccp_feat_entry_new(fn_list, feat, local);
513
514 if (new == NULL)

--- 171 unchanged lines hidden (view full) ---

686}
687
688/**
689 * __feat_register_nn - Register new NN value on socket
690 * @fn: feature-negotiation list to register with
691 * @feat: an NN feature from %dccp_feature_numbers
692 * @mandatory: use Mandatory option if 1
693 * @nn_val: value to register (restricted to 4 bytes)
510 * Returns 0 on success, a Reset code for further processing otherwise.
511 */
512static int dccp_feat_push_confirm(struct list_head *fn_list, u8 feat, u8 local,
513 dccp_feat_val *fval)
514{
515 struct dccp_feat_entry *new = dccp_feat_entry_new(fn_list, feat, local);
516
517 if (new == NULL)

--- 171 unchanged lines hidden (view full) ---

689}
690
691/**
692 * __feat_register_nn - Register new NN value on socket
693 * @fn: feature-negotiation list to register with
694 * @feat: an NN feature from %dccp_feature_numbers
695 * @mandatory: use Mandatory option if 1
696 * @nn_val: value to register (restricted to 4 bytes)
697 *
694 * Note that NN features are local by definition (RFC 4340, 6.3.2).
695 */
696static int __feat_register_nn(struct list_head *fn, u8 feat,
697 u8 mandatory, u64 nn_val)
698{
699 dccp_feat_val fval = { .nn = nn_val };
700
701 if (dccp_feat_type(feat) != FEAT_NN ||

--- 53 unchanged lines hidden (view full) ---

755 return __feat_register_sp(&dccp_sk(sk)->dccps_featneg, feat, is_local,
756 0, list, len);
757}
758
759/**
760 * dccp_feat_nn_get - Query current/pending value of NN feature
761 * @sk: DCCP socket of an established connection
762 * @feat: NN feature number from %dccp_feature_numbers
698 * Note that NN features are local by definition (RFC 4340, 6.3.2).
699 */
700static int __feat_register_nn(struct list_head *fn, u8 feat,
701 u8 mandatory, u64 nn_val)
702{
703 dccp_feat_val fval = { .nn = nn_val };
704
705 if (dccp_feat_type(feat) != FEAT_NN ||

--- 53 unchanged lines hidden (view full) ---

759 return __feat_register_sp(&dccp_sk(sk)->dccps_featneg, feat, is_local,
760 0, list, len);
761}
762
763/**
764 * dccp_feat_nn_get - Query current/pending value of NN feature
765 * @sk: DCCP socket of an established connection
766 * @feat: NN feature number from %dccp_feature_numbers
767 *
763 * For a known NN feature, returns value currently being negotiated, or
764 * current (confirmed) value if no negotiation is going on.
765 */
766u64 dccp_feat_nn_get(struct sock *sk, u8 feat)
767{
768 if (dccp_feat_type(feat) == FEAT_NN) {
769 struct dccp_sock *dp = dccp_sk(sk);
770 struct dccp_feat_entry *entry;

--- 14 unchanged lines hidden (view full) ---

785}
786EXPORT_SYMBOL_GPL(dccp_feat_nn_get);
787
788/**
789 * dccp_feat_signal_nn_change - Update NN values for an established connection
790 * @sk: DCCP socket of an established connection
791 * @feat: NN feature number from %dccp_feature_numbers
792 * @nn_val: the new value to use
768 * For a known NN feature, returns value currently being negotiated, or
769 * current (confirmed) value if no negotiation is going on.
770 */
771u64 dccp_feat_nn_get(struct sock *sk, u8 feat)
772{
773 if (dccp_feat_type(feat) == FEAT_NN) {
774 struct dccp_sock *dp = dccp_sk(sk);
775 struct dccp_feat_entry *entry;

--- 14 unchanged lines hidden (view full) ---

790}
791EXPORT_SYMBOL_GPL(dccp_feat_nn_get);
792
793/**
794 * dccp_feat_signal_nn_change - Update NN values for an established connection
795 * @sk: DCCP socket of an established connection
796 * @feat: NN feature number from %dccp_feature_numbers
797 * @nn_val: the new value to use
798 *
793 * This function is used to communicate NN updates out-of-band.
794 */
795int dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val)
796{
797 struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
798 dccp_feat_val fval = { .nn = nn_val };
799 struct dccp_feat_entry *entry;
800

--- 124 unchanged lines hidden (view full) ---

925 }
926}
927
928/**
929 * dccp_feat_propagate_ccid - Resolve dependencies of features on choice of CCID
930 * @fn: feature-negotiation list to update
931 * @id: CCID number to track
932 * @is_local: whether TX CCID (1) or RX CCID (0) is meant
799 * This function is used to communicate NN updates out-of-band.
800 */
801int dccp_feat_signal_nn_change(struct sock *sk, u8 feat, u64 nn_val)
802{
803 struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
804 dccp_feat_val fval = { .nn = nn_val };
805 struct dccp_feat_entry *entry;
806

--- 124 unchanged lines hidden (view full) ---

931 }
932}
933
934/**
935 * dccp_feat_propagate_ccid - Resolve dependencies of features on choice of CCID
936 * @fn: feature-negotiation list to update
937 * @id: CCID number to track
938 * @is_local: whether TX CCID (1) or RX CCID (0) is meant
939 *
933 * This function needs to be called after registering all other features.
934 */
935static int dccp_feat_propagate_ccid(struct list_head *fn, u8 id, bool is_local)
936{
937 const struct ccid_dependency *table = dccp_feat_ccid_deps(id, is_local);
938 int i, rc = (table == NULL);
939
940 for (i = 0; rc == 0 && table[i].dependent_feat != DCCPF_RESERVED; i++)

--- 7 unchanged lines hidden (view full) ---

948 table[i].is_mandatory,
949 table[i].val);
950 return rc;
951}
952
953/**
954 * dccp_feat_finalise_settings - Finalise settings before starting negotiation
955 * @dp: client or listening socket (settings will be inherited)
940 * This function needs to be called after registering all other features.
941 */
942static int dccp_feat_propagate_ccid(struct list_head *fn, u8 id, bool is_local)
943{
944 const struct ccid_dependency *table = dccp_feat_ccid_deps(id, is_local);
945 int i, rc = (table == NULL);
946
947 for (i = 0; rc == 0 && table[i].dependent_feat != DCCPF_RESERVED; i++)

--- 7 unchanged lines hidden (view full) ---

955 table[i].is_mandatory,
956 table[i].val);
957 return rc;
958}
959
960/**
961 * dccp_feat_finalise_settings - Finalise settings before starting negotiation
962 * @dp: client or listening socket (settings will be inherited)
963 *
956 * This is called after all registrations (socket initialisation, sysctls, and
957 * sockopt calls), and before sending the first packet containing Change options
958 * (ie. client-Request or server-Response), to ensure internal consistency.
959 */
960int dccp_feat_finalise_settings(struct dccp_sock *dp)
961{
962 struct list_head *fn = &dp->dccps_featneg;
963 struct dccp_feat_entry *entry;

--- 315 unchanged lines hidden (view full) ---

1279/**
1280 * dccp_feat_handle_nn_established - Fast-path reception of NN options
1281 * @sk: socket of an established DCCP connection
1282 * @mandatory: whether @opt was preceded by a Mandatory option
1283 * @opt: %DCCPO_CHANGE_L | %DCCPO_CONFIRM_R (NN only)
1284 * @feat: NN number, one of %dccp_feature_numbers
1285 * @val: NN value
1286 * @len: length of @val in bytes
964 * This is called after all registrations (socket initialisation, sysctls, and
965 * sockopt calls), and before sending the first packet containing Change options
966 * (ie. client-Request or server-Response), to ensure internal consistency.
967 */
968int dccp_feat_finalise_settings(struct dccp_sock *dp)
969{
970 struct list_head *fn = &dp->dccps_featneg;
971 struct dccp_feat_entry *entry;

--- 315 unchanged lines hidden (view full) ---

1287/**
1288 * dccp_feat_handle_nn_established - Fast-path reception of NN options
1289 * @sk: socket of an established DCCP connection
1290 * @mandatory: whether @opt was preceded by a Mandatory option
1291 * @opt: %DCCPO_CHANGE_L | %DCCPO_CONFIRM_R (NN only)
1292 * @feat: NN number, one of %dccp_feature_numbers
1293 * @val: NN value
1294 * @len: length of @val in bytes
1295 *
1287 * This function combines the functionality of change_recv/confirm_recv, with
1288 * the following differences (reset codes are the same):
1289 * - cleanup after receiving the Confirm;
1290 * - values are directly activated after successful parsing;
1291 * - deliberately restricted to NN features.
1292 * The restriction to NN features is essential since SP features can have non-
1293 * predictable outcomes (depending on the remote configuration), and are inter-
1294 * dependent (CCIDs for instance cause further dependencies).

--- 79 unchanged lines hidden (view full) ---

1374 * dccp_feat_parse_options - Process Feature-Negotiation Options
1375 * @sk: for general use and used by the client during connection setup
1376 * @dreq: used by the server during connection setup
1377 * @mandatory: whether @opt was preceded by a Mandatory option
1378 * @opt: %DCCPO_CHANGE_L | %DCCPO_CHANGE_R | %DCCPO_CONFIRM_L | %DCCPO_CONFIRM_R
1379 * @feat: one of %dccp_feature_numbers
1380 * @val: value contents of @opt
1381 * @len: length of @val in bytes
1296 * This function combines the functionality of change_recv/confirm_recv, with
1297 * the following differences (reset codes are the same):
1298 * - cleanup after receiving the Confirm;
1299 * - values are directly activated after successful parsing;
1300 * - deliberately restricted to NN features.
1301 * The restriction to NN features is essential since SP features can have non-
1302 * predictable outcomes (depending on the remote configuration), and are inter-
1303 * dependent (CCIDs for instance cause further dependencies).

--- 79 unchanged lines hidden (view full) ---

1383 * dccp_feat_parse_options - Process Feature-Negotiation Options
1384 * @sk: for general use and used by the client during connection setup
1385 * @dreq: used by the server during connection setup
1386 * @mandatory: whether @opt was preceded by a Mandatory option
1387 * @opt: %DCCPO_CHANGE_L | %DCCPO_CHANGE_R | %DCCPO_CONFIRM_L | %DCCPO_CONFIRM_R
1388 * @feat: one of %dccp_feature_numbers
1389 * @val: value contents of @opt
1390 * @len: length of @val in bytes
1391 *
1382 * Returns 0 on success, a Reset code for ending the connection otherwise.
1383 */
1384int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
1385 u8 mandatory, u8 opt, u8 feat, u8 *val, u8 len)
1386{
1387 struct dccp_sock *dp = dccp_sk(sk);
1388 struct list_head *fn = dreq ? &dreq->dreq_featneg : &dp->dccps_featneg;
1389 bool server = false;

--- 162 unchanged lines hidden ---
1392 * Returns 0 on success, a Reset code for ending the connection otherwise.
1393 */
1394int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
1395 u8 mandatory, u8 opt, u8 feat, u8 *val, u8 len)
1396{
1397 struct dccp_sock *dp = dccp_sk(sk);
1398 struct list_head *fn = dreq ? &dreq->dreq_featneg : &dp->dccps_featneg;
1399 bool server = false;

--- 162 unchanged lines hidden ---