From c74f398c58e7b77ca1c82a15d0b2e9eed4fb82ad Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 24 Oct 2012 13:40:12 +0200 Subject: automatic creation of built-in table and chains In order to emulate the iptables behaviour, this patch changes the current behaviour to: 1st) check if the table and chains are built-in. 2nd) If they don't exists, create them. If they exists, don't touch them. The automatic creation happens in the -I and -P paths. We should provide a new command to allow to delete (unregister) built-in tables and chains. It would be similar to unloading the iptable_X module that registers the custom table. This is not done for other commands like -C or -D since they will fail while trying to find the rule in the kernel if such combination of chain and table does not exists. Signed-off-by: Pablo Neira Ayuso --- iptables/nft.c | 143 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 38 deletions(-) (limited to 'iptables') diff --git a/iptables/nft.c b/iptables/nft.c index 91383bfb..9eaa2ac1 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -82,7 +82,7 @@ static int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, return 0; } -static void nft_table_init_one(struct nft_handle *h, const char *name, int portid) +static void nft_table_builtin_add(struct nft_handle *h, const char *table) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; @@ -92,7 +92,7 @@ static void nft_table_init_one(struct nft_handle *h, const char *name, int porti if (t == NULL) return; - nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)name); + nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)table); nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET, NLM_F_ACK|NLM_F_EXCL, h->seq); @@ -111,7 +111,7 @@ static void nft_table_init_one(struct nft_handle *h, const char *name, int porti #define SECURITY 3 #define TABLES_MAX 4 -static struct default_table { +static struct builtin_table { const char *name; uint32_t prio; } tables[TABLES_MAX] = { @@ -134,15 +134,7 @@ static struct default_table { /* nat already registered by nf_tables */ }; -static void nft_table_init(struct nft_handle *h) -{ - int i; - - for (i=0; iportid); -} - -static struct default_chain { +static struct builtin_chain { const char *name; uint32_t hook; } chains[TABLES_MAX][NF_IP_NUMHOOKS] = { @@ -208,17 +200,15 @@ static struct default_chain { }, }; -static void -nft_chain_default_add(struct nft_handle *h, struct default_table *table, - struct default_chain *chain, int policy) +static struct nft_chain * +nft_chain_builtin_alloc(struct builtin_table *table, + struct builtin_chain *chain, int policy) { - char buf[MNL_SOCKET_BUFFER_SIZE]; - struct nlmsghdr *nlh; struct nft_chain *c; c = nft_chain_alloc(); if (c == NULL) - return; + return NULL; nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table->name); nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain->name); @@ -226,6 +216,21 @@ nft_chain_default_add(struct nft_handle *h, struct default_table *table, nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_PRIO, table->prio); nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy); + return c; +} + +static void +nft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table, + struct builtin_chain *chain, int policy) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + struct nft_chain *c; + + c = nft_chain_builtin_alloc(table, chain, policy); + if (c == NULL) + return; + nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET, NLM_F_ACK|NLM_F_EXCL, h->seq); nft_chain_nlmsg_build_payload(nlh, c); @@ -233,23 +238,72 @@ nft_chain_default_add(struct nft_handle *h, struct default_table *table, if (mnl_talk(h, nlh, NULL, NULL) < 0) { if (errno != EEXIST) - perror("mnl_talk:nft_chain_default_add"); + perror("mnl_talk:nft_chain_builtin_add"); } } -static void nft_chain_init(struct nft_handle *h) +/* find if built-in table already exists */ +static struct builtin_table *nft_table_builtin_find(const char *table) +{ + int i; + bool found = false; + + for (i=0; iportid = mnl_socket_get_portid(h->nl); -/* - * In case we want to inconditionally register all tables / chain. - * This is not flexible and performance consuming. - * - * nft_table_init(h); - * nft_chain_init(h); - */ - return 0; } @@ -326,14 +372,32 @@ __nft_chain_set(struct nft_handle *h, const char *table, struct nlmsghdr *nlh; struct nft_chain *c; int ret; + struct builtin_table *_t; + struct builtin_chain *_c; - c = nft_chain_alloc(); - if (c == NULL) - return -1; + _t = nft_table_builtin_find(table); + /* if this built-in table does not exists, create it */ + if (_t != NULL) + nft_table_builtin_add(h, table); + + _c = nft_chain_builtin_find(table, chain); + if (_c != NULL) { + /* This is a built-in chain */ + c = nft_chain_builtin_alloc(_t, _c, policy); + if (c == NULL) + return -1; + + } else { + /* This is a custom chain */ + c = nft_chain_alloc(); + if (c == NULL) + return -1; + + nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table); + nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain); + nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy); + } - nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table); - nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain); - nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy); if (counters) { nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES, counters->bcnt); @@ -546,6 +610,9 @@ nft_rule_add(struct nft_handle *h, const char *chain, const char *table, uint32_t op; int flags = append ? NLM_F_APPEND : 0; + /* If built-in chain does not exists, create it */ + nft_chain_builtin_init(h, table, chain, NF_ACCEPT); + nft_fn = nft_rule_add; r = nft_rule_alloc(); -- cgit v1.2.3