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 int key_len = cipher_kt_key_size(ciphername);
616 const int nonce_tail_len = 8;
617
618 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_KEY_NEW);
619 if (!nl_msg)
620 {
621 return -ENOMEM;
622 }
623
624 dco_cipher_t dco_cipher = dco_get_cipher(ciphername);
625
626 int ret = -EMSGSIZE;
627
628 struct nlattr *key_conf = nla_nest_start(nl_msg, OVPN_A_KEYCONF);
629 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_PEER_ID, peerid);
630 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_SLOT, slot);
631 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_KEY_ID, keyid);
632 NLA_PUT_U32(nl_msg, OVPN_A_KEYCONF_CIPHER_ALG, dco_cipher);
633
634 struct nlattr *key_enc = nla_nest_start(nl_msg, OVPN_A_KEYCONF_ENCRYPT_DIR);
635 if (dco_cipher != OVPN_CIPHER_ALG_NONE)
636 {
637 NLA_PUT(nl_msg, OVPN_A_KEYDIR_CIPHER_KEY, key_len, encrypt_key);
638 NLA_PUT(nl_msg, OVPN_A_KEYDIR_NONCE_TAIL, nonce_tail_len, encrypt_iv);
639 }
640 nla_nest_end(nl_msg, key_enc);
641
642 struct nlattr *key_dec = nla_nest_start(nl_msg, OVPN_A_KEYCONF_DECRYPT_DIR);
643 if (dco_cipher != OVPN_CIPHER_ALG_NONE)
644 {
645 NLA_PUT(nl_msg, OVPN_A_KEYDIR_CIPHER_KEY, key_len, decrypt_key);
646 NLA_PUT(nl_msg, OVPN_A_KEYDIR_NONCE_TAIL, nonce_tail_len, decrypt_iv);
647 }
648 nla_nest_end(nl_msg, key_dec);
649
650 nla_nest_end(nl_msg, key_conf);
651
652
653 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
654
655nla_put_failure:
656 nlmsg_free(nl_msg);
657 return ret;
658}
659
660int
661dco_set_peer(dco_context_t *dco, unsigned int peerid, int keepalive_interval, int keepalive_timeout,
662 int mss)
663{
664 msg(D_DCO_DEBUG, "%s: peer-id %d, keepalive %d/%d, mss %d", __func__, peerid,
665 keepalive_interval, keepalive_timeout, mss);
666
667 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_SET);
668 if (!nl_msg)
669 {
670 return -ENOMEM;
671 }
672
673 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
674 int ret = -EMSGSIZE;
675 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peerid);
676 NLA_PUT_U32(nl_msg, OVPN_A_PEER_KEEPALIVE_INTERVAL, keepalive_interval);
677 NLA_PUT_U32(nl_msg, OVPN_A_PEER_KEEPALIVE_TIMEOUT, keepalive_timeout);
678 nla_nest_end(nl_msg, attr);
679
680 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
681
682nla_put_failure:
683 nlmsg_free(nl_msg);
684 return ret;
685}
686
687/* This function parses the reply provided by the kernel to the CTRL_CMD_GETFAMILY
688 * message. We parse the reply and we retrieve the multicast group ID associated
689 * with the "ovpn-dco" netlink family.
690 *
691 * The ID is later used to subscribe to the multicast group and be notified
692 * about any multicast message sent by the ovpn-dco kernel module.
693 */
694static int
695mcast_family_handler(struct nl_msg *msg, void *arg)
696{
697 dco_context_t *dco = arg;
698 struct nlattr *tb[CTRL_ATTR_MAX + 1];
699 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
700
701 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
702
703 if (!tb[CTRL_ATTR_MCAST_GROUPS])
704 {
705 return NL_SKIP;
706 }
707
708 struct nlattr *mcgrp;
709 int rem_mcgrp;
710 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp)
711 {
712 struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
713
714 nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp), nla_len(mcgrp), NULL);
715
716 if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
717 {
718 continue;
719 }
720
721 if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]), OVPN_MCGRP_PEERS,
722 nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]))
723 != 0)
724 {
725 continue;
726 }
727 dco->ovpn_dco_mcast_id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
728 break;
729 }
730
731 return NL_SKIP;
732}
738static int
739ovpn_get_mcast_id(dco_context_t *dco)
740{
741 dco->ovpn_dco_mcast_id = -ENOENT;
742
743 /* Even though 'nlctrl' is a constant, there seem to be no library
744 * provided define for it */
745 dco->ctrlid = genl_ctrl_resolve(dco->nl_sock, "nlctrl");
746
747 struct nl_msg *nl_msg = nlmsg_alloc();
748 if (!nl_msg)
749 {
750 return -ENOMEM;
751 }
752
753 genlmsg_put(nl_msg, 0, 0, dco->ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
754
755 int ret = -EMSGSIZE;
756 NLA_PUT_STRING(nl_msg, CTRL_ATTR_FAMILY_NAME, OVPN_FAMILY_NAME);
757
758 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
759
760nla_put_failure:
761 nlmsg_free(nl_msg);
762 return ret;
763}
764
765static bool
766ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out)
767{
768 if (!attrs[OVPN_A_PEER_REMOTE_PORT])
769 {
770 msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message");
771 return false;
772 }
773
774 if (attrs[OVPN_A_PEER_REMOTE_IPV4])
775 {
776 struct sockaddr_in *addr4 = (struct sockaddr_in *)out;
777 CLEAR(*addr4);
778 addr4->sin_family = AF_INET;
779 addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]);
780 addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]);
781 return true;
782 }
783 else if (attrs[OVPN_A_PEER_REMOTE_IPV6]
784 && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr))
785 {
786 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out;
787 CLEAR(*addr6);
788 addr6->sin6_family = AF_INET6;
789 addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]);
790 memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]),
791 sizeof(addr6->sin6_addr));
793 {
794 addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]);
795 }
796 return true;
797 }
798
799 msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message");
800 return false;
801}
802
803/* libnl < 3.11.0 does not implement nla_get_uint() */
804static uint64_t
805ovpn_nla_get_uint(struct nlattr *attr)
806{
807 if (nla_len(attr) == sizeof(uint32_t))
808 {
809 return nla_get_u32(attr);
810 }
811 else
812 {
813 return nla_get_u64(attr);
814 }
815}
816
817static void
818dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id)
819{
821 {
822 c2->dco_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_RX_BYTES]);
823 msg(D_DCO_DEBUG, "%s / dco_read_bytes: " counter_format, __func__, c2->dco_read_bytes);
824 }
825 else
826 {
827 msg(M_WARN, "%s: no link RX bytes provided in reply for peer %u", __func__, id);
828 }
829
831 {
832 c2->dco_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_LINK_TX_BYTES]);
833 msg(D_DCO_DEBUG, "%s / dco_write_bytes: " counter_format, __func__, c2->dco_write_bytes);
834 }
835 else
836 {
837 msg(M_WARN, "%s: no link TX bytes provided in reply for peer %u", __func__, id);
838 }
839
841 {
842 c2->tun_read_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_RX_BYTES]);
843 msg(D_DCO_DEBUG, "%s / tun_read_bytes: " counter_format, __func__, c2->tun_read_bytes);
844 }
845 else
846 {
847 msg(M_WARN, "%s: no VPN RX bytes provided in reply for peer %u", __func__, id);
848 }
849
851 {
852 c2->tun_write_bytes = ovpn_nla_get_uint(tb[OVPN_A_PEER_VPN_TX_BYTES]);
853 msg(D_DCO_DEBUG, "%s / tun_write_bytes: " counter_format, __func__, c2->tun_write_bytes);
854 }
855 else
856 {
857 msg(M_WARN, "%s: no VPN TX bytes provided in reply for peer %u", __func__, id);
858 }
859}
860
861#if defined(__GNUC__) || defined(__clang__)
862#pragma GCC diagnostic push
863#pragma GCC diagnostic ignored "-Wsign-compare"
864#endif
865
866static int
867ovpn_handle_peer(dco_context_t *dco, struct nlattr *attrs[])
868{
869 if (!attrs[OVPN_A_PEER])
870 {
871 msg(D_DCO_DEBUG, "%s: malformed reply", __func__);
872 return NL_SKIP;
873 }
874
875 struct nlattr *tb_peer[OVPN_A_PEER_MAX + 1];
876 nla_parse_nested(tb_peer, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL);
877
878 if (!tb_peer[OVPN_A_PEER_ID])
879 {
880 msg(M_WARN, "ovpn-dco: no peer-id provided in PEER_GET reply");
881 return NL_SKIP;
882 }
883
884 uint32_t peer_id = nla_get_u32(tb_peer[OVPN_A_PEER_ID]);
885 struct context_2 *c2;
886
887 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: parsing message for peer %u...", __func__, peer_id);
888
889 if (dco->ifmode == OVPN_MODE_P2P)
890 {
891 c2 = &dco->c->c2;
892 if (c2->tls_multi->dco_peer_id != peer_id)
893 {
894 return NL_SKIP;
895 }
896 }
897 else
898 {
899 if (peer_id >= dco->c->multi->max_clients)
900 {
901 msg(M_WARN, "%s: received out of bound peer_id %u (max=%u)", __func__, peer_id,
902 dco->c->multi->max_clients);
903 return NL_SKIP;
904 }
905
906 struct multi_instance *mi = dco->c->multi->instances[peer_id];
907 if (!mi)
908 {
909 msg(M_WARN | M_NOIPREFIX, "%s: received data for a non-existing peer %u", __func__, peer_id);
910 return NL_SKIP;
911 }
912
913 c2 = &mi->context.c2;
914 }
915
916 dco_update_peer_stat(c2, tb_peer, peer_id);
917
918 return NL_OK;
919}
920
921#if defined(__GNUC__) || defined(__clang__)
922#pragma GCC diagnostic pop
923#endif
924
925static bool
926ovpn_iface_check(dco_context_t *dco, struct nlattr *attrs[])
927{
928 /* we must know which interface this message is referring to in order to
929 * avoid mixing messages for other instances
930 */
931 if (!attrs[OVPN_A_IFINDEX])
932 {
933 msg(D_DCO, "ovpn-dco: Received message without ifindex");
934 return false;
935 }
936
937 uint32_t ifindex = nla_get_u32(attrs[OVPN_A_IFINDEX]);
938 if (ifindex != dco->ifindex)
939 {
940 msg(D_DCO_DEBUG, "ovpn-dco: ignoring message for foreign ifindex %d", ifindex);
941 return false;
942 }
943
944 return true;
945}
946
947static int
948ovpn_handle_peer_del_ntf(dco_context_t *dco, struct nlattr *attrs[])
949{
950 if (!ovpn_iface_check(dco, attrs))
951 {
952 return NL_STOP;
953 }
954
955 if (!attrs[OVPN_A_PEER])
956 {
957 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no peer in PEER_DEL_NTF message");
958 return NL_STOP;
959 }
960
961 struct nlattr *dp_attrs[OVPN_A_PEER_MAX + 1];
962 if (nla_parse_nested(dp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL))
963 {
964 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: can't parse peer in PEER_DEL_NTF messsage");
965 return NL_STOP;
966 }
967
968 if (!dp_attrs[OVPN_A_PEER_DEL_REASON])
969 {
970 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no reason in PEER_DEL_NTF message");
971 return NL_STOP;
972 }
973 if (!dp_attrs[OVPN_A_PEER_ID])
974 {
975 msg(D_DCO | M_NOIPREFIX, "ovpn-dco: no peer-id in PEER_DEL_NTF message");
976 return NL_STOP;
977 }
978
979 int reason = nla_get_u32(dp_attrs[OVPN_A_PEER_DEL_REASON]);
980 unsigned int peerid = nla_get_u32(dp_attrs[OVPN_A_PEER_ID]);
981
982 msg(D_DCO_DEBUG | M_NOIPREFIX, "ovpn-dco: received CMD_PEER_DEL_NTF, ifindex: %d, peer-id %u, reason: %d",
983 dco->ifindex, peerid, reason);
984 dco->dco_message_peer_id = peerid;
985 dco->dco_del_peer_reason = reason;
986 dco->dco_message_type = OVPN_CMD_PEER_DEL_NTF;
987
988 return NL_OK;
989}
990
991static int
992ovpn_handle_peer_float_ntf(dco_context_t *dco, struct nlattr *attrs[])
993{
994 if (!ovpn_iface_check(dco, attrs))
995 {
996 return NL_STOP;
997 }
998
999 if (!attrs[OVPN_A_PEER])
1000 {
1001 msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message");
1002 return NL_STOP;
1003 }
1004
1005 struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1];
1006 if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL))
1007 {
1008 msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage");
1009 return NL_STOP;
1010 }
1011
1012 if (!fp_attrs[OVPN_A_PEER_ID])
1013 {
1014 msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message");
1015 return NL_STOP;
1016 }
1017 uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]);
1018
1019 if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss))
1020 {
1021 return NL_STOP;
1022 }
1023
1024 struct gc_arena gc = gc_new();
1025 msg(D_DCO_DEBUG, "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s",
1026 dco->ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc));
1027 dco->dco_message_peer_id = (int)peerid;
1028 dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF;
1029
1030 gc_free(&gc);
1031
1032 return NL_OK;
1033}
1034
1035static int
1036ovpn_handle_key_swap_ntf(dco_context_t *dco, struct nlattr *attrs[])
1037{
1038 if (!ovpn_iface_check(dco, attrs))
1039 {
1040 return NL_STOP;
1041 }
1042
1043 if (!attrs[OVPN_A_KEYCONF])
1044 {
1045 msg(D_DCO, "ovpn-dco: no keyconf in KEY_SWAP_NTF message");
1046 return NL_STOP;
1047 }
1048
1049 struct nlattr *dp_attrs[OVPN_A_KEYCONF_MAX + 1];
1050 if (nla_parse_nested(dp_attrs, OVPN_A_KEYCONF_MAX, attrs[OVPN_A_KEYCONF], NULL))
1051 {
1052 msg(D_DCO, "ovpn-dco: can't parse keyconf in KEY_SWAP_NTF message");
1053 return NL_STOP;
1054 }
1055 if (!dp_attrs[OVPN_A_KEYCONF_PEER_ID])
1056 {
1057 msg(D_DCO, "ovpn-dco: no peer-id in KEY_SWAP_NTF message");
1058 return NL_STOP;
1059 }
1060 if (!dp_attrs[OVPN_A_KEYCONF_KEY_ID])
1061 {
1062 msg(D_DCO, "ovpn-dco: no key-id in KEY_SWAP_NTF message");
1063 return NL_STOP;
1064 }
1065
1066 int key_id = nla_get_u16(dp_attrs[OVPN_A_KEYCONF_KEY_ID]);
1067 unsigned int peer_id = nla_get_u32(dp_attrs[OVPN_A_KEYCONF_PEER_ID]);
1068
1069 msg(D_DCO_DEBUG, "ovpn-dco: received CMD_KEY_SWAP_NTF, ifindex: %d, peer-id %u, key-id: %d",
1070 dco->ifindex, peer_id, key_id);
1071 dco->dco_message_peer_id = peer_id;
1072 dco->dco_message_key_id = key_id;
1073 dco->dco_message_type = OVPN_CMD_KEY_SWAP_NTF;
1074
1075 return NL_OK;
1076}
1077
1078/* This function parses any netlink message sent by ovpn-dco to userspace */
1079static int
1080ovpn_handle_msg(struct nl_msg *msg, void *arg)
1081{
1082 dco_context_t *dco = arg;
1083
1084 struct nlattr *attrs[OVPN_A_MAX + 1];
1085 struct nlmsghdr *nlh = nlmsg_hdr(msg);
1086 struct genlmsghdr *gnlh = genlmsg_hdr(nlh);
1087
1088 msg(D_DCO_DEBUG | M_NOIPREFIX, "ovpn-dco: received netlink message type=%u cmd=%u flags=%#.4x",
1089 nlh->nlmsg_type, gnlh->cmd, nlh->nlmsg_flags);
1090
1091 /* if we get a message from the NLCTRL family, it means
1092 * this is the reply to the mcast ID resolution request
1093 * and we parse it accordingly.
1094 */
1095 if (nlh->nlmsg_type == dco->ctrlid)
1096 {
1097 msg(D_DCO_DEBUG, "ovpn-dco: received CTRLID message");
1098 return mcast_family_handler(msg, dco);
1099 }
1100
1101 if (!genlmsg_valid_hdr(nlh, 0))
1102 {
1103 msg(D_DCO, "ovpn-dco: invalid header");
1104 return NL_STOP;
1105 }
1106
1107 if (nla_parse(attrs, OVPN_A_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL))
1108 {
1109 msg(D_DCO, "received bogus data from ovpn-dco");
1110 return NL_STOP;
1111 }
1112
1113 /* based on the message type, we parse the subobject contained in the
1114 * message, that stores the type-specific attributes.
1115 *
1116 * the "dco" object is then filled accordingly with the information
1117 * retrieved from the message, so that *process_incoming_dco can react
1118 * as need be.
1119 */
1120 int ret;
1121 switch (gnlh->cmd)
1122 {
1123 case OVPN_CMD_PEER_GET:
1124 {
1125 /* return directly, there are no messages to pass to *process_incoming_dco() */
1126 return ovpn_handle_peer(dco, attrs);
1127 }
1128
1130 {
1131 ret = ovpn_handle_peer_del_ntf(dco, attrs);
1132 break;
1133 }
1134
1136 {
1137 ret = ovpn_handle_peer_float_ntf(dco, attrs);
1138 break;
1139 }
1140
1142 {
1143 ret = ovpn_handle_key_swap_ntf(dco, attrs);
1144 break;
1145 }
1146
1147 default:
1148 msg(D_DCO, "ovpn-dco: received unknown command: %d", gnlh->cmd);
1149 dco->dco_message_type = 0;
1150 return NL_STOP;
1151 }
1152
1153 if (ret != NL_OK)
1154 {
1155 return ret;
1156 }
1157
1158 if (dco->c->mode == CM_TOP)
1159 {
1161 }
1162 else
1163 {
1165 }
1166
1167 return NL_OK;
1168}
1169
1170int
1172{
1173 msg(D_DCO_DEBUG, __func__);
1174
1175 return ovpn_nl_recvmsgs(dco, __func__);
1176}
1177
1178static int
1179dco_get_peer(dco_context_t *dco, int peer_id, const bool raise_sigusr1_on_err)
1180{
1181 ASSERT(dco);
1182
1183 if (__is_locked)
1184 {
1185 msg(D_DCO_DEBUG, "%s: cannot request peer stats while parsing other messages", __func__);
1186 return 0;
1187 }
1188
1189 /* peer_id == -1 means "dump all peers", but this is allowed in MP mode only.
1190 * If it happens in P2P mode it means that the DCO peer was deleted and we
1191 * can simply bail out
1192 */
1193 if (peer_id == -1 && dco->ifmode == OVPN_MODE_P2P)
1194 {
1195 return 0;
1196 }
1197
1198 msg(D_DCO_DEBUG | M_NOIPREFIX, "%s: peer-id %d", __func__, peer_id);
1199
1200 struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_PEER_GET);
1201 struct nlattr *attr = nla_nest_start(nl_msg, OVPN_A_PEER);
1202 int ret = -EMSGSIZE;
1203
1204 if (peer_id != -1)
1205 {
1206 NLA_PUT_U32(nl_msg, OVPN_A_PEER_ID, peer_id);
1207 }
1208 else
1209 {
1210 nlmsg_hdr(nl_msg)->nlmsg_flags |= NLM_F_DUMP;
1211 }
1212 nla_nest_end(nl_msg, attr);
1213
1214 ret = ovpn_nl_msg_send(dco, nl_msg, __func__);
1215
1216nla_put_failure:
1217 nlmsg_free(nl_msg);
1218
1219 if (raise_sigusr1_on_err && ret < 0)
1220 {
1221 msg(M_WARN, "Error retrieving DCO peer stats: the underlying DCO peer"
1222 "may have been deleted from the kernel without notifying "
1223 "userspace. Restarting the session");
1224 register_signal(dco->c->sig, SIGUSR1, "dco peer stats error");
1225 }
1226 return ret;
1227}
1228
1229int
1230dco_get_peer_stats(struct context *c, const bool raise_sigusr1_on_err)
1231{
1232 if (!c->c1.tuntap || c->c1.tuntap->dco.ifindex == 0)
1233 {
1234 return -1;
1235 }
1236
1237 return dco_get_peer(&c->c1.tuntap->dco, c->c2.tls_multi->dco_peer_id, raise_sigusr1_on_err);
1238}
1239
1240int
1241dco_get_peer_stats_multi(dco_context_t *dco, const bool raise_sigusr1_on_err)
1242{
1243 return dco_get_peer(dco, -1, raise_sigusr1_on_err);
1244}
1245
1246bool
1247dco_available(msglvl_t msglevel)
1248{
1249 if (resolve_ovpn_netlink_id(D_DCO_DEBUG) < 0)
1250 {
1251 msg(msglevel, "Note: Kernel support for ovpn-dco missing, disabling data channel offload.");
1252 return false;
1253 }
1254
1255 return true;
1256}
1257
1262static const char *
1263dco_version_string_in_tree(struct gc_arena *gc)
1264{
1265 struct buffer buf = alloc_buf_gc(256, gc);
1266 struct utsname system;
1267
1268 if (uname(&system))
1269 {
1270 return "ERR";
1271 }
1272
1273 buf_puts(&buf, system.release);
1274 buf_puts(&buf, " ");
1275 buf_puts(&buf, system.version);
1276 return BSTR(&buf);
1277}
1278
1285static const char *
1286dco_version_string_backports(FILE *fp, struct gc_arena *gc)
1287{
1288 char *str = gc_malloc(PATH_MAX, false, gc);
1289
1290 if (!fgets(str, PATH_MAX, fp))
1291 {
1292 return "ERR";
1293 }
1294
1295 /* remove potential newline at the end of the string */
1296 char *nl = strchr(str, '\n');
1297 if (nl)
1298 {
1299 *nl = '\0';
1300 }
1301
1302 return str;
1303}
1304
1305const char *
1307{
1308 const char *version;
1309 struct stat sb;
1310 FILE *fp;
1311
1312 if (stat("/sys/module/ovpn", &sb) != 0 || !S_ISDIR(sb.st_mode))
1313 {
1314 return "N/A";
1315 }
1316
1317 /* now that we know for sure that the module is loaded, if there's no
1318 * version file it means we're dealing with the in-tree version, otherwise
1319 * it's backports */
1320 fp = fopen("/sys/module/ovpn/version", "r");
1321 if (!fp)
1322 {
1323 return dco_version_string_in_tree(gc);
1324 }
1325 version = dco_version_string_backports(fp, gc);
1326
1327 fclose(fp);
1328 return version;
1329}
1330
1331void
1332dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
1333{
1334 if (dco && dco->nl_sock)
1335 {
1336 event_ctl(es, nl_socket_get_fd(dco->nl_sock), EVENT_READ, arg);
1337 }
1338}
1339
1340const char *
1342{
1343 return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305";
1344}
1345
1346bool
1348{
1349 return false;
1350}
1351
1352#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
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:183
int type
Definition tun.h:185
dco_context_t dco
Definition tun.h:249
char * actual_name
Definition tun.h:207
#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