summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet/in.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet/in.c')
-rw-r--r--freebsd/sys/netinet/in.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/freebsd/sys/netinet/in.c b/freebsd/sys/netinet/in.c
index bc7323e3..653580c7 100644
--- a/freebsd/sys/netinet/in.c
+++ b/freebsd/sys/netinet/in.c
@@ -970,7 +970,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
{
struct in_ifaddr *ia;
struct in_addr prefix, mask, p, m;
- int error, fibnum;
+ int error;
if ((flags & RTF_HOST) != 0) {
prefix = target->ia_dstaddr.sin_addr;
@@ -981,9 +981,8 @@ in_addprefix(struct in_ifaddr *target, int flags)
prefix.s_addr &= mask.s_addr;
}
- fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS : target->ia_ifp->if_fib;
-
IN_IFADDR_RLOCK();
+ /* Look for an existing address with the same prefix, mask, and fib */
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (rtinitflags(ia)) {
p = ia->ia_dstaddr.sin_addr;
@@ -999,6 +998,8 @@ in_addprefix(struct in_ifaddr *target, int flags)
mask.s_addr != m.s_addr)
continue;
}
+ if (target->ia_ifp->if_fib != ia->ia_ifp->if_fib)
+ continue;
/*
* If we got a matching prefix route inserted by other
@@ -1019,6 +1020,10 @@ in_addprefix(struct in_ifaddr *target, int flags)
IN_IFADDR_RUNLOCK();
return (EEXIST);
} else {
+ int fibnum;
+
+ fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS :
+ target->ia_ifp->if_fib;
rt_addrmsg(RTM_ADD, &target->ia_ifa, fibnum);
IN_IFADDR_RUNLOCK();
return (0);
@@ -1048,11 +1053,9 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
{
struct in_ifaddr *ia;
struct in_addr prefix, mask, p;
- int error = 0, fibnum;
+ int error = 0;
struct sockaddr_in prefix0, mask0;
- fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS : target->ia_ifp->if_fib;
-
/*
* Remove the loopback route to the interface address.
* The "useloopback" setting is not consulted because if the
@@ -1068,10 +1071,12 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
(target->ia_flags & IFA_RTSELF)) {
struct route ia_ro;
int freeit = 0;
+ int fibnum;
bzero(&ia_ro, sizeof(ia_ro));
*((struct sockaddr_in *)(&ia_ro.ro_dst)) = target->ia_addr;
- rtalloc_ign_fib(&ia_ro, 0, 0);
+ fibnum = target->ia_ifp->if_fib;
+ rtalloc_ign_fib(&ia_ro, 0, fibnum);
if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
(ia_ro.ro_rt->rt_ifp == V_loif)) {
RT_LOCK(ia_ro.ro_rt);
@@ -1104,6 +1109,10 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
}
if ((target->ia_flags & IFA_ROUTE) == 0) {
+ int fibnum;
+
+ fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS :
+ target->ia_ifp->if_fib;
rt_addrmsg(RTM_DELETE, &target->ia_ifa, fibnum);
return (0);
}
@@ -1368,8 +1377,9 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr
KASSERT(l3addr->sa_family == AF_INET,
("sin_family %d", l3addr->sa_family));
- /* XXX rtalloc1 should take a const param */
- rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
+ /* XXX rtalloc1_fib should take a const param */
+ rt = rtalloc1_fib(__DECONST(struct sockaddr *, l3addr), 0, 0,
+ ifp->if_fib);
if (rt == NULL)
return (EINVAL);