Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netpfil/pf/if_pfsync.c
Show First 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | |||||
VNET_DEFINE_STATIC(int, pfsync_carp_adj) = CARP_MAXSKEW; | VNET_DEFINE_STATIC(int, pfsync_carp_adj) = CARP_MAXSKEW; | ||||
#define V_pfsync_carp_adj VNET(pfsync_carp_adj) | #define V_pfsync_carp_adj VNET(pfsync_carp_adj) | ||||
static void pfsync_timeout(void *); | static void pfsync_timeout(void *); | ||||
static void pfsync_push(struct pfsync_bucket *); | static void pfsync_push(struct pfsync_bucket *); | ||||
static void pfsync_push_all(struct pfsync_softc *); | static void pfsync_push_all(struct pfsync_softc *); | ||||
static void pfsyncintr(void *); | static void pfsyncintr(void *); | ||||
static int pfsync_multicast_setup(struct pfsync_softc *, struct ifnet *, | static int pfsync_multicast_setup(struct pfsync_softc *, struct ifnet *, | ||||
void *); | struct in_mfilter *imf); | ||||
static void pfsync_multicast_cleanup(struct pfsync_softc *); | static void pfsync_multicast_cleanup(struct pfsync_softc *); | ||||
static void pfsync_pointers_init(void); | static void pfsync_pointers_init(void); | ||||
static void pfsync_pointers_uninit(void); | static void pfsync_pointers_uninit(void); | ||||
static int pfsync_init(void); | static int pfsync_init(void); | ||||
static void pfsync_uninit(void); | static void pfsync_uninit(void); | ||||
static unsigned long pfsync_buckets; | static unsigned long pfsync_buckets; | ||||
▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | pfsync_clone_destroy(struct ifnet *ifp) | ||||
if (!(sc->sc_flags & PFSYNCF_OK) && carp_demote_adj_p) | if (!(sc->sc_flags & PFSYNCF_OK) && carp_demote_adj_p) | ||||
(*carp_demote_adj_p)(-V_pfsync_carp_adj, "pfsync destroy"); | (*carp_demote_adj_p)(-V_pfsync_carp_adj, "pfsync destroy"); | ||||
bpfdetach(ifp); | bpfdetach(ifp); | ||||
if_detach(ifp); | if_detach(ifp); | ||||
pfsync_drop(sc); | pfsync_drop(sc); | ||||
if_free(ifp); | if_free(ifp); | ||||
if (sc->sc_imo.imo_membership) | |||||
pfsync_multicast_cleanup(sc); | pfsync_multicast_cleanup(sc); | ||||
mtx_destroy(&sc->sc_mtx); | mtx_destroy(&sc->sc_mtx); | ||||
mtx_destroy(&sc->sc_bulk_mtx); | mtx_destroy(&sc->sc_bulk_mtx); | ||||
free(sc->sc_buckets, M_PFSYNC); | free(sc->sc_buckets, M_PFSYNC); | ||||
free(sc, M_PFSYNC); | free(sc, M_PFSYNC); | ||||
V_pfsyncif = NULL; | V_pfsyncif = NULL; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 925 Lines • ▼ Show 20 Lines | case SIOCGETPFSYNC: | ||||
pfsyncr.pfsyncr_defer = (PFSYNCF_DEFER == | pfsyncr.pfsyncr_defer = (PFSYNCF_DEFER == | ||||
(sc->sc_flags & PFSYNCF_DEFER)); | (sc->sc_flags & PFSYNCF_DEFER)); | ||||
PFSYNC_UNLOCK(sc); | PFSYNC_UNLOCK(sc); | ||||
return (copyout(&pfsyncr, ifr_data_get_ptr(ifr), | return (copyout(&pfsyncr, ifr_data_get_ptr(ifr), | ||||
sizeof(pfsyncr))); | sizeof(pfsyncr))); | ||||
case SIOCSETPFSYNC: | case SIOCSETPFSYNC: | ||||
{ | { | ||||
struct ip_moptions *imo = &sc->sc_imo; | struct in_mfilter *imf = NULL; | ||||
struct ifnet *sifp; | struct ifnet *sifp; | ||||
struct ip *ip; | struct ip *ip; | ||||
void *mship = NULL; | |||||
if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0) | if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0) | ||||
return (error); | return (error); | ||||
if ((error = copyin(ifr_data_get_ptr(ifr), &pfsyncr, | if ((error = copyin(ifr_data_get_ptr(ifr), &pfsyncr, | ||||
sizeof(pfsyncr)))) | sizeof(pfsyncr)))) | ||||
return (error); | return (error); | ||||
if (pfsyncr.pfsyncr_maxupdates > 255) | if (pfsyncr.pfsyncr_maxupdates > 255) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (pfsyncr.pfsyncr_syncdev[0] == 0) | if (pfsyncr.pfsyncr_syncdev[0] == 0) | ||||
sifp = NULL; | sifp = NULL; | ||||
else if ((sifp = ifunit_ref(pfsyncr.pfsyncr_syncdev)) == NULL) | else if ((sifp = ifunit_ref(pfsyncr.pfsyncr_syncdev)) == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (sifp != NULL && ( | if (sifp != NULL && ( | ||||
pfsyncr.pfsyncr_syncpeer.s_addr == 0 || | pfsyncr.pfsyncr_syncpeer.s_addr == 0 || | ||||
pfsyncr.pfsyncr_syncpeer.s_addr == | pfsyncr.pfsyncr_syncpeer.s_addr == | ||||
htonl(INADDR_PFSYNC_GROUP))) | htonl(INADDR_PFSYNC_GROUP))) | ||||
mship = malloc((sizeof(struct in_multi *) * | imf = ip_mfilter_alloc(M_WAITOK, 0, 0); | ||||
IP_MIN_MEMBERSHIPS), M_PFSYNC, M_WAITOK | M_ZERO); | |||||
PFSYNC_LOCK(sc); | PFSYNC_LOCK(sc); | ||||
if (pfsyncr.pfsyncr_syncpeer.s_addr == 0) | if (pfsyncr.pfsyncr_syncpeer.s_addr == 0) | ||||
sc->sc_sync_peer.s_addr = htonl(INADDR_PFSYNC_GROUP); | sc->sc_sync_peer.s_addr = htonl(INADDR_PFSYNC_GROUP); | ||||
else | else | ||||
sc->sc_sync_peer.s_addr = | sc->sc_sync_peer.s_addr = | ||||
pfsyncr.pfsyncr_syncpeer.s_addr; | pfsyncr.pfsyncr_syncpeer.s_addr; | ||||
sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates; | sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates; | ||||
if (pfsyncr.pfsyncr_defer) { | if (pfsyncr.pfsyncr_defer) { | ||||
sc->sc_flags |= PFSYNCF_DEFER; | sc->sc_flags |= PFSYNCF_DEFER; | ||||
V_pfsync_defer_ptr = pfsync_defer; | V_pfsync_defer_ptr = pfsync_defer; | ||||
} else { | } else { | ||||
sc->sc_flags &= ~PFSYNCF_DEFER; | sc->sc_flags &= ~PFSYNCF_DEFER; | ||||
V_pfsync_defer_ptr = NULL; | V_pfsync_defer_ptr = NULL; | ||||
} | } | ||||
if (sifp == NULL) { | if (sifp == NULL) { | ||||
if (sc->sc_sync_if) | if (sc->sc_sync_if) | ||||
if_rele(sc->sc_sync_if); | if_rele(sc->sc_sync_if); | ||||
sc->sc_sync_if = NULL; | sc->sc_sync_if = NULL; | ||||
if (imo->imo_membership) | |||||
pfsync_multicast_cleanup(sc); | pfsync_multicast_cleanup(sc); | ||||
PFSYNC_UNLOCK(sc); | PFSYNC_UNLOCK(sc); | ||||
break; | break; | ||||
} | } | ||||
for (c = 0; c < pfsync_buckets; c++) { | for (c = 0; c < pfsync_buckets; c++) { | ||||
PFSYNC_BUCKET_LOCK(&sc->sc_buckets[c]); | PFSYNC_BUCKET_LOCK(&sc->sc_buckets[c]); | ||||
if (sc->sc_buckets[c].b_len > PFSYNC_MINPKT && | if (sc->sc_buckets[c].b_len > PFSYNC_MINPKT && | ||||
(sifp->if_mtu < sc->sc_ifp->if_mtu || | (sifp->if_mtu < sc->sc_ifp->if_mtu || | ||||
(sc->sc_sync_if != NULL && | (sc->sc_sync_if != NULL && | ||||
sifp->if_mtu < sc->sc_sync_if->if_mtu) || | sifp->if_mtu < sc->sc_sync_if->if_mtu) || | ||||
sifp->if_mtu < MCLBYTES - sizeof(struct ip))) | sifp->if_mtu < MCLBYTES - sizeof(struct ip))) | ||||
pfsync_sendout(1, c); | pfsync_sendout(1, c); | ||||
PFSYNC_BUCKET_UNLOCK(&sc->sc_buckets[c]); | PFSYNC_BUCKET_UNLOCK(&sc->sc_buckets[c]); | ||||
} | } | ||||
if (imo->imo_membership) | |||||
pfsync_multicast_cleanup(sc); | pfsync_multicast_cleanup(sc); | ||||
if (sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) { | if (sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) { | ||||
error = pfsync_multicast_setup(sc, sifp, mship); | error = pfsync_multicast_setup(sc, sifp, imf); | ||||
if (error) { | if (error) { | ||||
if_rele(sifp); | if_rele(sifp); | ||||
free(mship, M_PFSYNC); | ip_mfilter_free(imf); | ||||
PFSYNC_UNLOCK(sc); | PFSYNC_UNLOCK(sc); | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
if (sc->sc_sync_if) | if (sc->sc_sync_if) | ||||
if_rele(sc->sc_sync_if); | if_rele(sc->sc_sync_if); | ||||
sc->sc_sync_if = sifp; | sc->sc_sync_if = sifp; | ||||
▲ Show 20 Lines • Show All 893 Lines • ▼ Show 20 Lines | for (; m != NULL; m = n) { | ||||
else | else | ||||
V_pfsyncstats.pfsyncs_oerrors++; | V_pfsyncstats.pfsyncs_oerrors++; | ||||
} | } | ||||
} | } | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
} | } | ||||
static int | static int | ||||
pfsync_multicast_setup(struct pfsync_softc *sc, struct ifnet *ifp, void *mship) | pfsync_multicast_setup(struct pfsync_softc *sc, struct ifnet *ifp, | ||||
struct in_mfilter *imf) | |||||
{ | { | ||||
struct ip_moptions *imo = &sc->sc_imo; | struct ip_moptions *imo = &sc->sc_imo; | ||||
int error; | int error; | ||||
if (!(ifp->if_flags & IFF_MULTICAST)) | if (!(ifp->if_flags & IFF_MULTICAST)) | ||||
return (EADDRNOTAVAIL); | return (EADDRNOTAVAIL); | ||||
imo->imo_membership = (struct in_multi **)mship; | |||||
imo->imo_max_memberships = IP_MIN_MEMBERSHIPS; | |||||
imo->imo_multicast_vif = -1; | imo->imo_multicast_vif = -1; | ||||
if ((error = in_joingroup(ifp, &sc->sc_sync_peer, NULL, | if ((error = in_joingroup(ifp, &sc->sc_sync_peer, NULL, | ||||
&imo->imo_membership[0])) != 0) { | &imf->imf_inm)) != 0) | ||||
imo->imo_membership = NULL; | |||||
return (error); | return (error); | ||||
} | |||||
imo->imo_num_memberships++; | ip_mfilter_init(&imo->imo_head); | ||||
ip_mfilter_insert(&imo->imo_head, imf); | |||||
imo->imo_multicast_ifp = ifp; | imo->imo_multicast_ifp = ifp; | ||||
imo->imo_multicast_ttl = PFSYNC_DFLTTL; | imo->imo_multicast_ttl = PFSYNC_DFLTTL; | ||||
imo->imo_multicast_loop = 0; | imo->imo_multicast_loop = 0; | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
pfsync_multicast_cleanup(struct pfsync_softc *sc) | pfsync_multicast_cleanup(struct pfsync_softc *sc) | ||||
{ | { | ||||
struct ip_moptions *imo = &sc->sc_imo; | struct ip_moptions *imo = &sc->sc_imo; | ||||
struct in_mfilter *imf; | |||||
in_leavegroup(imo->imo_membership[0], NULL); | while ((imf = ip_mfilter_first(&imo->imo_head)) != NULL) { | ||||
free(imo->imo_membership, M_PFSYNC); | ip_mfilter_remove(&imo->imo_head, imf); | ||||
imo->imo_membership = NULL; | in_leavegroup(imf->imf_inm, NULL); | ||||
ip_mfilter_free(imf); | |||||
} | |||||
imo->imo_multicast_ifp = NULL; | imo->imo_multicast_ifp = NULL; | ||||
} | } | ||||
void | void | ||||
pfsync_detach_ifnet(struct ifnet *ifp) | pfsync_detach_ifnet(struct ifnet *ifp) | ||||
{ | { | ||||
struct pfsync_softc *sc = V_pfsyncif; | struct pfsync_softc *sc = V_pfsyncif; | ||||
if (sc == NULL) | if (sc == NULL) | ||||
return; | return; | ||||
PFSYNC_LOCK(sc); | PFSYNC_LOCK(sc); | ||||
if (sc->sc_sync_if == ifp) { | if (sc->sc_sync_if == ifp) { | ||||
/* We don't need mutlicast cleanup here, because the interface | /* We don't need mutlicast cleanup here, because the interface | ||||
* is going away. We do need to ensure we don't try to do | * is going away. We do need to ensure we don't try to do | ||||
* cleanup later. | * cleanup later. | ||||
*/ | */ | ||||
sc->sc_imo.imo_membership = NULL; | ip_mfilter_init(&sc->sc_imo.imo_head); | ||||
sc->sc_imo.imo_multicast_ifp = NULL; | sc->sc_imo.imo_multicast_ifp = NULL; | ||||
sc->sc_sync_if = NULL; | sc->sc_sync_if = NULL; | ||||
} | } | ||||
PFSYNC_UNLOCK(sc); | PFSYNC_UNLOCK(sc); | ||||
} | } | ||||
#ifdef INET | #ifdef INET | ||||
▲ Show 20 Lines • Show All 137 Lines • Show Last 20 Lines |