Bug Summary

File:programs/pluto/kernel_xfrm.c
Warning:line 1617, column 3
Value stored to 'attr' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name kernel_xfrm.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -resource-dir /usr/lib64/clang/13.0.0 -D TimeZoneOffset=timezone -D PIE -D NSS_IPSEC_PROFILE -D XFRM_LIFETIME_DEFAULT=30 -D USE_IKEv1 -D XFRM_SUPPORT -D USE_XFRM_INTERFACE -D USE_DNSSEC -D DEFAULT_DNSSEC_ROOTKEY_FILE="/var/lib/unbound/root.key" -D HAVE_LABELED_IPSEC -D HAVE_SECCOMP -D LIBCURL -D USE_LINUX_AUDIT -D HAVE_NM -D USE_PAM_AUTH -D USE_3DES -D USE_AES -D USE_CAMELLIA -D USE_CHACHA -D USE_DH31 -D USE_MD5 -D USE_SHA1 -D USE_SHA2 -D USE_PRF_AES_XCBC -D USE_NSS_KDF -D DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/var/lib/ipsec/nss" -D IPSEC_CONFDIR="/etc" -D IPSEC_EXECDIR="/usr/local/libexec/ipsec" -D IPSEC_SBINDIR="/usr/local/sbin" -D IPSEC_VARDIR="/var" -D POLICYGROUPSDIR="/etc/ipsec.d/policies" -D IPSEC_SECRETS_FILE="/etc/ipsec.secrets" -D FORCE_PR_ASSERT -D USE_FORK=1 -D USE_VFORK=0 -D USE_DAEMON=0 -D USE_PTHREAD_SETSCHEDPRIO=1 -D GCC_LINT -D HAVE_LIBCAP_NG -I . -I ../../OBJ.linux.x86_64/programs/pluto -I ../../include -I /usr/include/nss3 -I /usr/include/nspr4 -I /home/build/quick-libreswan-2/programs/pluto/linux-copy -D HERE_FILENAME="programs/pluto/kernel_xfrm.c" -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu99 -fdebug-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -ferror-limit 19 -stack-protector 3 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-01-01-205714-1273399-1 -x c /home/build/quick-libreswan-2/programs/pluto/kernel_xfrm.c
1/*
2 * netlink interface to the kernel's IPsec mechanism
3 *
4 * Copyright (C) 2003-2008 Herbert Xu
5 * Copyright (C) 2006-2008 Michael Richardson <mcr@xelerance.com>
6 * Copyright (C) 2006 Ken Bantoft <ken@xelerance.com>
7 * Copyright (C) 2007 Bart Trojanowski <bart@jukie.net>
8 * Copyright (C) 2007 Ilia Sotnikov
9 * Copyright (C) 2009 Carsten Schlote <c.schlote@konzeptpark.de>
10 * Copyright (C) 2008 Andreas Steffen
11 * Copyright (C) 2008 Neil Horman <nhorman@redhat.com>
12 * Copyright (C) 2008-2010 David McCullough <david_mccullough@securecomputing.com>
13 * Copyright (C) 2006-2010 Paul Wouters <paul@xelerance.com>
14 * Copyright (C) 2010-2017 Tuomo Soini <tis@foobar.fi>
15 * Copyright (C) 2010 Mika Ilmaranta <ilmis@foobar.fi>
16 * Copyright (C) 2010 Roman Hoog Antink <rha@open.ch>
17 * Copyright (C) 2010 D. Hugh Redelmeier
18 * Copyright (C) 2012 Avesh Agarwal <avagarwa@redhat.com>
19 * Copyright (C) 2013 Kim B. Heino <b@bbbs.net>
20 * Copyright (C) 2012-2013 Paul Wouters <paul@libreswan.org>
21 * Copyright (C) 2013-2019 D. Hugh Redelmeier <hugh@mimosa.com>
22 * Copyright (C) 2017 Richard Guy Briggs <rgb@tricolour.ca>
23 * Copyright (C) 2016-2019 Andrew Cagney <cagney@gnu.org>
24 * Copyright (C) 2019 Paul Wouters <pwouters@redhat.com>
25 * Copyright (C) 2019 Antony Antony <antony@phenome.org>
26 * Copyright (C) 2017 Mayank Totale <mtotale@gmail.com>
27 *
28 * This program is free software; you can redistribute it and/or modify it
29 * under the terms of the GNU General Public License as published by the
30 * Free Software Foundation; either version 2 of the License, or (at your
31 * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
32 *
33 * This program is distributed in the hope that it will be useful, but
34 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
35 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36 * for more details.
37 */
38
39#include <errno(*__errno_location ()).h>
40#include <fcntl.h>
41#include <string.h>
42
43#include <sys/socket.h>
44
45#include <sys/types.h>
46#include <sys/ioctl.h>
47#include <stdint.h>
48#include <linux1/ethtool.h>
49#include <linux1/sockios.h>
50
51#include <linux1/udp.h> /* for TCP_ENCAP_ESPINTCP and UDP_ENCAP_ESPINUDP */
52#ifndef TCP_ENCAP_ESPINTCP7
53#define TCP_ENCAP_ESPINTCP7 7
54#endif
55
56#include <unistd.h>
57#include <sys/stat.h>
58
59#include <linux1/rtnetlink.h>
60#include <linux1/if_addr.h>
61#include <linux1/if_link.h>
62
63/* work around weird combo's of glibc and kernel header conflicts */
64#ifndef GLIBC_KERN_FLIP_HEADERS
65# include "linux/xfrm.h" /* local (if configured) or system copy */
66# include "libreswan.h"
67#else
68# include "libreswan.h"
69# include "linux/xfrm.h" /* local (if configured) or system copy */
70#endif
71
72#include "sysdep.h"
73#include "socketwrapper.h"
74#include "constants.h"
75#include "defs.h"
76#include "id.h"
77#include "state.h"
78#include "connections.h"
79#include "kernel.h"
80#include "kernel_ops.h"
81#include "server.h"
82#include "nat_traversal.h"
83#include "state.h"
84#include "kernel_xfrm.h"
85#include "netlink_attrib.h"
86#include "log.h"
87#include "whack.h" /* for RC_LOG_SERIOUS */
88#include "kernel_alg.h"
89#include "ike_alg.h"
90#include "ike_alg_integ.h"
91#include "ike_alg_encrypt.h"
92#include "ip_address.h"
93#include "ip_info.h"
94# include "kernel_xfrm_interface.h"
95#include "iface.h"
96#include "ip_selector.h"
97#include "ip_encap.h"
98#include "initiate.h" /* for initiate_ondemand() */
99#include "labeled_ipsec.h" /* for vet_seclabel() */
100#include "ikev2_mobike.h"
101
102/* required for Linux 2.6.26 kernel and later */
103#ifndef XFRM_STATE_AF_UNSPEC32
104#define XFRM_STATE_AF_UNSPEC32 32
105#endif
106
107static int nl_send_fd = NULL_FD(-1); /* to send to NETLINK_XFRM */
108static int nl_xfrm_fd = NULL_FD(-1); /* listen to NETLINK_XFRM broadcast */
109static int nl_route_fd = NULL_FD(-1); /* listen to NETLINK_ROUTE broadcast */
110
111static int kernel_mobike_supprt ; /* kernel xfrm_migrate_support */
112
113#define NE(x) { x, #x } /* Name Entry -- shorthand for sparse_names */
114
115static sparse_names xfrm_type_names = {
116 NE(NLMSG_NOOP0x1),
117 NE(NLMSG_ERROR0x2),
118 NE(NLMSG_DONE0x3),
119 NE(NLMSG_OVERRUN0x4),
120
121 NE(XFRM_MSG_NEWSAXFRM_MSG_NEWSA),
122 NE(XFRM_MSG_DELSAXFRM_MSG_DELSA),
123 NE(XFRM_MSG_GETSAXFRM_MSG_GETSA),
124
125 NE(XFRM_MSG_NEWPOLICYXFRM_MSG_NEWPOLICY),
126 NE(XFRM_MSG_DELPOLICYXFRM_MSG_DELPOLICY),
127 NE(XFRM_MSG_GETPOLICYXFRM_MSG_GETPOLICY),
128
129 NE(XFRM_MSG_ALLOCSPIXFRM_MSG_ALLOCSPI),
130 NE(XFRM_MSG_ACQUIREXFRM_MSG_ACQUIRE),
131 NE(XFRM_MSG_EXPIREXFRM_MSG_EXPIRE),
132
133 NE(XFRM_MSG_UPDPOLICYXFRM_MSG_UPDPOLICY),
134 NE(XFRM_MSG_UPDSAXFRM_MSG_UPDSA),
135
136 NE(XFRM_MSG_POLEXPIREXFRM_MSG_POLEXPIRE),
137
138 NE(XFRM_MSG_MAX(__XFRM_MSG_MAX - 1)),
139
140 { 0, sparse_end }
141};
142
143static sparse_names rtm_type_names = {
144 NE(RTM_BASERTM_BASE),
145 NE(RTM_NEWADDRRTM_NEWADDR),
146 NE(RTM_DELADDRRTM_DELADDR),
147 NE(RTM_MAX(((__RTM_MAX + 3) & ~3) - 1)),
148 { 0, sparse_end }
149};
150#undef NE
151
152#define RTA_TAIL(rta)((struct rtattr *) (((void *) (rta)) + ( (((rta)->rta_len)
+4U -1) & ~(4U -1) )))
((struct rtattr *) (((void *) (rta)) + \
153 RTA_ALIGN((rta)->rta_len)( (((rta)->rta_len)+4U -1) & ~(4U -1) )))
154
155#define NLMSG_TAIL(nmsg)((struct rtattr *) (((void *) (nmsg)) + ( (((nmsg)->nlmsg_len
)+4U -1) & ~(4U -1) )))
\
156 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)( (((nmsg)->nlmsg_len)+4U -1) & ~(4U -1) )))
157
158/*
159 * xfrm2ip - Take an xfrm and convert to an IP address
160 *
161 * @param xaddr xfrm_address_t
162 * @param addr ip_address IPv[46] Address from addr is copied here.
163 */
164static void xfrm2ip(const xfrm_address_t *xaddr, ip_address *addr, const sa_family_t family)
165{
166 shunk_t x = THING_AS_SHUNK(*xaddr)shunk2(&(*xaddr), sizeof(*xaddr));
167
168 const struct ip_info *afi = aftoinfo(family);
169 passert(afi != NULL)({ _Bool assertion__ = afi != ((void*)0); if (!assertion__) {
where_t here = ({ static const struct where here = { .func =
__func__, .file = "programs/pluto/kernel_xfrm.c", .line = 169
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "afi != ((void*)0)"); } (
void) 1; })
;
170
171 *addr = afi->address.any; /* initialize dst type and zero */
172 chunk_t a = address_as_chunk(addr);
173
174 /* a = x */
175 passert(x.len >= a.len)({ _Bool assertion__ = x.len >= a.len; if (!assertion__) {
where_t here = ({ static const struct where here = { .func =
__func__, .file = "programs/pluto/kernel_xfrm.c", .line = 175
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "x.len >= a.len"); } (
void) 1; })
;
176 memcpy(a.ptr, x.ptr, a.len);
177}
178
179/*
180 * xfrm_from-address - Take an IP address and convert to an xfrm.
181 */
182static xfrm_address_t xfrm_from_address(const ip_address *addr)
183{
184 xfrm_address_t xaddr;
185 zero(&xaddr)memset((&xaddr), '\0', sizeof(*(&xaddr)));
186
187 shunk_t a = address_as_shunk(addr);
188 /* .len == ipv6 len */
189 chunk_t x = THING_AS_CHUNK(xaddr)chunk2(&(xaddr), sizeof(xaddr));
190 /* x = a */
191 passert(x.len >= a.len)({ _Bool assertion__ = x.len >= a.len; if (!assertion__) {
where_t here = ({ static const struct where here = { .func =
__func__, .file = "programs/pluto/kernel_xfrm.c", .line = 191
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "x.len >= a.len"); } (
void) 1; })
;
192 memcpy(x.ptr, a.ptr, a.len);
193 return xaddr;
194}
195
196#define SELECTOR_TO_XFRM(CLIENT, REQ, L){ ip_selector client_ = *(CLIENT); ip_address address = selector_prefix
(client_); (REQ).Laddr = xfrm_from_address(&address); (REQ
).prefixlen_L = selector_prefix_bits(client_); (REQ).Lport = nport
(selector_port(client_)); }
\
197 { \
198 ip_selector client_ = *(CLIENT); \
199 ip_address address = selector_prefix(client_); \
200 (REQ).L##addr = xfrm_from_address(&address); \
201 (REQ).prefixlen_##L = selector_prefix_bits(client_); \
202 (REQ).L##port = nport(selector_port(client_)); \
203 }
204
205static void init_netlink_route_fd(struct logger *logger)
206{
207 nl_route_fd = safe_socket(AF_NETLINK16, SOCK_RAWSOCK_RAW, NETLINK_ROUTE0);
208 if (nl_route_fd < 0) {
209 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()), "socket()");
210 }
211
212 if (fcntl(nl_route_fd, F_SETFD2, FD_CLOEXEC1) != 0) {
213 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
214 "fcntl(FD_CLOEXEC) for bcast NETLINK_ROUTE ");
215 }
216
217 if (fcntl(nl_route_fd, F_SETFL4, O_NONBLOCK04000) != 0) {
218 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
219 "fcntl(O_NONBLOCK) for bcast NETLINK_ROUTE");
220 }
221
222 struct sockaddr_nl addr = {
223 .nl_family = AF_NETLINK16,
224 .nl_pid = getpid(),
225 .nl_groups = RTMGRP_IPV4_IFADDR0x10 | RTMGRP_IPV6_IFADDR0x100 |
226 RTMGRP_IPV4_ROUTE0x40 | RTMGRP_IPV6_ROUTE0x400 | RTMGRP_LINK1,
227 };
228
229 if (bind(nl_route_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
230 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
231 "failed to bind NETLINK_ROUTE bcast socket - Perhaps kernel was not compiled with CONFIG_XFRM");
232 }
233}
234
235
236/*
237 * init_netlink - Initialize the netlink interface. Opens the sockets and
238 * then binds to the broadcast socket.
239 */
240static void init_netlink(struct logger *logger)
241{
242#define XFRM_ACQ_EXPIRES"/proc/sys/net/core/xfrm_acq_expires" "/proc/sys/net/core/xfrm_acq_expires"
243 struct stat buf;
244 if (stat(XFRM_ACQ_EXPIRES"/proc/sys/net/core/xfrm_acq_expires", &buf) != 0) {
245 fatal_errno(PLUTO_EXIT_KERNEL_FAIL, logger, errno(*__errno_location ()),
246 "no XFRM kernel support detected, missing "XFRM_ACQ_EXPIRES"/proc/sys/net/core/xfrm_acq_expires");
247 }
248
249 struct sockaddr_nl addr;
250
251 nl_send_fd = safe_socket(AF_NETLINK16, SOCK_DGRAMSOCK_DGRAM, NETLINK_XFRM6);
252
253 if (nl_send_fd < 0) {
254 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
255 "socket() in init_netlink()");
256 }
257
258 if (fcntl(nl_send_fd, F_SETFD2, FD_CLOEXEC1) != 0) {
259 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
260 "fcntl(FD_CLOEXEC) in init_netlink()");
261 }
262
263 nl_xfrm_fd = safe_socket(AF_NETLINK16, SOCK_DGRAMSOCK_DGRAM, NETLINK_XFRM6);
264 if (nl_xfrm_fd < 0) {
265 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
266 "socket() for bcast in init_netlink()");
267 }
268
269 if (fcntl(nl_xfrm_fd, F_SETFD2, FD_CLOEXEC1) != 0) {
270 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
271 "fcntl(FD_CLOEXEC) for bcast in init_netlink()");
272 }
273
274 if (fcntl(nl_xfrm_fd, F_SETFL4, O_NONBLOCK04000) != 0) {
275 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
276 "fcntl(O_NONBLOCK) for bcast in init_netlink()");
277 }
278
279 addr.nl_family = AF_NETLINK16;
280 addr.nl_pid = getpid();
281 addr.nl_pad = 0; /* make coverity happy */
282 addr.nl_groups = XFRMGRP_ACQUIRE1 | XFRMGRP_EXPIRE2;
283 if (bind(nl_xfrm_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
284 fatal_errno(PLUTO_EXIT_FAIL, logger, errno(*__errno_location ()),
285 "Failed to bind bcast socket in init_netlink() - Perhaps kernel was not compiled with CONFIG_XFRM");
286 }
287
288 init_netlink_route_fd(logger);
289
290 /*
291 * pfkey_register_response() does not register an entry for
292 * msg->sadb_msg_satype=10 to indicate IPCOMP, so we override
293 * detection here. Seems the PF_KEY API in Linux with netkey
294 * is a joke that should be abandoned for a "linux children"
295 * native netlink query/response
296 *
297 * XXX: Given KLIPS defines K_SADB_X_SATYPE_COMP=9, and
298 * IPIP=10 which conflicts with the aboe, that might be the
299 * source of the problem?
300 */
301 can_do_IPcomp = true1;
302
303 /*
304 * Just assume any algorithm with a NETLINK_XFRM name works.
305 *
306 * Kind of lame since pluto should query the kernel for what
307 * it supports. OTOH, the query might happen before the
308 * crypto module gets loaded.
309 */
310 dbg("Hard-wiring algorithms"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("Hard-wiring algorithms"); } }
;
311 for (const struct encrypt_desc **algp = next_encrypt_desc(NULL((void*)0));
312 algp != NULL((void*)0); algp = next_encrypt_desc(algp)) {
313 const struct encrypt_desc *alg = *algp;
314 if (alg->encrypt_netlink_xfrm_name != NULL((void*)0)) {
315 kernel_encrypt_add(alg);
316 }
317 }
318 for (const struct integ_desc **algp = next_integ_desc(NULL((void*)0));
319 algp != NULL((void*)0); algp = next_integ_desc(algp)) {
320 const struct integ_desc *alg = *algp;
321 if (alg->integ_netlink_xfrm_name != NULL((void*)0)) {
322 kernel_integ_add(alg);
323 }
324 }
325}
326
327/*
328 * send_netlink_msg
329 *
330 * @param hdr - Data to be sent.
331 * @param expected_resp_type - type of message expected from netlink
332 * @param rbuf - Return Buffer - contains data returned from the send.
333 * @param description - String - user friendly description of what is
334 * being attempted. Used for diagnostics
335 * @param story - String
336 * @return bool True if the message was successfully sent.
337 */
338
339static bool_Bool send_netlink_msg(struct nlmsghdr *hdr,
340 unsigned expected_resp_type, struct nlm_resp *rbuf,
341 const char *description, const char *story,
342 int *recv_errno,
343 struct logger *logger)
344{
345 dbg("xfrm: %s() sending %d", __func__, hdr->nlmsg_type){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: %s() sending %d", __func__, hdr->nlmsg_type
); } }
;
346
347 struct nlm_resp rsp;
348 size_t len;
349 ssize_t r;
350 struct sockaddr_nl addr;
351 static uint32_t seq = 0; /* STATIC */
352
353 *recv_errno = 0;
354
355 hdr->nlmsg_seq = ++seq;
356 len = hdr->nlmsg_len;
357 do {
358 r = write(nl_send_fd, hdr, len);
359 } while (r < 0 && errno(*__errno_location ()) == EINTR4);
360
361 if (r < 0) {
362 log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink write() of %s message for %s %s failed"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), description
, story); }
363 "netlink write() of %s message for %s %s failed",{ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink write() of %s message for %s %s failed"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), description
, story); }
364 sparse_val_show(xfrm_type_names, hdr->nlmsg_type),{ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink write() of %s message for %s %s failed"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), description
, story); }
365 description, story){ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink write() of %s message for %s %s failed"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), description
, story); }
;
366 return false0;
367 }
368
369 if ((size_t)r != len) {
370 llog(RC_LOG_SERIOUS, logger,
371 "ERROR: netlink write() of %s message for %s %s truncated: %zd instead of %zu",
372 sparse_val_show(xfrm_type_names, hdr->nlmsg_type),
373 description, story, r, len);
374 return false0;
375 }
376
377 for (;;) {
378 socklen_t alen = sizeof(addr);
379
380 r = recvfrom(nl_send_fd, &rsp, sizeof(rsp), 0,
381 (struct sockaddr *)&addr, &alen);
382 if (r < 0) {
383 if (errno(*__errno_location ()) == EINTR4)
384 continue;
385 *recv_errno = errno(*__errno_location ());
386 log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink recvfrom() of response to our %s message for %s %s failed"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), description
, story); }
387 "netlink recvfrom() of response to our %s message for %s %s failed",{ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink recvfrom() of response to our %s message for %s %s failed"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), description
, story); }
388 sparse_val_show(xfrm_type_names,{ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink recvfrom() of response to our %s message for %s %s failed"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), description
, story); }
389 hdr->nlmsg_type),{ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink recvfrom() of response to our %s message for %s %s failed"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), description
, story); }
390 description, story){ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink recvfrom() of response to our %s message for %s %s failed"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), description
, story); }
;
391 return false0;
392 } else if ((size_t) r < sizeof(rsp.n)) {
393 llog(RC_LOG, logger,
394 "netlink read truncated message: %zd bytes; ignore message", r);
395 continue;
396 } else if (addr.nl_pid != 0) {
397 /* not for us: ignore */
398 dbg("xfrm: ignoring %s message from process %u",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: ignoring %s message from process %u", sparse_val_show
(xfrm_type_names, rsp.n.nlmsg_type), addr.nl_pid); } }
399 sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: ignoring %s message from process %u", sparse_val_show
(xfrm_type_names, rsp.n.nlmsg_type), addr.nl_pid); } }
400 addr.nl_pid){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: ignoring %s message from process %u", sparse_val_show
(xfrm_type_names, rsp.n.nlmsg_type), addr.nl_pid); } }
;
401 continue;
402 } else if (rsp.n.nlmsg_seq != seq) {
403 dbg("xfrm: ignoring out of sequence (%u/%u) message %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: ignoring out of sequence (%u/%u) message %s"
, rsp.n.nlmsg_seq, seq, sparse_val_show(xfrm_type_names, rsp.
n.nlmsg_type)); } }
404 rsp.n.nlmsg_seq, seq,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: ignoring out of sequence (%u/%u) message %s"
, rsp.n.nlmsg_seq, seq, sparse_val_show(xfrm_type_names, rsp.
n.nlmsg_type)); } }
405 sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: ignoring out of sequence (%u/%u) message %s"
, rsp.n.nlmsg_seq, seq, sparse_val_show(xfrm_type_names, rsp.
n.nlmsg_type)); } }
;
406 continue;
407 }
408 break;
409 }
410
411 if (rsp.n.nlmsg_len > (size_t) r) {
412 llog(RC_LOG_SERIOUS, logger,
413 "netlink recvfrom() of response to our %s message for %s %s was truncated: %zd instead of %zu",
414 sparse_val_show(xfrm_type_names, hdr->nlmsg_type),
415 description, story,
416 len, (size_t) rsp.n.nlmsg_len);
417 return false0;
418 }
419
420 if (rsp.n.nlmsg_type != expected_resp_type && rsp.n.nlmsg_type == NLMSG_ERROR0x2) {
421 if (rsp.u.e.error != 0) {
422 llog(RC_LOG_SERIOUS, logger,
423 "ERROR: netlink response for %s %s included errno %d: %s",
424 description, story, -rsp.u.e.error,
425 strerror(-rsp.u.e.error));
426 return false0;
427 }
428 /*
429 * What the heck does a 0 error mean?
430 * Since the caller doesn't depend on the result
431 * we'll let it pass.
432 * This really happens for netlink_add_sa().
433 */
434 dbg("netlink response for %s %s included non-error error",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("netlink response for %s %s included non-error error"
, description, story); } }
435 description, story){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("netlink response for %s %s included non-error error"
, description, story); } }
;
436 /* ignore */
437 }
438 if (rbuf == NULL((void*)0)) {
439 return true1;
440 }
441 if (rsp.n.nlmsg_type != expected_resp_type) {
442 llog(RC_LOG_SERIOUS, logger,
443 "netlink recvfrom() of response to our %s message for %s %s was of wrong type (%s)",
444 sparse_val_show(xfrm_type_names, hdr->nlmsg_type),
445 description, story,
446 sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type));
447 return false0;
448 }
449 memcpy(rbuf, &rsp, r);
450 return true1;
451}
452
453/*
454 * netlink_policy -
455 *
456 * @param hdr - Data to check
457 * @param enoent_ok - Boolean - OK or not OK.
458 * @param story - String
459 * @return boolean
460 */
461static bool_Bool netlink_policy(struct nlmsghdr *hdr, bool_Bool enoent_ok,
462 const char *story, struct logger *logger)
463{
464 struct nlm_resp rsp;
465
466 int recv_errno;
467 if (!send_netlink_msg(hdr, NLMSG_ERROR0x2, &rsp,
468 "policy", story,
469 &recv_errno, logger)) {
470 return false0;
471 }
472
473 /*
474 * Kind of surprising: we get here by success which implies an
475 * error structure!
476 */
477
478 int error = -rsp.u.e.error;
479 if (error == 0 || (error == ENOENT2 && enoent_ok))
480 return true1;
481
482 log_errno(logger, error,{ int e_ = error; log_error(logger, e_, "ERROR: netlink %s response for flow %s"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), story
); }
483 "ERROR: netlink %s response for flow %s",{ int e_ = error; log_error(logger, e_, "ERROR: netlink %s response for flow %s"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), story
); }
484 sparse_val_show(xfrm_type_names, hdr->nlmsg_type),{ int e_ = error; log_error(logger, e_, "ERROR: netlink %s response for flow %s"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), story
); }
485 story){ int e_ = error; log_error(logger, e_, "ERROR: netlink %s response for flow %s"
, sparse_val_show(xfrm_type_names, hdr->nlmsg_type), story
); }
;
486 return false0;
487}
488
489/*
490 * netlink_raw_policy
491 *
492 * @param kernel_policy_op op (operation - ie: KP_DELETE)
493 * @param src_host ip_address
494 * @param src_client ip_subnet
495 * @param dst_host ip_address
496 * @param dst_client ip_subnet
497 * @param spi
498 * @param sa_proto int (4=tunnel, 50=esp, 108=ipcomp, etc ...)
499 * @param transport_proto unsigned int Contains protocol
500 * (6=tcp, 17=udp, etc...)
501 * @param esatype int
502 * @param pfkey_proto_info proto_info
503 * @param use_lifetime monotime_t (Currently unused)
504 * @param story char *
505 * @return boolean True if successful
506 */
507static bool_Bool netlink_raw_policy(enum kernel_policy_op op,
508 const ip_address *src_host,
509 const ip_selector *src_client,
510 const ip_address *dst_host,
511 const ip_selector *dst_client,
512 ipsec_spi_t cur_spi, /* current SPI */
513 ipsec_spi_t new_spi, /* new SPI */
514 unsigned int transport_proto,
515 enum eroute_type esatype,
516 const struct kernel_encap *encap,
517 deltatime_t use_lifetime UNUSED__attribute__ ((unused)),
518 uint32_t sa_priority,
519 const struct sa_marks *sa_marks,
520 const uint32_t xfrm_if_id,
521 const shunk_t sec_label,
522 struct logger *logger)
523{
524 struct {
525 struct nlmsghdr n;
526 union {
527 struct xfrm_userpolicy_info p;
528 struct xfrm_userpolicy_id id;
529 } u;
530 /* ??? MAX_NETLINK_DATA_SIZE is defined in our header, not a kernel header */
531 char data[MAX_NETLINK_DATA_SIZE8192];
532 } req;
533
534 /*
535 * ???
536 * This enum was pointlessly copied from /usr/include/linux/ipsec.h
537 * We don't use that header because it is for Racoon or PFKEY2
538 * and we are neither.
539 * Only three of the five values remain.
540 * The values don't leak from this function (except in dbg output)
541 * so the numerical values are no longer specified.
542 * The value of "policy" is only used within this function and
543 * only in two places; surely this could be simplified further.
544 * The names should be made more appropriate and concise
545 * for this very local and specific context.
546 * Yet another meaning overloaded onto the word "policy".
547 */
548 enum {
549 IPSEC_POLICY_DISCARD,
550 IPSEC_POLICY_NONE,
551 IPSEC_POLICY_IPSEC,
552 } policy;
553
554 const char *policy_name;
555 switch (esatype) {
556 case ET_UNSPEC:
557 case ET_AH:
558 case ET_ESP:
559 case ET_IPCOMP:
560 case ET_IPIP:
561 policy = IPSEC_POLICY_IPSEC;
562 policy_name = protocol_by_ipproto(esatype)->name;
563 break;
564
565 case ET_INT:
566 /* shunt route */
567 switch (ntohl(new_spi)) {
568 case SPI_PASS:
569 policy = IPSEC_POLICY_NONE;
570 policy_name = "%pass(none)";
571 break;
572 case SPI_HOLD:
573 /*
574 * We don't know how to implement %hold, but it is okay.
575 * When we need a hold, the kernel XFRM acquire state
576 * will do the job (by dropping or holding the packet)
577 * until this entry expires. See /proc/sys/net/core/xfrm_acq_expires
578 * After expiration, the underlying policy causing the original acquire
579 * will fire again, dropping further packets.
580 */
581 dbg("%s() SPI_HOLD implemented as no-op", __func__){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() SPI_HOLD implemented as no-op", __func__
); } }
;
582 return true1; /* yes really */
583 case SPI_DROP:
584 /* used with type=passthrough - can it not use SPI_PASS ?? */
585 policy = IPSEC_POLICY_DISCARD;
586 policy_name = "%drop(discard)";
587 break;
588 case SPI_REJECT:
589 /* used with type=passthrough - can it not use SPI_PASS ?? */
590 policy = IPSEC_POLICY_DISCARD;
591 policy_name = "%reject(discard)";
592 break;
593 case 0:
594 /* used with type=passthrough - can it not use SPI_PASS ?? */
595 policy = IPSEC_POLICY_DISCARD;
596 policy_name = "%discard(discard)";
597 break;
598 case SPI_TRAP:
599 if (op == KP_ADD_INBOUND || op == KP_DELETE_INBOUND) {
600 dbg("%s() inbound SPI_TRAP implemented as no-op", __func__){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() inbound SPI_TRAP implemented as no-op", __func__
); } }
;
601 return true1;
602 }
603 policy = IPSEC_POLICY_IPSEC;
604 policy_name = "%trap(ipsec)";
605 break;
606 case SPI_IGNORE:
607 case SPI_TRAPSUBNET: /* unused in our code */
608 default:
609 bad_case(ntohl(new_spi))libreswan_bad_case("ntohl(new_spi)", (ntohl(new_spi)), ({ static
const struct where here = { .func = __func__, .file = "programs/pluto/kernel_xfrm.c"
, .line = 609, }; &here; }))
;
610 }
611 break;
612
613 default:
614 bad_case(esatype)libreswan_bad_case("esatype", (esatype), ({ static const struct
where here = { .func = __func__, .file = "programs/pluto/kernel_xfrm.c"
, .line = 614, }; &here; }))
;
615 }
616 const int dir = (op == KP_ADD_INBOUND ||
617 op == KP_DELETE_INBOUND) ?
618 XFRM_POLICY_IN : XFRM_POLICY_OUT;
619 dbg("%s() policy=%s/%d dir=%d", __func__, policy_name, policy, dir){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() policy=%s/%d dir=%d", __func__, policy_name
, policy, dir); } }
;
620
621 zero(&req)memset((&req), '\0', sizeof(*(&req)));
622 req.n.nlmsg_flags = NLM_F_REQUEST0x01 | NLM_F_ACK0x04;
623
624 const struct ip_info *dst_client_afi = selector_type(dst_client);
625 const int family = dst_client_afi->af;
626 dbg("%s() using family %s (%d)", __func__, dst_client_afi->ip_name, family){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() using family %s (%d)", __func__, dst_client_afi
->ip_name, family); } }
;
627
628 /* .[sd]addr, .prefixlen_[sd], .[sd]port */
629 SELECTOR_TO_XFRM(src_client, req.u.p.sel, s){ ip_selector client_ = *(src_client); ip_address address = selector_prefix
(client_); (req.u.p.sel).saddr = xfrm_from_address(&address
); (req.u.p.sel).prefixlen_s = selector_prefix_bits(client_);
(req.u.p.sel).sport = nport(selector_port(client_)); }
;
630 SELECTOR_TO_XFRM(dst_client, req.u.p.sel, d){ ip_selector client_ = *(dst_client); ip_address address = selector_prefix
(client_); (req.u.p.sel).daddr = xfrm_from_address(&address
); (req.u.p.sel).prefixlen_d = selector_prefix_bits(client_);
(req.u.p.sel).dport = nport(selector_port(client_)); }
;
631
632 /*
633 * Munge .[sd]port?
634 *
635 * As per RFC 4301/5996, icmp type is put in the most significant
636 * 8 bits and icmp code is in the least significant 8 bits of port
637 * field.
638 * Although Libreswan does not have any configuration options for
639 * icmp type/code values, it is possible to specify icmp type and code
640 * using protoport option. For example, icmp echo request
641 * (type 8/code 0) needs to be encoded as 0x0800 in the port field
642 * and can be specified as left/rightprotoport=icmp/2048. Now with
643 * XFRM, icmp type and code need to be passed as source and
644 * destination ports, respectively. Therefore, this code extracts
645 * upper 8 bits and lower 8 bits and puts into source and destination
646 * ports before passing to XFRM.
647 */
648 if (transport_proto == IPPROTO_ICMPIPPROTO_ICMP ||
649 transport_proto == IPPROTO_ICMPV658) {
650 uint16_t tc = ntohs(req.u.p.sel.sport);
651 uint16_t icmp_type = tc >> 8;
652 uint16_t icmp_code = tc & 0xFF;
653
654 req.u.p.sel.sport = htons(icmp_type);
655 req.u.p.sel.dport = htons(icmp_code);
656 }
657
658 /* note: byte order doesn't change 0 or ~0 */
659 req.u.p.sel.sport_mask = req.u.p.sel.sport == 0 ? 0 : ~0;
660 req.u.p.sel.dport_mask = req.u.p.sel.dport == 0 ? 0 : ~0;
661 req.u.p.sel.proto = transport_proto;
662 req.u.p.sel.family = family;
663
664 if (op == KP_DELETE_OUTBOUND ||
665 op == KP_DELETE_INBOUND) {
666 req.u.id.dir = dir;
667 req.n.nlmsg_type = XFRM_MSG_DELPOLICYXFRM_MSG_DELPOLICY;
668 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.id)))( ((((sizeof(req.u.id)) + ((int) ( ((sizeof(struct nlmsghdr))
+4U -1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
669 } else {
670 req.u.p.dir = dir;
671
672 /* The caller should have set the proper priority by now */
673 req.u.p.priority = sa_priority;
674 dbg("%s() IPsec SA SPD priority set to %d", __func__, req.u.p.priority){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() IPsec SA SPD priority set to %d", __func__
, req.u.p.priority); } }
;
675
676 req.u.p.action = policy == IPSEC_POLICY_DISCARD ?
677 XFRM_POLICY_BLOCK1 : XFRM_POLICY_ALLOW0;
678 /* req.u.p.lft.soft_use_expires_seconds = deltasecs(use_lifetime); */
679 req.u.p.lft.soft_byte_limit = XFRM_INF(~(__u64)0);
680 req.u.p.lft.soft_packet_limit = XFRM_INF(~(__u64)0);
681 req.u.p.lft.hard_byte_limit = XFRM_INF(~(__u64)0);
682 req.u.p.lft.hard_packet_limit = XFRM_INF(~(__u64)0);
683
684 /*
685 * NEW will fail when an existing policy, UPD always works.
686 * This seems to happen in cases with NAT'ed XP clients, or
687 * quick recycling/resurfacing of roadwarriors on the same IP.
688 *
689 * UPD is also needed for two separate tunnels with same end
690 * subnets
691 * Like A = B = C config where both A - B and B - C have
692 * tunnel A = C configured.
693 */
694 req.n.nlmsg_type = XFRM_MSG_UPDPOLICYXFRM_MSG_UPDPOLICY;
695 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.p)))( ((((sizeof(req.u.p)) + ((int) ( ((sizeof(struct nlmsghdr))+
4U -1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
696 }
697
698 /*
699 * Add the encapsulation protocol found in proto_info[] that
700 * will carry the packets (which the kernel seems to call
701 * user_templ).
702 *
703 * XXX: why not just test proto_info - let caller decide if it
704 * is needed. Lets find out.
705 */
706 if (encap != NULL((void*)0) &&
707 /* XXX: see comment above, and {else} below */
708 (policy == IPSEC_POLICY_IPSEC || policy == IPSEC_POLICY_DISCARD) &&
709 op != KP_DELETE_OUTBOUND) {
710 struct xfrm_user_tmpl tmpl[4] = {0};
711
712 int i;
713 for (i = 0; i <= encap->outer; i++) {
714 tmpl[i].reqid = encap->rule[i].reqid;
715 tmpl[i].id.proto = encap->rule[i].proto;
716 tmpl[i].optional = (encap->rule[i].proto == ENCAP_PROTO_IPCOMP && dir != XFRM_POLICY_OUT);
717 tmpl[i].aalgos = tmpl[i].ealgos = tmpl[i].calgos = ~0;
718 tmpl[i].family = addrtypeof(dst_host);
719 /* only the inner-most rule gets the worm; er tunnel flag */
720 tmpl[i].mode = (i == 0 && encap->mode == ENCAP_MODE_TUNNEL);
721
722 if (tmpl[i].mode) {
723 /* tunnel mode needs addresses */
724 tmpl[i].saddr = xfrm_from_address(src_host);
725 tmpl[i].id.daddr = xfrm_from_address(dst_host);
726 }
727
728 address_buf sb, db;
729 dbg("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s"
, __func__, tmpl[i].reqid, tmpl[i].id.proto, tmpl[i].optional
, tmpl[i].family, tmpl[i].mode, str_address(tmpl[i].mode ? src_host
: &unset_address, &sb), str_address(tmpl[i].mode ? dst_host
: &unset_address, &db)); } }
730 __func__,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s"
, __func__, tmpl[i].reqid, tmpl[i].id.proto, tmpl[i].optional
, tmpl[i].family, tmpl[i].mode, str_address(tmpl[i].mode ? src_host
: &unset_address, &sb), str_address(tmpl[i].mode ? dst_host
: &unset_address, &db)); } }
731 tmpl[i].reqid,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s"
, __func__, tmpl[i].reqid, tmpl[i].id.proto, tmpl[i].optional
, tmpl[i].family, tmpl[i].mode, str_address(tmpl[i].mode ? src_host
: &unset_address, &sb), str_address(tmpl[i].mode ? dst_host
: &unset_address, &db)); } }
732 tmpl[i].id.proto,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s"
, __func__, tmpl[i].reqid, tmpl[i].id.proto, tmpl[i].optional
, tmpl[i].family, tmpl[i].mode, str_address(tmpl[i].mode ? src_host
: &unset_address, &sb), str_address(tmpl[i].mode ? dst_host
: &unset_address, &db)); } }
733 tmpl[i].optional,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s"
, __func__, tmpl[i].reqid, tmpl[i].id.proto, tmpl[i].optional
, tmpl[i].family, tmpl[i].mode, str_address(tmpl[i].mode ? src_host
: &unset_address, &sb), str_address(tmpl[i].mode ? dst_host
: &unset_address, &db)); } }
734 tmpl[i].family,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s"
, __func__, tmpl[i].reqid, tmpl[i].id.proto, tmpl[i].optional
, tmpl[i].family, tmpl[i].mode, str_address(tmpl[i].mode ? src_host
: &unset_address, &sb), str_address(tmpl[i].mode ? dst_host
: &unset_address, &db)); } }
735 tmpl[i].mode,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s"
, __func__, tmpl[i].reqid, tmpl[i].id.proto, tmpl[i].optional
, tmpl[i].family, tmpl[i].mode, str_address(tmpl[i].mode ? src_host
: &unset_address, &sb), str_address(tmpl[i].mode ? dst_host
: &unset_address, &db)); } }
736 str_address(tmpl[i].mode ? src_host : &unset_address, &sb),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s"
, __func__, tmpl[i].reqid, tmpl[i].id.proto, tmpl[i].optional
, tmpl[i].family, tmpl[i].mode, str_address(tmpl[i].mode ? src_host
: &unset_address, &sb), str_address(tmpl[i].mode ? dst_host
: &unset_address, &db)); } }
737 str_address(tmpl[i].mode ? dst_host : &unset_address, &db)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_tmpl reqid=%d id.proto=%d optional=%d family=%d mode=%d saddr=%s id.daddr=%s"
, __func__, tmpl[i].reqid, tmpl[i].id.proto, tmpl[i].optional
, tmpl[i].family, tmpl[i].mode, str_address(tmpl[i].mode ? src_host
: &unset_address, &sb), str_address(tmpl[i].mode ? dst_host
: &unset_address, &db)); } }
;
738 }
739
740 /* append */
741 struct rtattr *attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
742 attr->rta_type = XFRMA_TMPL;
743 attr->rta_len = i * sizeof(tmpl[0]);
744 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, tmpl, attr->rta_len);
745 attr->rta_len = RTA_LENGTH(attr->rta_len)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (attr->
rta_len))
;
746 req.n.nlmsg_len += attr->rta_len;
747
748 } else if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX)))) && encap != NULL((void*)0)) {
749 /*
750 * Dump ignored proto_info[].
751 */
752 for (unsigned i = 0; encap->rule[i].proto; i++) {
753 DBG_log("%s() ignoring xfrm_user_tmpl reqid=%d proto=%s %s because policy=%d op=%d",
754 __func__, encap->rule[i].reqid,
755 protocol_by_ipproto(encap->rule[i].proto)->name,
756 encap_mode_name(encap->mode)({ enum encap_mode e_ = encap->mode; (e_ == ENCAP_MODE_TUNNEL
? "tunnel" : e_ == ENCAP_MODE_TRANSPORT ? "transport" : "unknown"
); })
,
757 policy, op);
758 }
759
760 }
761
762 /*
763 * Add mark policy extension if present.
764 *
765 * XXX: again, can't the caller decide this?
766 */
767 if (sa_marks != NULL((void*)0) &&
768 /* XXX: see comment above and {else} below */
769 (policy == IPSEC_POLICY_IPSEC || policy == IPSEC_POLICY_DISCARD)) {
770 if (xfrm_if_id == 0) {
771 struct sa_mark sa_mark = (dir == XFRM_POLICY_IN) ? sa_marks->in : sa_marks->out;
772
773 if (sa_mark.val != 0 && sa_mark.mask != 0) {
774 struct xfrm_mark xfrm_mark = {
775 .v = sa_mark.val,
776 .m = sa_mark.mask,
777 };
778 dbg("%s() adding xfrm_mark %x/%x", __func__, xfrm_mark.v, xfrm_mark.m){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_mark %x/%x", __func__, xfrm_mark
.v, xfrm_mark.m); } }
;
779 /* append */
780 struct rtattr *attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
781 attr->rta_type = XFRMA_MARK;
782 attr->rta_len = sizeof(xfrm_mark);
783 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &xfrm_mark, attr->rta_len);
784 attr->rta_len = RTA_LENGTH(attr->rta_len)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (attr->
rta_len))
;
785 req.n.nlmsg_len += attr->rta_len;
786 }
787#ifdef USE_XFRM_INTERFACE1
788 } else {
789 dbg("%s() adding XFRMA_IF_ID %" PRIu32 " req.n.nlmsg_type=%" PRIu32,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding XFRMA_IF_ID %" "u" " req.n.nlmsg_type=%"
"u", __func__, xfrm_if_id, req.n.nlmsg_type); } }
790 __func__, xfrm_if_id, req.n.nlmsg_type){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding XFRMA_IF_ID %" "u" " req.n.nlmsg_type=%"
"u", __func__, xfrm_if_id, req.n.nlmsg_type); } }
;
791 nl_addattr32(&req.n, sizeof(req.data), XFRMA_IF_ID, xfrm_if_id);
792 if (sa_marks->out.val == 0 && sa_marks->out.mask == 0) {
793 /* XFRMA_SET_MARK = XFRMA_IF_ID */
794 nl_addattr32(&req.n, sizeof(req.data), XFRMA_SET_MARK, xfrm_if_id);
795 } else {
796 /* manually configured mark-out=mark/mask */
797 nl_addattr32(&req.n, sizeof(req.data),
798 XFRMA_SET_MARK, sa_marks->out.val);
799 nl_addattr32(&req.n, sizeof(req.data),
800 XFRMA_SET_MARK_MASK, sa_marks->out.mask);
801 }
802#endif
803 }
804 } else if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX)))) && sa_marks != NULL((void*)0)) {
805 DBG_log("%s() ignoring xfrm_mark in %x/%x out %x/%x because policy=%d op=%d", __func__,
806 sa_marks->in.val, sa_marks->in.mask,
807 sa_marks->out.val, sa_marks->out.mask,
808 policy, op);
809 }
810
811 if (sec_label.len > 0) {
812 struct rtattr *attr = (struct rtattr *)
813 ((char *)&req + req.n.nlmsg_len);
814 struct xfrm_user_sec_ctx *uctx;
815
816 passert(sec_label.len <= MAX_SECCTX_LEN)({ _Bool assertion__ = sec_label.len <= 4096; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/kernel_xfrm.c", .line = 816
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "sec_label.len <= 4096"
); } (void) 1; })
;
817 attr->rta_type = XFRMA_SEC_CTX;
818
819 dbg("%s() adding xfrm_user_sec_ctx sec_label="PRI_SHUNK" to kernel", __func__, pri_shunk(sec_label)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding xfrm_user_sec_ctx sec_label=""%.*s"
" to kernel", __func__, ((int) (sec_label).len), (const char *
) ((sec_label).ptr)); } }
;
820 attr->rta_len = RTA_LENGTH(sizeof(struct xfrm_user_sec_ctx) + sec_label.len)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(struct xfrm_user_sec_ctx) + sec_label.len))
;
821 uctx = RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
;
822 uctx->exttype = XFRMA_SEC_CTX;
823 uctx->len = sizeof(struct xfrm_user_sec_ctx) + sec_label.len;
824 uctx->ctx_doi = XFRM_SC_DOI_LSM1;
825 uctx->ctx_alg = XFRM_SC_ALG_SELINUX1;
826 uctx->ctx_len = sec_label.len;
827 memcpy(uctx + 1, sec_label.ptr, sec_label.len);
828 req.n.nlmsg_len += attr->rta_len;
829 }
830
831 bool_Bool enoent_ok = (op == KP_DELETE_INBOUND ||
832 (op == KP_DELETE_OUTBOUND && ntohl(cur_spi) == SPI_HOLD));
833
834 bool_Bool ok = netlink_policy(&req.n, enoent_ok, policy_name, logger);
835
836 /*
837 * ??? deal with any forwarding policy.
838 *
839 * For tunnel mode the inbound SA needs a add/delete a forward
840 * policy; from where, to where? Why?
841 *
842 * XXX: and yes, the code below doesn't exactly do just that.
843 */
844 switch (op) {
845 case KP_DELETE_INBOUND:
846#if 0
847 /*
848 * XXX: does sec_label need a forward? Lets assume
849 * not.
850 */
851 if (sec_label.len > 0) {
852 break;
853 }
854#endif
855 /*
856 * ??? we will call netlink_policy even if !ok.
857 *
858 * XXX: It's also called when transport mode!
859 *
860 * Presumably this is trying to also delete earlier
861 * SNAFUs.
862 */
863 dbg("xfrm: %s() deleting policy forward (even when there may not be one)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: %s() deleting policy forward (even when there may not be one)"
, __func__); } }
864 __func__){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: %s() deleting policy forward (even when there may not be one)"
, __func__); } }
;
865 req.u.id.dir = XFRM_POLICY_FWD;
866 ok &= netlink_policy(&req.n, enoent_ok, policy_name, logger);
867 break;
868 case KP_ADD_INBOUND:
869#if 0
870 /*
871 * XXX: does sec_label need a forward? Lets assume
872 * not.
873 */
874 if (sec_label.len > 0) {
875 break;
876 }
877#endif
878 if (!ok) {
879 break;
880 }
881 if (esatype != ET_INT &&
882 encap != NULL((void*)0) && encap->mode == ENCAP_MODE_TRANSPORT) {
883 break;
884 }
885 dbg("xfrm: %s() adding policy forward (suspect a tunnel)", __func__){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: %s() adding policy forward (suspect a tunnel)"
, __func__); } }
;
886 req.u.p.dir = XFRM_POLICY_FWD;
887 ok &= netlink_policy(&req.n, enoent_ok, policy_name, logger);
888 break;
889 default:
890 break; /*no-op*/
891 }
892 return ok;
893}
894
895static void set_migration_attr(const struct kernel_sa *sa,
896 struct xfrm_user_migrate *m)
897{
898 m->old_saddr = xfrm_from_address(sa->src.address);
899 m->old_daddr = xfrm_from_address(sa->dst.address);
900 m->new_saddr = xfrm_from_address(&sa->src.new_address);
901 m->new_daddr = xfrm_from_address(&sa->dst.new_address);
902 m->mode = (sa->level == 0 && sa->tunnel ? ENCAPSULATION_MODE_TUNNEL : XFRM_MODE_TRANSPORT0);
903 m->proto = sa->proto->ipproto;
904 m->reqid = sa->reqid;
905 m->old_family = m->new_family = address_type(sa->src.address)->af;
906}
907
908/*
909 * size of buffer needed for "story"
910 *
911 * RFC 1886 old IPv6 reverse-lookup format is the bulkiest.
912 *
913 * Since the bufs have 2 char padding, this slightly overallocates.
914 */
915typedef struct {
916 char buf[16 + sizeof(said_buf) + sizeof(address_reversed_buf)];
917} story_buf;
918
919static bool_Bool create_xfrm_migrate_sa(struct state *st,
920 const int dir, /* netkey SA direction XFRM_POLICY_* */
921 struct kernel_sa *ret_sa,
922 story_buf *story /* must live as long as sa */)
923{
924 const struct connection *const c = st->st_connection;
925
926 const struct ip_encap *encap_type =
927 (st->st_interface->protocol == &ip_protocol_tcpip_protocols[IPPROTO_TCP]) ? &ip_encap_esp_in_tcp :
928 (st->hidden_variables.st_nat_traversal & NAT_T_DETECTED( ((lset_t)1 << (NATED_HOST)) | ((lset_t)1 << (NATED_PEER
)) )
) ? &ip_encap_esp_in_udp :
929 NULL((void*)0);
930 dbg("TCP/NAT: encap type "PRI_IP_ENCAP, pri_ip_encap(encap_type)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("TCP/NAT: encap type ""%u(%s)", (encap_type) ==
((void*)0) ? 0 : (encap_type)->encap_type, (encap_type) ==
((void*)0) ? "none" : (encap_type)->name); } }
;
931
932 const struct ip_protocol *proto;
933 struct ipsec_proto_info *proto_info;
934
935 if (st->st_esp.present) {
936 proto = &ip_protocol_espip_protocols[IPPROTO_ESP];
937 proto_info = &st->st_esp;
938 } else if (st->st_ah.present) {
939 proto = &ip_protocol_ahip_protocols[IPPROTO_AH];
940 proto_info = &st->st_ah;
941 } else {
942 return false0;
943 }
944
945 struct jambuf story_jb = ARRAY_AS_JAMBUF(story->buf)array_as_jambuf((story->buf), sizeof(story->buf));
946
947 struct kernel_sa sa = {
948 .xfrm_dir = dir,
949 .proto = proto,
950 .reqid = reqid_esp(c->spd.reqid),
951 .encap_type = encap_type,
952 .tunnel = (st->st_ah.attrs.mode == ENCAPSULATION_MODE_TUNNEL ||
953 st->st_esp.attrs.mode == ENCAPSULATION_MODE_TUNNEL),
954 .story = story->buf, /* content will evolve */
955 /* WWW what about sec_label? */
956 };
957
958 ip_endpoint new_endpoint;
959 uint16_t old_port;
960 uint16_t encap_sport;
961 uint16_t encap_dport;
962
963 /* note: XFRM_POLICY_FWD is inbound too */
964 bool_Bool inbound = dir != XFRM_POLICY_OUT;
965
966 const struct end *src_end, *dst_end;
967
968 if (inbound) {
969 src_end = &c->spd.that;
970 dst_end = &c->spd.this;
971 sa.spi = proto_info->our_spi;
972 } else {
973 src_end = &c->spd.this;
974 dst_end = &c->spd.that;
975 sa.spi = proto_info->attrs.spi;
976 }
977 const ip_address *src = &src_end->host_addr;
978 const ip_address *dst = &dst_end->host_addr;
979
980 sa.src.new_address = *src; /* may be overridden */
981 sa.dst.new_address = *dst; /* may be overridden */
982
983 if (endpoint_is_specified(st->st_mobike_local_endpoint)) {
984 jam_string(&story_jb, "initiator migrate kernel SA ");
985 old_port = endpoint_hport(st->st_interface->local_endpoint);
986 new_endpoint = st->st_mobike_local_endpoint;
987
988 if (inbound) {
989 sa.dst.new_address = endpoint_address(new_endpoint);
990 encap_sport = endpoint_hport(st->st_remote_endpoint);
991 encap_dport = endpoint_hport(new_endpoint);
992 } else {
993 sa.src.new_address = endpoint_address(new_endpoint);
994 encap_sport = endpoint_hport(new_endpoint);
995 encap_dport = endpoint_hport(st->st_remote_endpoint);
996 }
997 } else {
998 jam_string(&story_jb, "responder migrate kernel SA ");
999 old_port = endpoint_hport(st->st_remote_endpoint);
1000 new_endpoint = st->st_mobike_remote_endpoint;
1001
1002 if (inbound) {
1003 sa.src.new_address = endpoint_address(new_endpoint);
1004 encap_sport = endpoint_hport(new_endpoint);
1005 encap_dport = endpoint_hport(st->st_interface->local_endpoint);
1006 } else {
1007 sa.dst.new_address = endpoint_address(new_endpoint);
1008 encap_sport = endpoint_hport(st->st_interface->local_endpoint);
1009 encap_dport = endpoint_hport(new_endpoint);
1010 }
1011 }
1012
1013 if (encap_type == NULL((void*)0)) {
1014 encap_sport = 0;
1015 encap_dport = 0;
1016 }
1017
1018 sa.src.address = src;
1019 sa.dst.address = dst;
1020 sa.src.client = &src_end->client;
1021 sa.dst.client = &dst_end->client;
1022 sa.src.encap_port = encap_sport;
1023 sa.dst.encap_port = encap_dport;
1024
1025 ip_said said = said_from_address_protocol_spi(*dst, proto, sa.spi);
1026 jam_said(&story_jb, &said);
1027
1028 endpoint_buf ra;
1029 jam(&story_jb, ":%u to %s reqid=%u %s",
1030 old_port,
1031 str_endpoint(&new_endpoint, &ra),
1032 sa.reqid,
1033 enum_name(&netkey_sa_dir_names, dir));
1034
1035 dbg("%s", story->buf){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s", story->buf); } }
;
1036
1037 *ret_sa = sa;
1038 return true1;
1039}
1040
1041static bool_Bool migrate_xfrm_sa(const struct kernel_sa *sa,
1042 struct logger *logger)
1043{
1044 struct {
1045 struct nlmsghdr n;
1046 struct xfrm_userpolicy_id id;
1047 char data[MAX_NETLINK_DATA_SIZE8192];
1048 } req;
1049 struct nlm_resp rsp;
1050 struct rtattr *attr;
1051
1052 zero(&req)memset((&req), '\0', sizeof(*(&req)));
1053
1054 req.id.dir = sa->xfrm_dir;
1055 req.id.sel.family = address_type(sa->src.address)->af;
1056 /* .[sd]addr, .prefixlen_[sd], .[sd]port */
1057 SELECTOR_TO_XFRM(sa->src.client, req.id.sel, s){ ip_selector client_ = *(sa->src.client); ip_address address
= selector_prefix(client_); (req.id.sel).saddr = xfrm_from_address
(&address); (req.id.sel).prefixlen_s = selector_prefix_bits
(client_); (req.id.sel).sport = nport(selector_port(client_))
; }
;
1058 SELECTOR_TO_XFRM(sa->dst.client, req.id.sel, d){ ip_selector client_ = *(sa->dst.client); ip_address address
= selector_prefix(client_); (req.id.sel).daddr = xfrm_from_address
(&address); (req.id.sel).prefixlen_d = selector_prefix_bits
(client_); (req.id.sel).dport = nport(selector_port(client_))
; }
;
1059 req.n.nlmsg_flags = NLM_F_REQUEST0x01 | NLM_F_ACK0x04;
1060 req.n.nlmsg_type = XFRM_MSG_MIGRATEXFRM_MSG_MIGRATE;
1061 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)))( ((((sizeof(req.id)) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
1062
1063 /* add attrs[XFRM_MSG_MIGRATE] */
1064 {
1065 struct xfrm_user_migrate migrate;
1066
1067 zero(&migrate)memset((&migrate), '\0', sizeof(*(&migrate)));
1068 attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
1069 attr->rta_type = XFRMA_MIGRATE;
1070 attr->rta_len = sizeof(migrate);
1071
1072 set_migration_attr(sa, &migrate);
1073
1074 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &migrate, attr->rta_len);
1075 attr->rta_len = RTA_LENGTH(attr->rta_len)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (attr->
rta_len))
;
1076 req.n.nlmsg_len += attr->rta_len;
1077 }
1078
1079 if (sa->encap_type != NULL((void*)0)) {
1080 dbg("adding xfrm_encap_templ when migrating sa encap_type="PRI_IP_ENCAP" sport=%d dport=%d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("adding xfrm_encap_templ when migrating sa encap_type="
"%u(%s)"" sport=%d dport=%d", (sa->encap_type) == ((void*)
0) ? 0 : (sa->encap_type)->encap_type, (sa->encap_type
) == ((void*)0) ? "none" : (sa->encap_type)->name, sa->
src.encap_port, sa->dst.encap_port); } }
1081 pri_ip_encap(sa->encap_type),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("adding xfrm_encap_templ when migrating sa encap_type="
"%u(%s)"" sport=%d dport=%d", (sa->encap_type) == ((void*)
0) ? 0 : (sa->encap_type)->encap_type, (sa->encap_type
) == ((void*)0) ? "none" : (sa->encap_type)->name, sa->
src.encap_port, sa->dst.encap_port); } }
1082 sa->src.encap_port, sa->dst.encap_port){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("adding xfrm_encap_templ when migrating sa encap_type="
"%u(%s)"" sport=%d dport=%d", (sa->encap_type) == ((void*)
0) ? 0 : (sa->encap_type)->encap_type, (sa->encap_type
) == ((void*)0) ? "none" : (sa->encap_type)->name, sa->
src.encap_port, sa->dst.encap_port); } }
;
1083 attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
1084 struct xfrm_encap_tmpl natt;
1085
1086 natt.encap_type = sa->encap_type->encap_type;
1087 natt.encap_sport = ntohs(sa->src.encap_port);
1088 natt.encap_dport = ntohs(sa->dst.encap_port);
1089 zero(&natt.encap_oa)memset((&natt.encap_oa), '\0', sizeof(*(&natt.encap_oa
)))
;
1090
1091 attr->rta_type = XFRMA_ENCAP;
1092 attr->rta_len = RTA_LENGTH(sizeof(natt))(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(natt)))
;
1093
1094 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &natt, sizeof(natt));
1095
1096 req.n.nlmsg_len += attr->rta_len;
1097 }
1098
1099 /*
1100 * Note: Coverity believes that req.n will be overrun
1101 * but that is wrong: the type of req.n only covers the header.
1102 * Maybe there is a way to write this that doesn't mislead Coverity.
1103 */
1104 int recv_errno;
1105 bool_Bool r = send_netlink_msg(&req.n, NLMSG_ERROR0x2, &rsp,
1106 "mobike", sa->story,
1107 &recv_errno, logger);
1108 return r && rsp.u.e.error >= 0;
1109}
1110
1111static bool_Bool netlink_migrate_sa(struct state *st)
1112{
1113 struct kernel_sa sa;
1114 story_buf story; /* must live as long as sa */
1115
1116 return
1117 create_xfrm_migrate_sa(st, XFRM_POLICY_OUT, &sa, &story) &&
1118 migrate_xfrm_sa(&sa, st->st_logger) &&
1119
1120 create_xfrm_migrate_sa(st, XFRM_POLICY_IN, &sa, &story) &&
1121 migrate_xfrm_sa(&sa, st->st_logger) &&
1122
1123 create_xfrm_migrate_sa(st, XFRM_POLICY_FWD, &sa, &story) &&
1124 migrate_xfrm_sa(&sa, st->st_logger);
1125}
1126
1127
1128/* see /usr/include/linux/ethtool.h */
1129
1130enum nic_offload_state {
1131 NIC_OFFLOAD_UNKNOWN,
1132 NIC_OFFLOAD_UNSUPPORTED,
1133 NIC_OFFLOAD_SUPPORTED
1134};
1135
1136static struct {
1137 unsigned int bit;
1138 unsigned int total_blocks;
1139 enum nic_offload_state state;
1140} netlink_esp_hw_offload;
1141
1142static bool_Bool siocethtool(const char *ifname, void *data, const char *action, struct logger *logger)
1143{
1144 struct ifreq ifr = { .ifr_dataifr_ifru.ifru_data = data };
1145 jam_str(ifr.ifr_nameifr_ifrn.ifrn_name, sizeof(ifr.ifr_nameifr_ifrn.ifrn_name), ifname);
1146 if (ioctl(nl_send_fd, SIOCETHTOOL0x8946, &ifr) != 0) {
1147 /* EOPNOTSUPP is expected if kernel doesn't support this */
1148 if (errno(*__errno_location ()) == EOPNOTSUPP95) {
1149 dbg("cannot offload to %s because SIOCETHTOOL %s failed: %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("cannot offload to %s because SIOCETHTOOL %s failed: %s"
, ifname, action, strerror((*__errno_location ()))); } }
1150 ifname, action, strerror(errno)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("cannot offload to %s because SIOCETHTOOL %s failed: %s"
, ifname, action, strerror((*__errno_location ()))); } }
;
1151 } else {
1152 log_errno(logger, errno, "can't offload to %s because SIOCETHTOOL %s failed",{ int e_ = (*__errno_location ()); log_error(logger, e_, "can't offload to %s because SIOCETHTOOL %s failed"
, ifname, action); }
1153 ifname, action){ int e_ = (*__errno_location ()); log_error(logger, e_, "can't offload to %s because SIOCETHTOOL %s failed"
, ifname, action); }
;
1154 }
1155 return false0;
1156 } else {
1157 return true1;
1158 }
1159}
1160
1161static void netlink_find_offload_feature(const char *ifname,
1162 struct logger *logger)
1163{
1164 netlink_esp_hw_offload.state = NIC_OFFLOAD_UNSUPPORTED;
1165
1166 /* Determine number of device-features */
1167
1168 struct ethtool_sset_info *sset_info = alloc_bytes(
1169 sizeof(*sset_info) + sizeof(sset_info->data[0]),
1170 "ethtool_sset_info");
1171 sset_info->cmd = ETHTOOL_GSSET_INFO0x00000037;
1172 sset_info->sset_mask = 1ULL << ETH_SS_FEATURES;
1173
1174 if (!siocethtool(ifname, sset_info, "ETHTOOL_GSSET_INFO", logger) ||
1175 sset_info->sset_mask != 1ULL << ETH_SS_FEATURES) {
1176 pfree(sset_info);
1177 llog(RC_LOG, logger, "Kernel does not support NIC esp-hw-offload (ETHTOOL_GSSET_INFO failed)");
1178 return;
1179 }
1180
1181 uint32_t sset_len = sset_info->data[0];
1182
1183 pfree(sset_info);
1184
1185 /* Retrieve names of device-features */
1186
1187 struct ethtool_gstrings *cmd = alloc_bytes(
1188 sizeof(*cmd) + ETH_GSTRING_LEN32 * sset_len, "ethtool_gstrings");
1189 cmd->cmd = ETHTOOL_GSTRINGS0x0000001b;
1190 cmd->string_set = ETH_SS_FEATURES;
1191
1192 if (siocethtool(ifname, cmd, "ETHTOOL_GSTRINGS", logger)) {
1193 /* Look for the ESP_HW feature bit */
1194 char *str = (char *)cmd->data;
1195 for (uint32_t i = 0; i < cmd->len; i++) {
1196 if (strneq(str, "esp-hw-offload", ETH_GSTRING_LEN)(strncmp((str), ("esp-hw-offload"), (32)) == 0)) {
1197 netlink_esp_hw_offload.bit = i;
1198 netlink_esp_hw_offload.total_blocks = (sset_len + 31) / 32;
1199 netlink_esp_hw_offload.state = NIC_OFFLOAD_SUPPORTED;
1200 break;
1201 }
1202 str += ETH_GSTRING_LEN32;
1203 }
1204 }
1205
1206 pfree(cmd);
1207
1208 if (netlink_esp_hw_offload.state == NIC_OFFLOAD_SUPPORTED) {
1209 llog(RC_LOG, logger, "Kernel supports NIC esp-hw-offload");
1210 } else {
1211 llog(RC_LOG, logger, "Kernel does not support NIC esp-hw-offload");
1212 }
1213}
1214
1215static bool_Bool netlink_detect_offload(const struct raw_iface *ifp, struct logger *logger)
1216{
1217 const char *ifname = ifp->name;
1218 /*
1219 * Kernel requires a real interface in order to query the kernel-wide
1220 * capability, so we do it here on first invocation.
1221 */
1222 if (netlink_esp_hw_offload.state == NIC_OFFLOAD_UNKNOWN)
1223 netlink_find_offload_feature(ifname, logger);
1224
1225 if (netlink_esp_hw_offload.state == NIC_OFFLOAD_UNSUPPORTED) {
1226 return false0;
1227 }
1228
1229 /* Feature is supported by kernel. Query device features */
1230
1231 struct ethtool_gfeatures *cmd = alloc_bytes(
1232 sizeof(*cmd) + sizeof(cmd->features[0]) * netlink_esp_hw_offload.total_blocks,
1233 "ethtool_gfeatures");
1234
1235 cmd->cmd = ETHTOOL_GFEATURES0x0000003a;
1236 cmd->size = netlink_esp_hw_offload.total_blocks;
1237
1238 bool_Bool ret = false0;
1239
1240 if (siocethtool(ifname, cmd, "ETHTOOL_GFEATURES", logger)) {
1241 int block = netlink_esp_hw_offload.bit / 32;
1242 uint32_t feature_bit = 1U << (netlink_esp_hw_offload.bit % 32);
1243 if (cmd->features[block].active & feature_bit)
1244 ret = true1;
1245 }
1246 pfree(cmd);
1247 return ret;
1248}
1249
1250/*
1251 * netlink_add_sa - Add an SA into the kernel SPDB via netlink
1252 *
1253 * @param sa Kernel SA to add/modify
1254 * @param replace boolean - true if this replaces an existing SA
1255 * @return bool True if successful
1256 */
1257static bool_Bool netlink_add_sa(const struct kernel_sa *sa, bool_Bool replace,
1258 struct logger *logger)
1259{
1260 struct {
1261 struct nlmsghdr n;
1262 struct xfrm_usersa_info p;
1263 char data[MAX_NETLINK_DATA_SIZE8192];
1264 } req;
1265 struct rtattr *attr;
1266 int ret;
1267
1268 zero(&req)memset((&req), '\0', sizeof(*(&req)));
1269 req.n.nlmsg_flags = NLM_F_REQUEST0x01 | NLM_F_ACK0x04;
1270 req.n.nlmsg_type = replace ? XFRM_MSG_UPDSAXFRM_MSG_UPDSA : XFRM_MSG_NEWSAXFRM_MSG_NEWSA;
1271
1272 req.p.saddr = xfrm_from_address(sa->src.address);
1273 req.p.id.daddr = xfrm_from_address(sa->dst.address);
1274
1275 req.p.id.spi = sa->spi;
1276 req.p.id.proto = esatype2proto(sa->esatype)((int)(sa->esatype));
1277 req.p.family = addrtypeof(sa->src.address);
1278 /*
1279 * This requires ipv6 modules. It is required to support 6in4
1280 * and 4in6 tunnels in linux 2.6.25+
1281 *
1282 * Only the innermost SA gets the "tunnel" flag.
1283 */
1284 if (sa->level == 0 && sa->tunnel) {
1285 dbg("xfrm: enabling tunnel mode"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: enabling tunnel mode"); } }
;
1286 req.p.mode = XFRM_MODE_TUNNEL1;
1287 req.p.flags |= XFRM_STATE_AF_UNSPEC32;
1288 } else {
1289 dbg("xfrm: enabling transport mode"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: enabling transport mode"); } }
;
1290 req.p.mode = XFRM_MODE_TRANSPORT0;
1291 }
1292
1293 /*
1294 * We only add traffic selectors for transport mode.
1295 *
1296 * The problem is that Tunnel mode ipsec with ipcomp is
1297 * layered so that ipcomp tunnel is protected with transport
1298 * mode ipsec but in this case we shouldn't any more add
1299 * traffic selectors. Caller function will inform us if we
1300 * need or don't need selectors.
1301 */
1302 if (!sa->tunnel) {
1303 /* .[sd]addr, .prefixlen_[sd], .[sd]port */
1304 SELECTOR_TO_XFRM(sa->src.client, req.p.sel, s){ ip_selector client_ = *(sa->src.client); ip_address address
= selector_prefix(client_); (req.p.sel).saddr = xfrm_from_address
(&address); (req.p.sel).prefixlen_s = selector_prefix_bits
(client_); (req.p.sel).sport = nport(selector_port(client_));
}
;
1305 SELECTOR_TO_XFRM(sa->dst.client, req.p.sel, d){ ip_selector client_ = *(sa->dst.client); ip_address address
= selector_prefix(client_); (req.p.sel).daddr = xfrm_from_address
(&address); (req.p.sel).prefixlen_d = selector_prefix_bits
(client_); (req.p.sel).dport = nport(selector_port(client_));
}
;
1306
1307 /*
1308 * Munge .[sd]port?
1309 *
1310 * As per RFC 4301/5996, icmp type is put in the most
1311 * significant 8 bits and icmp code is in the least
1312 * significant 8 bits of port field. Although Libreswan does
1313 * not have any configuration options for
1314 * icmp type/code values, it is possible to specify icmp type
1315 * and code using protoport option. For example,
1316 * icmp echo request (type 8/code 0) needs to be encoded as
1317 * 0x0800 in the port field and can be specified
1318 * as left/rightprotoport=icmp/2048. Now with XFRM,
1319 * icmp type and code need to be passed as source and
1320 * destination ports, respectively. Therefore, this code
1321 * extracts upper 8 bits and lower 8 bits and puts
1322 * into source and destination ports before passing to XFRM.
1323 */
1324 if (IPPROTO_ICMPIPPROTO_ICMP == sa->transport_proto ||
1325 IPPROTO_ICMPV658 == sa->transport_proto) {
1326 uint16_t icmp_type;
1327 uint16_t icmp_code;
1328
1329 icmp_type = ntohs(req.p.sel.sport) >> 8;
1330 icmp_code = ntohs(req.p.sel.sport) & 0xFF;
1331
1332 req.p.sel.sport = htons(icmp_type);
1333 req.p.sel.dport = htons(icmp_code);
1334 }
1335
1336 req.p.sel.sport_mask = req.p.sel.sport == 0 ? 0 : ~0;
1337 req.p.sel.dport_mask = req.p.sel.dport == 0 ? 0 : ~0;
1338 req.p.sel.proto = sa->transport_proto;
1339 req.p.sel.family = selector_type(sa->src.client)->af;
1340 }
1341
1342 req.p.reqid = sa->reqid;
1343 dbg("%s() adding IPsec SA with reqid %d", __func__, sa->reqid){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s() adding IPsec SA with reqid %d", __func__
, sa->reqid); } }
;
1344
1345 /* TODO expose limits to kernel_sa via config */
1346 req.p.lft.soft_byte_limit = XFRM_INF(~(__u64)0);
1347 req.p.lft.soft_packet_limit = XFRM_INF(~(__u64)0);
1348 req.p.lft.hard_byte_limit = XFRM_INF(~(__u64)0);
1349 req.p.lft.hard_packet_limit = XFRM_INF(~(__u64)0);
1350
1351 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.p)))( ((((sizeof(req.p)) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
1352
1353 attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
1354
1355 /*
1356 * The Linux IPv4 AH stack aligns the AH header on a 64 bit boundary
1357 * (like in IPv6). This is not RFC compliant (see RFC4302, Section
1358 * 3.3.3.2.1), it should be aligned on 32 bits.
1359 *
1360 * For most of the authentication algorithms, the ICV size is 96 bits.
1361 * The AH header alignment on 32 or 64 bits gives the same results.
1362 *
1363 * However for SHA-256-128 for instance, the wrong 64 bit alignment results
1364 * in adding useless padding in IPv4 AH, which is forbidden by the RFC.
1365 *
1366 * To avoid breaking backward compatibility, we use a new flag
1367 * (XFRM_STATE_ALIGN4) do change original behavior.
1368 */
1369 if (sa->esatype == ET_AH && addrtypeof(sa->src.address) == AF_INET2) {
1370 dbg("xfrm: aligning IPv4 AH to 32bits as per RFC-4302, Section 3.3.3.2.1"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: aligning IPv4 AH to 32bits as per RFC-4302, Section 3.3.3.2.1"
); } }
;
1371 req.p.flags |= XFRM_STATE_ALIGN464;
1372 }
1373
1374 if (sa->esatype != ET_IPCOMP) {
1375 if (sa->esn) {
1376 dbg("xfrm: enabling ESN"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: enabling ESN"); } }
;
1377 req.p.flags |= XFRM_STATE_ESN128;
1378 }
1379 if (sa->decap_dscp) {
1380 dbg("xfrm: enabling Decap DSCP"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: enabling Decap DSCP"); } }
;
1381 req.p.flags |= XFRM_STATE_DECAP_DSCP2;
1382 }
1383 if (sa->nopmtudisc) {
1384 dbg("xfrm: disabling Path MTU Discovery"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: disabling Path MTU Discovery"); } }
;
1385 req.p.flags |= XFRM_STATE_NOPMTUDISC4;
1386 }
1387
1388 if (sa->replay_window <= 32 && !sa->esn) {
1389 /* this only works up to 32, for > 32 and for ESN, we need struct xfrm_replay_state_esn */
1390 req.p.replay_window = sa->replay_window;
1391 dbg("xfrm: setting IPsec SA replay-window to %d using old-style req",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: setting IPsec SA replay-window to %d using old-style req"
, req.p.replay_window); } }
1392 req.p.replay_window){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: setting IPsec SA replay-window to %d using old-style req"
, req.p.replay_window); } }
;
1393 } else {
1394 uint32_t bmp_size = BYTES_FOR_BITS(sa->replay_window +(((sa->replay_window + (((sizeof(uint32_t) * 8) - 1) - (((
sa->replay_window) + (sizeof(uint32_t) * 8) - 1) % (sizeof
(uint32_t) * 8)))) + 8 - 1) / 8)
1395 pad_up(sa->replay_window, sizeof(uint32_t) * BITS_PER_BYTE) )(((sa->replay_window + (((sizeof(uint32_t) * 8) - 1) - (((
sa->replay_window) + (sizeof(uint32_t) * 8) - 1) % (sizeof
(uint32_t) * 8)))) + 8 - 1) / 8)
;
1396 /* this is where we could fill in sequence numbers for this SA */
1397 struct xfrm_replay_state_esn xre = {
1398 /* replay_window must be multiple of 8 */
1399 .replay_window = sa->replay_window,
1400 .bmp_len = bmp_size / sizeof(uint32_t),
1401 };
1402 dbg("xfrm: setting IPsec SA replay-window to %" PRIu32 " using xfrm_replay_state_esn",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: setting IPsec SA replay-window to %" "u"
" using xfrm_replay_state_esn", xre.replay_window); } }
1403 xre.replay_window){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: setting IPsec SA replay-window to %" "u"
" using xfrm_replay_state_esn", xre.replay_window); } }
;
1404
1405 attr->rta_type = XFRMA_REPLAY_ESN_VAL;
1406 attr->rta_len = RTA_LENGTH(sizeof(xre) + bmp_size)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(xre) + bmp_size))
;
1407 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &xre, sizeof(xre));
1408 req.n.nlmsg_len += attr->rta_len;
1409 attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
1410 }
1411 }
1412
1413 if (sa->authkeylen != 0) {
1414 const char *name = sa->integ->integ_netlink_xfrm_name;
1415 if (name == NULL((void*)0)) {
1416 llog(RC_LOG_SERIOUS, logger,
1417 "XFRM: unknown authentication algorithm: %s",
1418 sa->integ->common.fqn);
1419 return false0;
1420 }
1421
1422 /*
1423 * According to RFC-4868 the hash should be nnn/2, so
1424 * 128 bits for SHA256 and 256 for SHA512. The XFRM
1425 * kernel uses a default of 96, which was the value in
1426 * an earlier draft. The kernel then introduced a new struct
1427 * xfrm_algo_auth to replace struct xfrm_algo to deal with
1428 * this.
1429 */
1430
1431 struct xfrm_algo_auth algo = {
1432 .alg_key_len = sa->integ->integ_keymat_size * BITS_PER_BYTE8,
1433 .alg_trunc_len = sa->integ->integ_output_size * BITS_PER_BYTE8,
1434 };
1435
1436 attr->rta_type = XFRMA_ALG_AUTH_TRUNC;
1437 attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->authkeylen)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(algo) + sa->authkeylen))
;
1438
1439 fill_and_terminate(algo.alg_name, name, sizeof(algo.alg_name)){ strncpy((algo.alg_name), (name), (sizeof(algo.alg_name))-1)
; (algo.alg_name)[(sizeof(algo.alg_name))-1] = '\0'; }
;
1440 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &algo, sizeof(algo));
1441 memcpy((char *)RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
+ sizeof(algo),
1442 sa->authkey, sa->authkeylen);
1443
1444 req.n.nlmsg_len += attr->rta_len;
1445 attr = (struct rtattr *)((char *)attr + attr->rta_len);
1446 }
1447
1448 /*
1449 * ??? why does IPCOMP trump aead and ESP?
1450 * Shouldn't all be bundled?
1451 */
1452 if (sa->esatype == ET_IPCOMP) {
1453
1454 /* Compress Algs */
1455 static const char *calg_list[] = {
1456 [IPCOMP_DEFLATE] = "deflate",
1457 [IPCOMP_LZS] = "lzs",
1458 [IPCOMP_LZJH] = "lzjh",
1459 };
1460
1461 const char *calg_name = (sa->ipcomp_algo >= elemsof(calg_list)(sizeof(calg_list) / sizeof(*(calg_list))) ? NULL((void*)0) :
1462 calg_list[sa->ipcomp_algo]);
1463 if (calg_name == NULL((void*)0)) {
1464 llog(RC_LOG_SERIOUS, logger,
1465 "unsupported compression algorithm: %s",
1466 enum_name(&ipsec_ipcomp_algo_names, sa->ipcomp_algo));
1467 return false0;
1468 }
1469
1470 struct xfrm_algo algo;
1471 fill_and_terminate(algo.alg_name, calg_name, sizeof(algo.alg_name)){ strncpy((algo.alg_name), (calg_name), (sizeof(algo.alg_name
))-1); (algo.alg_name)[(sizeof(algo.alg_name))-1] = '\0'; }
;
1472 algo.alg_key_len = 0;
1473
1474 /* append */
1475 attr->rta_type = XFRMA_ALG_COMP;
1476 attr->rta_len = RTA_LENGTH(sizeof(algo))(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(algo)))
;
1477 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &algo, sizeof(algo));
1478 req.n.nlmsg_len += attr->rta_len;
1479 attr = (struct rtattr *)((char *)attr + attr->rta_len);
1480
1481 } else if (sa->esatype == ET_ESP) {
1482 const char *name = sa->encrypt->encrypt_netlink_xfrm_name;
1483
1484 if (name == NULL((void*)0)) {
1485 llog(RC_LOG_SERIOUS, logger,
1486 "unknown encryption algorithm: %s",
1487 sa->encrypt->common.fqn);
1488 return false0;
1489 }
1490
1491 if (encrypt_desc_is_aead(sa->encrypt)) {
1492 struct xfrm_algo_aead algo;
1493
1494 fill_and_terminate(algo.alg_name, name,{ strncpy((algo.alg_name), (name), (sizeof(algo.alg_name))-1)
; (algo.alg_name)[(sizeof(algo.alg_name))-1] = '\0'; }
1495 sizeof(algo.alg_name)){ strncpy((algo.alg_name), (name), (sizeof(algo.alg_name))-1)
; (algo.alg_name)[(sizeof(algo.alg_name))-1] = '\0'; }
;
1496 algo.alg_key_len = sa->enckeylen * BITS_PER_BYTE8;
1497 algo.alg_icv_len = sa->encrypt->aead_tag_size * BITS_PER_BYTE8;
1498
1499 attr->rta_type = XFRMA_ALG_AEAD;
1500 attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->enckeylen)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(algo) + sa->enckeylen))
;
1501
1502 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &algo, sizeof(algo));
1503 memcpy((char *)RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
+ sizeof(algo),
1504 sa->enckey, sa->enckeylen);
1505
1506 req.n.nlmsg_len += attr->rta_len;
1507 attr = (struct rtattr *)((char *)attr + attr->rta_len);
1508
1509 } else {
1510 struct xfrm_algo algo;
1511
1512 fill_and_terminate(algo.alg_name, name,{ strncpy((algo.alg_name), (name), (sizeof(algo.alg_name))-1)
; (algo.alg_name)[(sizeof(algo.alg_name))-1] = '\0'; }
1513 sizeof(algo.alg_name)){ strncpy((algo.alg_name), (name), (sizeof(algo.alg_name))-1)
; (algo.alg_name)[(sizeof(algo.alg_name))-1] = '\0'; }
;
1514 algo.alg_key_len = sa->enckeylen * BITS_PER_BYTE8;
1515
1516 attr->rta_type = XFRMA_ALG_CRYPT;
1517 attr->rta_len = RTA_LENGTH(sizeof(algo) + sa->enckeylen)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(algo) + sa->enckeylen))
;
1518
1519 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &algo, sizeof(algo));
1520 memcpy((char *)RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
+ sizeof(algo),
1521 sa->enckey,
1522 sa->enckeylen);
1523
1524 req.n.nlmsg_len += attr->rta_len;
1525 attr = (struct rtattr *)((char *)attr + attr->rta_len);
1526
1527 /* Traffic Flow Confidentiality is only for ESP tunnel mode */
1528 if (sa->tfcpad != 0 && sa->tunnel && sa->level == 0) {
1529 dbg("xfrm: setting TFC to %" PRIu32 " (up to PMTU)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: setting TFC to %" "u" " (up to PMTU)", sa
->tfcpad); } }
1530 sa->tfcpad){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: setting TFC to %" "u" " (up to PMTU)", sa
->tfcpad); } }
;
1531
1532 attr->rta_type = XFRMA_TFCPAD;
1533 attr->rta_len = RTA_LENGTH(sizeof(sa->tfcpad))(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(sa->tfcpad)))
;
1534 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &sa->tfcpad, sizeof(sa->tfcpad));
1535 req.n.nlmsg_len += attr->rta_len;
1536 attr = (struct rtattr *)((char *)attr + attr->rta_len);
1537
1538 }
1539 }
1540 }
1541
1542 if (sa->encap_type != NULL((void*)0)) {
1543 dbg("adding xfrm-encap-tmpl when adding sa encap_type="PRI_IP_ENCAP" sport=%d dport=%d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("adding xfrm-encap-tmpl when adding sa encap_type="
"%u(%s)"" sport=%d dport=%d", (sa->encap_type) == ((void*)
0) ? 0 : (sa->encap_type)->encap_type, (sa->encap_type
) == ((void*)0) ? "none" : (sa->encap_type)->name, sa->
src.encap_port, sa->dst.encap_port); } }
1544 pri_ip_encap(sa->encap_type),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("adding xfrm-encap-tmpl when adding sa encap_type="
"%u(%s)"" sport=%d dport=%d", (sa->encap_type) == ((void*)
0) ? 0 : (sa->encap_type)->encap_type, (sa->encap_type
) == ((void*)0) ? "none" : (sa->encap_type)->name, sa->
src.encap_port, sa->dst.encap_port); } }
1545 sa->src.encap_port, sa->dst.encap_port){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("adding xfrm-encap-tmpl when adding sa encap_type="
"%u(%s)"" sport=%d dport=%d", (sa->encap_type) == ((void*)
0) ? 0 : (sa->encap_type)->encap_type, (sa->encap_type
) == ((void*)0) ? "none" : (sa->encap_type)->name, sa->
src.encap_port, sa->dst.encap_port); } }
;
1546 struct xfrm_encap_tmpl natt;
1547
1548 natt.encap_type = sa->encap_type->encap_type;
1549 natt.encap_sport = ntohs(sa->src.encap_port);
1550 natt.encap_dport = ntohs(sa->dst.encap_port);
1551 zero(&natt.encap_oa)memset((&natt.encap_oa), '\0', sizeof(*(&natt.encap_oa
)))
;
1552
1553 attr->rta_type = XFRMA_ENCAP;
1554 attr->rta_len = RTA_LENGTH(sizeof(natt))(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(natt)))
;
1555
1556 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &natt, sizeof(natt));
1557
1558 req.n.nlmsg_len += attr->rta_len;
1559 attr = (struct rtattr *)((char *)attr + attr->rta_len);
1560 }
1561
1562#ifdef USE_XFRM_INTERFACE1
1563 if (sa->xfrm_if_id != 0) {
1564 dbg("%s xfrm: XFRMA_IF_ID %" PRIu32 " req.n.nlmsg_type=%" PRIu32,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s xfrm: XFRMA_IF_ID %" "u" " req.n.nlmsg_type=%"
"u", __func__, sa->xfrm_if_id, req.n.nlmsg_type); } }
1565 __func__, sa->xfrm_if_id, req.n.nlmsg_type){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s xfrm: XFRMA_IF_ID %" "u" " req.n.nlmsg_type=%"
"u", __func__, sa->xfrm_if_id, req.n.nlmsg_type); } }
;
1566 nl_addattr32(&req.n, sizeof(req.data), XFRMA_IF_ID, sa->xfrm_if_id);
1567 if (sa->mark_set.val != 0 || sa->mark_set.mask != 0) {
1568 /* manually configured mark-out=mark/mask */
1569 nl_addattr32(&req.n, sizeof(req.data), XFRMA_SET_MARK, sa->mark_set.val);
1570 nl_addattr32(&req.n, sizeof(req.data), XFRMA_SET_MARK_MASK, sa->mark_set.mask);
1571 } else {
1572 /* XFRMA_SET_MARK = XFRMA_IF_ID */
1573 nl_addattr32(&req.n, sizeof(req.data), XFRMA_SET_MARK, sa->xfrm_if_id);
1574 }
1575 attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
1576 }
1577#endif
1578
1579 if (sa->nic_offload_dev) {
1580 struct xfrm_user_offload xuo = {
1581 .flags = (sa->inbound ? XFRM_OFFLOAD_INBOUND2 : 0) |
1582 (addrtypeof(sa->src.address) == AF_INET610 ? XFRM_OFFLOAD_IPV61 : 0),
1583 .ifindex = if_nametoindex(sa->nic_offload_dev),
1584 };
1585
1586 attr->rta_type = XFRMA_OFFLOAD_DEV;
1587 attr->rta_len = RTA_LENGTH(sizeof(xuo))(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (sizeof
(xuo)))
;
1588
1589 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &xuo, sizeof(xuo));
1590
1591 req.n.nlmsg_len += attr->rta_len;
1592 attr = (struct rtattr *)((char *)attr + attr->rta_len);
1593 dbg("xfrm: esp-hw-offload set via interface %s for IPsec SA", sa->nic_offload_dev){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: esp-hw-offload set via interface %s for IPsec SA"
, sa->nic_offload_dev); } }
;
1594 } else {
1595 dbg("xfrm: esp-hw-offload not set for IPsec SA"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: esp-hw-offload not set for IPsec SA"); }
}
;
1596 }
1597
1598 if (sa->sec_label.len != 0) {
1599 struct xfrm_user_sec_ctx xuctx;
1600
1601 xuctx.len = sizeof(struct xfrm_user_sec_ctx) + sa->sec_label.len;
1602 xuctx.exttype = XFRMA_SEC_CTX;
1603 xuctx.ctx_alg = XFRM_SC_ALG_SELINUX1; /* 1 */
1604 xuctx.ctx_doi = XFRM_SC_DOI_LSM1; /* 1 */
1605 xuctx.ctx_len = sa->sec_label.len;
1606
1607 attr->rta_type = XFRMA_SEC_CTX;
1608 attr->rta_len = RTA_LENGTH(xuctx.len)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (xuctx.
len))
;
1609
1610 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &xuctx, sizeof(xuctx));
1611 memcpy((char *)RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
+ sizeof(xuctx),
1612 sa->sec_label.ptr, sa->sec_label.len);
1613
1614 req.n.nlmsg_len += attr->rta_len;
1615
1616 /* attr not subsequently used */
1617 attr = (struct rtattr *)((char *)attr + attr->rta_len);
Value stored to 'attr' is never read
1618 }
1619
1620 int recv_errno;
1621 ret = send_netlink_msg(&req.n, NLMSG_NOOP0x1, NULL((void*)0),
1622 "Add SA", sa->story,
1623 &recv_errno, logger);
1624 if (!ret && recv_errno == ESRCH3 &&
1625 req.n.nlmsg_type == XFRM_MSG_UPDSAXFRM_MSG_UPDSA) {
1626 llog(RC_LOG_SERIOUS, logger,
1627 "Warning: kernel expired our reserved IPsec SA SPI - negotiation took too long? Try increasing /proc/sys/net/core/xfrm_acq_expires");
1628 }
1629 return ret;
1630}
1631
1632/*
1633 * netlink_del_sa - Delete an SA from the Kernel
1634 *
1635 * @param sa Kernel SA to be deleted
1636 * @return bool True if successful
1637 */
1638static bool_Bool netlink_del_sa(const struct kernel_sa *sa,
1639 struct logger *logger)
1640{
1641 struct {
1642 struct nlmsghdr n;
1643 struct xfrm_usersa_id id;
1644 char data[MAX_NETLINK_DATA_SIZE8192];
1645 } req;
1646
1647 zero(&req)memset((&req), '\0', sizeof(*(&req)));
1648 req.n.nlmsg_flags = NLM_F_REQUEST0x01 | NLM_F_ACK0x04;
1649 req.n.nlmsg_type = XFRM_MSG_DELSAXFRM_MSG_DELSA;
1650
1651 req.id.daddr = xfrm_from_address(sa->dst.address);
1652
1653 req.id.spi = sa->spi;
1654 req.id.family = addrtypeof(sa->src.address);
1655 req.id.proto = sa->proto->ipproto;
1656
1657 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)))( ((((sizeof(req.id)) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
1658
1659 dbg("XFRM: deleting IPsec SA with reqid %d", sa->reqid){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("XFRM: deleting IPsec SA with reqid %d", sa->
reqid); } }
;
1660
1661 int recv_errno;
1662 return send_netlink_msg(&req.n, NLMSG_NOOP0x1, NULL((void*)0),
1663 "Del SA", sa->story,
1664 &recv_errno, logger);
1665}
1666
1667/*
1668 * Create ip_address out of xfrm_address_t.
1669 *
1670 * @param family
1671 * @param src xfrm formatted IP address
1672 * @param dst ip_address formatted destination
1673 * @return err_t NULL if okay, otherwise an error
1674 */
1675static ip_address address_from_xfrm(const struct ip_info *afi,
1676 const xfrm_address_t *xaddr)
1677{
1678 /* .len == ipv6 size */
1679 shunk_t x = THING_AS_SHUNK(*xaddr)shunk2(&(*xaddr), sizeof(*xaddr));
1680
1681 ip_address addr = afi->address.any; /* "zero" it & set type */
1682 chunk_t a = address_as_chunk(&addr);
1683
1684 /* a = x */
1685 passert(a.len <= x.len)({ _Bool assertion__ = a.len <= x.len; if (!assertion__) {
where_t here = ({ static const struct where here = { .func =
__func__, .file = "programs/pluto/kernel_xfrm.c", .line = 1685
, }; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "a.len <= x.len"); } (
void) 1; })
;
1686 memcpy(a.ptr, x.ptr, a.len);
1687
1688 return addr;
1689}
1690
1691/*
1692 * Create the client's ip_endpoint from xfrm_address_t:NPORT.
1693 */
1694
1695static ip_endpoint endpoint_from_xfrm(const struct ip_info *afi,
1696 const ip_protocol *protocol,
1697 const xfrm_address_t *src,
1698 uint16_t nport)
1699{
1700 ip_address address = address_from_xfrm(afi, src);
1701 ip_port port = ip_nport(nport);
1702 return endpoint_from_address_protocol_port(address, protocol, port);
1703}
1704
1705static void netlink_acquire(struct nlmsghdr *n, struct logger *logger)
1706{
1707 struct xfrm_user_acquire *acquire;
1708 shunk_t sec_label = NULL_HUNK{ .ptr = ((void*)0), .len = 0, };
1709
1710 dbg("xfrm netlink msg len %zu", (size_t) n->nlmsg_len){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm netlink msg len %zu", (size_t) n->nlmsg_len
); } }
;
1711
1712 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*acquire))((sizeof(*acquire)) + ((int) ( ((sizeof(struct nlmsghdr))+4U -
1) & ~(4U -1) )))
) {
1713 llog(RC_LOG, logger,
1714 "netlink_acquire got message with length %zu < %zu bytes; ignore message",
1715 (size_t) n->nlmsg_len,
1716 sizeof(*acquire));
1717 return;
1718 }
1719
1720 /*
1721 * WARNING: netlink only guarantees 32-bit alignment.
1722 * See NLMSG_ALIGNTO in the kernel's include/uapi/linux/netlink.h.
1723 * BUT some fields in struct xfrm_user_acquire are 64-bit and so access
1724 * may be improperly aligned. This will fail on a few strict
1725 * architectures (it does break C rules).
1726 *
1727 * WARNING: this code's understanding to the XFRM netlink
1728 * messages is from programs/pluto/linux26/xfrm.h.
1729 * There is no guarantee that this matches the kernel's
1730 * understanding.
1731 *
1732 * Many things are defined to be int or unsigned int.
1733 * This isn't safe when the kernel and userland may
1734 * be compiled with different models.
1735 */
1736 acquire = NLMSG_DATA(n)((void *)(((char *)n) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))
; /* insufficiently aligned */
1737
1738 const struct ip_info *afi = aftoinfo(acquire->policy.sel.family);
1739 if (afi == NULL((void*)0)) {
1740 llog(RC_LOG, logger,
1741 "XFRM_MSG_ACQUIRE message from kernel malformed: family %u unknown",
1742 acquire->policy.sel.family);
1743 return;
1744 }
1745 const ip_protocol *protocol = protocol_by_ipproto(acquire->sel.proto);
1746 if (protocol == NULL((void*)0)) {
1747 llog(RC_LOG, logger,
1748 "XFRM_MSG_ACQUIRE message from kernel malformed: protocol %u unknown",
1749 acquire->policy.sel.proto);
1750 return;
1751 }
1752 ip_endpoint local = endpoint_from_xfrm(afi, protocol,
1753 &acquire->sel.saddr,
1754 acquire->sel.sport);
1755 ip_endpoint remote = endpoint_from_xfrm(afi, protocol,
1756 &acquire->sel.daddr,
1757 acquire->sel.dport);
1758
1759 /*
1760 * Run through rtattributes looking for XFRMA_SEC_CTX
1761 * Instead, it should loop through all (known rtattributes
1762 * and use/log them.
1763 */
1764 struct rtattr *attr = (struct rtattr *)
1765 ((char*) NLMSG_DATA(n)((void *)(((char *)n) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))
+
1766 NLMSG_ALIGN(sizeof(struct xfrm_user_acquire))( ((sizeof(struct xfrm_user_acquire))+4U -1) & ~(4U -1) ));
1767 size_t remaining = n->nlmsg_len -
1768 NLMSG_SPACE(sizeof(struct xfrm_user_acquire))( ((((sizeof(struct xfrm_user_acquire)) + ((int) ( ((sizeof(struct
nlmsghdr))+4U -1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
1769
1770 while (remaining > 0) {
1771 dbg("xfrm acquire rtattribute type %u ...", attr->rta_type){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm acquire rtattribute type %u ...", attr->
rta_type); } }
;
1772 switch (attr->rta_type) {
1773 case XFRMA_TMPL:
1774 {
1775 struct xfrm_user_tmpl* tmpl = (struct xfrm_user_tmpl *) RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
;
1776 dbg("... xfrm template attribute with reqid:%d, spi:%d, proto:%d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("... xfrm template attribute with reqid:%d, spi:%d, proto:%d"
, tmpl->reqid, tmpl->id.spi, tmpl->id.proto); } }
1777 tmpl->reqid, tmpl->id.spi, tmpl->id.proto){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("... xfrm template attribute with reqid:%d, spi:%d, proto:%d"
, tmpl->reqid, tmpl->id.spi, tmpl->id.proto); } }
;
1778 break;
1779 }
1780 case XFRMA_POLICY_TYPE:
1781 /* discard */
1782 dbg("... xfrm policy type ignored"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("... xfrm policy type ignored"); } }
;
1783 break;
1784 case XFRMA_SEC_CTX:
1785 {
1786 struct xfrm_user_sec_ctx *xuctx = (struct xfrm_user_sec_ctx *) RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
;
1787 /* length of text of label */
1788 size_t len = xuctx->ctx_len;
1789
1790 dbg("... xfrm xuctx: exttype=%d, len=%d, ctx_doi=%d, ctx_alg=%d, ctx_len=%zu",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("... xfrm xuctx: exttype=%d, len=%d, ctx_doi=%d, ctx_alg=%d, ctx_len=%zu"
, xuctx->exttype, xuctx->len, xuctx->ctx_doi, xuctx->
ctx_alg, len); } }
1791 xuctx->exttype, xuctx->len,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("... xfrm xuctx: exttype=%d, len=%d, ctx_doi=%d, ctx_alg=%d, ctx_len=%zu"
, xuctx->exttype, xuctx->len, xuctx->ctx_doi, xuctx->
ctx_alg, len); } }
1792 xuctx->ctx_doi, xuctx->ctx_alg,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("... xfrm xuctx: exttype=%d, len=%d, ctx_doi=%d, ctx_alg=%d, ctx_len=%zu"
, xuctx->exttype, xuctx->len, xuctx->ctx_doi, xuctx->
ctx_alg, len); } }
1793 len){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("... xfrm xuctx: exttype=%d, len=%d, ctx_doi=%d, ctx_alg=%d, ctx_len=%zu"
, xuctx->exttype, xuctx->len, xuctx->ctx_doi, xuctx->
ctx_alg, len); } }
;
1794
1795 if (xuctx->ctx_doi != XFRM_SC_DOI_LSM1) {
1796 llog(RC_LOG, logger,
1797 "Acquire message for unknown sec_label DOI %d; ignoring Acquire message",
1798 xuctx->ctx_doi);
1799 return;
1800 }
1801 if (xuctx->ctx_alg != XFRM_SC_ALG_SELINUX1) {
1802 llog(RC_LOG, logger,
1803 "Acquire message for unknown sec_label LSM %d; ignoring Acquire message",
1804 xuctx->ctx_alg);
1805 return;
1806 }
1807
1808 /*
1809 * note: xuctx + 1 is tricky:
1810 * first byte after header
1811 */
1812 sec_label.ptr = (uint8_t *)(xuctx + 1);
1813 sec_label.len = len;
1814
1815 err_t ugh = vet_seclabel(sec_label);
1816
1817 if (ugh != NULL((void*)0)) {
1818 llog(RC_LOG, logger,
1819 "received bad %s; ignoring Acquire message", ugh);
1820 return;
1821 }
1822
1823 dbg("xfrm: xuctx security context value: %.*s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: xuctx security context value: %.*s", (int
)len, (const char *) (xuctx + 1)); } }
1824 (int)len,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: xuctx security context value: %.*s", (int
)len, (const char *) (xuctx + 1)); } }
1825 (const char *) (xuctx + 1)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm: xuctx security context value: %.*s", (int
)len, (const char *) (xuctx + 1)); } }
;
1826 break;
1827 }
1828 default:
1829 dbg("... ignoring unknown xfrm acquire payload type %u",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("... ignoring unknown xfrm acquire payload type %u"
, attr->rta_type); } }
1830 attr->rta_type){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("... ignoring unknown xfrm acquire payload type %u"
, attr->rta_type); } }
;
1831 break;
1832 }
1833 /* updates remaining too */
1834 attr = RTA_NEXT(attr, remaining)((remaining) -= ( (((attr)->rta_len)+4U -1) & ~(4U -1)
), (struct rtattr*)(((char*)(attr)) + ( (((attr)->rta_len
)+4U -1) & ~(4U -1) )))
;
1835 }
1836 initiate_ondemand(&local, &remote,
1837 /*by_acquire*/true1,
1838 /*background?*/true1/*no whack so doesn't matter*/,
1839 sec_label, logger);
1840}
1841
1842static void netlink_shunt_expire(struct xfrm_userpolicy_info *pol,
1843 struct logger *logger)
1844{
1845 const xfrm_address_t *srcx = &pol->sel.saddr;
1846 const xfrm_address_t *dstx = &pol->sel.daddr;
1847 unsigned transport_proto = pol->sel.proto;
1848
1849 const struct ip_info *afi = aftoinfo(pol->sel.family);
1850 if (afi == NULL((void*)0)) {
1851 llog(RC_LOG, logger,
1852 "XFRM_MSG_POLEXPIRE message from kernel malformed: address family %u unknown",
1853 pol->sel.family);
1854 return;
1855 }
1856
1857 ip_address src = address_from_xfrm(afi, srcx);
1858 ip_address dst = address_from_xfrm(afi, dstx);
1859
1860 if (delete_bare_shunt(&src, &dst,
1861 transport_proto, SPI_HOLD /* why spi to use? */,
1862 /*skip_xfrm_policy_delete?*/false0,
1863 "delete expired bare shunt", logger)) {
1864 dbg("netlink_shunt_expire() called delete_bare_shunt() with success"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("netlink_shunt_expire() called delete_bare_shunt() with success"
); } }
;
1865 } else {
1866 llog(RC_LOG, logger,
1867 "netlink_shunt_expire() called delete_bare_shunt() which failed!");
1868 }
1869}
1870
1871static void process_addr_chage(struct nlmsghdr *n, struct logger *logger)
1872{
1873 struct ifaddrmsg *nl_msg = NLMSG_DATA(n)((void *)(((char *)n) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))
;
1874 struct rtattr *rta = IFLA_RTA(nl_msg)((struct rtattr*)(((char*)(nl_msg)) + ( ((sizeof(struct ifinfomsg
))+4U -1) & ~(4U -1) )))
;
1875 size_t msg_size = IFA_PAYLOAD (n)((n)->nlmsg_len - ( (((((sizeof(struct ifaddrmsg))) + ((int
) ( ((sizeof(struct nlmsghdr))+4U -1) & ~(4U -1) ))))+4U -
1) & ~(4U -1) ))
;
1876 ip_address ip;
1877
1878 dbg("xfrm netlink address change %s msg len %zu",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm netlink address change %s msg len %zu", sparse_val_show
(rtm_type_names, n->nlmsg_type), (size_t) n->nlmsg_len)
; } }
1879 sparse_val_show(rtm_type_names, n->nlmsg_type),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm netlink address change %s msg len %zu", sparse_val_show
(rtm_type_names, n->nlmsg_type), (size_t) n->nlmsg_len)
; } }
1880 (size_t) n->nlmsg_len){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm netlink address change %s msg len %zu", sparse_val_show
(rtm_type_names, n->nlmsg_type), (size_t) n->nlmsg_len)
; } }
;
1881
1882 while (RTA_OK(rta, msg_size)((msg_size) >= (int)sizeof(struct rtattr) && (rta)
->rta_len >= sizeof(struct rtattr) && (rta)->
rta_len <= (msg_size))
) {
1883 err_t ugh;
1884
1885 switch (rta->rta_type) {
1886 case IFA_LOCAL:
1887 ugh = data_to_address(RTA_DATA(rta)((void*)(((char*)(rta)) + (( ((sizeof(struct rtattr))+4U -1) &
~(4U -1) ) + (0))))
, RTA_PAYLOAD(rta)((int)((rta)->rta_len) - (( ((sizeof(struct rtattr))+4U -1
) & ~(4U -1) ) + (0)))
/*size*/,
1888 aftoinfo(nl_msg->ifa_family), &ip);
1889 if (ugh != NULL((void*)0)) {
1890 llog(RC_LOG, logger,
1891 "ERROR IFA_LOCAL invalid %s", ugh);
1892 } else {
1893 if (n->nlmsg_type == RTM_DELADDRRTM_DELADDR)
1894 record_deladdr(&ip, "IFA_LOCAL");
1895 else if (n->nlmsg_type == RTM_NEWADDRRTM_NEWADDR)
1896 record_newaddr(&ip, "IFA_LOCAL");
1897 }
1898 break;
1899
1900 case IFA_ADDRESS:
1901 ugh = data_to_address(RTA_DATA(rta)((void*)(((char*)(rta)) + (( ((sizeof(struct rtattr))+4U -1) &
~(4U -1) ) + (0))))
, RTA_PAYLOAD(rta)((int)((rta)->rta_len) - (( ((sizeof(struct rtattr))+4U -1
) & ~(4U -1) ) + (0)))
/*size*/,
1902 aftoinfo(nl_msg->ifa_family), &ip);
1903 if (ugh != NULL((void*)0)) {
1904 llog(RC_LOG, logger,
1905 "ERROR IFA_ADDRESS invalid %s", ugh);
1906 } else {
1907 address_buf ip_str;
1908 dbg("XFRM IFA_ADDRESS %s IFA_ADDRESS is this PPP?",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("XFRM IFA_ADDRESS %s IFA_ADDRESS is this PPP?"
, str_address(&ip, &ip_str)); } }
1909 str_address(&ip, &ip_str)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("XFRM IFA_ADDRESS %s IFA_ADDRESS is this PPP?"
, str_address(&ip, &ip_str)); } }
;
1910 }
1911 break;
1912
1913 default:
1914 dbg("IKEv2 received address %s type %u",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("IKEv2 received address %s type %u", sparse_val_show
(rtm_type_names, n->nlmsg_type), rta->rta_type); } }
1915 sparse_val_show(rtm_type_names, n->nlmsg_type),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("IKEv2 received address %s type %u", sparse_val_show
(rtm_type_names, n->nlmsg_type), rta->rta_type); } }
1916 rta->rta_type){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("IKEv2 received address %s type %u", sparse_val_show
(rtm_type_names, n->nlmsg_type), rta->rta_type); } }
;
1917 break;
1918 }
1919
1920 rta = RTA_NEXT(rta, msg_size)((msg_size) -= ( (((rta)->rta_len)+4U -1) & ~(4U -1) )
, (struct rtattr*)(((char*)(rta)) + ( (((rta)->rta_len)+4U
-1) & ~(4U -1) )))
;
1921 }
1922}
1923
1924static void netlink_policy_expire(struct nlmsghdr *n, struct logger *logger)
1925{
1926 struct xfrm_user_polexpire *upe;
1927 ip_address src, dst;
1928
1929 struct {
1930 struct nlmsghdr n;
1931 struct xfrm_userpolicy_id id;
1932 } req;
1933 struct nlm_resp rsp;
1934
1935 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*upe))((sizeof(*upe)) + ((int) ( ((sizeof(struct nlmsghdr))+4U -1) &
~(4U -1) )))
) {
1936 llog(RC_LOG, logger,
1937 "netlink_policy_expire got message with length %zu < %zu bytes; ignore message",
1938 (size_t) n->nlmsg_len,
1939 sizeof(*upe));
1940 return;
1941 }
1942
1943 upe = NLMSG_DATA(n)((void *)(((char *)n) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))
;
1944 xfrm2ip(&upe->pol.sel.saddr, &src, upe->pol.sel.family);
1945 xfrm2ip(&upe->pol.sel.daddr, &dst, upe->pol.sel.family);
1946 address_buf a;
1947 address_buf b;
1948 dbg("%s src %s/%u dst %s/%u dir %d index %d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s src %s/%u dst %s/%u dir %d index %d", __func__
, str_address(&src, &a), upe->pol.sel.prefixlen_s,
str_address(&dst, &b), upe->pol.sel.prefixlen_d, upe
->pol.dir, upe->pol.index); } }
1949 __func__,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s src %s/%u dst %s/%u dir %d index %d", __func__
, str_address(&src, &a), upe->pol.sel.prefixlen_s,
str_address(&dst, &b), upe->pol.sel.prefixlen_d, upe
->pol.dir, upe->pol.index); } }
1950 str_address(&src, &a), upe->pol.sel.prefixlen_s,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s src %s/%u dst %s/%u dir %d index %d", __func__
, str_address(&src, &a), upe->pol.sel.prefixlen_s,
str_address(&dst, &b), upe->pol.sel.prefixlen_d, upe
->pol.dir, upe->pol.index); } }
1951 str_address(&dst, &b), upe->pol.sel.prefixlen_d,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s src %s/%u dst %s/%u dir %d index %d", __func__
, str_address(&src, &a), upe->pol.sel.prefixlen_s,
str_address(&dst, &b), upe->pol.sel.prefixlen_d, upe
->pol.dir, upe->pol.index); } }
1952 upe->pol.dir, upe->pol.index){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s src %s/%u dst %s/%u dir %d index %d", __func__
, str_address(&src, &a), upe->pol.sel.prefixlen_s,
str_address(&dst, &b), upe->pol.sel.prefixlen_d, upe
->pol.dir, upe->pol.index); } }
;
1953
1954 req.id.dir = upe->pol.dir;
1955 req.id.index = upe->pol.index;
1956 req.n.nlmsg_flags = NLM_F_REQUEST0x01;
1957 req.n.nlmsg_type = XFRM_MSG_GETPOLICYXFRM_MSG_GETPOLICY;
1958 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)))( ((((sizeof(req.id)) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
1959
1960 int recv_errno;
1961 if (!send_netlink_msg(&req.n, XFRM_MSG_NEWPOLICYXFRM_MSG_NEWPOLICY, &rsp,
1962 "Get policy", "?",
1963 &recv_errno, logger)) {
1964 dbg("netlink_policy_expire: policy died on us: dir=%d, index=%d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("netlink_policy_expire: policy died on us: dir=%d, index=%d"
, req.id.dir, req.id.index); } }
1965 req.id.dir, req.id.index){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("netlink_policy_expire: policy died on us: dir=%d, index=%d"
, req.id.dir, req.id.index); } }
;
1966 } else if (rsp.n.nlmsg_len < NLMSG_LENGTH(sizeof(rsp.u.pol))((sizeof(rsp.u.pol)) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) )))
) {
1967 llog(RC_LOG, logger,
1968 "netlink_policy_expire: XFRM_MSG_GETPOLICY returned message with length %zu < %zu bytes; ignore message",
1969 (size_t) rsp.n.nlmsg_len,
1970 sizeof(rsp.u.pol));
1971 } else if (req.id.index != rsp.u.pol.index) {
1972 dbg("netlink_policy_expire: policy was replaced: dir=%d, oldindex=%d, newindex=%d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("netlink_policy_expire: policy was replaced: dir=%d, oldindex=%d, newindex=%d"
, req.id.dir, req.id.index, rsp.u.pol.index); } }
1973 req.id.dir, req.id.index, rsp.u.pol.index){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("netlink_policy_expire: policy was replaced: dir=%d, oldindex=%d, newindex=%d"
, req.id.dir, req.id.index, rsp.u.pol.index); } }
;
1974 } else if (upe->pol.curlft.add_time != rsp.u.pol.curlft.add_time) {
1975 dbg("netlink_policy_expire: policy was replaced and you have won the lottery: dir=%d, index=%d",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("netlink_policy_expire: policy was replaced and you have won the lottery: dir=%d, index=%d"
, req.id.dir, req.id.index); } }
1976 req.id.dir, req.id.index){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("netlink_policy_expire: policy was replaced and you have won the lottery: dir=%d, index=%d"
, req.id.dir, req.id.index); } }
;
1977 } else {
1978 switch (upe->pol.dir) {
1979 case XFRM_POLICY_OUT:
1980 netlink_shunt_expire(&rsp.u.pol, logger);
1981 break;
1982 }
1983 }
1984}
1985
1986static void netlink_expire(struct nlmsghdr *n, struct logger *logger)
1987{
1988 struct xfrm_user_expire *expire; /* not aligned */
1989
1990 dbg("xfrm netlink msg len %zu", (size_t) n->nlmsg_len){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("xfrm netlink msg len %zu", (size_t) n->nlmsg_len
); } }
;
1991 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(*expire))((sizeof(*expire)) + ((int) ( ((sizeof(struct nlmsghdr))+4U -
1) & ~(4U -1) )))
) {
1992 llog(RC_LOG, logger,
1993 "netlink_acquire got message with length %zu < %zu bytes; ignore message",
1994 (size_t) n->nlmsg_len,
1995 sizeof(*expire));
1996 return;
1997 }
1998
1999 /*
2000 * WARNING: netlink only guarantees 32-bit alignment.
2001 * See NLMSG_ALIGNTO in the kernel's include/uapi/linux/netlink.h.
2002 * BUT some fields in struct xfrm_user_acquire are 64-bit and so access
2003 * may be improperly aligned. This will fail on a few strict
2004 * architectures (it does break C rules).
2005 *
2006 * WARNING: this code's understanding to the XFRM netlink
2007 * messages is from programs/pluto/linux26/xfrm.h.
2008 * There is no guarantee that this matches the kernel's
2009 * understanding.
2010 *
2011 * Many things are defined to be int or unsigned int.
2012 * This isn't safe when the kernel and userland may
2013 * be compiled with different models.
2014 */
2015 expire = NLMSG_DATA(n)((void *)(((char *)n) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))
; /* insufficiently aligned */
2016
2017 const struct ip_info *afi = aftoinfo(expire->state.family);
2018 if (afi == NULL((void*)0)) {
2019 llog(RC_LOG, logger,
2020 "kernel: XFRM_MSG_EXPIRE message malformed: family %u unknown",
2021 expire->state.family);
2022 return;
2023 }
2024
2025 const ip_protocol *protocol = protocol_by_ipproto(expire->state.id.proto);
2026 if (protocol == NULL((void*)0)) {
2027 llog(RC_LOG, logger,
2028 "XFRM_MSG_EXPIRE message from kernel malformed: protocol %u unknown",
2029 expire->state.id.proto);
2030 return;
2031 }
2032
2033 ip_address daddr = address_from_xfrm(afi, &expire->state.id.daddr);
2034
2035 address_buf b;
2036 dbg("kernel: expire: protocol %s dest %s SPI "PRI_IPSEC_SPI,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: expire: protocol %s dest %s SPI ""%08x"
, protocol->name, str_address(&daddr, &b), htonl(expire
->state.id.spi)); } }
2037 protocol->name, str_address(&daddr, &b),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: expire: protocol %s dest %s SPI ""%08x"
, protocol->name, str_address(&daddr, &b), htonl(expire
->state.id.spi)); } }
2038 pri_ipsec_spi(expire->state.id.spi)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: expire: protocol %s dest %s SPI ""%08x"
, protocol->name, str_address(&daddr, &b), htonl(expire
->state.id.spi)); } }
;
2039}
2040
2041/* returns FALSE iff EAGAIN */
2042static bool_Bool netlink_get(int fd, struct logger *logger)
2043{
2044 struct nlm_resp rsp;
2045 struct sockaddr_nl addr;
2046 socklen_t alen = sizeof(addr);
2047 ssize_t r = recvfrom(fd, &rsp, sizeof(rsp), 0,
2048 (struct sockaddr *)&addr, &alen);
2049
2050 if (r < 0) {
2051 if (errno(*__errno_location ()) == EAGAIN11)
2052 return false0;
2053
2054 if (errno(*__errno_location ()) != EINTR4) {
2055 log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "kernel: recvfrom() failed in netlink_get: errno(%d): %s"
, (*__errno_location ()), strerror((*__errno_location ()))); }
2056 "kernel: recvfrom() failed in netlink_get: errno(%d): %s",{ int e_ = (*__errno_location ()); log_error(logger, e_, "kernel: recvfrom() failed in netlink_get: errno(%d): %s"
, (*__errno_location ()), strerror((*__errno_location ()))); }
2057 errno, strerror(errno)){ int e_ = (*__errno_location ()); log_error(logger, e_, "kernel: recvfrom() failed in netlink_get: errno(%d): %s"
, (*__errno_location ()), strerror((*__errno_location ()))); }
;
2058 }
2059 return true1;
2060 } else if ((size_t)r < sizeof(rsp.n)) {
2061 llog(RC_LOG, logger,
2062 "kernel: netlink_get read truncated message: %zd bytes; ignore message",
2063 r);
2064 return true1;
2065 } else if (addr.nl_pid != 0) {
2066 /* not for us: ignore */
2067 dbg("kernel: netlink_get: ignoring %s message from process %u",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: netlink_get: ignoring %s message from process %u"
, sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type), addr.nl_pid
); } }
2068 sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: netlink_get: ignoring %s message from process %u"
, sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type), addr.nl_pid
); } }
2069 addr.nl_pid){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: netlink_get: ignoring %s message from process %u"
, sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type), addr.nl_pid
); } }
;
2070 return true1;
2071 } else if ((size_t)r != rsp.n.nlmsg_len) {
2072 llog(RC_LOG, logger,
2073 "kernel: netlink_get: read message with length %zd that doesn't equal nlmsg_len %zu bytes; ignore message",
2074 r, (size_t) rsp.n.nlmsg_len);
2075 return true1;
2076 }
2077
2078 dbg("kernel: netlink_get: %s message",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: netlink_get: %s message", sparse_val_show
(xfrm_type_names, rsp.n.nlmsg_type)); } }
2079 sparse_val_show(xfrm_type_names, rsp.n.nlmsg_type)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: netlink_get: %s message", sparse_val_show
(xfrm_type_names, rsp.n.nlmsg_type)); } }
;
2080
2081 switch (rsp.n.nlmsg_type) {
2082 case XFRM_MSG_ACQUIREXFRM_MSG_ACQUIRE:
2083 netlink_acquire(&rsp.n, logger);
2084 break;
2085 case XFRM_MSG_POLEXPIREXFRM_MSG_POLEXPIRE:
2086 netlink_policy_expire(&rsp.n, logger);
2087 break;
2088 case XFRM_MSG_EXPIREXFRM_MSG_EXPIRE:
2089 netlink_expire(&rsp.n, logger);
2090 break;
2091
2092 case RTM_NEWADDRRTM_NEWADDR:
2093 process_addr_chage(&rsp.n, logger);
2094 break;
2095
2096 case RTM_DELADDRRTM_DELADDR:
2097 process_addr_chage(&rsp.n, logger);
2098 break;
2099
2100 default:
2101 /* ignored */
2102 break;
2103 }
2104
2105 return true1;
2106}
2107
2108static void netlink_process_msg(int fd, struct logger *logger)
2109{
2110 do {} while (netlink_get(fd, logger));
2111}
2112
2113static ipsec_spi_t netlink_get_spi(const ip_address *src,
2114 const ip_address *dst,
2115 const struct ip_protocol *proto,
2116 bool_Bool tunnel_mode,
2117 reqid_t reqid,
2118 uintmax_t min, uintmax_t max,
2119 const char *story,
2120 struct logger *logger)
2121{
2122 struct {
2123 struct nlmsghdr n;
2124 struct xfrm_userspi_info spi;
2125 } req;
2126 struct nlm_resp rsp;
2127
2128 zero(&req)memset((&req), '\0', sizeof(*(&req)));
2129 req.n.nlmsg_flags = NLM_F_REQUEST0x01;
2130 req.n.nlmsg_type = XFRM_MSG_ALLOCSPIXFRM_MSG_ALLOCSPI;
2131
2132 req.spi.info.saddr = xfrm_from_address(src);
2133 req.spi.info.id.daddr = xfrm_from_address(dst);
2134 req.spi.info.mode = tunnel_mode;
2135 req.spi.info.reqid = reqid;
2136 req.spi.info.id.proto = proto->ipproto;
2137 req.spi.info.family = addrtypeof(src);
2138
2139 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.spi)))( ((((sizeof(req.spi)) + ((int) ( ((sizeof(struct nlmsghdr))+
4U -1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
2140
2141 req.spi.min = min;
2142 req.spi.max = max;
2143
2144 int recv_errno;
2145 if (!send_netlink_msg(&req.n, XFRM_MSG_NEWSAXFRM_MSG_NEWSA, &rsp,
2146 "Get SPI", story,
2147 &recv_errno, logger)) {
2148 return 0;
2149 }
2150
2151 if (rsp.n.nlmsg_len < NLMSG_LENGTH(sizeof(rsp.u.sa))((sizeof(rsp.u.sa)) + ((int) ( ((sizeof(struct nlmsghdr))+4U -
1) & ~(4U -1) )))
) {
2152 llog(RC_LOG, logger,
2153 "kernel: netlink_get_spi: XFRM_MSG_ALLOCSPI returned message with length %zu < %zu bytes; ignore message",
2154 (size_t) rsp.n.nlmsg_len,
2155 sizeof(rsp.u.sa));
2156 return 0;
2157 }
2158
2159 dbg("kernel: netlink_get_spi: allocated 0x%x for %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: netlink_get_spi: allocated 0x%x for %s"
, ntohl(rsp.u.sa.id.spi), story); } }
2160 ntohl(rsp.u.sa.id.spi), story){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("kernel: netlink_get_spi: allocated 0x%x for %s"
, ntohl(rsp.u.sa.id.spi), story); } }
;
2161 return rsp.u.sa.id.spi;
2162}
2163
2164/* Check if there was traffic on given SA during the last idle_max
2165 * seconds. If TRUE, the SA was idle and DPD exchange should be performed.
2166 * If FALSE, DPD is not necessary. We also return TRUE for errors, as they
2167 * could mean that the SA is broken and needs to be replace anyway.
2168 *
2169 * note: this mutates *st by calling get_sa_info
2170 */
2171static bool_Bool netlink_eroute_idle(struct state *st, deltatime_t idle_max)
2172{
2173 deltatime_t idle_time;
2174
2175 passert(st != NULL)({ _Bool assertion__ = st != ((void*)0); if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/kernel_xfrm.c", .line = 2175, }; &
here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "st != ((void*)0)"); } (void
) 1; })
;
2176 return !get_sa_info(st, true1, &idle_time) ||
2177 deltatime_cmp(idle_time, >=, idle_max)(deltatime_sub_sign(idle_time, idle_max) >= 0);
2178}
2179
2180static bool_Bool netlink_shunt_policy(enum kernel_policy_op op,
2181 const struct connection *c,
2182 const struct spd_route *sr,
2183 enum routing_t rt_kind,
2184 const char *opname,
2185 struct logger *logger)
2186{
2187 ipsec_spi_t spi;
2188
2189 /*
2190 * We are constructing a special SAID for the eroute.
2191 * The destination doesn't seem to matter, but the family does.
2192 * The protocol is &ip_protocol_internal -- mark this as shunt.
2193 * The satype has no meaning, but is required for PF_KEY header!
2194 * The SPI signifies the kind of shunt.
2195 */
2196 spi = shunt_policy_spi(c, rt_kind == RT_ROUTED_PROSPECTIVE);
2197
2198 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
2199 selector_buf this_buf, that_buf;
2200 DBG_log("netlink_shunt_policy for proto %d, and source %s dest %s",
2201 sr->this.protocol,
2202 str_selector(&sr->this.client, &this_buf),
2203 str_selector(&sr->that.client, &that_buf));
2204 }
2205
2206 if (spi == 0) {
2207 /*
2208 * we're supposed to end up with no eroute: rejig op and
2209 * opname
2210 */
2211 switch (op) {
2212 case KP_REPLACE_OUTBOUND:
2213 /* replace with nothing == delete */
2214 op = KP_DELETE_OUTBOUND;
2215 opname = "delete";
2216 break;
2217 case KP_ADD_OUTBOUND:
2218 /* add nothing == do nothing */
2219 return true1;
2220
2221 case KP_DELETE_OUTBOUND:
2222 /* delete remains delete */
2223 break;
2224
2225 case KP_ADD_INBOUND:
2226 break;
2227
2228 case KP_DELETE_INBOUND:
2229 break;
2230
2231 default:
2232 bad_case(op)libreswan_bad_case("op", (op), ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/kernel_xfrm.c"
, .line = 2232, }; &here; }))
;
2233 }
2234 }
2235
2236 if (sr->routing == RT_ROUTED_ECLIPSED && c->kind == CK_TEMPLATE) {
2237 /*
2238 * We think that we have an eroute, but we don't.
2239 * Adjust the request and account for eclipses.
2240 */
2241 passert(eclipsable(sr))({ _Bool assertion__ = (selector_contains_one_address((sr)->
this.client) && selector_contains_one_address((sr)->
that.client)); if (!assertion__) { where_t here = ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/kernel_xfrm.c"
, .line = 2241, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_passert(logger_, here, "%s", "(selector_contains_one_address((sr)->this.client) && selector_contains_one_address((sr)->that.client))"
); } (void) 1; })
;
2242 switch (op) {
2243 case KP_REPLACE_OUTBOUND:
2244 /* really an add */
2245 op = KP_ADD_OUTBOUND;
2246 opname = "replace eclipsed";
2247 eclipse_count--;
2248 break;
2249 case KP_DELETE_OUTBOUND:
2250 /*
2251 * delete unnecessary:
2252 * we don't actually have an eroute
2253 */
2254 eclipse_count--;
2255 return true1;
2256
2257 case KP_ADD_OUTBOUND:
2258 default:
2259 bad_case(op)libreswan_bad_case("op", (op), ({ static const struct where here
= { .func = __func__, .file = "programs/pluto/kernel_xfrm.c"
, .line = 2259, }; &here; }))
;
2260 }
2261 } else if (eclipse_count > 0 && op == KP_DELETE_OUTBOUND && eclipsable(sr)(selector_contains_one_address((sr)->this.client) &&
selector_contains_one_address((sr)->that.client))
) {
2262 /* maybe we are uneclipsing something */
2263 struct spd_route *esr;
2264 struct connection *ue = eclipsed(c, &esr);
2265
2266 if (ue != NULL((void*)0)) {
2267 esr->routing = RT_ROUTED_PROSPECTIVE;
2268 return netlink_shunt_policy(KP_REPLACE_OUTBOUND, ue, esr,
2269 RT_ROUTED_PROSPECTIVE,
2270 "restoring eclipsed",
2271 logger);
2272 }
2273 }
2274
2275 /*
2276 * XXX: the two calls below to raw_policy() seems to be the
2277 * only place where SA_PROTO and ESATYPE disagree - when
2278 * ENCAPSULATION_MODE_TRANSPORT SA_PROTO==&ip_protocol_esp and
2279 * ESATYPE==ET_INT!?! Looking in the function there's a weird
2280 * test involving both SA_PROTO and ESATYPE.
2281 *
2282 * XXX: suspect sa_proto should be dropped (when is SPI not
2283 * internal) and instead esatype (encapsulated sa type) should
2284 * receive &ip_protocol ...
2285 *
2286 * Use raw_policy() as it gives a better log result.
2287 */
2288
2289 if (!raw_policy(op,
2290 &sr->this.host_addr, &sr->this.client,
2291 &sr->that.host_addr, &sr->that.client,
2292 htonl(spi), htonl(spi),
2293 sr->this.protocol,
2294 ET_INT,
2295 esp_transport_proto_info&esp_transport_kernel_encap,
2296 deltatime(0),
2297 calculate_sa_prio(c, false0),
2298 &c->sa_marks,
2299 (c->xfrmi != NULL((void*)0)) ? c->xfrmi->if_id : 0,
2300 HUNK_AS_SHUNK(sr->this.sec_label)({ typeof(sr->this.sec_label) h_ = (sr->this.sec_label)
; shunk2(h_.ptr, h_.len); })
, logger,
2301 "%s() adding outbound shunt for %s", __func__, opname))
2302 return false0;
2303
2304 switch (op) {
2305 case KP_ADD_OUTBOUND:
2306 op = KP_ADD_INBOUND;
2307 break;
2308 case KP_DELETE_OUTBOUND:
2309 op = KP_DELETE_INBOUND;
2310 break;
2311 default:
2312 return true1;
2313 }
2314
2315 /*
2316 * note the crossed streams since inbound
2317 */
2318 return raw_policy(op,
2319 &sr->that.host_addr, &sr->that.client,
2320 &sr->this.host_addr, &sr->this.client,
2321 htonl(spi), htonl(spi),
2322 sr->this.protocol,
2323 ET_INT,
2324 esp_transport_proto_info&esp_transport_kernel_encap,
2325 deltatime(0),
2326 calculate_sa_prio(c, false0),
2327 &c->sa_marks,
2328 0, /* xfrm_if_id needed for shunt? */
2329 HUNK_AS_SHUNK(sr->this.sec_label)({ typeof(sr->this.sec_label) h_ = (sr->this.sec_label)
; shunk2(h_.ptr, h_.len); })
, logger,
2330 "%s() adding inbound shunt for %s", __func__, opname);
2331}
2332
2333static void netlink_process_raw_ifaces(struct raw_iface *rifaces, struct logger *logger)
2334{
2335 struct raw_iface *ifp;
2336 ip_address lip; /* --listen filter option */
2337
2338 if (pluto_listen) {
2339 err_t e = ttoaddress_num(shunk1(pluto_listen), NULL((void*)0)/*UNSPEC*/, &lip);
2340
2341 if (e != NULL((void*)0)) {
2342 DBG_log("invalid listen= option ignored: %s", e);
2343 pluto_listen = NULL((void*)0);
2344 }
2345 address_buf b;
2346 dbg("Only looking to listen on %s", str_address(&lip, &b)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("Only looking to listen on %s", str_address(&
lip, &b)); } }
;
2347 }
2348
2349 /*
2350 * Find all virtual/real interface pairs.
2351 * For each real interface...
2352 */
2353 for (ifp = rifaces; ifp != NULL((void*)0); ifp = ifp->next) {
2354 struct raw_iface *v = NULL((void*)0); /* matching ipsecX interface */
2355 bool_Bool after = false0; /* has vfp passed ifp on the list? */
2356 bool_Bool bad = false0;
2357 struct raw_iface *vfp;
2358
2359 /* ignore if virtual (ipsec*) interface */
2360 if (startswith(ifp->name, IPSECDEVPREFIX)(strncmp(((ifp->name)), (("ipsec")), (strlen("ipsec"))) ==
0)
)
2361 continue;
2362
2363 /* ignore if virtual (mast*) interface */
2364 if (startswith(ifp->name, MASTDEVPREFIX)(strncmp(((ifp->name)), (("mast")), (strlen("mast"))) == 0
)
)
2365 continue;
2366
2367 for (vfp = rifaces; vfp != NULL((void*)0); vfp = vfp->next) {
2368 if (vfp == ifp) {
2369 after = true1;
2370 } else if (sameaddr(&ifp->addr, &vfp->addr)) {
2371 /*
2372 * Different entries with matching IP
2373 * addresses.
2374 *
2375 * Many interesting cases.
2376 */
2377 if (startswith(vfp->name, IPSECDEVPREFIX)(strncmp(((vfp->name)), (("ipsec")), (strlen("ipsec"))) ==
0)
) {
2378 if (v != NULL((void*)0)) {
2379 ipstr_buf b;
2380
2381 llog(RC_LOG_SERIOUS, logger,
2382 "ipsec interfaces %s and %s share same address %s",
2383 v->name, vfp->name,
2384 ipstr(&ifp->addr, &b));
2385 bad = true1;
2386 } else {
2387 /* current winner */
2388 v = vfp;
2389 }
2390 } else {
2391 /*
2392 * ugh: a second real interface with
2393 * the same IP address "after" allows
2394 * us to avoid double reporting.
2395 */
2396 /* XXX: isn't this always true? */
2397 if (kernel_ops->type == USE_XFRM) {
2398 if (after) {
2399 bad = true1;
2400 break;
2401 }
2402 continue;
2403 }
2404 if (after) {
2405 ipstr_buf b;
2406
2407 llog(RC_LOG_SERIOUS, logger,
2408 "IP interfaces %s and %s share address %s!",
2409 ifp->name, vfp->name,
2410 ipstr(&ifp->addr, &b));
2411 }
2412 bad = true1;
2413 }
2414 }
2415 }
2416
2417 if (bad)
2418 continue;
2419
2420 /* XXX: isn't this always true? */
2421 if (kernel_ops->type == USE_XFRM) {
2422 v = ifp;
2423 }
2424
2425 /* what if we didn't find a virtual interface? */
2426 if (v == NULL((void*)0)) {
2427 address_buf b;
2428 dbg("IP interface %s %s has no matching ipsec* interface -- ignored",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("IP interface %s %s has no matching ipsec* interface -- ignored"
, ifp->name, str_address(&ifp->addr, &b)); } }
2429 ifp->name, str_address(&ifp->addr, &b)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("IP interface %s %s has no matching ipsec* interface -- ignored"
, ifp->name, str_address(&ifp->addr, &b)); } }
;
2430 continue;
2431 }
2432
2433 /*
2434 * We've got all we need; see if this is a new thing:
2435 * search old interfaces list.
2436 */
2437
2438 /*
2439 * last check before we actually add the entry.
2440 *
2441 * ignore if --listen is specified and we do not match
2442 */
2443 if (pluto_listen != NULL((void*)0) && !sameaddr(&lip, &ifp->addr)) {
2444 ipstr_buf b;
2445
2446 llog(RC_LOG, logger,
2447 "skipping interface %s with %s",
2448 ifp->name, ipstr(&ifp->addr, &b));
2449 continue;
2450 }
2451
2452 add_or_keep_iface_dev(ifp, logger);
2453 }
2454
2455 /* delete the raw interfaces list */
2456 while (rifaces != NULL((void*)0)) {
2457 struct raw_iface *t = rifaces;
2458
2459 rifaces = t->next;
2460 pfree(t);
2461 }
2462}
2463
2464/*
2465 * netlink_get_sa - Get SA information from the kernel
2466 *
2467 * @param sa Kernel SA to be queried
2468 * @param bytes octets processed by IPsec SA
2469 * @param add_time timestamp when IPsec SA added
2470 * @return bool True if successful
2471 */
2472static bool_Bool netlink_get_sa(const struct kernel_sa *sa, uint64_t *bytes,
2473 uint64_t *add_time, struct logger *logger)
2474{
2475 struct {
2476 struct nlmsghdr n;
2477 struct xfrm_usersa_id id;
2478 } req;
2479
2480 struct nlm_resp rsp;
2481
2482 zero(&req)memset((&req), '\0', sizeof(*(&req)));
2483 req.n.nlmsg_flags = NLM_F_REQUEST0x01;
2484 req.n.nlmsg_type = XFRM_MSG_GETSAXFRM_MSG_GETSA;
2485
2486 req.id.daddr = xfrm_from_address(sa->dst.address);
2487
2488 req.id.spi = sa->spi;
2489 req.id.family = addrtypeof(sa->src.address);
2490 req.id.proto = sa->proto->ipproto;
2491
2492 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)))( ((((sizeof(req.id)) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
2493
2494 int recv_errno;
2495 if (!send_netlink_msg(&req.n, XFRM_MSG_NEWSAXFRM_MSG_NEWSA, &rsp,
2496 "Get SA", sa->story,
2497 &recv_errno, logger)) {
2498 return false0;
2499 }
2500
2501 *bytes = rsp.u.info.curlft.bytes;
2502 *add_time = rsp.u.info.curlft.add_time;
2503 return true1;
2504}
2505
2506/* add bypass policies/holes icmp */
2507static bool_Bool netlink_bypass_policy(int family, int proto, int port,
2508 struct logger *logger)
2509{
2510 struct {
2511 struct nlmsghdr n;
2512 union {
2513 struct xfrm_userpolicy_info p;
2514 struct xfrm_userpolicy_id id;
2515 } u;
2516 char data[MAX_NETLINK_DATA_SIZE8192];
2517 } req;
2518
2519 zero(&req)memset((&req), '\0', sizeof(*(&req)));
2520
2521 req.n.nlmsg_flags = NLM_F_REQUEST0x01 | NLM_F_ACK0x04;
2522
2523 req.n.nlmsg_type = XFRM_MSG_UPDPOLICYXFRM_MSG_UPDPOLICY;
2524 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.u.p)))( ((((sizeof(req.u.p)) + ((int) ( ((sizeof(struct nlmsghdr))+
4U -1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
2525
2526 req.u.p.dir = XFRM_POLICY_IN;
2527 req.u.p.priority = 1; /* give admin prio 0 as override */
2528 req.u.p.action = XFRM_POLICY_ALLOW0;
2529 req.u.p.share = XFRM_SHARE_ANY;
2530
2531 req.u.p.lft.soft_byte_limit = XFRM_INF(~(__u64)0);
2532 req.u.p.lft.soft_packet_limit = XFRM_INF(~(__u64)0);
2533 req.u.p.lft.hard_byte_limit = XFRM_INF(~(__u64)0);
2534 req.u.p.lft.hard_packet_limit = XFRM_INF(~(__u64)0);
2535
2536 req.u.p.sel.proto = proto;
2537 req.u.p.sel.family = family;
2538
2539 const char* text = "add port bypass";
2540
2541 if (proto == IPPROTO_ICMPV658) {
2542 uint16_t icmp_type;
2543 uint16_t icmp_code;
2544
2545 icmp_type = port >> 8;
2546 icmp_code = port & 0xFF;
2547 req.u.p.sel.sport = htons(icmp_type);
2548 req.u.p.sel.dport = htons(icmp_code);
2549 req.u.p.sel.sport_mask = 0xffff;
2550
2551 if (!netlink_policy(&req.n, 1, text, logger))
2552 return false0;
2553
2554 req.u.p.dir = XFRM_POLICY_FWD;
2555
2556 if (!netlink_policy(&req.n, 1, text, logger))
2557 return false0;
2558
2559 req.u.p.dir = XFRM_POLICY_OUT;
2560
2561 if (!netlink_policy(&req.n, 1, text, logger))
2562 return false0;
2563 } else {
2564 req.u.p.sel.dport = htons(port);
2565 req.u.p.sel.dport_mask = 0xffff;
2566
2567 if (!netlink_policy(&req.n, 1, text, logger))
2568 return false0;
2569
2570 req.u.p.dir = XFRM_POLICY_OUT;
2571
2572 req.u.p.sel.sport = htons(port);
2573 req.u.p.sel.sport_mask = 0xffff;
2574 req.u.p.sel.dport = 0;
2575 req.u.p.sel.dport_mask = 0;
2576
2577 if (!netlink_policy(&req.n, 1, text, logger))
2578 return false0;
2579 }
2580
2581 return true1;
2582}
2583
2584static void netlink_v6holes(struct logger *logger)
2585{
2586 /* this could be per interface specific too */
2587 const char proc_f[] = "/proc/sys/net/ipv6/conf/all/disable_ipv6";
2588
2589 struct stat sts;
2590 if (stat(proc_f, &sts) != 0) {
2591 /* not error */
2592 llog_errno(RC_LOG, logger, errno(*__errno_location ()),
2593 "kernel: starting without ipv6 support! could not stat \"%s\""/*: */,
2594 proc_f);
2595 /*
2596 * pretend success, do not exit pluto, likely IPv6 is
2597 * disabled in kernel at compile time. e.g. OpenWRT.
2598 */
2599 return;
2600 }
2601
2602 /*
2603 * If the IPv6 enabled file is present, insist on being able
2604 * to read it.
2605 */
2606
2607 FILE *f = fopen(proc_f, "r");
2608 if (f == NULL((void*)0)) {
2609 fatal_errno(PLUTO_EXIT_KERNEL_FAIL, logger, errno(*__errno_location ()),
2610 "kernel: could not open \"%s\"", proc_f);
2611 }
2612
2613 char buf[64];
2614 if (fgets(buf, sizeof(buf), f) == NULL((void*)0)) {
2615 (void) fclose(f);
2616 fatal_errno(PLUTO_EXIT_KERNEL_FAIL, logger, errno(*__errno_location ()),
2617 "kernel: could not read \"%s\"", proc_f);
2618 }
2619 (void) fclose(f);
2620
2621 int disable_ipv6 = atoi(buf);
2622 if (disable_ipv6 == 1) {
2623 llog(RC_LOG, logger, "kernel: %s=1 ignore ipv6 holes", proc_f);
2624 return;
2625 }
2626
2627 if (!netlink_bypass_policy(AF_INET610, IPPROTO_ICMPV658,
2628 ICMP_NEIGHBOR_DISCOVERY34816,
2629 logger)) {
2630 fatal(PLUTO_EXIT_KERNEL_FAIL, logger,
2631 "kernel: could not insert ICMP_NEIGHBOUR_DISCOVERY bypass policy");
2632 }
2633 if (!netlink_bypass_policy(AF_INET610, IPPROTO_ICMPV658,
2634 ICMP_NEIGHBOR_SOLICITATION34560,
2635 logger)) {
2636 fatal(PLUTO_EXIT_KERNEL_FAIL, logger,
2637 "kernel: could not insert ICMP_NEIGHBOUR_SOLICITATION bypass policy");
2638 }
2639}
2640
2641static bool_Bool qry_xfrm_mirgrate_support(struct nlmsghdr *hdr, struct logger *logger)
2642{
2643 struct nlm_resp rsp;
2644 size_t len;
2645 ssize_t r;
2646 struct sockaddr_nl addr;
2647 int nl_fd = socket(AF_NETLINK16, SOCK_DGRAMSOCK_DGRAM, NETLINK_XFRM6);
2648
2649 if (nl_fd < 0) {
2650 log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "socket() in qry_xfrm_mirgrate_support()"
); }
2651 "socket() in qry_xfrm_mirgrate_support()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "socket() in qry_xfrm_mirgrate_support()"
); }
;
2652 return false0;
2653 }
2654
2655 if (fcntl(nl_fd, F_SETFL4, O_NONBLOCK04000) != 0) {
2656 log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "fcntl(O_NONBLOCK in qry_xfrm_mirgrate_support()"
); }
2657 "fcntl(O_NONBLOCK in qry_xfrm_mirgrate_support()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "fcntl(O_NONBLOCK in qry_xfrm_mirgrate_support()"
); }
;
2658 close(nl_fd);
2659
2660 return false0;
2661 }
2662
2663 /* hdr->nlmsg_seq = ++seq; */
2664 len = hdr->nlmsg_len;
2665 do {
2666 r = write(nl_fd, hdr, len);
2667 } while (r < 0 && errno(*__errno_location ()) == EINTR4);
2668 if (r < 0) {
2669 log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink write() xfrm_migrate_support lookup"
); }
2670 "netlink write() xfrm_migrate_support lookup"){ int e_ = (*__errno_location ()); log_error(logger, e_, "netlink write() xfrm_migrate_support lookup"
); }
;
2671 close(nl_fd);
2672 return false0;
2673 } else if ((size_t)r != len) {
2674 llog(RC_LOG_SERIOUS, logger,
2675 "ERROR: netlink write() xfrm_migrate_support message truncated: %zd instead of %zu",
2676 r, len);
2677 close(nl_fd);
2678 return false0;
2679 }
2680
2681 for (;;) {
2682 socklen_t alen = sizeof(addr);
2683
2684 r = recvfrom(nl_fd, &rsp, sizeof(rsp), 0,
2685 (struct sockaddr *)&addr, &alen);
2686 if (r < 0) {
2687 if (errno(*__errno_location ()) == EINTR4) {
2688 continue;
2689 } else if (errno(*__errno_location ()) == EAGAIN11) {
2690 /* old kernel F22 - dos not return proper error ??? */
2691 dbg("ignore EAGAIN in %s assume MOBIKE migration is supported", __func__){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("ignore EAGAIN in %s assume MOBIKE migration is supported"
, __func__); } }
;
2692 break;
2693 }
2694 }
2695 break;
2696 }
2697
2698 close(nl_fd);
2699
2700 if (rsp.n.nlmsg_type == NLMSG_ERROR0x2 && rsp.u.e.error == -ENOPROTOOPT92) {
2701 dbg("MOBIKE will fail got ENOPROTOOPT"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("MOBIKE will fail got ENOPROTOOPT"); } }
;
2702 return false0;
2703 }
2704
2705 return true1;
2706}
2707
2708static err_t netlink_migrate_sa_check(struct logger *logger)
2709{
2710 if (kernel_mobike_supprt == 0) {
2711 /* check the kernel */
2712
2713 struct {
2714 struct nlmsghdr n;
2715 struct xfrm_userpolicy_id id;
2716 char data[MAX_NETLINK_DATA_SIZE8192];
2717 } req;
2718
2719 zero(&req)memset((&req), '\0', sizeof(*(&req)));
2720 req.n.nlmsg_flags = NLM_F_REQUEST0x01;
2721 req.n.nlmsg_type = XFRM_MSG_MIGRATEXFRM_MSG_MIGRATE;
2722 req.n.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.id)))( ((((sizeof(req.id)) + ((int) ( ((sizeof(struct nlmsghdr))+4U
-1) & ~(4U -1) ))))+4U -1) & ~(4U -1) )
;
2723
2724 /* add attrs[XFRM_MSG_MIGRATE] */
2725 struct rtattr *attr;
2726 struct xfrm_user_migrate migrate;
2727
2728 zero(&migrate)memset((&migrate), '\0', sizeof(*(&migrate)));
2729 attr = (struct rtattr *)((char *)&req + req.n.nlmsg_len);
2730 attr->rta_type = XFRMA_MIGRATE;
2731 attr->rta_len = sizeof(migrate);
2732
2733 memcpy(RTA_DATA(attr)((void*)(((char*)(attr)) + (( ((sizeof(struct rtattr))+4U -1)
& ~(4U -1) ) + (0))))
, &migrate, attr->rta_len);
2734 attr->rta_len = RTA_LENGTH(attr->rta_len)(( ((sizeof(struct rtattr))+4U -1) & ~(4U -1) ) + (attr->
rta_len))
;
2735 req.n.nlmsg_len += attr->rta_len;
2736
2737 bool_Bool ret = qry_xfrm_mirgrate_support(&req.n, logger);
2738 kernel_mobike_supprt = ret ? 1 : -1;
2739 }
2740
2741 if (kernel_mobike_supprt > 0) {
2742 return NULL((void*)0);
2743 } else {
2744 return "CONFIG_XFRM_MIGRATE";
2745 }
2746}
2747
2748static bool_Bool netlink_poke_ipsec_policy_hole(const struct iface_dev *ifd, int fd, struct logger *logger)
2749{
2750 const struct ip_info *type = address_type(&ifd->id_address);
2751 struct xfrm_userpolicy_info policy = {
2752 .action = XFRM_POLICY_ALLOW0,
2753 .sel = {
2754 .family = type->af,
2755 }
2756 };
2757
2758 int opt, sol;
2759
2760 if (type == &ipv6_info) {
2761 sol = IPPROTO_IPV6IPPROTO_IPV6;
2762 opt = IPV6_XFRM_POLICY35;
2763 } else {
2764 sol = SOL_IP0;
2765 opt = IP_XFRM_POLICY17;
2766 }
2767
2768 policy.dir = XFRM_POLICY_IN;
2769 if (setsockopt(fd, sol, opt, &policy, sizeof(policy)) < 0) {
2770 log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt IP_XFRM_POLICY XFRM_POLICY_IN in process_raw_ifaces()"
); }
2771 "setsockopt IP_XFRM_POLICY XFRM_POLICY_IN in process_raw_ifaces()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt IP_XFRM_POLICY XFRM_POLICY_IN in process_raw_ifaces()"
); }
;
2772 return false0;
2773 }
2774
2775 policy.dir = XFRM_POLICY_OUT;
2776 if (setsockopt(fd, sol, opt, &policy, sizeof(policy)) < 0) {
2777 log_errno(logger, errno,{ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt IP_XFRM_POLICY XFRM_POLICY_OUT in process_raw_ifaces()"
); }
2778 "setsockopt IP_XFRM_POLICY XFRM_POLICY_OUT in process_raw_ifaces()"){ int e_ = (*__errno_location ()); log_error(logger, e_, "setsockopt IP_XFRM_POLICY XFRM_POLICY_OUT in process_raw_ifaces()"
); }
;
2779 return false0;
2780 }
2781
2782 return true1;
2783}
2784
2785const struct kernel_ops xfrm_kernel_ops = {
2786 .kern_name = "xfrm",
2787 .type = USE_XFRM,
2788 .async_fdp = &nl_xfrm_fd,
2789 .route_fdp = &nl_route_fd,
2790 .replay_window = IPSEC_SA_DEFAULT_REPLAY_WINDOW32,
2791
2792 .init = init_netlink,
2793#ifdef USE_XFRM_INTERFACE1
2794 .shutdown = free_xfrmi_ipsec1,
2795#else
2796 .shutdown = NULL((void*)0),
2797#endif
2798 .process_msg = netlink_process_msg,
2799 .raw_policy = netlink_raw_policy,
2800 .add_sa = netlink_add_sa,
2801 .del_sa = netlink_del_sa,
2802 .get_sa = netlink_get_sa,
2803 .process_queue = NULL((void*)0),
2804 .grp_sa = NULL((void*)0),
2805 .get_spi = netlink_get_spi,
2806 .exceptsocket = NULL((void*)0),
2807 .process_raw_ifaces = netlink_process_raw_ifaces,
2808 .shunt_policy = netlink_shunt_policy,
2809 .eroute_idle = netlink_eroute_idle,
2810 .migrate_sa_check = netlink_migrate_sa_check,
2811 .migrate_sa = netlink_migrate_sa,
2812 .overlap_supported = false0,
2813 .sha2_truncbug_support = true1,
2814 .v6holes = netlink_v6holes,
2815 .poke_ipsec_policy_hole = netlink_poke_ipsec_policy_hole,
2816 .detect_offload = netlink_detect_offload,
2817};