Skip to content

Commit 1ebec5f

Browse files
committed
route: fix missed ref adds
- ensure that we bump the ifa ref whenever we add a reference - defer freeing epoch protected references until after the if_purgaddrs loop
1 parent 20c44ba commit 1ebec5f

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

sys/net/if.c

+7-4
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ if_purgeaddrs(struct ifnet *ifp)
967967
{
968968
struct ifaddr *ifa, *next;
969969

970-
/* XXX cannot hold IF_ADDR_WLOCK over called functions. */
970+
NET_EPOCH_ENTER();
971971
CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
972972
if (ifa->ifa_addr->sa_family == AF_LINK)
973973
continue;
@@ -997,6 +997,7 @@ if_purgeaddrs(struct ifnet *ifp)
997997
IF_ADDR_WUNLOCK(ifp);
998998
ifa_free(ifa);
999999
}
1000+
NET_EPOCH_EXIT();
10001001
}
10011002

10021003
/*
@@ -2196,6 +2197,10 @@ link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
21962197
ifa = ifaof_ifpforaddr(dst, ifp);
21972198
if (ifa) {
21982199
oifa = rt->rt_ifa;
2200+
if (oifa != ifa) {
2201+
ifa_free(oifa);
2202+
ifa_ref(ifa);
2203+
}
21992204
rt->rt_ifa = ifa;
22002205
if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
22012206
ifa->ifa_rtrequest(cmd, rt, info);
@@ -3675,10 +3680,8 @@ if_delmulti_ifma_flags(struct ifmultiaddr *ifma, int flags)
36753680
CK_STAILQ_FOREACH(oifp, &V_ifnet, if_link)
36763681
if (ifp == oifp)
36773682
break;
3678-
if (ifp != oifp) {
3679-
printf("%s: ifnet %p disappeared\n", __func__, ifp);
3683+
if (ifp != oifp)
36803684
ifp = NULL;
3681-
}
36823685
IFNET_RUNLOCK_NOSLEEP();
36833686
}
36843687
#endif

sys/net/route.c

+11-4
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ rtredirect_fib(struct sockaddr *dst,
653653
info.rti_info[RTAX_DST] = dst;
654654
info.rti_info[RTAX_GATEWAY] = gateway;
655655
info.rti_info[RTAX_NETMASK] = netmask;
656+
ifa_ref(ifa);
656657
info.rti_ifa = ifa;
657658
info.rti_flags = flags;
658659
error = rtrequest1_fib(RTM_ADD, &info, &rt, fibnum);
@@ -899,7 +900,7 @@ rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *info, int flags)
899900
info->rti_flags = rt->rt_flags;
900901
info->rti_ifp = rt->rt_ifp;
901902
info->rti_ifa = rt->rt_ifa;
902-
903+
ifa_ref(info->rti_ifa);
903904
if (flags & NHR_REF) {
904905
/* Do 'traditional' refcouting */
905906
if_ref(info->rti_ifp);
@@ -1275,12 +1276,14 @@ int
12751276
rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum)
12761277
{
12771278
struct ifaddr *ifa;
1278-
int error = 0;
1279+
int needref, error;
12791280

12801281
/*
12811282
* ifp may be specified by sockaddr_dl
12821283
* when protocol address is ambiguous.
12831284
*/
1285+
error = 0;
1286+
needref = (info->rti_ifa == NULL);
12841287
NET_EPOCH_ENTER();
12851288
if (info->rti_ifp == NULL && ifpaddr != NULL &&
12861289
ifpaddr->sa_family == AF_LINK &&
@@ -1303,7 +1306,7 @@ rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum)
13031306
info->rti_ifa = ifa_ifwithroute(flags, sa, sa,
13041307
fibnum);
13051308
}
1306-
if ((ifa = info->rti_ifa) != NULL) {
1309+
if (needref && info->rti_ifa != NULL) {
13071310
if (info->rti_ifp == NULL)
13081311
info->rti_ifp = ifa->ifa_ifp;
13091312
ifa_ref(info->rti_ifa);
@@ -1785,6 +1788,7 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_addrinfo *info,
17851788
if (rt->rt_ifa->ifa_rtrequest != NULL)
17861789
rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, info);
17871790
ifa_free(rt->rt_ifa);
1791+
rt->rt_ifa = NULL;
17881792
}
17891793
/* Update gateway address */
17901794
if (info->rti_info[RTAX_GATEWAY] != NULL) {
@@ -1836,8 +1840,10 @@ rtrequest1_fib_change(struct rib_head *rnh, struct rt_addrinfo *info,
18361840
}
18371841
bad:
18381842
RT_UNLOCK(rt);
1839-
if (free_ifa != 0)
1843+
if (free_ifa != 0) {
18401844
ifa_free(info->rti_ifa);
1845+
info->rti_ifa = NULL;
1846+
}
18411847
return (error);
18421848
}
18431849

@@ -2052,6 +2058,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
20522058
* Do the actual request
20532059
*/
20542060
bzero((caddr_t)&info, sizeof(info));
2061+
ifa_ref(ifa);
20552062
info.rti_ifa = ifa;
20562063
info.rti_flags = flags |
20572064
(ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;

0 commit comments

Comments
 (0)