mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-04 00:00:14 -04:00
Merge branch 'nm-xfrmi'
Use XFRM interfaces instead of dummy TUN devices to avoid issues with name resolution if supported by the kernel. Closes strongswan/strongswan#1048
This commit is contained in:
commit
292eb7893f
@ -1,3 +1,6 @@
|
|||||||
charon-nm.ca_dir = <default>
|
charon-nm.ca_dir = <default>
|
||||||
Directory from which to load CA certificates if no certificate is
|
Directory from which to load CA certificates if no certificate is
|
||||||
configured.
|
configured.
|
||||||
|
|
||||||
|
charon-nm.mtu = 1400
|
||||||
|
MTU for XFRM interfaces created by the NM plugin.
|
||||||
|
@ -28,6 +28,16 @@ charon.plugins.kernel-netlink.hw_offload_feature_interface = lo
|
|||||||
cannot be used to obtain the appropriate feature flag, this option can
|
cannot be used to obtain the appropriate feature flag, this option can
|
||||||
be used to specify an alternative interface for offload feature detection.
|
be used to specify an alternative interface for offload feature detection.
|
||||||
|
|
||||||
|
charon.plugins.kernel-netlink.install_routes_xfrmi = no
|
||||||
|
Whether to install routes for SAs that reference XFRM interfaces.
|
||||||
|
|
||||||
|
Whether routes via XFRM interfaces are automatically installed for SAs that
|
||||||
|
reference such an interface via _if_id_. If the traffic selectors include
|
||||||
|
the IKE traffic to the peer, this requires special care (e.g. installing
|
||||||
|
bypass policies and/or routes, or setting a mark on the IKE socket and
|
||||||
|
excluding such packets from the configured routing table via _fwmark_
|
||||||
|
option).
|
||||||
|
|
||||||
charon.plugins.kernel-netlink.mss = 0
|
charon.plugins.kernel-netlink.mss = 0
|
||||||
MSS to set on installed routes, 0 to disable.
|
MSS to set on installed routes, 0 to disable.
|
||||||
|
|
||||||
|
@ -195,6 +195,22 @@ int main(int argc, char *argv[])
|
|||||||
lib->settings->set_default_str(lib->settings, "charon-nm.port", "0");
|
lib->settings->set_default_str(lib->settings, "charon-nm.port", "0");
|
||||||
lib->settings->set_default_str(lib->settings, "charon-nm.port_nat_t", "0");
|
lib->settings->set_default_str(lib->settings, "charon-nm.port_nat_t", "0");
|
||||||
|
|
||||||
|
/* install VIPs on lo as NM might modify the physical interface (this seems
|
||||||
|
* to affect IPv6 in particular), it actually installs the VIPs on the
|
||||||
|
* passed device again, but since that happens after we require them for
|
||||||
|
* installing routes, we install them ourselves too */
|
||||||
|
lib->settings->set_default_str(lib->settings,
|
||||||
|
"charon-nm.install_virtual_ip_on", "lo");
|
||||||
|
|
||||||
|
/* install routes via XFRM interfaces, if we can use them */
|
||||||
|
lib->settings->set_default_str(lib->settings,
|
||||||
|
"charon-nm.plugins.kernel-netlink.install_routes_xfrmi", "yes");
|
||||||
|
/* bypass IKE traffic from these routes in case traffic selectors conflict */
|
||||||
|
lib->settings->set_default_str(lib->settings,
|
||||||
|
"charon-nm.plugins.socket-default.fwmark", "220");
|
||||||
|
lib->settings->set_default_str(lib->settings,
|
||||||
|
"charon-nm.plugins.kernel-netlink.fwmark", "!220");
|
||||||
|
|
||||||
DBG1(DBG_DMN, "Starting charon NetworkManager backend (strongSwan "VERSION")");
|
DBG1(DBG_DMN, "Starting charon NetworkManager backend (strongSwan "VERSION")");
|
||||||
if (lib->integrity)
|
if (lib->integrity)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 Lubomir Rintel
|
* Copyright (C) 2017 Lubomir Rintel
|
||||||
*
|
* Copyright (C) 2013-2023 Tobias Brunner
|
||||||
* Copyright (C) 2013-2020 Tobias Brunner
|
|
||||||
* Copyright (C) 2008-2009 Martin Willi
|
* Copyright (C) 2008-2009 Martin Willi
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@ -15,6 +14,10 @@
|
|||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
#include "nm_service.h"
|
#include "nm_service.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
@ -23,8 +26,9 @@
|
|||||||
#include <config/peer_cfg.h>
|
#include <config/peer_cfg.h>
|
||||||
#include <credentials/certificates/x509.h>
|
#include <credentials/certificates/x509.h>
|
||||||
#include <networking/tun_device.h>
|
#include <networking/tun_device.h>
|
||||||
|
#include <plugins/kernel_netlink/kernel_netlink_xfrmi.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#define XFRMI_DEFAULT_MTU 1400
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data of NMStrongswanPlugin
|
* Private data of NMStrongswanPlugin
|
||||||
@ -40,7 +44,13 @@ typedef struct {
|
|||||||
nm_creds_t *creds;
|
nm_creds_t *creds;
|
||||||
/* attribute handler for DNS/NBNS server information */
|
/* attribute handler for DNS/NBNS server information */
|
||||||
nm_handler_t *handler;
|
nm_handler_t *handler;
|
||||||
/* dummy TUN device */
|
/* manager for XFRM interfaces, if supported */
|
||||||
|
kernel_netlink_xfrmi_t *xfrmi_manager;
|
||||||
|
/* interface ID of XFRM interface */
|
||||||
|
uint32_t xfrmi_id;
|
||||||
|
/* name of XFRM interface if one is used */
|
||||||
|
char *xfrmi;
|
||||||
|
/* dummy TUN device if not using XFRM interface */
|
||||||
tun_device_t *tun;
|
tun_device_t *tun;
|
||||||
/* name of the connection */
|
/* name of the connection */
|
||||||
char *name;
|
char *name;
|
||||||
@ -107,6 +117,24 @@ static GVariant* handler_to_variant(nm_handler_t *handler, char *variant_type,
|
|||||||
return g_variant_builder_end (&builder);
|
return g_variant_builder_end (&builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy any allocated XFRM or TUN interface
|
||||||
|
*/
|
||||||
|
static void delete_interface(NMStrongswanPluginPrivate *priv)
|
||||||
|
{
|
||||||
|
if (priv->xfrmi)
|
||||||
|
{
|
||||||
|
priv->xfrmi_manager->delete(priv->xfrmi_manager, priv->xfrmi);
|
||||||
|
free(priv->xfrmi);
|
||||||
|
priv->xfrmi = NULL;
|
||||||
|
}
|
||||||
|
if (priv->tun)
|
||||||
|
{
|
||||||
|
priv->tun->destroy(priv->tun);
|
||||||
|
priv->tun = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal IP config to NM, set connection as established
|
* Signal IP config to NM, set connection as established
|
||||||
*/
|
*/
|
||||||
@ -127,21 +155,54 @@ static void signal_ip_config(NMVpnServicePlugin *plugin,
|
|||||||
|
|
||||||
handler = priv->handler;
|
handler = priv->handler;
|
||||||
|
|
||||||
/* NM apparently requires to know the gateway */
|
/* NM apparently requires to know the gateway (it uses it to install a
|
||||||
|
* direct route via physical interface if conflicting routes are passed) */
|
||||||
other = ike_sa->get_other_host(ike_sa);
|
other = ike_sa->get_other_host(ike_sa);
|
||||||
g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY,
|
g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY,
|
||||||
host_to_variant(other));
|
host_to_variant(other));
|
||||||
|
|
||||||
/* systemd-resolved requires a device to properly install DNS servers, but
|
/* systemd-resolved requires a device to properly install DNS servers, but
|
||||||
* Netkey does not use one. Passing the physical interface is not ideal,
|
* Netkey does not require one. Passing the physical interface is not ideal,
|
||||||
* as NM fiddles around with it and systemd-resolved likes a separate
|
* as NM fiddles around with it and systemd-resolved likes a separate
|
||||||
* device. So we pass a dummy TUN device along for NM etc. to play with...
|
* device. So we pass either an XFRM interface or a dummy TUN device along
|
||||||
|
* for NM etc. to play with...
|
||||||
*/
|
*/
|
||||||
if (priv->tun)
|
delete_interface(priv);
|
||||||
|
if (priv->xfrmi_manager && priv->xfrmi_id)
|
||||||
|
{
|
||||||
|
char name[IFNAMSIZ];
|
||||||
|
int mtu;
|
||||||
|
|
||||||
|
/* use the interface ID to get a unique name, fine if it's cut off */
|
||||||
|
snprintf(name, sizeof(name), "nm-xfrm-%" PRIu32, priv->xfrmi_id);
|
||||||
|
mtu = lib->settings->get_int(lib->settings, "charon-nm.mtu",
|
||||||
|
XFRMI_DEFAULT_MTU);
|
||||||
|
|
||||||
|
if (priv->xfrmi_manager->create(priv->xfrmi_manager, name,
|
||||||
|
priv->xfrmi_id, NULL, mtu))
|
||||||
|
{
|
||||||
|
priv->xfrmi = strdup(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!priv->xfrmi)
|
||||||
|
{
|
||||||
|
priv->tun = tun_device_create(NULL);
|
||||||
|
}
|
||||||
|
if (priv->xfrmi)
|
||||||
|
{
|
||||||
|
g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_TUNDEV,
|
||||||
|
g_variant_new_string (priv->xfrmi));
|
||||||
|
}
|
||||||
|
else if (priv->tun)
|
||||||
{
|
{
|
||||||
g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_TUNDEV,
|
g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_TUNDEV,
|
||||||
g_variant_new_string (priv->tun->get_name(priv->tun)));
|
g_variant_new_string (priv->tun->get_name(priv->tun)));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "failed to create XFRM or dummy TUN device, might affect "
|
||||||
|
"DNS server installation negatively");
|
||||||
|
}
|
||||||
|
|
||||||
/* pass the first virtual IPs we got or use the physical IP */
|
/* pass the first virtual IPs we got or use the physical IP */
|
||||||
enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
|
enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
|
||||||
@ -184,18 +245,16 @@ static void signal_ip_config(NMVpnServicePlugin *plugin,
|
|||||||
host_to_variant(vip4));
|
host_to_variant(vip4));
|
||||||
g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX,
|
g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX,
|
||||||
g_variant_new_uint32 (vip4->get_address(vip4).len * 8));
|
g_variant_new_uint32 (vip4->get_address(vip4).len * 8));
|
||||||
|
g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DNS,
|
||||||
|
handler_to_variant(handler, "au", INTERNAL_IP4_DNS));
|
||||||
|
g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NBNS,
|
||||||
|
handler_to_variant(handler, "au", INTERNAL_IP4_NBNS));
|
||||||
|
|
||||||
/* prevent NM from changing the default route. we set our own route in our
|
/* prevent NM from changing the default route, as we set our own routes
|
||||||
* own routing table
|
* in a separate routing table
|
||||||
*/
|
*/
|
||||||
g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT,
|
g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT,
|
||||||
g_variant_new_boolean (TRUE));
|
g_variant_new_boolean (TRUE));
|
||||||
|
|
||||||
g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DNS,
|
|
||||||
handler_to_variant(handler, "au", INTERNAL_IP4_DNS));
|
|
||||||
|
|
||||||
g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NBNS,
|
|
||||||
handler_to_variant(handler, "au", INTERNAL_IP4_NBNS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vip6)
|
if (vip6)
|
||||||
@ -204,11 +263,12 @@ static void signal_ip_config(NMVpnServicePlugin *plugin,
|
|||||||
host_to_variant(vip6));
|
host_to_variant(vip6));
|
||||||
g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_PREFIX,
|
g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_PREFIX,
|
||||||
g_variant_new_uint32 (vip6->get_address(vip6).len * 8));
|
g_variant_new_uint32 (vip6->get_address(vip6).len * 8));
|
||||||
g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT,
|
|
||||||
g_variant_new_boolean (TRUE));
|
|
||||||
g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_DNS,
|
g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_DNS,
|
||||||
handler_to_variant(handler, "aay", INTERNAL_IP6_DNS));
|
handler_to_variant(handler, "aay", INTERNAL_IP6_DNS));
|
||||||
/* NM_VPN_PLUGIN_IP6_CONFIG_NBNS is not defined */
|
/* NM_VPN_PLUGIN_IP6_CONFIG_NBNS is not defined */
|
||||||
|
|
||||||
|
g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT,
|
||||||
|
g_variant_new_boolean (TRUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
ip4config = g_variant_builder_end (&ip4builder);
|
ip4config = g_variant_builder_end (&ip4builder);
|
||||||
@ -646,6 +706,11 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
|
|||||||
NM_TYPE_SETTING_CONNECTION));
|
NM_TYPE_SETTING_CONNECTION));
|
||||||
vpn = NM_SETTING_VPN(nm_connection_get_setting(connection,
|
vpn = NM_SETTING_VPN(nm_connection_get_setting(connection,
|
||||||
NM_TYPE_SETTING_VPN));
|
NM_TYPE_SETTING_VPN));
|
||||||
|
if (priv->xfrmi_manager)
|
||||||
|
{
|
||||||
|
/* allocate a random interface ID */
|
||||||
|
priv->xfrmi_id = random();
|
||||||
|
}
|
||||||
if (priv->name)
|
if (priv->name)
|
||||||
{
|
{
|
||||||
free(priv->name);
|
free(priv->name);
|
||||||
@ -655,11 +720,6 @@ static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
|
|||||||
priv->name);
|
priv->name);
|
||||||
DBG4(DBG_CFG, "%s",
|
DBG4(DBG_CFG, "%s",
|
||||||
nm_setting_to_string(NM_SETTING(vpn)));
|
nm_setting_to_string(NM_SETTING(vpn)));
|
||||||
if (!priv->tun)
|
|
||||||
{
|
|
||||||
DBG1(DBG_CFG, "failed to create dummy TUN device, might affect DNS "
|
|
||||||
"server installation negatively");
|
|
||||||
}
|
|
||||||
ike.remote = (char*)nm_setting_vpn_get_data_item(vpn, "address");
|
ike.remote = (char*)nm_setting_vpn_get_data_item(vpn, "address");
|
||||||
if (!ike.remote || !*ike.remote)
|
if (!ike.remote || !*ike.remote)
|
||||||
{
|
{
|
||||||
@ -989,7 +1049,7 @@ static gboolean do_disconnect(gpointer plugin)
|
|||||||
NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
|
NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
ike_sa_t *ike_sa;
|
ike_sa_t *ike_sa;
|
||||||
u_int id;
|
u_int id = 0;
|
||||||
|
|
||||||
/* our ike_sa pointer might be invalid, lookup sa */
|
/* our ike_sa pointer might be invalid, lookup sa */
|
||||||
enumerator = charon->controller->create_ike_sa_enumerator(
|
enumerator = charon->controller->create_ike_sa_enumerator(
|
||||||
@ -999,20 +1059,27 @@ static gboolean do_disconnect(gpointer plugin)
|
|||||||
if (priv->ike_sa == ike_sa)
|
if (priv->ike_sa == ike_sa)
|
||||||
{
|
{
|
||||||
id = ike_sa->get_unique_id(ike_sa);
|
id = ike_sa->get_unique_id(ike_sa);
|
||||||
enumerator->destroy(enumerator);
|
break;
|
||||||
charon->controller->terminate_ike(charon->controller, id, FALSE,
|
|
||||||
controller_cb_empty, NULL, 0);
|
|
||||||
|
|
||||||
/* clear secrets as we are asked for new secrets (where we'd find
|
|
||||||
* the cached secrets from earlier connections) before we clear
|
|
||||||
* them in connect() */
|
|
||||||
priv->creds->clear(priv->creds);
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
g_debug("Connection not found.");
|
if (id)
|
||||||
|
{
|
||||||
|
charon->controller->terminate_ike(charon->controller, id, FALSE,
|
||||||
|
controller_cb_empty, NULL, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_debug("Connection not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear secrets as we are asked for new secrets (where we'd find the cached
|
||||||
|
* secrets from earlier connections) before we clear them in connect() */
|
||||||
|
priv->creds->clear(priv->creds);
|
||||||
|
|
||||||
|
/* delete any allocated interface */
|
||||||
|
delete_interface(priv);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1044,8 +1111,7 @@ static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
|
|||||||
priv->listener.ike_reestablish_pre = _ike_reestablish_pre;
|
priv->listener.ike_reestablish_pre = _ike_reestablish_pre;
|
||||||
priv->listener.ike_reestablish_post = _ike_reestablish_post;
|
priv->listener.ike_reestablish_post = _ike_reestablish_post;
|
||||||
charon->bus->add_listener(charon->bus, &priv->listener);
|
charon->bus->add_listener(charon->bus, &priv->listener);
|
||||||
priv->tun = tun_device_create(NULL);
|
priv->xfrmi_manager = lib->get(lib, KERNEL_NETLINK_XFRMI_MANAGER);
|
||||||
priv->name = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1058,11 +1124,7 @@ static void nm_strongswan_plugin_dispose(GObject *obj)
|
|||||||
|
|
||||||
plugin = NM_STRONGSWAN_PLUGIN(obj);
|
plugin = NM_STRONGSWAN_PLUGIN(obj);
|
||||||
priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
|
priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
|
||||||
if (priv->tun)
|
delete_interface(priv);
|
||||||
{
|
|
||||||
priv->tun->destroy(priv->tun);
|
|
||||||
priv->tun = NULL;
|
|
||||||
}
|
|
||||||
G_OBJECT_CLASS (nm_strongswan_plugin_parent_class)->dispose (obj);
|
G_OBJECT_CLASS (nm_strongswan_plugin_parent_class)->dispose (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,8 @@ libstrongswan_kernel_netlink_la_SOURCES = \
|
|||||||
kernel_netlink_plugin.h kernel_netlink_plugin.c \
|
kernel_netlink_plugin.h kernel_netlink_plugin.c \
|
||||||
kernel_netlink_ipsec.h kernel_netlink_ipsec.c \
|
kernel_netlink_ipsec.h kernel_netlink_ipsec.c \
|
||||||
kernel_netlink_net.h kernel_netlink_net.c \
|
kernel_netlink_net.h kernel_netlink_net.c \
|
||||||
kernel_netlink_shared.h kernel_netlink_shared.c
|
kernel_netlink_shared.h kernel_netlink_shared.c \
|
||||||
|
kernel_netlink_xfrmi.h kernel_netlink_xfrmi.c
|
||||||
|
|
||||||
libstrongswan_kernel_netlink_la_LIBADD = $(DLLIB)
|
libstrongswan_kernel_netlink_la_LIBADD = $(DLLIB)
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
|
|
||||||
#include "kernel_netlink_ipsec.h"
|
#include "kernel_netlink_ipsec.h"
|
||||||
#include "kernel_netlink_shared.h"
|
#include "kernel_netlink_shared.h"
|
||||||
|
#include "kernel_netlink_xfrmi.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
@ -337,6 +338,11 @@ struct private_kernel_netlink_ipsec_t {
|
|||||||
*/
|
*/
|
||||||
netlink_socket_t *socket_xfrm;
|
netlink_socket_t *socket_xfrm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XFRM interface manager
|
||||||
|
*/
|
||||||
|
kernel_netlink_xfrmi_t *xfrmi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Netlink xfrm socket to receive acquire and expire events
|
* Netlink xfrm socket to receive acquire and expire events
|
||||||
*/
|
*/
|
||||||
@ -352,6 +358,11 @@ struct private_kernel_netlink_ipsec_t {
|
|||||||
*/
|
*/
|
||||||
bool install_routes;
|
bool install_routes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to install routes via XFRM interfaces
|
||||||
|
*/
|
||||||
|
bool install_routes_xfrmi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to set protocol and ports on selector installed with transport
|
* Whether to set protocol and ports on selector installed with transport
|
||||||
* mode IPsec SAs
|
* mode IPsec SAs
|
||||||
@ -2730,6 +2741,30 @@ static void policy_change_done(private_kernel_netlink_ipsec_t *this,
|
|||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an XFRM interface with the given ID
|
||||||
|
*/
|
||||||
|
static bool find_xfrmi(private_kernel_netlink_ipsec_t *this, uint32_t target,
|
||||||
|
char **if_name)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
char *name;
|
||||||
|
uint32_t if_id;
|
||||||
|
|
||||||
|
enumerator = this->xfrmi->create_enumerator(this->xfrmi);
|
||||||
|
while (enumerator->enumerate(enumerator, &name, &if_id, NULL, NULL))
|
||||||
|
{
|
||||||
|
if (if_id == target)
|
||||||
|
{
|
||||||
|
*if_name = strdup(name);
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a route for the given policy if enabled and required
|
* Install a route for the given policy if enabled and required
|
||||||
*/
|
*/
|
||||||
@ -2759,9 +2794,15 @@ static void install_route(private_kernel_netlink_ipsec_t *this,
|
|||||||
|
|
||||||
if (!ipsec->dst->is_anyaddr(ipsec->dst))
|
if (!ipsec->dst->is_anyaddr(ipsec->dst))
|
||||||
{
|
{
|
||||||
route->gateway = charon->kernel->get_nexthop(charon->kernel,
|
/* if if_ids are used, install a route via XFRM interface if any,
|
||||||
ipsec->dst, -1, ipsec->src,
|
* otherwise install the route via the interface we reach the peer */
|
||||||
&route->if_name);
|
if (!policy->if_id || !this->xfrmi ||
|
||||||
|
!find_xfrmi(this, policy->if_id, &route->if_name))
|
||||||
|
{
|
||||||
|
route->gateway = charon->kernel->get_nexthop(charon->kernel,
|
||||||
|
ipsec->dst, -1, ipsec->src,
|
||||||
|
&route->if_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* for shunt policies */
|
{ /* for shunt policies */
|
||||||
@ -3000,12 +3041,12 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
|
|||||||
* - this is an outbound policy (to just get one for each child)
|
* - this is an outbound policy (to just get one for each child)
|
||||||
* - routing is not disabled via strongswan.conf
|
* - routing is not disabled via strongswan.conf
|
||||||
* - the selector is not for a specific protocol/port
|
* - the selector is not for a specific protocol/port
|
||||||
* - no XFRM interface ID is configured
|
* - routes via XFRM interfaces are enabled or no interface ID is configured
|
||||||
* - we are in tunnel/BEET mode or install a bypass policy
|
* - we are in tunnel/BEET mode or install a bypass policy
|
||||||
*/
|
*/
|
||||||
if (policy->direction == POLICY_OUT && this->install_routes &&
|
if (policy->direction == POLICY_OUT && this->install_routes &&
|
||||||
!policy->sel.proto && !policy->sel.dport && !policy->sel.sport &&
|
!policy->sel.proto && !policy->sel.dport && !policy->sel.sport &&
|
||||||
!policy->if_id)
|
(this->install_routes_xfrmi || !policy->if_id))
|
||||||
{
|
{
|
||||||
if (mapping->type == POLICY_PASS ||
|
if (mapping->type == POLICY_PASS ||
|
||||||
(mapping->type == POLICY_IPSEC && ipsec->cfg.mode != MODE_TRANSPORT))
|
(mapping->type == POLICY_IPSEC && ipsec->cfg.mode != MODE_TRANSPORT))
|
||||||
@ -3949,6 +3990,11 @@ METHOD(kernel_ipsec_t, destroy, void,
|
|||||||
DESTROY_IF(this->socket_link_events);
|
DESTROY_IF(this->socket_link_events);
|
||||||
DESTROY_IF(this->socket_xfrm_events);
|
DESTROY_IF(this->socket_xfrm_events);
|
||||||
array_destroy_function(this->bypass, remove_port_bypass, this);
|
array_destroy_function(this->bypass, remove_port_bypass, this);
|
||||||
|
if (this->xfrmi)
|
||||||
|
{
|
||||||
|
lib->set(lib, KERNEL_NETLINK_XFRMI_MANAGER, NULL);
|
||||||
|
kernel_netlink_xfrmi_destroy(this->xfrmi);
|
||||||
|
}
|
||||||
DESTROY_IF(this->socket_xfrm);
|
DESTROY_IF(this->socket_xfrm);
|
||||||
enumerator = this->policies->create_enumerator(this->policies);
|
enumerator = this->policies->create_enumerator(this->policies);
|
||||||
while (enumerator->enumerate(enumerator, NULL, &policy))
|
while (enumerator->enumerate(enumerator, NULL, &policy))
|
||||||
@ -4137,9 +4183,13 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
|
|||||||
.get_priority = dlsym(RTLD_DEFAULT,
|
.get_priority = dlsym(RTLD_DEFAULT,
|
||||||
"kernel_netlink_get_priority_custom"),
|
"kernel_netlink_get_priority_custom"),
|
||||||
.policy_update = lib->settings->get_bool(lib->settings,
|
.policy_update = lib->settings->get_bool(lib->settings,
|
||||||
"%s.plugins.kernel-netlink.policy_update", FALSE, lib->ns),
|
"%s.plugins.kernel-netlink.policy_update",
|
||||||
|
FALSE, lib->ns),
|
||||||
.install_routes = lib->settings->get_bool(lib->settings,
|
.install_routes = lib->settings->get_bool(lib->settings,
|
||||||
"%s.install_routes", TRUE, lib->ns),
|
"%s.install_routes", TRUE, lib->ns),
|
||||||
|
.install_routes_xfrmi = lib->settings->get_bool(lib->settings,
|
||||||
|
"%s.plugins.kernel-netlink.install_routes_xfrmi",
|
||||||
|
FALSE, lib->ns),
|
||||||
.proto_port_transport = lib->settings->get_bool(lib->settings,
|
.proto_port_transport = lib->settings->get_bool(lib->settings,
|
||||||
"%s.plugins.kernel-netlink.set_proto_port_transport_sa",
|
"%s.plugins.kernel-netlink.set_proto_port_transport_sa",
|
||||||
FALSE, lib->ns),
|
FALSE, lib->ns),
|
||||||
@ -4188,5 +4238,11 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->xfrmi = kernel_netlink_xfrmi_create(TRUE);
|
||||||
|
if (this->xfrmi)
|
||||||
|
{
|
||||||
|
lib->set(lib, KERNEL_NETLINK_XFRMI_MANAGER, this->xfrmi);
|
||||||
|
}
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
445
src/libcharon/plugins/kernel_netlink/kernel_netlink_xfrmi.c
Normal file
445
src/libcharon/plugins/kernel_netlink/kernel_netlink_xfrmi.c
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019-2023 Tobias Brunner
|
||||||
|
*
|
||||||
|
* Copyright (C) secunet Security Networks AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include "kernel_netlink_xfrmi.h"
|
||||||
|
#include "kernel_netlink_shared.h"
|
||||||
|
|
||||||
|
#ifndef IFLA_XFRM_MAX
|
||||||
|
enum {
|
||||||
|
IFLA_XFRM_UNSPEC,
|
||||||
|
IFLA_XFRM_LINK,
|
||||||
|
IFLA_XFRM_IF_ID,
|
||||||
|
__IFLA_XFRM_MAX
|
||||||
|
};
|
||||||
|
#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct private_kernel_netlink_xfrmi_t private_kernel_netlink_xfrmi_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data
|
||||||
|
*/
|
||||||
|
struct private_kernel_netlink_xfrmi_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public interface
|
||||||
|
*/
|
||||||
|
kernel_netlink_xfrmi_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Netlink socket
|
||||||
|
*/
|
||||||
|
netlink_socket_t *socket;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "up" the interface with the given name
|
||||||
|
*/
|
||||||
|
static bool interface_up(private_kernel_netlink_xfrmi_t *this, char *name)
|
||||||
|
{
|
||||||
|
netlink_buf_t request;
|
||||||
|
struct nlmsghdr *hdr;
|
||||||
|
struct ifinfomsg *msg;
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof(request));
|
||||||
|
|
||||||
|
hdr = &request.hdr;
|
||||||
|
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
|
hdr->nlmsg_type = RTM_SETLINK;
|
||||||
|
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
|
|
||||||
|
msg = NLMSG_DATA(hdr);
|
||||||
|
msg->ifi_family = AF_UNSPEC;
|
||||||
|
msg->ifi_change |= IFF_UP;
|
||||||
|
msg->ifi_flags |= IFF_UP;
|
||||||
|
|
||||||
|
netlink_add_attribute(hdr, IFLA_IFNAME, chunk_from_str(name),
|
||||||
|
sizeof(request));
|
||||||
|
|
||||||
|
if (this->socket->send_ack(this->socket, hdr) != SUCCESS)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "failed to bring up XFRM interface '%s'", name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(kernel_netlink_xfrmi_t, create, bool,
|
||||||
|
private_kernel_netlink_xfrmi_t *this, char *name, uint32_t if_id,
|
||||||
|
char *phys, uint32_t mtu)
|
||||||
|
{
|
||||||
|
netlink_buf_t request;
|
||||||
|
struct nlmsghdr *hdr;
|
||||||
|
struct ifinfomsg *msg;
|
||||||
|
struct rtattr *linkinfo, *info_data;
|
||||||
|
uint32_t ifindex = 0;
|
||||||
|
|
||||||
|
if (phys)
|
||||||
|
{
|
||||||
|
ifindex = if_nametoindex(phys);
|
||||||
|
if (!ifindex)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "physical interface '%s' not found", phys);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof(request));
|
||||||
|
|
||||||
|
hdr = &request.hdr;
|
||||||
|
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
|
||||||
|
hdr->nlmsg_type = RTM_NEWLINK;
|
||||||
|
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
|
|
||||||
|
msg = NLMSG_DATA(hdr);
|
||||||
|
msg->ifi_family = AF_UNSPEC;
|
||||||
|
|
||||||
|
netlink_add_attribute(hdr, IFLA_IFNAME, chunk_from_str(name),
|
||||||
|
sizeof(request));
|
||||||
|
if (mtu)
|
||||||
|
{
|
||||||
|
netlink_add_attribute(hdr, IFLA_MTU, chunk_from_thing(mtu),
|
||||||
|
sizeof(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
linkinfo = netlink_nested_start(hdr, sizeof(request), IFLA_LINKINFO);
|
||||||
|
|
||||||
|
netlink_add_attribute(hdr, IFLA_INFO_KIND, chunk_from_str("xfrm"),
|
||||||
|
sizeof(request));
|
||||||
|
|
||||||
|
info_data = netlink_nested_start(hdr, sizeof(request), IFLA_INFO_DATA);
|
||||||
|
|
||||||
|
netlink_add_attribute(hdr, IFLA_XFRM_IF_ID, chunk_from_thing(if_id),
|
||||||
|
sizeof(request));
|
||||||
|
if (ifindex)
|
||||||
|
{
|
||||||
|
netlink_add_attribute(hdr, IFLA_XFRM_LINK, chunk_from_thing(ifindex),
|
||||||
|
sizeof(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
netlink_nested_end(hdr, info_data);
|
||||||
|
netlink_nested_end(hdr, linkinfo);
|
||||||
|
|
||||||
|
switch (this->socket->send_ack(this->socket, hdr))
|
||||||
|
{
|
||||||
|
case SUCCESS:
|
||||||
|
return interface_up(this, name);
|
||||||
|
case ALREADY_DONE:
|
||||||
|
DBG1(DBG_KNL, "XFRM interface '%s' already exists", name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBG1(DBG_KNL, "failed to create XFRM interface '%s'", name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** enumerator over XFRM interfaces */
|
||||||
|
typedef struct {
|
||||||
|
/** public interface */
|
||||||
|
enumerator_t public;
|
||||||
|
/** message from the kernel */
|
||||||
|
struct nlmsghdr *msg;
|
||||||
|
/** current message from the kernel */
|
||||||
|
struct nlmsghdr *current;
|
||||||
|
/** remaining length */
|
||||||
|
size_t len;
|
||||||
|
/** current physical interface (if any) */
|
||||||
|
char phys[IFNAMSIZ];
|
||||||
|
} interface_enumerator_t;
|
||||||
|
|
||||||
|
METHOD(enumerator_t, destroy_enumerator, void,
|
||||||
|
interface_enumerator_t *this)
|
||||||
|
{
|
||||||
|
free(this->msg);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse attributes nested in IFLA_INFO_DATA
|
||||||
|
*/
|
||||||
|
static void parse_info_data(struct rtattr *rta, size_t rtasize, bool *has_phys,
|
||||||
|
char *phys, uint32_t *if_id)
|
||||||
|
{
|
||||||
|
uint32_t ifindex;
|
||||||
|
|
||||||
|
while (RTA_OK(rta, rtasize))
|
||||||
|
{
|
||||||
|
switch (rta->rta_type)
|
||||||
|
{
|
||||||
|
case IFLA_XFRM_IF_ID:
|
||||||
|
if (RTA_PAYLOAD(rta) == sizeof(*if_id))
|
||||||
|
{
|
||||||
|
*if_id = *(uint32_t*)RTA_DATA(rta);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IFLA_XFRM_LINK:
|
||||||
|
if (RTA_PAYLOAD(rta) == sizeof(ifindex))
|
||||||
|
{
|
||||||
|
ifindex = *(uint32_t*)RTA_DATA(rta);
|
||||||
|
if (ifindex)
|
||||||
|
{
|
||||||
|
if_indextoname(ifindex, phys);
|
||||||
|
*has_phys = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rta = RTA_NEXT(rta, rtasize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse attributes nested in IFLA_LINKINFO
|
||||||
|
*/
|
||||||
|
static void parse_linkinfo(struct rtattr *rta, size_t rtasize, bool *type_match,
|
||||||
|
bool *has_phys, char *phys, uint32_t *if_id)
|
||||||
|
{
|
||||||
|
while (RTA_OK(rta, rtasize))
|
||||||
|
{
|
||||||
|
switch (rta->rta_type)
|
||||||
|
{
|
||||||
|
case IFLA_INFO_KIND:
|
||||||
|
*type_match = streq("xfrm", RTA_DATA(rta));
|
||||||
|
break;
|
||||||
|
case IFLA_INFO_DATA:
|
||||||
|
parse_info_data(RTA_DATA(rta), RTA_PAYLOAD(rta), has_phys,
|
||||||
|
phys, if_id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rta = RTA_NEXT(rta, rtasize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(enumerator_t, enumerate, bool,
|
||||||
|
interface_enumerator_t *this, va_list args)
|
||||||
|
{
|
||||||
|
char **name;
|
||||||
|
uint32_t *if_id, *mtu;
|
||||||
|
char **phys;
|
||||||
|
|
||||||
|
VA_ARGS_VGET(args, name, if_id, phys, mtu);
|
||||||
|
|
||||||
|
if (!this->current)
|
||||||
|
{
|
||||||
|
this->current = this->msg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->current = NLMSG_NEXT(this->current, this->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (NLMSG_OK(this->current, this->len))
|
||||||
|
{
|
||||||
|
switch (this->current->nlmsg_type)
|
||||||
|
{
|
||||||
|
case NLMSG_DONE:
|
||||||
|
break;
|
||||||
|
case RTM_NEWLINK:
|
||||||
|
{
|
||||||
|
struct ifinfomsg *msg = NLMSG_DATA(this->current);
|
||||||
|
struct rtattr *rta = IFLA_RTA(msg);
|
||||||
|
size_t rtasize = IFLA_PAYLOAD(this->current);
|
||||||
|
bool type_match = FALSE, has_phys = FALSE;
|
||||||
|
|
||||||
|
*name = NULL;
|
||||||
|
|
||||||
|
while (RTA_OK(rta, rtasize))
|
||||||
|
{
|
||||||
|
switch (rta->rta_type)
|
||||||
|
{
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
*name = RTA_DATA(rta);
|
||||||
|
break;
|
||||||
|
case IFLA_MTU:
|
||||||
|
if (mtu && RTA_PAYLOAD(rta) == sizeof(*mtu))
|
||||||
|
{
|
||||||
|
*mtu = *(uint32_t*)RTA_DATA(rta);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IFLA_LINKINFO:
|
||||||
|
parse_linkinfo(RTA_DATA(rta), RTA_PAYLOAD(rta),
|
||||||
|
&type_match, &has_phys, this->phys,
|
||||||
|
if_id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rta = RTA_NEXT(rta, rtasize);
|
||||||
|
}
|
||||||
|
if (*name && type_match)
|
||||||
|
{
|
||||||
|
if (phys)
|
||||||
|
{
|
||||||
|
*phys = has_phys ? this->phys : NULL;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/* fall-through */
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
this->current = NLMSG_NEXT(this->current, this->len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(kernel_netlink_xfrmi_t, create_enumerator, enumerator_t*,
|
||||||
|
private_kernel_netlink_xfrmi_t *this)
|
||||||
|
{
|
||||||
|
netlink_buf_t request;
|
||||||
|
struct nlmsghdr *hdr, *out;
|
||||||
|
struct ifinfomsg *msg;
|
||||||
|
struct rtattr *linkinfo;
|
||||||
|
size_t len;
|
||||||
|
interface_enumerator_t *enumerator;
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof(request));
|
||||||
|
|
||||||
|
hdr = &request.hdr;
|
||||||
|
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||||
|
hdr->nlmsg_type = RTM_GETLINK;
|
||||||
|
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
|
|
||||||
|
msg = NLMSG_DATA(hdr);
|
||||||
|
msg->ifi_family = AF_UNSPEC;
|
||||||
|
|
||||||
|
/* if the kernel doesn't know the type we set here, it will just return all
|
||||||
|
* interfaces, so we filter the type ourselves too in the callback */
|
||||||
|
linkinfo = netlink_nested_start(hdr, sizeof(request), IFLA_LINKINFO);
|
||||||
|
|
||||||
|
netlink_add_attribute(hdr, IFLA_INFO_KIND, chunk_from_str("xfrm"),
|
||||||
|
sizeof(request));
|
||||||
|
|
||||||
|
netlink_nested_end(hdr, linkinfo);
|
||||||
|
|
||||||
|
if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS)
|
||||||
|
{
|
||||||
|
DBG2(DBG_KNL, "enumerating XFRM interfaces failed");
|
||||||
|
return enumerator_create_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT(enumerator,
|
||||||
|
.public = {
|
||||||
|
.enumerate = enumerator_enumerate_default,
|
||||||
|
.venumerate = _enumerate,
|
||||||
|
.destroy = _destroy_enumerator,
|
||||||
|
},
|
||||||
|
.msg = out,
|
||||||
|
.len = len,
|
||||||
|
);
|
||||||
|
return &enumerator->public;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(kernel_netlink_xfrmi_t, delete, bool,
|
||||||
|
private_kernel_netlink_xfrmi_t *this, char *name)
|
||||||
|
{
|
||||||
|
netlink_buf_t request;
|
||||||
|
struct nlmsghdr *hdr;
|
||||||
|
struct ifinfomsg *msg;
|
||||||
|
struct rtattr *linkinfo;
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof(request));
|
||||||
|
|
||||||
|
hdr = &request.hdr;
|
||||||
|
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
|
hdr->nlmsg_type = RTM_DELLINK;
|
||||||
|
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
|
|
||||||
|
msg = NLMSG_DATA(hdr);
|
||||||
|
msg->ifi_family = AF_UNSPEC;
|
||||||
|
|
||||||
|
netlink_add_attribute(hdr, IFLA_IFNAME, chunk_from_str(name),
|
||||||
|
sizeof(request));
|
||||||
|
|
||||||
|
/* the type doesn't seem to matter, but let's still set it */
|
||||||
|
linkinfo = netlink_nested_start(hdr, sizeof(request), IFLA_LINKINFO);
|
||||||
|
|
||||||
|
netlink_add_attribute(hdr, IFLA_INFO_KIND, chunk_from_str("xfrm"),
|
||||||
|
sizeof(request));
|
||||||
|
|
||||||
|
netlink_nested_end(hdr, linkinfo);
|
||||||
|
|
||||||
|
switch (this->socket->send_ack(this->socket, hdr))
|
||||||
|
{
|
||||||
|
case SUCCESS:
|
||||||
|
return TRUE;
|
||||||
|
case NOT_FOUND:
|
||||||
|
DBG1(DBG_KNL, "XFRM interface '%s' not found to delete", name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBG1(DBG_KNL, "failed to delete XFRM interface '%s'", name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_netlink_xfrmi_destroy(kernel_netlink_xfrmi_t *pub)
|
||||||
|
{
|
||||||
|
private_kernel_netlink_xfrmi_t *this = (private_kernel_netlink_xfrmi_t*)pub;
|
||||||
|
|
||||||
|
this->socket->destroy(this->socket);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
kernel_netlink_xfrmi_t *kernel_netlink_xfrmi_create(bool test)
|
||||||
|
{
|
||||||
|
private_kernel_netlink_xfrmi_t *this;
|
||||||
|
char name[IFNAMSIZ] = {};
|
||||||
|
uint32_t if_id;
|
||||||
|
|
||||||
|
INIT(this,
|
||||||
|
.public = {
|
||||||
|
.create = _create,
|
||||||
|
.create_enumerator = _create_enumerator,
|
||||||
|
.delete = _delete,
|
||||||
|
},
|
||||||
|
.socket = netlink_socket_create(NETLINK_ROUTE, NULL, FALSE),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!this->socket)
|
||||||
|
{
|
||||||
|
free(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (test)
|
||||||
|
{
|
||||||
|
/* try to create an XFRM interface to see if the kernel supports it, use
|
||||||
|
* a random ID and name for the test to avoid conflicts */
|
||||||
|
if_id = random();
|
||||||
|
snprintf(name, sizeof(name), "xfrmi-test-%u", if_id);
|
||||||
|
|
||||||
|
if (!create(this, name, if_id, NULL, 0))
|
||||||
|
{
|
||||||
|
kernel_netlink_xfrmi_destroy(&this->public);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
DBG2(DBG_KNL, "XFRM interfaces supported by kernel");
|
||||||
|
delete(this, name);
|
||||||
|
}
|
||||||
|
return &this->public;
|
||||||
|
}
|
84
src/libcharon/plugins/kernel_netlink/kernel_netlink_xfrmi.h
Normal file
84
src/libcharon/plugins/kernel_netlink/kernel_netlink_xfrmi.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022-2023 Tobias Brunner
|
||||||
|
*
|
||||||
|
* Copyright (C) secunet Security Networks AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup kernel_netlink_xfrmi kernel_netlink_xfrmi
|
||||||
|
* @{ @ingroup kernel_netlink
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KERNEL_NETLINK_XFRMI_H_
|
||||||
|
#define KERNEL_NETLINK_XFRMI_H_
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
#define KERNEL_NETLINK_XFRMI_MANAGER "kernel-netlink-xfrmi"
|
||||||
|
|
||||||
|
typedef struct kernel_netlink_xfrmi_t kernel_netlink_xfrmi_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple manager for XFRM interfaces. An instance can be retrieved via
|
||||||
|
* lib::get() under the key "kernel-netlink-xfrmi" if the kernel-netlink plugin
|
||||||
|
* is loaded and XFRM interfaces are supported by the kernel.
|
||||||
|
*/
|
||||||
|
struct kernel_netlink_xfrmi_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an XFRM interface with the given name, interface ID and
|
||||||
|
* optional underlying physical interface and MTU.
|
||||||
|
*
|
||||||
|
* @param name name of the XFRM interface
|
||||||
|
* @param if_id interface ID (has to match SAs/policies)
|
||||||
|
* @param phys name of the underlying physical interface (optional)
|
||||||
|
* @param mtu MTU of the interface (optional, 0 for default)
|
||||||
|
* @return TRUE if interface was successfully created
|
||||||
|
*/
|
||||||
|
bool (*create)(kernel_netlink_xfrmi_t *this, char *name, uint32_t if_id,
|
||||||
|
char *phys, uint32_t mtu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerate existing XFRM interfaces.
|
||||||
|
*
|
||||||
|
* @return enumerator over (char *name, uint32_t if_id,
|
||||||
|
* char *phys, u_int mtu)
|
||||||
|
*/
|
||||||
|
enumerator_t *(*create_enumerator)(kernel_netlink_xfrmi_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the XFRM interface with the given name.
|
||||||
|
*
|
||||||
|
* @note This deletes any type of interface with the given name.
|
||||||
|
*
|
||||||
|
* @param name name of the XFRM interface
|
||||||
|
* @return TRUE if interface was successfully deleted
|
||||||
|
*/
|
||||||
|
bool (*delete)(kernel_netlink_xfrmi_t *this, char *name);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the manager.
|
||||||
|
*
|
||||||
|
* @param test test if XFRM interfaces can be created (requires CAP_NET_ADMIN)
|
||||||
|
* @return kernel_netlink_xfrmi_t instance, or NULL if test failed
|
||||||
|
*/
|
||||||
|
kernel_netlink_xfrmi_t *kernel_netlink_xfrmi_create(bool test);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the given manager. Not a method in the interface above to prevent
|
||||||
|
* users from destroying the manager.
|
||||||
|
*/
|
||||||
|
void kernel_netlink_xfrmi_destroy(kernel_netlink_xfrmi_t *this);
|
||||||
|
|
||||||
|
#endif /** KERNEL_NETLINK_XFRMI_H_ @}*/
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 Tobias Brunner
|
* Copyright (C) 2019-2023 Tobias Brunner
|
||||||
*
|
*
|
||||||
* Copyright (C) secunet Security Networks AG
|
* Copyright (C) secunet Security Networks AG
|
||||||
*
|
*
|
||||||
@ -19,222 +19,46 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <linux/netlink.h>
|
|
||||||
#include <linux/rtnetlink.h>
|
|
||||||
|
|
||||||
#include "kernel_netlink_shared.h"
|
#include "kernel_netlink_xfrmi.h"
|
||||||
|
|
||||||
#ifndef IFLA_XFRM_MAX
|
|
||||||
enum {
|
|
||||||
IFLA_XFRM_UNSPEC,
|
|
||||||
IFLA_XFRM_LINK,
|
|
||||||
IFLA_XFRM_IF_ID,
|
|
||||||
__IFLA_XFRM_MAX
|
|
||||||
};
|
|
||||||
#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an XFRM interface with the given ID and underlying interface
|
* Default MTU
|
||||||
*/
|
*/
|
||||||
static int add_xfrm_interface(char *name, uint32_t xfrm_id, uint32_t ifindex)
|
#define XFRMI_DEFAULT_MTU 1400
|
||||||
{
|
|
||||||
netlink_buf_t request;
|
|
||||||
struct nlmsghdr *hdr;
|
|
||||||
struct ifinfomsg *msg;
|
|
||||||
struct rtattr *linkinfo, *info_data;
|
|
||||||
netlink_socket_t *socket;
|
|
||||||
int status = 1;
|
|
||||||
|
|
||||||
socket = netlink_socket_create(NETLINK_ROUTE, NULL, FALSE);
|
|
||||||
if (!socket)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&request, 0, sizeof(request));
|
|
||||||
|
|
||||||
hdr = &request.hdr;
|
|
||||||
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
|
|
||||||
hdr->nlmsg_type = RTM_NEWLINK;
|
|
||||||
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
|
||||||
|
|
||||||
msg = NLMSG_DATA(hdr);
|
|
||||||
msg->ifi_family = AF_UNSPEC;
|
|
||||||
|
|
||||||
netlink_add_attribute(hdr, IFLA_IFNAME, chunk_from_str(name),
|
|
||||||
sizeof(request));
|
|
||||||
|
|
||||||
linkinfo = netlink_nested_start(hdr, sizeof(request), IFLA_LINKINFO);
|
|
||||||
|
|
||||||
netlink_add_attribute(hdr, IFLA_INFO_KIND, chunk_from_str("xfrm"),
|
|
||||||
sizeof(request));
|
|
||||||
|
|
||||||
info_data = netlink_nested_start(hdr, sizeof(request), IFLA_INFO_DATA);
|
|
||||||
|
|
||||||
netlink_add_attribute(hdr, IFLA_XFRM_IF_ID, chunk_from_thing(xfrm_id),
|
|
||||||
sizeof(request));
|
|
||||||
netlink_add_attribute(hdr, IFLA_XFRM_LINK, chunk_from_thing(ifindex),
|
|
||||||
sizeof(request));
|
|
||||||
|
|
||||||
netlink_nested_end(hdr, info_data);
|
|
||||||
netlink_nested_end(hdr, linkinfo);
|
|
||||||
|
|
||||||
switch (socket->send_ack(socket, hdr))
|
|
||||||
{
|
|
||||||
case SUCCESS:
|
|
||||||
status = 0;
|
|
||||||
break;
|
|
||||||
case ALREADY_DONE:
|
|
||||||
fprintf(stderr, "XFRM interface already exists\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "failed to create XFRM interface\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
socket->destroy(socket);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse attributes nested in IFLA_INFO_DATA
|
* Manager for XFRM interfaces
|
||||||
*/
|
*/
|
||||||
static void parse_info_data(struct rtattr *rta, size_t rtasize, char *phys,
|
static kernel_netlink_xfrmi_t *manager;
|
||||||
uint32_t *if_id)
|
|
||||||
{
|
|
||||||
uint32_t ifindex;
|
|
||||||
|
|
||||||
while (RTA_OK(rta, rtasize))
|
|
||||||
{
|
|
||||||
switch (rta->rta_type)
|
|
||||||
{
|
|
||||||
case IFLA_XFRM_IF_ID:
|
|
||||||
if (RTA_PAYLOAD(rta) == sizeof(*if_id))
|
|
||||||
{
|
|
||||||
*if_id = *(uint32_t*)RTA_DATA(rta);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case IFLA_XFRM_LINK:
|
|
||||||
if (RTA_PAYLOAD(rta) == sizeof(ifindex))
|
|
||||||
{
|
|
||||||
ifindex = *(uint32_t*)RTA_DATA(rta);
|
|
||||||
if_indextoname(ifindex, phys);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rta = RTA_NEXT(rta, rtasize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse attributes nested in IFLA_LINKINFO
|
* Destroy the allocated manager
|
||||||
*/
|
*/
|
||||||
static void parse_linkinfo(struct rtattr *rta, size_t rtasize, char *phys,
|
static void destroy_manager()
|
||||||
uint32_t *if_id)
|
|
||||||
{
|
{
|
||||||
while (RTA_OK(rta, rtasize))
|
if (manager)
|
||||||
{
|
{
|
||||||
switch (rta->rta_type)
|
kernel_netlink_xfrmi_destroy(manager);
|
||||||
{
|
|
||||||
case IFLA_INFO_DATA:
|
|
||||||
parse_info_data(RTA_DATA(rta), RTA_PAYLOAD(rta), phys, if_id);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rta = RTA_NEXT(rta, rtasize);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all installed XFRM interfaces
|
* List all installed XFRM interfaces
|
||||||
*/
|
*/
|
||||||
static int list_xfrm_interfaces()
|
static void list_xfrm_interfaces(kernel_netlink_xfrmi_t *manager)
|
||||||
{
|
{
|
||||||
netlink_buf_t request;
|
enumerator_t *enumerator;
|
||||||
struct nlmsghdr *hdr, *out, *current;
|
char *name, *dev;
|
||||||
struct ifinfomsg *msg;
|
uint32_t xfrm_id, mtu;
|
||||||
struct rtattr *linkinfo;
|
|
||||||
netlink_socket_t *socket;
|
|
||||||
size_t len;
|
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
socket = netlink_socket_create(NETLINK_ROUTE, NULL, FALSE);
|
enumerator = manager->create_enumerator(manager);
|
||||||
if (!socket)
|
while (enumerator->enumerate(enumerator, &name, &xfrm_id, &dev, &mtu))
|
||||||
{
|
{
|
||||||
return 1;
|
printf("%2u: %-16s dev %-12s if_id 0x%.8x [%10u] mtu %u\n",
|
||||||
|
if_nametoindex(name), name, dev ?: "-", xfrm_id, xfrm_id, mtu);
|
||||||
}
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
memset(&request, 0, sizeof(request));
|
|
||||||
|
|
||||||
hdr = &request.hdr;
|
|
||||||
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
|
||||||
hdr->nlmsg_type = RTM_GETLINK;
|
|
||||||
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
|
||||||
|
|
||||||
msg = NLMSG_DATA(hdr);
|
|
||||||
msg->ifi_family = AF_UNSPEC;
|
|
||||||
|
|
||||||
linkinfo = netlink_nested_start(hdr, sizeof(request), IFLA_LINKINFO);
|
|
||||||
|
|
||||||
netlink_add_attribute(hdr, IFLA_INFO_KIND, chunk_from_str("xfrm"),
|
|
||||||
sizeof(request));
|
|
||||||
|
|
||||||
netlink_nested_end(hdr, linkinfo);
|
|
||||||
|
|
||||||
if (socket->send(socket, hdr, &out, &len) != SUCCESS)
|
|
||||||
{
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
current = out;
|
|
||||||
while (NLMSG_OK(current, len))
|
|
||||||
{
|
|
||||||
switch (current->nlmsg_type)
|
|
||||||
{
|
|
||||||
case NLMSG_DONE:
|
|
||||||
break;
|
|
||||||
case RTM_NEWLINK:
|
|
||||||
msg = NLMSG_DATA(current);
|
|
||||||
struct rtattr *rta = IFLA_RTA(msg);
|
|
||||||
size_t rtasize = IFLA_PAYLOAD(current);
|
|
||||||
char *name = NULL, phys[IF_NAMESIZE] = {};
|
|
||||||
uint32_t if_id = 0;
|
|
||||||
|
|
||||||
while (RTA_OK(rta, rtasize))
|
|
||||||
{
|
|
||||||
switch (rta->rta_type)
|
|
||||||
{
|
|
||||||
case IFLA_IFNAME:
|
|
||||||
name = RTA_DATA(rta);
|
|
||||||
break;
|
|
||||||
case IFLA_LINKINFO:
|
|
||||||
parse_linkinfo(RTA_DATA(rta), RTA_PAYLOAD(rta),
|
|
||||||
phys, &if_id);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rta = RTA_NEXT(rta, rtasize);
|
|
||||||
}
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
printf("%2u: %-16s dev %-8s if_id 0x%.8x [%u]\n",
|
|
||||||
msg->ifi_index, name, phys, if_id, if_id);
|
|
||||||
}
|
|
||||||
/* fall through */
|
|
||||||
default:
|
|
||||||
current = NLMSG_NEXT(current, len);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
free(out);
|
|
||||||
|
|
||||||
socket->destroy(socket);
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(FILE *out, char *name)
|
static void usage(FILE *out, char *name)
|
||||||
@ -247,19 +71,22 @@ static void usage(FILE *out, char *name)
|
|||||||
fprintf(out, " -l, --list list XFRM interfaces.\n");
|
fprintf(out, " -l, --list list XFRM interfaces.\n");
|
||||||
fprintf(out, " -n, --name=NAME name of the XFRM interface.\n");
|
fprintf(out, " -n, --name=NAME name of the XFRM interface.\n");
|
||||||
fprintf(out, " -i, --id=ID optional numeric XFRM ID.\n");
|
fprintf(out, " -i, --id=ID optional numeric XFRM ID.\n");
|
||||||
fprintf(out, " -d, --dev=DEVICE underlying physical interface.\n");
|
fprintf(out, " -d, --dev=DEVICE optional underlying physical interface.\n");
|
||||||
|
fprintf(out, " -m, --mtu=MTU optional MTU, default: 1400 (use 0 for kernel default).\n");
|
||||||
fprintf(out, "\n");
|
fprintf(out, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *name = NULL, *dev = NULL, *end;
|
char *name = NULL, *dev = NULL, *end;
|
||||||
uint32_t xfrm_id = 0;
|
uint32_t xfrm_id = 0, mtu = XFRMI_DEFAULT_MTU;
|
||||||
u_int ifindex;
|
|
||||||
|
|
||||||
library_init(NULL, "xfrmi");
|
library_init(NULL, "xfrmi");
|
||||||
atexit(library_deinit);
|
atexit(library_deinit);
|
||||||
|
|
||||||
|
manager = kernel_netlink_xfrmi_create(FALSE);
|
||||||
|
atexit(destroy_manager);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
struct option long_opts[] = {
|
struct option long_opts[] = {
|
||||||
@ -269,9 +96,10 @@ int main(int argc, char *argv[])
|
|||||||
{"name", required_argument, NULL, 'n' },
|
{"name", required_argument, NULL, 'n' },
|
||||||
{"id", required_argument, NULL, 'i' },
|
{"id", required_argument, NULL, 'i' },
|
||||||
{"dev", required_argument, NULL, 'd' },
|
{"dev", required_argument, NULL, 'd' },
|
||||||
|
{"mtu", required_argument, NULL, 'm' },
|
||||||
{0,0,0,0 },
|
{0,0,0,0 },
|
||||||
};
|
};
|
||||||
switch (getopt_long(argc, argv, "hvln:i:d:", long_opts, NULL))
|
switch (getopt_long(argc, argv, "hvln:i:d:m:", long_opts, NULL))
|
||||||
{
|
{
|
||||||
case EOF:
|
case EOF:
|
||||||
break;
|
break;
|
||||||
@ -279,7 +107,7 @@ int main(int argc, char *argv[])
|
|||||||
usage(stdout, argv[0]);
|
usage(stdout, argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
case 'l':
|
case 'l':
|
||||||
list_xfrm_interfaces();
|
list_xfrm_interfaces(manager);
|
||||||
return 0;
|
return 0;
|
||||||
case 'v':
|
case 'v':
|
||||||
dbg_default_set_level(atoi(optarg));
|
dbg_default_set_level(atoi(optarg));
|
||||||
@ -300,24 +128,26 @@ int main(int argc, char *argv[])
|
|||||||
case 'd':
|
case 'd':
|
||||||
dev = optarg;
|
dev = optarg;
|
||||||
continue;
|
continue;
|
||||||
|
case 'm':
|
||||||
|
errno = 0;
|
||||||
|
mtu = strtoul(optarg, &end, 0);
|
||||||
|
if (errno || *end)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "invalid MTU: %s\n",
|
||||||
|
errno ? strerror(errno) : end);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
default:
|
default:
|
||||||
usage(stderr, argv[0]);
|
usage(stderr, argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!name)
|
||||||
if (!name || !dev)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "please specify a name and a physical interface\n");
|
fprintf(stderr, "please specify a name\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ifindex = if_nametoindex(dev);
|
return !manager->create(manager, name, xfrm_id, dev, mtu);
|
||||||
if (!ifindex)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "physical interface %s not found\n", dev);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return add_xfrm_interface(name, xfrm_id, ifindex);
|
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,10 @@ def handle_interfaces(ike_sa, up):
|
|||||||
|
|
||||||
if up:
|
if up:
|
||||||
logger.info("add XFRM interfaces %s and %s", ifname_in, ifname_out)
|
logger.info("add XFRM interfaces %s and %s", ifname_in, ifname_out)
|
||||||
subprocess.call(["/usr/local/libexec/ipsec/xfrmi", "-n", ifname_out,
|
subprocess.call(["ip", "link", "add", ifname_out, "type", "xfrm",
|
||||||
"-i", str(if_id_out), "-d", "eth0"])
|
"if_id", str(if_id_out), "dev", "eth0"])
|
||||||
subprocess.call(["/usr/local/libexec/ipsec/xfrmi", "-n", ifname_in,
|
subprocess.call(["ip", "link", "add", ifname_in, "type", "xfrm",
|
||||||
"-i", str(if_id_in), "-d", "eth0"])
|
"if_id", str(if_id_in), "dev", "eth0"])
|
||||||
subprocess.call(["ip", "link", "set", ifname_out, "up"])
|
subprocess.call(["ip", "link", "set", ifname_out, "up"])
|
||||||
subprocess.call(["ip", "link", "set", ifname_in, "up"])
|
subprocess.call(["ip", "link", "set", ifname_in, "up"])
|
||||||
subprocess.call(["iptables", "-A", "FORWARD", "-o", ifname_out,
|
subprocess.call(["iptables", "-A", "FORWARD", "-o", ifname_out,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
moon::iptables-restore < /etc/iptables.rules
|
moon::iptables-restore < /etc/iptables.rules
|
||||||
sun::iptables-restore < /etc/iptables.rules
|
sun::iptables-restore < /etc/iptables.rules
|
||||||
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon-out -d eth0 -i 1337
|
moon::ip link add xfrm-moon-out type xfrm dev eth0 if_id 1337
|
||||||
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon-in -d eth0 -i 42
|
moon::ip link add xfrm-moon-in type xfrm dev eth0 if_id 42
|
||||||
moon::ip link set xfrm-moon-out up
|
moon::ip link set xfrm-moon-out up
|
||||||
moon::ip link set xfrm-moon-in up
|
moon::ip link set xfrm-moon-in up
|
||||||
moon::ip route add 10.2.0.0/16 dev xfrm-moon-out
|
moon::ip route add 10.2.0.0/16 dev xfrm-moon-out
|
||||||
|
@ -4,7 +4,7 @@ IF_NAME="xfrmi-${PLUTO_IF_ID_IN}"
|
|||||||
|
|
||||||
case "${PLUTO_VERB}" in
|
case "${PLUTO_VERB}" in
|
||||||
up-client)
|
up-client)
|
||||||
/usr/local/libexec/ipsec/xfrmi -n "${IF_NAME}" -i "${PLUTO_IF_ID_IN}" -d eth0
|
ip link add "${IF_NAME}" type xfrm if_id "${PLUTO_IF_ID_IN}" dev eth0
|
||||||
ip link set "${IF_NAME}" up
|
ip link set "${IF_NAME}" up
|
||||||
ip route add 10.1.0.0/16 dev "${IF_NAME}"
|
ip route add 10.1.0.0/16 dev "${IF_NAME}"
|
||||||
iptables -A FORWARD -i "${IF_NAME}" -j ACCEPT
|
iptables -A FORWARD -i "${IF_NAME}" -j ACCEPT
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
moon::iptables-restore < /etc/iptables.rules
|
moon::iptables-restore < /etc/iptables.rules
|
||||||
sun::iptables-restore < /etc/iptables.rules
|
sun::iptables-restore < /etc/iptables.rules
|
||||||
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon -i 42 -d eth0
|
moon::ip link add xfrm-moon type xfrm if_id 42 dev eth0
|
||||||
moon::ip link set xfrm-moon up
|
moon::ip link set xfrm-moon up
|
||||||
moon::ip route add 10.2.0.0/16 dev xfrm-moon
|
moon::ip route add 10.2.0.0/16 dev xfrm-moon
|
||||||
moon::iptables -A FORWARD -i xfrm-moon -j ACCEPT
|
moon::iptables -A FORWARD -i xfrm-moon -j ACCEPT
|
||||||
|
@ -6,8 +6,8 @@ IF_NAME_OUT="${IF_NAME}${PLUTO_IF_ID_OUT}-out"
|
|||||||
|
|
||||||
case "${PLUTO_VERB}" in
|
case "${PLUTO_VERB}" in
|
||||||
up-client)
|
up-client)
|
||||||
/usr/local/libexec/ipsec/xfrmi -n "${IF_NAME_OUT}" -i "${PLUTO_IF_ID_OUT}" -d eth0
|
ip link add "${IF_NAME_OUT}" type xfrm if_id "${PLUTO_IF_ID_OUT}" dev eth0
|
||||||
/usr/local/libexec/ipsec/xfrmi -n "${IF_NAME_IN}" -i "${PLUTO_IF_ID_IN}" -d eth0
|
ip link add "${IF_NAME_IN}" type xfrm if_id "${PLUTO_IF_ID_IN}" dev eth0
|
||||||
ip link set "${IF_NAME_OUT}" up
|
ip link set "${IF_NAME_OUT}" up
|
||||||
ip link set "${IF_NAME_IN}" up
|
ip link set "${IF_NAME_IN}" up
|
||||||
ip route add 10.1.0.0/16 dev "${IF_NAME_OUT}"
|
ip route add 10.1.0.0/16 dev "${IF_NAME_OUT}"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
moon::iptables-restore < /etc/iptables.rules
|
moon::iptables-restore < /etc/iptables.rules
|
||||||
sun::iptables-restore < /etc/iptables.rules
|
sun::iptables-restore < /etc/iptables.rules
|
||||||
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon-out -d eth0 -i 1337
|
moon::ip link add xfrm-moon-out type xfrm dev eth0 if_id 1337
|
||||||
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon-in -d eth0 -i 42
|
moon::ip link add xfrm-moon-in type xfrm dev eth0 if_id 42
|
||||||
moon::ip link set xfrm-moon-out up
|
moon::ip link set xfrm-moon-out up
|
||||||
moon::ip link set xfrm-moon-in up
|
moon::ip link set xfrm-moon-in up
|
||||||
moon::ip route add 10.2.0.0/16 dev xfrm-moon-out
|
moon::ip route add 10.2.0.0/16 dev xfrm-moon-out
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
moon::iptables-restore < /etc/iptables.rules
|
moon::iptables-restore < /etc/iptables.rules
|
||||||
carol::iptables-restore < /etc/iptables.rules
|
carol::iptables-restore < /etc/iptables.rules
|
||||||
dave::iptables-restore < /etc/iptables.rules
|
dave::iptables-restore < /etc/iptables.rules
|
||||||
moon::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon -i 42 -d eth0
|
moon::ip link add xfrm-moon type xfrm if_id 42 dev eth0
|
||||||
moon::ip link set xfrm-moon up
|
moon::ip link set xfrm-moon up
|
||||||
moon::ip route add 10.3.0.0/28 dev xfrm-moon
|
moon::ip route add 10.3.0.0/28 dev xfrm-moon
|
||||||
moon::iptables -A FORWARD -i xfrm-moon -j ACCEPT
|
moon::iptables -A FORWARD -i xfrm-moon -j ACCEPT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user