libxtables: XTTYPE_MARKMASK32 support

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
diff --git a/xtoptions.c b/xtoptions.c
index 631e7a3..e9bcaa8 100644
--- a/xtoptions.c
+++ b/xtoptions.c
@@ -186,11 +186,40 @@
 	p[z] = '\0';
 }
 
+/**
+ * Validate the input for being conformant to "mark[/mask]".
+ */
+static void xtopt_parse_markmask(struct xt_option_call *cb)
+{
+	unsigned int mark = 0, mask = ~0U;
+	char *end;
+
+	if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX))
+		xt_params->exit_err(PARAMETER_PROBLEM,
+			"%s: bad mark value for option \"--%s\", "
+			"or out of range.\n",
+			cb->ext_name, cb->entry->name);
+	if (*end == '/' &&
+	    !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
+		xt_params->exit_err(PARAMETER_PROBLEM,
+			"%s: bad mask value for option \"--%s\", "
+			"or out of range.\n",
+			cb->ext_name, cb->entry->name);
+	if (*end != '\0')
+		xt_params->exit_err(PARAMETER_PROBLEM,
+			"%s: trailing garbage after value "
+			"for option \"--%s\".\n",
+			cb->ext_name, cb->entry->name);
+	cb->val.mark = mark;
+	cb->val.mask = mask;
+}
+
 static void (*const xtopt_subparse[])(struct xt_option_call *) = {
 	[XTTYPE_UINT8]       = xtopt_parse_int,
 	[XTTYPE_UINT32]      = xtopt_parse_int,
 	[XTTYPE_UINT32RC]    = xtopt_parse_mint,
 	[XTTYPE_STRING]      = xtopt_parse_string,
+	[XTTYPE_MARKMASK32]  = xtopt_parse_markmask,
 };
 
 static const size_t xtopt_psize[] = {