From 9f28b685b473b2424524d0443ef1e0ed8ba276de Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Fri, 3 Aug 2018 23:47:11 +0200 Subject: src: introduce passive OS fingerprint matching Add support for "osf" expression. Example: table ip foo { chain bar { type filter hook input priority 0; policy accept; osf name "Linux" counter packets 3 bytes 132 } } Signed-off-by: Fernando Fernandez Mancera Signed-off-by: Pablo Neira Ayuso --- include/expression.h | 3 +++ include/linux/netfilter/nf_tables.h | 12 ++++++++++++ src/Makefile.am | 1 + src/evaluate.c | 7 +++++++ src/netlink_delinearize.c | 14 ++++++++++++++ src/netlink_linearize.c | 13 +++++++++++++ src/osf.c | 35 +++++++++++++++++++++++++++++++++++ src/parser_bison.y | 12 ++++++++++++ src/scanner.l | 2 ++ 9 files changed, 99 insertions(+) create mode 100644 src/osf.c diff --git a/include/expression.h b/include/expression.h index 2bb51e53..f2c5c1ad 100644 --- a/include/expression.h +++ b/include/expression.h @@ -25,6 +25,7 @@ * @EXPR_EXTHDR: exthdr expression * @EXPR_META: meta expression * @EXPR_SOCKET: socket expression + * @EXPR_OSF: osf expression * @EXPR_CT: conntrack expression * @EXPR_CONCAT: concatenation * @EXPR_LIST: list of expressions @@ -52,6 +53,7 @@ enum expr_types { EXPR_EXTHDR, EXPR_META, EXPR_SOCKET, + EXPR_OSF, EXPR_CT, EXPR_CONCAT, EXPR_LIST, @@ -191,6 +193,7 @@ enum expr_flags { #include #include #include +#include /** * struct expr diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index ea374ae6..63b90546 100644 --- a/include/linux/netfilter/nf_tables.h +++ b/include/linux/netfilter/nf_tables.h @@ -933,6 +933,18 @@ enum nft_socket_keys { }; #define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1) +/** + * enum nft_osf_attributes - nf_tables osf expression netlink attributes + * + * @NFTA_OSF_DREG: destination register (NLA_U32: nft_registers) + */ +enum nft_osf_attributes { + NFTA_OSF_UNSPEC, + NFTA_OSF_DREG, + __NFTA_OSF_MAX +}; +#define NFT_OSF_MAX (__NFTA_OSF_MAX - 1) + /** * enum nft_ct_keys - nf_tables ct expression keys * diff --git a/src/Makefile.am b/src/Makefile.am index bd6fe07b..ed3640e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,6 +56,7 @@ libnftables_la_SOURCES = \ iface.c \ services.c \ mergesort.c \ + osf.c \ tcpopt.c \ socket.c \ libnftables.c diff --git a/src/evaluate.c b/src/evaluate.c index b793c125..1fc861f6 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1724,6 +1724,11 @@ static int expr_evaluate_socket(struct eval_ctx *ctx, struct expr **expr) return 0; } +static int expr_evaluate_osf(struct eval_ctx *ctx, struct expr **expr) +{ + return expr_evaluate_primary(ctx, expr); +} + static int expr_evaluate_variable(struct eval_ctx *ctx, struct expr **exprp) { struct expr *new = expr_clone((*exprp)->sym->expr); @@ -1763,6 +1768,8 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr) return expr_evaluate_meta(ctx, expr); case EXPR_SOCKET: return expr_evaluate_socket(ctx, expr); + case EXPR_OSF: + return expr_evaluate_osf(ctx, expr); case EXPR_FIB: return expr_evaluate_fib(ctx, expr); case EXPR_PAYLOAD: diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c index c886ff98..dbf1f618 100644 --- a/src/netlink_delinearize.c +++ b/src/netlink_delinearize.c @@ -630,6 +630,18 @@ static void netlink_parse_socket(struct netlink_parse_ctx *ctx, netlink_set_register(ctx, dreg, expr); } +static void netlink_parse_osf(struct netlink_parse_ctx *ctx, + const struct location *loc, + const struct nftnl_expr *nle) +{ + enum nft_registers dreg; + struct expr *expr; + + expr = osf_expr_alloc(loc); + dreg = netlink_parse_register(nle, NFTNL_EXPR_OSF_DREG); + netlink_set_register(ctx, dreg, expr); +} + static void netlink_parse_meta_stmt(struct netlink_parse_ctx *ctx, const struct location *loc, const struct nftnl_expr *nle) @@ -1397,6 +1409,7 @@ static const struct { { .name = "exthdr", .parse = netlink_parse_exthdr }, { .name = "meta", .parse = netlink_parse_meta }, { .name = "socket", .parse = netlink_parse_socket }, + { .name = "osf", .parse = netlink_parse_osf }, { .name = "rt", .parse = netlink_parse_rt }, { .name = "ct", .parse = netlink_parse_ct }, { .name = "connlimit", .parse = netlink_parse_connlimit }, @@ -2087,6 +2100,7 @@ static void expr_postprocess(struct rule_pp_ctx *ctx, struct expr **exprp) case EXPR_NUMGEN: case EXPR_FIB: case EXPR_SOCKET: + case EXPR_OSF: break; case EXPR_HASH: if (expr->hash.expr) diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c index aa00564a..442c5a94 100644 --- a/src/netlink_linearize.c +++ b/src/netlink_linearize.c @@ -219,6 +219,17 @@ static void netlink_gen_socket(struct netlink_linearize_ctx *ctx, nftnl_rule_add_expr(ctx->nlr, nle); } +static void netlink_gen_osf(struct netlink_linearize_ctx *ctx, + const struct expr *expr, + enum nft_registers dreg) +{ + struct nftnl_expr *nle; + + nle = alloc_nft_expr("osf"); + netlink_put_register(nle, NFTNL_EXPR_OSF_DREG, dreg); + nftnl_rule_add_expr(ctx->nlr, nle); +} + static void netlink_gen_numgen(struct netlink_linearize_ctx *ctx, const struct expr *expr, enum nft_registers dreg) @@ -708,6 +719,8 @@ static void netlink_gen_expr(struct netlink_linearize_ctx *ctx, return netlink_gen_fib(ctx, expr, dreg); case EXPR_SOCKET: return netlink_gen_socket(ctx, expr, dreg); + case EXPR_OSF: + return netlink_gen_osf(ctx, expr, dreg); default: BUG("unknown expression type %s\n", expr->ops->name); } diff --git a/src/osf.c b/src/osf.c new file mode 100644 index 00000000..f07a725c --- /dev/null +++ b/src/osf.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include + +#include + +static void osf_expr_print(const struct expr *expr, struct output_ctx *octx) +{ + nft_print(octx, "osf name"); +} + +static void osf_expr_clone(struct expr *new, const struct expr *expr) +{ +} + +static const struct expr_ops osf_expr_ops = { + .type = EXPR_OSF, + .name = "osf", + .print = osf_expr_print, + .clone = osf_expr_clone, +}; + +struct expr *osf_expr_alloc(const struct location *loc) +{ + unsigned int len = IFNAMSIZ * BITS_PER_BYTE; + const struct datatype *type = &string_type; + struct expr *expr; + + expr = expr_alloc(loc, &osf_expr_ops, type, + BYTEORDER_HOST_ENDIAN, len); + + return expr; +} diff --git a/src/parser_bison.y b/src/parser_bison.y index 827b0580..9a75120a 100644 --- a/src/parser_bison.y +++ b/src/parser_bison.y @@ -194,6 +194,8 @@ int nft_lex(void *, void *, void *); %token TPROXY "tproxy" +%token OSF "osf" + %token HOOK "hook" %token DEVICE "device" %token DEVICES "devices" @@ -721,6 +723,9 @@ int nft_lex(void *, void *, void *); %destructor { expr_free($$); } fib_expr %type fib_tuple fib_result fib_flag +%type osf_expr +%destructor { expr_free($$); } osf_expr + %type markup_format %type monitor_event %destructor { xfree($$); } monitor_event @@ -2952,6 +2957,7 @@ primary_expr : symbol_expr { $$ = $1; } | numgen_expr { $$ = $1; } | hash_expr { $$ = $1; } | fib_expr { $$ = $1; } + | osf_expr { $$ = $1; } | '(' basic_expr ')' { $$ = $2; } ; @@ -2997,6 +3003,12 @@ fib_tuple : fib_flag DOT fib_tuple | fib_flag ; +osf_expr : OSF NAME + { + $$ = osf_expr_alloc(&@$); + } + ; + shift_expr : primary_expr | shift_expr LSHIFT primary_expr { diff --git a/src/scanner.l b/src/scanner.l index 703700fe..bce69152 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -536,6 +536,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "fib" { return FIB; } +"osf" { return OSF; } + "notrack" { return NOTRACK; } "options" { return OPTIONS; } -- cgit v1.2.3