summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorsyrinx <syrinx@FreeBSD.org>2010-03-18 14:54:31 +0000
committersyrinx <syrinx@FreeBSD.org>2010-03-18 14:54:31 +0000
commit52f973a7e829d3e3dc4f048eed00f3910c6f9256 (patch)
tree2f22b0b58ffddd2e45bea39cae4f8f14eff86bc7 /usr.sbin
parentcf2b4e13961ec4a3a2103497e3d9111d8a7cc252 (diff)
downloadFreeBSD-src-52f973a7e829d3e3dc4f048eed00f3910c6f9256.zip
FreeBSD-src-52f973a7e829d3e3dc4f048eed00f3910c6f9256.tar.gz
Add support for retrieving labeled pf filter rule counters.
PR: bin/132847 Submitted by: Szalai Andras <szalai (dot) bandi (at) gmail.com>
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_pf/BEGEMOT-PF-MIB.txt102
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c270
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def14
3 files changed, 382 insertions, 4 deletions
diff --git a/usr.sbin/bsnmpd/modules/snmp_pf/BEGEMOT-PF-MIB.txt b/usr.sbin/bsnmpd/modules/snmp_pf/BEGEMOT-PF-MIB.txt
index 72ebdb7..5f395f8 100644
--- a/usr.sbin/bsnmpd/modules/snmp_pf/BEGEMOT-PF-MIB.txt
+++ b/usr.sbin/bsnmpd/modules/snmp_pf/BEGEMOT-PF-MIB.txt
@@ -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 ::= { begemotPfObjects 7 }
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
diff --git a/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c b/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c
index 4e554c0..56c2cda 100644
--- a/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c
+++ b/usr.sbin/bsnmpd/modules/snmp_pf/pf_snmp.c
@@ -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 *ctx, struct snmp_value *val,
}
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 __unused argc, char __unused *argv[])
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 __unused argc, char __unused *argv[])
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 = {
diff --git a/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def b/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def
index 003a3ec..f7833eb 100644
--- a/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def
+++ b/usr.sbin/bsnmpd/modules/snmp_pf/pf_tree.def
@@ -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)
+ )
+ )
+ )
)
)
)
OpenPOWER on IntegriCloud