From 1419b0003fccca32bf61ed40265a5539e2465497 Mon Sep 17 00:00:00 2001 From: Liping Zhang Date: Sat, 19 Nov 2016 19:31:15 +0800 Subject: src: add log flags syntax support Now NF_LOG_XXX is exposed to the userspace, we can set it explicitly. Like iptables LOG target, we can log TCP sequence numbers, TCP options, IP options, UID owning local socket and decode MAC header. Note the log flags are mutually exclusive with group. Some examples are listed below: # nft add rule t c log flags tcp sequence,options # nft add rule t c log flags ip options # nft add rule t c log flags skuid # nft add rule t c log flags ether # nft add rule t c log flags all # nft add rule t c log flags all group 1 :1:14-16: Error: flags and group are mutually exclusive add rule t c log flags all group 1 ^^^ Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso --- doc/nft.xml | 56 ++++++++++++++++++++++++++++++++++++++++ include/linux/netfilter/nf_log.h | 12 +++++++++ include/statement.h | 1 + src/evaluate.c | 12 +++++---- src/netlink_delinearize.c | 4 +++ src/netlink_linearize.c | 3 +++ src/parser_bison.y | 50 ++++++++++++++++++++++++++++++++++- src/scanner.l | 3 +++ src/statement.c | 23 +++++++++++++++++ tests/py/any/log.t | 6 +++++ tests/py/any/log.t.payload | 15 +++++++++++ 11 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 include/linux/netfilter/nf_log.h diff --git a/doc/nft.xml b/doc/nft.xml index d11abca4..8026d85f 100644 --- a/doc/nft.xml +++ b/doc/nft.xml @@ -2400,6 +2400,8 @@ ip forward ip dscp set 42 quoted_string level syslog-level + flags + log-flags log @@ -2459,6 +2461,60 @@ ip forward ip dscp set 42 + + log-flags + + + + + + Flag + Description + + + + + tcp sequence + Log TCP sequence numbers. + + + tcp options + Log options from the TCP packet header. + + + ip options + Log options from the IP/IPv6 packet header. + + + skuid + Log the userid of the process which generated the packet. + + + ether + Decode MAC addresses and protocol. + + + all + Enable all log flags listed above. + + + +
+ + + + Using log statement + +# log the UID which generated the packet and ip options +ip filter output log flags skuid flags ip options + +# log the tcp sequence numbers and tcp options from the TCP packet +ip filter output log flags tcp sequence,options + +# enable all supported log flags +ip6 filter output log flags all + + diff --git a/include/linux/netfilter/nf_log.h b/include/linux/netfilter/nf_log.h new file mode 100644 index 00000000..8be21e02 --- /dev/null +++ b/include/linux/netfilter/nf_log.h @@ -0,0 +1,12 @@ +#ifndef _NETFILTER_NF_LOG_H +#define _NETFILTER_NF_LOG_H + +#define NF_LOG_TCPSEQ 0x01 /* Log TCP sequence numbers */ +#define NF_LOG_TCPOPT 0x02 /* Log TCP options */ +#define NF_LOG_IPOPT 0x04 /* Log IP options */ +#define NF_LOG_UID 0x08 /* Log UID owning local socket */ +#define NF_LOG_NFLOG 0x10 /* Unsupported, don't reuse */ +#define NF_LOG_MACDECODE 0x20 /* Decode MAC header */ +#define NF_LOG_MASK 0x2f + +#endif /* _NETFILTER_NF_LOG_H */ diff --git a/include/statement.h b/include/statement.h index fe83717f..277ff2f4 100644 --- a/include/statement.h +++ b/include/statement.h @@ -50,6 +50,7 @@ struct log_stmt { uint16_t group; uint16_t qthreshold; uint32_t level; + uint32_t logflags; uint32_t flags; }; diff --git a/src/evaluate.c b/src/evaluate.c index c60e0f11..8b113c8c 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -2429,12 +2429,14 @@ static int stmt_evaluate_queue(struct eval_ctx *ctx, struct stmt *stmt) static int stmt_evaluate_log(struct eval_ctx *ctx, struct stmt *stmt) { - if (stmt->log.flags & STMT_LOG_LEVEL && - (stmt->log.flags & STMT_LOG_GROUP || - stmt->log.flags & STMT_LOG_SNAPLEN || - stmt->log.flags & STMT_LOG_QTHRESHOLD)) { - return stmt_error(ctx, stmt, + if (stmt->log.flags & (STMT_LOG_GROUP | STMT_LOG_SNAPLEN | + STMT_LOG_QTHRESHOLD)) { + if (stmt->log.flags & STMT_LOG_LEVEL) + return stmt_error(ctx, stmt, "level and group are mutually exclusive"); + if (stmt->log.logflags) + return stmt_error(ctx, stmt, + "flags and group are mutually exclusive"); } return 0; } diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index 66d38caa..0ebe3683 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -738,6 +738,10 @@ static void netlink_parse_log(struct netlink_parse_ctx *ctx, nftnl_expr_get_u32(nle, NFTNL_EXPR_LOG_LEVEL); stmt->log.flags |= STMT_LOG_LEVEL; } + if (nftnl_expr_is_set(nle, NFTNL_EXPR_LOG_FLAGS)) { + stmt->log.logflags = + nftnl_expr_get_u32(nle, NFTNL_EXPR_LOG_FLAGS); + } ctx->stmt = stmt; } diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index 2bee6844..2945392b 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -833,6 +833,9 @@ static void netlink_gen_log_stmt(struct netlink_linearize_ctx *ctx, if (stmt->log.flags & STMT_LOG_LEVEL) nftnl_expr_set_u32(nle, NFTNL_EXPR_LOG_LEVEL, stmt->log.level); + if (stmt->log.logflags) + nftnl_expr_set_u32(nle, NFTNL_EXPR_LOG_FLAGS, + stmt->log.logflags); } nftnl_rule_add_expr(ctx->nlr, nle); } diff --git a/src/parser_bison.y b/src/parser_bison.y index 91955c18..981ffc81 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -201,6 +202,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token EXPORT "export" %token MONITOR "monitor" +%token ALL "all" + %token ACCEPT "accept" %token DROP "drop" %token CONTINUE "continue" @@ -268,6 +271,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token GATEWAY "gateway" %token MTU "mtu" +%token OPTIONS "options" + %token IP6 "ip6" %token PRIORITY "priority" %token FLOWLABEL "flowlabel" @@ -481,7 +486,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %destructor { stmt_free($$); } meta_stmt %type log_stmt log_stmt_alloc %destructor { stmt_free($$); } log_stmt log_stmt_alloc -%type level_type +%type level_type log_flags log_flags_tcp log_flag_tcp %type limit_stmt quota_stmt %destructor { stmt_free($$); } limit_stmt quota_stmt %type limit_burst limit_mode time_unit quota_mode @@ -1530,6 +1535,10 @@ log_arg : PREFIX string $0->log.level = $2; $0->log.flags |= STMT_LOG_LEVEL; } + | FLAGS log_flags + { + $0->log.logflags |= $2; + } ; level_type : string @@ -1558,6 +1567,45 @@ level_type : string } ; +log_flags : TCP log_flags_tcp + { + $$ = $2; + } + | IP OPTIONS + { + $$ = NF_LOG_IPOPT; + } + | SKUID + { + $$ = NF_LOG_UID; + } + | ETHER + { + $$ = NF_LOG_MACDECODE; + } + | ALL + { + $$ = NF_LOG_MASK; + } + ; + +log_flags_tcp : log_flags_tcp COMMA log_flag_tcp + { + $$ = $1 | $3; + } + | log_flag_tcp + ; + +log_flag_tcp : SEQUENCE + { + $$ = NF_LOG_TCPSEQ; + } + | OPTIONS + { + $$ = NF_LOG_TCPOPT; + } + ; + limit_stmt : LIMIT RATE limit_mode NUM SLASH time_unit limit_burst { $$ = limit_stmt_alloc(&@$); diff --git a/src/scanner.l b/src/scanner.l index cd7398b4..625023f5 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -469,6 +469,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "notrack" { return NOTRACK; } +"options" { return OPTIONS; } +"all" { return ALL; } + "xml" { return XML; } "json" { return JSON; } diff --git a/src/statement.c b/src/statement.c index 8ccd4891..e70eb51e 100644 --- a/src/statement.c +++ b/src/statement.c @@ -27,6 +27,7 @@ #include #include +#include struct stmt *stmt_alloc(const struct location *loc, const struct stmt_ops *ops) @@ -193,6 +194,28 @@ static void log_stmt_print(const struct stmt *stmt) if ((stmt->log.flags & STMT_LOG_LEVEL) && stmt->log.level != LOG_WARNING) printf(" level %s", log_level(stmt->log.level)); + + if ((stmt->log.logflags & NF_LOG_MASK) == NF_LOG_MASK) { + printf(" flags all"); + } else { + if (stmt->log.logflags & (NF_LOG_TCPSEQ | NF_LOG_TCPOPT)) { + const char *delim = " "; + + printf(" flags tcp"); + if (stmt->log.logflags & NF_LOG_TCPSEQ) { + printf(" sequence"); + delim = ","; + } + if (stmt->log.logflags & NF_LOG_TCPOPT) + printf("%soptions", delim); + } + if (stmt->log.logflags & NF_LOG_IPOPT) + printf(" flags ip options"); + if (stmt->log.logflags & NF_LOG_UID) + printf(" flags skuid"); + if (stmt->log.logflags & NF_LOG_MACDECODE) + printf(" flags ether"); + } } static void log_stmt_destroy(struct stmt *stmt) diff --git a/tests/py/any/log.t b/tests/py/any/log.t index 99a7f1f1..37982022 100644 --- a/tests/py/any/log.t +++ b/tests/py/any/log.t @@ -25,3 +25,9 @@ log prefix aaaaa-aaaaaa group 2 snaplen 33;ok;log prefix "aaaaa-aaaaaa" group 2 log group 2 queue-threshold 2;ok log group 2 snaplen 33;ok log group 2 prefix \"nft-test: \";ok;log prefix "nft-test: " group 2 + +log flags all;ok +log level debug flags ip options flags skuid;ok +log flags tcp sequence,options;ok +log flags ip options flags ether flags skuid flags tcp sequence,options;ok;log flags all +log flags all group 2;fail diff --git a/tests/py/any/log.t.payload b/tests/py/any/log.t.payload index dc885b4b..385b8bba 100644 --- a/tests/py/any/log.t.payload +++ b/tests/py/any/log.t.payload @@ -50,3 +50,18 @@ ip test-ip4 output ip test-ip4 output [ log prefix nft-test: group 2 snaplen 0 qthreshold 0 ] +# log flags all +ip test-ip4 output + [ log tcpseq tcpopt ipopt uid macdecode ] + +# log level debug flags ip options flags skuid +ip test-ip4 output + [ log level 7 ipopt uid ] + +# log flags tcp sequence,options +ip test-ip4 output + [ log tcpseq tcpopt ] + +# log flags ip options flags ether flags skuid flags tcp sequence,options +ip test-ip4 output + [ log tcpseq tcpopt ipopt uid macdecode ] -- cgit v1.2.3