[PATCH v2] tests: shell: fetch rule handle with '-a' option and then delete rule

2018-01-23 Thread Harsha Sharma
Fetch rule handle and then delete rule via that rule handle.

Signed-off-by: Harsha Sharma 
---
Changes in v2:
 - No need to use grep

 tests/shell/testcases/cache/0001_cache_handling_0 | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/shell/testcases/cache/0001_cache_handling_0 
b/tests/shell/testcases/cache/0001_cache_handling_0
index 9a73769..3693f15 100755
--- a/tests/shell/testcases/cache/0001_cache_handling_0
+++ b/tests/shell/testcases/cache/0001_cache_handling_0
@@ -24,6 +24,7 @@ table inet test {
 set -e
 
 $NFT -f $tmpfile
-$NFT delete rule inet test test handle 2
+rule_handle=$($NFT list ruleset -a | awk '/saddr/{print $NF}')
+$NFT delete rule inet test test handle $rule_handle
 $NFT delete set inet test test
 $NFT -f $tmpfile
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] netfilter: nf_tables: Add extra bits for object handles

2018-01-23 Thread Harsha Sharma
Add extra bits for table, chain, sets and object handle.

Signed-off-by: Harsha Sharma 
---
 net/netfilter/nf_tables_trace.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/nf_tables_trace.c b/net/netfilter/nf_tables_trace.c
index e1dc527a493b..f804c3924d32 100644
--- a/net/netfilter/nf_tables_trace.c
+++ b/net/netfilter/nf_tables_trace.c
@@ -212,7 +212,11 @@ void nft_trace_notify(struct nft_traceinfo *info)
nla_total_size(sizeof(__be16)) +/* oiftype */
nla_total_size(sizeof(u32)) +   /* mark */
nla_total_size(sizeof(u32)) +   /* nfproto */
-   nla_total_size(sizeof(u32));/* policy */
+   nla_total_size(sizeof(u32)); +  /* policy */
+   nla_total_size_64bit(sizeof(__be64)) +  /* table handle */
+   nla_total_size_64bit(sizeof(__be64)) +  /* chain handle */
+   nla_total_size_64bit(sizeof(__be64)) +  /* set handle */
+   nla_total_size_64bit(sizeof(__be64))/* object handle */
 
if (nft_trace_have_verdict_chain(info))
size += nla_total_size(strlen(info->verdict->chain->name)); /* 
jump target */
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] tests: shell: fetch rule handle with '-a' option and then delete

2018-01-23 Thread Dmitry V. Levin
On Wed, Jan 24, 2018 at 04:47:39AM +0530, Harsha Sharma wrote:
> Fetch rule handle and then delete rule via that rule handle.
> 
> Signed-off-by: Harsha Sharma 
> ---
>  tests/shell/testcases/cache/0001_cache_handling_0 | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/shell/testcases/cache/0001_cache_handling_0 
> b/tests/shell/testcases/cache/0001_cache_handling_0
> index 9a73769..2bcb8c5 100755
> --- a/tests/shell/testcases/cache/0001_cache_handling_0
> +++ b/tests/shell/testcases/cache/0001_cache_handling_0
> @@ -24,6 +24,7 @@ table inet test {
>  set -e
>  
>  $NFT -f $tmpfile
> -$NFT delete rule inet test test handle 2
> +rule_handle=$($NFT list ruleset -a | grep "saddr" | awk '{print $NF}')
> +$NFT delete rule inet test test handle $rule_handle

No need to use both grep and awk in the same pipeline.

If you prefer awk, then
  awk '/saddr/ {print $NF}'
would do the same thing.


-- 
ldv


signature.asc
Description: PGP signature


[PATCH] tests: shell: fetch rule handle with '-a' option and then delete

2018-01-23 Thread Harsha Sharma
Fetch rule handle and then delete rule via that rule handle.

Signed-off-by: Harsha Sharma 
---
 tests/shell/testcases/cache/0001_cache_handling_0 | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/shell/testcases/cache/0001_cache_handling_0 
b/tests/shell/testcases/cache/0001_cache_handling_0
index 9a73769..2bcb8c5 100755
--- a/tests/shell/testcases/cache/0001_cache_handling_0
+++ b/tests/shell/testcases/cache/0001_cache_handling_0
@@ -24,6 +24,7 @@ table inet test {
 set -e
 
 $NFT -f $tmpfile
-$NFT delete rule inet test test handle 2
+rule_handle=$($NFT list ruleset -a | grep "saddr" | awk '{print $NF}')
+$NFT delete rule inet test test handle $rule_handle
 $NFT delete set inet test test
 $NFT -f $tmpfile
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] doc/nft.xml: Add deletion for objects via handles

2018-01-23 Thread Harsha Sharma
Add documentation for deletion of tables, chains, sets and objects
via unique handles.

Signed-off-by: Harsha Sharma 
---
 doc/nft.xml | 37 -
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/doc/nft.xml b/doc/nft.xml
index 9e979af..c1ab48d 100644
--- a/doc/nft.xml
+++ b/doc/nft.xml
@@ -141,7 +141,7 @@ vi:ts=4 sw=4
-a, --handle


-   Show rule handles in output.
+   Show object handles in output.



@@ -555,6 +555,14 @@ filter input iif $int_ifs accept
family
table

+   
+   
+   delete
+   
+   table
+   family
+handle 
handle
+   

 

@@ -646,6 +654,15 @@ filter input iif $int_ifs accept
table
chain

+   
+   
+   delete
+   
+   chain
+   family
+   table
+handle 
handle
+   

rename
chain
@@ -896,6 +913,15 @@ filter input iif $int_ifs accept
table
set

+   
+   
+   delete
+   
+set
+   family
+   table
+handle 
handle
+   


add
@@ -1174,6 +1200,15 @@ filter input iif $int_ifs accept
table
object

+   
+   
+   delete
+   
+type
+   family
+   table
+handle 
handle
+   


Stateful objects are attached to tables and are 
identified by an unique name. They group stateful information from rules, to 
reference them in rules the keywords "type name" are used e.g. "counter name".
-- 
2.14.1

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] build: do install libipset/args.h

2018-01-23 Thread Jozsef Kadlecsik
Hi Jan,

On Mon, 22 Jan 2018, Jan Engelhardt wrote:

> libipset/types.h includes args.h, therefore args.h must be installed
> too.
> 
> Signed-off-by: Jan Engelhardt 
> ---
>  include/libipset/Makefile.am | 1 +
>  1 file changed, 1 insertion(+)

Yes, it's required. Thanks, patch is applied.

