From szalai.bandi@gmail.com  Fri Mar 20 09:15:39 2009
Return-Path: <szalai.bandi@gmail.com>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 860FA106566B
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 20 Mar 2009 09:15:39 +0000 (UTC)
	(envelope-from szalai.bandi@gmail.com)
Received: from mail-bw0-f164.google.com (mail-bw0-f164.google.com [209.85.218.164])
	by mx1.freebsd.org (Postfix) with ESMTP id A24248FC0A
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 20 Mar 2009 09:15:38 +0000 (UTC)
	(envelope-from szalai.bandi@gmail.com)
Received: by bwz8 with SMTP id 8so756952bwz.43
        for <FreeBSD-gnats-submit@freebsd.org>; Fri, 20 Mar 2009 02:15:37 -0700 (PDT)
Received: by 10.223.115.80 with SMTP id h16mr2990196faq.94.1237540537267;
        Fri, 20 Mar 2009 02:15:37 -0700 (PDT)
Received: from tristania.mooo.com (94-21-14-184.pool.digikabel.hu [94.21.14.184])
        by mx.google.com with ESMTPS id b17sm3354811fka.24.2009.03.20.02.15.34
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Fri, 20 Mar 2009 02:15:35 -0700 (PDT)
Received: by tristania.kispest.home (Postfix, from userid 1000)
	id 27414D4C29; Fri, 20 Mar 2009 10:15:33 +0100 (CET)
Message-Id: <20090320091532.GA28471@tristania.kispest.home>
Date: Fri, 20 Mar 2009 10:15:32 +0100
From: Szalai Andras <szalai.bandi@gmail.com>
Reply-To: Szalai Andras <szalai.bandi@gmail.com>
To: FreeBSD-gnats-submit@freebsd.org
Subject: [patch] snmp_pf: add support for retrieving pf filter rule counters
X-Send-Pr-Version: 3.113

>Number:         132847
>Category:       bin
>Synopsis:       [patch] bsnmpd(8): snmp_pf: add support for retrieving pf filter rule counters
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    syrinx
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Fri Mar 20 09:20:01 UTC 2009
>Closed-Date:    Thu Mar 18 17:31:53 UTC 2010
>Last-Modified:  Thu Mar 18 17:31:53 UTC 2010
>Originator:     Szalai Andras
>Release:        FreeBSD 7.1-RELEASE-p1 i386
>Organization:
none
>Environment:
System: FreeBSD tristania.kispest.home 7.1-RELEASE-p1 FreeBSD 7.1-RELEASE-p1 #0: Sun Jan 11 17:34:03 CET 2009 root@tristania.kispest.home:/disk/ad8p5/root.usr/src/sys/i386/compile/TRISTANIA i386

>Description:

The FreeBSD base system contains a snmp daemon called bsnmpd. It implements
most of its functionality via loadable modules. The snmp_pf module is
responsible for constructing the MIB for the pf packet filter, however
it doesn't support retrieving counters of (labeled) pf filter rules.

>How-To-Repeat:

>Fix:

The attached patch adds a table which contains counters (evaluations,
packets in/out, bytes in/out) for each labeled pf filter rule. It can
be applied cleanly to snmp_pf from RELENG_7_1.

--- snmp_pf.diff begins here ---
diff -ru snmp_pf.orig/BEGEMOT-PF-MIB.txt snmp_pf/BEGEMOT-PF-MIB.txt
--- snmp_pf.orig/BEGEMOT-PF-MIB.txt	2009-01-10 16:46:38.000000000 +0100
+++ snmp_pf/BEGEMOT-PF-MIB.txt	2009-03-20 09:52:13.000000000 +0100
@@ -51,6 +51,7 @@
 pfInterfaces		OBJECT IDENTIFIER ::= { begemotPfObjects 8 }
 pfTables		OBJECT IDENTIFIER ::= { begemotPfObjects 9 }
 pfAltq			OBJECT IDENTIFIER ::= { begemotPfObjects 10 }
+pfLabels		OBJECT IDENTIFIER ::= { begemotPfObjects 11 }
 
 -- --------------------------------------------------------------------------
 
@@ -1227,4 +1228,102 @@
 	"Maximum number of packets in the queue."
     ::= { pfAltqQueueEntry 7 }
 
