OpenVPN 3 Core Library
Loading...
Searching...
No Matches
genl.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8// Copyright (C) 2020-2022 Lev Stipakov <lev@openvpn.net>
9//
10// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
11//
12
13
14#pragma once
15
16#include <openvpn/addr/ipv4.hpp>
17#include <openvpn/addr/ipv6.hpp>
21#include <openvpn/dco/key.hpp>
22
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>
29
30#include <memory>
31
32/* The following enum members exist in netlink.h since linux-6.1.
33 * However, some distro we support still ship an old header, thus
34 * failing the OpenVPN compilation.
35 *
36 * For the time being we add the needed defines manually.
37 * We will drop this definition once we stop supporting those old
38 * distros.
39 *
40 * @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute,
41 * %NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was
42 * missing at the message level
43 * @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing
44 */
51
52namespace openvpn {
53
54#define nla_nest_start(_msg, _type) nla_nest_start(_msg, (_type) | NLA_F_NESTED)
55
56/* libnl < 3.11.0 does not implement nla_get_uint() */
57uint64_t ovpn_nla_get_uint(struct nlattr *attr)
58{
59 if (nla_len(attr) == sizeof(uint32_t))
60 return nla_get_u32(attr);
61 else
62 return nla_get_u64(attr);
63}
64
65typedef int (*ovpn_nl_cb)(struct nl_msg *msg, void *arg);
66
68{
70 __u32 id;
71 struct in_addr ipv4;
72 struct in6_addr ipv6;
74 struct sockaddr_storage remote;
75 struct
76 {
77 __u32 interval;
78 __u32 timeout;
80 struct
81 {
84 } vpn;
85 struct
86 {
87 __u64 rx_bytes, tx_bytes;
88 __u32 rx_pkts, tx_pkts;
90};
91
105template <typename ReadHandler>
106class GeNL : public RC<thread_unsafe_refcount>
107{
108 OPENVPN_EXCEPTION(netlink_error);
109
110 typedef std::unique_ptr<nl_msg, decltype(&nlmsg_free)> NlMsgPtr;
111 typedef std::unique_ptr<nl_sock, decltype(&nl_socket_free)> NlSockPtr;
112 typedef std::unique_ptr<nl_cb, decltype(&nl_cb_put)> NlCbPtr;
113
114 public:
116
122 static bool available()
123 {
124 NlSockPtr sock_ptr(nl_socket_alloc(), nl_socket_free);
125
126 int nl_family_id = -1;
127 if (sock_ptr && genl_connect(sock_ptr.get()) == 0)
128 nl_family_id = genl_ctrl_resolve(sock_ptr.get(), OVPN_FAMILY_NAME);
129
130 return nl_family_id >= 0;
131 }
132
141 explicit GeNL(openvpn_io::io_context &io_context,
142 unsigned int ifindex_arg,
143 ReadHandler read_handler_arg)
144 : sock_ptr(nl_socket_alloc(), nl_socket_free),
145 cb_ptr(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put),
146 sock(sock_ptr.get()),
147 cb(cb_ptr.get()),
148 ifindex(ifindex_arg),
149 read_handler(read_handler_arg),
150 halt(false)
151 {
152 nl_socket_set_buffer_size(sock, 8192, 8192);
153
154 int ret = genl_connect(sock);
155 if (ret != 0)
156 OPENVPN_THROW(netlink_error,
157 " cannot connect to generic netlink: " << nl_geterror(ret));
158
159 ret = 1;
160 if (setsockopt(nl_socket_get_fd(sock), SOL_NETLINK, NETLINK_EXT_ACK, &ret, sizeof(ret)) < 0)
161 OPENVPN_THROW(netlink_error,
162 " cannot enable NETLINK_EXT_ACK on socket: " << errno);
163
164 int mcast_id = get_mcast_id();
165 if (mcast_id < 0)
166 OPENVPN_THROW(netlink_error,
167 " cannot get multicast group: " << nl_geterror(mcast_id));
168
169 ret = nl_socket_add_membership(sock, mcast_id);
170 if (ret)
171 OPENVPN_THROW(netlink_error, "failed to join mcast group: " << ret);
172
173 ovpn_dco_id = genl_ctrl_resolve(sock, OVPN_FAMILY_NAME);
174 if (ovpn_dco_id < 0)
175 OPENVPN_THROW(netlink_error,
176 " cannot find ovpn_dco netlink component: " << ovpn_dco_id);
177
178 // set callback to handle control channel messages
179 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, message_received, this);
180
181 // clang-format off
182 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
183 [](struct nl_msg *, void *) -> int
184 { return NL_OK; },
185 NULL);
186 // clang-format on
187
188 nl_socket_set_cb(sock, cb);
189
190 // wrap netlink socket into ASIO primitive for async read
191 stream.reset(new openvpn_io::posix::stream_descriptor(
192 io_context, nl_socket_get_fd(sock)));
193
194 nl_socket_set_nonblocking(sock);
195
197 }
198
212 void new_peer(int peer_id,
213 int fd,
214 struct sockaddr *sa,
215 socklen_t salen,
216 IPv4::Addr vpn4,
217 IPv6::Addr vpn6)
218 {
219 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
220 auto msg_ptr = create_msg(OVPN_CMD_PEER_NEW);
221 auto *msg = msg_ptr.get();
222 struct nlattr *attr = nla_nest_start(msg, OVPN_A_PEER);
223
224 NLA_PUT_U32(msg, OVPN_A_PEER_ID, peer_id);
225 NLA_PUT_U32(msg, OVPN_A_PEER_SOCKET, fd);
226 if (sa->sa_family == AF_INET)
227 {
228 NLA_PUT_U32(msg, OVPN_A_PEER_REMOTE_IPV4, sin->sin_addr.s_addr);
229 }
230 else if (sa->sa_family == AF_INET6)
231 {
232 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
233 NLA_PUT(msg, OVPN_A_PEER_REMOTE_IPV6, sizeof(sin6->sin6_addr), &sin6->sin6_addr);
234 NLA_PUT_U32(msg, OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID, sin6->sin6_scope_id);
235 }
236 else
237 {
238 OPENVPN_THROW(netlink_error, " new_peer() bogus remote address family " << sa->sa_family);
239 }
240 NLA_PUT_U16(msg, OVPN_A_PEER_REMOTE_PORT, sin->sin_port);
241
242 if (vpn4.specified())
243 {
244 NLA_PUT_U32(msg, OVPN_A_PEER_VPN_IPV4, vpn4.to_uint32_net());
245 }
246
247 if (vpn6.specified())
248 {
249 struct in6_addr addr6 = vpn6.to_in6_addr();
250 NLA_PUT(msg, OVPN_A_PEER_VPN_IPV6, sizeof(addr6), &addr6);
251 }
252
253 nla_nest_end(msg, attr);
254
256 return;
257
258 nla_put_failure:
259 OPENVPN_THROW(netlink_error, " new_peer() nla_put_failure");
260 }
261
269 void new_key(unsigned int key_slot, const KoRekey::KeyConfig *kc)
270 {
271 auto msg_ptr = create_msg(OVPN_CMD_KEY_NEW);
272 auto *msg = msg_ptr.get();
273
274 const int NONCE_TAIL_LEN = 8;
275
276 struct nlattr *key_dir;
277
278 struct nlattr *attr = nla_nest_start(msg, OVPN_A_KEYCONF);
279 if (!attr)
280 OPENVPN_THROW(netlink_error, " new_key() cannot allocate submessage");
281
282 NLA_PUT_U32(msg, OVPN_A_KEYCONF_PEER_ID, kc->remote_peer_id);
283 NLA_PUT_U32(msg, OVPN_A_KEYCONF_SLOT, key_slot);
284 NLA_PUT_U32(msg, OVPN_A_KEYCONF_KEY_ID, kc->key_id);
285 NLA_PUT_U32(msg, OVPN_A_KEYCONF_CIPHER_ALG, kc->cipher_alg);
286
288 if (!key_dir)
289 OPENVPN_THROW(netlink_error,
290 " new_key() cannot allocate encrypt key submessage");
291
295 {
296 NLA_PUT(msg, OVPN_A_KEYDIR_NONCE_TAIL, NONCE_TAIL_LEN, kc->encrypt.nonce_tail);
297 }
298 nla_nest_end(msg, key_dir);
299
301 if (!key_dir)
302 OPENVPN_THROW(netlink_error,
303 " new_key() cannot allocate decrypt key submessage");
304
308 {
309 NLA_PUT(msg, OVPN_A_KEYDIR_NONCE_TAIL, NONCE_TAIL_LEN, kc->decrypt.nonce_tail);
310 }
311 nla_nest_end(msg, key_dir);
312
313 nla_nest_end(msg, attr);
314
316 return;
317
318 nla_put_failure:
319 OPENVPN_THROW(netlink_error, " new_key() nla_put_failure");
320 }
321
329 void swap_keys(int peer_id)
330 {
331 auto msg_ptr = create_msg(OVPN_CMD_KEY_SWAP);
332 auto *msg = msg_ptr.get();
333 struct nlattr *attr = nla_nest_start(msg, OVPN_A_KEYCONF);
334 if (!attr)
335 OPENVPN_THROW(netlink_error, " swap_keys() cannot allocate submessage");
336
337 NLA_PUT_U32(msg, OVPN_A_KEYCONF_PEER_ID, peer_id);
338
339 nla_nest_end(msg, attr);
340
342 return;
343
344 nla_put_failure:
345 OPENVPN_THROW(netlink_error, " swap_keys() nla_put_failure");
346 }
347
355 void del_key(int peer_id, unsigned int key_slot)
356 {
357 auto msg_ptr = create_msg(OVPN_CMD_KEY_DEL);
358 auto *msg = msg_ptr.get();
359 struct nlattr *attr = nla_nest_start(msg, OVPN_A_KEYCONF);
360 if (!attr)
361 OPENVPN_THROW(netlink_error, " del_key() cannot allocate submessage");
362
363 NLA_PUT_U32(msg, OVPN_A_KEYCONF_PEER_ID, peer_id);
364 NLA_PUT_U8(msg, OVPN_A_KEYCONF_SLOT, static_cast<uint8_t>(key_slot));
365
366 nla_nest_end(msg, attr);
367
369 return;
370
371 nla_put_failure:
372 OPENVPN_THROW(netlink_error, " del_key() nla_put_failure");
373 }
374
385 void set_peer(int peer_id, unsigned int keepalive_interval, unsigned int keepalive_timeout)
386 {
387 auto msg_ptr = create_msg(OVPN_CMD_PEER_SET);
388 auto *msg = msg_ptr.get();
389 struct nlattr *attr = nla_nest_start(msg, OVPN_A_PEER);
390 if (!attr)
391 OPENVPN_THROW(netlink_error, " set_peer() cannot allocate submessage");
392
393 NLA_PUT_U32(msg, OVPN_A_PEER_ID, peer_id);
394 NLA_PUT_U32(msg, OVPN_A_PEER_KEEPALIVE_INTERVAL, keepalive_interval);
395 NLA_PUT_U32(msg, OVPN_A_PEER_KEEPALIVE_TIMEOUT, keepalive_timeout);
396
397 nla_nest_end(msg, attr);
398
400 return;
401
402 nla_put_failure:
403 OPENVPN_THROW(netlink_error, " set_peer() nla_put_failure");
404 }
405
412 void del_peer(int peer_id)
413 {
414 auto msg_ptr = create_msg(OVPN_CMD_PEER_DEL);
415 auto *msg = msg_ptr.get();
416 struct nlattr *attr = nla_nest_start(msg, OVPN_A_PEER);
417 if (!attr)
418 OPENVPN_THROW(netlink_error, " del_peer() cannot allocate submessage");
419
420 NLA_PUT_U32(msg, OVPN_A_PEER_ID, peer_id);
421
422 nla_nest_end(msg, attr);
423
425 return;
426
427 nla_put_failure:
428 OPENVPN_THROW(netlink_error, " del_peer() nla_put_failure");
429 }
430
438 void get_peer(int peer_id, bool sync)
439 {
440 auto msg_ptr = create_msg(OVPN_CMD_PEER_GET);
441 auto *msg = msg_ptr.get();
442 struct nlattr *attr = nla_nest_start(msg, OVPN_A_PEER);
443 if (!attr)
444 OPENVPN_THROW(netlink_error, " get_peer() cannot allocate submessage");
445
446 NLA_PUT_U32(msg, OVPN_A_PEER_ID, peer_id);
447
448 nla_nest_end(msg, attr);
449
450 nl_status = 1;
452
453 /* if the user has requested a synchronous execution, wait for the reply and parse
454 * it here directly
455 */
456 while (sync && nl_status == 1)
457 {
458 stream->wait(openvpn_io::posix::stream_descriptor::wait_read);
460 }
461
462 return;
463
464 nla_put_failure:
465 OPENVPN_THROW(netlink_error, " get_peer() nla_put_failure");
466 }
467
468 void stop()
469 {
470 if (!halt)
471 {
472 halt = true;
473
474 try
475 {
476 stream->cancel();
477 stream->close();
478 }
479 catch (...)
480 {
481 // ASIO might throw transport exceptions which I found is safe to ignore
482 }
483
484 // contrary to what ASIO doc says, stream->close() doesn't
485 // cancel async read on netlink socket, explicitly close it here
486 sock_ptr.reset();
487 cb_ptr.reset();
488 }
489 }
490
491 private:
493 {
494 const char *group;
495 int id;
496 };
497
507 static int mcast_family_handler(struct nl_msg *msg, void *arg)
508 {
509 struct mcast_handler_args *grp = static_cast<mcast_handler_args *>(arg);
510 struct nlattr *tb[CTRL_ATTR_MAX + 1];
511 struct genlmsghdr *gnlh = static_cast<genlmsghdr *>(
512 nlmsg_data(reinterpret_cast<const nlmsghdr *>(nlmsg_hdr(msg))));
513 struct nlattr *mcgrp;
514 int rem_mcgrp;
515
516 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
517
518 if (!tb[CTRL_ATTR_MCAST_GROUPS])
519 return NL_SKIP;
520
521 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp)
522 {
523 struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
524
525 nla_parse(tb_mcgrp,
526 CTRL_ATTR_MCAST_GRP_MAX,
527 static_cast<nlattr *>(nla_data(mcgrp)),
528 nla_len(mcgrp),
529 NULL);
530
531 if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
532 continue;
533 if (strncmp((const char *)nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
534 grp->group,
535 nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])))
536 continue;
537 grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
538 break;
539 }
540
541 return NL_SKIP;
542 }
543
551 {
552 int ret = 1;
553 struct mcast_handler_args grp = {
555 .id = -ENOENT,
556 };
557 NlMsgPtr msg_ptr(nlmsg_alloc(), nlmsg_free);
558 auto *msg = msg_ptr.get();
559
560 NlCbPtr mcast_cb_ptr(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put);
561 auto *mcast_cb = mcast_cb_ptr.get();
562
563 int ctrlid = genl_ctrl_resolve(sock, "nlctrl");
564
565 genlmsg_put(msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
566 NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, OVPN_FAMILY_NAME);
567
569
570 // clang-format off
571 nl_cb_err(mcast_cb, NL_CB_CUSTOM,
572 [](struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) -> int
573 {
574 int *ret = static_cast<int *>(arg);
575 *ret = err->error;
576 return NL_STOP; },
577 &ret);
578 nl_cb_set(mcast_cb, NL_CB_ACK, NL_CB_CUSTOM,
579 [](struct nl_msg *msg, void *arg) -> int
580 {
581 int *ret = static_cast<int *>(arg);
582 *ret = 0;
583 return NL_STOP; },
584 &ret);
585 // clang-format on
586
587 nl_cb_set(mcast_cb, NL_CB_VALID, NL_CB_CUSTOM, mcast_family_handler, &grp);
588
589 while (ret > 0)
590 nl_recvmsgs(sock, mcast_cb);
591
592 if (ret == 0)
593 ret = grp.id;
594
595 return ret;
596
597 nla_put_failure:
598 OPENVPN_THROW(netlink_error, "get_mcast_id() nla_put_failure");
599 }
600
601 void handle_read(const openvpn_io::error_code &error)
602 {
603 if (halt)
604 return;
605
606 std::ostringstream os;
607 if (error)
608 {
609 os << "error reading netlink message: " << error.message() << ", "
610 << error;
611 reset_buffer();
612 int8_t cmd = -1;
613 buf.write(&cmd, sizeof(cmd));
614 buf_write_string(buf, os.str());
615 read_handler->tun_read_handler(buf);
616 }
617
618 try
619 {
622 }
623 catch (const netlink_error &e)
624 {
625 reset_buffer();
626 int8_t cmd = -1;
627 buf.write(&cmd, sizeof(cmd));
628 buf_write_string(buf, e.what());
629 read_handler->tun_read_handler(buf);
630 }
631 }
632
634 {
635 stream->async_wait(openvpn_io::posix::stream_descriptor::wait_read,
636 [self = Ptr(this)](const openvpn_io::error_code &error)
637 {
638 self->handle_read(error);
639 });
640 }
641
643 {
644 NlMsgPtr msg_ptr(nlmsg_alloc(), nlmsg_free);
645 genlmsg_put(msg_ptr.get(), 0, 0, ovpn_dco_id, 0, 0, cmd, 0);
646 NLA_PUT_U32(msg_ptr.get(), OVPN_A_IFINDEX, ifindex);
647 return msg_ptr;
648
649 nla_put_failure:
650 OPENVPN_THROW(netlink_error, " create_msg() nla_put_failure");
651 }
652
654 {
655 // this is standard error code returned from kernel
656 // and assigned inside ovpn_nl_cb_error()
657 int ovpn_dco_err = 0;
658 nl_cb_err(cb, NL_CB_CUSTOM, ovpn_nl_cb_error, &ovpn_dco_err);
659
660 // this triggers reading callback, GeNL::message_received(),
661 // and, if neccessary, ovpn_nl_cb_error() and returns netlink error code
662 int netlink_err = nl_recvmsgs(sock, cb);
663
664 if (ovpn_dco_err != 0)
665 OPENVPN_THROW(netlink_error,
666 "ovpn-dco error on receiving message: "
667 << strerror(-ovpn_dco_err) << ", " << ovpn_dco_err);
668
669 if (netlink_err < 0)
670 OPENVPN_THROW(netlink_error,
671 "netlink error on receiving message: "
672 << nl_geterror(netlink_err) << ", " << netlink_err);
673 }
674
683 static int message_received(struct nl_msg *msg, void *arg)
684 {
685 GeNL *self = static_cast<GeNL *>(arg);
686 int ret;
687
688 struct genlmsghdr *gnlh = static_cast<genlmsghdr *>(
689 nlmsg_data(reinterpret_cast<const nlmsghdr *>(nlmsg_hdr(msg))));
690 struct nlmsghdr *nlh = nlmsg_hdr(msg);
691 struct nlattr *attrs[OVPN_A_MAX + 1];
692
693 if (!genlmsg_valid_hdr(nlh, 0))
694 {
695 OPENVPN_LOG("ovpn-dco: invalid header");
696 return NL_SKIP;
697 }
698
699 if (nla_parse(attrs, OVPN_A_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL))
700 {
701 OPENVPN_LOG("received bogus data from ovpn-dco");
702 return NL_SKIP;
703 }
704
705 switch (gnlh->cmd)
706 {
708 if (!attrs[OVPN_A_IFINDEX])
709 {
710 OPENVPN_LOG("missing OVPN_A_IFINDEX attribute in message");
711 return NL_SKIP;
712 }
713
714 if (self->ifindex != nla_get_u32(attrs[OVPN_A_IFINDEX]))
715 return NL_SKIP;
716
717 if (!attrs[OVPN_A_PEER])
718 OPENVPN_THROW(netlink_error, "missing OVPN_A_PEER attribute in "
719 "OVPN_CMD_PEER_DEL_NTF message");
720
721 struct nlattr *del_peer_attrs[OVPN_A_PEER_MAX + 1];
722 ret = nla_parse_nested(del_peer_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL);
723 if (ret)
724 OPENVPN_THROW(netlink_error,
725 "cannot parse OVPN_A_PEER attribute");
726
727 if (!del_peer_attrs[OVPN_A_PEER_ID] || !del_peer_attrs[OVPN_A_PEER_DEL_REASON])
728 OPENVPN_THROW(netlink_error, "missing attributes in OVPN_CMD_PEER_DEL_NTF");
729
730 self->reset_buffer();
731 self->buf.write(&gnlh->cmd, sizeof(gnlh->cmd));
732
733 {
734 uint32_t peer_id = nla_get_u32(del_peer_attrs[OVPN_A_PEER_ID]);
735 self->buf.write(&peer_id, sizeof(peer_id));
736 }
737
738 {
739 uint8_t reason = nla_get_u8(del_peer_attrs[OVPN_A_PEER_DEL_REASON]);
740 self->buf.write(&reason, sizeof(reason));
741 }
742
743 self->read_handler->tun_read_handler(self->buf);
744 break;
745
747 {
748 if (!attrs[OVPN_A_PEER])
749 OPENVPN_THROW(netlink_error, "missing OVPN_A_PEER attribute in "
750 "OVPN_CMD_PEER_GET command reply");
751
752 struct nlattr *get_peer_attrs[OVPN_A_PEER_MAX + 1];
753 ret = nla_parse_nested(get_peer_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], NULL);
754 if (ret)
755 OPENVPN_THROW(netlink_error, "cannot parse OVPN_A_PEER attribute");
756
757 if (!get_peer_attrs[OVPN_A_PEER_ID])
758 OPENVPN_THROW(netlink_error, "missing attribute PEER_ID in OVPN_CMD_PEER_GET reply");
759
760 struct OvpnDcoPeer peer = {0};
761 peer.id = nla_get_u32(get_peer_attrs[OVPN_A_PEER_ID]);
762
763 /* peer.remote is expected to contain the remote endpoint encoded in a
764 * sockaddr object. However, ovpn now sends us address, port and scope_id
765 * all separated, which means we need to manually "build" a sockaddr here.
766 * Since peer.remote is currently unused in the rest of the codebase, we
767 * can postpone this complexity.
768 *
769 * TODO: fill peer.remote with a sockaddr object built out of the remote
770 * attrs send by ovpn
771 */
772
773 if (get_peer_attrs[OVPN_A_PEER_VPN_IPV4])
774 {
775 memcpy(&peer.ipv4, nla_data(get_peer_attrs[OVPN_A_PEER_VPN_IPV4]), sizeof(peer.ipv4));
776 }
777 if (get_peer_attrs[OVPN_A_PEER_VPN_IPV6])
778 {
779 memcpy(&peer.ipv6, nla_data(get_peer_attrs[OVPN_A_PEER_VPN_IPV6]), sizeof(peer.ipv6));
780 }
781
782 peer.local_port = nla_get_u16(get_peer_attrs[OVPN_A_PEER_LOCAL_PORT]);
783
784 peer.keepalive.interval = nla_get_u32(get_peer_attrs[OVPN_A_PEER_KEEPALIVE_INTERVAL]);
785 peer.keepalive.timeout = nla_get_u32(get_peer_attrs[OVPN_A_PEER_KEEPALIVE_TIMEOUT]);
790
795
796 self->reset_buffer();
797 self->buf.write(&gnlh->cmd, sizeof(gnlh->cmd));
798 self->buf.write(&peer, sizeof(peer));
799
800 self->read_handler->tun_read_handler(self->buf);
801 /* report to the other context that the reply has been received */
802 nl_status = 0;
803 break;
804 }
805 default:
806 OPENVPN_LOG(__func__ << " unknown netlink command: " << (int)gnlh->cmd);
807 }
808
809 return NL_SKIP;
810 }
811
813 {
814 // good enough values to handle control packets
816 }
817
827 static int ovpn_nl_cb_error(struct sockaddr_nl *nla,
828 struct nlmsgerr *err,
829 void *arg)
830 {
831 struct nlmsghdr *nlh = (struct nlmsghdr *)err - 1;
832 struct nlattr *tb_msg[OVPN_NLMSGERR_ATTR_MAX + 1];
833 int len = nlh->nlmsg_len;
834 struct nlattr *attrs;
835 int *ret = static_cast<int *>(arg);
836 int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh);
837
838 *ret = err->error;
839
840 if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
841 return NL_STOP;
842
843 if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
844 ack_len += static_cast<int>(err->msg.nlmsg_len - sizeof(*nlh));
845
846 if (len <= ack_len)
847 return NL_STOP;
848
849 attrs = reinterpret_cast<nlattr *>((unsigned char *)nlh + ack_len);
850 len -= ack_len;
851
852 nla_parse(tb_msg, NLMSGERR_ATTR_MAX, attrs, len, NULL);
853 if (tb_msg[NLMSGERR_ATTR_MSG])
854 {
855 OPENVPN_LOG(__func__ << " kernel error "
856 << (char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]));
857 }
858
860 {
861 OPENVPN_LOG(__func__ << "missing required nesting type "
862 << nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_NEST]));
863 }
864
866 {
867 OPENVPN_LOG(__func__ << "missing required attribute type "
868 << nla_get_u32(tb_msg[OVPN_NLMSGERR_ATTR_MISS_TYPE]));
869 }
870
871 return NL_STOP;
872 }
873
874 void send_netlink_message(struct nl_msg *msg)
875 {
876 int netlink_err = nl_send_auto(sock, msg);
877
878 if (netlink_err < 0)
879 OPENVPN_THROW(netlink_error,
880 "netlink error on sending message: "
881 << nl_geterror(netlink_err) << ", " << netlink_err);
882 }
883
886
887 struct nl_sock *sock;
888 struct nl_cb *cb;
889
891 unsigned int ifindex;
892
893 ReadHandler read_handler;
894
895 bool halt;
897
898 std::unique_ptr<openvpn_io::posix::stream_descriptor> stream;
899 static int nl_status;
900};
901
902template <typename ReadHandler>
904
905} // namespace openvpn
void reset(const size_t min_capacity, const BufferFlags flags=BufAllocFlags::NO_FLAGS)
Resets the buffer with the specified minimum capacity and flags.
Definition buffer.hpp:1770
void write(const T *data, const size_t size)
Write data to the buffer.
Definition buffer.hpp:1560
OPENVPN_EXCEPTION(netlink_error)
void new_key(unsigned int key_slot, const KoRekey::KeyConfig *kc)
Definition genl.hpp:269
unsigned int ifindex
Definition genl.hpp:891
void reset_buffer()
Definition genl.hpp:812
NlCbPtr cb_ptr
Definition genl.hpp:885
std::unique_ptr< nl_cb, decltype(&nl_cb_put)> NlCbPtr
Definition genl.hpp:112
static int mcast_family_handler(struct nl_msg *msg, void *arg)
Definition genl.hpp:507
RCPtr< GeNL > Ptr
Definition genl.hpp:115
void handle_read(const openvpn_io::error_code &error)
Definition genl.hpp:601
void new_peer(int peer_id, int fd, struct sockaddr *sa, socklen_t salen, IPv4::Addr vpn4, IPv6::Addr vpn6)
Definition genl.hpp:212
struct nl_sock * sock
Definition genl.hpp:887
static int nl_status
Definition genl.hpp:899
NlMsgPtr create_msg(int cmd)
Definition genl.hpp:642
static bool available()
Definition genl.hpp:122
void get_peer(int peer_id, bool sync)
Definition genl.hpp:438
void send_netlink_message(struct nl_msg *msg)
Definition genl.hpp:874
void stop()
Definition genl.hpp:468
BufferAllocated buf
Definition genl.hpp:896
ReadHandler read_handler
Definition genl.hpp:893
void swap_keys(int peer_id)
Definition genl.hpp:329
static int ovpn_nl_cb_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
Definition genl.hpp:827
void read_netlink_message()
Definition genl.hpp:653
NlSockPtr sock_ptr
Definition genl.hpp:884
GeNL(openvpn_io::io_context &io_context, unsigned int ifindex_arg, ReadHandler read_handler_arg)
Definition genl.hpp:141
void queue_genl_read()
Definition genl.hpp:633
void del_peer(int peer_id)
Definition genl.hpp:412
void del_key(int peer_id, unsigned int key_slot)
Definition genl.hpp:355
std::unique_ptr< nl_sock, decltype(&nl_socket_free)> NlSockPtr
Definition genl.hpp:111
int get_mcast_id()
Definition genl.hpp:550
struct nl_cb * cb
Definition genl.hpp:888
std::unique_ptr< openvpn_io::posix::stream_descriptor > stream
Definition genl.hpp:898
int ovpn_dco_id
Definition genl.hpp:890
void set_peer(int peer_id, unsigned int keepalive_interval, unsigned int keepalive_timeout)
Definition genl.hpp:385
std::unique_ptr< nl_msg, decltype(&nlmsg_free)> NlMsgPtr
Definition genl.hpp:110
static int message_received(struct nl_msg *msg, void *arg)
Definition genl.hpp:683
std::uint32_t to_uint32_net() const
Definition ipv4.hpp:121
bool specified() const
Definition ipv4.hpp:431
bool specified() const
Definition ipv6.hpp:484
in6_addr to_in6_addr() const
Definition ipv6.hpp:72
The smart pointer class.
Definition rc.hpp:119
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:908
#define OPENVPN_THROW(exc, stuff)
#define nla_nest_start(_msg, _type)
Definition genl.hpp:54
ovpn_nlmsgerr_attrs
Definition genl.hpp:46
@ OVPN_NLMSGERR_ATTR_MISS_TYPE
Definition genl.hpp:47
@ OVPN_NLMSGERR_ATTR_MISS_NEST
Definition genl.hpp:48
@ OVPN_NLMSGERR_ATTR_MAX
Definition genl.hpp:49
#define OPENVPN_LOG(args)
constexpr BufferFlags GROW(1U<< 2)
if enabled, buffer will grow (otherwise buffer_full exception will be thrown)
constexpr BufferFlags DESTRUCT_ZERO(1U<< 1)
if enabled, destructor will zero data before deletion
constexpr BufferFlags CONSTRUCT_ZERO(1U<< 0)
if enabled, constructors/init will zero allocated space
uint64_t ovpn_nla_get_uint(struct nlattr *attr)
Definition genl.hpp:57
int(* ovpn_nl_cb)(struct nl_msg *msg, void *arg)
Definition genl.hpp:65
void buf_write_string(Buffer &buf, const std::string &str)
Definition bufstr.hpp:34
@ OVPN_CIPHER_ALG_CHACHA20_POLY1305
Definition ovpn-dco.h:104
@ OVPN_CIPHER_ALG_AES_GCM
Definition ovpn-dco.h:103
@ OVPN_A_KEYCONF
@ OVPN_A_MAX
@ OVPN_A_PEER
@ OVPN_A_IFINDEX
@ OVPN_CMD_KEY_DEL
@ OVPN_CMD_PEER_NEW
@ OVPN_CMD_PEER_GET
@ OVPN_CMD_KEY_SWAP
@ OVPN_CMD_PEER_DEL_NTF
@ OVPN_CMD_PEER_SET
@ OVPN_CMD_KEY_NEW
@ OVPN_CMD_PEER_DEL
@ OVPN_A_KEYCONF_SLOT
@ OVPN_A_KEYCONF_PEER_ID
@ OVPN_A_KEYCONF_DECRYPT_DIR
@ OVPN_A_KEYCONF_CIPHER_ALG
@ OVPN_A_KEYCONF_ENCRYPT_DIR
@ OVPN_A_KEYCONF_KEY_ID
#define OVPN_FAMILY_NAME
#define OVPN_MCGRP_PEERS
@ OVPN_A_KEYDIR_CIPHER_KEY
@ OVPN_A_KEYDIR_NONCE_TAIL
@ OVPN_A_PEER_LINK_RX_BYTES
@ OVPN_A_PEER_VPN_IPV6
@ OVPN_A_PEER_LINK_TX_BYTES
@ OVPN_A_PEER_VPN_IPV4
@ OVPN_A_PEER_KEEPALIVE_TIMEOUT
@ OVPN_A_PEER_LINK_TX_PACKETS
@ OVPN_A_PEER_LOCAL_PORT
@ OVPN_A_PEER_VPN_RX_PACKETS
@ OVPN_A_PEER_VPN_TX_BYTES
@ OVPN_A_PEER_REMOTE_IPV6
@ OVPN_A_PEER_VPN_RX_BYTES
@ OVPN_A_PEER_MAX
@ OVPN_A_PEER_DEL_REASON
@ OVPN_A_PEER_ID
@ OVPN_A_PEER_LINK_RX_PACKETS
@ OVPN_A_PEER_VPN_TX_PACKETS
@ OVPN_A_PEER_SOCKET
@ OVPN_A_PEER_REMOTE_IPV4
@ OVPN_A_PEER_KEEPALIVE_INTERVAL
@ OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID
@ OVPN_A_PEER_REMOTE_PORT
unsigned int cipher_alg
Definition key.hpp:32
KeyDirection encrypt
Definition key.hpp:27
KeyDirection decrypt
Definition key.hpp:28
const unsigned char * cipher_key
Definition key.hpp:20
unsigned int cipher_key_size
Definition key.hpp:22
unsigned char nonce_tail[8]
Definition key.hpp:21
struct in_addr ipv4
Definition genl.hpp:71
struct sockaddr_storage remote
Definition genl.hpp:74
struct in6_addr ipv6
Definition genl.hpp:72
struct openvpn::OvpnDcoPeer::@110 vpn
struct openvpn::OvpnDcoPeer::@111 transport
RCPtr< struct OvpnDcoPeer > Ptr
Definition genl.hpp:69
struct openvpn::OvpnDcoPeer::@109 keepalive
#define msg(flags,...)