1 #include "rtnetlink_server.hpp" 2 3 #include "netlink.hpp" 4 #include "types.hpp" 5 6 #include <linux/netlink.h> 7 #include <linux/rtnetlink.h> 8 #include <netinet/in.h> 9 10 #include <memory> 11 #include <stdplus/fd/create.hpp> 12 #include <stdplus/fd/ops.hpp> 13 #include <string_view> 14 15 namespace phosphor 16 { 17 namespace network 18 { 19 20 extern std::unique_ptr<Timer> refreshObjectTimer; 21 22 namespace netlink 23 { 24 25 static bool shouldRefresh(const struct nlmsghdr& hdr, 26 std::string_view data) noexcept 27 { 28 switch (hdr.nlmsg_type) 29 { 30 case RTM_NEWADDR: 31 case RTM_DELADDR: 32 case RTM_NEWROUTE: 33 case RTM_DELROUTE: 34 return true; 35 case RTM_NEWNEIGH: 36 case RTM_DELNEIGH: 37 { 38 if (data.size() < sizeof(ndmsg)) 39 { 40 return false; 41 } 42 const auto& ndm = *reinterpret_cast<const ndmsg*>(data.data()); 43 // We only want to refresh for static neighbors 44 return ndm.ndm_state & NUD_PERMANENT; 45 } 46 } 47 return false; 48 } 49 50 static void handler(const nlmsghdr& hdr, std::string_view data) 51 { 52 if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled()) 53 { 54 refreshObjectTimer->restartOnce(refreshTimeout); 55 } 56 } 57 58 static void eventHandler(sdeventplus::source::IO&, int fd, uint32_t) 59 { 60 while (receive(fd, handler) > 0) 61 ; 62 } 63 64 static stdplus::ManagedFd makeSock() 65 { 66 using namespace stdplus::fd; 67 68 auto sock = socket(SocketDomain::Netlink, SocketType::Raw, 69 static_cast<stdplus::fd::SocketProto>(NETLINK_ROUTE)); 70 71 sock.fcntlSetfl(sock.fcntlGetfl().set(FileFlag::NonBlock)); 72 73 sockaddr_nl local{}; 74 local.nl_family = AF_NETLINK; 75 local.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | 76 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH; 77 bind(sock, local); 78 79 return sock; 80 } 81 82 Server::Server(sdeventplus::Event& event) : 83 sock(makeSock()), io(event, sock.get(), EPOLLIN | EPOLLET, eventHandler) 84 { 85 } 86 87 } // namespace netlink 88 } // namespace network 89 } // namespace phosphor 90