aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_ipv4.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 13:37:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 13:37:28 -0400
commitd7e9660ad9d5e0845f52848bce31bcf5cdcdea6b (patch)
treec6c67d145771187b194d79d603742b31090a59d6 /net/ipv4/tcp_ipv4.c
parentb8cb48aae1b8c50b37dcb7710363aa69a7a0d9ca (diff)
parent13af7a6ea502fcdd4c0e3d7de6e332b102309491 (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.c66
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
331void tcp_v4_err(struct sk_buff *skb, u32 info) 331void 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
1161static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { 1199static 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
1720struct inet_connection_sock_af_ops ipv4_specific = { 1758const 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
1740static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { 1778static 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,