Home | History | Annotate | Download | only in wifi_hal
      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 #include "netlink.h"
     18 
     19 #include "log.h"
     20 #include "netlinkmessage.h"
     21 
     22 #include <errno.h>
     23 #include <poll.h>
     24 #include <string.h>
     25 #include <linux/netlink.h>
     26 #include <sys/socket.h>
     27 #include <sys/types.h>
     28 #include <unistd.h>
     29 
     30 static const size_t kControlRead = 0;
     31 static const size_t kControlWrite = 1;
     32 
     33 static void closeIfOpen(int* fd) {
     34     if (*fd != -1) {
     35         ::close(*fd);
     36         *fd = -1;
     37     }
     38 }
     39 
     40 Netlink::Netlink()
     41     : mNextSequenceNumber(1)
     42     , mSocket(-1) {
     43     mControlPipe[kControlRead] = -1;
     44     mControlPipe[kControlWrite] = -1;
     45 }
     46 
     47 Netlink::~Netlink() {
     48     closeIfOpen(&mSocket);
     49     closeIfOpen(&mControlPipe[kControlRead]);
     50     closeIfOpen(&mControlPipe[kControlWrite]);
     51 }
     52 
     53 bool Netlink::init() {
     54     if (mSocket != -1) {
     55         ALOGE("Netlink already initialized");
     56         return false;
     57     }
     58 
     59     int status = ::pipe2(mControlPipe, O_CLOEXEC);
     60     if (status != 0) {
     61         ALOGE("Failed to create control pipe: %s", strerror(errno));
     62         return false;
     63     }
     64 
     65     mSocket = ::socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
     66     if (mSocket == -1) {
     67         ALOGE("Failed to create netlink socket: %s", strerror(errno));
     68         return false;
     69     }
     70 
     71     struct sockaddr_nl addr;
     72     memset(&addr, 0, sizeof(addr));
     73     addr.nl_family = AF_NETLINK;
     74     status = ::bind(mSocket,
     75                     reinterpret_cast<struct sockaddr*>(&addr),
     76                     sizeof(addr));
     77     if (status != 0) {
     78         ALOGE("Failed to bind netlink socket: %s", strerror(errno));
     79         return false;
     80     }
     81 
     82     return true;
     83 }
     84 
     85 void Netlink::stop(StopHandler handler) {
     86     char stop = 1;
     87     // Set the handler before writing so that it's guaranteed to be available
     88     // when the event loop reads from the control pipe.
     89     {
     90         // No need to keep the lock while writing so make it scoped
     91         std::unique_lock<std::mutex> lock(mStopHandlerMutex);
     92         mStopHandler = handler;
     93     }
     94     ::write(mControlPipe[kControlWrite], &stop, sizeof(stop));
     95 }
     96 
     97 bool Netlink::eventLoop() {
     98     struct pollfd fds[2];
     99     memset(fds, 0, sizeof(fds));
    100     fds[0].fd = mSocket;
    101     fds[0].events = POLLIN;
    102     fds[1].fd = mControlPipe[kControlRead];
    103     fds[1].events = POLLIN;
    104 
    105     for (;;) {
    106         int status = ::poll(fds, 2, -1);
    107         if (status == 0) {
    108             // Timeout, not really supposed to happen
    109             ALOGW("poll encountered a timeout despite infinite timeout");
    110             continue;
    111         } else if (status < 0) {
    112             if (errno == EINTR) {
    113                 continue;
    114             }
    115             ALOGE("poll encountered an error: %s", strerror(errno));
    116             return false;
    117         }
    118         for (auto& fd : fds) {
    119             if ((fd.revents & POLLIN) == 0) {
    120                 continue;
    121             }
    122             if (fd.fd == mSocket) {
    123                 readNetlinkMessage(fd.fd);
    124             } else if (fd.fd == mControlPipe[kControlRead]) {
    125                 if (readControlMessage()) {
    126                     // Make a copy of the stop handler while holding the lock
    127                     // and then call it after releasing the lock. This prevents
    128                     // the potential deadlock of someone calling stop from the
    129                     // stop callback. The drawback of this is that if someone
    130                     // calls stop again with a new stop handler that new stop
    131                     // handler might not be called if the timing is wrong.
    132                     // Both of these scenarios indicate highly questionable
    133                     // behavior on the callers part but at least this way the
    134                     // event loop will terminate which seems better than a
    135                     // total deadlock.
    136                     StopHandler handler;
    137                     {
    138                         std::unique_lock<std::mutex> lock(mStopHandlerMutex);
    139                         handler = mStopHandler;
    140                     }
    141                     if (handler) {
    142                         handler();
    143                     }
    144                     return true;
    145                 }
    146             }
    147         }
    148     }
    149 }
    150 
    151 uint32_t Netlink::getSequenceNumber() {
    152     return mNextSequenceNumber++;
    153 }
    154 
    155 bool Netlink::sendMessage(const NetlinkMessage& message,
    156                           ReplyHandler handler) {
    157     // Keep lock the entire time so that we can safely erase the handler
    158     // without worrying about another call to sendAsync adding a handler that
    159     // shouldn't be deleted.
    160     std::unique_lock<std::mutex> lock(mHandlersMutex);
    161     // Register handler before sending in case the read thread picks up the
    162     // response between the send thread sending and registering the handler.
    163     mHandlers[message.sequence()] = handler;
    164     for (;;) {
    165         int bytesSent = ::send(mSocket, message.data(), message.size(), 0);
    166         if (bytesSent > 0 && static_cast<size_t>(bytesSent) == message.size()) {
    167             return true;
    168         }
    169         if (bytesSent < 0 && errno == EINTR) {
    170             // We need to try again, keep the mutex locked
    171             continue;
    172         }
    173         // It's a failure, remove the handler and unlock the mutex
    174         mHandlers.erase(message.sequence());
    175         lock.unlock();
    176 
    177         if (bytesSent < 0) {
    178             ALOGE("Failed to send netlink message: %s", strerror(errno));
    179         }
    180         return false;
    181     }
    182 }
    183 
    184 bool Netlink::readNetlinkMessage(int fd) {
    185     char buffer[8 * 1024];
    186     for (;;) {
    187         int bytesReceived = ::recv(fd, buffer, sizeof(buffer), 0);
    188         if (bytesReceived < 0) {
    189             if (errno == EINTR) {
    190                 continue;
    191             }
    192             ALOGE("recv failed to receive on netlink socket: %s",
    193                   strerror(errno));
    194             return false;
    195         }
    196         char* data = buffer;
    197         char* end = data + bytesReceived;
    198         while (data < end) {
    199             if (data + sizeof(nlmsghdr) > end) {
    200                 ALOGE("received invalid netlink message, too small for header");
    201                 return false;
    202             }
    203             auto header = reinterpret_cast<nlmsghdr*>(data);
    204             if (data + header->nlmsg_len > end) {
    205                 ALOGE("received invalid netlink message, too small for data");
    206                 return false;
    207             }
    208 
    209             if (header->nlmsg_type == NLMSG_ERROR) {
    210                 if (data + NLMSG_HDRLEN + sizeof(nlmsgerr) <= end) {
    211                     auto err = reinterpret_cast<nlmsgerr*>(NLMSG_DATA(header));
    212                     ALOGE("Receive netlink error message: %s, sequence %u",
    213                           strerror(-err->error), header->nlmsg_seq);
    214                 } else {
    215                     ALOGE("Received netlink error code but no error message");
    216                 }
    217                 return false;
    218             }
    219 
    220             notifyHandler(data, header->nlmsg_len);
    221 
    222             data += header->nlmsg_len;
    223         }
    224         return true;
    225     }
    226 }
    227 
    228 bool Netlink::readControlMessage() {
    229     char buffer[32];
    230 
    231     for (;;) {
    232         int bytesReceived = ::recv(mControlPipe[kControlRead],
    233                                    buffer,
    234                                    sizeof(buffer),
    235                                    0);
    236         if (bytesReceived < 0) {
    237             if (errno == EINTR) {
    238                 continue;
    239             }
    240         } else if (bytesReceived == 0) {
    241             return false;
    242         }
    243         return true;
    244     }
    245 }
    246 
    247 
    248 void Netlink::notifyHandler(const char* data, size_t size) {
    249     NetlinkMessage message(data, size);
    250 
    251     ReplyHandler replyHandler;
    252     {
    253         std::unique_lock<std::mutex> lock(mHandlersMutex);
    254         auto handler = mHandlers.find(message.sequence());
    255         if (handler == mHandlers.end()) {
    256             // No handler found, ignore message
    257             return;
    258         }
    259         replyHandler = handler->second;
    260         mHandlers.erase(handler);
    261     }
    262 
    263     replyHandler(message);
    264 }
    265 
    266