blob: 6b456b7f67562757f27bd160b5e86d8d49e50544 [file] [log] [blame]
William A. Kennington IIIa7344c32022-10-31 14:12:27 -07001#include "rtnetlink.hpp"
2
3#include "netlink.hpp"
William A. Kennington III6a923632022-11-06 18:17:33 -08004#include "util.hpp"
William A. Kennington IIIa7344c32022-10-31 14:12:27 -07005
6#include <linux/rtnetlink.h>
7
8namespace phosphor::network::netlink
9{
10
11template <typename Addr>
12static std::optional<std::tuple<unsigned, InAddrAny>>
13 parse(std::string_view msg)
14{
15 std::optional<unsigned> ifIdx;
16 std::optional<InAddrAny> gw;
17 while (!msg.empty())
18 {
19 auto [hdr, data] = extractRtAttr(msg);
20 switch (hdr.rta_type)
21 {
22 case RTA_OIF:
William A. Kennington III6a923632022-11-06 18:17:33 -080023 ifIdx.emplace(stdplus::raw::copyFromStrict<int>(data));
William A. Kennington IIIa7344c32022-10-31 14:12:27 -070024 break;
25 case RTA_GATEWAY:
William A. Kennington III6a923632022-11-06 18:17:33 -080026 gw.emplace(stdplus::raw::copyFromStrict<Addr>(data));
William A. Kennington IIIa7344c32022-10-31 14:12:27 -070027 break;
28 }
29 }
30 if (ifIdx && gw)
31 {
32 return std::make_tuple(*ifIdx, *gw);
33 }
34 return std::nullopt;
35}
36
37std::optional<std::tuple<unsigned, InAddrAny>>
38 gatewayFromRtm(std::string_view msg)
39{
40 const auto& rtm = extractRtData<rtmsg>(msg);
41 if (rtm.rtm_table != RT_TABLE_MAIN || rtm.rtm_dst_len != 0)
42 {
43 return std::nullopt;
44 }
45 switch (rtm.rtm_family)
46 {
47 case AF_INET:
48 return parse<in_addr>(msg);
49 case AF_INET6:
50 return parse<in6_addr>(msg);
51 }
52 return std::nullopt;
53}
54
William A. Kennington III6a923632022-11-06 18:17:33 -080055AddressInfo addrFromRtm(std::string_view msg)
56{
57 const auto& ifa = extractRtData<ifaddrmsg>(msg);
58
59 AddressInfo ret;
60 ret.ifidx = ifa.ifa_index;
61 ret.flags = ifa.ifa_flags;
62 ret.scope = ifa.ifa_scope;
63 std::optional<InAddrAny> addr;
64 while (!msg.empty())
65 {
66 auto [hdr, data] = extractRtAttr(msg);
67 if (hdr.rta_type == IFA_ADDRESS)
68 {
69 addr.emplace(addrFromBuf(ifa.ifa_family, data));
70 }
71 else if (hdr.rta_type == IFA_FLAGS)
72 {
73 ret.flags = stdplus::raw::copyFromStrict<uint32_t>(data);
74 }
75 }
76 if (!addr)
77 {
78 throw std::runtime_error("Missing address");
79 }
80 ret.ifaddr = {*addr, ifa.ifa_prefixlen};
81 return ret;
82}
83
William A. Kennington IIIa8426902022-11-07 15:37:41 -080084NeighborInfo neighFromRtm(std::string_view msg)
85{
86 const auto& ndm = netlink::extractRtData<ndmsg>(msg);
87
88 NeighborInfo ret;
89 ret.ifidx = ndm.ndm_ifindex;
90 ret.state = ndm.ndm_state;
91 bool set_addr = false;
92 while (!msg.empty())
93 {
94 auto [hdr, data] = netlink::extractRtAttr(msg);
95 if (hdr.rta_type == NDA_LLADDR)
96 {
97 ret.mac = stdplus::raw::copyFrom<ether_addr>(data);
98 }
99 else if (hdr.rta_type == NDA_DST)
100 {
101 ret.addr = addrFromBuf(ndm.ndm_family, data);
102 set_addr = true;
103 }
104 }
105 if (!set_addr)
106 {
107 throw std::runtime_error("Missing address");
108 }
109 return ret;
110}
111
William A. Kennington IIIa7344c32022-10-31 14:12:27 -0700112} // namespace phosphor::network::netlink