1 //
2 // Copyright (C) 2016 Google, Inc.
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 #include <rapidjson/document.h>
17 #include <rapidjson/writer.h>
18 #include <rapidjson/stringbuffer.h>
19 #include <net/if.h>
20 #include <sys/ioctl.h>
21 #include <sys/socket.h>
22
23 #include <base.h>
24 #include <base/at_exit.h>
25 #include <base/command_line.h>
26 #include <base/logging.h>
27 #include <base/macros.h>
28 #include <base/strings/string_split.h>
29 #include <base/strings/string_util.h>
30 #include <utils/command_receiver.h>
31 #include <utils/common_utils.h>
32 #include <wifi_hal.h>
33 #include <wifi_hal_stub.h>
34
35 #include "wifi_facade.h"
36
37 const char kWlanInterface[] = "wlan0";
38 const char kP2pInterface[] = "p2p0";
39
WifiInit()40 std::tuple<bool, int> WifiFacade::WifiInit() {
41 if (!WifiStartHal()) {
42 return std::make_tuple(false, sl4n_error_codes::kFailInt);
43 }
44
45 if (!WifiGetInterfaces() || wlan0_index == -1) {
46 return std::make_tuple(false, sl4n_error_codes::kFailInt);
47 }
48
49 return std::make_tuple(true, sl4n_error_codes::kPassInt);
50 }
51
WifiStartHal()52 bool WifiFacade::WifiStartHal() {
53 if (wifi_hal_handle == NULL) {
54 if (init_wifi_stub_hal_func_table(&hal_fn) != 0) {
55 LOG(ERROR) << sl4n::kTagStr
56 << ": Can not initialize the basic function pointer table";
57 return false;
58 }
59
60 wifi_error res = init_wifi_vendor_hal_func_table(&hal_fn);
61 if (res != WIFI_SUCCESS) {
62 LOG(ERROR) << sl4n::kTagStr
63 << ": Can not initialize the vendor function pointer table";
64 return false;
65 }
66
67 int ret = BringInterfaceUpDown(kWlanInterface, 1);
68 if (ret != 0) {
69 return false;
70 }
71
72 res = hal_fn.wifi_initialize(&wifi_hal_handle);
73 return res == WIFI_SUCCESS;
74 } else {
75 return BringInterfaceUpDown(kWlanInterface, 1) == 0;
76 }
77 }
78
WifiGetInterfaces()79 bool WifiFacade::WifiGetInterfaces() {
80 int num_ifaces;
81 int result = hal_fn.wifi_get_ifaces(wifi_hal_handle, &num_ifaces,
82 &wifi_iface_handles);
83 if (result < 0) {
84 LOG(ERROR) << sl4n::kTagStr << ": Can not get Wi-Fi interfaces";
85 return false;
86 }
87
88 if (num_ifaces < 0) {
89 LOG(ERROR) << sl4n::kTagStr << ": Negative number of interfaces";
90 return false;
91 }
92
93 if (wifi_iface_handles == NULL) {
94 LOG(ERROR) << sl4n::kTagStr
95 << "wifi_get_ifaces returned null interface array";
96 return false;
97 }
98
99 if (num_ifaces > 8) {
100 LOG(ERROR) << sl4n::kTagStr
101 << "wifi_get_ifaces returned too many interfaces";
102 return false;
103 }
104
105 char buf[128];
106 for (int i = 0; i < num_ifaces; ++i) {
107 int result = hal_fn.wifi_get_iface_name(wifi_iface_handles[i], buf,
108 sizeof(buf));
109 if (result < 0) {
110 LOG(ERROR) << sl4n::kTagStr
111 << "Can't obtain interface name for interface #" << i;
112 continue;
113 }
114 if (!strcmp(buf, kWlanInterface)) {
115 wlan0_index = i;
116 } else if (!strcmp(buf, kP2pInterface)) {
117 p2p0_index = i;
118 }
119 }
120
121 return true;
122 }
123
SharedValidator()124 bool WifiFacade::SharedValidator() {
125 if (wifi_hal_handle == NULL) {
126 LOG(ERROR) << sl4n::kTagStr << "HAL handle not initialized";
127 return false;
128 }
129
130 if (wifi_iface_handles == NULL) {
131 LOG(ERROR) << sl4n::kTagStr << "HAL interfaces not initialized";
132 return false;
133 }
134
135 if (wlan0_index == -1) {
136 LOG(ERROR) << sl4n::kTagStr << kWlanInterface << " interface not found";
137 return false;
138 }
139
140 return true;
141 }
142
WifiGetSupportedFeatureSet()143 std::tuple<int, int> WifiFacade::WifiGetSupportedFeatureSet() {
144 if (!SharedValidator()) {
145 return std::make_tuple(0, sl4n_error_codes::kFailInt);
146 }
147
148 feature_set set = 0;
149 int result = hal_fn.wifi_get_supported_feature_set(
150 wifi_iface_handles[wlan0_index], &set);
151 if (result == WIFI_SUCCESS) {
152 return std::make_tuple(set, sl4n_error_codes::kPassInt);
153 } else {
154 return std::make_tuple(0, sl4n_error_codes::kFailInt);
155 }
156 }
157
158 // TODO: copy of set_iface_flags from Wi-Fi JNI. Consolidate into a support
159 // library.
BringInterfaceUpDown(const char * ifname,int dev_up)160 int WifiFacade::BringInterfaceUpDown(const char *ifname, int dev_up) {
161 struct ifreq ifr;
162 int ret;
163 int sock = socket(PF_INET, SOCK_DGRAM, 0);
164 if (sock < 0) {
165 LOG(ERROR) << "Bad socket: " << sock;
166 return -errno;
167 }
168
169 memset(&ifr, 0, sizeof(ifr));
170 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
171
172 if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
173 ret = errno ? -errno : -999;
174 LOG(ERROR) << "Could not read interface " << ifname << " flags: " << errno;
175 close(sock);
176 return ret;
177 }
178
179 if (dev_up) {
180 if (ifr.ifr_flags & IFF_UP) {
181 close(sock);
182 return 0;
183 }
184 ifr.ifr_flags |= IFF_UP;
185 } else {
186 if (!(ifr.ifr_flags & IFF_UP)) {
187 close(sock);
188 return 0;
189 }
190 ifr.ifr_flags &= ~IFF_UP;
191 }
192
193 if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
194 LOG(ERROR) << "Could not set interface " << ifname << " flags: " << errno;
195 ret = errno ? -errno : -999;
196 close(sock);
197 return ret;
198 }
199 close(sock);
200 return 0;
201 }
202
203 //////////////////
204 // wrappers
205 /////////////////
206
207 static WifiFacade facade; // triggers registration with CommandReceiver
208
wifi_init_wrapper(rapidjson::Document & doc)209 void wifi_init_wrapper(rapidjson::Document &doc) {
210 int expected_param_size = 0;
211 if (!CommonUtils::IsParamLengthMatching(doc, expected_param_size)) {
212 return;
213 }
214 bool result;
215 int error_code;
216 std::tie(result, error_code) = facade.WifiInit();
217 if (error_code == sl4n_error_codes::kFailInt) {
218 doc.AddMember(sl4n::kResultStr, false, doc.GetAllocator());
219 doc.AddMember(sl4n::kErrorStr, sl4n::kFailStr, doc.GetAllocator());
220 } else {
221 doc.AddMember(sl4n::kResultStr, result, doc.GetAllocator());
222 doc.AddMember(sl4n::kErrorStr, NULL, doc.GetAllocator());
223 }
224 }
225
wifi_get_supported_feature_set_wrapper(rapidjson::Document & doc)226 void wifi_get_supported_feature_set_wrapper(rapidjson::Document &doc) {
227 int expected_param_size = 0;
228 if (!CommonUtils::IsParamLengthMatching(doc, expected_param_size)) {
229 return;
230 }
231 int result;
232 int error_code;
233 std::tie(result, error_code) = facade.WifiGetSupportedFeatureSet();
234 if (error_code == sl4n_error_codes::kFailInt) {
235 doc.AddMember(sl4n::kResultStr, false, doc.GetAllocator());
236 doc.AddMember(sl4n::kErrorStr, sl4n::kFailStr, doc.GetAllocator());
237 } else {
238 doc.AddMember(sl4n::kResultStr, result, doc.GetAllocator());
239 doc.AddMember(sl4n::kErrorStr, NULL, doc.GetAllocator());
240 }
241 }
242
243 ////////////////
244 // constructor
245 ////////////////
246
WifiFacade()247 WifiFacade::WifiFacade() {
248 wifi_hal_handle = NULL;
249 wifi_iface_handles = NULL;
250 num_wifi_iface_handles = 0;
251 wlan0_index = -1;
252 p2p0_index = -1;
253
254 CommandReceiver::RegisterCommand("WifiInit", &wifi_init_wrapper);
255 CommandReceiver::RegisterCommand("WifiGetSupportedFeatureSet",
256 &wifi_get_supported_feature_set_wrapper);
257 }
258