mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 00:32:25 -04:00
pf: Introduce nvlist variant of DIOCGETSTATUS
Make it possible to extend the GETSTATUS call (e.g. when we want to add new counters, such as for syncookie support) by introducing an nvlist-based alternative. MFC after: 1 week Sponsored by: Modirum MDPay Differential Revision: https://reviews.freebsd.org/D31694
This commit is contained in:
parent
5d785ad65e
commit
2b10cf85f8
3 changed files with 143 additions and 0 deletions
|
|
@ -1667,6 +1667,7 @@ struct pfioc_iface {
|
|||
#define DIOCGETSTATENV _IOWR('D', 19, struct pfioc_nv)
|
||||
#define DIOCSETSTATUSIF _IOWR('D', 20, struct pfioc_if)
|
||||
#define DIOCGETSTATUS _IOWR('D', 21, struct pf_status)
|
||||
#define DIOCGETSTATUSNV _IOWR('D', 21, struct pfioc_nv)
|
||||
#define DIOCCLRSTATUS _IO ('D', 22)
|
||||
#define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook)
|
||||
#define DIOCSETDEBUG _IOWR('D', 24, u_int32_t)
|
||||
|
|
|
|||
|
|
@ -179,6 +179,15 @@ enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
|
|||
#define FCNT_STATE_REMOVALS 2
|
||||
#define FCNT_MAX 3
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define FCNT_NAMES { \
|
||||
"searches", \
|
||||
"inserts", \
|
||||
"removals", \
|
||||
NULL \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* src_node operation counters */
|
||||
#define SCNT_SRC_NODE_SEARCH 0
|
||||
#define SCNT_SRC_NODE_INSERT 1
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ static int pf_killstates_row(struct pf_kstate_kill *,
|
|||
static int pf_killstates_nv(struct pfioc_nv *);
|
||||
static int pf_clearstates_nv(struct pfioc_nv *);
|
||||
static int pf_getstate(struct pfioc_nv *);
|
||||
static int pf_getstatus(struct pfioc_nv *);
|
||||
static int pf_clear_tables(void);
|
||||
static void pf_clear_srcnodes(struct pf_ksrc_node *);
|
||||
static void pf_kill_srcnodes(struct pfioc_src_node_kill *);
|
||||
|
|
@ -2179,6 +2180,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
|||
case DIOCGETSTATENV:
|
||||
case DIOCSETSTATUSIF:
|
||||
case DIOCGETSTATUS:
|
||||
case DIOCGETSTATUSNV:
|
||||
case DIOCCLRSTATUS:
|
||||
case DIOCNATLOOK:
|
||||
case DIOCSETDEBUG:
|
||||
|
|
@ -2236,6 +2238,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
|||
case DIOCGETSTATE:
|
||||
case DIOCGETSTATENV:
|
||||
case DIOCGETSTATUS:
|
||||
case DIOCGETSTATUSNV:
|
||||
case DIOCGETSTATES:
|
||||
case DIOCGETSTATESV2:
|
||||
case DIOCGETTIMEOUT:
|
||||
|
|
@ -3096,6 +3099,11 @@ DIOCGETSTATESV2_full:
|
|||
break;
|
||||
}
|
||||
|
||||
case DIOCGETSTATUSNV: {
|
||||
error = pf_getstatus((struct pfioc_nv *)addr);
|
||||
break;
|
||||
}
|
||||
|
||||
case DIOCSETSTATUSIF: {
|
||||
struct pfioc_if *pi = (struct pfioc_if *)addr;
|
||||
|
||||
|
|
@ -4887,6 +4895,131 @@ pf_tbladdr_copyout(struct pf_addr_wrap *aw)
|
|||
kt->pfrkt_cnt : -1;
|
||||
}
|
||||
|
||||
static int
|
||||
pf_add_status_counters(nvlist_t *nvl, const char *name, counter_u64_t *counters,
|
||||
size_t number, char **names)
|
||||
{
|
||||
nvlist_t *nvc;
|
||||
|
||||
nvc = nvlist_create(0);
|
||||
if (nvc == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
for (int i = 0; i < number; i++) {
|
||||
nvlist_append_number_array(nvc, "counters",
|
||||
counter_u64_fetch(counters[i]));
|
||||
nvlist_append_string_array(nvc, "names",
|
||||
names[i]);
|
||||
nvlist_append_number_array(nvc, "ids",
|
||||
i);
|
||||
}
|
||||
nvlist_add_nvlist(nvl, name, nvc);
|
||||
nvlist_destroy(nvc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pf_getstatus(struct pfioc_nv *nv)
|
||||
{
|
||||
nvlist_t *nvl = NULL, *nvc = NULL;
|
||||
void *nvlpacked = NULL;
|
||||
int error;
|
||||
struct pf_status s;
|
||||
char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
|
||||
char *pf_lcounter[LCNT_MAX+1] = LCNT_NAMES;
|
||||
char *pf_fcounter[FCNT_MAX+1] = FCNT_NAMES;
|
||||
PF_RULES_RLOCK_TRACKER;
|
||||
|
||||
#define ERROUT(x) ERROUT_FUNCTION(errout, x)
|
||||
|
||||
PF_RULES_RLOCK();
|
||||
|
||||
nvl = nvlist_create(0);
|
||||
if (nvl == NULL)
|
||||
ERROUT(ENOMEM);
|
||||
|
||||
nvlist_add_bool(nvl, "running", V_pf_status.running);
|
||||
nvlist_add_number(nvl, "since", V_pf_status.since);
|
||||
nvlist_add_number(nvl, "debug", V_pf_status.debug);
|
||||
nvlist_add_number(nvl, "hostid", V_pf_status.hostid);
|
||||
nvlist_add_number(nvl, "states", V_pf_status.states);
|
||||
nvlist_add_number(nvl, "src_nodes", V_pf_status.src_nodes);
|
||||
|
||||
/* counters */
|
||||
error = pf_add_status_counters(nvl, "counters", V_pf_status.counters,
|
||||
PFRES_MAX, pf_reasons);
|
||||
if (error != 0)
|
||||
ERROUT(error);
|
||||
|
||||
/* lcounters */
|
||||
error = pf_add_status_counters(nvl, "lcounters", V_pf_status.lcounters,
|
||||
LCNT_MAX, pf_lcounter);
|
||||
if (error != 0)
|
||||
ERROUT(error);
|
||||
|
||||
/* fcounters */
|
||||
nvc = nvlist_create(0);
|
||||
if (nvc == NULL)
|
||||
ERROUT(ENOMEM);
|
||||
|
||||
for (int i = 0; i < FCNT_MAX; i++) {
|
||||
nvlist_append_number_array(nvc, "counters",
|
||||
pf_counter_u64_fetch(&V_pf_status.fcounters[i]));
|
||||
nvlist_append_string_array(nvc, "names",
|
||||
pf_fcounter[i]);
|
||||
nvlist_append_number_array(nvc, "ids",
|
||||
i);
|
||||
}
|
||||
nvlist_add_nvlist(nvl, "fcounters", nvc);
|
||||
nvlist_destroy(nvc);
|
||||
nvc = NULL;
|
||||
|
||||
/* scounters */
|
||||
error = pf_add_status_counters(nvl, "scounters", V_pf_status.scounters,
|
||||
SCNT_MAX, pf_fcounter);
|
||||
if (error != 0)
|
||||
ERROUT(error);
|
||||
|
||||
nvlist_add_string(nvl, "ifname", V_pf_status.ifname);
|
||||
nvlist_add_binary(nvl, "chksum", V_pf_status.pf_chksum,
|
||||
PF_MD5_DIGEST_LENGTH);
|
||||
|
||||
pfi_update_status(V_pf_status.ifname, &s);
|
||||
|
||||
/* pcounters / bcounters */
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
nvlist_append_number_array(nvl, "pcounters",
|
||||
s.pcounters[i][j][k]);
|
||||
}
|
||||
nvlist_append_number_array(nvl, "bcounters",
|
||||
s.bcounters[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
nvlpacked = nvlist_pack(nvl, &nv->len);
|
||||
if (nvlpacked == NULL)
|
||||
ERROUT(ENOMEM);
|
||||
|
||||
if (nv->size == 0)
|
||||
ERROUT(0);
|
||||
else if (nv->size < nv->len)
|
||||
ERROUT(ENOSPC);
|
||||
|
||||
error = copyout(nvlpacked, nv->data, nv->len);
|
||||
|
||||
#undef ERROUT
|
||||
errout:
|
||||
PF_RULES_RUNLOCK();
|
||||
free(nvlpacked, M_NVLIST);
|
||||
nvlist_destroy(nvc);
|
||||
nvlist_destroy(nvl);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - Check for version missmatch!!!
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue