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, const struct in_addr *vpn_ipv4,
226 const struct in6_addr *vpn_ipv6)
227{
228 struct gc_arena gc = gc_new();
229 const char *remotestr = "[undefined]";
230 if (remoteaddr)
231 {
232 remotestr = print_sockaddr(remoteaddr, &gc);
233 }
234 msg(D_DCO_DEBUG, "%s: peer-id %d, fd %d, remote addr: %s", __func__, peerid, sd, remotestr);
235
236 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_NEW);
237 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
238 int ret = -EMSGSIZE;
239
240 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peerid);
241 NLA_PUT_U32(nl_msg, OVPN_A_PEER_SOCKET, sd);
242
243 /* Set the remote endpoint if defined (for UDP) */
244 if (remoteaddr)
245 {
246 remoteaddr = mapped_v4_to_v6(remoteaddr, &gc);
247
248 if (remoteaddr->sa_family == AF_INET)
249 {
250 NLA_PUT(nl_msg, OVPN_A_PEER_REMOTE_IPV4, sizeof(struct in_addr),
251 &((struct sockaddr_in *)remoteaddr)->sin_addr);
252 NLA_PUT_U16(nl_msg, OVPN_A_PEER_REMOTE_PORT,
253 ((struct sockaddr_in *)remoteaddr)->sin_port);
254 }
255 else if (remoteaddr->sa_family == AF_INET6)
256 {
257 NLA_PUT(nl_msg, OVPN_A_PEER_REMOTE_IPV6, sizeof(struct in6_addr),
258 &((struct sockaddr_in6 *)remoteaddr)->sin6_addr);
259 NLA_PUT_U16(nl_msg, OVPN_A_PEER_REMOTE_PORT,
260 ((struct sockaddr_in6 *)remoteaddr)->sin6_port);
261 NLA_PUT_U32(nl_msg, OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID,
262 ((struct sockaddr_in6 *)remoteaddr)->sin6_scope_id);
263 }
264 }
265
266 if (localaddr)
267 {
268 localaddr = mapped_v4_to_v6(localaddr, &gc);
269 if (localaddr->sa_family == AF_INET)
270 {
271 NLA_PUT(nl_msg, OVPN_A_PEER_LOCAL_IPV4, sizeof(struct in_addr),
272 &((struct sockaddr_in *)localaddr)->sin_addr);
273 }
274 else if (localaddr->sa_family == AF_INET6)
275 {
276 NLA_PUT(nl_msg, OVPN_A_PEER_LOCAL_IPV6, sizeof(struct in6_addr),
277 &((struct sockaddr_in6 *)localaddr)->sin6_addr);
278 }
279 }
280
281 /* Set the primary VPN IP addresses of the peer */
282 if (vpn_ipv4)
283 {
284 NLA_PUT_U32(nl_msg, OVPN_A_PEER_VPN_IPV4, vpn_ipv4->s_addr);
285 }
286 if (vpn_ipv6)
287 {
288 NLA_PUT(nl_msg, OVPN_A_PEER_VPN_IPV6, sizeof(struct in6_addr), vpn_ipv6);
289 }
290 nla_nest_end(nl_msg, attr);
291
292 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
293
294nla_put_failure:
295 nlmsg_free(nl_msg);
296 gc_free(&gc);
297 return ret;
298}
299
300static int
301ovpn_nl_cb_finish(struct nl_msg(*msg) __attribute__((unused)), void *arg)
302{
303 int *status = arg;
304
305 *status = 0;
306 return NL_SKIP;
307}
308
309/* The following enum members exist in netlink.h since linux-6.1.
310 * However, some distro we support still ship an old header, thus
311 * failing the OpenVPN compilation.
312 *
313 * For the time being we add the needed defines manually.
314 * We will drop this definition once we stop supporting those old
315 * distros.
316 *
317 * @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute,
318 * %NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was
319 * missing at the message level
320 * @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing
321 */
322enum ovpn_nlmsgerr_attrs
323{
324 OVPN_NLMSGERR_ATTR_MISS_TYPE = 5,
325 OVPN_NLMSGERR_ATTR_MISS_NEST = 6,
326 OVPN_NLMSGERR_ATTR_MAX = 6,
327};
328
329/* This function is used as error callback on the netlink socket.
330 * When something goes wrong and the kernel returns an error, this function is
331 * invoked.
332 *
333 * We pass the error code to the user by means of a variable pointed by *arg
334 * (supplied by the user when setting this callback) and we parse the kernel
335 * reply to see if it contains a human-readable error. If found, it is printed.
336 */
337static int
338ovpn_nl_cb_error(struct sockaddr_nl(*nla) __attribute__((unused)), struct nlmsgerr *err, void *arg)
339{
340 struct nlmsghdr *nlh = (struct nlmsghdr *)err - 1;
341 struct nlattr *tb_msg[OVPN_NLMSGERR_ATTR_MAX + 1];
342 int len = nlh->nlmsg_len;
343 struct nlattr *attrs;
344 int *ret = arg;
345 int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh);
346
347 *ret = err->error;
348
349 if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
350 {
351 return NL_STOP;
352 }
353
354 if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
355 {
356 ack_len += err->msg.nlmsg_len - (int)sizeof(*nlh);
357 }
358
359 if (len <= ack_len)
360 {
361 return NL_STOP;
362 }
363
364 attrs = (void *)((unsigned char *)nlh + ack_len);
365 len -= ack_len;
366
367 nla_parse(tb_msg, OVPN_NLMSGERR_ATTR_MAX, attrs, len, NULL);
368 if (tb_msg[NLMSGERR_ATTR_MSG])
369 {
370 len = (int)strnlen((char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]),
371 nla_len(tb_msg[NLMSGERR_ATTR_MSG]));
372 msg(M_WARN, "kernel error: %*s", len, (char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]));
373 }
374
375 if (tb_msg[OVPN_NLMSGERR_ATTR_MISS_NEST])
376 {
377 msg(M_WARN, "kernel error: missing required nesting type %u",
378 nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_NEST]));
379 }
380
381 if (tb_msg[OVPN_NLMSGERR_ATTR_MISS_TYPE])
382 {
383 msg(M_WARN, "kernel error: missing required attribute type %u",
384 nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_TYPE]));
385 }
386
387 return NL_STOP;
388}
389
390static void
391ovpn_dco_register(dco_context_t *dco)
392{
393 msg(D_DCO_DEBUG, __func__);
394 ovpn_get_mcast_id(dco);
395
396 if (dco->ovpn_dco_mcast_id < 0)
397 {
398 msg(M_FATAL, "cannot get mcast group: %s", nl_geterror(dco->ovpn_dco_mcast_id));
399 }
400
401 /* Register for ovpn-dco specific multicast messages that the kernel may
402 * send
403 */
404 int ret = nl_socket_add_membership(dco->nl_sock, dco->ovpn_dco_mcast_id);
405 if (ret)
406 {
407 msg(M_FATAL, "%s: failed to join groups: %d", __func__, ret);
408 }
409}
410
411static int ovpn_handle_msg(struct nl_msg *msg, void *arg);
412
413static void
414ovpn_dco_init_netlink(dco_context_t *dco)
415{
416 dco->ovpn_dco_id = resolve_ovpn_netlink_id(M_FATAL);
417
418 dco->nl_sock = nl_socket_alloc();
419
420 if (!dco->nl_sock)
421 {
422 msg(M_FATAL, "Cannot create netlink socket");
423 }
424
425 int ret = genl_connect(dco->nl_sock);
426 if (ret)
427 {
428 msg(M_FATAL, "Cannot connect to generic netlink: %s", nl_geterror(ret));
429 }
430
431 /* enable Extended ACK for detailed error reporting */
432 ret = 1;
433 setsockopt(nl_socket_get_fd(dco->nl_sock), SOL_NETLINK, NETLINK_EXT_ACK, &ret, sizeof(ret));
434
435 /* set close on exec and non-block on the netlink socket */
436 set_cloexec(nl_socket_get_fd(dco->nl_sock));
437 set_nonblock(nl_socket_get_fd(dco->nl_sock));
438
439 dco->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
440 if (!dco->nl_cb)
441 {
442 msg(M_FATAL, "failed to allocate netlink callback");
443 }
444
445 nl_socket_set_cb(dco->nl_sock, dco->nl_cb);
446
447 dco->dco_message_peer_id = -1;
448 nl_cb_err(dco->nl_cb, NL_CB_CUSTOM, ovpn_nl_cb_error, &dco->status);
449 nl_cb_set(dco->nl_cb, NL_CB_FINISH, NL_CB_CUSTOM, ovpn_nl_cb_finish, &dco->status);
450 nl_cb_set(dco->nl_cb, NL_CB_ACK, NL_CB_CUSTOM, ovpn_nl_cb_finish, &dco->status);
451 nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, ovpn_handle_msg, dco);
452
453 ovpn_dco_register(dco);
454
455 /* The async PACKET messages confuse libnl and it will drop them with
456 * wrong sequence numbers (NLE_SEQ_MISMATCH), so disable libnl's sequence
457 * number check */
458 nl_socket_disable_seq_check(dco->nl_sock);
459
460 /* nl library sets the buffer size to 32k/32k by default which is sometimes
461 * overrun with very fast connecting/disconnecting clients.
462 * TODO: fix this in a better and more reliable way */
463 ASSERT(!nl_socket_set_buffer_size(dco->nl_sock, 1024 * 1024, 1024 * 1024));
464}
465
466bool
467ovpn_dco_init(struct context *c)
468{
469 dco_context_t *dco = &c->c1.tuntap->dco;
470
471 switch (c->mode)
472 {
473 case CM_TOP:
474 dco->ifmode = OVPN_MODE_MP;
475 break;
476
477 case CM_P2P:
478 dco->ifmode = OVPN_MODE_P2P;
479 break;
480
481 default:
482 ASSERT(false);
483 }
484
485 /* store pointer to context as it may be required by message
486 * parsing routines
487 */
488 dco->c = c;
489 ovpn_dco_init_netlink(dco);
490 return true;
491}
492
493static void
494ovpn_dco_uninit_netlink(dco_context_t *dco)
495{
496 nl_socket_free(dco->nl_sock);
497 dco->nl_sock = NULL;
498
499 /* Decrease reference count */
500 nl_cb_put(dco->nl_cb);
501
502 CLEAR(dco);
503}
504
505int
506open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev)
507{
508 msg(D_DCO_DEBUG, "%s: %s", __func__, dev);
509 ASSERT(tt->type == DEV_TYPE_TUN);
510
511 int ret = net_iface_new(ctx, dev, OVPN_FAMILY_NAME, &tt->dco);
512 if (ret < 0)
513 {
514 msg(D_DCO_DEBUG, "Cannot create DCO interface %s: %d", dev, ret);
515 return ret;
516 }
517
518 tt->dco.ifindex = if_nametoindex(dev);
519 if (!tt->dco.ifindex)
520 {
521 msg(M_FATAL, "DCO: cannot retrieve ifindex for interface %s", dev);
522 }
523
524 return 0;
525}
526
527void
528close_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx)
529{
530 msg(D_DCO_DEBUG, __func__);
531
532 net_iface_del(ctx, tt->actual_name);
533 ovpn_dco_uninit_netlink(&tt->dco);
534}
535
536int
537dco_swap_keys(dco_context_t *dco, unsigned int peerid)
538{
539 msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peerid);
540
541 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_KEY_SWAP);
542 if (!nl_msg)
543 {
544 return -ENOMEM;
545 }
546
547 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_KEYCONF);
548 int ret = -EMSGSIZE;
549 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_PEER_ID, peerid);
550 nla_nest_end(nl_msg, attr);
551
552 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
553
554nla_put_failure:
555 nlmsg_free(nl_msg);
556 return ret;
557}
558
559
560int
561dco_del_peer(dco_context_t *dco, unsigned int peerid)
562{
563 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: peer-id %d", __func__, peerid);
564
565 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_DEL);
566 if (!nl_msg)
567 {
568 return -ENOMEM;
569 }
570
571 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
572 int ret = -EMSGSIZE;
573 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peerid);
574 nla_nest_end(nl_msg, attr);
575
576 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
577
578nla_put_failure:
579 nlmsg_free(nl_msg);
580 return ret;
581}
582
583
584int
585dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot)
586{
587 int ret = -EMSGSIZE;
588 msg(D_DCO_DEBUG, "%s: peer-id %d, slot %d", __func__, peerid, slot);
589
590 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_KEY_DEL);
591 if (!nl_msg)
592 {
593 return -ENOMEM;
594 }
595
596 struct nlattr *keyconf = nla_nest_start(nl_msg, OVPN_A_KEYCONF);
597 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_PEER_ID, peerid);
598 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_SLOT, slot);
599 nla_nest_end(nl_msg, keyconf);
600
601 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
602
603nla_put_failure:
604 nlmsg_free(nl_msg);
605 return ret;
606}
607
608int
609dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t slot,
610 const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key,
611 const uint8_t *decrypt_iv, const char *ciphername, bool epoch)
612{
613 msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s, epoch %d", __func__, slot, keyid, peerid,
614 ciphername, epoch);
615
616 const size_t key_len = cipher_kt_key_size(ciphername);
617 ASSERT(key_len <= INT_MAX);
618 const int nonce_tail_len = 8;
619
620 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_KEY_NEW);
621 if (!nl_msg)
622 {
623 return -ENOMEM;
624 }
625
626 dco_cipher_t dco_cipher = dco_get_cipher(ciphername);
627
628 int ret = -EMSGSIZE;
629
630 struct nlattr *key_conf = nla_nest_start(nl_msg, OVPN_A_KEYCONF);
631 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_PEER_ID, peerid);
632 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_SLOT, slot);
633 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_KEY_ID, keyid);
634 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_CIPHER_ALG, dco_cipher);
635
636 struct nlattr *key_enc = nla_nest_start(nl_msg, OVPN_A_KEYCONF_ENCRYPT_DIR);
637 if (dco_cipher != OVPN_CIPHER_ALG_NONE)
638 {
639 NLA_PUT(nl_msg, OVPN_A_KEYDIR_CIPHER_KEY, (int)key_len, encrypt_key);
640 NLA_PUT(nl_msg, OVPN_A_KEYDIR_NONCE_TAIL, nonce_tail_len, encrypt_iv);
641 }
642 nla_nest_end(nl_msg, key_enc);
643
644 struct nlattr *key_dec = nla_nest_start(nl_msg, OVPN_A_KEYCONF_DECRYPT_DIR);
645 if (dco_cipher != OVPN_CIPHER_ALG_NONE)
646 {
647 NLA_PUT(nl_msg, OVPN_A_KEYDIR_CIPHER_KEY, (int)key_len, decrypt_key);
648 NLA_PUT(nl_msg, OVPN_A_KEYDIR_NONCE_TAIL, nonce_tail_len, decrypt_iv);
649 }
650 nla_nest_end(nl_msg, key_dec);
651
652 nla_nest_end(nl_msg, key_conf);
653
654
655 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
656
657nla_put_failure:
658 nlmsg_free(nl_msg);
659 return ret;
660}
661
662int
663dco_set_peer(dco_context_t *dco, unsigned int peerid, int keepalive_interval, int keepalive_timeout,
664 int mss)
665{
666 msg(D_DCO_DEBUG, "%s: peer-id %d, keepalive %d/%d, mss %d", __func__, peerid,
667 keepalive_interval, keepalive_timeout, mss);
668
669 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_SET);
670 if (!nl_msg)
671 {
672 return -ENOMEM;
673 }
674
675 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
676 int ret = -EMSGSIZE;
677 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peerid);
678 NLA_PUT_U32(nl_msg, OVPN_A_PEER_KEEPALIVE_INTERVAL, keepalive_interval);
679 NLA_PUT_U32(nl_msg, OVPN_A_PEER_KEEPALIVE_TIMEOUT, keepalive_timeout);
680 nla_nest_end(nl_msg, attr);
681
682 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
683
684nla_put_failure:
685 nlmsg_free(nl_msg);
686 return ret;
687}
688
689/* This function parses the reply provided by the kernel to the CTRL_CMD_GETFAMILY
690 * message. We parse the reply and we retrieve the multicast group ID associated
691 * with the "ovpn-dco" netlink family.
692 *
693 * The ID is later used to subscribe to the multicast group and be notified
694 * about any multicast message sent by the ovpn-dco kernel module.
695 */
696static int
697mcast_family_handler(struct nl_msg *msg, void *arg)
698{
699 dco_context_t *dco = arg;
700 struct nlattr *tb[CTRL_ATTR_MAX + 1];
701 const struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
702
703 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
704
705 if (!tb[CTRL_ATTR_MCAST_GROUPS])
706 {
707 return NL_SKIP;
708 }
709
710 const struct nlattr *mcgrp;
711 int rem_mcgrp;
712 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp)
713 {
714 struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
715
716 nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp), nla_len(mcgrp), NULL);
717
718 if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
719 {
720 continue;
721 }
722
723 if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]), OVPN_MCGRP_PEERS,
724 nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]))
725 != 0)
726 {
727 continue;
728 }
729 dco->ovpn_dco_mcast_id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
730 break;
731 }
732
733 return NL_SKIP;
734}
740static int
741ovpn_get_mcast_id(dco_context_t *dco)
742{
743 dco->ovpn_dco_mcast_id = -ENOENT;
744
745 /* Even though 'nlctrl' is a constant, there seem to be no library
746 * provided define for it */
747 dco->ctrlid = genl_ctrl_resolve(dco->nl_sock, "nlctrl");
748
749 struct nl_msg *nl_msg = nlmsg_alloc();
750 if (!nl_msg)
751 {
752 return -ENOMEM;
753 }
754
755 genlmsg_put(nl_msg, 0, 0, dco->ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
756
757 int ret = -EMSGSIZE;
758 NLA_PUT_STRING(nl_msg, CTRL_ATTR_FAMILY_NAME, OVPN_FAMILY_NAME);
759
760 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
761
762nla_put_failure:
763 nlmsg_free(nl_msg);
764 return ret;
765}
766
767static bool
768ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out)
769{
770 if (!attrs[OVPN_A_PEER_REMOTE_PORT])
771 {
772 msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message");
773 return false;
774 }
775
776 if (attrs[OVPN_A_PEER_REMOTE_IPV4])
777 {
778 struct sockaddr_in *addr4 = (struct sockaddr_in *)out;
779 CLEAR(*addr4);
780 addr4->sin_family = AF_INET;
781 addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]);
782 addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]);
783 return true;
784 }
785 else if (attrs[OVPN_A_PEER_REMOTE_IPV6]
786 && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr))
787 {
788 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out;
789 CLEAR(*addr6);
790 addr6->sin6_family = AF_INET6;
791 addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]);
792 memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]),
793 sizeof(addr6->sin6_addr));
795 {
796 addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]);
797 }
798 return true;
799 }
800
801 msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message");
802 return false;
803}
804
805/* libnl < 3.11.0 does not implement nla_get_uint() */
806static uint64_t
807ovpn_nla_get_uint(struct nlattr *attr)
808{
809 if (nla_len(attr) == sizeof(uint32_t))
810 {
811 return nla_get_u32(attr);
812 }
813 else
814 {
815 return nla_get_u64(attr);
816 }
817}
818
819static void
820dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id)
821{
823 {
824 c2->dco_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_RX_BYTES]);
825 msg(D_DCO_DEBUG, "%s / dco_read_bytes: " counter_format, __func__, c2->dco_read_bytes);
826 }
827 else
828 {
829 msg(M_WARN, "%s: no link RX bytes provided in reply for peer %u", __func__, id);
830 }
831
833 {
834 c2->dco_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_TX_BYTES]);
835 msg(D_DCO_DEBUG, "%s / dco_write_bytes: " counter_format, __func__, c2->dco_write_bytes);
836 }
837 else
838 {
839 msg(M_WARN, "%s: no link TX bytes provided in reply for peer %u", __func__, id);
840 }
841
843 {
844 c2->tun_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_RX_BYTES]);
845 msg(D_DCO_DEBUG, "%s / tun_read_bytes: " counter_format, __func__, c2->tun_read_bytes);
846 }
847 else
848 {
849 msg(M_WARN, "%s: no VPN RX bytes provided in reply for peer %u", __func__, id);
850 }
851
853 {
854 c2->tun_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_TX_BYTES]);
855 msg(D_DCO_DEBUG, "%s / tun_write_bytes: " counter_format, __func__, c2->tun_write_bytes);
856 }
857 else
858 {
859 msg(M_WARN, "%s: no VPN TX bytes provided in reply for peer %u", __func__, id);
860 }
861}
862
863static int
864ovpn_handle_peer(dco_context_t *dco, struct nlattr *attrs[])
865{
866 if (!attrs[OVPN_A_PEER])
867 {
868 msg(D_DCO_DEBUG, "%s: malformed reply", __func__);
869 return NL_SKIP;
870 }
871
872 struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1];
873 nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL);
874
875 if (!tb_peer[OVPN_A_PEER_ID])
876 {
877 msg(M_WARN, "ovpn-dco: no peer-id provided in PEER_GET reply");
878 return NL_SKIP;
879 }
880
881 uint32_t peer_id = nla_get_u32(tb_peer[OVPN_A_PEER_ID]);
882 struct context_2 *c2;
883
884 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: parsing message for peer %u...", __func__, peer_id);
885
886 if (dco->ifmode == OVPN_MODE_P2P)
887 {
888 c2 = &dco->c->c2;
889 if (c2->tls_multi->dco_peer_id != (int)peer_id)
890 {
891 return NL_SKIP;
892 }
893 }
894 else
895 {
896 if (peer_id >= dco->c->multi->max_clients)
897 {
898 msg(M_WARN, "%s: received out of bound peer_id %u (max=%u)", __func__, peer_id,
899 dco->c->multi->max_clients);
900 return NL_SKIP;
901 }
902
903 struct multi_instance *mi = dco->c->multi->instances[peer_id];
904 if (!mi)
905 {
906 msg(M_WARN | M_NOIPREFIX, "%s: received data for a non-existing peer %u", __func__, peer_id);
907 return NL_SKIP;
908 }
909
910 c2 = &mi->context.c2;
911 }
912
913 dco_update_peer_stat(c2, tb_peer, peer_id);
914
915 return NL_OK;
916}
917
918static bool
919ovpn_iface_check(dco_context_t *dco, struct nlattr *attrs[])
920{
921 /* we must know which interface this message is referring to in order to
922 * avoid mixing messages for other instances
923 */
924 if (!attrs[OVPN_A_IFINDEX])
925 {
926 msg(D_DCO, "ovpn-dco: Received message without ifindex");
927 return false;
928 }
929
930 uint32_t ifindex = nla_get_u32(attrs[OVPN_A_IFINDEX]);
931 if (ifindex != dco->ifindex)
932 {
933 msg(D_DCO_DEBUG, "ovpn-dco: ignoring message for foreign ifindex %d", ifindex);
934 return false;
935 }
936
937 return true;
938}
939
940static int
941ovpn_handle_peer_del_ntf(dco_context_t *dco, struct nlattr *attrs[])
942{
943 if (!ovpn_iface_check(dco, attrs))
944 {
945 return NL_STOP;
946 }
947
948 if (!attrs[OVPN_A_PEER])
949 {
950 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no peer in PEER_DEL_NTF message");
951 return NL_STOP;
952 }
953
954 struct nlattr *dp_attrs[OVPN_A_PEER_MAX + 1];
955 if (nla_parse_nested(dp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL))
956 {
957 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: can't parse peer in PEER_DEL_NTF messsage");
958 return NL_STOP;
959 }
960
961 if (!dp_attrs[OVPN_A_PEER_DEL_REASON])
962 {
963 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no reason in PEER_DEL_NTF message");
964 return NL_STOP;
965 }
966 if (!dp_attrs[OVPN_A_PEER_ID])
967 {
968 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no peer-id in PEER_DEL_NTF message");
969 return NL_STOP;
970 }
971
972 int reason = nla_get_u32(dp_attrs[OVPN_A_PEER_DEL_REASON]);
973 unsigned int peerid = nla_get_u32(dp_attrs[OVPN_A_PEER_ID]);
974
975 msg(D_DCO_DEBUG | M_NOIPREFIX, "ovpn-dco: received CMD_PEER_DEL_NTF, ifindex: %d, peer-id %u, reason: %d",
976 dco->ifindex, peerid, reason);
977 dco->dco_message_peer_id = peerid;
978 dco->dco_del_peer_reason = reason;
979 dco->dco_message_type = OVPN_CMD_PEER_DEL_NTF;
980
981 return NL_OK;
982}
983
984static int
985ovpn_handle_peer_float_ntf(dco_context_t *dco, struct nlattr *attrs[])
986{
987 if (!ovpn_iface_check(dco, attrs))
988 {
989 return NL_STOP;
990 }
991
992 if (!attrs[OVPN_A_PEER])
993 {
994 msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message");
995 return NL_STOP;
996 }
997
998 struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1];
999 if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL))
1000 {
1001 msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage");
1002 return NL_STOP;
1003 }
1004
1005 if (!fp_attrs[OVPN_A_PEER_ID])
1006 {
1007 msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message");
1008 return NL_STOP;
1009 }
1010 uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]);
1011
1012 if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss))
1013 {
1014 return NL_STOP;
1015 }
1016
1017 struct gc_arena gc = gc_new();
1018 msg(D_DCO_DEBUG, "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s",
1019 dco->ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc));
1020 dco->dco_message_peer_id = (int)peerid;
1021 dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF;
1022
1023 gc_free(&gc);
1024
1025 return NL_OK;
1026}
1027
1028static int
1029ovpn_handle_key_swap_ntf(dco_context_t *dco, struct nlattr *attrs[])
1030{
1031 if (!ovpn_iface_check(dco, attrs))
1032 {
1033 return NL_STOP;
1034 }
1035
1036 if (!attrs[OVPN_A_KEYCONF])
1037 {
1038 msg(D_DCO, "ovpn-dco: no keyconf in KEY_SWAP_NTF message");
1039 return NL_STOP;
1040 }
1041
1042 struct nlattr *dp_attrs[OVPN_A_KEYCONF_MAX + 1];
1043 if (nla_parse_nested(dp_attrs, OVPN_A_KEYCONF_MAX, attrs[OVPN_A_KEYCONF], NULL))
1044 {
1045 msg(D_DCO, "ovpn-dco: can't parse keyconf in KEY_SWAP_NTF message");
1046 return NL_STOP;
1047 }
1048 if (!dp_attrs[OVPN_A_KEYCONF_PEER_ID])
1049 {
1050 msg(D_DCO, "ovpn-dco: no peer-id in KEY_SWAP_NTF message");
1051 return NL_STOP;
1052 }
1053 if (!dp_attrs[OVPN_A_KEYCONF_KEY_ID])
1054 {
1055 msg(D_DCO, "ovpn-dco: no key-id in KEY_SWAP_NTF message");
1056 return NL_STOP;
1057 }
1058
1059 int key_id = nla_get_u16(dp_attrs[OVPN_A_KEYCONF_KEY_ID]);
1060 unsigned int peer_id = nla_get_u32(dp_attrs[OVPN_A_KEYCONF_PEER_ID]);
1061
1062 msg(D_DCO_DEBUG, "ovpn-dco: received CMD_KEY_SWAP_NTF, ifindex: %d, peer-id %u, key-id: %d",
1063 dco->ifindex, peer_id, key_id);
1064 dco->dco_message_peer_id = peer_id;
1065 dco->dco_message_key_id = key_id;
1066 dco->dco_message_type = OVPN_CMD_KEY_SWAP_NTF;
1067
1068 return NL_OK;
1069}
1070
1071/* This function parses any netlink message sent by ovpn-dco to userspace */
1072static int
1073ovpn_handle_msg(struct nl_msg *msg, void *arg)
1074{
1075 dco_context_t *dco = arg;
1076
1077 struct nlattr *attrs[OVPN_A_MAX + 1];
1078 struct nlmsghdr *nlh = nlmsg_hdr(msg);
1079 struct genlmsghdr *gnlh = genlmsg_hdr(nlh);
1080
1081 msg(D_DCO_DEBUG | M_NOIPREFIX, "ovpn-dco: received netlink message type=%u cmd=%u flags=%#.4x",
1082 nlh->nlmsg_type, gnlh->cmd, nlh->nlmsg_flags);
1083
1084 /* if we get a message from the NLCTRL family, it means
1085 * this is the reply to the mcast ID resolution request
1086 * and we parse it accordingly.
1087 */
1088 if (nlh->nlmsg_type == dco->ctrlid)
1089 {
1090 msg(D_DCO_DEBUG, "ovpn-dco: received CTRLID message");
1091 return mcast_family_handler(msg, dco);
1092 }
1093
1094 if (!genlmsg_valid_hdr(nlh, 0))
1095 {
1096 msg(D_DCO, "ovpn-dco: invalid header");
1097 return NL_STOP;
1098 }
1099
1100 if (nla_parse(attrs, OVPN_A_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL))
1101 {
1102 msg(D_DCO, "received bogus data from ovpn-dco");
1103 return NL_STOP;
1104 }
1105
1106 /* based on the message type, we parse the subobject contained in the
1107 * message, that stores the type-specific attributes.
1108 *
1109 * the "dco" object is then filled accordingly with the information
1110 * retrieved from the message, so that *process_incoming_dco can react
1111 * as need be.
1112 */
1113 int ret;
1114 switch (gnlh->cmd)
1115 {
1116 case OVPN_CMD_PEER_GET:
1117 {
1118 /* return directly, there are no messages to pass to *process_incoming_dco() */
1119 return ovpn_handle_peer(dco, attrs);
1120 }
1121
1123 {
1124 ret = ovpn_handle_peer_del_ntf(dco, attrs);
1125 break;
1126 }
1127
1129 {
1130 ret = ovpn_handle_peer_float_ntf(dco, attrs);
1131 break;
1132 }
1133
1135 {
1136 ret = ovpn_handle_key_swap_ntf(dco, attrs);
1137 break;
1138 }
1139
1140 default:
1141 msg(D_DCO, "ovpn-dco: received unknown command: %d", gnlh->cmd);
1142 dco->dco_message_type = 0;
1143 return NL_STOP;
1144 }
1145
1146 if (ret != NL_OK)
1147 {
1148 return ret;
1149 }
1150
1151 if (dco->c->mode == CM_TOP)
1152 {
1154 }
1155 else
1156 {
1158 }
1159
1160 return NL_OK;
1161}
1162
1163int
1165{
1166 msg(D_DCO_DEBUG, __func__);
1167
1168 return ovpn_nl_recvmsgs(dco, __func__);
1169}
1170
1171static int
1172dco_get_peer(dco_context_t *dco, int peer_id, const bool raise_sigusr1_on_err)
1173{
1174 ASSERT(dco);
1175
1176 if (__is_locked)
1177 {
1178 msg(D_DCO_DEBUG, "%s: cannot request peer stats while parsing other messages", __func__);
1179 return 0;
1180 }
1181
1182 /* peer_id == -1 means "dump all peers", but this is allowed in MP mode only.
1183 * If it happens in P2P mode it means that the DCO peer was deleted and we
1184 * can simply bail out
1185 */
1186 if (peer_id == -1 && dco->ifmode == OVPN_MODE_P2P)
1187 {
1188 return 0;
1189 }
1190
1191 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: peer-id %d", __func__, peer_id);
1192
1193 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_GET);
1194 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
1195 int ret = -EMSGSIZE;
1196
1197 if (peer_id != -1)
1198 {
1199 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peer_id);
1200 }
1201 else
1202 {
1203 nlmsg_hdr(nl_msg)->nlmsg_flags |= NLM_F_DUMP;
1204 }
1205 nla_nest_end(nl_msg, attr);
1206
1207 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
1208
1209nla_put_failure:
1210 nlmsg_free(nl_msg);
1211
1212 if (raise_sigusr1_on_err && ret < 0)
1213 {
1214 msg(M_WARN, "Error retrieving DCO peer stats: the underlying DCO peer"
1215 "may have been deleted from the kernel without notifying "
1216 "userspace. Restarting the session");
1217 register_signal(dco->c->sig, SIGUSR1, "dco peer stats error");
1218 }
1219 return ret;
1220}
1221
1222int
1223dco_get_peer_stats(struct context *c, const bool raise_sigusr1_on_err)
1224{
1225 if (!c->c1.tuntap || c->c1.tuntap->dco.ifindex == 0)
1226 {
1227 return -1;
1228 }
1229
1230 return dco_get_peer(&c->c1.tuntap->dco, c->c2.tls_multi->dco_peer_id, raise_sigusr1_on_err);
1231}
1232
1233int
1234dco_get_peer_stats_multi(dco_context_t *dco, const bool raise_sigusr1_on_err)
1235{
1236 return dco_get_peer(dco, -1, raise_sigusr1_on_err);
1237}
1238
1239bool
1240dco_available(msglvl_t msglevel)
1241{
1242 if (resolve_ovpn_netlink_id(D_DCO_DEBUG) < 0)
1243 {
1244 msg(msglevel, "Note: Kernel support for ovpn interfaces missing, "
1245 "disabling data channel offload. Use Linux 6.16.0 or "
1246 "newer with ovpn support or use ovpn-backports for "
1247 "interface support.");
1248 return false;
1249 }
1250
1251 return true;
1252}
1253
1258static const char *
1259dco_version_string_in_tree(struct gc_arena *gc)
1260{
1261 struct buffer buf = alloc_buf_gc(256, gc);
1262 struct utsname system;
1263
1264 if (uname(&system))
1265 {
1266 return "ERR";
1267 }
1268
1269 buf_puts(&buf, system.release);
1270 buf_puts(&buf, " ");
1271 buf_puts(&buf, system.version);
1272 return BSTR(&buf);
1273}
1274
1281static const char *
1282dco_version_string_backports(FILE *fp, struct gc_arena *gc)
1283{
1284 char *str = gc_malloc(PATH_MAX, false, gc);
1285
1286 if (!fgets(str, PATH_MAX, fp))
1287 {
1288 return "ERR";
1289 }
1290
1291 /* remove potential newline at the end of the string */
1292 char *nl = strchr(str, '\n');
1293 if (nl)
1294 {
1295 *nl = '\0';
1296 }
1297
1298 return str;
1299}
1300
1301const char *
1303{
1304 const char *version;
1305 struct stat sb;
1306 FILE *fp;
1307
1308 if (stat("/sys/module/ovpn", &sb) != 0 || !S_ISDIR(sb.st_mode))
1309 {
1310 return "N/A";
1311 }
1312
1313 /* now that we know for sure that the module is loaded, if there's no
1314 * version file it means we're dealing with the in-tree version, otherwise
1315 * it's backports */
1316 fp = fopen("/sys/module/ovpn/version", "r");
1317 if (!fp)
1318 {
1319 return dco_version_string_in_tree(gc);
1320 }
1321 version = dco_version_string_backports(fp, gc);
1322
1323 fclose(fp);
1324 return version;
1325}
1326
1327void
1328dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
1329{
1330 if (dco && dco->nl_sock)
1331 {
1332 event_ctl(es, nl_socket_get_fd(dco->nl_sock), EVENT_READ, arg);
1333 }
1334}
1335
1336const char *
1338{
1339 return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305";
1340}
1341
1342bool
1344{
1345 return false;
1346}
1347
1348#endif /* defined(ENABLE_DCO) && defined(TARGET_LINUX) */
bool buf_puts(struct buffer *buf, const char *str)
Append a string to a buffer with overflow check.
Definition buffer.c:253
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
Definition buffer.c:318
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
Definition buffer.c:77
Buffer management functions and garbage collection.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
Definition buffer.h:157
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Allocate and zero-initialise a garbage-collected object of the given type.
Definition buffer.h:2132
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1974
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1958
#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:585
int dco_del_peer(dco_context_t *dco, unsigned int peerid)
Definition dco_win.c:470
int dco_swap_keys(dco_context_t *dco, unsigned int peer_id)
Definition dco_win.c:593
int dco_new_peer(dco_context_t *dco, unsigned int peerid, socket_descriptor_t sd, struct sockaddr *localaddr, struct sockaddr *remoteaddr, const struct in_addr *vpn_ipv4, const struct in6_addr *vpn_ipv6)
Definition dco_win.c:418
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:530
#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:1245
static SERVICE_STATUS status
Definition interactive.c:52
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:71
struct tuntap * tuntap
Tun/tap virtual network interface.
Definition openvpn.h:173
Level 2 context containing state that is reset on both SIGHUP and SIGUSR1 restarts.
Definition openvpn.h:225
counter_type dco_read_bytes
Definition openvpn.h:268
counter_type tun_read_bytes
Definition openvpn.h:265
counter_type dco_write_bytes
Definition openvpn.h:271
struct tls_multi * tls_multi
TLS state structure for this VPN tunnel.
Definition openvpn.h:324
counter_type tun_write_bytes
Definition openvpn.h:266
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:127
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:725
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 gc_arena gc
Definition test_ssl.c:122