aboutsummaryrefslogtreecommitdiffstats
path: root/src/libhydra/plugins/kernel_netlink
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2015-08-05 16:51:38 +0200
committerTobias Brunner <tobias@strongswan.org>2015-08-18 12:06:08 +0200
commit6bd1216e7a8a41eb6c103c27a05f50871e1aef99 (patch)
treeef4bf9aec5b84f3b1c0bbd2ee2d043393b1d5f5e /src/libhydra/plugins/kernel_netlink
parent7ff7ce3ed661c8e20ce6b0bee1df340a03b5a4da (diff)
downloadstrongswan-6bd1216e7a8a41eb6c103c27a05f50871e1aef99.tar.bz2
strongswan-6bd1216e7a8a41eb6c103c27a05f50871e1aef99.tar.xz
kernel-netlink: Avoid route dump if routing rule excludes traffic with a certain mark
If the routing rule we use to direct traffic to our own routing table excludes traffic with a certain mark (fwmark = !<mark>) we can simplify the route lookup and avoid dumping all routes by passing the mark to the request. That way our own routes are ignored and we get the preferred route back without having to dump and analyze all routes, which is quite a burden on hosts with lots of routes.
Diffstat (limited to 'src/libhydra/plugins/kernel_netlink')
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
index 1515b01cc..4e5e02d07 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
@@ -491,6 +491,16 @@ struct private_kernel_netlink_net_t {
bool rta_prefsrc_for_ipv6;
/**
+ * whether marks can be used in route lookups
+ */
+ bool rta_mark;
+
+ /**
+ * the mark excluded from the routing rule used for virtual IPs
+ */
+ mark_t routing_mark;
+
+ /**
* whether to prefer temporary IPv6 addresses over public ones
*/
bool prefer_temporary_addrs;
@@ -1676,18 +1686,25 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
family = dest->get_family(dest);
hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST;
- if (family == AF_INET || this->rta_prefsrc_for_ipv6 ||
- this->routing_table || match_net)
- { /* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes.
- * as we want to ignore routes with virtual IPs we cannot use DUMP
- * if these routes are not installed in a separate table */
- hdr->nlmsg_flags |= NLM_F_DUMP;
- }
hdr->nlmsg_type = RTM_GETROUTE;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
msg = NLMSG_DATA(hdr);
msg->rtm_family = family;
+ if (!match_net && this->rta_mark && this->routing_mark.value)
+ {
+ /* if our routing rule excludes packets with a certain mark we can
+ * get the preferred route without having to dump all routes */
+ chunk = chunk_from_thing(this->routing_mark.value);
+ netlink_add_attribute(hdr, RTA_MARK, chunk, sizeof(request));
+ }
+ else if (family == AF_INET || this->rta_prefsrc_for_ipv6 ||
+ this->routing_table || match_net)
+ { /* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes.
+ * as we want to ignore routes with virtual IPs we cannot use DUMP
+ * if these routes are not installed in a separate table */
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+ }
if (candidate)
{
chunk = candidate->get_address(candidate);
@@ -2412,6 +2429,10 @@ static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
netlink_add_attribute(hdr, FRA_FWMARK, chunk, sizeof(request));
chunk = chunk_from_thing(mark.mask);
netlink_add_attribute(hdr, FRA_FWMASK, chunk, sizeof(request));
+ if (msg->rtm_flags & FIB_RULE_INVERT)
+ {
+ this->routing_mark = mark;
+ }
}
#else
DBG1(DBG_KNL, "setting firewall mark on routing rule is not supported");
@@ -2435,6 +2456,10 @@ static void check_kernel_features(private_kernel_netlink_net_t *this)
case 3:
if (a == 2)
{
+ if (b == 6 && c >= 36)
+ {
+ this->rta_mark = TRUE;
+ }
DBG2(DBG_KNL, "detected Linux %d.%d.%d, no support for "
"RTA_PREFSRC for IPv6 routes", a, b, c);
break;
@@ -2443,6 +2468,7 @@ static void check_kernel_features(private_kernel_netlink_net_t *this)
case 2:
/* only 3.x+ uses two part version numbers */
this->rta_prefsrc_for_ipv6 = TRUE;
+ this->rta_mark = TRUE;
break;
default:
break;