diff options
Diffstat (limited to 'src/tcpopt.c')
-rw-r--r-- | src/tcpopt.c | 81 |
1 files changed, 66 insertions, 15 deletions
diff --git a/src/tcpopt.c b/src/tcpopt.c index c3e07d78..d8139337 100644 --- a/src/tcpopt.c +++ b/src/tcpopt.c @@ -1,8 +1,7 @@ +#include <nft.h> + #include <stddef.h> -#include <stdlib.h> #include <stdio.h> -#include <stdint.h> -#include <string.h> #include <netinet/in.h> #include <netinet/ip6.h> #include <netinet/tcp.h> @@ -109,6 +108,31 @@ static const struct exthdr_desc tcpopt_md5sig = { }, }; +static const struct symbol_table mptcp_subtype_tbl = { + .base = BASE_DECIMAL, + .symbols = { + SYMBOL("mp-capable", 0), + SYMBOL("mp-join", 1), + SYMBOL("dss", 2), + SYMBOL("add-addr", 3), + SYMBOL("remove-addr", 4), + SYMBOL("mp-prio", 5), + SYMBOL("mp-fail", 6), + SYMBOL("mp-fastclose", 7), + SYMBOL("mp-tcprst", 8), + SYMBOL_LIST_END + }, +}; + +/* alias of integer_type to parse mptcp subtypes */ +const struct datatype mptcpopt_subtype = { + .type = TYPE_INTEGER, + .name = "integer", + .desc = "mptcp option subtype", + .size = 4, + .basetype = &integer_type, + .sym_tbl = &mptcp_subtype_tbl, +}; static const struct exthdr_desc tcpopt_mptcp = { .name = "mptcp", @@ -116,7 +140,17 @@ static const struct exthdr_desc tcpopt_mptcp = { .templates = { [TCPOPT_MPTCP_KIND] = PHT("kind", 0, 8), [TCPOPT_MPTCP_LENGTH] = PHT("length", 8, 8), - [TCPOPT_MPTCP_SUBTYPE] = PHT("subtype", 16, 4), + [TCPOPT_MPTCP_SUBTYPE] = PROTO_HDR_TEMPLATE("subtype", + &mptcpopt_subtype, + BYTEORDER_BIG_ENDIAN, + 16, 4), + }, +}; + +static const struct exthdr_desc tcpopt_fallback = { + .templates = { + [TCPOPT_COMMON_KIND] = PHT("kind", 0, 8), + [TCPOPT_COMMON_LENGTH] = PHT("length", 8, 8), }, }; #undef PHT @@ -134,6 +168,17 @@ const struct exthdr_desc *tcpopt_protocols[] = { [TCPOPT_KIND_FASTOPEN] = &tcpopt_fastopen, }; +static void tcpopt_assign_tmpl(struct expr *expr, + const struct proto_hdr_template *tmpl, + const struct exthdr_desc *desc) +{ + expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT; + + expr->exthdr.desc = desc; + expr->exthdr.tmpl = tmpl; + expr->exthdr.offset = tmpl->offset; +} + /** * tcpopt_expr_alloc - allocate tcp option extension expression * @@ -183,32 +228,38 @@ struct expr *tcpopt_expr_alloc(const struct location *loc, desc = tcpopt_protocols[kind]; if (!desc) { - if (field != TCPOPT_COMMON_KIND || kind > 255) + if (kind > 255) return NULL; + desc = &tcpopt_fallback; + + switch (field) { + case TCPOPT_COMMON_KIND: + case TCPOPT_COMMON_LENGTH: + tmpl = &desc->templates[field]; + break; + default: + tmpl = &tcpopt_unknown_template; + break; + } + expr = expr_alloc(loc, EXPR_EXTHDR, &integer_type, BYTEORDER_BIG_ENDIAN, 8); - desc = tcpopt_protocols[TCPOPT_NOP]; - tmpl = &desc->templates[field]; - expr->exthdr.desc = desc; - expr->exthdr.tmpl = tmpl; - expr->exthdr.op = NFT_EXTHDR_OP_TCPOPT; expr->exthdr.raw_type = kind; + tcpopt_assign_tmpl(expr, tmpl, desc); return expr; } tmpl = &desc->templates[field]; - if (!tmpl) + if (!tmpl || !tmpl->dtype) 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_TCPOPT; + expr->exthdr.raw_type = desc->type; - expr->exthdr.offset = tmpl->offset; + tcpopt_assign_tmpl(expr, tmpl, desc); return expr; } |