--- a/dom/system/gonk/NetworkUtils.cpp
+++ b/dom/system/gonk/NetworkUtils.cpp
@@ -46,16 +46,21 @@ static const char* SYS_USB_CONFIG_PROPER
static const char* SYS_USB_STATE_PROPERTY = "sys.usb.state";
static const char* USB_FUNCTION_RNDIS = "rndis";
static const char* USB_FUNCTION_ADB = "adb";
// Use this command to continue the function chain.
static const char* DUMMY_COMMAND = "tether status";
+// IPV6 Tethering is not supported in AOSP, use the property to
+// identify vendor specific support in IPV6. We can remove this flag
+// once upstream Android support IPV6 in tethering.
+static const char* IPV6_TETHERING = "ro.tethering.ipv6";
+
// Retry 20 times (2 seconds) for usb state transition.
static const uint32_t USB_FUNCTION_RETRY_TIMES = 20;
// Check "sys.usb.state" every 100ms.
static const uint32_t USB_FUNCTION_RETRY_INTERVAL = 100;
// 1xx - Requested action is proceeding
static const uint32_t NETD_COMMAND_PROCEEDING = 100;
// 2xx - Requested action has been successfully completed
@@ -76,16 +81,17 @@ static const char* INTERFACE_DELIMIT = "
static const char* USB_CONFIG_DELIMIT = ",";
static const char* NETD_MESSAGE_DELIMIT = " ";
static const uint32_t BUF_SIZE = 1024;
static const int32_t SUCCESS = 0;
static uint32_t SDK_VERSION;
+static uint32_t SUPPORT_IPV6_TETHERING;
struct IFProperties {
char gateway[PROPERTY_VALUE_MAX];
char dns1[PROPERTY_VALUE_MAX];
char dns2[PROPERTY_VALUE_MAX];
};
struct CurrentCommand {
@@ -196,39 +202,43 @@ const CommandFunc NetworkUtils::sUSBEnab
NetworkUtils::enableNat,
NetworkUtils::setIpForwardingEnabled,
NetworkUtils::tetherInterface,
NetworkUtils::addInterfaceToLocalNetwork,
NetworkUtils::addRouteToLocalNetwork,
NetworkUtils::tetheringStatus,
NetworkUtils::startTethering,
NetworkUtils::setDnsForwarders,
+ NetworkUtils::addUpstreamInterface,
NetworkUtils::usbTetheringSuccess
};
const CommandFunc NetworkUtils::sUSBDisableChain[] = {
NetworkUtils::untetherInterface,
NetworkUtils::removeInterfaceFromLocalNetwork,
NetworkUtils::preTetherInterfaceList,
NetworkUtils::postTetherInterfaceList,
+ NetworkUtils::removeUpstreamInterface,
NetworkUtils::disableNat,
NetworkUtils::setIpForwardingEnabled,
NetworkUtils::stopTethering,
NetworkUtils::usbTetheringSuccess
};
const CommandFunc NetworkUtils::sUSBFailChain[] = {
NetworkUtils::stopSoftAP,
NetworkUtils::setIpForwardingEnabled,
NetworkUtils::stopTethering
};
const CommandFunc NetworkUtils::sUpdateUpStreamChain[] = {
NetworkUtils::cleanUpStream,
+ NetworkUtils::removeUpstreamInterface,
NetworkUtils::createUpStream,
+ NetworkUtils::addUpstreamInterface,
NetworkUtils::updateUpStreamSuccess
};
const CommandFunc NetworkUtils::sStartDhcpServerChain[] = {
NetworkUtils::setInterfaceUp,
NetworkUtils::startTethering,
NetworkUtils::setDhcpServerSuccess
};
@@ -808,16 +818,89 @@ void NetworkUtils::postTetherInterfaceLi
char buf[BUF_SIZE];
NS_ConvertUTF16toUTF8 reason(aResult.mResultReason);
memcpy(buf, reason.get(), reason.Length() + 1);
split(buf, INTERFACE_DELIMIT, GET_FIELD(mInterfaceList));
doCommand(command, aChain, aCallback);
}
+bool isCommandChainIPv6(CommandChain* aChain, const char *externalInterface) {
+ // Check by gateway address
+ if (getIpType(GET_CHAR(mGateway)) == AF_INET6) {
+ return true;
+ }
+
+ uint32_t length = GET_FIELD(mGateways).Length();
+ for (uint32_t i = 0; i < length; i++) {
+ NS_ConvertUTF16toUTF8 autoGateway(GET_FIELD(mGateways)[i]);
+ if(getIpType(autoGateway.get()) == AF_INET6) {
+ return true;
+ }
+ }
+
+ // Check by external inteface address
+ FILE *file = fopen("/proc/net/if_inet6", "r");
+ if (!file) {
+ return false;
+ }
+
+ bool isIPv6 = false;
+ char interface[32];
+ while(fscanf(file, "%*s %*s %*s %*s %*s %32s", interface)) {
+ if (strcmp(interface, externalInterface) == 0) {
+ isIPv6 = true;
+ break;
+ }
+ }
+
+ fclose(file);
+ return isIPv6;
+}
+
+void NetworkUtils::addUpstreamInterface(CommandChain* aChain,
+ CommandCallback aCallback,
+ NetworkResultOptions& aResult)
+{
+ nsCString interface(GET_CHAR(mExternalIfname));
+ if (!interface.get()[0]) {
+ interface = GET_CHAR(mCurExternalIfname);
+ }
+
+ if (SUPPORT_IPV6_TETHERING == 0 || !isCommandChainIPv6(aChain, interface.get())) {
+ aCallback(aChain, false, aResult);
+ return;
+ }
+
+ char command[MAX_COMMAND_SIZE];
+ snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface add_upstream %s",
+ interface.get());
+ doCommand(command, aChain, aCallback);
+}
+
+void NetworkUtils::removeUpstreamInterface(CommandChain* aChain,
+ CommandCallback aCallback,
+ NetworkResultOptions& aResult)
+{
+ nsCString interface(GET_CHAR(mExternalIfname));
+ if (!interface.get()[0]) {
+ interface = GET_CHAR(mPreExternalIfname);
+ }
+
+ if (SUPPORT_IPV6_TETHERING == 0 || !isCommandChainIPv6(aChain, interface.get())) {
+ aCallback(aChain, false, aResult);
+ return;
+ }
+
+ char command[MAX_COMMAND_SIZE];
+ snprintf(command, MAX_COMMAND_SIZE - 1, "tether interface remove_upstream %s",
+ interface.get());
+ doCommand(command, aChain, aCallback);
+}
+
void NetworkUtils::setIpForwardingEnabled(CommandChain* aChain,
CommandCallback aCallback,
NetworkResultOptions& aResult)
{
char command[MAX_COMMAND_SIZE];
if (GET_FIELD(mEnable)) {
snprintf(command, MAX_COMMAND_SIZE - 1, "ipfwd enable");
@@ -1477,16 +1560,19 @@ NetworkUtils::NetworkUtils(MessageCallba
: mMessageCallback(aCallback)
{
mNetUtils = new NetUtils();
char value[PROPERTY_VALUE_MAX];
property_get("ro.build.version.sdk", value, nullptr);
SDK_VERSION = atoi(value);
+ property_get(IPV6_TETHERING, value, "0");
+ SUPPORT_IPV6_TETHERING = atoi(value);
+
gNetworkUtils = this;
}
NetworkUtils::~NetworkUtils()
{
}
#define GET_CHAR(prop) NS_ConvertUTF16toUTF8(aOptions.prop).get()