28#if defined(ENABLE_DCO) && defined(TARGET_LINUX)
47#include <netlink/socket.h>
48#include <netlink/netlink.h>
49#include <netlink/genl/genl.h>
50#include <netlink/genl/family.h>
51#include <netlink/genl/ctrl.h>
58#define nla_nest_start(_msg, _type) \
59 nla_nest_start(_msg, (_type) | NLA_F_NESTED)
65typedef int (*ovpn_nl_cb)(
struct nl_msg *
msg,
void *arg);
79resolve_ovpn_netlink_id(
int msglevel)
82 struct nl_sock *nl_sock = nl_socket_alloc();
86 msg(msglevel,
"Allocating net link socket failed");
90 ret = genl_connect(nl_sock);
93 msg(msglevel,
"Cannot connect to generic netlink: %s",
102 msg(msglevel,
"Cannot find ovpn_dco netlink component: %s",
107 nl_socket_free(nl_sock);
111static struct nl_msg *
114 struct nl_msg *nl_msg = nlmsg_alloc();
117 msg(
M_ERR,
"cannot allocate netlink message");
121 genlmsg_put(nl_msg, 0, 0, dco->ovpn_dco_id, 0, 0, cmd, 0);
127 msg(
M_INFO,
"cannot put into netlink message");
134 int ret = nl_recvmsgs(dco->nl_sock, dco->nl_cb);
139 msg(
M_WARN,
"%s: netlink received interrupt due to signal - ignoring", prefix);
143 msg(
M_ERR,
"%s: netlink out of memory error", prefix);
147 msg(
M_WARN,
"%s: netlink reports blocking read - aborting wait", prefix);
151 msg(
M_ERR,
"%s: netlink reports device not found:", prefix);
154 case -NLE_OBJ_NOTFOUND:
155 msg(
M_INFO,
"%s: netlink reports object not found, ovpn-dco unloaded?", prefix);
161 msg(
M_NONFATAL,
"%s: netlink reports error (%d): %s", prefix, ret, nl_geterror(-ret));
181ovpn_nl_msg_send(
dco_context_t *dco,
struct nl_msg *nl_msg, ovpn_nl_cb cb,
182 void *cb_arg,
const char *prefix)
186 nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, cb, cb_arg);
187 nl_send_auto(dco->nl_sock, nl_msg);
189 while (dco->status == 1)
191 ovpn_nl_recvmsgs(dco, prefix);
196 msg(
M_INFO,
"%s: failed to send netlink message: %s (%d)",
197 prefix, strerror(-dco->status), dco->status);
204mapped_v4_to_v6(
struct sockaddr *sock,
struct gc_arena *
gc)
206 struct sockaddr_in6 *sock6 = (
struct sockaddr_in6 *)sock;
207 if (sock->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sock6->sin6_addr))
210 struct sockaddr_in *sock4;
212 memcpy(&sock4->sin_addr, sock6->sin6_addr.s6_addr + 12, 4);
213 sock4->sin_port = sock6->sin6_port;
214 sock4->sin_family = AF_INET;
215 return (
struct sockaddr *)sock4;
222 struct sockaddr *localaddr,
struct sockaddr *remoteaddr,
223 struct in_addr *vpn_ipv4,
struct in6_addr *vpn_ipv6)
226 const char *remotestr =
"[undefined]";
231 msg(
D_DCO_DEBUG,
"%s: peer-id %d, fd %d, remote addr: %s", __func__,
232 peerid, sd, remotestr);
244 remoteaddr = mapped_v4_to_v6(remoteaddr, &
gc);
252 localaddr = mapped_v4_to_v6(localaddr, &
gc);
253 if (localaddr->sa_family == AF_INET)
256 &((
struct sockaddr_in *)localaddr)->sin_addr);
258 else if (localaddr->sa_family == AF_INET6)
261 &((
struct sockaddr_in6 *)localaddr)->sin6_addr);
275 nla_nest_end(nl_msg, attr);
277 ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
307enum ovpn_nlmsgerr_attrs {
308 OVPN_NLMSGERR_ATTR_MISS_TYPE = 5,
309 OVPN_NLMSGERR_ATTR_MISS_NEST = 6,
310 OVPN_NLMSGERR_ATTR_MAX = 6,
322ovpn_nl_cb_error(
struct sockaddr_nl (*nla)
__attribute__ ((unused)),
323 struct nlmsgerr *err,
void *arg)
325 struct nlmsghdr *nlh = (
struct nlmsghdr *)err - 1;
326 struct nlattr *tb_msg[OVPN_NLMSGERR_ATTR_MAX + 1];
327 int len = nlh->nlmsg_len;
328 struct nlattr *attrs;
330 int ack_len =
sizeof(*nlh) +
sizeof(int) +
sizeof(*nlh);
334 if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
339 if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
341 ack_len += err->msg.nlmsg_len -
sizeof(*nlh);
349 attrs = (
void *)((
unsigned char *)nlh + ack_len);
352 nla_parse(tb_msg, OVPN_NLMSGERR_ATTR_MAX, attrs, len, NULL);
353 if (tb_msg[NLMSGERR_ATTR_MSG])
355 len = strnlen((
char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]),
356 nla_len(tb_msg[NLMSGERR_ATTR_MSG]));
358 (
char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]));
361 if (tb_msg[OVPN_NLMSGERR_ATTR_MISS_NEST])
363 msg(
M_WARN,
"kernel error: missing required nesting type %u\n",
364 nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_NEST]));
367 if (tb_msg[OVPN_NLMSGERR_ATTR_MISS_TYPE])
369 msg(
M_WARN,
"kernel error: missing required attribute type %u\n",
370 nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_TYPE]));
379 dco->ovpn_dco_id = resolve_ovpn_netlink_id(
M_ERR);
381 dco->nl_sock = nl_socket_alloc();
385 msg(
M_ERR,
"Cannot create netlink socket");
388 int ret = genl_connect(dco->nl_sock);
391 msg(
M_ERR,
"Cannot connect to generic netlink: %s",
399 dco->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
402 msg(
M_ERR,
"failed to allocate netlink callback");
405 nl_socket_set_cb(dco->nl_sock, dco->nl_cb);
407 nl_cb_err(dco->nl_cb, NL_CB_CUSTOM, ovpn_nl_cb_error, &dco->status);
408 nl_cb_set(dco->nl_cb, NL_CB_FINISH, NL_CB_CUSTOM, ovpn_nl_cb_finish,
410 nl_cb_set(dco->nl_cb, NL_CB_ACK, NL_CB_CUSTOM, ovpn_nl_cb_finish,
416 nl_socket_disable_seq_check(dco->nl_sock);
421 ASSERT(!nl_socket_set_buffer_size(dco->nl_sock, 1024*1024, 1024*1024));
441 ovpn_dco_init_netlink(dco);
448 nl_socket_free(dco->nl_sock);
452 nl_cb_put(dco->nl_cb);
461 ovpn_get_mcast_id(dco);
463 if (dco->ovpn_dco_mcast_id < 0)
465 msg(
M_ERR,
"cannot get mcast group: %s", nl_geterror(dco->ovpn_dco_mcast_id));
471 int ret = nl_socket_add_membership(dco->nl_sock, dco->ovpn_dco_mcast_id);
474 msg(
M_ERR,
"%s: failed to join groups: %d", __func__, ret);
484 int ret = net_iface_new(ctx, dev,
"ovpn-dco", &tt->
dco);
491 tt->
dco.ifindex = if_nametoindex(dev);
492 if (!tt->
dco.ifindex)
494 msg(
M_FATAL,
"DCO: cannot retrieve ifindex for interface %s", dev);
497 tt->
dco.dco_message_peer_id = -1;
499 ovpn_dco_register(&tt->
dco);
510 ovpn_dco_uninit_netlink(&tt->
dco);
527 nla_nest_end(nl_msg, attr);
529 ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
551 nla_nest_end(nl_msg, attr);
553 ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
565 msg(
D_DCO_DEBUG,
"%s: peer-id %d, slot %d", __func__, peerid, slot);
577 nla_nest_end(nl_msg, attr);
579 ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
589 const uint8_t *encrypt_key,
const uint8_t *encrypt_iv,
590 const uint8_t *decrypt_key,
const uint8_t *decrypt_iv,
591 const char *ciphername)
594 __func__, slot, keyid, peerid, ciphername);
597 const int nonce_tail_len = 8;
605 dco_cipher_t dco_cipher = dco_get_cipher(ciphername);
614 struct nlattr *key_enc = nla_nest_start(nl_msg,
622 nla_nest_end(nl_msg, key_enc);
624 struct nlattr *key_dec = nla_nest_start(nl_msg,
632 nla_nest_end(nl_msg, key_dec);
634 nla_nest_end(nl_msg, attr);
636 ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
645 int keepalive_interval,
int keepalive_timeout,
int mss)
647 msg(
D_DCO_DEBUG,
"%s: peer-id %d, keepalive %d/%d, mss %d", __func__,
648 peerid, keepalive_interval, keepalive_timeout, mss);
663 nla_nest_end(nl_msg, attr);
665 ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
680mcast_family_handler(
struct nl_msg *
msg,
void *arg)
683 struct nlattr *tb[CTRL_ATTR_MAX + 1];
684 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(
msg));
686 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
687 genlmsg_attrlen(gnlh, 0), NULL);
689 if (!tb[CTRL_ATTR_MCAST_GROUPS])
694 struct nlattr *mcgrp;
696 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp)
698 struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
700 nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX,
701 nla_data(mcgrp), nla_len(mcgrp), NULL);
703 if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]
704 || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
709 if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
711 nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
715 dco->ovpn_dco_mcast_id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
729 dco->ovpn_dco_mcast_id = -ENOENT;
733 int ctrlid = genl_ctrl_resolve(dco->nl_sock,
"nlctrl");
735 struct nl_msg *nl_msg = nlmsg_alloc();
741 genlmsg_put(nl_msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
744 NLA_PUT_STRING(nl_msg, CTRL_ATTR_FAMILY_NAME,
OVPN_NL_NAME);
746 ret = ovpn_nl_msg_send(dco, nl_msg, mcast_family_handler, dco, __func__);
755ovpn_handle_msg(
struct nl_msg *
msg,
void *arg)
759 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(
msg));
761 struct nlmsghdr *nlh = nlmsg_hdr(
msg);
763 if (!genlmsg_valid_hdr(nlh, 0))
765 msg(
D_DCO,
"ovpn-dco: invalid header");
769 if (nla_parse(attrs,
OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
770 genlmsg_attrlen(gnlh, 0), NULL))
772 msg(
D_DCO,
"received bogus data from ovpn-dco");
781 msg(
D_DCO,
"ovpn-dco: Received message without ifindex");
786 if (ifindex != dco->ifindex)
789 "ovpn-dco: ignoring message (type=%d) for foreign ifindex %d",
807 msg(
D_DCO,
"ovpn-dco: no attributes in OVPN_DEL_PEER message");
815 msg(
D_DCO,
"received bogus del peer packet data from ovpn-dco");
821 msg(
D_DCO,
"ovpn-dco: no reason in DEL_PEER message");
826 msg(
D_DCO,
"ovpn-dco: no peer-id in DEL_PEER message");
832 msg(
D_DCO_DEBUG,
"ovpn-dco: received CMD_DEL_PEER, ifindex: %d, peer-id %d, reason: %d",
833 ifindex, peerid, reason);
834 dco->dco_message_peer_id = peerid;
835 dco->dco_del_peer_reason = reason;
842 msg(
D_DCO,
"ovpn-dco: received unknown command: %d", gnlh->cmd);
843 dco->dco_message_type = 0;
854 nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, ovpn_handle_msg, dco);
856 return ovpn_nl_recvmsgs(dco, __func__);
860dco_update_peer_stat(
struct context_2 *c2,
struct nlattr *tb[], uint32_t
id)
870 msg(
M_WARN,
"%s: no link RX bytes provided in reply for peer %u",
882 msg(
M_WARN,
"%s: no link TX bytes provided in reply for peer %u",
894 msg(
M_WARN,
"%s: no VPN RX bytes provided in reply for peer %u",
906 msg(
M_WARN,
"%s: no VPN TX bytes provided in reply for peer %u",
912dco_parse_peer_multi(
struct nl_msg *
msg,
void *arg)
915 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(
msg));
920 genlmsg_attrlen(gnlh, 0), NULL);
935 msg(
M_WARN,
"%s: no peer-id provided in reply", __func__);
944 msg(
M_WARN,
"%s: cannot store DCO stats for peer %u", __func__,
956 const bool raise_sigusr1_on_err)
962 nlmsg_hdr(nl_msg)->nlmsg_flags |= NLM_F_DUMP;
964 int ret = ovpn_nl_msg_send(dco, nl_msg, dco_parse_peer_multi, m, __func__);
968 if (raise_sigusr1_on_err && ret < 0)
970 msg(
M_WARN,
"Error retrieving DCO peer stats: the underlying DCO peer"
971 "may have been deleted from the kernel without notifying "
972 "userspace. Restarting the session");
979dco_parse_peer(
struct nl_msg *
msg,
void *arg)
983 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(
msg));
988 genlmsg_attrlen(gnlh, 0), NULL);
1004 msg(
M_WARN,
"%s: no peer-id provided in reply", __func__);
1014 dco_update_peer_stat(&c->
c2, tb_peer, peer_id);
1038 int ret = -EMSGSIZE;
1041 nla_nest_end(nl_msg, attr);
1043 ret = ovpn_nl_msg_send(dco, nl_msg, dco_parse_peer, c, __func__);
1048 if (raise_sigusr1_on_err && ret < 0)
1050 msg(
M_WARN,
"Error retrieving DCO peer stats: the underlying DCO peer"
1051 "may have been deleted from the kernel without notifying "
1052 "userspace. Restarting the session");
1064 "Note: Kernel support for ovpn-dco missing, disabling data channel offload.");
1075 FILE *fp =
fopen(
"/sys/module/ovpn_dco_v2/version",
"r");
1102 if (dco && dco->nl_sock)
1111 return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305";
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
static void gc_free(struct gc_arena *a)
static struct gc_arena gc_new(void)
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)
void set_nonblock(socket_descriptor_t fd)
void set_cloexec(socket_descriptor_t fd)
static SERVICE_STATUS status
Header file for server-mode related structures and functions.
@ OVPN_DEL_PEER_ATTR_REASON
@ OVPN_DEL_PEER_ATTR_PEER_ID
@ OVPN_GET_PEER_RESP_ATTR_PEER_ID
@ OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES
@ OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES
@ OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES
@ OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES
@ OVPN_GET_PEER_RESP_ATTR_MAX
@ OVPN_NEW_KEY_ATTR_DECRYPT_KEY
@ OVPN_NEW_KEY_ATTR_KEY_ID
@ OVPN_NEW_KEY_ATTR_ENCRYPT_KEY
@ OVPN_NEW_KEY_ATTR_PEER_ID
@ OVPN_NEW_KEY_ATTR_CIPHER_ALG
@ OVPN_NEW_KEY_ATTR_KEY_SLOT
ovpn_nl_commands
enum ovpn_nl_commands - supported netlink commands
@ OVPN_CMD_SET_PEER
@OVPN_CMD_SET_PEER: Tweak parameters for an existing peer
@ OVPN_CMD_DEL_PEER
@OVPN_CMD_DEL_PEER: Remove peer from internal table
@ OVPN_CMD_NEW_PEER
@OVPN_CMD_NEW_PEER: Configure peer with its crypto keys
@ OVPN_CMD_GET_PEER
@OVPN_CMD_GET_PEER: Retrieve the status of a peer or all peers
@ OVPN_SET_PEER_ATTR_KEEPALIVE_INTERVAL
@ OVPN_SET_PEER_ATTR_KEEPALIVE_TIMEOUT
@ OVPN_SET_PEER_ATTR_PEER_ID
#define OVPN_NL_MULTICAST_GROUP_PEERS
@ OVPN_GET_PEER_ATTR_PEER_ID
@ OVPN_DEL_KEY_ATTR_PEER_ID
@ OVPN_DEL_KEY_ATTR_KEY_SLOT
@ OVPN_SWAP_KEYS_ATTR_PEER_ID
@ OVPN_NEW_PEER_ATTR_SOCKADDR_REMOTE
@ OVPN_NEW_PEER_ATTR_IPV4
@ OVPN_NEW_PEER_ATTR_PEER_ID
@ OVPN_NEW_PEER_ATTR_LOCAL_IP
@ OVPN_NEW_PEER_ATTR_SOCKET
@ OVPN_NEW_PEER_ATTR_IPV6
@ OVPN_KEY_DIR_ATTR_CIPHER_KEY
@ OVPN_KEY_DIR_ATTR_NONCE_TAIL
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.
static const char * print_sockaddr(const struct sockaddr *addr, struct gc_arena *gc)
static int af_addr_size(sa_family_t af)
Control Channel SSL/Data channel negotiation module.
Control Channel Verification Module.
Wrapper structure for dynamically allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
struct tuntap * tuntap
Tun/tap virtual network interface.
Level 2 context containing state that is reset on both SIGHUP and SIGUSR1 restarts.
counter_type dco_read_bytes
counter_type tun_read_bytes
counter_type dco_write_bytes
struct tls_multi * tls_multi
TLS state structure for this VPN tunnel.
counter_type tun_write_bytes
Contains all state information for one tunnel.
struct signal_info * sig
Internal error signaling object.
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 two sets of OpenSSL cipher and/or HMAC contexts for both sending and receiving directio...
Container for unidirectional cipher and HMAC key material.
Main OpenVPN server state structure.
struct context top
Storage structure for process-wide configuration.
struct multi_instance ** instances
Array of multi_instances.
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.