blob: d1b1c46524d9704d42c60adead854c0d1a5b8008 [file] [log] [blame]
William A. Kennington III08505792019-01-30 16:00:04 -08001#include "config.h"
2
3#include "neighbor.hpp"
4
5#include "ethernet_interface.hpp"
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -07006#include "netlink.hpp"
William A. Kennington III08505792019-01-30 16:00:04 -08007#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 <cstring>
17#include <stdexcept>
18#include <string_view>
19#include <system_error>
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070020#include <vector>
William A. Kennington III08505792019-01-30 16:00:04 -080021
22namespace phosphor
23{
24namespace network
25{
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070026namespace detail
William A. Kennington III08505792019-01-30 16:00:04 -080027{
William A. Kennington III08505792019-01-30 16:00:04 -080028
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070029void parseNeighbor(const nlmsghdr& hdr, std::string_view msg,
30 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 = extract<ndmsg>(msg, "Bad neighbor msg");
37
38 NeighborInfo neighbor;
39 neighbor.interface.resize(IF_NAMESIZE);
40 if (if_indextoname(ndm.ndm_ifindex, neighbor.interface.data()) == nullptr)
William A. Kennington III08505792019-01-30 16:00:04 -080041 {
42 throw std::system_error(errno, std::generic_category(),
43 "if_indextoname");
44 }
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070045 neighbor.interface.resize(strlen(neighbor.interface.c_str()));
46 neighbor.permanent = ndm.ndm_state & NUD_PERMANENT;
William A. Kennington III08505792019-01-30 16:00:04 -080047 bool set_addr = false;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070048 while (!msg.empty())
William A. Kennington III08505792019-01-30 16:00:04 -080049 {
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070050 auto [hdr, data] = netlink::extractRtAttr(msg);
William A. Kennington III08505792019-01-30 16:00:04 -080051 if (hdr.rta_type == NDA_LLADDR)
52 {
William A. Kennington III6ca08d82019-04-20 16:04:18 -070053 neighbor.mac = copyFrom<ether_addr>(data, "Bad neighbor MAC");
William A. Kennington III08505792019-01-30 16:00:04 -080054 }
55 else if (hdr.rta_type == NDA_DST)
56 {
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070057 neighbor.address = addrFromBuf(ndm.ndm_family, data);
William A. Kennington III08505792019-01-30 16:00:04 -080058 set_addr = true;
59 }
William A. Kennington III08505792019-01-30 16:00:04 -080060 }
61 if (!set_addr)
62 {
63 throw std::runtime_error("Missing address");
64 }
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070065 neighbors.push_back(std::move(neighbor));
William A. Kennington III08505792019-01-30 16:00:04 -080066}
67
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070068} // namespace detail
William A. Kennington III08505792019-01-30 16:00:04 -080069
70std::vector<NeighborInfo> getCurrentNeighbors()
71{
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070072 std::vector<NeighborInfo> neighbors;
73 auto cb = [&neighbors](const nlmsghdr& hdr, std::string_view msg) {
74 detail::parseNeighbor(hdr, msg, neighbors);
75 };
76 netlink::performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, ndmsg{},
77 cb);
78 return neighbors;
William A. Kennington III08505792019-01-30 16:00:04 -080079}
80
81Neighbor::Neighbor(sdbusplus::bus::bus& bus, const char* objPath,
82 EthernetInterface& parent, const std::string& ipAddress,
83 const std::string& macAddress, State state) :
84 NeighborObj(bus, objPath, true),
85 parent(parent)
86{
87 this->iPAddress(ipAddress);
88 this->mACAddress(macAddress);
89 this->state(state);
90
91 // Emit deferred signal.
92 emit_object_added();
93}
94
95void Neighbor::delete_()
96{
97 parent.deleteStaticNeighborObject(iPAddress());
98}
99
100} // namespace network
101} // namespace phosphor