1 #include "config.h" 2 3 #include "neighbor.hpp" 4 5 #include "ethernet_interface.hpp" 6 #include "netlink.hpp" 7 #include "util.hpp" 8 9 #include <linux/neighbour.h> 10 #include <linux/netlink.h> 11 #include <linux/rtnetlink.h> 12 #include <net/if.h> 13 #include <sys/socket.h> 14 #include <sys/types.h> 15 16 #include <stdexcept> 17 #include <stdplus/raw.hpp> 18 #include <string_view> 19 #include <utility> 20 #include <vector> 21 22 namespace phosphor 23 { 24 namespace network 25 { 26 namespace detail 27 { 28 29 void parseNeighbor(const NeighborFilter& filter, const nlmsghdr& hdr, 30 std::string_view msg, std::vector<NeighborInfo>& neighbors) 31 { 32 if (hdr.nlmsg_type != RTM_NEWNEIGH) 33 { 34 throw std::runtime_error("Not a neighbor msg"); 35 } 36 auto ndm = stdplus::raw::extract<ndmsg>(msg); 37 38 // Filter out neighbors we don't care about 39 unsigned ifindex = ndm.ndm_ifindex; 40 if (filter.interface != 0 && filter.interface != ifindex) 41 { 42 return; 43 } 44 if ((ndm.ndm_state & filter.state) == 0) 45 { 46 return; 47 } 48 49 // Build the neighbor info for our valid neighbor 50 NeighborInfo neighbor; 51 neighbor.interface = ifindex; 52 neighbor.state = ndm.ndm_state; 53 bool set_addr = false; 54 while (!msg.empty()) 55 { 56 auto [hdr, data] = netlink::extractRtAttr(msg); 57 if (hdr.rta_type == NDA_LLADDR) 58 { 59 neighbor.mac = stdplus::raw::copyFrom<ether_addr>(data); 60 } 61 else if (hdr.rta_type == NDA_DST) 62 { 63 neighbor.address = addrFromBuf(ndm.ndm_family, data); 64 set_addr = true; 65 } 66 } 67 if (!set_addr) 68 { 69 throw std::runtime_error("Missing address"); 70 } 71 neighbors.push_back(std::move(neighbor)); 72 } 73 74 } // namespace detail 75 76 std::vector<NeighborInfo> getCurrentNeighbors(const NeighborFilter& filter) 77 { 78 std::vector<NeighborInfo> neighbors; 79 auto cb = [&filter, &neighbors](const nlmsghdr& hdr, std::string_view msg) { 80 detail::parseNeighbor(filter, hdr, msg, neighbors); 81 }; 82 ndmsg msg{}; 83 msg.ndm_ifindex = filter.interface; 84 netlink::performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, msg, cb); 85 return neighbors; 86 } 87 88 Neighbor::Neighbor(sdbusplus::bus::bus& bus, const char* objPath, 89 EthernetInterface& parent, const std::string& ipAddress, 90 const std::string& macAddress, State state) : 91 NeighborObj(bus, objPath, NeighborObj::action::defer_emit), 92 parent(parent) 93 { 94 this->ipAddress(ipAddress); 95 this->macAddress(macAddress); 96 this->state(state); 97 98 // Emit deferred signal. 99 emit_object_added(); 100 } 101 102 void Neighbor::delete_() 103 { 104 parent.deleteStaticNeighborObject(ipAddress()); 105 } 106 107 } // namespace network 108 } // namespace phosphor 109