kernel-netlink: Add manager for XFRM interfaces

The manager will allow charon-nm to create XFRM interfaces if supported
by the kernel instead of creating an unused dummy TUN interface.

The xfrmi tool is mostly obsolete nowadays as iproute2 supports creating
XFRM interfaces since 5.1.0 (2019-05).  Older Debians don't ship that and
early versions didn't list the interface IDs.  So there might still be
some uses for this tool.
This commit is contained in:
Tobias Brunner 2022-07-11 13:12:46 +02:00
parent 85d56b1c6a
commit e1ff1eefcf
12 changed files with 570 additions and 225 deletions

View File

@ -18,7 +18,8 @@ libstrongswan_kernel_netlink_la_SOURCES = \
kernel_netlink_plugin.h kernel_netlink_plugin.c \
kernel_netlink_ipsec.h kernel_netlink_ipsec.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)

View File

@ -63,6 +63,7 @@
#include "kernel_netlink_ipsec.h"
#include "kernel_netlink_shared.h"
#include "kernel_netlink_xfrmi.h"
#include <daemon.h>
#include <utils/debug.h>
@ -337,6 +338,11 @@ struct private_kernel_netlink_ipsec_t {
*/
netlink_socket_t *socket_xfrm;
/**
* XFRM interface manager
*/
kernel_netlink_xfrmi_t *xfrmi;
/**
* Netlink xfrm socket to receive acquire and expire events
*/
@ -3949,6 +3955,11 @@ METHOD(kernel_ipsec_t, destroy, void,
DESTROY_IF(this->socket_link_events);
DESTROY_IF(this->socket_xfrm_events);
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);
enumerator = this->policies->create_enumerator(this->policies);
while (enumerator->enumerate(enumerator, NULL, &policy))
@ -4188,5 +4199,11 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
return NULL;
}
}
this->xfrmi = kernel_netlink_xfrmi_create(TRUE);
if (this->xfrmi)
{
lib->set(lib, KERNEL_NETLINK_XFRMI_MANAGER, this->xfrmi);
}
return &this->public;
}

View File

