pf: Make pf work w/ the MPSAFE network stack
authorJan Lentfer <Jan.Lentfer@web.de>
Sat, 11 Sep 2010 22:34:08 +0000 (00:34 +0200)
committerJan Lentfer <Jan.Lentfer@web.de>
Tue, 14 Sep 2010 17:31:20 +0000 (19:31 +0200)
   add pf_token where appropriate

   in pf_socket_lookup() use lwkt_domsg() instead of lwkt_sendmsg()
   to make race conditions more unlikely

   if_pfsyn.c: re-add lost init code

sys/net/pf/if_pflog.c
sys/net/pf/if_pfsync.c
sys/net/pf/pf.c
sys/net/pf/pf_ioctl.c
sys/net/pf/pfvar.h

index 98344f3..3c0439d 100644 (file)
@@ -114,14 +114,21 @@ pflog_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused)
        struct ifnet *ifp;
        struct pflog_softc *pflogif;
 
-       if (unit >= PFLOGIFS_MAX)
+       lwkt_gettoken(&pf_token);
+
+       if (unit >= PFLOGIFS_MAX) {
+               lwkt_reltoken(&pf_token);
                return (EINVAL);
+       }
 
-       if ((pflogif = kmalloc(sizeof(*pflogif), M_DEVBUF, M_WAITOK)) == NULL)
+       if ((pflogif = kmalloc(sizeof(*pflogif), M_DEVBUF, M_WAITOK)) == NULL) {
+               lwkt_reltoken(&pf_token);
                return (ENOMEM);
+       }
        bzero(pflogif, sizeof(*pflogif));
 
        pflogif->sc_unit = unit;
+       lwkt_reltoken(&pf_token);
        ifp = &pflogif->sc_if;
        ksnprintf(ifp->if_xname, sizeof ifp->if_xname, "pflog%d", unit);
        ifp->if_softc = pflogif;
@@ -135,12 +142,14 @@ pflog_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused)
        if_attach(ifp, NULL);
 
        bpfattach(&pflogif->sc_if, DLT_PFLOG, PFLOG_HDRLEN);
+       lwkt_gettoken(&pf_token);
 
        crit_enter();
        LIST_INSERT_HEAD(&pflogif_list, pflogif, sc_list);
        pflogifs[unit] = ifp;
        crit_exit();
 
+       lwkt_reltoken(&pf_token);
        return (0);
 }
 
