25#if defined(ENABLE_DCO) && defined(TARGET_FREEBSD)
30#include <sys/linker.h>
32#include <sys/utsname.h>
34#include <netinet/in.h>
44sockaddr_to_nvlist(
const struct sockaddr *sa)
46 nvlist_t *nvl = nvlist_create(0);
48 nvlist_add_number(nvl,
"af", sa->sa_family);
50 switch (sa->sa_family)
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);
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);
77 struct sockaddr *localaddr,
struct sockaddr *remoteaddr,
78 struct in_addr *vpn_ipv4,
struct in6_addr *vpn_ipv6)
81 nvlist_t *nvl, *local_nvl, *remote_nvl;
84 nvl = nvlist_create(0);
90 local_nvl = sockaddr_to_nvlist(localaddr);
91 nvlist_add_nvlist(nvl,
"local", local_nvl);
96 remote_nvl = sockaddr_to_nvlist(remoteaddr);
97 nvlist_add_nvlist(nvl,
"remote", remote_nvl);
102 nvlist_add_binary(nvl,
"vpn_ipv4", &vpn_ipv4->s_addr,
103 sizeof(vpn_ipv4->s_addr));
108 nvlist_add_binary(nvl,
"vpn_ipv6", vpn_ipv6,
sizeof(*vpn_ipv6));
111 nvlist_add_number(nvl,
"fd", sd);
112 nvlist_add_number(nvl,
"peerid", peerid);
115 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
117 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
119 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
128 nvlist_destroy(local_nvl);
132 nvlist_destroy(remote_nvl);
144 ret = pipe2(dco->pipefd, O_CLOEXEC | O_NONBLOCK);
150 dco->fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
162 close(dco->pipefd[0]);
163 close(dco->pipefd[1]);
170 if (open_fd(dco) < 0)
172 msg(
M_ERR,
"Failed to open socket");
185 nvl = nvlist_create(0);
186 nvlist_add_number(nvl,
"ifmode", ifmode);
189 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
191 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
193 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
206create_interface(
struct tuntap *tt,
const char *dev)
214 snprintf(ifr.ifr_name, IFNAMSIZ,
"ovpn");
215 ret = ioctl(tt->
dco.fd, SIOCIFCREATE2, &ifr);
219 msg(
M_WARN|
M_ERRNO,
"Failed to create interface %s (SIOCIFCREATE2)", ifr.ifr_name);
224 if (!strcmp(dev,
"tun"))
226 ifr.ifr_data =
"ovpn";
230 ifr.ifr_data = (
char *)dev;
233 snprintf(tt->
dco.ifname, IFNAMSIZ,
"%s", ifr.ifr_data);
235 ret = ioctl(tt->
dco.fd, SIOCSIFNAME, &ifr);
240 (void)ioctl(tt->
dco.fd, SIOCIFDESTROY, &ifr);
241 msg(
M_WARN|
M_ERRNO,
"Failed to create interface %s (SIOCSIFNAME)", ifr.ifr_data);
249remove_interface(
struct tuntap *tt)
255 snprintf(ifr.ifr_name, IFNAMSIZ,
"%s", tt->
dco.ifname);
257 ret = ioctl(tt->
dco.fd, SIOCIFDESTROY, &ifr);
263 tt->
dco.ifname[0] = 0;
271 int ret = create_interface(tt, dev);
273 if (ret >= 0 || ret == -EEXIST)
276 int i = IFF_POINTOPOINT | IFF_MULTICAST;
279 i = IFF_BROADCAST | IFF_MULTICAST;
281 dco_set_ifmode(&tt->
dco, i);
290 remove_interface(tt);
303 nvl = nvlist_create(0);
304 nvlist_add_number(nvl,
"peerid", peerid);
307 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
309 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
311 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
332 nvl = nvlist_create(0);
333 nvlist_add_number(nvl,
"peerid", peerid);
336 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
338 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
340 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
360 msg(
D_DCO_DEBUG,
"%s: peer-id %d, slot %d", __func__, peerid, slot);
362 nvl = nvlist_create(0);
363 nvlist_add_number(nvl,
"slot", slot);
364 nvlist_add_number(nvl,
"peerid", peerid);
367 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
369 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
371 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
384key_to_nvlist(
const uint8_t *
key,
const uint8_t *implicit_iv,
const char *ciphername)
389 nvl = nvlist_create(0);
391 nvlist_add_string(nvl,
"cipher", ciphername);
393 if (strcmp(ciphername,
"none") != 0)
397 nvlist_add_binary(nvl,
"key",
key, key_len);
398 nvlist_add_binary(nvl,
"iv", implicit_iv, 8);
411 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
414 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
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)
431 nvlist_t *nvl, *encrypt_nvl, *decrypt_nvl;
435 __func__, slot, keyid, peerid, ciphername);
437 nvl = nvlist_create(0);
439 nvlist_add_number(nvl,
"slot", slot);
440 nvlist_add_number(nvl,
"keyid", keyid);
441 nvlist_add_number(nvl,
"peerid", peerid);
443 encrypt_nvl = key_to_nvlist(encrypt_key, encrypt_iv, ciphername);
444 decrypt_nvl = key_to_nvlist(decrypt_key, decrypt_iv, ciphername);
446 nvlist_add_nvlist(nvl,
"encrypt", encrypt_nvl);
447 nvlist_add_nvlist(nvl,
"decrypt", decrypt_nvl);
450 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
452 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
454 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
461 ret = start_tun(dco);
465 nvlist_destroy(encrypt_nvl);
466 nvlist_destroy(decrypt_nvl);
474 int keepalive_interval,
int keepalive_timeout,
481 msg(
D_DCO_DEBUG,
"%s: peer-id %d, ping interval %d, ping timeout %d",
482 __func__, peerid, keepalive_interval, keepalive_timeout);
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);
490 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
492 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
494 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
516 (void)
read(dco->pipefd[1], buf,
sizeof(buf));
519 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
522 drv.ifd_len =
sizeof(buf);
524 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
531 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
538 dco->dco_message_peer_id = nvlist_get_number(nvl,
"peerid");
540 type = nvlist_get_number(nvl,
"notification");
546 if (nvlist_exists_number(nvl,
"del_reason"))
548 uint32_t reason = nvlist_get_number(nvl,
"del_reason");
559 if (nvlist_exists_nvlist(nvl,
"bytes"))
561 const nvlist_t *bytes = nvlist_get_nvlist(nvl,
"bytes");
563 dco->dco_read_bytes = nvlist_get_number(bytes,
"in");
564 dco->dco_write_bytes = nvlist_get_number(bytes,
"out");
575 msg(
M_WARN,
"Unknown kernel notification %d", type);
587 struct if_clonereq ifcr;
591 bool available =
false;
595 (void)kldload(
"if_ovpn");
597 fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
607 ret = ioctl(fd, SIOCIFGCLONERS, &ifcr);
613 buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
619 ifcr.ifcr_count = ifcr.ifcr_total;
620 ifcr.ifcr_buffer = buf;
621 ret = ioctl(fd, SIOCIFGCLONERS, &ifcr);
627 for (
int i = 0; i < ifcr.ifcr_total; i++)
629 if (strcmp(buf + (i * IFNAMSIZ),
"openvpn") == 0)
665 if (!dco || !dco->open)
671 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
673 drv.ifd_len =
sizeof(buf);
676 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
683 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
690 if (nvlist_get_number(nvl,
"pending") > 0)
692 (void)
write(dco->pipefd[0],
" ", 1);
700dco_update_peer_stat(
struct multi_context *m, uint32_t peerid,
const nvlist_t *nvl)
705 msg(
M_WARN,
"dco_update_peer_stat: invalid peer ID %d returned by kernel", peerid);
717 const bool raise_sigusr1_on_err)
722 size_t buf_size = 4096;
724 const nvlist_t *
const *nvpeers;
728 if (!dco || !dco->open)
734 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
738 buf = realloc(buf, buf_size);
739 drv.ifd_len = buf_size;
742 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
743 if (ret && errno == ENOSPC)
756 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
764 if (!nvlist_exists_nvlist_array(nvl,
"peers"))
771 nvpeers = nvlist_get_nvlist_array(nvl,
"peers", &npeers);
772 for (
size_t i = 0; i < npeers; i++)
774 const nvlist_t *peer = nvpeers[i];
775 uint32_t peerid = nvlist_get_number(peer,
"peerid");
777 dco_update_peer_stat(m, peerid, nvlist_get_nvlist(peer,
"bytes"));
794 return "none:AES-256-GCM:AES-192-GCM:AES-128-GCM:CHACHA20-POLY1305";
#define ALLOC_OBJ_GC(dptr, type, gc)
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)
static int dco_set_peer(dco_context_t *dco, unsigned int peerid, int keepalive_interval, int keepalive_timeout, int mss)
static const char * dco_get_supported_ciphers(void)
static int dco_do_read(dco_context_t *dco)
static void dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
static int open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev)
static int dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m, const bool raise_sigusr1_on_err)
static bool ovpn_dco_init(int mode, dco_context_t *dco, const char *dev_node)
static const char * dco_version_string(struct gc_arena *gc)
static void close_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx)
static int dco_get_peer_stats(struct context *c, const bool raise_sigusr1_on_err)
int dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot)
int dco_del_peer(dco_context_t *dco, unsigned int peerid)
int dco_swap_keys(dco_context_t *dco, unsigned int peer_id)
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)
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)
static void event_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
Header file for server-mode related structures and functions.
@ OVPN_DEL_REASON_TIMEOUT
#define OVPN_GET_PEER_STATS
@ OVPN_CMD_DEL_PEER
@OVPN_CMD_DEL_PEER: Remove peer from internal table
@ OVPN_DEL_PEER_REASON_EXPIRED
@ OVPN_DEL_PEER_REASON_USERSPACE
Control Channel Common Data Structures.
counter_type dco_read_bytes
counter_type dco_write_bytes
Contains all state information for one tunnel.
struct context_2 c2
Level 2 context.
Garbage collection arena used to keep track of dynamically allocated memory.
Container for unidirectional cipher and HMAC key material.
Main OpenVPN server state structure.
struct multi_instance ** instances
Array of multi_instances.
Server-mode state structure for one single VPN tunnel.
struct context context
The context structure storing state for this VPN tunnel.