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 <android-base/thread_annotations.h> 26 #include <netdutils/Netlink.h> 27 #include <netdutils/Slice.h> 28 #include <netdutils/Status.h> 29 #include <netdutils/UniqueFd.h> 30 31 namespace android { 32 namespace net { 33 34 class NetlinkListenerInterface { 35 public: 36 using DispatchFn = std::function<void(const nlmsghdr& nlmsg, const netdutils::Slice msg)>; 37 38 using SkErrorHandler = std::function<void(const int fd, const int err)>; 39 40 virtual ~NetlinkListenerInterface() = default; 41 42 // Send message to the kernel using the underlying netlink socket 43 virtual netdutils::Status send(const netdutils::Slice msg) = 0; 44 45 // Deliver future messages with nlmsghdr.nlmsg_type == type to fn. 46 // 47 // Threadsafe. 48 // All dispatch functions invoked on a single service thread. 49 // subscribe() and join() must not be called from the stack of fn(). 50 virtual netdutils::Status subscribe(uint16_t type, const DispatchFn& fn) = 0; 51 52 // Halt delivery of future messages with nlmsghdr.nlmsg_type == type. 53 // Threadsafe. 54 virtual netdutils::Status unsubscribe(uint16_t type) = 0; 55 56 virtual void registerSkErrorHandler(const SkErrorHandler& handler) = 0; 57 }; 58 59 // NetlinkListener manages a netlink socket and associated blocking 60 // service thread. 61 // 62 // This class is written in a generic way to allow multiple different 63 // netlink subsystems to share this common infrastructure. If multiple 64 // subsystems share the same message delivery requirements (drops ok, 65 // no drops) they may share a single listener by calling subscribe() 66 // with multiple types. 67 // 68 // This class is suitable for moderate performance message 69 // processing. In particular it avoids extra copies of received 70 // message data and allows client code to control which message 71 // attributes are processed. 72 // 73 // Note that NetlinkListener is capable of processing multiple batched 74 // netlink messages in a single system call. This is useful to 75 // netfilter extensions that allow batching of events like NFLOG. 76 class NetlinkListener : public NetlinkListenerInterface { 77 public: 78 NetlinkListener(netdutils::UniqueFd event, netdutils::UniqueFd sock, const std::string& name); 79 80 ~NetlinkListener() override; 81 82 netdutils::Status send(const netdutils::Slice msg) override; 83 84 netdutils::Status subscribe(uint16_t type, const DispatchFn& fn) override EXCLUDES(mMutex); 85 86 netdutils::Status unsubscribe(uint16_t type) override EXCLUDES(mMutex); 87 88 void registerSkErrorHandler(const SkErrorHandler& handler) override; 89 90 private: 91 netdutils::Status run(); 92 93 const netdutils::UniqueFd mEvent; 94 const netdutils::UniqueFd mSock; 95 const std::string mThreadName; 96 std::mutex mMutex; 97 std::map<uint16_t, DispatchFn> mDispatchMap GUARDED_BY(mMutex); 98 std::thread mWorker; 99 SkErrorHandler mErrorHandler; 100 }; 101 102 } // namespace net 103 } // namespace android 104 105 #endif /* NETLINK_LISTENER_H */ 106