1a7344c3aSWilliam A. Kennington III #include "rtnetlink.hpp"
2a7344c3aSWilliam A. Kennington III
3a7344c3aSWilliam A. Kennington III #include "netlink.hpp"
46a92363eSWilliam A. Kennington III #include "util.hpp"
5a7344c3aSWilliam A. Kennington III
6a7344c3aSWilliam A. Kennington III #include <linux/rtnetlink.h>
7a7344c3aSWilliam A. Kennington III
8a7344c3aSWilliam A. Kennington III namespace phosphor::network::netlink
9a7344c3aSWilliam A. Kennington III {
10a7344c3aSWilliam A. Kennington III
111aeacc90SWilliam A. Kennington III using std::literals::string_view_literals::operator""sv;
121aeacc90SWilliam A. Kennington III
parseVlanInfo(InterfaceInfo & info,std::string_view msg)131aeacc90SWilliam A. Kennington III static void parseVlanInfo(InterfaceInfo& info, std::string_view msg)
141aeacc90SWilliam A. Kennington III {
151aeacc90SWilliam A. Kennington III if (msg.data() == nullptr)
161aeacc90SWilliam A. Kennington III {
171aeacc90SWilliam A. Kennington III throw std::runtime_error("Missing VLAN data");
181aeacc90SWilliam A. Kennington III }
191aeacc90SWilliam A. Kennington III while (!msg.empty())
201aeacc90SWilliam A. Kennington III {
211aeacc90SWilliam A. Kennington III auto [hdr, data] = netlink::extractRtAttr(msg);
221aeacc90SWilliam A. Kennington III switch (hdr.rta_type)
231aeacc90SWilliam A. Kennington III {
241aeacc90SWilliam A. Kennington III case IFLA_VLAN_ID:
251aeacc90SWilliam A. Kennington III info.vlan_id.emplace(stdplus::raw::copyFrom<uint16_t>(data));
261aeacc90SWilliam A. Kennington III break;
271aeacc90SWilliam A. Kennington III }
281aeacc90SWilliam A. Kennington III }
291aeacc90SWilliam A. Kennington III }
301aeacc90SWilliam A. Kennington III
parseLinkInfo(InterfaceInfo & info,std::string_view msg)311aeacc90SWilliam A. Kennington III static void parseLinkInfo(InterfaceInfo& info, std::string_view msg)
321aeacc90SWilliam A. Kennington III {
331aeacc90SWilliam A. Kennington III std::string_view submsg;
341aeacc90SWilliam A. Kennington III while (!msg.empty())
351aeacc90SWilliam A. Kennington III {
361aeacc90SWilliam A. Kennington III auto [hdr, data] = netlink::extractRtAttr(msg);
371aeacc90SWilliam A. Kennington III switch (hdr.rta_type)
381aeacc90SWilliam A. Kennington III {
391aeacc90SWilliam A. Kennington III case IFLA_INFO_KIND:
401aeacc90SWilliam A. Kennington III data.remove_suffix(1);
411aeacc90SWilliam A. Kennington III info.kind.emplace(data);
421aeacc90SWilliam A. Kennington III break;
431aeacc90SWilliam A. Kennington III case IFLA_INFO_DATA:
441aeacc90SWilliam A. Kennington III submsg = data;
451aeacc90SWilliam A. Kennington III break;
461aeacc90SWilliam A. Kennington III }
471aeacc90SWilliam A. Kennington III }
481aeacc90SWilliam A. Kennington III if (info.kind == "vlan"sv)
491aeacc90SWilliam A. Kennington III {
501aeacc90SWilliam A. Kennington III parseVlanInfo(info, submsg);
511aeacc90SWilliam A. Kennington III }
521aeacc90SWilliam A. Kennington III }
531aeacc90SWilliam A. Kennington III
intfFromRtm(std::string_view msg)541aeacc90SWilliam A. Kennington III InterfaceInfo intfFromRtm(std::string_view msg)
551aeacc90SWilliam A. Kennington III {
561aeacc90SWilliam A. Kennington III const auto& ifinfo = netlink::extractRtData<ifinfomsg>(msg);
571aeacc90SWilliam A. Kennington III InterfaceInfo ret;
589c441fd4SWilliam A. Kennington III ret.type = ifinfo.ifi_type;
591aeacc90SWilliam A. Kennington III ret.idx = ifinfo.ifi_index;
609c441fd4SWilliam A. Kennington III ret.flags = ifinfo.ifi_flags;
611aeacc90SWilliam A. Kennington III while (!msg.empty())
621aeacc90SWilliam A. Kennington III {
631aeacc90SWilliam A. Kennington III auto [hdr, data] = netlink::extractRtAttr(msg);
641aeacc90SWilliam A. Kennington III switch (hdr.rta_type)
651aeacc90SWilliam A. Kennington III {
661aeacc90SWilliam A. Kennington III case IFLA_IFNAME:
671aeacc90SWilliam A. Kennington III ret.name.emplace(data.begin(), data.end() - 1);
681aeacc90SWilliam A. Kennington III break;
691aeacc90SWilliam A. Kennington III case IFLA_ADDRESS:
70b7d6a1a7SWilliam A. Kennington III if (data.size() == sizeof(stdplus::EtherAddr))
711aeacc90SWilliam A. Kennington III {
72b7d6a1a7SWilliam A. Kennington III ret.mac.emplace(
73b7d6a1a7SWilliam A. Kennington III stdplus::raw::copyFrom<stdplus::EtherAddr>(data));
741aeacc90SWilliam A. Kennington III }
751aeacc90SWilliam A. Kennington III break;
761aeacc90SWilliam A. Kennington III case IFLA_MTU:
771aeacc90SWilliam A. Kennington III ret.mtu.emplace(stdplus::raw::copyFrom<unsigned>(data));
781aeacc90SWilliam A. Kennington III break;
791aeacc90SWilliam A. Kennington III case IFLA_LINK:
801aeacc90SWilliam A. Kennington III ret.parent_idx.emplace(stdplus::raw::copyFrom<unsigned>(data));
811aeacc90SWilliam A. Kennington III break;
821aeacc90SWilliam A. Kennington III case IFLA_LINKINFO:
831aeacc90SWilliam A. Kennington III parseLinkInfo(ret, data);
841aeacc90SWilliam A. Kennington III break;
851aeacc90SWilliam A. Kennington III }
861aeacc90SWilliam A. Kennington III }
871aeacc90SWilliam A. Kennington III return ret;
881aeacc90SWilliam A. Kennington III }
891aeacc90SWilliam A. Kennington III
90a7344c3aSWilliam A. Kennington III template <typename Addr>
91*9b2a20d3SWilliam A. Kennington III static std::optional<std::tuple<unsigned, stdplus::InAnyAddr>>
parse(std::string_view msg)92a7344c3aSWilliam A. Kennington III parse(std::string_view msg)
93a7344c3aSWilliam A. Kennington III {
94a7344c3aSWilliam A. Kennington III std::optional<unsigned> ifIdx;
95*9b2a20d3SWilliam A. Kennington III std::optional<stdplus::InAnyAddr> gw;
96a7344c3aSWilliam A. Kennington III while (!msg.empty())
97a7344c3aSWilliam A. Kennington III {
98a7344c3aSWilliam A. Kennington III auto [hdr, data] = extractRtAttr(msg);
99a7344c3aSWilliam A. Kennington III switch (hdr.rta_type)
100a7344c3aSWilliam A. Kennington III {
101a7344c3aSWilliam A. Kennington III case RTA_OIF:
1026a92363eSWilliam A. Kennington III ifIdx.emplace(stdplus::raw::copyFromStrict<int>(data));
103a7344c3aSWilliam A. Kennington III break;
104a7344c3aSWilliam A. Kennington III case RTA_GATEWAY:
1056a92363eSWilliam A. Kennington III gw.emplace(stdplus::raw::copyFromStrict<Addr>(data));
106a7344c3aSWilliam A. Kennington III break;
107a7344c3aSWilliam A. Kennington III }
108a7344c3aSWilliam A. Kennington III }
109a7344c3aSWilliam A. Kennington III if (ifIdx && gw)
110a7344c3aSWilliam A. Kennington III {
111a7344c3aSWilliam A. Kennington III return std::make_tuple(*ifIdx, *gw);
112a7344c3aSWilliam A. Kennington III }
113a7344c3aSWilliam A. Kennington III return std::nullopt;
114a7344c3aSWilliam A. Kennington III }
115a7344c3aSWilliam A. Kennington III
116*9b2a20d3SWilliam A. Kennington III std::optional<std::tuple<unsigned, stdplus::InAnyAddr>>
gatewayFromRtm(std::string_view msg)117a7344c3aSWilliam A. Kennington III gatewayFromRtm(std::string_view msg)
118a7344c3aSWilliam A. Kennington III {
119a7344c3aSWilliam A. Kennington III const auto& rtm = extractRtData<rtmsg>(msg);
120a7344c3aSWilliam A. Kennington III if (rtm.rtm_table != RT_TABLE_MAIN || rtm.rtm_dst_len != 0)
121a7344c3aSWilliam A. Kennington III {
122a7344c3aSWilliam A. Kennington III return std::nullopt;
123a7344c3aSWilliam A. Kennington III }
124a7344c3aSWilliam A. Kennington III switch (rtm.rtm_family)
125a7344c3aSWilliam A. Kennington III {
126a7344c3aSWilliam A. Kennington III case AF_INET:
127*9b2a20d3SWilliam A. Kennington III return parse<stdplus::In4Addr>(msg);
128a7344c3aSWilliam A. Kennington III case AF_INET6:
129*9b2a20d3SWilliam A. Kennington III return parse<stdplus::In6Addr>(msg);
130a7344c3aSWilliam A. Kennington III }
131a7344c3aSWilliam A. Kennington III return std::nullopt;
132a7344c3aSWilliam A. Kennington III }
133a7344c3aSWilliam A. Kennington III
addrFromRtm(std::string_view msg)1346a92363eSWilliam A. Kennington III AddressInfo addrFromRtm(std::string_view msg)
1356a92363eSWilliam A. Kennington III {
1366a92363eSWilliam A. Kennington III const auto& ifa = extractRtData<ifaddrmsg>(msg);
1376a92363eSWilliam A. Kennington III
138*9b2a20d3SWilliam A. Kennington III uint32_t flags = ifa.ifa_flags;
139*9b2a20d3SWilliam A. Kennington III std::optional<stdplus::InAnyAddr> addr;
1406a92363eSWilliam A. Kennington III while (!msg.empty())
1416a92363eSWilliam A. Kennington III {
1426a92363eSWilliam A. Kennington III auto [hdr, data] = extractRtAttr(msg);
1436a92363eSWilliam A. Kennington III if (hdr.rta_type == IFA_ADDRESS)
1446a92363eSWilliam A. Kennington III {
1456a92363eSWilliam A. Kennington III addr.emplace(addrFromBuf(ifa.ifa_family, data));
1466a92363eSWilliam A. Kennington III }
1476a92363eSWilliam A. Kennington III else if (hdr.rta_type == IFA_FLAGS)
1486a92363eSWilliam A. Kennington III {
149*9b2a20d3SWilliam A. Kennington III flags = stdplus::raw::copyFromStrict<uint32_t>(data);
1506a92363eSWilliam A. Kennington III }
1516a92363eSWilliam A. Kennington III }
1526a92363eSWilliam A. Kennington III if (!addr)
1536a92363eSWilliam A. Kennington III {
1546a92363eSWilliam A. Kennington III throw std::runtime_error("Missing address");
1556a92363eSWilliam A. Kennington III }
156*9b2a20d3SWilliam A. Kennington III return AddressInfo{.ifidx = ifa.ifa_index,
157*9b2a20d3SWilliam A. Kennington III .ifaddr = stdplus::SubnetAny{*addr, ifa.ifa_prefixlen},
158*9b2a20d3SWilliam A. Kennington III .scope = ifa.ifa_scope,
159*9b2a20d3SWilliam A. Kennington III .flags = flags};
1606a92363eSWilliam A. Kennington III }
1616a92363eSWilliam A. Kennington III
neighFromRtm(std::string_view msg)162a8426902SWilliam A. Kennington III NeighborInfo neighFromRtm(std::string_view msg)
163a8426902SWilliam A. Kennington III {
164a8426902SWilliam A. Kennington III const auto& ndm = netlink::extractRtData<ndmsg>(msg);
165a8426902SWilliam A. Kennington III
166a8426902SWilliam A. Kennington III NeighborInfo ret;
167a8426902SWilliam A. Kennington III ret.ifidx = ndm.ndm_ifindex;
168a8426902SWilliam A. Kennington III ret.state = ndm.ndm_state;
169a8426902SWilliam A. Kennington III while (!msg.empty())
170a8426902SWilliam A. Kennington III {
171a8426902SWilliam A. Kennington III auto [hdr, data] = netlink::extractRtAttr(msg);
172a8426902SWilliam A. Kennington III if (hdr.rta_type == NDA_LLADDR)
173a8426902SWilliam A. Kennington III {
174b7d6a1a7SWilliam A. Kennington III ret.mac = stdplus::raw::copyFrom<stdplus::EtherAddr>(data);
175a8426902SWilliam A. Kennington III }
176a8426902SWilliam A. Kennington III else if (hdr.rta_type == NDA_DST)
177a8426902SWilliam A. Kennington III {
178a8426902SWilliam A. Kennington III ret.addr = addrFromBuf(ndm.ndm_family, data);
179a8426902SWilliam A. Kennington III }
180a8426902SWilliam A. Kennington III }
181a8426902SWilliam A. Kennington III return ret;
182a8426902SWilliam A. Kennington III }
183a8426902SWilliam A. Kennington III
184a7344c3aSWilliam A. Kennington III } // namespace phosphor::network::netlink
185