diff options
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r-- | net/ipv4/tcp_output.c | 336 |
1 files changed, 274 insertions, 62 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index fcd278a7080e..0dda86e72ad8 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <net/tcp.h> | 37 | #include <net/tcp.h> |
38 | 38 | ||
39 | #include <linux/compiler.h> | 39 | #include <linux/compiler.h> |
40 | #include <linux/gfp.h> | ||
40 | #include <linux/module.h> | 41 | #include <linux/module.h> |
41 | 42 | ||
42 | /* People can turn this off for buggy TCP's found in printers etc. */ | 43 | /* People can turn this off for buggy TCP's found in printers etc. */ |
@@ -59,6 +60,10 @@ int sysctl_tcp_base_mss __read_mostly = 512; | |||
59 | /* By default, RFC2861 behavior. */ | 60 | /* By default, RFC2861 behavior. */ |
60 | int sysctl_tcp_slow_start_after_idle __read_mostly = 1; | 61 | int sysctl_tcp_slow_start_after_idle __read_mostly = 1; |
61 | 62 | ||
63 | int sysctl_tcp_cookie_size __read_mostly = 0; /* TCP_COOKIE_MAX */ | ||
64 | EXPORT_SYMBOL_GPL(sysctl_tcp_cookie_size); | ||
65 | |||
66 | |||
62 | /* Account for new data that has been sent to the network. */ | 67 | /* Account for new data that has been sent to the network. */ |
63 | static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb) | 68 | static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb) |
64 | { | 69 | { |
@@ -179,7 +184,8 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts) | |||
179 | */ | 184 | */ |
180 | void tcp_select_initial_window(int __space, __u32 mss, | 185 | void tcp_select_initial_window(int __space, __u32 mss, |
181 | __u32 *rcv_wnd, __u32 *window_clamp, | 186 | __u32 *rcv_wnd, __u32 *window_clamp, |
182 | int wscale_ok, __u8 *rcv_wscale) | 187 | int wscale_ok, __u8 *rcv_wscale, |
188 | __u32 init_rcv_wnd) | ||
183 | { | 189 | { |
184 | unsigned int space = (__space < 0 ? 0 : __space); | 190 | unsigned int space = (__space < 0 ? 0 : __space); |
185 | 191 | ||
@@ -228,7 +234,13 @@ void tcp_select_initial_window(int __space, __u32 mss, | |||
228 | init_cwnd = 2; | 234 | init_cwnd = 2; |
229 | else if (mss > 1460) | 235 | else if (mss > 1460) |
230 | init_cwnd = 3; | 236 | init_cwnd = 3; |
231 | if (*rcv_wnd > init_cwnd * mss) | 237 | /* when initializing use the value from init_rcv_wnd |
238 | * rather than the default from above | ||
239 | */ | ||
240 | if (init_rcv_wnd && | ||
241 | (*rcv_wnd > init_rcv_wnd * mss)) | ||
242 | *rcv_wnd = init_rcv_wnd * mss; | ||
243 | else if (*rcv_wnd > init_cwnd * mss) | ||
232 | *rcv_wnd = init_cwnd * mss; | 244 | *rcv_wnd = init_cwnd * mss; |
233 | } | 245 | } |
234 | 246 | ||
@@ -362,15 +374,45 @@ static inline int tcp_urg_mode(const struct tcp_sock *tp) | |||
362 | #define OPTION_TS (1 << 1) | 374 | #define OPTION_TS (1 << 1) |
363 | #define OPTION_MD5 (1 << 2) | 375 | #define OPTION_MD5 (1 << 2) |
364 | #define OPTION_WSCALE (1 << 3) | 376 | #define OPTION_WSCALE (1 << 3) |
377 | #define OPTION_COOKIE_EXTENSION (1 << 4) | ||
365 | 378 | ||
366 | struct tcp_out_options { | 379 | struct tcp_out_options { |
367 | u8 options; /* bit field of OPTION_* */ | 380 | u8 options; /* bit field of OPTION_* */ |
368 | u8 ws; /* window scale, 0 to disable */ | 381 | u8 ws; /* window scale, 0 to disable */ |
369 | u8 num_sack_blocks; /* number of SACK blocks to include */ | 382 | u8 num_sack_blocks; /* number of SACK blocks to include */ |
383 | u8 hash_size; /* bytes in hash_location */ | ||
370 | u16 mss; /* 0 to disable */ | 384 | u16 mss; /* 0 to disable */ |
371 | __u32 tsval, tsecr; /* need to include OPTION_TS */ | 385 | __u32 tsval, tsecr; /* need to include OPTION_TS */ |
386 | __u8 *hash_location; /* temporary pointer, overloaded */ | ||
372 | }; | 387 | }; |
373 | 388 | ||
389 | /* The sysctl int routines are generic, so check consistency here. | ||
390 | */ | ||
391 | static u8 tcp_cookie_size_check(u8 desired) | ||
392 | { | ||
393 | if (desired > 0) { | ||
394 | /* previously specified */ | ||
395 | return desired; | ||
396 | } | ||
397 | if (sysctl_tcp_cookie_size <= 0) { | ||
398 | /* no default specified */ | ||
399 | return 0; | ||
400 | } | ||
401 | if (sysctl_tcp_cookie_size <= TCP_COOKIE_MIN) { | ||
402 | /* value too small, specify minimum */ | ||
403 | return TCP_COOKIE_MIN; | ||
404 | } | ||
405 | if (sysctl_tcp_cookie_size >= TCP_COOKIE_MAX) { | ||
406 | /* value too large, specify maximum */ | ||
407 | return TCP_COOKIE_MAX; | ||
408 | } | ||
409 | if (0x1 & sysctl_tcp_cookie_size) { | ||
410 | /* 8-bit multiple, illegal, fix it */ | ||
411 | return (u8)(sysctl_tcp_cookie_size + 0x1); | ||
412 | } | ||
413 | return (u8)sysctl_tcp_cookie_size; | ||
414 | } | ||
415 | |||
374 | /* Write previously computed TCP options to the packet. | 416 | /* Write previously computed TCP options to the packet. |
375 | * | 417 | * |
376 | * Beware: Something in the Internet is very sensitive to the ordering of | 418 | * Beware: Something in the Internet is very sensitive to the ordering of |
@@ -385,17 +427,34 @@ struct tcp_out_options { | |||
385 | * (but it may well be that other scenarios fail similarly). | 427 | * (but it may well be that other scenarios fail similarly). |
386 | */ | 428 | */ |
387 | static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | 429 | static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, |
388 | const struct tcp_out_options *opts, | 430 | struct tcp_out_options *opts) |
389 | __u8 **md5_hash) { | 431 | { |
390 | if (unlikely(OPTION_MD5 & opts->options)) { | 432 | u8 options = opts->options; /* mungable copy */ |
391 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 433 | |
392 | (TCPOPT_NOP << 16) | | 434 | /* Having both authentication and cookies for security is redundant, |
393 | (TCPOPT_MD5SIG << 8) | | 435 | * and there's certainly not enough room. Instead, the cookie-less |
394 | TCPOLEN_MD5SIG); | 436 | * extension variant is proposed. |
395 | *md5_hash = (__u8 *)ptr; | 437 | * |
438 | * Consider the pessimal case with authentication. The options | ||
439 | * could look like: | ||
440 | * COOKIE|MD5(20) + MSS(4) + SACK|TS(12) + WSCALE(4) == 40 | ||
441 | */ | ||
442 | if (unlikely(OPTION_MD5 & options)) { | ||
443 | if (unlikely(OPTION_COOKIE_EXTENSION & options)) { | ||
444 | *ptr++ = htonl((TCPOPT_COOKIE << 24) | | ||
445 | (TCPOLEN_COOKIE_BASE << 16) | | ||
446 | (TCPOPT_MD5SIG << 8) | | ||
447 | TCPOLEN_MD5SIG); | ||
448 | } else { | ||
449 | *ptr++ = htonl((TCPOPT_NOP << 24) | | ||
450 | (TCPOPT_NOP << 16) | | ||
451 | (TCPOPT_MD5SIG << 8) | | ||
452 | TCPOLEN_MD5SIG); | ||
453 | } | ||
454 | options &= ~OPTION_COOKIE_EXTENSION; | ||
455 | /* overload cookie hash location */ | ||
456 | opts->hash_location = (__u8 *)ptr; | ||
396 | ptr += 4; | 457 | ptr += 4; |
397 | } else { | ||
398 | *md5_hash = NULL; | ||
399 | } | 458 | } |
400 | 459 | ||
401 | if (unlikely(opts->mss)) { | 460 | if (unlikely(opts->mss)) { |
@@ -404,12 +463,13 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | |||
404 | opts->mss); | 463 | opts->mss); |
405 | } | 464 | } |
406 | 465 | ||
407 | if (likely(OPTION_TS & opts->options)) { | 466 | if (likely(OPTION_TS & options)) { |
408 | if (unlikely(OPTION_SACK_ADVERTISE & opts->options)) { | 467 | if (unlikely(OPTION_SACK_ADVERTISE & options)) { |
409 | *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | | 468 | *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | |
410 | (TCPOLEN_SACK_PERM << 16) | | 469 | (TCPOLEN_SACK_PERM << 16) | |
411 | (TCPOPT_TIMESTAMP << 8) | | 470 | (TCPOPT_TIMESTAMP << 8) | |
412 | TCPOLEN_TIMESTAMP); | 471 | TCPOLEN_TIMESTAMP); |
472 | options &= ~OPTION_SACK_ADVERTISE; | ||
413 | } else { | 473 | } else { |
414 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 474 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
415 | (TCPOPT_NOP << 16) | | 475 | (TCPOPT_NOP << 16) | |
@@ -420,15 +480,52 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | |||
420 | *ptr++ = htonl(opts->tsecr); | 480 | *ptr++ = htonl(opts->tsecr); |
421 | } | 481 | } |
422 | 482 | ||
423 | if (unlikely(OPTION_SACK_ADVERTISE & opts->options && | 483 | /* Specification requires after timestamp, so do it now. |
424 | !(OPTION_TS & opts->options))) { | 484 | * |
485 | * Consider the pessimal case without authentication. The options | ||
486 | * could look like: | ||
487 | * MSS(4) + SACK|TS(12) + COOKIE(20) + WSCALE(4) == 40 | ||
488 | */ | ||
489 | if (unlikely(OPTION_COOKIE_EXTENSION & options)) { | ||
490 | __u8 *cookie_copy = opts->hash_location; | ||
491 | u8 cookie_size = opts->hash_size; | ||
492 | |||
493 | /* 8-bit multiple handled in tcp_cookie_size_check() above, | ||
494 | * and elsewhere. | ||
495 | */ | ||
496 | if (0x2 & cookie_size) { | ||
497 | __u8 *p = (__u8 *)ptr; | ||
498 | |||
499 | /* 16-bit multiple */ | ||
500 | *p++ = TCPOPT_COOKIE; | ||
501 | *p++ = TCPOLEN_COOKIE_BASE + cookie_size; | ||
502 | *p++ = *cookie_copy++; | ||
503 | *p++ = *cookie_copy++; | ||
504 | ptr++; | ||
505 | cookie_size -= 2; | ||
506 | } else { | ||
507 | /* 32-bit multiple */ | ||
508 | *ptr++ = htonl(((TCPOPT_NOP << 24) | | ||
509 | (TCPOPT_NOP << 16) | | ||
510 | (TCPOPT_COOKIE << 8) | | ||
511 | TCPOLEN_COOKIE_BASE) + | ||
512 | cookie_size); | ||
513 | } | ||
514 | |||
515 | if (cookie_size > 0) { | ||
516 | memcpy(ptr, cookie_copy, cookie_size); | ||
517 | ptr += (cookie_size / 4); | ||
518 | } | ||
519 | } | ||
520 | |||
521 | if (unlikely(OPTION_SACK_ADVERTISE & options)) { | ||
425 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 522 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
426 | (TCPOPT_NOP << 16) | | 523 | (TCPOPT_NOP << 16) | |
427 | (TCPOPT_SACK_PERM << 8) | | 524 | (TCPOPT_SACK_PERM << 8) | |
428 | TCPOLEN_SACK_PERM); | 525 | TCPOLEN_SACK_PERM); |
429 | } | 526 | } |
430 | 527 | ||
431 | if (unlikely(OPTION_WSCALE & opts->options)) { | 528 | if (unlikely(OPTION_WSCALE & options)) { |
432 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 529 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
433 | (TCPOPT_WINDOW << 16) | | 530 | (TCPOPT_WINDOW << 16) | |
434 | (TCPOLEN_WINDOW << 8) | | 531 | (TCPOLEN_WINDOW << 8) | |
@@ -463,13 +560,17 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb, | |||
463 | struct tcp_out_options *opts, | 560 | struct tcp_out_options *opts, |
464 | struct tcp_md5sig_key **md5) { | 561 | struct tcp_md5sig_key **md5) { |
465 | struct tcp_sock *tp = tcp_sk(sk); | 562 | struct tcp_sock *tp = tcp_sk(sk); |
466 | unsigned size = 0; | 563 | struct tcp_cookie_values *cvp = tp->cookie_values; |
564 | unsigned remaining = MAX_TCP_OPTION_SPACE; | ||
565 | u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp != NULL) ? | ||
566 | tcp_cookie_size_check(cvp->cookie_desired) : | ||
567 | 0; | ||
467 | 568 | ||
468 | #ifdef CONFIG_TCP_MD5SIG | 569 | #ifdef CONFIG_TCP_MD5SIG |
469 | *md5 = tp->af_specific->md5_lookup(sk, sk); | 570 | *md5 = tp->af_specific->md5_lookup(sk, sk); |
470 | if (*md5) { | 571 | if (*md5) { |
471 | opts->options |= OPTION_MD5; | 572 | opts->options |= OPTION_MD5; |
472 | size += TCPOLEN_MD5SIG_ALIGNED; | 573 | remaining -= TCPOLEN_MD5SIG_ALIGNED; |
473 | } | 574 | } |
474 | #else | 575 | #else |
475 | *md5 = NULL; | 576 | *md5 = NULL; |
@@ -485,26 +586,72 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb, | |||
485 | * SACKs don't matter, we never delay an ACK when we have any of those | 586 | * SACKs don't matter, we never delay an ACK when we have any of those |
486 | * going out. */ | 587 | * going out. */ |
487 | opts->mss = tcp_advertise_mss(sk); | 588 | opts->mss = tcp_advertise_mss(sk); |
488 | size += TCPOLEN_MSS_ALIGNED; | 589 | remaining -= TCPOLEN_MSS_ALIGNED; |
489 | 590 | ||
490 | if (likely(sysctl_tcp_timestamps && *md5 == NULL)) { | 591 | if (likely(sysctl_tcp_timestamps && *md5 == NULL)) { |
491 | opts->options |= OPTION_TS; | 592 | opts->options |= OPTION_TS; |
492 | opts->tsval = TCP_SKB_CB(skb)->when; | 593 | opts->tsval = TCP_SKB_CB(skb)->when; |
493 | opts->tsecr = tp->rx_opt.ts_recent; | 594 | opts->tsecr = tp->rx_opt.ts_recent; |
494 | size += TCPOLEN_TSTAMP_ALIGNED; | 595 | remaining -= TCPOLEN_TSTAMP_ALIGNED; |
495 | } | 596 | } |
496 | if (likely(sysctl_tcp_window_scaling)) { | 597 | if (likely(sysctl_tcp_window_scaling)) { |
497 | opts->ws = tp->rx_opt.rcv_wscale; | 598 | opts->ws = tp->rx_opt.rcv_wscale; |
498 | opts->options |= OPTION_WSCALE; | 599 | opts->options |= OPTION_WSCALE; |
499 | size += TCPOLEN_WSCALE_ALIGNED; | 600 | remaining -= TCPOLEN_WSCALE_ALIGNED; |
500 | } | 601 | } |
501 | if (likely(sysctl_tcp_sack)) { | 602 | if (likely(sysctl_tcp_sack)) { |
502 | opts->options |= OPTION_SACK_ADVERTISE; | 603 | opts->options |= OPTION_SACK_ADVERTISE; |
503 | if (unlikely(!(OPTION_TS & opts->options))) | 604 | if (unlikely(!(OPTION_TS & opts->options))) |
504 | size += TCPOLEN_SACKPERM_ALIGNED; | 605 | remaining -= TCPOLEN_SACKPERM_ALIGNED; |
505 | } | 606 | } |
506 | 607 | ||
507 | return size; | 608 | /* Note that timestamps are required by the specification. |
609 | * | ||
610 | * Odd numbers of bytes are prohibited by the specification, ensuring | ||
611 | * that the cookie is 16-bit aligned, and the resulting cookie pair is | ||
612 | * 32-bit aligned. | ||
613 | */ | ||
614 | if (*md5 == NULL && | ||
615 | (OPTION_TS & opts->options) && | ||
616 | cookie_size > 0) { | ||
617 | int need = TCPOLEN_COOKIE_BASE + cookie_size; | ||
618 | |||
619 | if (0x2 & need) { | ||
620 | /* 32-bit multiple */ | ||
621 | need += 2; /* NOPs */ | ||
622 | |||
623 | if (need > remaining) { | ||
624 | /* try shrinking cookie to fit */ | ||
625 | cookie_size -= 2; | ||
626 | need -= 4; | ||
627 | } | ||
628 | } | ||
629 | while (need > remaining && TCP_COOKIE_MIN <= cookie_size) { | ||
630 | cookie_size -= 4; | ||
631 | need -= 4; | ||
632 | } | ||
633 | if (TCP_COOKIE_MIN <= cookie_size) { | ||
634 | opts->options |= OPTION_COOKIE_EXTENSION; | ||
635 | opts->hash_location = (__u8 *)&cvp->cookie_pair[0]; | ||
636 | opts->hash_size = cookie_size; | ||
637 | |||
638 | /* Remember for future incarnations. */ | ||
639 | cvp->cookie_desired = cookie_size; | ||
640 | |||
641 | if (cvp->cookie_desired != cvp->cookie_pair_size) { | ||
642 | /* Currently use random bytes as a nonce, | ||
643 | * assuming these are completely unpredictable | ||
644 | * by hostile users of the same system. | ||
645 | */ | ||
646 | get_random_bytes(&cvp->cookie_pair[0], | ||
647 | cookie_size); | ||
648 | cvp->cookie_pair_size = cookie_size; | ||
649 | } | ||
650 | |||
651 | remaining -= need; | ||
652 | } | ||
653 | } | ||
654 | return MAX_TCP_OPTION_SPACE - remaining; | ||
508 | } | 655 | } |
509 | 656 | ||
510 | /* Set up TCP options for SYN-ACKs. */ | 657 | /* Set up TCP options for SYN-ACKs. */ |
@@ -512,48 +659,77 @@ static unsigned tcp_synack_options(struct sock *sk, | |||
512 | struct request_sock *req, | 659 | struct request_sock *req, |
513 | unsigned mss, struct sk_buff *skb, | 660 | unsigned mss, struct sk_buff *skb, |
514 | struct tcp_out_options *opts, | 661 | struct tcp_out_options *opts, |
515 | struct tcp_md5sig_key **md5) { | 662 | struct tcp_md5sig_key **md5, |
516 | unsigned size = 0; | 663 | struct tcp_extend_values *xvp) |
664 | { | ||
517 | struct inet_request_sock *ireq = inet_rsk(req); | 665 | struct inet_request_sock *ireq = inet_rsk(req); |
518 | char doing_ts; | 666 | unsigned remaining = MAX_TCP_OPTION_SPACE; |
667 | u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ? | ||
668 | xvp->cookie_plus : | ||
669 | 0; | ||
670 | bool doing_ts = ireq->tstamp_ok; | ||
519 | 671 | ||
520 | #ifdef CONFIG_TCP_MD5SIG | 672 | #ifdef CONFIG_TCP_MD5SIG |
521 | *md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req); | 673 | *md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req); |
522 | if (*md5) { | 674 | if (*md5) { |
523 | opts->options |= OPTION_MD5; | 675 | opts->options |= OPTION_MD5; |
524 | size += TCPOLEN_MD5SIG_ALIGNED; | 676 | remaining -= TCPOLEN_MD5SIG_ALIGNED; |
677 | |||
678 | /* We can't fit any SACK blocks in a packet with MD5 + TS | ||
679 | * options. There was discussion about disabling SACK | ||
680 | * rather than TS in order to fit in better with old, | ||
681 | * buggy kernels, but that was deemed to be unnecessary. | ||
682 | */ | ||
683 | doing_ts &= !ireq->sack_ok; | ||
525 | } | 684 | } |
526 | #else | 685 | #else |
527 | *md5 = NULL; | 686 | *md5 = NULL; |
528 | #endif | 687 | #endif |
529 | 688 | ||
530 | /* we can't fit any SACK blocks in a packet with MD5 + TS | 689 | /* We always send an MSS option. */ |
531 | options. There was discussion about disabling SACK rather than TS in | ||
532 | order to fit in better with old, buggy kernels, but that was deemed | ||
533 | to be unnecessary. */ | ||
534 | doing_ts = ireq->tstamp_ok && !(*md5 && ireq->sack_ok); | ||
535 | |||
536 | opts->mss = mss; | 690 | opts->mss = mss; |
537 | size += TCPOLEN_MSS_ALIGNED; | 691 | remaining -= TCPOLEN_MSS_ALIGNED; |
538 | 692 | ||
539 | if (likely(ireq->wscale_ok)) { | 693 | if (likely(ireq->wscale_ok)) { |
540 | opts->ws = ireq->rcv_wscale; | 694 | opts->ws = ireq->rcv_wscale; |
541 | opts->options |= OPTION_WSCALE; | 695 | opts->options |= OPTION_WSCALE; |
542 | size += TCPOLEN_WSCALE_ALIGNED; | 696 | remaining -= TCPOLEN_WSCALE_ALIGNED; |
543 | } | 697 | } |
544 | if (likely(doing_ts)) { | 698 | if (likely(doing_ts)) { |
545 | opts->options |= OPTION_TS; | 699 | opts->options |= OPTION_TS; |
546 | opts->tsval = TCP_SKB_CB(skb)->when; | 700 | opts->tsval = TCP_SKB_CB(skb)->when; |
547 | opts->tsecr = req->ts_recent; | 701 | opts->tsecr = req->ts_recent; |
548 | size += TCPOLEN_TSTAMP_ALIGNED; | 702 | remaining -= TCPOLEN_TSTAMP_ALIGNED; |
549 | } | 703 | } |
550 | if (likely(ireq->sack_ok)) { | 704 | if (likely(ireq->sack_ok)) { |
551 | opts->options |= OPTION_SACK_ADVERTISE; | 705 | opts->options |= OPTION_SACK_ADVERTISE; |
552 | if (unlikely(!doing_ts)) | 706 | if (unlikely(!doing_ts)) |
553 | size += TCPOLEN_SACKPERM_ALIGNED; | 707 | remaining -= TCPOLEN_SACKPERM_ALIGNED; |
554 | } | 708 | } |
555 | 709 | ||
556 | return size; | 710 | /* Similar rationale to tcp_syn_options() applies here, too. |
711 | * If the <SYN> options fit, the same options should fit now! | ||
712 | */ | ||
713 | if (*md5 == NULL && | ||
714 | doing_ts && | ||
715 | cookie_plus > TCPOLEN_COOKIE_BASE) { | ||
716 | int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */ | ||
717 | |||
718 | if (0x2 & need) { | ||
719 | /* 32-bit multiple */ | ||
720 | need += 2; /* NOPs */ | ||
721 | } | ||
722 | if (need <= remaining) { | ||
723 | opts->options |= OPTION_COOKIE_EXTENSION; | ||
724 | opts->hash_size = cookie_plus - TCPOLEN_COOKIE_BASE; | ||
725 | remaining -= need; | ||
726 | } else { | ||
727 | /* There's no error return, so flag it. */ | ||
728 | xvp->cookie_out_never = 1; /* true */ | ||
729 | opts->hash_size = 0; | ||
730 | } | ||
731 | } | ||
732 | return MAX_TCP_OPTION_SPACE - remaining; | ||
557 | } | 733 | } |
558 | 734 | ||
559 | /* Compute TCP options for ESTABLISHED sockets. This is not the | 735 | /* Compute TCP options for ESTABLISHED sockets. This is not the |
@@ -619,7 +795,6 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
619 | struct tcp_out_options opts; | 795 | struct tcp_out_options opts; |
620 | unsigned tcp_options_size, tcp_header_size; | 796 | unsigned tcp_options_size, tcp_header_size; |
621 | struct tcp_md5sig_key *md5; | 797 | struct tcp_md5sig_key *md5; |
622 | __u8 *md5_hash_location; | ||
623 | struct tcphdr *th; | 798 | struct tcphdr *th; |
624 | int err; | 799 | int err; |
625 | 800 | ||
@@ -661,8 +836,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
661 | 836 | ||
662 | /* Build TCP header and checksum it. */ | 837 | /* Build TCP header and checksum it. */ |
663 | th = tcp_hdr(skb); | 838 | th = tcp_hdr(skb); |
664 | th->source = inet->sport; | 839 | th->source = inet->inet_sport; |
665 | th->dest = inet->dport; | 840 | th->dest = inet->inet_dport; |
666 | th->seq = htonl(tcb->seq); | 841 | th->seq = htonl(tcb->seq); |
667 | th->ack_seq = htonl(tp->rcv_nxt); | 842 | th->ack_seq = htonl(tp->rcv_nxt); |
668 | *(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) | | 843 | *(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) | |
@@ -690,7 +865,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
690 | } | 865 | } |
691 | } | 866 | } |
692 | 867 | ||
693 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); | 868 | tcp_options_write((__be32 *)(th + 1), tp, &opts); |
694 | if (likely((tcb->flags & TCPCB_FLAG_SYN) == 0)) | 869 | if (likely((tcb->flags & TCPCB_FLAG_SYN) == 0)) |
695 | TCP_ECN_send(sk, skb, tcp_header_size); | 870 | TCP_ECN_send(sk, skb, tcp_header_size); |
696 | 871 | ||
@@ -698,7 +873,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
698 | /* Calculate the MD5 hash, as we have all we need now */ | 873 | /* Calculate the MD5 hash, as we have all we need now */ |
699 | if (md5) { | 874 | if (md5) { |
700 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 875 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
701 | tp->af_specific->calc_md5_hash(md5_hash_location, | 876 | tp->af_specific->calc_md5_hash(opts.hash_location, |
702 | md5, sk, NULL, skb); | 877 | md5, sk, NULL, skb); |
703 | } | 878 | } |
704 | #endif | 879 | #endif |
@@ -1627,11 +1802,6 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
1627 | void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, | 1802 | void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, |
1628 | int nonagle) | 1803 | int nonagle) |
1629 | { | 1804 | { |
1630 | struct sk_buff *skb = tcp_send_head(sk); | ||
1631 | |||
1632 | if (!skb) | ||
1633 | return; | ||
1634 | |||
1635 | /* If we are closed, the bytes will have to remain here. | 1805 | /* If we are closed, the bytes will have to remain here. |
1636 | * In time closedown will finish, we empty the write queue and | 1806 | * In time closedown will finish, we empty the write queue and |
1637 | * all will be happy. | 1807 | * all will be happy. |
@@ -1918,8 +2088,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
1918 | * case, when window is shrunk to zero. In this case | 2088 | * case, when window is shrunk to zero. In this case |
1919 | * our retransmit serves as a zero window probe. | 2089 | * our retransmit serves as a zero window probe. |
1920 | */ | 2090 | */ |
1921 | if (!before(TCP_SKB_CB(skb)->seq, tcp_wnd_end(tp)) | 2091 | if (!before(TCP_SKB_CB(skb)->seq, tcp_wnd_end(tp)) && |
1922 | && TCP_SKB_CB(skb)->seq != tp->snd_una) | 2092 | TCP_SKB_CB(skb)->seq != tp->snd_una) |
1923 | return -EAGAIN; | 2093 | return -EAGAIN; |
1924 | 2094 | ||
1925 | if (skb->len > cur_mss) { | 2095 | if (skb->len > cur_mss) { |
@@ -2219,19 +2389,24 @@ int tcp_send_synack(struct sock *sk) | |||
2219 | 2389 | ||
2220 | /* Prepare a SYN-ACK. */ | 2390 | /* Prepare a SYN-ACK. */ |
2221 | struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | 2391 | struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, |
2222 | struct request_sock *req) | 2392 | struct request_sock *req, |
2393 | struct request_values *rvp) | ||
2223 | { | 2394 | { |
2395 | struct tcp_out_options opts; | ||
2396 | struct tcp_extend_values *xvp = tcp_xv(rvp); | ||
2224 | struct inet_request_sock *ireq = inet_rsk(req); | 2397 | struct inet_request_sock *ireq = inet_rsk(req); |
2225 | struct tcp_sock *tp = tcp_sk(sk); | 2398 | struct tcp_sock *tp = tcp_sk(sk); |
2399 | const struct tcp_cookie_values *cvp = tp->cookie_values; | ||
2226 | struct tcphdr *th; | 2400 | struct tcphdr *th; |
2227 | int tcp_header_size; | ||
2228 | struct tcp_out_options opts; | ||
2229 | struct sk_buff *skb; | 2401 | struct sk_buff *skb; |
2230 | struct tcp_md5sig_key *md5; | 2402 | struct tcp_md5sig_key *md5; |
2231 | __u8 *md5_hash_location; | 2403 | int tcp_header_size; |
2232 | int mss; | 2404 | int mss; |
2405 | int s_data_desired = 0; | ||
2233 | 2406 | ||
2234 | skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); | 2407 | if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired) |
2408 | s_data_desired = cvp->s_data_desired; | ||
2409 | skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15 + s_data_desired, 1, GFP_ATOMIC); | ||
2235 | if (skb == NULL) | 2410 | if (skb == NULL) |
2236 | return NULL; | 2411 | return NULL; |
2237 | 2412 | ||
@@ -2254,7 +2429,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2254 | &req->rcv_wnd, | 2429 | &req->rcv_wnd, |
2255 | &req->window_clamp, | 2430 | &req->window_clamp, |
2256 | ireq->wscale_ok, | 2431 | ireq->wscale_ok, |
2257 | &rcv_wscale); | 2432 | &rcv_wscale, |
2433 | dst_metric(dst, RTAX_INITRWND)); | ||
2258 | ireq->rcv_wscale = rcv_wscale; | 2434 | ireq->rcv_wscale = rcv_wscale; |
2259 | } | 2435 | } |
2260 | 2436 | ||
@@ -2266,8 +2442,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2266 | #endif | 2442 | #endif |
2267 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 2443 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
2268 | tcp_header_size = tcp_synack_options(sk, req, mss, | 2444 | tcp_header_size = tcp_synack_options(sk, req, mss, |
2269 | skb, &opts, &md5) + | 2445 | skb, &opts, &md5, xvp) |
2270 | sizeof(struct tcphdr); | 2446 | + sizeof(*th); |
2271 | 2447 | ||
2272 | skb_push(skb, tcp_header_size); | 2448 | skb_push(skb, tcp_header_size); |
2273 | skb_reset_transport_header(skb); | 2449 | skb_reset_transport_header(skb); |
@@ -2284,19 +2460,54 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2284 | */ | 2460 | */ |
2285 | tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn, | 2461 | tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn, |
2286 | TCPCB_FLAG_SYN | TCPCB_FLAG_ACK); | 2462 | TCPCB_FLAG_SYN | TCPCB_FLAG_ACK); |
2463 | |||
2464 | if (OPTION_COOKIE_EXTENSION & opts.options) { | ||
2465 | if (s_data_desired) { | ||
2466 | u8 *buf = skb_put(skb, s_data_desired); | ||
2467 | |||
2468 | /* copy data directly from the listening socket. */ | ||
2469 | memcpy(buf, cvp->s_data_payload, s_data_desired); | ||
2470 | TCP_SKB_CB(skb)->end_seq += s_data_desired; | ||
2471 | } | ||
2472 | |||
2473 | if (opts.hash_size > 0) { | ||
2474 | __u32 workspace[SHA_WORKSPACE_WORDS]; | ||
2475 | u32 *mess = &xvp->cookie_bakery[COOKIE_DIGEST_WORDS]; | ||
2476 | u32 *tail = &mess[COOKIE_MESSAGE_WORDS-1]; | ||
2477 | |||
2478 | /* Secret recipe depends on the Timestamp, (future) | ||
2479 | * Sequence and Acknowledgment Numbers, Initiator | ||
2480 | * Cookie, and others handled by IP variant caller. | ||
2481 | */ | ||
2482 | *tail-- ^= opts.tsval; | ||
2483 | *tail-- ^= tcp_rsk(req)->rcv_isn + 1; | ||
2484 | *tail-- ^= TCP_SKB_CB(skb)->seq + 1; | ||
2485 | |||
2486 | /* recommended */ | ||
2487 | *tail-- ^= ((th->dest << 16) | th->source); | ||
2488 | *tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */ | ||
2489 | |||
2490 | sha_transform((__u32 *)&xvp->cookie_bakery[0], | ||
2491 | (char *)mess, | ||
2492 | &workspace[0]); | ||
2493 | opts.hash_location = | ||
2494 | (__u8 *)&xvp->cookie_bakery[0]; | ||
2495 | } | ||
2496 | } | ||
2497 | |||
2287 | th->seq = htonl(TCP_SKB_CB(skb)->seq); | 2498 | th->seq = htonl(TCP_SKB_CB(skb)->seq); |
2288 | th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1); | 2499 | th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1); |
2289 | 2500 | ||
2290 | /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ | 2501 | /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ |
2291 | th->window = htons(min(req->rcv_wnd, 65535U)); | 2502 | th->window = htons(min(req->rcv_wnd, 65535U)); |
2292 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); | 2503 | tcp_options_write((__be32 *)(th + 1), tp, &opts); |
2293 | th->doff = (tcp_header_size >> 2); | 2504 | th->doff = (tcp_header_size >> 2); |
2294 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); | 2505 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); |
2295 | 2506 | ||
2296 | #ifdef CONFIG_TCP_MD5SIG | 2507 | #ifdef CONFIG_TCP_MD5SIG |
2297 | /* Okay, we have all we need - do the md5 hash if needed */ | 2508 | /* Okay, we have all we need - do the md5 hash if needed */ |
2298 | if (md5) { | 2509 | if (md5) { |
2299 | tcp_rsk(req)->af_specific->calc_md5_hash(md5_hash_location, | 2510 | tcp_rsk(req)->af_specific->calc_md5_hash(opts.hash_location, |
2300 | md5, NULL, req, skb); | 2511 | md5, NULL, req, skb); |
2301 | } | 2512 | } |
2302 | #endif | 2513 | #endif |
@@ -2342,7 +2553,8 @@ static void tcp_connect_init(struct sock *sk) | |||
2342 | &tp->rcv_wnd, | 2553 | &tp->rcv_wnd, |
2343 | &tp->window_clamp, | 2554 | &tp->window_clamp, |
2344 | sysctl_tcp_window_scaling, | 2555 | sysctl_tcp_window_scaling, |
2345 | &rcv_wscale); | 2556 | &rcv_wscale, |
2557 | dst_metric(dst, RTAX_INITRWND)); | ||
2346 | 2558 | ||
2347 | tp->rx_opt.rcv_wscale = rcv_wscale; | 2559 | tp->rx_opt.rcv_wscale = rcv_wscale; |
2348 | tp->rcv_ssthresh = tp->rcv_wnd; | 2560 | tp->rcv_ssthresh = tp->rcv_wnd; |