@@ -149,16 +158,21 @@ pflog_clone_destroy(struct ifnet *ifp)
 {
        struct pflog_softc      *pflogif = ifp->if_softc;
 
+       lwkt_gettoken(&pf_token);
+
        crit_enter();
        pflogifs[pflogif->sc_unit] = NULL;
        LIST_REMOVE(pflogif, sc_list);
        crit_exit();
 
+       lwkt_reltoken(&pf_token);
 #if NBPFILTER > 0
        bpfdetach(ifp);
 #endif
        if_detach(ifp);
+       lwkt_gettoken(&pf_token);
        kfree(pflogif, M_DEVBUF);
+       lwkt_reltoken(&pf_token);
 }
 
 /*
@@ -169,11 +183,15 @@ pflogstart(struct ifnet *ifp)
 {
        struct mbuf *m;
 
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
        for (;;) {
+               lwkt_reltoken(&pf_token);
                crit_enter();
                IF_DROP(&ifp->if_snd);
                IF_DEQUEUE(&ifp->if_snd, m);
                crit_exit();
+               lwkt_gettoken(&pf_token);
 
                if (m == NULL)
                        return;
@@ -202,20 +220,27 @@ pflogrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa)
 int
 pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
 {
+
+       lwkt_gettoken(&pf_token);
+
        switch (cmd) {
        case SIOCSIFADDR:
        case SIOCAIFADDR:
        case SIOCSIFDSTADDR:
        case SIOCSIFFLAGS:
+               lwkt_reltoken(&pf_token);
                if (ifp->if_flags & IFF_UP)
                        ifp->if_flags |= IFF_RUNNING;
                else
                        ifp->if_flags &= ~IFF_RUNNING;
+               lwkt_gettoken(&pf_token);
                break;
        default:
+               lwkt_reltoken(&pf_token);
                return (EINVAL);
        }
 
+       lwkt_reltoken(&pf_token);
        return (0);
 }
 
@@ -227,6 +252,8 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
        struct ifnet *ifn = NULL;
        struct pfloghdr hdr;
 
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
        if (kif == NULL || m == NULL || rm == NULL)
                return (-1);
 
@@ -279,8 +306,10 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
 
        ifn->if_opackets++;
        ifn->if_obytes += m->m_pkthdr.len;
+       lwkt_reltoken(&pf_token);
        bpf_mtap_hdr(ifn->if_bpf, (char *)&hdr, PFLOG_HDRLEN, m,
            BPF_DIRECTION_OUT);
+       lwkt_gettoken(&pf_token);
 
 #ifdef INET
        if (af == AF_INET) {
@@ -299,25 +328,31 @@ pflog_modevent(module_t mod, int type, void *data)
 {
        int error = 0;
 
+       lwkt_gettoken(&pf_token);
+
        switch (type) {
        case MOD_LOAD:
                LIST_INIT(&pflogif_list);
+               lwkt_reltoken(&pf_token);
                if_clone_attach(&pflog_cloner);
+               lwkt_gettoken(&pf_token);
                break;
 
        case MOD_UNLOAD:
+               lwkt_reltoken(&pf_token);
                if_clone_detach(&pflog_cloner);
                while (!LIST_EMPTY(&pflogif_list)) {
                        pflog_clone_destroy(
                                &LIST_FIRST(&pflogif_list)->sc_if);
                }
+               lwkt_gettoken(&pf_token);
                break;
 
        default:
                error = EINVAL;
                break;
        }
-
+       lwkt_reltoken(&pf_token);
        return error;
 }
 
index 3c05de9..1253cf9 100644 (file)
@@ -126,6 +126,8 @@ pfsync_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused)
        struct pfsync_softc *sc;
        struct ifnet *ifp;
 
+       lwkt_gettoken(&pf_token);
+
        MALLOC(sc, struct pfsync_softc *, sizeof(*sc), M_PFSYNC,
            M_WAITOK|M_ZERO);
 
@@ -144,6 +146,7 @@ pfsync_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused)
        sc->sc_bulk_send_next = NULL;
        sc->sc_bulk_terminator = NULL;
 
+       lwkt_reltoken(&pf_token);
        ifp = &sc->sc_if;
        ksnprintf(ifp->if_xname, sizeof ifp->if_xname, "pfsync%d", unit);
        if_initname(ifp, ifc->ifc_name, unit);
@@ -168,17 +171,22 @@ pfsync_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused)
 #if NCARP > 0
        if_addgroup(ifp, "carp");
 #endif
+       lwkt_gettoken(&pf_token);
 
+       lwkt_reltoken(&pf_token);
        return (0);
 }
 
 static void
 pfsync_clone_destroy(struct ifnet *ifp)
 {
+       lwkt_gettoken(&pf_token);
+       lwkt_reltoken(&pf_token);
 #if NBPFILTER > 0
        bpfdetach(ifp);
 #endif
        if_detach(ifp);
+       lwkt_gettoken(&pf_token);
        kfree(pfsyncif, M_DEVBUF);
        pfsyncif = NULL;
 }
@@ -336,6 +344,10 @@ pfsync_input(struct mbuf *m, ...)
        int iplen, action, error, i, count, offp, sfail, stale = 0;
        u_int8_t chksum_flag = 0;
 
+       /* This function is not yet called from anywhere */
+       /* Still we assume for safety that pf_token must be held */
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
        pfsyncstats.pfsyncs_ipackets++;
 
        /* verify that we have a sync interface configured */
@@ -756,9 +768,11 @@ pfsync_input(struct mbuf *m, ...)
                                        kprintf("pfsync: received "
                                            "bulk update request\n");
                                pfsync_send_bus(sc, PFSYNC_BUS_START);
+                               lwkt_reltoken(&pf_token);
                                callout_reset(&sc->sc_bulk_tmo, 1 * hz,
                                    pfsync_bulk_update,
                                    LIST_FIRST(&pfsync_list));
