diff options
author | ae <ae@FreeBSD.org> | 2017-04-17 09:36:35 +0000 |
---|---|---|
committer | Luiz Souza <luiz@netgate.com> | 2017-07-15 11:19:09 -0500 |
commit | 522323933bf93029d030d5744c0f5ac95c0db56e (patch) | |
tree | 54fb55ba3d0b1ffd2cd31cf3c9ad67f9ebb388f1 | |
parent | 20f1059c99efbc31a8e3694dd8a9c86ebf90f4fb (diff) | |
download | FreeBSD-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.c | 16 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 1 | ||||
-rw-r--r-- | sys/netpfil/ipfw/ip_fw_eaction.c | 23 | ||||
-rw-r--r-- | sys/netpfil/ipfw/ip_fw_sockopt.c | 13 |
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) |