diff options
| author | William Allen Simpson <william.allen.simpson@gmail.com> | 2009-12-02 13:23:05 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-12-03 01:07:26 -0500 |
| commit | bd0388ae77075026d6a9f9eb6026dfd1d52ce0e9 (patch) | |
| tree | b2262d2bf3f60e42f8c3573c89e6a47042b20122 /net/ipv4 | |
| parent | e56fb50f2b7958b931c8a2fc0966061b3f3c8f3a (diff) | |
TCPCT part 1f: Initiator Cookie => Responder
Calculate and format <SYN> TCP_COOKIE option.
This is a significantly revised implementation of an earlier (year-old)
patch that no longer applies cleanly, with permission of the original
author (Adam Langley):
http://thread.gmane.org/gmane.linux.network/102586
Requires:
TCPCT part 1c: sysctl_tcp_cookie_size, socket option TCP_COOKIE_TRANSACTIONS
TCPCT part 1d: define TCP cookie option, extend existing struct's
Signed-off-by: William.Allen.Simpson@gmail.com
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/tcp_output.c | 193 |
1 files changed, 163 insertions, 30 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 307f318fe931..35dd983a8a99 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -365,15 +365,45 @@ static inline int tcp_urg_mode(const struct tcp_sock *tp) | |||
| 365 | #define OPTION_TS (1 << 1) | 365 | #define OPTION_TS (1 << 1) |
| 366 | #define OPTION_MD5 (1 << 2) | 366 | #define OPTION_MD5 (1 << 2) |
| 367 | #define OPTION_WSCALE (1 << 3) | 367 | #define OPTION_WSCALE (1 << 3) |
| 368 | #define OPTION_COOKIE_EXTENSION (1 << 4) | ||
| 368 | 369 | ||
| 369 | struct tcp_out_options { | 370 | struct tcp_out_options { |
| 370 | u8 options; /* bit field of OPTION_* */ | 371 | u8 options; /* bit field of OPTION_* */ |
| 371 | u8 ws; /* window scale, 0 to disable */ | 372 | u8 ws; /* window scale, 0 to disable */ |
| 372 | u8 num_sack_blocks; /* number of SACK blocks to include */ | 373 | u8 num_sack_blocks; /* number of SACK blocks to include */ |
| 374 | u8 hash_size; /* bytes in hash_location */ | ||
| 373 | u16 mss; /* 0 to disable */ | 375 | u16 mss; /* 0 to disable */ |
| 374 | __u32 tsval, tsecr; /* need to include OPTION_TS */ | 376 | __u32 tsval, tsecr; /* need to include OPTION_TS */ |
| 377 | __u8 *hash_location; /* temporary pointer, overloaded */ | ||
| 375 | }; | 378 | }; |
| 376 | 379 | ||
| 380 | /* The sysctl int routines are generic, so check consistency here. | ||
| 381 | */ | ||
| 382 | static u8 tcp_cookie_size_check(u8 desired) | ||
| 383 | { | ||
| 384 | if (desired > 0) { | ||
| 385 | /* previously specified */ | ||
| 386 | return desired; | ||
| 387 | } | ||
| 388 | if (sysctl_tcp_cookie_size <= 0) { | ||
| 389 | /* no default specified */ | ||
| 390 | return 0; | ||
| 391 | } | ||
| 392 | if (sysctl_tcp_cookie_size <= TCP_COOKIE_MIN) { | ||
| 393 | /* value too small, specify minimum */ | ||
| 394 | return TCP_COOKIE_MIN; | ||
| 395 | } | ||
| 396 | if (sysctl_tcp_cookie_size >= TCP_COOKIE_MAX) { | ||
| 397 | /* value too large, specify maximum */ | ||
| 398 | return TCP_COOKIE_MAX; | ||
| 399 | } | ||
| 400 | if (0x1 & sysctl_tcp_cookie_size) { | ||
| 401 | /* 8-bit multiple, illegal, fix it */ | ||
| 402 | return (u8)(sysctl_tcp_cookie_size + 0x1); | ||
| 403 | } | ||
| 404 | return (u8)sysctl_tcp_cookie_size; | ||
| 405 | } | ||
| 406 | |||
| 377 | /* Write previously computed TCP options to the packet. | 407 | /* Write previously computed TCP options to the packet. |
| 378 | * | 408 | * |
| 379 | * Beware: Something in the Internet is very sensitive to the ordering of | 409 | * Beware: Something in the Internet is very sensitive to the ordering of |
| @@ -388,17 +418,34 @@ struct tcp_out_options { | |||
| 388 | * (but it may well be that other scenarios fail similarly). | 418 | * (but it may well be that other scenarios fail similarly). |
| 389 | */ | 419 | */ |
| 390 | static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | 420 | static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, |
| 391 | const struct tcp_out_options *opts, | 421 | struct tcp_out_options *opts) |
| 392 | __u8 **md5_hash) { | 422 | { |
| 393 | if (unlikely(OPTION_MD5 & opts->options)) { | 423 | u8 options = opts->options; /* mungable copy */ |
| 394 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 424 | |
| 395 | (TCPOPT_NOP << 16) | | 425 | /* Having both authentication and cookies for security is redundant, |
| 396 | (TCPOPT_MD5SIG << 8) | | 426 | * and there's certainly not enough room. Instead, the cookie-less |
| 397 | TCPOLEN_MD5SIG); | 427 | * extension variant is proposed. |
| 398 | *md5_hash = (__u8 *)ptr; | 428 | * |
| 429 | * Consider the pessimal case with authentication. The options | ||
| 430 | * could look like: | ||
| 431 | * COOKIE|MD5(20) + MSS(4) + SACK|TS(12) + WSCALE(4) == 40 | ||
| 432 | */ | ||
| 433 | if (unlikely(OPTION_MD5 & options)) { | ||
| 434 | if (unlikely(OPTION_COOKIE_EXTENSION & options)) { | ||
| 435 | *ptr++ = htonl((TCPOPT_COOKIE << 24) | | ||
| 436 | (TCPOLEN_COOKIE_BASE << 16) | | ||
| 437 | (TCPOPT_MD5SIG << 8) | | ||
| 438 | TCPOLEN_MD5SIG); | ||
| 439 | } else { | ||
| 440 | *ptr++ = htonl((TCPOPT_NOP << 24) | | ||
| 441 | (TCPOPT_NOP << 16) | | ||
| 442 | (TCPOPT_MD5SIG << 8) | | ||
| 443 | TCPOLEN_MD5SIG); | ||
| 444 | } | ||
| 445 | options &= ~OPTION_COOKIE_EXTENSION; | ||
| 446 | /* overload cookie hash location */ | ||
| 447 | opts->hash_location = (__u8 *)ptr; | ||
| 399 | ptr += 4; | 448 | ptr += 4; |
| 400 | } else { | ||
| 401 | *md5_hash = NULL; | ||
| 402 | } | 449 | } |
| 403 | 450 | ||
| 404 | if (unlikely(opts->mss)) { | 451 | if (unlikely(opts->mss)) { |
| @@ -407,12 +454,13 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | |||
| 407 | opts->mss); | 454 | opts->mss); |
| 408 | } | 455 | } |
| 409 | 456 | ||
| 410 | if (likely(OPTION_TS & opts->options)) { | 457 | if (likely(OPTION_TS & options)) { |
| 411 | if (unlikely(OPTION_SACK_ADVERTISE & opts->options)) { | 458 | if (unlikely(OPTION_SACK_ADVERTISE & options)) { |
| 412 | *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | | 459 | *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | |
| 413 | (TCPOLEN_SACK_PERM << 16) | | 460 | (TCPOLEN_SACK_PERM << 16) | |
| 414 | (TCPOPT_TIMESTAMP << 8) | | 461 | (TCPOPT_TIMESTAMP << 8) | |
| 415 | TCPOLEN_TIMESTAMP); | 462 | TCPOLEN_TIMESTAMP); |
| 463 | options &= ~OPTION_SACK_ADVERTISE; | ||
| 416 | } else { | 464 | } else { |
| 417 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 465 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
| 418 | (TCPOPT_NOP << 16) | | 466 | (TCPOPT_NOP << 16) | |
| @@ -423,15 +471,52 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | |||
| 423 | *ptr++ = htonl(opts->tsecr); | 471 | *ptr++ = htonl(opts->tsecr); |
| 424 | } | 472 | } |
| 425 | 473 | ||
| 426 | if (unlikely(OPTION_SACK_ADVERTISE & opts->options && | 474 | /* Specification requires after timestamp, so do it now. |
| 427 | !(OPTION_TS & opts->options))) { | 475 | * |
| 476 | * Consider the pessimal case without authentication. The options | ||
| 477 | * could look like: | ||
| 478 | * MSS(4) + SACK|TS(12) + COOKIE(20) + WSCALE(4) == 40 | ||
| 479 | */ | ||
| 480 | if (unlikely(OPTION_COOKIE_EXTENSION & options)) { | ||
| 481 | __u8 *cookie_copy = opts->hash_location; | ||
| 482 | u8 cookie_size = opts->hash_size; | ||
| 483 | |||
| 484 | /* 8-bit multiple handled in tcp_cookie_size_check() above, | ||
| 485 | * and elsewhere. | ||
| 486 | */ | ||
| 487 | if (0x2 & cookie_size) { | ||
| 488 | __u8 *p = (__u8 *)ptr; | ||
| 489 | |||
| 490 | /* 16-bit multiple */ | ||
| 491 | *p++ = TCPOPT_COOKIE; | ||
| 492 | *p++ = TCPOLEN_COOKIE_BASE + cookie_size; | ||
| 493 | *p++ = *cookie_copy++; | ||
| 494 | *p++ = *cookie_copy++; | ||
| 495 | ptr++; | ||
| 496 | cookie_size -= 2; | ||
| 497 | } else { | ||
| 498 | /* 32-bit multiple */ | ||
| 499 | *ptr++ = htonl(((TCPOPT_NOP << 24) | | ||
| 500 | (TCPOPT_NOP << 16) | | ||
| 501 | (TCPOPT_COOKIE << 8) | | ||
| 502 | TCPOLEN_COOKIE_BASE) + | ||
| 503 | cookie_size); | ||
| 504 | } | ||
| 505 | |||
| 506 | if (cookie_size > 0) { | ||
| 507 | memcpy(ptr, cookie_copy, cookie_size); | ||
| 508 | ptr += (cookie_size / 4); | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | if (unlikely(OPTION_SACK_ADVERTISE & options)) { | ||
| 428 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 513 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
| 429 | (TCPOPT_NOP << 16) | | 514 | (TCPOPT_NOP << 16) | |
| 430 | (TCPOPT_SACK_PERM << 8) | | 515 | (TCPOPT_SACK_PERM << 8) | |
| 431 | TCPOLEN_SACK_PERM); | 516 | TCPOLEN_SACK_PERM); |
| 432 | } | 517 | } |
| 433 | 518 | ||
| 434 | if (unlikely(OPTION_WSCALE & opts->options)) { | 519 | if (unlikely(OPTION_WSCALE & options)) { |
| 435 | *ptr++ = htonl((TCPOPT_NOP << 24) | | 520 | *ptr++ = htonl((TCPOPT_NOP << 24) | |
| 436 | (TCPOPT_WINDOW << 16) | | 521 | (TCPOPT_WINDOW << 16) | |
| 437 | (TCPOLEN_WINDOW << 8) | | 522 | (TCPOLEN_WINDOW << 8) | |
| @@ -466,14 +551,18 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb, | |||
| 466 | struct tcp_out_options *opts, | 551 | struct tcp_out_options *opts, |
| 467 | struct tcp_md5sig_key **md5) { | 552 | struct tcp_md5sig_key **md5) { |
| 468 | struct tcp_sock *tp = tcp_sk(sk); | 553 | struct tcp_sock *tp = tcp_sk(sk); |
| 469 | unsigned size = 0; | 554 | struct tcp_cookie_values *cvp = tp->cookie_values; |
| 470 | struct dst_entry *dst = __sk_dst_get(sk); | 555 | struct dst_entry *dst = __sk_dst_get(sk); |
| 556 | unsigned remaining = MAX_TCP_OPTION_SPACE; | ||
| 557 | u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp != NULL) ? | ||
| 558 | tcp_cookie_size_check(cvp->cookie_desired) : | ||
| 559 | 0; | ||
| 471 | 560 | ||
| 472 | #ifdef CONFIG_TCP_MD5SIG | 561 | #ifdef CONFIG_TCP_MD5SIG |
| 473 | *md5 = tp->af_specific->md5_lookup(sk, sk); | 562 | *md5 = tp->af_specific->md5_lookup(sk, sk); |
| 474 | if (*md5) { | 563 | if (*md5) { |
| 475 | opts->options |= OPTION_MD5; | 564 | opts->options |= OPTION_MD5; |
| 476 | size += TCPOLEN_MD5SIG_ALIGNED; | 565 | remaining -= TCPOLEN_MD5SIG_ALIGNED; |
| 477 | } | 566 | } |
| 478 | #else | 567 | #else |
| 479 | *md5 = NULL; | 568 | *md5 = NULL; |
| @@ -489,7 +578,7 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb, | |||
| 489 | * SACKs don't matter, we never delay an ACK when we have any of those | 578 | * SACKs don't matter, we never delay an ACK when we have any of those |
| 490 | * going out. */ | 579 | * going out. */ |
| 491 | opts->mss = tcp_advertise_mss(sk); | 580 | opts->mss = tcp_advertise_mss(sk); |
| 492 | size += TCPOLEN_MSS_ALIGNED; | 581 | remaining -= TCPOLEN_MSS_ALIGNED; |
| 493 | 582 | ||
| 494 | if (likely(sysctl_tcp_timestamps && | 583 | if (likely(sysctl_tcp_timestamps && |
| 495 | !dst_feature(dst, RTAX_FEATURE_NO_TSTAMP) && | 584 | !dst_feature(dst, RTAX_FEATURE_NO_TSTAMP) && |
| @@ -497,22 +586,68 @@ static unsigned tcp_syn_options(struct sock *sk, struct sk_buff *skb, | |||
| 497 | opts->options |= OPTION_TS; | 586 | opts->options |= OPTION_TS; |
| 498 | opts->tsval = TCP_SKB_CB(skb)->when; | 587 | opts->tsval = TCP_SKB_CB(skb)->when; |
| 499 | opts->tsecr = tp->rx_opt.ts_recent; | 588 | opts->tsecr = tp->rx_opt.ts_recent; |
| 500 | size += TCPOLEN_TSTAMP_ALIGNED; | 589 | remaining -= TCPOLEN_TSTAMP_ALIGNED; |
| 501 | } | 590 | } |
| 502 | if (likely(sysctl_tcp_window_scaling && | 591 | if (likely(sysctl_tcp_window_scaling && |
| 503 | !dst_feature(dst, RTAX_FEATURE_NO_WSCALE))) { | 592 | !dst_feature(dst, RTAX_FEATURE_NO_WSCALE))) { |
| 504 | opts->ws = tp->rx_opt.rcv_wscale; | 593 | opts->ws = tp->rx_opt.rcv_wscale; |
| 505 | opts->options |= OPTION_WSCALE; | 594 | opts->options |= OPTION_WSCALE; |
| 506 | size += TCPOLEN_WSCALE_ALIGNED; | 595 | remaining -= TCPOLEN_WSCALE_ALIGNED; |
| 507 | } | 596 | } |
| 508 | if (likely(sysctl_tcp_sack && | 597 | if (likely(sysctl_tcp_sack && |
| 509 | !dst_feature(dst, RTAX_FEATURE_NO_SACK))) { | 598 | !dst_feature(dst, RTAX_FEATURE_NO_SACK))) { |
| 510 | opts->options |= OPTION_SACK_ADVERTISE; | 599 | opts->options |= OPTION_SACK_ADVERTISE; |
| 511 | if (unlikely(!(OPTION_TS & opts->options))) | 600 | if (unlikely(!(OPTION_TS & opts->options))) |
| 512 | size += TCPOLEN_SACKPERM_ALIGNED; | 601 | remaining -= TCPOLEN_SACKPERM_ALIGNED; |
| 513 | } | 602 | } |
| 514 | 603 | ||
| 515 | return size; | 604 | /* Note that timestamps are required by the specification. |
| 605 | * | ||
| 606 | * Odd numbers of bytes are prohibited by the specification, ensuring | ||
| 607 | * that the cookie is 16-bit aligned, and the resulting cookie pair is | ||
| 608 | * 32-bit aligned. | ||
| 609 | */ | ||
| 610 | if (*md5 == NULL && | ||
| 611 | (OPTION_TS & opts->options) && | ||
| 612 | cookie_size > 0) { | ||
| 613 | int need = TCPOLEN_COOKIE_BASE + cookie_size; | ||
| 614 | |||
| 615 | if (0x2 & need) { | ||
| 616 | /* 32-bit multiple */ | ||
| 617 | need += 2; /* NOPs */ | ||
| 618 | |||
| 619 | if (need > remaining) { | ||
| 620 | /* try shrinking cookie to fit */ | ||
| 621 | cookie_size -= 2; | ||
| 622 | need -= 4; | ||
| 623 | } | ||
| 624 | } | ||
| 625 | while (need > remaining && TCP_COOKIE_MIN <= cookie_size) { | ||
| 626 | cookie_size -= 4; | ||
| 627 | need -= 4; | ||
| 628 | } | ||
| 629 | if (TCP_COOKIE_MIN <= cookie_size) { | ||
| 630 | opts->options |= OPTION_COOKIE_EXTENSION; | ||
| 631 | opts->hash_location = (__u8 *)&cvp->cookie_pair[0]; | ||
| 632 | opts->hash_size = cookie_size; | ||
| 633 | |||
| 634 | /* Remember for future incarnations. */ | ||
| 635 | cvp->cookie_desired = cookie_size; | ||
| 636 | |||
| 637 | if (cvp->cookie_desired != cvp->cookie_pair_size) { | ||
| 638 | /* Currently use random bytes as a nonce, | ||
| 639 | * assuming these are completely unpredictable | ||
| 640 | * by hostile users of the same system. | ||
| 641 | */ | ||
| 642 | get_random_bytes(&cvp->cookie_pair[0], | ||
| 643 | cookie_size); | ||
| 644 | cvp->cookie_pair_size = cookie_size; | ||
| 645 | } | ||
| 646 | |||
| 647 | remaining -= need; | ||
| 648 | } | ||
| 649 | } | ||
| 650 | return MAX_TCP_OPTION_SPACE - remaining; | ||
| 516 | } | 651 | } |
| 517 | 652 | ||
| 518 | /* Set up TCP options for SYN-ACKs. */ | 653 | /* Set up TCP options for SYN-ACKs. */ |
| @@ -627,7 +762,6 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 627 | struct tcp_out_options opts; | 762 | struct tcp_out_options opts; |
| 628 | unsigned tcp_options_size, tcp_header_size; | 763 | unsigned tcp_options_size, tcp_header_size; |
| 629 | struct tcp_md5sig_key *md5; | 764 | struct tcp_md5sig_key *md5; |
| 630 | __u8 *md5_hash_location; | ||
| 631 | struct tcphdr *th; | 765 | struct tcphdr *th; |
| 632 | int err; | 766 | int err; |
| 633 | 767 | ||
| @@ -698,7 +832,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 698 | } | 832 | } |
| 699 | } | 833 | } |
| 700 | 834 | ||
| 701 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); | 835 | tcp_options_write((__be32 *)(th + 1), tp, &opts); |
| 702 | if (likely((tcb->flags & TCPCB_FLAG_SYN) == 0)) | 836 | if (likely((tcb->flags & TCPCB_FLAG_SYN) == 0)) |
| 703 | TCP_ECN_send(sk, skb, tcp_header_size); | 837 | TCP_ECN_send(sk, skb, tcp_header_size); |
| 704 | 838 | ||
| @@ -706,7 +840,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 706 | /* Calculate the MD5 hash, as we have all we need now */ | 840 | /* Calculate the MD5 hash, as we have all we need now */ |
| 707 | if (md5) { | 841 | if (md5) { |
| 708 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 842 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
| 709 | tp->af_specific->calc_md5_hash(md5_hash_location, | 843 | tp->af_specific->calc_md5_hash(opts.hash_location, |
| 710 | md5, sk, NULL, skb); | 844 | md5, sk, NULL, skb); |
| 711 | } | 845 | } |
| 712 | #endif | 846 | #endif |
| @@ -2230,14 +2364,13 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
| 2230 | struct request_sock *req, | 2364 | struct request_sock *req, |
| 2231 | struct request_values *rvp) | 2365 | struct request_values *rvp) |
| 2232 | { | 2366 | { |
| 2367 | struct tcp_out_options opts; | ||
| 2233 | struct inet_request_sock *ireq = inet_rsk(req); | 2368 | struct inet_request_sock *ireq = inet_rsk(req); |
| 2234 | struct tcp_sock *tp = tcp_sk(sk); | 2369 | struct tcp_sock *tp = tcp_sk(sk); |
| 2235 | struct tcphdr *th; | 2370 | struct tcphdr *th; |
| 2236 | int tcp_header_size; | ||
| 2237 | struct tcp_out_options opts; | ||
| 2238 | struct sk_buff *skb; | 2371 | struct sk_buff *skb; |
| 2239 | struct tcp_md5sig_key *md5; | 2372 | struct tcp_md5sig_key *md5; |
| 2240 | __u8 *md5_hash_location; | 2373 | int tcp_header_size; |
| 2241 | int mss; | 2374 | int mss; |
| 2242 | 2375 | ||
| 2243 | skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); | 2376 | skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); |
| @@ -2298,14 +2431,14 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
| 2298 | 2431 | ||
| 2299 | /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ | 2432 | /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ |
| 2300 | th->window = htons(min(req->rcv_wnd, 65535U)); | 2433 | th->window = htons(min(req->rcv_wnd, 65535U)); |
| 2301 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); | 2434 | tcp_options_write((__be32 *)(th + 1), tp, &opts); |
| 2302 | th->doff = (tcp_header_size >> 2); | 2435 | th->doff = (tcp_header_size >> 2); |
| 2303 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); | 2436 | TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); |
| 2304 | 2437 | ||
| 2305 | #ifdef CONFIG_TCP_MD5SIG | 2438 | #ifdef CONFIG_TCP_MD5SIG |
| 2306 | /* Okay, we have all we need - do the md5 hash if needed */ | 2439 | /* Okay, we have all we need - do the md5 hash if needed */ |
| 2307 | if (md5) { | 2440 | if (md5) { |
| 2308 | tcp_rsk(req)->af_specific->calc_md5_hash(md5_hash_location, | 2441 | tcp_rsk(req)->af_specific->calc_md5_hash(opts.hash_location, |
| 2309 | md5, NULL, req, skb); | 2442 | md5, NULL, req, skb); |
| 2310 | } | 2443 | } |
| 2311 | #endif | 2444 | #endif |