+                               lwkt_gettoken(&pf_token);
                        } else {
                                st = pf_find_state_byid(&id_key);
                                if (st == NULL) {
@@ -787,10 +801,12 @@ pfsync_input(struct mbuf *m, ...)
                bus = (struct pfsync_state_bus *)(mp->m_data + offp);
                switch (bus->status) {
                case PFSYNC_BUS_START:
+                       lwkt_reltoken(&pf_token);
                        callout_reset(&sc->sc_bulkfail_tmo,
                            pf_pool_limits[PF_LIMIT_STATES].limit /
                            (PFSYNC_BULKPACKETS * sc->sc_maxcount), 
                            pfsync_bulkfail, LIST_FIRST(&pfsync_list));
+                       lwkt_gettoken(&pf_token);
                        if (pf_status.debug >= PF_DEBUG_MISC)
                                kprintf("pfsync: received bulk "
                                    "update start\n");
@@ -801,10 +817,15 @@ pfsync_input(struct mbuf *m, ...)
                                /* that's it, we're happy */
                                sc->sc_ureq_sent = 0;
                                sc->sc_bulk_tries = 0;
+                               lwkt_reltoken(&pf_token);
                                callout_stop(&sc->sc_bulkfail_tmo);
+                               lwkt_gettoken(&pf_token);
 #if NCARP > 0
-                               if (!pfsync_sync_ok)
+                               if (!pfsync_sync_ok) {
+                                       lwkt_reltoken(&pf_token);
                                        carp_group_demote_adj(&sc->sc_if, -1);
+                                       lwkt_gettoken(&pf_token);
+                               }
 #endif
                                pfsync_sync_ok = 1;
                                if (pf_status.debug >= PF_DEBUG_MISC)
@@ -825,11 +846,11 @@ pfsync_input(struct mbuf *m, ...)
                        pfsyncstats.pfsyncs_badlen++;
                        return;
                }
-               s = splsoftnet();
+               crit_enter();
                for (i = 0, pt = (struct pfsync_tdb *)(mp->m_data + offp);
                    i < count; i++, pt++)
                        pfsync_update_net_tdb(pt);
-               splx(s);
+               crit_exit();
                break;
 #endif
        }
@@ -858,6 +879,8 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
        struct ifnet    *sifp;
        int error;
 
+       lwkt_gettoken(&pf_token);
+
        switch (cmd) {
        case SIOCSIFADDR:
        case SIOCAIFADDR:
@@ -869,8 +892,10 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
                        ifp->if_flags &= ~IFF_RUNNING;
                break;
        case SIOCSIFMTU:
-               if (ifr->ifr_mtu < PFSYNC_MINMTU)
+               if (ifr->ifr_mtu < PFSYNC_MINMTU) {
+                       lwkt_reltoken(&pf_token);
                        return (EINVAL);
+               }       
                if (ifr->ifr_mtu > MCLBYTES)
                        ifr->ifr_mtu = MCLBYTES;
                crit_enter();
@@ -886,14 +911,20 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
                            sc->sc_sync_ifp->if_xname, IFNAMSIZ);
                pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
                pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
+               lwkt_reltoken(&pf_token);
                if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
                        return (error);
+               lwkt_gettoken(&pf_token);
                break;
        case SIOCSETPFSYNC:
-               if ((error = priv_check_cred(cr, PRIV_ROOT, NULL_CRED_OKAY)) != 0)
+               if ((error = priv_check_cred(cr, PRIV_ROOT, NULL_CRED_OKAY)) != 0) {
+                       lwkt_reltoken(&pf_token);
                        return (error);
-               if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr))))
+               }
+               if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr)))) {
+                       lwkt_reltoken(&pf_token);
                        return (error);
+               }
 
                if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
                        sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
@@ -901,8 +932,10 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
                        sc->sc_sync_peer.s_addr =
                            pfsyncr.pfsyncr_syncpeer.s_addr;
 
-               if (pfsyncr.pfsyncr_maxupdates > 255)
+               if (pfsyncr.pfsyncr_maxupdates > 255) {
+                       lwkt_reltoken(&pf_token);
                        return (EINVAL);
+               }
                sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
 
                if (pfsyncr.pfsyncr_syncdev[0] == 0) {
@@ -922,8 +955,10 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
                        break;
                }
 
