blob: 955706ca8b9178d4275360f9079272d056334d90 [file] [log] [blame]
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05301#include "rtnetlink_server.hpp"
Ratan Guptaa54d8f82017-09-08 17:05:46 +05302#include "timer.hpp"
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05303#include "types.hpp"
4#include "util.hpp"
5
6
7#include <netinet/in.h>
8#include <linux/netlink.h>
9#include <linux/rtnetlink.h>
10#include <net/if.h>
11#include <sys/types.h>
12#include <systemd/sd-daemon.h>
13#include <unistd.h>
14
15#include <phosphor-logging/log.hpp>
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +053016#include <phosphor-logging/elog-errors.hpp>
17#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053018
19#include <memory>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053020
21namespace phosphor
22{
23namespace network
24{
Ratan Guptaa54d8f82017-09-08 17:05:46 +053025
Ratan Gupta16f12882017-09-22 18:26:11 +053026extern std::unique_ptr<phosphor::network::Timer> refreshObjectTimer;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053027
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053028namespace rtnetlink
29{
30
31/* Call Back for the sd event loop */
32static int eventHandler(sd_event_source* es, int fd, uint32_t revents,
33 void* userdata)
34{
35 char buffer[phosphor::network::rtnetlink::BUFSIZE] {};
36 int len {};
37
38 auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer);
39 while ((len = recv(fd, netLinkHeader,
40 phosphor::network::rtnetlink::BUFSIZE, 0)) > 0)
41 {
42 for (; (NLMSG_OK(netLinkHeader, len)) &&
43 (netLinkHeader->nlmsg_type != NLMSG_DONE);
44 netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
45 {
46 if (netLinkHeader->nlmsg_type == RTM_NEWADDR ||
47 netLinkHeader->nlmsg_type == RTM_DELADDR)
48 {
Ratan Guptaa54d8f82017-09-08 17:05:46 +053049 // starting the timer here to make sure that we don't want
50 // create the child objects multiple times.
Ratan Gupta16f12882017-09-22 18:26:11 +053051 if (refreshObjectTimer->isExpired())
Ratan Guptaa54d8f82017-09-08 17:05:46 +053052 {
53 using namespace std::chrono;
Ratan Gupta16f12882017-09-22 18:26:11 +053054 auto time = duration_cast<microseconds>(refreshTimeout);
Ratan Guptaa54d8f82017-09-08 17:05:46 +053055 // if start timer throws exception then let the application
56 // crash
Ratan Gupta16f12882017-09-22 18:26:11 +053057 refreshObjectTimer->startTimer(time);
Ratan Guptaa54d8f82017-09-08 17:05:46 +053058 } // end if
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053059 } // end if
60
61 } // end for
62
63 } // end while
64
65 return 0;
66}
67
Ratan Guptaf6657382017-11-10 17:58:17 +053068Server::Server(EventPtr& eventPtr, const phosphor::Descriptor& smartSock)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053069{
70 using namespace phosphor::logging;
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +053071 using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
72 Error::InternalFailure;
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053073 struct sockaddr_nl addr {};
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053074 int r {};
75
76 sigset_t ss {};
Ratan Guptaf6657382017-11-10 17:58:17 +053077 // check that the given socket is valid or not.
78 if(smartSock() < 0)
79 {
80 r = -EBADF;
81 goto finish;
82 }
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053083
84 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
85 sigaddset(&ss, SIGINT) < 0)
86 {
87 r = -errno;
88 goto finish;
89 }
90 /* Block SIGTERM first, so that the event loop can handle it */
91 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
92 {
93 r = -errno;
94 goto finish;
95 }
96
97 /* Let's make use of the default handler and "floating"
98 reference features of sd_event_add_signal() */
99
100 r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
101 if (r < 0)
102 {
103 goto finish;
104 }
105
106 r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
107 if (r < 0)
108 {
109 goto finish;
110 }
111
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530112 memset(&addr, 0, sizeof(addr));
113 addr.nl_family = AF_NETLINK;
Ratan Gupta16f12882017-09-22 18:26:11 +0530114 addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530115
116 if (bind(smartSock(), (struct sockaddr*)&addr, sizeof(addr)) < 0)
117 {
118 r = -errno;
119 goto finish;
120 }
121
122 r = sd_event_add_io(eventPtr.get(), nullptr,
123 smartSock(), EPOLLIN, eventHandler, nullptr);
124 if (r < 0)
125 {
126 goto finish;
127 }
128
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530129finish:
130
131 if (r < 0)
132 {
Gunnar Millsd75f0492017-10-25 20:33:32 -0500133 log<level::ERR>("Failure Occurred in starting of server:",
Gunnar Millsfc7df192017-10-19 16:11:05 -0500134 entry("ERRNO=%d", errno));
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530135 elog<InternalFailure>();
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530136 }
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530137}
138
139
140} //rtnetlink
141} //network
142} //phosphor