Add support for retrieving labeled pf filter rule counters.

PR:		bin/132847
Submitted by:	Szalai Andras <szalai (dot) bandi (at) gmail.com>
This commit is contained in:
Shteryana Shopova 2010-03-18 14:54:31 +00:00
parent b0990a1dae
commit 72d420c708
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=205280
3 changed files with 382 additions and 4 deletions

View File

@ -21,7 +21,7 @@ IMPORTS
FROM BEGEMOT-MIB; FROM BEGEMOT-MIB;
begemotPf MODULE-IDENTITY begemotPf MODULE-IDENTITY
LAST-UPDATED "200501240000Z" LAST-UPDATED "201003170000Z"
ORGANIZATION "NixSys BVBA" ORGANIZATION "NixSys BVBA"
CONTACT-INFO CONTACT-INFO
" Philip Paeps " Philip Paeps
@ -34,6 +34,13 @@ begemotPf MODULE-IDENTITY
E-Mail: philip@FreeBSD.org" E-Mail: philip@FreeBSD.org"
DESCRIPTION DESCRIPTION
"The Begemot MIB for the pf packet filter." "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 } ::= { begemot 200 }
@ -51,6 +58,7 @@ pfLogInterface OBJECT IDENTIFIER ::= { begemotPfObjects 7 }
pfInterfaces OBJECT IDENTIFIER ::= { begemotPfObjects 8 } pfInterfaces OBJECT IDENTIFIER ::= { begemotPfObjects 8 }
pfTables OBJECT IDENTIFIER ::= { begemotPfObjects 9 } pfTables OBJECT IDENTIFIER ::= { begemotPfObjects 9 }
pfAltq OBJECT IDENTIFIER ::= { begemotPfObjects 10 } pfAltq OBJECT IDENTIFIER ::= { begemotPfObjects 10 }
pfLabels OBJECT IDENTIFIER ::= { begemotPfObjects 11 }
-- -------------------------------------------------------------------------- -- --------------------------------------------------------------------------
@ -1227,4 +1235,96 @@ pfAltqQueueLimit OBJECT-TYPE
"Maximum number of packets in the queue." "Maximum number of packets in the queue."
::= { pfAltqQueueEntry 7 } ::= { 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 END

View File

@ -100,14 +100,32 @@ static int altq_enabled = 0;
#define PFQ_TABLE_MAXAGE 5 #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 */ /* Forward declarations */
static int pfi_refresh(void); static int pfi_refresh(void);
static int pfq_refresh(void); static int pfq_refresh(void);
static int pfs_refresh(void); static int pfs_refresh(void);
static int pft_refresh(void); static int pft_refresh(void);
static int pfl_refresh(void);
static struct pfi_entry * pfi_table_find(u_int idx); static struct pfi_entry * pfi_table_find(u_int idx);
static struct pfq_entry * pfq_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 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 altq_is_enabled(int pfdevice);
@ -873,7 +891,95 @@ pf_altqq(struct snmp_context __unused *ctx, struct snmp_value *val,
} }
return (SNMP_ERR_NOERROR); 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 * static struct pfi_entry *
pfi_table_find(u_int idx) pfi_table_find(u_int idx)
@ -890,6 +996,7 @@ static struct pfq_entry *
pfq_table_find(u_int idx) pfq_table_find(u_int idx)
{ {
struct pfq_entry *e; struct pfq_entry *e;
TAILQ_FOREACH(e, &pfq_table, link) TAILQ_FOREACH(e, &pfq_table, link)
if (e->index == idx) if (e->index == idx)
return (e); return (e);
@ -907,6 +1014,18 @@ pft_table_find(u_int idx)
return (NULL); 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 static int
pfi_refresh(void) pfi_refresh(void)
{ {
@ -1129,6 +1248,135 @@ pft_refresh(void)
return(-1); 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 * 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(&pfi_table);
TAILQ_INIT(&pfq_table); TAILQ_INIT(&pfq_table);
TAILQ_INIT(&pft_table); TAILQ_INIT(&pft_table);
TAILQ_INIT(&pfl_table);
pfi_refresh(); pfi_refresh();
if (altq_enabled) { if (altq_enabled) {
@ -1183,6 +1432,7 @@ pf_init(struct lmodule *mod, int __unused argc, char __unused *argv[])
pfs_refresh(); pfs_refresh();
pft_refresh(); pft_refresh();
pfl_refresh();
started = 1; started = 1;
@ -1195,6 +1445,7 @@ pf_fini(void)
struct pfi_entry *i1, *i2; struct pfi_entry *i1, *i2;
struct pfq_entry *q1, *q2; struct pfq_entry *q1, *q2;
struct pft_entry *t1, *t2; struct pft_entry *t1, *t2;
struct pfl_entry *l1, *l2;
/* Empty the list of interfaces */ /* Empty the list of interfaces */
i1 = TAILQ_FIRST(&pfi_table); i1 = TAILQ_FIRST(&pfi_table);
@ -1212,7 +1463,7 @@ pf_fini(void)
q1 = q2; q1 = q2;
} }
/* And the list of tables */ /* List of tables */
t1 = TAILQ_FIRST(&pft_table); t1 = TAILQ_FIRST(&pft_table);
while (t1 != NULL) { while (t1 != NULL) {
t2 = TAILQ_NEXT(t1, link); t2 = TAILQ_NEXT(t1, link);
@ -1220,6 +1471,14 @@ pf_fini(void)
t1 = t2; 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); close(dev);
return (0); return (0);
} }
@ -1232,6 +1491,7 @@ pf_dump(void)
pfq_refresh(); pfq_refresh();
} }
pft_refresh(); pft_refresh();
pfl_refresh();
syslog(LOG_ERR, "Dump: pfi_table_age = %jd", syslog(LOG_ERR, "Dump: pfi_table_age = %jd",
(intmax_t)pfi_table_age); (intmax_t)pfi_table_age);
@ -1245,9 +1505,13 @@ pf_dump(void)
syslog(LOG_ERR, "Dump: pft_table_age = %jd", syslog(LOG_ERR, "Dump: pft_table_age = %jd",
(intmax_t)pft_table_age); (intmax_t)pft_table_age);
syslog(LOG_ERR, "Dump: pft_table_count = %d", syslog(LOG_ERR, "Dump: pft_table_count = %d",
pft_table_count); 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 = { const struct snmp_module config = {

View File

@ -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)
)
)
)
) )
) )
) )