-               if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL)
+               if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL) {
+                       lwkt_reltoken(&pf_token);
                        return (EINVAL);
+               }
 
                crit_enter();
                if (sifp->if_mtu < sc->sc_if.if_mtu ||
@@ -946,6 +981,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
 
                        if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) {
                                sc->sc_sync_ifp = NULL;
+                               lwkt_reltoken(&pf_token);
                                crit_exit();
                                return (EADDRNOTAVAIL);
                        }
@@ -955,6 +991,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
                        if ((imo->imo_membership[0] =
                            in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
                                sc->sc_sync_ifp = NULL;
+                               lwkt_reltoken(&pf_token);
                                crit_exit();
                                return (ENOBUFS);
                        }
@@ -975,10 +1012,13 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
                        pfsync_sync_ok = 0;
                        if (pf_status.debug >= PF_DEBUG_MISC)
                                kprintf("pfsync: requesting bulk update\n");
+                       lwkt_reltoken(&pf_token);
                        callout_reset(&sc->sc_bulkfail_tmo, 5 * hz,
                            pfsync_bulkfail, LIST_FIRST(&pfsync_list));
+                       lwkt_gettoken(&pf_token);
                        error = pfsync_request_update(NULL, NULL);
                        if (error == ENOMEM) {
+                               lwkt_reltoken(&pf_token);
                                crit_exit();
                                return (ENOMEM);
                        }
@@ -989,9 +1029,11 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
                break;
 
        default:
+               lwkt_reltoken(&pf_token);
                return (ENOTTY);
        }
 
+       lwkt_reltoken(&pf_token);
        return (0);
 }
 
@@ -1020,6 +1062,8 @@ pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
        struct mbuf *m;
        int len;
 
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
        MGETHDR(m, M_WAITOK, MT_DATA);
        if (m == NULL) {
                sc->sc_if.if_oerrors++;
@@ -1077,8 +1121,10 @@ pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
        h->action = action;
 
        *sp = (void *)((char *)h + PFSYNC_HDRLEN);
+       lwkt_reltoken(&pf_token);
        callout_reset(&sc->sc_tmo, hz, pfsync_timeout,
            LIST_FIRST(&pfsync_list));
+       lwkt_gettoken(&pf_token);
        return (m);
 }
 
@@ -1282,7 +1328,6 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
        return (ret);
 }
 
-/* This must be called in splnet() */
 int
 pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src)
 {
@@ -1397,6 +1442,8 @@ pfsync_bulk_update(void *v)
        int i = 0;
        struct pf_state *state;
 
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
        crit_enter();
        if (sc->sc_mbuf != NULL)
                pfsync_sendout(sc);
@@ -1431,13 +1478,17 @@ pfsync_bulk_update(void *v)
                sc->sc_ureq_received = 0;
                sc->sc_bulk_send_next = NULL;
                sc->sc_bulk_terminator = NULL;
+               lwkt_reltoken(&pf_token);
                callout_stop(&sc->sc_bulk_tmo);
+               lwkt_gettoken(&pf_token);
                if (pf_status.debug >= PF_DEBUG_MISC)
                        kprintf("pfsync: bulk update complete\n");
        } else {
                /* look again for more in a bit */
+               lwkt_reltoken(&pf_token);
                callout_reset(&sc->sc_bulk_tmo, 1, pfsync_timeout,
                            LIST_FIRST(&pfsync_list));
+               lwkt_gettoken(&pf_token);
                sc->sc_bulk_send_next = state;
        }
        if (sc->sc_mbuf != NULL)
@@ -1451,10 +1502,14 @@ pfsync_bulkfail(void *v)
        struct pfsync_softc *sc = v;
        int error;
 
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
        if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
                /* Try again in a bit */
+               lwkt_reltoken(&pf_token);
                callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail,
                    LIST_FIRST(&pfsync_list));
+               lwkt_gettoken(&pf_token);
                crit_enter();
                error = pfsync_request_update(NULL, NULL);
                if (error == ENOMEM) {
@@ -1476,7 +1531,9 @@ pfsync_bulkfail(void *v)
                if (pf_status.debug >= PF_DEBUG_MISC)
                        kprintf("pfsync: failed to receive "
                            "bulk update status\n");
+               lwkt_reltoken(&pf_token);
                callout_stop(&sc->sc_bulkfail_tmo);
+               lwkt_gettoken(&pf_token);
        }
 }
 
