blob: 4a211d5f589ec6dc7f2177d12c9b540c1d2a4241 [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
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05307#include <linux/netlink.h>
8#include <linux/rtnetlink.h>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05309
Jagpal Singh Gill49f9d252023-04-17 15:15:39 -070010#include <phosphor-logging/lg2.hpp>
William A. Kennington III32eef712022-01-24 17:03:03 -080011#include <stdplus/fd/create.hpp>
12#include <stdplus/fd/ops.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053013
William A. Kennington III5b179382022-11-15 15:23:26 -080014namespace phosphor::network::netlink
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053015{
16
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080017inline void rthandler(std::string_view data, auto&& cb)
William A. Kennington III71590bf2022-10-31 14:14:16 -070018{
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080019 auto ret = gatewayFromRtm(data);
William A. Kennington III71590bf2022-10-31 14:14:16 -070020 if (!ret)
21 {
22 return;
23 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -070024 cb(std::get<unsigned>(*ret), std::get<stdplus::InAnyAddr>(*ret));
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -080025}
26
William A. Kennington III0d763822023-02-27 16:37:31 -080027static unsigned getIfIdx(const nlmsghdr& hdr, std::string_view data)
28{
29 switch (hdr.nlmsg_type)
30 {
31 case RTM_NEWLINK:
32 case RTM_DELLINK:
33 return extractRtData<ifinfomsg>(data).ifi_index;
34 case RTM_NEWADDR:
35 case RTM_DELADDR:
36 return extractRtData<ifaddrmsg>(data).ifa_index;
37 case RTM_NEWNEIGH:
38 case RTM_DELNEIGH:
39 return extractRtData<ndmsg>(data).ndm_ifindex;
40 }
41 throw std::runtime_error("Unknown nlmsg_type");
42}
43
William A. Kennington III71590bf2022-10-31 14:14:16 -070044static void handler(Manager& m, const nlmsghdr& hdr, std::string_view data)
William A. Kennington III5f165dc2022-10-24 15:58:55 -070045{
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080046 try
William A. Kennington III71590bf2022-10-31 14:14:16 -070047 {
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080048 switch (hdr.nlmsg_type)
49 {
William A. Kennington IIIef2b28e2022-11-13 18:33:10 -080050 case RTM_NEWLINK:
51 m.addInterface(intfFromRtm(data));
52 break;
53 case RTM_DELLINK:
54 m.removeInterface(intfFromRtm(data));
55 break;
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080056 case RTM_NEWROUTE:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080057 rthandler(data, [&](auto ifidx, auto addr) {
58 m.addDefGw(ifidx, addr);
59 });
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080060 break;
61 case RTM_DELROUTE:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080062 rthandler(data, [&](auto ifidx, auto addr) {
63 m.removeDefGw(ifidx, addr);
64 });
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080065 break;
66 case RTM_NEWADDR:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080067 m.addAddress(addrFromRtm(data));
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080068 break;
69 case RTM_DELADDR:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080070 m.removeAddress(addrFromRtm(data));
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080071 break;
72 case RTM_NEWNEIGH:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080073 m.addNeighbor(neighFromRtm(data));
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080074 break;
75 case RTM_DELNEIGH:
William A. Kennington IIIed5ff472022-11-12 16:24:02 -080076 m.removeNeighbor(neighFromRtm(data));
William A. Kennington IIIc0fdaaf2022-11-07 16:44:56 -080077 break;
78 }
79 }
80 catch (const std::exception& e)
81 {
William A. Kennington III0d763822023-02-27 16:37:31 -080082 try
83 {
84 if (m.ignoredIntf.contains(getIfIdx(hdr, data)))
85 {
86 // We don't want to log errors for ignored interfaces
87 return;
88 }
89 }
90 catch (...)
91 {}
Jagpal Singh Gill49f9d252023-04-17 15:15:39 -070092 lg2::error("Failed handling netlink event: {ERROR}", "ERROR", e);
William A. Kennington III71590bf2022-10-31 14:14:16 -070093 }
William A. Kennington III5f165dc2022-10-24 15:58:55 -070094}
95
William A. Kennington III71590bf2022-10-31 14:14:16 -070096static void eventHandler(Manager& m, sdeventplus::source::IO&, int fd, uint32_t)
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053097{
William A. Kennington III71590bf2022-10-31 14:14:16 -070098 auto cb = [&](auto&&... args) {
99 return handler(m, std::forward<decltype(args)>(args)...);
100 };
101 while (receive(fd, cb) > 0)
William A. Kennington III29418ef2022-11-07 22:59:47 -0800102 ;
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530103}
104
William A. Kennington III32eef712022-01-24 17:03:03 -0800105static stdplus::ManagedFd makeSock()
106{
107 using namespace stdplus::fd;
108
109 auto sock = socket(SocketDomain::Netlink, SocketType::Raw,
110 static_cast<stdplus::fd::SocketProto>(NETLINK_ROUTE));
111
112 sock.fcntlSetfl(sock.fcntlGetfl().set(FileFlag::NonBlock));
113
114 sockaddr_nl local{};
115 local.nl_family = AF_NETLINK;
William A. Kennington III226cada2022-10-28 16:33:11 -0700116 local.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
William A. Kennington III32eef712022-01-24 17:03:03 -0800117 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH;
118 bind(sock, local);
119
120 return sock;
121}
122
William A. Kennington III71590bf2022-10-31 14:14:16 -0700123Server::Server(sdeventplus::Event& event, Manager& manager) :
124 sock(makeSock()),
125 io(event, sock.get(), EPOLLIN | EPOLLET, [&](auto&&... args) {
126 return eventHandler(manager, std::forward<decltype(args)>(args)...);
127 })
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530128{
William A. Kennington IIIe1b50d52022-11-14 17:14:04 -0800129 auto cb = [&](const nlmsghdr& hdr, std::string_view data) {
130 handler(manager, hdr, data);
131 };
132 performRequest(NETLINK_ROUTE, RTM_GETLINK, NLM_F_DUMP, ifinfomsg{}, cb);
133 performRequest(NETLINK_ROUTE, RTM_GETADDR, NLM_F_DUMP, ifaddrmsg{}, cb);
134 performRequest(NETLINK_ROUTE, RTM_GETROUTE, NLM_F_DUMP, rtmsg{}, cb);
135 performRequest(NETLINK_ROUTE, RTM_GETNEIGH, NLM_F_DUMP, ndmsg{}, cb);
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530136}
137
William A. Kennington III5b179382022-11-15 15:23:26 -0800138} // namespace phosphor::network::netlink