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" 5*434a943cSWilliam A. Kennington III #include "network_manager.hpp" 61bbe3d1eSWilliam A. Kennington III #include "util.hpp" 71bbe3d1eSWilliam A. Kennington III 81bbe3d1eSWilliam A. Kennington III #include <linux/neighbour.h> 91bbe3d1eSWilliam A. Kennington III #include <linux/netlink.h> 101bbe3d1eSWilliam A. Kennington III #include <linux/rtnetlink.h> 111bbe3d1eSWilliam A. Kennington III #include <net/if.h> 121bbe3d1eSWilliam A. Kennington III #include <sys/socket.h> 131bbe3d1eSWilliam A. Kennington III #include <sys/types.h> 141bbe3d1eSWilliam A. Kennington III 158e61ca9dSWilliam A. Kennington III #include <phosphor-logging/elog-errors.hpp> 168e61ca9dSWilliam A. Kennington III #include <phosphor-logging/elog.hpp> 171bbe3d1eSWilliam A. Kennington III #include <stdexcept> 181bbe3d1eSWilliam A. Kennington III #include <stdplus/raw.hpp> 19be3bd2fcSWilliam A. Kennington III #include <string> 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 } 39f1289a0aSWilliam A. Kennington III const auto& ndm = netlink::extractRtData<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 91*434a943cSWilliam A. Kennington III static auto makeObjPath(std::string_view root, InAddrAny addr) 921bbe3d1eSWilliam A. Kennington III { 93*434a943cSWilliam A. Kennington III auto ret = sdbusplus::message::object_path(std::string(root)); 94*434a943cSWilliam A. Kennington III ret /= std::to_string(addr); 95*434a943cSWilliam A. Kennington III return ret; 96*434a943cSWilliam A. Kennington III } 97*434a943cSWilliam A. Kennington III 98*434a943cSWilliam A. Kennington III Neighbor::Neighbor(sdbusplus::bus_t& bus, std::string_view objRoot, 99*434a943cSWilliam A. Kennington III EthernetInterface& parent, InAddrAny addr, ether_addr lladdr, 100*434a943cSWilliam A. Kennington III State state) : 101*434a943cSWilliam A. Kennington III Neighbor(bus, makeObjPath(objRoot, addr), parent, addr, lladdr, state) 102*434a943cSWilliam A. Kennington III { 103*434a943cSWilliam A. Kennington III } 104*434a943cSWilliam A. Kennington III 105*434a943cSWilliam A. Kennington III Neighbor::Neighbor(sdbusplus::bus_t& bus, 106*434a943cSWilliam A. Kennington III sdbusplus::message::object_path objPath, 107*434a943cSWilliam A. Kennington III EthernetInterface& parent, InAddrAny addr, ether_addr lladdr, 108*434a943cSWilliam A. Kennington III State state) : 109*434a943cSWilliam A. Kennington III NeighborObj(bus, objPath.str.c_str(), NeighborObj::action::defer_emit), 110*434a943cSWilliam A. Kennington III parent(parent), objPath(std::move(objPath)) 111*434a943cSWilliam A. Kennington III { 112*434a943cSWilliam A. Kennington III NeighborObj::ipAddress(std::to_string(addr)); 113*434a943cSWilliam A. Kennington III NeighborObj::macAddress(std::to_string(lladdr)); 11419194627SWilliam A. Kennington III NeighborObj::state(state); 1151bbe3d1eSWilliam A. Kennington III 1161bbe3d1eSWilliam A. Kennington III // Emit deferred signal. 1171bbe3d1eSWilliam A. Kennington III emit_object_added(); 1181bbe3d1eSWilliam A. Kennington III } 1191bbe3d1eSWilliam A. Kennington III 1201bbe3d1eSWilliam A. Kennington III void Neighbor::delete_() 1211bbe3d1eSWilliam A. Kennington III { 122*434a943cSWilliam A. Kennington III auto& neighbors = parent.staticNeighbors; 123*434a943cSWilliam A. Kennington III std::unique_ptr<Neighbor> ptr; 124*434a943cSWilliam A. Kennington III for (auto it = neighbors.begin(); it != neighbors.end(); ++it) 125*434a943cSWilliam A. Kennington III { 126*434a943cSWilliam A. Kennington III if (it->second.get() == this) 127*434a943cSWilliam A. Kennington III { 128*434a943cSWilliam A. Kennington III ptr = std::move(it->second); 129*434a943cSWilliam A. Kennington III neighbors.erase(it); 130*434a943cSWilliam A. Kennington III break; 131*434a943cSWilliam A. Kennington III } 132*434a943cSWilliam A. Kennington III } 133*434a943cSWilliam A. Kennington III 134*434a943cSWilliam A. Kennington III parent.writeConfigurationFile(); 135*434a943cSWilliam A. Kennington III parent.manager.reloadConfigs(); 1361bbe3d1eSWilliam A. Kennington III } 1371bbe3d1eSWilliam A. Kennington III 1388e61ca9dSWilliam A. Kennington III using sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 1398e61ca9dSWilliam A. Kennington III using REASON = 1408e61ca9dSWilliam A. Kennington III phosphor::logging::xyz::openbmc_project::Common::NotAllowed::REASON; 1418e61ca9dSWilliam A. Kennington III using phosphor::logging::elog; 1428e61ca9dSWilliam A. Kennington III 1438e61ca9dSWilliam A. Kennington III std::string Neighbor::ipAddress(std::string /*ipAddress*/) 1448e61ca9dSWilliam A. Kennington III { 1458e61ca9dSWilliam A. Kennington III elog<NotAllowed>(REASON("Property update is not allowed")); 1468e61ca9dSWilliam A. Kennington III } 1478e61ca9dSWilliam A. Kennington III 1488e61ca9dSWilliam A. Kennington III std::string Neighbor::macAddress(std::string /*macAddress*/) 1498e61ca9dSWilliam A. Kennington III { 1508e61ca9dSWilliam A. Kennington III elog<NotAllowed>(REASON("Property update is not allowed")); 1518e61ca9dSWilliam A. Kennington III } 1528e61ca9dSWilliam A. Kennington III 1538e61ca9dSWilliam A. Kennington III Neighbor::State Neighbor::state(State /*state*/) 1548e61ca9dSWilliam A. Kennington III { 1558e61ca9dSWilliam A. Kennington III elog<NotAllowed>(REASON("Property update is not allowed")); 1568e61ca9dSWilliam A. Kennington III } 1578e61ca9dSWilliam A. Kennington III 1581bbe3d1eSWilliam A. Kennington III } // namespace network 1591bbe3d1eSWilliam A. Kennington III } // namespace phosphor 160