1 /*
2  * Copyright 2019, 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 "local_connection.h"
18 
19 #include "hwsim.h"
20 #include "log.h"
21 #include "macaddress.h"
22 #include "netlink_message.h"
23 
24 #include <net/ethernet.h>
25 #include <netlink/netlink.h>
26 #include <netlink/genl/ctrl.h>
27 #include <netlink/genl/genl.h>
28 
29 #include <utils/CallStack.h>
30 
31 #include <inttypes.h>
32 #include <stdlib.h>
33 
34 static const char kHwSimFamilyName[] = "MAC80211_HWSIM";
35 static const int kHwSimVersion = 1;
36 static const unsigned int kDefaultSignalStrength = -50;
37 static const int kDefaultSocketBufferSize = 8 * (1 << 20);
38 
getSeqNum(struct nl_msg * msg)39 static uint32_t getSeqNum(struct nl_msg* msg) {
40     return nlmsg_hdr(msg)->nlmsg_seq;
41 }
42 
onSent(struct nl_msg *,void *)43 static int onSent(struct nl_msg* , void*) {
44     return NL_OK;
45 }
46 
onSeqCheck(struct nl_msg * msg,void *)47 static int onSeqCheck(struct nl_msg* msg, void*) {
48     uint32_t seq = getSeqNum(msg);
49     return seq == 0 ? NL_SKIP : NL_OK;
50 }
51 
LocalConnection(OnFrameCallback onFrameCallback,OnAckCallback onAckCallback,OnErrorCallback onErrorCallback)52 LocalConnection::LocalConnection(OnFrameCallback onFrameCallback,
53                                  OnAckCallback onAckCallback,
54                                  OnErrorCallback onErrorCallback)
55     : mOnFrameCallback(onFrameCallback)
56     , mOnAckCallback(onAckCallback)
57     , mOnErrorCallback(onErrorCallback) {
58 
59 }
60 
init(std::chrono::steady_clock::time_point now)61 Result LocalConnection::init(std::chrono::steady_clock::time_point now) {
62     Result res = mNetlinkSocket.init();
63     if (!res) { return res; }
64     res = mNetlinkSocket.setOnMsgInCallback(staticOnMessage, this);
65     if (!res) { return res; }
66     res = mNetlinkSocket.setOnMsgOutCallback(onSent, this);
67     if (!res) { return res; }
68     res = mNetlinkSocket.setOnSeqCheckCallback(onSeqCheck, this);
69     if (!res) { return res; }
70     res = mNetlinkSocket.setOnAckCallback(staticOnAck, this);
71     if (!res) { return res; }
72     res = mNetlinkSocket.setOnErrorCallback(staticOnError, this);
73     if (!res) { return res; }
74     res = mNetlinkSocket.connectGeneric();
75     if (!res) { return res; }
76     res = mNetlinkSocket.setBufferSizes(kDefaultSocketBufferSize,
77                                         kDefaultSocketBufferSize);
78     if (!res) { return res; }
79 
80     mNetlinkFamily = mNetlinkSocket.resolveNetlinkFamily(kHwSimFamilyName);
81     if (mNetlinkFamily < 0) {
82         return Result::error("Failed to resolve netlink family name: %s",
83                              nl_geterror(mNetlinkFamily));
84     }
85 
86     mPendingFrames.setCurrentTime(now);
87     mSequenceNumberCookies.setCurrentTime(now);
88 
89     mLastCacheTimeUpdate = now;
90     mLastCacheExpiration = now;
91 
92     return registerReceiver();
93 }
94 
getFd() const95 int LocalConnection::getFd() const {
96     return mNetlinkSocket.getFd();
97 }
98 
receive()99 bool LocalConnection::receive() {
100     return mNetlinkSocket.receive();
101 }
102 
transferFrame(std::unique_ptr<Frame> frame,const MacAddress & dest)103 uint32_t LocalConnection::transferFrame(std::unique_ptr<Frame> frame,
104                                         const MacAddress& dest) {
105     NetlinkMessage msg;
106 
107     if (!msg.initGeneric(mNetlinkFamily, HWSIM_CMD_FRAME, kHwSimVersion)) {
108         ALOGE("LocalConnection transferFrame failed to init msg");
109         return 0;
110     }
111 
112     frame->incrementAttempts();
113 
114     if (!msg.addAttribute(HWSIM_ATTR_ADDR_RECEIVER, dest.addr, ETH_ALEN) ||
115         !msg.addAttribute(HWSIM_ATTR_FRAME, frame->data(), frame->size()) ||
116         !msg.addAttribute(HWSIM_ATTR_RX_RATE, 1u) ||
117         !msg.addAttribute(HWSIM_ATTR_SIGNAL, kDefaultSignalStrength) ||
118         !msg.addAttribute(HWSIM_ATTR_FREQ, frame->channel())) {
119 
120         ALOGE("LocalConnection transferFrame failed to set attrs");
121         return 0;
122     }
123 
124     if (!mNetlinkSocket.send(msg)) {
125         return 0;
126     }
127 
128     // Store the radio destination for potential retransmissions.
129     frame->setRadioDestination(dest);
130 
131     uint32_t seqNum = msg.getSeqNum();
132     uint64_t cookie = frame->cookie();
133     FrameId id(cookie, frame->transmitter());
134     mSequenceNumberCookies[seqNum] = id;
135     mPendingFrames[id] = std::move(frame);
136 
137     return seqNum;
138 }
139 
cloneFrame(const Frame & frame,const MacAddress & dest)140 uint32_t LocalConnection::cloneFrame(const Frame& frame,
141                                      const MacAddress& dest) {
142     auto copy = std::make_unique<Frame>(frame.data(),
143                                         frame.size(),
144                                         frame.transmitter(),
145                                         frame.cookie(),
146                                         frame.flags(),
147                                         frame.channel(),
148                                         frame.rates().data(),
149                                         frame.rates().size());
150     return transferFrame(std::move(copy), dest);
151 }
152 
ackFrame(FrameInfo & info,bool success)153 bool LocalConnection::ackFrame(FrameInfo& info, bool success) {
154     NetlinkMessage msg;
155 
156     if (!msg.initGeneric(mNetlinkFamily,
157                          HWSIM_CMD_TX_INFO_FRAME,
158                          kHwSimVersion)) {
159         ALOGE("LocalConnection ackFrame failed to create msg");
160         return false;
161     }
162 
163     uint32_t flags = info.flags();
164     if (success) {
165         flags |= HWSIM_TX_STAT_ACK;
166     }
167 
168     const uint8_t* transmitter = info.transmitter().addr;
169     const Rates& rates = info.rates();
170     if (!msg.addAttribute(HWSIM_ATTR_ADDR_TRANSMITTER, transmitter, ETH_ALEN) ||
171         !msg.addAttribute(HWSIM_ATTR_TX_INFO, rates.data(), rates.size()) ||
172         !msg.addAttribute(HWSIM_ATTR_FLAGS, flags) ||
173         !msg.addAttribute(HWSIM_ATTR_SIGNAL, kDefaultSignalStrength) ||
174         !msg.addAttribute(HWSIM_ATTR_COOKIE, info.cookie())) {
175 
176         ALOGE("LocalConnection ackFrame failed to set attributes");
177         return false;
178     }
179 
180     if (!mNetlinkSocket.send(msg)) {
181         return false;
182     }
183     mPendingFrames.erase(FrameId(info.cookie(), info.transmitter()));
184     return true;
185 }
186 
getTimeout() const187 std::chrono::steady_clock::time_point LocalConnection::getTimeout() const {
188     if (mRetryQueue.empty()) {
189         return std::chrono::steady_clock::time_point::max();
190     }
191     return mRetryQueue.top().first;
192 }
193 
onTimeout(std::chrono::steady_clock::time_point now)194 void LocalConnection::onTimeout(std::chrono::steady_clock::time_point now) {
195 
196     if (now - mLastCacheTimeUpdate > std::chrono::seconds(1)) {
197         // Only update the time once per second, there's no need for a super
198         // high resolution here. We just want to make sure these caches don't
199         // fill up over a long period of time.
200         mPendingFrames.setCurrentTime(now);
201         mSequenceNumberCookies.setCurrentTime(now);
202         mLastCacheTimeUpdate = now;
203     }
204     if (now - mLastCacheExpiration > std::chrono::seconds(10)) {
205         // Only expire entries every 10 seconds, this is an operation that has
206         // some cost to it and doesn't have to happen very often.
207         mPendingFrames.expireEntries();
208         mSequenceNumberCookies.expireEntries();
209         mLastCacheExpiration = now;
210     }
211 
212     while (!mRetryQueue.empty() && now >= mRetryQueue.top().first) {
213         FrameId id = mRetryQueue.top().second;
214         auto frameIt = mPendingFrames.find(id);
215         if (frameIt != mPendingFrames.end()) {
216             // Frame is still available, retry it
217             std::unique_ptr<Frame> frame = std::move(frameIt->second);
218             mPendingFrames.erase(frameIt);
219             MacAddress dest = frame->radioDestination();
220             transferFrame(std::move(frame), dest);
221         }
222         mRetryQueue.pop();
223     }
224 }
225 
registerReceiver()226 Result LocalConnection::registerReceiver() {
227     NetlinkMessage msg;
228 
229     if (!msg.initGeneric(mNetlinkFamily, HWSIM_CMD_REGISTER, kHwSimVersion)) {
230         return Result::error("Failed to create register receiver message");
231     }
232 
233     if (!mNetlinkSocket.send(msg)) {
234         return Result::error("Failed to send register receiver message");
235     }
236     return Result::success();
237 }
238 
staticOnMessage(struct nl_msg * msg,void * context)239 int LocalConnection::staticOnMessage(struct nl_msg* msg, void* context) {
240     if (!context) {
241         return NL_SKIP;
242     }
243     auto connection = static_cast<LocalConnection*>(context);
244     return connection->onMessage(msg);
245 }
246 
staticOnAck(struct nl_msg * msg,void * context)247 int LocalConnection::staticOnAck(struct nl_msg* msg, void* context) {
248     if (!context) {
249         return NL_SKIP;
250     }
251     auto connection = static_cast<LocalConnection*>(context);
252     return connection->onAck(msg);
253 }
254 
staticOnError(struct sockaddr_nl * addr,struct nlmsgerr * error,void * context)255 int LocalConnection::staticOnError(struct sockaddr_nl* addr,
256                                    struct nlmsgerr* error,
257                                    void* context) {
258     if (!context) {
259         return NL_SKIP;
260     }
261     auto connection = static_cast<LocalConnection*>(context);
262     return connection->onError(addr, error);
263 }
264 
onMessage(struct nl_msg * msg)265 int LocalConnection::onMessage(struct nl_msg* msg) {
266     struct nlmsghdr* hdr = nlmsg_hdr(msg);
267     auto generic = reinterpret_cast<const struct genlmsghdr*>(nlmsg_data(hdr));
268 
269     switch (generic->cmd) {
270         case HWSIM_CMD_FRAME:
271             return onFrame(msg);
272     }
273     return NL_OK;
274 }
275 
onFrame(struct nl_msg * msg)276 int LocalConnection::onFrame(struct nl_msg* msg) {
277 
278     struct nlmsghdr* hdr = nlmsg_hdr(msg);
279     std::unique_ptr<Frame> frame = parseFrame(hdr);
280     if (!frame) {
281         return NL_SKIP;
282     }
283 
284     mOnFrameCallback(std::move(frame));
285     return NL_OK;
286 }
287 
parseFrame(struct nlmsghdr * hdr)288 std::unique_ptr<Frame> LocalConnection::parseFrame(struct nlmsghdr* hdr) {
289     struct nlattr* attrs[HWSIM_ATTR_MAX + 1];
290     genlmsg_parse(hdr, 0, attrs, HWSIM_ATTR_MAX, nullptr);
291     if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER]) {
292         ALOGE("Received cmd frame without transmitter address");
293         return nullptr;
294     }
295     if (!attrs[HWSIM_ATTR_TX_INFO]) {
296         ALOGE("Received cmd frame without tx rates");
297         return nullptr;
298     }
299     if (!attrs[HWSIM_ATTR_FREQ]) {
300         ALOGE("Recieved cmd frame without channel frequency");
301         return nullptr;
302     }
303 
304     uint64_t cookie = nla_get_u64(attrs[HWSIM_ATTR_COOKIE]);
305 
306     const auto& source = *reinterpret_cast<const MacAddress*>(
307         nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]));
308 
309     auto rates = reinterpret_cast<const hwsim_tx_rate*>(
310         nla_data(attrs[HWSIM_ATTR_TX_INFO]));
311     int rateLength = nla_len(attrs[HWSIM_ATTR_TX_INFO]);
312     // Make sure the length is valid, must be multiple of hwsim_tx_rate
313     if (rateLength <= 0 || (rateLength % sizeof(hwsim_tx_rate)) != 0) {
314         ALOGE("Invalid tx rate length %d", rateLength);
315     }
316     size_t numRates = static_cast<size_t>(rateLength) / sizeof(hwsim_tx_rate);
317 
318     int length = nla_len(attrs[HWSIM_ATTR_FRAME]);
319     auto data = reinterpret_cast<uint8_t*>(nla_data(attrs[HWSIM_ATTR_FRAME]));
320 
321     uint32_t flags = nla_get_u32(attrs[HWSIM_ATTR_FLAGS]);
322 
323     uint32_t channel = nla_get_u32(attrs[HWSIM_ATTR_FREQ]);
324 
325     return std::make_unique<Frame>(data, length, source, cookie,
326                                    flags, channel, rates, numRates);
327 }
328 
onAck(struct nl_msg * msg)329 int LocalConnection::onAck(struct nl_msg* msg) {
330     struct nlmsghdr* hdr = nlmsg_hdr(msg);
331     uint32_t seqNum = hdr->nlmsg_seq;
332     auto cookie = mSequenceNumberCookies.find(seqNum);
333     if (cookie == mSequenceNumberCookies.end()) {
334         // This is not a frame we sent. This is fairly common for libnl's
335         // internal use so don't log this.
336         return NL_SKIP;
337     }
338     auto pendingFrame = mPendingFrames.find(cookie->second);
339     // We don't need to keep this around anymore, erase it.
340     mSequenceNumberCookies.erase(seqNum);
341     if (pendingFrame == mPendingFrames.end()) {
342         // We have no cookie associated with this sequence number. This might
343         // happen if the remote connection already acked the frame and removed
344         // the frame info. Consider this resolved.
345         return NL_SKIP;
346     }
347 
348     Frame* frame = pendingFrame->second.get();
349     mOnAckCallback(frame->info());
350     // Make sure to erase using the cookie instead of the iterator. The callback
351     // might have already erased this entry so the iterator could be invalid at
352     // this point. Instead of a fancy scheme of checking this just play it safe
353     // to allow the callback more freedom.
354     mPendingFrames.erase(cookie->second);
355 
356     return NL_OK;
357 }
358 
onError(struct sockaddr_nl *,struct nlmsgerr * error)359 int LocalConnection::onError(struct sockaddr_nl*, struct nlmsgerr* error) {
360     struct nlmsghdr* hdr = &error->msg;
361     uint32_t seqNum = hdr->nlmsg_seq;
362 
363     auto idIt = mSequenceNumberCookies.find(seqNum);
364     if (idIt == mSequenceNumberCookies.end()) {
365         return NL_SKIP;
366     }
367     FrameId id = idIt->second;
368     // No need to keep the sequence number around anymore, it's expired and is
369     // no longer useful.
370     mSequenceNumberCookies.erase(idIt);
371 
372     auto frameIt = mPendingFrames.find(id);
373     if (frameIt == mPendingFrames.end()) {
374         return NL_SKIP;
375     }
376     Frame* frame = frameIt->second.get();
377 
378     if (!frame->hasRemainingAttempts()) {
379         // This frame has used up all its attempts, there's nothing we can do
380         mOnErrorCallback(frame->info());
381         mPendingFrames.erase(id);
382         return NL_SKIP;
383     }
384     // Store the frame in the retry queue
385     uint64_t timeout = frame->calcNextTimeout();
386     auto deadline = std::chrono::steady_clock::now() +
387                     std::chrono::microseconds(timeout);
388     mRetryQueue.emplace(deadline, id);
389 
390     return NL_SKIP;
391 }
392 
393