When working on an RTM_CHANGE do the route editing in the following

sequence. First, if rt_ifa is going to be changed, then call
ifa_rtrequest(RTM_DELETE). Second, if gateway is going to be changed,
then call rt_setgate(). Third, change rt_ifa.

With this change we are able to change a link level route to a
gateway one, that wasn't possible before:

	# ifconfig em0 192.168.22.1/24
        # arp -s 192.168.22.99 00:11:22:33:44:55
        # route change 192.168.22.99 192.168.22.199
        # ping 192.168.22.99
	db>

Reported by:	avatar
This commit is contained in:
glebius 2007-03-22 10:51:03 +00:00
parent d983ff428e
commit 060c94f5be

View File

@ -318,7 +318,6 @@ route_output(struct mbuf *m, struct socket *so)
struct rt_addrinfo info;
int len, error = 0;
struct ifnet *ifp = NULL;
struct ifaddr *ifa = NULL;
struct sockaddr_in jail;
#define senderr(e) { error = e; goto flush;}
@ -515,25 +514,25 @@ route_output(struct mbuf *m, struct socket *so)
senderr(error);
RT_LOCK(rt);
}
if (info.rti_info[RTAX_GATEWAY] != NULL &&
(error = rt_setgate(rt, rt_key(rt),
info.rti_info[RTAX_GATEWAY])) != 0) {
RT_UNLOCK(rt);
senderr(error);
if (info.rti_ifa != rt->rt_ifa && rt->rt_ifa != NULL &&
rt->rt_ifa->ifa_rtrequest != NULL) {
rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt,
&info);
IFAFREE(rt->rt_ifa);
}
if ((ifa = info.rti_ifa) != NULL) {
struct ifaddr *oifa = rt->rt_ifa;
if (oifa != ifa) {
if (oifa) {
if (oifa->ifa_rtrequest)
oifa->ifa_rtrequest(
RTM_DELETE, rt,
&info);
IFAFREE(oifa);
}
IFAREF(ifa);
rt->rt_ifa = ifa;
rt->rt_ifp = info.rti_ifp;
if (info.rti_info[RTAX_GATEWAY] != NULL) {
if ((error = rt_setgate(rt, rt_key(rt),
info.rti_info[RTAX_GATEWAY])) != 0) {
RT_UNLOCK(rt);
senderr(error);
}
rt->rt_flags |= RTF_GATEWAY;
}
if (info.rti_ifa != rt->rt_ifa) {
rt->rt_ifa = info.rti_ifa;
if (info.rti_ifa != NULL) {
IFAREF(info.rti_ifa);
rt->rt_ifp = info.rti_ifp;
}
}
/* Allow some flags to be toggled on change. */