pf: Add DIOCGETSTATESNV
Add DIOCGETSTATESNV, an nvlist-based alternative to DIOCGETSTATES. MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D30243
This commit is contained in:
parent
1732afaa0d
commit
0592a4c83d
@ -415,30 +415,65 @@ Set the debug level.
|
||||
enum { PF_DEBUG_NONE, PF_DEBUG_URGENT, PF_DEBUG_MISC,
|
||||
PF_DEBUG_NOISY };
|
||||
.Ed
|
||||
.It Dv DIOCGETSTATES Fa "struct pfioc_states *ps"
|
||||
.It Dv DIOCGETSTATESNV Fa "struct pfioc_nv *nv"
|
||||
Get state table entries.
|
||||
.Bd -literal
|
||||
struct pfioc_states {
|
||||
int ps_len;
|
||||
union {
|
||||
caddr_t psu_buf;
|
||||
struct pf_state *psu_states;
|
||||
} ps_u;
|
||||
#define ps_buf ps_u.psu_buf
|
||||
#define ps_states ps_u.psu_states
|
||||
nvlist pf_state_key {
|
||||
nvlist pf_addr addr[2];
|
||||
number port[2];
|
||||
number af;
|
||||
number proto;
|
||||
};
|
||||
|
||||
nvlist pf_state_scrub {
|
||||
bool timestamp;
|
||||
number ttl;
|
||||
number ts_mod;
|
||||
};
|
||||
|
||||
nvlist pf_state_peer {
|
||||
nvlist pf_state_scrub scrub;
|
||||
number seqlo;
|
||||
number seqhi;
|
||||
number seqdiff;
|
||||
number max_win;
|
||||
number mss;
|
||||
number state;
|
||||
number wscale;
|
||||
};
|
||||
|
||||
nvlist pf_state {
|
||||
number id;
|
||||
string ifname;
|
||||
nvlist pf_state_key stack_key;
|
||||
nvlist pf_state_key wire_key;
|
||||
nvlist pf_state_peer src;
|
||||
nvlist pf_state_peer dst;
|
||||
nvlist pf_addr rt_addr;
|
||||
number rule;
|
||||
number anchor;
|
||||
number nat_rule;
|
||||
number expire;
|
||||
number packets[2];
|
||||
number bytes[2];
|
||||
number creatorid;
|
||||
number direction;
|
||||
number log;
|
||||
number state_flags;
|
||||
number timeout;
|
||||
number sync_flags;
|
||||
};
|
||||
|
||||
nvlist pf_states {
|
||||
number count;
|
||||
nvlist pf_state states[];
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
If
|
||||
.Va ps_len
|
||||
is non-zero on entry, as many states as possible that can fit into this
|
||||
size will be copied into the supplied buffer
|
||||
.Va ps_states .
|
||||
On exit,
|
||||
.Va ps_len
|
||||
is always set to the total size required to hold all state table entries
|
||||
(i.e., it is set to
|
||||
.Li sizeof(struct pf_state) * nr ) .
|
||||
.Va pfioc_nv.size
|
||||
is insufficiently large, as many states as possible that can fit into this
|
||||
size will be copied into the supplied buffer.
|
||||
.It Dv DIOCCHANGERULE Fa "struct pfioc_rule *pcr"
|
||||
Add or remove the
|
||||
.Va rule
|
||||
|
@ -1264,6 +1264,7 @@ struct pfioc_iface {
|
||||
#define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook)
|
||||
#define DIOCSETDEBUG _IOWR('D', 24, u_int32_t)
|
||||
#define DIOCGETSTATES _IOWR('D', 25, struct pfioc_states)
|
||||
#define DIOCGETSTATESNV _IOWR('D', 25, struct pfioc_nv)
|
||||
#define DIOCCHANGERULE _IOWR('D', 26, struct pfioc_rule)
|
||||
/* XXX cut 26 - 28 */
|
||||
#define DIOCSETTIMEOUT _IOWR('D', 29, struct pfioc_tm)
|
||||
|
@ -209,6 +209,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_getstates(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 *);
|
||||
@ -2948,6 +2949,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
case DIOCNATLOOK:
|
||||
case DIOCSETDEBUG:
|
||||
case DIOCGETSTATES:
|
||||
case DIOCGETSTATESNV:
|
||||
case DIOCGETTIMEOUT:
|
||||
case DIOCCLRRULECTRS:
|
||||
case DIOCGETLIMIT:
|
||||
@ -3000,6 +3002,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
case DIOCGETSTATENV:
|
||||
case DIOCGETSTATUS:
|
||||
case DIOCGETSTATES:
|
||||
case DIOCGETSTATESNV:
|
||||
case DIOCGETTIMEOUT:
|
||||
case DIOCGETLIMIT:
|
||||
case DIOCGETALTQSV0:
|
||||
@ -3709,6 +3712,11 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
break;
|
||||
}
|
||||
|
||||
case DIOCGETSTATESNV: {
|
||||
error = pf_getstates((struct pfioc_nv *)addr);
|
||||
break;
|
||||
}
|
||||
|
||||
case DIOCGETSTATUS: {
|
||||
struct pf_status *s = (struct pf_status *)addr;
|
||||
|
||||
@ -5916,6 +5924,74 @@ pf_getstate(struct pfioc_nv *nv)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
pf_getstates(struct pfioc_nv *nv)
|
||||
{
|
||||
nvlist_t *nvl = NULL, *nvls;
|
||||
void *nvlpacked = NULL;
|
||||
struct pf_state *s = NULL;
|
||||
int error = 0;
|
||||
uint64_t count = 0;
|
||||
|
||||
#define ERROUT(x) ERROUT_FUNCTION(errout, x)
|
||||
|
||||
nvl = nvlist_create(0);
|
||||
if (nvl == NULL)
|
||||
ERROUT(ENOMEM);
|
||||
|
||||
nvlist_add_number(nvl, "count", uma_zone_get_cur(V_pf_state_z));
|
||||
|
||||
for (int i = 0; i < pf_hashmask; i++) {
|
||||
struct pf_idhash *ih = &V_pf_idhash[i];
|
||||
|
||||
PF_HASHROW_LOCK(ih);
|
||||
LIST_FOREACH(s, &ih->states, entry) {
|
||||
if (s->timeout == PFTM_UNLINKED)
|
||||
continue;
|
||||
|
||||
nvls = pf_state_to_nvstate(s);
|
||||
if (nvls == NULL) {
|
||||
PF_HASHROW_UNLOCK(ih);
|
||||
ERROUT(ENOMEM);
|
||||
}
|
||||
if ((nvlist_size(nvl) + nvlist_size(nvls)) > nv->size) {
|
||||
/* We've run out of room for more states. */
|
||||
nvlist_destroy(nvls);
|
||||
PF_HASHROW_UNLOCK(ih);
|
||||
goto DIOCGETSTATESNV_full;
|
||||
}
|
||||
nvlist_append_nvlist_array(nvl, "states", nvls);
|
||||
count++;
|
||||
}
|
||||
PF_HASHROW_UNLOCK(ih);
|
||||
}
|
||||
|
||||
/* We've managed to put them all the available space. Let's make sure
|
||||
* 'count' matches our array (that's racy, because we don't hold a lock
|
||||
* over all states, only over each row individually. */
|
||||
(void)nvlist_take_number(nvl, "count");
|
||||
nvlist_add_number(nvl, "count", count);
|
||||
|
||||
DIOCGETSTATESNV_full:
|
||||
|
||||
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:
|
||||
free(nvlpacked, M_TEMP);
|
||||
nvlist_destroy(nvl);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - Check for version missmatch!!!
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user