Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 289844
b: refs/heads/master
c: 658ddaa
h: refs/heads/master
v: v3
  • Loading branch information
Shawn Lu authored and David S. Miller committed Feb 1, 2012
1 parent 2a39cfd commit 1c14a61
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5b11b2e4bdef20e839d90dce96c5bbeafaf9616c
refs/heads/master: 658ddaaf6694adf63f67451dec9ddeb87a7cb2d7
45 changes: 42 additions & 3 deletions trunk/net/ipv4/tcp_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,10 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
struct ip_reply_arg arg;
#ifdef CONFIG_TCP_MD5SIG
struct tcp_md5sig_key *key;
const __u8 *hash_location = NULL;
unsigned char newhash[16];
int genhash;
struct sock *sk1 = NULL;
#endif
struct net *net;

Expand Down Expand Up @@ -623,9 +627,36 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
arg.iov[0].iov_len = sizeof(rep.th);

#ifdef CONFIG_TCP_MD5SIG
key = sk ? tcp_md5_do_lookup(sk,
(union tcp_md5_addr *)&ip_hdr(skb)->saddr,
AF_INET) : NULL;
hash_location = tcp_parse_md5sig_option(th);
if (!sk && hash_location) {
/*
* active side is lost. Try to find listening socket through
* source port, and then find md5 key through listening socket.
* we are not loose security here:
* Incoming packet is checked with md5 hash with finding key,
* no RST generated if md5 hash doesn't match.
*/
sk1 = __inet_lookup_listener(dev_net(skb_dst(skb)->dev),
&tcp_hashinfo, ip_hdr(skb)->daddr,
ntohs(th->source), inet_iif(skb));
/* don't send rst if it can't find key */
if (!sk1)
return;
rcu_read_lock();
key = tcp_md5_do_lookup(sk1, (union tcp_md5_addr *)
&ip_hdr(skb)->saddr, AF_INET);
if (!key)
goto release_sk1;

genhash = tcp_v4_md5_hash_skb(newhash, key, NULL, NULL, skb);
if (genhash || memcmp(hash_location, newhash, 16) != 0)
goto release_sk1;
} else {
key = sk ? tcp_md5_do_lookup(sk, (union tcp_md5_addr *)
&ip_hdr(skb)->saddr,
AF_INET) : NULL;
}

if (key) {
rep.opt[0] = htonl((TCPOPT_NOP << 24) |
(TCPOPT_NOP << 16) |
Expand Down Expand Up @@ -653,6 +684,14 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)

TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);

#ifdef CONFIG_TCP_MD5SIG
release_sk1:
if (sk1) {
rcu_read_unlock();
sock_put(sk1);
}
#endif
}

/* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
Expand Down
43 changes: 41 additions & 2 deletions trunk/net/ipv6/tcp_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,13 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
const struct tcphdr *th = tcp_hdr(skb);
u32 seq = 0, ack_seq = 0;
struct tcp_md5sig_key *key = NULL;
#ifdef CONFIG_TCP_MD5SIG
const __u8 *hash_location = NULL;
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
unsigned char newhash[16];
int genhash;
struct sock *sk1 = NULL;
#endif

if (th->rst)
return;
Expand All @@ -931,8 +938,32 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
return;

#ifdef CONFIG_TCP_MD5SIG
if (sk)
key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr);
hash_location = tcp_parse_md5sig_option(th);
if (!sk && hash_location) {
/*
* active side is lost. Try to find listening socket through
* source port, and then find md5 key through listening socket.
* we are not loose security here:
* Incoming packet is checked with md5 hash with finding key,
* no RST generated if md5 hash doesn't match.
*/
sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
&tcp_hashinfo, &ipv6h->daddr,
ntohs(th->source), inet6_iif(skb));
if (!sk1)
return;

rcu_read_lock();
key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr);
if (!key)
goto release_sk1;

genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, NULL, skb);
if (genhash || memcmp(hash_location, newhash, 16) != 0)
goto release_sk1;
} else {
key = sk ? tcp_v6_md5_do_lookup(sk, &ipv6h->saddr) : NULL;
}
#endif

if (th->ack)
Expand All @@ -942,6 +973,14 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
(th->doff << 2);

tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0);

#ifdef CONFIG_TCP_MD5SIG
release_sk1:
if (sk1) {
rcu_read_unlock();
sock_put(sk1);
}
#endif
}

static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
Expand Down

0 comments on commit 1c14a61

Please sign in to comment.