From: Stephen Suryaputra <ssuryaextr@gmail.com>
To: netfilter-devel@vger.kernel.org
Cc: fw@strlen.de, Stephen Suryaputra <ssuryaextr@gmail.com>
Subject: [PATCH nftables] exthdr: doc: add support for matching IPv4 options
Date: Thu, 23 May 2019 05:42:01 -0400 [thread overview]
Message-ID: <20190523094201.3875-1-ssuryaextr@gmail.com> (raw)
This is the userspace change for the overall changes with this
description:
Add capability to have rules matching IPv4 options. This is developed
mainly to support dropping of IP packets with loose and/or strict source
route route options. Nevertheless, the implementation include others and
ability to get specific fields in the option.
Signed-off-by: Stephen Suryaputra <ssuryaextr@gmail.com>
---
doc/payload-expression.txt | 44 +++++-
include/Makefile.am | 1 +
include/exthdr.h | 1 +
include/ipopt.h | 30 ++++
include/linux/netfilter/nf_tables.h | 2 +
src/Makefile.am | 1 +
src/evaluate.c | 17 +++
src/exthdr.c | 22 ++-
src/ipopt.c | 217 ++++++++++++++++++++++++++++
src/parser_bison.y | 42 ++++++
src/payload.c | 4 +
src/scanner.l | 11 ++
tests/py/ip/ipopt.t | 41 ++++++
tests/py/ip/ipopt.t.payload | 147 +++++++++++++++++++
14 files changed, 576 insertions(+), 4 deletions(-)
create mode 100644 include/ipopt.h
create mode 100644 src/ipopt.c
create mode 100644 tests/py/ip/ipopt.t
create mode 100644 tests/py/ip/ipopt.t.payload
diff --git a/doc/payload-expression.txt b/doc/payload-expression.txt
index 7f3ca42..2a9739f 100644
--- a/doc/payload-expression.txt
+++ b/doc/payload-expression.txt
@@ -494,9 +494,9 @@ input meta iifname enp2s0 arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh
EXTENSION HEADER EXPRESSIONS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Extension header expressions refer to data from variable-sized protocol headers, such as IPv6 extension headers and TCP options.
+Extension header expressions refer to data from variable-sized protocol headers, such as IPv6 extension headers, TCP options and IPv4 options.
-nftables currently supports matching (finding) a given ipv6 extension header or TCP option.
+nftables currently supports matching (finding) a given ipv6 extension header, TCP option or IPv4 option.
[verse]
*hbh* {*nexthdr* | *hdrlength*}
*frag* {*nexthdr* | *frag-off* | *more-fragments* | *id*}
@@ -505,11 +505,13 @@ nftables currently supports matching (finding) a given ipv6 extension header or
*mh* {*nexthdr* | *hdrlength* | *checksum* | *type*}
*srh* {*flags* | *tag* | *sid* | *seg-left*}
*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-permitted* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*} 'tcp_option_field'
+*ip option* {eol | lsrr | noop | ra | rr | sid | sec | ssrr | timestamp} 'ip_option_field'
The following syntaxes are valid only in a relational expression with boolean type on right-hand side for checking header existence only:
[verse]
*exthdr* {*hbh* | *frag* | *rt* | *dst* | *mh*}
*tcp option* {*eol* | *noop* | *maxseg* | *window* | *sack-permitted* | *sack* | *sack0* | *sack1* | *sack2* | *sack3* | *timestamp*}
+*ip option* {eol | lsrr | noop | ra | rr | sid | sec | ssrr | timestamp}
.IPv6 extension headers
[options="header"]
@@ -568,6 +570,39 @@ TCP Timestamps |
kind, length, tsval, tsecr
|============================
+.IP Options
+[options="header"]
+|==================
+|Keyword| Description | IP option fields
+|eol|
+End of option list |
+type
+|lsrr|
+Loose Source Route |
+type, length, ptr, addr
+|noop|
+No operation |
+type
+|ra|
+Router Alert |
+type, length, value
+|rr|
+Record Route |
+type, length, ptr, addr
+|sid|
+Stream ID |
+type, length, value
+|sec|
+Security |
+type, length, value
+|ssrr|
+Strict Source Route |
+type, length, ptr, addr
+|timestamp|
+Time Stamp |
+type, length, ptr, overflow, flag, timestamp
+|============================
+
.finding TCP options
--------------------
filter input tcp option sack-permitted kind 1 counter
@@ -578,6 +613,11 @@ filter input tcp option sack-permitted kind 1 counter
ip6 filter input frag more-fragments 1 counter
---------------------------------------
+.finding IP option
+------------------
+filter input ip option lsrr exists counter
+---------------------------------------
+
CONNTRACK EXPRESSIONS
~~~~~~~~~~~~~~~~~~~~~
Conntrack expressions refer to meta data of the connection tracking entry associated with a packet. +
diff --git a/include/Makefile.am b/include/Makefile.am
index b1f4fcf..9606ae1 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -6,6 +6,7 @@ noinst_HEADERS = cli.h \
expression.h \
fib.h \
hash.h \
+ ipopt.h \
json.h \
mini-gmp.h \
gmputil.h \
diff --git a/include/exthdr.h b/include/exthdr.h
index 32f99c9..3959a65 100644
--- a/include/exthdr.h
+++ b/include/exthdr.h
@@ -3,6 +3,7 @@
#include <proto.h>
#include <tcpopt.h>
+#include <ipopt.h>
/**
* struct exthdr_desc - extension header description
diff --git a/include/ipopt.h b/include/ipopt.h
new file mode 100644
index 0000000..7cb03f5
--- /dev/null
+++ b/include/ipopt.h
@@ -0,0 +1,30 @@
+#ifndef NFTABLES_IPOPT_H
+#define NFTABLES_IPOPT_H
+
+#include <proto.h>
+#include <exthdr.h>
+#include <statement.h>
+
+extern struct expr *ipopt_expr_alloc(const struct location *loc,
+ uint8_t type, uint8_t field, uint8_t ptr);
+
+extern void ipopt_init_raw(struct expr *expr, uint8_t type,
+ unsigned int offset, unsigned int len,
+ uint32_t flags, bool set_unknown);
+
+extern bool ipopt_find_template(struct expr *expr, unsigned int offset,
+ unsigned int len);
+
+enum ipopt_fields {
+ IPOPT_FIELD_INVALID,
+ IPOPT_FIELD_TYPE,
+ IPOPT_FIELD_LENGTH,
+ IPOPT_FIELD_VALUE,
+ IPOPT_FIELD_PTR,
+ IPOPT_FIELD_ADDR_0,
+ IPOPT_FIELD_OVERFLOW,
+ IPOPT_FIELD_FLAG,
+ IPOPT_FIELD_TIMESTAMP_0,
+};
+
+#endif /* NFTABLES_IPOPT_H */
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 09a7b9e..c0487fa 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -728,10 +728,12 @@ enum nft_exthdr_flags {
*
* @NFT_EXTHDR_OP_IPV6: match against ipv6 extension headers
* @NFT_EXTHDR_OP_TCP: match against tcp options
+ * @NFT_EXTHDR_OP_IPV4: match against ip options
*/
enum nft_exthdr_op {
NFT_EXTHDR_OP_IPV6,
NFT_EXTHDR_OP_TCPOPT,
+ NFT_EXTHDR_OP_IPV4,
__NFT_EXTHDR_OP_MAX
};
#define NFT_EXTHDR_OP_MAX (__NFT_EXTHDR_OP_MAX - 1)
diff --git a/src/Makefile.am b/src/Makefile.am
index 8e1a4d8..a45d8e3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,6 +61,7 @@ libnftables_la_SOURCES = \
nfnl_osf.c \
tcpopt.c \
socket.c \
+ ipopt.c \
libnftables.c
# yacc and lex generate dirty code
diff --git a/src/evaluate.c b/src/evaluate.c
index 3593eb8..8227ab8 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -518,6 +518,20 @@ static int __expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
totlen, max_tcpoptlen);
break;
}
+ case NFT_EXTHDR_OP_IPV4: {
+ static const unsigned int max_ipoptlen = 40 * BITS_PER_BYTE;
+ unsigned int totlen = 0;
+
+ totlen += expr->exthdr.tmpl->offset;
+ totlen += expr->exthdr.tmpl->len;
+ totlen += expr->exthdr.offset;
+
+ if (totlen > max_ipoptlen)
+ return expr_error(ctx->msgs, expr,
+ "offset and size %u exceeds max ip option len (%u)",
+ totlen, max_ipoptlen);
+ break;
+ }
default:
break;
}
@@ -542,6 +556,9 @@ static int expr_evaluate_exthdr(struct eval_ctx *ctx, struct expr **exprp)
dependency = &proto_tcp;
pb = PROTO_BASE_TRANSPORT_HDR;
break;
+ case NFT_EXTHDR_OP_IPV4:
+ dependency = &proto_ip;
+ break;
case NFT_EXTHDR_OP_IPV6:
default:
dependency = &proto_ip6;
diff --git a/src/exthdr.c b/src/exthdr.c
index 0cd0319..d73cbcc 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -38,6 +38,11 @@ static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
if (offset)
nft_print(octx, "%d", offset);
nft_print(octx, " %s", expr->exthdr.tmpl->token);
+ } else if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
+ nft_print(octx, "ip option %s", expr->exthdr.desc->name);
+ if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
+ return;
+ nft_print(octx, " %s", expr->exthdr.tmpl->token);
} else {
if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
nft_print(octx, "exthdr %s", expr->exthdr.desc->name);
@@ -172,6 +177,8 @@ void exthdr_init_raw(struct expr *expr, uint8_t type,
assert(expr->etype == EXPR_EXTHDR);
if (op == NFT_EXTHDR_OP_TCPOPT)
return tcpopt_init_raw(expr, type, offset, len, flags);
+ if (op == NFT_EXTHDR_OP_IPV4)
+ return ipopt_init_raw(expr, type, offset, len, flags, true);
expr->len = len;
expr->exthdr.flags = flags;
@@ -222,7 +229,8 @@ bool exthdr_find_template(struct expr *expr, const struct expr *mask, unsigned i
{
unsigned int off, mask_offset, mask_len;
- if (expr->exthdr.tmpl != &exthdr_unknown_template)
+ if (expr->exthdr.op != NFT_EXTHDR_OP_IPV4 &&
+ expr->exthdr.tmpl != &exthdr_unknown_template)
return false;
/* In case we are handling tcp options instead of the default ipv6
@@ -237,8 +245,18 @@ bool exthdr_find_template(struct expr *expr, const struct expr *mask, unsigned i
off = expr->exthdr.offset;
off += round_up(mask->len, BITS_PER_BYTE) - mask_len;
+ /* Handle ip options after the offset and mask have been calculated. */
+ if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
+ if (ipopt_find_template(expr, off, mask_len - mask_offset)) {
+ *shift = mask_offset;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
exthdr_init_raw(expr, expr->exthdr.desc->type,
- off, mask_len - mask_offset, NFT_EXTHDR_OP_IPV6, 0);
+ off, mask_len - mask_offset, expr->exthdr.op, 0);
/* still failed to find a template... Bug. */
if (expr->exthdr.tmpl == &exthdr_unknown_template)
diff --git a/src/ipopt.c b/src/ipopt.c
new file mode 100644
index 0000000..5f291a3
--- /dev/null
+++ b/src/ipopt.c
@@ -0,0 +1,217 @@
+#include <stdint.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+
+#include <utils.h>
+#include <headers.h>
+#include <expression.h>
+#include <ipopt.h>
+
+static const struct proto_hdr_template ipopt_unknown_template =
+ PROTO_HDR_TEMPLATE("unknown", &invalid_type, BYTEORDER_INVALID, 0, 0);
+
+#define PHT(__token, __offset, __len) \
+ PROTO_HDR_TEMPLATE(__token, &integer_type, BYTEORDER_BIG_ENDIAN, \
+ __offset, __len)
+static const struct exthdr_desc ipopt_end = {
+ .name = "eol",
+ .type = IPOPT_END,
+ .templates = {
+ [IPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc ipopt_nop = {
+ .name = "noop",
+ .type = IPOPT_NOP,
+ .templates = {
+ [IPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc ipopt_sec = {
+ .name = "sec",
+ .type = IPOPT_SEC,
+ .templates = {
+ [IPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ [IPOPT_FIELD_LENGTH] = PHT("length", 8, 8),
+ [IPOPT_FIELD_VALUE] = PHT("value", 16, 72),
+ },
+};
+
+static const struct exthdr_desc ipopt_lsrr = {
+ .name = "lsrr",
+ .type = IPOPT_LSRR,
+ .templates = {
+ [IPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ [IPOPT_FIELD_LENGTH] = PHT("length", 8, 8),
+ [IPOPT_FIELD_PTR] = PHT("ptr", 16, 8),
+ [IPOPT_FIELD_ADDR_0] = PHT("addr", 24, 32),
+ },
+};
+
+static const struct exthdr_desc ipopt_timestamp = {
+ .name = "timestamp",
+ .type = IPOPT_TIMESTAMP,
+ .templates = {
+ [IPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ [IPOPT_FIELD_LENGTH] = PHT("length", 8, 8),
+ [IPOPT_FIELD_PTR] = PHT("ptr", 16, 8),
+ [IPOPT_FIELD_OVERFLOW] = PHT("overflow", 24, 4),
+ [IPOPT_FIELD_FLAG] = PHT("flag", 28, 4),
+ [IPOPT_FIELD_TIMESTAMP_0] = PHT("timestamp", 32, 32),
+ },
+};
+
+static const struct exthdr_desc ipopt_rr = {
+ .name = "rr",
+ .type = IPOPT_RR,
+ .templates = {
+ [IPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ [IPOPT_FIELD_LENGTH] = PHT("length", 8, 8),
+ [IPOPT_FIELD_PTR] = PHT("ptr", 16, 8),
+ [IPOPT_FIELD_ADDR_0] = PHT("addr", 24, 32),
+ },
+};
+
+static const struct exthdr_desc ipopt_sid = {
+ .name = "sid",
+ .type = IPOPT_SID,
+ .templates = {
+ [IPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ [IPOPT_FIELD_LENGTH] = PHT("length", 8, 8),
+ [IPOPT_FIELD_VALUE] = PHT("value", 16, 16),
+ },
+};
+
+static const struct exthdr_desc ipopt_ssrr = {
+ .name = "ssrr",
+ .type = IPOPT_SSRR,
+ .templates = {
+ [IPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ [IPOPT_FIELD_LENGTH] = PHT("length", 8, 8),
+ [IPOPT_FIELD_PTR] = PHT("ptr", 16, 8),
+ [IPOPT_FIELD_ADDR_0] = PHT("addr", 24, 32),
+ },
+};
+
+static const struct exthdr_desc ipopt_ra = {
+ .name = "ra",
+ .type = IPOPT_RA,
+ .templates = {
+ [IPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ [IPOPT_FIELD_LENGTH] = PHT("length", 8, 8),
+ [IPOPT_FIELD_VALUE] = PHT("value", 16, 16),
+ },
+};
+
+static const struct exthdr_desc *ipopt_protocols[] = {
+ [IPOPT_END] = &ipopt_end,
+ [IPOPT_NOP] = &ipopt_nop,
+ [IPOPT_SEC] = &ipopt_sec,
+ [IPOPT_LSRR] = &ipopt_lsrr,
+ [IPOPT_TIMESTAMP] = &ipopt_timestamp,
+ [IPOPT_RR] = &ipopt_rr,
+ [IPOPT_SID] = &ipopt_sid,
+ [IPOPT_SSRR] = &ipopt_ssrr,
+ [IPOPT_RA] = &ipopt_ra,
+};
+
+static unsigned int calc_offset(const struct exthdr_desc *desc,
+ const struct proto_hdr_template *tmpl,
+ unsigned int arg)
+{
+ if (!desc || tmpl == &ipopt_unknown_template)
+ return 0;
+
+ switch (desc->type) {
+ case IPOPT_RR:
+ case IPOPT_LSRR:
+ case IPOPT_SSRR:
+ if (tmpl == &desc->templates[IPOPT_FIELD_ADDR_0])
+ return (tmpl->offset < 24) ? 0 : arg;
+ return 0;
+ case IPOPT_TIMESTAMP:
+ if (tmpl == &desc->templates[IPOPT_FIELD_TIMESTAMP_0])
+ return (tmpl->offset < 24) ? 0 : arg;
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+struct expr *ipopt_expr_alloc(const struct location *loc, uint8_t type,
+ uint8_t field, uint8_t ptr)
+{
+ const struct proto_hdr_template *tmpl;
+ const struct exthdr_desc *desc;
+ struct expr *expr;
+
+ desc = ipopt_protocols[type];
+ tmpl = &desc->templates[field];
+ if (!tmpl)
+ return NULL;
+
+ expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype,
+ BYTEORDER_BIG_ENDIAN, tmpl->len);
+ expr->exthdr.desc = desc;
+ expr->exthdr.tmpl = tmpl;
+ expr->exthdr.op = NFT_EXTHDR_OP_IPV4;
+ expr->exthdr.offset = calc_offset(desc, tmpl, ptr);
+
+ return expr;
+}
+
+void ipopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
+ unsigned int len, uint32_t flags, bool set_unknown)
+{
+ const struct proto_hdr_template *tmpl;
+ unsigned int i;
+
+ assert(expr->etype == EXPR_EXTHDR);
+
+ expr->len = len;
+ expr->exthdr.flags = flags;
+ expr->exthdr.offset = offset;
+
+ assert(type < array_size(ipopt_protocols));
+ expr->exthdr.desc = ipopt_protocols[type];
+ expr->exthdr.flags = flags;
+
+ for (i = 0; i < array_size(expr->exthdr.desc->templates); ++i) {
+ tmpl = &expr->exthdr.desc->templates[i];
+
+ /* Make sure that it's the right template based on offset and len */
+ if (tmpl->offset != offset || tmpl->len != len)
+ continue;
+
+ if (flags & NFT_EXTHDR_F_PRESENT)
+ expr->dtype = &boolean_type;
+ else
+ expr->dtype = tmpl->dtype;
+ expr->exthdr.tmpl = tmpl;
+ expr->exthdr.op = NFT_EXTHDR_OP_IPV4;
+ break;
+ }
+ if (i == array_size(expr->exthdr.desc->templates) && set_unknown) {
+ expr->exthdr.tmpl = &ipopt_unknown_template;
+ expr->exthdr.op = NFT_EXTHDR_OP_IPV4;
+ }
+}
+
+bool ipopt_find_template(struct expr *expr, unsigned int offset,
+ unsigned int len)
+{
+ if (expr->exthdr.tmpl != &ipopt_unknown_template)
+ return false;
+
+ ipopt_init_raw(expr, expr->exthdr.desc->type, offset, len, 0, false);
+
+ if (expr->exthdr.tmpl == &ipopt_unknown_template)
+ return false;
+
+ return true;
+}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 9aea652..4c56885 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -309,6 +309,17 @@ int nft_lex(void *, void *, void *);
%token PROTOCOL "protocol"
%token CHECKSUM "checksum"
+%token FLAG "flag"
+%token OVERFLOW "overflow"
+%token PTR "ptr"
+%token VALUE "value"
+
+%token SEC "sec"
+%token LSRR "lsrr"
+%token RR "rr"
+%token SSRR "ssrr"
+%token RA "ra"
+
%token ICMP "icmp"
%token CODE "code"
%token SEQUENCE "seq"
@@ -698,6 +709,7 @@ int nft_lex(void *, void *, void *);
%type <expr> ip_hdr_expr icmp_hdr_expr igmp_hdr_expr numgen_expr hash_expr
%destructor { expr_free($$); } ip_hdr_expr icmp_hdr_expr igmp_hdr_expr numgen_expr hash_expr
%type <val> ip_hdr_field icmp_hdr_field igmp_hdr_field
+%type <val> ip_option_type ip_option_field
%type <expr> ip6_hdr_expr icmp6_hdr_expr
%destructor { expr_free($$); } ip6_hdr_expr icmp6_hdr_expr
%type <val> ip6_hdr_field icmp6_hdr_field
@@ -4248,6 +4260,15 @@ ip_hdr_expr : IP ip_hdr_field
{
$$ = payload_expr_alloc(&@$, &proto_ip, $2);
}
+ | IP OPTION ip_option_type ip_option_field
+ {
+ $$ = ipopt_expr_alloc(&@$, $3, $4, 0);
+ }
+ | IP OPTION ip_option_type
+ {
+ $$ = ipopt_expr_alloc(&@$, $3, IPOPT_FIELD_TYPE, 0);
+ $$->exthdr.flags = NFT_EXTHDR_F_PRESENT;
+ }
;
ip_hdr_field : HDRVERSION { $$ = IPHDR_VERSION; }
@@ -4264,6 +4285,27 @@ ip_hdr_field : HDRVERSION { $$ = IPHDR_VERSION; }
| DADDR { $$ = IPHDR_DADDR; }
;
+ip_option_type : EOL { $$ = IPOPT_END; }
+ | NOOP { $$ = IPOPT_NOOP; }
+ | SEC { $$ = IPOPT_SEC; }
+ | LSRR { $$ = IPOPT_LSRR; }
+ | TIMESTAMP { $$ = IPOPT_TIMESTAMP; }
+ | RR { $$ = IPOPT_RR; }
+ | SID { $$ = IPOPT_SID; }
+ | SSRR { $$ = IPOPT_SSRR; }
+ | RA { $$ = IPOPT_RA; }
+ ;
+
+ip_option_field : TYPE { $$ = IPOPT_FIELD_TYPE; }
+ | LENGTH { $$ = IPOPT_FIELD_LENGTH; }
+ | VALUE { $$ = IPOPT_FIELD_VALUE; }
+ | PTR { $$ = IPOPT_FIELD_PTR; }
+ | ADDR { $$ = IPOPT_FIELD_ADDR_0; }
+ | OVERFLOW { $$ = IPOPT_FIELD_OVERFLOW; }
+ | FLAG { $$ = IPOPT_FIELD_FLAG; }
+ | TIMESTAMP { $$ = IPOPT_FIELD_TIMESTAMP_0; }
+ ;
+
icmp_hdr_expr : ICMP icmp_hdr_field
{
$$ = payload_expr_alloc(&@$, &proto_icmp, $2);
diff --git a/src/payload.c b/src/payload.c
index 338a4b7..931370f 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -524,6 +524,10 @@ void exthdr_dependency_kill(struct payload_dep_ctx *ctx, struct expr *expr,
if (payload_dependency_exists(ctx, PROTO_BASE_NETWORK_HDR))
payload_dependency_release(ctx);
break;
+ case NFT_EXTHDR_OP_IPV4:
+ if (payload_dependency_exists(ctx, PROTO_BASE_NETWORK_HDR))
+ payload_dependency_release(ctx);
+ break;
default:
break;
}
diff --git a/src/scanner.l b/src/scanner.l
index 558bf92..a75b1e9 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -401,6 +401,17 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
"protocol" { return PROTOCOL; }
"checksum" { return CHECKSUM; }
+"sec" { return SEC; }
+"lsrr" { return LSRR; }
+"rr" { return RR; }
+"ssrr" { return SSRR; }
+"ra" { return RA; }
+
+"value" { return VALUE; }
+"ptr" { return PTR; }
+"overflow" { return OVERFLOW; }
+"flag" { return FLAG; }
+
"echo" { return ECHO; }
"eol" { return EOL; }
"maxseg" { return MAXSEG; }
diff --git a/tests/py/ip/ipopt.t b/tests/py/ip/ipopt.t
new file mode 100644
index 0000000..539c206
--- /dev/null
+++ b/tests/py/ip/ipopt.t
@@ -0,0 +1,41 @@
+:input;type filter hook input priority 0
+
+*ip;test-ipopt;input
+
+ip option eol type 1;ok
+ip option noop type 1;ok
+ip option sec type 1;ok
+ip option sec length 1;ok
+ip option sec value 1;ok
+ip option lsrr type 1;ok
+ip option lsrr length 1;ok
+ip option lsrr ptr 1;ok
+ip option lsrr addr 1;ok
+ip option timestamp type 1;ok
+ip option timestamp length 1;ok
+ip option timestamp ptr 1;ok
+ip option timestamp overflow 1;ok
+ip option timestamp flag 1;ok
+ip option timestamp timestamp 1;ok
+ip option rr type 1;ok
+ip option rr length 1;ok
+ip option rr ptr 1;ok
+ip option rr addr 1;ok
+ip option sid type 1;ok
+ip option sid length 1;ok
+ip option sid value 1;ok
+ip option ssrr type 1;ok
+ip option ssrr length 1;ok
+ip option ssrr ptr 1;ok
+ip option ssrr addr 1;ok
+ip option ra type 1;ok
+ip option ra length 1;ok
+ip option ra value 1;ok
+
+ip option foobar;fail
+ip option foo bar;fail
+ip option eol length;fail
+ip option eol length 1;fail
+ip option eol addr 1;fail
+ip option lsrr type;fail
+ip option lsrr flag 1;fail
diff --git a/tests/py/ip/ipopt.t.payload b/tests/py/ip/ipopt.t.payload
new file mode 100644
index 0000000..b4c2246
--- /dev/null
+++ b/tests/py/ip/ipopt.t.payload
@@ -0,0 +1,147 @@
+# ip option eol type 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 0 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option noop type 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 1 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option sec type 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 130 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option sec length 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 130 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option sec value 1
+ip test-ipopt input
+ [ exthdr load ipv4 9b @ 130 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000000 0x00000000 0x00000001 ]
+
+# ip option lsrr type 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 131 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option lsrr length 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 131 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option lsrr ptr 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 131 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option lsrr addr 1
+ip test-ipopt input
+ [ exthdr load ipv4 4b @ 131 + 3 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# ip option timestamp type 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 68 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option timestamp length 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 68 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option timestamp ptr 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 68 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option timestamp overflow 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 68 + 3 => reg 1 ]
+ [ bitwise reg 1 = (reg=1 & 0x000000f0 ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000010 ]
+
+# ip option timestamp flag 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 68 + 3 => reg 1 ]
+ [ bitwise reg 1 = (reg=1 & 0x0000000f ) ^ 0x00000000 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option timestamp timestamp 1
+ip test-ipopt input
+ [ exthdr load ipv4 4b @ 68 + 4 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# ip option rr type 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 7 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option rr length 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 7 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option rr ptr 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 7 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option rr addr 1
+ip test-ipopt input
+ [ exthdr load ipv4 4b @ 7 + 3 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# ip option sid type 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 136 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option sid length 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 136 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option sid value 1
+ip test-ipopt input
+ [ exthdr load ipv4 2b @ 136 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 ]
+
+# ip option ssrr type 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 137 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option ssrr length 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 137 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option ssrr ptr 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 137 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option ssrr addr 1
+ip test-ipopt input
+ [ exthdr load ipv4 4b @ 137 + 3 => reg 1 ]
+ [ cmp eq reg 1 0x01000000 ]
+
+# ip option ra type 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 148 + 0 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option ra length 1
+ip test-ipopt input
+ [ exthdr load ipv4 1b @ 148 + 1 => reg 1 ]
+ [ cmp eq reg 1 0x00000001 ]
+
+# ip option ra value 1
+ip test-ipopt input
+ [ exthdr load ipv4 2b @ 148 + 2 => reg 1 ]
+ [ cmp eq reg 1 0x00000100 ]
+
--
2.17.1
reply other threads:[~2019-05-23 13:29 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190523094201.3875-1-ssuryaextr@gmail.com \
--to=ssuryaextr@gmail.com \
--cc=fw@strlen.de \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).