diff options
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r-- | net/dccp/options.c | 109 |
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 | ||
286 | void dccp_insert_option(struct sock *sk, struct sk_buff *skb, | 286 | int 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 | ||
307 | EXPORT_SYMBOL_GPL(dccp_insert_option); | 305 | EXPORT_SYMBOL_GPL(dccp_insert_option); |
308 | 306 | ||
309 | static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb) | 307 | static 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 | ||
336 | static inline int dccp_elapsed_time_len(const u32 elapsed_time) | 336 | static 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 | ||
341 | void dccp_insert_option_elapsed_time(struct sock *sk, | 341 | int 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 | ||
383 | EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); | 371 | EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); |
@@ -398,7 +386,7 @@ void dccp_timestamp(const struct sock *sk, struct timeval *tv) | |||
398 | 386 | ||
399 | EXPORT_SYMBOL_GPL(dccp_timestamp); | 387 | EXPORT_SYMBOL_GPL(dccp_timestamp); |
400 | 388 | ||
401 | void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) | 389 | int 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 | ||
414 | EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp); | 402 | EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp); |
415 | 403 | ||
416 | static void dccp_insert_option_timestamp_echo(struct sock *sk, | 404 | static 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 | ||
469 | static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, | 446 | static 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 | ||
494 | static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb) | 471 | static 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 | ||
556 | void dccp_insert_options(struct sock *sk, struct sk_buff *skb) | 535 | int 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 | } |