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