+-- --------------------------------------------------------------------------
+
+--
+-- Labeled filter rules statistics
+--
+
+pfLabelsLblNumber OBJECT-TYPE
+    SYNTAX	Integer32
+    MAX-ACCESS	read-only
+    STATUS	current
+    DESCRIPTION
+	"The number of labeled filter rules on this system."
+    ::= { pfLabels 1 }
+
+pfLabelsLblTable OBJECT-TYPE
+    SYNTAX	SEQUENCE OF pfLabelsLblEntry
+    MAX-ACCESS	not-accessible
+    STATUS	current
+    DESCRIPTION
+	"Table of filter rules, index on pfLabelsLblIndex."
+    ::= { pfLabels 2 }
+
+pfLabelsLblEntry OBJECT-TYPE
+    SYNTAX	pfLabelsLblEntry
+    MAX-ACCESS	not-accessible
+    STATUS	current
+    DESCRIPTION
+	"Any entry in the pfLabelsLblTable containing information
+	about a particular filter rule on the system."
+    INDEX	{ pfLabelsLblIndex }
+    ::= { pfLabelsLblTable 1 }
+
+pfLabelsLblEntry ::= SEQUENCE {
+    pfLabelsLblIndex		    Integer32,
+    pfLabelsLblName	 	    OCTET STRING,
+    pfLabelsLblEvals		    Counter64,
+    pfLabelsLblBytesIn		    Counter64,
+    pfLabelsLblBytesOut		    Counter64,
+    pfLabelsLblPktsIn		    Counter64,
+    pfLabelsLblPktsOut		    Counter64
+}
+
+pfLabelsLblIndex OBJECT-TYPE
+    SYNTAX	Integer32 (1..2147483647)
+    MAX-ACCESS  not-accessible
+    STATUS	current
+    DESCRIPTION
+        "A unique value, greater than zero, for each label."
+    ::= { pfLabelsLblEntry 1 }
+
+pfLabelsLblName OBJECT-TYPE
+    SYNTAX	OCTET STRING
+    MAX-ACCESS  read-only
+    STATUS	current
+    DESCRIPTION
+        "The name of the rule label."
+    ::= { pfLabelsLblEntry 2 }
+
+pfLabelsLblEvals OBJECT-TYPE
+    SYNTAX	Counter64
+    MAX-ACCESS  read-only
+    STATUS	current
+    DESCRIPTION
+        "The number of rule evaluations."
+    ::= { pfLabelsLblEntry 3 }
+
+pfLabelsLblBytesIn OBJECT-TYPE
+    SYNTAX	Counter64
+    MAX-ACCESS  read-only
+    STATUS	current
+    DESCRIPTION
+        "The number of incoming bytes matched by the rule."
+    ::= { pfLabelsLblEntry 4 }
+
+pfLabelsLblBytesOut OBJECT-TYPE
+    SYNTAX	Counter64
+    MAX-ACCESS  read-only
+    STATUS	current
+    DESCRIPTION
+        "The number of outgoing bytes matched by the rule."
+    ::= { pfLabelsLblEntry 5 }
+
+pfLabelsLblPktsIn OBJECT-TYPE
+    SYNTAX	Counter64
+    MAX-ACCESS  read-only
+    STATUS	current
+    DESCRIPTION
+        "The number of incoming packets matched by the rule."
+    ::= { pfLabelsLblEntry 6 }
+
+pfLabelsLblPktsOut OBJECT-TYPE
+    SYNTAX	Counter64
+    MAX-ACCESS  read-only
+    STATUS	current
+    DESCRIPTION
+        "The number of outgoing packets matched by the rule."
+    ::= { pfLabelsLblEntry 7 }
+
 END
diff -ru snmp_pf.orig/pf_snmp.c snmp_pf/pf_snmp.c
--- snmp_pf.orig/pf_snmp.c	2008-11-25 03:59:29.000000000 +0100
+++ snmp_pf/pf_snmp.c	2009-03-20 09:51:57.000000000 +0100
@@ -100,17 +100,38 @@
 
 #define PFQ_TABLE_MAXAGE	5
 
+struct pfl_entry {
+	char		name[MAXPATHLEN + PF_RULE_LABEL_SIZE];
+	u_int64_t	evals;
+	u_int64_t	bytes[2];
+	u_int64_t	pkts[2];
+	u_int		index;
+	TAILQ_ENTRY(pfl_entry) link;
+};
+TAILQ_HEAD(pfl_table, pfl_entry);
+
+static struct pfl_table pfl_table;
+static time_t pfl_table_age;
+static int pfl_table_count;
+
+#define PFL_TABLE_MAXAGE	5
+
 /* Forward declarations */
 static int pfi_refresh(void);
 static int pfq_refresh(void);
 static int pfs_refresh(void);
 static int pft_refresh(void);
+static int pfl_refresh(void);
 static struct pfi_entry * pfi_table_find(u_int idx);
 static struct pfq_entry * pfq_table_find(u_int idx);
 static struct pft_entry * pft_table_find(u_int idx);
+static struct pfl_entry * pfl_table_find(u_int idx);
 
 static int altq_is_enabled(int pfdevice);
 
+static int pfl_walk_rulesets(const char *path);
+static int pfl_scan_ruleset(const char *path);
+
 int
 pf_status(struct snmp_context __unused *ctx, struct snmp_value *val,
 	u_int sub, u_int __unused vindex, enum snmp_op op)
@@ -773,6 +794,94 @@
 }
 
 int
+pf_labels(struct snmp_context __unused *ctx, struct snmp_value *val,
+	u_int sub, u_int __unused vindex, enum snmp_op op)
+{
+	asn_subid_t	which = val->var.subs[sub - 1];
+
+	if (op == SNMP_OP_SET)
+		return (SNMP_ERR_NOT_WRITEABLE);
+
+	if (op == SNMP_OP_GET) {
+		if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
+			if (pfl_refresh() == -1)
+			    return (SNMP_ERR_GENERR);
+
+		switch (which) {
+			case LEAF_pfLabelsLblNumber:
+				val->v.uint32 = pfl_table_count;
+				break;
+
+			default:
+				return (SNMP_ERR_NOSUCHNAME);
+		}
+
+		return (SNMP_ERR_NOERROR);
+	}
+
+	abort();
+}
+
+int
+pf_lbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
+	u_int sub, u_int __unused vindex, enum snmp_op op)
+{
+	asn_subid_t	which = val->var.subs[sub - 1];
+	struct pfl_entry *e = NULL;
+
+	switch (op) {
+		case SNMP_OP_SET:
+			return (SNMP_ERR_NOT_WRITEABLE);
+		case SNMP_OP_GETNEXT:
+			if ((e = NEXT_OBJECT_INT(&pfl_table,
+			    &val->var, sub)) == NULL)
+				return (SNMP_ERR_NOSUCHNAME);
+			val->var.len = sub + 1;
+			val->var.subs[sub] = e->index;
+			break;
+		case SNMP_OP_GET:
+			if (val->var.len - sub != 1)
+				return (SNMP_ERR_NOSUCHNAME);
+			if ((e = pfl_table_find(val->var.subs[sub])) == NULL)
+				return (SNMP_ERR_NOSUCHNAME);
+			break;
+
+		case SNMP_OP_COMMIT:
+		case SNMP_OP_ROLLBACK:
+		default:
+			abort();
+	}
+
+	if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
+		pfl_refresh();
+
+	switch (which) {
+	        case LEAF_pfLabelsLblName:
+			return (string_get(val, e->name, -1));
+		case LEAF_pfLabelsLblEvals:
+			val->v.counter64 = e->evals;
+			break;
+		case LEAF_pfLabelsLblBytesIn:
+			val->v.counter64 = e->bytes[IN];
+			break;
+		case LEAF_pfLabelsLblBytesOut:
+			val->v.counter64 = e->bytes[OUT];
+			break;
+		case LEAF_pfLabelsLblPktsIn:
+			val->v.counter64 = e->pkts[IN];
+			break;
+		case LEAF_pfLabelsLblPktsOut:
+			val->v.counter64 = e->pkts[OUT];
+			break;
+
+		default:
+			return (SNMP_ERR_NOSUCHNAME);
+	}
+
+	return (SNMP_ERR_NOERROR);
+}
+
+int
 pf_tbladdr(struct snmp_context __unused *ctx, struct snmp_value __unused *val,
 	u_int __unused sub, u_int __unused vindex, enum snmp_op __unused op)
 {
@@ -907,6 +1016,17 @@
 	return (NULL);
 }
 
+static struct pfl_entry *
+pfl_table_find(u_int idx)
+{
+	struct pfl_entry *e;
+
+	TAILQ_FOREACH(e, &pfl_table, link)
+		if (e->index == idx)
+			return (e);
+	return (NULL);
+}
+
 static int
 pfi_refresh(void)
 {
@@ -1129,6 +1249,135 @@
 	return(-1);
 }
 
+static int
+pfl_refresh(void)
+{
+	struct pfl_entry *e;
+
+	if (started && this_tick <= pf_tick)
+		return (0);
+
+	pfl_table_count = 0;
+	while (!TAILQ_EMPTY(&pfl_table)) {
+		e = TAILQ_FIRST(&pfl_table);
+		TAILQ_REMOVE(&pfl_table, e, link);
+		free(e);
+	}
+
+	if (pfl_walk_rulesets(""))
+		goto err;
+
+	pfl_table_age = time(NULL);
+	pf_tick = this_tick;
+
+	return (0);
+
+err:
+	pfl_table_count = 0;
+	while (!TAILQ_EMPTY(&pfl_table)) {
+		e = TAILQ_FIRST(&pfl_table);
+		TAILQ_REMOVE(&pfl_table, e, link);
+		free(e);
+	}
+
+	return (-1);
+}
+
+static int
+pfl_walk_rulesets(const char *path)
+{
+	struct pfioc_ruleset prs;
+	char newpath[MAXPATHLEN];
+	u_int32_t nr, i;
+
+	if (pfl_scan_ruleset(path))
+		goto err;
+
+	bzero(&prs, sizeof(prs));
+	strlcpy(prs.path, path, sizeof(prs.path));
+	if (ioctl(dev, DIOCGETRULESETS, &prs)) {
+		syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESETS): %s",
+		    strerror(errno));
+		goto err;
+	}
+
+	for (nr = prs.nr, i = 0; i < nr; i++) {
+		prs.nr = i;
+		if (ioctl(dev, DIOCGETRULESET, &prs)) {
+			syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESET): %s",
+			    strerror(errno));			
+			goto err;
+		}
+
+                if (!strcmp(prs.name, PF_RESERVED_ANCHOR))
+                        continue;
+
+		strlcpy(newpath, path, sizeof(newpath));
+		if (path[0])
+			strlcat(newpath, "/", sizeof(newpath));
+		strlcat(newpath, prs.name, sizeof(newpath));
+
+		if (pfl_walk_rulesets(newpath))
+			goto err;
+	}
+
+	return (0);
+
+err:
+	return (-1);
+}
+
+static int
+pfl_scan_ruleset(const char *path)
+{
+	struct pfioc_rule pr;
+	struct pfl_entry *e;
+	u_int32_t nr, i;
+
+	bzero(&pr, sizeof(pr));
+	strlcpy(pr.anchor, path, sizeof(pr.anchor));
+	pr.rule.action = PF_PASS;
+	if (ioctl(dev, DIOCGETRULES, &pr)) {
+		syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULES): %s",
+		    strerror(errno));
+		goto err;
+	}
+
+	for (nr = pr.nr, i = 0; i < nr; i++) {
+		pr.nr = i;
+		if (ioctl(dev, DIOCGETRULE, &pr)) {
+			syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULE): %s",
+			    strerror(errno));
+			goto err;
+		}
+
+		if (pr.rule.label[0]) {
+			e = (struct pfl_entry *)malloc(sizeof(*e));
+			if (e == NULL)
+				goto err;
+
+			strlcpy(e->name, path, sizeof(e->name));
+			if (path[0])
+				strlcat(e->name, "/", sizeof(e->name));
+			strlcat(e->name, pr.rule.label, sizeof(e->name));
+
+			e->evals      = pr.rule.evaluations;
+			e->bytes[IN]  = pr.rule.bytes[IN];
+			e->bytes[OUT] = pr.rule.bytes[OUT];
+			e->pkts[IN]   = pr.rule.packets[IN];
+			e->pkts[OUT]  = pr.rule.packets[OUT];
+			e->index      = ++pfl_table_count;
+
+			TAILQ_INSERT_TAIL(&pfl_table, e, link);
+		}
+	}
+
+	return (0);
+
+err:
+	return (-1);
+}
+
 /*
  * check whether altq support is enabled in kernel
  */
