Date: Tue, 27 Feb 2007 13:44:27 +0100 From: Max Laier <max@love2party.net> To: freebsd-stable@freebsd.org Cc: Kurt Jaeger <lists@c0mplx.org> Subject: Re: Sequence of packet processing with ipfw, pf, ipfilter ? Message-ID: <200702271344.33881.max@love2party.net> In-Reply-To: <20070227083126.GD26839@home.c0mplx.org> References: <20070227083126.GD26839@home.c0mplx.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--nextPart23452799.USI6mqnrhR Content-Type: multipart/mixed; boundary="Boundary-01=_seC5F187reQBkMk" Content-Transfer-Encoding: 7bit Content-Disposition: inline --Boundary-01=_seC5F187reQBkMk Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline On Tuesday 27 February 2007 09:31, Kurt Jaeger wrote: > can someone point me to some documentation about the sequence > of packet processing in fbsd6 if more than one of the filter > systems is active ? Unfortunately, there is no defined sequence. Currently it depends on the=20 sequence the individual components are enabled, or - more specificly -=20 the sequence of pfil_add_hook() calls. Note that ipfw does this on=20 module load, while pf waits until you issue "pfctl -e". I had=20 experimental patches to control the sequence back in 2005 (see attached). = =20 Note that this will not work!!! It's more for reference. Back then=20 nobody was interesting in testing. > There once was a nice ascii graphic which described the flow > of packets through the rules -- I can't find it any more ? =2D-=20 /"\ Best regards, | mlaier@freebsd.org \ / Max Laier | ICQ #67774661 X http://pf4freebsd.love2party.net/ | mlaier@EFnet / \ ASCII Ribbon Campaign | Against HTML Mail and News --Boundary-01=_seC5F187reQBkMk Content-Type: text/x-diff; charset="iso-8859-1"; name="pfil_lockless_20051204.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="pfil_lockless_20051204.diff" Index: contrib/pf/net/pf_ioctl.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/contrib/pf/net/pf_ioctl.c,v retrieving revision 1.21 diff -u -r1.21 pf_ioctl.c =2D-- contrib/pf/net/pf_ioctl.c 8 Sep 2005 15:06:52 -0000 1.21 +++ contrib/pf/net/pf_ioctl.c 4 Dec 2005 13:47:24 -0000 @@ -3461,19 +3461,23 @@ pfh_inet =3D pfil_head_get(PFIL_TYPE_AF, AF_INET); if (pfh_inet =3D=3D NULL) return (ESRCH); /* XXX */ =2D pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet); =2D pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet); + pfil_add_named_hook(pf_check_in, NULL, "pf", PFIL_IN|PFIL_WAITOK, + pfh_inet); + pfil_add_named_hook(pf_check_out, NULL, "pf", PFIL_OUT|PFIL_WAITOK, + pfh_inet); #ifdef INET6 pfh_inet6 =3D pfil_head_get(PFIL_TYPE_AF, AF_INET6); if (pfh_inet6 =3D=3D NULL) { =2D pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, + pfil_remove_hook(pf_check_in, NULL, PFIL_IN|PFIL_WAITOK, pfh_inet); =2D pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, + pfil_remove_hook(pf_check_out, NULL, PFIL_OUT|PFIL_WAITOK, pfh_inet); return (ESRCH); /* XXX */ } =2D pfil_add_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6); =2D pfil_add_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6); + pfil_add_named_hook(pf_check6_in, NULL, "pf", PFIL_IN|PFIL_WAITOK, + pfh_inet6); + pfil_add_named_hook(pf_check6_out, NULL, "pf", PFIL_OUT|PFIL_WAITOK, + pfh_inet6); #endif =20 pf_pfil_hooked =3D 1; Index: net/bridge.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/net/Attic/bridge.c,v retrieving revision 1.93.2.1 diff -u -r1.93.2.1 bridge.c =2D-- net/bridge.c 25 Aug 2005 05:01:19 -0000 1.93.2.1 +++ net/bridge.c 3 Dec 2005 16:47:15 -0000 @@ -995,7 +995,7 @@ * and pkts already gone through a pipe. */ if (src !=3D NULL && ( =2D (inet_pfil_hook.ph_busy_count >=3D 0 && bdg_ipf !=3D 0) || + (!PFIL_IS_EMPTY(inet_pfil_hook) && bdg_ipf !=3D 0) || (IPFW_LOADED && bdg_ipfw !=3D 0))) { =20 int i; @@ -1044,7 +1044,7 @@ * Enables ipf(8) in bridging. */ if (!IPFW_LOADED) { /* XXX: Prevent ipfw from being run twice. */ =2D if (inet_pfil_hook.ph_busy_count >=3D 0 && + if (!PFIL_IS_EMPTY(inet_pfil_hook) && m0->m_pkthdr.len >=3D sizeof(struct ip) && ntohs(save_eh.ether_type) =3D=3D ETHERTYPE_IP) { /* Index: net/if_bridge.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/net/if_bridge.c,v retrieving revision 1.35 diff -u -r1.35 if_bridge.c =2D-- net/if_bridge.c 29 Nov 2005 20:29:44 -0000 1.35 +++ net/if_bridge.c 4 Dec 2005 13:47:57 -0000 @@ -1315,9 +1315,9 @@ return; } =20 =2D if (inet_pfil_hook.ph_busy_count >=3D 0 + if (!PFIL_IS_EMPTY(inet_pfil_hook) #ifdef INET6 =2D || inet6_pfil_hook.ph_busy_count >=3D 0 + || !PFIL_IS_EMPTY(inet6_pfil_hook) #endif ) { if (bridge_pfil(&m, sc->sc_ifp, ifp, PFIL_OUT) !=3D 0) @@ -1577,9 +1577,9 @@ } =20 /* run the packet filter */ =2D if (inet_pfil_hook.ph_busy_count >=3D 0 + if (!PFIL_IS_EMPTY(inet_pfil_hook) #ifdef INET6 =2D || inet6_pfil_hook.ph_busy_count >=3D 0 + || !PFIL_IS_EMPTY(inet6_pfil_hook) #endif ) { BRIDGE_UNLOCK(sc); @@ -1630,9 +1630,9 @@ =20 BRIDGE_UNLOCK(sc); =20 =2D if (inet_pfil_hook.ph_busy_count >=3D 0 + if (!PFIL_IS_EMPTY(inet_pfil_hook) #ifdef INET6 =2D || inet6_pfil_hook.ph_busy_count >=3D 0 + || !PFIL_IS_EMPTY(inet6_pfil_hook) #endif ) { if (bridge_pfil(&m, sc->sc_ifp, dst_if, PFIL_OUT) !=3D 0) @@ -1819,9 +1819,9 @@ } =20 /* Filter on the bridge interface before broadcasting */ =2D if (runfilt && (inet_pfil_hook.ph_busy_count >=3D 0 + if (runfilt && (!PFIL_IS_EMPTY(inet_pfil_hook) #ifdef INET6 =2D || inet6_pfil_hook.ph_busy_count >=3D 0 + || PFIL_IS_EMPTY(inet6_pfil_hook) #endif )) { if (bridge_pfil(&m, sc->sc_ifp, NULL, PFIL_OUT) !=3D 0) @@ -1866,9 +1866,9 @@ * pointer so we do not redundantly filter on the bridge for=20 * each interface we broadcast on. */ =2D if (runfilt && (inet_pfil_hook.ph_busy_count >=3D 0 + if (runfilt && (!PFIL_IS_EMPTY(inet_pfil_hook) #ifdef INET6 =2D || inet6_pfil_hook.ph_busy_count >=3D 0 + || !PFIL_IS_EMPTY(inet6_pfil_hook) #endif )) { if (bridge_pfil(&mc, NULL, dst_if, PFIL_OUT) !=3D 0) Index: net/pfil.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/net/pfil.c,v retrieving revision 1.13 diff -u -r1.13 pfil.c =2D-- net/pfil.c 23 May 2005 17:07:16 -0000 1.13 +++ net/pfil.c 4 Dec 2005 13:27:58 -0000 @@ -2,6 +2,7 @@ /* $NetBSD: pfil.c,v 1.20 2001/11/12 23:49:46 lukem Exp $ */ =20 /*- + * Copyright (c) 2005 Max Laier * Copyright (c) 1996 Matthew R. Green * All rights reserved. * @@ -33,8 +34,10 @@ #include <sys/kernel.h> #include <sys/errno.h> #include <sys/malloc.h> +#include <sys/sbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> +#include <sys/sysctl.h> #include <sys/systm.h> #include <sys/condvar.h> #include <sys/lock.h> @@ -46,67 +49,20 @@ #include <net/pfil.h> =20 static struct mtx pfil_global_lock; +static struct callout pfil_gc_tmo; =20 =2DMTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil_head_list lock", M= TX_DEF); =2D =2Dstatic int pfil_list_add(pfil_list_t *, struct packet_filter_hook *, int= ); =2D =2Dstatic int pfil_list_remove(pfil_list_t *, =2D int (*)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *)= , void *); +MTX_SYSINIT(pfil_heads_lock, &pfil_global_lock, "pfil lock", MTX_DEF); =20 LIST_HEAD(, pfil_head) pfil_head_list =3D =2D LIST_HEAD_INITIALIZER(&pfil_head_list); =2D =2Dstatic __inline void =2DPFIL_RLOCK(struct pfil_head *ph) =2D{ =2D mtx_lock(&ph->ph_mtx); =2D ph->ph_busy_count++; =2D mtx_unlock(&ph->ph_mtx); =2D} + LIST_HEAD_INITIALIZER(pfil_head_list); =20 =2Dstatic __inline void =2DPFIL_RUNLOCK(struct pfil_head *ph) =2D{ =2D mtx_lock(&ph->ph_mtx); =2D ph->ph_busy_count--; =2D if (ph->ph_busy_count =3D=3D 0 && ph->ph_want_write) =2D cv_signal(&ph->ph_cv); =2D mtx_unlock(&ph->ph_mtx); =2D} +STAILQ_HEAD(, packet_filter_list) pfil_gc_list =3D + STAILQ_HEAD_INITIALIZER(pfil_gc_list); =20 =2Dstatic __inline void =2DPFIL_WLOCK(struct pfil_head *ph) =2D{ =2D mtx_lock(&ph->ph_mtx); =2D ph->ph_want_write =3D 1; =2D while (ph->ph_busy_count > 0) =2D cv_wait(&ph->ph_cv, &ph->ph_mtx); =2D} =2D =2Dstatic __inline int =2DPFIL_TRY_WLOCK(struct pfil_head *ph) =2D{ =2D mtx_lock(&ph->ph_mtx); =2D ph->ph_want_write =3D 1; =2D if (ph->ph_busy_count > 0) { =2D ph->ph_want_write =3D 0; =2D mtx_unlock(&ph->ph_mtx); =2D return EBUSY; =2D } =2D return 0; =2D} =2D =2Dstatic __inline void =2DPFIL_WUNLOCK(struct pfil_head *ph) =2D{ =2D ph->ph_want_write =3D 0; =2D cv_signal(&ph->ph_cv); =2D mtx_unlock(&ph->ph_mtx); =2D} +#define PFIL_LOCK() mtx_lock(&pfil_global_lock) +#define PFIL_UNLOCK() mtx_unlock(&pfil_global_lock) =20 =2D#define PFIL_LIST_LOCK() mtx_lock(&pfil_global_lock) =2D#define PFIL_LIST_UNLOCK() mtx_unlock(&pfil_global_lock) +static void pfil_gc(void *); =20 /* * pfil_run_hooks() runs the specified packet filter hooks. @@ -115,33 +71,39 @@ pfil_run_hooks(struct pfil_head *ph, struct mbuf **mp, struct ifnet *ifp, int dir, struct inpcb *inp) { + struct packet_filter_list *pfl; struct packet_filter_hook *pfh; struct mbuf *m =3D *mp; =2D int rv =3D 0; + int i, rv =3D 0; =20 =2D if (ph->ph_busy_count =3D=3D -1) =2D return (0); =2D /* =2D * Prevent packet filtering from starving the modification of =2D * the packet filters. We would prefer a reader/writer locking =2D * mechanism with guaranteed ordering, though. =2D */ =2D if (ph->ph_want_write) { =2D m_freem(*mp); =2D *mp =3D NULL; =2D return (ENOBUFS); =2D } =2D =2D PFIL_RLOCK(ph); =2D for (pfh =3D pfil_hook_get(dir, ph); pfh !=3D NULL; =2D pfh =3D TAILQ_NEXT(pfh, pfil_link)) { =2D if (pfh->pfil_func !=3D NULL) { =2D rv =3D (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir, inp); =2D if (rv !=3D 0 || m =3D=3D NULL) =2D break; =2D } + if (dir & PFIL_IN) { + pfl =3D (struct packet_filter_list *)atomic_load_acq_ptr( + (void *)&ph->ph_in); + if (pfl !=3D NULL) + for (i =3D 0; i < pfl->pfl_size; i++) { + pfh =3D &pfl->pfl_hooks[i]; + if (pfh->pfil_func !=3D NULL) { + rv =3D (*pfh->pfil_func)(pfh->pfil_arg, + &m, ifp, dir, inp); + if (rv !=3D 0 || m =3D=3D NULL) + break; + } + } + } + if ((dir & PFIL_OUT) && rv =3D=3D 0) { + pfl =3D (struct packet_filter_list *)atomic_load_acq_ptr( + (void *)&ph->ph_out); + if (pfl !=3D NULL) + for (i =3D 0; i < pfl->pfl_size; i++) { + pfh =3D &pfl->pfl_hooks[i]; + if (pfh->pfil_func !=3D NULL) { + rv =3D (*pfh->pfil_func)(pfh->pfil_arg, + &m, ifp, dir, inp); + if (rv !=3D 0 || m =3D=3D NULL) + break; + } + } } =2D PFIL_RUNLOCK(ph); =09 *mp =3D m; return (rv); @@ -156,38 +118,141 @@ { struct pfil_head *lph; =20 =2D PFIL_LIST_LOCK(); + PFIL_LOCK(); + if (LIST_EMPTY(&pfil_head_list)) + callout_init_mtx(&pfil_gc_tmo, &pfil_global_lock, 0); LIST_FOREACH(lph, &pfil_head_list, ph_list) if (ph->ph_type =3D=3D lph->ph_type && ph->ph_un.phu_val =3D=3D lph->ph_un.phu_val) { =2D PFIL_LIST_UNLOCK(); + PFIL_UNLOCK(); return EEXIST; } =2D PFIL_LIST_UNLOCK(); =20 =2D if (mtx_initialized(&ph->ph_mtx)) { /* should not happen */ =2D KASSERT((0), ("%s: allready initialized!", __func__)); =2D return EBUSY; =2D } else { =2D ph->ph_busy_count =3D -1; =2D ph->ph_want_write =3D 1; =2D mtx_init(&ph->ph_mtx, "pfil_head_mtx", NULL, MTX_DEF); =2D cv_init(&ph->ph_cv, "pfil_head_cv"); =2D mtx_lock(&ph->ph_mtx); /* XXX: race? */ =2D } =2D =2D TAILQ_INIT(&ph->ph_in); =2D TAILQ_INIT(&ph->ph_out); + ph->ph_in =3D NULL; + ph->ph_out =3D NULL; + sysctl_ctx_init(&ph->ph_clist); =20 =2D PFIL_LIST_LOCK(); LIST_INSERT_HEAD(&pfil_head_list, ph, ph_list); =2D PFIL_LIST_UNLOCK(); =2D=09 =2D PFIL_WUNLOCK(ph); + PFIL_UNLOCK(); =09 return (0); } =20 +static int +pfil_sysctl_handler(SYSCTL_HANDLER_ARGS) +{ + struct packet_filter_list *pfl, *npfl; + struct sbuf *sb; + char *new_order, *elm, *parse; + int i, j, err, hintlen; + + hintlen =3D 0; + npfl =3D NULL; + + pfl =3D (struct packet_filter_list *)atomic_load_acq_ptr( + (void *)arg1); + if (pfl =3D=3D NULL || pfl->pfl_size =3D=3D 0) + err =3D SYSCTL_OUT(req, "empty", 6); + else { + sb =3D sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); + for (i =3D 0; i < pfl->pfl_size; i++) { + if (i > 0) + sbuf_printf(sb, ", "); + if (pfl->pfl_hooks[i].pfil_name) + sbuf_printf(sb, "%s", + pfl->pfl_hooks[i].pfil_name); + else + sbuf_printf(sb, "N/A"); + } + /* hint for sensible write buffer sizes */ + hintlen =3D sbuf_len(sb) + (pfl->pfl_size * 2); + err =3D SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1); + sbuf_delete(sb); + } + + if (err || pfl =3D=3D NULL || !req->newptr) + return (err); + + if ((req->newlen - req->newidx) > hintlen) + return (E2BIG); + new_order =3D malloc(req->newlen - req->newidx + 1, M_TEMP, + M_WAITOK|M_ZERO); + err =3D SYSCTL_IN(req, new_order, (req->newlen - req->newidx)); + if (err) + goto error; + + /* Get memory for new ordered hooks */ + npfl =3D (struct packet_filter_list *)malloc(sizeof(*npfl), M_IFADDR, + M_WAITOK); + npfl->pfl_size =3D pfl->pfl_size; + npfl->pfl_generation =3D pfl->pfl_generation + 1; + npfl->pfl_hooks =3D malloc(sizeof(struct packet_filter_hook) * + npfl->pfl_size, M_IFADDR, M_WAITOK); + + /* Parse request and collect hooks accordingly */ + j =3D 0; + parse =3D new_order; + while ((elm =3D strsep(&parse, " \t,")) !=3D NULL) { + if (*elm =3D=3D '\0') + continue; + for (i =3D 0; i < pfl->pfl_size; i++) + if (strcmp(pfl->pfl_hooks[i].pfil_name, elm) =3D=3D 0) { + npfl->pfl_hooks[j++] =3D pfl->pfl_hooks[i]; + break; + } + if (j >=3D npfl->pfl_size) + break; + } + if (parse !=3D NULL) { + err =3D EINVAL; + goto error; + } + npfl->pfl_size =3D j; + free(new_order, M_TEMP); + + /* Lock - only one writer at a time */ + PFIL_LOCK(); + if (pfl->pfl_generation !=3D + (*((struct packet_filter_list **)arg1))->pfl_generation) { + PFIL_UNLOCK(); + err =3D EAGAIN; + goto error; + } + atomic_store_rel_ptr((volatile void *)arg1, (uintptr_t)npfl); + PFIL_UNLOCK(); + + /* free old memory */ + tsleep(arg1, 0, "pfilrm", hz); + free(pfl->pfl_hooks, M_IFADDR); + free(pfl, M_IFADDR); + + return (0); +error: + if (npfl !=3D NULL) { + free(npfl->pfl_hooks, M_IFADDR); + free(npfl, M_IFADDR); + } + free(new_order, M_TEMP); + return (err); +} + +void +pfil_head_export_sysctl(struct pfil_head *ph, struct sysctl_oid_list *pare= nt) +{ + struct sysctl_oid *root; + + root =3D SYSCTL_ADD_NODE(&ph->ph_clist, parent, OID_AUTO, "pfil", + CTLFLAG_RW, 0, "pfil(9) management"); + SYSCTL_ADD_PROC(&ph->ph_clist, SYSCTL_CHILDREN(root), OID_AUTO, + "inbound", CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_SECURE3, + (void *)&ph->ph_in, 0, pfil_sysctl_handler, "A", + "Inbound filter hooks"); + SYSCTL_ADD_PROC(&ph->ph_clist, SYSCTL_CHILDREN(root), OID_AUTO, + "outbound", CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_SECURE3, + (void *)&ph->ph_out, 0, pfil_sysctl_handler, "A", + "Outbound filter hooks"); +} + /* * pfil_head_unregister() removes a pfil_head from the packet filter * hook mechanism. @@ -195,24 +260,20 @@ int pfil_head_unregister(struct pfil_head *ph) { =2D struct packet_filter_hook *pfh, *pfnext; =2D =09 =2D PFIL_LIST_LOCK(); =2D /*=20 =2D * LIST_REMOVE is safe for unlocked pfil_heads in ph_list. =2D * No need to WLOCK all of them. =2D */ + sysctl_ctx_free(&ph->ph_clist); + + PFIL_LOCK(); LIST_REMOVE(ph, ph_list); =2D PFIL_LIST_UNLOCK(); + PFIL_UNLOCK(); =20 =2D PFIL_WLOCK(ph); /* XXX: may sleep (cv_wait)! */ =2D=09 =2D TAILQ_FOREACH_SAFE(pfh, &ph->ph_in, pfil_link, pfnext) =2D free(pfh, M_IFADDR); =2D TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_link, pfnext) =2D free(pfh, M_IFADDR); =2D cv_destroy(&ph->ph_cv); =2D mtx_destroy(&ph->ph_mtx); + if (ph->ph_in !=3D NULL) { + free(ph->ph_in->pfl_hooks, M_IFADDR); + free(ph->ph_in, M_IFADDR); + } + if (ph->ph_out !=3D NULL) { + free(ph->ph_out->pfl_hooks, M_IFADDR); + free(ph->ph_out, M_IFADDR); + } =09 return (0); } @@ -225,15 +286,31 @@ { struct pfil_head *ph; =20 =2D PFIL_LIST_LOCK(); + PFIL_LOCK(); LIST_FOREACH(ph, &pfil_head_list, ph_list) if (ph->ph_type =3D=3D type && ph->ph_un.phu_val =3D=3D val) break; =2D PFIL_LIST_UNLOCK(); + PFIL_UNLOCK(); =09 return (ph); } =20 +static void +pfil_gc(void *arg) { + struct packet_filter_list *pfl; + + pfl =3D STAILQ_FIRST(&pfil_gc_list); + STAILQ_REMOVE_HEAD(&pfil_gc_list, pfl_next); + + free(pfl->pfl_hooks, M_IFADDR); + free(pfl, M_IFADDR); + + if (!STAILQ_EMPTY(&pfil_gc_list)) + callout_reset(&pfil_gc_tmo, hz, pfil_gc, NULL); + else + callout_deactivate(&pfil_gc_tmo); +} + /* * pfil_add_hook() adds a function to the packet filter hook. the * flags are: @@ -243,71 +320,157 @@ * PFIL_WAITOK OK to call malloc with M_WAITOK. */ int =2Dpfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, s= truct inpcb *), =2D void *arg, int flags, struct pfil_head *ph) +pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, + struct inpcb *), void *arg, int flags, struct pfil_head *ph) { =2D struct packet_filter_hook *pfh1 =3D NULL; =2D struct packet_filter_hook *pfh2 =3D NULL; =2D int err; + return (pfil_add_named_hook(func, arg, NULL, flags, ph)); +} + =20 +int +pfil_add_named_hook(int (*func)(void *, struct mbuf **, struct ifnet *, in= t, + struct inpcb *), void *arg, char *name, int flags, struct pfil_head *p= h) +{ + struct packet_filter_list *pfl_i, *pfl_o, *opfl_i, *opfl_o; + int i, err; + + pfl_i =3D pfl_o =3D NULL; + + /* Get old filter lists */ + opfl_i =3D (struct packet_filter_list *)atomic_load_acq_ptr((void *) + &ph->ph_in); + opfl_o =3D (struct packet_filter_list *)atomic_load_acq_ptr((void *) + &ph->ph_out); + + /* Check for duplicates */ + err =3D EEXIST; + if ((flags & PFIL_IN) && (opfl_i !=3D NULL)) + for (i =3D 0; i < opfl_i->pfl_size; i++) + if ((opfl_i->pfl_hooks[i].pfil_func =3D=3D func) && + (opfl_i->pfl_hooks[i].pfil_arg =3D=3D arg)) + goto error; + if ((flags & PFIL_OUT) && (opfl_o !=3D NULL)) + for (i =3D 0; i < opfl_o->pfl_size; i++) + if ((opfl_o->pfl_hooks[i].pfil_func =3D=3D func) && + (opfl_o->pfl_hooks[i].pfil_arg =3D=3D arg)) + goto error; =20 /* Get memory */ + err =3D ENOMEM; if (flags & PFIL_IN) { =2D pfh1 =3D (struct packet_filter_hook *)malloc(sizeof(*pfh1),=20 + pfl_i =3D (struct packet_filter_list *)malloc(sizeof(*pfl_i), M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); =2D if (pfh1 =3D=3D NULL) { =2D err =3D ENOMEM; + if (pfl_i =3D=3D NULL) goto error; + if (opfl_i !=3D NULL) { + pfl_i->pfl_size =3D opfl_i->pfl_size + 1; + pfl_i->pfl_generation =3D opfl_i->pfl_generation + 1; + } else { + pfl_i->pfl_size =3D 1; + pfl_i->pfl_generation =3D 1; } + pfl_i->pfl_hooks =3D malloc(sizeof(struct packet_filter_hook) * + pfl_i->pfl_size, M_IFADDR, + (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); + if (pfl_i->pfl_hooks =3D=3D NULL)=20 + goto error; } if (flags & PFIL_OUT) { =2D pfh2 =3D (struct packet_filter_hook *)malloc(sizeof(*pfh1), + pfl_o =3D (struct packet_filter_list *)malloc(sizeof(*pfl_o), M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); =2D if (pfh2 =3D=3D NULL) { =2D err =3D ENOMEM; + if (pfl_o =3D=3D NULL) goto error; + if (opfl_o !=3D NULL) { + pfl_o->pfl_size =3D opfl_o->pfl_size + 1; + pfl_o->pfl_generation =3D opfl_o->pfl_generation + 1; + } else { + pfl_o->pfl_size =3D 1; + pfl_o->pfl_generation =3D 1; } =2D } =2D =2D /* Lock */ =2D if (flags & PFIL_WAITOK) =2D PFIL_WLOCK(ph); =2D else { =2D err =3D PFIL_TRY_WLOCK(ph); =2D if (err) + pfl_o->pfl_hooks =3D malloc(sizeof(struct packet_filter_hook) * + pfl_o->pfl_size, M_IFADDR, + (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); + if (pfl_o->pfl_hooks =3D=3D NULL)=20 goto error; } =20 =2D /* Add */ + /* Copy old and add new hooks */ if (flags & PFIL_IN) { =2D pfh1->pfil_func =3D func; =2D pfh1->pfil_arg =3D arg; =2D err =3D pfil_list_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT); =2D if (err) =2D goto done; + pfl_i->pfl_hooks[0].pfil_func =3D func; + pfl_i->pfl_hooks[0].pfil_arg =3D arg; + pfl_i->pfl_hooks[0].pfil_name =3D name; + if (opfl_i !=3D NULL) + bcopy(&opfl_i->pfl_hooks[0], &pfl_i->pfl_hooks[1], + opfl_i->pfl_size * + sizeof(struct packet_filter_hook)); } if (flags & PFIL_OUT) { =2D pfh2->pfil_func =3D func; =2D pfh2->pfil_arg =3D arg; =2D err =3D pfil_list_add(&ph->ph_out, pfh2, flags & ~PFIL_IN); =2D if (err) { =2D if (flags & PFIL_IN) =2D pfil_list_remove(&ph->ph_in, func, arg); =2D goto done; =2D } + pfl_o->pfl_hooks[pfl_o->pfl_size - 1].pfil_func =3D func; + pfl_o->pfl_hooks[pfl_o->pfl_size - 1].pfil_arg =3D arg; + pfl_o->pfl_hooks[pfl_o->pfl_size - 1].pfil_name =3D name; + if (opfl_o !=3D NULL) + bcopy(&opfl_o->pfl_hooks[0], &pfl_o->pfl_hooks[0], + opfl_o->pfl_size * + sizeof(struct packet_filter_hook)); } =20 =2D ph->ph_busy_count =3D 0; =2D PFIL_WUNLOCK(ph); + /* Lock - only one writer at a time */ + PFIL_LOCK(); + err =3D EAGAIN; + if ((flags & PFIL_IN) && (opfl_i !=3D NULL) && + (opfl_i->pfl_generation !=3D ph->ph_in->pfl_generation)) { + PFIL_UNLOCK(); + goto error; + } + if ((flags & PFIL_OUT) && (opfl_o !=3D NULL) && + (opfl_o->pfl_generation !=3D ph->ph_out->pfl_generation)) { + PFIL_UNLOCK(); + goto error; + } + if (flags & PFIL_IN) + atomic_store_rel_ptr((volatile void *)&ph->ph_in, + (uintptr_t)pfl_i); + if (flags & PFIL_OUT) + atomic_store_rel_ptr((volatile void *)&ph->ph_out, + (uintptr_t)pfl_o); + + /* Put old hooks on the GC list and schedule a timeout */ + if (!(flags & PFIL_WAITOK)) { + if (flags & PFIL_IN && opfl_i !=3D NULL) + STAILQ_INSERT_TAIL(&pfil_gc_list, opfl_i, pfl_next); + if (flags & PFIL_IN && opfl_i !=3D NULL) + STAILQ_INSERT_TAIL(&pfil_gc_list, opfl_o, pfl_next); + if (!callout_active(&pfil_gc_tmo)) + callout_reset(&pfil_gc_tmo, hz, pfil_gc, NULL); + } + PFIL_UNLOCK(); =20 =2D return 0; =2Ddone: =2D PFIL_WUNLOCK(ph); + /* free old memory */ + if (flags & PFIL_WAITOK) { + tsleep(ph, 0, "pfilrm", hz); + if (flags & PFIL_IN && opfl_i !=3D NULL) { + free(opfl_i->pfl_hooks, M_IFADDR); + free(opfl_i, M_IFADDR); + } + if (flags & PFIL_OUT && opfl_o !=3D NULL) { + free(opfl_o->pfl_hooks, M_IFADDR); + free(opfl_o, M_IFADDR); + } + } + + return (0); error: =2D if (pfh1 !=3D NULL) =2D free(pfh1, M_IFADDR); =2D if (pfh2 !=3D NULL) =2D free(pfh2, M_IFADDR); =2D return err; + if (pfl_i !=3D NULL) { + if (pfl_i->pfl_hooks) + free(pfl_i->pfl_hooks, M_IFADDR); + free(pfl_i, M_IFADDR); + } + if (pfl_o !=3D NULL) { + if (pfl_o->pfl_hooks) + free(pfl_o->pfl_hooks, M_IFADDR); + free(pfl_o, M_IFADDR); + } + + return (err); } =20 /* @@ -315,71 +478,142 @@ * hook list. */ int =2Dpfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int= , struct inpcb *), =2D void *arg, int flags, struct pfil_head *ph) +pfil_remove_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, + struct inpcb *), void *arg, int flags, struct pfil_head *ph) { =2D int err =3D 0; + struct packet_filter_list *pfl_i, *pfl_o, *opfl_i, *opfl_o; + int i, j, lflags, err; =20 =2D if (flags & PFIL_WAITOK) =2D PFIL_WLOCK(ph); =2D else { =2D err =3D PFIL_TRY_WLOCK(ph); =2D if (err) =2D return err; =2D } + pfl_i =3D pfl_o =3D NULL; =20 =2D if (flags & PFIL_IN) =2D err =3D pfil_list_remove(&ph->ph_in, func, arg); =2D if ((err =3D=3D 0) && (flags & PFIL_OUT)) =2D err =3D pfil_list_remove(&ph->ph_out, func, arg); + /* Get old filter lists */ + opfl_i =3D (struct packet_filter_list *)atomic_load_acq_ptr((void *) + &ph->ph_in); + opfl_o =3D (struct packet_filter_list *)atomic_load_acq_ptr((void *) + &ph->ph_out); + + /* Check for existance, only delete when necessary */ + lflags =3D 0; + if ((flags & PFIL_IN) && (opfl_i !=3D NULL)) + for (i =3D 0; i < opfl_i->pfl_size; i++) + if ((opfl_i->pfl_hooks[i].pfil_func =3D=3D func) && + (opfl_i->pfl_hooks[i].pfil_arg =3D=3D arg)) { + lflags |=3D PFIL_IN; + break; + } + if ((flags & PFIL_OUT) && (opfl_o !=3D NULL)) + for (i =3D 0; i < opfl_o->pfl_size; i++) + if ((opfl_o->pfl_hooks[i].pfil_func =3D=3D func) && + (opfl_o->pfl_hooks[i].pfil_arg =3D=3D arg)) { + lflags |=3D PFIL_OUT; + break; + } =20 =2D if (TAILQ_EMPTY(&ph->ph_in) && TAILQ_EMPTY(&ph->ph_out)) =2D ph->ph_busy_count =3D -1; + if (!lflags & PFIL_ALL) + return (ENOENT); =20 =2D PFIL_WUNLOCK(ph); =2D=09 =2D return err; =2D} + /* Get memory */ + err =3D ENOMEM; + if ((lflags & PFIL_IN) && (opfl_i->pfl_size > 1)) { + pfl_i =3D (struct packet_filter_list *)malloc(sizeof(*pfl_i), + M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); + if (pfl_i =3D=3D NULL) + goto error; + pfl_i->pfl_size =3D opfl_i->pfl_size - 1; + pfl_i->pfl_generation =3D opfl_i->pfl_generation + 1; + pfl_i->pfl_hooks =3D malloc(sizeof(struct packet_filter_hook) * + pfl_i->pfl_size, M_IFADDR, + (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); + if (pfl_i->pfl_hooks =3D=3D NULL)=20 + goto error; + } + if ((lflags & PFIL_OUT) && (opfl_o->pfl_size > 1)) { + pfl_o =3D (struct packet_filter_list *)malloc(sizeof(*pfl_o), + M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); + if (pfl_o =3D=3D NULL) + goto error; + pfl_o->pfl_size =3D opfl_o->pfl_size - 1; + pfl_o->pfl_generation =3D opfl_o->pfl_generation + 1; + pfl_o->pfl_hooks =3D malloc(sizeof(struct packet_filter_hook) * + pfl_o->pfl_size, M_IFADDR, + (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT); + if (pfl_o->pfl_hooks =3D=3D NULL)=20 + goto error; + } =20 =2Dstatic int =2Dpfil_list_add(pfil_list_t *list, struct packet_filter_hook *pfh1, int fl= ags) =2D{ =2D struct packet_filter_hook *pfh; + /* Copy old hooks but the one we are deleting */ + if (lflags & PFIL_IN) + for (j =3D i =3D 0; i < opfl_i->pfl_size; i++) { + if ((opfl_i->pfl_hooks[i].pfil_func =3D=3D func) && + (opfl_i->pfl_hooks[i].pfil_arg =3D=3D arg)) + continue; + pfl_i->pfl_hooks[j++] =3D opfl_i->pfl_hooks[i]; + } + if (lflags & PFIL_OUT) + for (j =3D i =3D 0; i < opfl_o->pfl_size; i++) { + if ((opfl_o->pfl_hooks[i].pfil_func =3D=3D func) && + (opfl_o->pfl_hooks[i].pfil_arg =3D=3D arg)) + continue; + pfl_o->pfl_hooks[j++] =3D opfl_o->pfl_hooks[i]; + } =20 =2D /* =2D * First make sure the hook is not already there. =2D */ =2D TAILQ_FOREACH(pfh, list, pfil_link) =2D if (pfh->pfil_func =3D=3D pfh1->pfil_func && =2D pfh->pfil_arg =3D=3D pfh1->pfil_arg) =2D return EEXIST; =2D /* =2D * insert the input list in reverse order of the output list =2D * so that the same path is followed in or out of the kernel. =2D */ + /* Lock - only one writer at a time */ + PFIL_LOCK(); + err =3D EAGAIN; + if ((flags & PFIL_IN) && (opfl_i !=3D NULL) && + (opfl_i->pfl_generation !=3D ph->ph_in->pfl_generation)) { + PFIL_UNLOCK(); + goto error; + } + if ((flags & PFIL_OUT) && (opfl_o !=3D NULL) && + (opfl_o->pfl_generation !=3D ph->ph_out->pfl_generation)) { + PFIL_UNLOCK(); + goto error; + } if (flags & PFIL_IN) =2D TAILQ_INSERT_HEAD(list, pfh1, pfil_link); =2D else =2D TAILQ_INSERT_TAIL(list, pfh1, pfil_link); + atomic_store_rel_ptr((volatile void *)&ph->ph_in, + (uintptr_t)pfl_i); + if (flags & PFIL_OUT) + atomic_store_rel_ptr((volatile void *)&ph->ph_out, + (uintptr_t)pfl_o); + + /* Put old hooks on the GC list and schedule a timeout */ + if (!(flags & PFIL_WAITOK)) { + if (flags & PFIL_IN && opfl_i !=3D NULL) + STAILQ_INSERT_TAIL(&pfil_gc_list, opfl_i, pfl_next); + if (flags & PFIL_IN && opfl_i !=3D NULL) + STAILQ_INSERT_TAIL(&pfil_gc_list, opfl_o, pfl_next); + if (!callout_active(&pfil_gc_tmo)) + callout_reset(&pfil_gc_tmo, hz, pfil_gc, NULL); + } + PFIL_UNLOCK(); =20 =2D return 0; =2D} + /* free old memory */ + if (flags & PFIL_WAITOK) { + tsleep(ph, 0, "pfilrm", hz); + if (flags & PFIL_IN && opfl_i !=3D NULL) { + free(opfl_i->pfl_hooks, M_IFADDR); + free(opfl_i, M_IFADDR); + } + if (flags & PFIL_OUT && opfl_o !=3D NULL) { + free(opfl_o->pfl_hooks, M_IFADDR); + free(opfl_o, M_IFADDR); + } + } =20 =2D/* =2D * pfil_list_remove is an internal function that takes a function off the =2D * specified list. =2D */ =2Dstatic int =2Dpfil_list_remove(pfil_list_t *list, =2D int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpc= b *), void *arg) =2D{ =2D struct packet_filter_hook *pfh; + return (0); +error: + if (pfl_i !=3D NULL) { + if (pfl_i->pfl_hooks) + free(pfl_i->pfl_hooks, M_IFADDR); + free(pfl_i, M_IFADDR); + } + if (pfl_o !=3D NULL) { + if (pfl_o->pfl_hooks) + free(pfl_o->pfl_hooks, M_IFADDR); + free(pfl_o, M_IFADDR); + } + + return (err); =20 =2D TAILQ_FOREACH(pfh, list, pfil_link) =2D if (pfh->pfil_func =3D=3D func && pfh->pfil_arg =3D=3D arg) { =2D TAILQ_REMOVE(list, pfh, pfil_link); =2D free(pfh, M_IFADDR); =2D return 0; =2D } =2D return ENOENT; } Index: net/pfil.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/net/pfil.h,v retrieving revision 1.13 diff -u -r1.13 pfil.h =2D-- net/pfil.h 7 Jan 2005 01:45:35 -0000 1.13 +++ net/pfil.h 4 Dec 2005 13:24:24 -0000 @@ -2,6 +2,7 @@ /* $NetBSD: pfil.h,v 1.22 2003/06/23 12:57:08 martin Exp $ */ =20 /*- + * Copyright (c) 2005 Max Laier * Copyright (c) 1996 Matthew R. Green * All rights reserved. * @@ -34,9 +35,7 @@ =20 #include <sys/systm.h> #include <sys/queue.h> =2D#include <sys/_lock.h> =2D#include <sys/_mutex.h> =2D#include <sys/condvar.h> /* XXX */ +#include <sys/sysctl.h> =20 struct mbuf; struct ifnet; @@ -47,34 +46,34 @@ * possibly intercept the packet. */ struct packet_filter_hook { =2D TAILQ_ENTRY(packet_filter_hook) pfil_link; int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int, struct inpc= b *); void *pfil_arg; =2D int pfil_flags; + char *pfil_name; }; =20 +struct packet_filter_list { + STAILQ_ENTRY(packet_filter_list) pfl_next; + struct packet_filter_hook *pfl_hooks; + int pfl_size; + int pfl_generation; +}; + +STAILQ_HEAD(pfil_gclist, packet_filter_list); + #define PFIL_IN 0x00000001 #define PFIL_OUT 0x00000002 =2D#define PFIL_WAITOK 0x00000004 #define PFIL_ALL (PFIL_IN|PFIL_OUT) =2D =2Dtypedef TAILQ_HEAD(pfil_list, packet_filter_hook) pfil_list_t; +#define PFIL_WAITOK 0x00000004 =20 #define PFIL_TYPE_AF 1 /* key is AF_* type */ #define PFIL_TYPE_IFNET 2 /* key is ifnet pointer */ =20 struct pfil_head { =2D pfil_list_t ph_in; =2D pfil_list_t ph_out; + struct packet_filter_list *ph_in; + struct packet_filter_list *ph_out; +#define PFIL_IS_EMPTY(ph) (((ph).ph_in =3D=3D NULL) && ((ph).ph_out =3D=3D= NULL)) + struct sysctl_ctx_list ph_clist; int ph_type; =2D /* =2D * Locking: use a busycounter per pfil_head. =2D * Use ph_busy_count =3D -1 to indicate pfil_head is empty. =2D */ =2D int ph_busy_count; /* count of threads with read lock */ =2D int ph_want_write; /* want write lock flag */ =2D struct cv ph_cv; /* for waking up writers */ =2D struct mtx ph_mtx; /* mutex on locking state */ union { u_long phu_val; void *phu_ptr; @@ -88,26 +87,19 @@ int, struct inpcb *inp); =20 int pfil_add_hook(int (*func)(void *, struct mbuf **, =2D struct ifnet *, int, struct inpcb *), void *, int, struct pfil_head= *); + struct ifnet *, int, struct inpcb *), void *, int, + struct pfil_head *); +int pfil_add_named_hook(int (*func)(void *, struct mbuf **, + struct ifnet *, int, struct inpcb *), void *, char *, int, + struct pfil_head *); int pfil_remove_hook(int (*func)(void *, struct mbuf **, =2D struct ifnet *, int, struct inpcb *), void *, int, struct pfil_head= *); + struct ifnet *, int, struct inpcb *), void *, int, + struct pfil_head *); =20 int pfil_head_register(struct pfil_head *); +void pfil_head_export_sysctl(struct pfil_head *, struct sysctl_oid_list *); int pfil_head_unregister(struct pfil_head *); =20 struct pfil_head *pfil_head_get(int, u_long); =20 =2Dstatic __inline struct packet_filter_hook * =2Dpfil_hook_get(int dir, struct pfil_head *ph) =2D{ =2D KASSERT(ph->ph_busy_count > 0,=20 =2D ("pfil_hook_get: called on unbusy pfil_head")); =2D if (dir =3D=3D PFIL_IN) =2D return (TAILQ_FIRST(&ph->ph_in)); =2D else if (dir =3D=3D PFIL_OUT) =2D return (TAILQ_FIRST(&ph->ph_out)); =2D else =2D return (NULL); =2D} =2D #endif /* _NET_PFIL_H_ */ Index: netinet/ip_fastfwd.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/netinet/ip_fastfwd.c,v retrieving revision 1.33 diff -u -r1.33 ip_fastfwd.c =2D-- netinet/ip_fastfwd.c 18 Nov 2005 20:12:39 -0000 1.33 +++ netinet/ip_fastfwd.c 4 Dec 2005 13:47:59 -0000 @@ -345,7 +345,7 @@ /* * Run through list of ipfilter hooks for input packets */ =2D if (inet_pfil_hook.ph_busy_count =3D=3D -1) + if (PFIL_IS_EMPTY(inet_pfil_hook)) goto passin; =20 if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL)= || @@ -430,7 +430,7 @@ /* * Run through list of hooks for output packets. */ =2D if (inet_pfil_hook.ph_busy_count =3D=3D -1) + if (PFIL_IS_EMPTY(inet_pfil_hook)) goto passout; =20 if (pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT, NULL) || m =3D=3D = NULL) { Index: netinet/ip_fw_pfil.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/netinet/ip_fw_pfil.c,v retrieving revision 1.20 diff -u -r1.20 ip_fw_pfil.c =2D-- netinet/ip_fw_pfil.c 29 Nov 2005 17:56:11 -0000 1.20 +++ netinet/ip_fw_pfil.c 4 Dec 2005 13:47:59 -0000 @@ -433,11 +433,15 @@ return ENOENT; #endif =20 =2D pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet); =2D pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet); + pfil_add_named_hook(ipfw_check_in, NULL, "ipfw", PFIL_IN | PFIL_WAITOK, + pfh_inet); + pfil_add_named_hook(ipfw_check_out, NULL, "ipfw", + PFIL_OUT | PFIL_WAITOK, pfh_inet); #ifdef INET6 =2D pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6); =2D pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6); + pfil_add_named_hook(ipfw_check_in, NULL, "ipfw", PFIL_IN | PFIL_WAITOK, + pfh_inet6); + pfil_add_named_hook(ipfw_check_out, NULL, "ipfw", + PFIL_OUT | PFIL_WAITOK, pfh_inet6); #endif =20 return 0; Index: netinet/ip_input.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/netinet/ip_input.c,v retrieving revision 1.309 diff -u -r1.309 ip_input.c =2D-- netinet/ip_input.c 4 Dec 2005 02:12:43 -0000 1.309 +++ netinet/ip_input.c 4 Dec 2005 13:47:59 -0000 @@ -242,6 +242,9 @@ if ((i =3D pfil_head_register(&inet_pfil_hook)) !=3D 0) printf("%s: WARNING: unable to register pfil hook, " "error %d\n", __func__, i); + else + pfil_head_export_sysctl(&inet_pfil_hook, + SYSCTL_STATIC_CHILDREN(_net_inet_ip)); =20 /* Initialize IP reassembly queue. */ IPQ_LOCK_INIT(); @@ -415,7 +418,7 @@ */ =20 /* Jump over all PFIL processing if hooks are not active. */ =2D if (inet_pfil_hook.ph_busy_count =3D=3D -1) + if (PFIL_IS_EMPTY(inet_pfil_hook)) goto passin; =20 odst =3D ip->ip_dst; Index: netinet/ip_output.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/netinet/ip_output.c,v retrieving revision 1.250 diff -u -r1.250 ip_output.c =2D-- netinet/ip_output.c 18 Nov 2005 20:12:39 -0000 1.250 +++ netinet/ip_output.c 4 Dec 2005 13:47:59 -0000 @@ -654,7 +654,7 @@ #endif /* FAST_IPSEC */ =20 /* Jump over all PFIL processing if hooks are not active. */ =2D if (inet_pfil_hook.ph_busy_count =3D=3D -1) + if (PFIL_IS_EMPTY(inet_pfil_hook)) goto passout; =20 /* Run through list of hooks for output packets. */ Index: netinet6/ip6_forward.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/netinet6/ip6_forward.c,v retrieving revision 1.30 diff -u -r1.30 ip6_forward.c =2D-- netinet6/ip6_forward.c 10 Aug 2005 09:13:35 -0000 1.30 +++ netinet6/ip6_forward.c 4 Dec 2005 13:48:00 -0000 @@ -611,7 +611,7 @@ in6_clearscope(&ip6->ip6_dst); =20 /* Jump over all PFIL processing if hooks are not active. */ =2D if (inet6_pfil_hook.ph_busy_count =3D=3D -1) + if (PFIL_IS_EMPTY(inet6_pfil_hook)) goto pass; =20 /* Run through list of hooks for output packets. */ Index: netinet6/ip6_input.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/netinet6/ip6_input.c,v retrieving revision 1.84 diff -u -r1.84 ip6_input.c =2D-- netinet6/ip6_input.c 19 Oct 2005 16:20:18 -0000 1.84 +++ netinet6/ip6_input.c 4 Dec 2005 13:48:00 -0000 @@ -136,6 +136,7 @@ =20 int ip6_ours_check_algorithm; =20 +SYSCTL_DECL(_net_inet6_ip6); struct pfil_head inet6_pfil_hook; =20 /* firewall hooks */ @@ -192,6 +193,9 @@ if ((i =3D pfil_head_register(&inet6_pfil_hook)) !=3D 0) printf("%s: WARNING: unable to register pfil hook, " "error %d\n", __func__, i); + else + pfil_head_export_sysctl(&inet6_pfil_hook, + SYSCTL_STATIC_CHILDREN(_net_inet6_ip6)); =20 ip6intrq.ifq_maxlen =3D ip6qmaxlen; mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", NULL, MTX_DEF); @@ -434,7 +438,7 @@ odst =3D ip6->ip6_dst; =20 /* Jump over all PFIL processing if hooks are not active. */ =2D if (inet6_pfil_hook.ph_busy_count =3D=3D -1) + if (PFIL_IS_EMPTY(inet6_pfil_hook)) goto passin; =20 if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN, NULL= )) Index: netinet6/ip6_output.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /usr/store/mlaier/fcvs/src/sys/netinet6/ip6_output.c,v retrieving revision 1.100 diff -u -r1.100 ip6_output.c =2D-- netinet6/ip6_output.c 21 Oct 2005 16:23:00 -0000 1.100 +++ netinet6/ip6_output.c 4 Dec 2005 13:48:00 -0000 @@ -889,7 +889,7 @@ } =20 /* Jump over all PFIL processing if hooks are not active. */ =2D if (inet6_pfil_hook.ph_busy_count =3D=3D -1) + if (PFIL_IS_EMPTY(inet6_pfil_hook)) goto passout; =20 odst =3D ip6->ip6_dst; --Boundary-01=_seC5F187reQBkMk-- --nextPart23452799.USI6mqnrhR Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (FreeBSD) iD8DBQBF5CexXyyEoT62BG0RAqf4AJ9XhNbJW+cR3yXs1S0FfdIBRC86VACdHPx2 WV8KnMMIYJOTQADOAnuY96c= =40TZ -----END PGP SIGNATURE----- --nextPart23452799.USI6mqnrhR--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200702271344.33881.max>