summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Fernandez Mancera <ffmancera@riseup.net>2018-10-23 17:06:22 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2018-10-23 17:46:47 +0200
commit03eafe098d5eead786cbbe6f79348f05819cd99e (patch)
tree852498d1288759dafa8773c04fc24e3f54d4512a
parentd7ef1e206bd9b36607dddcf337fada11d743b61f (diff)
osf: add ttl option support
Add support for ttl option in "osf" expression. Example: table ip foo { chain bar { type filter hook input priority filter; policy accept; osf ttl skip name "Linux" } } Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/expression.h4
-rw-r--r--include/linux/netfilter/nf_tables.h2
-rw-r--r--include/osf.h2
-rw-r--r--src/json.c2
-rw-r--r--src/netlink_delinearize.c5
-rw-r--r--src/netlink_linearize.c1
-rw-r--r--src/osf.c24
-rw-r--r--src/parser_bison.y25
-rw-r--r--src/parser_json.c5
-rw-r--r--tests/py/inet/osf.t3
-rw-r--r--tests/py/inet/osf.t.json3
-rw-r--r--tests/py/inet/osf.t.payload68
12 files changed, 133 insertions, 11 deletions
diff --git a/include/expression.h b/include/expression.h
index d6977c3a..f018c958 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -345,6 +345,10 @@ struct expr {
uint8_t direction;
uint8_t spnum;
} xfrm;
+ struct {
+ /* EXPR_OSF */
+ uint8_t ttl;
+ } osf;
};
};
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 4e285988..1d13ad37 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -939,10 +939,12 @@ enum nft_socket_keys {
* enum nft_osf_attributes - nf_tables osf expression netlink attributes
*
* @NFTA_OSF_DREG: destination register (NLA_U32: nft_registers)
+ * @NFTA_OSF_TTL: Value of the TTL osf option (NLA_U8)
*/
enum nft_osf_attributes {
NFTA_OSF_UNSPEC,
NFTA_OSF_DREG,
+ NFTA_OSF_TTL,
__NFTA_OSF_MAX
};
#define NFT_OSF_MAX (__NFTA_OSF_MAX - 1)
diff --git a/include/osf.h b/include/osf.h
index 54cdd4af..23ea34d3 100644
--- a/include/osf.h
+++ b/include/osf.h
@@ -1,7 +1,7 @@
#ifndef NFTABLES_OSF_H
#define NFTABLES_OSF_H
-struct expr *osf_expr_alloc(const struct location *loc);
+struct expr *osf_expr_alloc(const struct location *loc, const uint8_t ttl);
extern int nfnl_osf_load_fingerprints(struct netlink_ctx *ctx, int del);
diff --git a/src/json.c b/src/json.c
index 1cde2706..cea9f19c 100644
--- a/src/json.c
+++ b/src/json.c
@@ -857,7 +857,7 @@ json_t *socket_expr_json(const struct expr *expr, struct output_ctx *octx)
json_t *osf_expr_json(const struct expr *expr, struct output_ctx *octx)
{
- return json_pack("{s:{s:s}}", "osf", "key", "name");
+ return json_pack("{s:{s:i, s:s}}", "osf", "ttl", expr->osf.ttl, "key", "name");
}
json_t *xfrm_expr_json(const struct expr *expr, struct output_ctx *octx)
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 3931127f..db1bf03e 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -655,8 +655,11 @@ static void netlink_parse_osf(struct netlink_parse_ctx *ctx,
{
enum nft_registers dreg;
struct expr *expr;
+ uint8_t ttl;
+
+ ttl = nftnl_expr_get_u8(nle, NFTNL_EXPR_OSF_TTL);
+ expr = osf_expr_alloc(loc, ttl);
- expr = osf_expr_alloc(loc);
dreg = netlink_parse_register(nle, NFTNL_EXPR_OSF_DREG);
netlink_set_register(ctx, dreg, expr);
}
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
index 0ac51bd0..0c8f5fe4 100644
--- a/src/netlink_linearize.c
+++ b/src/netlink_linearize.c
@@ -227,6 +227,7 @@ static void netlink_gen_osf(struct netlink_linearize_ctx *ctx,
nle = alloc_nft_expr("osf");
netlink_put_register(nle, NFTNL_EXPR_OSF_DREG, dreg);
+ nftnl_expr_set_u8(nle, NFTNL_EXPR_OSF_TTL, expr->osf.ttl);
nftnl_rule_add_expr(ctx->nlr, nle);
}
diff --git a/src/osf.c b/src/osf.c
index 85c95739..b98d1650 100644
--- a/src/osf.c
+++ b/src/osf.c
@@ -5,13 +5,31 @@
#include <osf.h>
#include <json.h>
+static const char *osf_ttl_int_to_str(const uint8_t ttl)
+{
+ if (ttl == 1)
+ return "ttl loose ";
+ else if (ttl == 2)
+ return "ttl skip ";
+
+ return "";
+}
+
static void osf_expr_print(const struct expr *expr, struct output_ctx *octx)
{
- nft_print(octx, "osf name");
+ const char *ttl_str = osf_ttl_int_to_str(expr->osf.ttl);
+
+ nft_print(octx, "osf %sname", ttl_str);
}
static void osf_expr_clone(struct expr *new, const struct expr *expr)
{
+ new->osf.ttl = expr->osf.ttl;
+}
+
+static bool osf_expr_cmp(const struct expr *e1, const struct expr *e2)
+{
+ return e1->osf.ttl == e2->osf.ttl;
}
static const struct expr_ops osf_expr_ops = {
@@ -19,10 +37,11 @@ static const struct expr_ops osf_expr_ops = {
.name = "osf",
.print = osf_expr_print,
.clone = osf_expr_clone,
+ .cmp = osf_expr_cmp,
.json = osf_expr_json,
};
-struct expr *osf_expr_alloc(const struct location *loc)
+struct expr *osf_expr_alloc(const struct location *loc, const uint8_t ttl)
{
unsigned int len = NFT_OSF_MAXGENRELEN * BITS_PER_BYTE;
const struct datatype *type = &string_type;
@@ -30,6 +49,7 @@ struct expr *osf_expr_alloc(const struct location *loc)
expr = expr_alloc(loc, &osf_expr_ops, type,
BYTEORDER_HOST_ENDIAN, len);
+ expr->osf.ttl = ttl;
return expr;
}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 36a98719..dfe30683 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -15,12 +15,14 @@
#include <inttypes.h>
#include <syslog.h>
#include <netinet/ip.h>
+#include <netinet/tcp.h>
#include <netinet/if_ether.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <linux/netfilter/nf_nat.h>
#include <linux/netfilter/nf_log.h>
+#include <linux/netfilter/nfnetlink_osf.h>
#include <linux/xfrm.h>
#include <netinet/ip_icmp.h>
#include <netinet/icmp6.h>
@@ -740,6 +742,7 @@ int nft_lex(void *, void *, void *);
%type <val> fib_tuple fib_result fib_flag
%type <expr> osf_expr
+%type <val> osf_ttl
%destructor { expr_free($$); } osf_expr
%type <val> markup_format
@@ -3173,9 +3176,27 @@ fib_tuple : fib_flag DOT fib_tuple
| fib_flag
;
-osf_expr : OSF NAME
+osf_expr : OSF osf_ttl NAME
{
- $$ = osf_expr_alloc(&@$);
+ $$ = osf_expr_alloc(&@$, $2);
+ }
+ ;
+
+osf_ttl : /* empty */
+ {
+ $$ = NF_OSF_TTL_TRUE;
+ }
+ | TTL STRING
+ {
+ if (!strcmp($2, "loose"))
+ $$ = NF_OSF_TTL_LESS;
+ else if (!strcmp($2, "skip"))
+ $$ = NF_OSF_TTL_NOCHECK;
+ else {
+ erec_queue(error(&@2, "invalid ttl option"),
+ state->msgs);
+ YYERROR;
+ }
}
;
diff --git a/src/parser_json.c b/src/parser_json.c
index 7047c00d..fc0dc9a9 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -376,12 +376,13 @@ static struct expr *json_parse_osf_expr(struct json_ctx *ctx,
const char *type, json_t *root)
{
const char *key;
+ uint8_t ttl;
- if (json_unpack_err(ctx, root, "{s:s}", "key", &key))
+ if (json_unpack_err(ctx, root, "{s:i, s:s}", "ttl", ttl,"key", &key))
return NULL;
if (!strcmp(key, "name"))
- return osf_expr_alloc(int_loc);
+ return osf_expr_alloc(int_loc, ttl);
json_error(ctx, "Invalid osf key value.");
return NULL;
diff --git a/tests/py/inet/osf.t b/tests/py/inet/osf.t
index bccfc751..fd5d9ed8 100644
--- a/tests/py/inet/osf.t
+++ b/tests/py/inet/osf.t
@@ -5,6 +5,9 @@
*inet;osfinet;osfchain
osf name "Linux";ok
+osf ttl loose name "Linux";ok
+osf ttl skip name "Linux";ok
+osf ttl nottl name "Linux";fail
osf name "morethansixteenbytes";fail
osf name ;fail
osf name { "Windows", "MacOs" };ok
diff --git a/tests/py/inet/osf.t.json b/tests/py/inet/osf.t.json
index 4bb413ca..45335cab 100644
--- a/tests/py/inet/osf.t.json
+++ b/tests/py/inet/osf.t.json
@@ -4,6 +4,7 @@
"match": {
"left": {
"osf": {
+ "ttl": 0,
"key": "name"
}
},
@@ -19,6 +20,7 @@
"match": {
"left": {
"osf": {
+ "ttl": 0,
"key": "name"
}
},
@@ -58,6 +60,7 @@
},
"key": {
"osf": {
+ "ttl": 0,
"key": "name"
}
}
diff --git a/tests/py/inet/osf.t.payload b/tests/py/inet/osf.t.payload
index 850ca29e..9b8f0bc0 100644
--- a/tests/py/inet/osf.t.payload
+++ b/tests/py/inet/osf.t.payload
@@ -13,19 +13,83 @@ inet osfinet osfchain
[ osf dreg 1 ]
[ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+# osf ttl loose name "Linux"
+ip osfip osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl loose name "Linux"
+ip6 osfip6 osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl loose name "Linux"
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl skip name "Linux"
+ip osfip osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl skip name "Linux"
+ip6 osfip6 osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf ttl skip name "Linux"
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ]
+
+# osf name { "Windows", "MacOs" }
+__set%d osfip 3 size 2
+__set%d osfip 0
+ element 646e6957 0073776f 00000000 00000000 : 0 [end] element 4f63614d 00000073 00000000 00000000 : 0 [end]
+ip osfip osfchain
+ [ osf dreg 1 ]
+ [ lookup reg 1 set __set%d ]
+
+# osf name { "Windows", "MacOs" }
+__set%d osfip6 3 size 2
+__set%d osfip6 0
+ element 646e6957 0073776f 00000000 00000000 : 0 [end] element 4f63614d 00000073 00000000 00000000 : 0 [end]
+ip6 osfip6 osfchain
+ [ osf dreg 1 ]
+ [ lookup reg 1 set __set%d ]
+
# osf name { "Windows", "MacOs" }
__set%d osfinet 3 size 2
__set%d osfinet 0
element 646e6957 0073776f 00000000 00000000 : 0 [end] element 4f63614d 00000073 00000000 00000000 : 0 [end]
-inet osfinet osfchain
+inet osfinet osfchain
[ osf dreg 1 ]
[ lookup reg 1 set __set%d ]
# ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 }
__map%d osfip b size 2
__map%d osfip 0
- element 646e6957 0073776f 00000000 00000000 : 00000001 0 [end] element 4f63614d 00000073 00000000 00000000 : 00000002 0 [end]
+ element 646e6957 0073776f 00000000 00000000 : 00000001 0 [end] element 4f63614d 00000073 00000000 00000000 : 00000002 0 [end]
ip osfip osfchain
[ osf dreg 1 ]
[ lookup reg 1 set __map%d dreg 1 ]
[ ct set mark with reg 1 ]
+
+# ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 }
+__map%d osfip6 b size 2
+__map%d osfip6 0
+ element 646e6957 0073776f 00000000 00000000 : 00000001 0 [end] element 4f63614d 00000073 00000000 00000000 : 00000002 0 [end]
+ip6 osfip6 osfchain
+ [ osf dreg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ ct set mark with reg 1 ]
+
+# ct mark set osf name map { "Windows" : 0x00000001, "MacOs" : 0x00000002 }
+__map%d osfinet b size 2
+__map%d osfinet 0
+ element 646e6957 0073776f 00000000 00000000 : 00000001 0 [end] element 4f63614d 00000073 00000000 00000000 : 00000002 0 [end]
+inet osfinet osfchain
+ [ osf dreg 1 ]
+ [ lookup reg 1 set __map%d dreg 1 ]
+ [ ct set mark with reg 1 ]