aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r--net/dccp/options.c291
1 files changed, 209 insertions, 82 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 0a76426c9aea..e9feb2a0c770 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -21,19 +21,23 @@
21#include "ackvec.h" 21#include "ackvec.h"
22#include "ccid.h" 22#include "ccid.h"
23#include "dccp.h" 23#include "dccp.h"
24#include "feat.h"
24 25
25/* stores the default values for new connection. may be changed with sysctl */ 26int dccp_feat_default_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;
26static const struct dccp_options dccpo_default_values = { 27int dccp_feat_default_rx_ccid = DCCPF_INITIAL_CCID;
27 .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, 28int dccp_feat_default_tx_ccid = DCCPF_INITIAL_CCID;
28 .dccpo_rx_ccid = DCCPF_INITIAL_CCID, 29int dccp_feat_default_ack_ratio = DCCPF_INITIAL_ACK_RATIO;
29 .dccpo_tx_ccid = DCCPF_INITIAL_CCID, 30int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
30 .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR, 31int dccp_feat_default_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT;
31 .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT,
32};
33 32
34void dccp_options_init(struct dccp_options *dccpo) 33void dccp_minisock_init(struct dccp_minisock *dmsk)
35{ 34{
36 memcpy(dccpo, &dccpo_default_values, sizeof(*dccpo)); 35 dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window;
36 dmsk->dccpms_rx_ccid = dccp_feat_default_rx_ccid;
37 dmsk->dccpms_tx_ccid = dccp_feat_default_tx_ccid;
38 dmsk->dccpms_ack_ratio = dccp_feat_default_ack_ratio;
39 dmsk->dccpms_send_ack_vector = dccp_feat_default_send_ack_vector;
40 dmsk->dccpms_send_ndp_count = dccp_feat_default_send_ndp_count;
37} 41}
38 42
39static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len) 43static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
@@ -69,9 +73,12 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
69 unsigned char opt, len; 73 unsigned char opt, len;
70 unsigned char *value; 74 unsigned char *value;
71 u32 elapsed_time; 75 u32 elapsed_time;
76 int rc;
77 int mandatory = 0;
72 78
73 memset(opt_recv, 0, sizeof(*opt_recv)); 79 memset(opt_recv, 0, sizeof(*opt_recv));
74 80
81 opt = len = 0;
75 while (opt_ptr != opt_end) { 82 while (opt_ptr != opt_end) {
76 opt = *opt_ptr++; 83 opt = *opt_ptr++;
77 len = 0; 84 len = 0;
@@ -100,6 +107,12 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
100 switch (opt) { 107 switch (opt) {
101 case DCCPO_PADDING: 108 case DCCPO_PADDING:
102 break; 109 break;
110 case DCCPO_MANDATORY:
111 if (mandatory)
112 goto out_invalid_option;
113 if (pkt_type != DCCP_PKT_DATA)
114 mandatory = 1;
115 break;
103 case DCCPO_NDP_COUNT: 116 case DCCPO_NDP_COUNT:
104 if (len > 3) 117 if (len > 3)
105 goto out_invalid_option; 118 goto out_invalid_option;
@@ -108,12 +121,37 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
108 dccp_pr_debug("%sNDP count=%d\n", debug_prefix, 121 dccp_pr_debug("%sNDP count=%d\n", debug_prefix,
109 opt_recv->dccpor_ndp); 122 opt_recv->dccpor_ndp);
110 break; 123 break;
124 case DCCPO_CHANGE_L:
125 /* fall through */
126 case DCCPO_CHANGE_R:
127 if (len < 2)
128 goto out_invalid_option;
129 rc = dccp_feat_change_recv(sk, opt, *value, value + 1,
130 len - 1);
131 /*
132 * When there is a change error, change_recv is
133 * responsible for dealing with it. i.e. reply with an
134 * empty confirm.
135 * If the change was mandatory, then we need to die.
136 */
137 if (rc && mandatory)
138 goto out_invalid_option;
139 break;
140 case DCCPO_CONFIRM_L:
141 /* fall through */
142 case DCCPO_CONFIRM_R:
143 if (len < 2)
144 goto out_invalid_option;
145 if (dccp_feat_confirm_recv(sk, opt, *value,
146 value + 1, len - 1))
147 goto out_invalid_option;
148 break;
111 case DCCPO_ACK_VECTOR_0: 149 case DCCPO_ACK_VECTOR_0:
112 case DCCPO_ACK_VECTOR_1: 150 case DCCPO_ACK_VECTOR_1:
113 if (pkt_type == DCCP_PKT_DATA) 151 if (pkt_type == DCCP_PKT_DATA)
114 continue; 152 break;
115 153
116 if (dp->dccps_options.dccpo_send_ack_vector && 154 if (dccp_msk(sk)->dccpms_send_ack_vector &&
117 dccp_ackvec_parse(sk, skb, opt, value, len)) 155 dccp_ackvec_parse(sk, skb, opt, value, len))
118 goto out_invalid_option; 156 goto out_invalid_option;
119 break; 157 break;
@@ -121,7 +159,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
121 if (len != 4) 159 if (len != 4)
122 goto out_invalid_option; 160 goto out_invalid_option;
123 161
124 opt_recv->dccpor_timestamp = ntohl(*(u32 *)value); 162 opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value);
125 163
126 dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; 164 dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
127 dccp_timestamp(sk, &dp->dccps_timestamp_time); 165 dccp_timestamp(sk, &dp->dccps_timestamp_time);
@@ -135,7 +173,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
135 if (len != 4 && len != 6 && len != 8) 173 if (len != 4 && len != 6 && len != 8)
136 goto out_invalid_option; 174 goto out_invalid_option;
137 175
138 opt_recv->dccpor_timestamp_echo = ntohl(*(u32 *)value); 176 opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value);
139 177
140 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ", 178 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ",
141 debug_prefix, 179 debug_prefix,
@@ -149,9 +187,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
149 break; 187 break;
150 188
151 if (len == 6) 189 if (len == 6)
152 elapsed_time = ntohs(*(u16 *)(value + 4)); 190 elapsed_time = ntohs(*(__be16 *)(value + 4));
153 else 191 else
154 elapsed_time = ntohl(*(u32 *)(value + 4)); 192 elapsed_time = ntohl(*(__be32 *)(value + 4));
155 193
156 /* Give precedence to the biggest ELAPSED_TIME */ 194 /* Give precedence to the biggest ELAPSED_TIME */
157 if (elapsed_time > opt_recv->dccpor_elapsed_time) 195 if (elapsed_time > opt_recv->dccpor_elapsed_time)
@@ -165,9 +203,9 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
165 continue; 203 continue;
166 204
167 if (len == 2) 205 if (len == 2)
168 elapsed_time = ntohs(*(u16 *)value); 206 elapsed_time = ntohs(*(__be16 *)value);
169 else 207 else
170 elapsed_time = ntohl(*(u32 *)value); 208 elapsed_time = ntohl(*(__be32 *)value);
171 209
172 if (elapsed_time > opt_recv->dccpor_elapsed_time) 210 if (elapsed_time > opt_recv->dccpor_elapsed_time)
173 opt_recv->dccpor_elapsed_time = elapsed_time; 211 opt_recv->dccpor_elapsed_time = elapsed_time;
@@ -208,8 +246,15 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
208 sk, opt, len); 246 sk, opt, len);
209 break; 247 break;
210 } 248 }
249
250 if (opt != DCCPO_MANDATORY)
251 mandatory = 0;
211 } 252 }
212 253
254 /* mandatory was the last byte in option list -> reset connection */
255 if (mandatory)
256 goto out_invalid_option;
257
213 return 0; 258 return 0;
214 259
215out_invalid_option: 260out_invalid_option:
@@ -219,6 +264,8 @@ out_invalid_option:
219 return -1; 264 return -1;
220} 265}
221 266
267EXPORT_SYMBOL_GPL(dccp_parse_options);
268
222static void dccp_encode_value_var(const u32 value, unsigned char *to, 269static void dccp_encode_value_var(const u32 value, unsigned char *to,
223 const unsigned int len) 270 const unsigned int len)
224{ 271{
@@ -237,17 +284,14 @@ static inline int dccp_ndp_len(const int ndp)
237 return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3; 284 return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3;
238} 285}
239 286
240void dccp_insert_option(struct sock *sk, struct sk_buff *skb, 287int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
241 const unsigned char option, 288 const unsigned char option,
242 const void *value, const unsigned char len) 289 const void *value, const unsigned char len)
243{ 290{
244 unsigned char *to; 291 unsigned char *to;
245 292
246 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN) { 293 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
247 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " 294 return -1;
248 "%d option!\n", option);
249 return;
250 }
251 295
252 DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2; 296 DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
253 297
@@ -256,11 +300,12 @@ void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
256 *to++ = len + 2; 300 *to++ = len + 2;
257 301
258 memcpy(to, value, len); 302 memcpy(to, value, len);
303 return 0;
259} 304}
260 305
261EXPORT_SYMBOL_GPL(dccp_insert_option); 306EXPORT_SYMBOL_GPL(dccp_insert_option);
262 307
263static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb) 308static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
264{ 309{
265 struct dccp_sock *dp = dccp_sk(sk); 310 struct dccp_sock *dp = dccp_sk(sk);
266 int ndp = dp->dccps_ndp_count; 311 int ndp = dp->dccps_ndp_count;
@@ -276,7 +321,7 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
276 const int len = ndp_len + 2; 321 const int len = ndp_len + 2;
277 322
278 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) 323 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
279 return; 324 return -1;
280 325
281 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 326 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
282 327
@@ -285,6 +330,8 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
285 *ptr++ = len; 330 *ptr++ = len;
286 dccp_encode_value_var(ndp, ptr, ndp_len); 331 dccp_encode_value_var(ndp, ptr, ndp_len);
287 } 332 }
333
334 return 0;
288} 335}
289 336
290static inline int dccp_elapsed_time_len(const u32 elapsed_time) 337static inline int dccp_elapsed_time_len(const u32 elapsed_time)
@@ -292,27 +339,18 @@ static inline int dccp_elapsed_time_len(const u32 elapsed_time)
292 return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4; 339 return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
293} 340}
294 341
295void dccp_insert_option_elapsed_time(struct sock *sk, 342int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb,
296 struct sk_buff *skb, 343 u32 elapsed_time)
297 u32 elapsed_time)
298{ 344{
299#ifdef CONFIG_IP_DCCP_DEBUG
300 struct dccp_sock *dp = dccp_sk(sk);
301 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
302 "CLIENT TX opt: " : "server TX opt: ";
303#endif
304 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 345 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
305 const int len = 2 + elapsed_time_len; 346 const int len = 2 + elapsed_time_len;
306 unsigned char *to; 347 unsigned char *to;
307 348
308 if (elapsed_time_len == 0) 349 if (elapsed_time_len == 0)
309 return; 350 return 0;
310 351
311 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { 352 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
312 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to " 353 return -1;
313 "insert elapsed time!\n");
314 return;
315 }
316 354
317 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 355 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
318 356
@@ -321,17 +359,14 @@ void dccp_insert_option_elapsed_time(struct sock *sk,
321 *to++ = len; 359 *to++ = len;
322 360
323 if (elapsed_time_len == 2) { 361 if (elapsed_time_len == 2) {
324 const u16 var16 = htons((u16)elapsed_time); 362 const __be16 var16 = htons((u16)elapsed_time);
325 memcpy(to, &var16, 2); 363 memcpy(to, &var16, 2);
326 } else { 364 } else {
327 const u32 var32 = htonl(elapsed_time); 365 const __be32 var32 = htonl(elapsed_time);
328 memcpy(to, &var32, 4); 366 memcpy(to, &var32, 4);
329 } 367 }
330 368
331 dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n", 369 return 0;
332 debug_prefix, elapsed_time,
333 len,
334 (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
335} 370}
336 371
337EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); 372EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
@@ -352,32 +387,27 @@ void dccp_timestamp(const struct sock *sk, struct timeval *tv)
352 387
353EXPORT_SYMBOL_GPL(dccp_timestamp); 388EXPORT_SYMBOL_GPL(dccp_timestamp);
354 389
355void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) 390int dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
356{ 391{
357 struct timeval tv; 392 struct timeval tv;
358 u32 now; 393 __be32 now;
359 394
360 dccp_timestamp(sk, &tv); 395 dccp_timestamp(sk, &tv);
361 now = timeval_usecs(&tv) / 10; 396 now = htonl(timeval_usecs(&tv) / 10);
362 /* yes this will overflow but that is the point as we want a 397 /* yes this will overflow but that is the point as we want a
363 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */ 398 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
364 399
365 now = htonl(now); 400 return dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
366 dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
367} 401}
368 402
369EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp); 403EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);
370 404
371static void dccp_insert_option_timestamp_echo(struct sock *sk, 405static int dccp_insert_option_timestamp_echo(struct sock *sk,
372 struct sk_buff *skb) 406 struct sk_buff *skb)
373{ 407{
374 struct dccp_sock *dp = dccp_sk(sk); 408 struct dccp_sock *dp = dccp_sk(sk);
375#ifdef CONFIG_IP_DCCP_DEBUG
376 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
377 "CLIENT TX opt: " : "server TX opt: ";
378#endif
379 struct timeval now; 409 struct timeval now;
380 u32 tstamp_echo; 410 __be32 tstamp_echo;
381 u32 elapsed_time; 411 u32 elapsed_time;
382 int len, elapsed_time_len; 412 int len, elapsed_time_len;
383 unsigned char *to; 413 unsigned char *to;
@@ -387,11 +417,8 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
387 elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 417 elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
388 len = 6 + elapsed_time_len; 418 len = 6 + elapsed_time_len;
389 419
390 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { 420 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
391 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " 421 return -1;
392 "timestamp echo!\n");
393 return;
394 }
395 422
396 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 423 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
397 424
@@ -402,51 +429,149 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
402 tstamp_echo = htonl(dp->dccps_timestamp_echo); 429 tstamp_echo = htonl(dp->dccps_timestamp_echo);
403 memcpy(to, &tstamp_echo, 4); 430 memcpy(to, &tstamp_echo, 4);
404 to += 4; 431 to += 4;
405 432
406 if (elapsed_time_len == 2) { 433 if (elapsed_time_len == 2) {
407 const u16 var16 = htons((u16)elapsed_time); 434 const __be16 var16 = htons((u16)elapsed_time);
408 memcpy(to, &var16, 2); 435 memcpy(to, &var16, 2);
409 } else if (elapsed_time_len == 4) { 436 } else if (elapsed_time_len == 4) {
410 const u32 var32 = htonl(elapsed_time); 437 const __be32 var32 = htonl(elapsed_time);
411 memcpy(to, &var32, 4); 438 memcpy(to, &var32, 4);
412 } 439 }
413 440
414 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, seqno=%llu\n",
415 debug_prefix, dp->dccps_timestamp_echo,
416 len,
417 (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
418
419 dp->dccps_timestamp_echo = 0; 441 dp->dccps_timestamp_echo = 0;
420 dp->dccps_timestamp_time.tv_sec = 0; 442 dp->dccps_timestamp_time.tv_sec = 0;
421 dp->dccps_timestamp_time.tv_usec = 0; 443 dp->dccps_timestamp_time.tv_usec = 0;
444 return 0;
422} 445}
423 446
424void dccp_insert_options(struct sock *sk, struct sk_buff *skb) 447static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
448 u8 *val, u8 len)
449{
450 u8 *to;
451
452 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) {
453 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small"
454 " to insert feature %d option!\n", feat);
455 return -1;
456 }
457
458 DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3;
459
460 to = skb_push(skb, len + 3);
461 *to++ = type;
462 *to++ = len + 3;
463 *to++ = feat;
464
465 if (len)
466 memcpy(to, val, len);
467 dccp_pr_debug("option %d feat %d len %d\n", type, feat, len);
468
469 return 0;
470}
471
472static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)
425{ 473{
426 struct dccp_sock *dp = dccp_sk(sk); 474 struct dccp_sock *dp = dccp_sk(sk);
475 struct dccp_minisock *dmsk = dccp_msk(sk);
476 struct dccp_opt_pend *opt, *next;
477 int change = 0;
478
479 /* confirm any options [NN opts] */
480 list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {
481 dccp_insert_feat_opt(skb, opt->dccpop_type,
482 opt->dccpop_feat, opt->dccpop_val,
483 opt->dccpop_len);
484 /* fear empty confirms */
485 if (opt->dccpop_val)
486 kfree(opt->dccpop_val);
487 kfree(opt);
488 }
489 INIT_LIST_HEAD(&dmsk->dccpms_conf);
490
491 /* see which features we need to send */
492 list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
493 /* see if we need to send any confirm */
494 if (opt->dccpop_sc) {
495 dccp_insert_feat_opt(skb, opt->dccpop_type + 1,
496 opt->dccpop_feat,
497 opt->dccpop_sc->dccpoc_val,
498 opt->dccpop_sc->dccpoc_len);
499
500 BUG_ON(!opt->dccpop_sc->dccpoc_val);
501 kfree(opt->dccpop_sc->dccpoc_val);
502 kfree(opt->dccpop_sc);
503 opt->dccpop_sc = NULL;
504 }
505
506 /* any option not confirmed, re-send it */
507 if (!opt->dccpop_conf) {
508 dccp_insert_feat_opt(skb, opt->dccpop_type,
509 opt->dccpop_feat, opt->dccpop_val,
510 opt->dccpop_len);
511 change++;
512 }
513 }
514
515 /* Retransmit timer.
516 * If this is the master listening sock, we don't set a timer on it. It
517 * should be fine because if the dude doesn't receive our RESPONSE
518 * [which will contain the CHANGE] he will send another REQUEST which
519 * will "retrnasmit" the change.
520 */
521 if (change && dp->dccps_role != DCCP_ROLE_LISTEN) {
522 dccp_pr_debug("reset feat negotiation timer %p\n", sk);
523
524 /* XXX don't reset the timer on re-transmissions. I.e. reset it
525 * only when sending new stuff i guess. Currently the timer
526 * never backs off because on re-transmission it just resets it!
527 */
528 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
529 inet_csk(sk)->icsk_rto, DCCP_RTO_MAX);
530 }
531
532 return 0;
533}
534
535int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
536{
537 struct dccp_sock *dp = dccp_sk(sk);
538 struct dccp_minisock *dmsk = dccp_msk(sk);
427 539
428 DCCP_SKB_CB(skb)->dccpd_opt_len = 0; 540 DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
429 541
430 if (dp->dccps_options.dccpo_send_ndp_count) 542 if (dmsk->dccpms_send_ndp_count &&
431 dccp_insert_option_ndp(sk, skb); 543 dccp_insert_option_ndp(sk, skb))
544 return -1;
432 545
433 if (!dccp_packet_without_ack(skb)) { 546 if (!dccp_packet_without_ack(skb)) {
434 if (dp->dccps_options.dccpo_send_ack_vector && 547 if (dmsk->dccpms_send_ack_vector &&
435 dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) 548 dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
436 dccp_insert_option_ackvec(sk, skb); 549 dccp_insert_option_ackvec(sk, skb))
437 if (dp->dccps_timestamp_echo != 0) 550 return -1;
438 dccp_insert_option_timestamp_echo(sk, skb); 551
552 if (dp->dccps_timestamp_echo != 0 &&
553 dccp_insert_option_timestamp_echo(sk, skb))
554 return -1;
439 } 555 }
440 556
441 if (dp->dccps_hc_rx_insert_options) { 557 if (dp->dccps_hc_rx_insert_options) {
442 ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb); 558 if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb))
559 return -1;
443 dp->dccps_hc_rx_insert_options = 0; 560 dp->dccps_hc_rx_insert_options = 0;
444 } 561 }
445 if (dp->dccps_hc_tx_insert_options) { 562 if (dp->dccps_hc_tx_insert_options) {
446 ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb); 563 if (ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb))
564 return -1;
447 dp->dccps_hc_tx_insert_options = 0; 565 dp->dccps_hc_tx_insert_options = 0;
448 } 566 }
449 567
568 /* Feature negotiation */
569 /* Data packets can't do feat negotiation */
570 if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&
571 DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&
572 dccp_insert_options_feat(sk, skb))
573 return -1;
574
450 /* XXX: insert other options when appropriate */ 575 /* XXX: insert other options when appropriate */
451 576
452 if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) { 577 if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) {
@@ -459,4 +584,6 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
459 DCCP_SKB_CB(skb)->dccpd_opt_len += padding; 584 DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
460 } 585 }
461 } 586 }
587
588 return 0;
462} 589}