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