diff mbox series

[nft,1/5] src: add table_spec

Message ID 20180503110012.11277-1-pablo@netfilter.org
State Accepted
Delegated to: Pablo Neira
Headers show
Series [nft,1/5] src: add table_spec | expand

Commit Message

Pablo Neira Ayuso May 3, 2018, 11 a.m. UTC
Store location object in handle to improve error reporting.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/rule.h            |  7 ++++++-
 src/evaluate.c            | 42 +++++++++++++++++++++---------------------
 src/monitor.c             |  4 ++--
 src/netlink.c             | 40 ++++++++++++++++++++--------------------
 src/netlink_delinearize.c |  2 +-
 src/parser_bison.y        |  3 ++-
 src/rule.c                | 42 +++++++++++++++++++++---------------------
 7 files changed, 73 insertions(+), 67 deletions(-)
diff mbox series

Patch

diff --git a/include/rule.h b/include/rule.h
index ee22cf217ac6..88750f0a4b54 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -27,6 +27,11 @@  struct position_spec {
 	uint64_t		id;
 };
 
+struct table_spec {
+	struct location		location;
+	const char		*name;
+};
+
 /**
  * struct handle - handle for tables, chains, rules and sets
  *
@@ -42,7 +47,7 @@  struct position_spec {
  */
 struct handle {
 	uint32_t		family;
-	const char		*table;
+	struct table_spec	table;
 	const char		*chain;
 	const char		*set;
 	const char		*obj;
diff --git a/src/evaluate.c b/src/evaluate.c
index 4384e2710176..76125fcd884d 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -191,7 +191,7 @@  static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr)
 		table = table_lookup_global(ctx);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 ctx->cmd->handle.table);
+					 ctx->cmd->handle.table.name);
 
 		set = set_lookup(table, (*expr)->identifier);
 		if (set == NULL)
@@ -2747,7 +2747,7 @@  static int setelem_evaluate(struct eval_ctx *ctx, struct expr **expr)
 	table = table_lookup_global(ctx);
 	if (table == NULL)
 		return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-				 ctx->cmd->handle.table);
+				 ctx->cmd->handle.table.name);
 
 	set = set_lookup(table, ctx->cmd->handle.set);
 	if (set == NULL)
@@ -2770,7 +2770,7 @@  static int set_evaluate(struct eval_ctx *ctx, struct set *set)
 	table = table_lookup_global(ctx);
 	if (table == NULL)
 		return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-				 ctx->cmd->handle.table);
+				 ctx->cmd->handle.table.name);
 
 	if (!(set->flags & NFT_SET_INTERVAL) && set->automerge)
 		return set_error(ctx, set, "auto-merge only works with interval sets");
@@ -2832,7 +2832,7 @@  static int flowtable_evaluate(struct eval_ctx *ctx, struct flowtable *ft)
 	table = table_lookup_global(ctx);
 	if (table == NULL)
 		return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-				 ctx->cmd->handle.table);
+				 ctx->cmd->handle.table.name);
 
 	ft->hooknum = str2hooknum(NFPROTO_NETDEV, ft->hookstr);
 	if (ft->hooknum == NF_INET_NUMHOOKS)
@@ -2924,7 +2924,7 @@  static int chain_evaluate(struct eval_ctx *ctx, struct chain *chain)
 	table = table_lookup_global(ctx);
 	if (table == NULL)
 		return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-				 ctx->cmd->handle.table);
