aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-12-13 12:52:06 +0100
committerMartin Willi <martin@revosec.ch>2014-06-04 16:32:08 +0200
commit0ef0493b4aae7b19ce5f81a9e376566546ee49f6 (patch)
tree7588dea202734265988932d15d50f9d62444da52 /src/libcharon/plugins/kernel_iph/kernel_iph_net.c
parent13e18cb2fc52661152c570a5be3e7cddce388902 (diff)
downloadstrongswan-0ef0493b4aae7b19ce5f81a9e376566546ee49f6.tar.bz2
strongswan-0ef0493b4aae7b19ce5f81a9e376566546ee49f6.tar.xz
kernel-iph: Implement add/del_route()
Diffstat (limited to 'src/libcharon/plugins/kernel_iph/kernel_iph_net.c')
-rw-r--r--src/libcharon/plugins/kernel_iph/kernel_iph_net.c86
1 files changed, 80 insertions, 6 deletions
diff --git a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
index 36e3c4c56..e0652ce6f 100644
--- a/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
+++ b/src/libcharon/plugins/kernel_iph/kernel_iph_net.c
@@ -546,18 +546,92 @@ METHOD(kernel_net_t, del_ip, status_t,
return NOT_SUPPORTED;
}
+/**
+ * Add or remove a route
+ */
+static status_t manage_route(private_kernel_iph_net_t *this, bool add,
+ chunk_t dst, u_int8_t prefixlen, host_t *gtw, char *name)
+{
+ MIB_IPFORWARD_ROW2 row = {
+ .DestinationPrefix = {
+ .PrefixLength = prefixlen,
+ },
+ .SitePrefixLength = prefixlen,
+ .ValidLifetime = INFINITE,
+ .PreferredLifetime = INFINITE,
+ .Metric = 10,
+ .Protocol = MIB_IPPROTO_NETMGMT,
+ };
+ enumerator_t *enumerator;
+ iface_t *entry;
+ ULONG ret;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->ifaces->create_enumerator(this->ifaces);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (streq(name, entry->ifname))
+ {
+ row.InterfaceIndex = entry->ifindex;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ if (!row.InterfaceIndex)
+ {
+ return NOT_FOUND;
+ }
+ switch (dst.len)
+ {
+ case 4:
+ row.DestinationPrefix.Prefix.si_family = AF_INET;
+ memcpy(&row.DestinationPrefix.Prefix.Ipv4.sin_addr,
+ dst.ptr, dst.len);
+ break;
+ case 16:
+ row.DestinationPrefix.Prefix.si_family = AF_INET6;
+ memcpy(&row.DestinationPrefix.Prefix.Ipv6.sin6_addr,
+ dst.ptr, dst.len);
+ break;
+ default:
+ return FAILED;
+ }
+ if (gtw)
+ {
+ memcpy(&row.NextHop, gtw->get_sockaddr(gtw),
+ *gtw->get_sockaddr_len(gtw));
+ }
+
+ if (add)
+ {
+ ret = CreateIpForwardEntry2(&row);
+ }
+ else
+ {
+ ret = DeleteIpForwardEntry2(&row);
+ }
+ if (ret != NO_ERROR)
+ {
+ DBG1(DBG_KNL, "%sing route failed: 0x%08lx", add ? "add" : "remov", ret);
+ return FAILED;
+ }
+ return SUCCESS;
+}
+
METHOD(kernel_net_t, add_route, status_t,
- private_kernel_iph_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
- host_t *gateway, host_t *src_ip, char *if_name)
+ private_kernel_iph_net_t *this, chunk_t dst, u_int8_t prefixlen,
+ host_t *gateway, host_t *src, char *name)
{
- return NOT_SUPPORTED;
+ return manage_route(this, TRUE, dst, prefixlen, gateway, name);
}
METHOD(kernel_net_t, del_route, status_t,
- private_kernel_iph_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
- host_t *gateway, host_t *src_ip, char *if_name)
+ private_kernel_iph_net_t *this, chunk_t dst, u_int8_t prefixlen,
+ host_t *gateway, host_t *src, char *name)
{
- return NOT_SUPPORTED;
+ return manage_route(this, FALSE, dst, prefixlen, gateway, name);
}
METHOD(kernel_net_t, destroy, void,