24#if defined(ENABLE_DCO) && defined(TARGET_FREEBSD)
29#include <sys/linker.h>
31#include <sys/utsname.h>
33#include <netinet/in.h>
43sockaddr_to_nvlist(
const struct sockaddr *sa)
45 nvlist_t *nvl = nvlist_create(0);
47 nvlist_add_number(nvl,
"af", sa->sa_family);
49 switch (sa->sa_family)
53 const struct sockaddr_in *in = (
const struct sockaddr_in *)sa;
54 nvlist_add_binary(nvl,
"address", &in->sin_addr,
sizeof(in->sin_addr));
55 nvlist_add_number(nvl,
"port", in->sin_port);
61 const struct sockaddr_in6 *in6 = (
const struct sockaddr_in6 *)sa;
62 nvlist_add_binary(nvl,
"address", &in6->sin6_addr,
sizeof(in6->sin6_addr));
63 nvlist_add_number(nvl,
"port", in6->sin6_port);
64 nvlist_add_number(nvl,
"scopeid", in6->sin6_scope_id);
76nvlist_to_sockaddr(
const nvlist_t *nvl,
struct sockaddr_storage *ss)
78 if (!nvlist_exists_number(nvl,
"af"))
82 if (!nvlist_exists_binary(nvl,
"address"))
86 if (!nvlist_exists_number(nvl,
"port"))
91 ss->ss_family = (
unsigned char)nvlist_get_number(nvl,
"af");
93 switch (ss->ss_family)
97 struct sockaddr_in *in = (
struct sockaddr_in *)ss;
101 in->sin_len =
sizeof(*in);
102 data = nvlist_get_binary(nvl,
"address", &len);
103 ASSERT(len ==
sizeof(in->sin_addr));
104 memcpy(&in->sin_addr, data,
sizeof(in->sin_addr));
105 in->sin_port = (
in_port_t)nvlist_get_number(nvl,
"port");
111 struct sockaddr_in6 *in6 = (
struct sockaddr_in6 *)ss;
115 in6->sin6_len =
sizeof(*in6);
116 data = nvlist_get_binary(nvl,
"address", &len);
117 ASSERT(len ==
sizeof(in6->sin6_addr));
118 memcpy(&in6->sin6_addr, data,
sizeof(in6->sin6_addr));
119 in6->sin6_port = (
in_port_t)nvlist_get_number(nvl,
"port");
121 if (nvlist_exists_number(nvl,
"scopeid"))
123 in6->sin6_scope_id = (uint32_t)nvlist_get_number(nvl,
"scopeid");
137 struct sockaddr *remoteaddr,
const struct in_addr *vpn_ipv4,
138 const struct in6_addr *vpn_ipv6)
141 nvlist_t *nvl, *local_nvl, *remote_nvl;
144 nvl = nvlist_create(0);
150 local_nvl = sockaddr_to_nvlist(localaddr);
151 nvlist_add_nvlist(nvl,
"local", local_nvl);
156 remote_nvl = sockaddr_to_nvlist(remoteaddr);
157 nvlist_add_nvlist(nvl,
"remote", remote_nvl);
162 nvlist_add_binary(nvl,
"vpn_ipv4", &vpn_ipv4->s_addr,
sizeof(vpn_ipv4->s_addr));
167 nvlist_add_binary(nvl,
"vpn_ipv6", vpn_ipv6,
sizeof(*vpn_ipv6));
170 nvlist_add_number(nvl,
"fd", sd);
171 nvlist_add_number(nvl,
"peerid", peerid);
174 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
176 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
178 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
181 msg(
M_ERR,
"Failed to create new peer");
187 nvlist_destroy(local_nvl);
191 nvlist_destroy(remote_nvl);
203 ret = pipe2(dco->pipefd, O_CLOEXEC | O_NONBLOCK);
209 dco->fd = socket(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
221 close(dco->pipefd[0]);
222 close(dco->pipefd[1]);
233 msg(
M_ERR,
"Failed to open socket");
246 nvl = nvlist_create(0);
247 nvlist_add_number(nvl,
"ifmode", ifmode);
250 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
252 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
254 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
267create_interface(
struct tuntap *tt,
const char *dev)
275 snprintf(ifr.ifr_name, IFNAMSIZ,
"ovpn");
276 ret = ioctl(tt->
dco.fd, SIOCIFCREATE2, &ifr);
280 msg(
M_WARN |
M_ERRNO,
"Failed to create interface %s (SIOCIFCREATE2)", ifr.ifr_name);
285 if (!strcmp(dev,
"tun"))
287 ifr.ifr_data =
"ovpn";
291 ifr.ifr_data = (
char *)dev;
294 snprintf(tt->
dco.ifname, IFNAMSIZ,
"%s", ifr.ifr_data);
296 ret = ioctl(tt->
dco.fd, SIOCSIFNAME, &ifr);
301 (void)ioctl(tt->
dco.fd, SIOCIFDESTROY, &ifr);
302 msg(
M_WARN |
M_ERRNO,
"Failed to create interface %s (SIOCSIFNAME)", ifr.ifr_data);
310remove_interface(
struct tuntap *tt)
316 snprintf(ifr.ifr_name, IFNAMSIZ,
"%s", tt->
dco.ifname);
318 ret = ioctl(tt->
dco.fd, SIOCIFDESTROY, &ifr);
321 msg(
M_ERR,
"Failed to remove interface %s", ifr.ifr_name);
324 tt->
dco.ifname[0] = 0;
332 int ret = create_interface(tt, dev);
334 if (ret >= 0 || ret == -EEXIST)
337 int i = IFF_POINTOPOINT | IFF_MULTICAST;
340 i = IFF_BROADCAST | IFF_MULTICAST;
342 dco_set_ifmode(&tt->
dco, i);
351 remove_interface(tt);
364 nvl = nvlist_create(0);
365 nvlist_add_number(nvl,
"peerid", peerid);
368 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
370 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
372 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
393 nvl = nvlist_create(0);
394 nvlist_add_number(nvl,
"peerid", peerid);
397 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
399 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
401 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
420 msg(
D_DCO_DEBUG,
"%s: peer-id %u, slot %d", __func__, peerid, slot);
422 nvl = nvlist_create(0);
423 nvlist_add_number(nvl,
"slot", slot);
424 nvlist_add_number(nvl,
"peerid", peerid);
427 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
429 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
431 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
444key_to_nvlist(
const uint8_t *
key,
const uint8_t *implicit_iv,
const char *ciphername)
449 nvl = nvlist_create(0);
451 nvlist_add_string(nvl,
"cipher", ciphername);
453 if (strcmp(ciphername,
"none") != 0)
457 nvlist_add_binary(nvl,
"key",
key, key_len);
458 nvlist_add_binary(nvl,
"iv", implicit_iv, 8);
471 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
474 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
485 const uint8_t *encrypt_key,
const uint8_t *encrypt_iv,
const uint8_t *decrypt_key,
486 const uint8_t *decrypt_iv,
const char *ciphername,
bool epoch)
489 nvlist_t *nvl, *encrypt_nvl, *decrypt_nvl;
492 msg(
D_DCO_DEBUG,
"%s: slot %d, key-id %d, peer-id %u, cipher %s, epoch %d", __func__, slot, keyid, peerid,
495 nvl = nvlist_create(0);
497 nvlist_add_number(nvl,
"slot", slot);
498 nvlist_add_number(nvl,
"keyid", keyid);
499 nvlist_add_number(nvl,
"peerid", peerid);
501 encrypt_nvl = key_to_nvlist(encrypt_key, encrypt_iv, ciphername);
502 decrypt_nvl = key_to_nvlist(decrypt_key, decrypt_iv, ciphername);
504 nvlist_add_nvlist(nvl,
"encrypt", encrypt_nvl);
505 nvlist_add_nvlist(nvl,
"decrypt", decrypt_nvl);
508 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
510 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
512 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
519 ret = start_tun(dco);
523 nvlist_destroy(encrypt_nvl);
524 nvlist_destroy(decrypt_nvl);
538 msg(
D_DCO_DEBUG,
"%s: peer-id %u, ping interval %d, ping timeout %d", __func__, peerid,
539 keepalive_interval, keepalive_timeout);
541 nvl = nvlist_create(0);
542 nvlist_add_number(nvl,
"peerid", peerid);
543 nvlist_add_number(nvl,
"interval", keepalive_interval);
544 nvlist_add_number(nvl,
"timeout", keepalive_timeout);
547 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
549 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
551 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
564dco_update_peer_stat(
struct multi_context *m, uint32_t peerid,
const nvlist_t *nvl)
568 msg(
M_WARN,
"dco_update_peer_stat: invalid peer ID %u returned by kernel", peerid);
591 (void)
read(dco->pipefd[1], buf,
sizeof(buf));
594 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
597 drv.ifd_len =
sizeof(buf);
599 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
606 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
616 dco->dco_message_peer_id = (int)nvlist_get_number(nvl,
"peerid");
625 if (nvlist_exists_number(nvl,
"del_reason"))
627 uint32_t reason = (uint32_t)nvlist_get_number(nvl,
"del_reason");
637 msg(
D_DCO_DEBUG,
"%s: received NOTIF_DEL_PEER for peer-id=%d, reason=%d", __func__,
638 dco->dco_message_peer_id, dco->dco_del_peer_reason);
640 if (nvlist_exists_nvlist(nvl,
"bytes"))
642 const nvlist_t *bytes = nvlist_get_nvlist(nvl,
"bytes");
644 if (dco->c->mode ==
CM_TOP)
646 dco_update_peer_stat(dco->c->multi, dco->dco_message_peer_id, bytes);
650 dco->c->c2.dco_read_bytes = nvlist_get_number(bytes,
"in");
651 dco->c->c2.dco_write_bytes = nvlist_get_number(bytes,
"out");
659 msg(
D_DCO_DEBUG,
"%s: received NOTIF_ROTATE_KEY for peer-id=%d", __func__,
660 dco->dco_message_peer_id);
668 if (!nvlist_exists_nvlist(nvl,
"address"))
670 msg(
M_WARN,
"Float notification without address");
674 address = nvlist_get_nvlist(nvl,
"address");
675 if (!nvlist_to_sockaddr(
address, &dco->dco_float_peer_ss))
677 msg(
M_WARN,
"Failed to parse float notification");
680 msg(
D_DCO_DEBUG,
"%s: received NOTIF_FLOAT for peer-id=%d", __func__,
681 dco->dco_message_peer_id);
687 msg(
M_WARN,
"%s: unknown kernel notification %d", __func__, type);
688 dco->dco_message_type = 0;
694 if (dco->c->mode ==
CM_TOP)
709 struct if_clonereq ifcr;
713 bool available =
false;
717 (void)kldload(
"if_ovpn");
719 fd = socket(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
722 msg(
M_WARN |
M_ERRNO,
"%s: socket() failed, disabling data channel offload", __func__);
730 ret = ioctl(fd, SIOCIFGCLONERS, &ifcr);
736 buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
742 ifcr.ifcr_count = ifcr.ifcr_total;
743 ifcr.ifcr_buffer = buf;
744 ret = ioctl(fd, SIOCIFGCLONERS, &ifcr);
750 for (
int i = 0; i < ifcr.ifcr_total; i++)
752 if (strcmp(buf + (i * IFNAMSIZ),
"openvpn") == 0)
788 if (!dco || !dco->open)
794 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
796 drv.ifd_len =
sizeof(buf);
799 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
806 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
813 if (nvlist_get_number(nvl,
"pending") > 0)
815 (void)
write(dco->pipefd[0],
" ", 1);
827 size_t buf_size = 4096;
829 const nvlist_t *
const *nvpeers;
833 if (!dco || !dco->open)
841 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
845 buf = realloc(buf, buf_size);
847 drv.ifd_len = buf_size;
850 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
851 if (ret && errno == ENOSPC)
864 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
872 if (!nvlist_exists_nvlist_array(nvl,
"peers"))
879 nvpeers = nvlist_get_nvlist_array(nvl,
"peers", &npeers);
880 for (
size_t i = 0; i < npeers; i++)
882 const nvlist_t *peer = nvpeers[i];
883 uint32_t peerid = (uint32_t)nvlist_get_number(peer,
"peerid");
884 const nvlist_t *bytes = nvlist_get_nvlist(peer,
"bytes");
889 if (dco->c->mode ==
CM_TOP)
891 dco_update_peer_stat(dco->c->multi, peerid, bytes);
895 dco->c->c2.dco_read_bytes = nvlist_get_number(bytes,
"in");
896 dco->c->c2.dco_write_bytes = nvlist_get_number(bytes,
"out");
929 return "none:AES-256-GCM:AES-192-GCM:AES-128-GCM:CHACHA20-POLY1305";
#define ALLOC_OBJ_GC(dptr, type, gc)
Allocate a garbage-collected object of the given type (uninitialised).
static void check_malloc_return(void *p)
Abort if a memory allocation returned NULL.
Data Channel Cryptography Module.
unsigned int cipher_kt_key_size(const char *ciphername)
Returns the size of keys used by the cipher, in bytes.
static int dco_get_peer_stats_multi(dco_context_t *dco, const bool raise_sigusr1_on_err)
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 bool dco_supports_epoch_data(struct context *c)
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_read_and_process(dco_context_t *dco)
static bool dco_available(msglvl_t msglevel)
static bool ovpn_dco_init(struct context *c)
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, socket_descriptor_t sd, struct sockaddr *localaddr, struct sockaddr *remoteaddr, const struct in_addr *vpn_ipv4, const 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, bool epoch)
static void event_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
void process_incoming_dco(dco_context_t *dco)
Process an incoming DCO message (from kernel space).
Header file for server-mode related structures and functions.
void multi_process_incoming_dco(dco_context_t *dco)
Process an incoming DCO message (from kernel space).
@ OVPN_DEL_REASON_TIMEOUT
#define OVPN_GET_PEER_STATS
@ OVPN_DEL_PEER_REASON_EXPIRED
@ OVPN_DEL_PEER_REASON_USERSPACE
Control Channel Common Data Structures.
struct tuntap * tuntap
Tun/tap virtual network interface.
counter_type dco_read_bytes
counter_type dco_write_bytes
struct tls_multi * tls_multi
TLS state structure for this VPN tunnel.
Contains all state information for one tunnel.
struct context_2 c2
Level 2 context.
struct context_1 c1
Level 1 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 with the size of max_clients.
Server-mode state structure for one single VPN tunnel.
struct context context
The context structure storing state for this VPN tunnel.
int dco_peer_id
This is the handle that DCO uses to identify this session with the kernel.