]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
child-sa: Use SA matching mark as SA set mark if the latter is %same
authorMartin Willi <martin@strongswan.org>
Wed, 9 May 2018 11:40:36 +0000 (13:40 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 31 Aug 2018 10:26:40 +0000 (12:26 +0200)
For inbound processing, it can be rather useful to apply the mark to the
packet in the SA, so the associated policy with that mark implicitly matches.
When using %unique as match mark, we don't know the mark beforehand, so
we most likely want to set the mark we match against.

src/libcharon/plugins/vici/vici_config.c
src/libcharon/sa/child_sa.c
src/libstrongswan/ipsec/ipsec_types.c
src/libstrongswan/ipsec/ipsec_types.h
src/libstrongswan/tests/suites/test_utils.c
src/swanctl/swanctl.opt

index 98f68264c29337819a78c8b8f27b1aff81235635..8afefaa094ae475ef5949e1e26b82cae5a7b47b2 100644 (file)
@@ -1184,6 +1184,21 @@ CALLBACK(parse_mark, bool,
        return mark_from_string(buf, MARK_OP_UNIQUE, out);
 }
 
+/**
+ * Parse a mark_t when using it as set_mark.
+ */
+CALLBACK(parse_set_mark, bool,
+       mark_t *out, chunk_t v)
+{
+       char buf[32];
+
+       if (!vici_stringify(v, buf, sizeof(buf)))
+       {
+               return FALSE;
+       }
+       return mark_from_string(buf, MARK_OP_SAME, out);
+}
+
 /**
  * Parse TFC padding option
  */
@@ -1643,8 +1658,8 @@ CALLBACK(child_kv, bool,
                { "mark_in",                    parse_mark,                     &child->cfg.mark_in                                     },
                { "mark_in_sa",                 parse_opt_mark_in,      &child->cfg.options                                     },
                { "mark_out",                   parse_mark,                     &child->cfg.mark_out                            },
-               { "set_mark_in",                parse_mark,                     &child->cfg.set_mark_in                         },
-               { "set_mark_out",               parse_mark,                     &child->cfg.set_mark_out                        },
+               { "set_mark_in",                parse_set_mark,         &child->cfg.set_mark_in                         },
+               { "set_mark_out",               parse_set_mark,         &child->cfg.set_mark_out                        },
                { "tfc_padding",                parse_tfc,                      &child->cfg.tfc                                         },
                { "priority",                   parse_uint32,           &child->cfg.priority                            },
                { "interface",                  parse_string,           &child->cfg.interface                           },
index efa790fc5e161d19a99c1c2de27fae153186f2e4..c33398beeb5d3d4df46ba3a21dc22da07a03b6ed 100644 (file)
@@ -900,6 +900,11 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
                .update = update,
        };
 
+       if (sa.mark.value == MARK_SAME)
+       {
+               sa.mark.value = inbound ? this->mark_in.value : this->mark_out.value;
+       }
+
        status = charon->kernel->add_sa(charon->kernel, &id, &sa);
 
        my_ts->destroy(my_ts);
index 7eed1566a88d7c00b59786a857bfecd2c146615f..6f19cc751367ce5e1adf75b7b26d34151f7c492a 100644 (file)
@@ -100,6 +100,24 @@ bool mark_from_string(const char *value, mark_op_t ops, mark_t *mark)
                        return FALSE;
                }
        }
+       else if (strcasepfx(value, "%same"))
+       {
+               if (!(ops & MARK_OP_SAME))
+               {
+                       DBG1(DBG_APP, "unexpected use of %%same mark", value);
+                       return FALSE;
+               }
+               endptr = (char*)value + strlen("%same");
+               if (!*endptr || *endptr == '/')
+               {
+                       mark->value = MARK_SAME;
+               }
+               else
+               {
+                       DBG1(DBG_APP, "invalid mark value: %s", value);
+                       return FALSE;
+               }
+       }
        else
        {
                mark->value = strtoul(value, &endptr, 0);
index 5b1735178a984e873e1a672bf4b133ef7b0f03b2..7b7bd3743e61d56d2efb5b09c8f0e0c04fab49a9 100644 (file)
@@ -215,6 +215,7 @@ struct mark_t {
  */
 #define MARK_UNIQUE (0xFFFFFFFF)
 #define MARK_UNIQUE_DIR (0xFFFFFFFE)
+#define MARK_SAME (0xFFFFFFFF)
 #define MARK_IS_UNIQUE(m) ((m) == MARK_UNIQUE || (m) == MARK_UNIQUE_DIR)
 
 /**
@@ -225,6 +226,8 @@ enum mark_op_t {
        MARK_OP_NONE = 0,
        /** %unique and %unique-dir */
        MARK_OP_UNIQUE = (1<<0),
+       /** %same */
+       MARK_OP_SAME = (1<<1),
 };
 
 /**
index 5a854f3f675fbc54288623ad3a8bf75c352a6e6d..f1d46ee6beddb7e932e0d9af0fb8a5a1692cf1a4 100644 (file)
@@ -916,6 +916,12 @@ static struct {
                { 0, 0 }},
        {"%unique-foo/0xffffffff",      FALSE,  MARK_OP_UNIQUE,
                { 0, 0 }},
+       {"%same",                                       TRUE,   MARK_OP_SAME,
+               { MARK_SAME, 0xffffffff }},
+       {"%same/0x0000ffff",            TRUE,   MARK_OP_SAME,
+               { MARK_SAME, 0x0000ffff }},
+       {"%%same",                                      FALSE,  MARK_OP_NONE,
+               { 0, 0 }},
 };
 
 START_TEST(test_mark_from_string)
index 79655ed357372bc8e1ea3ca56cf79ea2c42e9182..5b44c541bbf1c2e313012139111401824ce04079 100644 (file)
@@ -919,7 +919,9 @@ connections.<conn>.children.<child>.set_mark_in = 0/0x00000000
        policy routing).
 
        An additional mask may be appended to the mark, separated by _/_. The
-       default mask if omitted is 0xffffffff.
+       default mask if omitted is 0xffffffff. The special value _%same_ uses
+       the value (but not the mask) from **mark_in** as mark value, which can be
+       fixed, _%unique_ or _%unique-dir_.
 
        Setting marks in XFRM input requires Linux 4.19 or higher.
 
@@ -932,7 +934,9 @@ connections.<conn>.children.<child>.set_mark_out = 0/0x00000000
        traffic (e.g. via policy routing).
 
        An additional mask may be appended to the mark, separated by _/_. The
-       default mask if omitted is 0xffffffff.
+       default mask if omitted is 0xffffffff. The special value _%same_ uses
+       the value (but not the mask) from **mark_out** as mark value, which can be
+       fixed, _%unique_ or _%unique-dir_.
 
        Setting marks in XFRM output is supported since Linux 4.14. Setting a mask
        requires at least Linux 4.19.