diff options
author | ru <ru@FreeBSD.org> | 2001-03-15 14:52:12 +0000 |
---|---|---|
committer | ru <ru@FreeBSD.org> | 2001-03-15 14:52:12 +0000 |
commit | e4b7d932a19a7e68b2fe6b5b0ccb5013fcfc7469 (patch) | |
tree | ffd1d748ab689b5fb13295902794e0dad4bc76fe /sys | |
parent | a2c5f8fdaca23b3981f7016495ca06ae12220d18 (diff) | |
download | FreeBSD-src-e4b7d932a19a7e68b2fe6b5b0ccb5013fcfc7469.zip FreeBSD-src-e4b7d932a19a7e68b2fe6b5b0ccb5013fcfc7469.tar.gz |
net/route.c:
A route generated from an RTF_CLONING route had the RTF_WASCLONED flag
set but did not have a reference to the parent route, as documented in
the rtentry(9) manpage. This prevented such routes from being deleted
when their parent route is deleted.
Now, for example, if you delete an IP address from a network interface,
all ARP entries that were cloned from this interface route are flushed.
This also has an impact on netstat(1) output. Previously, dynamically
created ARP cache entries (RTF_STATIC flag is unset) were displayed as
part of the routing table display (-r). Now, they are only printed if
the -a option is given.
netinet/in.c, netinet/in_rmx.c:
When address is removed from an interface, also delete all routes that
point to this interface and address. Previously, for example, if you
changed the address on an interface, outgoing IP datagrams might still
use the old address. The only solution was to delete and re-add some
routes. (The problem is easily observed with the route(8) command.)
Note, that if the socket was already bound to the local address before
this address is removed, new datagrams generated from this socket will
still be sent from the old address.
PR: kern/20785, kern/21914
Reviewed by: wollman (the idea)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/route.c | 7 | ||||
-rw-r--r-- | sys/netinet/in.c | 11 | ||||
-rw-r--r-- | sys/netinet/in_rmx.c | 18 |
3 files changed, 23 insertions, 13 deletions
diff --git a/sys/net/route.c b/sys/net/route.c index 38867f4..884f0eb 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -496,8 +496,9 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt) * Now search what's left of the subtree for any cloned * routes which might have been formed from this node. */ - if ((rt->rt_flags & RTF_PRCLONING) && netmask) { - rnh->rnh_walktree_from(rnh, dst, netmask, + if ((rt->rt_flags & (RTF_CLONING | RTF_PRCLONING)) && + rt_mask(rt)) { + rnh->rnh_walktree_from(rnh, dst, rt_mask(rt), rt_fixdelete, rt); } @@ -654,7 +655,7 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt) */ if (req == RTM_RESOLVE) { rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ - if ((*ret_nrt)->rt_flags & RTF_PRCLONING) { + if ((*ret_nrt)->rt_flags & (RTF_CLONING | RTF_PRCLONING)) { rt->rt_parent = (*ret_nrt); (*ret_nrt)->rt_refcnt++; } diff --git a/sys/netinet/in.c b/sys/netinet/in.c index b9ab8b3..27fbefb 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -413,8 +413,19 @@ in_control(so, cmd, data, ifp, p) return (error); case SIOCDIFADDR: + /* + * in_ifscrub kills the interface route. + */ in_ifscrub(ifp, ia); /* + * in_ifadown gets rid of all the rest of + * the routes. This is not quite the right + * thing to do, but at least if we are running + * a routing process they will come back. + */ + in_ifadown(&ia->ia_ifa); + + /* * Protect from ipintr() traversing address list * while we're modifying it. */ diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c index 52d062d..51a5846 100644 --- a/sys/netinet/in_rmx.c +++ b/sys/netinet/in_rmx.c @@ -357,14 +357,12 @@ in_inithead(void **head, int off) /* - * This zaps old routes when the interface goes down. - * Currently it doesn't delete static routes; there are - * arguments one could make for both behaviors. For the moment, - * we will adopt the Principle of Least Surprise and leave them - * alone (with the knowledge that this will not be enough for some - * people). The ones we really want to get rid of are things like ARP - * entries, since the user might down the interface, walk over to a completely - * different network, and plug back in. + * This zaps old routes (including ARP entries) when the interface + * address is deleted. Previously it didn't delete static routes, + * and this caused some weird things to happen. In particular, if + * you changed the address on an interface, and the default route + * was using this interface and address, outgoing datagrams still + * used the old address. */ struct in_ifadown_arg { struct radix_node_head *rnh; @@ -378,7 +376,7 @@ in_ifadownkill(struct radix_node *rn, void *xap) struct rtentry *rt = (struct rtentry *)rn; int err; - if (rt->rt_ifa == ap->ifa && !(rt->rt_flags & RTF_STATIC)) { + if (rt->rt_ifa == ap->ifa) { /* * We need to disable the automatic prune that happens * in this case in rtrequest() because it will blow @@ -387,7 +385,7 @@ in_ifadownkill(struct radix_node *rn, void *xap) * the routes that rtrequest() would have in any case, * so that behavior is not needed there. */ - rt->rt_flags &= ~RTF_PRCLONING; + rt->rt_flags &= ~(RTF_CLONING | RTF_PRCLONING); err = rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); if (err) { |