Index: sys/contrib/pf/net/pf_ioctl.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/pf/net/pf_ioctl.c,v
retrieving revision 1.28.2.5
diff -u -r1.28.2.5 pf_ioctl.c
--- sys/contrib/pf/net/pf_ioctl.c 24 Jul 2008 19:05:32 -0000 1.28.2.5
+++ sys/contrib/pf/net/pf_ioctl.c 25 Oct 2008 14:22:34 -0000
@@ -3761,8 +3761,10 @@
pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
if (pfh_inet == NULL)
return (ESRCH); /* XXX */
- pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
- 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 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
if (pfh_inet6 == NULL) {
@@ -3772,8 +3774,10 @@
pfh_inet);
return (ESRCH); /* XXX */
}
- pfil_add_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
- 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
pf_pfil_hooked = 1;
Index: sys/net/pfil.c
===================================================================
RCS file: /home/ncvs/src/sys/net/pfil.c,v
retrieving revision 1.14
diff -u -r1.14 pfil.c
--- sys/net/pfil.c 2 Feb 2006 03:13:15 -0000 1.14
+++ sys/net/pfil.c 25 Oct 2008 14:22:34 -0000
@@ -34,6 +34,7 @@
#include <sys/errno.h>
#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/sbuf.h>
#include <sys/rwlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@@ -74,7 +75,7 @@
KASSERT(ph->ph_nhooks >= 0, ("Pfil hook count dropped < 0"));
for (pfh = pfil_hook_get(dir, ph); pfh != NULL;
pfh = TAILQ_NEXT(pfh, pfil_link)) {
- if (pfh->pfil_func != NULL) {
+ if (!(pfh->pfil_flags & PFIL_DISABLED) && pfh->pfil_func != NULL) {
rv = (*pfh->pfil_func)(pfh->pfil_arg, &m, ifp, dir, inp);
if (rv != 0 || m == NULL)
break;
@@ -148,6 +149,140 @@
return (0);
}
+static int
+pfil_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+ struct pfil_head *ph;
+ struct packet_filter_hook *pfh, *pfhtmp;
+ struct sbuf *sb;
+ pfil_list_t npfl, *pfl;
+ char *new_order, *elm, *parse;
+ int i = 0, err = 0, hintlen, reqlen;
+
+ hintlen = 0;
+
+ ph = (struct pfil_head *)arg1;
+ if (ph == NULL || !PFIL_HOOKED(ph)) {
+ err = SYSCTL_OUT(req, "", 2);
+ return (err);
+ }
+
+ if (arg2 == PFIL_IN)
+ pfl = &ph->ph_in;
+ else
+ pfl = &ph->ph_out;
+
+ if (TAILQ_EMPTY(pfl)) {
+ err = SYSCTL_OUT(req, "", 2);
+ return (err);
+ }
+
+ /*
+ * NOTE: This is needed to avoid witness(4) warnings.
+ */
+ PFIL_RLOCK(ph);
+ TAILQ_FOREACH(pfh, pfl, pfil_link) {
+ if (pfh->pfil_name != NULL)
+ hintlen = strlen(pfh->pfil_name);
+ else
+ hintlen += 2;
+ }
+ PFIL_RUNLOCK(ph);
+
+ sb = sbuf_new(NULL, NULL, hintlen + 1, SBUF_AUTOEXTEND);
+ if (sb == NULL)
+ return (EINVAL);
+
+ PFIL_RLOCK(ph);
+ TAILQ_FOREACH(pfh, pfl, pfil_link) {
+ if (i > 0)
+ sbuf_printf(sb, ", ");
+ if (pfh->pfil_name != NULL)
+ sbuf_printf(sb, "%s%s", pfh->pfil_name,
+ pfh->pfil_flags & PFIL_DISABLED ? "*" : "");
+ else
+ sbuf_printf(sb, "%s%s", "NA",
+ pfh->pfil_flags & PFIL_DISABLED ? "*" : "");
+ i++;
+ }
+ PFIL_RUNLOCK(ph);
+
+ sbuf_finish(sb);
+
+ /* hint for sensible write buffer sizes */
+ hintlen = sbuf_len(sb) + i * 2;
+ err = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
+ sbuf_delete(sb);
+
+ if (err || !req->newptr)
+ return (err);
+
+ if ((reqlen = req->newlen - req->newidx) > hintlen)
+ return (E2BIG);
+ new_order = malloc(reqlen + 1, M_TEMP, M_WAITOK|M_ZERO);
+
+ err = SYSCTL_IN(req, new_order, reqlen);
+ if (err)
+ goto error;
+ new_order[reqlen] = '\0'; /* Just in case */
+ parse = new_order;
+
+ TAILQ_INIT(&npfl);
+ PFIL_WLOCK(ph);
+ while ((elm = strsep(&parse, " \t,")) != NULL) {
+ if (*elm == '\0')
+ continue;
+ TAILQ_FOREACH_SAFE(pfh, pfl, pfil_link, pfhtmp) {
+ if (pfh->pfil_name != NULL) {
+ if (!strcmp(pfh->pfil_name, elm)) {
+ TAILQ_REMOVE(pfl, pfh, pfil_link);
+ TAILQ_INSERT_TAIL(&npfl, pfh, pfil_link);
+ pfh->pfil_flags &= ~PFIL_DISABLED;
+ break;
+ }
+ } else {
+ if (!strcmp(elm, "NA")) {
+ TAILQ_REMOVE(pfl, pfh, pfil_link);
+ TAILQ_INSERT_TAIL(&npfl, pfh, pfil_link);
+ pfh->pfil_flags &= ~PFIL_DISABLED;
+ break;
+ }
+ }
+ }
+ }
+
+ TAILQ_FOREACH_SAFE(pfh, pfl, pfil_link, pfhtmp) {
+ pfh->pfil_flags |= PFIL_DISABLED;
+ TAILQ_REMOVE(pfl, pfh, pfil_link);
+ TAILQ_INSERT_TAIL(&npfl, pfh, pfil_link);
+ }
+
+ TAILQ_CONCAT(pfl, &npfl, pfil_link);
+
+error:
+ PFIL_WUNLOCK(ph);
+ free(new_order, M_TEMP);
+ return (err);
+}
+
+void
+pfil_head_export_sysctl(struct pfil_head *ph, struct sysctl_oid_list *parent)
+{
+ struct sysctl_oid *root;
+
+ root = SYSCTL_ADD_NODE(&ph->ph_clist, parent, OID_AUTO, "pfil",
+ CTLFLAG_RW, 0, "pfil(9) management");
+ SYSCTL_ADD_PROC((void *)&ph->ph_clist, SYSCTL_CHILDREN(root), OID_AUTO,
+ "inbound", CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_SECURE3,
+ (void *)ph, PFIL_IN, pfil_sysctl_handler, "A",
+ "Inbound filter hooks");
+ SYSCTL_ADD_PROC((void *)&ph->ph_clist, SYSCTL_CHILDREN(root), OID_AUTO,
+ "outbound", CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_SECURE3,
+ (void *)ph, PFIL_OUT, pfil_sysctl_handler, "A",
+ "Outbound filter hooks");
+}
+
+
/*
* pfil_head_get() returns the pfil_head for a given key/dlt.
*/
@@ -177,6 +312,13 @@
pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *),
void *arg, int flags, struct pfil_head *ph)
{
+ return (pfil_add_named_hook(func, arg, NULL, flags, ph));
+}
+
+int
+pfil_add_named_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int,
+ struct inpcb *), void *arg, char *name, int flags, struct pfil_head *ph)
+{
struct packet_filter_hook *pfh1 = NULL;
struct packet_filter_hook *pfh2 = NULL;
int err;
@@ -206,6 +348,8 @@
if (flags & PFIL_IN) {
pfh1->pfil_func = func;
pfh1->pfil_arg = arg;
+ pfh1->pfil_name = name;
+ pfh1->pfil_flags &= ~PFIL_DISABLED;
err = pfil_list_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT);
if (err)
goto done;
@@ -214,6 +358,8 @@
if (flags & PFIL_OUT) {
pfh2->pfil_func = func;
pfh2->pfil_arg = arg;
+ pfh2->pfil_name = name;
+ pfh2->pfil_flags &= ~PFIL_DISABLED;
err = pfil_list_add(&ph->ph_out, pfh2, flags & ~PFIL_IN);
if (err) {
if (flags & PFIL_IN)
Index: sys/net/pfil.h
===================================================================
RCS file: /home/ncvs/src/sys/net/pfil.h,v
retrieving revision 1.16
diff -u -r1.16 pfil.h
--- sys/net/pfil.h 8 Jun 2007 12:43:25 -0000 1.16
+++ sys/net/pfil.h 25 Oct 2008 14:22:34 -0000
@@ -38,6 +38,7 @@
#include <sys/_mutex.h>
#include <sys/lock.h>
#include <sys/rwlock.h>
+#include <sys/sysctl.h>
struct mbuf;
struct ifnet;
@@ -52,8 +53,11 @@
int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *);
void *pfil_arg;
int pfil_flags;
+ char *pfil_name;
};
+#define PFIL_DISABLED 0x00000008
+
#define PFIL_IN 0x00000001
#define PFIL_OUT 0x00000002
#define PFIL_WAITOK 0x00000004
@@ -70,6 +74,7 @@
int ph_type;
int ph_nhooks;
struct rwlock ph_mtx;
+ struct sysctl_ctx_list ph_clist;
union {
u_long phu_val;
void *phu_ptr;
@@ -82,12 +87,16 @@
int pfil_run_hooks(struct pfil_head *, struct mbuf **, struct ifnet *,
int, struct inpcb *inp);
+int pfil_add_named_hook(int (*func)(void *, struct mbuf **,
+ struct ifnet *, int, struct inpcb *), void *, char *, int,
+ struct pfil_head *);
int pfil_add_hook(int (*func)(void *, struct mbuf **,
struct ifnet *, int, struct inpcb *), void *, int, struct pfil_head *);
int pfil_remove_hook(int (*func)(void *, struct mbuf **,
struct ifnet *, int, struct inpcb *), void *, int, struct pfil_head *);
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 *);
struct pfil_head *pfil_head_get(int, u_long);
Index: sys/netinet/ip_fw_pfil.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw_pfil.c,v
retrieving revision 1.25.2.2
diff -u -r1.25.2.2 ip_fw_pfil.c
--- sys/netinet/ip_fw_pfil.c 25 Apr 2008 10:26:30 -0000 1.25.2.2
+++ sys/netinet/ip_fw_pfil.c 25 Oct 2008 14:22:35 -0000
@@ -430,8 +430,10 @@
if (pfh_inet == NULL)
return ENOENT;
- pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
- 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);
return 0;
}
@@ -461,8 +463,10 @@
if (pfh_inet6 == NULL)
return ENOENT;
- pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
- 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);
return 0;
}
Index: sys/netinet/ip_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.332.2.4
diff -u -r1.332.2.4 ip_input.c
--- sys/netinet/ip_input.c 24 Jul 2008 01:13:22 -0000 1.332.2.4
+++ sys/netinet/ip_input.c 25 Oct 2008 14:22:36 -0000
@@ -244,6 +244,9 @@
if ((i = pfil_head_register(&inet_pfil_hook)) != 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));
/* Initialize IP reassembly queue. */
IPQ_LOCK_INIT();
Index: sys/netinet6/ip6_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.95.2.4
diff -u -r1.95.2.4 ip6_input.c
--- sys/netinet6/ip6_input.c 1 Sep 2008 19:23:04 -0000 1.95.2.4
+++ sys/netinet6/ip6_input.c 25 Oct 2008 14:22:38 -0000
@@ -126,6 +126,7 @@
int ip6_ours_check_algorithm;
+SYSCTL_DECL(_net_inet6_ip6);
struct pfil_head inet6_pfil_hook;
struct ip6stat ip6stat;
@@ -177,6 +178,9 @@
if ((i = pfil_head_register(&inet6_pfil_hook)) != 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));
ip6intrq.ifq_maxlen = ip6qmaxlen;
mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", NULL, MTX_DEF);
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>