dom/system/gonk/NetworkUtils.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* Copyright 2012 Mozilla Foundation and Mozilla contributors
michael@0 2 *
michael@0 3 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 4 * you may not use this file except in compliance with the License.
michael@0 5 * You may obtain a copy of the License at
michael@0 6 *
michael@0 7 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 8 *
michael@0 9 * Unless required by applicable law or agreed to in writing, software
michael@0 10 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 12 * See the License for the specific language governing permissions and
michael@0 13 * limitations under the License.
michael@0 14 */
michael@0 15
michael@0 16 #include "NetworkUtils.h"
michael@0 17
michael@0 18 #include <android/log.h>
michael@0 19 #include <cutils/properties.h>
michael@0 20 #include <limits>
michael@0 21 #include "mozilla/dom/network/NetUtils.h"
michael@0 22
michael@0 23 #include <sys/types.h> // struct addrinfo
michael@0 24 #include <sys/socket.h> // getaddrinfo(), freeaddrinfo()
michael@0 25 #include <netdb.h>
michael@0 26 #include <arpa/inet.h> // inet_ntop()
michael@0 27
michael@0 28 #define _DEBUG 0
michael@0 29
michael@0 30 #define WARN(args...) __android_log_print(ANDROID_LOG_WARN, "NetworkUtils", ## args)
michael@0 31 #define ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "NetworkUtils", ## args)
michael@0 32
michael@0 33 #if _DEBUG
michael@0 34 #define DEBUG(args...) __android_log_print(ANDROID_LOG_DEBUG, "NetworkUtils" , ## args)
michael@0 35 #else
michael@0 36 #define DEBUG(args...)
michael@0 37 #endif
michael@0 38
michael@0 39 using namespace mozilla::dom;
michael@0 40 using namespace mozilla::ipc;
michael@0 41
michael@0 42 static const char* PERSIST_SYS_USB_CONFIG_PROPERTY = "persist.sys.usb.config";
michael@0 43 static const char* SYS_USB_CONFIG_PROPERTY = "sys.usb.config";
michael@0 44 static const char* SYS_USB_STATE_PROPERTY = "sys.usb.state";
michael@0 45
michael@0 46 static const char* USB_FUNCTION_RNDIS = "rndis";
michael@0 47 static const char* USB_FUNCTION_ADB = "adb";
michael@0 48
michael@0 49 // Use this command to continue the function chain.
michael@0 50 static const char* DUMMY_COMMAND = "tether status";
michael@0 51
michael@0 52 // Retry 20 times (2 seconds) for usb state transition.
michael@0 53 static const uint32_t USB_FUNCTION_RETRY_TIMES = 20;
michael@0 54 // Check "sys.usb.state" every 100ms.
michael@0 55 static const uint32_t USB_FUNCTION_RETRY_INTERVAL = 100;
michael@0 56
michael@0 57 // 1xx - Requested action is proceeding
michael@0 58 static const uint32_t NETD_COMMAND_PROCEEDING = 100;
michael@0 59 // 2xx - Requested action has been successfully completed
michael@0 60 static const uint32_t NETD_COMMAND_OKAY = 200;
michael@0 61 // 4xx - The command is accepted but the requested action didn't
michael@0 62 // take place.
michael@0 63 static const uint32_t NETD_COMMAND_FAIL = 400;
michael@0 64 // 5xx - The command syntax or parameters error
michael@0 65 static const uint32_t NETD_COMMAND_ERROR = 500;
michael@0 66 // 6xx - Unsolicited broadcasts
michael@0 67 static const uint32_t NETD_COMMAND_UNSOLICITED = 600;
michael@0 68
michael@0 69 // Broadcast messages
michael@0 70 static const uint32_t NETD_COMMAND_INTERFACE_CHANGE = 600;
michael@0 71 static const uint32_t NETD_COMMAND_BANDWIDTH_CONTROLLER = 601;
michael@0 72
michael@0 73 static const char* INTERFACE_DELIMIT = ",";
michael@0 74 static const char* USB_CONFIG_DELIMIT = ",";
michael@0 75 static const char* NETD_MESSAGE_DELIMIT = " ";
michael@0 76
michael@0 77 static const uint32_t BUF_SIZE = 1024;
michael@0 78
michael@0 79 static uint32_t SDK_VERSION;
michael@0 80
michael@0 81 struct IFProperties {
michael@0 82 char gateway[PROPERTY_VALUE_MAX];
michael@0 83 char dns1[PROPERTY_VALUE_MAX];
michael@0 84 char dns2[PROPERTY_VALUE_MAX];
michael@0 85 };
michael@0 86
michael@0 87 struct CurrentCommand {
michael@0 88 CommandChain* chain;
michael@0 89 CommandCallback callback;
michael@0 90 char command[MAX_COMMAND_SIZE];
michael@0 91 };
michael@0 92
michael@0 93 typedef Tuple3<NetdCommand*, CommandChain*, CommandCallback> QueueData;
michael@0 94
michael@0 95 #define GET_CURRENT_NETD_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a)
michael@0 96 #define GET_CURRENT_CHAIN (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].b)
michael@0 97 #define GET_CURRENT_CALLBACK (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].c)
michael@0 98 #define GET_CURRENT_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a->mData)
michael@0 99
michael@0 100 static NetworkUtils* gNetworkUtils;
michael@0 101 static nsTArray<QueueData> gCommandQueue;
michael@0 102 static CurrentCommand gCurrentCommand;
michael@0 103 static bool gPending = false;
michael@0 104 static nsTArray<nsCString> gReason;
michael@0 105
michael@0 106 CommandFunc NetworkUtils::sWifiEnableChain[] = {
michael@0 107 NetworkUtils::wifiFirmwareReload,
michael@0 108 NetworkUtils::startAccessPointDriver,
michael@0 109 NetworkUtils::setAccessPoint,
michael@0 110 NetworkUtils::startSoftAP,
michael@0 111 NetworkUtils::setInterfaceUp,
michael@0 112 NetworkUtils::tetherInterface,
michael@0 113 NetworkUtils::setIpForwardingEnabled,
michael@0 114 NetworkUtils::tetheringStatus,
michael@0 115 NetworkUtils::startTethering,
michael@0 116 NetworkUtils::setDnsForwarders,
michael@0 117 NetworkUtils::enableNat,
michael@0 118 NetworkUtils::wifiTetheringSuccess
michael@0 119 };
michael@0 120
michael@0 121 CommandFunc NetworkUtils::sWifiDisableChain[] = {
michael@0 122 NetworkUtils::stopSoftAP,
michael@0 123 NetworkUtils::stopAccessPointDriver,
michael@0 124 NetworkUtils::wifiFirmwareReload,
michael@0 125 NetworkUtils::untetherInterface,
michael@0 126 NetworkUtils::preTetherInterfaceList,
michael@0 127 NetworkUtils::postTetherInterfaceList,
michael@0 128 NetworkUtils::disableNat,
michael@0 129 NetworkUtils::setIpForwardingEnabled,
michael@0 130 NetworkUtils::stopTethering,
michael@0 131 NetworkUtils::wifiTetheringSuccess
michael@0 132 };
michael@0 133
michael@0 134 CommandFunc NetworkUtils::sWifiFailChain[] = {
michael@0 135 NetworkUtils::stopSoftAP,
michael@0 136 NetworkUtils::setIpForwardingEnabled,
michael@0 137 NetworkUtils::stopTethering
michael@0 138 };
michael@0 139
michael@0 140 CommandFunc NetworkUtils::sWifiOperationModeChain[] = {
michael@0 141 NetworkUtils::wifiFirmwareReload,
michael@0 142 NetworkUtils::wifiOperationModeSuccess
michael@0 143 };
michael@0 144
michael@0 145 CommandFunc NetworkUtils::sUSBEnableChain[] = {
michael@0 146 NetworkUtils::setInterfaceUp,
michael@0 147 NetworkUtils::enableNat,
michael@0 148 NetworkUtils::setIpForwardingEnabled,
michael@0 149 NetworkUtils::tetherInterface,
michael@0 150 NetworkUtils::tetheringStatus,
michael@0 151 NetworkUtils::startTethering,
michael@0 152 NetworkUtils::setDnsForwarders,
michael@0 153 NetworkUtils::usbTetheringSuccess
michael@0 154 };
michael@0 155
michael@0 156 CommandFunc NetworkUtils::sUSBDisableChain[] = {
michael@0 157 NetworkUtils::untetherInterface,
michael@0 158 NetworkUtils::preTetherInterfaceList,
michael@0 159 NetworkUtils::postTetherInterfaceList,
michael@0 160 NetworkUtils::disableNat,
michael@0 161 NetworkUtils::setIpForwardingEnabled,
michael@0 162 NetworkUtils::stopTethering,
michael@0 163 NetworkUtils::usbTetheringSuccess
michael@0 164 };
michael@0 165
michael@0 166 CommandFunc NetworkUtils::sUSBFailChain[] = {
michael@0 167 NetworkUtils::stopSoftAP,
michael@0 168 NetworkUtils::setIpForwardingEnabled,
michael@0 169 NetworkUtils::stopTethering
michael@0 170 };
michael@0 171
michael@0 172 CommandFunc NetworkUtils::sUpdateUpStreamChain[] = {
michael@0 173 NetworkUtils::cleanUpStream,
michael@0 174 NetworkUtils::createUpStream,
michael@0 175 NetworkUtils::updateUpStreamSuccess
michael@0 176 };
michael@0 177
michael@0 178 CommandFunc NetworkUtils::sStartDhcpServerChain[] = {
michael@0 179 NetworkUtils::setInterfaceUp,
michael@0 180 NetworkUtils::startTethering,
michael@0 181 NetworkUtils::setDhcpServerSuccess
michael@0 182 };
michael@0 183
michael@0 184 CommandFunc NetworkUtils::sStopDhcpServerChain[] = {
michael@0 185 NetworkUtils::stopTethering,
michael@0 186 NetworkUtils::setDhcpServerSuccess
michael@0 187 };
michael@0 188
michael@0 189 CommandFunc NetworkUtils::sNetworkInterfaceStatsChain[] = {
michael@0 190 NetworkUtils::getRxBytes,
michael@0 191 NetworkUtils::getTxBytes,
michael@0 192 NetworkUtils::networkInterfaceStatsSuccess
michael@0 193 };
michael@0 194
michael@0 195 CommandFunc NetworkUtils::sNetworkInterfaceEnableAlarmChain[] = {
michael@0 196 NetworkUtils::enableAlarm,
michael@0 197 NetworkUtils::setQuota,
michael@0 198 NetworkUtils::setAlarm,
michael@0 199 NetworkUtils::networkInterfaceAlarmSuccess
michael@0 200 };
michael@0 201
michael@0 202 CommandFunc NetworkUtils::sNetworkInterfaceDisableAlarmChain[] = {
michael@0 203 NetworkUtils::removeQuota,
michael@0 204 NetworkUtils::disableAlarm,
michael@0 205 NetworkUtils::networkInterfaceAlarmSuccess
michael@0 206 };
michael@0 207
michael@0 208 CommandFunc NetworkUtils::sNetworkInterfaceSetAlarmChain[] = {
michael@0 209 NetworkUtils::setAlarm,
michael@0 210 NetworkUtils::networkInterfaceAlarmSuccess
michael@0 211 };
michael@0 212
michael@0 213 CommandFunc NetworkUtils::sSetDnsChain[] = {
michael@0 214 NetworkUtils::setDefaultInterface,
michael@0 215 NetworkUtils::setInterfaceDns
michael@0 216 };
michael@0 217
michael@0 218 /**
michael@0 219 * Helper function to get the mask from given prefix length.
michael@0 220 */
michael@0 221 static uint32_t makeMask(const uint32_t prefixLength)
michael@0 222 {
michael@0 223 uint32_t mask = 0;
michael@0 224 for (uint32_t i = 0; i < prefixLength; ++i) {
michael@0 225 mask |= (0x80000000 >> i);
michael@0 226 }
michael@0 227 return ntohl(mask);
michael@0 228 }
michael@0 229
michael@0 230 /**
michael@0 231 * Helper function to get the network part of an ip from prefix.
michael@0 232 * param ip must be in network byte order.
michael@0 233 */
michael@0 234 static char* getNetworkAddr(const uint32_t ip, const uint32_t prefix)
michael@0 235 {
michael@0 236 uint32_t mask = 0, subnet = 0;
michael@0 237
michael@0 238 mask = ~mask << (32 - prefix);
michael@0 239 mask = htonl(mask);
michael@0 240 subnet = ip & mask;
michael@0 241
michael@0 242 struct in_addr addr;
michael@0 243 addr.s_addr = subnet;
michael@0 244
michael@0 245 return inet_ntoa(addr);
michael@0 246 }
michael@0 247
michael@0 248 /**
michael@0 249 * Helper function to split string by seperator, store split result as an nsTArray.
michael@0 250 */
michael@0 251 static void split(char* str, const char* sep, nsTArray<nsCString>& result)
michael@0 252 {
michael@0 253 char *s = strtok(str, sep);
michael@0 254 while (s != nullptr) {
michael@0 255 result.AppendElement(s);
michael@0 256 s = strtok(nullptr, sep);
michael@0 257 }
michael@0 258 }
michael@0 259
michael@0 260 static void split(char* str, const char* sep, nsTArray<nsString>& result)
michael@0 261 {
michael@0 262 char *s = strtok(str, sep);
michael@0 263 while (s != nullptr) {
michael@0 264 result.AppendElement(NS_ConvertUTF8toUTF16(s));
michael@0 265 s = strtok(nullptr, sep);
michael@0 266 }
michael@0 267 }
michael@0 268
michael@0 269 /**
michael@0 270 * Helper function that implement join function.
michael@0 271 */
michael@0 272 static void join(nsTArray<nsCString>& array,
michael@0 273 const char* sep,
michael@0 274 const uint32_t maxlen,
michael@0 275 char* result)
michael@0 276 {
michael@0 277 #define CHECK_LENGTH(len, add, max) len += add; \
michael@0 278 if (len > max - 1) \
michael@0 279 return; \
michael@0 280
michael@0 281 uint32_t len = 0;
michael@0 282 uint32_t seplen = strlen(sep);
michael@0 283
michael@0 284 if (array.Length() > 0) {
michael@0 285 CHECK_LENGTH(len, strlen(array[0].get()), maxlen)
michael@0 286 strcpy(result, array[0].get());
michael@0 287
michael@0 288 for (uint32_t i = 1; i < array.Length(); i++) {
michael@0 289 CHECK_LENGTH(len, seplen, maxlen)
michael@0 290 strcat(result, sep);
michael@0 291
michael@0 292 CHECK_LENGTH(len, strlen(array[i].get()), maxlen)
michael@0 293 strcat(result, array[i].get());
michael@0 294 }
michael@0 295 }
michael@0 296
michael@0 297 #undef CHECK_LEN
michael@0 298 }
michael@0 299
michael@0 300 /**
michael@0 301 * Helper function to get network interface properties from the system property table.
michael@0 302 */
michael@0 303 static void getIFProperties(const char* ifname, IFProperties& prop)
michael@0 304 {
michael@0 305 char key[PROPERTY_KEY_MAX];
michael@0 306 snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.gw", ifname);
michael@0 307 property_get(key, prop.gateway, "");
michael@0 308 snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.dns1", ifname);
michael@0 309 property_get(key, prop.dns1, "");
michael@0 310 snprintf(key, PROPERTY_KEY_MAX - 1, "net.%s.dns2", ifname);
michael@0 311 property_get(key, prop.dns2, "");
michael@0 312 }
michael@0 313
michael@0 314 static int getIpType(const char *aIp) {
michael@0 315 struct addrinfo hint, *ip_info = NULL;
michael@0 316
michael@0 317 memset(&hint, 0, sizeof(hint));
michael@0 318 hint.ai_family = AF_UNSPEC;
michael@0 319 hint.ai_flags = AI_NUMERICHOST;
michael@0 320
michael@0 321 if (getaddrinfo(aIp, NULL, &hint, &ip_info)) {
michael@0 322 return AF_UNSPEC;
michael@0 323 }
michael@0 324
michael@0 325 int type = ip_info->ai_family;
michael@0 326 freeaddrinfo(ip_info);
michael@0 327
michael@0 328 return type;
michael@0 329 }
michael@0 330
michael@0 331 /**
michael@0 332 * Helper function to find the best match gateway. For now, return
michael@0 333 * the gateway that matches the address family passed.
michael@0 334 */
michael@0 335 static uint32_t selectGateway(nsTArray<nsString>& gateways, int addrFamily)
michael@0 336 {
michael@0 337 uint32_t length = gateways.Length();
michael@0 338
michael@0 339 for (uint32_t i = 0; i < length; i++) {
michael@0 340 NS_ConvertUTF16toUTF8 autoGateway(gateways[i]);
michael@0 341 if ((getIpType(autoGateway.get()) == AF_INET && addrFamily == AF_INET) ||
michael@0 342 (getIpType(autoGateway.get()) == AF_INET6 && addrFamily == AF_INET6)) {
michael@0 343 return i;
michael@0 344 }
michael@0 345 }
michael@0 346 return length; // invalid index.
michael@0 347 }
michael@0 348
michael@0 349 static void postMessage(NetworkResultOptions& aResult)
michael@0 350 {
michael@0 351 MOZ_ASSERT(gNetworkUtils);
michael@0 352 MOZ_ASSERT(gNetworkUtils->getMessageCallback());
michael@0 353
michael@0 354 if (*(gNetworkUtils->getMessageCallback()))
michael@0 355 (*(gNetworkUtils->getMessageCallback()))(aResult);
michael@0 356 }
michael@0 357
michael@0 358 static void postMessage(NetworkParams& aOptions, NetworkResultOptions& aResult)
michael@0 359 {
michael@0 360 MOZ_ASSERT(gNetworkUtils);
michael@0 361 MOZ_ASSERT(gNetworkUtils->getMessageCallback());
michael@0 362
michael@0 363 aResult.mId = aOptions.mId;
michael@0 364
michael@0 365 if (*(gNetworkUtils->getMessageCallback()))
michael@0 366 (*(gNetworkUtils->getMessageCallback()))(aResult);
michael@0 367 }
michael@0 368
michael@0 369 void NetworkUtils::next(CommandChain* aChain, bool aError, NetworkResultOptions& aResult)
michael@0 370 {
michael@0 371 if (aError) {
michael@0 372 ErrorCallback onError = aChain->getErrorCallback();
michael@0 373 if(onError) {
michael@0 374 aResult.mError = true;
michael@0 375 (*onError)(aChain->getParams(), aResult);
michael@0 376 }
michael@0 377 delete aChain;
michael@0 378 return;
michael@0 379 }
michael@0 380 CommandFunc f = aChain->getNextCommand();
michael@0 381 if (!f) {
michael@0 382 delete aChain;
michael@0 383 return;
michael@0 384 }
michael@0 385
michael@0 386 (*f)(aChain, next, aResult);
michael@0 387 }
michael@0 388
michael@0 389 /**
michael@0 390 * Send command to netd.
michael@0 391 */
michael@0 392 void NetworkUtils::nextNetdCommand()
michael@0 393 {
michael@0 394 if (gCommandQueue.IsEmpty() || gPending) {
michael@0 395 return;
michael@0 396 }
michael@0 397
michael@0 398 gCurrentCommand.chain = GET_CURRENT_CHAIN;
michael@0 399 gCurrentCommand.callback = GET_CURRENT_CALLBACK;
michael@0 400 snprintf(gCurrentCommand.command, MAX_COMMAND_SIZE - 1, "%s", GET_CURRENT_COMMAND);
michael@0 401
michael@0 402 DEBUG("Sending \'%s\' command to netd.", gCurrentCommand.command);
michael@0 403 SendNetdCommand(GET_CURRENT_NETD_COMMAND);
michael@0 404
michael@0 405 gCommandQueue.RemoveElementAt(0);
michael@0 406 gPending = true;
michael@0 407 }
michael@0 408
michael@0 409 /**
michael@0 410 * Composite NetdCommand sent to netd
michael@0 411 *
michael@0 412 * @param aCommand Command sent to netd to execute.
michael@0 413 * @param aChain Store command chain data, ex. command parameter.
michael@0 414 * @param aCallback Callback function to be executed when the result of
michael@0 415 * this command is returned from netd.
michael@0 416 */
michael@0 417 void NetworkUtils::doCommand(const char* aCommand, CommandChain* aChain, CommandCallback aCallback)
michael@0 418 {
michael@0 419 DEBUG("Preparing to send \'%s\' command...", aCommand);
michael@0 420
michael@0 421 NetdCommand* netdCommand = new NetdCommand();
michael@0 422
michael@0 423 // Android JB version adds sequence number to netd command.
michael@0 424 if (SDK_VERSION >= 16) {
michael@0 425 snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "0 %s", aCommand);
michael@0 426 } else {
michael@0 427 snprintf((char*)netdCommand->mData, MAX_COMMAND_SIZE - 1, "%s", aCommand);
michael@0 428 }
michael@0 429 netdCommand->mSize = strlen((char*)netdCommand->mData) + 1;
michael@0 430
michael@0 431 gCommandQueue.AppendElement(QueueData(netdCommand, aChain, aCallback));
michael@0 432
michael@0 433 nextNetdCommand();
michael@0 434 }
michael@0 435
michael@0 436 /*
michael@0 437 * Netd command function
michael@0 438 */
michael@0 439 #define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aChain->getParams().prop).get()
michael@0 440 #define GET_FIELD(prop) aChain->getParams().prop
michael@0 441
michael@0 442 void NetworkUtils::wifiFirmwareReload(CommandChain* aChain,
michael@0 443 CommandCallback aCallback,
michael@0 444 NetworkResultOptions& aResult)
michael@0 445 {
michael@0 446 char command[MAX_COMMAND_SIZE];
michael@0 447 snprintf(command, MAX_COMMAND_SIZE - 1, "softap fwreload %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
michael@0 448
michael@0 449 doCommand(command, aChain, aCallback);
michael@0 450 }
michael@0 451
michael@0 452 void NetworkUtils::startAccessPointDriver(CommandChain* aChain,
michael@0 453 CommandCallback aCallback,
michael@0 454 NetworkResultOptions& aResult)
michael@0 455 {
michael@0 456 // Skip the command for sdk version >= 16.
michael@0 457 if (SDK_VERSION >= 16) {
michael@0 458 aResult.mResultCode = 0;
michael@0 459 aResult.mResultReason = NS_ConvertUTF8toUTF16("");
michael@0 460 aCallback(aChain, false, aResult);
michael@0 461 return;
michael@0 462 }
michael@0 463
michael@0 464 char command[MAX_COMMAND_SIZE];
michael@0 465 snprintf(command, MAX_COMMAND_SIZE - 1, "softap start %s", GET_CHAR(mIfname));
michael@0 466
michael@0 467 doCommand(command, aChain, aCallback);
michael@0 468 }
michael@0 469
michael@0 470 void NetworkUtils::stopAccessPointDriver(CommandChain* aChain,
michael@0 471 CommandCallback aCallback,
michael@0 472 NetworkResultOptions& aResult)
michael@0 473 {
michael@0 474 // Skip the command for sdk version >= 16.
michael@0 475 if (SDK_VERSION >= 16) {
michael@0 476 aResult.mResultCode = 0;
michael@0 477 aResult.mResultReason = NS_ConvertUTF8toUTF16("");
michael@0 478 aCallback(aChain, false, aResult);
michael@0 479 return;
michael@0 480 }
michael@0 481
michael@0 482 char command[MAX_COMMAND_SIZE];
michael@0 483 snprintf(command, MAX_COMMAND_SIZE - 1, "softap stop %s", GET_CHAR(mIfname));
michael@0 484
michael@0 485 doCommand(command, aChain, aCallback);
michael@0 486 }
michael@0 487
michael@0 488 /**
michael@0 489 * Command format for sdk version < 16
michael@0 490 * Arguments:
michael@0 491 * argv[2] - wlan interface
michael@0 492 * argv[3] - SSID
michael@0 493 * argv[4] - Security
michael@0 494 * argv[5] - Key
michael@0 495 * argv[6] - Channel
michael@0 496 * argv[7] - Preamble
michael@0 497 * argv[8] - Max SCB
michael@0 498 *
michael@0 499 * Command format for sdk version >= 16
michael@0 500 * Arguments:
michael@0 501 * argv[2] - wlan interface
michael@0 502 * argv[3] - SSID
michael@0 503 * argv[4] - Security
michael@0 504 * argv[5] - Key
michael@0 505 *
michael@0 506 * Command format for sdk version >= 18
michael@0 507 * Arguments:
michael@0 508 * argv[2] - wlan interface
michael@0 509 * argv[3] - SSID
michael@0 510 * argv[4] - Broadcast/Hidden
michael@0 511 * argv[5] - Channel
michael@0 512 * argv[6] - Security
michael@0 513 * argv[7] - Key
michael@0 514 */
michael@0 515 void NetworkUtils::setAccessPoint(CommandChain* aChain,
michael@0 516 CommandCallback aCallback,
michael@0 517 NetworkResultOptions& aResult)
michael@0 518 {
michael@0 519 char command[MAX_COMMAND_SIZE];
michael@0 520 nsCString ssid(GET_CHAR(mSsid));
michael@0 521 nsCString key(GET_CHAR(mKey));
michael@0 522
michael@0 523 escapeQuote(ssid);
michael@0 524 escapeQuote(key);
michael@0 525
michael@0 526 if (SDK_VERSION >= 19) {
michael@0 527 snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s \"%s\" broadcast 6 %s \"%s\"",
michael@0 528 GET_CHAR(mIfname),
michael@0 529 ssid.get(),
michael@0 530 GET_CHAR(mSecurity),
michael@0 531 key.get());
michael@0 532 } else if (SDK_VERSION >= 16) {
michael@0 533 snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s \"%s\" %s \"%s\"",
michael@0 534 GET_CHAR(mIfname),
michael@0 535 ssid.get(),
michael@0 536 GET_CHAR(mSecurity),
michael@0 537 key.get());
michael@0 538 } else {
michael@0 539 snprintf(command, MAX_COMMAND_SIZE - 1, "softap set %s %s \"%s\" %s \"%s\" 6 0 8",
michael@0 540 GET_CHAR(mIfname),
michael@0 541 GET_CHAR(mWifictrlinterfacename),
michael@0 542 ssid.get(),
michael@0 543 GET_CHAR(mSecurity),
michael@0 544 key.get());
michael@0 545 }
michael@0 546
michael@0 547 doCommand(command, aChain, aCallback);
michael@0 548 }
michael@0 549
michael@0 550 void NetworkUtils::cleanUpStream(CommandChain* aChain,
michael@0 551 CommandCallback aCallback,
michael@0 552 NetworkResultOptions& aResult)
michael@0 553 {
michael@0 554 char command[MAX_COMMAND_SIZE];
michael@0 555 snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0", GET_CHAR(mPreInternalIfname), GET_CHAR(mPreExternalIfname));
michael@0 556
michael@0 557 doCommand(command, aChain, aCallback);
michael@0 558 }
michael@0 559
michael@0 560 void NetworkUtils::createUpStream(CommandChain* aChain,
michael@0 561 CommandCallback aCallback,
michael@0 562 NetworkResultOptions& aResult)
michael@0 563 {
michael@0 564 char command[MAX_COMMAND_SIZE];
michael@0 565 snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0", GET_CHAR(mCurInternalIfname), GET_CHAR(mCurExternalIfname));
michael@0 566
michael@0 567 doCommand(command, aChain, aCallback);
michael@0 568 }
michael@0 569
michael@0 570 void NetworkUtils::startSoftAP(CommandChain* aChain,
michael@0 571 CommandCallback aCallback,
michael@0 572 NetworkResultOptions& aResult)
michael@0 573 {
michael@0 574 const char* command= "softap startap";
michael@0 575 doCommand(command, aChain, aCallback);
michael@0 576 }
michael@0 577
michael@0 578 void NetworkUtils::stopSoftAP(CommandChain* aChain,
michael@0 579 CommandCallback aCallback,
michael@0 580 NetworkResultOptions& aResult)
michael@0 581 {
michael@0 582 const char* command= "softap stopap";
michael@0 583 doCommand(command, aChain, aCallback);
michael@0 584 }
michael@0 585
michael@0 586 void NetworkUtils::getRxBytes(CommandChain* aChain,
michael@0 587 CommandCallback aCallback,
michael@0 588 NetworkResultOptions& aResult)
michael@0 589 {
michael@0 590 char command[MAX_COMMAND_SIZE];
michael@0 591 snprintf(command, MAX_COMMAND_SIZE - 1, "interface readrxcounter %s", GET_CHAR(mIfname));
michael@0 592
michael@0 593 doCommand(command, aChain, aCallback);
michael@0 594 }
michael@0 595
michael@0 596 void NetworkUtils::getTxBytes(CommandChain* aChain,
michael@0 597 CommandCallback aCallback,
michael@0 598 NetworkResultOptions& aResult)
michael@0 599 {
michael@0 600 NetworkParams& options = aChain->getParams();
michael@0 601 options.mRxBytes = atof(NS_ConvertUTF16toUTF8(aResult.mResultReason).get());
michael@0 602
michael@0 603 char command[MAX_COMMAND_SIZE];
michael@0 604 snprintf(command, MAX_COMMAND_SIZE - 1, "interface readtxcounter %s", GET_CHAR(mIfname));
michael@0 605
michael@0 606 doCommand(command, aChain, aCallback);
michael@0 607 }
michael@0 608
michael@0 609 void NetworkUtils::enableAlarm(CommandChain* aChain,
michael@0 610 CommandCallback aCallback,
michael@0 611 NetworkResultOptions& aResult)
michael@0 612 {
michael@0 613 const char* command= "bandwidth enable";
michael@0 614 doCommand(command, aChain, aCallback);
michael@0 615 }
michael@0 616
michael@0 617 void NetworkUtils::disableAlarm(CommandChain* aChain,
michael@0 618 CommandCallback aCallback,
michael@0 619 NetworkResultOptions& aResult)
michael@0 620 {
michael@0 621 const char* command= "bandwidth disable";
michael@0 622 doCommand(command, aChain, aCallback);
michael@0 623 }
michael@0 624
michael@0 625 void NetworkUtils::setQuota(CommandChain* aChain,
michael@0 626 CommandCallback aCallback,
michael@0 627 NetworkResultOptions& aResult)
michael@0 628 {
michael@0 629 char command[MAX_COMMAND_SIZE];
michael@0 630 snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setiquota %s %lld", GET_CHAR(mIfname), LLONG_MAX);
michael@0 631
michael@0 632 doCommand(command, aChain, aCallback);
michael@0 633 }
michael@0 634
michael@0 635 void NetworkUtils::removeQuota(CommandChain* aChain,
michael@0 636 CommandCallback aCallback,
michael@0 637 NetworkResultOptions& aResult)
michael@0 638 {
michael@0 639 char command[MAX_COMMAND_SIZE];
michael@0 640 snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth removeiquota %s", GET_CHAR(mIfname));
michael@0 641
michael@0 642 doCommand(command, aChain, aCallback);
michael@0 643 }
michael@0 644
michael@0 645 void NetworkUtils::setAlarm(CommandChain* aChain,
michael@0 646 CommandCallback aCallback,
michael@0 647 NetworkResultOptions& aResult)
michael@0 648 {
michael@0 649 char command[MAX_COMMAND_SIZE];
michael@0 650 snprintf(command, MAX_COMMAND_SIZE - 1, "bandwidth setinterfacealert %s %ld", GET_CHAR(mIfname), GET_FIELD(mThreshold));
michael@0 651
michael@0 652 doCommand(command, aChain, aCallback);
michael@0 653 }
michael@0 654
michael@0 655 void NetworkUtils::setInterfaceUp(CommandChain* aChain,
michael@0 656 CommandCallback aCallback,
michael@0 657 NetworkResultOptions& aResult)
michael@0 658 {
michael@0 659 char command[MAX_COMMAND_SIZE];
michael@0 660 if (SDK_VERSION >= 16) {
michael@0 661 snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s %s",
michael@0 662 GET_CHAR(mIfname),
michael@0 663 GET_CHAR(mIp),
michael@0 664 GET_CHAR(mPrefix),
michael@0 665 GET_CHAR(mLink));
michael@0 666 } else {
michael@0 667 snprintf(command, MAX_COMMAND_SIZE - 1, "interface setcfg %s %s %s [%s]",
michael@0 668 GET_CHAR(mIfname),
michael@0 669 GET_CHAR(mIp),
michael@0 670 GET_CHAR(mPrefix),
michael@0 671 GET_CHAR(mLink));
michael@0 672 }
michael@0 673 doCommand(command, aChain, aCallback);
michael@0 674 }
michael@0 675
michael@0 676 void NetworkUtils::tetherInterface(CommandChain* aChain,
michael@0 677 CommandCallback aCallback,
michael@0 678 NetworkResultOptions& aResult)
michael@0 679 {
michael@0 680 char command[MAX_COMMAND_SIZE];
michael@0 681 snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface add %s", GET_CHAR(mIfname));
michael@0 682
michael@0 683 doCommand(command, aChain, aCallback);
michael@0 684 }
michael@0 685
michael@0 686 void NetworkUtils::preTetherInterfaceList(CommandChain* aChain,
michael@0 687 CommandCallback aCallback,
michael@0 688 NetworkResultOptions& aResult)
michael@0 689 {
michael@0 690 char command[MAX_COMMAND_SIZE];
michael@0 691 if (SDK_VERSION >= 16) {
michael@0 692 snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list");
michael@0 693 } else {
michael@0 694 snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface list 0");
michael@0 695 }
michael@0 696
michael@0 697 doCommand(command, aChain, aCallback);
michael@0 698 }
michael@0 699
michael@0 700 void NetworkUtils::postTetherInterfaceList(CommandChain* aChain,
michael@0 701 CommandCallback aCallback,
michael@0 702 NetworkResultOptions& aResult)
michael@0 703 {
michael@0 704 // Send the dummy command to continue the function chain.
michael@0 705 char command[MAX_COMMAND_SIZE];
michael@0 706 snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
michael@0 707
michael@0 708 char buf[BUF_SIZE];
michael@0 709 const char* reason = NS_ConvertUTF16toUTF8(aResult.mResultReason).get();
michael@0 710 memcpy(buf, reason, strlen(reason));
michael@0 711 split(buf, INTERFACE_DELIMIT, GET_FIELD(mInterfaceList));
michael@0 712
michael@0 713 doCommand(command, aChain, aCallback);
michael@0 714 }
michael@0 715
michael@0 716 void NetworkUtils::setIpForwardingEnabled(CommandChain* aChain,
michael@0 717 CommandCallback aCallback,
michael@0 718 NetworkResultOptions& aResult)
michael@0 719 {
michael@0 720 char command[MAX_COMMAND_SIZE];
michael@0 721
michael@0 722 if (GET_FIELD(mEnable)) {
michael@0 723 snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd enable");
michael@0 724 } else {
michael@0 725 // Don't disable ip forwarding because others interface still need it.
michael@0 726 // Send the dummy command to continue the function chain.
michael@0 727 if (GET_FIELD(mInterfaceList).Length() > 1) {
michael@0 728 snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
michael@0 729 } else {
michael@0 730 snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd disable");
michael@0 731 }
michael@0 732 }
michael@0 733
michael@0 734 doCommand(command, aChain, aCallback);
michael@0 735 }
michael@0 736
michael@0 737 void NetworkUtils::tetheringStatus(CommandChain* aChain,
michael@0 738 CommandCallback aCallback,
michael@0 739 NetworkResultOptions& aResult)
michael@0 740 {
michael@0 741 const char* command= "tether status";
michael@0 742 doCommand(command, aChain, aCallback);
michael@0 743 }
michael@0 744
michael@0 745 void NetworkUtils::stopTethering(CommandChain* aChain,
michael@0 746 CommandCallback aCallback,
michael@0 747 NetworkResultOptions& aResult)
michael@0 748 {
michael@0 749 char command[MAX_COMMAND_SIZE];
michael@0 750
michael@0 751 // Don't stop tethering because others interface still need it.
michael@0 752 // Send the dummy to continue the function chain.
michael@0 753 if (GET_FIELD(mInterfaceList).Length() > 1) {
michael@0 754 snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
michael@0 755 } else {
michael@0 756 snprintf(command, MAX_COMMAND_SIZE - 1, "tether stop");
michael@0 757 }
michael@0 758
michael@0 759 doCommand(command, aChain, aCallback);
michael@0 760 }
michael@0 761
michael@0 762 void NetworkUtils::startTethering(CommandChain* aChain,
michael@0 763 CommandCallback aCallback,
michael@0 764 NetworkResultOptions& aResult)
michael@0 765 {
michael@0 766 char command[MAX_COMMAND_SIZE];
michael@0 767
michael@0 768 // We don't need to start tethering again.
michael@0 769 // Send the dummy command to continue the function chain.
michael@0 770 if (aResult.mResultReason.Find("started") != kNotFound) {
michael@0 771 snprintf(command, MAX_COMMAND_SIZE - 1, "%s", DUMMY_COMMAND);
michael@0 772 } else {
michael@0 773 snprintf(command, MAX_COMMAND_SIZE - 1, "tether start %s %s", GET_CHAR(mWifiStartIp), GET_CHAR(mWifiEndIp));
michael@0 774
michael@0 775 // If usbStartIp/usbEndIp is not valid, don't append them since
michael@0 776 // the trailing white spaces will be parsed to extra empty args
michael@0 777 // See: http://androidxref.com/4.3_r2.1/xref/system/core/libsysutils/src/FrameworkListener.cpp#78
michael@0 778 if (!GET_FIELD(mUsbStartIp).IsEmpty() && !GET_FIELD(mUsbEndIp).IsEmpty()) {
michael@0 779 snprintf(command, MAX_COMMAND_SIZE - 1, "%s %s %s", command, GET_CHAR(mUsbStartIp), GET_CHAR(mUsbEndIp));
michael@0 780 }
michael@0 781 }
michael@0 782
michael@0 783 doCommand(command, aChain, aCallback);
michael@0 784 }
michael@0 785
michael@0 786 void NetworkUtils::untetherInterface(CommandChain* aChain,
michael@0 787 CommandCallback aCallback,
michael@0 788 NetworkResultOptions& aResult)
michael@0 789 {
michael@0 790 char command[MAX_COMMAND_SIZE];
michael@0 791 snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface remove %s", GET_CHAR(mIfname));
michael@0 792
michael@0 793 doCommand(command, aChain, aCallback);
michael@0 794 }
michael@0 795
michael@0 796 void NetworkUtils::setDnsForwarders(CommandChain* aChain,
michael@0 797 CommandCallback aCallback,
michael@0 798 NetworkResultOptions& aResult)
michael@0 799 {
michael@0 800 char command[MAX_COMMAND_SIZE];
michael@0 801 snprintf(command, MAX_COMMAND_SIZE - 1, "tether dns set %s %s", GET_CHAR(mDns1), GET_CHAR(mDns2));
michael@0 802
michael@0 803 doCommand(command, aChain, aCallback);
michael@0 804 }
michael@0 805
michael@0 806 void NetworkUtils::enableNat(CommandChain* aChain,
michael@0 807 CommandCallback aCallback,
michael@0 808 NetworkResultOptions& aResult)
michael@0 809 {
michael@0 810 char command[MAX_COMMAND_SIZE];
michael@0 811
michael@0 812 if (!GET_FIELD(mIp).IsEmpty() && !GET_FIELD(mPrefix).IsEmpty()) {
michael@0 813 uint32_t prefix = atoi(GET_CHAR(mPrefix));
michael@0 814 uint32_t ip = inet_addr(GET_CHAR(mIp));
michael@0 815 char* networkAddr = getNetworkAddr(ip, prefix);
michael@0 816
michael@0 817 // address/prefix will only take effect when secondary routing table exists.
michael@0 818 snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 1 %s/%s",
michael@0 819 GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname), networkAddr,
michael@0 820 GET_CHAR(mPrefix));
michael@0 821 } else {
michael@0 822 snprintf(command, MAX_COMMAND_SIZE - 1, "nat enable %s %s 0",
michael@0 823 GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
michael@0 824 }
michael@0 825
michael@0 826 doCommand(command, aChain, aCallback);
michael@0 827 }
michael@0 828
michael@0 829 void NetworkUtils::disableNat(CommandChain* aChain,
michael@0 830 CommandCallback aCallback,
michael@0 831 NetworkResultOptions& aResult)
michael@0 832 {
michael@0 833 char command[MAX_COMMAND_SIZE];
michael@0 834
michael@0 835 if (!GET_FIELD(mIp).IsEmpty() && !GET_FIELD(mPrefix).IsEmpty()) {
michael@0 836 uint32_t prefix = atoi(GET_CHAR(mPrefix));
michael@0 837 uint32_t ip = inet_addr(GET_CHAR(mIp));
michael@0 838 char* networkAddr = getNetworkAddr(ip, prefix);
michael@0 839
michael@0 840 snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 1 %s/%s",
michael@0 841 GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname), networkAddr,
michael@0 842 GET_CHAR(mPrefix));
michael@0 843 } else {
michael@0 844 snprintf(command, MAX_COMMAND_SIZE - 1, "nat disable %s %s 0",
michael@0 845 GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
michael@0 846 }
michael@0 847
michael@0 848 doCommand(command, aChain, aCallback);
michael@0 849 }
michael@0 850
michael@0 851 void NetworkUtils::setDefaultInterface(CommandChain* aChain,
michael@0 852 CommandCallback aCallback,
michael@0 853 NetworkResultOptions& aResult)
michael@0 854 {
michael@0 855 char command[MAX_COMMAND_SIZE];
michael@0 856 snprintf(command, MAX_COMMAND_SIZE - 1, "resolver setdefaultif %s", GET_CHAR(mIfname));
michael@0 857
michael@0 858 doCommand(command, aChain, aCallback);
michael@0 859 }
michael@0 860
michael@0 861 void NetworkUtils::setInterfaceDns(CommandChain* aChain,
michael@0 862 CommandCallback aCallback,
michael@0 863 NetworkResultOptions& aResult)
michael@0 864 {
michael@0 865 char command[MAX_COMMAND_SIZE];
michael@0 866 int written = snprintf(command, sizeof command, "resolver setifdns %s %s",
michael@0 867 GET_CHAR(mIfname), GET_CHAR(mDomain));
michael@0 868
michael@0 869 nsTArray<nsString>& dnses = GET_FIELD(mDnses);
michael@0 870 uint32_t length = dnses.Length();
michael@0 871
michael@0 872 for (uint32_t i = 0; i < length; i++) {
michael@0 873 NS_ConvertUTF16toUTF8 autoDns(dnses[i]);
michael@0 874
michael@0 875 int ret = snprintf(command + written, sizeof(command) - written, " %s", autoDns.get());
michael@0 876 if (ret <= 1) {
michael@0 877 command[written] = '\0';
michael@0 878 continue;
michael@0 879 }
michael@0 880
michael@0 881 if ((ret + written) >= sizeof(command)) {
michael@0 882 command[written] = '\0';
michael@0 883 break;
michael@0 884 }
michael@0 885
michael@0 886 written += ret;
michael@0 887 }
michael@0 888
michael@0 889 doCommand(command, aChain, aCallback);
michael@0 890 }
michael@0 891
michael@0 892 #undef GET_CHAR
michael@0 893 #undef GET_FIELD
michael@0 894
michael@0 895 /*
michael@0 896 * Netd command success/fail function
michael@0 897 */
michael@0 898 #define ASSIGN_FIELD(prop) aResult.prop = aChain->getParams().prop;
michael@0 899 #define ASSIGN_FIELD_VALUE(prop, value) aResult.prop = value;
michael@0 900
michael@0 901 #define RUN_CHAIN(param, cmds, err) \
michael@0 902 uint32_t size = sizeof(cmds) / sizeof(CommandFunc); \
michael@0 903 CommandChain* chain = new CommandChain(param, cmds, size, err); \
michael@0 904 NetworkResultOptions result; \
michael@0 905 next(chain, false, result);
michael@0 906
michael@0 907 void NetworkUtils::wifiTetheringFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
michael@0 908 {
michael@0 909 // Notify the main thread.
michael@0 910 postMessage(aOptions, aResult);
michael@0 911
michael@0 912 // If one of the stages fails, we try roll back to ensure
michael@0 913 // we don't leave the network systems in limbo.
michael@0 914 ASSIGN_FIELD_VALUE(mEnable, false)
michael@0 915 RUN_CHAIN(aOptions, sWifiFailChain, nullptr)
michael@0 916 }
michael@0 917
michael@0 918 void NetworkUtils::wifiTetheringSuccess(CommandChain* aChain,
michael@0 919 CommandCallback aCallback,
michael@0 920 NetworkResultOptions& aResult)
michael@0 921 {
michael@0 922 ASSIGN_FIELD(mEnable)
michael@0 923 postMessage(aChain->getParams(), aResult);
michael@0 924 }
michael@0 925
michael@0 926 void NetworkUtils::usbTetheringFail(NetworkParams& aOptions,
michael@0 927 NetworkResultOptions& aResult)
michael@0 928 {
michael@0 929 // Notify the main thread.
michael@0 930 postMessage(aOptions, aResult);
michael@0 931 // Try to roll back to ensure
michael@0 932 // we don't leave the network systems in limbo.
michael@0 933 // This parameter is used to disable ipforwarding.
michael@0 934 {
michael@0 935 aOptions.mEnable = false;
michael@0 936 RUN_CHAIN(aOptions, sUSBFailChain, nullptr)
michael@0 937 }
michael@0 938
michael@0 939 // Disable usb rndis function.
michael@0 940 {
michael@0 941 NetworkParams options;
michael@0 942 options.mEnable = false;
michael@0 943 options.mReport = false;
michael@0 944 gNetworkUtils->enableUsbRndis(options);
michael@0 945 }
michael@0 946 }
michael@0 947
michael@0 948 void NetworkUtils::usbTetheringSuccess(CommandChain* aChain,
michael@0 949 CommandCallback aCallback,
michael@0 950 NetworkResultOptions& aResult)
michael@0 951 {
michael@0 952 ASSIGN_FIELD(mEnable)
michael@0 953 postMessage(aChain->getParams(), aResult);
michael@0 954 }
michael@0 955
michael@0 956 void NetworkUtils::networkInterfaceStatsFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
michael@0 957 {
michael@0 958 postMessage(aOptions, aResult);
michael@0 959 }
michael@0 960
michael@0 961 void NetworkUtils::networkInterfaceStatsSuccess(CommandChain* aChain,
michael@0 962 CommandCallback aCallback,
michael@0 963 NetworkResultOptions& aResult)
michael@0 964 {
michael@0 965 ASSIGN_FIELD(mRxBytes)
michael@0 966 ASSIGN_FIELD_VALUE(mTxBytes, atof(NS_ConvertUTF16toUTF8(aResult.mResultReason).get()))
michael@0 967 postMessage(aChain->getParams(), aResult);
michael@0 968 }
michael@0 969
michael@0 970 void NetworkUtils::networkInterfaceAlarmFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
michael@0 971 {
michael@0 972 postMessage(aOptions, aResult);
michael@0 973 }
michael@0 974
michael@0 975 void NetworkUtils::networkInterfaceAlarmSuccess(CommandChain* aChain,
michael@0 976 CommandCallback aCallback,
michael@0 977 NetworkResultOptions& aResult)
michael@0 978 {
michael@0 979 // TODO : error is not used , and it is conflict with boolean type error.
michael@0 980 // params.error = parseFloat(params.resultReason);
michael@0 981 postMessage(aChain->getParams(), aResult);
michael@0 982 }
michael@0 983
michael@0 984 void NetworkUtils::updateUpStreamFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
michael@0 985 {
michael@0 986 postMessage(aOptions, aResult);
michael@0 987 }
michael@0 988
michael@0 989 void NetworkUtils::updateUpStreamSuccess(CommandChain* aChain,
michael@0 990 CommandCallback aCallback,
michael@0 991 NetworkResultOptions& aResult)
michael@0 992 {
michael@0 993 ASSIGN_FIELD(mCurExternalIfname)
michael@0 994 ASSIGN_FIELD(mCurInternalIfname)
michael@0 995 postMessage(aChain->getParams(), aResult);
michael@0 996 }
michael@0 997
michael@0 998 void NetworkUtils::setDhcpServerFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
michael@0 999 {
michael@0 1000 aResult.mSuccess = false;
michael@0 1001 postMessage(aOptions, aResult);
michael@0 1002 }
michael@0 1003
michael@0 1004 void NetworkUtils::setDhcpServerSuccess(CommandChain* aChain, CommandCallback aCallback, NetworkResultOptions& aResult)
michael@0 1005 {
michael@0 1006 aResult.mSuccess = true;
michael@0 1007 postMessage(aChain->getParams(), aResult);
michael@0 1008 }
michael@0 1009
michael@0 1010 void NetworkUtils::wifiOperationModeFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
michael@0 1011 {
michael@0 1012 postMessage(aOptions, aResult);
michael@0 1013 }
michael@0 1014
michael@0 1015 void NetworkUtils::wifiOperationModeSuccess(CommandChain* aChain,
michael@0 1016 CommandCallback aCallback,
michael@0 1017 NetworkResultOptions& aResult)
michael@0 1018 {
michael@0 1019 postMessage(aChain->getParams(), aResult);
michael@0 1020 }
michael@0 1021
michael@0 1022 void NetworkUtils::setDnsFail(NetworkParams& aOptions, NetworkResultOptions& aResult)
michael@0 1023 {
michael@0 1024 postMessage(aOptions, aResult);
michael@0 1025 }
michael@0 1026
michael@0 1027 #undef ASSIGN_FIELD
michael@0 1028 #undef ASSIGN_FIELD_VALUE
michael@0 1029
michael@0 1030 NetworkUtils::NetworkUtils(MessageCallback aCallback)
michael@0 1031 : mMessageCallback(aCallback)
michael@0 1032 {
michael@0 1033 mNetUtils = new NetUtils();
michael@0 1034
michael@0 1035 char value[PROPERTY_VALUE_MAX];
michael@0 1036 property_get("ro.build.version.sdk", value, nullptr);
michael@0 1037 SDK_VERSION = atoi(value);
michael@0 1038
michael@0 1039 gNetworkUtils = this;
michael@0 1040 }
michael@0 1041
michael@0 1042 NetworkUtils::~NetworkUtils()
michael@0 1043 {
michael@0 1044 }
michael@0 1045
michael@0 1046 #define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aOptions.prop).get()
michael@0 1047 #define GET_FIELD(prop) aOptions.prop
michael@0 1048
michael@0 1049 void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
michael@0 1050 {
michael@0 1051 bool ret = true;
michael@0 1052
michael@0 1053 if (aOptions.mCmd.EqualsLiteral("removeNetworkRoute")) {
michael@0 1054 removeNetworkRoute(aOptions);
michael@0 1055 } else if (aOptions.mCmd.EqualsLiteral("setDNS")) {
michael@0 1056 setDNS(aOptions);
michael@0 1057 } else if (aOptions.mCmd.EqualsLiteral("setDefaultRouteAndDNS")) {
michael@0 1058 setDefaultRouteAndDNS(aOptions);
michael@0 1059 } else if (aOptions.mCmd.EqualsLiteral("removeDefaultRoute")) {
michael@0 1060 removeDefaultRoute(aOptions);
michael@0 1061 } else if (aOptions.mCmd.EqualsLiteral("addHostRoute")) {
michael@0 1062 addHostRoute(aOptions);
michael@0 1063 } else if (aOptions.mCmd.EqualsLiteral("removeHostRoute")) {
michael@0 1064 removeHostRoute(aOptions);
michael@0 1065 } else if (aOptions.mCmd.EqualsLiteral("removeHostRoutes")) {
michael@0 1066 removeHostRoutes(aOptions);
michael@0 1067 } else if (aOptions.mCmd.EqualsLiteral("addSecondaryRoute")) {
michael@0 1068 addSecondaryRoute(aOptions);
michael@0 1069 } else if (aOptions.mCmd.EqualsLiteral("removeSecondaryRoute")) {
michael@0 1070 removeSecondaryRoute(aOptions);
michael@0 1071 } else if (aOptions.mCmd.EqualsLiteral("getNetworkInterfaceStats")) {
michael@0 1072 getNetworkInterfaceStats(aOptions);
michael@0 1073 } else if (aOptions.mCmd.EqualsLiteral("setNetworkInterfaceAlarm")) {
michael@0 1074 setNetworkInterfaceAlarm(aOptions);
michael@0 1075 } else if (aOptions.mCmd.EqualsLiteral("enableNetworkInterfaceAlarm")) {
michael@0 1076 enableNetworkInterfaceAlarm(aOptions);
michael@0 1077 } else if (aOptions.mCmd.EqualsLiteral("disableNetworkInterfaceAlarm")) {
michael@0 1078 disableNetworkInterfaceAlarm(aOptions);
michael@0 1079 } else if (aOptions.mCmd.EqualsLiteral("setWifiOperationMode")) {
michael@0 1080 setWifiOperationMode(aOptions);
michael@0 1081 } else if (aOptions.mCmd.EqualsLiteral("setDhcpServer")) {
michael@0 1082 setDhcpServer(aOptions);
michael@0 1083 } else if (aOptions.mCmd.EqualsLiteral("setWifiTethering")) {
michael@0 1084 setWifiTethering(aOptions);
michael@0 1085 } else if (aOptions.mCmd.EqualsLiteral("setUSBTethering")) {
michael@0 1086 setUSBTethering(aOptions);
michael@0 1087 } else if (aOptions.mCmd.EqualsLiteral("enableUsbRndis")) {
michael@0 1088 enableUsbRndis(aOptions);
michael@0 1089 } else if (aOptions.mCmd.EqualsLiteral("updateUpStream")) {
michael@0 1090 updateUpStream(aOptions);
michael@0 1091 } else {
michael@0 1092 WARN("unknon message");
michael@0 1093 return;
michael@0 1094 }
michael@0 1095
michael@0 1096 if (!aOptions.mIsAsync) {
michael@0 1097 NetworkResultOptions result;
michael@0 1098 result.mRet = ret;
michael@0 1099 postMessage(aOptions, result);
michael@0 1100 }
michael@0 1101 }
michael@0 1102
michael@0 1103 /**
michael@0 1104 * Handle received data from netd.
michael@0 1105 */
michael@0 1106 void NetworkUtils::onNetdMessage(NetdCommand* aCommand)
michael@0 1107 {
michael@0 1108 char* data = (char*)aCommand->mData;
michael@0 1109
michael@0 1110 // get code & reason.
michael@0 1111 char* result = strtok(data, NETD_MESSAGE_DELIMIT);
michael@0 1112
michael@0 1113 if (!result) {
michael@0 1114 nextNetdCommand();
michael@0 1115 return;
michael@0 1116 }
michael@0 1117 uint32_t code = atoi(result);
michael@0 1118
michael@0 1119 if (!isBroadcastMessage(code) && SDK_VERSION >= 16) {
michael@0 1120 strtok(nullptr, NETD_MESSAGE_DELIMIT);
michael@0 1121 }
michael@0 1122
michael@0 1123 char* reason = strtok(nullptr, "\0");
michael@0 1124
michael@0 1125 if (isBroadcastMessage(code)) {
michael@0 1126 DEBUG("Receiving broadcast message from netd.");
michael@0 1127 DEBUG(" ==> Code: %d Reason: %s", code, reason);
michael@0 1128 sendBroadcastMessage(code, reason);
michael@0 1129 nextNetdCommand();
michael@0 1130 return;
michael@0 1131 }
michael@0 1132
michael@0 1133 // Set pending to false before we handle next command.
michael@0 1134 DEBUG("Receiving \"%s\" command response from netd.", gCurrentCommand.command);
michael@0 1135 DEBUG(" ==> Code: %d Reason: %s", code, reason);
michael@0 1136
michael@0 1137 gReason.AppendElement(nsCString(reason));
michael@0 1138
michael@0 1139 // 1xx response code regards as command is proceeding, we need to wait for
michael@0 1140 // final response code such as 2xx, 4xx and 5xx before sending next command.
michael@0 1141 if (isProceeding(code)) {
michael@0 1142 return;
michael@0 1143 }
michael@0 1144
michael@0 1145 if (isComplete(code)) {
michael@0 1146 gPending = false;
michael@0 1147 }
michael@0 1148
michael@0 1149 if (gCurrentCommand.callback) {
michael@0 1150 char buf[BUF_SIZE];
michael@0 1151 join(gReason, INTERFACE_DELIMIT, BUF_SIZE, buf);
michael@0 1152
michael@0 1153 NetworkResultOptions result;
michael@0 1154 result.mResultCode = code;
michael@0 1155 result.mResultReason = NS_ConvertUTF8toUTF16(buf);
michael@0 1156 (*gCurrentCommand.callback)(gCurrentCommand.chain, isError(code), result);
michael@0 1157 gReason.Clear();
michael@0 1158 }
michael@0 1159
michael@0 1160 // Handling pending commands if any.
michael@0 1161 if (isComplete(code)) {
michael@0 1162 nextNetdCommand();
michael@0 1163 }
michael@0 1164 }
michael@0 1165
michael@0 1166 /**
michael@0 1167 * Start/Stop DHCP server.
michael@0 1168 */
michael@0 1169 bool NetworkUtils::setDhcpServer(NetworkParams& aOptions)
michael@0 1170 {
michael@0 1171 if (aOptions.mEnabled) {
michael@0 1172 aOptions.mWifiStartIp = aOptions.mStartIp;
michael@0 1173 aOptions.mWifiEndIp = aOptions.mEndIp;
michael@0 1174 aOptions.mIp = aOptions.mServerIp;
michael@0 1175 aOptions.mPrefix = aOptions.mMaskLength;
michael@0 1176 aOptions.mLink = NS_ConvertUTF8toUTF16("up");
michael@0 1177
michael@0 1178 RUN_CHAIN(aOptions, sStartDhcpServerChain, setDhcpServerFail)
michael@0 1179 } else {
michael@0 1180 RUN_CHAIN(aOptions, sStopDhcpServerChain, setDhcpServerFail)
michael@0 1181 }
michael@0 1182 return true;
michael@0 1183 }
michael@0 1184
michael@0 1185 /**
michael@0 1186 * Set DNS servers for given network interface.
michael@0 1187 */
michael@0 1188 bool NetworkUtils::setDNS(NetworkParams& aOptions)
michael@0 1189 {
michael@0 1190 uint32_t length = aOptions.mDnses.Length();
michael@0 1191
michael@0 1192 if (length > 0) {
michael@0 1193 for (uint32_t i = 0; i < length; i++) {
michael@0 1194 NS_ConvertUTF16toUTF8 autoDns(aOptions.mDnses[i]);
michael@0 1195
michael@0 1196 char dns_prop_key[PROPERTY_VALUE_MAX];
michael@0 1197 snprintf(dns_prop_key, sizeof dns_prop_key, "net.dns%d", i+1);
michael@0 1198 property_set(dns_prop_key, autoDns.get());
michael@0 1199 }
michael@0 1200 } else {
michael@0 1201 // Set dnses from system properties.
michael@0 1202 IFProperties interfaceProperties;
michael@0 1203 getIFProperties(GET_CHAR(mIfname), interfaceProperties);
michael@0 1204
michael@0 1205 property_set("net.dns1", interfaceProperties.dns1);
michael@0 1206 property_set("net.dns2", interfaceProperties.dns2);
michael@0 1207 }
michael@0 1208
michael@0 1209 // Bump the DNS change property.
michael@0 1210 char dnschange[PROPERTY_VALUE_MAX];
michael@0 1211 property_get("net.dnschange", dnschange, "0");
michael@0 1212
michael@0 1213 char num[PROPERTY_VALUE_MAX];
michael@0 1214 snprintf(num, PROPERTY_VALUE_MAX - 1, "%d", atoi(dnschange) + 1);
michael@0 1215 property_set("net.dnschange", num);
michael@0 1216
michael@0 1217 // DNS needs to be set through netd since JellyBean (4.3).
michael@0 1218 if (SDK_VERSION >= 18) {
michael@0 1219 RUN_CHAIN(aOptions, sSetDnsChain, setDnsFail)
michael@0 1220 }
michael@0 1221
michael@0 1222 return true;
michael@0 1223 }
michael@0 1224
michael@0 1225 /**
michael@0 1226 * Set default route and DNS servers for given network interface.
michael@0 1227 */
michael@0 1228 bool NetworkUtils::setDefaultRouteAndDNS(NetworkParams& aOptions)
michael@0 1229 {
michael@0 1230 NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
michael@0 1231
michael@0 1232 if (!aOptions.mOldIfname.IsEmpty()) {
michael@0 1233 // Remove IPv4's default route.
michael@0 1234 mNetUtils->do_ifc_remove_default_route(GET_CHAR(mOldIfname));
michael@0 1235 // Remove IPv6's default route.
michael@0 1236 mNetUtils->do_ifc_remove_route(GET_CHAR(mOldIfname), "::", 0, NULL);
michael@0 1237 }
michael@0 1238
michael@0 1239 uint32_t length = aOptions.mGateways.Length();
michael@0 1240 if (length > 0) {
michael@0 1241 for (uint32_t i = 0; i < length; i++) {
michael@0 1242 NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[i]);
michael@0 1243
michael@0 1244 int type = getIpType(autoGateway.get());
michael@0 1245 if (type != AF_INET && type != AF_INET6) {
michael@0 1246 continue;
michael@0 1247 }
michael@0 1248
michael@0 1249 if (type == AF_INET6) {
michael@0 1250 mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, autoGateway.get());
michael@0 1251 } else { /* type == AF_INET */
michael@0 1252 mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(autoGateway.get()));
michael@0 1253 }
michael@0 1254 }
michael@0 1255 } else {
michael@0 1256 // Set default froute from system properties.
michael@0 1257 char key[PROPERTY_KEY_MAX];
michael@0 1258 char gateway[PROPERTY_KEY_MAX];
michael@0 1259
michael@0 1260 snprintf(key, sizeof key - 1, "net.%s.gw", autoIfname.get());
michael@0 1261 property_get(key, gateway, "");
michael@0 1262
michael@0 1263 int type = getIpType(gateway);
michael@0 1264 if (type != AF_INET && type != AF_INET6) {
michael@0 1265 return false;
michael@0 1266 }
michael@0 1267
michael@0 1268 if (type == AF_INET6) {
michael@0 1269 mNetUtils->do_ifc_add_route(autoIfname.get(), "::", 0, gateway);
michael@0 1270 } else { /* type == AF_INET */
michael@0 1271 mNetUtils->do_ifc_set_default_route(autoIfname.get(), inet_addr(gateway));
michael@0 1272 }
michael@0 1273 }
michael@0 1274
michael@0 1275 setDNS(aOptions);
michael@0 1276 return true;
michael@0 1277 }
michael@0 1278
michael@0 1279 /**
michael@0 1280 * Remove default route for given network interface.
michael@0 1281 */
michael@0 1282 bool NetworkUtils::removeDefaultRoute(NetworkParams& aOptions)
michael@0 1283 {
michael@0 1284 uint32_t length = aOptions.mGateways.Length();
michael@0 1285 for (uint32_t i = 0; i < length; i++) {
michael@0 1286 NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[i]);
michael@0 1287
michael@0 1288 int type = getIpType(autoGateway.get());
michael@0 1289 if (type != AF_INET && type != AF_INET6) {
michael@0 1290 return false;
michael@0 1291 }
michael@0 1292
michael@0 1293 mNetUtils->do_ifc_remove_route(GET_CHAR(mIfname),
michael@0 1294 type == AF_INET ? "0.0.0.0" : "::",
michael@0 1295 0, autoGateway.get());
michael@0 1296 }
michael@0 1297
michael@0 1298 return true;
michael@0 1299 }
michael@0 1300
michael@0 1301 /**
michael@0 1302 * Add host route for given network interface.
michael@0 1303 */
michael@0 1304 bool NetworkUtils::addHostRoute(NetworkParams& aOptions)
michael@0 1305 {
michael@0 1306 NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
michael@0 1307 int type, prefix;
michael@0 1308
michael@0 1309 uint32_t length = aOptions.mHostnames.Length();
michael@0 1310 for (uint32_t i = 0; i < length; i++) {
michael@0 1311 NS_ConvertUTF16toUTF8 autoHostname(aOptions.mHostnames[i]);
michael@0 1312
michael@0 1313 type = getIpType(autoHostname.get());
michael@0 1314 if (type != AF_INET && type != AF_INET6) {
michael@0 1315 continue;
michael@0 1316 }
michael@0 1317
michael@0 1318 uint32_t index = selectGateway(aOptions.mGateways, type);
michael@0 1319 if (index >= aOptions.mGateways.Length()) {
michael@0 1320 continue;
michael@0 1321 }
michael@0 1322
michael@0 1323 NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[index]);
michael@0 1324 prefix = type == AF_INET ? 32 : 128;
michael@0 1325 mNetUtils->do_ifc_add_route(autoIfname.get(), autoHostname.get(), prefix,
michael@0 1326 autoGateway.get());
michael@0 1327 }
michael@0 1328 return true;
michael@0 1329 }
michael@0 1330
michael@0 1331 /**
michael@0 1332 * Remove host route for given network interface.
michael@0 1333 */
michael@0 1334 bool NetworkUtils::removeHostRoute(NetworkParams& aOptions)
michael@0 1335 {
michael@0 1336 NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
michael@0 1337 int type, prefix;
michael@0 1338
michael@0 1339 uint32_t length = aOptions.mHostnames.Length();
michael@0 1340 for (uint32_t i = 0; i < length; i++) {
michael@0 1341 NS_ConvertUTF16toUTF8 autoHostname(aOptions.mHostnames[i]);
michael@0 1342
michael@0 1343 type = getIpType(autoHostname.get());
michael@0 1344 if (type != AF_INET && type != AF_INET6) {
michael@0 1345 continue;
michael@0 1346 }
michael@0 1347
michael@0 1348 uint32_t index = selectGateway(aOptions.mGateways, type);
michael@0 1349 if (index >= aOptions.mGateways.Length()) {
michael@0 1350 continue;
michael@0 1351 }
michael@0 1352
michael@0 1353 NS_ConvertUTF16toUTF8 autoGateway(aOptions.mGateways[index]);
michael@0 1354 prefix = type == AF_INET ? 32 : 128;
michael@0 1355 mNetUtils->do_ifc_remove_route(autoIfname.get(), autoHostname.get(), prefix,
michael@0 1356 autoGateway.get());
michael@0 1357 }
michael@0 1358 return true;
michael@0 1359 }
michael@0 1360
michael@0 1361 /**
michael@0 1362 * Remove the routes associated with the named interface.
michael@0 1363 */
michael@0 1364 bool NetworkUtils::removeHostRoutes(NetworkParams& aOptions)
michael@0 1365 {
michael@0 1366 mNetUtils->do_ifc_remove_host_routes(GET_CHAR(mIfname));
michael@0 1367 return true;
michael@0 1368 }
michael@0 1369
michael@0 1370 bool NetworkUtils::removeNetworkRoute(NetworkParams& aOptions)
michael@0 1371 {
michael@0 1372 NS_ConvertUTF16toUTF8 autoIfname(aOptions.mIfname);
michael@0 1373 NS_ConvertUTF16toUTF8 autoIp(aOptions.mIp);
michael@0 1374
michael@0 1375 int type = getIpType(autoIp.get());
michael@0 1376 if (type != AF_INET && type != AF_INET6) {
michael@0 1377 return false;
michael@0 1378 }
michael@0 1379
michael@0 1380 uint32_t prefixLength = GET_FIELD(mPrefixLength);
michael@0 1381
michael@0 1382 if (type == AF_INET6) {
michael@0 1383 // Calculate subnet.
michael@0 1384 struct in6_addr in6;
michael@0 1385 if (inet_pton(AF_INET6, autoIp.get(), &in6) != 1) {
michael@0 1386 return false;
michael@0 1387 }
michael@0 1388
michael@0 1389 uint32_t p, i, p1, mask;
michael@0 1390 p = prefixLength;
michael@0 1391 i = 0;
michael@0 1392 while (i < 4) {
michael@0 1393 p1 = p > 32 ? 32 : p;
michael@0 1394 p -= p1;
michael@0 1395 mask = p1 ? ~0x0 << (32 - p1) : 0;
michael@0 1396 in6.s6_addr32[i++] &= htonl(mask);
michael@0 1397 }
michael@0 1398
michael@0 1399 char subnetStr[INET6_ADDRSTRLEN];
michael@0 1400 if (!inet_ntop(AF_INET6, &in6, subnetStr, sizeof subnetStr)) {
michael@0 1401 return false;
michael@0 1402 }
michael@0 1403
michael@0 1404 // Remove default route.
michael@0 1405 mNetUtils->do_ifc_remove_route(autoIfname.get(), "::", 0, NULL);
michael@0 1406
michael@0 1407 // Remove subnet route.
michael@0 1408 mNetUtils->do_ifc_remove_route(autoIfname.get(), subnetStr, prefixLength, NULL);
michael@0 1409 return true;
michael@0 1410 }
michael@0 1411
michael@0 1412 /* type == AF_INET */
michael@0 1413 uint32_t ip = inet_addr(autoIp.get());
michael@0 1414 uint32_t netmask = makeMask(prefixLength);
michael@0 1415 uint32_t subnet = ip & netmask;
michael@0 1416 const char* gateway = "0.0.0.0";
michael@0 1417 struct in_addr addr;
michael@0 1418 addr.s_addr = subnet;
michael@0 1419 const char* dst = inet_ntoa(addr);
michael@0 1420
michael@0 1421 mNetUtils->do_ifc_remove_default_route(autoIfname.get());
michael@0 1422 mNetUtils->do_ifc_remove_route(autoIfname.get(), dst, prefixLength, gateway);
michael@0 1423 return true;
michael@0 1424 }
michael@0 1425
michael@0 1426 bool NetworkUtils::addSecondaryRoute(NetworkParams& aOptions)
michael@0 1427 {
michael@0 1428 char command[MAX_COMMAND_SIZE];
michael@0 1429 snprintf(command, MAX_COMMAND_SIZE - 1,
michael@0 1430 "interface route add %s secondary %s %s %s",
michael@0 1431 GET_CHAR(mIfname),
michael@0 1432 GET_CHAR(mIp),
michael@0 1433 GET_CHAR(mPrefix),
michael@0 1434 GET_CHAR(mGateway));
michael@0 1435
michael@0 1436 doCommand(command, nullptr, nullptr);
michael@0 1437 return true;
michael@0 1438 }
michael@0 1439
michael@0 1440 bool NetworkUtils::removeSecondaryRoute(NetworkParams& aOptions)
michael@0 1441 {
michael@0 1442 char command[MAX_COMMAND_SIZE];
michael@0 1443 snprintf(command, MAX_COMMAND_SIZE - 1,
michael@0 1444 "interface route remove %s secondary %s %s %s",
michael@0 1445 GET_CHAR(mIfname),
michael@0 1446 GET_CHAR(mIp),
michael@0 1447 GET_CHAR(mPrefix),
michael@0 1448 GET_CHAR(mGateway));
michael@0 1449
michael@0 1450 doCommand(command, nullptr, nullptr);
michael@0 1451 return true;
michael@0 1452 }
michael@0 1453
michael@0 1454 bool NetworkUtils::getNetworkInterfaceStats(NetworkParams& aOptions)
michael@0 1455 {
michael@0 1456 DEBUG("getNetworkInterfaceStats: %s", GET_CHAR(mIfname));
michael@0 1457 aOptions.mRxBytes = -1;
michael@0 1458 aOptions.mTxBytes = -1;
michael@0 1459
michael@0 1460 RUN_CHAIN(aOptions, sNetworkInterfaceStatsChain, networkInterfaceStatsFail);
michael@0 1461 return true;
michael@0 1462 }
michael@0 1463
michael@0 1464 bool NetworkUtils::setNetworkInterfaceAlarm(NetworkParams& aOptions)
michael@0 1465 {
michael@0 1466 DEBUG("setNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
michael@0 1467 RUN_CHAIN(aOptions, sNetworkInterfaceSetAlarmChain, networkInterfaceAlarmFail);
michael@0 1468 return true;
michael@0 1469 }
michael@0 1470
michael@0 1471 bool NetworkUtils::enableNetworkInterfaceAlarm(NetworkParams& aOptions)
michael@0 1472 {
michael@0 1473 DEBUG("enableNetworkInterfaceAlarm: %s", GET_CHAR(mIfname));
michael@0 1474 RUN_CHAIN(aOptions, sNetworkInterfaceEnableAlarmChain, networkInterfaceAlarmFail);
michael@0 1475 return true;
michael@0 1476 }
michael@0 1477
michael@0 1478 bool NetworkUtils::disableNetworkInterfaceAlarm(NetworkParams& aOptions)
michael@0 1479 {
michael@0 1480 DEBUG("disableNetworkInterfaceAlarms: %s", GET_CHAR(mIfname));
michael@0 1481 RUN_CHAIN(aOptions, sNetworkInterfaceDisableAlarmChain, networkInterfaceAlarmFail);
michael@0 1482 return true;
michael@0 1483 }
michael@0 1484
michael@0 1485 /**
michael@0 1486 * handling main thread's reload Wifi firmware request
michael@0 1487 */
michael@0 1488 bool NetworkUtils::setWifiOperationMode(NetworkParams& aOptions)
michael@0 1489 {
michael@0 1490 DEBUG("setWifiOperationMode: %s %s", GET_CHAR(mIfname), GET_CHAR(mMode));
michael@0 1491 RUN_CHAIN(aOptions, sWifiOperationModeChain, wifiOperationModeFail);
michael@0 1492 return true;
michael@0 1493 }
michael@0 1494
michael@0 1495 /**
michael@0 1496 * handling main thread's enable/disable WiFi Tethering request
michael@0 1497 */
michael@0 1498 bool NetworkUtils::setWifiTethering(NetworkParams& aOptions)
michael@0 1499 {
michael@0 1500 bool enable = aOptions.mEnable;
michael@0 1501 IFProperties interfaceProperties;
michael@0 1502 getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
michael@0 1503
michael@0 1504 if (strcmp(interfaceProperties.dns1, "")) {
michael@0 1505 aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
michael@0 1506 }
michael@0 1507 if (strcmp(interfaceProperties.dns2, "")) {
michael@0 1508 aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
michael@0 1509 }
michael@0 1510 dumpParams(aOptions, "WIFI");
michael@0 1511
michael@0 1512 if (enable) {
michael@0 1513 DEBUG("Starting Wifi Tethering on %s <-> %s",
michael@0 1514 GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
michael@0 1515 RUN_CHAIN(aOptions, sWifiEnableChain, wifiTetheringFail)
michael@0 1516 } else {
michael@0 1517 DEBUG("Stopping Wifi Tethering on %s <-> %s",
michael@0 1518 GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
michael@0 1519 RUN_CHAIN(aOptions, sWifiDisableChain, wifiTetheringFail)
michael@0 1520 }
michael@0 1521 return true;
michael@0 1522 }
michael@0 1523
michael@0 1524 bool NetworkUtils::setUSBTethering(NetworkParams& aOptions)
michael@0 1525 {
michael@0 1526 bool enable = aOptions.mEnable;
michael@0 1527 IFProperties interfaceProperties;
michael@0 1528 getIFProperties(GET_CHAR(mExternalIfname), interfaceProperties);
michael@0 1529
michael@0 1530 if (strcmp(interfaceProperties.dns1, "")) {
michael@0 1531 aOptions.mDns1 = NS_ConvertUTF8toUTF16(interfaceProperties.dns1);
michael@0 1532 }
michael@0 1533 if (strcmp(interfaceProperties.dns2, "")) {
michael@0 1534 aOptions.mDns2 = NS_ConvertUTF8toUTF16(interfaceProperties.dns2);
michael@0 1535 }
michael@0 1536 dumpParams(aOptions, "USB");
michael@0 1537
michael@0 1538 if (enable) {
michael@0 1539 DEBUG("Starting USB Tethering on %s <-> %s",
michael@0 1540 GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
michael@0 1541 RUN_CHAIN(aOptions, sUSBEnableChain, usbTetheringFail)
michael@0 1542 } else {
michael@0 1543 DEBUG("Stopping USB Tethering on %s <-> %s",
michael@0 1544 GET_CHAR(mInternalIfname), GET_CHAR(mExternalIfname));
michael@0 1545 RUN_CHAIN(aOptions, sUSBDisableChain, usbTetheringFail)
michael@0 1546 }
michael@0 1547 return true;
michael@0 1548 }
michael@0 1549
michael@0 1550 void NetworkUtils::escapeQuote(nsCString& aString)
michael@0 1551 {
michael@0 1552 aString.ReplaceSubstring("\\", "\\\\");
michael@0 1553 aString.ReplaceSubstring("\"", "\\\"");
michael@0 1554 }
michael@0 1555
michael@0 1556 void NetworkUtils::checkUsbRndisState(NetworkParams& aOptions)
michael@0 1557 {
michael@0 1558 static uint32_t retry = 0;
michael@0 1559
michael@0 1560 char currentState[PROPERTY_VALUE_MAX];
michael@0 1561 property_get(SYS_USB_STATE_PROPERTY, currentState, nullptr);
michael@0 1562
michael@0 1563 nsTArray<nsCString> stateFuncs;
michael@0 1564 split(currentState, USB_CONFIG_DELIMIT, stateFuncs);
michael@0 1565 bool rndisPresent = stateFuncs.Contains(nsCString(USB_FUNCTION_RNDIS));
michael@0 1566
michael@0 1567 if (aOptions.mEnable == rndisPresent) {
michael@0 1568 NetworkResultOptions result;
michael@0 1569 result.mEnable = aOptions.mEnable;
michael@0 1570 result.mResult = true;
michael@0 1571 postMessage(aOptions, result);
michael@0 1572 retry = 0;
michael@0 1573 return;
michael@0 1574 }
michael@0 1575 if (retry < USB_FUNCTION_RETRY_TIMES) {
michael@0 1576 retry++;
michael@0 1577 usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
michael@0 1578 checkUsbRndisState(aOptions);
michael@0 1579 return;
michael@0 1580 }
michael@0 1581
michael@0 1582 NetworkResultOptions result;
michael@0 1583 result.mResult = false;
michael@0 1584 postMessage(aOptions, result);
michael@0 1585 retry = 0;
michael@0 1586 }
michael@0 1587
michael@0 1588 /**
michael@0 1589 * Modify usb function's property to turn on USB RNDIS function
michael@0 1590 */
michael@0 1591 bool NetworkUtils::enableUsbRndis(NetworkParams& aOptions)
michael@0 1592 {
michael@0 1593 bool report = aOptions.mReport;
michael@0 1594
michael@0 1595 // For some reason, rndis doesn't play well with diag,modem,nmea.
michael@0 1596 // So when turning rndis on, we set sys.usb.config to either "rndis"
michael@0 1597 // or "rndis,adb". When turning rndis off, we go back to
michael@0 1598 // persist.sys.usb.config.
michael@0 1599 //
michael@0 1600 // On the otoro/unagi, persist.sys.usb.config should be one of:
michael@0 1601 //
michael@0 1602 // diag,modem,nmea,mass_storage
michael@0 1603 // diag,modem,nmea,mass_storage,adb
michael@0 1604 //
michael@0 1605 // When rndis is enabled, sys.usb.config should be one of:
michael@0 1606 //
michael@0 1607 // rdnis
michael@0 1608 // rndis,adb
michael@0 1609 //
michael@0 1610 // and when rndis is disabled, it should revert to persist.sys.usb.config
michael@0 1611
michael@0 1612 char currentConfig[PROPERTY_VALUE_MAX];
michael@0 1613 property_get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
michael@0 1614
michael@0 1615 nsTArray<nsCString> configFuncs;
michael@0 1616 split(currentConfig, USB_CONFIG_DELIMIT, configFuncs);
michael@0 1617
michael@0 1618 char persistConfig[PROPERTY_VALUE_MAX];
michael@0 1619 property_get(PERSIST_SYS_USB_CONFIG_PROPERTY, persistConfig, nullptr);
michael@0 1620
michael@0 1621 nsTArray<nsCString> persistFuncs;
michael@0 1622 split(persistConfig, USB_CONFIG_DELIMIT, persistFuncs);
michael@0 1623
michael@0 1624 if (aOptions.mEnable) {
michael@0 1625 configFuncs.Clear();
michael@0 1626 configFuncs.AppendElement(nsCString(USB_FUNCTION_RNDIS));
michael@0 1627 if (persistFuncs.Contains(nsCString(USB_FUNCTION_ADB))) {
michael@0 1628 configFuncs.AppendElement(nsCString(USB_FUNCTION_ADB));
michael@0 1629 }
michael@0 1630 } else {
michael@0 1631 // We're turning rndis off, revert back to the persist setting.
michael@0 1632 // adb will already be correct there, so we don't need to do any
michael@0 1633 // further adjustments.
michael@0 1634 configFuncs = persistFuncs;
michael@0 1635 }
michael@0 1636
michael@0 1637 char newConfig[PROPERTY_VALUE_MAX] = "";
michael@0 1638 property_get(SYS_USB_CONFIG_PROPERTY, currentConfig, nullptr);
michael@0 1639 join(configFuncs, USB_CONFIG_DELIMIT, PROPERTY_VALUE_MAX, newConfig);
michael@0 1640 if (strcmp(currentConfig, newConfig)) {
michael@0 1641 property_set(SYS_USB_CONFIG_PROPERTY, newConfig);
michael@0 1642 }
michael@0 1643
michael@0 1644 // Trigger the timer to check usb state and report the result to NetworkManager.
michael@0 1645 if (report) {
michael@0 1646 usleep(USB_FUNCTION_RETRY_INTERVAL * 1000);
michael@0 1647 checkUsbRndisState(aOptions);
michael@0 1648 }
michael@0 1649 return true;
michael@0 1650 }
michael@0 1651
michael@0 1652 /**
michael@0 1653 * handling upstream interface change event.
michael@0 1654 */
michael@0 1655 bool NetworkUtils::updateUpStream(NetworkParams& aOptions)
michael@0 1656 {
michael@0 1657 RUN_CHAIN(aOptions, sUpdateUpStreamChain, updateUpStreamFail)
michael@0 1658 return true;
michael@0 1659 }
michael@0 1660
michael@0 1661 void NetworkUtils::sendBroadcastMessage(uint32_t code, char* reason)
michael@0 1662 {
michael@0 1663 NetworkResultOptions result;
michael@0 1664 switch(code) {
michael@0 1665 case NETD_COMMAND_INTERFACE_CHANGE:
michael@0 1666 result.mTopic = NS_ConvertUTF8toUTF16("netd-interface-change");
michael@0 1667 break;
michael@0 1668 case NETD_COMMAND_BANDWIDTH_CONTROLLER:
michael@0 1669 result.mTopic = NS_ConvertUTF8toUTF16("netd-bandwidth-control");
michael@0 1670 break;
michael@0 1671 default:
michael@0 1672 return;
michael@0 1673 }
michael@0 1674
michael@0 1675 result.mBroadcast = true;
michael@0 1676 result.mReason = NS_ConvertUTF8toUTF16(reason);
michael@0 1677 postMessage(result);
michael@0 1678 }
michael@0 1679
michael@0 1680 inline uint32_t NetworkUtils::netdResponseType(uint32_t code)
michael@0 1681 {
michael@0 1682 return (code / 100) * 100;
michael@0 1683 }
michael@0 1684
michael@0 1685 inline bool NetworkUtils::isBroadcastMessage(uint32_t code)
michael@0 1686 {
michael@0 1687 uint32_t type = netdResponseType(code);
michael@0 1688 return type == NETD_COMMAND_UNSOLICITED;
michael@0 1689 }
michael@0 1690
michael@0 1691 inline bool NetworkUtils::isError(uint32_t code)
michael@0 1692 {
michael@0 1693 uint32_t type = netdResponseType(code);
michael@0 1694 return type != NETD_COMMAND_PROCEEDING && type != NETD_COMMAND_OKAY;
michael@0 1695 }
michael@0 1696
michael@0 1697 inline bool NetworkUtils::isComplete(uint32_t code)
michael@0 1698 {
michael@0 1699 uint32_t type = netdResponseType(code);
michael@0 1700 return type != NETD_COMMAND_PROCEEDING;
michael@0 1701 }
michael@0 1702
michael@0 1703 inline bool NetworkUtils::isProceeding(uint32_t code)
michael@0 1704 {
michael@0 1705 uint32_t type = netdResponseType(code);
michael@0 1706 return type == NETD_COMMAND_PROCEEDING;
michael@0 1707 }
michael@0 1708
michael@0 1709 void NetworkUtils::dumpParams(NetworkParams& aOptions, const char* aType)
michael@0 1710 {
michael@0 1711 #ifdef _DEBUG
michael@0 1712 DEBUG("Dump params:");
michael@0 1713 DEBUG(" ifname: %s", GET_CHAR(mIfname));
michael@0 1714 DEBUG(" ip: %s", GET_CHAR(mIp));
michael@0 1715 DEBUG(" link: %s", GET_CHAR(mLink));
michael@0 1716 DEBUG(" prefix: %s", GET_CHAR(mPrefix));
michael@0 1717 DEBUG(" wifiStartIp: %s", GET_CHAR(mWifiStartIp));
michael@0 1718 DEBUG(" wifiEndIp: %s", GET_CHAR(mWifiEndIp));
michael@0 1719 DEBUG(" usbStartIp: %s", GET_CHAR(mUsbStartIp));
michael@0 1720 DEBUG(" usbEndIp: %s", GET_CHAR(mUsbEndIp));
michael@0 1721 DEBUG(" dnsserver1: %s", GET_CHAR(mDns1));
michael@0 1722 DEBUG(" dnsserver2: %s", GET_CHAR(mDns2));
michael@0 1723 DEBUG(" internalIfname: %s", GET_CHAR(mInternalIfname));
michael@0 1724 DEBUG(" externalIfname: %s", GET_CHAR(mExternalIfname));
michael@0 1725 if (!strcmp(aType, "WIFI")) {
michael@0 1726 DEBUG(" wifictrlinterfacename: %s", GET_CHAR(mWifictrlinterfacename));
michael@0 1727 DEBUG(" ssid: %s", GET_CHAR(mSsid));
michael@0 1728 DEBUG(" security: %s", GET_CHAR(mSecurity));
michael@0 1729 DEBUG(" key: %s", GET_CHAR(mKey));
michael@0 1730 }
michael@0 1731 #endif
michael@0 1732 }
michael@0 1733
michael@0 1734 #undef GET_CHAR
michael@0 1735 #undef GET_FIELD

mercurial