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