diff options
Diffstat (limited to 'common/netd/libnetdutils/NetlinkListener.cpp')
-rw-r--r-- | common/netd/libnetdutils/NetlinkListener.cpp | 152 |
1 files changed, 0 insertions, 152 deletions
diff --git a/common/netd/libnetdutils/NetlinkListener.cpp b/common/netd/libnetdutils/NetlinkListener.cpp deleted file mode 100644 index decaa9c8..00000000 --- a/common/netd/libnetdutils/NetlinkListener.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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. - */ - -#define LOG_TAG "NetlinkListener" - -#include <sstream> -#include <vector> - -#include <linux/netfilter/nfnetlink.h> - -#include <log/log.h> -#include <netdutils/Misc.h> -#include <netdutils/NetlinkListener.h> -#include <netdutils/Syscalls.h> - -namespace android { -namespace netdutils { - -using netdutils::Fd; -using netdutils::Slice; -using netdutils::Status; -using netdutils::UniqueFd; -using netdutils::findWithDefault; -using netdutils::forEachNetlinkMessage; -using netdutils::makeSlice; -using netdutils::sSyscalls; -using netdutils::status::ok; -using netdutils::statusFromErrno; - -namespace { - -constexpr int kNetlinkMsgErrorType = (NFNL_SUBSYS_NONE << 8) | NLMSG_ERROR; - -constexpr sockaddr_nl kKernelAddr = { - .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = 0, -}; - -const NetlinkListener::DispatchFn kDefaultDispatchFn = [](const nlmsghdr& nlmsg, const Slice) { - std::stringstream ss; - ss << nlmsg; - ALOGE("unhandled netlink message: %s", ss.str().c_str()); -}; - -} // namespace - -NetlinkListener::NetlinkListener(UniqueFd event, UniqueFd sock, const std::string& name) - : mEvent(std::move(event)), mSock(std::move(sock)), mThreadName(name) { - const auto rxErrorHandler = [](const nlmsghdr& nlmsg, const Slice msg) { - std::stringstream ss; - ss << nlmsg << " " << msg << " " << netdutils::toHex(msg, 32); - ALOGE("unhandled netlink message: %s", ss.str().c_str()); - }; - expectOk(NetlinkListener::subscribe(kNetlinkMsgErrorType, rxErrorHandler)); - - mErrorHandler = [& name = mThreadName](const int fd, const int err) { - ALOGE("Error on NetlinkListener(%s) fd=%d: %s", name.c_str(), fd, strerror(err)); - }; - - // Start the thread - mWorker = std::thread([this]() { run().ignoreError(); }); -} - -NetlinkListener::~NetlinkListener() { - const auto& sys = sSyscalls.get(); - const uint64_t data = 1; - // eventfd should never enter an error state unexpectedly - expectOk(sys.write(mEvent, makeSlice(data)).status()); - mWorker.join(); -} - -Status NetlinkListener::send(const Slice msg) { - const auto& sys = sSyscalls.get(); - ASSIGN_OR_RETURN(auto sent, sys.sendto(mSock, msg, 0, kKernelAddr)); - if (sent != msg.size()) { - return statusFromErrno(EMSGSIZE, "unexpect message size"); - } - return ok; -} - -Status NetlinkListener::subscribe(uint16_t type, const DispatchFn& fn) { - std::lock_guard guard(mMutex); - mDispatchMap[type] = fn; - return ok; -} - -Status NetlinkListener::unsubscribe(uint16_t type) { - std::lock_guard guard(mMutex); - mDispatchMap.erase(type); - return ok; -} - -void NetlinkListener::registerSkErrorHandler(const SkErrorHandler& handler) { - mErrorHandler = handler; -} - -Status NetlinkListener::run() { - std::vector<char> rxbuf(4096); - - const auto rxHandler = [this](const nlmsghdr& nlmsg, const Slice& buf) { - std::lock_guard guard(mMutex); - const auto& fn = findWithDefault(mDispatchMap, nlmsg.nlmsg_type, kDefaultDispatchFn); - fn(nlmsg, buf); - }; - - if (mThreadName.length() > 0) { - int ret = pthread_setname_np(pthread_self(), mThreadName.c_str()); - if (ret) { - ALOGE("thread name set failed, name: %s, ret: %s", mThreadName.c_str(), strerror(ret)); - } - } - const auto& sys = sSyscalls.get(); - const std::array<Fd, 2> fds{{{mEvent}, {mSock}}}; - const int events = POLLIN; - const double timeout = 3600; - while (true) { - ASSIGN_OR_RETURN(auto revents, sys.ppoll(fds, events, timeout)); - // After mEvent becomes readable, we should stop servicing mSock and return - if (revents[0] & POLLIN) { - break; - } - if (revents[1] & (POLLIN|POLLERR)) { - auto rx = sys.recvfrom(mSock, makeSlice(rxbuf), 0); - int err = rx.status().code(); - if (err) { - // Ignore errors. The only error we expect to see here is ENOBUFS, and there's - // nothing we can do about that. The recvfrom above will already have cleared the - // error indication and ensured we won't get EPOLLERR again. - // TODO: Consider using NETLINK_NO_ENOBUFS. - mErrorHandler(((Fd) mSock).get(), err); - continue; - } - forEachNetlinkMessage(rx.value(), rxHandler); - } - } - return ok; -} - -} // namespace netdutils -} // namespace android |