* @handle: chain handle
* @location: location the chain was defined at
* @flags: chain flags
+ * @hookstr: unified and human readable hook name (base chains)
* @hooknum: hook number (base chains)
* @priority: hook priority (base chains)
* @type: chain type
struct handle handle;
struct location location;
uint32_t flags;
+ const char *hookstr;
unsigned int hooknum;
unsigned int priority;
const char *type;
struct list_head rules;
};
+extern const char *chain_hookname_lookup(const char *name);
extern struct chain *chain_alloc(const char *name);
extern void chain_free(struct chain *chain);
extern void chain_add_hash(struct chain *chain, struct table *table);
#include <stdint.h>
#include <string.h>
#include <arpa/inet.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_arp.h>
#include <linux/netfilter/nf_tables.h>
#include <expression.h>
__stmt_binary_error(ctx, &(s1)->location, NULL, fmt, ## args)
#define stmt_binary_error(ctx, s1, s2, fmt, args...) \
__stmt_binary_error(ctx, &(s1)->location, &(s2)->location, fmt, ## args)
+#define chain_error(ctx, s1, fmt, args...) \
+ __stmt_binary_error(ctx, &(s1)->location, NULL, fmt, ## args)
static int __fmtstring(3, 4) set_error(struct eval_ctx *ctx,
const struct set *set,
return 0;
}
+static uint32_t str2hooknum(uint32_t family, const char *hook)
+{
+ switch (family) {
+ case NFPROTO_IPV4:
+ case NFPROTO_BRIDGE:
+ case NFPROTO_IPV6:
+ /* These families have overlapping values for each hook */
+ if (!strcmp(hook, "prerouting"))
+ return NF_INET_PRE_ROUTING;
+ else if (!strcmp(hook, "input"))
+ return NF_INET_LOCAL_IN;
+ else if (!strcmp(hook, "forward"))
+ return NF_INET_FORWARD;
+ else if (!strcmp(hook, "postrouting"))
+ return NF_INET_POST_ROUTING;
+ else if (!strcmp(hook, "output"))
+ return NF_INET_LOCAL_OUT;
+ case NFPROTO_ARP:
+ if (!strcmp(hook, "input"))
+ return NF_ARP_IN;
+ else if (!strcmp(hook, "forward"))
+ return NF_ARP_FORWARD;
+ else if (!strcmp(hook, "output"))
+ return NF_ARP_OUT;
+ default:
+ break;
+ }
+
+ return NF_INET_NUMHOOKS;
+}
+
static int chain_evaluate(struct eval_ctx *ctx, struct chain *chain)
{
struct rule *rule;
+ if (chain->flags & CHAIN_F_BASECHAIN) {
+ chain->hooknum = str2hooknum(chain->handle.family,
+ chain->hookstr);
+ if (chain->hooknum == NF_INET_NUMHOOKS)
+ return chain_error(ctx, chain, "invalid hook %s",
+ chain->hookstr);
+ }
+
list_for_each_entry(rule, &chain->rules, list) {
handle_merge(&rule->handle, &chain->handle);
if (rule_evaluate(ctx, rule) < 0)
%token DEFINE "define"
%token HOOK "hook"
-%token <val> HOOKNUM "hooknum"
%token TABLE "table"
%token TABLES "tables"
%token CHAIN "chain"
| CHAIN chain_spec chain_block_alloc
'{' chain_block '}'
{
+ $5->location = @5;
handle_merge(&$3->handle, &$2);
close_scope(state);
$$ = cmd_alloc(CMD_ADD, CMD_OBJ_CHAIN, &$2, &@$, $5);
chain_block_alloc '{' chain_block '}'
stmt_seperator
{
+ $4->location = @3;
handle_merge(&$4->handle, &$3);
handle_free(&$3);
close_scope(state);
}
;
-hook_spec : TYPE STRING HOOK HOOKNUM NUM
+hook_spec : TYPE STRING HOOK STRING NUM
{
$<chain>0->type = $2;
- $<chain>0->hooknum = $4;
+ $<chain>0->hookstr = chain_hookname_lookup($4);
+ if ($<chain>0->hookstr == NULL) {
+ erec_queue(error(&@4, "unknown hook name %s", $4),
+ state->msgs);
+ YYERROR;
+ }
$<chain>0->priority = $5;
$<chain>0->flags |= CHAIN_F_BASECHAIN;
}
- | TYPE STRING HOOK HOOKNUM DASH NUM
+ | TYPE STRING HOOK STRING DASH NUM
{
$<chain>0->type = $2;
- $<chain>0->hooknum = $4;
+ $<chain>0->hookstr = chain_hookname_lookup($4);
+ if ($<chain>0->hookstr == NULL) {
+ erec_queue(error(&@4, "unknown hook name %s", $4),
+ state->msgs);
+ YYERROR;
+ }
$<chain>0->priority = -$6;
$<chain>0->flags |= CHAIN_F_BASECHAIN;
}
#include <netinet/ip.h>
#include <linux/netfilter.h>
+#include <linux/netfilter_arp.h>
void handle_free(struct handle *h)
{
return NULL;
}
+static const char *chain_hookname_str_array[] = {
+ "prerouting",
+ "input",
+ "forward",
+ "postrouting",
+ "output",
+ NULL,
+};
+
+const char *chain_hookname_lookup(const char *name)
+{
+ int i;
+
+ for (i = 0; chain_hookname_str_array[i]; i++) {
+ if (!strcmp(name, chain_hookname_str_array[i]))
+ return chain_hookname_str_array[i];
+ }
+
+ return NULL;
+}
+
struct chain *chain_alloc(const char *name)
{
struct chain *chain;
return NULL;
}
-static const char *hooknum2str_array[NF_INET_NUMHOOKS] = {
- [NF_INET_PRE_ROUTING] = "NF_INET_PRE_ROUTING",
- [NF_INET_LOCAL_IN] = "NF_INET_LOCAL_IN",
- [NF_INET_FORWARD] = "NF_INET_FORWARD",
- [NF_INET_LOCAL_OUT] = "NF_INET_LOCAL_OUT",
- [NF_INET_POST_ROUTING] = "NF_INET_POST_ROUTING",
-};
-
-static const char *hooknum2str(unsigned int hooknum)
-{
- if (hooknum >= NF_INET_NUMHOOKS)
- return "UNKNOWN";
+static const char *hooknum2str(unsigned int family, unsigned int hooknum)
+{
+ switch (family) {
+ case NFPROTO_IPV4:
+ case NFPROTO_BRIDGE:
+ case NFPROTO_IPV6:
+ switch (hooknum) {
+ case NF_INET_PRE_ROUTING:
+ return "prerouting";
+ case NF_INET_LOCAL_IN:
+ return "input";
+ case NF_INET_FORWARD:
+ return "forward";
+ case NF_INET_POST_ROUTING:
+ return "postrouting";
+ case NF_INET_LOCAL_OUT:
+ return "output";
+ default:
+ break;
+ };
+ break;
+ case NFPROTO_ARP:
+ switch (hooknum) {
+ case NF_ARP_IN:
+ return "input";
+ case NF_ARP_FORWARD:
+ return "forward";
+ case NF_ARP_OUT:
+ return "output";
+ default:
+ break;
+ }
+ default:
+ break;
+ };
- return hooknum2str_array[hooknum];
+ return "unknown";
}
static void chain_print(const struct chain *chain)
printf("\tchain %s {\n", chain->handle.chain);
if (chain->flags & CHAIN_F_BASECHAIN) {
printf("\t\t type %s hook %s %u;\n", chain->type,
- hooknum2str(chain->hooknum), chain->priority);
+ hooknum2str(chain->handle.family, chain->hooknum),
+ chain->priority);
}
list_for_each_entry(rule, &chain->rules, list) {
printf("\t\t");
"=>" { return ARROW; }
"vmap" { return VMAP; }
-"NF_INET_PRE_ROUTING" { yylval->val = NF_INET_PRE_ROUTING; return HOOKNUM; }
-"NF_INET_LOCAL_IN" { yylval->val = NF_INET_LOCAL_IN; return HOOKNUM; }
-"NF_INET_FORWARD" { yylval->val = NF_INET_FORWARD; return HOOKNUM; }
-"NF_INET_LOCAL_OUT" { yylval->val = NF_INET_LOCAL_OUT; return HOOKNUM; }
-"NF_INET_POST_ROUTING" { yylval->val = NF_INET_POST_ROUTING; return HOOKNUM; }
-
"include" { return INCLUDE; }
"define" { return DEFINE; }