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 
161bbe3d1eSWilliam A. Kennington III #include <stdexcept>
171bbe3d1eSWilliam A. Kennington III #include <stdplus/raw.hpp>
181bbe3d1eSWilliam A. Kennington III #include <string_view>
191bbe3d1eSWilliam A. Kennington III #include <utility>
201bbe3d1eSWilliam A. Kennington III #include <vector>
211bbe3d1eSWilliam A. Kennington III 
221bbe3d1eSWilliam A. Kennington III namespace phosphor
231bbe3d1eSWilliam A. Kennington III {
241bbe3d1eSWilliam A. Kennington III namespace network
251bbe3d1eSWilliam A. Kennington III {
261bbe3d1eSWilliam A. Kennington III namespace detail
271bbe3d1eSWilliam A. Kennington III {
281bbe3d1eSWilliam A. Kennington III 
291bbe3d1eSWilliam A. Kennington III void parseNeighbor(const NeighborFilter& filter, const nlmsghdr& hdr,
301bbe3d1eSWilliam A. Kennington III                    std::string_view msg, std::vector<NeighborInfo>& neighbors)
311bbe3d1eSWilliam A. Kennington III {
321bbe3d1eSWilliam A. Kennington III     if (hdr.nlmsg_type != RTM_NEWNEIGH)
331bbe3d1eSWilliam A. Kennington III     {
341bbe3d1eSWilliam A. Kennington III         throw std::runtime_error("Not a neighbor msg");
351bbe3d1eSWilliam A. Kennington III     }
361bbe3d1eSWilliam A. Kennington III     auto ndm = stdplus::raw::extract<ndmsg>(msg);
371bbe3d1eSWilliam A. Kennington III 
381bbe3d1eSWilliam A. Kennington III     // Filter out neighbors we don't care about
391bbe3d1eSWilliam A. Kennington III     unsigned ifindex = ndm.ndm_ifindex;
401bbe3d1eSWilliam A. Kennington III     if (filter.interface != 0 && filter.interface != ifindex)
411bbe3d1eSWilliam A. Kennington III     {
421bbe3d1eSWilliam A. Kennington III         return;
431bbe3d1eSWilliam A. Kennington III     }
441bbe3d1eSWilliam A. Kennington III     if ((ndm.ndm_state & filter.state) == 0)
451bbe3d1eSWilliam A. Kennington III     {
461bbe3d1eSWilliam A. Kennington III         return;
471bbe3d1eSWilliam A. Kennington III     }
481bbe3d1eSWilliam A. Kennington III 
491bbe3d1eSWilliam A. Kennington III     // Build the neighbor info for our valid neighbor
501bbe3d1eSWilliam A. Kennington III     NeighborInfo neighbor;
511bbe3d1eSWilliam A. Kennington III     neighbor.interface = ifindex;
521bbe3d1eSWilliam A. Kennington III     neighbor.state = ndm.ndm_state;
531bbe3d1eSWilliam A. Kennington III     bool set_addr = false;
541bbe3d1eSWilliam A. Kennington III     while (!msg.empty())
551bbe3d1eSWilliam A. Kennington III     {
561bbe3d1eSWilliam A. Kennington III         auto [hdr, data] = netlink::extractRtAttr(msg);
571bbe3d1eSWilliam A. Kennington III         if (hdr.rta_type == NDA_LLADDR)
581bbe3d1eSWilliam A. Kennington III         {
591bbe3d1eSWilliam A. Kennington III             neighbor.mac = stdplus::raw::copyFrom<ether_addr>(data);
601bbe3d1eSWilliam A. Kennington III         }
611bbe3d1eSWilliam A. Kennington III         else if (hdr.rta_type == NDA_DST)
621bbe3d1eSWilliam A. Kennington III         {
631bbe3d1eSWilliam A. Kennington III             neighbor.address = addrFromBuf(ndm.ndm_family, data);
641bbe3d1eSWilliam A. Kennington III             set_addr = true;
651bbe3d1eSWilliam A. Kennington III         }
661bbe3d1eSWilliam A. Kennington III     }
671bbe3d1eSWilliam A. Kennington III     if (!set_addr)
681bbe3d1eSWilliam A. Kennington III     {
691bbe3d1eSWilliam A. Kennington III         throw std::runtime_error("Missing address");
701bbe3d1eSWilliam A. Kennington III     }
711bbe3d1eSWilliam A. Kennington III     neighbors.push_back(std::move(neighbor));
721bbe3d1eSWilliam A. Kennington III }
731bbe3d1eSWilliam A. Kennington III 
741bbe3d1eSWilliam A. Kennington III } // namespace detail
751bbe3d1eSWilliam A. Kennington III 
761bbe3d1eSWilliam A. Kennington III std::vector<NeighborInfo> getCurrentNeighbors(const NeighborFilter& filter)
771bbe3d1eSWilliam A. Kennington III {
781bbe3d1eSWilliam A. Kennington III     std::vector<NeighborInfo> neighbors;
791bbe3d1eSWilliam A. Kennington III     auto cb = [&filter, &neighbors](const nlmsghdr& hdr, std::string_view msg) {
801bbe3d1eSWilliam A. Kennington III         detail::parseNeighbor(filter, hdr, msg, neighbors);
811bbe3d1eSWilliam A. Kennington III     };
821bbe3d1eSWilliam A. Kennington III     ndmsg msg{};
831bbe3d1eSWilliam A. Kennington III     msg.ndm_ifindex = filter.interface;
841bbe3d1eSWilliam A. Kennington III     netlink::performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, msg, cb);
851bbe3d1eSWilliam A. Kennington III     return neighbors;
861bbe3d1eSWilliam A. Kennington III }
871bbe3d1eSWilliam A. Kennington III 
88*c38b0710SPatrick Williams Neighbor::Neighbor(sdbusplus::bus_t& bus, const char* objPath,
891bbe3d1eSWilliam A. Kennington III                    EthernetInterface& parent, const std::string& ipAddress,
901bbe3d1eSWilliam A. Kennington III                    const std::string& macAddress, State state) :
91166b9598SPatrick Williams     NeighborObj(bus, objPath, NeighborObj::action::defer_emit),
921bbe3d1eSWilliam A. Kennington III     parent(parent)
931bbe3d1eSWilliam A. Kennington III {
941bbe3d1eSWilliam A. Kennington III     this->ipAddress(ipAddress);
951bbe3d1eSWilliam A. Kennington III     this->macAddress(macAddress);
961bbe3d1eSWilliam A. Kennington III     this->state(state);
971bbe3d1eSWilliam A. Kennington III 
981bbe3d1eSWilliam A. Kennington III     // Emit deferred signal.
991bbe3d1eSWilliam A. Kennington III     emit_object_added();
1001bbe3d1eSWilliam A. Kennington III }
1011bbe3d1eSWilliam A. Kennington III 
1021bbe3d1eSWilliam A. Kennington III void Neighbor::delete_()
1031bbe3d1eSWilliam A. Kennington III {
1041bbe3d1eSWilliam A. Kennington III     parent.deleteStaticNeighborObject(ipAddress());
1051bbe3d1eSWilliam A. Kennington III }
1061bbe3d1eSWilliam A. Kennington III 
1071bbe3d1eSWilliam A. Kennington III } // namespace network
1081bbe3d1eSWilliam A. Kennington III } // namespace phosphor
109