24#include <netlink/genl/ctrl.h>
25#include <netlink/genl/family.h>
26#include <netlink/genl/genl.h>
27#include <netlink/netlink.h>
28#include <netlink/socket.h>
34#define nla_nest_start(_msg, _type) nla_nest_start(_msg, (_type) | NLA_F_NESTED)
76template <
typename ReadHandler>
77class GeNL :
public RC<thread_unsafe_refcount>
81 typedef std::unique_ptr<nl_msg,
decltype(&nlmsg_free)>
NlMsgPtr;
82 typedef std::unique_ptr<nl_sock,
decltype(&nl_socket_free)>
NlSockPtr;
83 typedef std::unique_ptr<nl_cb,
decltype(&nl_cb_put)>
NlCbPtr;
97 int nl_family_id = -1;
101 return nl_family_id >= 0;
112 explicit GeNL(openvpn_io::io_context &io_context,
113 unsigned int ifindex_arg,
114 ReadHandler read_handler_arg)
115 :
sock_ptr(nl_socket_alloc(), nl_socket_free),
116 cb_ptr(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put),
123 nl_socket_set_buffer_size(
sock, 8192, 8192);
128 " cannot connect to generic netlink: " << nl_geterror(
ret));
133 " cannot get multicast group: " << nl_geterror(mcast_id));
135 ret = nl_socket_add_membership(
sock, mcast_id);
142 " cannot find ovpn_dco netlink component: " <<
ovpn_dco_id);
148 nl_cb_set(
cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
149 [](
struct nl_msg *,
void *) ->
int
154 nl_socket_set_cb(
sock,
cb);
157 stream.reset(
new openvpn_io::posix::stream_descriptor(
158 io_context, nl_socket_get_fd(
sock)));
160 nl_socket_set_nonblocking(
sock);
186 auto *
msg = msg_ptr.get();
189 NLA_PUT_U32(
msg, OVPN_NEW_PEER_ATTR_PEER_ID, peer_id);
190 NLA_PUT_U32(
msg, OVPN_NEW_PEER_ATTR_SOCKET, fd);
191 NLA_PUT(
msg, OVPN_NEW_PEER_ATTR_SOCKADDR_REMOTE, salen, sa);
201 NLA_PUT(
msg, OVPN_NEW_PEER_ATTR_IPV6,
sizeof(addr6), &addr6);
204 nla_nest_end(
msg, attr);
223 auto *
msg = msg_ptr.get();
225 const int NONCE_TAIL_LEN = 8;
227 struct nlattr *key_dir;
231 OPENVPN_THROW(netlink_error,
" new_key() cannot allocate submessage");
234 NLA_PUT_U8(
msg, OVPN_NEW_KEY_ATTR_KEY_SLOT,
static_cast<uint8_t
>(key_slot));
235 NLA_PUT_U8(
msg, OVPN_NEW_KEY_ATTR_KEY_ID,
static_cast<uint8_t
>(kc->
key_id));
236 NLA_PUT_U16(
msg, OVPN_NEW_KEY_ATTR_CIPHER_ALG,
static_cast<uint16_t
>(kc->
cipher_alg));
241 " new_key() cannot allocate encrypt key submessage");
249 nla_nest_end(
msg, key_dir);
254 " new_key() cannot allocate decrypt key submessage");
262 nla_nest_end(
msg, key_dir);
264 nla_nest_end(
msg, attr);
282 auto msg_ptr =
create_msg(OVPN_CMD_SWAP_KEYS);
283 auto *
msg = msg_ptr.get();
286 OPENVPN_THROW(netlink_error,
" swap_keys() cannot allocate submessage");
288 NLA_PUT_U32(
msg, OVPN_SWAP_KEYS_ATTR_PEER_ID, peer_id);
290 nla_nest_end(
msg, attr);
296 OPENVPN_THROW(netlink_error,
" swap_keys() nla_put_failure");
306 void del_key(
int peer_id,
unsigned int key_slot)
309 auto *
msg = msg_ptr.get();
312 OPENVPN_THROW(netlink_error,
" del_key() cannot allocate submessage");
314 NLA_PUT_U32(
msg, OVPN_DEL_KEY_ATTR_PEER_ID, peer_id);
315 NLA_PUT_U8(
msg, OVPN_DEL_KEY_ATTR_KEY_SLOT,
static_cast<uint8_t
>(key_slot));
317 nla_nest_end(
msg, attr);
336 void set_peer(
int peer_id,
unsigned int keepalive_interval,
unsigned int keepalive_timeout)
339 auto *
msg = msg_ptr.get();
342 OPENVPN_THROW(netlink_error,
" set_peer() cannot allocate submessage");
344 NLA_PUT_U32(
msg, OVPN_SET_PEER_ATTR_PEER_ID, peer_id);
345 NLA_PUT_U32(
msg, OVPN_SET_PEER_ATTR_KEEPALIVE_INTERVAL, keepalive_interval);
346 NLA_PUT_U32(
msg, OVPN_SET_PEER_ATTR_KEEPALIVE_TIMEOUT, keepalive_timeout);
348 nla_nest_end(
msg, attr);
366 auto *
msg = msg_ptr.get();
369 OPENVPN_THROW(netlink_error,
" del_peer() cannot allocate submessage");
371 NLA_PUT_U32(
msg, OVPN_DEL_PEER_ATTR_PEER_ID, peer_id);
373 nla_nest_end(
msg, attr);
392 auto *
msg = msg_ptr.get();
395 OPENVPN_THROW(netlink_error,
" get_peer() cannot allocate submessage");
397 NLA_PUT_U32(
msg, OVPN_GET_PEER_ATTR_PEER_ID, peer_id);
399 nla_nest_end(
msg, attr);
409 stream->wait(openvpn_io::posix::stream_descriptor::wait_read);
461 struct nlattr *tb[CTRL_ATTR_MAX + 1];
462 struct genlmsghdr *gnlh =
static_cast<genlmsghdr *
>(
463 nlmsg_data(
reinterpret_cast<const nlmsghdr *
>(nlmsg_hdr(
msg))));
464 struct nlattr *mcgrp;
467 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
469 if (!tb[CTRL_ATTR_MCAST_GROUPS])
472 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp)
474 struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
477 CTRL_ATTR_MCAST_GRP_MAX,
478 static_cast<nlattr *
>(nla_data(mcgrp)),
482 if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
484 if (strncmp((
const char *)nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
486 nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])))
488 grp->
id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
508 NlMsgPtr msg_ptr(nlmsg_alloc(), nlmsg_free);
509 auto *
msg = msg_ptr.get();
511 NlCbPtr mcast_cb_ptr(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put);
512 auto *mcast_cb = mcast_cb_ptr.get();
514 int ctrlid = genl_ctrl_resolve(
sock,
"nlctrl");
516 genlmsg_put(
msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
522 nl_cb_err(mcast_cb, NL_CB_CUSTOM,
523 [](
struct sockaddr_nl *nla,
struct nlmsgerr *err,
void *arg) ->
int
525 int *
ret =
static_cast<int *
>(arg);
529 nl_cb_set(mcast_cb, NL_CB_ACK, NL_CB_CUSTOM,
530 [](
struct nl_msg *
msg,
void *arg) ->
int
532 int *
ret =
static_cast<int *
>(arg);
541 nl_recvmsgs(
sock, mcast_cb);
549 OPENVPN_THROW(netlink_error,
"get_mcast_id() nla_put_failure");
557 std::ostringstream os;
560 os <<
"error reading netlink message: " << error.message() <<
", "
574 catch (
const netlink_error &e)
586 stream->async_wait(openvpn_io::posix::stream_descriptor::wait_read,
587 [self =
Ptr(
this)](
const openvpn_io::error_code &error)
589 self->handle_read(error);
595 NlMsgPtr msg_ptr(nlmsg_alloc(), nlmsg_free);
596 genlmsg_put(msg_ptr.get(), 0, 0,
ovpn_dco_id, 0, 0, cmd, 0);
597 NLA_PUT_U32(msg_ptr.get(), OVPN_ATTR_IFINDEX,
ifindex);
601 OPENVPN_THROW(netlink_error,
" create_msg() nla_put_failure");
608 int ovpn_dco_err = 0;
613 int netlink_err = nl_recvmsgs(
sock,
cb);
615 if (ovpn_dco_err != 0)
617 "ovpn-dco error on receiving message: "
618 << strerror(-ovpn_dco_err) <<
", " << ovpn_dco_err);
622 "netlink error on receiving message: "
623 << nl_geterror(netlink_err) <<
", " << netlink_err);
636 GeNL *self =
static_cast<GeNL *
>(arg);
639 struct genlmsghdr *gnlh =
static_cast<genlmsghdr *
>(
640 nlmsg_data(
reinterpret_cast<const nlmsghdr *
>(nlmsg_hdr(
msg))));
641 struct nlmsghdr *nlh = nlmsg_hdr(
msg);
642 struct nlattr *attrs[OVPN_ATTR_MAX + 1];
644 if (!genlmsg_valid_hdr(nlh, 0))
650 if (nla_parse(attrs, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL))
656 if (!attrs[OVPN_ATTR_IFINDEX])
658 OPENVPN_LOG(
"missing OVPN_ATTR_IFINDEX attribute in message");
662 if (self->
ifindex != nla_get_u32(attrs[OVPN_ATTR_IFINDEX]))
667 case OVPN_CMD_DEL_PEER:
668 if (!attrs[OVPN_ATTR_DEL_PEER])
669 OPENVPN_THROW(netlink_error,
"missing OVPN_ATTR_DEL_PEER attribute in "
670 "OVPN_CMD_DEL_PEER command");
672 struct nlattr *del_peer_attrs[OVPN_DEL_PEER_ATTR_MAX + 1];
673 ret = nla_parse_nested(del_peer_attrs, OVPN_DEL_PEER_ATTR_MAX, attrs[OVPN_ATTR_DEL_PEER], NULL);
676 "cannot parse OVPN_ATTR_DEL_PEER attribute");
678 if (!del_peer_attrs[OVPN_DEL_PEER_ATTR_PEER_ID] || !del_peer_attrs[OVPN_DEL_PEER_ATTR_REASON])
679 OPENVPN_THROW(netlink_error,
"missing attributes in OVPN_CMD_DEL_PEER");
682 self->
buf.
write(&gnlh->cmd,
sizeof(gnlh->cmd));
685 uint32_t peer_id = nla_get_u32(del_peer_attrs[OVPN_DEL_PEER_ATTR_PEER_ID]);
686 self->
buf.
write(&peer_id,
sizeof(peer_id));
690 uint8_t reason = nla_get_u8(del_peer_attrs[OVPN_DEL_PEER_ATTR_REASON]);
691 self->
buf.
write(&reason,
sizeof(reason));
697 case OVPN_CMD_GET_PEER:
699 if (!attrs[OVPN_ATTR_GET_PEER])
700 OPENVPN_THROW(netlink_error,
"missing OVPN_ATTR_GET_PEER attribute in "
701 "OVPN_CMD_GET_PEER command reply");
703 struct nlattr *get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_MAX + 1];
704 ret = nla_parse_nested(get_peer_attrs, OVPN_GET_PEER_RESP_ATTR_MAX, attrs[OVPN_ATTR_GET_PEER], NULL);
706 OPENVPN_THROW(netlink_error,
"cannot parse OVPN_ATTR_GET_PEER attribute");
708 if (!get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_PEER_ID])
709 OPENVPN_THROW(netlink_error,
"missing attributes in OVPN_CMD_DEL_PEER");
712 peer.
id = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_PEER_ID]);
713 memcpy(&peer.
ipv4, nla_data(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_IPV4]),
sizeof(peer.
ipv4));
714 memcpy(&peer.
ipv6, nla_data(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_IPV6]),
sizeof(peer.
ipv6));
715 peer.
local_port = nla_get_u16(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LOCAL_PORT]);
717 nla_data(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_SOCKADDR_REMOTE]),
718 nla_len(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_SOCKADDR_REMOTE]));
719 peer.
keepalive.
interval = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_INTERVAL]);
720 peer.
keepalive.
timeout = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_KEEPALIVE_TIMEOUT]);
721 peer.
vpn.
rx_bytes = nla_get_u64(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES]);
722 peer.
vpn.
tx_bytes = nla_get_u64(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES]);
723 peer.
vpn.
rx_pkts = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_VPN_RX_PACKETS]);
724 peer.
vpn.
tx_pkts = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_VPN_TX_PACKETS]);
726 peer.
transport.
rx_bytes = nla_get_u64(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES]);
727 peer.
transport.
tx_bytes = nla_get_u64(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES]);
728 peer.
transport.
rx_pkts = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LINK_RX_PACKETS]);
729 peer.
transport.
tx_pkts = nla_get_u32(get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_LINK_TX_PACKETS]);
732 self->
buf.
write(&gnlh->cmd,
sizeof(gnlh->cmd));
733 self->
buf.
write(&peer,
sizeof(peer));
741 OPENVPN_LOG(__func__ <<
" unknown netlink command: " << (
int)gnlh->cmd);
763 struct nlmsgerr *err,
766 struct nlmsghdr *nlh = (
struct nlmsghdr *)err - 1;
767 struct nlattr *tb_msg[NLMSGERR_ATTR_MAX + 1];
768 int len = nlh->nlmsg_len;
769 struct nlattr *attrs;
770 int *
ret =
static_cast<int *
>(arg);
771 int ack_len =
sizeof(*nlh) +
sizeof(int) +
sizeof(*nlh);
775 if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
778 if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
779 ack_len +=
static_cast<int>(err->msg.nlmsg_len -
sizeof(*nlh));
784 attrs =
reinterpret_cast<nlattr *
>((
unsigned char *)nlh + ack_len);
787 nla_parse(tb_msg, NLMSGERR_ATTR_MAX, attrs, len, NULL);
788 if (tb_msg[NLMSGERR_ATTR_MSG])
791 << (
char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]));
799 int netlink_err = nl_send_auto(
sock,
msg);
803 "netlink error on sending message: "
804 << nl_geterror(netlink_err) <<
", " << netlink_err);
821 std::unique_ptr<openvpn_io::posix::stream_descriptor>
stream;
825template <
typename ReadHandler>
void reset(const size_t min_capacity, const unsigned int flags)
Resets the buffer with the specified minimum capacity and flags.
void write(const T *data, const size_t size)
Write data to the buffer.
OPENVPN_EXCEPTION(netlink_error)
void new_key(unsigned int key_slot, const KoRekey::KeyConfig *kc)
std::unique_ptr< nl_cb, decltype(&nl_cb_put)> NlCbPtr
static int mcast_family_handler(struct nl_msg *msg, void *arg)
void handle_read(const openvpn_io::error_code &error)
void new_peer(int peer_id, int fd, struct sockaddr *sa, socklen_t salen, IPv4::Addr vpn4, IPv6::Addr vpn6)
void get_peer(int peer_id, bool sync)
void send_netlink_message(struct nl_msg *msg)
void swap_keys(int peer_id)
static int ovpn_nl_cb_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
void read_netlink_message()
GeNL(openvpn_io::io_context &io_context, unsigned int ifindex_arg, ReadHandler read_handler_arg)
void del_peer(int peer_id)
NlMsgPtr create_msg(enum ovpn_nl_commands cmd)
void del_key(int peer_id, unsigned int key_slot)
std::unique_ptr< nl_sock, decltype(&nl_socket_free)> NlSockPtr
std::unique_ptr< openvpn_io::posix::stream_descriptor > stream
void set_peer(int peer_id, unsigned int keepalive_interval, unsigned int keepalive_timeout)
std::unique_ptr< nl_msg, decltype(&nlmsg_free)> NlMsgPtr
static int message_received(struct nl_msg *msg, void *arg)
std::uint32_t to_uint32_net() const
in6_addr to_in6_addr() const
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
#define OPENVPN_THROW(exc, stuff)
#define nla_nest_start(_msg, _type)
#define OPENVPN_LOG(args)
Support deferred server-side state creation when client connects.
int(* ovpn_nl_cb)(struct nl_msg *msg, void *arg)
void buf_write_string(Buffer &buf, const std::string &str)
@ OVPN_CIPHER_ALG_CHACHA20_POLY1305
@ OVPN_CIPHER_ALG_AES_GCM
#define OVPN_NL_MULTICAST_GROUP_PEERS
@ DESTRUCT_ZERO
if enabled, destructor will zero data before deletion
@ GROW
if enabled, buffer will grow (otherwise buffer_full exception will be thrown)
@ CONSTRUCT_ZERO
if enabled, constructors/init will zero allocated space
const unsigned char * cipher_key
unsigned int cipher_key_size
unsigned char nonce_tail[8]
struct sockaddr_storage remote
struct openvpn::OvpnDcoPeer::@110 vpn
struct openvpn::OvpnDcoPeer::@111 transport
RCPtr< struct OvpnDcoPeer > Ptr
struct openvpn::OvpnDcoPeer::@109 keepalive