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