summaryrefslogtreecommitdiff
path: root/src/libhydra/plugins/kernel_netlink
diff options
context:
space:
mode:
Diffstat (limited to 'src/libhydra/plugins/kernel_netlink')
-rw-r--r--src/libhydra/plugins/kernel_netlink/Makefile.in8
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c86
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c90
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c79
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h10
5 files changed, 169 insertions, 104 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.in b/src/libhydra/plugins/kernel_netlink/Makefile.in
index 2a67bd595..a9b523eb8 100644
--- a/src/libhydra/plugins/kernel_netlink/Makefile.in
+++ b/src/libhydra/plugins/kernel_netlink/Makefile.in
@@ -236,6 +236,7 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
GPRBUILD = @GPRBUILD@
@@ -296,6 +297,7 @@ PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
RTLIB = @RTLIB@
RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
RUBYINCLUDE = @RUBYINCLUDE@
RUBYLIB = @RUBYLIB@
SED = @SED@
@@ -361,6 +363,8 @@ ipsecdir = @ipsecdir@
ipsecgroup = @ipsecgroup@
ipseclibdir = @ipseclibdir@
ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
linux_headers = @linux_headers@
@@ -408,6 +412,10 @@ strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
target_alias = @target_alias@
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index d9b55cfa7..dfd71f3bd 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -310,6 +310,12 @@ struct private_kernel_netlink_ipsec_t {
bool install_routes;
/**
+ * Whether to set protocol and ports on selector installed with transport
+ * mode IPsec SAs
+ */
+ bool proto_port_transport;
+
+ /**
* Whether to track the history of a policy
*/
bool policy_history;
@@ -810,7 +816,7 @@ static void process_acquire(private_kernel_netlink_ipsec_t *this,
u_int32_t reqid = 0;
int proto = 0;
- acquire = (struct xfrm_user_acquire*)NLMSG_DATA(hdr);
+ acquire = NLMSG_DATA(hdr);
rta = XFRM_RTA(hdr, struct xfrm_user_acquire);
rtasize = XFRM_PAYLOAD(hdr, struct xfrm_user_acquire);
@@ -856,7 +862,7 @@ static void process_expire(private_kernel_netlink_ipsec_t *this,
u_int32_t spi, reqid;
u_int8_t protocol;
- expire = (struct xfrm_user_expire*)NLMSG_DATA(hdr);
+ expire = NLMSG_DATA(hdr);
protocol = expire->state.id.proto;
spi = expire->state.id.spi;
reqid = expire->state.reqid;
@@ -890,7 +896,7 @@ static void process_migrate(private_kernel_netlink_ipsec_t *this,
u_int32_t reqid = 0;
policy_dir_t dir;
- policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
+ policy_id = NLMSG_DATA(hdr);
rta = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
rtasize = XFRM_PAYLOAD(hdr, struct xfrm_userpolicy_id);
@@ -957,7 +963,7 @@ static void process_mapping(private_kernel_netlink_ipsec_t *this,
struct xfrm_user_mapping *mapping;
u_int32_t spi, reqid;
- mapping = (struct xfrm_user_mapping*)NLMSG_DATA(hdr);
+ mapping = NLMSG_DATA(hdr);
spi = mapping->id.spi;
reqid = mapping->reqid;
@@ -1059,12 +1065,12 @@ static status_t get_spi_internal(private_kernel_netlink_ipsec_t *this,
memset(&request, 0, sizeof(request));
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_ALLOCSPI;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userspi_info));
- userspi = (struct xfrm_userspi_info*)NLMSG_DATA(hdr);
+ userspi = NLMSG_DATA(hdr);
host2xfrm(src, &userspi->info.saddr);
host2xfrm(dst, &userspi->info.id.daddr);
userspi->info.id.proto = proto;
@@ -1208,12 +1214,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u} (mark "
"%u/0x%08x)", ntohl(spi), reqid, mark.value, mark.mask);
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
- sa = (struct xfrm_usersa_info*)NLMSG_DATA(hdr);
+ sa = NLMSG_DATA(hdr);
host2xfrm(src, &sa->saddr);
host2xfrm(dst, &sa->id.daddr);
sa->id.spi = spi;
@@ -1235,12 +1241,15 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if (src_ts && dst_ts)
{
sa->sel = ts2selector(src_ts, dst_ts);
- /* don't install proto/port on SA. This would break
- * potential secondary SAs for the same address using a
- * different prot/port. */
- sa->sel.proto = 0;
- sa->sel.dport = sa->sel.dport_mask = 0;
- sa->sel.sport = sa->sel.sport_mask = 0;
+ if (!this->proto_port_transport)
+ {
+ /* don't install proto/port on SA. This would break
+ * potential secondary SAs for the same address using a
+ * different prot/port. */
+ sa->sel.proto = 0;
+ sa->sel.dport = sa->sel.dport_mask = 0;
+ sa->sel.sport = sa->sel.sport_mask = 0;
+ }
}
break;
default:
@@ -1512,7 +1521,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
status = SUCCESS;
failed:
- memwipe(request, sizeof(request));
+ memwipe(&request, sizeof(request));
return status;
}
@@ -1540,12 +1549,12 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
DBG2(DBG_KNL, "querying replay state from SAD entry with SPI %.8x",
ntohl(spi));
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETAE;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id));
- aevent_id = (struct xfrm_aevent_id*)NLMSG_DATA(hdr);
+ aevent_id = NLMSG_DATA(hdr);
aevent_id->flags = XFRM_AE_RVAL;
host2xfrm(dst, &aevent_id->sa_id.daddr);
@@ -1632,12 +1641,12 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
DBG2(DBG_KNL, "querying SAD entry with SPI %.8x (mark %u/0x%08x)",
ntohl(spi), mark.value, mark.mask);
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
- sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
+ sa_id = NLMSG_DATA(hdr);
host2xfrm(dst, &sa_id->daddr);
sa_id->spi = spi;
sa_id->proto = protocol;
@@ -1657,7 +1666,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
{
case XFRM_MSG_NEWSA:
{
- sa = (struct xfrm_usersa_info*)NLMSG_DATA(hdr);
+ sa = NLMSG_DATA(hdr);
break;
}
case NLMSG_ERROR:
@@ -1735,12 +1744,12 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x (mark %u/0x%08x)",
ntohl(spi), mark.value, mark.mask);
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_DELSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
- sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
+ sa_id = NLMSG_DATA(hdr);
host2xfrm(dst, &sa_id->daddr);
sa_id->spi = spi;
sa_id->proto = protocol;
@@ -1804,12 +1813,12 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
DBG2(DBG_KNL, "querying SAD entry with SPI %.8x for update", ntohl(spi));
/* query the existing SA first */
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
- sa_id = (struct xfrm_usersa_id*)NLMSG_DATA(hdr);
+ sa_id = NLMSG_DATA(hdr);
host2xfrm(dst, &sa_id->daddr);
sa_id->spi = spi;
sa_id->proto = protocol;
@@ -1867,7 +1876,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H",
ntohl(spi), src, dst, new_src, new_dst);
/* copy over the SA from out to request */
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_NEWSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
@@ -1958,7 +1967,7 @@ failed:
free(replay);
free(replay_esn);
memwipe(out, len);
- memwipe(request, sizeof(request));
+ memwipe(&request, sizeof(request));
free(out);
return status;
@@ -1975,12 +1984,12 @@ METHOD(kernel_ipsec_t, flush_sas, status_t,
DBG2(DBG_KNL, "flushing all SAD entries");
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_FLUSHSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush));
- flush = (struct xfrm_usersa_flush*)NLMSG_DATA(hdr);
+ flush = NLMSG_DATA(hdr);
flush->proto = IPSEC_PROTO_ANY;
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
@@ -2011,12 +2020,12 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
memcpy(&clone, policy, sizeof(policy_entry_t));
memset(&request, 0, sizeof(request));
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = update ? XFRM_MSG_UPDPOLICY : XFRM_MSG_NEWPOLICY;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_info));
- policy_info = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr);
+ policy_info = NLMSG_DATA(hdr);
policy_info->sel = policy->sel;
policy_info->dir = policy->direction;
@@ -2335,12 +2344,12 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
src_ts, dst_ts, policy_dir_names, direction,
mark.value, mark.mask);
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
- policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
+ policy_id = NLMSG_DATA(hdr);
policy_id->sel = ts2selector(src_ts, dst_ts);
policy_id->dir = direction;
@@ -2358,7 +2367,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
{
case XFRM_MSG_NEWPOLICY:
{
- policy = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr);
+ policy = NLMSG_DATA(hdr);
break;
}
case NLMSG_ERROR:
@@ -2492,12 +2501,12 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
memset(&request, 0, sizeof(request));
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_DELPOLICY;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
- policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
+ policy_id = NLMSG_DATA(hdr);
policy_id->sel = current->sel;
policy_id->dir = direction;
@@ -2551,7 +2560,7 @@ METHOD(kernel_ipsec_t, flush_policies, status_t,
DBG2(DBG_KNL, "flushing all policies from SPD");
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_FLUSHPOLICY;
hdr->nlmsg_len = NLMSG_LENGTH(0); /* no data associated */
@@ -2683,6 +2692,9 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
.policy_history = TRUE,
.install_routes = lib->settings->get_bool(lib->settings,
"%s.install_routes", TRUE, lib->ns),
+ .proto_port_transport = lib->settings->get_bool(lib->settings,
+ "%s.plugins.kernel-netlink.set_proto_port_transport_sa",
+ FALSE, lib->ns),
);
if (streq(lib->ns, "starter"))
@@ -2699,7 +2711,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
fclose(f);
}
- this->socket_xfrm = netlink_socket_create(NETLINK_XFRM);
+ this->socket_xfrm = netlink_socket_create(NETLINK_XFRM, xfrm_msg_names);
if (!this->socket_xfrm)
{
destroy(this);
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
index 82b637d1e..9d9f15974 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
@@ -78,6 +78,27 @@
#define ROUTING_TABLE_PRIO 0
#endif
+ENUM(rt_msg_names, RTM_NEWLINK, RTM_GETRULE,
+ "RTM_NEWLINK",
+ "RTM_DELLINK",
+ "RTM_GETLINK",
+ "RTM_SETLINK",
+ "RTM_NEWADDR",
+ "RTM_DELADDR",
+ "RTM_GETADDR",
+ "31",
+ "RTM_NEWROUTE",
+ "RTM_DELROUTE",
+ "RTM_GETROUTE",
+ "35",
+ "RTM_NEWNEIGH",
+ "RTM_DELNEIGH",
+ "RTM_GETNEIGH",
+ "RTM_NEWRULE",
+ "RTM_DELRULE",
+ "RTM_GETRULE",
+);
+
typedef struct addr_entry_t addr_entry_t;
/**
@@ -478,6 +499,16 @@ struct private_kernel_netlink_net_t {
* list with routing tables to be excluded from route lookup
*/
linked_list_t *rt_exclude;
+
+ /**
+ * MTU to set on installed routes
+ */
+ u_int32_t mtu;
+
+ /**
+ * MSS to set on installed routes
+ */
+ u_int32_t mss;
};
/**
@@ -928,7 +959,7 @@ static void addr_entry_unregister(addr_entry_t *addr, iface_entry_t *iface,
static void process_link(private_kernel_netlink_net_t *this,
struct nlmsghdr *hdr, bool event)
{
- struct ifinfomsg* msg = (struct ifinfomsg*)(NLMSG_DATA(hdr));
+ struct ifinfomsg* msg = NLMSG_DATA(hdr);
struct rtattr *rta = IFLA_RTA(msg);
size_t rtasize = IFLA_PAYLOAD (hdr);
enumerator_t *enumerator;
@@ -1030,7 +1061,7 @@ static void process_link(private_kernel_netlink_net_t *this,
static void process_addr(private_kernel_netlink_net_t *this,
struct nlmsghdr *hdr, bool event)
{
- struct ifaddrmsg* msg = (struct ifaddrmsg*)(NLMSG_DATA(hdr));
+ struct ifaddrmsg* msg = NLMSG_DATA(hdr);
struct rtattr *rta = IFA_RTA(msg);
size_t rtasize = IFA_PAYLOAD (hdr);
host_t *host = NULL;
@@ -1173,7 +1204,7 @@ static void process_addr(private_kernel_netlink_net_t *this,
*/
static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *hdr)
{
- struct rtmsg* msg = (struct rtmsg*)(NLMSG_DATA(hdr));
+ struct rtmsg* msg = NLMSG_DATA(hdr);
struct rtattr *rta = RTM_RTA(msg);
size_t rtasize = RTM_PAYLOAD(hdr);
u_int32_t rta_oif = 0;
@@ -1530,7 +1561,7 @@ static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *route)
struct rtmsg *msg;
size_t rtasize;
- msg = (struct rtmsg*)(NLMSG_DATA(hdr));
+ msg = NLMSG_DATA(hdr);
rta = RTM_RTA(msg);
rtasize = RTM_PAYLOAD(hdr);
@@ -1615,7 +1646,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
memset(&request, 0, sizeof(request));
family = dest->get_family(dest);
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST;
if (family == AF_INET || this->rta_prefsrc_for_ipv6 ||
this->routing_table || match_net)
@@ -1627,7 +1658,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
hdr->nlmsg_type = RTM_GETROUTE;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- msg = (struct rtmsg*)NLMSG_DATA(hdr);
+ msg = NLMSG_DATA(hdr);
msg->rtm_family = family;
if (candidate)
{
@@ -1854,12 +1885,12 @@ static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type
chunk = ip->get_address(ip);
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
hdr->nlmsg_type = nlmsg_type;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- msg = (struct ifaddrmsg*)NLMSG_DATA(hdr);
+ msg = NLMSG_DATA(hdr);
msg->ifa_family = ip->get_family(ip);
msg->ifa_flags = 0;
msg->ifa_prefixlen = prefix < 0 ? chunk.len * 8 : prefix;
@@ -2055,6 +2086,7 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this,
netlink_buf_t request;
struct nlmsghdr *hdr;
struct rtmsg *msg;
+ struct rtattr *rta;
int ifindex;
chunk_t chunk;
@@ -2081,12 +2113,12 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this,
memset(&request, 0, sizeof(request));
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
hdr->nlmsg_type = nlmsg_type;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- msg = (struct rtmsg*)NLMSG_DATA(hdr);
+ msg = NLMSG_DATA(hdr);
msg->rtm_family = src_ip->get_family(src_ip);
msg->rtm_dst_len = prefixlen;
msg->rtm_table = this->routing_table;
@@ -2107,6 +2139,30 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this,
chunk.len = sizeof(ifindex);
netlink_add_attribute(hdr, RTA_OIF, chunk, sizeof(request));
+ if (this->mtu || this->mss)
+ {
+ chunk = chunk_alloca(RTA_LENGTH((sizeof(struct rtattr) +
+ sizeof(u_int32_t)) * 2));
+ chunk.len = 0;
+ rta = (struct rtattr*)chunk.ptr;
+ if (this->mtu)
+ {
+ rta->rta_type = RTAX_MTU;
+ rta->rta_len = RTA_LENGTH(sizeof(u_int32_t));
+ memcpy(RTA_DATA(rta), &this->mtu, sizeof(u_int32_t));
+ chunk.len = rta->rta_len;
+ }
+ if (this->mss)
+ {
+ rta = (struct rtattr*)(chunk.ptr + RTA_ALIGN(chunk.len));
+ rta->rta_type = RTAX_ADVMSS;
+ rta->rta_len = RTA_LENGTH(sizeof(u_int32_t));
+ memcpy(RTA_DATA(rta), &this->mss, sizeof(u_int32_t));
+ chunk.len = RTA_ALIGN(chunk.len) + rta->rta_len;
+ }
+ netlink_add_attribute(hdr, RTA_METRICS, chunk, sizeof(request));
+ }
+
return this->socket->send_ack(this->socket, hdr);
}
@@ -2186,10 +2242,10 @@ static status_t init_address_list(private_kernel_netlink_net_t *this)
memset(&request, 0, sizeof(request));
- in = (struct nlmsghdr*)&request;
+ in = &request.hdr;
in->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
in->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT;
- msg = (struct rtgenmsg*)NLMSG_DATA(in);
+ msg = NLMSG_DATA(in);
msg->rtgen_family = AF_UNSPEC;
/* get all links */
@@ -2273,7 +2329,7 @@ static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
char *fwmark;
memset(&request, 0, sizeof(request));
- hdr = (struct nlmsghdr*)request;
+ hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = nlmsg_type;
if (nlmsg_type == RTM_NEWRULE)
@@ -2282,7 +2338,7 @@ static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
}
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- msg = (struct rtmsg*)NLMSG_DATA(hdr);
+ msg = NLMSG_DATA(hdr);
msg->rtm_table = table;
msg->rtm_family = family;
msg->rtm_protocol = RTPROT_BOOT;
@@ -2434,7 +2490,7 @@ kernel_netlink_net_t *kernel_netlink_net_create()
.destroy = _destroy,
},
},
- .socket = netlink_socket_create(NETLINK_ROUTE),
+ .socket = netlink_socket_create(NETLINK_ROUTE, rt_msg_names),
.rt_exclude = linked_list_create(),
.routes = hashtable_create((hashtable_hash_t)route_entry_hash,
(hashtable_equals_t)route_entry_equals, 16),
@@ -2466,6 +2522,10 @@ kernel_netlink_net_t *kernel_netlink_net_create()
"%s.prefer_temporary_addrs", FALSE, lib->ns),
.roam_events = lib->settings->get_bool(lib->settings,
"%s.plugins.kernel-netlink.roam_events", TRUE, lib->ns),
+ .mtu = lib->settings->get_int(lib->settings,
+ "%s.plugins.kernel-netlink.mtu", 0, lib->ns),
+ .mss = lib->settings->get_int(lib->settings,
+ "%s.plugins.kernel-netlink.mss", 0, lib->ns),
);
timerclear(&this->last_route_reinstall);
timerclear(&this->next_roam);
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
index fd00c23af..b4cece720 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -46,14 +46,14 @@ struct private_netlink_socket_t {
int seq;
/**
- * netlink socket protocol
+ * netlink socket
*/
- int protocol;
+ int socket;
/**
- * netlink socket
+ * Enum names for Netlink messages
*/
- int socket;
+ enum_name_t *names;
};
/**
@@ -65,10 +65,13 @@ METHOD(netlink_socket_t, netlink_send, status_t,
private_netlink_socket_t *this, struct nlmsghdr *in, struct nlmsghdr **out,
size_t *out_len)
{
- int len, addr_len;
+ union {
+ struct nlmsghdr hdr;
+ u_char bytes[4096];
+ } response;
struct sockaddr_nl addr;
- chunk_t result = chunk_empty, tmp;
- struct nlmsghdr *msg, peek;
+ chunk_t result = chunk_empty;
+ int len;
this->mutex->lock(this->mutex);
@@ -80,13 +83,11 @@ METHOD(netlink_socket_t, netlink_send, status_t,
addr.nl_pid = 0;
addr.nl_groups = 0;
- if (this->protocol == NETLINK_XFRM)
+ if (this->names)
{
- chunk_t in_chunk = { (u_char*)in, in->nlmsg_len };
-
- DBG3(DBG_KNL, "sending %N: %B", xfrm_msg_names, in->nlmsg_type, &in_chunk);
+ DBG3(DBG_KNL, "sending %N: %b",
+ this->names, in->nlmsg_type, in, in->nlmsg_len);
}
-
while (TRUE)
{
len = sendto(this->socket, in, in->nlmsg_len, 0,
@@ -108,20 +109,7 @@ METHOD(netlink_socket_t, netlink_send, status_t,
while (TRUE)
{
- char buf[4096];
- tmp.len = sizeof(buf);
- tmp.ptr = buf;
- msg = (struct nlmsghdr*)tmp.ptr;
-
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
- addr.nl_pid = getpid();
- addr.nl_groups = 0;
- addr_len = sizeof(addr);
-
- len = recvfrom(this->socket, tmp.ptr, tmp.len, 0,
- (struct sockaddr*)&addr, &addr_len);
-
+ len = recv(this->socket, &response, sizeof(response), 0);
if (len < 0)
{
if (errno == EINTR)
@@ -135,17 +123,17 @@ METHOD(netlink_socket_t, netlink_send, status_t,
free(result.ptr);
return FAILED;
}
- if (!NLMSG_OK(msg, len))
+ if (!NLMSG_OK(&response.hdr, len))
{
DBG1(DBG_KNL, "received corrupted netlink message");
this->mutex->unlock(this->mutex);
free(result.ptr);
return FAILED;
}
- if (msg->nlmsg_seq != this->seq)
+ if (response.hdr.nlmsg_seq != this->seq)
{
DBG1(DBG_KNL, "received invalid netlink sequence number");
- if (msg->nlmsg_seq < this->seq)
+ if (response.hdr.nlmsg_seq < this->seq)
{
continue;
}
@@ -154,17 +142,13 @@ METHOD(netlink_socket_t, netlink_send, status_t,
return FAILED;
}
- tmp.len = len;
- result.ptr = realloc(result.ptr, result.len + tmp.len);
- memcpy(result.ptr + result.len, tmp.ptr, tmp.len);
- result.len += tmp.len;
+ result = chunk_cat("mc", result, chunk_create(response.bytes, len));
/* NLM_F_MULTI flag does not seem to be set correctly, we use sequence
* numbers to detect multi header messages */
- len = recvfrom(this->socket, &peek, sizeof(peek), MSG_PEEK | MSG_DONTWAIT,
- (struct sockaddr*)&addr, &addr_len);
-
- if (len == sizeof(peek) && peek.nlmsg_seq == this->seq)
+ len = recv(this->socket, &response.hdr, sizeof(response.hdr),
+ MSG_PEEK | MSG_DONTWAIT);
+ if (len == sizeof(response.hdr) && response.hdr.nlmsg_seq == this->seq)
{
/* seems to be multipart */
continue;
@@ -197,7 +181,7 @@ METHOD(netlink_socket_t, netlink_send_ack, status_t,
{
case NLMSG_ERROR:
{
- struct nlmsgerr* err = (struct nlmsgerr*)NLMSG_DATA(hdr);
+ struct nlmsgerr* err = NLMSG_DATA(hdr);
if (err->error)
{
@@ -235,7 +219,7 @@ METHOD(netlink_socket_t, netlink_send_ack, status_t,
METHOD(netlink_socket_t, destroy, void,
private_netlink_socket_t *this)
{
- if (this->socket > 0)
+ if (this->socket != -1)
{
close(this->socket);
}
@@ -246,10 +230,12 @@ METHOD(netlink_socket_t, destroy, void,
/**
* Described in header.
*/
-netlink_socket_t *netlink_socket_create(int protocol)
+netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names)
{
private_netlink_socket_t *this;
- struct sockaddr_nl addr;
+ struct sockaddr_nl addr = {
+ .nl_family = AF_NETLINK,
+ };
INIT(this,
.public = {
@@ -259,21 +245,16 @@ netlink_socket_t *netlink_socket_create(int protocol)
},
.seq = 200,
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
- .protocol = protocol,
+ .socket = socket(AF_NETLINK, SOCK_RAW, protocol),
+ .names = names,
);
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
-
- this->socket = socket(AF_NETLINK, SOCK_RAW, protocol);
- if (this->socket < 0)
+ if (this->socket == -1)
{
DBG1(DBG_KNL, "unable to create netlink socket");
destroy(this);
return NULL;
}
-
- addr.nl_groups = 0;
if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)))
{
DBG1(DBG_KNL, "unable to bind netlink socket");
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h
index 8be935bc3..069f746d1 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h
@@ -26,7 +26,10 @@
* 1024 byte is currently sufficient for all operations. Some platform
* require an enforced aligment to four bytes (e.g. ARM).
*/
-typedef u_char netlink_buf_t[1024] __attribute__((aligned(RTA_ALIGNTO)));
+typedef union {
+ struct nlmsghdr hdr;
+ u_char bytes[1024];
+} netlink_buf_t __attribute__((aligned(RTA_ALIGNTO)));
typedef struct netlink_socket_t netlink_socket_t;
@@ -61,9 +64,10 @@ struct netlink_socket_t {
/**
* Create a netlink_socket_t object.
*
- * @param protocol protocol type (e.g. NETLINK_XFRM or NETLINK_ROUTE)
+ * @param protocol protocol type (e.g. NETLINK_XFRM or NETLINK_ROUTE)
+ * @param names optional enum names for Netlink messages
*/
-netlink_socket_t *netlink_socket_create(int protocol);
+netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names);
/**
* Creates an rtattr and adds it to the given netlink message.