summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Fernandez Mancera <ffmancera@riseup.net>2018-08-03 23:47:11 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-08-04 00:21:19 +0200
commit9f28b685b473b2424524d0443ef1e0ed8ba276de (patch)
tree14834b9e589da013b8b058b49beaf8a2b8ceae72
parentcdb5655ee44da4113d1ee72fbd6afa6ca4ffaa14 (diff)
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 <ffmancera@riseup.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/expression.h3
-rw-r--r--include/linux/netfilter/nf_tables.h12
-rw-r--r--src/Makefile.am1
-rw-r--r--src/evaluate.c7
-rw-r--r--src/netlink_delinearize.c14
-rw-r--r--src/netlink_linearize.c13
-rw-r--r--src/osf.c35
-rw-r--r--src/parser_bison.y12
-rw-r--r--src/scanner.l2
9 files changed, 99 insertions, 0 deletions
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 <hash.h>
#include <ct.h>
#include <socket.h>
+#include <osf.h>
/**
* 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
@@ -934,6 +934,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
*
* @NFT_CT_STATE: conntrack state (bitmask of enum ip_conntrack_info)
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 <nftables.h>
+#include <expression.h>
+#include <utils.h>
+#include <string.h>
+#include <osf.h>
+
+#include <net/if.h>
+
+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 <val> fib_tuple fib_result fib_flag
+%type <expr> osf_expr
+%destructor { expr_free($$); } osf_expr
+
%type <val> markup_format
%type <string> 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; }