diff options
Diffstat (limited to 'sys/netinet/raw_ip.c')
-rw-r--r-- | sys/netinet/raw_ip.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 0157afb..00ec423 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -678,9 +678,12 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip) switch (cmd) { case PRC_IFDOWN: + IN_IFADDR_RLOCK(); TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { if (ia->ia_ifa.ifa_addr == sa && (ia->ia_flags & IFA_ROUTE)) { + ifa_ref(&ia->ia_ifa); + IN_IFADDR_RUNLOCK(); /* * in_ifscrub kills the interface route. */ @@ -692,18 +695,26 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip) * routing process they will come back. */ in_ifadown(&ia->ia_ifa, 0); + ifa_free(&ia->ia_ifa); break; } } + if (ia == NULL) /* If ia matched, already unlocked. */ + IN_IFADDR_RUNLOCK(); break; case PRC_IFUP: + IN_IFADDR_RLOCK(); TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { if (ia->ia_ifa.ifa_addr == sa) break; } - if (ia == 0 || (ia->ia_flags & IFA_ROUTE)) + if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) { + IN_IFADDR_RUNLOCK(); return; + } + ifa_ref(&ia->ia_ifa); + IN_IFADDR_RUNLOCK(); flags = RTF_UP; ifp = ia->ia_ifa.ifa_ifp; @@ -714,6 +725,7 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip) err = rtinit(&ia->ia_ifa, RTM_ADD, flags); if (err == 0) ia->ia_flags |= IFA_ROUTE; + ifa_free(&ia->ia_ifa); break; } } |