1 #include "rtnetlink_server.hpp" 2 3 #include "netlink.hpp" 4 #include "network_manager.hpp" 5 #include "rtnetlink.hpp" 6 7 #include <linux/netlink.h> 8 #include <linux/rtnetlink.h> 9 10 #include <memory> 11 #include <phosphor-logging/log.hpp> 12 #include <stdplus/fd/create.hpp> 13 #include <stdplus/fd/ops.hpp> 14 #include <string_view> 15 16 namespace phosphor 17 { 18 namespace network 19 { 20 21 extern std::unique_ptr<Timer> refreshObjectTimer; 22 23 namespace netlink 24 { 25 26 using phosphor::logging::entry; 27 using phosphor::logging::level; 28 using phosphor::logging::log; 29 30 inline void rthandler(std::string_view data, auto&& cb) 31 { 32 auto ret = gatewayFromRtm(data); 33 if (!ret) 34 { 35 return; 36 } 37 cb(std::get<unsigned>(*ret), std::get<InAddrAny>(*ret)); 38 } 39 40 static void handler(Manager& m, const nlmsghdr& hdr, std::string_view data) 41 { 42 try 43 { 44 switch (hdr.nlmsg_type) 45 { 46 case RTM_NEWLINK: 47 m.addInterface(intfFromRtm(data)); 48 break; 49 case RTM_DELLINK: 50 m.removeInterface(intfFromRtm(data)); 51 break; 52 case RTM_NEWROUTE: 53 rthandler(data, [&](auto ifidx, auto addr) { 54 m.addDefGw(ifidx, addr); 55 }); 56 break; 57 case RTM_DELROUTE: 58 rthandler(data, [&](auto ifidx, auto addr) { 59 m.removeDefGw(ifidx, addr); 60 }); 61 break; 62 case RTM_NEWADDR: 63 m.addAddress(addrFromRtm(data)); 64 break; 65 case RTM_DELADDR: 66 m.removeAddress(addrFromRtm(data)); 67 break; 68 case RTM_NEWNEIGH: 69 m.addNeighbor(neighFromRtm(data)); 70 break; 71 case RTM_DELNEIGH: 72 m.removeNeighbor(neighFromRtm(data)); 73 break; 74 } 75 } 76 catch (const std::exception& e) 77 { 78 auto msg = fmt::format("Failed handling netlink event: {}", e.what()); 79 log<level::ERR>(msg.c_str(), entry("ERROR=%s", e.what())); 80 } 81 } 82 83 static void eventHandler(Manager& m, sdeventplus::source::IO&, int fd, uint32_t) 84 { 85 auto cb = [&](auto&&... args) { 86 return handler(m, std::forward<decltype(args)>(args)...); 87 }; 88 while (receive(fd, cb) > 0) 89 ; 90 } 91 92 static stdplus::ManagedFd makeSock() 93 { 94 using namespace stdplus::fd; 95 96 auto sock = socket(SocketDomain::Netlink, SocketType::Raw, 97 static_cast<stdplus::fd::SocketProto>(NETLINK_ROUTE)); 98 99 sock.fcntlSetfl(sock.fcntlGetfl().set(FileFlag::NonBlock)); 100 101 sockaddr_nl local{}; 102 local.nl_family = AF_NETLINK; 103 local.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | 104 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH; 105 bind(sock, local); 106 107 return sock; 108 } 109 110 Server::Server(sdeventplus::Event& event, Manager& manager) : 111 sock(makeSock()), 112 io(event, sock.get(), EPOLLIN | EPOLLET, [&](auto&&... args) { 113 return eventHandler(manager, std::forward<decltype(args)>(args)...); 114 }) 115 { 116 } 117 118 } // namespace netlink 119 } // namespace network 120 } // namespace phosphor 121