diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-12-02 02:32:35 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-02 02:32:35 -0500 |
commit | e77b8363b2ea7c0d89919547c1a8b0562f298b57 (patch) | |
tree | 9fdef240be3aeb49c012fd00d41f9ee90afe776c /net/dccp/options.c | |
parent | 75757a7d0c54f8fdd414c74a6005d275032b0115 (diff) |
dccp: Process incoming Change feature-negotiation options
This adds/replaces code for processing incoming ChangeL/R options.
The main difference is that:
* mandatory FN options are now interpreted inside the function
(there are too many individual cases to do this externally);
* the function returns an appropriate Reset code or 0,
which is then used to fill in the data for the Reset packet.
Old code, which is no longer used or referenced, has been removed.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r-- | net/dccp/options.c | 23 |
1 files changed, 8 insertions, 15 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c index 86c7a20d39b2..2c444c199725 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -135,22 +135,13 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
135 | (unsigned long long)opt_recv->dccpor_ndp); | 135 | (unsigned long long)opt_recv->dccpor_ndp); |
136 | break; | 136 | break; |
137 | case DCCPO_CHANGE_L: | 137 | case DCCPO_CHANGE_L: |
138 | /* fall through */ | ||
139 | case DCCPO_CHANGE_R: | 138 | case DCCPO_CHANGE_R: |
140 | if (pkt_type == DCCP_PKT_DATA) | 139 | if (pkt_type == DCCP_PKT_DATA) |
141 | break; | 140 | break; |
142 | if (len < 2) | 141 | rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, |
143 | goto out_invalid_option; | 142 | *value, value + 1, len - 1); |
144 | rc = dccp_feat_change_recv(sk, opt, *value, value + 1, | 143 | if (rc) |
145 | len - 1); | 144 | goto out_featneg_failed; |
146 | /* | ||
147 | * When there is a change error, change_recv is | ||
148 | * responsible for dealing with it. i.e. reply with an | ||
149 | * empty confirm. | ||
150 | * If the change was mandatory, then we need to die. | ||
151 | */ | ||
152 | if (rc && mandatory) | ||
153 | goto out_invalid_option; | ||
154 | break; | 145 | break; |
155 | case DCCPO_CONFIRM_L: | 146 | case DCCPO_CONFIRM_L: |
156 | /* fall through */ | 147 | /* fall through */ |
@@ -292,8 +283,10 @@ out_nonsensical_length: | |||
292 | 283 | ||
293 | out_invalid_option: | 284 | out_invalid_option: |
294 | DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT); | 285 | DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT); |
295 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR; | 286 | rc = DCCP_RESET_CODE_OPTION_ERROR; |
296 | DCCP_WARN("DCCP(%p): invalid option %d, len=%d", sk, opt, len); | 287 | out_featneg_failed: |
288 | DCCP_WARN("DCCP(%p): Option %d (len=%d) error=%u\n", sk, opt, len, rc); | ||
289 | DCCP_SKB_CB(skb)->dccpd_reset_code = rc; | ||
297 | DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt; | 290 | DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt; |
298 | DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0; | 291 | DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0; |
299 | DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0; | 292 | DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0; |