OpenVPN
dco_linux.c
Go to the documentation of this file.
1/*
2 * Interface to linux dco networking code
3 *
4 * Copyright (C) 2020-2026 Antonio Quartulli <a@unstable.cc>
5 * Copyright (C) 2020-2026 Arne Schwabe <arne@rfc2549.org>
6 * Copyright (C) 2020-2026 OpenVPN Inc <sales@openvpn.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program (see the file COPYING included with this
19 * distribution); if not, see <https://www.gnu.org/licenses/>.
20 */
21
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#if defined(ENABLE_DCO) && defined(TARGET_LINUX)
28
29#include "syshead.h"
30
31#include "dco_linux.h"
32#include "errlevel.h"
33#include "buffer.h"
34#include "networking.h"
35#include "openvpn.h"
36
37#include "socket.h"
38#include "tun.h"
39#include "ssl.h"
40#include "fdmisc.h"
41#include "multi.h"
42#include "ssl_verify.h"
43
44#include "ovpn_dco_linux.h"
45
46#include <netlink/socket.h>
47#include <netlink/netlink.h>
48#include <netlink/genl/genl.h>
49#include <netlink/genl/family.h>
50#include <netlink/genl/ctrl.h>
51
52/* When parsing multiple DEL_PEER notifications, openvpn tries to request stats
53 * for each DEL_PEER message (see setenv_stats). This triggers a GET_PEER
54 * request-reply while we are still parsing the rest of the initial
55 * notifications, which can lead to NLE_BUSY or even NLE_NOMEM.
56 *
57 * This basic lock ensures we don't bite our own tail by issuing a dco_get_peer
58 * while still busy receiving and parsing other messages.
59 */
60static bool __is_locked = false;
61
62/* libnl < 3.5.0 does not set the NLA_F_NESTED on its own, therefore we
63 * have to explicitly do it to prevent the kernel from failing upon
64 * parsing of the message
65 */
66#define nla_nest_start(_msg, _type) nla_nest_start(_msg, (_type) | NLA_F_NESTED)
67
68static int ovpn_get_mcast_id(dco_context_t *dco);
69
70void dco_check_key_ctx(const struct key_ctx_bi *key);
71
72typedef int (*ovpn_nl_cb)(struct nl_msg *msg, void *arg);
73
85static int
86resolve_ovpn_netlink_id(msglvl_t msglevel)
87{
88 int ret;
89 struct nl_sock *nl_sock = nl_socket_alloc();
90
91 if (!nl_sock)
92 {
93 msg(msglevel, "Allocating net link socket failed");
94 return -ENOMEM;
95 }
96
97 ret = genl_connect(nl_sock);
98 if (ret)
99 {
100 msg(msglevel, "Cannot connect to generic netlink: %s", nl_geterror(ret));
101 goto err_sock;
102 }
103 set_cloexec(nl_socket_get_fd(nl_sock));
104
105 ret = genl_ctrl_resolve(nl_sock, OVPN_FAMILY_NAME);
106 if (ret < 0)
107 {
108 msg(msglevel, "Cannot find ovpn_dco netlink component: %s", nl_geterror(ret));
109 }
110
111err_sock:
112 nl_socket_free(nl_sock);
113 return ret;
114}
115
116static struct nl_msg *
117ovpn_dco_nlmsg_create(dco_context_t *dco, uint8_t cmd)
118{
119 struct nl_msg *nl_msg = nlmsg_alloc();
120 if (!nl_msg)
121 {
122 msg(M_FATAL, "cannot allocate netlink message");
123 return NULL;
124 }
125
126 genlmsg_put(nl_msg, 0, 0, dco->ovpn_dco_id, 0, 0, cmd, 0);
127 NLA_PUT_U32(nl_msg, OVPN_A_IFINDEX, dco->ifindex);
128
129 return nl_msg;
130nla_put_failure:
131 nlmsg_free(nl_msg);
132 msg(M_INFO, "cannot put into netlink message");
133 return NULL;
134}
135
136static int
137ovpn_nl_recvmsgs(dco_context_t *dco, const char *prefix)
138{
139 __is_locked = true;
140 int ret = nl_recvmsgs(dco->nl_sock, dco->nl_cb);
141 __is_locked = false;
142
143 switch (ret)
144 {
145 case -NLE_INTR:
146 msg(M_WARN, "%s: netlink received interrupt due to signal - ignoring", prefix);
147 break;
148
149 case -NLE_NOMEM:
150 msg(M_FATAL, "%s: netlink out of memory error", prefix);
151 break;
152
153 case -NLE_AGAIN:
154 msg(M_WARN, "%s: netlink reports blocking read - aborting wait", prefix);
155 break;
156
157 case -NLE_NODEV:
158 msg(M_FATAL, "%s: netlink reports device not found:", prefix);
159 break;
160
161 case -NLE_OBJ_NOTFOUND:
162 msg(M_INFO, "%s: netlink reports object not found, ovpn kernel module unloaded?", prefix);
163 break;
164
165 default:
166 if (ret)
167 {
168 msg(M_NONFATAL, "%s: netlink reports error (%d): %s", prefix, ret,
169 nl_geterror(-ret));
170 }
171 break;
172 }
173
174 return ret;
175}
176
186static int
187ovpn_nl_msg_send(dco_context_t *dco, struct nl_msg *nl_msg, const char *prefix)
188{
189 dco->status = 1;
190
191 nl_send_auto(dco->nl_sock, nl_msg);
192
193 while (dco->status == 1)
194 {
195 ovpn_nl_recvmsgs(dco, prefix);
196 }
197
198 if (dco->status < 0)
199 {
200 msg(M_INFO, "%s: failed to send netlink message: %s (%d)", prefix, strerror(-dco->status),
201 dco->status);
202 }
203
204 return dco->status;
205}
206
207struct sockaddr *
208mapped_v4_to_v6(struct sockaddr *sock, struct gc_arena *gc)
209{
210 struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)sock;
211 if (sock->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sock6->sin6_addr))
212 {
213 struct sockaddr_in *sock4;
214 ALLOC_OBJ_CLEAR_GC(sock4, struct sockaddr_in, gc);
215 memcpy(&sock4->sin_addr, sock6->sin6_addr.s6_addr + 12, 4);
216 sock4->sin_port = sock6->sin6_port;
217 sock4->sin_family = AF_INET;
218 return (struct sockaddr *)sock4;
219 }
220 return sock;
221}
222
223int
224dco_new_peer(dco_context_t *dco, unsigned int peerid, int sd, struct sockaddr *localaddr,
225 struct sockaddr *remoteaddr, struct in_addr *vpn_ipv4, struct in6_addr *vpn_ipv6)
226{
227 struct gc_arena gc = gc_new();
228 const char *remotestr = "[undefined]";
229 if (remoteaddr)
230 {
231 remotestr = print_sockaddr(remoteaddr, &gc);
232 }
233 msg(D_DCO_DEBUG, "%s: peer-id %d, fd %d, remote addr: %s", __func__, peerid, sd, remotestr);
234
235 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_NEW);
236 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
237 int ret = -EMSGSIZE;
238
239 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peerid);
240 NLA_PUT_U32(nl_msg, OVPN_A_PEER_SOCKET, sd);
241
242 /* Set the remote endpoint if defined (for UDP) */
243 if (remoteaddr)
244 {
245 remoteaddr = mapped_v4_to_v6(remoteaddr, &gc);
246
247 if (remoteaddr->sa_family == AF_INET)
248 {
249 NLA_PUT(nl_msg, OVPN_A_PEER_REMOTE_IPV4, sizeof(struct in_addr),
250 &((struct sockaddr_in *)remoteaddr)->sin_addr);
251 NLA_PUT_U16(nl_msg, OVPN_A_PEER_REMOTE_PORT,
252 ((struct sockaddr_in *)remoteaddr)->sin_port);
253 }
254 else if (remoteaddr->sa_family == AF_INET6)
255 {
256 NLA_PUT(nl_msg, OVPN_A_PEER_REMOTE_IPV6, sizeof(struct in6_addr),
257 &((struct sockaddr_in6 *)remoteaddr)->sin6_addr);
258 NLA_PUT_U16(nl_msg, OVPN_A_PEER_REMOTE_PORT,
259 ((struct sockaddr_in6 *)remoteaddr)->sin6_port);
260 NLA_PUT_U32(nl_msg, OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID,
261 ((struct sockaddr_in6 *)remoteaddr)->sin6_scope_id);
262 }
263 }
264
265 if (localaddr)
266 {
267 localaddr = mapped_v4_to_v6(localaddr, &gc);
268 if (localaddr->sa_family == AF_INET)
269 {
270 NLA_PUT(nl_msg, OVPN_A_PEER_LOCAL_IPV4, sizeof(struct in_addr),
271 &((struct sockaddr_in *)localaddr)->sin_addr);
272 }
273 else if (localaddr->sa_family == AF_INET6)
274 {
275 NLA_PUT(nl_msg, OVPN_A_PEER_LOCAL_IPV6, sizeof(struct in6_addr),
276 &((struct sockaddr_in6 *)localaddr)->sin6_addr);
277 }
278 }
279
280 /* Set the primary VPN IP addresses of the peer */
281 if (vpn_ipv4)
282 {
283 NLA_PUT_U32(nl_msg, OVPN_A_PEER_VPN_IPV4, vpn_ipv4->s_addr);
284 }
285 if (vpn_ipv6)
286 {
287 NLA_PUT(nl_msg, OVPN_A_PEER_VPN_IPV6, sizeof(struct in6_addr), vpn_ipv6);
288 }
289 nla_nest_end(nl_msg, attr);
290
291 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
292
293nla_put_failure:
294 nlmsg_free(nl_msg);
295 gc_free(&gc);
296 return ret;
297}
298
299static int
300ovpn_nl_cb_finish(struct nl_msg(*msg) __attribute__((unused)), void *arg)
301{
302 int *status = arg;
303
304 *status = 0;
305 return NL_SKIP;
306}
307
308/* The following enum members exist in netlink.h since linux-6.1.
309 * However, some distro we support still ship an old header, thus
310 * failing the OpenVPN compilation.
311 *
312 * For the time being we add the needed defines manually.
313 * We will drop this definition once we stop supporting those old
314 * distros.
315 *
316 * @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute,
317 * %NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was
318 * missing at the message level
319 * @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing
320 */
321enum ovpn_nlmsgerr_attrs
322{
323 OVPN_NLMSGERR_ATTR_MISS_TYPE = 5,
324 OVPN_NLMSGERR_ATTR_MISS_NEST = 6,
325 OVPN_NLMSGERR_ATTR_MAX = 6,
326};
327
328/* This function is used as error callback on the netlink socket.
329 * When something goes wrong and the kernel returns an error, this function is
330 * invoked.
331 *
332 * We pass the error code to the user by means of a variable pointed by *arg
333 * (supplied by the user when setting this callback) and we parse the kernel
334 * reply to see if it contains a human-readable error. If found, it is printed.
335 */
336static int
337ovpn_nl_cb_error(struct sockaddr_nl(*nla) __attribute__((unused)), struct nlmsgerr *err, void *arg)
338{
339 struct nlmsghdr *nlh = (struct nlmsghdr *)err - 1;
340 struct nlattr *tb_msg[OVPN_NLMSGERR_ATTR_MAX + 1];
341 int len = nlh->nlmsg_len;
342 struct nlattr *attrs;
343 int *ret = arg;
344 int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh);
345
346 *ret = err->error;
347
348 if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
349 {
350 return NL_STOP;
351 }
352
353 if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
354 {
355 ack_len += err->msg.nlmsg_len - (int)sizeof(*nlh);
356 }
357
358 if (len <= ack_len)
359 {
360 return NL_STOP;
361 }
362
363 attrs = (void *)((unsigned char *)nlh + ack_len);
364 len -= ack_len;
365
366 nla_parse(tb_msg, OVPN_NLMSGERR_ATTR_MAX, attrs, len, NULL);
367 if (tb_msg[NLMSGERR_ATTR_MSG])
368 {
369 len = (int)strnlen((char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]),
370 nla_len(tb_msg[NLMSGERR_ATTR_MSG]));
371 msg(M_WARN, "kernel error: %*s", len, (char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]));
372 }
373
374 if (tb_msg[OVPN_NLMSGERR_ATTR_MISS_NEST])
375 {
376 msg(M_WARN, "kernel error: missing required nesting type %u",
377 nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_NEST]));
378 }
379
380 if (tb_msg[OVPN_NLMSGERR_ATTR_MISS_TYPE])
381 {
382 msg(M_WARN, "kernel error: missing required attribute type %u",
383 nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_TYPE]));
384 }
385
386 return NL_STOP;
387}
388
389static void
390ovpn_dco_register(dco_context_t *dco)
391{
392 msg(D_DCO_DEBUG, __func__);
393 ovpn_get_mcast_id(dco);
394
395 if (dco->ovpn_dco_mcast_id < 0)
396 {
397 msg(M_FATAL, "cannot get mcast group: %s", nl_geterror(dco->ovpn_dco_mcast_id));
398 }
399
400 /* Register for ovpn-dco specific multicast messages that the kernel may
401 * send
402 */
403 int ret = nl_socket_add_membership(dco->nl_sock, dco->ovpn_dco_mcast_id);
404 if (ret)
405 {
406 msg(M_FATAL, "%s: failed to join groups: %d", __func__, ret);
407 }
408}
409
410static int ovpn_handle_msg(struct nl_msg *msg, void *arg);
411
412static void
413ovpn_dco_init_netlink(dco_context_t *dco)
414{
415 dco->ovpn_dco_id = resolve_ovpn_netlink_id(M_FATAL);
416
417 dco->nl_sock = nl_socket_alloc();
418
419 if (!dco->nl_sock)
420 {
421 msg(M_FATAL, "Cannot create netlink socket");
422 }
423
424 int ret = genl_connect(dco->nl_sock);
425 if (ret)
426 {
427 msg(M_FATAL, "Cannot connect to generic netlink: %s", nl_geterror(ret));
428 }
429
430 /* enable Extended ACK for detailed error reporting */
431 ret = 1;
432 setsockopt(nl_socket_get_fd(dco->nl_sock), SOL_NETLINK, NETLINK_EXT_ACK, &ret, sizeof(ret));
433
434 /* set close on exec and non-block on the netlink socket */
435 set_cloexec(nl_socket_get_fd(dco->nl_sock));
436 set_nonblock(nl_socket_get_fd(dco->nl_sock));
437
438 dco->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
439 if (!dco->nl_cb)
440 {
441 msg(M_FATAL, "failed to allocate netlink callback");
442 }
443
444 nl_socket_set_cb(dco->nl_sock, dco->nl_cb);
445
446 dco->dco_message_peer_id = -1;
447 nl_cb_err(dco->nl_cb, NL_CB_CUSTOM, ovpn_nl_cb_error, &dco->status);
448 nl_cb_set(dco->nl_cb, NL_CB_FINISH, NL_CB_CUSTOM, ovpn_nl_cb_finish, &dco->status);
449 nl_cb_set(dco->nl_cb, NL_CB_ACK, NL_CB_CUSTOM, ovpn_nl_cb_finish, &dco->status);
450 nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, ovpn_handle_msg, dco);
451
452 ovpn_dco_register(dco);
453
454 /* The async PACKET messages confuse libnl and it will drop them with
455 * wrong sequence numbers (NLE_SEQ_MISMATCH), so disable libnl's sequence
456 * number check */
457 nl_socket_disable_seq_check(dco->nl_sock);
458
459 /* nl library sets the buffer size to 32k/32k by default which is sometimes
460 * overrun with very fast connecting/disconnecting clients.
461 * TODO: fix this in a better and more reliable way */
462 ASSERT(!nl_socket_set_buffer_size(dco->nl_sock, 1024 * 1024, 1024 * 1024));
463}
464
465bool
466ovpn_dco_init(struct context *c)
467{
468 dco_context_t *dco = &c->c1.tuntap->dco;
469
470 switch (c->mode)
471 {
472 case CM_TOP:
473 dco->ifmode = OVPN_MODE_MP;
474 break;
475
476 case CM_P2P:
477 dco->ifmode = OVPN_MODE_P2P;
478 break;
479
480 default:
481 ASSERT(false);
482 }
483
484 /* store pointer to context as it may be required by message
485 * parsing routines
486 */
487 dco->c = c;
488 ovpn_dco_init_netlink(dco);
489 return true;
490}
491
492static void
493ovpn_dco_uninit_netlink(dco_context_t *dco)
494{
495 nl_socket_free(dco->nl_sock);
496 dco->nl_sock = NULL;
497
498 /* Decrease reference count */
499 nl_cb_put(dco->nl_cb);
500
501 CLEAR(dco);
502}
503
504int
505open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev)
506{
507 msg(D_DCO_DEBUG, "%s: %s", __func__, dev);
508 ASSERT(tt->type == DEV_TYPE_TUN);
509
510 int ret = net_iface_new(ctx, dev, OVPN_FAMILY_NAME, &tt->dco);
511 if (ret < 0)
512 {
513 msg(D_DCO_DEBUG, "Cannot create DCO interface %s: %d", dev, ret);
514 return ret;
515 }
516
517 tt->dco.ifindex = if_nametoindex(dev);
518 if (!tt->dco.ifindex)
519 {
520 msg(M_FATAL, "DCO: cannot retrieve ifindex for interface %s", dev);
521 }
522
523 return 0;
524}
525
526void
527close_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx)
528{
529 msg(D_DCO_DEBUG, __func__);
530
531 net_iface_del(ctx, tt->actual_name);
532 ovpn_dco_uninit_netlink(&tt->dco);
533}
534
535int
536dco_swap_keys(dco_context_t *dco, unsigned int peerid)
537{
538 msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peerid);
539
540 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_KEY_SWAP);
541 if (!nl_msg)
542 {
543 return -ENOMEM;
544 }
545
546 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_KEYCONF);
547 int ret = -EMSGSIZE;
548 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_PEER_ID, peerid);
549 nla_nest_end(nl_msg, attr);
550
551 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
552
553nla_put_failure:
554 nlmsg_free(nl_msg);
555 return ret;
556}
557
558
559int
560dco_del_peer(dco_context_t *dco, unsigned int peerid)
561{
562 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: peer-id %d", __func__, peerid);
563
564 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_DEL);
565 if (!nl_msg)
566 {
567 return -ENOMEM;
568 }
569
570 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
571 int ret = -EMSGSIZE;
572 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peerid);
573 nla_nest_end(nl_msg, attr);
574
575 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
576
577nla_put_failure:
578 nlmsg_free(nl_msg);
579 return ret;
580}
581
582
583int
584dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot)
585{
586 int ret = -EMSGSIZE;
587 msg(D_DCO_DEBUG, "%s: peer-id %d, slot %d", __func__, peerid, slot);
588
589 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_KEY_DEL);
590 if (!nl_msg)
591 {
592 return -ENOMEM;
593 }
594
595 struct nlattr *keyconf = nla_nest_start(nl_msg, OVPN_A_KEYCONF);
596 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_PEER_ID, peerid);
597 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_SLOT, slot);
598 nla_nest_end(nl_msg, keyconf);
599
600 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
601
602nla_put_failure:
603 nlmsg_free(nl_msg);
604 return ret;
605}
606
607int
608dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t slot,
609 const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key,
610 const uint8_t *decrypt_iv, const char *ciphername, bool epoch)
611{
612 msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, epoch %d", __func__, slot, keyid, peerid,
613 ciphername, epoch);
614
615 const size_t key_len = cipher_kt_key_size(ciphername);
616 ASSERT(key_len <= INT_MAX);
617 const int nonce_tail_len = 8;
618
619 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_KEY_NEW);
620 if (!nl_msg)
621 {
622 return -ENOMEM;
623 }
624
625 dco_cipher_t dco_cipher = dco_get_cipher(ciphername);
626
627 int ret = -EMSGSIZE;
628
629 struct nlattr *key_conf = nla_nest_start(nl_msg, OVPN_A_KEYCONF);
630 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_PEER_ID, peerid);
631 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_SLOT, slot);
632 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_KEY_ID, keyid);
633 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_CIPHER_ALG, dco_cipher);
634
635 struct nlattr *key_enc = nla_nest_start(nl_msg, OVPN_A_KEYCONF_ENCRYPT_DIR);
636 if (dco_cipher != OVPN_CIPHER_ALG_NONE)
637 {
638 NLA_PUT(nl_msg, OVPN_A_KEYDIR_CIPHER_KEY, (int)key_len, encrypt_key);
639 NLA_PUT(nl_msg, OVPN_A_KEYDIR_NONCE_TAIL, nonce_tail_len, encrypt_iv);
640 }
641 nla_nest_end(nl_msg, key_enc);
642
643 struct nlattr *key_dec = nla_nest_start(nl_msg, OVPN_A_KEYCONF_DECRYPT_DIR);
644 if (dco_cipher != OVPN_CIPHER_ALG_NONE)
645 {
646 NLA_PUT(nl_msg, OVPN_A_KEYDIR_CIPHER_KEY, (int)key_len, decrypt_key);
647 NLA_PUT(nl_msg, OVPN_A_KEYDIR_NONCE_TAIL, nonce_tail_len, decrypt_iv);
648 }
649 nla_nest_end(nl_msg, key_dec);
650
651 nla_nest_end(nl_msg, key_conf);
652
653
654 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
655
656nla_put_failure:
657 nlmsg_free(nl_msg);
658 return ret;
659}
660
661int
662dco_set_peer(dco_context_t *dco, unsigned int peerid, int keepalive_interval, int keepalive_timeout,
663 int mss)
664{
665 msg(D_DCO_DEBUG, "%s: peer-id %d, keepalive %d/%d, mss %d", __func__, peerid,
666 keepalive_interval, keepalive_timeout, mss);
667
668 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_SET);
669 if (!nl_msg)
670 {
671 return -ENOMEM;
672 }
673
674 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
675 int ret = -EMSGSIZE;
676 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peerid);
677 NLA_PUT_U32(nl_msg, OVPN_A_PEER_KEEPALIVE_INTERVAL, keepalive_interval);
678 NLA_PUT_U32(nl_msg, OVPN_A_PEER_KEEPALIVE_TIMEOUT, keepalive_timeout);
679 nla_nest_end(nl_msg, attr);
680
681 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
682
683nla_put_failure:
684 nlmsg_free(nl_msg);
685 return ret;
686}
687
688/* This function parses the reply provided by the kernel to the CTRL_CMD_GETFAMILY
689 * message. We parse the reply and we retrieve the multicast group ID associated
690 * with the "ovpn-dco" netlink family.
691 *
692 * The ID is later used to subscribe to the multicast group and be notified
693 * about any multicast message sent by the ovpn-dco kernel module.
694 */
695static int
696mcast_family_handler(struct nl_msg *msg, void *arg)
697{
698 dco_context_t *dco = arg;
699 struct nlattr *tb[CTRL_ATTR_MAX + 1];
700 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
701
702 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
703
704 if (!tb[CTRL_ATTR_MCAST_GROUPS])
705 {
706 return NL_SKIP;
707 }
708
709 struct nlattr *mcgrp;
710 int rem_mcgrp;
711 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp)
712 {
713 struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
714
715 nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp), nla_len(mcgrp), NULL);
716
717 if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
718 {
719 continue;
720 }
721
722 if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]), OVPN_MCGRP_PEERS,
723 nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]))
724 != 0)
725 {
726 continue;
727 }
728 dco->ovpn_dco_mcast_id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
729 break;
730 }
731
732 return NL_SKIP;
733}
739static int
740ovpn_get_mcast_id(dco_context_t *dco)
741{
742 dco->ovpn_dco_mcast_id = -ENOENT;
743
744 /* Even though 'nlctrl' is a constant, there seem to be no library
745 * provided define for it */
746 dco->ctrlid = genl_ctrl_resolve(dco->nl_sock, "nlctrl");
747
748 struct nl_msg *nl_msg = nlmsg_alloc();
749 if (!nl_msg)
750 {
751 return -ENOMEM;
752 }
753
754 genlmsg_put(nl_msg, 0, 0, dco->ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
755
756 int ret = -EMSGSIZE;
757 NLA_PUT_STRING(nl_msg, CTRL_ATTR_FAMILY_NAME, OVPN_FAMILY_NAME);
758
759 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
760
761nla_put_failure:
762 nlmsg_free(nl_msg);
763 return ret;
764}
765
766static bool
767ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out)
768{
769 if (!attrs[OVPN_A_PEER_REMOTE_PORT])
770 {
771 msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message");
772 return false;
773 }
774
775 if (attrs[OVPN_A_PEER_REMOTE_IPV4])
776 {
777 struct sockaddr_in *addr4 = (struct sockaddr_in *)out;
778 CLEAR(*addr4);
779 addr4->sin_family = AF_INET;
780 addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]);
781 addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]);
782 return true;
783 }
784 else if (attrs[OVPN_A_PEER_REMOTE_IPV6]
785 && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr))
786 {
787 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out;
788 CLEAR(*addr6);
789 addr6->sin6_family = AF_INET6;
790 addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]);
791 memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]),
792 sizeof(addr6->sin6_addr));
794 {
795 addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]);
796 }
797 return true;
798 }
799
800 msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message");
801 return false;
802}
803
804/* libnl < 3.11.0 does not implement nla_get_uint() */
805static uint64_t
806ovpn_nla_get_uint(struct nlattr *attr)
807{
808 if (nla_len(attr) == sizeof(uint32_t))
809 {
810 return nla_get_u32(attr);
811 }
812 else
813 {
814 return nla_get_u64(attr);
815 }
816}
817
818static void
819dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id)
820{
822 {
823 c2->dco_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_RX_BYTES]);
824 msg(D_DCO_DEBUG, "%s / dco_read_bytes: " counter_format, __func__, c2->dco_read_bytes);
825 }
826 else
827 {
828 msg(M_WARN, "%s: no link RX bytes provided in reply for peer %u", __func__, id);
829 }
830
832 {
833 c2->dco_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_TX_BYTES]);
834 msg(D_DCO_DEBUG, "%s / dco_write_bytes: " counter_format, __func__, c2->dco_write_bytes);
835 }
836 else
837 {
838 msg(M_WARN, "%s: no link TX bytes provided in reply for peer %u", __func__, id);
839 }
840
842 {
843 c2->tun_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_RX_BYTES]);
844 msg(D_DCO_DEBUG, "%s / tun_read_bytes: " counter_format, __func__, c2->tun_read_bytes);
845 }
846 else
847 {
848 msg(M_WARN, "%s: no VPN RX bytes provided in reply for peer %u", __func__, id);
849 }
850
852 {
853 c2->tun_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_TX_BYTES]);
854 msg(D_DCO_DEBUG, "%s / tun_write_bytes: " counter_format, __func__, c2->tun_write_bytes);
855 }
856 else
857 {
858 msg(M_WARN, "%s: no VPN TX bytes provided in reply for peer %u", __func__, id);
859 }
860}
861
862static int
863ovpn_handle_peer(dco_context_t *dco, struct nlattr *attrs[])
864{
865 if (!attrs[OVPN_A_PEER])
866 {
867 msg(D_DCO_DEBUG, "%s: malformed reply", __func__);
868 return NL_SKIP;
869 }
870
871 struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1];
872 nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL);
873
874 if (!tb_peer[OVPN_A_PEER_ID])
875 {
876 msg(M_WARN, "ovpn-dco: no peer-id provided in PEER_GET reply");
877 return NL_SKIP;
878 }
879
880 uint32_t peer_id = nla_get_u32(tb_peer[OVPN_A_PEER_ID]);
881 struct context_2 *c2;
882
883 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: parsing message for peer %u...", __func__, peer_id);
884
885 if (dco->ifmode == OVPN_MODE_P2P)
886 {
887 c2 = &dco->c->c2;
888 if (c2->tls_multi->dco_peer_id != (int)peer_id)
889 {
890 return NL_SKIP;
891 }
892 }
893 else
894 {
895 if (peer_id >= dco->c->multi->max_clients)
896 {
897 msg(M_WARN, "%s: received out of bound peer_id %u (max=%u)", __func__, peer_id,
898 dco->c->multi->max_clients);
899 return NL_SKIP;
900 }
901
902 struct multi_instance *mi = dco->c->multi->instances[peer_id];
903 if (!mi)
904 {
905 msg(M_WARN | M_NOIPREFIX, "%s: received data for a non-existing peer %u", __func__, peer_id);
906 return NL_SKIP;
907 }
908
909 c2 = &mi->context.c2;
910 }
911
912 dco_update_peer_stat(c2, tb_peer, peer_id);
913
914 return NL_OK;
915}
916
917static bool
918ovpn_iface_check(dco_context_t *dco, struct nlattr *attrs[])
919{
920 /* we must know which interface this message is referring to in order to
921 * avoid mixing messages for other instances
922 */
923 if (!attrs[OVPN_A_IFINDEX])
924 {
925 msg(D_DCO, "ovpn-dco: Received message without ifindex");
926 return false;
927 }
928
929 uint32_t ifindex = nla_get_u32(attrs[OVPN_A_IFINDEX]);
930 if (ifindex != dco->ifindex)
931 {
932 msg(D_DCO_DEBUG, "ovpn-dco: ignoring message for foreign ifindex %d", ifindex);
933 return false;
934 }
935
936 return true;
937}
938
939static int
940ovpn_handle_peer_del_ntf(dco_context_t *dco, struct nlattr *attrs[])
941{
942 if (!ovpn_iface_check(dco, attrs))
943 {
944 return NL_STOP;
945 }
946
947 if (!attrs[OVPN_A_PEER])
948 {
949 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no peer in PEER_DEL_NTF message");
950 return NL_STOP;
951 }
952
953 struct nlattr *dp_attrs[OVPN_A_PEER_MAX + 1];
954 if (nla_parse_nested(dp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL))
955 {
956 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: can't parse peer in PEER_DEL_NTF messsage");
957 return NL_STOP;
958 }
959
960 if (!dp_attrs[OVPN_A_PEER_DEL_REASON])
961 {
962 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no reason in PEER_DEL_NTF message");
963 return NL_STOP;
964 }
965 if (!dp_attrs[OVPN_A_PEER_ID])
966 {
967 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no peer-id in PEER_DEL_NTF message");
968 return NL_STOP;
969 }
970
971 int reason = nla_get_u32(dp_attrs[OVPN_A_PEER_DEL_REASON]);
972 unsigned int peerid = nla_get_u32(dp_attrs[OVPN_A_PEER_ID]);
973
974 msg(D_DCO_DEBUG | M_NOIPREFIX, "ovpn-dco: received CMD_PEER_DEL_NTF, ifindex: %d, peer-id %u, reason: %d",
975 dco->ifindex, peerid, reason);
976 dco->dco_message_peer_id = peerid;
977 dco->dco_del_peer_reason = reason;
978 dco->dco_message_type = OVPN_CMD_PEER_DEL_NTF;
979
980 return NL_OK;
981}
982
983static int
984ovpn_handle_peer_float_ntf(dco_context_t *dco, struct nlattr *attrs[])
985{
986 if (!ovpn_iface_check(dco, attrs))
987 {
988 return NL_STOP;
989 }
990
991 if (!attrs[OVPN_A_PEER])
992 {
993 msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message");
994 return NL_STOP;
995 }
996
997 struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1];
998 if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL))
999 {
1000 msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage");
1001 return NL_STOP;
1002 }
1003
1004 if (!fp_attrs[OVPN_A_PEER_ID])
1005 {
1006 msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message");
1007 return NL_STOP;
1008 }
1009 uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]);
1010
1011 if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss))
1012 {
1013 return NL_STOP;
1014 }
1015
1016 struct gc_arena gc = gc_new();
1017 msg(D_DCO_DEBUG, "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s",
1018 dco->ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc));
1019 dco->dco_message_peer_id = (int)peerid;
1020 dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF;
1021
1022 gc_free(&gc);
1023
1024 return NL_OK;
1025}
1026
1027static int
1028ovpn_handle_key_swap_ntf(dco_context_t *dco, struct nlattr *attrs[])
1029{
1030 if (!ovpn_iface_check(dco, attrs))
1031 {
1032 return NL_STOP;
1033 }
1034
1035 if (!attrs[OVPN_A_KEYCONF])
1036 {
1037 msg(D_DCO, "ovpn-dco: no keyconf in KEY_SWAP_NTF message");
1038 return NL_STOP;
1039 }
1040
1041 struct nlattr *dp_attrs[OVPN_A_KEYCONF_MAX + 1];
1042 if (nla_parse_nested(dp_attrs, OVPN_A_KEYCONF_MAX, attrs[OVPN_A_KEYCONF], NULL))
1043 {
1044 msg(D_DCO, "ovpn-dco: can't parse keyconf in KEY_SWAP_NTF message");
1045 return NL_STOP;
1046 }
1047 if (!dp_attrs[OVPN_A_KEYCONF_PEER_ID])
1048 {
1049 msg(D_DCO, "ovpn-dco: no peer-id in KEY_SWAP_NTF message");
1050 return NL_STOP;
1051 }
1052 if (!dp_attrs[OVPN_A_KEYCONF_KEY_ID])
1053 {
1054 msg(D_DCO, "ovpn-dco: no key-id in KEY_SWAP_NTF message");
1055 return NL_STOP;
1056 }
1057
1058 int key_id = nla_get_u16(dp_attrs[OVPN_A_KEYCONF_KEY_ID]);
1059 unsigned int peer_id = nla_get_u32(dp_attrs[OVPN_A_KEYCONF_PEER_ID]);
1060
1061 msg(D_DCO_DEBUG, "ovpn-dco: received CMD_KEY_SWAP_NTF, ifindex: %d, peer-id %u, key-id: %d",
1062 dco->ifindex, peer_id, key_id);
1063 dco->dco_message_peer_id = peer_id;
1064 dco->dco_message_key_id = key_id;
1065 dco->dco_message_type = OVPN_CMD_KEY_SWAP_NTF;
1066
1067 return NL_OK;
1068}
1069
1070/* This function parses any netlink message sent by ovpn-dco to userspace */
1071static int
1072ovpn_handle_msg(struct nl_msg *msg, void *arg)
1073{
1074 dco_context_t *dco = arg;
1075
1076 struct nlattr *attrs[OVPN_A_MAX + 1];
1077 struct nlmsghdr *nlh = nlmsg_hdr(msg);
1078 struct genlmsghdr *gnlh = genlmsg_hdr(nlh);
1079
1080 msg(D_DCO_DEBUG | M_NOIPREFIX, "ovpn-dco: received netlink message type=%u cmd=%u flags=%#.4x",
1081 nlh->nlmsg_type, gnlh->cmd, nlh->nlmsg_flags);
1082
1083 /* if we get a message from the NLCTRL family, it means
1084 * this is the reply to the mcast ID resolution request
1085 * and we parse it accordingly.
1086 */
1087 if (nlh->nlmsg_type == dco->ctrlid)
1088 {
1089 msg(D_DCO_DEBUG, "ovpn-dco: received CTRLID message");
1090 return mcast_family_handler(msg, dco);
1091 }
1092
1093 if (!genlmsg_valid_hdr(nlh, 0))
1094 {
1095 msg(D_DCO, "ovpn-dco: invalid header");
1096 return NL_STOP;
1097 }
1098
1099 if (nla_parse(attrs, OVPN_A_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL))
1100 {
1101 msg(D_DCO, "received bogus data from ovpn-dco");
1102 return NL_STOP;
1103 }
1104
1105 /* based on the message type, we parse the subobject contained in the
1106 * message, that stores the type-specific attributes.
1107 *
1108 * the "dco" object is then filled accordingly with the information
1109 * retrieved from the message, so that *process_incoming_dco can react
1110 * as need be.
1111 */
1112 int ret;
1113 switch (gnlh->cmd)
1114 {
1115 case OVPN_CMD_PEER_GET:
1116 {
1117 /* return directly, there are no messages to pass to *process_incoming_dco() */
1118 return ovpn_handle_peer(dco, attrs);
1119 }
1120
1122 {
1123 ret = ovpn_handle_peer_del_ntf(dco, attrs);
1124 break;
1125 }
1126
1128 {
1129 ret = ovpn_handle_peer_float_ntf(dco, attrs);
1130 break;
1131 }
1132
1134 {
1135 ret = ovpn_handle_key_swap_ntf(dco, attrs);
1136 break;
1137 }
1138
1139 default:
1140 msg(D_DCO, "ovpn-dco: received unknown command: %d", gnlh->cmd);
1141 dco->dco_message_type = 0;
1142 return NL_STOP;
1143 }
1144
1145 if (ret != NL_OK)
1146 {
1147 return ret;
1148 }
1149
1150 if (dco->c->mode == CM_TOP)
1151 {
1153 }
1154 else
1155 {
1157 }
1158
1159 return NL_OK;
1160}
1161
1162int
1164{
1165 msg(D_DCO_DEBUG, __func__);
1166
1167 return ovpn_nl_recvmsgs(dco, __func__);
1168}
1169
1170static int
1171dco_get_peer(dco_context_t *dco, int peer_id, const bool raise_sigusr1_on_err)
1172{
1173 ASSERT(dco);
1174
1175 if (__is_locked)
1176 {
1177 msg(D_DCO_DEBUG, "%s: cannot request peer stats while parsing other messages", __func__);
1178 return 0;
1179 }
1180
1181 /* peer_id == -1 means "dump all peers", but this is allowed in MP mode only.
1182 * If it happens in P2P mode it means that the DCO peer was deleted and we
1183 * can simply bail out
1184 */
1185 if (peer_id == -1 && dco->ifmode == OVPN_MODE_P2P)
1186 {
1187 return 0;
1188 }
1189
1190 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: peer-id %d", __func__, peer_id);
1191
1192 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_GET);
1193 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
1194 int ret = -EMSGSIZE;
1195
1196 if (peer_id != -1)
1197 {
1198 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peer_id);
1199 }
1200 else
1201 {
1202 nlmsg_hdr(nl_msg)->nlmsg_flags |= NLM_F_DUMP;
1203 }
1204 nla_nest_end(nl_msg, attr);
1205
1206 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
1207
1208nla_put_failure:
1209 nlmsg_free(nl_msg);
1210
1211 if (raise_sigusr1_on_err && ret < 0)
1212 {
1213 msg(M_WARN, "Error retrieving DCO peer stats: the underlying DCO peer"
1214 "may have been deleted from the kernel without notifying "
1215 "userspace. Restarting the session");
1216 register_signal(dco->c->sig, SIGUSR1, "dco peer stats error");
1217 }
1218 return ret;
1219}
1220
1221int
1222dco_get_peer_stats(struct context *c, const bool raise_sigusr1_on_err)
1223{
1224 if (!c->c1.tuntap || c->c1.tuntap->dco.ifindex == 0)
1225 {
1226 return -1;
1227 }
1228
1229 return dco_get_peer(&c->c1.tuntap->dco, c->c2.tls_multi->dco_peer_id, raise_sigusr1_on_err);
1230}
1231
1232int
1233dco_get_peer_stats_multi(dco_context_t *dco, const bool raise_sigusr1_on_err)
1234{
1235 return dco_get_peer(dco, -1, raise_sigusr1_on_err);
1236}
1237
1238bool
1239dco_available(msglvl_t msglevel)
1240{
1241 if (resolve_ovpn_netlink_id(D_DCO_DEBUG) < 0)
1242 {
1243 msg(msglevel, "Note: Kernel support for ovpn interfaces missing, "
1244 "disabling data channel offload. Use Linux 6.16.0 or "
1245 "newer with ovpn support or use ovpn-backports for "
1246 "interface support.");
1247 return false;
1248 }
1249
1250 return true;
1251}
1252
1257static const char *
1258dco_version_string_in_tree(struct gc_arena *gc)
1259{
1260 struct buffer buf = alloc_buf_gc(256, gc);
1261 struct utsname system;
1262
1263 if (uname(&system))
1264 {
1265 return "ERR";
1266 }
1267
1268 buf_puts(&buf, system.release);
1269 buf_puts(&buf, " ");
1270 buf_puts(&buf, system.version);
1271 return BSTR(&buf);
1272}
1273
1280static const char *
1281dco_version_string_backports(FILE *fp, struct gc_arena *gc)
1282{
1283 char *str = gc_malloc(PATH_MAX, false, gc);
1284
1285 if (!fgets(str, PATH_MAX, fp))
1286 {
1287 return "ERR";
1288 }
1289
1290 /* remove potential newline at the end of the string */
1291 char *nl = strchr(str, '\n');
1292 if (nl)
1293 {
1294 *nl = '\0';
1295 }
1296
1297 return str;
1298}
1299
1300const char *
1302{
1303 const char *version;
1304 struct stat sb;
1305 FILE *fp;
1306
1307 if (stat("/sys/module/ovpn", &sb) != 0 || !S_ISDIR(sb.st_mode))
1308 {
1309 return "N/A";
1310 }
1311
1312 /* now that we know for sure that the module is loaded, if there's no
1313 * version file it means we're dealing with the in-tree version, otherwise
1314 * it's backports */
1315 fp = fopen("/sys/module/ovpn/version", "r");
1316 if (!fp)
1317 {
1318 return dco_version_string_in_tree(gc);
1319 }
1320 version = dco_version_string_backports(fp, gc);
1321
1322 fclose(fp);
1323 return version;
1324}
1325
1326void
1327dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
1328{
1329 if (dco && dco->nl_sock)
1330 {
1331 event_ctl(es, nl_socket_get_fd(dco->nl_sock), EVENT_READ, arg);
1332 }
1333}
1334
1335const char *
1337{
1338 return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305";
1339}
1340
1341bool
1343{
1344 return false;
1345}
1346
1347#endif /* defined(ENABLE_DCO) && defined(TARGET_LINUX) */
bool buf_puts(struct buffer *buf, const char *str)
Definition buffer.c:268
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition buffer.c:336
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:89
#define BSTR(buf)
Definition buffer.h:129
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition buffer.h:1125
static void gc_free(struct gc_arena *a)
Definition buffer.h:1049
static struct gc_arena gc_new(void)
Definition buffer.h:1041
#define counter_format
Definition common.h:32
unsigned int cipher_kt_key_size(const char *ciphername)
Returns the size of keys used by the cipher, in bytes.
static int dco_get_peer_stats_multi(dco_context_t *dco, const bool raise_sigusr1_on_err)
Definition dco.h:369
static int dco_set_peer(dco_context_t *dco, unsigned int peerid, int keepalive_interval, int keepalive_timeout, int mss)
Definition dco.h:341
static const char * dco_get_supported_ciphers(void)
Definition dco.h:381
static bool dco_supports_epoch_data(struct context *c)
Definition dco.h:387
static void dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
Definition dco.h:316
static int open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev)
Definition dco.h:298
static int dco_read_and_process(dco_context_t *dco)
Definition dco.h:309
static bool dco_available(msglvl_t msglevel)
Definition dco.h:262
static bool ovpn_dco_init(struct context *c)
Definition dco.h:292
void * dco_context_t
Definition dco.h:259
static const char * dco_version_string(struct gc_arena *gc)
Definition dco.h:268
static void close_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx)
Definition dco.h:304
static int dco_get_peer_stats(struct context *c, const bool raise_sigusr1_on_err)
Definition dco.h:375
int dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot)
Definition dco_win.c:584
int dco_del_peer(dco_context_t *dco, unsigned int peerid)
Definition dco_win.c:469
int dco_new_peer(dco_context_t *dco, unsigned int peerid, socket_descriptor_t sd, struct sockaddr *localaddr, struct sockaddr *remoteaddr, struct in_addr *vpn_ipv4, struct in6_addr *vpn_ipv6)
Definition dco_win.c:418
int dco_swap_keys(dco_context_t *dco, unsigned int peer_id)
Definition dco_win.c:592
int dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t slot, const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, const uint8_t *decrypt_iv, const char *ciphername, bool epoch)
Definition dco_win.c:529
#define D_DCO
Definition errlevel.h:93
#define D_DCO_DEBUG
Definition errlevel.h:117
#define M_INFO
Definition errlevel.h:54
#define EVENT_READ
Definition event.h:37
static void event_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
Definition event.h:180
void set_nonblock(socket_descriptor_t fd)
Definition fdmisc.c:68
void set_cloexec(socket_descriptor_t fd)
Definition fdmisc.c:78
void process_incoming_dco(dco_context_t *dco)
Process an incoming DCO message (from kernel space).
Definition forward.c:1247
static SERVICE_STATUS status
Definition interactive.c:51
Header file for server-mode related structures and functions.
void multi_process_incoming_dco(dco_context_t *dco)
Process an incoming DCO message (from kernel space).
void * openvpn_net_ctx_t
Definition networking.h:38
#define CLEAR(x)
Definition basic.h:32
#define M_NOIPREFIX
Definition error.h:103
#define M_FATAL
Definition error.h:90
#define M_NONFATAL
Definition error.h:91
#define msg(flags,...)
Definition error.h:152
unsigned int msglvl_t
Definition error.h:77
#define ASSERT(x)
Definition error.h:219
#define M_WARN
Definition error.h:92
#define CM_P2P
Definition openvpn.h:479
#define CM_TOP
Definition openvpn.h:480
@ OVPN_CIPHER_ALG_NONE
@ OVPN_A_KEYCONF
@ OVPN_A_MAX
@ OVPN_A_PEER
@ OVPN_A_IFINDEX
@ OVPN_CMD_PEER_FLOAT_NTF
@ OVPN_CMD_KEY_DEL
@ OVPN_CMD_PEER_NEW
@ OVPN_CMD_PEER_GET
@ OVPN_CMD_KEY_SWAP
@ OVPN_CMD_KEY_SWAP_NTF
@ OVPN_CMD_PEER_DEL_NTF
@ OVPN_CMD_PEER_SET
@ OVPN_CMD_KEY_NEW
@ OVPN_CMD_PEER_DEL
@ OVPN_A_PEER_LINK_RX_BYTES
@ OVPN_A_PEER_VPN_IPV6
@ OVPN_A_PEER_LINK_TX_BYTES
@ OVPN_A_PEER_VPN_IPV4
@ OVPN_A_PEER_KEEPALIVE_TIMEOUT
@ OVPN_A_PEER_VPN_TX_BYTES
@ OVPN_A_PEER_LOCAL_IPV6
@ OVPN_A_PEER_REMOTE_IPV6
@ OVPN_A_PEER_VPN_RX_BYTES
@ OVPN_A_PEER_MAX
@ OVPN_A_PEER_LOCAL_IPV4
@ OVPN_A_PEER_DEL_REASON
@ OVPN_A_PEER_ID
@ OVPN_A_PEER_SOCKET
@ OVPN_A_PEER_REMOTE_IPV4
@ OVPN_A_PEER_KEEPALIVE_INTERVAL
@ OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID
@ OVPN_A_PEER_REMOTE_PORT
#define OVPN_FAMILY_NAME
#define OVPN_MCGRP_PEERS
@ OVPN_A_KEYCONF_SLOT
@ OVPN_A_KEYCONF_PEER_ID
@ OVPN_A_KEYCONF_MAX
@ OVPN_A_KEYCONF_DECRYPT_DIR
@ OVPN_A_KEYCONF_CIPHER_ALG
@ OVPN_A_KEYCONF_ENCRYPT_DIR
@ OVPN_A_KEYCONF_KEY_ID
@ OVPN_A_KEYDIR_CIPHER_KEY
@ OVPN_A_KEYDIR_NONCE_TAIL
@ OVPN_MODE_MP
@ OVPN_MODE_P2P
#define DEV_TYPE_TUN
Definition proto.h:35
void register_signal(struct signal_info *si, int signum, const char *signal_text)
Register a soft signal in the signal_info struct si respecting priority.
Definition sig.c:228
static const char * print_sockaddr(const struct sockaddr *addr, struct gc_arena *gc)
Definition socket_util.h:77
Control Channel SSL/Data channel negotiation module.
Control Channel Verification Module.
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
struct tuntap * tuntap
Tun/tap virtual network interface.
Definition openvpn.h:172
Level 2 context containing state that is reset on both SIGHUP and SIGUSR1 restarts.
Definition openvpn.h:224
counter_type dco_read_bytes
Definition openvpn.h:267
counter_type tun_read_bytes
Definition openvpn.h:264
counter_type dco_write_bytes
Definition openvpn.h:270
struct tls_multi * tls_multi
TLS state structure for this VPN tunnel.
Definition openvpn.h:323
counter_type tun_write_bytes
Definition openvpn.h:265
Contains all state information for one tunnel.
Definition openvpn.h:471
int mode
Role of this context within the OpenVPN process.
Definition openvpn.h:484
struct context_2 c2
Level 2 context.
Definition openvpn.h:514
struct context_1 c1
Level 1 context.
Definition openvpn.h:513
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
Container for two sets of OpenSSL cipher and/or HMAC contexts for both sending and receiving directio...
Definition crypto.h:280
Container for unidirectional cipher and HMAC key material.
Definition crypto.h:152
Server-mode state structure for one single VPN tunnel.
Definition multi.h:102
struct context context
The context structure storing state for this VPN tunnel.
Definition multi.h:142
int dco_peer_id
This is the handle that DCO uses to identify this session with the kernel.
Definition ssl_common.h:724
Definition tun.h:181
int type
Definition tun.h:183
dco_context_t dco
Definition tun.h:247
char * actual_name
Definition tun.h:205
#define SIGUSR1
Definition syshead.h:57
__attribute__((unused))
Definition test.c:42
struct env_set * es
struct gc_arena gc
Definition test_ssl.c:133