]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/if_pflog.c
xnu-2782.30.5.tar.gz
[apple/xnu.git] / bsd / net / if_pflog.c
index 278a7b19897a5c8a161827cf0b503ab197e555e6..3bc86c8209cd2eb6dc6f2ee04e0b02e7f53099ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
 #include <sys/proc_internal.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
+#include <sys/mcache.h>
 
 #include <net/if.h>
+#include <net/if_var.h>
 #include <net/if_types.h>
 #include <net/route.h>
 #include <net/bpf.h>
 #define DPRINTF(x)
 #endif
 
-static int pflog_create_dev(void);
+static int pflog_clone_create(struct if_clone *, u_int32_t, void *);
+static int pflog_clone_destroy(struct ifnet *);
 static errno_t pflogoutput(struct ifnet *, struct mbuf *);
 static errno_t pflogioctl(struct ifnet *, unsigned long, void *);
 static errno_t pflogdemux(struct ifnet *, struct mbuf *, char *,
@@ -108,50 +111,39 @@ static errno_t pflogdemux(struct ifnet *, struct mbuf *, char *,
 static errno_t pflogaddproto(struct ifnet *, protocol_family_t,
     const struct ifnet_demux_desc *, u_int32_t);
 static errno_t pflogdelproto(struct ifnet *, protocol_family_t);
+static void pflogfree(struct ifnet *);
 
 static LIST_HEAD(, pflog_softc)        pflogif_list;
+static struct if_clone pflog_cloner =
+    IF_CLONE_INITIALIZER(PFLOGNAME, pflog_clone_create, pflog_clone_destroy,
+        0, (PFLOGIFS_MAX - 1));
 
 struct ifnet *pflogifs[PFLOGIFS_MAX];  /* for fast access */
-static int npflog;
-static lck_attr_t *pflog_lock_attr;
-static lck_grp_t *pflog_lock_grp;
-static lck_grp_attr_t *pflog_lock_grp_attr;
-static lck_mtx_t *pflog_lock;
 
 void
 pfloginit(void)
 {
        int i;
 
-       if (pflog_lock != NULL)
-               return;
-
-       pflog_lock_grp_attr = lck_grp_attr_alloc_init();
-       pflog_lock_grp = lck_grp_alloc_init("pflog", pflog_lock_grp_attr);
-       pflog_lock_attr = lck_attr_alloc_init();
-       pflog_lock = lck_mtx_alloc_init(pflog_lock_grp, pflog_lock_attr);
-       if (pflog_lock == NULL) {
-               panic("%s: unable to allocate lock", __func__);
-               /* NOTREACHED */
-       }
        LIST_INIT(&pflogif_list);
        for (i = 0; i < PFLOGIFS_MAX; i++)
                pflogifs[i] = NULL;
 
-       pflog_create_dev();
+       (void) if_clone_attach(&pflog_cloner);
 }
 
 static int
-pflog_create_dev(void)
+pflog_clone_create(struct if_clone *ifc, u_int32_t unit, __unused void *params)
 {
        struct pflog_softc *pflogif;
        struct ifnet_init_params pf_init;
        int error = 0;
 
-       lck_mtx_lock(pflog_lock);
-       if (npflog >= PFLOGIFS_MAX) {
-               error = EINVAL;
-               goto done;
+       if (unit >= PFLOGIFS_MAX) {
+               /* Either the interface cloner or our initializer is broken */
+               panic("%s: unit (%d) exceeds max (%d)", __func__, unit,
+                   PFLOGIFS_MAX);
+               /* NOTREACHED */
        }
 
        if ((pflogif = _MALLOC(sizeof (*pflogif),
@@ -161,8 +153,8 @@ pflog_create_dev(void)
        }
 
        bzero(&pf_init, sizeof (pf_init));
-       pf_init.name = PFLOGNAME;
-       pf_init.unit = npflog;
+       pf_init.name = ifc->ifc_name;
+       pf_init.unit = unit;
        pf_init.type = IFT_PFLOG;
        pf_init.family = IFNET_FAMILY_LOOPBACK;
        pf_init.output = pflogoutput;
@@ -171,9 +163,10 @@ pflog_create_dev(void)
        pf_init.del_proto = pflogdelproto;
        pf_init.softc = pflogif;
        pf_init.ioctl = pflogioctl;
+       pf_init.detach = pflogfree;
 
        bzero(pflogif, sizeof (*pflogif));
-       pflogif->sc_unit = npflog;
+       pflogif->sc_unit = unit;
 
        error = ifnet_allocate(&pf_init, &pflogif->sc_if);
        if (error != 0) {
@@ -197,40 +190,39 @@ pflog_create_dev(void)
        bpfattach(pflogif->sc_if, DLT_PFLOG, PFLOG_HDRLEN);
 #endif
 
+       lck_rw_lock_shared(pf_perim_lock);
+       lck_mtx_lock(pf_lock);
        LIST_INSERT_HEAD(&pflogif_list, pflogif, sc_list);
-       pflogifs[npflog] = pflogif->sc_if;
-       ++npflog;
-done:
-       lck_mtx_unlock(pflog_lock);
+       pflogifs[unit] = pflogif->sc_if;
+       lck_mtx_unlock(pf_lock);
+       lck_rw_done(pf_perim_lock);
 
+done:
        return (error);
 }
 
-#if 0
-int
-pflog_destroy_dev(struct ifnet *ifp)
+static int
+pflog_clone_destroy(struct ifnet *ifp)
 {
-       struct pflog_softc      *pflogif = ifp->if_softc;
+       struct pflog_softc *pflogif = ifp->if_softc;
 
-       lck_mtx_lock(pflog_lock);
+       lck_rw_lock_shared(pf_perim_lock);
+       lck_mtx_lock(pf_lock);
        pflogifs[pflogif->sc_unit] = NULL;
        LIST_REMOVE(pflogif, sc_list);
-       lck_mtx_unlock(pflog_lock);
+       lck_mtx_unlock(pf_lock);
+       lck_rw_done(pf_perim_lock);
 
-#if NBPFILTER > 0
-       bpfdetach(ifp);
-#endif
-       if_detach(ifp);
-       _FREE(pflogif, M_DEVBUF);
-       return (0);
+       /* bpfdetach() is taken care of as part of interface detach */
+       (void) ifnet_detach(ifp);
+
+       return 0;
 }
-#endif
 
 static errno_t
 pflogoutput(struct ifnet *ifp, struct mbuf *m)
 {
-       printf("%s: freeing data for %s%d\n", __func__, ifp->if_name,
-           ifp->if_unit);
+       printf("%s: freeing data for %s\n", __func__, if_name(ifp));
        m_freem(m);
        return (ENOTSUP);
 }
@@ -260,8 +252,7 @@ static errno_t
 pflogdemux(struct ifnet *ifp, struct mbuf *m, char *h, protocol_family_t *ppf)
 {
 #pragma unused(h, ppf)
-       printf("%s: freeing data for %s%d\n", __func__, ifp->if_name,
-           ifp->if_unit);
+       printf("%s: freeing data for %s\n", __func__, if_name(ifp));
        m_freem(m);
        return (EJUSTRETURN);
 }
@@ -281,6 +272,14 @@ pflogdelproto(struct ifnet *ifp, protocol_family_t pf)
        return (0);
 }
 
+static void
+pflogfree(struct ifnet *ifp)
+{
+       _FREE(ifp->if_softc, M_DEVBUF);
+       ifp->if_softc = NULL;
+       (void) ifnet_release(ifp);
+}
+
 int
 pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
     u_int8_t reason, struct pf_rule *rm, struct pf_rule *am,
@@ -290,6 +289,8 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
        struct ifnet *ifn;
        struct pfloghdr hdr;
 
+       lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
+
        if (kif == NULL || m == NULL || rm == NULL || pd == NULL)
                return (-1);
 
@@ -338,8 +339,8 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
        }
 #endif /* INET */
 
-       ifn->if_opackets++;
-       ifn->if_obytes += m->m_pkthdr.len;
+       atomic_add_64(&ifn->if_opackets, 1);
+       atomic_add_64(&ifn->if_obytes, m->m_pkthdr.len);
 
        switch (dir) {
        case PF_IN: