1 #pragma once
2 #include <linux/netlink.h>
3 #include <linux/rtnetlink.h>
4
5 #include <stdplus/function_view.hpp>
6 #include <stdplus/raw.hpp>
7
8 #include <string_view>
9 #include <tuple>
10 #include <type_traits>
11
12 namespace phosphor
13 {
14 namespace network
15 {
16 namespace netlink
17 {
18
19 /* @brief Called on each nlmsg received on the socket
20 */
21 using ReceiveCallback =
22 stdplus::function_view<void(const nlmsghdr&, std::string_view)>;
23
24 namespace detail
25 {
26
27 void processMsg(std::string_view& msgs, bool& done, ReceiveCallback cb);
28
29 void performRequest(int protocol, void* data, size_t size, ReceiveCallback cb);
30
31 } // namespace detail
32
33 /** @brief Receives all outstanding messages on a netlink socket
34 *
35 * @param[in] sock - The socket to receive the messages on
36 * @param[in] cb - Called for each response message payload
37 */
38 size_t receive(int sock, ReceiveCallback cb);
39
40 /* @brief Call on an rtnetlink payload
41 * Updates the input to remove the attr parsed out.
42 *
43 * @param[in,out] data - The buffer holding rtpayload to parse
44 * @return The payload for the rt msg
45 */
46 template <typename T>
extractRtData(std::string_view & data)47 constexpr const T& extractRtData(std::string_view& data)
48 {
49 const T& ret = stdplus::raw::refFrom<T, stdplus::raw::Aligned>(data);
50 data.remove_prefix(NLMSG_ALIGN(sizeof(T)));
51 return ret;
52 }
53
54 /* @brief Call on a block of rtattrs to parse a single one out
55 * Updates the input to remove the attr parsed out.
56 *
57 * @param[in,out] attrs - The buffer holding rtattrs to parse
58 * @return A tuple of rtattr header + data buffer for the attr
59 */
60 std::tuple<rtattr, std::string_view> extractRtAttr(std::string_view& data);
61
62 /** @brief Performs a netlink request of the specified type with the given
63 * message Calls the callback upon receiving
64 *
65 * @param[in] protocol - The netlink protocol to use when opening the socket
66 * @param[in] type - The netlink message type
67 * @param[in] flags - Additional netlink flags for the request
68 * @param[in] msg - The message payload for the request
69 * @param[in] cb - Called for each response message payload
70 */
71 template <typename T>
performRequest(int protocol,uint16_t type,uint16_t flags,const T & msg,ReceiveCallback cb)72 void performRequest(int protocol, uint16_t type, uint16_t flags, const T& msg,
73 ReceiveCallback cb)
74 {
75 static_assert(std::is_trivially_copyable_v<T>);
76
77 struct
78 {
79 nlmsghdr hdr;
80 T msg;
81 } data{};
82 data.hdr.nlmsg_len = sizeof(data);
83 data.hdr.nlmsg_type = type;
84 data.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
85 data.msg = msg;
86
87 detail::performRequest(protocol, &data, sizeof(data), cb);
88 }
89
90 } // namespace netlink
91 } // namespace network
92 } // namespace phosphor
93