@@ -1489,7 +1546,11 @@ pfsync_sendout(struct pfsync_softc *sc)
 #endif
        struct mbuf *m;
 
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
+       lwkt_reltoken(&pf_token);
        callout_stop(&sc->sc_tmo);
+       lwkt_gettoken(&pf_token);
 
        if (sc->sc_mbuf == NULL)
                return (0);
@@ -1498,8 +1559,11 @@ pfsync_sendout(struct pfsync_softc *sc)
        sc->sc_statep.s = NULL;
 
 #if NBPFILTER > 0
-       if (ifp->if_bpf)
+       if (ifp->if_bpf) {
+               lwkt_reltoken(&pf_token);
                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+               lwkt_gettoken(&pf_token);
+       }
 #endif
 
        if (sc->sc_mbuf_net) {
@@ -1554,5 +1618,49 @@ pfsync_sendout_mbuf(struct pfsync_softc *sc, struct mbuf *m)
        return (0);
 }
 
+static int
+pfsync_modevent(module_t mod, int type, void *data)
+{
+       int error = 0;
+
+       lwkt_gettoken(&pf_token);
+
+       switch (type) {
+       case MOD_LOAD:
+               LIST_INIT(&pfsync_list);
+               lwkt_reltoken(&pf_token);
+               if_clone_attach(&pfsync_cloner);
+               lwkt_gettoken(&pf_token);
+               break;
+
+       case MOD_UNLOAD:
+               lwkt_reltoken(&pf_token);
+               if_clone_detach(&pfsync_cloner);
+               lwkt_gettoken(&pf_token);
+               while (!LIST_EMPTY(&pfsync_list))
+                       pfsync_clone_destroy(
+                               &LIST_FIRST(&pfsync_list)->sc_if);
+               break;
+
+       default:
+               error = EINVAL;
+               break;
+       }
+
+       lwkt_reltoken(&pf_token);
+       return error;
+}
+
+static moduledata_t pfsync_mod = {
+       "pfsync",
+       pfsync_modevent,
+       0
+};
+
+#define PFSYNC_MODVER 1
+
+DECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+MODULE_VERSION(pfsync, PFSYNC_MODVER);
+
 
 
index 10675f4..ac0d484 100644 (file)
 extern int ip_optcopy(struct ip *, struct ip *);
 extern int debug_pfugidhack;
 
+struct lwkt_token pf_token = LWKT_TOKEN_MP_INITIALIZER(pf_token);
+
 #define DPFPRINTF(n, x)        if (pf_status.debug >= (n)) kprintf x
 
 /*
@@ -1628,6 +1630,8 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
        struct tcphdr   *th = NULL;
        char            *opt;
 
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
        /* maximum segment size tcp option */
        tlen = sizeof(struct tcphdr);
        if (mss)
@@ -1648,8 +1652,9 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
 
        /* create outgoing mbuf */
        m = m_gethdr(MB_DONTWAIT, MT_HEADER);
-       if (m == NULL)
+       if (m == NULL) {
                return;
+       }
        if (tag)
                m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
        m->m_pkthdr.pf.tag = rtag;
@@ -1730,7 +1735,9 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
                h->ip_ttl = ttl ? ttl : ip_defttl;
                h->ip_sum = 0;
                if (eh == NULL) {
+                       lwkt_reltoken(&pf_token);
                        ip_output(m, NULL, NULL, 0, NULL, NULL);
+                       lwkt_gettoken(&pf_token);
                } else {
                        struct route             ro;
                        struct rtentry           rt;
@@ -1748,8 +1755,10 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
                        bcopy(eh->ether_shost, e->ether_dhost, ETHER_ADDR_LEN);
                        e->ether_type = eh->ether_type;
                        /* XXX_IMPORT: later */
+                       lwkt_reltoken(&pf_token);
                        ip_output(m, (void *)NULL, &ro, 0,
                            (void *)NULL, (void *)NULL);
+                       lwkt_gettoken(&pf_token);
                }
                break;
 #endif /* INET */
