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