blob: 732055a08dde413b6a92f68c03f4e3260f0fce25 [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>
17#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053018
19namespace phosphor
20{
21namespace network
22{
Ratan Guptaa54d8f82017-09-08 17:05:46 +053023
William A. Kennington III3a70fa22018-09-20 18:48:20 -070024extern std::unique_ptr<Timer> refreshObjectTimer;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053025
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053026namespace rtnetlink
27{
28
William A. Kennington IIId2d05942019-01-30 16:04:11 -080029static bool shouldRefresh(const struct nlmsghdr& hdr)
30{
31 switch (hdr.nlmsg_type)
32 {
33 case RTM_NEWADDR:
34 case RTM_DELADDR:
William A. Kennington III00506d82019-02-01 21:51:41 -080035 case RTM_NEWROUTE:
36 case RTM_DELROUTE:
William A. Kennington IIId2d05942019-01-30 16:04:11 -080037 {
38 return true;
39 }
40 }
41
42 return false;
43}
44
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053045/* Call Back for the sd event loop */
46static int eventHandler(sd_event_source* es, int fd, uint32_t revents,
47 void* userdata)
48{
Gunnar Mills57d9c502018-09-14 14:42:34 -050049 char buffer[phosphor::network::rtnetlink::BUFSIZE]{};
50 int len{};
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053051
52 auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer);
Gunnar Mills57d9c502018-09-14 14:42:34 -050053 while ((len = recv(fd, netLinkHeader, phosphor::network::rtnetlink::BUFSIZE,
54 0)) > 0)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053055 {
56 for (; (NLMSG_OK(netLinkHeader, len)) &&
57 (netLinkHeader->nlmsg_type != NLMSG_DONE);
Gunnar Mills57d9c502018-09-14 14:42:34 -050058 netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053059 {
William A. Kennington IIId2d05942019-01-30 16:04:11 -080060 if (shouldRefresh(*netLinkHeader))
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053061 {
Ratan Guptaa54d8f82017-09-08 17:05:46 +053062 // starting the timer here to make sure that we don't want
63 // create the child objects multiple times.
William A. Kennington IIIcb500dc2018-12-03 15:32:12 -080064 if (!refreshObjectTimer->isEnabled())
Ratan Guptaa54d8f82017-09-08 17:05:46 +053065 {
Ratan Guptaa54d8f82017-09-08 17:05:46 +053066 // if start timer throws exception then let the application
67 // crash
William A. Kennington III3a70fa22018-09-20 18:48:20 -070068 refreshObjectTimer->restartOnce(refreshTimeout);
Ratan Guptaa54d8f82017-09-08 17:05:46 +053069 } // end if
Gunnar Mills57d9c502018-09-14 14:42:34 -050070 } // end if
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053071
72 } // end for
73
74 } // end while
75
76 return 0;
77}
78
Ratan Guptaf6657382017-11-10 17:58:17 +053079Server::Server(EventPtr& eventPtr, const phosphor::Descriptor& smartSock)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053080{
81 using namespace phosphor::logging;
Gunnar Mills57d9c502018-09-14 14:42:34 -050082 using InternalFailure =
83 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
84 struct sockaddr_nl addr
85 {
86 };
87 int r{};
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053088
Gunnar Mills57d9c502018-09-14 14:42:34 -050089 sigset_t ss{};
Ratan Guptaf6657382017-11-10 17:58:17 +053090 // check that the given socket is valid or not.
Gunnar Mills57d9c502018-09-14 14:42:34 -050091 if (smartSock() < 0)
Ratan Guptaf6657382017-11-10 17:58:17 +053092 {
93 r = -EBADF;
94 goto finish;
95 }
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053096
97 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
98 sigaddset(&ss, SIGINT) < 0)
99 {
100 r = -errno;
101 goto finish;
102 }
103 /* Block SIGTERM first, so that the event loop can handle it */
104 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
105 {
106 r = -errno;
107 goto finish;
108 }
109
110 /* Let's make use of the default handler and "floating"
111 reference features of sd_event_add_signal() */
112
113 r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
114 if (r < 0)
115 {
116 goto finish;
117 }
118
119 r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
120 if (r < 0)
121 {
122 goto finish;
123 }
124
Patrick Venture836c91d2018-09-11 17:36:03 -0700125 std::memset(&addr, 0, sizeof(addr));
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530126 addr.nl_family = AF_NETLINK;
William A. Kennington III00506d82019-02-01 21:51:41 -0800127 addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
128 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE;
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530129
130 if (bind(smartSock(), (struct sockaddr*)&addr, sizeof(addr)) < 0)
131 {
132 r = -errno;
133 goto finish;
134 }
135
Gunnar Mills57d9c502018-09-14 14:42:34 -0500136 r = sd_event_add_io(eventPtr.get(), nullptr, smartSock(), EPOLLIN,
137 eventHandler, nullptr);
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530138 if (r < 0)
139 {
140 goto finish;
141 }
142
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530143finish:
144
145 if (r < 0)
146 {
Gunnar Millsd75f0492017-10-25 20:33:32 -0500147 log<level::ERR>("Failure Occurred in starting of server:",
Gunnar Millsfc7df192017-10-19 16:11:05 -0500148 entry("ERRNO=%d", errno));
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530149 elog<InternalFailure>();
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530150 }
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530151}
152
Gunnar Mills57d9c502018-09-14 14:42:34 -0500153} // namespace rtnetlink
154} // namespace network
155} // namespace phosphor