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 // Provide some arbitrary firmware and driver versions for now
26 static const char kFirmwareVersion[] = "1.0";
27 static const char kDriverVersion[] = "1.0";
28 
29 // A list of supported channels in the 2.4 GHz band, values in MHz
30 static const wifi_channel k2p4Channels[] = {
31     2412,
32     2417,
33     2422,
34     2427,
35     2432,
36     2437,
37     2442,
38     2447,
39     2452,
40     2457,
41     2462,
42     2467,
43     2472,
44     2484
45 };
46 
47 template<typename T, size_t N>
arraySize(const T (&)[N])48 constexpr size_t arraySize(const T (&)[N]) {
49     return N;
50 }
51 
Interface(Netlink & netlink,const char * name)52 Interface::Interface(Netlink& netlink, const char* name)
53     : mNetlink(netlink)
54     , mName(name)
55     , mInterfaceIndex(0) {
56 }
57 
Interface(Interface && other)58 Interface::Interface(Interface&& other) noexcept
59     : mNetlink(other.mNetlink)
60     , mName(std::move(other.mName))
61     , mInterfaceIndex(other.mInterfaceIndex) {
62 }
63 
init()64 bool Interface::init() {
65     mInterfaceIndex = if_nametoindex(mName.c_str());
66     if (mInterfaceIndex == 0) {
67         ALOGE("Unable to get interface index for %s", mName.c_str());
68         return false;
69     }
70     return true;
71 }
72 
getSupportedFeatureSet(feature_set * set)73 wifi_error Interface::getSupportedFeatureSet(feature_set* set) {
74     if (set == nullptr) {
75         return WIFI_ERROR_INVALID_ARGS;
76     }
77     *set = 0;
78     return WIFI_SUCCESS;
79 }
80 
getName(char * name,size_t size)81 wifi_error Interface::getName(char* name, size_t size) {
82     if (size < mName.size() + 1) {
83         return WIFI_ERROR_INVALID_ARGS;
84     }
85     strlcpy(name, mName.c_str(), size);
86     return WIFI_SUCCESS;
87 }
88 
getLinkStats(wifi_request_id requestId,wifi_stats_result_handler handler)89 wifi_error Interface::getLinkStats(wifi_request_id requestId,
90                                    wifi_stats_result_handler handler) {
91     NetlinkMessage message(RTM_GETLINK, mNetlink.getSequenceNumber());
92 
93     ifinfomsg* info = message.payload<ifinfomsg>();
94     info->ifi_family = AF_UNSPEC;
95     info->ifi_type = 1;
96     info->ifi_index = mInterfaceIndex;
97     info->ifi_flags = 0;
98     info->ifi_change = 0xFFFFFFFF;
99 
100     bool success = mNetlink.sendMessage(message,
101                                         std::bind(&Interface::onLinkStatsReply,
102                                                   this,
103                                                   requestId,
104                                                   handler,
105                                                   std::placeholders::_1));
106     return success ? WIFI_SUCCESS : WIFI_ERROR_UNKNOWN;
107 }
108 
setLinkStats(wifi_link_layer_params)109 wifi_error Interface::setLinkStats(wifi_link_layer_params /*params*/) {
110     return WIFI_SUCCESS;
111 }
112 
setAlertHandler(wifi_request_id,wifi_alert_handler)113 wifi_error Interface::setAlertHandler(wifi_request_id /*id*/,
114                                          wifi_alert_handler /*handler*/) {
115     return WIFI_SUCCESS;
116 }
117 
resetAlertHandler(wifi_request_id)118 wifi_error Interface::resetAlertHandler(wifi_request_id /*id*/) {
119     return WIFI_SUCCESS;
120 }
121 
getFirmwareVersion(char * buffer,size_t size)122 wifi_error Interface::getFirmwareVersion(char* buffer, size_t size) {
123     if (size < sizeof(kFirmwareVersion)) {
124         return WIFI_ERROR_INVALID_ARGS;
125     }
126     strcpy(buffer, kFirmwareVersion);
127     return WIFI_SUCCESS;
128 }
129 
getDriverVersion(char * buffer,size_t size)130 wifi_error Interface::getDriverVersion(char* buffer, size_t size) {
131     if (size < sizeof(kDriverVersion)) {
132         return WIFI_ERROR_INVALID_ARGS;
133     }
134     strcpy(buffer, kDriverVersion);
135     return WIFI_SUCCESS;
136 }
137 
setScanningMacOui(oui)138 wifi_error Interface::setScanningMacOui(oui /*scan_oui*/) {
139     return WIFI_SUCCESS;
140 }
141 
clearLinkStats(u32,u32 * responseMask,u8,u8 * response)142 wifi_error Interface::clearLinkStats(u32 /*requestMask*/,
143                                      u32* responseMask,
144                                      u8 /*request*/,
145                                      u8* response) {
146     if (responseMask == nullptr || response == nullptr) {
147         return WIFI_ERROR_INVALID_ARGS;
148     }
149     return WIFI_SUCCESS;
150 }
151 
getValidChannels(int band,int maxChannels,wifi_channel * channels,int * numChannels)152 wifi_error Interface::getValidChannels(int band,
153                                        int maxChannels,
154                                        wifi_channel* channels,
155                                        int* numChannels) {
156     if (channels == nullptr || numChannels == nullptr || maxChannels < 0) {
157         return WIFI_ERROR_INVALID_ARGS;
158     }
159     switch (band) {
160         case WIFI_BAND_BG: // 2.4 GHz
161             *numChannels = std::min<int>(maxChannels,
162                                          arraySize(k2p4Channels));
163             memcpy(channels, k2p4Channels, *numChannels);
164 
165             return WIFI_SUCCESS;
166         default:
167             return WIFI_ERROR_NOT_SUPPORTED;
168     }
169 }
170 
startLogging(u32,u32,u32,u32,char *)171 wifi_error Interface::startLogging(u32 /*verboseLevel*/,
172                                    u32 /*flags*/,
173                                    u32 /*maxIntervalSec*/,
174                                    u32 /*minDataSize*/,
175                                    char* /*ringName*/) {
176     return WIFI_SUCCESS;
177 }
178 
setCountryCode(const char *)179 wifi_error Interface::setCountryCode(const char* /*countryCode*/) {
180     return WIFI_SUCCESS;
181 }
182 
setLogHandler(wifi_request_id,wifi_ring_buffer_data_handler)183 wifi_error Interface::setLogHandler(wifi_request_id /*id*/,
184                                     wifi_ring_buffer_data_handler /*handler*/) {
185     return WIFI_SUCCESS;
186 }
187 
getRingBuffersStatus(u32 * numRings,wifi_ring_buffer_status * status)188 wifi_error Interface::getRingBuffersStatus(u32* numRings,
189                                            wifi_ring_buffer_status* status) {
190     if (numRings == nullptr || status == nullptr || *numRings == 0) {
191         return WIFI_ERROR_INVALID_ARGS;
192     }
193 
194     memset(status, 0, sizeof(*status));
195     strlcpy(reinterpret_cast<char*>(status->name),
196             "ring0",
197             sizeof(status->name));
198     *numRings = 1;
199     return WIFI_SUCCESS;
200 }
201 
getLoggerSupportedFeatureSet(unsigned int * support)202 wifi_error Interface::getLoggerSupportedFeatureSet(unsigned int* support) {
203     if (support == nullptr) {
204         return WIFI_ERROR_INVALID_ARGS;
205     }
206     *support = 0;
207     return WIFI_SUCCESS;
208 }
209 
getRingData(char *)210 wifi_error Interface::getRingData(char* /*ringName*/) {
211     return WIFI_SUCCESS;
212 }
213 
configureNdOffload(u8)214 wifi_error Interface::configureNdOffload(u8 /*enable*/) {
215     return WIFI_SUCCESS;
216 }
217 
startPacketFateMonitoring()218 wifi_error Interface::startPacketFateMonitoring() {
219     return WIFI_SUCCESS;
220 }
221 
getTxPacketFates(wifi_tx_report *,size_t,size_t * numProvidedFates)222 wifi_error Interface::getTxPacketFates(wifi_tx_report* /*txReportBuffers*/,
223                                        size_t /*numRequestedFates*/,
224                                        size_t* numProvidedFates) {
225     if (numProvidedFates == nullptr) {
226         return WIFI_ERROR_INVALID_ARGS;
227     }
228     *numProvidedFates = 0;
229     return WIFI_SUCCESS;
230 }
231 
getRxPacketFates(wifi_rx_report *,size_t,size_t * numProvidedFates)232 wifi_error Interface::getRxPacketFates(wifi_rx_report* /*rxReportBuffers*/,
233                                        size_t /*numRequestedFates*/,
234                                        size_t* numProvidedFates) {
235     if (numProvidedFates == nullptr) {
236         return WIFI_ERROR_INVALID_ARGS;
237     }
238     *numProvidedFates = 0;
239     return WIFI_SUCCESS;
240 }
241 
getPacketFilterCapabilities(u32 * version,u32 * maxLength)242 wifi_error Interface::getPacketFilterCapabilities(u32* version,
243                                                   u32* maxLength) {
244     if (version == nullptr || maxLength == nullptr) {
245         return WIFI_ERROR_INVALID_ARGS;
246     }
247     *version = 0;
248     *maxLength = 0;
249     return WIFI_SUCCESS;
250 }
251 
252 wifi_error
getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT * wakeReasonCount)253 Interface::getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT* wakeReasonCount) {
254     if (wakeReasonCount == nullptr) {
255         return WIFI_ERROR_INVALID_ARGS;
256     }
257     return WIFI_SUCCESS;
258 }
259 
onLinkStatsReply(wifi_request_id requestId,wifi_stats_result_handler handler,const NetlinkMessage & message)260 void Interface::onLinkStatsReply(wifi_request_id requestId,
261                                  wifi_stats_result_handler handler,
262                                  const NetlinkMessage& message) {
263     if (message.size() < sizeof(nlmsghdr) + sizeof(ifinfomsg)) {
264         ALOGE("Invalid link stats response, too small");
265         return;
266     }
267     if (message.type() != RTM_NEWLINK) {
268         ALOGE("Recieved invalid link stats reply type: %u",
269               static_cast<unsigned int>(message.type()));
270         return;
271     }
272 
273     int numRadios = 1;
274     wifi_radio_stat radioStats;
275     memset(&radioStats, 0, sizeof(radioStats));
276 
277     wifi_iface_stat ifStats;
278     memset(&ifStats, 0, sizeof(ifStats));
279     ifStats.iface = reinterpret_cast<wifi_interface_handle>(this);
280 
281     rtnl_link_stats64 netlinkStats64;
282     rtnl_link_stats netlinkStats;
283     if (message.getAttribute(IFLA_STATS64, &netlinkStats64)) {
284         ifStats.ac[WIFI_AC_BE].tx_mpdu = netlinkStats64.tx_packets;
285         ifStats.ac[WIFI_AC_BE].rx_mpdu = netlinkStats64.rx_packets;
286     } else if (message.getAttribute(IFLA_STATS, &netlinkStats)) {
287         ifStats.ac[WIFI_AC_BE].tx_mpdu = netlinkStats.tx_packets;
288         ifStats.ac[WIFI_AC_BE].rx_mpdu = netlinkStats.rx_packets;
289     } else {
290         return;
291     }
292 
293     handler.on_link_stats_results(requestId, &ifStats, numRadios, &radioStats);
294 }
295