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 #define LOG_TAG "NetlinkListener" 18 19 #include <sstream> 20 #include <vector> 21 22 #include <linux/netfilter/nfnetlink.h> 23 24 #include <cutils/log.h> 25 #include <netdutils/Misc.h> 26 #include <netdutils/Syscalls.h> 27 28 #include "NetlinkListener.h" 29 30 namespace android { 31 namespace net { 32 33 using netdutils::Fd; 34 using netdutils::Slice; 35 using netdutils::Status; 36 using netdutils::UniqueFd; 37 using netdutils::findWithDefault; 38 using netdutils::forEachNetlinkMessage; 39 using netdutils::makeSlice; 40 using netdutils::sSyscalls; 41 using netdutils::status::ok; 42 using netdutils::statusFromErrno; 43 44 namespace { 45 46 constexpr int kNetlinkMsgErrorType = (NFNL_SUBSYS_NONE << 8) | NLMSG_ERROR; 47 48 constexpr sockaddr_nl kKernelAddr = { 49 .nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = 0, .nl_groups = 0, 50 }; 51 52 const NetlinkListener::DispatchFn kDefaultDispatchFn = [](const nlmsghdr& nlmsg, const Slice) { 53 std::stringstream ss; 54 ss << nlmsg; 55 ALOGE("unhandled netlink message: %s", ss.str().c_str()); 56 }; 57 58 } // namespace 59 60 NetlinkListener::NetlinkListener(UniqueFd event, UniqueFd sock) 61 : mEvent(std::move(event)), mSock(std::move(sock)), mWorker([this]() { run(); }) { 62 const auto rxErrorHandler = [](const nlmsghdr& nlmsg, const Slice msg) { 63 std::stringstream ss; 64 ss << nlmsg << " " << msg << " " << netdutils::toHex(msg, 32); 65 ALOGE("unhandled netlink message: %s", ss.str().c_str()); 66 }; 67 expectOk(NetlinkListener::subscribe(kNetlinkMsgErrorType, rxErrorHandler)); 68 } 69 70 NetlinkListener::~NetlinkListener() { 71 const auto& sys = sSyscalls.get(); 72 const uint64_t data = 1; 73 // eventfd should never enter an error state unexpectedly 74 expectOk(sys.write(mEvent, makeSlice(data)).status()); 75 mWorker.join(); 76 } 77 78 Status NetlinkListener::send(const Slice msg) { 79 const auto& sys = sSyscalls.get(); 80 ASSIGN_OR_RETURN(auto sent, sys.sendto(mSock, msg, 0, kKernelAddr)); 81 if (sent != msg.size()) { 82 return statusFromErrno(EMSGSIZE, "unexpect message size"); 83 } 84 return ok; 85 } 86 87 Status NetlinkListener::subscribe(uint16_t type, const DispatchFn& fn) { 88 std::lock_guard<std::mutex> guard(mMutex); 89 mDispatchMap[type] = fn; 90 return ok; 91 } 92 93 Status NetlinkListener::unsubscribe(uint16_t type) { 94 std::lock_guard<std::mutex> guard(mMutex); 95 mDispatchMap.erase(type); 96 return ok; 97 } 98 99 Status NetlinkListener::run() { 100 std::vector<char> rxbuf(4096); 101 102 const auto rxHandler = [this](const nlmsghdr& nlmsg, const Slice& buf) { 103 std::lock_guard<std::mutex> guard(mMutex); 104 const auto& fn = findWithDefault(mDispatchMap, nlmsg.nlmsg_type, kDefaultDispatchFn); 105 fn(nlmsg, buf); 106 }; 107 108 const auto& sys = sSyscalls.get(); 109 const std::array<Fd, 2> fds{{{mEvent}, {mSock}}}; 110 const int events = POLLIN | POLLRDHUP | POLLERR | POLLHUP; 111 const double timeout = 3600; 112 while (true) { 113 ASSIGN_OR_RETURN(auto revents, sys.ppoll(fds, events, timeout)); 114 // After mEvent becomes readable, we should stop servicing mSock and return 115 if (revents[0] & POLLIN) { 116 break; 117 } 118 if (revents[1] & POLLIN) { 119 auto rx = sys.recvfrom(mSock, makeSlice(rxbuf), 0); 120 if (rx.status().code() == ENOBUFS) { 121 // Ignore ENOBUFS - the socket is still usable 122 // TODO: Users other than NFLOG may need to know about this 123 continue; 124 } 125 forEachNetlinkMessage(rx.value(), rxHandler); 126 } 127 } 128 return ok; 129 } 130 131 } // namespace net 132 } // namespace android 133