@@ -1175,6 +1424,7 @@
 	TAILQ_INIT(&pfi_table);
 	TAILQ_INIT(&pfq_table);
 	TAILQ_INIT(&pft_table);
+	TAILQ_INIT(&pfl_table);
 
 	pfi_refresh();
 	if (altq_enabled) {
@@ -1183,6 +1433,7 @@
 
 	pfs_refresh();
 	pft_refresh();
+	pfl_refresh();
 
 	started = 1;
 
@@ -1195,6 +1446,7 @@
 	struct pfi_entry *i1, *i2;
 	struct pfq_entry *q1, *q2;
 	struct pft_entry *t1, *t2;
+	struct pfl_entry *l1, *l2;
 
 	/* Empty the list of interfaces */
 	i1 = TAILQ_FIRST(&pfi_table);
@@ -1212,7 +1464,7 @@
 		q1 = q2;
 	}
 
-	/* And the list of tables */
+	/* List of tables */
 	t1 = TAILQ_FIRST(&pft_table);
 	while (t1 != NULL) {
 		t2 = TAILQ_NEXT(t1, link);
@@ -1220,6 +1472,14 @@
 		t1 = t2;
 	}
 
+	/* And the list of labeled filter rules */
+	l1 = TAILQ_FIRST(&pfl_table);
+	while (l1 != NULL) {
+		l2 = TAILQ_NEXT(l1, link);
+		free(l1);
+		l1 = l2;
+	}
+
 	close(dev);
 	return (0);
 }
@@ -1232,6 +1492,7 @@
 		pfq_refresh();
 	}
 	pft_refresh();
+	pfl_refresh();
 
 	syslog(LOG_ERR, "Dump: pfi_table_age = %jd",
 	    (intmax_t)pfi_table_age);
@@ -1245,9 +1506,13 @@
 
 	syslog(LOG_ERR, "Dump: pft_table_age = %jd",
 	    (intmax_t)pft_table_age);
-
 	syslog(LOG_ERR, "Dump: pft_table_count = %d",
 	    pft_table_count);
+
+	syslog(LOG_ERR, "Dump: pfl_table_age = %jd",
+	    (intmax_t)pfl_table_age);
+	syslog(LOG_ERR, "Dump: pfl_table_count = %d",
+	    pfl_table_count);
 }
 
 const struct snmp_module config = {
diff -ru snmp_pf.orig/pf_tree.def snmp_pf/pf_tree.def
--- snmp_pf.orig/pf_tree.def	2009-01-10 16:46:38.000000000 +0100
+++ snmp_pf/pf_tree.def	2009-03-18 09:54:20.000000000 +0100
@@ -186,6 +186,20 @@
 		  )
 		)
 	      )
+	      (11 pfLabels
+	        (1 pfLabelsLblNumber INTEGER32 pf_labels GET)
+		(2 pfLabelsLblTable
+		  (1 pfLabelsLblEntry : INTEGER32 pf_lbltable
+		    (1 pfLabelsLblIndex INTEGER32)
+		    (2 pfLabelsLblName OCTETSTRING GET)
+		    (3 pfLabelsLblEvals COUNTER64 GET)
+		    (4 pfLabelsLblBytesIn COUNTER64 GET)
+		    (5 pfLabelsLblBytesOut COUNTER64 GET)
+		    (6 pfLabelsLblPktsIn COUNTER64 GET)
+		    (7 pfLabelsLblPktsOut COUNTER64 GET)
+		  )
+		)
+	      )
             )
           )
         )
