dd ipfw_get_action() function to get the pointer to action opcode.
ACTION_PTR() returns pointer to the start of rule action section, but rule can keep several rule modifiers like O_LOG, O_TAG and O_ALTQ, and only then real action opcode is stored. ipfw_get_action() function inspects the rule action section, skips all modifiers and returns action opcode. Use this function in ipfw_reset_eaction() and flush_nat_ptrs(). MFC after: 1 week Sponsored by: Yandex LLC
This commit is contained in:
parent
52bb6100e9
commit
e758846c09
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=350417
@ -377,33 +377,30 @@ ipfw_reset_eaction(struct ip_fw_chain *ch, struct ip_fw *rule,
|
||||
uint16_t eaction_id, uint16_t default_id, uint16_t instance_id)
|
||||
{
|
||||
ipfw_insn *cmd, *icmd;
|
||||
int l, cmdlen;
|
||||
int l;
|
||||
|
||||
IPFW_UH_WLOCK_ASSERT(ch);
|
||||
IPFW_WLOCK_ASSERT(ch);
|
||||
|
||||
cmd = ACTION_PTR(rule);
|
||||
l = rule->cmd_len - rule->act_ofs;
|
||||
while (l > 0) {
|
||||
cmdlen = F_LEN(cmd);
|
||||
l -= cmdlen;
|
||||
if (cmd->opcode == O_EXTERNAL_ACTION || l <= 0)
|
||||
break;
|
||||
cmd += cmdlen;
|
||||
}
|
||||
/*
|
||||
* Return if there is not O_EXTERNAL_ACTION or its id is
|
||||
* different.
|
||||
*/
|
||||
cmd = ipfw_get_action(rule);
|
||||
if (cmd->opcode != O_EXTERNAL_ACTION ||
|
||||
cmd->arg1 != eaction_id)
|
||||
return (0);
|
||||
/*
|
||||
* If instance_id is specified, we need to truncate the
|
||||
* rule length. Check if there is O_EXTERNAL_INSTANCE opcode.
|
||||
*
|
||||
* NOTE: F_LEN(cmd) must be 1 for O_EXTERNAL_ACTION opcode,
|
||||
* and rule length should be enough to keep O_EXTERNAL_INSTANCE
|
||||
* opcode, thus we do check for l > 1.
|
||||
*/
|
||||
if (instance_id != 0 && l > 0) {
|
||||
MPASS(cmdlen == 1);
|
||||
l = rule->cmd + rule->cmd_len - cmd;
|
||||
if (instance_id != 0 && l > 1) {
|
||||
MPASS(F_LEN(cmd) == 1);
|
||||
icmd = cmd + 1;
|
||||
if (icmd->opcode != O_EXTERNAL_INSTANCE ||
|
||||
icmd->arg1 != instance_id)
|
||||
@ -415,8 +412,9 @@ ipfw_reset_eaction(struct ip_fw_chain *ch, struct ip_fw *rule,
|
||||
* opcode.
|
||||
*/
|
||||
EACTION_DEBUG("truncate rule %d: len %u -> %u",
|
||||
rule->rulenum, rule->cmd_len, rule->cmd_len - l);
|
||||
rule->cmd_len -= l;
|
||||
rule->rulenum, rule->cmd_len,
|
||||
rule->cmd_len - F_LEN(icmd));
|
||||
rule->cmd_len -= F_LEN(icmd);
|
||||
MPASS(((uint32_t *)icmd -
|
||||
(uint32_t *)rule->cmd) == rule->cmd_len);
|
||||
}
|
||||
|
@ -140,13 +140,12 @@ ifaddr_change(void *arg __unused, struct ifnet *ifp)
|
||||
static void
|
||||
flush_nat_ptrs(struct ip_fw_chain *chain, const int ix)
|
||||
{
|
||||
int i;
|
||||
ipfw_insn_nat *cmd;
|
||||
int i;
|
||||
|
||||
IPFW_WLOCK_ASSERT(chain);
|
||||
for (i = 0; i < chain->n_rules; i++) {
|
||||
cmd = (ipfw_insn_nat *)ACTION_PTR(chain->map[i]);
|
||||
/* XXX skip log and the like ? */
|
||||
cmd = (ipfw_insn_nat *)ipfw_get_action(chain->map[i]);
|
||||
if (cmd->o.opcode == O_NAT && cmd->nat != NULL &&
|
||||
(ix < 0 || cmd->nat->id == ix))
|
||||
cmd->nat = NULL;
|
||||
|
@ -665,6 +665,7 @@ struct ip_fw *ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize);
|
||||
void ipfw_free_rule(struct ip_fw *rule);
|
||||
int ipfw_match_range(struct ip_fw *rule, ipfw_range_tlv *rt);
|
||||
int ipfw_mark_object_kidx(uint32_t *bmask, uint16_t etlv, uint16_t kidx);
|
||||
ipfw_insn *ipfw_get_action(struct ip_fw *);
|
||||
|
||||
typedef int (sopt_handler_f)(struct ip_fw_chain *ch,
|
||||
ip_fw3_opheader *op3, struct sockopt_data *sd);
|
||||
|
@ -1217,6 +1217,35 @@ move_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns pointer to action instruction, skips all possible rule
|
||||
* modifiers like O_LOG, O_TAG, O_ALTQ.
|
||||
*/
|
||||
ipfw_insn *
|
||||
ipfw_get_action(struct ip_fw *rule)
|
||||
{
|
||||
ipfw_insn *cmd;
|
||||
int l, cmdlen;
|
||||
|
||||
cmd = ACTION_PTR(rule);
|
||||
l = rule->cmd_len - rule->act_ofs;
|
||||
while (l > 0) {
|
||||
switch (cmd->opcode) {
|
||||
case O_ALTQ:
|
||||
case O_LOG:
|
||||
case O_TAG:
|
||||
break;
|
||||
default:
|
||||
return (cmd);
|
||||
}
|
||||
cmdlen = F_LEN(cmd);
|
||||
l -= cmdlen;
|
||||
cmd += cmdlen;
|
||||
}
|
||||
panic("%s: rule (%p) has not action opcode", __func__, rule);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear counters for a specific rule.
|
||||
* Normally run under IPFW_UH_RLOCK, but these are idempotent ops
|
||||
|
Loading…
Reference in New Issue
Block a user