1 #include "rtnetlink.hpp" 2 3 #include "netlink.hpp" 4 #include "util.hpp" 5 6 #include <linux/rtnetlink.h> 7 8 namespace phosphor::network::netlink 9 { 10 11 template <typename Addr> 12 static 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: 23 ifIdx.emplace(stdplus::raw::copyFromStrict<int>(data)); 24 break; 25 case RTA_GATEWAY: 26 gw.emplace(stdplus::raw::copyFromStrict<Addr>(data)); 27 break; 28 } 29 } 30 if (ifIdx && gw) 31 { 32 return std::make_tuple(*ifIdx, *gw); 33 } 34 return std::nullopt; 35 } 36 37 std::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 55 AddressInfo 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 84 } // namespace phosphor::network::netlink 85