On Mon, Oct 22, 2018 at 10:46:18PM +0200, Fernando Fernandez Mancera wrote: > Add support for ttl option in "osf" expression. Example: > > table ip foo { > chain bar { > type filter hook input priority filter; policy accept; > osf skip name "Linux" osf ttl skip osf ttl loose Don't remove the 'ttl' token from there. I just didn't want to have: osf ttl ttl-nocheck, which was sort of redundant. > } > } > > Signed-off-by: Fernando Fernandez Mancera <ffmancera@xxxxxxxxxx> > --- > v1:initial patch > v2:use "ttl-global, ttl-nocheck.." instead of "1, 2.." > v3:better names for ttl options, add json and tests/py support Could you describe what is not yet working here? Thanks! > --- > include/expression.h | 4 +++ > include/linux/netfilter/nf_tables.h | 2 ++ > include/osf.h | 2 +- > src/json.c | 2 +- > src/netlink_delinearize.c | 5 +++- > src/netlink_linearize.c | 1 + > src/osf.c | 26 ++++++++++++++++-- > src/parser_bison.y | 19 +++++++++++-- > src/parser_json.c | 5 ++-- > tests/py/inet/osf.t | 3 +++ > tests/py/inet/osf.t.json | 3 +++ > tests/py/inet/osf.t.payload | 41 +++++++++++++++++++---------- > 12 files changed, 90 insertions(+), 23 deletions(-) > > diff --git a/include/expression.h b/include/expression.h > index d6977c3..f018c95 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 4e28598..1d13ad3 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 54cdd4a..23ea34d 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 1cde270..cea9f19 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 cd05885..84948db 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 0ac51bd..0c8f5fe 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 85c9573..1a224fd 100644 > --- a/src/osf.c > +++ b/src/osf.c > @@ -5,13 +5,32 @@ > #include <osf.h> > #include <json.h> > > +static const char *osf_ttl_int_to_str(const uint8_t ttl) > +{ > + if (ttl == 1) > + return "loose "; > + else if (ttl == 2) > + return "skip "; > + > + return ""; > +} > + > static void osf_expr_print(const struct expr *expr, struct output_ctx *octx) > { > - nft_print(octx, "osf name"); > + const char *ttl_str; > + > + 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 +38,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; > @@ -31,5 +51,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 947a3cd..8bf4f1c 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> > @@ -743,6 +745,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 > @@ -3176,9 +3179,21 @@ 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; } > + | STRING > + { > + if (!strcmp($1, "loose")) > + $$ = NF_OSF_TTL_LESS; > + else if (!strcmp($1, "skip")) > + $$ = NF_OSF_TTL_NOCHECK; > + else > + $$ = 3; > } > ; > > diff --git a/src/parser_json.c b/src/parser_json.c > index 7047c00..fc0dc9a 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 bccfc75..10439a6 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 loose name "Linux";ok > +osf skip name "Linux";ok > +osf 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 4bb413c..4c5e26d 100644 > --- a/tests/py/inet/osf.t.json > +++ b/tests/py/inet/osf.t.json > @@ -4,6 +4,7 @@ > "match": { > "left": { > "osf": { > + "ttl": 0, ^^^^^^^^^^^^^^^^^ Phil is using spaces here, not tabs. Note that "ttl" line is not aligned with the one below. > "key": "name" > } > }, > @@ -19,6 +20,7 @@ > "match": { > "left": { > "osf": { > + "ttl": 0, > "key": "name" > } > }, > @@ -58,6 +60,7 @@ > }, > "key": { > "osf": { > + "osf": 0, > "key": "name" > } > } > diff --git a/tests/py/inet/osf.t.payload b/tests/py/inet/osf.t.payload > index 850ca29..7897fea 100644 > --- a/tests/py/inet/osf.t.payload > +++ b/tests/py/inet/osf.t.payload > @@ -13,19 +13,32 @@ inet osfinet osfchain > [ osf dreg 1 ] > [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ] > > -# 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 > - [ 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] Please, don't remove these tests lines... > +# osf loose name "Linux" > ip osfip osfchain > [ osf dreg 1 ] > - [ lookup reg 1 set __map%d dreg 1 ] > - [ ct set mark with reg 1 ] > + [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ] > + > +# osf loose name "Linux" > +ip6 osfip6 osfchain > + [ osf dreg 1 ] > + [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ] > + > +# osf loose name "Linux" > +inet osfinet osfchain > + [ osf dreg 1 ] > + [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ] > + > +# osf skip name "Linux" > +ip osfip osfchain > + [ osf dreg 1 ] > + [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ] > + > +# osf skip name "Linux" > +ip6 osfip6 osfchain > + [ osf dreg 1 ] > + [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ] > + > +# osf skip name "Linux" > +inet osfinet osfchain > + [ osf dreg 1 ] > + [ cmp eq reg 1 0x756e694c 0x00000078 0x00000000 0x00000000 ] > -- > 2.19.1 >