@@ -1762,7 +1771,9 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
                h6->ip6_vfc |= IPV6_VERSION;
                h6->ip6_hlim = IPV6_DEFHLIM;
 
+               lwkt_reltoken(&pf_token);
                ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+               lwkt_gettoken(&pf_token);
                break;
 #endif /* INET6 */
        }
@@ -2750,8 +2761,8 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
        case AF_INET:
 #ifdef SMP
                if (msg != NULL) {
-                       lwkt_sendmsg(cpu_portfn(pi_cpu),
-                                    &msg->nm_netmsg.nm_lmsg);
+                       lwkt_domsg(cpu_portfn(pi_cpu),
+                                    &msg->nm_netmsg.nm_lmsg, 0);
                } else
 #endif /* SMP */
                {
@@ -4205,7 +4216,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
                         * the protocol stack on the wrong cpu for the
                         * post-translated address.
                         */
-                       m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH;
+                       /* m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH; */
+                       m->m_flags &= ~M_HASH;
                        pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
                            &th->th_sum, &(*state)->state_key->lan.addr,
                            (*state)->state_key->lan.port, 0, pd->af);
@@ -4276,7 +4288,8 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
                         * the protocol stack on the wrong cpu for the
                         * post-translated address.
                         */
-                       m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH;
+                       /* m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH; */
+                       m->m_flags &= ~M_HASH;
                        pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
                            &uh->uh_sum, &(*state)->state_key->lan.addr,
                            (*state)->state_key->lan.port, 1, pd->af);
@@ -5097,6 +5110,8 @@ pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
 #endif
        int                      ret = 0;
 
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
        bzero(&ro, sizeof(ro));
        switch (af) {
        case AF_INET:
@@ -5145,6 +5160,8 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
        struct m_tag            *mtag;
 #endif /* IPSEC */
 
+       ASSERT_LWKT_TOKEN_HELD(&pf_token);
+
        if (m == NULL || *m == NULL || r == NULL ||
            (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
                panic("pf_route: invalid parameters");
@@ -5161,11 +5178,13 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
        }
 
        if (r->rt == PF_DUPTO) {
-               if ((m0 = m_dup(*m, MB_DONTWAIT)) == NULL)
+               if ((m0 = m_dup(*m, MB_DONTWAIT)) == NULL) {
                        return;
+               }
        } else {
-               if ((r->rt == PF_REPLYTO) == (r->direction == dir))
+               if ((r->rt == PF_REPLYTO) == (r->direction == dir)) {
                        return;
+               }
                m0 = *m;
        }
 
@@ -5261,9 +5280,11 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
                                ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
                        }
                }
+               lwkt_reltoken(&pf_token);
                crit_exit();
                error = ifp->if_output(ifp, m0, sintosa(dst), ro->ro_rt);
                crit_enter();
+               lwkt_gettoken(&pf_token);
                goto done;
        }
 
@@ -5293,10 +5314,12 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
                m1 = m0->m_nextpkt;
                m0->m_nextpkt = 0;
                if (error == 0) {
+                       lwkt_reltoken(&pf_token);
                        crit_exit();
                        error = (*ifp->if_output)(ifp, m0, sintosa(dst),
                            NULL);
                        crit_enter();
+                       lwkt_gettoken(&pf_token);
                } else
                        m_freem(m0);
        }
index c69546e..b234bc7 100644 (file)
@@ -330,18 +330,26 @@ pfattach(void)
 int
 pfopen(struct dev_open_args *ap)
 {
+       lwkt_gettoken(&pf_token);
        cdev_t dev = ap->a_head.a_dev;
-       if (minor(dev) >= 1)
+       if (minor(dev) >= 1) {
+               lwkt_reltoken(&pf_token);
                return (ENXIO);
+       }
+       lwkt_reltoken(&pf_token);
        return (0);
 }
 
 int
 pfclose(struct dev_close_args *ap)
 {
+       lwkt_gettoken(&pf_token);
        cdev_t dev = ap->a_head.a_dev;
-       if (minor(dev) >= 1)
+       if (minor(dev) >= 1) {
+               lwkt_reltoken(&pf_token);
                return (ENXIO);
+       }
+       lwkt_reltoken(&pf_token);
        return (0);
 }
 
