diff options
-rw-r--r-- | include/net/ip6_route.h | 17 | ||||
-rw-r--r-- | include/net/route.h | 14 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 5 | ||||
-rw-r--r-- | net/ipv4/route.c | 35 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 4 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 6 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 11 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 6 | ||||
-rw-r--r-- | net/ipv6/route.c | 5 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 4 |
10 files changed, 49 insertions, 58 deletions
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 37c1a1ed82c1..73d750288121 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
@@ -53,18 +53,27 @@ static inline unsigned int rt6_flags2srcprefs(int flags) | |||
53 | return (flags >> 3) & 7; | 53 | return (flags >> 3) & 7; |
54 | } | 54 | } |
55 | 55 | ||
56 | extern void rt6_bind_peer(struct rt6_info *rt, | 56 | extern void rt6_bind_peer(struct rt6_info *rt, int create); |
57 | int create); | ||
58 | 57 | ||
59 | static inline struct inet_peer *rt6_get_peer(struct rt6_info *rt) | 58 | static inline struct inet_peer *__rt6_get_peer(struct rt6_info *rt, int create) |
60 | { | 59 | { |
61 | if (rt->rt6i_peer) | 60 | if (rt->rt6i_peer) |
62 | return rt->rt6i_peer; | 61 | return rt->rt6i_peer; |
63 | 62 | ||
64 | rt6_bind_peer(rt, 0); | 63 | rt6_bind_peer(rt, create); |
65 | return rt->rt6i_peer; | 64 | return rt->rt6i_peer; |
66 | } | 65 | } |
67 | 66 | ||
67 | static inline struct inet_peer *rt6_get_peer(struct rt6_info *rt) | ||
68 | { | ||
69 | return __rt6_get_peer(rt, 0); | ||
70 | } | ||
71 | |||
72 | static inline struct inet_peer *rt6_get_peer_create(struct rt6_info *rt) | ||
73 | { | ||
74 | return __rt6_get_peer(rt, 1); | ||
75 | } | ||
76 | |||
68 | extern void ip6_route_input(struct sk_buff *skb); | 77 | extern void ip6_route_input(struct sk_buff *skb); |
69 | 78 | ||
70 | extern struct dst_entry * ip6_route_output(struct net *net, | 79 | extern struct dst_entry * ip6_route_output(struct net *net, |
diff --git a/include/net/route.h b/include/net/route.h index ed2b78e2375d..433fc6c1d404 100644 --- a/include/net/route.h +++ b/include/net/route.h | |||
@@ -296,15 +296,25 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable | |||
296 | 296 | ||
297 | extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create); | 297 | extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create); |
298 | 298 | ||
299 | static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr) | 299 | static inline struct inet_peer *__rt_get_peer(struct rtable *rt, __be32 daddr, int create) |
300 | { | 300 | { |
301 | if (rt->peer) | 301 | if (rt->peer) |
302 | return rt->peer; | 302 | return rt->peer; |
303 | 303 | ||
304 | rt_bind_peer(rt, daddr, 0); | 304 | rt_bind_peer(rt, daddr, create); |
305 | return rt->peer; | 305 | return rt->peer; |
306 | } | 306 | } |
307 | 307 | ||
308 | static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr) | ||
309 | { | ||
310 | return __rt_get_peer(rt, daddr, 0); | ||
311 | } | ||
312 | |||
313 | static inline struct inet_peer *rt_get_peer_create(struct rtable *rt, __be32 daddr) | ||
314 | { | ||
315 | return __rt_get_peer(rt, daddr, 1); | ||
316 | } | ||
317 | |||
308 | static inline int inet_iif(const struct sk_buff *skb) | 318 | static inline int inet_iif(const struct sk_buff *skb) |
309 | { | 319 | { |
310 | return skb_rtable(skb)->rt_iif; | 320 | return skb_rtable(skb)->rt_iif; |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index c75efbdc71cb..0c78ef1e5dde 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -253,9 +253,8 @@ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt, | |||
253 | 253 | ||
254 | /* Limit if icmp type is enabled in ratemask. */ | 254 | /* Limit if icmp type is enabled in ratemask. */ |
255 | if ((1 << type) & net->ipv4.sysctl_icmp_ratemask) { | 255 | if ((1 << type) & net->ipv4.sysctl_icmp_ratemask) { |
256 | if (!rt->peer) | 256 | struct inet_peer *peer = rt_get_peer_create(rt, fl4->daddr); |
257 | rt_bind_peer(rt, fl4->daddr, 1); | 257 | rc = inet_peer_xrlim_allow(peer, |
258 | rc = inet_peer_xrlim_allow(rt->peer, | ||
259 | net->ipv4.sysctl_icmp_ratelimit); | 258 | net->ipv4.sysctl_icmp_ratelimit); |
260 | } | 259 | } |
261 | out: | 260 | out: |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 2c9f73f3b7cc..7a4d724765e6 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -162,10 +162,7 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
162 | struct inet_peer *peer; | 162 | struct inet_peer *peer; |
163 | u32 *p = NULL; | 163 | u32 *p = NULL; |
164 | 164 | ||
165 | if (!rt->peer) | 165 | peer = rt_get_peer_create(rt, rt->rt_dst); |
166 | rt_bind_peer(rt, rt->rt_dst, 1); | ||
167 | |||
168 | peer = rt->peer; | ||
169 | if (peer) { | 166 | if (peer) { |
170 | u32 *old_p = __DST_METRICS_PTR(old); | 167 | u32 *old_p = __DST_METRICS_PTR(old); |
171 | unsigned long prev, new; | 168 | unsigned long prev, new; |
@@ -1364,14 +1361,13 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more) | |||
1364 | struct rtable *rt = (struct rtable *) dst; | 1361 | struct rtable *rt = (struct rtable *) dst; |
1365 | 1362 | ||
1366 | if (rt && !(rt->dst.flags & DST_NOPEER)) { | 1363 | if (rt && !(rt->dst.flags & DST_NOPEER)) { |
1367 | if (rt->peer == NULL) | 1364 | struct inet_peer *peer = rt_get_peer_create(rt, rt->rt_dst); |
1368 | rt_bind_peer(rt, rt->rt_dst, 1); | ||
1369 | 1365 | ||
1370 | /* If peer is attached to destination, it is never detached, | 1366 | /* If peer is attached to destination, it is never detached, |
1371 | so that we need not to grab a lock to dereference it. | 1367 | so that we need not to grab a lock to dereference it. |
1372 | */ | 1368 | */ |
1373 | if (rt->peer) { | 1369 | if (peer) { |
1374 | iph->id = htons(inet_getid(rt->peer, more)); | 1370 | iph->id = htons(inet_getid(peer, more)); |
1375 | return; | 1371 | return; |
1376 | } | 1372 | } |
1377 | } else if (!rt) | 1373 | } else if (!rt) |
@@ -1481,10 +1477,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, | |||
1481 | rt->rt_gateway != old_gw) | 1477 | rt->rt_gateway != old_gw) |
1482 | continue; | 1478 | continue; |
1483 | 1479 | ||
1484 | if (!rt->peer) | 1480 | peer = rt_get_peer_create(rt, rt->rt_dst); |
1485 | rt_bind_peer(rt, rt->rt_dst, 1); | ||
1486 | |||
1487 | peer = rt->peer; | ||
1488 | if (peer) { | 1481 | if (peer) { |
1489 | if (peer->redirect_learned.a4 != new_gw) { | 1482 | if (peer->redirect_learned.a4 != new_gw) { |
1490 | peer->redirect_learned.a4 = new_gw; | 1483 | peer->redirect_learned.a4 = new_gw; |
@@ -1579,9 +1572,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) | |||
1579 | log_martians = IN_DEV_LOG_MARTIANS(in_dev); | 1572 | log_martians = IN_DEV_LOG_MARTIANS(in_dev); |
1580 | rcu_read_unlock(); | 1573 | rcu_read_unlock(); |
1581 | 1574 | ||
1582 | if (!rt->peer) | 1575 | peer = rt_get_peer_create(rt, rt->rt_dst); |
1583 | rt_bind_peer(rt, rt->rt_dst, 1); | ||
1584 | peer = rt->peer; | ||
1585 | if (!peer) { | 1576 | if (!peer) { |
1586 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); | 1577 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); |
1587 | return; | 1578 | return; |
@@ -1646,9 +1637,7 @@ static int ip_error(struct sk_buff *skb) | |||
1646 | break; | 1637 | break; |
1647 | } | 1638 | } |
1648 | 1639 | ||
1649 | if (!rt->peer) | 1640 | peer = rt_get_peer_create(rt, rt->rt_dst); |
1650 | rt_bind_peer(rt, rt->rt_dst, 1); | ||
1651 | peer = rt->peer; | ||
1652 | 1641 | ||
1653 | send = true; | 1642 | send = true; |
1654 | if (peer) { | 1643 | if (peer) { |
@@ -1754,9 +1743,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
1754 | 1743 | ||
1755 | dst_confirm(dst); | 1744 | dst_confirm(dst); |
1756 | 1745 | ||
1757 | if (!rt->peer) | 1746 | peer = rt_get_peer_create(rt, rt->rt_dst); |
1758 | rt_bind_peer(rt, rt->rt_dst, 1); | ||
1759 | peer = rt->peer; | ||
1760 | if (peer) { | 1747 | if (peer) { |
1761 | unsigned long pmtu_expires = ACCESS_ONCE(peer->pmtu_expires); | 1748 | unsigned long pmtu_expires = ACCESS_ONCE(peer->pmtu_expires); |
1762 | 1749 | ||
@@ -1782,12 +1769,8 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
1782 | static void ipv4_validate_peer(struct rtable *rt) | 1769 | static void ipv4_validate_peer(struct rtable *rt) |
1783 | { | 1770 | { |
1784 | if (rt->rt_peer_genid != rt_peer_genid()) { | 1771 | if (rt->rt_peer_genid != rt_peer_genid()) { |
1785 | struct inet_peer *peer; | 1772 | struct inet_peer *peer = rt_get_peer(rt, rt->rt_dst); |
1786 | |||
1787 | if (!rt->peer) | ||
1788 | rt_bind_peer(rt, rt->rt_dst, 0); | ||
1789 | 1773 | ||
1790 | peer = rt->peer; | ||
1791 | if (peer) { | 1774 | if (peer) { |
1792 | check_peer_pmtu(&rt->dst, peer); | 1775 | check_peer_pmtu(&rt->dst, peer); |
1793 | 1776 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f485b451f928..833e8d96a636 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1832,9 +1832,7 @@ struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it) | |||
1832 | peer = inet_getpeer_v4(net, inet->inet_daddr, 1); | 1832 | peer = inet_getpeer_v4(net, inet->inet_daddr, 1); |
1833 | *release_it = true; | 1833 | *release_it = true; |
1834 | } else { | 1834 | } else { |
1835 | if (!rt->peer) | 1835 | peer = rt_get_peer_create(rt, inet->inet_daddr); |
1836 | rt_bind_peer(rt, inet->inet_daddr, 1); | ||
1837 | peer = rt->peer; | ||
1838 | *release_it = false; | 1836 | *release_it = false; |
1839 | } | 1837 | } |
1840 | 1838 | ||
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 091a2971c7b7..ed89bba745a1 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -188,14 +188,14 @@ static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type, | |||
188 | } else { | 188 | } else { |
189 | struct rt6_info *rt = (struct rt6_info *)dst; | 189 | struct rt6_info *rt = (struct rt6_info *)dst; |
190 | int tmo = net->ipv6.sysctl.icmpv6_time; | 190 | int tmo = net->ipv6.sysctl.icmpv6_time; |
191 | struct inet_peer *peer; | ||
191 | 192 | ||
192 | /* Give more bandwidth to wider prefixes. */ | 193 | /* Give more bandwidth to wider prefixes. */ |
193 | if (rt->rt6i_dst.plen < 128) | 194 | if (rt->rt6i_dst.plen < 128) |
194 | tmo >>= ((128 - rt->rt6i_dst.plen)>>5); | 195 | tmo >>= ((128 - rt->rt6i_dst.plen)>>5); |
195 | 196 | ||
196 | if (!rt->rt6i_peer) | 197 | peer = rt6_get_peer_create(rt); |
197 | rt6_bind_peer(rt, 1); | 198 | res = inet_peer_xrlim_allow(peer, tmo); |
198 | res = inet_peer_xrlim_allow(rt->rt6i_peer, tmo); | ||
199 | } | 199 | } |
200 | dst_release(dst); | 200 | dst_release(dst); |
201 | return res; | 201 | return res; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 17b8c67998bb..62fcf3e48aca 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -463,6 +463,7 @@ int ip6_forward(struct sk_buff *skb) | |||
463 | */ | 463 | */ |
464 | if (skb->dev == dst->dev && opt->srcrt == 0 && !skb_sec_path(skb)) { | 464 | if (skb->dev == dst->dev && opt->srcrt == 0 && !skb_sec_path(skb)) { |
465 | struct in6_addr *target = NULL; | 465 | struct in6_addr *target = NULL; |
466 | struct inet_peer *peer; | ||
466 | struct rt6_info *rt; | 467 | struct rt6_info *rt; |
467 | 468 | ||
468 | /* | 469 | /* |
@@ -476,13 +477,12 @@ int ip6_forward(struct sk_buff *skb) | |||
476 | else | 477 | else |
477 | target = &hdr->daddr; | 478 | target = &hdr->daddr; |
478 | 479 | ||
479 | if (!rt->rt6i_peer) | 480 | peer = rt6_get_peer_create(rt); |
480 | rt6_bind_peer(rt, 1); | ||
481 | 481 | ||
482 | /* Limit redirects both by destination (here) | 482 | /* Limit redirects both by destination (here) |
483 | and by source (inside ndisc_send_redirect) | 483 | and by source (inside ndisc_send_redirect) |
484 | */ | 484 | */ |
485 | if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) | 485 | if (inet_peer_xrlim_allow(peer, 1*HZ)) |
486 | ndisc_send_redirect(skb, target); | 486 | ndisc_send_redirect(skb, target); |
487 | } else { | 487 | } else { |
488 | int addrtype = ipv6_addr_type(&hdr->saddr); | 488 | int addrtype = ipv6_addr_type(&hdr->saddr); |
@@ -602,11 +602,8 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | |||
602 | int old, new; | 602 | int old, new; |
603 | 603 | ||
604 | if (rt && !(rt->dst.flags & DST_NOPEER)) { | 604 | if (rt && !(rt->dst.flags & DST_NOPEER)) { |
605 | struct inet_peer *peer; | 605 | struct inet_peer *peer = rt6_get_peer_create(rt); |
606 | 606 | ||
607 | if (!rt->rt6i_peer) | ||
608 | rt6_bind_peer(rt, 1); | ||
609 | peer = rt->rt6i_peer; | ||
610 | if (peer) { | 607 | if (peer) { |
611 | fhdr->identification = htonl(inet_getid(peer, 0)); | 608 | fhdr->identification = htonl(inet_getid(peer, 0)); |
612 | return; | 609 | return; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 54f62d3b8dd6..69a6330dea91 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1472,6 +1472,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | |||
1472 | struct net *net = dev_net(dev); | 1472 | struct net *net = dev_net(dev); |
1473 | struct sock *sk = net->ipv6.ndisc_sk; | 1473 | struct sock *sk = net->ipv6.ndisc_sk; |
1474 | int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); | 1474 | int len = sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr); |
1475 | struct inet_peer *peer; | ||
1475 | struct sk_buff *buff; | 1476 | struct sk_buff *buff; |
1476 | struct icmp6hdr *icmph; | 1477 | struct icmp6hdr *icmph; |
1477 | struct in6_addr saddr_buf; | 1478 | struct in6_addr saddr_buf; |
@@ -1518,9 +1519,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | |||
1518 | "Redirect: destination is not a neighbour\n"); | 1519 | "Redirect: destination is not a neighbour\n"); |
1519 | goto release; | 1520 | goto release; |
1520 | } | 1521 | } |
1521 | if (!rt->rt6i_peer) | 1522 | peer = rt6_get_peer_create(rt); |
1522 | rt6_bind_peer(rt, 1); | 1523 | if (!inet_peer_xrlim_allow(peer, 1*HZ)) |
1523 | if (!inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ)) | ||
1524 | goto release; | 1524 | goto release; |
1525 | 1525 | ||
1526 | if (dev->addr_len) { | 1526 | if (dev->addr_len) { |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 4eca0130cce7..8a986be4aeda 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -99,10 +99,7 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
99 | if (!(rt->dst.flags & DST_HOST)) | 99 | if (!(rt->dst.flags & DST_HOST)) |
100 | return NULL; | 100 | return NULL; |
101 | 101 | ||
102 | if (!rt->rt6i_peer) | 102 | peer = rt6_get_peer_create(rt); |
103 | rt6_bind_peer(rt, 1); | ||
104 | |||
105 | peer = rt->rt6i_peer; | ||
106 | if (peer) { | 103 | if (peer) { |
107 | u32 *old_p = __DST_METRICS_PTR(old); | 104 | u32 *old_p = __DST_METRICS_PTR(old); |
108 | unsigned long prev, new; | 105 | unsigned long prev, new; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1a9cdd09f11c..218433cb9928 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1744,9 +1744,7 @@ static struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it) | |||
1744 | peer = inet_getpeer_v6(net, &np->daddr, 1); | 1744 | peer = inet_getpeer_v6(net, &np->daddr, 1); |
1745 | *release_it = true; | 1745 | *release_it = true; |
1746 | } else { | 1746 | } else { |
1747 | if (!rt->rt6i_peer) | 1747 | peer = rt6_get_peer_create(rt); |
1748 | rt6_bind_peer(rt, 1); | ||
1749 | peer = rt->rt6i_peer; | ||
1750 | *release_it = false; | 1748 | *release_it = false; |
1751 | } | 1749 | } |
1752 | 1750 | ||