diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-01-04 16:03:48 +0000 |
commit | 78c388aed2b7184182c08428db1de6c872d815f5 (patch) | |
tree | 4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /net/ipv4/route.c | |
parent | eb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff) |
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r-- | net/ipv4/route.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 5788342c9..a3d002fae 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -5,7 +5,7 @@ * * ROUTE - implementation of the IP router. * - * Version: $Id: route.c,v 1.57 1998/08/26 12:04:09 davem Exp $ + * Version: $Id: route.c,v 1.58 1998/10/03 09:37:50 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -333,7 +333,7 @@ void rt_cache_flush(int delay) otherwise fire it at deadline time. */ - if (user_mode && (long)(rt_deadline-now) < ip_rt_max_delay-ip_rt_min_delay) + if (user_mode && tmo < ip_rt_max_delay-ip_rt_min_delay) tmo = 0; if (delay > tmo) @@ -432,7 +432,7 @@ static struct rtable *rt_intern_hash(unsigned hash, struct rtable * rt) rthp = &rth->u.rt_next; } - /* Try to bind route ro arp only if it is output + /* Try to bind route to arp only if it is output route or unicast forwarding path. */ if (rt->rt_type == RTN_UNICAST || rt->key.iif == 0) @@ -569,12 +569,26 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) struct rtable *rt = (struct rtable*)dst; if (rt != NULL) { - if (dst->obsolete || rt->rt_flags&RTCF_REDIRECTED) { + if (dst->obsolete) { + ip_rt_put(rt); + return NULL; + } + if (rt->rt_flags&RTCF_REDIRECTED) { + unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos); + struct rtable **rthp; #if RT_CACHE_DEBUG >= 1 printk(KERN_DEBUG "ip_rt_advice: redirect to %d.%d.%d.%d/%02x dropped\n", NIPQUAD(rt->rt_dst), rt->key.tos); #endif ip_rt_put(rt); - rt_cache_flush(0); + start_bh_atomic(); + for (rthp = &rt_hash_table[hash]; *rthp; rthp = &(*rthp)->u.rt_next) { + if (*rthp == rt) { + *rthp = rt->u.rt_next; + rt_free(rt); + break; + } + } + end_bh_atomic(); return NULL; } } @@ -654,12 +668,12 @@ static int ip_error(struct sk_buff *skb) } now = jiffies; - if ((rt->u.dst.rate_tokens += now - rt->u.dst.rate_last) > ip_rt_error_burst) + if ((rt->u.dst.rate_tokens += (now - rt->u.dst.rate_last)) > ip_rt_error_burst) rt->u.dst.rate_tokens = ip_rt_error_burst; + rt->u.dst.rate_last = now; if (rt->u.dst.rate_tokens >= ip_rt_error_cost) { rt->u.dst.rate_tokens -= ip_rt_error_cost; icmp_send(skb, ICMP_DEST_UNREACH, code, 0); - rt->u.dst.rate_last = now; } kfree_skb(skb); @@ -1004,8 +1018,8 @@ int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr, flags |= RTCF_DOREDIRECT; if (skb->protocol != __constant_htons(ETH_P_IP)) { - /* Not IP (i.e. ARP). Do not make route for invalid - * destination AND it is not translated destination. + /* Not IP (i.e. ARP). Do not create route, if it is + * invalid for proxy arp. DNAT routes are always valid. */ if (out_dev == in_dev && !(flags&RTCF_DNAT)) return -EINVAL; @@ -1069,6 +1083,7 @@ brd_input: flags |= RTCF_DIRECTSRC; } flags |= RTCF_BROADCAST; + res.type = RTN_BROADCAST; local_input: rth = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops); @@ -1227,7 +1242,7 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int if address is local --- clear the flag. */ if (dev_out == NULL) { - if (nochecksrc == 0) + if (nochecksrc == 0 || inet_addr_type(saddr) != RTN_UNICAST) return -EINVAL; flags |= RTCF_TPROXY; } @@ -1251,7 +1266,7 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int (MULTICAST(daddr) || daddr == 0xFFFFFFFF)) { /* Special hack: user can direct multicasts and limited broadcast via necessary interface - without fiddling with IP_MULTICAST_IF or IP_TXINFO. + without fiddling with IP_MULTICAST_IF or IP_PKTINFO. This hack is not just for fun, it allows vic,vat and friends to work. They bind socket to loopback, set ttl to zero @@ -1280,11 +1295,9 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK); goto make_route; } - if (MULTICAST(daddr)) { + if (MULTICAST(daddr)) key.src = inet_select_addr(dev_out, 0, key.scope); - goto make_route; - } - if (!daddr) + else if (!daddr) key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST); } @@ -1378,13 +1391,18 @@ make_route: flags |= RTCF_LOCAL; if (res.type == RTN_BROADCAST) { - flags |= RTCF_BROADCAST; - if (dev_out->flags&IFF_BROADCAST) - flags |= RTCF_LOCAL; + flags |= RTCF_BROADCAST|RTCF_LOCAL; + res.fi = NULL; } else if (res.type == RTN_MULTICAST) { flags |= RTCF_MULTICAST|RTCF_LOCAL; if (!ip_check_mc(dev_out, daddr)) flags &= ~RTCF_LOCAL; + /* If multicast route do not exist use + default one, but do not gateway in this case. + Yes, it is hack. + */ + if (res.fi && res.prefixlen < 4) + res.fi = NULL; } rth = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops); |