Best regards,
Jozsef 
-
E-mail  : kad...@blackhole.kfki.hu, kadlecsik.joz...@wigner.mta.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : Wigner Research Centre for Physics, Hungarian Academy of Sciences
  H-1525 Budapest 114, POB. 49, Hungary
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: question about UNDEFINE/REDEFINE

2018-01-23 Thread David Fabian
Hello Pablo,

Dne úterý 23. ledna 2018 12:07:28 CET, Pablo Neira Ayuso napsal(a):
> I'm asking here because I would need to understand better how you've
> structured your scripts, if you could explain a bit more, we would
> appreciate.

I have packed an excerpt of a playground FW with two VLANs 3 and 54. The 
configuration already uses my redefine keyword.

ftp://ftp.bosson.eu/pub/tmp/nftables_excerpt.tar.gz

The intended use case is to call nft -f fw-on and reload the firewall from 
scratch every time there is a config change. I don't know how a cmdline 
parameter would help us with it. Maybe if we would wrap nft calls with bash 
scripts but that would defeat the purpose of using the nft scripting 
capabilities in the first place.

The most important for us is to have the FW logically structured for every 
customer and every FW rule related to a customer should be in his/her VLAN 
config file.

-- 
Best regards,

David Fabian
Cluster Design, s.r.o.

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nft 3/6] src: delete flowtable

2018-01-23 Thread Pablo Neira Ayuso
This patch allows you to delete an existing flowtable:

 # nft delete flowtable x m

Signed-off-by: Pablo Neira Ayuso 
---
 include/mnl.h  |  3 +++
 include/netlink.h  |  3 +++
 src/evaluate.c |  1 +
 src/mnl.c  | 16 
 src/netlink.c  | 18 ++
 src/parser_bison.y |  4 
 src/rule.c |  3 +++
 7 files changed, 48 insertions(+)

diff --git a/include/mnl.h b/include/mnl.h
index 470b29787fa6..1b2450a9388e 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -95,6 +95,9 @@ mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, 
const char *table);
 int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo,
struct nftnl_batch *batch, unsigned int flags,
uint32_t seqnum);
+int mnl_nft_flowtable_batch_del(struct nftnl_flowtable *flow,
+   struct nftnl_batch *batch, unsigned int flags,
+   uint32_t seqnum);
 
 struct nftnl_ruleset *mnl_nft_ruleset_dump(struct netlink_ctx *ctx,
   uint32_t family);
diff --git a/include/netlink.h b/include/netlink.h
index b80acbabe80f..9ae021a8dd49 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -188,6 +188,9 @@ extern int netlink_list_flowtables(struct netlink_ctx *ctx,
 extern int netlink_add_flowtable(struct netlink_ctx *ctx,
 const struct handle *h, struct flowtable *ft,
 uint32_t flags);
+extern int netlink_delete_flowtable(struct netlink_ctx *ctx,
+   const struct handle *h,
+   struct location *loc);
 
 extern void netlink_dump_chain(const struct nftnl_chain *nlc,
   struct netlink_ctx *ctx);
diff --git a/src/evaluate.c b/src/evaluate.c
index 70a61c72838a..892d1e0c8c5b 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -3118,6 +3118,7 @@ static int cmd_evaluate_delete(struct eval_ctx *ctx, 
struct cmd *cmd)
case CMD_OBJ_RULE:
case CMD_OBJ_CHAIN:
case CMD_OBJ_TABLE:
+   case CMD_OBJ_FLOWTABLE:
case CMD_OBJ_COUNTER:
case CMD_OBJ_QUOTA:
case CMD_OBJ_CT_HELPER:
diff --git a/src/mnl.c b/src/mnl.c
index be6e05da5936..f620a3bda8d5 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1027,6 +1027,22 @@ int mnl_nft_flowtable_batch_add(struct nftnl_flowtable 
*flo,
return 0;
 }
 
+int mnl_nft_flowtable_batch_del(struct nftnl_flowtable *flo,
+   struct nftnl_batch *batch, unsigned int flags,
+   uint32_t seqnum)
+{
+   struct nlmsghdr *nlh;
+
+   nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(batch),
+   NFT_MSG_DELFLOWTABLE,
+   nftnl_flowtable_get_u32(flo, 
NFTNL_FLOWTABLE_FAMILY),
+   flags, seqnum);
+   nftnl_flowtable_nlmsg_build_payload(nlh, flo);
+   mnl_nft_batch_continue(batch);
+
+   return 0;
+}
+
 /*
  * ruleset
  */
diff --git a/src/netlink.c b/src/netlink.c
index 89513584a50f..56c6b6a3725e 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1820,6 +1820,24 @@ int netlink_add_flowtable(struct netlink_ctx *ctx, const 
struct handle *h,
return err;
 }
 
