summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/evaluate.c43
-rw-r--r--src/parser.y21
-rw-r--r--src/rule.c74
-rw-r--r--src/scanner.l6
4 files changed, 119 insertions, 25 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index 85c647e5..29fa32bd 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -14,6 +14,8 @@
#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>
@@ -54,6 +56,8 @@ static int __fmtstring(4, 5) __stmt_binary_error(struct eval_ctx *ctx,
__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,
@@ -1247,10 +1251,49 @@ static int rule_evaluate(struct eval_ctx *ctx, struct rule *rule)
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)
diff --git a/src/parser.y b/src/parser.y
index f0eb8e32..ec78e7fd 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -155,7 +155,6 @@ static void location_update(struct location *loc, struct location *rhs, int n)
%token DEFINE "define"
%token HOOK "hook"
-%token <val> HOOKNUM "hooknum"
%token TABLE "table"
%token TABLES "tables"
%token CHAIN "chain"
@@ -550,6 +549,7 @@ add_cmd : TABLE table_spec
| 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);
@@ -667,6 +667,7 @@ table_block : /* empty */ { $$ = $<table>-1; }
chain_block_alloc '{' chain_block '}'
stmt_seperator
{
+ $4->location = @3;
handle_merge(&$4->handle, &$3);
handle_free(&$3);
close_scope(state);
@@ -766,17 +767,27 @@ map_block : /* empty */ { $$ = $<set>-1; }
}
;
-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;
}
diff --git a/src/rule.c b/src/rule.c
index 73054bad..f493cd48 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -21,6 +21,7 @@
#include <netinet/ip.h>
#include <linux/netfilter.h>
+#include <linux/netfilter_arp.h>
void handle_free(struct handle *h)
{
@@ -189,6 +190,27 @@ struct symbol *symbol_lookup(const struct scope *scope, const char *identifier)
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;
@@ -228,20 +250,43 @@ struct chain *chain_lookup(const struct table *table, const struct handle *h)
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)
@@ -251,7 +296,8 @@ 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");
diff --git a/src/scanner.l b/src/scanner.l
index 59e0aac7..cee6aa6e 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -212,12 +212,6 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"=>" { 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; }