Add O_EXTERNAL_DATA opcode support.
This opcode can be used to attach some data to external action opcode. And unlike to O_EXTERNAL_INSTANCE opcode, this opcode does not require creating of named instance to pass configuration arguments to external action handler. The data is coming just next to O_EXTERNAL_ACTION opcode. The userlevel part currenly supports formatting for opcode with ipfw_insn size, by default it expects u16 numeric value in the arg1. Obtained from: Yandex LLC MFC after: 2 weeks Sponsored by: Yandex LLC
This commit is contained in:
parent
399ad57874
commit
11c56650f0
@ -1642,6 +1642,22 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
|
||||
break;
|
||||
}
|
||||
|
||||
case O_EXTERNAL_DATA: {
|
||||
if (has_eaction == NULL)
|
||||
break;
|
||||
/*
|
||||
* Currently we support data formatting only for
|
||||
* external data with datalen u16. For unknown data
|
||||
* print its size in bytes.
|
||||
*/
|
||||
if (cmd->len == F_INSN_SIZE(ipfw_insn))
|
||||
bprintf(bp, " %u", cmd->arg1);
|
||||
else
|
||||
bprintf(bp, " %ubytes",
|
||||
cmd->len * sizeof(uint32_t));
|
||||
break;
|
||||
}
|
||||
|
||||
case O_SETDSCP:
|
||||
{
|
||||
const char *code;
|
||||
|
@ -281,6 +281,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
|
||||
|
||||
O_EXTERNAL_ACTION, /* arg1=id of external action handler */
|
||||
O_EXTERNAL_INSTANCE, /* arg1=id of eaction handler instance */
|
||||
O_EXTERNAL_DATA, /* variable length data */
|
||||
|
||||
O_LAST_OPCODE /* not an opcode! */
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Yandex LLC
|
||||
* Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org>
|
||||
* Copyright (c) 2016-2017 Yandex LLC
|
||||
* Copyright (c) 2016-2017 Andrey V. Elsukov <ae@FreeBSD.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -57,7 +57,7 @@ __FBSDID("$FreeBSD$");
|
||||
* rules.
|
||||
* Module should implement opcode handler with type ipfw_eaction_t.
|
||||
* This handler will be called by ipfw_chk() function when
|
||||
* O_EXTERNAL_ACTION opcode will be matched. The handler must return
|
||||
* O_EXTERNAL_ACTION opcode is matched. The handler must return
|
||||
* value used as return value in ipfw_chk(), i.e. IP_FW_PASS,
|
||||
* IP_FW_DENY (see ip_fw_private.h).
|
||||
* Also the last argument must be set by handler. If it is zero,
|
||||
@ -69,9 +69,12 @@ __FBSDID("$FreeBSD$");
|
||||
* This function will return eaction_id, that can be used by module.
|
||||
*
|
||||
* It is possible to pass some additional information to external
|
||||
* action handler via the O_EXTERNAL_INSTANCE opcode. This opcode
|
||||
* will be next after the O_EXTERNAL_ACTION opcode. cmd->arg1 will
|
||||
* contain index of named object related to instance of external action.
|
||||
* action handler using O_EXTERNAL_INSTANCE and O_EXTERNAL_DATA opcodes.
|
||||
* Such opcodes should be next after the O_EXTERNAL_ACTION opcode.
|
||||
* For the O_EXTERNAL_INSTANCE opcode the cmd->arg1 contains index of named
|
||||
* object related to an instance of external action.
|
||||
* For the O_EXTERNAL_DATA opcode the cmd contains the data that can be used
|
||||
* by external action handler without needing to create named instance.
|
||||
*
|
||||
* In case when eaction module uses named instances, it should register
|
||||
* opcode rewriting routines for O_EXTERNAL_INSTANCE opcode. The
|
||||
@ -284,11 +287,13 @@ reset_eaction_obj(struct ip_fw_chain *ch, uint16_t eaction_id)
|
||||
/*
|
||||
* Since named_object related to this instance will be
|
||||
* also destroyed, truncate the chain of opcodes to
|
||||
* remove O_EXTERNAL_INSTANCE opcode.
|
||||
* remove the rest of cmd chain just after O_EXTERNAL_ACTION
|
||||
* opcode.
|
||||
*/
|
||||
if (rule->act_ofs < rule->cmd_len - 1) {
|
||||
EACTION_DEBUG("truncate rule %d", rule->rulenum);
|
||||
rule->cmd_len--;
|
||||
EACTION_DEBUG("truncate rule %d: len %u -> %u",
|
||||
rule->rulenum, rule->cmd_len, rule->act_ofs + 1);
|
||||
rule->cmd_len = rule->act_ofs + 1;
|
||||
}
|
||||
}
|
||||
IPFW_WUNLOCK(ch);
|
||||
|
@ -1736,11 +1736,16 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
|
||||
return (EINVAL);
|
||||
}
|
||||
ci->object_opcodes++;
|
||||
/* Do we have O_EXTERNAL_INSTANCE opcode? */
|
||||
/*
|
||||
* Do we have O_EXTERNAL_INSTANCE or O_EXTERNAL_DATA
|
||||
* opcode?
|
||||
*/
|
||||
if (l != cmdlen) {
|
||||
l -= cmdlen;
|
||||
cmd += cmdlen;
|
||||
cmdlen = F_LEN(cmd);
|
||||
if (cmd->opcode == O_EXTERNAL_DATA)
|
||||
goto check_action;
|
||||
if (cmd->opcode != O_EXTERNAL_INSTANCE) {
|
||||
printf("ipfw: invalid opcode "
|
||||
"next to external action %u\n",
|
||||
@ -2618,11 +2623,11 @@ unref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule)
|
||||
continue;
|
||||
no = rw->find_bykidx(ch, kidx);
|
||||
|
||||
KASSERT(no != NULL, ("table id %d not found", kidx));
|
||||
KASSERT(no != NULL, ("object id %d not found", kidx));
|
||||
KASSERT(no->subtype == subtype,
|
||||
("wrong type %d (%d) for table id %d",
|
||||
("wrong type %d (%d) for object id %d",
|
||||
no->subtype, subtype, kidx));
|
||||
KASSERT(no->refcnt > 0, ("refcount for table %d is %d",
|
||||
KASSERT(no->refcnt > 0, ("refcount for object %d is %d",
|
||||
kidx, no->refcnt));
|
||||
|
||||
if (no->refcnt == 1 && rw->destroy_object != NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user