blob: 3121e4de1e9b81b4b6e7401ba096fadeb334e59f [file] [log] [blame]
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05301#include "rtnetlink_server.hpp"
Patrick Venture189d44e2018-07-09 12:30:59 -07002
Ratan Guptaa54d8f82017-09-08 17:05:46 +05303#include "timer.hpp"
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05304#include "types.hpp"
5#include "util.hpp"
6
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05307#include <linux/netlink.h>
8#include <linux/rtnetlink.h>
9#include <net/if.h>
Patrick Venture189d44e2018-07-09 12:30:59 -070010#include <netinet/in.h>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053011#include <sys/types.h>
12#include <systemd/sd-daemon.h>
13#include <unistd.h>
14
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053015#include <memory>
Patrick Venture189d44e2018-07-09 12:30:59 -070016#include <phosphor-logging/elog-errors.hpp>
17#include <phosphor-logging/log.hpp>
18#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
Ratan Gupta16f12882017-09-22 18:26:11 +053025extern std::unique_ptr<phosphor::network::Timer> refreshObjectTimer;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053026
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053027namespace rtnetlink
28{
29
30/* Call Back for the sd event loop */
31static int eventHandler(sd_event_source* es, int fd, uint32_t revents,
32 void* userdata)
33{
Gunnar Mills57d9c502018-09-14 14:42:34 -050034 char buffer[phosphor::network::rtnetlink::BUFSIZE]{};
35 int len{};
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053036
37 auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer);
Gunnar Mills57d9c502018-09-14 14:42:34 -050038 while ((len = recv(fd, netLinkHeader, phosphor::network::rtnetlink::BUFSIZE,
39 0)) > 0)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053040 {
41 for (; (NLMSG_OK(netLinkHeader, len)) &&
42 (netLinkHeader->nlmsg_type != NLMSG_DONE);
Gunnar Mills57d9c502018-09-14 14:42:34 -050043 netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053044 {
45 if (netLinkHeader->nlmsg_type == RTM_NEWADDR ||
46 netLinkHeader->nlmsg_type == RTM_DELADDR)
47 {
Ratan Guptaa54d8f82017-09-08 17:05:46 +053048 // starting the timer here to make sure that we don't want
49 // create the child objects multiple times.
Ratan Gupta16f12882017-09-22 18:26:11 +053050 if (refreshObjectTimer->isExpired())
Ratan Guptaa54d8f82017-09-08 17:05:46 +053051 {
52 using namespace std::chrono;
Ratan Gupta16f12882017-09-22 18:26:11 +053053 auto time = duration_cast<microseconds>(refreshTimeout);
Ratan Guptaa54d8f82017-09-08 17:05:46 +053054 // if start timer throws exception then let the application
55 // crash
Ratan Gupta16f12882017-09-22 18:26:11 +053056 refreshObjectTimer->startTimer(time);
Ratan Guptaa54d8f82017-09-08 17:05:46 +053057 } // end if
Gunnar Mills57d9c502018-09-14 14:42:34 -050058 } // end if
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053059
60 } // end for
61
62 } // end while
63
64 return 0;
65}
66
Ratan Guptaf6657382017-11-10 17:58:17 +053067Server::Server(EventPtr& eventPtr, const phosphor::Descriptor& smartSock)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053068{
69 using namespace phosphor::logging;
Gunnar Mills57d9c502018-09-14 14:42:34 -050070 using InternalFailure =
71 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
72 struct sockaddr_nl addr
73 {
74 };
75 int r{};
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053076
Gunnar Mills57d9c502018-09-14 14:42:34 -050077 sigset_t ss{};
Ratan Guptaf6657382017-11-10 17:58:17 +053078 // check that the given socket is valid or not.
Gunnar Mills57d9c502018-09-14 14:42:34 -050079 if (smartSock() < 0)
Ratan Guptaf6657382017-11-10 17:58:17 +053080 {
81 r = -EBADF;
82 goto finish;
83 }
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053084
85 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
86 sigaddset(&ss, SIGINT) < 0)
87 {
88 r = -errno;
89 goto finish;
90 }
91 /* Block SIGTERM first, so that the event loop can handle it */
92 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
93 {
94 r = -errno;
95 goto finish;
96 }
97
98 /* Let's make use of the default handler and "floating"
99 reference features of sd_event_add_signal() */
100
101 r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
102 if (r < 0)
103 {
104 goto finish;
105 }
106
107 r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
108 if (r < 0)
109 {
110 goto finish;
111 }
112
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530113 memset(&addr, 0, sizeof(addr));
114 addr.nl_family = AF_NETLINK;
Ratan Gupta16f12882017-09-22 18:26:11 +0530115 addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530116
117 if (bind(smartSock(), (struct sockaddr*)&addr, sizeof(addr)) < 0)
118 {
119 r = -errno;
120 goto finish;
121 }
122
Gunnar Mills57d9c502018-09-14 14:42:34 -0500123 r = sd_event_add_io(eventPtr.get(), nullptr, smartSock(), EPOLLIN,
124 eventHandler, nullptr);
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530125 if (r < 0)
126 {
127 goto finish;
128 }
129
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530130finish:
131
132 if (r < 0)
133 {
Gunnar Millsd75f0492017-10-25 20:33:32 -0500134 log<level::ERR>("Failure Occurred in starting of server:",
Gunnar Millsfc7df192017-10-19 16:11:05 -0500135 entry("ERRNO=%d", errno));
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530136 elog<InternalFailure>();
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530137 }
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530138}
139
Gunnar Mills57d9c502018-09-14 14:42:34 -0500140} // namespace rtnetlink
141} // namespace network
142} // namespace phosphor