diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-04-17 23:45:16 -0400 |
---|---|---|
committer | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-06-11 14:46:30 -0400 |
commit | 9501f9722922f2e80e1f9dc6682311d65c2b5690 (patch) | |
tree | ca8195e04ea63e8273801030ce26527fe5a8a7c7 | |
parent | 8d26d76dd4a4c87ef037a44a42a0608ffc730199 (diff) |
tcp md5sig: Let the caller pass appropriate key for tcp_v{4,6}_do_calc_md5_hash().
As we do for other socket/timewait-socket specific parameters,
let the callers pass appropriate arguments to
tcp_v{4,6}_do_calc_md5_hash().
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
-rw-r--r-- | include/net/tcp.h | 10 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 50 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 33 |
3 files changed, 42 insertions, 51 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index eac26b73bcc3..07005ebb47a7 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1142,6 +1142,16 @@ extern int tcp_v4_md5_do_add(struct sock *sk, | |||
1142 | extern int tcp_v4_md5_do_del(struct sock *sk, | 1142 | extern int tcp_v4_md5_do_del(struct sock *sk, |
1143 | __be32 addr); | 1143 | __be32 addr); |
1144 | 1144 | ||
1145 | #ifdef CONFIG_TCP_MD5SIG | ||
1146 | #define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_keylen ? \ | ||
1147 | &(struct tcp_md5sig_key) { \ | ||
1148 | .key = (twsk)->tw_md5_key, \ | ||
1149 | .keylen = (twsk)->tw_md5_keylen, \ | ||
1150 | } : NULL) | ||
1151 | #else | ||
1152 | #define tcp_twsk_md5_key(twsk) NULL | ||
1153 | #endif | ||
1154 | |||
1145 | extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void); | 1155 | extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void); |
1146 | extern void tcp_free_md5sig_pool(void); | 1156 | extern void tcp_free_md5sig_pool(void); |
1147 | 1157 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index e331cdbd0953..f7ff2a64a7f0 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -96,6 +96,12 @@ static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, | |||
96 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | 96 | static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, |
97 | __be32 saddr, __be32 daddr, | 97 | __be32 saddr, __be32 daddr, |
98 | struct tcphdr *th, unsigned int tcplen); | 98 | struct tcphdr *th, unsigned int tcplen); |
99 | #else | ||
100 | static inline | ||
101 | struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) | ||
102 | { | ||
103 | return NULL; | ||
104 | } | ||
99 | #endif | 105 | #endif |
100 | 106 | ||
101 | struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { | 107 | struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { |
@@ -604,9 +610,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
604 | outside socket context is ugly, certainly. What can I do? | 610 | outside socket context is ugly, certainly. What can I do? |
605 | */ | 611 | */ |
606 | 612 | ||
607 | static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | 613 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, |
608 | struct sk_buff *skb, u32 seq, u32 ack, | 614 | u32 win, u32 ts, int oif, |
609 | u32 win, u32 ts) | 615 | struct tcp_md5sig_key *key) |
610 | { | 616 | { |
611 | struct tcphdr *th = tcp_hdr(skb); | 617 | struct tcphdr *th = tcp_hdr(skb); |
612 | struct { | 618 | struct { |
@@ -618,10 +624,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | |||
618 | ]; | 624 | ]; |
619 | } rep; | 625 | } rep; |
620 | struct ip_reply_arg arg; | 626 | struct ip_reply_arg arg; |
621 | #ifdef CONFIG_TCP_MD5SIG | ||
622 | struct tcp_md5sig_key *key; | ||
623 | struct tcp_md5sig_key tw_key; | ||
624 | #endif | ||
625 | 627 | ||
626 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 628 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
627 | memset(&arg, 0, sizeof(arg)); | 629 | memset(&arg, 0, sizeof(arg)); |
@@ -647,23 +649,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | |||
647 | rep.th.window = htons(win); | 649 | rep.th.window = htons(win); |
648 | 650 | ||
649 | #ifdef CONFIG_TCP_MD5SIG | 651 | #ifdef CONFIG_TCP_MD5SIG |
650 | /* | ||
651 | * The SKB holds an imcoming packet, but may not have a valid ->sk | ||
652 | * pointer. This is especially the case when we're dealing with a | ||
653 | * TIME_WAIT ack, because the sk structure is long gone, and only | ||
654 | * the tcp_timewait_sock remains. So the md5 key is stashed in that | ||
655 | * structure, and we use it in preference. I believe that (twsk || | ||
656 | * skb->sk) holds true, but we program defensively. | ||
657 | */ | ||
658 | if (!twsk && skb->sk) { | ||
659 | key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr); | ||
660 | } else if (twsk && twsk->tw_md5_keylen) { | ||
661 | tw_key.key = twsk->tw_md5_key; | ||
662 | tw_key.keylen = twsk->tw_md5_keylen; | ||
663 | key = &tw_key; | ||
664 | } else | ||
665 | key = NULL; | ||
666 | |||
667 | if (key) { | 652 | if (key) { |
668 | int offset = (ts) ? 3 : 0; | 653 | int offset = (ts) ? 3 : 0; |
669 | 654 | ||
@@ -685,8 +670,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, | |||
685 | ip_hdr(skb)->saddr, /* XXX */ | 670 | ip_hdr(skb)->saddr, /* XXX */ |
686 | arg.iov[0].iov_len, IPPROTO_TCP, 0); | 671 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
687 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 672 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
688 | if (twsk) | 673 | if (oif) |
689 | arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if; | 674 | arg.bound_dev_if = oif; |
690 | 675 | ||
691 | ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb, | 676 | ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb, |
692 | &arg, arg.iov[0].iov_len); | 677 | &arg, arg.iov[0].iov_len); |
@@ -699,9 +684,12 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
699 | struct inet_timewait_sock *tw = inet_twsk(sk); | 684 | struct inet_timewait_sock *tw = inet_twsk(sk); |
700 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 685 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
701 | 686 | ||
702 | tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 687 | tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
703 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 688 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
704 | tcptw->tw_ts_recent); | 689 | tcptw->tw_ts_recent, |
690 | tw->tw_bound_dev_if, | ||
691 | tcp_twsk_md5_key(tcptw) | ||
692 | ); | ||
705 | 693 | ||
706 | inet_twsk_put(tw); | 694 | inet_twsk_put(tw); |
707 | } | 695 | } |
@@ -709,9 +697,11 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
709 | static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, | 697 | static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, |
710 | struct request_sock *req) | 698 | struct request_sock *req) |
711 | { | 699 | { |
712 | tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, | 700 | tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, |
713 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 701 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, |
714 | req->ts_recent); | 702 | req->ts_recent, |
703 | 0, | ||
704 | tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr)); | ||
715 | } | 705 | } |
716 | 706 | ||
717 | /* | 707 | /* |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0ae0311082fb..ecdbb9f46541 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -82,6 +82,12 @@ static struct inet_connection_sock_af_ops ipv6_specific; | |||
82 | #ifdef CONFIG_TCP_MD5SIG | 82 | #ifdef CONFIG_TCP_MD5SIG |
83 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific; | 83 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific; |
84 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; | 84 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; |
85 | #else | ||
86 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | ||
87 | struct in6_addr *addr) | ||
88 | { | ||
89 | return NULL; | ||
90 | } | ||
85 | #endif | 91 | #endif |
86 | 92 | ||
87 | static void tcp_v6_hash(struct sock *sk) | 93 | static void tcp_v6_hash(struct sock *sk) |
@@ -1011,8 +1017,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1011 | kfree_skb(buff); | 1017 | kfree_skb(buff); |
1012 | } | 1018 | } |
1013 | 1019 | ||
1014 | static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | 1020 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, |
1015 | struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) | 1021 | struct tcp_md5sig_key *key) |
1016 | { | 1022 | { |
1017 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1023 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1018 | struct sk_buff *buff; | 1024 | struct sk_buff *buff; |
@@ -1021,22 +1027,6 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1021 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 1027 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
1022 | unsigned int tot_len = sizeof(struct tcphdr); | 1028 | unsigned int tot_len = sizeof(struct tcphdr); |
1023 | __be32 *topt; | 1029 | __be32 *topt; |
1024 | #ifdef CONFIG_TCP_MD5SIG | ||
1025 | struct tcp_md5sig_key *key; | ||
1026 | struct tcp_md5sig_key tw_key; | ||
1027 | #endif | ||
1028 | |||
1029 | #ifdef CONFIG_TCP_MD5SIG | ||
1030 | if (!tw && skb->sk) { | ||
1031 | key = tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr); | ||
1032 | } else if (tw && tw->tw_md5_keylen) { | ||
1033 | tw_key.key = tw->tw_md5_key; | ||
1034 | tw_key.keylen = tw->tw_md5_keylen; | ||
1035 | key = &tw_key; | ||
1036 | } else { | ||
1037 | key = NULL; | ||
1038 | } | ||
1039 | #endif | ||
1040 | 1030 | ||
1041 | if (ts) | 1031 | if (ts) |
1042 | tot_len += TCPOLEN_TSTAMP_ALIGNED; | 1032 | tot_len += TCPOLEN_TSTAMP_ALIGNED; |
@@ -1116,16 +1106,17 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
1116 | struct inet_timewait_sock *tw = inet_twsk(sk); | 1106 | struct inet_timewait_sock *tw = inet_twsk(sk); |
1117 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 1107 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
1118 | 1108 | ||
1119 | tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 1109 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
1120 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 1110 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
1121 | tcptw->tw_ts_recent); | 1111 | tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw)); |
1122 | 1112 | ||
1123 | inet_twsk_put(tw); | 1113 | inet_twsk_put(tw); |
1124 | } | 1114 | } |
1125 | 1115 | ||
1126 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | 1116 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) |
1127 | { | 1117 | { |
1128 | tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); | 1118 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, |
1119 | tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr)); | ||
1129 | } | 1120 | } |
1130 | 1121 | ||
1131 | 1122 | ||