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_NEWLINK: 31 case RTM_DELLINK: 32 case RTM_NEWADDR: 33 case RTM_DELADDR: 34 case RTM_NEWROUTE: 35 case RTM_DELROUTE: 36 return true; 37 case RTM_NEWNEIGH: 38 case RTM_DELNEIGH: 39 { 40 if (data.size() < sizeof(ndmsg)) 41 { 42 return false; 43 } 44 const auto& ndm = *reinterpret_cast<const ndmsg*>(data.data()); 45 // We only want to refresh for static neighbors 46 return ndm.ndm_state & NUD_PERMANENT; 47 } 48 } 49 return false; 50 } 51 52 static void handler(const nlmsghdr& hdr, std::string_view data) 53 { 54 if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled()) 55 { 56 refreshObjectTimer->restartOnce(refreshTimeout); 57 } 58 } 59 60 static void eventHandler(sdeventplus::source::IO&, int fd, uint32_t) 61 { 62 while (receive(fd, handler) > 0) 63 ; 64 } 65 66 static stdplus::ManagedFd makeSock() 67 { 68 using namespace stdplus::fd; 69 70 auto sock = socket(SocketDomain::Netlink, SocketType::Raw, 71 static_cast<stdplus::fd::SocketProto>(NETLINK_ROUTE)); 72 73 sock.fcntlSetfl(sock.fcntlGetfl().set(FileFlag::NonBlock)); 74 75 sockaddr_nl local{}; 76 local.nl_family = AF_NETLINK; 77 local.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | 78 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_NEIGH; 79 bind(sock, local); 80 81 return sock; 82 } 83 84 Server::Server(sdeventplus::Event& event) : 85 sock(makeSock()), io(event, sock.get(), EPOLLIN | EPOLLET, eventHandler) 86 { 87 } 88 89 } // namespace netlink 90 } // namespace network 91 } // namespace phosphor 92