diff options
author | qingli <qingli@FreeBSD.org> | 2009-09-15 19:18:34 +0000 |
---|---|---|
committer | qingli <qingli@FreeBSD.org> | 2009-09-15 19:18:34 +0000 |
commit | 3a82e44273f4a5c05d848c2959b2a9d8188b1ba0 (patch) | |
tree | 8e25508f7a40afe500dc06cba8d3a6b18f4d7335 /sys/net/if.c | |
parent | 620c678111a81c88256575cb8a1e9fff36f90003 (diff) | |
download | FreeBSD-src-3a82e44273f4a5c05d848c2959b2a9d8188b1ba0.zip FreeBSD-src-3a82e44273f4a5c05d848c2959b2a9d8188b1ba0.tar.gz |
Self pointing routes are installed for configured interface addresses
and address aliases. After an interface is brought down and brought
back up again, those self pointing routes disappeared. This patch
ensures after an interface is brought back up, the loopback routes
are reinstalled properly.
Reviewed by: bz
MFC after: immediately
Diffstat (limited to 'sys/net/if.c')
-rw-r--r-- | sys/net/if.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 36c0d03..c0ff443 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1414,6 +1414,59 @@ ifa_free(struct ifaddr *ifa) } } +int +ifa_add_loopback_route(struct ifaddr *ifa, struct sockaddr *ia) +{ + int error = 0; + struct rtentry *rt = NULL; + struct rt_addrinfo info; + static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; + + bzero(&info, sizeof(info)); + info.rti_ifp = V_loif; + info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC; + info.rti_info[RTAX_DST] = ia; + info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl; + error = rtrequest1_fib(RTM_ADD, &info, &rt, 0); + + if (error == 0 && rt != NULL) { + RT_LOCK(rt); + ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type = + rt->rt_ifp->if_type; + ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index = + rt->rt_ifp->if_index; + RT_REMREF(rt); + RT_UNLOCK(rt); + } else if (error != 0) + log(LOG_INFO, "ifa_add_loopback_route: insertion failed\n"); + + return (error); +} + +int +ifa_del_loopback_route(struct ifaddr *ifa, struct sockaddr *ia) +{ + int error = 0; + struct rt_addrinfo info; + struct sockaddr_dl null_sdl; + + bzero(&null_sdl, sizeof(null_sdl)); + null_sdl.sdl_len = sizeof(null_sdl); + null_sdl.sdl_family = AF_LINK; + null_sdl.sdl_type = ifa->ifa_ifp->if_type; + null_sdl.sdl_index = ifa->ifa_ifp->if_index; + bzero(&info, sizeof(info)); + info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC; + info.rti_info[RTAX_DST] = ia; + info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl; + error = rtrequest1_fib(RTM_DELETE, &info, NULL, 0); + + if (error != 0) + log(LOG_INFO, "ifa_del_loopback_route: deletion failed\n"); + + return (error); +} + /* * XXX: Because sockaddr_dl has deeper structure than the sockaddr * structs used to represent other address families, it is necessary |