Skip to content

Commit

Permalink
dccp: Support for exchanging of NN options in established state
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Gerrit Renker committed Sep 4, 2008
1 parent 624a965 commit 4861a35
Showing 1 changed file with 96 additions and 0 deletions.
96 changes: 96 additions & 0 deletions net/dccp/feat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,93 @@ static u8 dccp_feat_confirm_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
: DCCP_RESET_CODE_OPTION_ERROR;
}

/**
* dccp_feat_handle_nn_established - Fast-path reception of NN options
* @sk: socket of an established DCCP connection
* @mandatory: whether @opt was preceded by a Mandatory option
* @opt: %DCCPO_CHANGE_L | %DCCPO_CONFIRM_R (NN only)
* @feat: NN number, one of %dccp_feature_numbers
* @val: NN value
* @len: length of @val in bytes
* This function combines the functionality of change_recv/confirm_recv, with
* the following differences (reset codes are the same):
* - cleanup after receiving the Confirm;
* - values are directly activated after successful parsing;
* - deliberately restricted to NN features.
* The restriction to NN features is essential since SP features can have non-
* predictable outcomes (depending on the remote configuration), and are inter-
* dependent (CCIDs for instance cause further dependencies).
*/
static u8 dccp_feat_handle_nn_established(struct sock *sk, u8 mandatory, u8 opt,
u8 feat, u8 *val, u8 len)
{
struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
const bool local = (opt == DCCPO_CONFIRM_R);
struct dccp_feat_entry *entry;
u8 type = dccp_feat_type(feat);
dccp_feat_val fval;

dccp_feat_print_opt(opt, feat, val, len, mandatory);

/* Ignore non-mandatory unknown and non-NN features */
if (type == FEAT_UNKNOWN) {
if (local && !mandatory)
return 0;
goto fast_path_unknown;
} else if (type != FEAT_NN) {
return 0;
}

/*
* We don't accept empty Confirms, since in fast-path feature
* negotiation the values are enabled immediately after sending
* the Change option.
* Empty Changes on the other hand are invalid (RFC 4340, 6.1).
*/
if (len == 0 || len > sizeof(fval.nn))
goto fast_path_unknown;

if (opt == DCCPO_CHANGE_L) {
fval.nn = dccp_decode_value_var(val, len);
if (!dccp_feat_is_valid_nn_val(feat, fval.nn))
goto fast_path_unknown;

if (dccp_feat_push_confirm(fn, feat, local, &fval) ||
dccp_feat_activate(sk, feat, local, &fval))
return DCCP_RESET_CODE_TOO_BUSY;

/* set the `Ack Pending' flag to piggyback a Confirm */
inet_csk_schedule_ack(sk);

} else if (opt == DCCPO_CONFIRM_R) {
entry = dccp_feat_list_lookup(fn, feat, local);
if (entry == NULL || entry->state != FEAT_CHANGING)
return 0;

fval.nn = dccp_decode_value_var(val, len);
if (fval.nn != entry->val.nn) {
DCCP_WARN("Bogus Confirm for non-existing value\n");
goto fast_path_failed;
}

/* It has been confirmed - so remove the entry */
dccp_feat_list_pop(entry);

} else {
DCCP_WARN("Received illegal option %u\n", opt);
goto fast_path_failed;
}
return 0;

fast_path_unknown:
if (!mandatory)
return dccp_push_empty_confirm(fn, feat, local);

fast_path_failed:
return mandatory ? DCCP_RESET_CODE_MANDATORY_ERROR
: DCCP_RESET_CODE_OPTION_ERROR;
}

/**
* dccp_feat_parse_options - Process Feature-Negotiation Options
* @sk: for general use and used by the client during connection setup
Expand Down Expand Up @@ -1281,6 +1368,15 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
return dccp_feat_confirm_recv(fn, mandatory, opt, feat,
val, len, server);
}
break;
/*
* Support for exchanging NN options on an established connection
* This is currently restricted to Ack Ratio (RFC 4341, 6.1.2)
*/
case DCCP_OPEN:
case DCCP_PARTOPEN:
return dccp_feat_handle_nn_established(sk, mandatory, opt, feat,
val, len);
}
return 0; /* ignore FN options in all other states */
}
Expand Down

0 comments on commit 4861a35

Please sign in to comment.