blob: cf6834009da3104d1c39feec65dca897d887648b [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 {
35 return true;
36 }
William A. Kennington III08505792019-01-30 16:00:04 -080037 case RTM_NEWNEIGH:
38 case RTM_DELNEIGH:
39 {
40 struct ndmsg ndm;
41 if (data.size() < sizeof(ndm))
42 {
43 return false;
44 }
45 memcpy(&ndm, data.data(), sizeof(ndm));
46 // We only want to refresh for static neighbors
47 return ndm.ndm_state & NUD_PERMANENT;
48 }
William A. Kennington IIId2d05942019-01-30 16:04:11 -080049 }
50
51 return false;
52}
53
William A. Kennington III5f165dc2022-10-24 15:58:55 -070054static void handler(const nlmsghdr& hdr, std::string_view data)
55{
56 if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled())
57 {
58 refreshObjectTimer->restartOnce(refreshTimeout);
59 }
60}
61
William A. Kennington III217bb3f2022-09-29 13:43:13 -070062static void eventHandler(sdeventplus::source::IO&, int fd, uint32_t)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053063{
William A. Kennington III5f165dc2022-10-24 15:58:55 -070064 receive(fd, handler);
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053065}
66
William A. Kennington III32eef712022-01-24 17:03:03 -080067static stdplus::ManagedFd makeSock()
68{
69 using namespace stdplus::fd;
70
71 auto sock = socket(SocketDomain::Netlink, SocketType::Raw,
72 static_cast<stdplus::fd::SocketProto>(NETLINK_ROUTE));
73
74 sock.fcntlSetfl(sock.fcntlGetfl().set(FileFlag::NonBlock));
75
76 sockaddr_nl local{};
77 local.nl_family = AF_NETLINK;
78 local.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
79 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH;
80 bind(sock, local);
81
82 return sock;
83}
84
William A. Kennington III217bb3f2022-09-29 13:43:13 -070085Server::Server(sdeventplus::Event& event) :
86 sock(makeSock()), io(event, sock.get(), EPOLLIN | EPOLLET, eventHandler)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053087{
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053088}
89
William A. Kennington III5f165dc2022-10-24 15:58:55 -070090} // namespace netlink
Gunnar Mills57d9c502018-09-14 14:42:34 -050091} // namespace network
92} // namespace phosphor