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 = {
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 {
];
} 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));
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;
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);
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);
}
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));
}
/*
#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)
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;
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;
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));
}