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