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
32namespace openvpn {
33
34#define nla_nest_start(_msg, _type) nla_nest_start(_msg, (_type) | NLA_F_NESTED)
35
36typedef int (*ovpn_nl_cb)(struct nl_msg *msg, void *arg);
37
39{
41 __u32 id;
42 struct in_addr ipv4;
43 struct in6_addr ipv6;
45 struct sockaddr_storage remote;
46 struct
47 {
48 __u32 interval;
49 __u32 timeout;
51 struct
52 {
55 } vpn;
56 struct
57 {
58 __u64 rx_bytes, tx_bytes;
59 __u32 rx_pkts, tx_pkts;
61};
62
76template <typename ReadHandler>
77class GeNL : public RC<thread_unsafe_refcount>
78{
79 OPENVPN_EXCEPTION(netlink_error);
80
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;
84
85 public:
87
93 static bool available()
94 {
95 NlSockPtr sock_ptr(nl_socket_alloc(), nl_socket_free);
96
97 int nl_family_id = -1;
98 if (sock_ptr && genl_connect(sock_ptr.get()) == 0)
99 nl_family_id = genl_ctrl_resolve(sock_ptr.get(), OVPN_NL_NAME);
100
101 return nl_family_id >= 0;
102 }
103
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),
117 sock(sock_ptr.get()),
118 cb(cb_ptr.get()),
119 ifindex(ifindex_arg),
120 read_handler(read_handler_arg),
121 halt(false)
122 {
123 nl_socket_set_buffer_size(sock, 8192, 8192);
124
125 int ret = genl_connect(sock);
126 if (ret != 0)
127 OPENVPN_THROW(netlink_error,
128 " cannot connect to generic netlink: " << nl_geterror(ret));
129
130 int mcast_id = get_mcast_id();
131 if (mcast_id < 0)
132 OPENVPN_THROW(netlink_error,
133 " cannot get multicast group: " << nl_geterror(mcast_id));
134
135 ret = nl_socket_add_membership(sock, mcast_id);
136 if (ret)
137 OPENVPN_THROW(netlink_error, "failed to join mcast group: " << ret);
138
139 ovpn_dco_id = genl_ctrl_resolve(sock, OVPN_NL_NAME);
140 if (ovpn_dco_id < 0)
141 OPENVPN_THROW(netlink_error,
142 " cannot find ovpn_dco netlink component: " << ovpn_dco_id);
143
144 // set callback to handle control channel messages
145 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, message_received, this);
146
147 // clang-format off
148 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
149 [](struct nl_msg *, void *) -> int
150 { return NL_OK; },
151 NULL);
152 // clang-format on
153
154 nl_socket_set_cb(sock, cb);
155
156 // wrap netlink socket into ASIO primitive for async read
157 stream.reset(new openvpn_io::posix::stream_descriptor(
158 io_context, nl_socket_get_fd(sock)));
159
160 nl_socket_set_nonblocking(sock);
161
163 }
164
178 void new_peer(int peer_id,
179 int fd,
180 struct sockaddr *sa,
181 socklen_t salen,
182 IPv4::Addr vpn4,
183 IPv6::Addr vpn6)
184 {
185 auto msg_ptr = create_msg(OVPN_CMD_NEW_PEER);
186 auto *msg = msg_ptr.get();
187 struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_NEW_PEER);
188
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);
192
193 if (vpn4.specified())
194 {
195 NLA_PUT_U32(msg, OVPN_NEW_PEER_ATTR_IPV4, vpn4.to_uint32_net());
196 }
197
198 if (vpn6.specified())
199 {
200 struct in6_addr addr6 = vpn6.to_in6_addr();
201 NLA_PUT(msg, OVPN_NEW_PEER_ATTR_IPV6, sizeof(addr6), &addr6);
202 }
203
204 nla_nest_end(msg, attr);
205
207 return;
208
209 nla_put_failure:
210 OPENVPN_THROW(netlink_error, " new_peer() nla_put_failure");
211 }
212
220 void new_key(unsigned int key_slot, const KoRekey::KeyConfig *kc)
221 {
222 auto msg_ptr = create_msg(OVPN_CMD_NEW_KEY);
223 auto *msg = msg_ptr.get();
224
225 const int NONCE_TAIL_LEN = 8;
226
227 struct nlattr *key_dir;
228
229 struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_NEW_KEY);
230 if (!attr)
231 OPENVPN_THROW(netlink_error, " new_key() cannot allocate submessage");
232
233 NLA_PUT_U32(msg, OVPN_NEW_KEY_ATTR_PEER_ID, kc->remote_peer_id);
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));
237
238 key_dir = nla_nest_start(msg, OVPN_NEW_KEY_ATTR_ENCRYPT_KEY);
239 if (!key_dir)
240 OPENVPN_THROW(netlink_error,
241 " new_key() cannot allocate encrypt key submessage");
242
243 NLA_PUT(msg, OVPN_KEY_DIR_ATTR_CIPHER_KEY, kc->encrypt.cipher_key_size, kc->encrypt.cipher_key);
246 {
247 NLA_PUT(msg, OVPN_KEY_DIR_ATTR_NONCE_TAIL, NONCE_TAIL_LEN, kc->encrypt.nonce_tail);
248 }
249 nla_nest_end(msg, key_dir);
250
251 key_dir = nla_nest_start(msg, OVPN_NEW_KEY_ATTR_DECRYPT_KEY);
252 if (!key_dir)
253 OPENVPN_THROW(netlink_error,
254 " new_key() cannot allocate decrypt key submessage");
255
256 NLA_PUT(msg, OVPN_KEY_DIR_ATTR_CIPHER_KEY, kc->decrypt.cipher_key_size, kc->decrypt.cipher_key);
259 {
260 NLA_PUT(msg, OVPN_KEY_DIR_ATTR_NONCE_TAIL, NONCE_TAIL_LEN, kc->decrypt.nonce_tail);
261 }
262 nla_nest_end(msg, key_dir);
263
264 nla_nest_end(msg, attr);
265
267 return;
268
269 nla_put_failure:
270 OPENVPN_THROW(netlink_error, " new_key() nla_put_failure");
271 }
272
280 void swap_keys(int peer_id)
281 {
282 auto msg_ptr = create_msg(OVPN_CMD_SWAP_KEYS);
283 auto *msg = msg_ptr.get();
284 struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_SWAP_KEYS);
285 if (!attr)
286 OPENVPN_THROW(netlink_error, " swap_keys() cannot allocate submessage");
287
288 NLA_PUT_U32(msg, OVPN_SWAP_KEYS_ATTR_PEER_ID, peer_id);
289
290 nla_nest_end(msg, attr);
291
293 return;
294
295 nla_put_failure:
296 OPENVPN_THROW(netlink_error, " swap_keys() nla_put_failure");
297 }
298
306 void del_key(int peer_id, unsigned int key_slot)
307 {
308 auto msg_ptr = create_msg(OVPN_CMD_DEL_KEY);
309 auto *msg = msg_ptr.get();
310 struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_DEL_KEY);
311 if (!attr)
312 OPENVPN_THROW(netlink_error, " del_key() cannot allocate submessage");
313
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));
316
317 nla_nest_end(msg, attr);
318
320 return;
321
322 nla_put_failure:
323 OPENVPN_THROW(netlink_error, " del_key() nla_put_failure");
324 }
325
336 void set_peer(int peer_id, unsigned int keepalive_interval, unsigned int keepalive_timeout)
337 {
338 auto msg_ptr = create_msg(OVPN_CMD_SET_PEER);
339 auto *msg = msg_ptr.get();
340 struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_SET_PEER);
341 if (!attr)
342 OPENVPN_THROW(netlink_error, " set_peer() cannot allocate submessage");
343
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);
347
348 nla_nest_end(msg, attr);
349
351 return;
352
353 nla_put_failure:
354 OPENVPN_THROW(netlink_error, " set_peer() nla_put_failure");
355 }
356
363 void del_peer(int peer_id)
364 {
365 auto msg_ptr = create_msg(OVPN_CMD_DEL_PEER);
366 auto *msg = msg_ptr.get();
367 struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_DEL_PEER);
368 if (!attr)
369 OPENVPN_THROW(netlink_error, " del_peer() cannot allocate submessage");
370
371 NLA_PUT_U32(msg, OVPN_DEL_PEER_ATTR_PEER_ID, peer_id);
372
373 nla_nest_end(msg, attr);
374
376 return;
377
378 nla_put_failure:
379 OPENVPN_THROW(netlink_error, " del_peer() nla_put_failure");
380 }
381
389 void get_peer(int peer_id, bool sync)
390 {
391 auto msg_ptr = create_msg(OVPN_CMD_GET_PEER);
392 auto *msg = msg_ptr.get();
393 struct nlattr *attr = nla_nest_start(msg, OVPN_ATTR_GET_PEER);
394 if (!attr)
395 OPENVPN_THROW(netlink_error, " get_peer() cannot allocate submessage");
396
397 NLA_PUT_U32(msg, OVPN_GET_PEER_ATTR_PEER_ID, peer_id);
398
399 nla_nest_end(msg, attr);
400
401 nl_status = 1;
403
404 /* if the user has requested a synchronous execution, wait for the reply and parse
405 * it here directly
406 */
407 while (sync && nl_status == 1)
408 {
409 stream->wait(openvpn_io::posix::stream_descriptor::wait_read);
411 }
412
413 return;
414
415 nla_put_failure:
416 OPENVPN_THROW(netlink_error, " get_peer() nla_put_failure");
417 }
418
419 void stop()
420 {
421 if (!halt)
422 {
423 halt = true;
424
425 try
426 {
427 stream->cancel();
428 stream->close();
429 }
430 catch (...)
431 {
432 // ASIO might throw transport exceptions which I found is safe to ignore
433 }
434
435 // contrary to what ASIO doc says, stream->close() doesn't
436 // cancel async read on netlink socket, explicitly close it here
437 sock_ptr.reset();
438 cb_ptr.reset();
439 }
440 }
441
442 private:
444 {
445 const char *group;
446 int id;
447 };
448
458 static int mcast_family_handler(struct nl_msg *msg, void *arg)
459 {
460 struct mcast_handler_args *grp = static_cast<mcast_handler_args *>(arg);
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;
465 int rem_mcgrp;
466
467 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
468
469 if (!tb[CTRL_ATTR_MCAST_GROUPS])
470 return NL_SKIP;
471
472 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp)
473 {
474 struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
475
476 nla_parse(tb_mcgrp,
477 CTRL_ATTR_MCAST_GRP_MAX,
478 static_cast<nlattr *>(nla_data(mcgrp)),
479 nla_len(mcgrp),
480 NULL);
481
482 if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
483 continue;
484 if (strncmp((const char *)nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
485 grp->group,
486 nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])))
487 continue;
488 grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
489 break;
490 }
491
492 return NL_SKIP;
493 }
494
502 {
503 int ret = 1;
504 struct mcast_handler_args grp = {
506 .id = -ENOENT,
507 };
508 NlMsgPtr msg_ptr(nlmsg_alloc(), nlmsg_free);
509 auto *msg = msg_ptr.get();
510
511 NlCbPtr mcast_cb_ptr(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put);
512 auto *mcast_cb = mcast_cb_ptr.get();
513
514 int ctrlid = genl_ctrl_resolve(sock, "nlctrl");
515
516 genlmsg_put(msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
517 NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, OVPN_NL_NAME);
518
520
521 // clang-format off
522 nl_cb_err(mcast_cb, NL_CB_CUSTOM,
523 [](struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) -> int
524 {
525 int *ret = static_cast<int *>(arg);
526 *ret = err->error;
527 return NL_STOP; },
528 &ret);
529 nl_cb_set(mcast_cb, NL_CB_ACK, NL_CB_CUSTOM,
530 [](struct nl_msg *msg, void *arg) -> int
531 {
532 int *ret = static_cast<int *>(arg);
533 *ret = 0;
534 return NL_STOP; },
535 &ret);
536 // clang-format on
537
538 nl_cb_set(mcast_cb, NL_CB_VALID, NL_CB_CUSTOM, mcast_family_handler, &grp);
539
540 while (ret > 0)
541 nl_recvmsgs(sock, mcast_cb);
542
543 if (ret == 0)
544 ret = grp.id;
545
546 return ret;
547
548 nla_put_failure:
549 OPENVPN_THROW(netlink_error, "get_mcast_id() nla_put_failure");
550 }
551
552 void handle_read(const openvpn_io::error_code &error)
553 {
554 if (halt)
555 return;
556
557 std::ostringstream os;
558 if (error)
559 {
560 os << "error reading netlink message: " << error.message() << ", "
561 << error;
562 reset_buffer();
563 int8_t cmd = -1;
564 buf.write(&cmd, sizeof(cmd));
565 buf_write_string(buf, os.str());
566 read_handler->tun_read_handler(buf);
567 }
568
569 try
570 {
573 }
574 catch (const netlink_error &e)
575 {
576 reset_buffer();
577 int8_t cmd = -1;
578 buf.write(&cmd, sizeof(cmd));
579 buf_write_string(buf, e.what());
580 read_handler->tun_read_handler(buf);
581 }
582 }
583
585 {
586 stream->async_wait(openvpn_io::posix::stream_descriptor::wait_read,
587 [self = Ptr(this)](const openvpn_io::error_code &error)
588 {
589 self->handle_read(error);
590 });
591 }
592
593 NlMsgPtr create_msg(enum ovpn_nl_commands cmd)
594 {
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);
598 return msg_ptr;
599
600 nla_put_failure:
601 OPENVPN_THROW(netlink_error, " create_msg() nla_put_failure");
602 }
603
605 {
606 // this is standard error code returned from kernel
607 // and assigned inside ovpn_nl_cb_error()
608 int ovpn_dco_err = 0;
609 nl_cb_err(cb, NL_CB_CUSTOM, ovpn_nl_cb_error, &ovpn_dco_err);
610
611 // this triggers reading callback, GeNL::message_received(),
612 // and, if neccessary, ovpn_nl_cb_error() and returns netlink error code
613 int netlink_err = nl_recvmsgs(sock, cb);
614
615 if (ovpn_dco_err != 0)
616 OPENVPN_THROW(netlink_error,
617 "ovpn-dco error on receiving message: "
618 << strerror(-ovpn_dco_err) << ", " << ovpn_dco_err);
619
620 if (netlink_err < 0)
621 OPENVPN_THROW(netlink_error,
622 "netlink error on receiving message: "
623 << nl_geterror(netlink_err) << ", " << netlink_err);
624 }
625
634 static int message_received(struct nl_msg *msg, void *arg)
635 {
636 GeNL *self = static_cast<GeNL *>(arg);
637 int ret;
638
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];
643
644 if (!genlmsg_valid_hdr(nlh, 0))
645 {
646 OPENVPN_LOG("ovpn-dco: invalid header");
647 return NL_SKIP;
648 }
649
650 if (nla_parse(attrs, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL))
651 {
652 OPENVPN_LOG("received bogus data from ovpn-dco");
653 return NL_SKIP;
654 }
655
656 if (!attrs[OVPN_ATTR_IFINDEX])
657 {
658 OPENVPN_LOG("missing OVPN_ATTR_IFINDEX attribute in message");
659 return NL_SKIP;
660 }
661
662 if (self->ifindex != nla_get_u32(attrs[OVPN_ATTR_IFINDEX]))
663 return NL_SKIP;
664
665 switch (gnlh->cmd)
666 {
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");
671
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);
674 if (ret)
675 OPENVPN_THROW(netlink_error,
676 "cannot parse OVPN_ATTR_DEL_PEER attribute");
677
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");
680
681 self->reset_buffer();
682 self->buf.write(&gnlh->cmd, sizeof(gnlh->cmd));
683
684 {
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));
687 }
688
689 {
690 uint8_t reason = nla_get_u8(del_peer_attrs[OVPN_DEL_PEER_ATTR_REASON]);
691 self->buf.write(&reason, sizeof(reason));
692 }
693
694 self->read_handler->tun_read_handler(self->buf);
695 break;
696
697 case OVPN_CMD_GET_PEER:
698 {
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");
702
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);
705 if (ret)
706 OPENVPN_THROW(netlink_error, "cannot parse OVPN_ATTR_GET_PEER attribute");
707
708 if (!get_peer_attrs[OVPN_GET_PEER_RESP_ATTR_PEER_ID])
709 OPENVPN_THROW(netlink_error, "missing attributes in OVPN_CMD_DEL_PEER");
710
711 struct OvpnDcoPeer peer = {0};
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]);
716 memcpy(&peer.remote,
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]);
725
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]);
730
731 self->reset_buffer();
732 self->buf.write(&gnlh->cmd, sizeof(gnlh->cmd));
733 self->buf.write(&peer, sizeof(peer));
734
735 self->read_handler->tun_read_handler(self->buf);
736 /* report to the other context that the reply has been received */
737 nl_status = 0;
738 break;
739 }
740 default:
741 OPENVPN_LOG(__func__ << " unknown netlink command: " << (int)gnlh->cmd);
742 }
743
744 return NL_SKIP;
745 }
746
748 {
749 // good enough values to handle control packets
751 }
752
762 static int ovpn_nl_cb_error(struct sockaddr_nl *nla,
763 struct nlmsgerr *err,
764 void *arg)
765 {
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);
772
773 *ret = err->error;
774
775 if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
776 return NL_STOP;
777
778 if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
779 ack_len += static_cast<int>(err->msg.nlmsg_len - sizeof(*nlh));
780
781 if (len <= ack_len)
782 return NL_STOP;
783
784 attrs = reinterpret_cast<nlattr *>((unsigned char *)nlh + ack_len);
785 len -= ack_len;
786
787 nla_parse(tb_msg, NLMSGERR_ATTR_MAX, attrs, len, NULL);
788 if (tb_msg[NLMSGERR_ATTR_MSG])
789 {
790 OPENVPN_LOG(__func__ << " kernel error "
791 << (char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]));
792 }
793
794 return NL_STOP;
795 }
796
797 void send_netlink_message(struct nl_msg *msg)
798 {
799 int netlink_err = nl_send_auto(sock, msg);
800
801 if (netlink_err < 0)
802 OPENVPN_THROW(netlink_error,
803 "netlink error on sending message: "
804 << nl_geterror(netlink_err) << ", " << netlink_err);
805 }
806
809
810 struct nl_sock *sock;
811 struct nl_cb *cb;
812
814 unsigned int ifindex;
815
816 ReadHandler read_handler;
817
818 bool halt;
820
821 std::unique_ptr<openvpn_io::posix::stream_descriptor> stream;
822 static int nl_status;
823};
824
825template <typename ReadHandler>
827
828} // namespace openvpn
void reset(const size_t min_capacity, const unsigned int flags)
Resets the buffer with the specified minimum capacity and flags.
Definition buffer.hpp:1741
void write(const T *data, const size_t size)
Write data to the buffer.
Definition buffer.hpp:1546
OPENVPN_EXCEPTION(netlink_error)
void new_key(unsigned int key_slot, const KoRekey::KeyConfig *kc)
Definition genl.hpp:220
unsigned int ifindex
Definition genl.hpp:814
void reset_buffer()
Definition genl.hpp:747
NlCbPtr cb_ptr
Definition genl.hpp:808
std::unique_ptr< nl_cb, decltype(&nl_cb_put)> NlCbPtr
Definition genl.hpp:83
static int mcast_family_handler(struct nl_msg *msg, void *arg)
Definition genl.hpp:458
RCPtr< GeNL > Ptr
Definition genl.hpp:86
void handle_read(const openvpn_io::error_code &error)
Definition genl.hpp:552
void new_peer(int peer_id, int fd, struct sockaddr *sa, socklen_t salen, IPv4::Addr vpn4, IPv6::Addr vpn6)
Definition genl.hpp:178
struct nl_sock * sock
Definition genl.hpp:810
static int nl_status
Definition genl.hpp:822
static bool available()
Definition genl.hpp:93
void get_peer(int peer_id, bool sync)
Definition genl.hpp:389
void send_netlink_message(struct nl_msg *msg)
Definition genl.hpp:797
void stop()
Definition genl.hpp:419
BufferAllocated buf
Definition genl.hpp:819
ReadHandler read_handler
Definition genl.hpp:816
void swap_keys(int peer_id)
Definition genl.hpp:280
static int ovpn_nl_cb_error(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
Definition genl.hpp:762
void read_netlink_message()
Definition genl.hpp:604
NlSockPtr sock_ptr
Definition genl.hpp:807
GeNL(openvpn_io::io_context &io_context, unsigned int ifindex_arg, ReadHandler read_handler_arg)
Definition genl.hpp:112
void queue_genl_read()
Definition genl.hpp:584
void del_peer(int peer_id)
Definition genl.hpp:363
NlMsgPtr create_msg(enum ovpn_nl_commands cmd)
Definition genl.hpp:593
void del_key(int peer_id, unsigned int key_slot)
Definition genl.hpp:306
std::unique_ptr< nl_sock, decltype(&nl_socket_free)> NlSockPtr
Definition genl.hpp:82
int get_mcast_id()
Definition genl.hpp:501
struct nl_cb * cb
Definition genl.hpp:811
std::unique_ptr< openvpn_io::posix::stream_descriptor > stream
Definition genl.hpp:821
int ovpn_dco_id
Definition genl.hpp:813
void set_peer(int peer_id, unsigned int keepalive_interval, unsigned int keepalive_timeout)
Definition genl.hpp:336
std::unique_ptr< nl_msg, decltype(&nlmsg_free)> NlMsgPtr
Definition genl.hpp:81
static int message_received(struct nl_msg *msg, void *arg)
Definition genl.hpp:634
std::uint32_t to_uint32_net() const
Definition ipv4.hpp:124
bool specified() const
Definition ipv4.hpp:434
bool specified() const
Definition ipv6.hpp:490
in6_addr to_in6_addr() const
Definition ipv6.hpp:75
The smart pointer class.
Definition rc.hpp:119
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:912
#define OPENVPN_THROW(exc, stuff)
#define nla_nest_start(_msg, _type)
Definition genl.hpp:34
#define OPENVPN_LOG(args)
Support deferred server-side state creation when client connects.
Definition ovpncli.cpp:95
int(* ovpn_nl_cb)(struct nl_msg *msg, void *arg)
Definition genl.hpp:36
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
#define OVPN_NL_MULTICAST_GROUP_PEERS
#define OVPN_NL_NAME
@ DESTRUCT_ZERO
if enabled, destructor will zero data before deletion
Definition buffer.hpp:871
@ GROW
if enabled, buffer will grow (otherwise buffer_full exception will be thrown)
Definition buffer.hpp:872
@ CONSTRUCT_ZERO
if enabled, constructors/init will zero allocated space
Definition buffer.hpp:870
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:42
struct sockaddr_storage remote
Definition genl.hpp:45
struct in6_addr ipv6
Definition genl.hpp:43
struct openvpn::OvpnDcoPeer::@110 vpn
struct openvpn::OvpnDcoPeer::@111 transport
RCPtr< struct OvpnDcoPeer > Ptr
Definition genl.hpp:40
struct openvpn::OvpnDcoPeer::@109 keepalive
std::string ret
#define msg(flags,...)