summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2017-04-17 09:36:35 +0000
committerLuiz Souza <luiz@netgate.com>2017-07-15 11:19:09 -0500
commit522323933bf93029d030d5744c0f5ac95c0db56e (patch)
tree54fb55ba3d0b1ffd2cd31cf3c9ad67f9ebb388f1
parent20f1059c99efbc31a8e3694dd8a9c86ebf90f4fb (diff)
downloadFreeBSD-src-522323933bf93029d030d5744c0f5ac95c0db56e.zip
FreeBSD-src-522323933bf93029d030d5744c0f5ac95c0db56e.tar.gz
MFC r316434:
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 Sponsored by: Yandex LLC (cherry picked from commit 7a6d766f1284a41887dd6302256d4bb01df92e5c)
-rw-r--r--sbin/ipfw/ipfw2.c16
-rw-r--r--sys/netinet/ip_fw.h1
-rw-r--r--sys/netpfil/ipfw/ip_fw_eaction.c23
-rw-r--r--sys/netpfil/ipfw/ip_fw_sockopt.c13
4 files changed, 40 insertions, 13 deletions
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index fd3ad2a..b954131 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -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;
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 3b67029..adbc41b 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -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_MACADDR2_LOOKUP, /* arg1=table number, u32=value */
diff --git a/sys/netpfil/ipfw/ip_fw_eaction.c b/sys/netpfil/ipfw/ip_fw_eaction.c
index a9de696..39dbd71 100644
--- a/sys/netpfil/ipfw/ip_fw_eaction.c
+++ b/sys/netpfil/ipfw/ip_fw_eaction.c
@@ -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);
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
index ff33522..664a950 100644
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -1737,11 +1737,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",
@@ -2631,11 +2636,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)
OpenPOWER on IntegriCloud