11bbe3d1eSWilliam A. Kennington III #include "neighbor.hpp" 21bbe3d1eSWilliam A. Kennington III 31bbe3d1eSWilliam A. Kennington III #include "ethernet_interface.hpp" 41bbe3d1eSWilliam A. Kennington III #include "netlink.hpp" 51bbe3d1eSWilliam A. Kennington III #include "util.hpp" 61bbe3d1eSWilliam A. Kennington III 71bbe3d1eSWilliam A. Kennington III #include <linux/neighbour.h> 81bbe3d1eSWilliam A. Kennington III #include <linux/netlink.h> 91bbe3d1eSWilliam A. Kennington III #include <linux/rtnetlink.h> 101bbe3d1eSWilliam A. Kennington III #include <net/if.h> 111bbe3d1eSWilliam A. Kennington III #include <sys/socket.h> 121bbe3d1eSWilliam A. Kennington III #include <sys/types.h> 131bbe3d1eSWilliam A. Kennington III 148e61ca9dSWilliam A. Kennington III #include <phosphor-logging/elog-errors.hpp> 158e61ca9dSWilliam A. Kennington III #include <phosphor-logging/elog.hpp> 161bbe3d1eSWilliam A. Kennington III #include <stdexcept> 171bbe3d1eSWilliam A. Kennington III #include <stdplus/raw.hpp> 18*be3bd2fcSWilliam A. Kennington III #include <string> 191bbe3d1eSWilliam A. Kennington III #include <string_view> 201bbe3d1eSWilliam A. Kennington III #include <utility> 211bbe3d1eSWilliam A. Kennington III #include <vector> 228e61ca9dSWilliam A. Kennington III #include <xyz/openbmc_project/Common/error.hpp> 231bbe3d1eSWilliam A. Kennington III 241bbe3d1eSWilliam A. Kennington III namespace phosphor 251bbe3d1eSWilliam A. Kennington III { 261bbe3d1eSWilliam A. Kennington III namespace network 271bbe3d1eSWilliam A. Kennington III { 281bbe3d1eSWilliam A. Kennington III namespace detail 291bbe3d1eSWilliam A. Kennington III { 301bbe3d1eSWilliam A. Kennington III 311bbe3d1eSWilliam A. Kennington III void parseNeighbor(const NeighborFilter& filter, const nlmsghdr& hdr, 321bbe3d1eSWilliam A. Kennington III std::string_view msg, std::vector<NeighborInfo>& neighbors) 331bbe3d1eSWilliam A. Kennington III { 341bbe3d1eSWilliam A. Kennington III if (hdr.nlmsg_type != RTM_NEWNEIGH) 351bbe3d1eSWilliam A. Kennington III { 361bbe3d1eSWilliam A. Kennington III throw std::runtime_error("Not a neighbor msg"); 371bbe3d1eSWilliam A. Kennington III } 381bbe3d1eSWilliam A. Kennington III auto ndm = stdplus::raw::extract<ndmsg>(msg); 391bbe3d1eSWilliam A. Kennington III 401bbe3d1eSWilliam A. Kennington III // Filter out neighbors we don't care about 411bbe3d1eSWilliam A. Kennington III unsigned ifindex = ndm.ndm_ifindex; 421bbe3d1eSWilliam A. Kennington III if (filter.interface != 0 && filter.interface != ifindex) 431bbe3d1eSWilliam A. Kennington III { 441bbe3d1eSWilliam A. Kennington III return; 451bbe3d1eSWilliam A. Kennington III } 461bbe3d1eSWilliam A. Kennington III if ((ndm.ndm_state & filter.state) == 0) 471bbe3d1eSWilliam A. Kennington III { 481bbe3d1eSWilliam A. Kennington III return; 491bbe3d1eSWilliam A. Kennington III } 501bbe3d1eSWilliam A. Kennington III 511bbe3d1eSWilliam A. Kennington III // Build the neighbor info for our valid neighbor 521bbe3d1eSWilliam A. Kennington III NeighborInfo neighbor; 531bbe3d1eSWilliam A. Kennington III neighbor.interface = ifindex; 541bbe3d1eSWilliam A. Kennington III neighbor.state = ndm.ndm_state; 551bbe3d1eSWilliam A. Kennington III bool set_addr = false; 561bbe3d1eSWilliam A. Kennington III while (!msg.empty()) 571bbe3d1eSWilliam A. Kennington III { 581bbe3d1eSWilliam A. Kennington III auto [hdr, data] = netlink::extractRtAttr(msg); 591bbe3d1eSWilliam A. Kennington III if (hdr.rta_type == NDA_LLADDR) 601bbe3d1eSWilliam A. Kennington III { 611bbe3d1eSWilliam A. Kennington III neighbor.mac = stdplus::raw::copyFrom<ether_addr>(data); 621bbe3d1eSWilliam A. Kennington III } 631bbe3d1eSWilliam A. Kennington III else if (hdr.rta_type == NDA_DST) 641bbe3d1eSWilliam A. Kennington III { 651bbe3d1eSWilliam A. Kennington III neighbor.address = addrFromBuf(ndm.ndm_family, data); 661bbe3d1eSWilliam A. Kennington III set_addr = true; 671bbe3d1eSWilliam A. Kennington III } 681bbe3d1eSWilliam A. Kennington III } 691bbe3d1eSWilliam A. Kennington III if (!set_addr) 701bbe3d1eSWilliam A. Kennington III { 711bbe3d1eSWilliam A. Kennington III throw std::runtime_error("Missing address"); 721bbe3d1eSWilliam A. Kennington III } 731bbe3d1eSWilliam A. Kennington III neighbors.push_back(std::move(neighbor)); 741bbe3d1eSWilliam A. Kennington III } 751bbe3d1eSWilliam A. Kennington III 761bbe3d1eSWilliam A. Kennington III } // namespace detail 771bbe3d1eSWilliam A. Kennington III 781bbe3d1eSWilliam A. Kennington III std::vector<NeighborInfo> getCurrentNeighbors(const NeighborFilter& filter) 791bbe3d1eSWilliam A. Kennington III { 801bbe3d1eSWilliam A. Kennington III std::vector<NeighborInfo> neighbors; 811bbe3d1eSWilliam A. Kennington III auto cb = [&filter, &neighbors](const nlmsghdr& hdr, std::string_view msg) { 821bbe3d1eSWilliam A. Kennington III detail::parseNeighbor(filter, hdr, msg, neighbors); 831bbe3d1eSWilliam A. Kennington III }; 841bbe3d1eSWilliam A. Kennington III ndmsg msg{}; 851bbe3d1eSWilliam A. Kennington III msg.ndm_ifindex = filter.interface; 861bbe3d1eSWilliam A. Kennington III netlink::performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, msg, cb); 871bbe3d1eSWilliam A. Kennington III return neighbors; 881bbe3d1eSWilliam A. Kennington III } 891bbe3d1eSWilliam A. Kennington III 90*be3bd2fcSWilliam A. Kennington III Neighbor::Neighbor(sdbusplus::bus_t& bus, stdplus::const_zstring objPath, 91*be3bd2fcSWilliam A. Kennington III EthernetInterface& parent, std::string_view ipAddress, 92*be3bd2fcSWilliam A. Kennington III std::string_view macAddress, State state) : 93*be3bd2fcSWilliam A. Kennington III NeighborObj(bus, objPath.c_str(), NeighborObj::action::defer_emit), 941bbe3d1eSWilliam A. Kennington III parent(parent) 951bbe3d1eSWilliam A. Kennington III { 96*be3bd2fcSWilliam A. Kennington III NeighborObj::ipAddress(std::string(ipAddress)); 97*be3bd2fcSWilliam A. Kennington III NeighborObj::macAddress(std::string(macAddress)); 9819194627SWilliam A. Kennington III NeighborObj::state(state); 991bbe3d1eSWilliam A. Kennington III 1001bbe3d1eSWilliam A. Kennington III // Emit deferred signal. 1011bbe3d1eSWilliam A. Kennington III emit_object_added(); 1021bbe3d1eSWilliam A. Kennington III } 1031bbe3d1eSWilliam A. Kennington III 1041bbe3d1eSWilliam A. Kennington III void Neighbor::delete_() 1051bbe3d1eSWilliam A. Kennington III { 1061bbe3d1eSWilliam A. Kennington III parent.deleteStaticNeighborObject(ipAddress()); 1071bbe3d1eSWilliam A. Kennington III } 1081bbe3d1eSWilliam A. Kennington III 1098e61ca9dSWilliam A. Kennington III using sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 1108e61ca9dSWilliam A. Kennington III using REASON = 1118e61ca9dSWilliam A. Kennington III phosphor::logging::xyz::openbmc_project::Common::NotAllowed::REASON; 1128e61ca9dSWilliam A. Kennington III using phosphor::logging::elog; 1138e61ca9dSWilliam A. Kennington III 1148e61ca9dSWilliam A. Kennington III std::string Neighbor::ipAddress(std::string /*ipAddress*/) 1158e61ca9dSWilliam A. Kennington III { 1168e61ca9dSWilliam A. Kennington III elog<NotAllowed>(REASON("Property update is not allowed")); 1178e61ca9dSWilliam A. Kennington III } 1188e61ca9dSWilliam A. Kennington III 1198e61ca9dSWilliam A. Kennington III std::string Neighbor::macAddress(std::string /*macAddress*/) 1208e61ca9dSWilliam A. Kennington III { 1218e61ca9dSWilliam A. Kennington III elog<NotAllowed>(REASON("Property update is not allowed")); 1228e61ca9dSWilliam A. Kennington III } 1238e61ca9dSWilliam A. Kennington III 1248e61ca9dSWilliam A. Kennington III Neighbor::State Neighbor::state(State /*state*/) 1258e61ca9dSWilliam A. Kennington III { 1268e61ca9dSWilliam A. Kennington III elog<NotAllowed>(REASON("Property update is not allowed")); 1278e61ca9dSWilliam A. Kennington III } 1288e61ca9dSWilliam A. Kennington III 1291bbe3d1eSWilliam A. Kennington III } // namespace network 1301bbe3d1eSWilliam A. Kennington III } // namespace phosphor 131