blob: d14b28eda4e068f08d868f4d8eed6aa38c2edaee [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 III217bb3f2022-09-29 13:43:13 -07003#include "types.hpp"
4
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05305#include <linux/netlink.h>
6#include <linux/rtnetlink.h>
Patrick Venture189d44e2018-07-09 12:30:59 -07007#include <netinet/in.h>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05308
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05309#include <memory>
William A. Kennington III32eef712022-01-24 17:03:03 -080010#include <stdplus/fd/create.hpp>
11#include <stdplus/fd/ops.hpp>
William A. Kennington III08505792019-01-30 16:00:04 -080012#include <string_view>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053013
14namespace phosphor
15{
16namespace network
17{
Ratan Guptaa54d8f82017-09-08 17:05:46 +053018
William A. Kennington III3a70fa22018-09-20 18:48:20 -070019extern std::unique_ptr<Timer> refreshObjectTimer;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053020
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053021namespace rtnetlink
22{
23
William A. Kennington III08505792019-01-30 16:00:04 -080024static bool shouldRefresh(const struct nlmsghdr& hdr, std::string_view data)
William A. Kennington IIId2d05942019-01-30 16:04:11 -080025{
26 switch (hdr.nlmsg_type)
27 {
28 case RTM_NEWADDR:
29 case RTM_DELADDR:
William A. Kennington III00506d82019-02-01 21:51:41 -080030 case RTM_NEWROUTE:
31 case RTM_DELROUTE:
William A. Kennington IIId2d05942019-01-30 16:04:11 -080032 {
33 return true;
34 }
William A. Kennington III08505792019-01-30 16:00:04 -080035 case RTM_NEWNEIGH:
36 case RTM_DELNEIGH:
37 {
38 struct ndmsg ndm;
39 if (data.size() < sizeof(ndm))
40 {
41 return false;
42 }
43 memcpy(&ndm, data.data(), sizeof(ndm));
44 // We only want to refresh for static neighbors
45 return ndm.ndm_state & NUD_PERMANENT;
46 }
William A. Kennington IIId2d05942019-01-30 16:04:11 -080047 }
48
49 return false;
50}
51
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053052/* Call Back for the sd event loop */
William A. Kennington III217bb3f2022-09-29 13:43:13 -070053static void eventHandler(sdeventplus::source::IO&, int fd, uint32_t)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053054{
William A. Kennington III217bb3f2022-09-29 13:43:13 -070055 std::array<char, BUFSIZE> buffer = {};
Gunnar Mills57d9c502018-09-14 14:42:34 -050056 int len{};
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053057
sureshvijayv1205cc102021-09-22 13:05:22 +053058 auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer.data());
59
William A. Kennington III217bb3f2022-09-29 13:43:13 -070060 while ((len = recv(fd, netLinkHeader, buffer.size(), 0)) > 0)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053061 {
62 for (; (NLMSG_OK(netLinkHeader, len)) &&
63 (netLinkHeader->nlmsg_type != NLMSG_DONE);
Gunnar Mills57d9c502018-09-14 14:42:34 -050064 netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053065 {
William A. Kennington III08505792019-01-30 16:00:04 -080066 std::string_view data(
67 reinterpret_cast<const char*>(NLMSG_DATA(netLinkHeader)),
68 netLinkHeader->nlmsg_len - NLMSG_HDRLEN);
69 if (shouldRefresh(*netLinkHeader, data))
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053070 {
Ratan Guptaa54d8f82017-09-08 17:05:46 +053071 // starting the timer here to make sure that we don't want
72 // create the child objects multiple times.
William A. Kennington IIIcb500dc2018-12-03 15:32:12 -080073 if (!refreshObjectTimer->isEnabled())
Ratan Guptaa54d8f82017-09-08 17:05:46 +053074 {
Ratan Guptaa54d8f82017-09-08 17:05:46 +053075 // if start timer throws exception then let the application
76 // crash
William A. Kennington III3a70fa22018-09-20 18:48:20 -070077 refreshObjectTimer->restartOnce(refreshTimeout);
Ratan Guptaa54d8f82017-09-08 17:05:46 +053078 } // end if
Gunnar Mills57d9c502018-09-14 14:42:34 -050079 } // end if
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053080
81 } // end for
82
sureshvijayv1205cc102021-09-22 13:05:22 +053083 buffer.fill('\0');
84
85 netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer.data());
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053086 } // end while
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053087}
88
William A. Kennington III32eef712022-01-24 17:03:03 -080089static stdplus::ManagedFd makeSock()
90{
91 using namespace stdplus::fd;
92
93 auto sock = socket(SocketDomain::Netlink, SocketType::Raw,
94 static_cast<stdplus::fd::SocketProto>(NETLINK_ROUTE));
95
96 sock.fcntlSetfl(sock.fcntlGetfl().set(FileFlag::NonBlock));
97
98 sockaddr_nl local{};
99 local.nl_family = AF_NETLINK;
100 local.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
101 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH;
102 bind(sock, local);
103
104 return sock;
105}
106
William A. Kennington III217bb3f2022-09-29 13:43:13 -0700107Server::Server(sdeventplus::Event& event) :
108 sock(makeSock()), io(event, sock.get(), EPOLLIN | EPOLLET, eventHandler)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530109{
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530110}
111
Gunnar Mills57d9c502018-09-14 14:42:34 -0500112} // namespace rtnetlink
113} // namespace network
114} // namespace phosphor