diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2017-04-01 16:26:44 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2017-04-01 16:26:44 +0200 |
commit | 05ddd767992d68bb38c7f16ece142e8c2e9ae016 (patch) | |
tree | 302c618be306d4ed3c7f9fc58a1f6aaad4dd252f /src/libcharon/plugins/kernel_netlink | |
parent | 25663e04c3ab01ef8dc9f906608282319cfea2db (diff) | |
download | vyos-strongswan-05ddd767992d68bb38c7f16ece142e8c2e9ae016.tar.gz vyos-strongswan-05ddd767992d68bb38c7f16ece142e8c2e9ae016.zip |
New upstream version 5.5.2
Diffstat (limited to 'src/libcharon/plugins/kernel_netlink')
4 files changed, 347 insertions, 44 deletions
diff --git a/src/libcharon/plugins/kernel_netlink/Makefile.in b/src/libcharon/plugins/kernel_netlink/Makefile.in index b2df52a61..26a7090b3 100644 --- a/src/libcharon/plugins/kernel_netlink/Makefile.in +++ b/src/libcharon/plugins/kernel_netlink/Makefile.in @@ -399,7 +399,6 @@ exec_prefix = @exec_prefix@ fips_mode = @fips_mode@ gtk_CFLAGS = @gtk_CFLAGS@ gtk_LIBS = @gtk_LIBS@ -h_plugins = @h_plugins@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -434,6 +433,7 @@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ +p_plugins = @p_plugins@ pcsclite_CFLAGS = @pcsclite_CFLAGS@ pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c index f3846ec07..becf6b5dc 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2016 Tobias Brunner + * Copyright (C) 2006-2017 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2008-2016 Andreas Steffen * Copyright (C) 2006-2007 Fabian Hartmann, Noah Heusser @@ -76,7 +76,7 @@ #endif /** Base priority for installed policies */ -#define PRIO_BASE 100000 +#define PRIO_BASE 200000 /** Default lifetime of an acquire XFRM state (in seconds) */ #define DEFAULT_ACQUIRE_LIFETIME 165 @@ -117,7 +117,7 @@ struct kernel_algorithm_t { /** * Name of the algorithm in linux crypto API */ - char *name; + const char *name; }; ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, XFRM_MSG_MAPPING, @@ -221,6 +221,7 @@ static kernel_algorithm_t integrity_algs[] = { /* {AUTH_DES_MAC, "***" }, */ /* {AUTH_KPDK_MD5, "***" }, */ {AUTH_AES_XCBC_96, "xcbc(aes)" }, + {AUTH_AES_CMAC_96, "cmac(aes)" }, }; /** @@ -236,7 +237,7 @@ static kernel_algorithm_t compression_algs[] = { /** * Look up a kernel algorithm name and its key size */ -static char* lookup_algorithm(transform_type_t type, int ikev2) +static const char* lookup_algorithm(transform_type_t type, int ikev2) { kernel_algorithm_t *list; int i, count; @@ -652,14 +653,15 @@ static inline uint32_t port_mask_bits(uint16_t port_mask) /** * Calculate the priority of a policy * - * bits 0-0: restriction to network interface (0..1) 1 bit - * bits 1-6: src + dst port mask bits (2 * 0..16) 6 bits - * bits 7-7: restriction to protocol (0..1) 1 bit - * bits 8-16: src + dst network mask bits (2 * 0..128) 9 bits - * 17 bits + * bits 0-0: separate trap and regular policies (0..1) 1 bit + * bits 1-1: restriction to network interface (0..1) 1 bit + * bits 2-7: src + dst port mask bits (2 * 0..16) 6 bits + * bits 8-8: restriction to protocol (0..1) 1 bit + * bits 9-17: src + dst network mask bits (2 * 0..128) 9 bits + * 18 bits * - * smallest value: 000000000 0 000000 0: 0, lowest priority = 100'000 - * largest value : 100000000 1 100000 1: 65'729, highst priority = 34'271 + * smallest value: 000000000 0 000000 0 0: 0, lowest priority = 200'000 + * largest value : 100000000 1 100000 1 1: 131'459, highst priority = 68'541 */ static uint32_t get_priority(policy_entry_t *policy, policy_priority_t prio, char *interface) @@ -672,8 +674,6 @@ static uint32_t get_priority(policy_entry_t *policy, policy_priority_t prio, priority += PRIO_BASE; /* fall-through to next case */ case POLICY_PRIORITY_ROUTED: - priority += PRIO_BASE; - /* fall-through to next case */ case POLICY_PRIORITY_DEFAULT: priority += PRIO_BASE; /* fall-through to next case */ @@ -684,10 +684,11 @@ static uint32_t get_priority(policy_entry_t *policy, policy_priority_t prio, dport_mask_bits = port_mask_bits(policy->sel.dport_mask); /* calculate priority */ - priority -= (policy->sel.prefixlen_s + policy->sel.prefixlen_d) * 256; - priority -= policy->sel.proto ? 128 : 0; - priority -= (sport_mask_bits + dport_mask_bits) * 2; - priority -= (interface != NULL); + priority -= (policy->sel.prefixlen_s + policy->sel.prefixlen_d) * 512; + priority -= policy->sel.proto ? 256 : 0; + priority -= (sport_mask_bits + dport_mask_bits) * 4; + priority -= (interface != NULL) * 2; + priority -= (prio != POLICY_PRIORITY_ROUTED); return priority; } @@ -1210,8 +1211,15 @@ METHOD(kernel_ipsec_t, get_spi, status_t, private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, uint8_t protocol, uint32_t *spi) { - if (get_spi_internal(this, src, dst, protocol, - 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS) + uint32_t spi_min, spi_max; + + spi_min = lib->settings->get_int(lib->settings, "%s.spi_min", + KERNEL_SPI_MIN, lib->ns); + spi_max = lib->settings->get_int(lib->settings, "%s.spi_max", + KERNEL_SPI_MAX, lib->ns); + + if (get_spi_internal(this, src, dst, protocol, min(spi_min, spi_max), + max(spi_min, spi_max), spi) != SUCCESS) { DBG1(DBG_KNL, "unable to get SPI"); return FAILED; @@ -1276,7 +1284,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, kernel_ipsec_add_sa_t *data) { netlink_buf_t request; - char *alg_name, markstr[32] = ""; + const char *alg_name; + char markstr[32] = ""; struct nlmsghdr *hdr; struct xfrm_usersa_info *sa; uint16_t icv_size = 64, ipcomp = data->ipcomp; @@ -1367,6 +1376,11 @@ METHOD(kernel_ipsec_t, add_sa, status_t, default: break; } + if (id->proto == IPPROTO_AH && sa->family == AF_INET) + { /* use alignment to 4 bytes for IPv4 instead of the incorrect 8 byte + * alignment that's used by default but is only valid for IPv6 */ + sa->flags |= XFRM_STATE_ALIGN4; + } sa->reqid = data->reqid; sa->lft.soft_byte_limit = XFRM_LIMIT(data->lifetime->bytes.rekey); @@ -2523,7 +2537,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t, { /* we don't update the policy if the priority is lower than that of * the currently installed one */ policy_change_done(this, policy); - DBG2(DBG_KNL, "not updating policy %R === %R %N%s [priority %u," + DBG2(DBG_KNL, "not updating policy %R === %R %N%s [priority %u, " "refcount %d]", id->src_ts, id->dst_ts, policy_dir_names, id->dir, markstr, cur_priority, use_count); return SUCCESS; diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c index 0132f7269..2dc76d941 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c @@ -476,6 +476,11 @@ struct private_kernel_netlink_net_t { bool roam_events; /** + * whether to install IPsec policy routes + */ + bool install_routes; + + /** * whether to actually install virtual IPs */ bool install_virtual_ip; @@ -795,6 +800,68 @@ static u_char get_scope(host_t *ip) } /** + * Determine the label of the given unicast IP address. + * + * We currently only support the default table given in RFC 6724: + * + * Prefix Precedence Label + * ::1/128 50 0 + * ::/0 40 1 + * ::ffff:0:0/96 35 4 + * 2002::/16 30 2 + * 2001::/32 5 5 + * fc00::/7 3 13 + * ::/96 1 3 + * fec0::/10 1 11 + * 3ffe::/16 1 12 + */ +static u_char get_label(host_t *ip) +{ + struct { + chunk_t net; + u_char prefix; + u_char label; + } priorities[] = { + /* priority table ordered by prefix */ + /* ::1/128 */ + { chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01), 128, 0 }, + /* ::ffff:0:0/96 */ + { chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00), 96, 4 }, + /* ::/96 */ + { chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 96, 3 }, + /* 2001::/32 */ + { chunk_from_chars(0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 32, 5 }, + /* 2002::/16 */ + { chunk_from_chars(0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 16, 2 }, + /* 3ffe::/16 */ + { chunk_from_chars(0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 16, 12 }, + /* fec0::/10 */ + { chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 10, 11 }, + /* fc00::/7 */ + { chunk_from_chars(0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 7, 13 }, + }; + int i; + + for (i = 0; i < countof(priorities); i++) + { + if (host_in_subnet(ip, priorities[i].net, priorities[i].prefix)) + { + return priorities[i].label; + } + } + /* ::/0 */ + return 1; +} + +/** * Returns the length of the common prefix in bits up to the length of a's * prefix, defined by RFC 6724 as the portion of the address not including the * interface ID, which is 64-bit for most unicast addresses (see RFC 4291). @@ -829,7 +896,7 @@ static u_char common_prefix(host_t *a, host_t *b) static bool is_address_better(private_kernel_netlink_net_t *this, addr_entry_t *a, addr_entry_t *b, host_t *d) { - u_char sa, sb, sd, pa, pb; + u_char sa, sb, sd, la, lb, ld, pa, pb; /* rule 2: prefer appropriate scope */ if (d) @@ -858,9 +925,22 @@ static bool is_address_better(private_kernel_netlink_net_t *this, /* rule 4 is not applicable as we don't know if an address is a home or * care-of addresses. * rule 5 does not apply as we only compare addresses from one interface - * rule 6 requires a policy table (optionally configurable) to match - * configurable labels */ + /* rule 6: prefer matching label */ + if (d) + { + la = get_label(a->ip); + lb = get_label(b->ip); + ld = get_label(d); + if (la == ld && lb != ld) + { + return FALSE; + } + else if (lb == ld && la != ld) + { + return TRUE; + } + } /* rule 7: prefer temporary addresses (WE REVERSE THIS BY DEFAULT!) */ if ((a->flags & IFA_F_TEMPORARY) != (b->flags & IFA_F_TEMPORARY)) { @@ -1795,12 +1875,22 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, { /* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes. * as we want to ignore routes with virtual IPs we cannot use DUMP * if these routes are not installed in a separate table */ - hdr->nlmsg_flags |= NLM_F_DUMP; + if (this->install_routes) + { + hdr->nlmsg_flags |= NLM_F_DUMP; + } } if (candidate) { chunk = candidate->get_address(candidate); - netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request)); + if (hdr->nlmsg_flags & NLM_F_DUMP) + { + netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request)); + } + else + { + netlink_add_attribute(hdr, RTA_SRC, chunk, sizeof(request)); + } } /* we use this below to match against the routes */ chunk = dest->get_address(dest); @@ -2050,6 +2140,146 @@ METHOD(kernel_net_t, get_nexthop, host_t*, return get_route(this, dest, prefix, TRUE, src, iface, 0); } +/** enumerator over subnets */ +typedef struct { + enumerator_t public; + private_kernel_netlink_net_t *private; + /** message from the kernel */ + struct nlmsghdr *msg; + /** current message from the kernel */ + struct nlmsghdr *current; + /** remaining length */ + size_t len; + /** last subnet enumerated */ + host_t *net; + /** interface of current net */ + char ifname[IFNAMSIZ]; +} subnet_enumerator_t; + +METHOD(enumerator_t, destroy_subnet_enumerator, void, + subnet_enumerator_t *this) +{ + DESTROY_IF(this->net); + free(this->msg); + free(this); +} + +METHOD(enumerator_t, enumerate_subnets, bool, + subnet_enumerator_t *this, host_t **net, uint8_t *mask, char **ifname) +{ + if (!this->current) + { + this->current = this->msg; + } + else + { + this->current = NLMSG_NEXT(this->current, this->len); + DESTROY_IF(this->net); + this->net = NULL; + } + + while (NLMSG_OK(this->current, this->len)) + { + switch (this->current->nlmsg_type) + { + case NLMSG_DONE: + break; + case RTM_NEWROUTE: + { + struct rtmsg *msg; + struct rtattr *rta; + size_t rtasize; + chunk_t dst = chunk_empty; + uint32_t oif = 0; + + msg = NLMSG_DATA(this->current); + + if (!route_usable(this->current)) + { + break; + } + else if (msg->rtm_table && ( + msg->rtm_table == RT_TABLE_LOCAL || + msg->rtm_table == this->private->routing_table)) + { /* ignore our own and the local routing tables */ + break; + } + + rta = RTM_RTA(msg); + rtasize = RTM_PAYLOAD(this->current); + while (RTA_OK(rta, rtasize)) + { + switch (rta->rta_type) + { + case RTA_DST: + dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)); + break; + case RTA_OIF: + if (RTA_PAYLOAD(rta) == sizeof(oif)) + { + oif = *(uint32_t*)RTA_DATA(rta); + } + break; + } + rta = RTA_NEXT(rta, rtasize); + } + + if (dst.ptr && oif && if_indextoname(oif, this->ifname)) + { + this->net = host_create_from_chunk(msg->rtm_family, dst, 0); + *net = this->net; + *mask = msg->rtm_dst_len; + *ifname = this->ifname; + return TRUE; + } + break; + } + default: + break; + } + this->current = NLMSG_NEXT(this->current, this->len); + } + return FALSE; +} + +METHOD(kernel_net_t, create_local_subnet_enumerator, enumerator_t*, + private_kernel_netlink_net_t *this) +{ + netlink_buf_t request; + struct nlmsghdr *hdr, *out; + struct rtmsg *msg; + size_t len; + subnet_enumerator_t *enumerator; + + memset(&request, 0, sizeof(request)); + + hdr = &request.hdr; + hdr->nlmsg_flags = NLM_F_REQUEST; + hdr->nlmsg_type = RTM_GETROUTE; + hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + hdr->nlmsg_flags |= NLM_F_DUMP; + + msg = NLMSG_DATA(hdr); + msg->rtm_scope = RT_SCOPE_LINK; + + if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS) + { + DBG2(DBG_KNL, "enumerating local subnets failed"); + return enumerator_create_empty(); + } + + INIT(enumerator, + .public = { + .enumerate = (void*)_enumerate_subnets, + .destroy = _destroy_subnet_enumerator, + }, + .private = this, + .msg = out, + .len = len, + ); + return &enumerator->public; +} + /** * Manages the creation and deletion of ip addresses on an interface. * By setting the appropriate nlmsg_type, the ip will be set or unset. @@ -2080,16 +2310,22 @@ static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type netlink_add_attribute(hdr, IFA_LOCAL, chunk, sizeof(request)); - if (ip->get_family(ip) == AF_INET6 && this->rta_prefsrc_for_ipv6) - { /* if source routes are possible we let the virtual IP get deprecated - * immediately (but mark it as valid forever) so it gets only used if - * forced by our route, and not by the default IPv6 address selection */ - struct ifa_cacheinfo cache = { - .ifa_valid = 0xFFFFFFFF, - .ifa_prefered = 0, - }; - netlink_add_attribute(hdr, IFA_CACHEINFO, chunk_from_thing(cache), - sizeof(request)); + if (ip->get_family(ip) == AF_INET6) + { + msg->ifa_flags |= IFA_F_NODAD; + if (this->rta_prefsrc_for_ipv6) + { + /* if source routes are possible we let the virtual IP get + * deprecated immediately (but mark it as valid forever) so it gets + * only used if forced by our route, and not by the default IPv6 + * address selection */ + struct ifa_cacheinfo cache = { + .ifa_valid = 0xFFFFFFFF, + .ifa_prefered = 0, + }; + netlink_add_attribute(hdr, IFA_CACHEINFO, chunk_from_thing(cache), + sizeof(request)); + } } return this->socket->send_ack(this->socket, hdr); } @@ -2680,6 +2916,7 @@ kernel_netlink_net_t *kernel_netlink_net_create() .interface = { .get_interface = _get_interface_name, .create_address_enumerator = _create_address_enumerator, + .create_local_subnet_enumerator = _create_local_subnet_enumerator, .get_source_addr = _get_source_addr, .get_nexthop = _get_nexthop, .add_ip = _add_ip, @@ -2715,6 +2952,8 @@ kernel_netlink_net_t *kernel_netlink_net_create() "%s.routing_table_prio", ROUTING_TABLE_PRIO, lib->ns), .process_route = lib->settings->get_bool(lib->settings, "%s.process_route", TRUE, lib->ns), + .install_routes = lib->settings->get_bool(lib->settings, + "%s.install_routes", TRUE, lib->ns), .install_virtual_ip = lib->settings->get_bool(lib->settings, "%s.install_virtual_ip", TRUE, lib->ns), .install_virtual_ip_on = lib->settings->get_str(lib->settings, diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c index 7165b655b..da54031a1 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_shared.c @@ -15,6 +15,29 @@ * for more details. */ +/* + * Copyright (C) 2016 secunet Security Networks AG + * Copyright (C) 2016 Thomas Egerer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + #include <sys/socket.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> @@ -281,8 +304,9 @@ static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in, uintptr_t seq, struct nlmsghdr **out, size_t *out_len) { struct nlmsghdr *hdr; - chunk_t result = {}; entry_t *entry; + u_char *ptr; + int i; in->nlmsg_seq = seq; in->nlmsg_pid = getpid(); @@ -343,6 +367,14 @@ static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in, return OUT_OF_RES; } + for (i = 0, *out_len = 0; i < array_count(entry->hdrs); i++) + { + array_get(entry->hdrs, i, &hdr); + *out_len += hdr->nlmsg_len; + } + ptr = malloc(*out_len); + *out = (struct nlmsghdr*)ptr; + while (array_remove(entry->hdrs, ARRAY_HEAD, &hdr)) { if (this->names) @@ -350,14 +382,11 @@ static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in, DBG3(DBG_KNL, "received %N %u: %b", this->names, hdr->nlmsg_type, hdr->nlmsg_seq, hdr, hdr->nlmsg_len); } - result = chunk_cat("mm", result, - chunk_create((char*)hdr, hdr->nlmsg_len)); + memcpy(ptr, hdr, hdr->nlmsg_len); + ptr += hdr->nlmsg_len; + free(hdr); } destroy_entry(entry); - - *out_len = result.len; - *out = (struct nlmsghdr*)result.ptr; - return SUCCESS; } @@ -557,6 +586,8 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names, struct sockaddr_nl addr = { .nl_family = AF_NETLINK, }; + bool force_buf = FALSE; + int rcvbuf_size = 0; INIT(this, .public = { @@ -606,6 +637,25 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names, destroy(this); return NULL; } + rcvbuf_size = lib->settings->get_int(lib->settings, + "%s.plugins.kernel-netlink.receive_buffer_size", + rcvbuf_size, lib->ns); + if (rcvbuf_size) + { + int optname; + + force_buf = lib->settings->get_bool(lib->settings, + "%s.plugins.kernel-netlink.force_receive_buffer_size", + force_buf, lib->ns); + optname = force_buf ? SO_RCVBUFFORCE : SO_RCVBUF; + + if (setsockopt(this->socket, SOL_SOCKET, optname, &rcvbuf_size, + sizeof(rcvbuf_size)) == -1) + { + DBG1(DBG_KNL, "failed to %supdate receive buffer size to %d: %s", + force_buf ? "forcibly " : "", rcvbuf_size, strerror(errno)); + } + } if (this->parallel) { lib->watcher->add(lib->watcher, this->socket, WATCHER_READ, watch, this); |