@ -0,0 +1,413 @@
/*
* 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;
};
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 TRUE;
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;
}

View 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_ @}*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Tobias Brunner
* Copyright (C) 2019-2023 Tobias Brunner
*
* Copyright (C) secunet Security Networks AG
*
@ -19,222 +19,46 @@
#include <getopt.h>
#include <errno.h>
#include <net/if.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.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
#include "kernel_netlink_xfrmi.h"
/**
* 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)
{
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;
}
#define XFRMI_DEFAULT_MTU 1400
/**
* Parse attributes nested in IFLA_INFO_DATA
* Manager for XFRM interfaces
*/
static void parse_info_data(struct rtattr *rta, size_t rtasize, 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_indextoname(ifindex, phys);
}
break;
default:
break;
}
rta = RTA_NEXT(rta, rtasize);
}
}
static kernel_netlink_xfrmi_t *manager;
/**
* Parse attributes nested in IFLA_LINKINFO
* Destroy the allocated manager
*/
static void parse_linkinfo(struct rtattr *rta, size_t rtasize, char *phys,
uint32_t *if_id)
static void destroy_manager()
{
while (RTA_OK(rta, rtasize))
if (manager)
{
switch (rta->rta_type)
{
case IFLA_INFO_DATA:
parse_info_data(RTA_DATA(rta), RTA_PAYLOAD(rta), phys, if_id);
break;
default:
break;
}
rta = RTA_NEXT(rta, rtasize);
kernel_netlink_xfrmi_destroy(manager);
}
}
/**
* List all installed XFRM interfaces
*/
static int list_xfrm_interfaces()
static void list_xfrm_interfaces(kernel_netlink_xfrmi_t *manager)
{
netlink_buf_t request;
struct nlmsghdr *hdr, *out, *current;
struct ifinfomsg *msg;
struct rtattr *linkinfo;
netlink_socket_t *socket;
size_t len;
int status = 0;
enumerator_t *enumerator;
char *name, *dev;
uint32_t xfrm_id, mtu;
socket = netlink_socket_create(NETLINK_ROUTE, NULL, FALSE);
if (!socket)
enumerator = manager->create_enumerator(manager);
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);
}
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;
enumerator->destroy(enumerator);
}
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, " -n, --name=NAME name of the XFRM interface.\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");
}
int main(int argc, char *argv[])
{
char *name = NULL, *dev = NULL, *end;
uint32_t xfrm_id = 0;
u_int ifindex;
uint32_t xfrm_id = 0, mtu = XFRMI_DEFAULT_MTU;
library_init(NULL, "xfrmi");
atexit(library_deinit);
manager = kernel_netlink_xfrmi_create(FALSE);
atexit(destroy_manager);
while (true)
{
struct option long_opts[] = {
@ -269,9 +96,10 @@ int main(int argc, char *argv[])
{"name", required_argument, NULL, 'n' },
{"id", required_argument, NULL, 'i' },
{"dev", required_argument, NULL, 'd' },
{"mtu", required_argument, NULL, 'm' },
{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:
break;
@ -279,7 +107,7 @@ int main(int argc, char *argv[])
usage(stdout, argv[0]);
return 0;
case 'l':
list_xfrm_interfaces();
list_xfrm_interfaces(manager);
return 0;
case 'v':
dbg_default_set_level(atoi(optarg));
@ -300,24 +128,26 @@ int main(int argc, char *argv[])
case 'd':
dev = optarg;
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:
usage(stderr, argv[0]);
return 1;
}
break;
}
if (!name || !dev)
if (!name)
{
fprintf(stderr, "please specify a name and a physical interface\n");
fprintf(stderr, "please specify a name\n");
return 1;
}
ifindex = if_nametoindex(dev);
if (!ifindex)
{
fprintf(stderr, "physical interface %s not found\n", dev);
return 1;
}
return add_xfrm_interface(name, xfrm_id, ifindex);
return !manager->create(manager, name, xfrm_id, dev, mtu);
}

View File

@ -27,10 +27,10 @@ def handle_interfaces(ike_sa, up):
if up:
logger.info("add XFRM interfaces %s and %s", ifname_in, ifname_out)
subprocess.call(["/usr/local/libexec/ipsec/xfrmi", "-n", ifname_out,
"-i", str(if_id_out), "-d", "eth0"])
subprocess.call(["/usr/local/libexec/ipsec/xfrmi", "-n", ifname_in,
"-i", str(if_id_in), "-d", "eth0"])
subprocess.call(["ip", "link", "add", ifname_out, "type", "xfrm",
"if_id", str(if_id_out), "dev", "eth0"])
subprocess.call(["ip", "link", "add", ifname_in, "type", "xfrm",
"if_id", str(if_id_in), "dev", "eth0"])
subprocess.call(["ip", "link", "set", ifname_out, "up"])
subprocess.call(["ip", "link", "set", ifname_in, "up"])
subprocess.call(["iptables", "-A", "FORWARD", "-o", ifname_out,

View File

@ -1,7 +1,7 @@
moon::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::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon-in -d eth0 -i 42
moon::ip link add xfrm-moon-out type xfrm dev eth0 if_id 1337
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-in up
moon::ip route add 10.2.0.0/16 dev xfrm-moon-out

View File

@ -4,7 +4,7 @@ IF_NAME="xfrmi-${PLUTO_IF_ID_IN}"
case "${PLUTO_VERB}" in
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 route add 10.1.0.0/16 dev "${IF_NAME}"
iptables -A FORWARD -i "${IF_NAME}" -j ACCEPT

View File

@ -1,6 +1,6 @@
moon::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 route add 10.2.0.0/16 dev xfrm-moon
moon::iptables -A FORWARD -i xfrm-moon -j ACCEPT

View File

@ -6,8 +6,8 @@ IF_NAME_OUT="${IF_NAME}${PLUTO_IF_ID_OUT}-out"
case "${PLUTO_VERB}" in
up-client)
/usr/local/libexec/ipsec/xfrmi -n "${IF_NAME_OUT}" -i "${PLUTO_IF_ID_OUT}" -d eth0
/usr/local/libexec/ipsec/xfrmi -n "${IF_NAME_IN}" -i "${PLUTO_IF_ID_IN}" -d eth0
ip link add "${IF_NAME_OUT}" type xfrm if_id "${PLUTO_IF_ID_OUT}" dev 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_IN}" up
ip route add 10.1.0.0/16 dev "${IF_NAME_OUT}"

View File

@ -1,7 +1,7 @@
moon::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::/usr/local/libexec/ipsec/xfrmi -n xfrm-moon-in -d eth0 -i 42
moon::ip link add xfrm-moon-out type xfrm dev eth0 if_id 1337
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-in up
moon::ip route add 10.2.0.0/16 dev xfrm-moon-out

View File

@ -1,7 +1,7 @@
moon::iptables-restore < /etc/iptables.rules
carol::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 route add 10.3.0.0/28 dev xfrm-moon
moon::iptables -A FORWARD -i xfrm-moon -j ACCEPT