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