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