Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 122106
b: refs/heads/master
c: 8c862c2
h: refs/heads/master
v: v3
  • Loading branch information
Gerrit Renker authored and David S. Miller committed Nov 24, 2008
1 parent ba1b0ad commit 34ddc1c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 61 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d371056695ef993d36c57b73d654e66080377a9c
refs/heads/master: 8c862c23e2563e6aedfc6c4aa6827cadb83f2414
2 changes: 2 additions & 0 deletions trunk/net/dccp/feat.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,6 @@ extern void dccp_encode_value_var(const u64 value, u8 *to, const u8 len);
extern u64 dccp_decode_value_var(const u8 *bf, const u8 len);

extern int dccp_insert_option_mandatory(struct sk_buff *skb);
extern int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
u8 *val, u8 len, bool repeat_first);
#endif /* _DCCP_FEAT_H */
91 changes: 31 additions & 60 deletions trunk/net/dccp/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,23 +482,46 @@ int dccp_insert_option_mandatory(struct sk_buff *skb)
return 0;
}

static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
u8 *val, u8 len)
/**
* dccp_insert_fn_opt - Insert single Feature-Negotiation option into @skb
* @type: %DCCPO_CHANGE_L, %DCCPO_CHANGE_R, %DCCPO_CONFIRM_L, %DCCPO_CONFIRM_R
* @feat: one out of %dccp_feature_numbers
* @val: NN value or SP array (preferred element first) to copy
* @len: true length of @val in bytes (excluding first element repetition)
* @repeat_first: whether to copy the first element of @val twice
* The last argument is used to construct Confirm options, where the preferred
* value and the preference list appear separately (RFC 4340, 6.3.1). Preference
* lists are kept such that the preferred entry is always first, so we only need
* to copy twice, and avoid the overhead of cloning into a bigger array.
*/
int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
u8 *val, u8 len, bool repeat_first)
{
u8 *to;
u8 tot_len, *to;

if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) {
DCCP_WARN("packet too small for feature %d option!\n", feat);
/* take the `Feature' field and possible repetition into account */
if (len > (DCCP_SINGLE_OPT_MAXLEN - 2)) {
DCCP_WARN("length %u for feature %u too large\n", len, feat);
return -1;
}

DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3;
if (unlikely(val == NULL || len == 0))
len = repeat_first = 0;
tot_len = 3 + repeat_first + len;

if (DCCP_SKB_CB(skb)->dccpd_opt_len + tot_len > DCCP_MAX_OPT_LEN) {
DCCP_WARN("packet too small for feature %d option!\n", feat);
return -1;
}
DCCP_SKB_CB(skb)->dccpd_opt_len += tot_len;

to = skb_push(skb, len + 3);
to = skb_push(skb, tot_len);
*to++ = type;
*to++ = len + 3;
*to++ = tot_len;
*to++ = feat;

if (repeat_first)
*to++ = *val;
if (len)
memcpy(to, val, len);

Expand All @@ -508,51 +531,6 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
return 0;
}

static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)
{
struct dccp_minisock *dmsk = dccp_msk(sk);
struct dccp_opt_pend *opt, *next;
int change = 0;

/* confirm any options [NN opts] */
list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {
dccp_insert_feat_opt(skb, opt->dccpop_type,
opt->dccpop_feat, opt->dccpop_val,
opt->dccpop_len);
/* fear empty confirms */
if (opt->dccpop_val)
kfree(opt->dccpop_val);
kfree(opt);
}
INIT_LIST_HEAD(&dmsk->dccpms_conf);

/* see which features we need to send */
list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
/* see if we need to send any confirm */
if (opt->dccpop_sc) {
dccp_insert_feat_opt(skb, opt->dccpop_type + 1,
opt->dccpop_feat,
opt->dccpop_sc->dccpoc_val,
opt->dccpop_sc->dccpoc_len);

BUG_ON(!opt->dccpop_sc->dccpoc_val);
kfree(opt->dccpop_sc->dccpoc_val);
kfree(opt->dccpop_sc);
opt->dccpop_sc = NULL;
}

/* any option not confirmed, re-send it */
if (!opt->dccpop_conf) {
dccp_insert_feat_opt(skb, opt->dccpop_type,
opt->dccpop_feat, opt->dccpop_val,
opt->dccpop_len);
change++;
}
}

return 0;
}

/* The length of all options needs to be a multiple of 4 (5.8) */
static void dccp_insert_option_padding(struct sk_buff *skb)
{
Expand Down Expand Up @@ -589,13 +567,6 @@ int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
dp->dccps_hc_rx_insert_options = 0;
}

/* Feature negotiation */
/* Data packets can't do feat negotiation */
if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&
DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&
dccp_insert_options_feat(sk, skb))
return -1;

/*
* Obtain RTT sample from Request/Response exchange.
* This is currently used in CCID 3 initialisation.
Expand Down

0 comments on commit 34ddc1c

Please sign in to comment.