25 #if defined(ENABLE_DCO) && defined(TARGET_FREEBSD)
29 #include <sys/param.h>
30 #include <sys/linker.h>
32 #include <sys/utsname.h>
34 #include <netinet/in.h>
44 sockaddr_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 *remote_in4,
struct in6_addr *remote_in6)
84 nvl = nvlist_create(0);
90 nvlist_add_nvlist(nvl,
"local", sockaddr_to_nvlist(localaddr));
95 nvlist_add_nvlist(nvl,
"remote", sockaddr_to_nvlist(remoteaddr));
100 nvlist_add_binary(nvl,
"vpn_ipv4", &remote_in4->s_addr,
101 sizeof(remote_in4->s_addr));
106 nvlist_add_binary(nvl,
"vpn_ipv6", remote_in6,
sizeof(*remote_in6));
109 nvlist_add_number(nvl,
"fd", sd);
110 nvlist_add_number(nvl,
"peerid", peerid);
113 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
115 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
117 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
134 ret = pipe2(dco->pipefd, O_CLOEXEC | O_NONBLOCK);
140 dco->fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
152 close(dco->pipefd[0]);
153 close(dco->pipefd[1]);
160 if (open_fd(dco) < 0)
162 msg(
M_ERR,
"Failed to open socket");
175 nvl = nvlist_create(0);
176 nvlist_add_number(nvl,
"ifmode", ifmode);
179 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
181 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
183 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
196 create_interface(
struct tuntap *tt,
const char *dev)
204 snprintf(ifr.ifr_name, IFNAMSIZ,
"ovpn");
205 ret = ioctl(tt->
dco.fd, SIOCIFCREATE2, &ifr);
209 msg(
M_WARN|
M_ERRNO,
"Failed to create interface %s (SIOCIFCREATE2)", ifr.ifr_name);
214 if (!strcmp(dev,
"tun"))
216 ifr.ifr_data =
"ovpn";
220 ifr.ifr_data = (
char *)dev;
223 snprintf(tt->
dco.ifname, IFNAMSIZ,
"%s", ifr.ifr_data);
225 ret = ioctl(tt->
dco.fd, SIOCSIFNAME, &ifr);
230 (void)ioctl(tt->
dco.fd, SIOCIFDESTROY, &ifr);
231 msg(
M_WARN|
M_ERRNO,
"Failed to create interface %s (SIOCSIFNAME)", ifr.ifr_data);
239 remove_interface(
struct tuntap *tt)
245 snprintf(ifr.ifr_name, IFNAMSIZ,
"%s", tt->
dco.ifname);
247 ret = ioctl(tt->
dco.fd, SIOCIFDESTROY, &ifr);
253 tt->
dco.ifname[0] = 0;
261 int ret = create_interface(tt, dev);
263 if (ret >= 0 || ret == -EEXIST)
266 int i = IFF_POINTOPOINT | IFF_MULTICAST;
269 i = IFF_BROADCAST | IFF_MULTICAST;
271 dco_set_ifmode(&tt->
dco, i);
280 remove_interface(tt);
293 nvl = nvlist_create(0);
294 nvlist_add_number(nvl,
"peerid", peerid);
297 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
299 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
301 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
322 nvl = nvlist_create(0);
323 nvlist_add_number(nvl,
"peerid", peerid);
326 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
328 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
330 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
350 msg(
D_DCO_DEBUG,
"%s: peer-id %d, slot %d", __func__, peerid, slot);
352 nvl = nvlist_create(0);
353 nvlist_add_number(nvl,
"slot", slot);
354 nvlist_add_number(nvl,
"peerid", peerid);
357 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
359 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
361 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
374 key_to_nvlist(
const uint8_t *
key,
const uint8_t *implicit_iv,
const char *ciphername)
379 nvl = nvlist_create(0);
381 nvlist_add_string(nvl,
"cipher", ciphername);
383 if (strcmp(ciphername,
"none") != 0)
387 nvlist_add_binary(nvl,
"key",
key, key_len);
388 nvlist_add_binary(nvl,
"iv", implicit_iv, 8);
401 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
404 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
416 const uint8_t *encrypt_key,
const uint8_t *encrypt_iv,
417 const uint8_t *decrypt_key,
const uint8_t *decrypt_iv,
418 const char *ciphername)
425 __func__, slot, keyid, peerid, ciphername);
427 nvl = nvlist_create(0);
429 nvlist_add_number(nvl,
"slot", slot);
430 nvlist_add_number(nvl,
"keyid", keyid);
431 nvlist_add_number(nvl,
"peerid", peerid);
433 nvlist_add_nvlist(nvl,
"encrypt",
434 key_to_nvlist(encrypt_key, encrypt_iv, ciphername));
435 nvlist_add_nvlist(nvl,
"decrypt",
436 key_to_nvlist(decrypt_key, decrypt_iv, ciphername));
439 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
441 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
443 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
450 ret = start_tun(dco);
461 int keepalive_interval,
int keepalive_timeout,
468 msg(
D_DCO_DEBUG,
"%s: peer-id %d, ping interval %d, ping timeout %d",
469 __func__, peerid, keepalive_interval, keepalive_timeout);
471 nvl = nvlist_create(0);
472 nvlist_add_number(nvl,
"peerid", peerid);
473 nvlist_add_number(nvl,
"interval", keepalive_interval);
474 nvlist_add_number(nvl,
"timeout", keepalive_timeout);
477 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
479 drv.ifd_data = nvlist_pack(nvl, &drv.ifd_len);
481 ret = ioctl(dco->fd, SIOCSDRVSPEC, &drv);
503 (void)
read(dco->pipefd[1], buf,
sizeof(buf));
506 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
509 drv.ifd_len =
sizeof(buf);
511 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
518 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
525 dco->dco_message_peer_id = nvlist_get_number(nvl,
"peerid");
527 type = nvlist_get_number(nvl,
"notification");
533 if (nvlist_exists_number(nvl,
"del_reason"))
535 uint32_t reason = nvlist_get_number(nvl,
"del_reason");
546 if (nvlist_exists_nvlist(nvl,
"bytes"))
548 const nvlist_t *bytes = nvlist_get_nvlist(nvl,
"bytes");
550 dco->dco_read_bytes = nvlist_get_number(bytes,
"in");
551 dco->dco_write_bytes = nvlist_get_number(bytes,
"out");
562 msg(
M_WARN,
"Unknown kernel notification %d", type);
574 struct if_clonereq ifcr;
578 bool available =
false;
582 (void)kldload(
"if_ovpn");
584 fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
594 ret = ioctl(fd, SIOCIFGCLONERS, &ifcr);
600 buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
606 ifcr.ifcr_count = ifcr.ifcr_total;
607 ifcr.ifcr_buffer = buf;
608 ret = ioctl(fd, SIOCIFGCLONERS, &ifcr);
614 for (
int i = 0; i < ifcr.ifcr_total; i++)
616 if (strcmp(buf + (i * IFNAMSIZ),
"openvpn") == 0)
652 if (!dco || !dco->open)
658 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
660 drv.ifd_len =
sizeof(buf);
663 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
670 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
677 if (nvlist_get_number(nvl,
"pending") > 0)
679 (void)
write(dco->pipefd[0],
" ", 1);
687 dco_update_peer_stat(
struct multi_context *m, uint32_t peerid,
const nvlist_t *nvl)
692 msg(
M_WARN,
"dco_update_peer_stat: invalid peer ID %d returned by kernel", peerid);
708 size_t buf_size = 4096;
710 const nvlist_t *
const *nvpeers;
714 if (!dco || !dco->open)
720 snprintf(drv.ifd_name, IFNAMSIZ,
"%s", dco->ifname);
724 buf = realloc(buf, buf_size);
725 drv.ifd_len = buf_size;
728 ret = ioctl(dco->fd, SIOCGDRVSPEC, &drv);
729 if (ret && errno == ENOSPC)
742 nvl = nvlist_unpack(buf, drv.ifd_len, 0);
750 if (!nvlist_exists_nvlist_array(nvl,
"peers"))
756 nvpeers = nvlist_get_nvlist_array(nvl,
"peers", &npeers);
757 for (
size_t i = 0; i < npeers; i++)
759 const nvlist_t *peer = nvpeers[i];
760 uint32_t peerid = nvlist_get_number(peer,
"peerid");
762 dco_update_peer_stat(m, peerid, nvlist_get_nvlist(peer,
"bytes"));
778 return "none:AES-256-GCM:AES-192-GCM:AES-128-GCM:CHACHA20-POLY1305";