@@ -1068,6 +1076,8 @@ pfioctl(struct dev_ioctl_args *ap)
        struct pf_pool          *pool = NULL;
        int                      error = 0;
 
+       lwkt_gettoken(&pf_token);
+
        /* XXX keep in sync with switch() below */
        if (securelevel > 1)
                switch (cmd) {
@@ -1116,8 +1126,10 @@ pfioctl(struct dev_ioctl_args *ap)
                        if (((struct pfioc_table *)addr)->pfrio_flags &
                            PFR_FLAG_DUMMY)
                                break; /* dummy operation ok */
+                       lwkt_reltoken(&pf_token);
                        return (EPERM);
                default:
+                       lwkt_reltoken(&pf_token);
                        return (EPERM);
                }
 
@@ -1159,12 +1171,16 @@ pfioctl(struct dev_ioctl_args *ap)
                        if (((struct pfioc_table *)addr)->pfrio_flags &
                            PFR_FLAG_DUMMY)
                                break; /* dummy operation ok */
+                       lwkt_reltoken(&pf_token);
                        return (EACCES);
                case DIOCGETRULE:
-                       if (((struct pfioc_rule *)addr)->action == PF_GET_CLR_CNTR)
+                       if (((struct pfioc_rule *)addr)->action == PF_GET_CLR_CNTR) {
+                               lwkt_reltoken(&pf_token);
                                return (EACCES);
+                       }
                        break;
                default:
+                       lwkt_reltoken(&pf_token);
                        return (EACCES);
                }
 
@@ -3056,6 +3072,7 @@ pfioctl(struct dev_ioctl_args *ap)
                break;
        }
 fail:
+       lwkt_reltoken(&pf_token);
        return (error);
 }
 
@@ -3193,11 +3210,14 @@ pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
         */
        int chk;
 
+       lwkt_gettoken(&pf_token);
+
        chk = pf_test(PF_IN, ifp, m, NULL, NULL);
        if (chk && *m) {
                m_freem(*m);
                *m = NULL;
        }
+       lwkt_reltoken(&pf_token);
        return chk;
 }
 
@@ -3211,6 +3231,8 @@ pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
         */
        int chk;
 
+       lwkt_gettoken(&pf_token);
+
        /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
        if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
                in_delayed_cksum(*m);
@@ -3221,6 +3243,7 @@ pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
                m_freem(*m);
                *m = NULL;
        }
+       lwkt_reltoken(&pf_token);
        return chk;
 }
 
@@ -3233,11 +3256,14 @@ pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
         */
        int chk;
 
+       lwkt_gettoken(&pf_token);
+
        chk = pf_test6(PF_IN, ifp, m, NULL, NULL);
        if (chk && *m) {
                m_freem(*m);
                *m = NULL;
        }
+       lwkt_reltoken(&pf_token);
        return chk;
 }
 
@@ -3249,6 +3275,8 @@ pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
         */
        int chk;
 
+       lwkt_gettoken(&pf_token);
+
        /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
        if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
                in_delayed_cksum(*m);
@@ -3259,6 +3287,7 @@ pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
                m_freem(*m);
                *m = NULL;
        }
+       lwkt_reltoken(&pf_token);
        return chk;
 }
 #endif /* INET6 */
@@ -3270,13 +3299,19 @@ hook_pf(void)
 #ifdef INET6
        struct pfil_head *pfh_inet6;
 #endif
-       
-       if (pf_pfil_hooked)
-               return (0); 
+
+       lwkt_gettoken(&pf_token);
+
+       if (pf_pfil_hooked) {
+               lwkt_reltoken(&pf_token);
+               return (0);
+       }
        
        pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
-       if (pfh_inet == NULL)
+       if (pfh_inet == NULL) {
+               lwkt_reltoken(&pf_token);
                return (ENODEV);
+       }
        pfil_add_hook(pf_check_in, NULL, PFIL_IN, pfh_inet);
        pfil_add_hook(pf_check_out, NULL, PFIL_OUT, pfh_inet);
 #ifdef INET6
