/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef NETLINK_LISTENER_H #define NETLINK_LISTENER_H #include #include #include #include #include #include #include #include #include namespace android { namespace netdutils { class NetlinkListenerInterface { public: using DispatchFn = std::function; using SkErrorHandler = std::function; virtual ~NetlinkListenerInterface() = default; // Send message to the kernel using the underlying netlink socket virtual netdutils::Status send(const netdutils::Slice msg) = 0; // Deliver future messages with nlmsghdr.nlmsg_type == type to fn. // // Threadsafe. // All dispatch functions invoked on a single service thread. // subscribe() and join() must not be called from the stack of fn(). virtual netdutils::Status subscribe(uint16_t type, const DispatchFn& fn) = 0; // Halt delivery of future messages with nlmsghdr.nlmsg_type == type. // Threadsafe. virtual netdutils::Status unsubscribe(uint16_t type) = 0; virtual void registerSkErrorHandler(const SkErrorHandler& handler) = 0; }; // NetlinkListener manages a netlink socket and associated blocking // service thread. // // This class is written in a generic way to allow multiple different // netlink subsystems to share this common infrastructure. If multiple // subsystems share the same message delivery requirements (drops ok, // no drops) they may share a single listener by calling subscribe() // with multiple types. // // This class is suitable for moderate performance message // processing. In particular it avoids extra copies of received // message data and allows client code to control which message // attributes are processed. // // Note that NetlinkListener is capable of processing multiple batched // netlink messages in a single system call. This is useful to // netfilter extensions that allow batching of events like NFLOG. class NetlinkListener : public NetlinkListenerInterface { public: NetlinkListener(netdutils::UniqueFd event, netdutils::UniqueFd sock, const std::string& name); ~NetlinkListener() override; netdutils::Status send(const netdutils::Slice msg) override; netdutils::Status subscribe(uint16_t type, const DispatchFn& fn) override EXCLUDES(mMutex); netdutils::Status unsubscribe(uint16_t type) override EXCLUDES(mMutex); void registerSkErrorHandler(const SkErrorHandler& handler) override; private: netdutils::Status run(); const netdutils::UniqueFd mEvent; const netdutils::UniqueFd mSock; const std::string mThreadName; std::mutex mMutex; std::map mDispatchMap GUARDED_BY(mMutex); std::thread mWorker; SkErrorHandler mErrorHandler; }; } // namespace netdutils } // namespace android #endif /* NETLINK_LISTENER_H */