blob: b7b7cb3323f8f3c9a9663f39fee85debbb5472c3 [file] [log] [blame]
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05301#include "rtnetlink_server.hpp"
Patrick Venture189d44e2018-07-09 12:30:59 -07002
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05303#include "types.hpp"
4#include "util.hpp"
5
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05306#include <linux/netlink.h>
7#include <linux/rtnetlink.h>
8#include <net/if.h>
Patrick Venture189d44e2018-07-09 12:30:59 -07009#include <netinet/in.h>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053010#include <sys/types.h>
11#include <systemd/sd-daemon.h>
12#include <unistd.h>
13
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053014#include <memory>
Patrick Venture189d44e2018-07-09 12:30:59 -070015#include <phosphor-logging/elog-errors.hpp>
16#include <phosphor-logging/log.hpp>
William A. Kennington III08505792019-01-30 16:00:04 -080017#include <string_view>
Patrick Venture189d44e2018-07-09 12:30:59 -070018#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053019
20namespace phosphor
21{
22namespace network
23{
Ratan Guptaa54d8f82017-09-08 17:05:46 +053024
William A. Kennington III3a70fa22018-09-20 18:48:20 -070025extern std::unique_ptr<Timer> refreshObjectTimer;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053026
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053027namespace rtnetlink
28{
29
William A. Kennington III08505792019-01-30 16:00:04 -080030static bool shouldRefresh(const struct nlmsghdr& hdr, std::string_view data)
William A. Kennington IIId2d05942019-01-30 16:04:11 -080031{
32 switch (hdr.nlmsg_type)
33 {
34 case RTM_NEWADDR:
35 case RTM_DELADDR:
William A. Kennington III00506d82019-02-01 21:51:41 -080036 case RTM_NEWROUTE:
37 case RTM_DELROUTE:
William A. Kennington IIId2d05942019-01-30 16:04:11 -080038 {
39 return true;
40 }
William A. Kennington III08505792019-01-30 16:00:04 -080041 case RTM_NEWNEIGH:
42 case RTM_DELNEIGH:
43 {
44 struct ndmsg ndm;
45 if (data.size() < sizeof(ndm))
46 {
47 return false;
48 }
49 memcpy(&ndm, data.data(), sizeof(ndm));
50 // We only want to refresh for static neighbors
51 return ndm.ndm_state & NUD_PERMANENT;
52 }
William A. Kennington IIId2d05942019-01-30 16:04:11 -080053 }
54
55 return false;
56}
57
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053058/* Call Back for the sd event loop */
Manojkiran Edaaa57fa52020-06-13 14:59:53 +053059static int eventHandler(sd_event_source* /*es*/, int fd, uint32_t /*revents*/,
60 void* /*userdata*/)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053061{
sureshvijayv1205cc102021-09-22 13:05:22 +053062 std::array<char, phosphor::network::rtnetlink::BUFSIZE> buffer = {};
Gunnar Mills57d9c502018-09-14 14:42:34 -050063 int len{};
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053064
sureshvijayv1205cc102021-09-22 13:05:22 +053065 auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer.data());
66
Gunnar Mills57d9c502018-09-14 14:42:34 -050067 while ((len = recv(fd, netLinkHeader, phosphor::network::rtnetlink::BUFSIZE,
68 0)) > 0)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053069 {
70 for (; (NLMSG_OK(netLinkHeader, len)) &&
71 (netLinkHeader->nlmsg_type != NLMSG_DONE);
Gunnar Mills57d9c502018-09-14 14:42:34 -050072 netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053073 {
William A. Kennington III08505792019-01-30 16:00:04 -080074 std::string_view data(
75 reinterpret_cast<const char*>(NLMSG_DATA(netLinkHeader)),
76 netLinkHeader->nlmsg_len - NLMSG_HDRLEN);
77 if (shouldRefresh(*netLinkHeader, data))
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053078 {
Ratan Guptaa54d8f82017-09-08 17:05:46 +053079 // starting the timer here to make sure that we don't want
80 // create the child objects multiple times.
William A. Kennington IIIcb500dc2018-12-03 15:32:12 -080081 if (!refreshObjectTimer->isEnabled())
Ratan Guptaa54d8f82017-09-08 17:05:46 +053082 {
Ratan Guptaa54d8f82017-09-08 17:05:46 +053083 // if start timer throws exception then let the application
84 // crash
William A. Kennington III3a70fa22018-09-20 18:48:20 -070085 refreshObjectTimer->restartOnce(refreshTimeout);
Ratan Guptaa54d8f82017-09-08 17:05:46 +053086 } // end if
Gunnar Mills57d9c502018-09-14 14:42:34 -050087 } // end if
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053088
89 } // end for
90
sureshvijayv1205cc102021-09-22 13:05:22 +053091 buffer.fill('\0');
92
93 netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer.data());
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053094 } // end while
95
96 return 0;
97}
98
Ratan Guptaf6657382017-11-10 17:58:17 +053099Server::Server(EventPtr& eventPtr, const phosphor::Descriptor& smartSock)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530100{
101 using namespace phosphor::logging;
Gunnar Mills57d9c502018-09-14 14:42:34 -0500102 using InternalFailure =
103 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
104 struct sockaddr_nl addr
105 {
106 };
107 int r{};
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530108
Gunnar Mills57d9c502018-09-14 14:42:34 -0500109 sigset_t ss{};
Ratan Guptaf6657382017-11-10 17:58:17 +0530110 // check that the given socket is valid or not.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500111 if (smartSock() < 0)
Ratan Guptaf6657382017-11-10 17:58:17 +0530112 {
113 r = -EBADF;
114 goto finish;
115 }
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530116
117 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
118 sigaddset(&ss, SIGINT) < 0)
119 {
120 r = -errno;
121 goto finish;
122 }
123 /* Block SIGTERM first, so that the event loop can handle it */
124 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
125 {
126 r = -errno;
127 goto finish;
128 }
129
130 /* Let's make use of the default handler and "floating"
131 reference features of sd_event_add_signal() */
132
133 r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
134 if (r < 0)
135 {
136 goto finish;
137 }
138
139 r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
140 if (r < 0)
141 {
142 goto finish;
143 }
144
Patrick Venture836c91d2018-09-11 17:36:03 -0700145 std::memset(&addr, 0, sizeof(addr));
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530146 addr.nl_family = AF_NETLINK;
William A. Kennington III00506d82019-02-01 21:51:41 -0800147 addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
William A. Kennington III08505792019-01-30 16:00:04 -0800148 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH;
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530149
150 if (bind(smartSock(), (struct sockaddr*)&addr, sizeof(addr)) < 0)
151 {
152 r = -errno;
153 goto finish;
154 }
155
Gunnar Mills57d9c502018-09-14 14:42:34 -0500156 r = sd_event_add_io(eventPtr.get(), nullptr, smartSock(), EPOLLIN,
157 eventHandler, nullptr);
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530158 if (r < 0)
159 {
160 goto finish;
161 }
162
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530163finish:
164
165 if (r < 0)
166 {
Gunnar Millsd75f0492017-10-25 20:33:32 -0500167 log<level::ERR>("Failure Occurred in starting of server:",
Gunnar Millsfc7df192017-10-19 16:11:05 -0500168 entry("ERRNO=%d", errno));
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530169 elog<InternalFailure>();
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530170 }
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530171}
172
Gunnar Mills57d9c502018-09-14 14:42:34 -0500173} // namespace rtnetlink
174} // namespace network
175} // namespace phosphor