diff options
-rw-r--r-- | share/man/man9/EVENTHANDLER.9 | 4 | ||||
-rw-r--r-- | sys/net/if.c | 12 | ||||
-rw-r--r-- | sys/net/if_var.h | 5 | ||||
-rw-r--r-- | sys/netinet/in.c | 10 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 8 |
5 files changed, 34 insertions, 5 deletions
diff --git a/share/man/man9/EVENTHANDLER.9 b/share/man/man9/EVENTHANDLER.9 index fd9411b7a9e7..bf9877032796 100644 --- a/share/man/man9/EVENTHANDLER.9 +++ b/share/man/man9/EVENTHANDLER.9 @@ -23,7 +23,7 @@ .\" SUCH DAMAGE. .\" $FreeBSD$ .\" -.Dd September 6, 2018 +.Dd October 21, 2018 .Dt EVENTHANDLER 9 .Os .Sh NAME @@ -298,6 +298,8 @@ Callback invoked when an change has been made to an interface group. Callback invoked when an interfance has been removed from an interface group. .It Vt ifaddr_event Callbacks invoked when an address is set up on a network interface. +.It Vt ifaddr_event_ext +Callback invoked when an address has been added or removed from an interface. .It Vt if_clone_event Callbacks invoked when an interface is cloned. .It Vt iflladdr_event diff --git a/sys/net/if.c b/sys/net/if.c index 2acea128cdfd..3469f75f1354 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -328,6 +328,18 @@ static MALLOC_DEFINE(M_IFNET, "ifnet", "interface internals"); MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address"); MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address"); +/* + * Support for old ifaddr_event. + */ +static void +ifaddr_event_compat(void *arg __unused, struct ifnet *ifp, + struct ifaddr *ifa __unused, int event __unused) +{ + + EVENTHANDLER_INVOKE(ifaddr_event, ifp); +} +EVENTHANDLER_DEFINE(ifaddr_event_ext, ifaddr_event_compat, NULL, 0); + struct ifnet * ifnet_byindex_locked(u_short idx) { diff --git a/sys/net/if_var.h b/sys/net/if_var.h index c9452406a151..a7edae305223 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -432,6 +432,11 @@ EVENTHANDLER_DECLARE(iflladdr_event, iflladdr_event_handler_t); /* interface address change event */ typedef void (*ifaddr_event_handler_t)(void *, struct ifnet *); EVENTHANDLER_DECLARE(ifaddr_event, ifaddr_event_handler_t); +typedef void (*ifaddr_event_ext_handler_t)(void *, struct ifnet *, + struct ifaddr *, int); +EVENTHANDLER_DECLARE(ifaddr_event_ext, ifaddr_event_ext_handler_t); +#define IFADDR_EVENT_ADD 0 +#define IFADDR_EVENT_DEL 1 /* new interface arrival event */ typedef void (*ifnet_arrival_event_handler_t)(void *, struct ifnet *); EVENTHANDLER_DECLARE(ifnet_arrival_event, ifnet_arrival_event_handler_t); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 9646f73a2045..a08860b125cb 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -520,7 +520,12 @@ in_aifaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) &ii->ii_allhosts); } - EVENTHANDLER_INVOKE(ifaddr_event, ifp); + /* + * Note: we don't need extra reference for ifa, since we called + * with sx lock held, and ifaddr can not be deleted in concurrent + * thread. + */ + EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, ifa, IFADDR_EVENT_ADD); return (error); @@ -643,7 +648,8 @@ in_difaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) } IF_ADDR_WUNLOCK(ifp); - EVENTHANDLER_INVOKE(ifaddr_event, ifp); + EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, + IFADDR_EVENT_DEL); ifa_free(&ia->ia_ifa); /* in_ifaddrhead */ return (0); diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 82eb08fb505e..5fb8b72bce25 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -712,7 +712,8 @@ aifaddr_out: ND6_WUNLOCK(); nd6_prefix_del(pr); } - EVENTHANDLER_INVOKE(ifaddr_event, ifp); + EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, + IFADDR_EVENT_DEL); break; } @@ -1456,7 +1457,10 @@ done: WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "Invoking IPv6 network device address event may sleep"); - EVENTHANDLER_INVOKE(ifaddr_event, ifp); + ifa_ref(&ia->ia_ifa); + EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, + IFADDR_EVENT_ADD); + ifa_free(&ia->ia_ifa); return (error); } |