blob: d3cac197a7a9a547292135c8287246ad49bd73ee [file] [log] [blame]
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05301#include "xyz/openbmc_project/Common/error.hpp"
2#include "rtnetlink_server.hpp"
3#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>
16#include <phosphor-logging/elog-errors.hpp>
17
18#include <memory>
19#include <iostream>
20
21namespace phosphor
22{
23namespace network
24{
25namespace rtnetlink
26{
27
28/* Call Back for the sd event loop */
29static int eventHandler(sd_event_source* es, int fd, uint32_t revents,
30 void* userdata)
31{
32 char buffer[phosphor::network::rtnetlink::BUFSIZE] {};
33 int len {};
34
35 auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer);
36 while ((len = recv(fd, netLinkHeader,
37 phosphor::network::rtnetlink::BUFSIZE, 0)) > 0)
38 {
39 for (; (NLMSG_OK(netLinkHeader, len)) &&
40 (netLinkHeader->nlmsg_type != NLMSG_DONE);
41 netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
42 {
43 if (netLinkHeader->nlmsg_type == RTM_NEWADDR ||
44 netLinkHeader->nlmsg_type == RTM_DELADDR)
45 {
46 // TODO delete the below trace in later commit.
47 std::cout << "Address Changed\n";
48
49 } // end if
50
51 } // end for
52
53 } // end while
54
55 return 0;
56}
57
58
59int Server::run()
60{
61 using namespace phosphor::logging;
62
63 struct sockaddr_nl addr {};
64
65 int fd = -1;
66 phosphor::Descriptor smartSock(fd);
67
68 int r {};
69
70 sigset_t ss {};
71
72
73 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
74 sigaddset(&ss, SIGINT) < 0)
75 {
76 r = -errno;
77 goto finish;
78 }
79 /* Block SIGTERM first, so that the event loop can handle it */
80 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
81 {
82 r = -errno;
83 goto finish;
84 }
85
86 /* Let's make use of the default handler and "floating"
87 reference features of sd_event_add_signal() */
88
89 r = sd_event_add_signal(eventPtr.get(), NULL, SIGTERM, NULL, NULL);
90 if (r < 0)
91 {
92 goto finish;
93 }
94
95 r = sd_event_add_signal(eventPtr.get(), NULL, SIGINT, NULL, NULL);
96 if (r < 0)
97 {
98 goto finish;
99 }
100
101 fd = socket(PF_NETLINK, SOCK_RAW | SOCK_NONBLOCK, NETLINK_ROUTE);
102 if (fd < 0)
103 {
104 r = -errno;
105 goto finish;
106 }
107
108 smartSock.set(fd);
109 fd = -1;
110
111 memset(&addr, 0, sizeof(addr));
112 addr.nl_family = AF_NETLINK;
113 addr.nl_groups = RTMGRP_IPV4_IFADDR;
114
115 if (bind(smartSock(), (struct sockaddr*)&addr, sizeof(addr)) < 0)
116 {
117 r = -errno;
118 goto finish;
119 }
120
121 r = sd_event_add_io(eventPtr.get(), nullptr,
122 smartSock(), EPOLLIN, eventHandler, nullptr);
123 if (r < 0)
124 {
125 goto finish;
126 }
127
128 r = sd_event_loop(eventPtr.get());
129
130finish:
131
132 if (r < 0)
133 {
134 log<level::ERR>("Failure Occured in starting of server:",
135 entry("errno = %d", errno));
136 }
137
138 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
139}
140
141
142} //rtnetlink
143} //network
144} //phosphor