aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ah4.c8
-rw-r--r--net/ipv4/inet_diag.c4
-rw-r--r--net/ipv4/ip_options.c1
-rw-r--r--net/ipv4/ping.c2
-rw-r--r--net/ipv4/route.c120
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv4/tcp_output.c2
7 files changed, 73 insertions, 65 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index c1f4154552fc..36d14406261e 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -136,8 +136,6 @@ static void ah_output_done(struct crypto_async_request *base, int err)
136 memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr)); 136 memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
137 } 137 }
138 138
139 err = ah->nexthdr;
140
141 kfree(AH_SKB_CB(skb)->tmp); 139 kfree(AH_SKB_CB(skb)->tmp);
142 xfrm_output_resume(skb, err); 140 xfrm_output_resume(skb, err);
143} 141}
@@ -264,12 +262,12 @@ static void ah_input_done(struct crypto_async_request *base, int err)
264 if (err) 262 if (err)
265 goto out; 263 goto out;
266 264
265 err = ah->nexthdr;
266
267 skb->network_header += ah_hlen; 267 skb->network_header += ah_hlen;
268 memcpy(skb_network_header(skb), work_iph, ihl); 268 memcpy(skb_network_header(skb), work_iph, ihl);
269 __skb_pull(skb, ah_hlen + ihl); 269 __skb_pull(skb, ah_hlen + ihl);
270 skb_set_transport_header(skb, -ihl); 270 skb_set_transport_header(skb, -ihl);
271
272 err = ah->nexthdr;
273out: 271out:
274 kfree(AH_SKB_CB(skb)->tmp); 272 kfree(AH_SKB_CB(skb)->tmp);
275 xfrm_input_resume(skb, err); 273 xfrm_input_resume(skb, err);
@@ -371,8 +369,6 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
371 if (err == -EINPROGRESS) 369 if (err == -EINPROGRESS)
372 goto out; 370 goto out;
373 371
374 if (err == -EBUSY)
375 err = NET_XMIT_DROP;
376 goto out_free; 372 goto out_free;
377 } 373 }
378 374
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index f5e2bdaef949..68e8ac514383 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -133,8 +133,8 @@ static int inet_csk_diag_fill(struct sock *sk,
133 &np->rcv_saddr); 133 &np->rcv_saddr);
134 ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, 134 ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst,
135 &np->daddr); 135 &np->daddr);
136 if (ext & (1 << (INET_DIAG_TOS - 1))) 136 if (ext & (1 << (INET_DIAG_TCLASS - 1)))
137 RTA_PUT_U8(skb, INET_DIAG_TOS, np->tclass); 137 RTA_PUT_U8(skb, INET_DIAG_TCLASS, np->tclass);
138 } 138 }
139#endif 139#endif
140 140
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index ec93335901dd..05d20cca9d66 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -640,6 +640,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
640 } 640 }
641 if (srrptr <= srrspace) { 641 if (srrptr <= srrspace) {
642 opt->srr_is_hit = 1; 642 opt->srr_is_hit = 1;
643 iph->daddr = nexthop;
643 opt->is_changed = 1; 644 opt->is_changed = 1;
644 } 645 }
645 return 0; 646 return 0;
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index a06f73fdb3c0..43d4c3b22369 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -339,7 +339,6 @@ void ping_err(struct sk_buff *skb, u32 info)
339 sk = ping_v4_lookup(net, iph->daddr, iph->saddr, 339 sk = ping_v4_lookup(net, iph->daddr, iph->saddr,
340 ntohs(icmph->un.echo.id), skb->dev->ifindex); 340 ntohs(icmph->un.echo.id), skb->dev->ifindex);
341 if (sk == NULL) { 341 if (sk == NULL) {
342 ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
343 pr_debug("no socket, dropping\n"); 342 pr_debug("no socket, dropping\n");
344 return; /* No socket for error */ 343 return; /* No socket for error */
345 } 344 }
@@ -679,7 +678,6 @@ static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
679 pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n", 678 pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n",
680 inet_sk(sk), inet_sk(sk)->inet_num, skb); 679 inet_sk(sk), inet_sk(sk)->inet_num, skb);
681 if (sock_queue_rcv_skb(sk, skb) < 0) { 680 if (sock_queue_rcv_skb(sk, skb) < 0) {
682 ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_INERRORS);
683 kfree_skb(skb); 681 kfree_skb(skb);
684 pr_debug("ping_queue_rcv_skb -> failed\n"); 682 pr_debug("ping_queue_rcv_skb -> failed\n");
685 return -1; 683 return -1;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 155138d8ec8b..0c74da8a0473 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1304,16 +1304,42 @@ static void rt_del(unsigned hash, struct rtable *rt)
1304 spin_unlock_bh(rt_hash_lock_addr(hash)); 1304 spin_unlock_bh(rt_hash_lock_addr(hash));
1305} 1305}
1306 1306
1307static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
1308{
1309 struct rtable *rt = (struct rtable *) dst;
1310 __be32 orig_gw = rt->rt_gateway;
1311 struct neighbour *n, *old_n;
1312
1313 dst_confirm(&rt->dst);
1314
1315 rt->rt_gateway = peer->redirect_learned.a4;
1316
1317 n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
1318 if (IS_ERR(n))
1319 return PTR_ERR(n);
1320 old_n = xchg(&rt->dst._neighbour, n);
1321 if (old_n)
1322 neigh_release(old_n);
1323 if (!n || !(n->nud_state & NUD_VALID)) {
1324 if (n)
1325 neigh_event_send(n, NULL);
1326 rt->rt_gateway = orig_gw;
1327 return -EAGAIN;
1328 } else {
1329 rt->rt_flags |= RTCF_REDIRECTED;
1330 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
1331 }
1332 return 0;
1333}
1334
1307/* called in rcu_read_lock() section */ 1335/* called in rcu_read_lock() section */
1308void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, 1336void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1309 __be32 saddr, struct net_device *dev) 1337 __be32 saddr, struct net_device *dev)
1310{ 1338{
1311 int s, i; 1339 int s, i;
1312 struct in_device *in_dev = __in_dev_get_rcu(dev); 1340 struct in_device *in_dev = __in_dev_get_rcu(dev);
1313 struct rtable *rt;
1314 __be32 skeys[2] = { saddr, 0 }; 1341 __be32 skeys[2] = { saddr, 0 };
1315 int ikeys[2] = { dev->ifindex, 0 }; 1342 int ikeys[2] = { dev->ifindex, 0 };
1316 struct flowi4 fl4;
1317 struct inet_peer *peer; 1343 struct inet_peer *peer;
1318 struct net *net; 1344 struct net *net;
1319 1345
@@ -1336,33 +1362,42 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1336 goto reject_redirect; 1362 goto reject_redirect;
1337 } 1363 }
1338 1364
1339 memset(&fl4, 0, sizeof(fl4));
1340 fl4.daddr = daddr;
1341 for (s = 0; s < 2; s++) { 1365 for (s = 0; s < 2; s++) {
1342 for (i = 0; i < 2; i++) { 1366 for (i = 0; i < 2; i++) {
1343 fl4.flowi4_oif = ikeys[i]; 1367 unsigned int hash;
1344 fl4.saddr = skeys[s]; 1368 struct rtable __rcu **rthp;
1345 rt = __ip_route_output_key(net, &fl4); 1369 struct rtable *rt;
1346 if (IS_ERR(rt)) 1370
1347 continue; 1371 hash = rt_hash(daddr, skeys[s], ikeys[i], rt_genid(net));
1348 1372
1349 if (rt->dst.error || rt->dst.dev != dev || 1373 rthp = &rt_hash_table[hash].chain;
1350 rt->rt_gateway != old_gw) { 1374
1351 ip_rt_put(rt); 1375 while ((rt = rcu_dereference(*rthp)) != NULL) {
1352 continue; 1376 rthp = &rt->dst.rt_next;
1353 } 1377
1378 if (rt->rt_key_dst != daddr ||
1379 rt->rt_key_src != skeys[s] ||
1380 rt->rt_oif != ikeys[i] ||
1381 rt_is_input_route(rt) ||
1382 rt_is_expired(rt) ||
1383 !net_eq(dev_net(rt->dst.dev), net) ||
1384 rt->dst.error ||
1385 rt->dst.dev != dev ||
1386 rt->rt_gateway != old_gw)
1387 continue;
1354 1388
1355 if (!rt->peer) 1389 if (!rt->peer)
1356 rt_bind_peer(rt, rt->rt_dst, 1); 1390 rt_bind_peer(rt, rt->rt_dst, 1);
1357 1391
1358 peer = rt->peer; 1392 peer = rt->peer;
1359 if (peer) { 1393 if (peer) {
1360 peer->redirect_learned.a4 = new_gw; 1394 if (peer->redirect_learned.a4 != new_gw) {
1361 atomic_inc(&__rt_peer_genid); 1395 peer->redirect_learned.a4 = new_gw;
1396 atomic_inc(&__rt_peer_genid);
1397 }
1398 check_peer_redir(&rt->dst, peer);
1399 }
1362 } 1400 }
1363
1364 ip_rt_put(rt);
1365 return;
1366 } 1401 }
1367 } 1402 }
1368 return; 1403 return;
@@ -1649,33 +1684,6 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1649 } 1684 }
1650} 1685}
1651 1686
1652static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
1653{
1654 struct rtable *rt = (struct rtable *) dst;
1655 __be32 orig_gw = rt->rt_gateway;
1656 struct neighbour *n, *old_n;
1657
1658 dst_confirm(&rt->dst);
1659
1660 rt->rt_gateway = peer->redirect_learned.a4;
1661
1662 n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
1663 if (IS_ERR(n))
1664 return PTR_ERR(n);
1665 old_n = xchg(&rt->dst._neighbour, n);
1666 if (old_n)
1667 neigh_release(old_n);
1668 if (!n || !(n->nud_state & NUD_VALID)) {
1669 if (n)
1670 neigh_event_send(n, NULL);
1671 rt->rt_gateway = orig_gw;
1672 return -EAGAIN;
1673 } else {
1674 rt->rt_flags |= RTCF_REDIRECTED;
1675 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
1676 }
1677 return 0;
1678}
1679 1687
1680static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) 1688static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
1681{ 1689{
@@ -2845,7 +2853,7 @@ static int rt_fill_info(struct net *net,
2845 struct rtable *rt = skb_rtable(skb); 2853 struct rtable *rt = skb_rtable(skb);
2846 struct rtmsg *r; 2854 struct rtmsg *r;
2847 struct nlmsghdr *nlh; 2855 struct nlmsghdr *nlh;
2848 long expires = 0; 2856 unsigned long expires = 0;
2849 const struct inet_peer *peer = rt->peer; 2857 const struct inet_peer *peer = rt->peer;
2850 u32 id = 0, ts = 0, tsage = 0, error; 2858 u32 id = 0, ts = 0, tsage = 0, error;
2851 2859
@@ -2902,8 +2910,12 @@ static int rt_fill_info(struct net *net,
2902 tsage = get_seconds() - peer->tcp_ts_stamp; 2910 tsage = get_seconds() - peer->tcp_ts_stamp;
2903 } 2911 }
2904 expires = ACCESS_ONCE(peer->pmtu_expires); 2912 expires = ACCESS_ONCE(peer->pmtu_expires);
2905 if (expires) 2913 if (expires) {
2906 expires -= jiffies; 2914 if (time_before(jiffies, expires))
2915 expires -= jiffies;
2916 else
2917 expires = 0;
2918 }
2907 } 2919 }
2908 2920
2909 if (rt_is_input_route(rt)) { 2921 if (rt_is_input_route(rt)) {
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a7443159c400..a9db4b1a2215 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1510,6 +1510,7 @@ exit:
1510 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); 1510 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
1511 return NULL; 1511 return NULL;
1512put_and_exit: 1512put_and_exit:
1513 tcp_clear_xmit_timers(newsk);
1513 bh_unlock_sock(newsk); 1514 bh_unlock_sock(newsk);
1514 sock_put(newsk); 1515 sock_put(newsk);
1515 goto exit; 1516 goto exit;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 980b98f6288c..63170e297540 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1382,7 +1382,7 @@ static inline int tcp_minshall_check(const struct tcp_sock *tp)
1382/* Return 0, if packet can be sent now without violation Nagle's rules: 1382/* Return 0, if packet can be sent now without violation Nagle's rules:
1383 * 1. It is full sized. 1383 * 1. It is full sized.
1384 * 2. Or it contains FIN. (already checked by caller) 1384 * 2. Or it contains FIN. (already checked by caller)
1385 * 3. Or TCP_NODELAY was set. 1385 * 3. Or TCP_CORK is not set, and TCP_NODELAY is set.
1386 * 4. Or TCP_CORK is not set, and all sent packets are ACKed. 1386 * 4. Or TCP_CORK is not set, and all sent packets are ACKed.
1387 * With Minshall's modification: all sent small packets are ACKed. 1387 * With Minshall's modification: all sent small packets are ACKed.
1388 */ 1388 */