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 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 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 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 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 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. 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 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 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 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