diff options
Diffstat (limited to 'src/libcharon/plugins/kernel_netlink')
5 files changed, 120 insertions, 34 deletions
diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.in b/src/libcharon/plugins/kernel_netlink/Makefile.in index 7ec64084b..b6b3af6d5 100644 --- a/src/libcharon/plugins/kernel_netlink/Makefile.in +++ b/src/libcharon/plugins/kernel_netlink/Makefile.in @@ -355,7 +355,6 @@ PYTHON_VERSION = @PYTHON_VERSION@ PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ -RUBY = @RUBY@ RUBYGEMDIR = @RUBYGEMDIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -381,6 +380,8 @@ am__tar = @am__tar@ am__untar = @am__untar@ attest_plugins = @attest_plugins@ bindir = @bindir@ +botan_CFLAGS = @botan_CFLAGS@ +botan_LIBS = @botan_LIBS@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ @@ -401,8 +402,6 @@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ fips_mode = @fips_mode@ fuzz_plugins = @fuzz_plugins@ -gtk_CFLAGS = @gtk_CFLAGS@ -gtk_LIBS = @gtk_LIBS@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -457,8 +456,6 @@ random_device = @random_device@ resolv_conf = @resolv_conf@ routing_table = @routing_table@ routing_table_prio = @routing_table_prio@ -ruby_CFLAGS = @ruby_CFLAGS@ -ruby_LIBS = @ruby_LIBS@ runstatedir = @runstatedir@ s_plugins = @s_plugins@ sbindir = @sbindir@ @@ -487,8 +484,12 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ tss2_CFLAGS = @tss2_CFLAGS@ tss2_LIBS = @tss2_LIBS@ +tss2_esys_CFLAGS = @tss2_esys_CFLAGS@ +tss2_esys_LIBS = @tss2_esys_LIBS@ tss2_socket_CFLAGS = @tss2_socket_CFLAGS@ tss2_socket_LIBS = @tss2_socket_LIBS@ +tss2_sys_CFLAGS = @tss2_sys_CFLAGS@ +tss2_sys_LIBS = @tss2_sys_LIBS@ tss2_tabrmd_CFLAGS = @tss2_tabrmd_CFLAGS@ tss2_tabrmd_LIBS = @tss2_tabrmd_LIBS@ urandom_device = @urandom_device@ diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c index 4926c3de8..1292e0895 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -1131,7 +1131,7 @@ static void process_mapping(private_kernel_netlink_ipsec_t *this, static bool receive_events(private_kernel_netlink_ipsec_t *this, int fd, watcher_event_t event) { - char response[1024]; + char response[netlink_get_buflen()]; struct nlmsghdr *hdr = (struct nlmsghdr*)response; struct sockaddr_nl addr; socklen_t addr_len = sizeof(addr); @@ -1336,6 +1336,23 @@ static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark) } /** + * Add a uint32 attribute to message + */ +static bool add_uint32(struct nlmsghdr *hdr, int buflen, + enum xfrm_attr_type_t type, uint32_t value) +{ + uint32_t *xvalue; + + xvalue = netlink_reserve(hdr, buflen, type, sizeof(*xvalue)); + if (!xvalue) + { + return FALSE; + } + *xvalue = value; + return TRUE; +} + +/** * Check if kernel supports HW offload */ static void netlink_find_offload_feature(const char *ifname, int query_socket) @@ -1586,6 +1603,49 @@ METHOD(kernel_ipsec_t, add_sa, status_t, sa->id.proto = id->proto; sa->family = id->src->get_family(id->src); sa->mode = mode2kernel(mode); + + if (!data->copy_df) + { + sa->flags |= XFRM_STATE_NOPMTUDISC; + } + + if (!data->copy_ecn) + { + sa->flags |= XFRM_STATE_NOECN; + } + + if (data->inbound) + { + switch (data->copy_dscp) + { + case DSCP_COPY_YES: + case DSCP_COPY_IN_ONLY: + sa->flags |= XFRM_STATE_DECAP_DSCP; + break; + default: + break; + } + } + else + { + switch (data->copy_dscp) + { + case DSCP_COPY_IN_ONLY: + case DSCP_COPY_NO: + { + /* currently the only extra flag */ + if (!add_uint32(hdr, sizeof(request), XFRMA_SA_EXTRA_FLAGS, + XFRM_SA_XFLAG_DONT_ENCAP_DSCP)) + { + goto failed; + } + break; + } + default: + break; + } + } + switch (mode) { case MODE_TUNNEL: @@ -1829,17 +1889,23 @@ METHOD(kernel_ipsec_t, add_sa, status_t, goto failed; } + if (ipcomp == IPCOMP_NONE && (data->mark.value | data->mark.mask)) + { + if (!add_uint32(hdr, sizeof(request), XFRMA_SET_MARK, + data->mark.value) || + !add_uint32(hdr, sizeof(request), XFRMA_SET_MARK_MASK, + data->mark.mask)) + { + goto failed; + } + } + if (data->tfc && id->proto == IPPROTO_ESP && mode == MODE_TUNNEL) { /* the kernel supports TFC padding only for tunnel mode ESP SAs */ - uint32_t *tfcpad; - - tfcpad = netlink_reserve(hdr, sizeof(request), XFRMA_TFCPAD, - sizeof(*tfcpad)); - if (!tfcpad) + if (!add_uint32(hdr, sizeof(request), XFRMA_TFCPAD, data->tfc)) { goto failed; } - *tfcpad = data->tfc; } if (id->proto != IPPROTO_COMP) diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c index b6eb54370..760a875ca 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c @@ -1504,7 +1504,7 @@ static void process_rule(private_kernel_netlink_net_t *this, struct nlmsghdr *hd static bool receive_events(private_kernel_netlink_net_t *this, int fd, watcher_event_t event) { - char response[1536]; + char response[netlink_get_buflen()]; struct nlmsghdr *hdr = (struct nlmsghdr*)response; struct sockaddr_nl addr; socklen_t addr_len = sizeof(addr); @@ -2586,11 +2586,11 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this, memset(half_net.ptr, 0, half_net.len); half_prefixlen = 1; - status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen, - gateway, src_ip, if_name); + status = manage_srcroute(this, nlmsg_type, flags, half_net, + half_prefixlen, gateway, src_ip, if_name); half_net.ptr[0] |= 0x80; - status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen, - gateway, src_ip, if_name); + status |= manage_srcroute(this, nlmsg_type, flags, half_net, + half_prefixlen, gateway, src_ip, if_name); return status; } @@ -2925,7 +2925,7 @@ static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type, msg->rtm_flags |= FIB_RULE_INVERT; fwmark++; } - if (mark_from_string(fwmark, &mark)) + if (mark_from_string(fwmark, MARK_OP_NONE, &mark)) { chunk = chunk_from_thing(mark.value); netlink_add_attribute(hdr, FRA_FWMARK, chunk, sizeof(request)); diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c index 441c0c482..84d78eca2 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c @@ -381,7 +381,7 @@ static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in, for (i = 0, *out_len = 0; i < array_count(entry->hdrs); i++) { array_get(entry->hdrs, i, &hdr); - *out_len += hdr->nlmsg_len; + *out_len += NLMSG_ALIGN(hdr->nlmsg_len); } ptr = malloc(*out_len); *out = (struct nlmsghdr*)ptr; @@ -394,7 +394,7 @@ static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in, hdr->nlmsg_seq, hdr, hdr->nlmsg_len); } memcpy(ptr, hdr, hdr->nlmsg_len); - ptr += hdr->nlmsg_len; + ptr += NLMSG_ALIGN(hdr->nlmsg_len); free(hdr); } destroy_entry(entry); @@ -587,8 +587,31 @@ METHOD(netlink_socket_t, destroy, void, free(this); } -/** - * Described in header. +/* + * Described in header + */ +u_int netlink_get_buflen() +{ + u_int buflen; + + buflen = lib->settings->get_int(lib->settings, + "%s.plugins.kernel-netlink.buflen", 0, lib->ns); + if (!buflen) + { + long pagesize = sysconf(_SC_PAGESIZE); + + if (pagesize == -1) + { + pagesize = 4096; + } + /* base this on NLMSG_GOODSIZE */ + buflen = min(pagesize, 8192); + } + return buflen; +} + +/* + * Described in header */ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names, bool parallel) @@ -612,8 +635,7 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names, .entries = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4), .protocol = protocol, .names = names, - .buflen = lib->settings->get_int(lib->settings, - "%s.plugins.kernel-netlink.buflen", 0, lib->ns), + .buflen = netlink_get_buflen(), .timeout = lib->settings->get_int(lib->settings, "%s.plugins.kernel-netlink.timeout", 0, lib->ns), .retries = lib->settings->get_int(lib->settings, @@ -624,16 +646,6 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names, .parallel = parallel, ); - if (!this->buflen) - { - long pagesize = sysconf(_SC_PAGESIZE); - if (pagesize == -1) - { - pagesize = 4096; - } - /* base this on NLMSG_GOODSIZE */ - this->buflen = min(pagesize, 8192); - } if (this->socket == -1) { DBG1(DBG_KNL, "unable to create netlink socket: %s (%d)", diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h index 7056e6ccc..82dce4c5c 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.h @@ -101,4 +101,11 @@ void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, */ void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len); +/** + * Determine buffer size for received messages (e.g. events). + * + * @return buffer size + */ +u_int netlink_get_buflen(); + #endif /* KERNEL_NETLINK_SHARED_H_ */ |