mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-13 05:41:26 +01:00
pf: migrate DIOCGETLIMIT/DIOCSETLIMIT to netlink
Event: Kitchener-Waterloo Hackathon 202406
This commit is contained in:
parent
ea6d6addc9
commit
d9ab899931
@ -2213,7 +2213,7 @@ pfctl_clear_eth_rules(int dev, const char *anchorname)
|
||||
}
|
||||
|
||||
static int
|
||||
pfctl_get_limit(int dev, const int index, uint *limit)
|
||||
_pfctl_get_limit(int dev, const int index, uint *limit)
|
||||
{
|
||||
struct pfioc_limit pl;
|
||||
|
||||
@ -2237,7 +2237,7 @@ pfctl_set_syncookies(int dev, const struct pfctl_syncookies *s)
|
||||
uint state_limit;
|
||||
uint64_t lim, hi, lo;
|
||||
|
||||
ret = pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit);
|
||||
ret = _pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
@ -2274,7 +2274,7 @@ pfctl_get_syncookies(int dev, struct pfctl_syncookies *s)
|
||||
uint state_limit;
|
||||
bool enabled, adaptive;
|
||||
|
||||
ret = pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit);
|
||||
ret = _pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
@ -2606,3 +2606,85 @@ pfctl_get_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t *seconds)
|
||||
return (e.error);
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_limit(struct pfctl_handle *h, const int index, const uint limit)
|
||||
{
|
||||
struct snl_writer nw;
|
||||
struct snl_errmsg_data e = {};
|
||||
struct nlmsghdr *hdr;
|
||||
uint32_t seq_id;
|
||||
int family_id;
|
||||
|
||||
family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
|
||||
if (family_id == 0)
|
||||
return (ENOTSUP);
|
||||
|
||||
snl_init_writer(&h->ss, &nw);
|
||||
hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_SET_LIMIT);
|
||||
|
||||
snl_add_msg_attr_u32(&nw, PF_LI_INDEX, index);
|
||||
snl_add_msg_attr_u32(&nw, PF_LI_LIMIT, limit);
|
||||
|
||||
if ((hdr = snl_finalize_msg(&nw)) == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
seq_id = hdr->nlmsg_seq;
|
||||
|
||||
if (! snl_send_message(&h->ss, hdr))
|
||||
return (ENXIO);
|
||||
|
||||
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
|
||||
}
|
||||
|
||||
return (e.error);
|
||||
}
|
||||
|
||||
struct pfctl_nl_limit {
|
||||
unsigned int limit;
|
||||
};
|
||||
#define _OUT(_field) offsetof(struct pfctl_nl_limit, _field)
|
||||
static struct snl_attr_parser ap_get_limit[] = {
|
||||
{ .type = PF_LI_LIMIT, .off = _OUT(limit), .cb = snl_attr_get_uint32 },
|
||||
};
|
||||
static struct snl_field_parser fp_get_limit[] = {};
|
||||
#undef _OUT
|
||||
SNL_DECLARE_PARSER(get_limit_parser, struct genlmsghdr, fp_get_limit, ap_get_limit);
|
||||
|
||||
int
|
||||
pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit)
|
||||
{
|
||||
struct snl_writer nw;
|
||||
struct pfctl_nl_limit li = {};
|
||||
struct snl_errmsg_data e = {};
|
||||
struct nlmsghdr *hdr;
|
||||
uint32_t seq_id;
|
||||
int family_id;
|
||||
|
||||
family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
|
||||
if (family_id == 0)
|
||||
return (ENOTSUP);
|
||||
|
||||
snl_init_writer(&h->ss, &nw);
|
||||
hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GET_LIMIT);
|
||||
hdr->nlmsg_flags |= NLM_F_DUMP;
|
||||
|
||||
snl_add_msg_attr_u32(&nw, PF_LI_INDEX, index);
|
||||
|
||||
if ((hdr = snl_finalize_msg(&nw)) == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
seq_id = hdr->nlmsg_seq;
|
||||
|
||||
if (! snl_send_message(&h->ss, hdr))
|
||||
return (ENXIO);
|
||||
|
||||
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
|
||||
if (! snl_parse_nlmsg(&h->ss, hdr, &get_limit_parser, &li))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (limit != NULL)
|
||||
*limit = li.limit;
|
||||
|
||||
return (e.error);
|
||||
}
|
||||
|
@ -495,5 +495,7 @@ int pfctl_natlook(struct pfctl_handle *h,
|
||||
int pfctl_set_debug(struct pfctl_handle *h, uint32_t level);
|
||||
int pfctl_set_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t seconds);
|
||||
int pfctl_get_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t *seconds);
|
||||
int pfctl_set_limit(struct pfctl_handle *h, const int index, const uint limit);
|
||||
int pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit);
|
||||
|
||||
#endif
|
||||
|
@ -5198,7 +5198,7 @@ limit_spec : STRING NUMBER
|
||||
yyerror("only positive values permitted");
|
||||
YYERROR;
|
||||
}
|
||||
if (pfctl_set_limit(pf, $1, $2) != 0) {
|
||||
if (pfctl_apply_limit(pf, $1, $2) != 0) {
|
||||
yyerror("unable to set limit %s %u", $1, $2);
|
||||
free($1);
|
||||
YYERROR;
|
||||
|
@ -1679,21 +1679,19 @@ pfctl_show_timeouts(int dev, int opts)
|
||||
int
|
||||
pfctl_show_limits(int dev, int opts)
|
||||
{
|
||||
struct pfioc_limit pl;
|
||||
unsigned int limit;
|
||||
int i;
|
||||
|
||||
if (opts & PF_OPT_SHOWALL)
|
||||
pfctl_print_title("LIMITS:");
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
for (i = 0; pf_limits[i].name; i++) {
|
||||
pl.index = pf_limits[i].index;
|
||||
if (ioctl(dev, DIOCGETLIMIT, &pl))
|
||||
if (pfctl_get_limit(pfh, pf_limits[i].index, &limit))
|
||||
err(1, "DIOCGETLIMIT");
|
||||
printf("%-13s ", pf_limits[i].name);
|
||||
if (pl.limit == UINT_MAX)
|
||||
if (limit == UINT_MAX)
|
||||
printf("unlimited\n");
|
||||
else
|
||||
printf("hard limit %8u\n", pl.limit);
|
||||
printf("hard limit %8u\n", limit);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@ -2425,7 +2423,7 @@ pfctl_load_options(struct pfctl *pf)
|
||||
}
|
||||
|
||||
int
|
||||
pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
|
||||
pfctl_apply_limit(struct pfctl *pf, const char *opt, unsigned int limit)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -2451,12 +2449,7 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
|
||||
int
|
||||
pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit)
|
||||
{
|
||||
struct pfioc_limit pl;
|
||||
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
pl.index = index;
|
||||
pl.limit = limit;
|
||||
if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
|
||||
if (pfctl_set_limit(pf->h, index, limit)) {
|
||||
if (errno == EBUSY)
|
||||
warnx("Current pool size exceeds requested hard limit");
|
||||
else
|
||||
|
@ -288,7 +288,7 @@ void pfctl_clear_pool(struct pfctl_pool *);
|
||||
int pfctl_apply_timeout(struct pfctl *, const char *, int, int);
|
||||
int pfctl_set_reassembly(struct pfctl *, int, int);
|
||||
int pfctl_set_optimization(struct pfctl *, const char *);
|
||||
int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
|
||||
int pfctl_apply_limit(struct pfctl *, const char *, unsigned int);
|
||||
int pfctl_set_logif(struct pfctl *, char *);
|
||||
int pfctl_set_hostid(struct pfctl *, u_int32_t);
|
||||
int pfctl_do_set_debug(struct pfctl *, char *);
|
||||
|
@ -2505,6 +2505,8 @@ int pf_ioctl_addrule(struct pf_krule *, uint32_t,
|
||||
void pf_ioctl_clear_status(void);
|
||||
int pf_ioctl_get_timeout(int, int *);
|
||||
int pf_ioctl_set_timeout(int, int, int *);
|
||||
int pf_ioctl_get_limit(int, unsigned int *);
|
||||
int pf_ioctl_set_limit(int, unsigned int, unsigned int *);
|
||||
|
||||
void pf_krule_free(struct pf_krule *);
|
||||
void pf_krule_clear_counters(struct pf_krule *);
|
||||
|
@ -2483,6 +2483,40 @@ pf_ioctl_get_timeout(int timeout, int *seconds)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pf_ioctl_set_limit(int index, unsigned int limit, unsigned int *old_limit)
|
||||
{
|
||||
|
||||
PF_RULES_WLOCK();
|
||||
if (index < 0 || index >= PF_LIMIT_MAX ||
|
||||
V_pf_limits[index].zone == NULL) {
|
||||
PF_RULES_WUNLOCK();
|
||||
return (EINVAL);
|
||||
}
|
||||
uma_zone_set_max(V_pf_limits[index].zone, limit);
|
||||
if (old_limit != NULL)
|
||||
*old_limit = V_pf_limits[index].limit;
|
||||
V_pf_limits[index].limit = limit;
|
||||
PF_RULES_WUNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pf_ioctl_get_limit(int index, unsigned int *limit)
|
||||
{
|
||||
PF_RULES_RLOCK_TRACKER;
|
||||
|
||||
if (index < 0 || index >= PF_LIMIT_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
PF_RULES_RLOCK();
|
||||
*limit = V_pf_limits[index].limit;
|
||||
PF_RULES_RUNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
|
||||
{
|
||||
@ -3894,32 +3928,16 @@ DIOCGETSTATESV2_full:
|
||||
case DIOCGETLIMIT: {
|
||||
struct pfioc_limit *pl = (struct pfioc_limit *)addr;
|
||||
|
||||
if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
PF_RULES_RLOCK();
|
||||
pl->limit = V_pf_limits[pl->index].limit;
|
||||
PF_RULES_RUNLOCK();
|
||||
error = pf_ioctl_get_limit(pl->index, &pl->limit);
|
||||
break;
|
||||
}
|
||||
|
||||
case DIOCSETLIMIT: {
|
||||
struct pfioc_limit *pl = (struct pfioc_limit *)addr;
|
||||
int old_limit;
|
||||
unsigned int old_limit;
|
||||
|
||||
PF_RULES_WLOCK();
|
||||
if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
|
||||
V_pf_limits[pl->index].zone == NULL) {
|
||||
PF_RULES_WUNLOCK();
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
uma_zone_set_max(V_pf_limits[pl->index].zone, pl->limit);
|
||||
old_limit = V_pf_limits[pl->index].limit;
|
||||
V_pf_limits[pl->index].limit = pl->limit;
|
||||
error = pf_ioctl_set_limit(pl->index, pl->limit, &old_limit);
|
||||
pl->limit = old_limit;
|
||||
PF_RULES_WUNLOCK();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1410,6 +1410,67 @@ pf_handle_get_timeout(struct nlmsghdr *hdr, struct nl_pstate *npt)
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct pf_nl_set_limit
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t limit;
|
||||
};
|
||||
#define _OUT(_field) offsetof(struct pf_nl_set_limit, _field)
|
||||
static const struct nlattr_parser nla_p_set_limit[] = {
|
||||
{ .type = PF_LI_INDEX, .off = _OUT(index), .cb = nlattr_get_uint32 },
|
||||
{ .type = PF_LI_LIMIT, .off = _OUT(limit), .cb = nlattr_get_uint32 },
|
||||
};
|
||||
static const struct nlfield_parser nlf_p_set_limit[] = {};
|
||||
#undef _OUT
|
||||
NL_DECLARE_PARSER(set_limit_parser, struct genlmsghdr, nlf_p_set_limit, nla_p_set_limit);
|
||||
|
||||
static int
|
||||
pf_handle_set_limit(struct nlmsghdr *hdr, struct nl_pstate *npt)
|
||||
{
|
||||
struct pf_nl_set_limit attrs = {};
|
||||
int error;
|
||||
|
||||
error = nl_parse_nlmsg(hdr, &set_limit_parser, npt, &attrs);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
return (pf_ioctl_set_limit(attrs.index, attrs.limit, NULL));
|
||||
}
|
||||
|
||||
static int
|
||||
pf_handle_get_limit(struct nlmsghdr *hdr, struct nl_pstate *npt)
|
||||
{
|
||||
struct pf_nl_set_limit attrs = {};
|
||||
struct nl_writer *nw = npt->nw;
|
||||
struct genlmsghdr *ghdr_new;
|
||||
int error;
|
||||
|
||||
error = nl_parse_nlmsg(hdr, &set_limit_parser, npt, &attrs);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = pf_ioctl_get_limit(attrs.index, &attrs.limit);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr)))
|
||||
return (ENOMEM);
|
||||
|
||||
ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr);
|
||||
ghdr_new->cmd = PFNL_CMD_GET_LIMIT;
|
||||
ghdr_new->version = 0;
|
||||
ghdr_new->reserved = 0;
|
||||
|
||||
nlattr_add_u32(nw, PF_LI_LIMIT, attrs.limit);
|
||||
|
||||
if (!nlmsg_end(nw)) {
|
||||
nlmsg_abort(nw);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const struct nlhdr_parser *all_parsers[] = {
|
||||
&state_parser,
|
||||
&addrule_parser,
|
||||
@ -1419,6 +1480,7 @@ static const struct nlhdr_parser *all_parsers[] = {
|
||||
&natlook_parser,
|
||||
&set_debug_parser,
|
||||
&set_timeout_parser,
|
||||
&set_limit_parser,
|
||||
};
|
||||
|
||||
static int family_id;
|
||||
@ -1536,6 +1598,20 @@ static const struct genl_cmd pf_cmds[] = {
|
||||
.cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL,
|
||||
.cmd_priv = PRIV_NETINET_PF,
|
||||
},
|
||||
{
|
||||
.cmd_num = PFNL_CMD_SET_LIMIT,
|
||||
.cmd_name = "SET_LIMIT",
|
||||
.cmd_cb = pf_handle_set_limit,
|
||||
.cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL,
|
||||
.cmd_priv = PRIV_NETINET_PF,
|
||||
},
|
||||
{
|
||||
.cmd_num = PFNL_CMD_GET_LIMIT,
|
||||
.cmd_name = "GET_LIMIT",
|
||||
.cmd_cb = pf_handle_get_limit,
|
||||
.cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL,
|
||||
.cmd_priv = PRIV_NETINET_PF,
|
||||
},
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -52,6 +52,8 @@ enum {
|
||||
PFNL_CMD_SET_DEBUG = 14,
|
||||
PFNL_CMD_SET_TIMEOUT = 15,
|
||||
PFNL_CMD_GET_TIMEOUT = 16,
|
||||
PFNL_CMD_SET_LIMIT = 17,
|
||||
PFNL_CMD_GET_LIMIT = 18,
|
||||
__PFNL_CMD_MAX,
|
||||
};
|
||||
#define PFNL_CMD_MAX (__PFNL_CMD_MAX -1)
|
||||
@ -342,6 +344,12 @@ enum pf_timeout_types_t {
|
||||
PF_TO_SECONDS = 2, /* u32 */
|
||||
};
|
||||
|
||||
enum pf_limit_types_t {
|
||||
PF_LI_UNSPEC,
|
||||
PF_LI_INDEX = 1, /* u32 */
|
||||
PF_LI_LIMIT = 2, /* u32 */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
void pf_nl_register(void);
|
||||
|
@ -17,6 +17,7 @@ ATF_TESTS_SH+= altq \
|
||||
fragmentation_no_reassembly \
|
||||
get_state \
|
||||
icmp \
|
||||
limits \
|
||||
loginterface \
|
||||
killstate \
|
||||
macro \
|
||||
|
66
tests/sys/netpfil/pf/limits.sh
Normal file
66
tests/sys/netpfil/pf/limits.sh
Normal file
@ -0,0 +1,66 @@
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (c) 2024 Kristof Provost <kp@FreeBSD.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
. $(atf_get_srcdir)/utils.subr
|
||||
|
||||
atf_test_case "basic" "cleanup"
|
||||
basic_head()
|
||||
{
|
||||
atf_set descr 'Test setting and retrieving limits'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
basic_body()
|
||||
{
|
||||
pft_init
|
||||
|
||||
vnet_mkjail alcatraz
|
||||
|
||||
pft_set_rules alcatraz \
|
||||
"set limit states 200" \
|
||||
"set limit frags 100" \
|
||||
"set limit src-nodes 50" \
|
||||
"set limit table-entries 25"
|
||||
|
||||
atf_check -s exit:0 -o match:'states.*200' \
|
||||
jexec alcatraz pfctl -sm
|
||||
atf_check -s exit:0 -o match:'frags.*100' \
|
||||
jexec alcatraz pfctl -sm
|
||||
atf_check -s exit:0 -o match:'src-nodes.*50' \
|
||||
jexec alcatraz pfctl -sm
|
||||
atf_check -s exit:0 -o match:'table-entries.*25' \
|
||||
jexec alcatraz pfctl -sm
|
||||
}
|
||||
|
||||
basic_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "basic"
|
||||
}
|
@ -318,36 +318,34 @@ pf_limits(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 pfioc_limit pl;
|
||||
unsigned int index, limit;
|
||||
|
||||
if (op == SNMP_OP_SET)
|
||||
return (SNMP_ERR_NOT_WRITEABLE);
|
||||
|
||||
if (op == SNMP_OP_GET) {
|
||||
bzero(&pl, sizeof(struct pfioc_limit));
|
||||
|
||||
switch (which) {
|
||||
case LEAF_pfLimitsStates:
|
||||
pl.index = PF_LIMIT_STATES;
|
||||
index = PF_LIMIT_STATES;
|
||||
break;
|
||||
case LEAF_pfLimitsSrcNodes:
|
||||
pl.index = PF_LIMIT_SRC_NODES;
|
||||
index = PF_LIMIT_SRC_NODES;
|
||||
break;
|
||||
case LEAF_pfLimitsFrags:
|
||||
pl.index = PF_LIMIT_FRAGS;
|
||||
index = PF_LIMIT_FRAGS;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (SNMP_ERR_NOSUCHNAME);
|
||||
}
|
||||
|
||||
if (ioctl(pfctl_fd(pfh), DIOCGETLIMIT, &pl)) {
|
||||
if (pfctl_get_limit(pfh, index, &limit)) {
|
||||
syslog(LOG_ERR, "pf_limits(): ioctl(): %s",
|
||||
strerror(errno));
|
||||
return (SNMP_ERR_GENERR);
|
||||
}
|
||||
|
||||
val->v.uint32 = pl.limit;
|
||||
val->v.uint32 = limit;
|
||||
|
||||
return (SNMP_ERR_NOERROR);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user