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.c109
1 files changed, 46 insertions, 63 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 0161a18e739a..da1676016484 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -283,17 +283,14 @@ static inline int dccp_ndp_len(const int ndp)
283 return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3; 283 return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3;
284} 284}
285 285
286void dccp_insert_option(struct sock *sk, struct sk_buff *skb, 286int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
287 const unsigned char option, 287 const unsigned char option,
288 const void *value, const unsigned char len) 288 const void *value, const unsigned char len)
289{ 289{
290 unsigned char *to; 290 unsigned char *to;
291 291
292 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN) { 292 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
293 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " 293 return -1;
294 "%d option!\n", option);
295 return;
296 }
297 294
298 DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2; 295 DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
299 296
@@ -302,11 +299,12 @@ void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
302 *to++ = len + 2; 299 *to++ = len + 2;
303 300
304 memcpy(to, value, len); 301 memcpy(to, value, len);
302 return 0;
305} 303}
306 304
307EXPORT_SYMBOL_GPL(dccp_insert_option); 305EXPORT_SYMBOL_GPL(dccp_insert_option);
308 306
309static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb) 307static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
310{ 308{
311 struct dccp_sock *dp = dccp_sk(sk); 309 struct dccp_sock *dp = dccp_sk(sk);
312 int ndp = dp->dccps_ndp_count; 310 int ndp = dp->dccps_ndp_count;
@@ -322,7 +320,7 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
322 const int len = ndp_len + 2; 320 const int len = ndp_len + 2;
323 321
324 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) 322 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
325 return; 323 return -1;
326 324
327 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 325 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
328 326
@@ -331,6 +329,8 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
331 *ptr++ = len; 329 *ptr++ = len;
332 dccp_encode_value_var(ndp, ptr, ndp_len); 330 dccp_encode_value_var(ndp, ptr, ndp_len);
333 } 331 }
332
333 return 0;
334} 334}
335 335
336static inline int dccp_elapsed_time_len(const u32 elapsed_time) 336static inline int dccp_elapsed_time_len(const u32 elapsed_time)
@@ -338,27 +338,18 @@ static inline int dccp_elapsed_time_len(const u32 elapsed_time)
338 return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4; 338 return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
339} 339}
340 340
341void dccp_insert_option_elapsed_time(struct sock *sk, 341int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb,
342 struct sk_buff *skb, 342 u32 elapsed_time)
343 u32 elapsed_time)
344{ 343{
345#ifdef CONFIG_IP_DCCP_DEBUG
346 struct dccp_sock *dp = dccp_sk(sk);
347 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
348 "CLIENT TX opt: " : "server TX opt: ";
349#endif
350 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 344 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
351 const int len = 2 + elapsed_time_len; 345 const int len = 2 + elapsed_time_len;
352 unsigned char *to; 346 unsigned char *to;
353 347
354 if (elapsed_time_len == 0) 348 if (elapsed_time_len == 0)
355 return; 349 return 0;
356 350
357 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { 351 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
358 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to " 352 return -1;
359 "insert elapsed time!\n");
360 return;
361 }
362 353
363 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 354 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
364 355
@@ -374,10 +365,7 @@ void dccp_insert_option_elapsed_time(struct sock *sk,
374 memcpy(to, &var32, 4); 365 memcpy(to, &var32, 4);
375 } 366 }
376 367
377 dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n", 368 return 0;
378 debug_prefix, elapsed_time,
379 len,
380 (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
381} 369}
382 370
383EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); 371EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
@@ -398,7 +386,7 @@ void dccp_timestamp(const struct sock *sk, struct timeval *tv)
398 386
399EXPORT_SYMBOL_GPL(dccp_timestamp); 387EXPORT_SYMBOL_GPL(dccp_timestamp);
400 388
401void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) 389int dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
402{ 390{
403 struct timeval tv; 391 struct timeval tv;
404 __be32 now; 392 __be32 now;
@@ -408,19 +396,15 @@ void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
408 /* yes this will overflow but that is the point as we want a 396 /* yes this will overflow but that is the point as we want a
409 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */ 397 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
410 398
411 dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now)); 399 return dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
412} 400}
413 401
414EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp); 402EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);
415 403
416static void dccp_insert_option_timestamp_echo(struct sock *sk, 404static int dccp_insert_option_timestamp_echo(struct sock *sk,
417 struct sk_buff *skb) 405 struct sk_buff *skb)
418{ 406{
419 struct dccp_sock *dp = dccp_sk(sk); 407 struct dccp_sock *dp = dccp_sk(sk);
420#ifdef CONFIG_IP_DCCP_DEBUG
421 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
422 "CLIENT TX opt: " : "server TX opt: ";
423#endif
424 struct timeval now; 408 struct timeval now;
425 __be32 tstamp_echo; 409 __be32 tstamp_echo;
426 u32 elapsed_time; 410 u32 elapsed_time;
@@ -432,11 +416,8 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
432 elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 416 elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
433 len = 6 + elapsed_time_len; 417 len = 6 + elapsed_time_len;
434 418
435 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { 419 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
436 LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " 420 return -1;
437 "timestamp echo!\n");
438 return;
439 }
440 421
441 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 422 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
442 423
@@ -456,14 +437,10 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
456 memcpy(to, &var32, 4); 437 memcpy(to, &var32, 4);
457 } 438 }
458 439
459 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, seqno=%llu\n",
460 debug_prefix, dp->dccps_timestamp_echo,
461 len,
462 (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
463
464 dp->dccps_timestamp_echo = 0; 440 dp->dccps_timestamp_echo = 0;
465 dp->dccps_timestamp_time.tv_sec = 0; 441 dp->dccps_timestamp_time.tv_sec = 0;
466 dp->dccps_timestamp_time.tv_usec = 0; 442 dp->dccps_timestamp_time.tv_usec = 0;
443 return 0;
467} 444}
468 445
469static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, 446static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
@@ -491,7 +468,7 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
491 return 0; 468 return 0;
492} 469}
493 470
494static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb) 471static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)
495{ 472{
496 struct dccp_sock *dp = dccp_sk(sk); 473 struct dccp_sock *dp = dccp_sk(sk);
497 struct dccp_opt_pend *opt, *next; 474 struct dccp_opt_pend *opt, *next;
@@ -551,44 +528,48 @@ static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb)
551 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, 528 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
552 inet_csk(sk)->icsk_rto, DCCP_RTO_MAX); 529 inet_csk(sk)->icsk_rto, DCCP_RTO_MAX);
553 } 530 }
531
532 return 0;
554} 533}
555 534
556void dccp_insert_options(struct sock *sk, struct sk_buff *skb) 535int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
557{ 536{
558 struct dccp_sock *dp = dccp_sk(sk); 537 struct dccp_sock *dp = dccp_sk(sk);
559 538
560 DCCP_SKB_CB(skb)->dccpd_opt_len = 0; 539 DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
561 540
562 if (dp->dccps_options.dccpo_send_ndp_count) 541 if (dp->dccps_options.dccpo_send_ndp_count &&
563 dccp_insert_option_ndp(sk, skb); 542 dccp_insert_option_ndp(sk, skb))
543 return -1;
564 544
565 if (!dccp_packet_without_ack(skb)) { 545 if (!dccp_packet_without_ack(skb)) {
566 if (dp->dccps_options.dccpo_send_ack_vector && 546 if (dp->dccps_options.dccpo_send_ack_vector &&
567 dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) 547 dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
568 dccp_insert_option_ackvec(sk, skb); 548 dccp_insert_option_ackvec(sk, skb))
569 if (dp->dccps_timestamp_echo != 0) 549 return -1;
570 dccp_insert_option_timestamp_echo(sk, skb); 550
551 if (dp->dccps_timestamp_echo != 0 &&
552 dccp_insert_option_timestamp_echo(sk, skb))
553 return -1;
571 } 554 }
572 555
573 if (dp->dccps_hc_rx_insert_options) { 556 if (dp->dccps_hc_rx_insert_options) {
574 ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb); 557 if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb))
558 return -1;
575 dp->dccps_hc_rx_insert_options = 0; 559 dp->dccps_hc_rx_insert_options = 0;
576 } 560 }
577 if (dp->dccps_hc_tx_insert_options) { 561 if (dp->dccps_hc_tx_insert_options) {
578 ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb); 562 if (ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb))
563 return -1;
579 dp->dccps_hc_tx_insert_options = 0; 564 dp->dccps_hc_tx_insert_options = 0;
580 } 565 }
581 566
582 /* Feature negotiation */ 567 /* Feature negotiation */
583 switch(DCCP_SKB_CB(skb)->dccpd_type) { 568 /* Data packets can't do feat negotiation */
584 /* Data packets can't do feat negotiation */ 569 if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&
585 case DCCP_PKT_DATA: 570 DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&
586 case DCCP_PKT_DATAACK: 571 dccp_insert_options_feat(sk, skb))
587 break; 572 return -1;
588 default:
589 dccp_insert_feat(sk, skb);
590 break;
591 }
592 573
593 /* XXX: insert other options when appropriate */ 574 /* XXX: insert other options when appropriate */
594 575
@@ -602,4 +583,6 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
602 DCCP_SKB_CB(skb)->dccpd_opt_len += padding; 583 DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
603 } 584 }
604 } 585 }
586
587 return 0;
605} 588}