Add IP_FW_DUMP_SOPTCODES sopt to be able to determine
which opcodes are currently available in kernel.
This commit is contained in:
parent
eadf3b965c
commit
be8bc45790
@ -104,6 +104,8 @@ typedef struct _ip_fw3_opheader {
|
||||
#define IP_FW_NAT44_LIST_NAT 114 /* List all NAT44 instances */
|
||||
#define IP_FW_NAT44_XGETLOG 115 /* Get log from NAT44 instance */
|
||||
|
||||
#define IP_FW_DUMP_SOPTCODES 116 /* Dump available sopts/versions */
|
||||
|
||||
/*
|
||||
* The kernel representation of ipfw rules is made of a list of
|
||||
* 'instructions' (for all practical purposes equivalent to BPF
|
||||
@ -991,4 +993,12 @@ typedef struct _ipfw_range_header {
|
||||
ipfw_range_tlv range;
|
||||
} ipfw_range_header;
|
||||
|
||||
typedef struct _ipfw_sopt_info {
|
||||
uint16_t opcode;
|
||||
uint8_t version;
|
||||
uint8_t dir;
|
||||
uint8_t spare;
|
||||
uint64_t refcnt;
|
||||
} ipfw_sopt_info;
|
||||
|
||||
#endif /* _IPFW2_H */
|
||||
|
@ -115,6 +115,8 @@ static int move_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
static int manage_sets(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
static int dump_soptcodes(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
|
||||
/* ctl3 handler data */
|
||||
struct mtx ctl3_lock;
|
||||
@ -141,6 +143,7 @@ static struct ipfw_sopt_handler scodes[] = {
|
||||
{ IP_FW_SET_SWAP, 0, HDIR_SET, manage_sets },
|
||||
{ IP_FW_SET_MOVE, 0, HDIR_SET, manage_sets },
|
||||
{ IP_FW_SET_ENABLE, 0, HDIR_SET, manage_sets },
|
||||
{ IP_FW_DUMP_SOPTCODES, 0, HDIR_GET, dump_soptcodes },
|
||||
};
|
||||
|
||||
/*
|
||||
@ -2284,6 +2287,57 @@ add_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lists all sopts currently registered.
|
||||
* Data layout (v0)(current):
|
||||
* Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
|
||||
* Reply: [ ipfw_obj_lheader ipfw_sopt_info x N ]
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
static int
|
||||
dump_soptcodes(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
struct _ipfw_obj_lheader *olh;
|
||||
ipfw_sopt_info *i;
|
||||
struct ipfw_sopt_handler *sh;
|
||||
uint32_t count, n, size;
|
||||
|
||||
olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
|
||||
if (olh == NULL)
|
||||
return (EINVAL);
|
||||
if (sd->valsize < olh->size)
|
||||
return (EINVAL);
|
||||
|
||||
CTL3_LOCK();
|
||||
count = ctl3_hsize;
|
||||
size = count * sizeof(ipfw_sopt_info) + sizeof(ipfw_obj_lheader);
|
||||
|
||||
/* Fill in header regadless of buffer size */
|
||||
olh->count = count;
|
||||
olh->objsize = sizeof(ipfw_sopt_info);
|
||||
|
||||
if (size > olh->size) {
|
||||
olh->size = size;
|
||||
CTL3_UNLOCK();
|
||||
return (ENOMEM);
|
||||
}
|
||||
olh->size = size;
|
||||
|
||||
for (n = 1; n <= count; n++) {
|
||||
i = (ipfw_sopt_info *)ipfw_get_sopt_space(sd, sizeof(*i));
|
||||
KASSERT(i != 0, ("previously checked buffer is not enough"));
|
||||
sh = &ctl3_handlers[n];
|
||||
i->opcode = sh->opcode;
|
||||
i->version = sh->version;
|
||||
i->refcnt = sh->refcnt;
|
||||
}
|
||||
CTL3_UNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compares two sopt handlers (code, version and handler ptr).
|
||||
* Used both as qsort() and bsearch().
|
||||
|
@ -547,8 +547,15 @@ ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts)
|
||||
IPFW_UH_WLOCK(ch);
|
||||
tc_unref(tc);
|
||||
del_toperation_state(ch, ts);
|
||||
if (ts->modified != 0)
|
||||
if (ts->modified != 0) {
|
||||
|
||||
/*
|
||||
* In general, we should free all state/indexes here
|
||||
* and return. However, we keep allocated state instead
|
||||
* to ensure we achieve some progress on each restart.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
KASSERT(pval == ch->tablestate, ("resize_storage() notify failure"));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user