+				 ctx->cmd->handle.table.name);
 
 	if (chain == NULL) {
 		if (chain_lookup(table, &ctx->cmd->handle) == NULL) {
@@ -3088,7 +3088,7 @@  static int cmd_evaluate_get(struct eval_ctx *ctx, struct cmd *cmd)
 		table = table_lookup(&cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		set = set_lookup(table, cmd->handle.set);
 		if (set == NULL || set->flags & (NFT_SET_MAP | NFT_SET_EVAL))
 			return cmd_error(ctx, "Could not process rule: Set '%s' does not exist",
@@ -3111,7 +3111,7 @@  static int cmd_evaluate_list_obj(struct eval_ctx *ctx, const struct cmd *cmd,
 	table = table_lookup(&cmd->handle, ctx->cache);
 	if (table == NULL)
 		return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-				 cmd->handle.table);
+				 cmd->handle.table.name);
 	if (obj_lookup(table, cmd->handle.obj, obj_type) == NULL)
 		return cmd_error(ctx, "Could not process rule: Object '%s' does not exist",
 					 cmd->handle.obj);
@@ -3131,19 +3131,19 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 
 	switch (cmd->obj) {
 	case CMD_OBJ_TABLE:
-		if (cmd->handle.table == NULL)
+		if (cmd->handle.table.name == NULL)
 			return 0;
 
 		table = table_lookup(&cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		return 0;
 	case CMD_OBJ_SET:
 		table = table_lookup(&cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		set = set_lookup(table, cmd->handle.set);
 		if (set == NULL || set->flags & (NFT_SET_MAP | NFT_SET_EVAL))
 			return cmd_error(ctx, "Could not process rule: Set '%s' does not exist",
@@ -3153,7 +3153,7 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 		table = table_lookup(&cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		set = set_lookup(table, cmd->handle.set);
 		if (set == NULL || !(set->flags & NFT_SET_EVAL))
 			return cmd_error(ctx, "Could not process rule: Meter '%s' does not exist",
@@ -3163,7 +3163,7 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 		table = table_lookup(&cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		set = set_lookup(table, cmd->handle.set);
 		if (set == NULL || !(set->flags & NFT_SET_MAP))
 			return cmd_error(ctx, "Could not process rule: Map '%s' does not exist",
@@ -3173,7 +3173,7 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 		table = table_lookup(&cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		if (chain_lookup(table, &cmd->handle) == NULL)
 			return cmd_error(ctx, "Could not process rule: Chain '%s' does not exist",
 					 cmd->handle.chain);
@@ -3192,11 +3192,11 @@  static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_LIMITS:
 	case CMD_OBJ_SETS:
 	case CMD_OBJ_FLOWTABLES:
-		if (cmd->handle.table == NULL)
+		if (cmd->handle.table.name == NULL)
 			return 0;
 		if (table_lookup(&cmd->handle, ctx->cache) == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		return 0;
 	case CMD_OBJ_CHAINS:
 	case CMD_OBJ_RULESET:
@@ -3222,11 +3222,11 @@  static int cmd_evaluate_reset(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_QUOTA:
 	case CMD_OBJ_COUNTERS:
 	case CMD_OBJ_QUOTAS:
-		if (cmd->handle.table == NULL)
+		if (cmd->handle.table.name == NULL)
 			return 0;
 		if (table_lookup(&cmd->handle, ctx->cache) == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		return 0;
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
@@ -3259,7 +3259,7 @@  static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 		table = table_lookup(&cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		set = set_lookup(table, cmd->handle.set);
 		if (set == NULL || set->flags & (NFT_SET_MAP | NFT_SET_EVAL))
 			return cmd_error(ctx, "Could not process rule: Set '%s' does not exist",
@@ -3274,7 +3274,7 @@  static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 		table = table_lookup(&cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		set = set_lookup(table, cmd->handle.set);
 		if (set == NULL || !(set->flags & NFT_SET_MAP))
 			return cmd_error(ctx, "Could not process rule: Map '%s' does not exist",
@@ -3289,7 +3289,7 @@  static int cmd_evaluate_flush(struct eval_ctx *ctx, struct cmd *cmd)
 		table = table_lookup(&cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 cmd->handle.table);
+					 cmd->handle.table.name);
 		set = set_lookup(table, cmd->handle.set);
 		if (set == NULL || !(set->flags & NFT_SET_EVAL))
 			return cmd_error(ctx, "Could not process rule: Meter '%s' does not exist",
@@ -3316,7 +3316,7 @@  static int cmd_evaluate_rename(struct eval_ctx *ctx, struct cmd *cmd)
 		table = table_lookup(&ctx->cmd->handle, ctx->cache);
 		if (table == NULL)
 			return cmd_error(ctx, "Could not process rule: Table '%s' does not exist",
-					 ctx->cmd->handle.table);
+					 ctx->cmd->handle.table.name);
 		if (chain_lookup(table, &ctx->cmd->handle) == NULL)
 			return cmd_error(ctx, "Could not process rule: Chain '%s' does not exist",
 					 ctx->cmd->handle.chain);
diff --git a/src/monitor.c b/src/monitor.c
index 9249a21cfc0b..4310c3b8dc43 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -576,7 +576,7 @@  static void netlink_events_cache_deltable(struct netlink_mon_handler *monh,
 
 	nlt      = netlink_table_alloc(nlh);
 	h.family = nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY);
-	h.table  = nftnl_table_get_str(nlt, NFTNL_TABLE_NAME);
+	h.table.name  = nftnl_table_get_str(nlt, NFTNL_TABLE_NAME);
 
 	t = table_lookup(&h, monh->cache);
 	if (t == NULL)
@@ -722,7 +722,7 @@  static void netlink_events_cache_delobj(struct netlink_mon_handler *monh,
 
 	nlo      = netlink_obj_alloc(nlh);
 	h.family = nftnl_obj_get_u32(nlo, NFTNL_OBJ_FAMILY);
-	h.table  = nftnl_obj_get_str(nlo, NFTNL_OBJ_TABLE);
+	h.table.name  = nftnl_obj_get_str(nlo, NFTNL_OBJ_TABLE);
 
 	name     = nftnl_obj_get_str(nlo, NFTNL_OBJ_NAME);
 	type	 = nftnl_obj_get_u32(nlo, NFTNL_OBJ_TYPE);
diff --git a/src/netlink.c b/src/netlink.c
index 5fb42074d900..0c078d643344 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -125,8 +125,8 @@  struct nftnl_table *alloc_nftnl_table(const struct handle *h)
 		memory_allocation_error();
 
 	nftnl_table_set_u32(nlt, NFTNL_TABLE_FAMILY, h->family);
-	if (h->table != NULL)
-		nftnl_table_set(nlt, NFTNL_TABLE_NAME, h->table);
+	if (h->table.name != NULL)
+		nftnl_table_set(nlt, NFTNL_TABLE_NAME, h->table.name);
 	if (h->handle.id)
 		nftnl_table_set_u64(nlt, NFTNL_TABLE_HANDLE, h->handle.id);
 
@@ -142,7 +142,7 @@  struct nftnl_chain *alloc_nftnl_chain(const struct handle *h)
 		memory_allocation_error();
 
 	nftnl_chain_set_u32(nlc, NFTNL_CHAIN_FAMILY, h->family);
-	nftnl_chain_set_str(nlc, NFTNL_CHAIN_TABLE, h->table);
+	nftnl_chain_set_str(nlc, NFTNL_CHAIN_TABLE, h->table.name);
 	if (h->handle.id)
 		nftnl_chain_set_u64(nlc, NFTNL_CHAIN_HANDLE, h->handle.id);
 	if (h->chain != NULL)
@@ -160,7 +160,7 @@  struct nftnl_rule *alloc_nftnl_rule(const struct handle *h)
 		memory_allocation_error();
 
 	nftnl_rule_set_u32(nlr, NFTNL_RULE_FAMILY, h->family);
-	nftnl_rule_set_str(nlr, NFTNL_RULE_TABLE, h->table);
+	nftnl_rule_set_str(nlr, NFTNL_RULE_TABLE, h->table.name);
 	if (h->chain != NULL)
 		nftnl_rule_set_str(nlr, NFTNL_RULE_CHAIN, h->chain);
 	if (h->handle.id)
@@ -191,7 +191,7 @@  struct nftnl_set *alloc_nftnl_set(const struct handle *h)
 		memory_allocation_error();
 
 	nftnl_set_set_u32(nls, NFTNL_SET_FAMILY, h->family);
-	nftnl_set_set_str(nls, NFTNL_SET_TABLE, h->table);
+	nftnl_set_set_str(nls, NFTNL_SET_TABLE, h->table.name);
 	if (h->set != NULL)
 		nftnl_set_set_str(nls, NFTNL_SET_NAME, h->set);
 	if (h->set_id)
@@ -292,7 +292,7 @@  __alloc_nftnl_obj(const struct handle *h, uint32_t type)
 		memory_allocation_error();
 
 	nftnl_obj_set_u32(nlo, NFTNL_OBJ_FAMILY, h->family);
-	nftnl_obj_set_str(nlo, NFTNL_OBJ_TABLE, h->table);
+	nftnl_obj_set_str(nlo, NFTNL_OBJ_TABLE, h->table.name);
 	if (h->obj != NULL)
 		nftnl_obj_set_str(nlo, NFTNL_OBJ_NAME, h->obj);
 
@@ -539,7 +539,7 @@  static int list_rule_cb(struct nftnl_rule *nlr, void *arg)
 	chain  = nftnl_rule_get_str(nlr, NFTNL_RULE_CHAIN);
 
 	if (h->family != family ||
-	    strcmp(table, h->table) != 0 ||
+	    strcmp(table, h->table.name) != 0 ||
 	    (h->chain && strcmp(chain, h->chain) != 0))
 		return 0;
 
@@ -653,7 +653,7 @@  struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
 	chain = chain_alloc(nftnl_chain_get_str(nlc, NFTNL_CHAIN_NAME));
 	chain->handle.family =
 		nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FAMILY);
-	chain->handle.table  =
+	chain->handle.table.name  =
 		xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_TABLE));
 	chain->handle.handle.id =
 		nftnl_chain_get_u64(nlc, NFTNL_CHAIN_HANDLE);
@@ -695,7 +695,7 @@  static int list_chain_cb(struct nftnl_chain *nlc, void *arg)
 	name   = nftnl_chain_get_str(nlc, NFTNL_CHAIN_NAME);
 	family = nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FAMILY);
 
-	if (h->family != family || strcmp(table, h->table) != 0)
+	if (h->family != family || strcmp(table, h->table.name) != 0)
 		return 0;
 	if (h->chain && strcmp(name, h->chain) != 0)
 		return 0;
@@ -767,7 +767,7 @@  struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
 
 	table = table_alloc();
 	table->handle.family = nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY);
-	table->handle.table  = xstrdup(nftnl_table_get_str(nlt, NFTNL_TABLE_NAME));
+	table->handle.table.name = xstrdup(nftnl_table_get_str(nlt, NFTNL_TABLE_NAME));
 	table->flags	     = nftnl_table_get_u32(nlt, NFTNL_TABLE_FLAGS);
 	table->handle.handle.id = nftnl_table_get_u64(nlt, NFTNL_TABLE_HANDLE);
 
@@ -925,7 +925,7 @@  struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
 
 	set = set_alloc(&netlink_location);
 	set->handle.family = nftnl_set_get_u32(nls, NFTNL_SET_FAMILY);
-	set->handle.table  = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_TABLE));
+	set->handle.table.name = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_TABLE));
 	set->handle.set    = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_NAME));
 	set->automerge	   = automerge;
 
@@ -1062,7 +1062,7 @@  int netlink_list_sets(struct netlink_ctx *ctx, const struct handle *h)
 	struct nftnl_set_list *set_cache;
 	int err;
 
-	set_cache = mnl_nft_set_dump(ctx, h->family, h->table);
+	set_cache = mnl_nft_set_dump(ctx, h->family, h->table.name);
 	if (set_cache == NULL) {
 		if (errno == EINTR)
 			return -1;
@@ -1408,7 +1408,7 @@  struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
 
 	obj = obj_alloc(&netlink_location);
 	obj->handle.family = nftnl_obj_get_u32(nlo, NFTNL_OBJ_FAMILY);
-	obj->handle.table =
+	obj->handle.table.name =
 		xstrdup(nftnl_obj_get_str(nlo, NFTNL_OBJ_TABLE));
 	obj->handle.obj =
 		xstrdup(nftnl_obj_get_str(nlo, NFTNL_OBJ_NAME));
@@ -1465,7 +1465,7 @@  static struct nftnl_flowtable *alloc_nftnl_flowtable(const struct handle *h,
 		memory_allocation_error();
 
 	nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_FAMILY, h->family);
-	nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE, h->table);
+	nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE, h->table.name);
 	if (h->flowtable != NULL)
 		nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_NAME, h->flowtable);
 
@@ -1543,7 +1543,7 @@  int netlink_list_objs(struct netlink_ctx *ctx, const struct handle *h)
 	int err;
 
 	obj_cache = mnl_nft_obj_dump(ctx, h->family,
-				     h->table, NULL, 0, true, false);
+				     h->table.name, NULL, 0, true, false);
 	if (obj_cache == NULL) {
 		if (errno == EINTR)
 			return -1;
@@ -1564,7 +1564,7 @@  int netlink_reset_objs(struct netlink_ctx *ctx, const struct cmd *cmd,
 	int err;
 
 	obj_cache = mnl_nft_obj_dump(ctx, h->family,
-				     h->table, h->obj, type, dump, true);
+				     h->table.name, h->obj, type, dump, true);
 	if (obj_cache == NULL)
 		return -1;
 
@@ -1584,7 +1584,7 @@  netlink_delinearize_flowtable(struct netlink_ctx *ctx,
 	flowtable = flowtable_alloc(&netlink_location);
 	flowtable->handle.family =
 		nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FAMILY);
-	flowtable->handle.table =
+	flowtable->handle.table.name =
 		xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_TABLE));
 	flowtable->handle.flowtable =
 		xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_NAME));
@@ -1623,7 +1623,7 @@  int netlink_list_flowtables(struct netlink_ctx *ctx, const struct handle *h)
 	struct nftnl_flowtable_list *flowtable_cache;
 	int err;
 
-	flowtable_cache = mnl_nft_flowtable_dump(ctx, h->family, h->table);
+	flowtable_cache = mnl_nft_flowtable_dump(ctx, h->family, h->table.name);
 	if (flowtable_cache == NULL) {
 		if (errno == EINTR)
 			return -1;
@@ -1719,10 +1719,10 @@  static void trace_print_rule(const struct nftnl_trace *nlt,
 	struct handle h;
 
 	h.family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
-	h.table  = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
+	h.table.name  = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
 	h.chain  = nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN);
 
-	if (!h.table)
+	if (!h.table.name)
 		return;
 
 	table = table_lookup(&h, cache);
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 2126cf20c995..8b42850ecd43 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -2444,7 +2444,7 @@  struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
 
 	memset(&h, 0, sizeof(h));
 	h.family = nftnl_rule_get_u32(nlr, NFTNL_RULE_FAMILY);
-	h.table  = xstrdup(nftnl_rule_get_str(nlr, NFTNL_RULE_TABLE));
+	h.table.name  = xstrdup(nftnl_rule_get_str(nlr, NFTNL_RULE_TABLE));
 	h.chain  = xstrdup(nftnl_rule_get_str(nlr, NFTNL_RULE_CHAIN));
 	h.handle.id = nftnl_rule_get_u64(nlr, NFTNL_RULE_HANDLE);
 
diff --git a/src/parser_bison.y b/src/parser_bison.y
index f546b9edd42e..c104bc86fadb 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1845,7 +1845,8 @@  table_spec		:	family_spec	identifier
 			{
 				memset(&$$, 0, sizeof($$));
 				$$.family	= $1;
-				$$.table	= $2;
+				$$.table.location = @2;
+				$$.table.name	= $2;
 			}
 			;
 
diff --git a/src/rule.c b/src/rule.c
index 5693888c31db..6c2b4eea7c24 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -30,7 +30,7 @@ 
 
 void handle_free(struct handle *h)
 {
-	xfree(h->table);
+	xfree(h->table.name);
 	xfree(h->chain);
 	xfree(h->set);
 	xfree(h->flowtable);
@@ -40,8 +40,8 @@  void handle_merge(struct handle *dst, const struct handle *src)
 {
 	if (dst->family == 0)
 		dst->family = src->family;
-	if (dst->table == NULL && src->table != NULL)
-		dst->table = xstrdup(src->table);
+	if (dst->table.name == NULL && src->table.name != NULL)
+		dst->table.name = xstrdup(src->table.name);
 	if (dst->chain == NULL && src->chain != NULL)
 		dst->chain = xstrdup(src->chain);
 	if (dst->set == NULL && src->set != NULL)
@@ -270,7 +270,7 @@  struct set *set_lookup_global(uint32_t family, const char *table,
 	struct table *t;
 
 	h.family = family;
-	h.table = table;
+	h.table.name = table;
 
 	t = table_lookup(&h, cache);
 	if (t == NULL)
@@ -418,7 +418,7 @@  void set_print_plain(const struct set *s, struct output_ctx *octx)
 	struct print_fmt_options opts = {
 		.tab		= "",
 		.nl		= " ",
-		.table		= s->handle.table,
+		.table		= s->handle.table.name,
 		.family		= family2str(s->handle.family),
 		.stmt_separator	= "; ",
 	};
@@ -777,7 +777,7 @@  static void chain_print(const struct chain *chain, struct output_ctx *octx)
 void chain_print_plain(const struct chain *chain, struct output_ctx *octx)
 {
 	nft_print(octx, "chain %s %s %s", family2str(chain->handle.family),
-		  chain->handle.table, chain->handle.chain);
+		  chain->handle.table.name, chain->handle.chain);
 
 	if (chain->flags & CHAIN_F_BASECHAIN) {
 		nft_print(octx, " { type %s hook %s priority %d; policy %s; }",
@@ -842,7 +842,7 @@  struct table *table_lookup(const struct handle *h,
 
 	list_for_each_entry(table, &cache->list, list) {
 		if (table->handle.family == h->family &&
-		    !strcmp(table->handle.table, h->table))
+		    !strcmp(table->handle.table.name, h->table.name))
 			return table;
 	}
 	return NULL;
@@ -884,7 +884,7 @@  static void table_print(const struct table *table, struct output_ctx *octx)
 	const char *delim = "";
 	const char *family = family2str(table->handle.family);
 
-	nft_print(octx, "table %s %s {", family, table->handle.table);
+	nft_print(octx, "table %s %s {", family, table->handle.table.name);
 	if (octx->handle > 0)
 		nft_print(octx, " # handle %" PRIu64, table->handle.handle.id);
 	nft_print(octx, "\n");
@@ -1318,7 +1318,7 @@  static int do_list_sets(struct netlink_ctx *ctx, struct cmd *cmd)
 
 		nft_print(ctx->octx, "table %s %s {\n",
 			  family2str(table->handle.family),
-			  table->handle.table);
+			  table->handle.table.name);
 
 		list_for_each_entry(set, &table->sets, list) {
 			if (cmd->obj == CMD_OBJ_SETS &&
@@ -1543,7 +1543,7 @@  void obj_print_plain(const struct obj *obj, struct output_ctx *octx)
 	struct print_fmt_options opts = {
 		.tab		= "",
 		.nl		= " ",
-		.table		= obj->handle.table,
+		.table		= obj->handle.table.name,
 		.family		= family2str(obj->handle.family),
 	};
 
@@ -1567,10 +1567,10 @@  static int do_list_obj(struct netlink_ctx *ctx, struct cmd *cmd, uint32_t type)
 
 		nft_print(ctx->octx, "table %s %s {\n",
 			  family2str(table->handle.family),
-			  table->handle.table);
+			  table->handle.table.name);
 
-		if (cmd->handle.table != NULL &&
-		    strcmp(cmd->handle.table, table->handle.table)) {
+		if (cmd->handle.table.name != NULL &&
+		    strcmp(cmd->handle.table.name, table->handle.table.name)) {
 			nft_print(ctx->octx, "}\n");
 			continue;
 		}
@@ -1686,7 +1686,7 @@  static int do_list_flowtables(struct netlink_ctx *ctx, struct cmd *cmd)
 
 		nft_print(ctx->octx, "table %s %s {\n",
 			  family2str(table->handle.family),
-			  table->handle.table);
+			  table->handle.table.name);
 
 		list_for_each_entry(flowtable, &table->flowtables, list) {
 			flowtable_print_declaration(flowtable, &opts, ctx->octx);
@@ -1709,13 +1709,13 @@  static int do_list_ruleset(struct netlink_ctx *ctx, struct cmd *cmd)
 			continue;
 
 		cmd->handle.family = table->handle.family;
-		cmd->handle.table = table->handle.table;
+		cmd->handle.table.name = table->handle.table.name;
 
 		if (do_list_table(ctx, cmd, table) < 0)
 			return -1;
 	}
 
-	cmd->handle.table = NULL;
+	cmd->handle.table.name = NULL;
 
 	return 0;
 }
@@ -1731,7 +1731,7 @@  static int do_list_tables(struct netlink_ctx *ctx, struct cmd *cmd)
 
 		nft_print(ctx->octx, "table %s %s\n",
 			  family2str(table->handle.family),
-			  table->handle.table);
+			  table->handle.table.name);
 	}
 
 	return 0;
@@ -1742,7 +1742,7 @@  static void table_print_declaration(struct table *table,
 {
 	nft_print(octx, "table %s %s {\n",
 		  family2str(table->handle.family),
-		  table->handle.table);
+		  table->handle.table.name);
 }
 
 static int do_list_chain(struct netlink_ctx *ctx, struct cmd *cmd,
@@ -1813,12 +1813,12 @@  static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
 {
 	struct table *table = NULL;
 
-	if (cmd->handle.table != NULL)
+	if (cmd->handle.table.name != NULL)
 		table = table_lookup(&cmd->handle, ctx->cache);
 
 	switch (cmd->obj) {
 	case CMD_OBJ_TABLE:
-		if (!cmd->handle.table)
+		if (!cmd->handle.table.name)
 			return do_list_tables(ctx, cmd);
 		return do_list_table(ctx, cmd, table);
 	case CMD_OBJ_CHAIN:
@@ -1897,7 +1897,7 @@  static int do_command_get(struct netlink_ctx *ctx, struct cmd *cmd)
 {
 	struct table *table = NULL;
 
-	if (cmd->handle.table != NULL)
+	if (cmd->handle.table.name != NULL)
 		table = table_lookup(&cmd->handle, ctx->cache);
 
 	switch (cmd->obj) {