blob: c0e5ad55ddc1288bfe1f571c8c5bac427ff7cb21 [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
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +053068Server::Server(EventPtr& eventPtr)
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 {};
74
75 int fd = -1;
76 phosphor::Descriptor smartSock(fd);
77
78 int r {};
79
80 sigset_t ss {};
81
82
83 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
84 sigaddset(&ss, SIGINT) < 0)
85 {
86 r = -errno;
87 goto finish;
88 }
89 /* Block SIGTERM first, so that the event loop can handle it */
90 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
91 {
92 r = -errno;
93 goto finish;
94 }
95
96 /* Let's make use of the default handler and "floating"
97 reference features of sd_event_add_signal() */
98
99 r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
100 if (r < 0)
101 {
102 goto finish;
103 }
104
105 r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
106 if (r < 0)
107 {
108 goto finish;
109 }
110
111 fd = socket(PF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE);
112 if (fd < 0)
113 {
114 r = -errno;
115 goto finish;
116 }
117
118 smartSock.set(fd);
119 fd = -1;
120
121 memset(&addr, 0, sizeof(addr));
122 addr.nl_family = AF_NETLINK;
Ratan Gupta16f12882017-09-22 18:26:11 +0530123 addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530124
125 if (bind(smartSock(), (struct sockaddr*)&addr, sizeof(addr)) < 0)
126 {
127 r = -errno;
128 goto finish;
129 }
130
131 r = sd_event_add_io(eventPtr.get(), nullptr,
132 smartSock(), EPOLLIN, eventHandler, nullptr);
133 if (r < 0)
134 {
135 goto finish;
136 }
137
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530138finish:
139
140 if (r < 0)
141 {
142 log<level::ERR>("Failure Occured in starting of server:",
143 entry("errno = %d", errno));
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530144 elog<InternalFailure>();
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530145 }
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530146}
147
148
149} //rtnetlink
150} //network
151} //phosphor