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)
#include "kernel_netlink_ipsec.h"
#include "kernel_netlink_shared.h"
+#include "kernel_netlink_xfrmi.h"
#include <daemon.h>
#include <utils/debug.h>
*/
netlink_socket_t *socket_xfrm;
+ /**
+ * XFRM interface manager
+ */
+ kernel_netlink_xfrmi_t *xfrmi;
+
/**
* Netlink xfrm socket to receive acquire and expire events
*/
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))
return NULL;
}
}
+
+ this->xfrmi = kernel_netlink_xfrmi_create(TRUE);
+ if (this->xfrmi)
+ {
+ lib->set(lib, KERNEL_NETLINK_XFRMI_MANAGER, this->xfrmi);
+ }
return &this->public;
}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ @}*/
/*
- * Copyright (C) 2019 Tobias Brunner
+ * Copyright (C) 2019-2023 Tobias Brunner
*
* Copyright (C) secunet Security Networks AG
*
#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;
- }
-
- 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;
+ printf("%2u: %-16s dev %-12s if_id 0x%.8x [%10u] mtu %u\n",
+ if_nametoindex(name), name, dev ?: "-", xfrm_id, xfrm_id, mtu);
}
- free(out);
-
- socket->destroy(socket);
- return status;
+ enumerator->destroy(enumerator);
}
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[] = {
{"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;
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));
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);
}
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,
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
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
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
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}"
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
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