OpenVPN
dco_freebsd.c
Go to the documentation of this file.
1/*
2 * Interface to FreeBSD dco networking code
3 *
4 * Copyright (C) 2022 Rubicon Communications, LLC (Netgate). All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program (see the file COPYING included with this
17 * distribution); if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#if defined(ENABLE_DCO) && defined(TARGET_FREEBSD)
26
27#include "syshead.h"
28
29#include <sys/param.h>
30#include <sys/linker.h>
31#include <sys/nv.h>
32#include <sys/utsname.h>
33
34#include <netinet/in.h>
35
36#include "dco_freebsd.h"
37#include "dco.h"
38#include "tun.h"
39#include "crypto.h"
40#include "multi.h"
41#include "ssl_common.h"
42
43static nvlist_t *
44sockaddr_to_nvlist(const struct sockaddr *sa)
45{
46 nvlist_t *nvl = nvlist_create(0);
47
48 nvlist_add_number(nvl, "af", sa->sa_family);
49
50 switch (sa->sa_family)
51 {
52 case AF_INET:
53 {
54 const struct sockaddr_in *in = (const struct sockaddr_in *)sa;
55 nvlist_add_binary(nvl, "address", &in->sin_addr, sizeof(in->sin_addr));
56 nvlist_add_number(nvl, "port", in->sin_port);
57 break;
58 }
59
60 case AF_INET6:
61 {
62 const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *)sa;
63 nvlist_add_binary(nvl, "address", &in6->sin6_addr, sizeof(in6->sin6_addr));
64 nvlist_add_number(nvl, "port", in6->sin6_port);
65 break;
66 }
67
68 default:
69 ASSERT(0);
70 }
71
72 return (nvl);
73}
74
75int
76dco_new_peer(dco_context_t *dco, unsigned int peerid, int sd,
77 struct sockaddr *localaddr, struct sockaddr *remoteaddr,
78 struct in_addr *vpn_ipv4, struct in6_addr *vpn_ipv6)
79{
80 struct ifdrv drv;
81 nvlist_t *nvl, *local_nvl, *remote_nvl;
82 int ret;
83
84 nvl = nvlist_create(0);
85
86 msg(D_DCO_DEBUG, "%s: peer-id %d, fd %d", __func__, peerid, sd);
87
88 if (localaddr)
89 {
90 local_nvl = sockaddr_to_nvlist(localaddr);
91 nvlist_add_nvlist(nvl, "local", local_nvl);
92 }
93
94 if (remoteaddr)
95 {
96 remote_nvl = sockaddr_to_nvlist(remoteaddr);
97 nvlist_add_nvlist(nvl, "remote", remote_nvl);
98 }
99
100 if (vpn_ipv4)
101 {
102 nvlist_add_binary(nvl, "vpn_ipv4", &vpn_ipv4->s_addr,
103 sizeof(vpn_ipv4->s_addr));
104 }
105
106 if (vpn_ipv6)
107 {
108 nvlist_add_binary(nvl, "vpn_ipv6", vpn_ipv6, sizeof(*vpn_ipv6));
109 }
110
111 nvlist_add_number(nvl, "fd", sd);
112 nvlist_add_number(nvl, "peerid", peerid);
113
114 CLEAR(drv);
115 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
116 drv.ifd_cmd = OVPN_NEW_PEER;
117 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
118
119 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
120 if (ret)
121 {
122 msg(M_ERR | M_ERRNO, "Failed to create new peer");
123 }
124
125 free(drv.ifd_data);
126 if (localaddr)
127 {
128 nvlist_destroy(local_nvl);
129 }
130 if (remoteaddr)
131 {
132 nvlist_destroy(remote_nvl);
133 }
134 nvlist_destroy(nvl);
135
136 return ret;
137}
138
139static int
140open_fd(dco_context_t *dco)
141{
142 int ret;
143
144 ret = pipe2(dco->pipefd, O_CLOEXEC | O_NONBLOCK);
145 if (ret != 0)
146 {
147 return -1;
148 }
149
150 dco->fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
151 if (dco->fd != -1)
152 {
153 dco->open = true;
154 }
155
156 return dco->fd;
157}
158
159static void
160close_fd(dco_context_t *dco)
161{
162 close(dco->pipefd[0]);
163 close(dco->pipefd[1]);
164 close(dco->fd);
165}
166
167bool
168ovpn_dco_init(int mode, dco_context_t *dco, const char *dev_node)
169{
170 if (open_fd(dco) < 0)
171 {
172 msg(M_ERR, "Failed to open socket");
173 return false;
174 }
175 return true;
176}
177
178static int
179dco_set_ifmode(dco_context_t *dco, int ifmode)
180{
181 struct ifdrv drv;
182 nvlist_t *nvl;
183 int ret;
184
185 nvl = nvlist_create(0);
186 nvlist_add_number(nvl, "ifmode", ifmode);
187
188 CLEAR(drv);
189 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
190 drv.ifd_cmd = OVPN_SET_IFMODE;
191 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
192
193 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
194 if (ret)
195 {
196 msg(M_WARN | M_ERRNO, "dco_set_ifmode: failed to set ifmode=%08x", ifmode);
197 }
198
199 free(drv.ifd_data);
200 nvlist_destroy(nvl);
201
202 return ret;
203}
204
205static int
206create_interface(struct tuntap *tt, const char *dev)
207{
208 int ret;
209 struct ifreq ifr;
210
211 CLEAR(ifr);
212
213 /* Create ovpnx first, then rename it. */
214 snprintf(ifr.ifr_name, IFNAMSIZ, "ovpn");
215 ret = ioctl(tt->dco.fd, SIOCIFCREATE2, &ifr);
216 if (ret)
217 {
218 ret = -errno;
219 msg(M_WARN|M_ERRNO, "Failed to create interface %s (SIOCIFCREATE2)", ifr.ifr_name);
220 return ret;
221 }
222
223 /* Rename */
224 if (!strcmp(dev, "tun"))
225 {
226 ifr.ifr_data = "ovpn";
227 }
228 else
229 {
230 ifr.ifr_data = (char *)dev;
231 }
232
233 snprintf(tt->dco.ifname, IFNAMSIZ, "%s", ifr.ifr_data);
234
235 ret = ioctl(tt->dco.fd, SIOCSIFNAME, &ifr);
236 if (ret)
237 {
238 ret = -errno;
239 /* Delete the created interface again. */
240 (void)ioctl(tt->dco.fd, SIOCIFDESTROY, &ifr);
241 msg(M_WARN|M_ERRNO, "Failed to create interface %s (SIOCSIFNAME)", ifr.ifr_data);
242 return ret;
243 }
244
245 return 0;
246}
247
248static int
249remove_interface(struct tuntap *tt)
250{
251 int ret;
252 struct ifreq ifr;
253
254 CLEAR(ifr);
255 snprintf(ifr.ifr_name, IFNAMSIZ, "%s", tt->dco.ifname);
256
257 ret = ioctl(tt->dco.fd, SIOCIFDESTROY, &ifr);
258 if (ret)
259 {
260 msg(M_ERR | M_ERRNO, "Failed to remove interface %s", ifr.ifr_name);
261 }
262
263 tt->dco.ifname[0] = 0;
264
265 return ret;
266}
267
268int
269open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev)
270{
271 int ret = create_interface(tt, dev);
272
273 if (ret >= 0 || ret == -EEXIST)
274 {
275 /* see "Interface Flags" in ifnet(9) */
276 int i = IFF_POINTOPOINT | IFF_MULTICAST;
277 if (tt->topology == TOP_SUBNET)
278 {
279 i = IFF_BROADCAST | IFF_MULTICAST;
280 }
281 dco_set_ifmode(&tt->dco, i);
282 }
283
284 return ret;
285}
286
287void
288close_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx)
289{
290 remove_interface(tt);
291 close_fd(&tt->dco);
292}
293
294int
295dco_swap_keys(dco_context_t *dco, unsigned int peerid)
296{
297 struct ifdrv drv;
298 nvlist_t *nvl;
299 int ret;
300
301 msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peerid);
302
303 nvl = nvlist_create(0);
304 nvlist_add_number(nvl, "peerid", peerid);
305
306 CLEAR(drv);
307 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
308 drv.ifd_cmd = OVPN_SWAP_KEYS;
309 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
310
311 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
312 if (ret)
313 {
314 msg(M_WARN | M_ERRNO, "Failed to swap keys");
315 }
316
317 free(drv.ifd_data);
318 nvlist_destroy(nvl);
319
320 return ret;
321}
322
323int
324dco_del_peer(dco_context_t *dco, unsigned int peerid)
325{
326 struct ifdrv drv;
327 nvlist_t *nvl;
328 int ret;
329
330 msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peerid);
331
332 nvl = nvlist_create(0);
333 nvlist_add_number(nvl, "peerid", peerid);
334
335 CLEAR(drv);
336 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
337 drv.ifd_cmd = OVPN_DEL_PEER;
338 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
339
340 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
341 if (ret)
342 {
343 msg(M_WARN | M_ERRNO, "Failed to delete peer");
344 }
345
346 free(drv.ifd_data);
347 nvlist_destroy(nvl);
348
349 return ret;
350}
351
352int
353dco_del_key(dco_context_t *dco, unsigned int peerid,
354 dco_key_slot_t slot)
355{
356 struct ifdrv drv;
357 nvlist_t *nvl;
358 int ret;
359
360 msg(D_DCO_DEBUG, "%s: peer-id %d, slot %d", __func__, peerid, slot);
361
362 nvl = nvlist_create(0);
363 nvlist_add_number(nvl, "slot", slot);
364 nvlist_add_number(nvl, "peerid", peerid);
365
366 CLEAR(drv);
367 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
368 drv.ifd_cmd = OVPN_DEL_KEY;
369 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
370
371 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
372 if (ret)
373 {
374 msg(M_WARN | M_ERRNO, "Failed to delete key");
375 }
376
377 free(drv.ifd_data);
378 nvlist_destroy(nvl);
379
380 return ret;
381}
382
383static nvlist_t *
384key_to_nvlist(const uint8_t *key, const uint8_t *implicit_iv, const char *ciphername)
385{
386 nvlist_t *nvl;
387 size_t key_len;
388
389 nvl = nvlist_create(0);
390
391 nvlist_add_string(nvl, "cipher", ciphername);
392
393 if (strcmp(ciphername, "none") != 0)
394 {
395 key_len = cipher_kt_key_size(ciphername);
396
397 nvlist_add_binary(nvl, "key", key, key_len);
398 nvlist_add_binary(nvl, "iv", implicit_iv, 8);
399 }
400
401 return (nvl);
402}
403
404static int
405start_tun(dco_context_t *dco)
406{
407 struct ifdrv drv;
408 int ret;
409
410 CLEAR(drv);
411 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
412 drv.ifd_cmd = OVPN_START_VPN;
413
414 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
415 if (ret)
416 {
417 msg(M_ERR | M_ERRNO, "Failed to start vpn");
418 }
419
420 return ret;
421}
422
423int
424dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid,
425 dco_key_slot_t slot,
426 const uint8_t *encrypt_key, const uint8_t *encrypt_iv,
427 const uint8_t *decrypt_key, const uint8_t *decrypt_iv,
428 const char *ciphername)
429{
430 struct ifdrv drv;
431 nvlist_t *nvl, *encrypt_nvl, *decrypt_nvl;
432 int ret;
433
434 msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s",
435 __func__, slot, keyid, peerid, ciphername);
436
437 nvl = nvlist_create(0);
438
439 nvlist_add_number(nvl, "slot", slot);
440 nvlist_add_number(nvl, "keyid", keyid);
441 nvlist_add_number(nvl, "peerid", peerid);
442
443 encrypt_nvl = key_to_nvlist(encrypt_key, encrypt_iv, ciphername);
444 decrypt_nvl = key_to_nvlist(decrypt_key, decrypt_iv, ciphername);
445
446 nvlist_add_nvlist(nvl, "encrypt", encrypt_nvl);
447 nvlist_add_nvlist(nvl, "decrypt", decrypt_nvl);
448
449 CLEAR(drv);
450 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
451 drv.ifd_cmd = OVPN_NEW_KEY;
452 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
453
454 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
455 if (ret)
456 {
457 msg(M_ERR | M_ERRNO, "Failed to set key");
458 }
459 else
460 {
461 ret = start_tun(dco);
462 }
463
464 free(drv.ifd_data);
465 nvlist_destroy(encrypt_nvl);
466 nvlist_destroy(decrypt_nvl);
467 nvlist_destroy(nvl);
468
469 return ret;
470}
471
472int
473dco_set_peer(dco_context_t *dco, unsigned int peerid,
474 int keepalive_interval, int keepalive_timeout,
475 int mss)
476{
477 struct ifdrv drv;
478 nvlist_t *nvl;
479 int ret;
480
481 msg(D_DCO_DEBUG, "%s: peer-id %d, ping interval %d, ping timeout %d",
482 __func__, peerid, keepalive_interval, keepalive_timeout);
483
484 nvl = nvlist_create(0);
485 nvlist_add_number(nvl, "peerid", peerid);
486 nvlist_add_number(nvl, "interval", keepalive_interval);
487 nvlist_add_number(nvl, "timeout", keepalive_timeout);
488
489 CLEAR(drv);
490 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
491 drv.ifd_cmd = OVPN_SET_PEER;
492 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
493
494 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
495 if (ret)
496 {
497 msg(M_WARN | M_ERRNO, "Failed to set keepalive");
498 }
499
500 free(drv.ifd_data);
501 nvlist_destroy(nvl);
502
503 return ret;
504}
505
506int
508{
509 struct ifdrv drv;
510 uint8_t buf[4096];
511 nvlist_t *nvl;
512 enum ovpn_notif_type type;
513 int ret;
514
515 /* Flush any pending data from the pipe. */
516 (void)read(dco->pipefd[1], buf, sizeof(buf));
517
518 CLEAR(drv);
519 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
520 drv.ifd_cmd = OVPN_GET_PKT;
521 drv.ifd_data = buf;
522 drv.ifd_len = sizeof(buf);
523
524 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
525 if (ret)
526 {
527 msg(M_WARN | M_ERRNO, "Failed to read control packet");
528 return -errno;
529 }
530
531 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
532 if (!nvl)
533 {
534 msg(M_WARN, "Failed to unpack nvlist");
535 return -EINVAL;
536 }
537
538 dco->dco_message_peer_id = nvlist_get_number(nvl, "peerid");
539
540 type = nvlist_get_number(nvl, "notification");
541 switch (type)
542 {
544 dco->dco_del_peer_reason = OVPN_DEL_PEER_REASON_EXPIRED;
545
546 if (nvlist_exists_number(nvl, "del_reason"))
547 {
548 uint32_t reason = nvlist_get_number(nvl, "del_reason");
549 if (reason == OVPN_DEL_REASON_TIMEOUT)
550 {
551 dco->dco_del_peer_reason = OVPN_DEL_PEER_REASON_EXPIRED;
552 }
553 else
554 {
555 dco->dco_del_peer_reason = OVPN_DEL_PEER_REASON_USERSPACE;
556 }
557 }
558
559 if (nvlist_exists_nvlist(nvl, "bytes"))
560 {
561 const nvlist_t *bytes = nvlist_get_nvlist(nvl, "bytes");
562
563 dco->dco_read_bytes = nvlist_get_number(bytes, "in");
564 dco->dco_write_bytes = nvlist_get_number(bytes, "out");
565 }
566
567 dco->dco_message_type = OVPN_CMD_DEL_PEER;
568 break;
569
571 dco->dco_message_type = OVPN_CMD_SWAP_KEYS;
572 break;
573
574 default:
575 msg(M_WARN, "Unknown kernel notification %d", type);
576 break;
577 }
578
579 nvlist_destroy(nvl);
580
581 return 0;
582}
583
584bool
585dco_available(int msglevel)
586{
587 struct if_clonereq ifcr;
588 char *buf = NULL;
589 int fd;
590 int ret;
591 bool available = false;
592
593 /* Attempt to load the module. Ignore errors, because it might already be
594 * loaded, or built into the kernel. */
595 (void)kldload("if_ovpn");
596
597 fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
598 if (fd < 0)
599 {
600 return false;
601 }
602
603 CLEAR(ifcr);
604
605 /* List cloners and check if openvpn is there. That tells us if this kernel
606 * supports if_ovpn (i.e. DCO) or not. */
607 ret = ioctl(fd, SIOCIFGCLONERS, &ifcr);
608 if (ret != 0)
609 {
610 goto out;
611 }
612
613 buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
614 if (!buf)
615 {
616 goto out;
617 }
618
619 ifcr.ifcr_count = ifcr.ifcr_total;
620 ifcr.ifcr_buffer = buf;
621 ret = ioctl(fd, SIOCIFGCLONERS, &ifcr);
622 if (ret != 0)
623 {
624 goto out;
625 }
626
627 for (int i = 0; i < ifcr.ifcr_total; i++)
628 {
629 if (strcmp(buf + (i * IFNAMSIZ), "openvpn") == 0)
630 {
631 available = true;
632 goto out;
633 }
634 }
635
636out:
637 free(buf);
638 close(fd);
639
640 return available;
641}
642
643const char *
645{
646 struct utsname *uts;
647 ALLOC_OBJ_GC(uts, struct utsname, gc);
648
649 if (uname(uts) != 0)
650 {
651 return "N/A";
652 }
653
654 return uts->version;
655}
656
657void
658dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
659{
660 struct ifdrv drv;
661 nvlist_t *nvl;
662 uint8_t buf[128];
663 int ret;
664
665 if (!dco || !dco->open)
666 {
667 return;
668 }
669
670 CLEAR(drv);
671 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
672 drv.ifd_cmd = OVPN_POLL_PKT;
673 drv.ifd_len = sizeof(buf);
674 drv.ifd_data = buf;
675
676 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
677 if (ret)
678 {
679 msg(M_WARN | M_ERRNO, "Failed to poll for packets");
680 return;
681 }
682
683 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
684 if (!nvl)
685 {
686 msg(M_WARN, "Failed to unpack nvlist");
687 return;
688 }
689
690 if (nvlist_get_number(nvl, "pending") > 0)
691 {
692 (void)write(dco->pipefd[0], " ", 1);
693 event_ctl(es, dco->pipefd[1], EVENT_READ, arg);
694 }
695
696 nvlist_destroy(nvl);
697}
698
699static void
700dco_update_peer_stat(struct multi_context *m, uint32_t peerid, const nvlist_t *nvl)
701{
702
703 if (peerid >= m->max_clients || !m->instances[peerid])
704 {
705 msg(M_WARN, "dco_update_peer_stat: invalid peer ID %d returned by kernel", peerid);
706 return;
707 }
708
709 struct multi_instance *mi = m->instances[peerid];
710
711 mi->context.c2.dco_read_bytes = nvlist_get_number(nvl, "in");
712 mi->context.c2.dco_write_bytes = nvlist_get_number(nvl, "out");
713}
714
715int
717 const bool raise_sigusr1_on_err)
718{
719
720 struct ifdrv drv;
721 uint8_t *buf = NULL;
722 size_t buf_size = 4096;
723 nvlist_t *nvl;
724 const nvlist_t *const *nvpeers;
725 size_t npeers;
726 int ret;
727
728 if (!dco || !dco->open)
729 {
730 return 0;
731 }
732
733 CLEAR(drv);
734 snprintf(drv.ifd_name, IFNAMSIZ, "%s", dco->ifname);
735 drv.ifd_cmd = OVPN_GET_PEER_STATS;
736
737retry:
738 buf = realloc(buf, buf_size);
739 drv.ifd_len = buf_size;
740 drv.ifd_data = buf;
741
742 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
743 if (ret && errno == ENOSPC)
744 {
745 buf_size *= 2;
746 goto retry;
747 }
748
749 if (ret)
750 {
751 free(buf);
752 msg(M_WARN | M_ERRNO, "Failed to get peer stats");
753 return -EINVAL;
754 }
755
756 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
757 free(buf);
758 if (!nvl)
759 {
760 msg(M_WARN, "Failed to unpack nvlist");
761 return -EINVAL;
762 }
763
764 if (!nvlist_exists_nvlist_array(nvl, "peers"))
765 {
766 /* no peers */
767 nvlist_destroy(nvl);
768 return 0;
769 }
770
771 nvpeers = nvlist_get_nvlist_array(nvl, "peers", &npeers);
772 for (size_t i = 0; i < npeers; i++)
773 {
774 const nvlist_t *peer = nvpeers[i];
775 uint32_t peerid = nvlist_get_number(peer, "peerid");
776
777 dco_update_peer_stat(m, peerid, nvlist_get_nvlist(peer, "bytes"));
778 }
779
780 nvlist_destroy(nvl);
781 return 0;
782}
783
784int
785dco_get_peer_stats(struct context *c, const bool raise_sigusr1_on_err)
786{
787 /* Not implemented. */
788 return 0;
789}
790
791const char *
793{
794 return "none:AES-256-GCM:AES-192-GCM:AES-128-GCM:CHACHA20-POLY1305";
795}
796
797#endif /* defined(ENABLE_DCO) && defined(TARGET_FREEBSD) */
#define ALLOC_OBJ_GC(dptr, type, gc)
Definition buffer.h:1092
Data Channel Cryptography Module.
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_DEBUG
Definition errlevel.h:118
#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
@ write
@ read
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_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 M_ERRNO
Definition error.h:94
#define OVPN_SET_IFMODE
#define OVPN_SWAP_KEYS
#define OVPN_POLL_PKT
#define OVPN_DEL_PEER
@ OVPN_DEL_REASON_TIMEOUT
#define OVPN_GET_PKT
#define OVPN_GET_PEER_STATS
#define OVPN_START_VPN
#define OVPN_NEW_KEY
#define OVPN_NEW_PEER
ovpn_notif_type
@ OVPN_NOTIF_DEL_PEER
@ OVPN_NOTIF_ROTATE_KEY
#define OVPN_SET_PEER
#define OVPN_DEL_KEY
@ OVPN_CMD_SWAP_KEYS
@ OVPN_CMD_DEL_PEER
@OVPN_CMD_DEL_PEER: Remove peer from internal table
@ OVPN_DEL_PEER_REASON_EXPIRED
@ OVPN_DEL_PEER_REASON_USERSPACE
#define TOP_SUBNET
Definition proto.h:44
Control Channel Common Data Structures.
counter_type dco_read_bytes
Definition openvpn.h:267
counter_type dco_write_bytes
Definition openvpn.h:270
Contains all state information for one tunnel.
Definition openvpn.h:474
struct context_2 c2
Level 2 context.
Definition openvpn.h:514
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:117
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 multi_instance ** instances
Array of multi_instances.
Definition multi.h:164
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
Definition tun.h:181
int topology
Definition tun.h:186
dco_context_t dco
Definition tun.h:249
struct env_set * es
struct gc_arena gc
Definition test_ssl.c:155