--- /dev/null
+From a4d7f5ee6f36decdcd18d70078e1f0a847fe9b24 Mon Sep 17 00:00:00 2001
+Date: Mon, 30 Nov 2015 16:04:35 +0100
+Subject: [PATCH 1/2] connmark: Fix alignment when adding rules
+
+The structs that make up a message sent to the kernel have all to be
+aligned with XT_ALIGN. That was not necessarily the case when
+initializing the complete message as struct.
+
+ #1212
+---
+ src/libcharon/plugins/connmark/connmark_listener.c | 332 +++++++++++----------
+ 1 file changed, 172 insertions(+), 160 deletions(-)
+
+diff --git a/src/libcharon/plugins/connmark/connmark_listener.c b/src/libcharon/plugins/connmark/connmark_listener.c
+index 23df690..cd53701 100644
+--- a/src/libcharon/plugins/connmark/connmark_listener.c
++++ b/src/libcharon/plugins/connmark/connmark_listener.c
+@@ -1,4 +1,7 @@
+ /*
++ * Copyright (C) 2015 Tobias Brunner
++ * Hochschule fuer Technik Rapperswil
++ *
+ * Copyright (C) 2014 Martin Willi
+ * Copyright (C) 2014 revosec AG
+ *
+@@ -25,6 +28,14 @@
+ #include <linux/netfilter/xt_policy.h>
+ #include <linux/netfilter/xt_CONNMARK.h>
+
++/**
++ * Add a struct at the current position in the buffer
++ */
++#define ADD_STRUCT(pos, st, ...) ({\
++ typeof(pos) _cur = pos; pos += XT_ALIGN(sizeof(st));\
++ *(st*)_cur = (st){ __VA_ARGS__ };\
++ (st*)_cur;\
++})
+
+ typedef struct private_connmark_listener_t private_connmark_listener_t;
+
+@@ -108,54 +119,54 @@ static bool manage_pre_esp_in_udp(private_connmark_listener_t *this,
+ u_int mark, u_int32_t spi,
+ host_t *dst, host_t *src)
+ {
+- struct {
+- struct ipt_entry e;
+- struct ipt_entry_match m;
+- struct xt_udp udp;
+- struct ipt_entry_target t;
+- struct xt_mark_tginfo2 tm;
+- } ipt = {
+- .e = {
+- .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
+- sizeof(ipt.udp)),
+- .next_offset = sizeof(ipt),
+- .ip = {
+- .proto = IPPROTO_UDP,
+- },
++ u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) +
++ XT_ALIGN(sizeof(struct xt_udp));
++ 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_mark_tginfo2));
++ u_int16_t entry_size = target_offset + target_size;
++ u_char ipt[entry_size], *pos = ipt;
++ struct ipt_entry *e;
++
++ memset(ipt, 0, sizeof(ipt));
++ e = ADD_STRUCT(pos, struct ipt_entry,
++ .target_offset = target_offset,
++ .next_offset = entry_size,
++ .ip = {
++ .proto = IPPROTO_UDP,
+ },
+- .m = {
+- .u = {
+- .user = {
+- .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.udp)),
+- .name = "udp",
+- },
++ );
++ if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) ||
++ !host2in(src, &e->ip.src, &e->ip.smsk))
++ {
++ return FALSE;
++ }
++ ADD_STRUCT(pos, struct ipt_entry_match,
++ .u = {
++ .user = {
++ .match_size = match_size,
++ .name = "udp",
+ },
+ },
+- .udp = {
+- .spts = { src->get_port(src), src->get_port(src) },
+- .dpts = { dst->get_port(dst), dst->get_port(dst) },
+- },
+- .t = {
+- .u = {
+- .user = {
+- .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
+- .name = "MARK",
+- .revision = 2,
+- },
++ );
++ ADD_STRUCT(pos, struct xt_udp,
++ .spts = { src->get_port(src), src->get_port(src) },
++ .dpts = { dst->get_port(dst), dst->get_port(dst) },
++ );
++ ADD_STRUCT(pos, struct ipt_entry_target,
++ .u = {
++ .user = {
++ .target_size = target_size,
++ .name = "MARK",
++ .revision = 2,
+ },
+ },
+- .tm = {
+- .mark = mark,
+- .mask = ~0,
+- },
+- };
+-
+- if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
+- !host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
+- {
+- return FALSE;
+- }
+- return manage_rule(ipth, "PREROUTING", add, &ipt.e);
++ );
++ ADD_STRUCT(pos, struct xt_mark_tginfo2,
++ .mark = mark,
++ .mask = ~0,
++ );
++ return manage_rule(ipth, "PREROUTING", add, e);
+ }
+
+ /**
+@@ -166,53 +177,53 @@ static bool manage_pre_esp(private_connmark_listener_t *this,
+ u_int mark, u_int32_t spi,
+ host_t *dst, host_t *src)
+ {
+- struct {
+- struct ipt_entry e;
+- struct ipt_entry_match m;
+- struct xt_esp esp;
+- struct ipt_entry_target t;
+- struct xt_mark_tginfo2 tm;
+- } ipt = {
+- .e = {
+- .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
+- sizeof(ipt.esp)),
+- .next_offset = sizeof(ipt),
+- .ip = {
+- .proto = IPPROTO_ESP,
+- },
++ u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) +
++ XT_ALIGN(sizeof(struct xt_esp));
++ 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_mark_tginfo2));
++ u_int16_t entry_size = target_offset + target_size;
++ u_char ipt[entry_size], *pos = ipt;
++ struct ipt_entry *e;
++
++ memset(ipt, 0, sizeof(ipt));
++ e = ADD_STRUCT(pos, struct ipt_entry,
++ .target_offset = target_offset,
++ .next_offset = entry_size,
++ .ip = {
++ .proto = IPPROTO_ESP,
+ },
+- .m = {
+- .u = {
+- .user = {
+- .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.esp)),
+- .name = "esp",
+- },
++ );
++ if (!host2in(dst, &e->ip.dst, &e->ip.dmsk) ||
++ !host2in(src, &e->ip.src, &e->ip.smsk))
++ {
++ return FALSE;
++ }
++ ADD_STRUCT(pos, struct ipt_entry_match,
++ .u = {
++ .user = {
++ .match_size = match_size,
++ .name = "esp",
+ },
+ },
+- .esp = {
+- .spis = { htonl(spi), htonl(spi) },
+- },
+- .t = {
+- .u = {
+- .user = {
+- .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.tm)),
+- .name = "MARK",
+- .revision = 2,
+- },
++ );
++ ADD_STRUCT(pos, struct xt_esp,
++ .spis = { htonl(spi), htonl(spi) },
++ );
++ ADD_STRUCT(pos, struct ipt_entry_target,
++ .u = {
++ .user = {
++ .target_size = target_size,
++ .name = "MARK",
++ .revision = 2,
+ },
+ },
+- .tm = {
+- .mark = mark,
+- .mask = ~0,
+- },
+- };
+-
+- if (!host2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
+- !host2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
+- {
+- return FALSE;
+- }
+- return manage_rule(ipth, "PREROUTING", add, &ipt.e);
++ );
++ ADD_STRUCT(pos, struct xt_mark_tginfo2,
++ .mark = mark,
++ .mask = ~0,
++ );
++ return manage_rule(ipth, "PREROUTING", add, e);
+ }
+
+ /**
+@@ -238,59 +249,59 @@ static bool manage_in(private_connmark_listener_t *this,
+ u_int mark, u_int32_t spi,
+ traffic_selector_t *dst, traffic_selector_t *src)
+ {
+- struct {
+- struct ipt_entry e;
+- struct ipt_entry_match m;
+- struct xt_policy_info p;
+- struct ipt_entry_target t;
+- struct xt_connmark_tginfo1 cm;
+- } ipt = {
+- .e = {
+- .target_offset = XT_ALIGN(sizeof(ipt.e) + sizeof(ipt.m) +
+- sizeof(ipt.p)),
+- .next_offset = sizeof(ipt),
+- },
+- .m = {
+- .u = {
+- .user = {
+- .match_size = XT_ALIGN(sizeof(ipt.m) + sizeof(ipt.p)),
+- .name = "policy",
+- },
++ u_int16_t match_size = XT_ALIGN(sizeof(struct ipt_entry_match)) +
++ XT_ALIGN(sizeof(struct xt_policy_info));
++ 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;
++ u_char ipt[entry_size], *pos = ipt;
++ struct ipt_entry *e;
++
++ memset(ipt, 0, sizeof(ipt));
++ e = ADD_STRUCT(pos, struct ipt_entry,
++ .target_offset = target_offset,
++ .next_offset = entry_size,
++ );
++ if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) ||
++ !ts2in(src, &e->ip.src, &e->ip.smsk))
++ {
++ return FALSE;
++ }
++ ADD_STRUCT(pos, struct ipt_entry_match,
++ .u = {
++ .user = {
++ .match_size = match_size,
++ .name = "policy",
+ },
+ },
+- .p = {
+- .pol = {
+- {
+- .spi = spi,
+- .match.spi = 1,
+- },
++ );
++ ADD_STRUCT(pos, struct xt_policy_info,
++ .pol = {
++ {
++ .spi = spi,
++ .match.spi = 1,
+ },
+- .len = 1,
+- .flags = XT_POLICY_MATCH_IN,
+ },
+- .t = {
+- .u = {
+- .user = {
+- .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)),
+- .name = "CONNMARK",
+- .revision = 1,
+- },
++ .len = 1,
++ .flags = XT_POLICY_MATCH_IN,
++ );
++ ADD_STRUCT(pos, struct ipt_entry_target,
++ .u = {
++ .user = {
++ .target_size = target_size,
++ .name = "CONNMARK",
++ .revision = 1,
+ },
+ },
+- .cm = {
+- .ctmark = mark,
+- .ctmask = ~0,
+- .nfmask = ~0,
+- .mode = XT_CONNMARK_SET,
+- },
+- };
+-
+- if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
+- !ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
+- {
+- return FALSE;
+- }
+- return manage_rule(ipth, "INPUT", add, &ipt.e);
++ );
++ ADD_STRUCT(pos, struct xt_connmark_tginfo1,
++ .ctmark = mark,
++ .ctmask = ~0,
++ .nfmask = ~0,
++ .mode = XT_CONNMARK_SET,
++ );
++ return manage_rule(ipth, "INPUT", add, e);
+ }
+
+ /**
+@@ -300,37 +311,38 @@ static bool manage_out(private_connmark_listener_t *this,
+ struct iptc_handle *ipth, bool add,
+ traffic_selector_t *dst, traffic_selector_t *src)
+ {
+- struct {
+- struct ipt_entry e;
+- struct ipt_entry_target t;
+- struct xt_connmark_tginfo1 cm;
+- } ipt = {
+- .e = {
+- .target_offset = XT_ALIGN(sizeof(ipt.e)),
+- .next_offset = sizeof(ipt),
+- },
+- .t = {
+- .u = {
+- .user = {
+- .target_size = XT_ALIGN(sizeof(ipt.t) + sizeof(ipt.cm)),
+- .name = "CONNMARK",
+- .revision = 1,
+- },
+- },
+- },
+- .cm = {
+- .ctmask = ~0,
+- .nfmask = ~0,
+- .mode = XT_CONNMARK_RESTORE,
+- },
+- };
+-
+- if (!ts2in(dst, &ipt.e.ip.dst, &ipt.e.ip.dmsk) ||
+- !ts2in(src, &ipt.e.ip.src, &ipt.e.ip.smsk))
++ u_int16_t target_offset = XT_ALIGN(sizeof(struct ipt_entry));
++ 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;
++ u_char ipt[entry_size], *pos = ipt;
++ struct ipt_entry *e;
++
++ memset(ipt, 0, sizeof(ipt));
++ e = ADD_STRUCT(pos, struct ipt_entry,
++ .target_offset = target_offset,
++ .next_offset = entry_size,
++ );
++ if (!ts2in(dst, &e->ip.dst, &e->ip.dmsk) ||
++ !ts2in(src, &e->ip.src, &e->ip.smsk))
+ {
+ return FALSE;
+ }
+- return manage_rule(ipth, "OUTPUT", add, &ipt.e);
++ ADD_STRUCT(pos, struct ipt_entry_target,
++ .u = {
++ .user = {
++ .target_size = target_size,
++ .name = "CONNMARK",
++ .revision = 1,
++ },
++ },
++ );
++ ADD_STRUCT(pos, struct xt_connmark_tginfo1,
++ .ctmask = ~0,
++ .nfmask = ~0,
++ .mode = XT_CONNMARK_RESTORE,
++ );
++ return manage_rule(ipth, "OUTPUT", add, e);
+ }
+
+ /**
+--
+2.4.10