patch-2.1.120 linux/net/ipv6/ndisc.c
Next file: linux/net/ipv6/proc.c
Previous file: linux/net/ipv6/mcast.c
Back to the patch index
Back to the overall index
- Lines: 271
- Date:
Thu Aug 27 19:33:09 1998
- Orig file:
v2.1.119/linux/net/ipv6/ndisc.c
- Orig date:
Thu May 14 19:47:45 1998
diff -u --recursive --new-file v2.1.119/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c
@@ -68,8 +68,7 @@
#include <net/ndisc.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
-
-
+#include <net/icmp.h>
#include <net/checksum.h>
#include <linux/proc_fs.h>
@@ -350,6 +349,9 @@
len, 0));
dev_queue_xmit(skb);
+
+ icmpv6_statistics.Icmp6OutNeighborAdvertisements++;
+ icmpv6_statistics.Icmp6OutMsgs++;
}
void ndisc_send_ns(struct device *dev, struct neighbour *neigh,
@@ -410,6 +412,9 @@
len, 0));
/* send it! */
dev_queue_xmit(skb);
+
+ icmpv6_statistics.Icmp6OutNeighborSolicits++;
+ icmpv6_statistics.Icmp6OutMsgs++;
}
void ndisc_send_rs(struct device *dev, struct in6_addr *saddr,
@@ -458,6 +463,9 @@
/* send it! */
dev_queue_xmit(skb);
+
+ icmpv6_statistics.Icmp6OutRouterSolicits++;
+ icmpv6_statistics.Icmp6OutMsgs++;
}
@@ -575,6 +583,7 @@
if (rt && lifetime == 0) {
ip6_del_rt(rt);
+ dst_release(&rt->u.dst);
rt = NULL;
}
@@ -582,11 +591,6 @@
ND_PRINTK2("ndisc_rdisc: adding default router\n");
rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
-
-#if 1
- /* BUGGGGG! Previous routine can return invalid pointer. */
- rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
-#endif
if (rt == NULL) {
ND_PRINTK1("route_add failed\n");
return;
@@ -595,6 +599,7 @@
neigh = rt->rt6i_nexthop;
if (neigh == NULL) {
ND_PRINTK1("nd: add default router: null neighbour\n");
+ dst_release(&rt->u.dst);
return;
}
neigh->flags |= NTF_ROUTER;
@@ -658,7 +663,7 @@
mtu = htonl(*(__u32 *)(opt+4));
- if (mtu < 576 || mtu > skb->dev->mtu) {
+ if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
ND_PRINTK0("NDISC: router "
"announcement with mtu = %d\n",
mtu);
@@ -671,10 +676,7 @@
if (rt)
rt->u.dst.pmtu = mtu;
- /* BUGGG... Scan routing tables and
- adjust mtu on routes going
- via this device
- */
+ rt6_mtu_change(skb->dev, mtu);
}
}
break;
@@ -689,6 +691,8 @@
optlen -= len;
opt += len;
}
+ if (rt)
+ dst_release(&rt->u.dst);
}
static void ndisc_redirect_rcv(struct sk_buff *skb)
@@ -698,7 +702,6 @@
struct in6_addr *dest;
struct in6_addr *target; /* new first hop to destination */
struct neighbour *neigh;
- struct rt6_info *rt;
int on_link = 0;
int optlen;
@@ -740,20 +743,21 @@
if (!in6_dev || in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects)
return;
- /* passed validation tests
+ /* passed validation tests */
- NOTE We should not install redirect if sender did not supply
- ll address on link, which requires it. It would break, if
- we have non-transitive address resolution protocol.
- Fix it later. --ANK
+ /*
+ We install redirect only if nexthop state is valid.
*/
- rt = rt6_redirect(dest, &skb->nh.ipv6h->saddr, target, skb->dev, on_link);
- if (rt == NULL)
- return;
-
- neigh = rt->rt6i_nexthop;
- ndisc_update(neigh, (u8*)(dest + 1), optlen, ND_OPT_TARGET_LL_ADDR);
+ neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
+ if (neigh) {
+ ndisc_update(neigh, (u8*)(dest + 1), optlen, ND_OPT_TARGET_LL_ADDR);
+ if (neigh->nud_state&NUD_VALID)
+ rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, on_link);
+ else
+ __neigh_event_send(neigh, NULL);
+ neigh_release(neigh);
+ }
}
void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
@@ -773,17 +777,21 @@
int hlen;
dev = skb->dev;
- rt = rt6_lookup(&skb->nh.ipv6h->saddr, NULL, dev->ifindex, 0);
+ rt = rt6_lookup(&skb->nh.ipv6h->saddr, NULL, dev->ifindex, 1);
- if (rt == NULL || rt->u.dst.error) {
- ND_PRINTK1("ndisc_send_redirect: hostunreach\n");
+ if (rt == NULL)
return;
- }
if (rt->rt6i_flags & RTF_GATEWAY) {
ND_PRINTK1("ndisc_send_redirect: not a neighbour\n");
+ dst_release(&rt->u.dst);
return;
}
+ if (!xrlim_allow(&rt->u.dst, 1*HZ)) {
+ dst_release(&rt->u.dst);
+ return;
+ }
+ dst_release(&rt->u.dst);
if (dev->addr_len) {
if (neigh->nud_state&NUD_VALID) {
@@ -797,7 +805,7 @@
}
}
- rd_len = min(536 - len, ntohs(skb->nh.ipv6h->payload_len) + 8);
+ rd_len = min(IPV6_MIN_MTU-sizeof(struct ipv6hdr)-len, ntohs(skb->nh.ipv6h->payload_len) + 8);
rd_len &= ~0x7;
len += rd_len;
@@ -814,14 +822,14 @@
ND_PRINTK1("ndisc_send_redirect: alloc_skb failed\n");
return;
}
-
+
hlen = 0;
if (ndisc_build_ll_hdr(buff, dev, &skb->nh.ipv6h->saddr, NULL, len) == 0) {
kfree_skb(buff);
return;
}
-
+
ip6_nd_hdr(sk, buff, dev, &ifp->addr, &skb->nh.ipv6h->saddr,
IPPROTO_ICMPV6, len);
@@ -838,9 +846,9 @@
ipv6_addr_copy(addrp, target);
addrp++;
ipv6_addr_copy(addrp, &skb->nh.ipv6h->daddr);
-
+
opt = (u8*) (addrp + 1);
-
+
/*
* include target_address option
*/
@@ -858,12 +866,15 @@
opt += 6;
memcpy(opt, &skb->nh.ipv6h, rd_len - 8);
-
+
icmph->icmp6_cksum = csum_ipv6_magic(&ifp->addr, &skb->nh.ipv6h->saddr,
len, IPPROTO_ICMPV6,
csum_partial((u8 *) icmph, len, 0));
dev_queue_xmit(buff);
+
+ icmpv6_statistics.Icmp6OutRedirects++;
+ icmpv6_statistics.Icmp6OutMsgs++;
}
static __inline__ struct neighbour *
@@ -894,15 +905,15 @@
static void pndisc_redo(struct sk_buff *skb)
{
- ndisc_rcv(skb, skb->dev, &skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
- NULL, skb->len);
+ ndisc_rcv(skb, skb->len);
kfree_skb(skb);
}
-int ndisc_rcv(struct sk_buff *skb, struct device *dev,
- struct in6_addr *saddr, struct in6_addr *daddr,
- struct ipv6_options *opt, unsigned short len)
+int ndisc_rcv(struct sk_buff *skb, unsigned long len)
{
+ struct device *dev = skb->dev;
+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
+ struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
struct nd_msg *msg = (struct nd_msg *) skb->h.raw;
struct neighbour *neigh;
struct inet6_ifaddr *ifp;
@@ -977,7 +988,7 @@
if (neigh) {
ndisc_send_na(dev, neigh, saddr, &msg->target,
- 1, 0, inc, inc);
+ 0, 0, inc, inc);
neigh_release(neigh);
}
} else {
@@ -1023,13 +1034,14 @@
/*
* Change: router to host
*/
-#if 0
struct rt6_info *rt;
- rt = ndisc_get_dflt_router(skb->dev,
- saddr);
- if (rt)
- ndisc_del_dflt_router(rt);
-#endif
+ rt = rt6_get_dflt_router(saddr, skb->dev);
+ if (rt) {
+ /* It is safe only because
+ we aer in BH */
+ dst_release(&rt->u.dst);
+ ip6_del_rt(rt);
+ }
}
} else {
if (msg->icmph.icmp6_router)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov