diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 13:37:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 13:37:28 -0400 |
commit | d7e9660ad9d5e0845f52848bce31bcf5cdcdea6b (patch) | |
tree | c6c67d145771187b194d79d603742b31090a59d6 /net/ipv4/tcp_ipv4.c | |
parent | b8cb48aae1b8c50b37dcb7710363aa69a7a0d9ca (diff) | |
parent | 13af7a6ea502fcdd4c0e3d7de6e332b102309491 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1623 commits)
netxen: update copyright
netxen: fix tx timeout recovery
netxen: fix file firmware leak
netxen: improve pci memory access
netxen: change firmware write size
tg3: Fix return ring size breakage
netxen: build fix for INET=n
cdc-phonet: autoconfigure Phonet address
Phonet: back-end for autoconfigured addresses
Phonet: fix netlink address dump error handling
ipv6: Add IFA_F_DADFAILED flag
net: Add DEVTYPE support for Ethernet based devices
mv643xx_eth.c: remove unused txq_set_wrr()
ucc_geth: Fix hangs after switching from full to half duplex
ucc_geth: Rearrange some code to avoid forward declarations
phy/marvell: Make non-aneg speed/duplex forcing work for 88E1111 PHYs
drivers/net/phy: introduce missing kfree
drivers/net/wan: introduce missing kfree
net: force bridge module(s) to be GPL
Subject: [PATCH] appletalk: Fix skb leak when ipddp interface is not loaded
...
Fixed up trivial conflicts:
- arch/x86/include/asm/socket.h
converted to <asm-generic/socket.h> in the x86 tree. The generic
header has the same new #define's, so that works out fine.
- drivers/net/tun.c
fix conflict between 89f56d1e9 ("tun: reuse struct sock fields") that
switched over to using 'tun->socket.sk' instead of the redundantly
available (and thus removed) 'tun->sk', and 2b980dbd ("lsm: Add hooks
to the TUN driver") which added a new 'tun->sk' use.
Noted in 'next' by Stephen Rothwell.
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 66 |
1 files changed, 52 insertions, 14 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 6d88219c5e22..0543561da999 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -328,26 +328,29 @@ static void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, u32 mtu) | |||
328 | * | 328 | * |
329 | */ | 329 | */ |
330 | 330 | ||
331 | void tcp_v4_err(struct sk_buff *skb, u32 info) | 331 | void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) |
332 | { | 332 | { |
333 | struct iphdr *iph = (struct iphdr *)skb->data; | 333 | struct iphdr *iph = (struct iphdr *)icmp_skb->data; |
334 | struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); | 334 | struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2)); |
335 | struct inet_connection_sock *icsk; | ||
335 | struct tcp_sock *tp; | 336 | struct tcp_sock *tp; |
336 | struct inet_sock *inet; | 337 | struct inet_sock *inet; |
337 | const int type = icmp_hdr(skb)->type; | 338 | const int type = icmp_hdr(icmp_skb)->type; |
338 | const int code = icmp_hdr(skb)->code; | 339 | const int code = icmp_hdr(icmp_skb)->code; |
339 | struct sock *sk; | 340 | struct sock *sk; |
341 | struct sk_buff *skb; | ||
340 | __u32 seq; | 342 | __u32 seq; |
343 | __u32 remaining; | ||
341 | int err; | 344 | int err; |
342 | struct net *net = dev_net(skb->dev); | 345 | struct net *net = dev_net(icmp_skb->dev); |
343 | 346 | ||
344 | if (skb->len < (iph->ihl << 2) + 8) { | 347 | if (icmp_skb->len < (iph->ihl << 2) + 8) { |
345 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | 348 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); |
346 | return; | 349 | return; |
347 | } | 350 | } |
348 | 351 | ||
349 | sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest, | 352 | sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest, |
350 | iph->saddr, th->source, inet_iif(skb)); | 353 | iph->saddr, th->source, inet_iif(icmp_skb)); |
351 | if (!sk) { | 354 | if (!sk) { |
352 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | 355 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); |
353 | return; | 356 | return; |
@@ -367,6 +370,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) | |||
367 | if (sk->sk_state == TCP_CLOSE) | 370 | if (sk->sk_state == TCP_CLOSE) |
368 | goto out; | 371 | goto out; |
369 | 372 | ||
373 | icsk = inet_csk(sk); | ||
370 | tp = tcp_sk(sk); | 374 | tp = tcp_sk(sk); |
371 | seq = ntohl(th->seq); | 375 | seq = ntohl(th->seq); |
372 | if (sk->sk_state != TCP_LISTEN && | 376 | if (sk->sk_state != TCP_LISTEN && |
@@ -393,6 +397,39 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) | |||
393 | } | 397 | } |
394 | 398 | ||
395 | err = icmp_err_convert[code].errno; | 399 | err = icmp_err_convert[code].errno; |
400 | /* check if icmp_skb allows revert of backoff | ||
401 | * (see draft-zimmermann-tcp-lcd) */ | ||
402 | if (code != ICMP_NET_UNREACH && code != ICMP_HOST_UNREACH) | ||
403 | break; | ||
404 | if (seq != tp->snd_una || !icsk->icsk_retransmits || | ||
405 | !icsk->icsk_backoff) | ||
406 | break; | ||
407 | |||
408 | icsk->icsk_backoff--; | ||
409 | inet_csk(sk)->icsk_rto = __tcp_set_rto(tp) << | ||
410 | icsk->icsk_backoff; | ||
411 | tcp_bound_rto(sk); | ||
412 | |||
413 | skb = tcp_write_queue_head(sk); | ||
414 | BUG_ON(!skb); | ||
415 | |||
416 | remaining = icsk->icsk_rto - min(icsk->icsk_rto, | ||
417 | tcp_time_stamp - TCP_SKB_CB(skb)->when); | ||
418 | |||
419 | if (remaining) { | ||
420 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | ||
421 | remaining, TCP_RTO_MAX); | ||
422 | } else if (sock_owned_by_user(sk)) { | ||
423 | /* RTO revert clocked out retransmission, | ||
424 | * but socket is locked. Will defer. */ | ||
425 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | ||
426 | HZ/20, TCP_RTO_MAX); | ||
427 | } else { | ||
428 | /* RTO revert clocked out retransmission. | ||
429 | * Will retransmit now */ | ||
430 | tcp_retransmit_timer(sk); | ||
431 | } | ||
432 | |||
396 | break; | 433 | break; |
397 | case ICMP_TIME_EXCEEDED: | 434 | case ICMP_TIME_EXCEEDED: |
398 | err = EHOSTUNREACH; | 435 | err = EHOSTUNREACH; |
@@ -849,7 +886,7 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | |||
849 | } | 886 | } |
850 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 887 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
851 | } | 888 | } |
852 | if (tcp_alloc_md5sig_pool() == NULL) { | 889 | if (tcp_alloc_md5sig_pool(sk) == NULL) { |
853 | kfree(newkey); | 890 | kfree(newkey); |
854 | return -ENOMEM; | 891 | return -ENOMEM; |
855 | } | 892 | } |
@@ -970,8 +1007,9 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
970 | 1007 | ||
971 | if (!tcp_sk(sk)->md5sig_info) { | 1008 | if (!tcp_sk(sk)->md5sig_info) { |
972 | struct tcp_sock *tp = tcp_sk(sk); | 1009 | struct tcp_sock *tp = tcp_sk(sk); |
973 | struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL); | 1010 | struct tcp_md5sig_info *p; |
974 | 1011 | ||
1012 | p = kzalloc(sizeof(*p), sk->sk_allocation); | ||
975 | if (!p) | 1013 | if (!p) |
976 | return -EINVAL; | 1014 | return -EINVAL; |
977 | 1015 | ||
@@ -979,7 +1017,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
979 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1017 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
980 | } | 1018 | } |
981 | 1019 | ||
982 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); | 1020 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation); |
983 | if (!newkey) | 1021 | if (!newkey) |
984 | return -ENOMEM; | 1022 | return -ENOMEM; |
985 | return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, | 1023 | return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, |
@@ -1158,7 +1196,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { | |||
1158 | }; | 1196 | }; |
1159 | 1197 | ||
1160 | #ifdef CONFIG_TCP_MD5SIG | 1198 | #ifdef CONFIG_TCP_MD5SIG |
1161 | static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { | 1199 | static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { |
1162 | .md5_lookup = tcp_v4_reqsk_md5_lookup, | 1200 | .md5_lookup = tcp_v4_reqsk_md5_lookup, |
1163 | .calc_md5_hash = tcp_v4_md5_hash_skb, | 1201 | .calc_md5_hash = tcp_v4_md5_hash_skb, |
1164 | }; | 1202 | }; |
@@ -1717,7 +1755,7 @@ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw) | |||
1717 | return 0; | 1755 | return 0; |
1718 | } | 1756 | } |
1719 | 1757 | ||
1720 | struct inet_connection_sock_af_ops ipv4_specific = { | 1758 | const struct inet_connection_sock_af_ops ipv4_specific = { |
1721 | .queue_xmit = ip_queue_xmit, | 1759 | .queue_xmit = ip_queue_xmit, |
1722 | .send_check = tcp_v4_send_check, | 1760 | .send_check = tcp_v4_send_check, |
1723 | .rebuild_header = inet_sk_rebuild_header, | 1761 | .rebuild_header = inet_sk_rebuild_header, |
@@ -1737,7 +1775,7 @@ struct inet_connection_sock_af_ops ipv4_specific = { | |||
1737 | }; | 1775 | }; |
1738 | 1776 | ||
1739 | #ifdef CONFIG_TCP_MD5SIG | 1777 | #ifdef CONFIG_TCP_MD5SIG |
1740 | static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { | 1778 | static const struct tcp_sock_af_ops tcp_sock_ipv4_specific = { |
1741 | .md5_lookup = tcp_v4_md5_lookup, | 1779 | .md5_lookup = tcp_v4_md5_lookup, |
1742 | .calc_md5_hash = tcp_v4_md5_hash_skb, | 1780 | .calc_md5_hash = tcp_v4_md5_hash_skb, |
1743 | .md5_add = tcp_v4_md5_add_func, | 1781 | .md5_add = tcp_v4_md5_add_func, |