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