summaryrefslogtreecommitdiffstats
path: root/src/dccpopt.c
diff options
context:
space:
mode:
authorJeremy Sowden <jeremy@azazel.net>2023-04-11 21:45:34 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2023-06-01 21:43:16 +0200
commit6ab0fd6c67dbccedb49209b94eb7f740dd32fd2a (patch)
tree8f376a718fd3c1bc28577a6fb00ec5c3ccdf9133 /src/dccpopt.c
parent19245dd1e0c8e1e007a3b98527e379337d57b49a (diff)
exthdr: add boolean DCCP option matching
Iptables supports the matching of DCCP packets based on the presence or absence of DCCP options. Extend exthdr expressions to add this functionality to nftables. Link: https://bugzilla.netfilter.org/show_bug.cgi?id=930 Signed-off-by: Jeremy Sowden <jeremy@azazel.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/dccpopt.c')
-rw-r--r--src/dccpopt.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/dccpopt.c b/src/dccpopt.c
new file mode 100644
index 00000000..3a2eb952
--- /dev/null
+++ b/src/dccpopt.c
@@ -0,0 +1,276 @@
+#include <stddef.h>
+#include <stdint.h>
+
+#include <datatype.h>
+#include <dccpopt.h>
+#include <expression.h>
+#include <nftables.h>
+#include <utils.h>
+
+#define PHT(__token, __offset, __len) \
+ PROTO_HDR_TEMPLATE(__token, &integer_type, BYTEORDER_BIG_ENDIAN, \
+ __offset, __len)
+
+static const struct proto_hdr_template dccpopt_unknown_template =
+ PROTO_HDR_TEMPLATE("unknown", &invalid_type, BYTEORDER_INVALID, 0, 0);
+
+/*
+ * Option DCCP- Section
+ * Type Length Meaning Data? Reference
+ * ---- ------ ------- ----- ---------
+ * 0 1 Padding Y 5.8.1
+ * 1 1 Mandatory N 5.8.2
+ * 2 1 Slow Receiver Y 11.6
+ * 3-31 1 Reserved
+ * 32 variable Change L N 6.1
+ * 33 variable Confirm L N 6.2
+ * 34 variable Change R N 6.1
+ * 35 variable Confirm R N 6.2
+ * 36 variable Init Cookie N 8.1.4
+ * 37 3-8 NDP Count Y 7.7
+ * 38 variable Ack Vector [Nonce 0] N 11.4
+ * 39 variable Ack Vector [Nonce 1] N 11.4
+ * 40 variable Data Dropped N 11.7
+ * 41 6 Timestamp Y 13.1
+ * 42 6/8/10 Timestamp Echo Y 13.3
+ * 43 4/6 Elapsed Time N 13.2
+ * 44 6 Data Checksum Y 9.3
+ * 45-127 variable Reserved
+ * 128-255 variable CCID-specific options - 10.3
+ */
+
+static const struct exthdr_desc dccpopt_padding = {
+ .name = "padding",
+ .type = DCCPOPT_PADDING,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_mandatory = {
+ .name = "mandatory",
+ .type = DCCPOPT_MANDATORY,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_slow_receiver = {
+ .name = "slow_receiver",
+ .type = DCCPOPT_SLOW_RECEIVER,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_reserved_short = {
+ .name = "reserved_short",
+ .type = DCCPOPT_RESERVED_SHORT,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_change_l = {
+ .name = "change_l",
+ .type = DCCPOPT_CHANGE_L,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8)
+ },
+};
+
+static const struct exthdr_desc dccpopt_confirm_l = {
+ .name = "confirm_l",
+ .type = DCCPOPT_CONFIRM_L,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_change_r = {
+ .name = "change_r",
+ .type = DCCPOPT_CHANGE_R,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_confirm_r = {
+ .name = "confirm_r",
+ .type = DCCPOPT_CONFIRM_R,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_init_cookie = {
+ .name = "init_cookie",
+ .type = DCCPOPT_INIT_COOKIE,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_ndp_count = {
+ .name = "ndp_count",
+ .type = DCCPOPT_NDP_COUNT,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_ack_vector_nonce_0 = {
+ .name = "ack_vector_nonce_0",
+ .type = DCCPOPT_ACK_VECTOR_NONCE_0,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_ack_vector_nonce_1 = {
+ .name = "ack_vector_nonce_1",
+ .type = DCCPOPT_ACK_VECTOR_NONCE_1,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_data_dropped = {
+ .name = "data_dropped",
+ .type = DCCPOPT_DATA_DROPPED,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_timestamp = {
+ .name = "timestamp",
+ .type = DCCPOPT_TIMESTAMP,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_timestamp_echo = {
+ .name = "timestamp_echo",
+ .type = DCCPOPT_TIMESTAMP_ECHO,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_elapsed_time = {
+ .name = "elapsed_time",
+ .type = DCCPOPT_ELAPSED_TIME,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_data_checksum = {
+ .name = "data_checksum",
+ .type = DCCPOPT_DATA_CHECKSUM,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_reserved_long = {
+ .name = "reserved_long",
+ .type = DCCPOPT_RESERVED_LONG,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+static const struct exthdr_desc dccpopt_ccid_specific = {
+ .name = "ccid_specific",
+ .type = DCCPOPT_CCID_SPECIFIC,
+ .templates = {
+ [DCCPOPT_FIELD_TYPE] = PHT("type", 0, 8),
+ },
+};
+
+const struct exthdr_desc *dccpopt_protocols[1 + UINT8_MAX] = {
+ [DCCPOPT_PADDING] = &dccpopt_padding,
+ [DCCPOPT_MANDATORY] = &dccpopt_mandatory,
+ [DCCPOPT_SLOW_RECEIVER] = &dccpopt_slow_receiver,
+ [DCCPOPT_RESERVED_SHORT] = &dccpopt_reserved_short,
+ [DCCPOPT_CHANGE_L] = &dccpopt_change_l,
+ [DCCPOPT_CONFIRM_L] = &dccpopt_confirm_l,
+ [DCCPOPT_CHANGE_R] = &dccpopt_change_r,
+ [DCCPOPT_CONFIRM_R] = &dccpopt_confirm_r,
+ [DCCPOPT_INIT_COOKIE] = &dccpopt_init_cookie,
+ [DCCPOPT_NDP_COUNT] = &dccpopt_ndp_count,
+ [DCCPOPT_ACK_VECTOR_NONCE_0] = &dccpopt_ack_vector_nonce_0,
+ [DCCPOPT_ACK_VECTOR_NONCE_1] = &dccpopt_ack_vector_nonce_1,
+ [DCCPOPT_DATA_DROPPED] = &dccpopt_data_dropped,
+ [DCCPOPT_TIMESTAMP] = &dccpopt_timestamp,
+ [DCCPOPT_TIMESTAMP_ECHO] = &dccpopt_timestamp_echo,
+ [DCCPOPT_ELAPSED_TIME] = &dccpopt_elapsed_time,
+ [DCCPOPT_DATA_CHECKSUM] = &dccpopt_data_checksum,
+ [DCCPOPT_RESERVED_LONG] = &dccpopt_reserved_long,
+ [DCCPOPT_CCID_SPECIFIC] = &dccpopt_ccid_specific,
+};
+
+const struct exthdr_desc *
+dccpopt_find_desc(uint8_t type)
+{
+ enum dccpopt_types proto_idx =
+ 3 <= type && type <= 31 ? DCCPOPT_RESERVED_SHORT :
+ 45 <= type && type <= 127 ? DCCPOPT_RESERVED_LONG :
+ 128 <= type ? DCCPOPT_CCID_SPECIFIC : type;
+
+ return dccpopt_protocols[proto_idx];
+}
+
+struct expr *
+dccpopt_expr_alloc(const struct location *loc, uint8_t type)
+{
+ const struct proto_hdr_template *tmpl;
+ const struct exthdr_desc *desc;
+ struct expr *expr;
+
+ desc = dccpopt_find_desc(type);
+ tmpl = &desc->templates[DCCPOPT_FIELD_TYPE];
+
+ expr = expr_alloc(loc, EXPR_EXTHDR, tmpl->dtype,
+ BYTEORDER_BIG_ENDIAN, BITS_PER_BYTE);
+ expr->exthdr.desc = desc;
+ expr->exthdr.tmpl = tmpl;
+ expr->exthdr.offset = tmpl->offset;
+ expr->exthdr.raw_type = type;
+ expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
+ expr->exthdr.op = NFT_EXTHDR_OP_DCCP;
+
+ return expr;
+}
+
+void
+dccpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
+ unsigned int len)
+{
+ const struct proto_hdr_template *tmpl;
+ const struct exthdr_desc *desc;
+
+ assert(expr->etype == EXPR_EXTHDR);
+
+ desc = dccpopt_find_desc(type);
+ tmpl = &desc->templates[DCCPOPT_FIELD_TYPE];
+
+ expr->len = len;
+ datatype_set(expr, &boolean_type);
+
+ expr->exthdr.offset = offset;
+ expr->exthdr.desc = desc;
+ expr->exthdr.flags = NFT_EXTHDR_F_PRESENT;
+ expr->exthdr.op = NFT_EXTHDR_OP_DCCP;
+
+ /* Make sure that it's the right template based on offset and
+ * len
+ */
+ if (tmpl->offset != offset || tmpl->len != len)
+ expr->exthdr.tmpl = &dccpopt_unknown_template;
+ else
+ expr->exthdr.tmpl = tmpl;
+}