Page MenuHomeFreeBSD

D20076.diff
No OneTemporary

D20076.diff

Index: head/sys/net/if.c
===================================================================
--- head/sys/net/if.c
+++ head/sys/net/if.c
@@ -264,7 +264,6 @@
static int if_setflag(struct ifnet *, int, int, int *, int);
static int if_transmit(struct ifnet *ifp, struct mbuf *m);
static void if_unroute(struct ifnet *, int flag, int fam);
-static void link_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
static int if_delmulti_locked(struct ifnet *, struct ifmultiaddr *, int);
static void do_link_state_change(void *, int);
static int if_getgroup(struct ifgroupreq *, struct ifnet *);
@@ -862,7 +861,6 @@
sdl->sdl_type = ifp->if_type;
ifp->if_addr = ifa;
ifa->ifa_ifp = ifp;
- ifa->ifa_rtrequest = link_rtrequest;
ifa->ifa_addr = (struct sockaddr *)sdl;
sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
ifa->ifa_netmask = (struct sockaddr *)sdl;
@@ -1892,6 +1890,7 @@
ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa,
struct sockaddr *ia)
{
+ struct epoch_tracker et;
int error;
struct rt_addrinfo info;
struct sockaddr_dl null_sdl;
@@ -1902,6 +1901,16 @@
bzero(&info, sizeof(info));
if (cmd != RTM_DELETE)
info.rti_ifp = V_loif;
+ if (cmd == RTM_ADD) {
+ /* explicitly specify (loopback) ifa */
+ if (info.rti_ifp != NULL) {
+ NET_EPOCH_ENTER(et);
+ info.rti_ifa = ifaof_ifpforaddr(ifa->ifa_addr, info.rti_ifp);
+ if (info.rti_ifa != NULL)
+ ifa_ref(info.rti_ifa);
+ NET_EPOCH_EXIT(et);
+ }
+ }
info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC | RTF_PINNED;
info.rti_info[RTAX_DST] = ia;
info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl;
@@ -2208,39 +2217,6 @@
return (cur->ifa_carp && (!next->ifa_carp ||
((*carp_master_p)(next) && !(*carp_master_p)(cur))));
-}
-
-#include <net/if_llatbl.h>
-
-/*
- * Default action when installing a route with a Link Level gateway.
- * Lookup an appropriate real ifa to point to.
- * This should be moved to /sys/net/link.c eventually.
- */
-static void
-link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
-{
- struct epoch_tracker et;
- struct ifaddr *ifa, *oifa;
- struct sockaddr *dst;
- struct ifnet *ifp;
-
- if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == NULL) ||
- ((ifp = ifa->ifa_ifp) == NULL) || ((dst = rt_key(rt)) == NULL))
- return;
- NET_EPOCH_ENTER(et);
- ifa = ifaof_ifpforaddr(dst, ifp);
- if (ifa) {
- oifa = rt->rt_ifa;
- if (oifa != ifa) {
- ifa_free(oifa);
- ifa_ref(ifa);
- }
- rt->rt_ifa = ifa;
- if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
- ifa->ifa_rtrequest(cmd, rt, info);
- }
- NET_EPOCH_EXIT(et);
}
struct sockaddr_dl *
Index: head/sys/net/route.c
===================================================================
--- head/sys/net/route.c
+++ head/sys/net/route.c
@@ -1276,12 +1276,14 @@
/*
* Look up rt_addrinfo for a specific fib. Note that if rti_ifa is defined,
* it will be referenced so the caller must free it.
+ *
+ * Assume basic consistency checks are executed by callers:
+ * RTAX_DST exists, if RTF_GATEWAY is set, RTAX_GATEWAY exists as well.
*/
int
rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum)
{
struct epoch_tracker et;
- struct ifaddr *ifa;
int needref, error;
/*
@@ -1291,21 +1293,54 @@
error = 0;
needref = (info->rti_ifa == NULL);
NET_EPOCH_ENTER(et);
+
+ /* If we have interface specified by the ifindex in the address, use it */
if (info->rti_ifp == NULL && ifpaddr != NULL &&
- ifpaddr->sa_family == AF_LINK &&
- (ifa = ifa_ifwithnet(ifpaddr, 0, fibnum)) != NULL) {
- info->rti_ifp = ifa->ifa_ifp;
+ ifpaddr->sa_family == AF_LINK) {
+ const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)ifpaddr;
+ if (sdl->sdl_index != 0)
+ info->rti_ifp = ifnet_byindex_locked(sdl->sdl_index);
}
+ /*
+ * If we have source address specified, try to find it
+ * TODO: avoid enumerating all ifas on all interfaces.
+ */
if (info->rti_ifa == NULL && ifaaddr != NULL)
info->rti_ifa = ifa_ifwithaddr(ifaaddr);
if (info->rti_ifa == NULL) {
struct sockaddr *sa;
- sa = ifaaddr != NULL ? ifaaddr :
- (gateway != NULL ? gateway : dst);
- if (sa != NULL && info->rti_ifp != NULL)
+ /*
+ * Most common use case for the userland-supplied routes.
+ *
+ * Choose sockaddr to select ifa.
+ * -- if ifp is set --
+ * Order of preference:
+ * 1) IFA address
+ * 2) gateway address
+ * Note: for interface routes link-level gateway address
+ * is specified to indicate the interface index without
+ * specifying RTF_GATEWAY. In this case, ignore gateway
+ * Note: gateway AF may be different from dst AF. In this case,
+ * ignore gateway
+ * 3) final destination.
+ * 4) if all of these fails, try to get at least link-level ifa.
+ * -- else --
+ * try to lookup gateway or dst in the routing table to get ifa
+ */
+ if (info->rti_info[RTAX_IFA] != NULL)
+ sa = info->rti_info[RTAX_IFA];
+ else if ((info->rti_flags & RTF_GATEWAY) != 0 &&
+ gateway->sa_family == dst->sa_family)
+ sa = gateway;
+ else
+ sa = dst;
+ if (info->rti_ifp != NULL) {
info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp);
- else if (dst != NULL && gateway != NULL)
+ /* Case 4 */
+ if (info->rti_ifa == NULL && gateway != NULL)
+ info->rti_ifa = ifaof_ifpforaddr(gateway, info->rti_ifp);
+ } else if (dst != NULL && gateway != NULL)
info->rti_ifa = ifa_ifwithroute(flags, dst, gateway,
fibnum);
else if (sa != NULL)

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 30, 12:58 AM (2 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14934276
Default Alt Text
D20076.diff (5 KB)

Event Timeline