diff options
Diffstat (limited to 'sys/net/if_pfsync.c')
-rw-r--r-- | sys/net/if_pfsync.c | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c index a7e5ab34736..d3b1e43f41c 100644 --- a/sys/net/if_pfsync.c +++ b/sys/net/if_pfsync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.c,v 1.179 2011/12/01 20:43:03 mcbride Exp $ */ +/* $OpenBSD: if_pfsync.c,v 1.180 2012/01/16 10:28:02 mikeb Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff @@ -228,6 +228,8 @@ struct pfsync_softc { TAILQ_HEAD(, tdb) sc_tdb_q; + void *sc_lhcookie; + struct timeout sc_tmo; }; @@ -244,6 +246,7 @@ int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int pfsyncioctl(struct ifnet *, u_long, caddr_t); void pfsyncstart(struct ifnet *); +void pfsync_syncdev_state(void *); struct mbuf *pfsync_if_dequeue(struct ifnet *); @@ -355,6 +358,10 @@ pfsync_clone_destroy(struct ifnet *ifp) if (!pfsync_sync_ok) carp_group_demote_adj(&sc->sc_if, -1, "pfsync destroy"); #endif + if (sc->sc_lhcookie != NULL) + hook_disestablish( + sc->sc_sync_if->if_linkstatehooks, + sc->sc_lhcookie); if_detach(ifp); pfsync_drop(sc); @@ -402,6 +409,37 @@ pfsyncstart(struct ifnet *ifp) splx(s); } +void +pfsync_syncdev_state(void *arg) +{ + struct pfsync_softc *sc = arg; + + if (!sc->sc_sync_if) + return; + + if (sc->sc_sync_if->if_link_state == LINK_STATE_DOWN || + !(sc->sc_sync_if->if_flags & IFF_UP)) { + sc->sc_if.if_flags &= ~IFF_RUNNING; +#if NCARP > 0 + carp_group_demote_adj(&sc->sc_if, 1, "pfsyncdev"); +#endif + /* drop everything */ + timeout_del(&sc->sc_tmo); + pfsync_drop(sc); + + /* cancel bulk update */ + timeout_del(&sc->sc_bulk_tmo); + sc->sc_bulk_next = NULL; + sc->sc_bulk_last = NULL; + } else { + sc->sc_if.if_flags |= IFF_RUNNING; + pfsync_request_full_update(sc); +#if NCARP > 0 + carp_group_demote_adj(&sc->sc_if, -1, "pfsyncdev"); +#endif + } +} + int pfsync_alloc_scrub_memory(struct pfsync_state_peer *s, struct pf_state_peer *d) @@ -1355,6 +1393,10 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sc->sc_defer = pfsyncr.pfsyncr_defer; if (pfsyncr.pfsyncr_syncdev[0] == 0) { + if (sc->sc_lhcookie != NULL) + hook_disestablish( + sc->sc_sync_if->if_linkstatehooks, + sc->sc_lhcookie); sc->sc_sync_if = NULL; if (imo->imo_num_memberships > 0) { in_delmulti(imo->imo_membership[ @@ -1387,6 +1429,10 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct in_addr addr; if (!(sc->sc_sync_if->if_flags & IFF_MULTICAST)) { + if (sc->sc_lhcookie != NULL) + hook_disestablish( + sc->sc_sync_if->if_linkstatehooks, + sc->sc_lhcookie); sc->sc_sync_if = NULL; splx(s); return (EADDRNOTAVAIL); @@ -1396,6 +1442,10 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if ((imo->imo_membership[0] = in_addmulti(&addr, sc->sc_sync_if)) == NULL) { + if (sc->sc_lhcookie != NULL) + hook_disestablish( + sc->sc_sync_if->if_linkstatehooks, + sc->sc_lhcookie); sc->sc_sync_if = NULL; splx(s); return (ENOBUFS); @@ -1418,6 +1468,10 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) ip->ip_src.s_addr = INADDR_ANY; ip->ip_dst.s_addr = sc->sc_sync_peer.s_addr; + sc->sc_lhcookie = + hook_establish(sc->sc_sync_if->if_linkstatehooks, 1, + pfsync_syncdev_state, sc); + pfsync_request_full_update(sc); splx(s); |