aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c94
1 files changed, 66 insertions, 28 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index aa13ef105110..33137307d52a 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -108,6 +108,7 @@
108#ifdef CONFIG_SYSCTL 108#ifdef CONFIG_SYSCTL
109#include <linux/sysctl.h> 109#include <linux/sysctl.h>
110#endif 110#endif
111#include <net/atmclip.h>
111 112
112#define RT_FL_TOS(oldflp4) \ 113#define RT_FL_TOS(oldflp4) \
113 ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) 114 ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
@@ -184,6 +185,8 @@ static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
184 return p; 185 return p;
185} 186}
186 187
188static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr);
189
187static struct dst_ops ipv4_dst_ops = { 190static struct dst_ops ipv4_dst_ops = {
188 .family = AF_INET, 191 .family = AF_INET,
189 .protocol = cpu_to_be16(ETH_P_IP), 192 .protocol = cpu_to_be16(ETH_P_IP),
@@ -198,6 +201,7 @@ static struct dst_ops ipv4_dst_ops = {
198 .link_failure = ipv4_link_failure, 201 .link_failure = ipv4_link_failure,
199 .update_pmtu = ip_rt_update_pmtu, 202 .update_pmtu = ip_rt_update_pmtu,
200 .local_out = __ip_local_out, 203 .local_out = __ip_local_out,
204 .neigh_lookup = ipv4_neigh_lookup,
201}; 205};
202 206
203#define ECN_OR_COST(class) TC_PRIO_##class 207#define ECN_OR_COST(class) TC_PRIO_##class
@@ -411,8 +415,10 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
411 "HHUptod\tSpecDst"); 415 "HHUptod\tSpecDst");
412 else { 416 else {
413 struct rtable *r = v; 417 struct rtable *r = v;
418 struct neighbour *n;
414 int len; 419 int len;
415 420
421 n = dst_get_neighbour(&r->dst);
416 seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t" 422 seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t"
417 "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n", 423 "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",
418 r->dst.dev ? r->dst.dev->name : "*", 424 r->dst.dev ? r->dst.dev->name : "*",
@@ -425,9 +431,8 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
425 (int)((dst_metric(&r->dst, RTAX_RTT) >> 3) + 431 (int)((dst_metric(&r->dst, RTAX_RTT) >> 3) +
426 dst_metric(&r->dst, RTAX_RTTVAR)), 432 dst_metric(&r->dst, RTAX_RTTVAR)),
427 r->rt_key_tos, 433 r->rt_key_tos,
428 r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1, 434 -1,
429 r->dst.hh ? (r->dst.hh->hh_output == 435 (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0,
430 dev_queue_xmit) : 0,
431 r->rt_spec_dst, &len); 436 r->rt_spec_dst, &len);
432 437
433 seq_printf(seq, "%*s\n", 127 - len, ""); 438 seq_printf(seq, "%*s\n", 127 - len, "");
@@ -1006,6 +1011,37 @@ static int slow_chain_length(const struct rtable *head)
1006 return length >> FRACT_BITS; 1011 return length >> FRACT_BITS;
1007} 1012}
1008 1013
1014static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const void *daddr)
1015{
1016 struct neigh_table *tbl = &arp_tbl;
1017 static const __be32 inaddr_any = 0;
1018 struct net_device *dev = dst->dev;
1019 const __be32 *pkey = daddr;
1020 struct neighbour *n;
1021
1022#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
1023 if (dev->type == ARPHRD_ATM)
1024 tbl = clip_tbl_hook;
1025#endif
1026 if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
1027 pkey = &inaddr_any;
1028
1029 n = __ipv4_neigh_lookup(tbl, dev, *(__force u32 *)pkey);
1030 if (n)
1031 return n;
1032 return neigh_create(tbl, pkey, dev);
1033}
1034
1035static int rt_bind_neighbour(struct rtable *rt)
1036{
1037 struct neighbour *n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
1038 if (IS_ERR(n))
1039 return PTR_ERR(n);
1040 dst_set_neighbour(&rt->dst, n);
1041
1042 return 0;
1043}
1044
1009static struct rtable *rt_intern_hash(unsigned hash, struct rtable *rt, 1045static struct rtable *rt_intern_hash(unsigned hash, struct rtable *rt,
1010 struct sk_buff *skb, int ifindex) 1046 struct sk_buff *skb, int ifindex)
1011{ 1047{
@@ -1042,7 +1078,7 @@ restart:
1042 1078
1043 rt->dst.flags |= DST_NOCACHE; 1079 rt->dst.flags |= DST_NOCACHE;
1044 if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) { 1080 if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) {
1045 int err = arp_bind_neighbour(&rt->dst); 1081 int err = rt_bind_neighbour(rt);
1046 if (err) { 1082 if (err) {
1047 if (net_ratelimit()) 1083 if (net_ratelimit())
1048 printk(KERN_WARNING 1084 printk(KERN_WARNING
@@ -1138,7 +1174,7 @@ restart:
1138 route or unicast forwarding path. 1174 route or unicast forwarding path.
1139 */ 1175 */
1140 if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) { 1176 if (rt->rt_type == RTN_UNICAST || rt_is_output_route(rt)) {
1141 int err = arp_bind_neighbour(&rt->dst); 1177 int err = rt_bind_neighbour(rt);
1142 if (err) { 1178 if (err) {
1143 spin_unlock_bh(rt_hash_lock_addr(hash)); 1179 spin_unlock_bh(rt_hash_lock_addr(hash));
1144 1180
@@ -1439,20 +1475,20 @@ static int ip_error(struct sk_buff *skb)
1439 int code; 1475 int code;
1440 1476
1441 switch (rt->dst.error) { 1477 switch (rt->dst.error) {
1442 case EINVAL: 1478 case EINVAL:
1443 default: 1479 default:
1444 goto out; 1480 goto out;
1445 case EHOSTUNREACH: 1481 case EHOSTUNREACH:
1446 code = ICMP_HOST_UNREACH; 1482 code = ICMP_HOST_UNREACH;
1447 break; 1483 break;
1448 case ENETUNREACH: 1484 case ENETUNREACH:
1449 code = ICMP_NET_UNREACH; 1485 code = ICMP_NET_UNREACH;
1450 IP_INC_STATS_BH(dev_net(rt->dst.dev), 1486 IP_INC_STATS_BH(dev_net(rt->dst.dev),
1451 IPSTATS_MIB_INNOROUTES); 1487 IPSTATS_MIB_INNOROUTES);
1452 break; 1488 break;
1453 case EACCES: 1489 case EACCES:
1454 code = ICMP_PKT_FILTERED; 1490 code = ICMP_PKT_FILTERED;
1455 break; 1491 break;
1456 } 1492 }
1457 1493
1458 if (!rt->peer) 1494 if (!rt->peer)
@@ -1592,23 +1628,24 @@ static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
1592{ 1628{
1593 struct rtable *rt = (struct rtable *) dst; 1629 struct rtable *rt = (struct rtable *) dst;
1594 __be32 orig_gw = rt->rt_gateway; 1630 __be32 orig_gw = rt->rt_gateway;
1631 struct neighbour *n;
1595 1632
1596 dst_confirm(&rt->dst); 1633 dst_confirm(&rt->dst);
1597 1634
1598 neigh_release(rt->dst.neighbour); 1635 neigh_release(dst_get_neighbour(&rt->dst));
1599 rt->dst.neighbour = NULL; 1636 dst_set_neighbour(&rt->dst, NULL);
1600 1637
1601 rt->rt_gateway = peer->redirect_learned.a4; 1638 rt->rt_gateway = peer->redirect_learned.a4;
1602 if (arp_bind_neighbour(&rt->dst) || 1639 rt_bind_neighbour(rt);
1603 !(rt->dst.neighbour->nud_state & NUD_VALID)) { 1640 n = dst_get_neighbour(&rt->dst);
1604 if (rt->dst.neighbour) 1641 if (!n || !(n->nud_state & NUD_VALID)) {
1605 neigh_event_send(rt->dst.neighbour, NULL); 1642 if (n)
1643 neigh_event_send(n, NULL);
1606 rt->rt_gateway = orig_gw; 1644 rt->rt_gateway = orig_gw;
1607 return -EAGAIN; 1645 return -EAGAIN;
1608 } else { 1646 } else {
1609 rt->rt_flags |= RTCF_REDIRECTED; 1647 rt->rt_flags |= RTCF_REDIRECTED;
1610 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, 1648 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
1611 rt->dst.neighbour);
1612 } 1649 }
1613 return 0; 1650 return 0;
1614} 1651}
@@ -2708,6 +2745,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
2708 .default_advmss = ipv4_default_advmss, 2745 .default_advmss = ipv4_default_advmss,
2709 .update_pmtu = ipv4_rt_blackhole_update_pmtu, 2746 .update_pmtu = ipv4_rt_blackhole_update_pmtu,
2710 .cow_metrics = ipv4_rt_blackhole_cow_metrics, 2747 .cow_metrics = ipv4_rt_blackhole_cow_metrics,
2748 .neigh_lookup = ipv4_neigh_lookup,
2711}; 2749};
2712 2750
2713struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) 2751struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig)
@@ -3303,7 +3341,7 @@ int __init ip_rt_init(void)
3303 xfrm_init(); 3341 xfrm_init();
3304 xfrm4_init(ip_rt_max_size); 3342 xfrm4_init(ip_rt_max_size);
3305#endif 3343#endif
3306 rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL); 3344 rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);
3307 3345
3308#ifdef CONFIG_SYSCTL 3346#ifdef CONFIG_SYSCTL
3309 register_pernet_subsys(&sysctl_route_ops); 3347 register_pernet_subsys(&sysctl_route_ops);