aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/tcp.h10
-rw-r--r--net/ipv4/tcp_ipv4.c50
-rw-r--r--net/ipv6/tcp_ipv6.c33
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,
1142extern int tcp_v4_md5_do_del(struct sock *sk, 1142extern 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
1145extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void); 1155extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void);
1146extern void tcp_free_md5sig_pool(void); 1156extern 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,
96static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, 96static 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
100static inline
101struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
102{
103 return NULL;
104}
99#endif 105#endif
100 106
101struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { 107struct 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
607static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, 613static 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)
709static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, 697static 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
83static struct tcp_sock_af_ops tcp_sock_ipv6_specific; 83static struct tcp_sock_af_ops tcp_sock_ipv6_specific;
84static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; 84static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
85#else
86static 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
87static void tcp_v6_hash(struct sock *sk) 93static 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
1014static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, 1020static 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
1126static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) 1116static 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