1 #include "neighbor.hpp" 2 3 #include "ethernet_interface.hpp" 4 #include "netlink.hpp" 5 #include "util.hpp" 6 7 #include <linux/neighbour.h> 8 #include <linux/netlink.h> 9 #include <linux/rtnetlink.h> 10 #include <net/if.h> 11 #include <sys/socket.h> 12 #include <sys/types.h> 13 14 #include <phosphor-logging/elog-errors.hpp> 15 #include <phosphor-logging/elog.hpp> 16 #include <stdexcept> 17 #include <stdplus/raw.hpp> 18 #include <string_view> 19 #include <utility> 20 #include <vector> 21 #include <xyz/openbmc_project/Common/error.hpp> 22 23 namespace phosphor 24 { 25 namespace network 26 { 27 namespace detail 28 { 29 30 void parseNeighbor(const NeighborFilter& filter, const nlmsghdr& hdr, 31 std::string_view msg, std::vector<NeighborInfo>& neighbors) 32 { 33 if (hdr.nlmsg_type != RTM_NEWNEIGH) 34 { 35 throw std::runtime_error("Not a neighbor msg"); 36 } 37 auto ndm = stdplus::raw::extract<ndmsg>(msg); 38 39 // Filter out neighbors we don't care about 40 unsigned ifindex = ndm.ndm_ifindex; 41 if (filter.interface != 0 && filter.interface != ifindex) 42 { 43 return; 44 } 45 if ((ndm.ndm_state & filter.state) == 0) 46 { 47 return; 48 } 49 50 // Build the neighbor info for our valid neighbor 51 NeighborInfo neighbor; 52 neighbor.interface = ifindex; 53 neighbor.state = ndm.ndm_state; 54 bool set_addr = false; 55 while (!msg.empty()) 56 { 57 auto [hdr, data] = netlink::extractRtAttr(msg); 58 if (hdr.rta_type == NDA_LLADDR) 59 { 60 neighbor.mac = stdplus::raw::copyFrom<ether_addr>(data); 61 } 62 else if (hdr.rta_type == NDA_DST) 63 { 64 neighbor.address = addrFromBuf(ndm.ndm_family, data); 65 set_addr = true; 66 } 67 } 68 if (!set_addr) 69 { 70 throw std::runtime_error("Missing address"); 71 } 72 neighbors.push_back(std::move(neighbor)); 73 } 74 75 } // namespace detail 76 77 std::vector<NeighborInfo> getCurrentNeighbors(const NeighborFilter& filter) 78 { 79 std::vector<NeighborInfo> neighbors; 80 auto cb = [&filter, &neighbors](const nlmsghdr& hdr, std::string_view msg) { 81 detail::parseNeighbor(filter, hdr, msg, neighbors); 82 }; 83 ndmsg msg{}; 84 msg.ndm_ifindex = filter.interface; 85 netlink::performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, msg, cb); 86 return neighbors; 87 } 88 89 Neighbor::Neighbor(sdbusplus::bus_t& bus, const char* objPath, 90 EthernetInterface& parent, const std::string& ipAddress, 91 const std::string& macAddress, State state) : 92 NeighborObj(bus, objPath, NeighborObj::action::defer_emit), 93 parent(parent) 94 { 95 NeighborObj::ipAddress(ipAddress); 96 NeighborObj::macAddress(macAddress); 97 NeighborObj::state(state); 98 99 // Emit deferred signal. 100 emit_object_added(); 101 } 102 103 void Neighbor::delete_() 104 { 105 parent.deleteStaticNeighborObject(ipAddress()); 106 } 107 108 using sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 109 using REASON = 110 phosphor::logging::xyz::openbmc_project::Common::NotAllowed::REASON; 111 using phosphor::logging::elog; 112 113 std::string Neighbor::ipAddress(std::string /*ipAddress*/) 114 { 115 elog<NotAllowed>(REASON("Property update is not allowed")); 116 } 117 118 std::string Neighbor::macAddress(std::string /*macAddress*/) 119 { 120 elog<NotAllowed>(REASON("Property update is not allowed")); 121 } 122 123 Neighbor::State Neighbor::state(State /*state*/) 124 { 125 elog<NotAllowed>(REASON("Property update is not allowed")); 126 } 127 128 } // namespace network 129 } // namespace phosphor 130