blob: 57ec475637accfc39706309dca2f92791a402eff [file] [log] [blame]
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05301#include "rtnetlink_server.hpp"
Patrick Venture189d44e2018-07-09 12:30:59 -07002
William A. Kennington III5f165dc2022-10-24 15:58:55 -07003#include "netlink.hpp"
William A. Kennington III217bb3f2022-09-29 13:43:13 -07004#include "types.hpp"
5
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05306#include <linux/netlink.h>
7#include <linux/rtnetlink.h>
Patrick Venture189d44e2018-07-09 12:30:59 -07008#include <netinet/in.h>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05309
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053010#include <memory>
William A. Kennington III32eef712022-01-24 17:03:03 -080011#include <stdplus/fd/create.hpp>
12#include <stdplus/fd/ops.hpp>
William A. Kennington III08505792019-01-30 16:00:04 -080013#include <string_view>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053014
15namespace phosphor
16{
17namespace network
18{
Ratan Guptaa54d8f82017-09-08 17:05:46 +053019
William A. Kennington III3a70fa22018-09-20 18:48:20 -070020extern std::unique_ptr<Timer> refreshObjectTimer;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053021
William A. Kennington III5f165dc2022-10-24 15:58:55 -070022namespace netlink
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053023{
24
William A. Kennington III5f165dc2022-10-24 15:58:55 -070025static bool shouldRefresh(const struct nlmsghdr& hdr,
26 std::string_view data) noexcept
William A. Kennington IIId2d05942019-01-30 16:04:11 -080027{
28 switch (hdr.nlmsg_type)
29 {
30 case RTM_NEWADDR:
31 case RTM_DELADDR:
William A. Kennington III00506d82019-02-01 21:51:41 -080032 case RTM_NEWROUTE:
33 case RTM_DELROUTE:
William A. Kennington IIId2d05942019-01-30 16:04:11 -080034 return true;
William A. Kennington III08505792019-01-30 16:00:04 -080035 case RTM_NEWNEIGH:
36 case RTM_DELNEIGH:
37 {
William A. Kennington IIIc8e992f2022-10-24 16:15:32 -070038 if (data.size() < sizeof(ndmsg))
William A. Kennington III08505792019-01-30 16:00:04 -080039 {
40 return false;
41 }
William A. Kennington IIIc8e992f2022-10-24 16:15:32 -070042 const auto& ndm = *reinterpret_cast<const ndmsg*>(data.data());
William A. Kennington III08505792019-01-30 16:00:04 -080043 // We only want to refresh for static neighbors
44 return ndm.ndm_state & NUD_PERMANENT;
45 }
William A. Kennington IIId2d05942019-01-30 16:04:11 -080046 }
William A. Kennington IIId2d05942019-01-30 16:04:11 -080047 return false;
48}
49
William A. Kennington III5f165dc2022-10-24 15:58:55 -070050static void handler(const nlmsghdr& hdr, std::string_view data)
51{
52 if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled())
53 {
54 refreshObjectTimer->restartOnce(refreshTimeout);
55 }
56}
57
William A. Kennington III217bb3f2022-09-29 13:43:13 -070058static void eventHandler(sdeventplus::source::IO&, int fd, uint32_t)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053059{
William A. Kennington III29418ef2022-11-07 22:59:47 -080060 while (receive(fd, handler) > 0)
61 ;
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053062}
63
William A. Kennington III32eef712022-01-24 17:03:03 -080064static stdplus::ManagedFd makeSock()
65{
66 using namespace stdplus::fd;
67
68 auto sock = socket(SocketDomain::Netlink, SocketType::Raw,
69 static_cast<stdplus::fd::SocketProto>(NETLINK_ROUTE));
70
71 sock.fcntlSetfl(sock.fcntlGetfl().set(FileFlag::NonBlock));
72
73 sockaddr_nl local{};
74 local.nl_family = AF_NETLINK;
75 local.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
76 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH;
77 bind(sock, local);
78
79 return sock;
80}
81
William A. Kennington III217bb3f2022-09-29 13:43:13 -070082Server::Server(sdeventplus::Event& event) :
83 sock(makeSock()), io(event, sock.get(), EPOLLIN | EPOLLET, eventHandler)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053084{
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053085}
86
William A. Kennington III5f165dc2022-10-24 15:58:55 -070087} // namespace netlink
Gunnar Mills57d9c502018-09-14 14:42:34 -050088} // namespace network
89} // namespace phosphor