]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
extensions: connlabel: Fallback on missing connlabel.conf
authorPhil Sutter <phil@nwl.cc>
Mon, 4 Mar 2019 15:53:46 +0000 (16:53 +0100)
committerFlorian Westphal <fw@strlen.de>
Fri, 8 Mar 2019 15:35:36 +0000 (16:35 +0100)
If connlabel.conf was not found, fall back to manually parsing arguments
as plain numbers.

If nfct_labelmap_new() has failed, nfct_labelmap_get_name() segfaults.
Therefore make sure it is not called in connlabel_get_name() if that's
the case.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
extensions/libxt_connlabel.c
extensions/libxt_connlabel.t
extensions/libxt_connlabel.txlate

index d06bb27a7c2e983bd97bcefe6841d65835123055..5a01fe7237bd8bc27f3f737e711c3453ba35d7f6 100644 (file)
@@ -1,8 +1,10 @@
+#define _GNU_SOURCE
 #include <errno.h>
 #include <stdbool.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <stdlib.h>
 #include <xtables.h>
 #include <linux/netfilter/xt_connlabel.h>
 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
@@ -32,40 +34,59 @@ static const struct xt_option_entry connlabel_mt_opts[] = {
 /* cannot do this via _init, else static builds might spew error message
  * for every iptables invocation.
  */
-static void connlabel_open(void)
+static int connlabel_open(void)
 {
        const char *fname;
 
        if (map)
-               return;
+               return 0;
 
        map = nfct_labelmap_new(NULL);
        if (map != NULL)
-               return;
+               return 0;
 
        fname = nfct_labels_get_path();
        if (errno) {
-               xtables_error(RESOURCE_PROBLEM,
-                       "cannot open %s: %s", fname, strerror(errno));
+               fprintf(stderr, "Warning: cannot open %s: %s\n",
+                       fname, strerror(errno));
        } else {
                xtables_error(RESOURCE_PROBLEM,
                        "cannot parse %s: no labels found", fname);
        }
+       return 1;
+}
+
+static int connlabel_value_parse(const char *in)
+{
+       char *end;
+       unsigned long value = strtoul(in, &end, 0);
+
+       if (in[0] == '\0' || *end != '\0')
+               return -1;
+
+       return value;
 }
 
 static void connlabel_mt_parse(struct xt_option_call *cb)
 {
        struct xt_connlabel_mtinfo *info = cb->data;
+       bool have_labelmap = !connlabel_open();
        int tmp;
 
-       connlabel_open();
        xtables_option_parse(cb);
 
        switch (cb->entry->id) {
        case O_LABEL:
-               tmp = nfct_labelmap_get_bit(map, cb->arg);
+               if (have_labelmap)
+                       tmp = nfct_labelmap_get_bit(map, cb->arg);
+               else
+                       tmp = connlabel_value_parse(cb->arg);
+
                if (tmp < 0)
-                       xtables_error(PARAMETER_PROBLEM, "label '%s' not found", cb->arg);
+                       xtables_error(PARAMETER_PROBLEM,
+                                     "label '%s' not found or invalid value",
+                                     cb->arg);
+
                info->bit = tmp;
                if (cb->invert)
                        info->options |= XT_CONNLABEL_OP_INVERT;
@@ -81,7 +102,8 @@ static const char *connlabel_get_name(int b)
 {
        const char *name;
 
-       connlabel_open();
+       if (connlabel_open())
+               return NULL;
 
        name = nfct_labelmap_get_name(map, b);
        if (name && strcmp(name, ""))
@@ -134,9 +156,13 @@ static int connlabel_mt_xlate(struct xt_xlate *xl,
        const struct xt_connlabel_mtinfo *info =
                (const void *)params->match->data;
        const char *name = connlabel_get_name(info->bit);
+       char *valbuf = NULL;
 
-       if (name == NULL)
-               return 0;
+       if (name == NULL) {
+               if (asprintf(&valbuf, "%u", info->bit) < 0)
+                       return 0;
+               name = valbuf;
+       }
 
        if (info->options & XT_CONNLABEL_OP_SET)
                xt_xlate_add(xl, "ct label set %s ", name);
@@ -146,6 +172,7 @@ static int connlabel_mt_xlate(struct xt_xlate *xl,
                xt_xlate_add(xl, "and %s != ", name);
        xt_xlate_add(xl, "%s", name);
 
+       free(valbuf);
        return 1;
 }
 
index aad1032b5a8bb172931f85dcb221b1326bf4dc4e..7265bd4764865a9d9b3c714a53f5e98e014d33a8 100644 (file)
@@ -1,18 +1,7 @@
 :INPUT,FORWARD,OUTPUT
-# Backup the connlabel.conf, then add some label maps for test
-@[ -f /etc/xtables/connlabel.conf ] && mv /etc/xtables/connlabel.conf /tmp/connlabel.conf.bak
-@mkdir -p /etc/xtables
-@echo "40 bit40" > /etc/xtables/connlabel.conf
-@echo "41 bit41" >> /etc/xtables/connlabel.conf
-@echo "128 bit128" >> /etc/xtables/connlabel.conf
--m connlabel --label "bit40";=;OK
--m connlabel ! --label "bit40";=;OK
--m connlabel --label "bit41" --set;=;OK
--m connlabel ! --label "bit41" --set;=;OK
--m connlabel --label "bit128";;FAIL
-@echo > /etc/xtables/connlabel.conf
--m connlabel --label "abc";;FAIL
-@rm -f /etc/xtables/connlabel.conf
--m connlabel --label "abc";;FAIL
-# Restore the original connlabel.conf
-@[ -f /tmp/connlabel.conf.bak ] && mv /tmp/connlabel.conf.bak /etc/xtables/connlabel.conf
+-m connlabel --label "40";=;OK
+-m connlabel ! --label "40";=;OK
+-m connlabel --label "41" --set;=;OK
+-m connlabel ! --label "41" --set;=;OK
+-m connlabel --label "2048";;FAIL
+-m connlabel --label "foobar_not_there";;FAIL
index 5be422044637d27890b0fefc2634f3c01b680e8c..12e4ac0351103060a0a4579f8cb125bb8136a4a2 100644 (file)
@@ -1,5 +1,5 @@
-iptables-translate -A INPUT -m connlabel --label bit40
-nft add rule ip filter INPUT ct label bit40 counter
+iptables-translate -A INPUT -m connlabel --label 40
+nft add rule ip filter INPUT ct label 40 counter
 
-iptables-translate -A INPUT -m connlabel ! --label bit40 --set
-nft add rule ip filter INPUT ct label set bit40 ct label and bit40 != bit40 counter
+iptables-translate -A INPUT -m connlabel ! --label 40 --set
+nft add rule ip filter INPUT ct label set 40 ct label and 40 != 40 counter