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-dco 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
862#if defined(__GNUC__) || defined(__clang__)
863#pragma GCC diagnostic push
864#pragma GCC diagnostic ignored "-Wsign-compare"
865#endif
866
867static int
868ovpn_handle_peer(dco_context_t *dco, struct nlattr *attrs[])
869{
870 if (!attrs[OVPN_A_PEER])
871 {
872 msg(D_DCO_DEBUG, "%s: malformed reply", __func__);
873 return NL_SKIP;
874 }
875
876 struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1];
877 nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL);
878
879 if (!tb_peer[OVPN_A_PEER_ID])
880 {
881 msg(M_WARN, "ovpn-dco: no peer-id provided in PEER_GET reply");
882 return NL_SKIP;
883 }
884
885 uint32_t peer_id = nla_get_u32(tb_peer[OVPN_A_PEER_ID]);
886 struct context_2 *c2;
887
888 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: parsing message for peer %u...", __func__, peer_id);
889
890 if (dco->ifmode == OVPN_MODE_P2P)
891 {
892 c2 = &dco->c->c2;
893 if (c2->tls_multi->dco_peer_id != peer_id)
894 {
895 return NL_SKIP;
896 }
897 }
898 else
899 {
900 if (peer_id >= dco->c->multi->max_clients)
901 {
902 msg(M_WARN, "%s: received out of bound peer_id %u (max=%u)", __func__, peer_id,
903 dco->c->multi->max_clients);
904 return NL_SKIP;
905 }
906
907 struct multi_instance *mi = dco->c->multi->instances[peer_id];
908 if (!mi)
909 {
910 msg(M_WARN | M_NOIPREFIX, "%s: received data for a non-existing peer %u", __func__, peer_id);
911 return NL_SKIP;
912 }
913
914 c2 = &mi->context.c2;
915 }
916
917 dco_update_peer_stat(c2, tb_peer, peer_id);
918
919 return NL_OK;
920}
921
922#if defined(__GNUC__) || defined(__clang__)
923#pragma GCC diagnostic pop
924#endif
925
926static bool
927ovpn_iface_check(dco_context_t *dco, struct nlattr *attrs[])
928{
929 /* we must know which interface this message is referring to in order to
930 * avoid mixing messages for other instances
931 */
932 if (!attrs[OVPN_A_IFINDEX])
933 {
934 msg(D_DCO, "ovpn-dco: Received message without ifindex");
935 return false;
936 }
937
938 uint32_t ifindex = nla_get_u32(attrs[OVPN_A_IFINDEX]);
939 if (ifindex != dco->ifindex)
940 {
941 msg(D_DCO_DEBUG, "ovpn-dco: ignoring message for foreign ifindex %d", ifindex);
942 return false;
943 }
944
945 return true;
946}
947
948static int
949ovpn_handle_peer_del_ntf(dco_context_t *dco, struct nlattr *attrs[])
950{
951 if (!ovpn_iface_check(dco, attrs))
952 {
953 return NL_STOP;
954 }
955
956 if (!attrs[OVPN_A_PEER])
957 {
958 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no peer in PEER_DEL_NTF message");
959 return NL_STOP;
960 }
961
962 struct nlattr *dp_attrs[OVPN_A_PEER_MAX + 1];
963 if (nla_parse_nested(dp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL))
964 {
965 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: can't parse peer in PEER_DEL_NTF messsage");
966 return NL_STOP;
967 }
968
969 if (!dp_attrs[OVPN_A_PEER_DEL_REASON])
970 {
971 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no reason in PEER_DEL_NTF message");
972 return NL_STOP;
973 }
974 if (!dp_attrs[OVPN_A_PEER_ID])
975 {
976 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no peer-id in PEER_DEL_NTF message");
977 return NL_STOP;
978 }
979
980 int reason = nla_get_u32(dp_attrs[OVPN_A_PEER_DEL_REASON]);
981 unsigned int peerid = nla_get_u32(dp_attrs[OVPN_A_PEER_ID]);
982
983 msg(D_DCO_DEBUG | M_NOIPREFIX, "ovpn-dco: received CMD_PEER_DEL_NTF, ifindex: %d, peer-id %u, reason: %d",
984 dco->ifindex, peerid, reason);
985 dco->dco_message_peer_id = peerid;
986 dco->dco_del_peer_reason = reason;
987 dco->dco_message_type = OVPN_CMD_PEER_DEL_NTF;
988
989 return NL_OK;
990}
991
992static int
993ovpn_handle_peer_float_ntf(dco_context_t *dco, struct nlattr *attrs[])
994{
995 if (!ovpn_iface_check(dco, attrs))
996 {
997 return NL_STOP;
998 }
999
1000 if (!attrs[OVPN_A_PEER])
1001 {
1002 msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message");
1003 return NL_STOP;
1004 }
1005
1006 struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1];
1007 if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL))
1008 {
1009 msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage");
1010 return NL_STOP;
1011 }
1012
1013 if (!fp_attrs[OVPN_A_PEER_ID])
1014 {
1015 msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message");
1016 return NL_STOP;
1017 }
1018 uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]);
1019
1020 if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss))
1021 {
1022 return NL_STOP;
1023 }
1024
1025 struct gc_arena gc = gc_new();
1026 msg(D_DCO_DEBUG, "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s",
1027 dco->ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc));
1028 dco->dco_message_peer_id = (int)peerid;
1029 dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF;
1030
1031 gc_free(&gc);
1032
1033 return NL_OK;
1034}
1035
1036static int
1037ovpn_handle_key_swap_ntf(dco_context_t *dco, struct nlattr *attrs[])
1038{
1039 if (!ovpn_iface_check(dco, attrs))
1040 {
1041 return NL_STOP;
1042 }
1043
1044 if (!attrs[OVPN_A_KEYCONF])
1045 {
1046 msg(D_DCO, "ovpn-dco: no keyconf in KEY_SWAP_NTF message");
1047 return NL_STOP;
1048 }
1049
1050 struct nlattr *dp_attrs[OVPN_A_KEYCONF_MAX + 1];
1051 if (nla_parse_nested(dp_attrs, OVPN_A_KEYCONF_MAX, attrs[OVPN_A_KEYCONF], NULL))
1052 {
1053 msg(D_DCO, "ovpn-dco: can't parse keyconf in KEY_SWAP_NTF message");
1054 return NL_STOP;
1055 }
1056 if (!dp_attrs[OVPN_A_KEYCONF_PEER_ID])
1057 {
1058 msg(D_DCO, "ovpn-dco: no peer-id in KEY_SWAP_NTF message");
1059 return NL_STOP;
1060 }
1061 if (!dp_attrs[OVPN_A_KEYCONF_KEY_ID])
1062 {
1063 msg(D_DCO, "ovpn-dco: no key-id in KEY_SWAP_NTF message");
1064 return NL_STOP;
1065 }
1066
1067 int key_id = nla_get_u16(dp_attrs[OVPN_A_KEYCONF_KEY_ID]);
1068 unsigned int peer_id = nla_get_u32(dp_attrs[OVPN_A_KEYCONF_PEER_ID]);
1069
1070 msg(D_DCO_DEBUG, "ovpn-dco: received CMD_KEY_SWAP_NTF, ifindex: %d, peer-id %u, key-id: %d",
1071 dco->ifindex, peer_id, key_id);
1072 dco->dco_message_peer_id = peer_id;
1073 dco->dco_message_key_id = key_id;
1074 dco->dco_message_type = OVPN_CMD_KEY_SWAP_NTF;
1075
1076 return NL_OK;
1077}
1078
1079/* This function parses any netlink message sent by ovpn-dco to userspace */
1080static int
1081ovpn_handle_msg(struct nl_msg *msg, void *arg)
1082{
1083 dco_context_t *dco = arg;
1084
1085 struct nlattr *attrs[OVPN_A_MAX + 1];
1086 struct nlmsghdr *nlh = nlmsg_hdr(msg);
1087 struct genlmsghdr *gnlh = genlmsg_hdr(nlh);
1088
1089 msg(D_DCO_DEBUG | M_NOIPREFIX, "ovpn-dco: received netlink message type=%u cmd=%u flags=%#.4x",
1090 nlh->nlmsg_type, gnlh->cmd, nlh->nlmsg_flags);
1091
1092 /* if we get a message from the NLCTRL family, it means
1093 * this is the reply to the mcast ID resolution request
1094 * and we parse it accordingly.
1095 */
1096 if (nlh->nlmsg_type == dco->ctrlid)
1097 {
1098 msg(D_DCO_DEBUG, "ovpn-dco: received CTRLID message");
1099 return mcast_family_handler(msg, dco);
1100 }
1101
1102 if (!genlmsg_valid_hdr(nlh, 0))
1103 {
1104 msg(D_DCO, "ovpn-dco: invalid header");
1105 return NL_STOP;
1106 }
1107
1108 if (nla_parse(attrs, OVPN_A_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL))
1109 {
1110 msg(D_DCO, "received bogus data from ovpn-dco");
1111 return NL_STOP;
1112 }
1113
1114 /* based on the message type, we parse the subobject contained in the
1115 * message, that stores the type-specific attributes.
1116 *
1117 * the "dco" object is then filled accordingly with the information
1118 * retrieved from the message, so that *process_incoming_dco can react
1119 * as need be.
1120 */
1121 int ret;
1122 switch (gnlh->cmd)
1123 {
1124 case OVPN_CMD_PEER_GET:
1125 {
1126 /* return directly, there are no messages to pass to *process_incoming_dco() */
1127 return ovpn_handle_peer(dco, attrs);
1128 }
1129
1131 {
1132 ret = ovpn_handle_peer_del_ntf(dco, attrs);
1133 break;
1134 }
1135
1137 {
1138 ret = ovpn_handle_peer_float_ntf(dco, attrs);
1139 break;
1140 }
1141
1143 {
1144 ret = ovpn_handle_key_swap_ntf(dco, attrs);
1145 break;
1146 }
1147
1148 default:
1149 msg(D_DCO, "ovpn-dco: received unknown command: %d", gnlh->cmd);
1150 dco->dco_message_type = 0;
1151 return NL_STOP;
1152 }
1153
1154 if (ret != NL_OK)
1155 {
1156 return ret;
1157 }
1158
1159 if (dco->c->mode == CM_TOP)
1160 {
1162 }
1163 else
1164 {
1166 }
1167
1168 return NL_OK;
1169}
1170
1171int
1173{
1174 msg(D_DCO_DEBUG, __func__);
1175
1176 return ovpn_nl_recvmsgs(dco, __func__);
1177}
1178
1179static int
1180dco_get_peer(dco_context_t *dco, int peer_id, const bool raise_sigusr1_on_err)
1181{
1182 ASSERT(dco);
1183
1184 if (__is_locked)
1185 {
1186 msg(D_DCO_DEBUG, "%s: cannot request peer stats while parsing other messages", __func__);
1187 return 0;
1188 }
1189
1190 /* peer_id == -1 means "dump all peers", but this is allowed in MP mode only.
1191 * If it happens in P2P mode it means that the DCO peer was deleted and we
1192 * can simply bail out
1193 */
1194 if (peer_id == -1 && dco->ifmode == OVPN_MODE_P2P)
1195 {
1196 return 0;
1197 }
1198
1199 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: peer-id %d", __func__, peer_id);
1200
1201 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_GET);
1202 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
1203 int ret = -EMSGSIZE;
1204
1205 if (peer_id != -1)
1206 {
1207 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peer_id);
1208 }
1209 else
1210 {
1211 nlmsg_hdr(nl_msg)->nlmsg_flags |= NLM_F_DUMP;
1212 }
1213 nla_nest_end(nl_msg, attr);
1214
1215 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
1216
1217nla_put_failure:
1218 nlmsg_free(nl_msg);
1219
1220 if (raise_sigusr1_on_err && ret < 0)
1221 {
1222 msg(M_WARN, "Error retrieving DCO peer stats: the underlying DCO peer"
1223 "may have been deleted from the kernel without notifying "
1224 "userspace. Restarting the session");
1225 register_signal(dco->c->sig, SIGUSR1, "dco peer stats error");
1226 }
1227 return ret;
1228}
1229
1230int
1231dco_get_peer_stats(struct context *c, const bool raise_sigusr1_on_err)
1232{
1233 if (!c->c1.tuntap || c->c1.tuntap->dco.ifindex == 0)
1234 {
1235 return -1;
1236 }
1237
1238 return dco_get_peer(&c->c1.tuntap->dco, c->c2.tls_multi->dco_peer_id, raise_sigusr1_on_err);
1239}
1240
1241int
1242dco_get_peer_stats_multi(dco_context_t *dco, const bool raise_sigusr1_on_err)
1243{
1244 return dco_get_peer(dco, -1, raise_sigusr1_on_err);
1245}
1246
1247bool
1248dco_available(msglvl_t msglevel)
1249{
1250 if (resolve_ovpn_netlink_id(D_DCO_DEBUG) < 0)
1251 {
1252 msg(msglevel, "Note: Kernel support for ovpn-dco missing, disabling data channel offload.");
1253 return false;
1254 }
1255
1256 return true;
1257}
1258
1263static const char *
1264dco_version_string_in_tree(struct gc_arena *gc)
1265{
1266 struct buffer buf = alloc_buf_gc(256, gc);
1267 struct utsname system;
1268
1269 if (uname(&system))
1270 {
1271 return "ERR";
1272 }
1273
1274 buf_puts(&buf, system.release);
1275 buf_puts(&buf, " ");
1276 buf_puts(&buf, system.version);
1277 return BSTR(&buf);
1278}
1279
1286static const char *
1287dco_version_string_backports(FILE *fp, struct gc_arena *gc)
1288{
1289 char *str = gc_malloc(PATH_MAX, false, gc);
1290
1291 if (!fgets(str, PATH_MAX, fp))
1292 {
1293 return "ERR";
1294 }
1295
1296 /* remove potential newline at the end of the string */
1297 char *nl = strchr(str, '\n');
1298 if (nl)
1299 {
1300 *nl = '\0';
1301 }
1302
1303 return str;
1304}
1305
1306const char *
1308{
1309 const char *version;
1310 struct stat sb;
1311 FILE *fp;
1312
1313 if (stat("/sys/module/ovpn", &sb) != 0 || !S_ISDIR(sb.st_mode))
1314 {
1315 return "N/A";
1316 }
1317
1318 /* now that we know for sure that the module is loaded, if there's no
1319 * version file it means we're dealing with the in-tree version, otherwise
1320 * it's backports */
1321 fp = fopen("/sys/module/ovpn/version", "r");
1322 if (!fp)
1323 {
1324 return dco_version_string_in_tree(gc);
1325 }
1326 version = dco_version_string_backports(fp, gc);
1327
1328 fclose(fp);
1329 return version;
1330}
1331
1332void
1333dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
1334{
1335 if (dco && dco->nl_sock)
1336 {
1337 event_ctl(es, nl_socket_get_fd(dco->nl_sock), EVENT_READ, arg);
1338 }
1339}
1340
1341const char *
1343{
1344 return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305";
1345}
1346
1347bool
1349{
1350 return false;
1351}
1352
1353#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:341
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:143
int dco_peer_id
This is the handle that DCO uses to identify this session with the kernel.
Definition ssl_common.h:723
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:131