--- snmp_pf.diff ends here ---
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Fri Mar 20 19:08:48 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=132847 
Responsible-Changed-From-To: freebsd-net->syrinx 
Responsible-Changed-By: bz 
Responsible-Changed-When: Sat Mar 21 13:42:37 UTC 2009 
Responsible-Changed-Why:  
She'll review and test it in a few days she said. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=132847 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/132847: commit references a PR
Date: Thu, 18 Mar 2010 14:54:44 +0000 (UTC)

 Author: syrinx
 Date: Thu Mar 18 14:54:31 2010
 New Revision: 205280
 URL: http://svn.freebsd.org/changeset/base/205280
 
 Log:
   Add support for retrieving labeled pf filter rule counters.
   
   PR:		bin/132847
   Submitted by:	Szalai Andras <szalai (dot) bandi (at) gmail.com>
 
 Modified:
   head/usr.sbin/bsnmpd/modules/snmp_pf/BEGEMOT-PF-MIB.txt
   head/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c
   head/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def
 
 Modified: head/usr.sbin/bsnmpd/modules/snmp_pf/BEGEMOT-PF-MIB.txt
 ==============================================================================
 --- head/usr.sbin/bsnmpd/modules/snmp_pf/BEGEMOT-PF-MIB.txt	Thu Mar 18 13:11:43 2010	(r205279)
 +++ head/usr.sbin/bsnmpd/modules/snmp_pf/BEGEMOT-PF-MIB.txt	Thu Mar 18 14:54:31 2010	(r205280)
 @@ -21,7 +21,7 @@ IMPORTS
  	FROM BEGEMOT-MIB;
  
  begemotPf MODULE-IDENTITY
 -    LAST-UPDATED "200501240000Z"
 +    LAST-UPDATED "201003170000Z"
      ORGANIZATION "NixSys BVBA"
      CONTACT-INFO
  	    "		Philip Paeps
 @@ -34,6 +34,13 @@ begemotPf MODULE-IDENTITY
  	     E-Mail:	philip@FreeBSD.org"
      DESCRIPTION
  	    "The Begemot MIB for the pf packet filter."
 +    REVISION	"200912050000Z"
 +    DESCRIPTION
 +	    "Added support for retrieving counters of labeled
 +	    pf filter rules via pfLabelspfLabels subtree."
 +    REVISION	"200501240000Z"
 +    DESCRIPTION
 +	    "Initial revision."
  
      ::= { begemot 200 }
  
 @@ -51,6 +58,7 @@ pfLogInterface		OBJECT IDENTIFIER ::= { 
  pfInterfaces		OBJECT IDENTIFIER ::= { begemotPfObjects 8 }
  pfTables		OBJECT IDENTIFIER ::= { begemotPfObjects 9 }
  pfAltq			OBJECT IDENTIFIER ::= { begemotPfObjects 10 }
 +pfLabels		OBJECT IDENTIFIER ::= { begemotPfObjects 11 }
  
  -- --------------------------------------------------------------------------
  
 @@ -1227,4 +1235,96 @@ pfAltqQueueLimit OBJECT-TYPE
  	"Maximum number of packets in the queue."
      ::= { pfAltqQueueEntry 7 }
  
 +pfLabelsLblNumber OBJECT-TYPE
 +    SYNTAX	Integer32
 +    MAX-ACCESS	read-only
 +    STATUS	current
 +    DESCRIPTION
 +	"The number of labeled filter rules on this system."
 +    ::= { pfLabels 1 }
 +
 +pfLabelsLblTable OBJECT-TYPE
 +    SYNTAX	SEQUENCE OF PfLabelsLblEntry
 +    MAX-ACCESS	not-accessible
 +    STATUS	current
 +    DESCRIPTION
 +	"Table of filter rules, index on pfLabelsLblIndex."
 +    ::= { pfLabels 2 }
 +
 +pfLabelsLblEntry OBJECT-TYPE
 +    SYNTAX	PfLabelsLblEntry
 +    MAX-ACCESS	not-accessible
 +    STATUS	current
 +    DESCRIPTION
 +	"Any entry in the pfLabelsLblTable containing information
 +	about a particular filter rule on the system."
 +    INDEX	{ pfLabelsLblIndex }
 +    ::= { pfLabelsLblTable 1 }
 +
 +PfLabelsLblEntry ::= SEQUENCE {
 +    pfLabelsLblIndex		Integer32,
 +    pfLabelsLblName		OCTET STRING,
 +    pfLabelsLblEvals		Counter64,
 +    pfLabelsLblBytesIn		Counter64,
 +    pfLabelsLblBytesOut		Counter64,
 +    pfLabelsLblPktsIn		Counter64,
 +    pfLabelsLblPktsOut		Counter64
 +}
 +
 +pfLabelsLblIndex OBJECT-TYPE
 +    SYNTAX	Integer32 (1..2147483647)
 +    MAX-ACCESS	not-accessible
 +    STATUS	current
 +    DESCRIPTION
 +	"A unique value, greater than zero, for each label."
 +    ::= { pfLabelsLblEntry 1 } 
 +
 +pfLabelsLblName OBJECT-TYPE
 +    SYNTAX	OCTET STRING
 +    MAX-ACCESS	read-only
 +    STATUS	current
 +    DESCRIPTION
 +	"The name of the rule label."
 +    ::= { pfLabelsLblEntry 2 }
 +
 +pfLabelsLblEvals OBJECT-TYPE
 +    SYNTAX	Counter64
 +    MAX-ACCESS	read-only
 +    STATUS	current
 +    DESCRIPTION
 +	"The number of rule evaluations."
 +    ::= { pfLabelsLblEntry 3 }
 +
 +pfLabelsLblBytesIn OBJECT-TYPE
 +    SYNTAX	Counter64
 +    MAX-ACCESS	read-only
 +    STATUS	current
 +    DESCRIPTION
 +	"The number of incoming bytes matched by the rule."
 +    ::= { pfLabelsLblEntry 4 }
 +
 +pfLabelsLblBytesOut OBJECT-TYPE
 +    SYNTAX	Counter64
 +    MAX-ACCESS	read-only
 +    STATUS	current
 +    DESCRIPTION
 +	"The number of outgoing bytes matched by the rule."
 +    ::= { pfLabelsLblEntry 5 }
 +
 +pfLabelsLblPktsIn OBJECT-TYPE
 +    SYNTAX	Counter64
 +    MAX-ACCESS	read-only
 +    STATUS	current
 +    DESCRIPTION
 +	"The number of incoming packets matched by the rule."
 +    ::= { pfLabelsLblEntry 6 }
 +
 +pfLabelsLblPktsOut OBJECT-TYPE
 +    SYNTAX	Counter64
 +    MAX-ACCESS	read-only
 +    STATUS	current
 +    DESCRIPTION
 +	"The number of outgoing packets matched by the rule."
 +    ::= { pfLabelsLblEntry 7 }
 +
  END
 
 Modified: head/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c
 ==============================================================================
 --- head/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c	Thu Mar 18 13:11:43 2010	(r205279)
 +++ head/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c	Thu Mar 18 14:54:31 2010	(r205280)
 @@ -100,14 +100,32 @@ static int altq_enabled = 0;
  
  #define PFQ_TABLE_MAXAGE	5
  
 +struct pfl_entry {
 +	char		name[MAXPATHLEN + PF_RULE_LABEL_SIZE];
 +	u_int64_t	evals;
 +	u_int64_t	bytes[2];
 +	u_int64_t	pkts[2];
 +	u_int		index;
 +	TAILQ_ENTRY(pfl_entry) link;
 +};
 +TAILQ_HEAD(pfl_table, pfl_entry);
 +
 +static struct pfl_table pfl_table;
 +static time_t pfl_table_age;
 +static int pfl_table_count;
 +
 +#define	PFL_TABLE_MAXAGE	5
 +
  /* Forward declarations */
  static int pfi_refresh(void);
  static int pfq_refresh(void);
  static int pfs_refresh(void);
  static int pft_refresh(void);
 +static int pfl_refresh(void);
  static struct pfi_entry * pfi_table_find(u_int idx);
  static struct pfq_entry * pfq_table_find(u_int idx);
  static struct pft_entry * pft_table_find(u_int idx);
 +static struct pfl_entry * pfl_table_find(u_int idx);
  
  static int altq_is_enabled(int pfdevice);
  
 @@ -873,7 +891,95 @@ pf_altqq(struct snmp_context __unused *c
  	}
  
  	return (SNMP_ERR_NOERROR);
 -}	
 +}
 +
 +int
 +pf_labels(struct snmp_context __unused *ctx, struct snmp_value *val,
 +	u_int sub, u_int __unused vindex, enum snmp_op op)
 +{
 +	asn_subid_t	which = val->var.subs[sub - 1];
 +
 +	if (op == SNMP_OP_SET)
 +		return (SNMP_ERR_NOT_WRITEABLE);
 +
 +	if (op == SNMP_OP_GET) {
 +		if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
 +			if (pfl_refresh() == -1)
 +				return (SNMP_ERR_GENERR);
 +
 +		switch (which) {
 +			case LEAF_pfLabelsLblNumber:
 +				val->v.uint32 = pfl_table_count;
 +				break;
 +
 +			default:
 +				return (SNMP_ERR_NOSUCHNAME);
 +		}
 +
 +		return (SNMP_ERR_NOERROR);
 +	}
 +
 +	abort();
 +	return (SNMP_ERR_GENERR);
 +}
 +
 +int
 +pf_lbltable(struct snmp_context __unused *ctx, struct snmp_value *val,
 +	u_int sub, u_int __unused vindex, enum snmp_op op)
 +{
 +	asn_subid_t	which = val->var.subs[sub - 1];
 +	struct pfl_entry *e = NULL;
 +
 +	switch (op) {
 +		case SNMP_OP_SET:
 +			return (SNMP_ERR_NOT_WRITEABLE);
 +		case SNMP_OP_GETNEXT:
 +			if ((e = NEXT_OBJECT_INT(&pfl_table,
 +			    &val->var, sub)) == NULL)
 +				return (SNMP_ERR_NOSUCHNAME);
 +			val->var.len = sub + 1;
 +			val->var.subs[sub] = e->index;
 +			break;
 +		case SNMP_OP_GET:
 +			if (val->var.len - sub != 1)
 +				return (SNMP_ERR_NOSUCHNAME);
 +			if ((e = pfl_table_find(val->var.subs[sub])) == NULL)
 +				return (SNMP_ERR_NOSUCHNAME);
 +			break;
 +
 +		case SNMP_OP_COMMIT:
 +		case SNMP_OP_ROLLBACK:
 +		default:
 +			abort();
 +	}
 +
 +	if ((time(NULL) - pfl_table_age) > PFL_TABLE_MAXAGE)
 +		pfl_refresh();
 +
 +	switch (which) {
 +		case LEAF_pfLabelsLblName:
 +			return (string_get(val, e->name, -1));
 +		case LEAF_pfLabelsLblEvals:
 +			val->v.counter64 = e->evals;
 +			break;
 +		case LEAF_pfLabelsLblBytesIn:
 +			val->v.counter64 = e->bytes[IN];
 +			break;
 +		case LEAF_pfLabelsLblBytesOut:
 +			val->v.counter64 = e->bytes[OUT];
 +			break;
 +		case LEAF_pfLabelsLblPktsIn:
 +			val->v.counter64 = e->pkts[IN];
 +			break;
 +		case LEAF_pfLabelsLblPktsOut:
 +			val->v.counter64 = e->pkts[OUT];
 +			break;
 +		default:
 +			return (SNMP_ERR_NOSUCHNAME);
 +	}
 +
 +	return (SNMP_ERR_NOERROR);
 +}
  
  static struct pfi_entry *
  pfi_table_find(u_int idx)
 @@ -890,6 +996,7 @@ static struct pfq_entry *
  pfq_table_find(u_int idx)
  {
  	struct pfq_entry *e;
 +
  	TAILQ_FOREACH(e, &pfq_table, link)
  		if (e->index == idx)
  			return (e);
 @@ -907,6 +1014,18 @@ pft_table_find(u_int idx)
  	return (NULL);
  }
  
 +static struct pfl_entry *
 +pfl_table_find(u_int idx)
 +{
 +	struct pfl_entry *e;
 +
 +	TAILQ_FOREACH(e, &pfl_table, link)
 +		if (e->index == idx)
 +			return (e);
 +
 +	return (NULL);
 +}
 +
  static int
  pfi_refresh(void)
  {
 @@ -1129,6 +1248,135 @@ err2:
  	return(-1);
  }
  
 +static int
 +pfl_scan_ruleset(const char *path)
 +{
 +	struct pfioc_rule pr;
 +	struct pfl_entry *e;
 +	u_int32_t nr, i;
 +
 +	bzero(&pr, sizeof(pr));
 +	strlcpy(pr.anchor, path, sizeof(pr.anchor));
 +	pr.rule.action = PF_PASS;
 +	if (ioctl(dev, DIOCGETRULES, &pr)) {
 +		syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULES): %s",
 +		    strerror(errno));
 +		goto err;
 +	}
 +
 +	for (nr = pr.nr, i = 0; i < nr; i++) {
 +		pr.nr = i;
 +		if (ioctl(dev, DIOCGETRULE, &pr)) {
 +			syslog(LOG_ERR, "pfl_scan_ruleset: ioctl(DIOCGETRULE):"
 +			    " %s", strerror(errno));
 +			goto err;
 +		}
 +
 +		if (pr.rule.label[0]) {
 +			e = (struct pfl_entry *)malloc(sizeof(*e));
 +			if (e == NULL)
 +				goto err;
 +
 +			strlcpy(e->name, path, sizeof(e->name));
 +			if (path[0])
 +				strlcat(e->name, "/", sizeof(e->name));
 +			strlcat(e->name, pr.rule.label, sizeof(e->name));
 +
 +			e->evals = pr.rule.evaluations;
 +			e->bytes[IN] = pr.rule.bytes[IN];
 +			e->bytes[OUT] = pr.rule.bytes[OUT];
 +			e->pkts[IN] = pr.rule.packets[IN];
 +			e->pkts[OUT] = pr.rule.packets[OUT];
 +			e->index = ++pfl_table_count;
 +
 +			TAILQ_INSERT_TAIL(&pfl_table, e, link);
 +		}
 +	}
 +
 +	return (0);
 +
 +err:
 +	return (-1);
 +}
 +
 +static int
 +pfl_walk_rulesets(const char *path)
 +{
 +	struct pfioc_ruleset prs;
 +	char newpath[MAXPATHLEN];
 +	u_int32_t nr, i;
 +
 +	if (pfl_scan_ruleset(path))
 +		goto err;
 +
 +	bzero(&prs, sizeof(prs));
 +	strlcpy(prs.path, path, sizeof(prs.path));
 +	if (ioctl(dev, DIOCGETRULESETS, &prs)) {
 +		syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESETS): %s",
 +		    strerror(errno));
 +		goto err;
 +	}
 +
 +	for (nr = prs.nr, i = 0; i < nr; i++) {
 +		prs.nr = i;
 +		if (ioctl(dev, DIOCGETRULESET, &prs)) {
 +			syslog(LOG_ERR, "pfl_walk_rulesets: ioctl(DIOCGETRULESET):"
 +			    " %s", strerror(errno));
 +			goto err;
 +		}
 +
 +		if (strcmp(prs.name, PF_RESERVED_ANCHOR) == 0)
 +			continue;
 +
 +		strlcpy(newpath, path, sizeof(newpath));
 +		if (path[0])
 +			strlcat(newpath, "/", sizeof(newpath));
 +
 +		strlcat(newpath, prs.name, sizeof(newpath));
 +		if (pfl_walk_rulesets(newpath))
 +			goto err;
 +	}
 +
 +	return (0);
 +
 +err:
 +	return (-1);
 +}
 +
 +static int
 +pfl_refresh(void)
 +{
 +	struct pfl_entry *e;
 +
 +	if (started && this_tick <= pf_tick)
 +		return (0);
 +
 +	while (!TAILQ_EMPTY(&pfl_table)) {
 +		e = TAILQ_FIRST(&pfl_table);
 +		TAILQ_REMOVE(&pfl_table, e, link);
 +		free(e);
 +	}
 +	pfl_table_count = 0;
 +
 +	if (pfl_walk_rulesets(""))
 +		goto err;
 +
 +	pfl_table_age = time(NULL);
 +	pf_tick = this_tick;
 +
 +	return (0);
 +
 +err:
 +	while (!TAILQ_EMPTY(&pfl_table)) {
 +		e = TAILQ_FIRST(&pfl_table);
 +		TAILQ_REMOVE(&pfl_table, e, link);
 +		free(e);
 +	}
 +	pfl_table_count = 0;
 +
 +	return (-1);
 +}
 +
  /*
   * check whether altq support is enabled in kernel
   */
 @@ -1175,6 +1423,7 @@ pf_init(struct lmodule *mod, int __unuse
  	TAILQ_INIT(&pfi_table);
  	TAILQ_INIT(&pfq_table);
  	TAILQ_INIT(&pft_table);
 +	TAILQ_INIT(&pfl_table);
  
  	pfi_refresh();
  	if (altq_enabled) {
 @@ -1183,6 +1432,7 @@ pf_init(struct lmodule *mod, int __unuse
  
  	pfs_refresh();
  	pft_refresh();
 +	pfl_refresh();
  
  	started = 1;
  
 @@ -1195,6 +1445,7 @@ pf_fini(void)
  	struct pfi_entry *i1, *i2;
  	struct pfq_entry *q1, *q2;
  	struct pft_entry *t1, *t2;
 +	struct pfl_entry *l1, *l2;
  
  	/* Empty the list of interfaces */
  	i1 = TAILQ_FIRST(&pfi_table);
 @@ -1212,7 +1463,7 @@ pf_fini(void)
  		q1 = q2;
  	}
  
 -	/* And the list of tables */
 +	/* List of tables */
  	t1 = TAILQ_FIRST(&pft_table);
  	while (t1 != NULL) {
  		t2 = TAILQ_NEXT(t1, link);
 @@ -1220,6 +1471,14 @@ pf_fini(void)
  		t1 = t2;
  	}
  
 +	/* And the list of labeled filter rules */
 +	l1 = TAILQ_FIRST(&pfl_table);
 +	while (l1 != NULL) {
 +		l2 = TAILQ_NEXT(l1, link);
 +		free(l1);
 +		l1 = l2;
 +	}
 +
  	close(dev);
  	return (0);
  }
 @@ -1232,6 +1491,7 @@ pf_dump(void)
  		pfq_refresh();
  	}
  	pft_refresh();
 +	pfl_refresh();
  
  	syslog(LOG_ERR, "Dump: pfi_table_age = %jd",
  	    (intmax_t)pfi_table_age);
 @@ -1245,9 +1505,13 @@ pf_dump(void)
  
  	syslog(LOG_ERR, "Dump: pft_table_age = %jd",
  	    (intmax_t)pft_table_age);
 -
  	syslog(LOG_ERR, "Dump: pft_table_count = %d",
  	    pft_table_count);
 +
 +	syslog(LOG_ERR, "Dump: pfl_table_age = %jd",
 +	    (intmax_t)pfl_table_age);
 +	syslog(LOG_ERR, "Dump: pfl_table_count = %d",
 +	    pfl_table_count);
  }
  
  const struct snmp_module config = {
 
 Modified: head/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def
 ==============================================================================
 --- head/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def	Thu Mar 18 13:11:43 2010	(r205279)
 +++ head/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def	Thu Mar 18 14:54:31 2010	(r205280)
 @@ -186,6 +186,20 @@
  		  )
  		)
  	      )
 +	      (11 pfLabels
 +		(1 pfLabelsLblNumber INTEGER32 pf_labels GET)
 +		(2 pfLabelsLblTable
 +		  (1 pfLabelsLblEntry : INTEGER pf_lbltable
 +		    (1 pfLabelsLblIndex INTEGER)
 +		    (2 pfLabelsLblName OCTETSTRING GET)
 +		    (3 pfLabelsLblEvals COUNTER64 GET)
 +		    (4 pfLabelsLblBytesIn COUNTER64 GET)
 +		    (5 pfLabelsLblBytesOut COUNTER64 GET)
 +		    (6 pfLabelsLblPktsIn COUNTER64 GET)
 +		    (7 pfLabelsLblPktsOut COUNTER64 GET)
 +		  )
 +		)
 +	      )
              )
            )
          )
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: syrinx 
State-Changed-When: Thu Mar 18 17:30:39 UTC 2010 
State-Changed-Why:  
Patch committed to current. Thanks for submitting! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=132847 
>Unformatted:
