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 "interface.h"
18 
19 #include "log.h"
20 #include "netlink.h"
21 #include "netlinkmessage.h"
22 
23 #include <linux/rtnetlink.h>
24 
25 #include <algorithm>
26 #include <future>
27 
28 static const int kApfRamSize = 4096;
29 
30 // Provide some arbitrary firmware and driver versions for now
31 static const char kFirmwareVersion[] = "1.0";
32 static const char kDriverVersion[] = "1.0";
33 
34 // A list of supported channels in the 2.4 GHz band, values in MHz
35 static const wifi_channel k2p4Channels[] = {
36     2412,
37     2417,
38     2422,
39     2427,
40     2432,
41     2437,
42     2442,
43     2447,
44     2452,
45     2457,
46     2462,
47     2467,
48     2472,
49     2484
50 };
51 
52 template<typename T, size_t N>
arraySize(const T (&)[N])53 constexpr size_t arraySize(const T (&)[N]) {
54     return N;
55 }
56 
Interface(Netlink & netlink,const char * name)57 Interface::Interface(Netlink& netlink, const char* name)
58     : mNetlink(netlink)
59     , mName(name)
60     , mInterfaceIndex(0)
61     , mApfMemory(kApfRamSize) {
62 }
63 
Interface(Interface && other)64 Interface::Interface(Interface&& other) noexcept
65     : mNetlink(other.mNetlink)
66     , mName(std::move(other.mName))
67     , mInterfaceIndex(other.mInterfaceIndex)
68     , mApfMemory(std::move(other.mApfMemory)) {
69 }
70 
init()71 bool Interface::init() {
72     mInterfaceIndex = if_nametoindex(mName.c_str());
73     if (mInterfaceIndex == 0) {
74         ALOGE("Unable to get interface index for %s", mName.c_str());
75         return false;
76     }
77     return true;
78 }
79 
getSupportedFeatureSet(feature_set * set)80 wifi_error Interface::getSupportedFeatureSet(feature_set* set) {
81     if (set == nullptr) {
82         return WIFI_ERROR_INVALID_ARGS;
83     }
84     *set = 0;
85     return WIFI_SUCCESS;
86 }
87 
getName(char * name,size_t size)88 wifi_error Interface::getName(char* name, size_t size) {
89     if (size < mName.size() + 1) {
90         return WIFI_ERROR_INVALID_ARGS;
91     }
92     strlcpy(name, mName.c_str(), size);
93     return WIFI_SUCCESS;
94 }
95 
96 // Wifi legacy HAL implicitly assumes getLinkStats is blocking and
97 // handler will be set to nullptr immediately after invocation.
98 // Therefore, this function will wait until onLinkStatsReply is called.
getLinkStats(wifi_request_id requestId,wifi_stats_result_handler handler)99 wifi_error Interface::getLinkStats(wifi_request_id requestId,
100                                    wifi_stats_result_handler handler) {
101     NetlinkMessage message(RTM_GETLINK, mNetlink.getSequenceNumber());
102 
103     ifinfomsg* info = message.payload<ifinfomsg>();
104     info->ifi_family = AF_UNSPEC;
105     info->ifi_type = 1;
106     info->ifi_index = mInterfaceIndex;
107     info->ifi_flags = 0;
108     info->ifi_change = 0xFFFFFFFF;
109 
110     std::promise<void> p;
111 
112     auto callback = [this, requestId, &handler,
113         &p] (const NetlinkMessage& message) {
114         onLinkStatsReply(requestId, handler, message);
115         p.set_value();
116     };
117 
118     bool success = mNetlink.sendMessage(message, callback);
119     // Only wait when callback will be invoked. Therefore, test if the message
120     // is sent successfully first.
121     if (success) {
122         p.get_future().wait();
123     }
124     return success ? WIFI_SUCCESS : WIFI_ERROR_UNKNOWN;
125 }
126 
setLinkStats(wifi_link_layer_params)127 wifi_error Interface::setLinkStats(wifi_link_layer_params /*params*/) {
128     return WIFI_SUCCESS;
129 }
130 
setAlertHandler(wifi_request_id,wifi_alert_handler)131 wifi_error Interface::setAlertHandler(wifi_request_id /*id*/,
132                                          wifi_alert_handler /*handler*/) {
133     return WIFI_SUCCESS;
134 }
135 
resetAlertHandler(wifi_request_id)136 wifi_error Interface::resetAlertHandler(wifi_request_id /*id*/) {
137     return WIFI_SUCCESS;
138 }
139 
getFirmwareVersion(char * buffer,size_t size)140 wifi_error Interface::getFirmwareVersion(char* buffer, size_t size) {
141     if (size < sizeof(kFirmwareVersion)) {
142         return WIFI_ERROR_INVALID_ARGS;
143     }
144     strcpy(buffer, kFirmwareVersion);
145     return WIFI_SUCCESS;
146 }
147 
getDriverVersion(char * buffer,size_t size)148 wifi_error Interface::getDriverVersion(char* buffer, size_t size) {
149     if (size < sizeof(kDriverVersion)) {
150         return WIFI_ERROR_INVALID_ARGS;
151     }
152     strcpy(buffer, kDriverVersion);
153     return WIFI_SUCCESS;
154 }
155 
setScanningMacOui(oui)156 wifi_error Interface::setScanningMacOui(oui /*scan_oui*/) {
157     return WIFI_SUCCESS;
158 }
159 
clearLinkStats(u32,u32 * responseMask,u8,u8 * response)160 wifi_error Interface::clearLinkStats(u32 /*requestMask*/,
161                                      u32* responseMask,
162                                      u8 /*request*/,
163                                      u8* response) {
164     if (responseMask == nullptr || response == nullptr) {
165         return WIFI_ERROR_INVALID_ARGS;
166     }
167     return WIFI_SUCCESS;
168 }
169 
getValidChannels(int band,int maxChannels,wifi_channel * channels,int * numChannels)170 wifi_error Interface::getValidChannels(int band,
171                                        int maxChannels,
172                                        wifi_channel* channels,
173                                        int* numChannels) {
174     if (channels == nullptr || numChannels == nullptr || maxChannels < 0) {
175         return WIFI_ERROR_INVALID_ARGS;
176     }
177     switch (band) {
178         case WIFI_BAND_BG: // 2.4 GHz
179             *numChannels = std::min<int>(maxChannels,
180                                          arraySize(k2p4Channels));
181             memcpy(channels, k2p4Channels, *numChannels);
182 
183             return WIFI_SUCCESS;
184         default:
185             return WIFI_ERROR_NOT_SUPPORTED;
186     }
187 }
188 
startLogging(u32,u32,u32,u32,char *)189 wifi_error Interface::startLogging(u32 /*verboseLevel*/,
190                                    u32 /*flags*/,
191                                    u32 /*maxIntervalSec*/,
192                                    u32 /*minDataSize*/,
193                                    char* /*ringName*/) {
194     return WIFI_SUCCESS;
195 }
196 
setCountryCode(const char *)197 wifi_error Interface::setCountryCode(const char* /*countryCode*/) {
198     return WIFI_SUCCESS;
199 }
200 
setLogHandler(wifi_request_id,wifi_ring_buffer_data_handler)201 wifi_error Interface::setLogHandler(wifi_request_id /*id*/,
202                                     wifi_ring_buffer_data_handler /*handler*/) {
203     return WIFI_SUCCESS;
204 }
205 
getRingBuffersStatus(u32 * numRings,wifi_ring_buffer_status * status)206 wifi_error Interface::getRingBuffersStatus(u32* numRings,
207                                            wifi_ring_buffer_status* status) {
208     if (numRings == nullptr || status == nullptr || *numRings == 0) {
209         return WIFI_ERROR_INVALID_ARGS;
210     }
211 
212     memset(status, 0, sizeof(*status));
213     strlcpy(reinterpret_cast<char*>(status->name),
214             "ring0",
215             sizeof(status->name));
216     *numRings = 1;
217     return WIFI_SUCCESS;
218 }
219 
getLoggerSupportedFeatureSet(unsigned int * support)220 wifi_error Interface::getLoggerSupportedFeatureSet(unsigned int* support) {
221     if (support == nullptr) {
222         return WIFI_ERROR_INVALID_ARGS;
223     }
224     *support = 0;
225     return WIFI_SUCCESS;
226 }
227 
getRingData(char *)228 wifi_error Interface::getRingData(char* /*ringName*/) {
229     return WIFI_SUCCESS;
230 }
231 
configureNdOffload(u8)232 wifi_error Interface::configureNdOffload(u8 /*enable*/) {
233     return WIFI_SUCCESS;
234 }
235 
startPacketFateMonitoring()236 wifi_error Interface::startPacketFateMonitoring() {
237     return WIFI_SUCCESS;
238 }
239 
getTxPacketFates(wifi_tx_report *,size_t,size_t * numProvidedFates)240 wifi_error Interface::getTxPacketFates(wifi_tx_report* /*txReportBuffers*/,
241                                        size_t /*numRequestedFates*/,
242                                        size_t* numProvidedFates) {
243     if (numProvidedFates == nullptr) {
244         return WIFI_ERROR_INVALID_ARGS;
245     }
246     *numProvidedFates = 0;
247     return WIFI_SUCCESS;
248 }
249 
getRxPacketFates(wifi_rx_report *,size_t,size_t * numProvidedFates)250 wifi_error Interface::getRxPacketFates(wifi_rx_report* /*rxReportBuffers*/,
251                                        size_t /*numRequestedFates*/,
252                                        size_t* numProvidedFates) {
253     if (numProvidedFates == nullptr) {
254         return WIFI_ERROR_INVALID_ARGS;
255     }
256     *numProvidedFates = 0;
257     return WIFI_SUCCESS;
258 }
259 
getPacketFilterCapabilities(u32 * version,u32 * maxLength)260 wifi_error Interface::getPacketFilterCapabilities(u32* version,
261                                                   u32* maxLength) {
262     if (version == nullptr || maxLength == nullptr) {
263         return WIFI_ERROR_INVALID_ARGS;
264     }
265     *version = 4;
266     *maxLength = kApfRamSize;
267     return WIFI_SUCCESS;
268 }
269 
readPacketFilter(u32 src_offset,u8 * host_dst,u32 length)270 wifi_error Interface::readPacketFilter(u32 src_offset, u8 *host_dst, u32 length) {
271     if (src_offset >= mApfMemory.size() || host_dst == nullptr
272         || length > mApfMemory.size() - src_offset) {
273         return WIFI_ERROR_INVALID_ARGS;
274     }
275     std::copy(mApfMemory.begin() + src_offset, mApfMemory.begin() + src_offset + length, host_dst);
276     return WIFI_SUCCESS;
277 }
278 
setPacketFilter(const u8 * program,u32 len)279 wifi_error Interface::setPacketFilter(const u8 *program, u32 len) {
280     if (program == nullptr || len > mApfMemory.size()) {
281         return WIFI_ERROR_INVALID_ARGS;
282     }
283     std::copy(program, program + len, mApfMemory.begin());
284     return WIFI_SUCCESS;
285 }
286 
287 wifi_error
getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT * wakeReasonCount)288 Interface::getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT* wakeReasonCount) {
289     if (wakeReasonCount == nullptr) {
290         return WIFI_ERROR_INVALID_ARGS;
291     }
292     return WIFI_SUCCESS;
293 }
294 
startSendingOffloadedPacket(wifi_request_id,u16,u8 *,u16,u8 *,u8 *,u32)295 wifi_error Interface::startSendingOffloadedPacket(wifi_request_id /*id*/,
296                                                   u16 /*ether_type*/,
297                                                   u8 * /*ip_packet*/,
298                                                   u16 /*ip_packet_len*/,
299                                                   u8 * /*src_mac_addr*/,
300                                                   u8 * /*dst_mac_addr*/,
301                                                   u32 /*period_msec*/) {
302     // Drop the packet and pretend everything is fine. Currentlty this is only
303     // used for keepalive packets to allow the CPU to go to sleep and let the
304     // hardware send keepalive packets on its own. By dropping this we lose the
305     // keepalive packets but networking will still be fine.
306     return WIFI_SUCCESS;
307 }
308 
stopSendingOffloadedPacket(wifi_request_id)309 wifi_error Interface::stopSendingOffloadedPacket(wifi_request_id /*id*/) {
310     return WIFI_SUCCESS;
311 }
312 
onLinkStatsReply(wifi_request_id requestId,wifi_stats_result_handler handler,const NetlinkMessage & message)313 void Interface::onLinkStatsReply(wifi_request_id requestId,
314                                  wifi_stats_result_handler handler,
315                                  const NetlinkMessage& message) {
316     if (message.size() < sizeof(nlmsghdr) + sizeof(ifinfomsg)) {
317         ALOGE("Invalid link stats response, too small");
318         return;
319     }
320     if (message.type() != RTM_NEWLINK) {
321         ALOGE("Recieved invalid link stats reply type: %u",
322               static_cast<unsigned int>(message.type()));
323         return;
324     }
325 
326     int numRadios = 1;
327     wifi_radio_stat radioStats;
328     memset(&radioStats, 0, sizeof(radioStats));
329 
330     wifi_iface_stat ifStats;
331     memset(&ifStats, 0, sizeof(ifStats));
332     ifStats.iface = reinterpret_cast<wifi_interface_handle>(this);
333 
334     rtnl_link_stats64 netlinkStats64;
335     rtnl_link_stats netlinkStats;
336     if (message.getAttribute(IFLA_STATS64, &netlinkStats64)) {
337         ifStats.ac[WIFI_AC_BE].tx_mpdu = netlinkStats64.tx_packets;
338         ifStats.ac[WIFI_AC_BE].rx_mpdu = netlinkStats64.rx_packets;
339     } else if (message.getAttribute(IFLA_STATS, &netlinkStats)) {
340         ifStats.ac[WIFI_AC_BE].tx_mpdu = netlinkStats.tx_packets;
341         ifStats.ac[WIFI_AC_BE].rx_mpdu = netlinkStats.rx_packets;
342     } else {
343         return;
344     }
345 
346     handler.on_link_stats_results(requestId, &ifStats, numRadios, &radioStats);
347 }
348