connmark: Don't restore CONNMARK for packets that already have a mark set
authorTobias Brunner <tobias@strongswan.org>
Mon, 7 Mar 2016 15:52:43 +0000 (16:52 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 10 Mar 2016 16:26:26 +0000 (17:26 +0100)
This allows e.g. modified versions of xl2tpd to set the mark in
situations where two clients are using the same source port behind the
same NAT, which CONNMARK can't restore properly as only one conntrack entry
will exist with the mark set to that of the client that sent the last packet.

Fixes #1230.

src/libcharon/plugins/connmark/connmark_listener.c

index 9dde7c1..607316f 100644 (file)
@@ -308,13 +308,16 @@ static bool manage_in(private_connmark_listener_t *this,
 }
 
 /**
- * Add outbund rule restoring CONNMARK on matching traffic
+ * Add outbund rule restoring CONNMARK on matching traffic unless the packet
+ * already has a mark set
  */
 static bool manage_out(private_connmark_listener_t *this,
                                           struct iptc_handle *ipth, bool add,
                                           traffic_selector_t *dst, traffic_selector_t *src)
 {
-       u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry));
+       u_int16_t match_size    = XT_ALIGN(sizeof(struct ipt_entry_match)) +
+                                                         XT_ALIGN(sizeof(struct xt_mark_mtinfo1));
+       u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry)) + match_size;
        u_int16_t target_size   = XT_ALIGN(sizeof(struct ipt_entry_target)) +
                                                          XT_ALIGN(sizeof(struct xt_connmark_tginfo1));
        u_int16_t entry_size    = target_offset + target_size;
@@ -331,6 +334,18 @@ static bool manage_out(private_connmark_listener_t *this,
        {
                return FALSE;
        }
+       ADD_STRUCT(pos, struct ipt_entry_match,
+               .u = {
+                       .user = {
+                               .match_size = match_size,
+                               .name = "mark",
+                               .revision = 1,
+                       },
+               },
+       );
+       ADD_STRUCT(pos, struct xt_mark_mtinfo1,
+               .mask = ~0,
+       );
        ADD_STRUCT(pos, struct ipt_entry_target,
                .u = {
                        .user = {