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