summaryrefslogtreecommitdiffstats
path: root/src/exthdr.c
diff options
context:
space:
mode:
authorStephen Suryaputra <ssuryaextr@gmail.com>2019-07-03 20:30:52 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2019-07-04 14:29:08 +0200
commit226a0e072d5c1edeb53cb61b959b011168c5c29a (patch)
tree07e43268efe15dc8b64b8ca9baca71e02239213f /src/exthdr.c
parent1694c01c30fba06461ca82ede070bf6a9cd9a4db (diff)
exthdr: add support for matching IPv4 options
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. Signed-off-by: Stephen Suryaputra <ssuryaextr@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/exthdr.c')
-rw-r--r--src/exthdr.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/src/exthdr.c b/src/exthdr.c
index c9c2bf50..e1ec6f3d 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)