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