aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2015-11-30 16:04:35 +0100
committerTobias Brunner <tobias@strongswan.org>2016-03-03 17:20:09 +0100
commitc4cb652a562a1a6674adc90b615e4c866375194c (patch)
tree3cf65fc90c437822dd915fe996a3e00907ec6c69 /src
parentefd7fa7be1bb1f20d9741b3b01afa86fd8fc1a08 (diff)
downloadstrongswan-c4cb652a562a1a6674adc90b615e4c866375194c.tar.bz2
strongswan-c4cb652a562a1a6674adc90b615e4c866375194c.tar.xz
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. Fixes #1212.
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/plugins/connmark/connmark_listener.c332
1 files changed, 172 insertions, 160 deletions
diff --git a/src/libcharon/plugins/connmark/connmark_listener.c b/src/libcharon/plugins/connmark/connmark_listener.c
index 23df690e8..cd53701e8 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);
}
/**