@@ -3284,6 +3319,7 @@ hook_pf(void)
        if (pfh_inet6 == NULL) {
                pfil_remove_hook(pf_check_in, NULL, PFIL_IN, pfh_inet);
                pfil_remove_hook(pf_check_out, NULL, PFIL_OUT, pfh_inet);
+               lwkt_reltoken(&pf_token);
                return (ENODEV);
        }
        pfil_add_hook(pf_check6_in, NULL, PFIL_IN, pfh_inet6);
@@ -3291,6 +3327,7 @@ hook_pf(void)
 #endif
 
        pf_pfil_hooked = 1;
+       lwkt_reltoken(&pf_token);
        return (0);
 }
 
@@ -3302,23 +3339,32 @@ dehook_pf(void)
        struct pfil_head *pfh_inet6;
 #endif
 
-       if (pf_pfil_hooked == 0)
+       lwkt_gettoken(&pf_token);
+
+       if (pf_pfil_hooked == 0) {
+               lwkt_reltoken(&pf_token);
                return (0);
+       }
 
        pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
-       if (pfh_inet == NULL)
+       if (pfh_inet == NULL) {
+               lwkt_reltoken(&pf_token);
                return (ENODEV);
+       }
        pfil_remove_hook(pf_check_in, NULL, PFIL_IN, pfh_inet);
        pfil_remove_hook(pf_check_out, NULL, PFIL_OUT, pfh_inet);
 #ifdef INET6
        pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
-       if (pfh_inet6 == NULL)
+       if (pfh_inet6 == NULL) {
+               lwkt_reltoken(&pf_token);
                return (ENODEV);
+       }
        pfil_remove_hook(pf_check6_in, NULL, PFIL_IN, pfh_inet6);
        pfil_remove_hook(pf_check6_out, NULL, PFIL_OUT, pfh_inet6);
 #endif
 
        pf_pfil_hooked = 0;
+       lwkt_reltoken(&pf_token);
        return (0);
 }
 
@@ -3327,6 +3373,8 @@ pf_load(void)
 {
        int error;
 
+       lwkt_gettoken(&pf_token);
+
        init_zone_var();
        lockinit(&pf_mod_lck, "pf task lck", 0, LK_CANRECURSE);
        pf_dev = make_dev(&pf_ops, 0, 0, 0, 0600, PF_NAME);
@@ -3334,9 +3382,11 @@ pf_load(void)
        if (error) {
                dev_ops_remove_all(&pf_ops);
                lockuninit(&pf_mod_lck);
+               lwkt_reltoken(&pf_token);
                return (error);
        }
        lockinit(&pf_consistency_lock, "pfconslck", 0, LK_CANRECURSE);
+       lwkt_reltoken(&pf_token);
        return (0);
 }
 
@@ -3344,8 +3394,10 @@ static int
 pf_unload(void)
 {
        int error;
-
        pf_status.running = 0;
+
+       lwkt_gettoken(&pf_token);
+
        error = dehook_pf();
        if (error) {
                /*
@@ -3354,6 +3406,7 @@ pf_unload(void)
                 * a message like 'No such process'.
                 */
                kprintf("pfil unregistration fail\n");
+               lwkt_reltoken(&pf_token);
                return error;
        }
        shutdown_pf();
@@ -3370,6 +3423,7 @@ pf_unload(void)
        dev_ops_remove_all(&pf_ops);
        lockuninit(&pf_consistency_lock);
        lockuninit(&pf_mod_lck);
+       lwkt_reltoken(&pf_token);
        return 0;
 }
 
@@ -3378,6 +3432,8 @@ pf_modevent(module_t mod, int type, void *data)
 {
        int error = 0;
 
+       lwkt_gettoken(&pf_token);
+
        switch(type) {
        case MOD_LOAD:
                error = pf_load();
@@ -3390,6 +3446,7 @@ pf_modevent(module_t mod, int type, void *data)
                error = EINVAL;
                break;
        }
+       lwkt_reltoken(&pf_token);
        return error;
 }
 
index 4010eb0..1a0de07 100644 (file)
@@ -68,6 +68,8 @@ union sockaddr_union {
 struct ip;
 struct ip6_hdr;
 
+extern struct lwkt_token pf_token;
+
 #define        PF_TCPS_PROXY_SRC       ((TCP_NSTATES)+0)
 #define        PF_TCPS_PROXY_DST       ((TCP_NSTATES)+1)