tcp md5sig: Let the caller pass appropriate key for tcp_v{4,6}_do_calc_md5_hash().
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Fri, 18 Apr 2008 03:45:16 +0000 (12:45 +0900)
committerYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Wed, 11 Jun 2008 18:46:30 +0000 (03:46 +0900)
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>
include/net/tcp.h
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c

index eac26b73bcc3f717c02d93d9ed1e2b6ce7e8fb1c..07005ebb47a731c74656c826ac640412b8d870ba 100644 (file)
@@ -1142,6 +1142,16 @@ extern int                       tcp_v4_md5_do_add(struct sock *sk,
 extern int                     tcp_v4_md5_do_del(struct sock *sk,
                                                  __be32 addr);
 
+#ifdef CONFIG_TCP_MD5SIG
+#define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_keylen ?                 \
+                                &(struct tcp_md5sig_key) {              \
+                                       .key = (twsk)->tw_md5_key,       \
+                                       .keylen = (twsk)->tw_md5_keylen, \
+                               } : NULL)
+#else
+#define tcp_twsk_md5_key(twsk) NULL
+#endif
+
 extern struct tcp_md5sig_pool  **tcp_alloc_md5sig_pool(void);
 extern void                    tcp_free_md5sig_pool(void);
 
index e331cdbd09537e7cb5e02a4a76aeff31b73c3c8d..f7ff2a64a7f054488cdaba6a32e0c986287642d3 100644 (file)
@@ -96,6 +96,12 @@ static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
 static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
                                   __be32 saddr, __be32 daddr,
                                   struct tcphdr *th, unsigned int tcplen);
+#else
+static inline
+struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
+{
+       return NULL;
+}
 #endif
 
 struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
@@ -604,9 +610,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
    outside socket context is ugly, certainly. What can I do?
  */
 
-static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
-                           struct sk_buff *skb, u32 seq, u32 ack,
-                           u32 win, u32 ts)
+static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
+                           u32 win, u32 ts, int oif,
+                           struct tcp_md5sig_key *key)
 {
        struct tcphdr *th = tcp_hdr(skb);
        struct {
@@ -618,10 +624,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
                        ];
        } rep;
        struct ip_reply_arg arg;
-#ifdef CONFIG_TCP_MD5SIG
-       struct tcp_md5sig_key *key;
-       struct tcp_md5sig_key tw_key;
-#endif
 
        memset(&rep.th, 0, sizeof(struct tcphdr));
        memset(&arg, 0, sizeof(arg));
@@ -647,23 +649,6 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
        rep.th.window  = htons(win);
 
 #ifdef CONFIG_TCP_MD5SIG
-       /*
-        * The SKB holds an imcoming packet, but may not have a valid ->sk
-        * pointer. This is especially the case when we're dealing with a
-        * TIME_WAIT ack, because the sk structure is long gone, and only
-        * the tcp_timewait_sock remains. So the md5 key is stashed in that
-        * structure, and we use it in preference.  I believe that (twsk ||
-        * skb->sk) holds true, but we program defensively.
-        */
-       if (!twsk && skb->sk) {
-               key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr);
-       } else if (twsk && twsk->tw_md5_keylen) {
-               tw_key.key = twsk->tw_md5_key;
-               tw_key.keylen = twsk->tw_md5_keylen;
-               key = &tw_key;
-       } else
-               key = NULL;
-
        if (key) {
                int offset = (ts) ? 3 : 0;
 
@@ -685,8 +670,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
                                      ip_hdr(skb)->saddr, /* XXX */
                                      arg.iov[0].iov_len, IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
-       if (twsk)
-               arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
+       if (oif)
+               arg.bound_dev_if = oif;
 
        ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb,
                      &arg, arg.iov[0].iov_len);
@@ -699,9 +684,12 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
        struct inet_timewait_sock *tw = inet_twsk(sk);
        struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
 
-       tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+       tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
-                       tcptw->tw_ts_recent);
+                       tcptw->tw_ts_recent,
+                       tw->tw_bound_dev_if,
+                       tcp_twsk_md5_key(tcptw)
+                       );
 
        inet_twsk_put(tw);
 }
@@ -709,9 +697,11 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
 static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
                                  struct request_sock *req)
 {
-       tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
+       tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1,
                        tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
-                       req->ts_recent);
+                       req->ts_recent,
+                       0,
+                       tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr));
 }
 
 /*
index 0ae0311082fbd22a47163b429d0423a3b88ea863..ecdbb9f46541ca1c2ef65a955248c62f12914b11 100644 (file)
@@ -82,6 +82,12 @@ static struct inet_connection_sock_af_ops ipv6_specific;
 #ifdef CONFIG_TCP_MD5SIG
 static struct tcp_sock_af_ops tcp_sock_ipv6_specific;
 static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
+#else
+static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
+                                                  struct in6_addr *addr)
+{
+       return NULL;
+}
 #endif
 
 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)
        kfree_skb(buff);
 }
 
-static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
-                           struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts)
+static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
+                           struct tcp_md5sig_key *key)
 {
        struct tcphdr *th = tcp_hdr(skb), *t1;
        struct sk_buff *buff;
@@ -1021,22 +1027,6 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
        struct sock *ctl_sk = net->ipv6.tcp_sk;
        unsigned int tot_len = sizeof(struct tcphdr);
        __be32 *topt;
-#ifdef CONFIG_TCP_MD5SIG
-       struct tcp_md5sig_key *key;
-       struct tcp_md5sig_key tw_key;
-#endif
-
-#ifdef CONFIG_TCP_MD5SIG
-       if (!tw && skb->sk) {
-               key = tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr);
-       } else if (tw && tw->tw_md5_keylen) {
-               tw_key.key = tw->tw_md5_key;
-               tw_key.keylen = tw->tw_md5_keylen;
-               key = &tw_key;
-       } else {
-               key = NULL;
-       }
-#endif
 
        if (ts)
                tot_len += TCPOLEN_TSTAMP_ALIGNED;
@@ -1116,16 +1106,17 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
        struct inet_timewait_sock *tw = inet_twsk(sk);
        struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
 
-       tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+       tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
-                       tcptw->tw_ts_recent);
+                       tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw));
 
        inet_twsk_put(tw);
 }
 
 static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
 {
-       tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent);
+       tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
+                       tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr));
 }