blob: 2f2a1522c70c1ba4ef3f656acfb2f9f4a9263a08 [file] [log] [blame]
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05301#include "rtnetlink_server.hpp"
Patrick Venture189d44e2018-07-09 12:30:59 -07002
William A. Kennington III5f165dc2022-10-24 15:58:55 -07003#include "netlink.hpp"
William A. Kennington III71590bf2022-10-31 14:14:16 -07004#include "network_manager.hpp"
5#include "rtnetlink.hpp"
William A. Kennington III217bb3f2022-09-29 13:43:13 -07006#include "types.hpp"
7
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05308#include <linux/netlink.h>
9#include <linux/rtnetlink.h>
Patrick Venture189d44e2018-07-09 12:30:59 -070010#include <netinet/in.h>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053011
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053012#include <memory>
William A. Kennington III71590bf2022-10-31 14:14:16 -070013#include <phosphor-logging/log.hpp>
William A. Kennington III32eef712022-01-24 17:03:03 -080014#include <stdplus/fd/create.hpp>
15#include <stdplus/fd/ops.hpp>
William A. Kennington III08505792019-01-30 16:00:04 -080016#include <string_view>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053017
18namespace phosphor
19{
20namespace network
21{
Ratan Guptaa54d8f82017-09-08 17:05:46 +053022
William A. Kennington III3a70fa22018-09-20 18:48:20 -070023extern std::unique_ptr<Timer> refreshObjectTimer;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053024
William A. Kennington III5f165dc2022-10-24 15:58:55 -070025namespace netlink
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053026{
27
William A. Kennington III71590bf2022-10-31 14:14:16 -070028using phosphor::logging::entry;
29using phosphor::logging::level;
30using phosphor::logging::log;
31
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -080032static bool shouldRefresh(const struct nlmsghdr& hdr, std::string_view) noexcept
William A. Kennington IIId2d05942019-01-30 16:04:11 -080033{
34 switch (hdr.nlmsg_type)
35 {
William A. Kennington III226cada2022-10-28 16:33:11 -070036 case RTM_NEWLINK:
37 case RTM_DELLINK:
William A. Kennington IIId2d05942019-01-30 16:04:11 -080038 return true;
William A. Kennington IIId2d05942019-01-30 16:04:11 -080039 }
William A. Kennington IIId2d05942019-01-30 16:04:11 -080040 return false;
41}
42
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080043inline void rthandler(std::string_view data, auto&& cb)
William A. Kennington III71590bf2022-10-31 14:14:16 -070044{
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080045 auto ret = gatewayFromRtm(data);
William A. Kennington III71590bf2022-10-31 14:14:16 -070046 if (!ret)
47 {
48 return;
49 }
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080050 cb(std::get<unsigned>(*ret), std::get<InAddrAny>(*ret));
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -080051}
52
William A. Kennington III71590bf2022-10-31 14:14:16 -070053static void handler(Manager& m, const nlmsghdr& hdr, std::string_view data)
William A. Kennington III5f165dc2022-10-24 15:58:55 -070054{
55 if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled())
56 {
57 refreshObjectTimer->restartOnce(refreshTimeout);
58 }
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080059 try
William A. Kennington III71590bf2022-10-31 14:14:16 -070060 {
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080061 switch (hdr.nlmsg_type)
62 {
63 case RTM_NEWROUTE:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080064 rthandler(data, [&](auto ifidx, auto addr) {
65 m.addDefGw(ifidx, addr);
66 });
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080067 break;
68 case RTM_DELROUTE:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080069 rthandler(data, [&](auto ifidx, auto addr) {
70 m.removeDefGw(ifidx, addr);
71 });
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080072 break;
73 case RTM_NEWADDR:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080074 m.addAddress(addrFromRtm(data));
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080075 break;
76 case RTM_DELADDR:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080077 m.removeAddress(addrFromRtm(data));
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080078 break;
79 case RTM_NEWNEIGH:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080080 m.addNeighbor(neighFromRtm(data));
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080081 break;
82 case RTM_DELNEIGH:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080083 m.removeNeighbor(neighFromRtm(data));
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080084 break;
85 }
86 }
87 catch (const std::exception& e)
88 {
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080089 auto msg = fmt::format("Failed handling netlink event: {}", e.what());
90 log<level::ERR>(msg.c_str(), entry("ERROR=%s", e.what()));
William A. Kennington III71590bf2022-10-31 14:14:16 -070091 }
William A. Kennington III5f165dc2022-10-24 15:58:55 -070092}
93
William A. Kennington III71590bf2022-10-31 14:14:16 -070094static void eventHandler(Manager& m, sdeventplus::source::IO&, int fd, uint32_t)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053095{
William A. Kennington III71590bf2022-10-31 14:14:16 -070096 auto cb = [&](auto&&... args) {
97 return handler(m, std::forward<decltype(args)>(args)...);
98 };
99 while (receive(fd, cb) > 0)
William A. Kennington III29418ef2022-11-07 22:59:47 -0800100 ;
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530101}
102
William A. Kennington III32eef712022-01-24 17:03:03 -0800103static stdplus::ManagedFd makeSock()
104{
105 using namespace stdplus::fd;
106
107 auto sock = socket(SocketDomain::Netlink, SocketType::Raw,
108 static_cast<stdplus::fd::SocketProto>(NETLINK_ROUTE));
109
110 sock.fcntlSetfl(sock.fcntlGetfl().set(FileFlag::NonBlock));
111
112 sockaddr_nl local{};
113 local.nl_family = AF_NETLINK;
William A. Kennington III226cada2022-10-28 16:33:11 -0700114 local.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
William A. Kennington III32eef712022-01-24 17:03:03 -0800115 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH;
116 bind(sock, local);
117
118 return sock;
119}
120
William A. Kennington III71590bf2022-10-31 14:14:16 -0700121Server::Server(sdeventplus::Event& event, Manager& manager) :
122 sock(makeSock()),
123 io(event, sock.get(), EPOLLIN | EPOLLET, [&](auto&&... args) {
124 return eventHandler(manager, std::forward<decltype(args)>(args)...);
125 })
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530126{
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530127}
128
William A. Kennington III5f165dc2022-10-24 15:58:55 -0700129} // namespace netlink
Gunnar Mills57d9c502018-09-14 14:42:34 -0500130} // namespace network
131} // namespace phosphor