1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef NETLINK_LISTENER_H 18 #define NETLINK_LISTENER_H 19 20 #include <functional> 21 #include <map> 22 #include <mutex> 23 #include <thread> 24 25 #include <netdutils/Netlink.h> 26 #include <netdutils/Slice.h> 27 #include <netdutils/StatusOr.h> 28 #include <netdutils/UniqueFd.h> 29 30 namespace android { 31 namespace net { 32 33 class NetlinkListenerInterface { 34 public: 35 using DispatchFn = std::function<void(const nlmsghdr& nlmsg, const netdutils::Slice msg)>; 36 37 virtual ~NetlinkListenerInterface() = default; 38 39 // Send message to the kernel using the underlying netlink socket 40 virtual netdutils::Status send(const netdutils::Slice msg) = 0; 41 42 // Deliver future messages with nlmsghdr.nlmsg_type == type to fn. 43 // 44 // Threadsafe. 45 // All dispatch functions invoked on a single service thread. 46 // subscribe() and join() must not be called from the stack of fn(). 47 virtual netdutils::Status subscribe(uint16_t type, const DispatchFn& fn) = 0; 48 49 // Halt delivery of future messages with nlmsghdr.nlmsg_type == type. 50 // Threadsafe. 51 virtual netdutils::Status unsubscribe(uint16_t type) = 0; 52 }; 53 54 // NetlinkListener manages a netlink socket and associated blocking 55 // service thread. 56 // 57 // This class is written in a generic way to allow multiple different 58 // netlink subsystems to share this common infrastructure. If multiple 59 // subsystems share the same message delivery requirements (drops ok, 60 // no drops) they may share a single listener by calling subscribe() 61 // with multiple types. 62 // 63 // This class is suitable for moderate performance message 64 // processing. In particular it avoids extra copies of received 65 // message data and allows client code to control which message 66 // attributes are processed. 67 // 68 // Note that NetlinkListener is capable of processing multiple batched 69 // netlink messages in a single system call. This is useful to 70 // netfilter extensions that allow batching of events like NFLOG. 71 class NetlinkListener : public NetlinkListenerInterface { 72 public: 73 NetlinkListener(netdutils::UniqueFd event, netdutils::UniqueFd sock); 74 75 ~NetlinkListener() override; 76 77 netdutils::Status send(const netdutils::Slice msg) override; 78 79 netdutils::Status subscribe(uint16_t type, const DispatchFn& fn) override; 80 81 netdutils::Status unsubscribe(uint16_t type) override; 82 83 private: 84 netdutils::Status run(); 85 86 netdutils::UniqueFd mEvent; 87 netdutils::UniqueFd mSock; 88 std::mutex mMutex; 89 std::map<uint16_t, DispatchFn> mDispatchMap; // guarded by mMutex 90 std::thread mWorker; 91 }; 92 93 } // namespace net 94 } // namespace android 95 96 #endif /* NETLINK_LISTENER_H */ 97