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 NeighborInfo 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 112 } // namespace phosphor::network::netlink 113