+int netlink_delete_flowtable(struct netlink_ctx *ctx, const struct handle *h,
+struct location *loc)
+{
+   struct nftnl_flowtable *flo;
+   int err;
+
+   flo = alloc_nftnl_flowtable(h, NULL);
+   netlink_dump_flowtable(flo, ctx);
+
+   err = mnl_nft_flowtable_batch_del(flo, ctx->batch, 0, ctx->seqnum);
+   if (err < 0)
+   netlink_io_error(ctx, loc, "Could not delete flowtable: %s",
+strerror(errno));
+   nftnl_flowtable_free(flo);
+
+   return err;
+}
+
 static int list_obj_cb(struct nftnl_obj *nls, void *arg)
 {
struct netlink_ctx *ctx = arg;
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 45cc3b4114ff..0623cd12aeb5 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1023,6 +1023,10 @@ delete_cmd   :   TABLE   
table_spec
{
$$ = cmd_alloc(CMD_DELETE, CMD_OBJ_SETELEM, 
&$2, &@$, $3);
}
+   |   FLOWTABLE   flowtable_spec
+   {
+   $$ = cmd_alloc(CMD_DELETE, CMD_OBJ_FLOWTABLE, 
&$2, &@$, NULL);
+   }
|   COUNTER obj_spec
{
$$ = cmd_alloc(CMD_DELETE, CMD_OBJ_COUNTER, 
&$2, &@$, NULL);
diff --git a/src/rule.c b/src/rule.c
index 8a38bcc66a66..b06f30eb5528 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -1174,6 +1174,9 @@ static int do_command_delete(struct netlink_ctx *ctx, 
struct cmd 

[PATCH nft 4/6] src: flow offload support

2018-01-23 Thread Pablo Neira Ayuso
This patch allows us to refer to existing flowtables:

 # nft add rule x x flow offload @m

Packets matching this rule create an entry in the flow table 'm', hence,
follow up packets that get to the flowtable at ingress bypass the
classic forwarding path.

Signed-off-by: Pablo Neira Ayuso 
---
 include/ct.h  |  2 ++
 include/statement.h   |  9 +
 src/ct.c  | 23 +++
 src/evaluate.c|  1 +
 src/netlink_delinearize.c | 11 +++
 src/netlink_linearize.c   | 13 +
 src/parser_bison.y|  5 +
 src/scanner.l |  1 +
 8 files changed, 65 insertions(+)

diff --git a/include/ct.h b/include/ct.h
index ec5d55d85dd0..2c3392d36c94 100644
--- a/include/ct.h
+++ b/include/ct.h
@@ -29,6 +29,8 @@ extern struct expr *ct_expr_alloc(const struct location *loc,
 extern void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr);
 
 extern struct stmt *notrack_stmt_alloc(const struct location *loc);
+extern struct stmt *flow_offload_stmt_alloc(const struct location *loc,
+   const char *table_name);
 
 extern const struct datatype ct_dir_type;
 extern const struct datatype ct_state_type;
diff --git a/include/statement.h b/include/statement.h
index 23a551b67f2b..993727c933f2 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -10,6 +10,12 @@ extern struct stmt *expr_stmt_alloc(const struct location 
*loc,
 extern struct stmt *verdict_stmt_alloc(const struct location *loc,
   struct expr *expr);
 
+struct flow_stmt {
+   const char  *table_name;
+};
+
+struct stmt *flow_stmt_alloc(const struct location *loc, const char *name);
+
 struct objref_stmt {
uint32_ttype;
struct expr *expr;
@@ -229,6 +235,7 @@ struct xt_stmt {
  * @STMT_NOTRACK:  notrack statement
  * @STMT_OBJREF:   stateful object reference statement
  * @STMT_EXTHDR:   extension header statement
+ * @STMT_FLOW_OFFLOAD: flow offload statement
  */
 enum stmt_types {
STMT_INVALID,
@@ -254,6 +261,7 @@ enum stmt_types {
STMT_NOTRACK,
STMT_OBJREF,
STMT_EXTHDR,
+   STMT_FLOW_OFFLOAD,
 };
 
 /**
@@ -314,6 +322,7 @@ struct stmt {
struct fwd_stmt fwd;
struct xt_stmt  xt;
struct objref_stmt  objref;
+   struct flow_stmtflow;
};
 };
 
diff --git a/src/ct.c b/src/ct.c
index d5347974bd0d..fb908531862b 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -456,3 +456,26 @@ struct stmt *notrack_stmt_alloc(const struct location *loc)
 {
return stmt_alloc(loc, _stmt_ops);
 }
+
+static void flow_offload_stmt_print(const struct stmt *stmt,
+   struct output_ctx *octx)
+{
+   printf("flow offload @%s", stmt->flow.table_name);
+}
+
+static const struct stmt_ops flow_offload_stmt_ops = {
+   .type   = STMT_FLOW_OFFLOAD,
+   .name   = "flow_offload",
+   .print  = flow_offload_stmt_print,
+};
+
+struct stmt *flow_offload_stmt_alloc(const struct location *loc,
+const char *table_name)
+{
+   struct stmt *stmt;
+
+   stmt = stmt_alloc(loc, _offload_stmt_ops);
+   stmt->flow.table_name   = table_name;
+
+   return stmt;
+}
diff --git a/src/evaluate.c b/src/evaluate.c
index 892d1e0c8c5b..14fadd538850 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2773,6 +2773,7 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
case STMT_LIMIT:
case STMT_QUOTA:
case STMT_NOTRACK:
+   case STMT_FLOW_OFFLOAD:
return 0;
case STMT_EXPRESSION:
return stmt_evaluate_expr(ctx, stmt);
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 2637f4baaec4..bbc9ccead1bf 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -677,6 +677,16 @@ static void netlink_parse_notrack(struct netlink_parse_ctx 
*ctx,
ctx->stmt = notrack_stmt_alloc(loc);
 }
 
+static void netlink_parse_flow_offload(struct netlink_parse_ctx *ctx,
+  const struct location *loc,
+  const struct nftnl_expr *nle)
+{
+   const char *table_name;
+
+   table_name = xstrdup(nftnl_expr_get_str(nle, 
NFTNL_EXPR_FLOW_TABLE_NAME));
+   ctx->stmt = flow_offload_stmt_alloc(loc, table_name);
+}
+
 static void netlink_parse_ct_stmt(struct netlink_parse_ctx *ctx,
  const struct location *loc,
  const struct nftnl_expr *nle)
@@ -1252,6 +1262,7 @@ static const struct {
{ .name = "hash",   .parse = netlink_parse_hash },
{ .name = "fib",.parse = netlink_parse_fib },
{ .name = "tcpopt", .parse = netlink_parse_exthdr },
+   { 

[PATCH nft 6/6] doc: nft: document flowtable

2018-01-23 Thread Pablo Neira Ayuso
Document the new flowtable objects available since Linux kernel 4.16-rc.

Signed-off-by: Pablo Neira Ayuso 
---
 doc/nft.xml | 103 
 1 file changed, 103 insertions(+)

diff --git a/doc/nft.xml b/doc/nft.xml
index 9e979af3c280..1b901c17b5a0 100644
--- a/doc/nft.xml
+++ b/doc/nft.xml
@@ -1160,6 +1160,91 @@ filter input iif $int_ifs accept

 

+   Flowtables
+   
+   
+   
+   add
+   create
+   
+   flowtable
+   family
+   table
+   flowtable
+   
+   hook hook
+   priority 
priority ;
+   devices = { 
device[,...] } ;
+   
+   
+   
+   
+   delete
+   list
+   
+   flowtable
+   family
+   table
+   flowtable
+   
+   
+
+   
+   Flowtables allow you to accelerate packet forwarding in 
software.
+   Flowtables entries are represented through a tuple that 
is composed of the
+   input interface, source and destination address, source 
and destination
+   port; and layer 3/4 protocols. Each entry also caches 
the destination
+   interface and the gateway address - to update the 
destination link-layer
+   address - to forward packets. The ttl and hoplimit 
fields are also
+   decremented. Hence, flowtables provides an alternative 
path that allow
+   packets to bypass the classic forwarding path. 
Flowtables reside in the
+   ingress hook, that is located before the prerouting 
hook. You can select
+   what flows you want to offload through the 
flow offload
+   expression from the forward chain. 
Flowtables are
+   identified by their address family and their name. The 
address family
+   must be one of
+
+   
+   ip
+   ip6
+   inet
+   .
+
+   The inet address family is a dummy 
family which is used to create
+   hybrid IPv4/IPv6 tables.
+
+   When no address family is specified, 
ip is used by default.
+   
+
+   
+   
+   add
+   
+   
+   Add a new flowtable for the 
given family with the given name.
+   
+   
+   
+   
+   delete
+   
+   
+   Delete the specified flowtable.
+   
+   
+   
+   
+   list
+   
+   
+   List all flowtables.
+   
+   
+   
+   
+   
+
+   
Stateful objects


@@ -4917,6 +5002,24 @@ add rule nat prerouting tcp dport 22 redirect to :



+
+   
+   Flow offload statement
+   
+   A flow offload statement allows us to select 
what flows
+   you want to accelerate forwarding through layer 
3 network
+   stack bypass. You have to specify the flowtable 
name where
+   you want to offload this flow.
+   
+   
+   
+   flow offload
+   @flowtable
+   
+   
+
+  

[PATCH nft 1/6] src: support for flowtable listing

2018-01-23 Thread Pablo Neira Ayuso
This patch allows you to dump existing flowtable.

 # nft list ruleset
 table ip x {
flowtable x {
hook ingress priority 10
devices = { eth0, tap0 }
}
 }

You can also list existing flowtables via:

 # nft list flowtables
 table ip x {
flowtable x {
hook ingress priority 10
devices = { eth0, tap0 }
}
 }

 You need a Linux kernel >= 4.16-rc to test this new feature.

Signed-off-by: Pablo Neira Ayuso 
---
 include/linux/netfilter/nf_tables.h |   6 ++
 include/mnl.h   |   3 +
 include/netlink.h   |   4 ++
 include/rule.h  |  24 +++
 src/evaluate.c  |   1 +
 src/mnl.c   |  58 +
 src/netlink.c   |  65 +++
 src/parser_bison.y  |   6 ++
 src/rule.c  | 122 
 src/scanner.l   |   2 +
 10 files changed, 291 insertions(+)

diff --git a/include/linux/netfilter/nf_tables.h 
b/include/linux/netfilter/nf_tables.h
index 2efbf9744c2a..b2d36004b85d 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -92,6 +92,9 @@ enum nft_verdicts {
  * @NFT_MSG_GETOBJ: get a stateful object (enum nft_obj_attributes)
  * @NFT_MSG_DELOBJ: delete a stateful object (enum nft_obj_attributes)
  * @NFT_MSG_GETOBJ_RESET: get and reset a stateful object (enum 
nft_obj_attributes)
+ * @NFT_MSG_NEWFLOWTABLE: add new flow table (enum nft_flowtable_attributes)
+ * @NFT_MSG_GETFLOWTABLE: get flow table (enum nft_flowtable_attributes)
+ * @NFT_MSG_DELFLOWTABLE: delete flow table (enum nft_flowtable_attributes)
  */
 enum nf_tables_msg_types {
NFT_MSG_NEWTABLE,
@@ -116,6 +119,9 @@ enum nf_tables_msg_types {
NFT_MSG_GETOBJ,
NFT_MSG_DELOBJ,
NFT_MSG_GETOBJ_RESET,
+   NFT_MSG_NEWFLOWTABLE,
+   NFT_MSG_GETFLOWTABLE,
+   NFT_MSG_DELFLOWTABLE,
NFT_MSG_MAX,
 };
 
diff --git a/include/mnl.h b/include/mnl.h
index 4662cd04df9b..4475e7f872d9 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -89,6 +89,9 @@ int mnl_nft_obj_batch_add(struct nftnl_obj *nln, struct 
nftnl_batch *batch,
 int mnl_nft_obj_batch_del(struct nftnl_obj *nln, struct nftnl_batch *batch,
  unsigned int flags, uint32_t seqnum);
 
+struct nftnl_flowtable_list *
+mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table);
+
 struct nftnl_ruleset *mnl_nft_ruleset_dump(struct netlink_ctx *ctx,
   uint32_t family);
 int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
diff --git a/include/netlink.h b/include/netlink.h
index 0d71a6b96d82..bca59bbd9ebe 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -181,6 +181,10 @@ extern int netlink_add_obj(struct netlink_ctx *ctx, const 
struct handle *h,
 extern int netlink_delete_obj(struct netlink_ctx *ctx, const struct handle *h,
  struct location *loc, uint32_t type);
 
+extern int netlink_list_flowtables(struct netlink_ctx *ctx,
+  const struct handle *h,
+  const struct location *loc);
+
 extern void netlink_dump_chain(const struct nftnl_chain *nlc,
   struct netlink_ctx *ctx);
 extern void netlink_dump_rule(const struct nftnl_rule *nlr,
diff --git a/include/rule.h b/include/rule.h
index 4e5a349a806a..5ee5389a6c36 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -35,6 +35,7 @@ struct position_spec {
  * @chain: chain name (chains and rules only)
  * @set:   set name (sets only)
  * @obj:   stateful object name (stateful object only)
+ * @flowtable: flow table name (flow table only)
  * @handle:rule handle (rules only)
  * @position:  rule position (rules only)
  * @set_id:set ID (sets only)
@@ -45,6 +46,7 @@ struct handle {
const char  *chain;
const char  *set;
const char  *obj;
+   const char  *flowtable;
struct handle_spec  handle;
struct position_specposition;
uint32_tset_id;
@@ -98,6 +100,7 @@ enum table_flags {
  * @chains:chains contained in the table
  * @sets:  sets contained in the table
  * @objs:  stateful objects contained in the table
+ * @flowtables:flow tables contained in the table
  * @flags: table flags
  * @refcnt:table reference counter
  */
@@ -109,6 +112,7 @@ struct table {
struct list_headchains;
struct list_headsets;
struct list_headobjs;
+   struct list_headflowtables;
enum table_flagsflags;
unsigned intrefcnt;
 };
@@ -313,6 +317,24 @@ void obj_print_plain(const struct obj *obj, 

[PATCH nft 5/6] tests: shell: add flowtable tests

2018-01-23 Thread Pablo Neira Ayuso
Add basic flowtable tests.

Signed-off-by: Pablo Neira Ayuso 
---
 tests/shell/run-tests.sh   |  4 ++-
 tests/shell/testcases/flowtable/0001flowtable_0| 33 ++
 .../testcases/flowtable/0002create_flowtable_0 | 12 
 .../testcases/flowtable/0003add_after_flush_0  |  8 ++
 .../testcases/flowtable/0004delete_after_add0  |  6 
 .../shell/testcases/flowtable/0005delete_in_use_1  |  9 ++
 6 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100755 tests/shell/testcases/flowtable/0001flowtable_0
 create mode 100755 tests/shell/testcases/flowtable/0002create_flowtable_0
 create mode 100755 tests/shell/testcases/flowtable/0003add_after_flush_0
 create mode 100755 tests/shell/testcases/flowtable/0004delete_after_add0
 create mode 100755 tests/shell/testcases/flowtable/0005delete_in_use_1

diff --git a/tests/shell/run-tests.sh b/tests/shell/run-tests.sh
index fe30115e0807..3eee99dfb739 100755
--- a/tests/shell/run-tests.sh
+++ b/tests/shell/run-tests.sh
@@ -68,7 +68,9 @@ kernel_cleanup() {
nft_set_hash nft_set_rbtree nft_set_bitmap \
nft_chain_nat_ipv4 nft_chain_nat_ipv6 \
nf_tables_inet nf_tables_bridge nf_tables_arp \
-   nf_tables_ipv4 nf_tables_ipv6 nf_tables
+   nf_tables_ipv4 nf_tables_ipv6 nf_tables \
+   nf_flow_table nf_flow_table_ipv4 nf_flow_tables_ipv6 \
+   nf_flow_table_inet nft_flow_offload
 }
 
 find_tests() {
diff --git a/tests/shell/testcases/flowtable/0001flowtable_0 
b/tests/shell/testcases/flowtable/0001flowtable_0
new file mode 100755
index ..307f06f62ebd
--- /dev/null
+++ b/tests/shell/testcases/flowtable/0001flowtable_0
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+tmpfile=$(mktemp)
+if [ ! -w $tmpfile ] ; then
+   echo "Failed to create tmp file" >&2
+   exit 0
+fi
+
+trap "rm -rf $tmpfile" EXIT # cleanup if aborted
+
+
+EXPECTED='table inet t {
+   flowtable f {
+   hook ingress priority 10
+   devices = { eth0, wlan0 }
+   }
+
+   chain c {
+   flow offload @f
+   }
+}'
+
+echo "$EXPECTED" > $tmpfile
+set -e
+$NFT -f $tmpfile
+
+GET="$($NFT list ruleset)"
+
+if [ "$EXPECTED" != "$GET" ] ; then
+   DIFF="$(which diff)"
+   [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET")
+   exit 1
+fi
diff --git a/tests/shell/testcases/flowtable/0002create_flowtable_0 
b/tests/shell/testcases/flowtable/0002create_flowtable_0
new file mode 100755
index ..b6941c58eea9
--- /dev/null
+++ b/tests/shell/testcases/flowtable/0002create_flowtable_0
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+set -e
+$NFT add table t
+$NFT add flowtable t f { hook ingress priority 10 \; devices = { eth0, wlan0 
}\; }
+if $NFT create flowtable t f { hook ingress priority 10 \; devices = { eth0, 
wlan0 }\; } 2>/dev/null ; then
+   echo "E: flowtable creation not failing on existing set" >&2
+   exit 1
+fi
+$NFT add flowtable t f { hook ingress priority 10 \; devices = { eth0, wlan0 
}\; }
+
+exit 0
diff --git a/tests/shell/testcases/flowtable/0003add_after_flush_0 
b/tests/shell/testcases/flowtable/0003add_after_flush_0
new file mode 100755
index ..1f3cb18a46d9
--- /dev/null
+++ b/tests/shell/testcases/flowtable/0003add_after_flush_0
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+set -e
+$NFT add table x
+$NFT add flowtable x y { hook ingress priority 0\; devices = { eth0, wlan0 }\;}
+$NFT flush ruleset
+$NFT add table x
+$NFT add flowtable x y { hook ingress priority 0\; devices = { eth0, wlan0 }\;}
diff --git a/tests/shell/testcases/flowtable/0004delete_after_add0 
b/tests/shell/testcases/flowtable/0004delete_after_add0
new file mode 100755
index ..b72977b37ce6
--- /dev/null
+++ b/tests/shell/testcases/flowtable/0004delete_after_add0
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+set -e
+$NFT add table x
+$NFT add flowtable x y { hook ingress priority 0\; devices = { eth0, wlan0 }\;}
+$NFT delete flowtable x y
diff --git a/tests/shell/testcases/flowtable/0005delete_in_use_1 
b/tests/shell/testcases/flowtable/0005delete_in_use_1
new file mode 100755
index ..ce39e24e601d
--- /dev/null
+++ b/tests/shell/testcases/flowtable/0005delete_in_use_1
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+set -e
+$NFT add table x
+$NFT add chain x x
+$NFT add flowtable x y { hook ingress priority 0\; devices = { eth0, wlan0 }\;}
+$NFT add rule x x flow offload @y
+$NFT delete flowtable x y
+echo "E: delete flowtable in use"
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nft 2/6] src: add support to add flowtables

2018-01-23 Thread Pablo Neira Ayuso
This patch allows you to create flowtable:

 # nft add table x
 # nft add flowtable x m { hook ingress priority 10\; devices = { eth0, wlan0 
}\; }

You have to specify hook and priority. So far, only the ingress hook is
supported. The priority represents where this flowtable is placed in the
ingress hook, which is registered to the devices that the user
specifies.

You can also use the 'create' command instead to bail out in case that
there is an existing flowtable with this name.

Signed-off-by: Pablo Neira Ayuso 
---
 include/expression.h |   2 +
 include/mnl.h|   4 ++
 include/netlink.h|   4 ++
 include/rule.h   |   7 
 src/evaluate.c   |  26 
 src/expression.c |   4 +-
 src/mnl.c|  16 
 src/netlink.c|  58 ++
 src/parser_bison.y   | 112 ---
 src/rule.c   |  17 
 src/scanner.l|   2 +
 11 files changed, 245 insertions(+), 7 deletions(-)

diff --git a/include/expression.h b/include/expression.h
index 0a0e178fe468..8f9da1b1c7c9 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -407,6 +407,8 @@ extern struct expr *prefix_expr_alloc(const struct location 
*loc,
 extern struct expr *range_expr_alloc(const struct location *loc,
 struct expr *low, struct expr *high);
 
+extern struct expr *compound_expr_alloc(const struct location *loc,
+   const struct expr_ops *ops);
 extern void compound_expr_add(struct expr *compound, struct expr *expr);
 extern void compound_expr_remove(struct expr *compound, struct expr *expr);
 extern void list_expr_sort(struct list_head *head);
diff --git a/include/mnl.h b/include/mnl.h
index 4475e7f872d9..470b29787fa6 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -92,6 +92,10 @@ int mnl_nft_obj_batch_del(struct nftnl_obj *nln, struct 
nftnl_batch *batch,
 struct nftnl_flowtable_list *
 mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table);
 
+int mnl_nft_flowtable_batch_add(struct nftnl_flowtable *flo,
+   struct nftnl_batch *batch, unsigned int flags,
+   uint32_t seqnum);
+
 struct nftnl_ruleset *mnl_nft_ruleset_dump(struct netlink_ctx *ctx,
   uint32_t family);
 int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
diff --git a/include/netlink.h b/include/netlink.h
index bca59bbd9ebe..b80acbabe80f 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -184,6 +185,9 @@ extern int netlink_delete_obj(struct netlink_ctx *ctx, 
const struct handle *h,
 extern int netlink_list_flowtables(struct netlink_ctx *ctx,
   const struct handle *h,
   const struct location *loc);
+extern int netlink_add_flowtable(struct netlink_ctx *ctx,
+const struct handle *h, struct flowtable *ft,
+uint32_t flags);
 
 extern void netlink_dump_chain(const struct nftnl_chain *nlc,
   struct netlink_ctx *ctx);
diff --git a/include/rule.h b/include/rule.h
index 5ee5389a6c36..de84cfc0ae64 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -320,10 +320,13 @@ uint32_t obj_type_to_cmd(uint32_t type);
 struct flowtable {
struct list_headlist;
struct handle   handle;
+   struct scopescope;
struct location location;
+   const char *hookstr;
unsigned inthooknum;
int priority;
const char  **dev_array;
+   struct expr *dev_expr;
int dev_array_len;
unsigned intrefcnt;
 };
@@ -381,6 +384,8 @@ enum cmd_ops {
  * @CMD_OBJ_CHAIN: chain
  * @CMD_OBJ_CHAINS:multiple chains
  * @CMD_OBJ_TABLE: table
+ * @CMD_OBJ_FLOWTABLE: flowtable
+ * @CMD_OBJ_FLOWTABLES:flowtables
  * @CMD_OBJ_RULESET:   ruleset
  * @CMD_OBJ_EXPR:  expression
  * @CMD_OBJ_MONITOR:   monitor
@@ -420,6 +425,7 @@ enum cmd_obj {
CMD_OBJ_CT_HELPERS,
CMD_OBJ_LIMIT,
CMD_OBJ_LIMITS,
+   CMD_OBJ_FLOWTABLE,
CMD_OBJ_FLOWTABLES,
 };
 
@@ -479,6 +485,7 @@ struct cmd {
struct rule *rule;
struct chain*chain;
struct table*table;
+   struct flowtable *flowtable;
struct monitor  *monitor;
struct markup   *markup;
struct obj  *object;
diff --git a/src/evaluate.c b/src/evaluate.c
index a58fca9e6362..70a61c72838a 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -2894,6 +2894,24 @@ static int set_evaluate(struct eval_ctx *ctx, struct set 

iptables-save - suggest patch to add functionality

2018-01-23 Thread Alban Vidal
Package: iptables

Dear Maintainers,
 
Please find attached a suggest patch to add functionality in iptables-save.

---

1) Adding -z or --zero option: Reset to zero counters of the chains.

Example without:

iptables-save
# Generated by iptables-save v1.6.1 on Tue Jan  9 21:42:51 2018
*nat
:PREROUTING ACCEPT [923:217673]
:INPUT ACCEPT [309:97481]
(...)

Example with:

iptables-save -z
# Generated by iptables-save v1.6.1 on Tue Jan  9 21:42:26 2018
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
(...)

---

2) Adding -h or --help option: print help/usage (inspired by manpage)

Content:

iptables-save -h
iptables-save and ip6tables-save are provides from iptables package — version 
1.6.1

iptables-save and ip6tables-save are used to dump the contents of IP or IPv6 
Table in easily parseable format to STDOUT. Use I/O-redirection provided by 
your shell to write to a file.

Usage: iptables-save  [-h] [-M modprobe] [-c] [-z] [-t table]
   ip6tables-save [-h] [-M modprobe] [-c] [-z] [-t table]

Options:
Either long or short options are allowed.

  -h, --help
  Print this help usage.

  -M, --modprobe modprobe_program
  Specify the path to the modprobe program. By default, iptables-save will 
inspect /proc/sys/kernel/mod‐probe to determine the executable's path.

  -c, --counters
  Include the current values of all packet and byte counters in the output.

  -z, --zero
  Reset to zero counters of the chains.

  -t, --table tablename
  Restrict output to only one table. If not specified, output includes all 
available tables.

  -f, --file filename
  Specify a filename to log the output to. If not specified, iptables-save 
will log to STDOUT.

 ---

3) Layout layout: uppercase, dot...


Best regards,

Alban Vidal

--
-- System Information:
Debian Release: 9.3
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 4.9.0-5-amd64 (SMP w/4 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8), 
LANGUAGE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

diff --git a/iptables/ip6tables-save.c b/iptables/ip6tables-save.c
index 8e3a6afd..466ce0ce 100644
--- a/iptables/ip6tables-save.c
+++ b/iptables/ip6tables-save.c
@@ -3,6 +3,8 @@
  * Original code: iptables-save
  * Authors: Paul 'Rusty' Russel  and
  *  Harald Welte 
+ * Contributor: Alban Vidal 
+ *
  * This code is distributed under the terms of GNU GPL v2
  */
 #include 
@@ -18,18 +20,12 @@
 #include "libiptc/libip6tc.h"
 #include "ip6tables.h"
 #include "ip6tables-multi.h"
+#include "ipXtables-save-common.c" /* Common code for iptables-save.c and ip6tables-save.c */
 
-static int show_counters;
-
-static const struct option options[] = {
-	{.name = "counters", .has_arg = false, .val = 'c'},
-	{.name = "dump", .has_arg = false, .val = 'd'},
-	{.name = "table",.has_arg = true,  .val = 't'},
-	{.name = "modprobe", .has_arg = true,  .val = 'M'},
-	{.name = "file", .has_arg = true,  .val = 'f'},
-	{NULL},
-};
+static int show_counters = 0;
 
+/* if = 1 (opt -z): Reset to zero counters of the chains */
+static int rst_chain_counters = 0;
 
 /* Debugging prototype. */
 static int for_each_table(int (*func)(const char *tablename))
@@ -96,7 +92,10 @@ static int do_output(const char *tablename)
 			struct xt_counters count;
 			printf("%s ",
 			   ip6tc_get_policy(chain, , h));
-			printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt);
+			if (rst_chain_counters > 0)
+printf("[0:0]\n"); /* Reset to zero counters of the chains */
+			else
+printf("[%llu:%llu]\n", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt);
 		} else {
 			printf("- [0:0]\n");
 		}
@@ -146,7 +145,7 @@ int ip6tables_save_main(int argc, char *argv[])
 	init_extensions6();
 #endif
 
-	while ((c = getopt_long(argc, argv, "bcdt:M:f:", options, NULL)) != -1) {
+	while ((c = getopt_long(argc, argv, "bhcdzt:M:f:", options, NULL)) != -1) {
 		switch (c) {
 		case 'b':
 			fprintf(stderr, "-b/--binary option is not implemented\n");
@@ -154,14 +153,20 @@ int ip6tables_save_main(int argc, char *argv[])
 		case 'c':
 			show_counters = 1;
 			break;
-
 		case 't':
 			/* Select specific table. */
 			tablename = optarg;
 			break;
+		case 'h':
+			/* Print Help and quit */
+			print_help_usage();
+			break;
 		case 'M':
 			xtables_modprobe_program = optarg;
 			break;
+		case 'z':
+			rst_chain_counters = 1;
+			break;
 		case 'f':
 			file = fopen(optarg, "w");
 			if (file == NULL) {
diff --git a/iptables/ipXtables-save-common.c 

[PATCH libnftnl 1/2] src: add flowtable support

2018-01-23 Thread Pablo Neira Ayuso
This patch allows you to add, delete and list flowtable through the
existing netlink interface.

Signed-off-by: Pablo Neira Ayuso 
---
 examples/Makefile.am|  12 +
 examples/nft-flowtable-add.c| 136 +++
 examples/nft-flowtable-del.c| 122 ++
 examples/nft-flowtable-get.c| 121 ++
 include/libnftnl/Makefile.am|   1 +
 include/libnftnl/flowtable.h|  81 
 include/linux/netfilter/nf_tables.h |  53 +++
 src/Makefile.am |   1 +
 src/flowtable.c | 793 
 src/libnftnl.map|  31 ++
 10 files changed, 1351 insertions(+)
 create mode 100644 examples/nft-flowtable-add.c
 create mode 100644 examples/nft-flowtable-del.c
 create mode 100644 examples/nft-flowtable-get.c
 create mode 100644 include/libnftnl/flowtable.h
 create mode 100644 src/flowtable.c

diff --git a/examples/Makefile.am b/examples/Makefile.am
index 48bc7a16c9c6..c0d84ebbcbff 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -25,6 +25,9 @@ check_PROGRAMS = nft-table-add\
 nft-obj-add\
 nft-obj-get\
 nft-obj-del\
+nft-flowtable-add  \
+nft-flowtable-del  \
+nft-flowtable-get  \
 nft-ruleset-get\
 nft-ruleset-parse-file \
 nft-compat-get
@@ -104,6 +107,15 @@ nft_obj_del_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}
 nft_obj_get_SOURCES = nft-obj-get.c
 nft_obj_get_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}
 
+nft_flowtable_add_SOURCES = nft-flowtable-add.c
+nft_flowtable_add_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}
+
+nft_flowtable_del_SOURCES = nft-flowtable-del.c
+nft_flowtable_del_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}
+
+nft_flowtable_get_SOURCES = nft-flowtable-get.c
+nft_flowtable_get_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}
+
 nft_ruleset_get_SOURCES = nft-ruleset-get.c
 nft_ruleset_get_LDADD = ../src/libnftnl.la ${LIBMNL_LIBS}
 
diff --git a/examples/nft-flowtable-add.c b/examples/nft-flowtable-add.c
new file mode 100644
index ..bd6cd0f59b79
--- /dev/null
+++ b/examples/nft-flowtable-add.c
@@ -0,0 +1,136 @@
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+#include 
+
+static struct nftnl_flowtable *flowtable_add_parse(int argc, char *argv[])
+{
+   const char *dev_array[] = { "eth0", "tap0", NULL };
+   struct nftnl_flowtable *t;
+   int hooknum = 0;
+
+   if (strcmp(argv[4], "ingress") == 0)
+   hooknum = NF_NETDEV_INGRESS;
+   else {
+   fprintf(stderr, "Unknown hook: %s\n", argv[4]);
+   return NULL;
+   }
+
+   t = nftnl_flowtable_alloc();
+   if (t == NULL) {
+   perror("OOM");
+   return NULL;
+   }
+   nftnl_flowtable_set(t, NFTNL_FLOWTABLE_TABLE, argv[2]);
+   nftnl_flowtable_set(t, NFTNL_FLOWTABLE_NAME, argv[3]);
+   if (argc == 6) {
+   nftnl_flowtable_set_u32(t, NFTNL_FLOWTABLE_HOOKNUM, hooknum);
+   nftnl_flowtable_set_u32(t, NFTNL_FLOWTABLE_PRIO, atoi(argv[5]));
+   }
+   nftnl_flowtable_set_array(t, NFTNL_FLOWTABLE_DEVICES, dev_array);
+
+   return t;
+}
+
+int main(int argc, char *argv[])
+{
+   struct mnl_socket *nl;
+   char buf[MNL_SOCKET_BUFFER_SIZE];
+   struct nlmsghdr *nlh;
+   uint32_t portid, seq, flowtable_seq;
+   int ret, family;
+   struct nftnl_flowtable *t;
+   struct mnl_nlmsg_batch *batch;
+   int batching;
+
+   if (argc != 6) {
+   fprintf(stderr, "Usage: %s 
\n",
+   argv[0]);
+   exit(EXIT_FAILURE);
+   }
+
+   if (strcmp(argv[1], "ip") == 0)
+   family = NFPROTO_IPV4;
+   else if (strcmp(argv[1], "ip6") == 0)
+   family = NFPROTO_IPV6;
+   else if (strcmp(argv[1], "bridge") == 0)
+   family = NFPROTO_BRIDGE;
+   else if (strcmp(argv[1], "arp") == 0)
+   family = NFPROTO_ARP;
+   else {
+   fprintf(stderr, "Unknown family: ip, ip6, bridge, arp\n");
+   exit(EXIT_FAILURE);
+   }
+
+   t = flowtable_add_parse(argc, argv);
+   if (t == NULL)
+   exit(EXIT_FAILURE);
+
+   batching = nftnl_batch_is_supported();
+   if (batching < 0) {
+   perror("cannot talk to nfnetlink");
+   exit(EXIT_FAILURE);
+   }
+
+   seq = time(NULL);
+   batch = mnl_nlmsg_batch_start(buf, sizeof(buf));
+
+   if (batching) {
+   nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++);
+   mnl_nlmsg_batch_next(batch);
+   }
+
+   flowtable_seq = seq;
+   nlh = nftnl_flowtable_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch),
+   

[PATCH libnftnl 2/2] expr: add flow offload expression

2018-01-23 Thread Pablo Neira Ayuso
This patch adds the new "flow_offload" expression to select what flows
are offloaded to an existing flowtable.

Signed-off-by: Pablo Neira Ayuso 
---
 include/libnftnl/expr.h |   4 +
 include/linux/netfilter/nf_tables.h |  11 +++
 src/Makefile.am |   1 +
 src/expr/flow_offload.c | 184 
 src/expr_ops.c  |   2 +
 5 files changed, 202 insertions(+)
 create mode 100644 src/expr/flow_offload.c

diff --git a/include/libnftnl/expr.h b/include/libnftnl/expr.h
index f37f50963d6c..76df94276c46 100644
--- a/include/libnftnl/expr.h
+++ b/include/libnftnl/expr.h
@@ -221,6 +221,10 @@ enum {
 };
 
 enum {
+   NFTNL_EXPR_FLOW_TABLE_NAME = NFTNL_EXPR_BASE,
+};
+
+enum {
NFTNL_EXPR_FWD_SREG_DEV = NFTNL_EXPR_BASE,
 };
 
diff --git a/include/linux/netfilter/nf_tables.h 
b/include/linux/netfilter/nf_tables.h
index c525e67a665d..2edccfee9506 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -952,6 +952,17 @@ enum nft_ct_attributes {
 };
 #define NFTA_CT_MAX(__NFTA_CT_MAX - 1)
 
+/**
+ * enum nft_flow_attributes - ct offload expression attributes
+ * @NFTA_FLOW_TABLE_NAME: flow table name (NLA_STRING)
+ */
+enum nft_offload_attributes {
+   NFTA_FLOW_UNSPEC,
+   NFTA_FLOW_TABLE_NAME,
+   __NFTA_FLOW_MAX,
+};
+#define NFTA_FLOW_MAX  (__NFTA_FLOW_MAX - 1)
+
 enum nft_limit_type {
NFT_LIMIT_PKTS,
NFT_LIMIT_PKT_BYTES
diff --git a/src/Makefile.am b/src/Makefile.am
index 7708c279c9da..578b7d36d8a9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,7 @@ libnftnl_la_SOURCES = utils.c \
  expr/data_reg.c   \
  expr/dup.c\
  expr/exthdr.c \
+ expr/flow_offload.c \
  expr/fib.c\
  expr/fwd.c\
  expr/limit.c  \
diff --git a/src/expr/flow_offload.c b/src/expr/flow_offload.c
new file mode 100644
index ..a2001c9ae9db
--- /dev/null
+++ b/src/expr/flow_offload.c
@@ -0,0 +1,184 @@
+#include "internal.h"
+
+#include 
+#include 
+#include  /* for memcpy */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct nftnl_expr_flow {
+   char*table_name;
+};
+
+static int nftnl_expr_flow_set(struct nftnl_expr *e, uint16_t type,
+  const void *data, uint32_t data_len)
+{
+   struct nftnl_expr_flow *flow = nftnl_expr_data(e);
+
+   switch (type) {
+   case NFTNL_EXPR_FLOW_TABLE_NAME:
+   flow->table_name = strdup((const char *)data);
+   if (!flow->table_name)
+   return -1;
+   break;
+   default:
+   return -1;
+   }
+   return 0;
+}
+
+static const void *nftnl_expr_flow_get(const struct nftnl_expr *e,
+  uint16_t type, uint32_t *data_len)
+{
+   struct nftnl_expr_flow *flow = nftnl_expr_data(e);
+
+   switch(type) {
+   case NFTNL_EXPR_FLOW_TABLE_NAME:
+   *data_len = strlen(flow->table_name) + 1;
+   return flow->table_name;
+   }
+   return NULL;
+}
+
+static int nftnl_expr_flow_cb(const struct nlattr *attr, void *data)
+{
+   const struct nlattr **tb = data;
+   int type = mnl_attr_get_type(attr);
+
+   if (mnl_attr_type_valid(attr, NFTA_FLOW_MAX) < 0)
+   return MNL_CB_OK;
+
+   switch(type) {
+   case NFTA_FLOW_TABLE_NAME:
+   if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
+   abi_breakage();
+   break;
+   }
+
+   tb[type] = attr;
+   return MNL_CB_OK;
+}
+
+static void nftnl_expr_flow_build(struct nlmsghdr *nlh,
+ const struct nftnl_expr *e)
+{
+   struct nftnl_expr_flow *flow = nftnl_expr_data(e);
+
+   if (e->flags & (1 << NFTNL_EXPR_FLOW_TABLE_NAME))
+   mnl_attr_put_strz(nlh, NFTA_FLOW_TABLE_NAME, flow->table_name);
+}
+
+static int nftnl_expr_flow_parse(struct nftnl_expr *e, struct nlattr *attr)
+{
+   struct nftnl_expr_flow *flow = nftnl_expr_data(e);
+   struct nlattr *tb[NFTA_FLOW_MAX+1] = {};
+   int ret = 0;
+
+   if (mnl_attr_parse_nested(attr, nftnl_expr_flow_cb, tb) < 0)
+   return -1;
+
+   if (tb[NFTA_FLOW_TABLE_NAME]) {
+   flow->table_name =
+   strdup(mnl_attr_get_str(tb[NFTA_FLOW_TABLE_NAME]));
+   if (!flow->table_name)
+   return -1;
+   e->flags |= (1 << NFTNL_EXPR_FLOW_TABLE_NAME);
+   }
+
+   return ret;
+}
+
+static int
+nftnl_expr_flow_json_parse(struct nftnl_expr *e, json_t *root,
+   struct nftnl_parse_err *err)
+{
+#ifdef JSON_PARSING
+   const char *table_name;
+
+ 

Re: question about UNDEFINE/REDEFINE

2018-01-23 Thread Pablo Neira Ayuso
Hi David,

On Mon, Jan 22, 2018 at 02:53:09PM +0100, David Fabian wrote:
> Hello,
> 
> we have a firewall written in bash (using iptables) that is organized by 
> customer VLANs. Each VLAN has its own set of bash variables holding things 
> like uplink iface names, gateway IPs, etc. We want to rewrite the firewall to 
> nftables but are stuck on the fact that nft variables cannot be overridden in 
> the same scope. We have each VLAN configuration in a separate file containing 
> pre/post-routing, input, output and forward rules,and we include those files 
> to 
> a master firewall configuration. One solution is to rename all the variables 
> with some VLAN specific (pre/su)ffix. But that is cumbersome.
> 
> I have made a small patch to nft which adds two new keywords - undefine and 
> redefine. undefine simply undefines a variable from the current scope. 
> redefine 
> allows one to change a variable definition. The patch works against the 
> latest 
> fedora nft (version 0.7) but I believe it should work against master as well. 
> I don't know how to properly send the patch to the project so I am attaching 
> it here. I would like to know your opinion.

Thanks for sending us this patch.

Question here: If we allow to pass variable definitions via -D option
from the command line, would that work for you too?

I'm asking here because I would need to understand better how you've
structured your scripts, if you could explain a bit more, we would
appreciate.

Thanks!
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html