aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/af_inet.c16
-rw-r--r--net/ipv4/arp.c11
-rw-r--r--net/ipv4/devinet.c30
-rw-r--r--net/ipv4/inet_timewait_sock.c2
-rw-r--r--net/ipv4/inetpeer.c2
-rw-r--r--net/ipv4/ip_gre.c1
-rw-r--r--net/ipv4/ipmr.c76
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c6
-rw-r--r--net/ipv4/raw.c19
-rw-r--r--net/ipv4/route.c7
-rw-r--r--net/ipv4/tcp_input.c7
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv4/tcp_output.c2
13 files changed, 155 insertions, 25 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index f2b61107df6c..45b89d7bda5a 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -880,6 +880,19 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
880} 880}
881EXPORT_SYMBOL(inet_ioctl); 881EXPORT_SYMBOL(inet_ioctl);
882 882
883#ifdef CONFIG_COMPAT
884int inet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
885{
886 struct sock *sk = sock->sk;
887 int err = -ENOIOCTLCMD;
888
889 if (sk->sk_prot->compat_ioctl)
890 err = sk->sk_prot->compat_ioctl(sk, cmd, arg);
891
892 return err;
893}
894#endif
895
883const struct proto_ops inet_stream_ops = { 896const struct proto_ops inet_stream_ops = {
884 .family = PF_INET, 897 .family = PF_INET,
885 .owner = THIS_MODULE, 898 .owner = THIS_MODULE,
@@ -903,6 +916,7 @@ const struct proto_ops inet_stream_ops = {
903#ifdef CONFIG_COMPAT 916#ifdef CONFIG_COMPAT
904 .compat_setsockopt = compat_sock_common_setsockopt, 917 .compat_setsockopt = compat_sock_common_setsockopt,
905 .compat_getsockopt = compat_sock_common_getsockopt, 918 .compat_getsockopt = compat_sock_common_getsockopt,
919 .compat_ioctl = inet_compat_ioctl,
906#endif 920#endif
907}; 921};
908EXPORT_SYMBOL(inet_stream_ops); 922EXPORT_SYMBOL(inet_stream_ops);
@@ -929,6 +943,7 @@ const struct proto_ops inet_dgram_ops = {
929#ifdef CONFIG_COMPAT 943#ifdef CONFIG_COMPAT
930 .compat_setsockopt = compat_sock_common_setsockopt, 944 .compat_setsockopt = compat_sock_common_setsockopt,
931 .compat_getsockopt = compat_sock_common_getsockopt, 945 .compat_getsockopt = compat_sock_common_getsockopt,
946 .compat_ioctl = inet_compat_ioctl,
932#endif 947#endif
933}; 948};
934EXPORT_SYMBOL(inet_dgram_ops); 949EXPORT_SYMBOL(inet_dgram_ops);
@@ -959,6 +974,7 @@ static const struct proto_ops inet_sockraw_ops = {
959#ifdef CONFIG_COMPAT 974#ifdef CONFIG_COMPAT
960 .compat_setsockopt = compat_sock_common_setsockopt, 975 .compat_setsockopt = compat_sock_common_setsockopt,
961 .compat_getsockopt = compat_sock_common_getsockopt, 976 .compat_getsockopt = compat_sock_common_getsockopt,
977 .compat_ioctl = inet_compat_ioctl,
962#endif 978#endif
963}; 979};
964 980
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 04c8b69fd426..7927589813b5 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1017,14 +1017,13 @@ static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on)
1017 IPV4_DEVCONF_ALL(net, PROXY_ARP) = on; 1017 IPV4_DEVCONF_ALL(net, PROXY_ARP) = on;
1018 return 0; 1018 return 0;
1019 } 1019 }
1020 if (__in_dev_get_rcu(dev)) { 1020 if (__in_dev_get_rtnl(dev)) {
1021 IN_DEV_CONF_SET(__in_dev_get_rcu(dev), PROXY_ARP, on); 1021 IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on);
1022 return 0; 1022 return 0;
1023 } 1023 }
1024 return -ENXIO; 1024 return -ENXIO;
1025} 1025}
1026 1026
1027/* must be called with rcu_read_lock() */
1028static int arp_req_set_public(struct net *net, struct arpreq *r, 1027static int arp_req_set_public(struct net *net, struct arpreq *r,
1029 struct net_device *dev) 1028 struct net_device *dev)
1030{ 1029{
@@ -1233,10 +1232,10 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1233 if (!(r.arp_flags & ATF_NETMASK)) 1232 if (!(r.arp_flags & ATF_NETMASK))
1234 ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr = 1233 ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr =
1235 htonl(0xFFFFFFFFUL); 1234 htonl(0xFFFFFFFFUL);
1236 rcu_read_lock(); 1235 rtnl_lock();
1237 if (r.arp_dev[0]) { 1236 if (r.arp_dev[0]) {
1238 err = -ENODEV; 1237 err = -ENODEV;
1239 dev = dev_get_by_name_rcu(net, r.arp_dev); 1238 dev = __dev_get_by_name(net, r.arp_dev);
1240 if (dev == NULL) 1239 if (dev == NULL)
1241 goto out; 1240 goto out;
1242 1241
@@ -1263,7 +1262,7 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1263 break; 1262 break;
1264 } 1263 }
1265out: 1264out:
1266 rcu_read_unlock(); 1265 rtnl_unlock();
1267 if (cmd == SIOCGARP && !err && copy_to_user(arg, &r, sizeof(r))) 1266 if (cmd == SIOCGARP && !err && copy_to_user(arg, &r, sizeof(r)))
1268 err = -EFAULT; 1267 err = -EFAULT;
1269 return err; 1268 return err;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 748cb5b337bd..df4616fce929 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1030,6 +1030,21 @@ static inline bool inetdev_valid_mtu(unsigned mtu)
1030 return mtu >= 68; 1030 return mtu >= 68;
1031} 1031}
1032 1032
1033static void inetdev_send_gratuitous_arp(struct net_device *dev,
1034 struct in_device *in_dev)
1035
1036{
1037 struct in_ifaddr *ifa = in_dev->ifa_list;
1038
1039 if (!ifa)
1040 return;
1041
1042 arp_send(ARPOP_REQUEST, ETH_P_ARP,
1043 ifa->ifa_address, dev,
1044 ifa->ifa_address, NULL,
1045 dev->dev_addr, NULL);
1046}
1047
1033/* Called only under RTNL semaphore */ 1048/* Called only under RTNL semaphore */
1034 1049
1035static int inetdev_event(struct notifier_block *this, unsigned long event, 1050static int inetdev_event(struct notifier_block *this, unsigned long event,
@@ -1082,18 +1097,13 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
1082 } 1097 }
1083 ip_mc_up(in_dev); 1098 ip_mc_up(in_dev);
1084 /* fall through */ 1099 /* fall through */
1085 case NETDEV_NOTIFY_PEERS:
1086 case NETDEV_CHANGEADDR: 1100 case NETDEV_CHANGEADDR:
1101 if (!IN_DEV_ARP_NOTIFY(in_dev))
1102 break;
1103 /* fall through */
1104 case NETDEV_NOTIFY_PEERS:
1087 /* Send gratuitous ARP to notify of link change */ 1105 /* Send gratuitous ARP to notify of link change */
1088 if (IN_DEV_ARP_NOTIFY(in_dev)) { 1106 inetdev_send_gratuitous_arp(dev, in_dev);
1089 struct in_ifaddr *ifa = in_dev->ifa_list;
1090
1091 if (ifa)
1092 arp_send(ARPOP_REQUEST, ETH_P_ARP,
1093 ifa->ifa_address, dev,
1094 ifa->ifa_address, NULL,
1095 dev->dev_addr, NULL);
1096 }
1097 break; 1107 break;
1098 case NETDEV_DOWN: 1108 case NETDEV_DOWN:
1099 ip_mc_down(in_dev); 1109 ip_mc_down(in_dev);
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index c5af909cf701..3c8dfa16614d 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -505,7 +505,9 @@ restart:
505 } 505 }
506 506
507 rcu_read_unlock(); 507 rcu_read_unlock();
508 local_bh_disable();
508 inet_twsk_deschedule(tw, twdr); 509 inet_twsk_deschedule(tw, twdr);
510 local_bh_enable();
509 inet_twsk_put(tw); 511 inet_twsk_put(tw);
510 goto restart_rcu; 512 goto restart_rcu;
511 } 513 }
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index d9bc85751c74..a96e65674ac3 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -475,7 +475,7 @@ static int cleanup_once(unsigned long ttl)
475struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create) 475struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
476{ 476{
477 struct inet_peer __rcu **stack[PEER_MAXDEPTH], ***stackptr; 477 struct inet_peer __rcu **stack[PEER_MAXDEPTH], ***stackptr;
478 struct inet_peer_base *base = family_to_base(AF_INET); 478 struct inet_peer_base *base = family_to_base(daddr->family);
479 struct inet_peer *p; 479 struct inet_peer *p;
480 480
481 /* Look up for the address quickly, lockless. 481 /* Look up for the address quickly, lockless.
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index eb68a0e34e49..6613edfac28c 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -775,6 +775,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
775 .fl4_dst = dst, 775 .fl4_dst = dst,
776 .fl4_src = tiph->saddr, 776 .fl4_src = tiph->saddr,
777 .fl4_tos = RT_TOS(tos), 777 .fl4_tos = RT_TOS(tos),
778 .proto = IPPROTO_GRE,
778 .fl_gre_key = tunnel->parms.o_key 779 .fl_gre_key = tunnel->parms.o_key
779 }; 780 };
780 if (ip_route_output_key(dev_net(dev), &rt, &fl)) { 781 if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 3f3a9afd73e0..8b65a12654e7 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -60,6 +60,7 @@
60#include <linux/notifier.h> 60#include <linux/notifier.h>
61#include <linux/if_arp.h> 61#include <linux/if_arp.h>
62#include <linux/netfilter_ipv4.h> 62#include <linux/netfilter_ipv4.h>
63#include <linux/compat.h>
63#include <net/ipip.h> 64#include <net/ipip.h>
64#include <net/checksum.h> 65#include <net/checksum.h>
65#include <net/netlink.h> 66#include <net/netlink.h>
@@ -1434,6 +1435,81 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
1434 } 1435 }
1435} 1436}
1436 1437
1438#ifdef CONFIG_COMPAT
1439struct compat_sioc_sg_req {
1440 struct in_addr src;
1441 struct in_addr grp;
1442 compat_ulong_t pktcnt;
1443 compat_ulong_t bytecnt;
1444 compat_ulong_t wrong_if;
1445};
1446
1447struct compat_sioc_vif_req {
1448 vifi_t vifi; /* Which iface */
1449 compat_ulong_t icount;
1450 compat_ulong_t ocount;
1451 compat_ulong_t ibytes;
1452 compat_ulong_t obytes;
1453};
1454
1455int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1456{
1457 struct compat_sioc_sg_req sr;
1458 struct compat_sioc_vif_req vr;
1459 struct vif_device *vif;
1460 struct mfc_cache *c;
1461 struct net *net = sock_net(sk);
1462 struct mr_table *mrt;
1463
1464 mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
1465 if (mrt == NULL)
1466 return -ENOENT;
1467
1468 switch (cmd) {
1469 case SIOCGETVIFCNT:
1470 if (copy_from_user(&vr, arg, sizeof(vr)))
1471 return -EFAULT;
1472 if (vr.vifi >= mrt->maxvif)
1473 return -EINVAL;
1474 read_lock(&mrt_lock);
1475 vif = &mrt->vif_table[vr.vifi];
1476 if (VIF_EXISTS(mrt, vr.vifi)) {
1477 vr.icount = vif->pkt_in;
1478 vr.ocount = vif->pkt_out;
1479 vr.ibytes = vif->bytes_in;
1480 vr.obytes = vif->bytes_out;
1481 read_unlock(&mrt_lock);
1482
1483 if (copy_to_user(arg, &vr, sizeof(vr)))
1484 return -EFAULT;
1485 return 0;
1486 }
1487 read_unlock(&mrt_lock);
1488 return -EADDRNOTAVAIL;
1489 case SIOCGETSGCNT:
1490 if (copy_from_user(&sr, arg, sizeof(sr)))
1491 return -EFAULT;
1492
1493 rcu_read_lock();
1494 c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr);
1495 if (c) {
1496 sr.pktcnt = c->mfc_un.res.pkt;
1497 sr.bytecnt = c->mfc_un.res.bytes;
1498 sr.wrong_if = c->mfc_un.res.wrong_if;
1499 rcu_read_unlock();
1500
1501 if (copy_to_user(arg, &sr, sizeof(sr)))
1502 return -EFAULT;
1503 return 0;
1504 }
1505 rcu_read_unlock();
1506 return -EADDRNOTAVAIL;
1507 default:
1508 return -ENOIOCTLCMD;
1509 }
1510}
1511#endif
1512
1437 1513
1438static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr) 1514static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
1439{ 1515{
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index b8ddcc480ed9..a5e52a9f0a12 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -60,12 +60,12 @@ static int checkentry(const struct xt_tgchk_param *par)
60 60
61 if (mangle->flags & ~ARPT_MANGLE_MASK || 61 if (mangle->flags & ~ARPT_MANGLE_MASK ||
62 !(mangle->flags & ARPT_MANGLE_MASK)) 62 !(mangle->flags & ARPT_MANGLE_MASK))
63 return false; 63 return -EINVAL;
64 64
65 if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT && 65 if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT &&
66 mangle->target != XT_CONTINUE) 66 mangle->target != XT_CONTINUE)
67 return false; 67 return -EINVAL;
68 return true; 68 return 0;
69} 69}
70 70
71static struct xt_target arpt_mangle_reg __read_mostly = { 71static struct xt_target arpt_mangle_reg __read_mostly = {
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index a3d5ab786e81..6390ba299b3d 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -76,6 +76,7 @@
76#include <linux/seq_file.h> 76#include <linux/seq_file.h>
77#include <linux/netfilter.h> 77#include <linux/netfilter.h>
78#include <linux/netfilter_ipv4.h> 78#include <linux/netfilter_ipv4.h>
79#include <linux/compat.h>
79 80
80static struct raw_hashinfo raw_v4_hashinfo = { 81static struct raw_hashinfo raw_v4_hashinfo = {
81 .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock), 82 .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
@@ -838,6 +839,23 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
838 } 839 }
839} 840}
840 841
842#ifdef CONFIG_COMPAT
843static int compat_raw_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
844{
845 switch (cmd) {
846 case SIOCOUTQ:
847 case SIOCINQ:
848 return -ENOIOCTLCMD;
849 default:
850#ifdef CONFIG_IP_MROUTE
851 return ipmr_compat_ioctl(sk, cmd, compat_ptr(arg));
852#else
853 return -ENOIOCTLCMD;
854#endif
855 }
856}
857#endif
858
841struct proto raw_prot = { 859struct proto raw_prot = {
842 .name = "RAW", 860 .name = "RAW",
843 .owner = THIS_MODULE, 861 .owner = THIS_MODULE,
@@ -860,6 +878,7 @@ struct proto raw_prot = {
860#ifdef CONFIG_COMPAT 878#ifdef CONFIG_COMPAT
861 .compat_setsockopt = compat_raw_setsockopt, 879 .compat_setsockopt = compat_raw_setsockopt,
862 .compat_getsockopt = compat_raw_getsockopt, 880 .compat_getsockopt = compat_raw_getsockopt,
881 .compat_ioctl = compat_raw_ioctl,
863#endif 882#endif
864}; 883};
865 884
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 351dc4e85242..6ed6603c2f6d 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2707,6 +2707,11 @@ static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 coo
2707 return NULL; 2707 return NULL;
2708} 2708}
2709 2709
2710static unsigned int ipv4_blackhole_default_mtu(const struct dst_entry *dst)
2711{
2712 return 0;
2713}
2714
2710static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) 2715static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
2711{ 2716{
2712} 2717}
@@ -2716,6 +2721,8 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
2716 .protocol = cpu_to_be16(ETH_P_IP), 2721 .protocol = cpu_to_be16(ETH_P_IP),
2717 .destroy = ipv4_dst_destroy, 2722 .destroy = ipv4_dst_destroy,
2718 .check = ipv4_blackhole_dst_check, 2723 .check = ipv4_blackhole_dst_check,
2724 .default_mtu = ipv4_blackhole_default_mtu,
2725 .default_advmss = ipv4_default_advmss,
2719 .update_pmtu = ipv4_rt_blackhole_update_pmtu, 2726 .update_pmtu = ipv4_rt_blackhole_update_pmtu,
2720}; 2727};
2721 2728
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 2549b29b062d..65f6c0406245 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1222,7 +1222,7 @@ static int tcp_check_dsack(struct sock *sk, struct sk_buff *ack_skb,
1222 } 1222 }
1223 1223
1224 /* D-SACK for already forgotten data... Do dumb counting. */ 1224 /* D-SACK for already forgotten data... Do dumb counting. */
1225 if (dup_sack && 1225 if (dup_sack && tp->undo_marker && tp->undo_retrans &&
1226 !after(end_seq_0, prior_snd_una) && 1226 !after(end_seq_0, prior_snd_una) &&
1227 after(end_seq_0, tp->undo_marker)) 1227 after(end_seq_0, tp->undo_marker))
1228 tp->undo_retrans--; 1228 tp->undo_retrans--;
@@ -1299,7 +1299,8 @@ static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk,
1299 1299
1300 /* Account D-SACK for retransmitted packet. */ 1300 /* Account D-SACK for retransmitted packet. */
1301 if (dup_sack && (sacked & TCPCB_RETRANS)) { 1301 if (dup_sack && (sacked & TCPCB_RETRANS)) {
1302 if (after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker)) 1302 if (tp->undo_marker && tp->undo_retrans &&
1303 after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker))
1303 tp->undo_retrans--; 1304 tp->undo_retrans--;
1304 if (sacked & TCPCB_SACKED_ACKED) 1305 if (sacked & TCPCB_SACKED_ACKED)
1305 state->reord = min(fack_count, state->reord); 1306 state->reord = min(fack_count, state->reord);
@@ -4399,7 +4400,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
4399 if (!skb_copy_datagram_iovec(skb, 0, tp->ucopy.iov, chunk)) { 4400 if (!skb_copy_datagram_iovec(skb, 0, tp->ucopy.iov, chunk)) {
4400 tp->ucopy.len -= chunk; 4401 tp->ucopy.len -= chunk;
4401 tp->copied_seq += chunk; 4402 tp->copied_seq += chunk;
4402 eaten = (chunk == skb->len && !th->fin); 4403 eaten = (chunk == skb->len);
4403 tcp_rcv_space_adjust(sk); 4404 tcp_rcv_space_adjust(sk);
4404 } 4405 }
4405 local_bh_disable(); 4406 local_bh_disable();
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 856f68466d49..02f583b3744a 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1994,7 +1994,6 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
1994 } 1994 }
1995 req = req->dl_next; 1995 req = req->dl_next;
1996 } 1996 }
1997 st->offset = 0;
1998 if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries) 1997 if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries)
1999 break; 1998 break;
2000get_req: 1999get_req:
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 406f320336e6..dfa5beb0c1c8 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2162,7 +2162,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
2162 if (!tp->retrans_stamp) 2162 if (!tp->retrans_stamp)
2163 tp->retrans_stamp = TCP_SKB_CB(skb)->when; 2163 tp->retrans_stamp = TCP_SKB_CB(skb)->when;
2164 2164
2165 tp->undo_retrans++; 2165 tp->undo_retrans += tcp_skb_pcount(skb);
2166 2166
2167 /* snd_nxt is stored to detect loss of retransmitted segment, 2167 /* snd_nxt is stored to detect loss of retransmitted segment,
2168 * see tcp_input.c tcp_sacktag_write_queue(). 2168 * see tcp_input.c tcp_sacktag_write_queue().