From 060c94f5be5dc06fae3d10b45b46f15f5b349d26 Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 22 Mar 2007 10:51:03 +0000 Subject: 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 --- sys/net/rtsock.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'sys/net/rtsock.c') diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index c13f4ec..16b94ad 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -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), + 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 (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_UNLOCK(rt); + senderr(error); + } + rt->rt_flags |= RTF_GATEWAY; } - 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_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. */ -- cgit v1.1