/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef NetworkUtils_h #define NetworkUtils_h #include "nsAutoPtr.h" #include "nsString.h" #include "mozilla/dom/NetworkOptionsBinding.h" #include "mozilla/dom/network/NetUtils.h" #include "mozilla/ipc/Netd.h" #include "nsTArray.h" #include "NetIdManager.h" class NetworkParams; class CommandChain; class CommandCallback { public: typedef void (*CallbackType)(CommandChain*, bool, mozilla::dom::NetworkResultOptions& aResult); typedef void (*CallbackWrapperType)(CallbackType aOriginalCallback, CommandChain*, bool, mozilla::dom::NetworkResultOptions& aResult); CommandCallback() : mCallback(nullptr) , mCallbackWrapper(nullptr) { } CommandCallback(CallbackType aCallback) : mCallback(aCallback) , mCallbackWrapper(nullptr) { } CommandCallback(CallbackWrapperType aCallbackWrapper, CommandCallback aOriginalCallback) : mCallback(aOriginalCallback.mCallback) , mCallbackWrapper(aCallbackWrapper) { } void operator()(CommandChain* aChain, bool aError, mozilla::dom::NetworkResultOptions& aResult) { if (mCallbackWrapper) { return mCallbackWrapper(mCallback, aChain, aError, aResult); } if (mCallback) { return mCallback(aChain, aError, aResult); } } private: CallbackType mCallback; CallbackWrapperType mCallbackWrapper; }; typedef void (*CommandFunc)(CommandChain*, CommandCallback, mozilla::dom::NetworkResultOptions& aResult); typedef void (*MessageCallback)(mozilla::dom::NetworkResultOptions& aResult); typedef void (*ErrorCallback)(NetworkParams& aOptions, mozilla::dom::NetworkResultOptions& aResult); class NetworkParams { public: NetworkParams() { } NetworkParams(const mozilla::dom::NetworkCommandOptions& aOther) { #define COPY_SEQUENCE_FIELD(prop, type) \ if (aOther.prop.WasPassed()) { \ mozilla::dom::Sequence<type > const & currentValue = aOther.prop.InternalValue(); \ uint32_t length = currentValue.Length(); \ for (uint32_t idx = 0; idx < length; idx++) { \ prop.AppendElement(currentValue[idx]); \ } \ } #define COPY_OPT_STRING_FIELD(prop, defaultValue) \ if (aOther.prop.WasPassed()) { \ if (aOther.prop.Value().EqualsLiteral("null")) { \ prop = defaultValue; \ } else { \ prop = aOther.prop.Value(); \ } \ } else { \ prop = defaultValue; \ } #define COPY_OPT_FIELD(prop, defaultValue) \ if (aOther.prop.WasPassed()) { \ prop = aOther.prop.Value(); \ } else { \ prop = defaultValue; \ } #define COPY_FIELD(prop) prop = aOther.prop; COPY_FIELD(mId) COPY_FIELD(mCmd) COPY_OPT_STRING_FIELD(mDomain, EmptyString()) COPY_OPT_STRING_FIELD(mGateway, EmptyString()) COPY_SEQUENCE_FIELD(mGateways, nsString) COPY_OPT_STRING_FIELD(mIfname, EmptyString()) COPY_OPT_STRING_FIELD(mIp, EmptyString()) COPY_OPT_FIELD(mPrefixLength, 0) COPY_OPT_STRING_FIELD(mMode, EmptyString()) COPY_OPT_FIELD(mReport, false) COPY_OPT_FIELD(mEnabled, false) COPY_OPT_STRING_FIELD(mWifictrlinterfacename, EmptyString()) COPY_OPT_STRING_FIELD(mInternalIfname, EmptyString()) COPY_OPT_STRING_FIELD(mExternalIfname, EmptyString()) COPY_OPT_FIELD(mEnable, false) COPY_OPT_STRING_FIELD(mSsid, EmptyString()) COPY_OPT_STRING_FIELD(mSecurity, EmptyString()) COPY_OPT_STRING_FIELD(mKey, EmptyString()) COPY_OPT_STRING_FIELD(mPrefix, EmptyString()) COPY_OPT_STRING_FIELD(mLink, EmptyString()) COPY_SEQUENCE_FIELD(mInterfaceList, nsString) COPY_OPT_STRING_FIELD(mWifiStartIp, EmptyString()) COPY_OPT_STRING_FIELD(mWifiEndIp, EmptyString()) COPY_OPT_STRING_FIELD(mUsbStartIp, EmptyString()) COPY_OPT_STRING_FIELD(mUsbEndIp, EmptyString()) COPY_OPT_STRING_FIELD(mDns1, EmptyString()) COPY_OPT_STRING_FIELD(mDns2, EmptyString()) COPY_SEQUENCE_FIELD(mDnses, nsString) COPY_OPT_STRING_FIELD(mStartIp, EmptyString()) COPY_OPT_STRING_FIELD(mEndIp, EmptyString()) COPY_OPT_STRING_FIELD(mServerIp, EmptyString()) COPY_OPT_STRING_FIELD(mMaskLength, EmptyString()) COPY_OPT_STRING_FIELD(mPreInternalIfname, EmptyString()) COPY_OPT_STRING_FIELD(mPreExternalIfname, EmptyString()) COPY_OPT_STRING_FIELD(mCurInternalIfname, EmptyString()) COPY_OPT_STRING_FIELD(mCurExternalIfname, EmptyString()) COPY_OPT_FIELD(mThreshold, -1) COPY_OPT_FIELD(mIpaddr, 0) COPY_OPT_FIELD(mMask, 0) COPY_OPT_FIELD(mGateway_long, 0) COPY_OPT_FIELD(mDns1_long, 0) COPY_OPT_FIELD(mDns2_long, 0) COPY_OPT_FIELD(mMtu, 0) mLoopIndex = 0; #undef COPY_SEQUENCE_FIELD #undef COPY_OPT_STRING_FIELD #undef COPY_OPT_FIELD #undef COPY_FIELD } // Followings attributes are 1-to-1 mapping to NetworkCommandOptions. int32_t mId; nsString mCmd; nsString mDomain; nsString mGateway; nsTArray<nsString> mGateways; nsString mIfname; nsString mIp; uint32_t mPrefixLength; nsString mMode; bool mReport; bool mEnabled; nsString mWifictrlinterfacename; nsString mInternalIfname; nsString mExternalIfname; bool mEnable; nsString mSsid; nsString mSecurity; nsString mKey; nsString mPrefix; nsString mLink; nsTArray<nsString> mInterfaceList; nsString mWifiStartIp; nsString mWifiEndIp; nsString mUsbStartIp; nsString mUsbEndIp; nsString mDns1; nsString mDns2; nsTArray<nsString> mDnses; nsString mStartIp; nsString mEndIp; nsString mServerIp; nsString mMaskLength; nsString mPreInternalIfname; nsString mPreExternalIfname; nsString mCurInternalIfname; nsString mCurExternalIfname; long long mThreshold; long mIpaddr; long mMask; long mGateway_long; long mDns1_long; long mDns2_long; long mMtu; // Auxiliary information required to carry accros command chain. int mNetId; // A locally defined id per interface. uint32_t mLoopIndex; // Loop index for adding/removing multiple gateways. }; // CommandChain store the necessary information to execute command one by one. // Including : // 1. Command parameters. // 2. Command list. // 3. Error callback function. // 4. Index of current execution command. class CommandChain final { public: CommandChain(const NetworkParams& aParams, const CommandFunc aCmds[], uint32_t aLength, ErrorCallback aError) : mIndex(-1) , mParams(aParams) , mCommands(aCmds) , mLength(aLength) , mError(aError) { } NetworkParams& getParams() { return mParams; }; CommandFunc getNextCommand() { mIndex++; return mIndex < mLength ? mCommands[mIndex] : nullptr; }; ErrorCallback getErrorCallback() const { return mError; }; private: uint32_t mIndex; NetworkParams mParams; const CommandFunc* mCommands; uint32_t mLength; ErrorCallback mError; }; // A helper class to easily construct a resolved // or a pending result for command execution. class CommandResult { public: struct Pending {}; public: CommandResult(int32_t aResultCode); CommandResult(const mozilla::dom::NetworkResultOptions& aResult); CommandResult(const Pending&); bool isPending() const; mozilla::dom::NetworkResultOptions mResult; private: bool mIsPending; }; class NetworkUtils final { public: NetworkUtils(MessageCallback aCallback); ~NetworkUtils(); void ExecuteCommand(NetworkParams aOptions); void onNetdMessage(mozilla::ipc::NetdCommand* aCommand); MessageCallback getMessageCallback() { return mMessageCallback; } private: /** * Commands supported by NetworkUtils. */ CommandResult configureInterface(NetworkParams& aOptions); CommandResult dhcpRequest(NetworkParams& aOptions); CommandResult stopDhcp(NetworkParams& aOptions); CommandResult enableInterface(NetworkParams& aOptions); CommandResult disableInterface(NetworkParams& aOptions); CommandResult resetConnections(NetworkParams& aOptions); CommandResult setDefaultRoute(NetworkParams& aOptions); CommandResult addHostRoute(NetworkParams& aOptions); CommandResult removeDefaultRoute(NetworkParams& aOptions); CommandResult removeHostRoute(NetworkParams& aOptions); CommandResult removeNetworkRoute(NetworkParams& aOptions); CommandResult setDNS(NetworkParams& aOptions); CommandResult addSecondaryRoute(NetworkParams& aOptions); CommandResult removeSecondaryRoute(NetworkParams& aOptions); CommandResult setNetworkInterfaceAlarm(NetworkParams& aOptions); CommandResult enableNetworkInterfaceAlarm(NetworkParams& aOptions); CommandResult disableNetworkInterfaceAlarm(NetworkParams& aOptions); CommandResult setTetheringAlarm(NetworkParams& aOptions); CommandResult removeTetheringAlarm(NetworkParams& aOptions); CommandResult getTetheringStatus(NetworkParams& aOptions); CommandResult setWifiOperationMode(NetworkParams& aOptions); CommandResult setDhcpServer(NetworkParams& aOptions); CommandResult setWifiTethering(NetworkParams& aOptions); CommandResult setUSBTethering(NetworkParams& aOptions); CommandResult enableUsbRndis(NetworkParams& aOptions); CommandResult updateUpStream(NetworkParams& aOptions); CommandResult createNetwork(NetworkParams& aOptions); CommandResult destroyNetwork(NetworkParams& aOptions); CommandResult getNetId(NetworkParams& aOptions); CommandResult setMtu(NetworkParams& aOptions); CommandResult getInterfaces(NetworkParams& aOptions); CommandResult getInterfaceConfig(NetworkParams& aOptions); CommandResult setInterfaceConfig(NetworkParams& aOptions); CommandResult addHostRouteLegacy(NetworkParams& aOptions); CommandResult removeHostRouteLegacy(NetworkParams& aOptions); CommandResult setDefaultRouteLegacy(NetworkParams& aOptions); CommandResult removeDefaultRouteLegacy(NetworkParams& aOptions); CommandResult removeNetworkRouteLegacy(NetworkParams& aOptions); /** * function pointer array holds all netd commands should be executed * in sequence to accomplish a given command by other module. */ static const CommandFunc sWifiEnableChain[]; static const CommandFunc sWifiDisableChain[]; static const CommandFunc sWifiFailChain[]; static const CommandFunc sWifiRetryChain[]; static const CommandFunc sWifiOperationModeChain[]; static const CommandFunc sUSBEnableChain[]; static const CommandFunc sUSBDisableChain[]; static const CommandFunc sUSBFailChain[]; static const CommandFunc sUpdateUpStreamChain[]; static const CommandFunc sStartDhcpServerChain[]; static const CommandFunc sStopDhcpServerChain[]; static const CommandFunc sNetworkInterfaceEnableAlarmChain[]; static const CommandFunc sNetworkInterfaceDisableAlarmChain[]; static const CommandFunc sNetworkInterfaceSetAlarmChain[]; static const CommandFunc sTetheringInterfaceSetAlarmChain[]; static const CommandFunc sTetheringInterfaceRemoveAlarmChain[]; static const CommandFunc sTetheringGetStatusChain[]; static const CommandFunc sGetInterfacesChain[]; static const CommandFunc sGetInterfaceConfigChain[]; static const CommandFunc sSetInterfaceConfigChain[]; /** * Individual netd command stored in command chain. */ #define PARAMS CommandChain* aChain, CommandCallback aCallback, \ mozilla::dom::NetworkResultOptions& aResult static void wifiFirmwareReload(PARAMS); static void startAccessPointDriver(PARAMS); static void stopAccessPointDriver(PARAMS); static void setAccessPoint(PARAMS); static void cleanUpStream(PARAMS); static void createUpStream(PARAMS); static void startSoftAP(PARAMS); static void stopSoftAP(PARAMS); static void clearWifiTetherParms(PARAMS); static void enableAlarm(PARAMS); static void disableAlarm(PARAMS); static void setQuota(PARAMS); static void removeQuota(PARAMS); static void setAlarm(PARAMS); static void removeAlarm(PARAMS); static void setGlobalAlarm(PARAMS); static void removeGlobalAlarm(PARAMS); static void tetherInterface(PARAMS); static void addInterfaceToLocalNetwork(PARAMS); static void addRouteToLocalNetwork(PARAMS); static void preTetherInterfaceList(PARAMS); static void postTetherInterfaceList(PARAMS); static void addUpstreamInterface(PARAMS); static void removeUpstreamInterface(PARAMS); static void setIpForwardingEnabled(PARAMS); static void tetheringStatus(PARAMS); static void stopTethering(PARAMS); static void startTethering(PARAMS); static void untetherInterface(PARAMS); static void removeInterfaceFromLocalNetwork(PARAMS); static void setDnsForwarders(PARAMS); static void enableNat(PARAMS); static void disableNat(PARAMS); static void setDefaultInterface(PARAMS); static void setInterfaceDns(PARAMS); static void getInterfaceList(PARAMS); static void getConfig(PARAMS); static void setConfig(PARAMS); static void wifiTetheringSuccess(PARAMS); static void usbTetheringSuccess(PARAMS); static void networkInterfaceAlarmSuccess(PARAMS); static void updateUpStreamSuccess(PARAMS); static void setDhcpServerSuccess(PARAMS); static void wifiOperationModeSuccess(PARAMS); static void clearAddrForInterface(PARAMS); static void createNetwork(PARAMS); static void destroyNetwork(PARAMS); static void addInterfaceToNetwork(PARAMS); static void addDefaultRouteToNetwork(PARAMS); static void setDefaultNetwork(PARAMS); static void removeDefaultRoute(PARAMS); static void removeNetworkRouteSuccess(PARAMS); static void removeNetworkRoute(PARAMS); static void addRouteToInterface(PARAMS); static void removeRouteFromInterface(PARAMS); static void modifyRouteOnInterface(PARAMS, bool aDoAdd); static void enableIpv6(PARAMS); static void disableIpv6(PARAMS); static void setMtu(PARAMS); static void setIpv6Enabled(PARAMS, bool aEnabled); static void addRouteToSecondaryTable(PARAMS); static void removeRouteFromSecondaryTable(PARAMS); static void defaultAsyncSuccessHandler(PARAMS); static void getInterfacesSuccess(PARAMS); static void getInterfaceConfigSuccess(PARAMS); static void setInterfaceConfigSuccess(PARAMS); #undef PARAMS /** * Error callback function executed when a command is fail. */ #define PARAMS NetworkParams& aOptions, \ mozilla::dom::NetworkResultOptions& aResult static void wifiTetheringFail(PARAMS); static void wifiOperationModeFail(PARAMS); static void usbTetheringFail(PARAMS); static void updateUpStreamFail(PARAMS); static void setDhcpServerFail(PARAMS); static void networkInterfaceAlarmFail(PARAMS); static void setDnsFail(PARAMS); static void defaultAsyncFailureHandler(PARAMS); static void getInterfacesFail(PARAMS); static void getInterfaceConfigFail(PARAMS); static void setInterfaceConfigFail(PARAMS); #undef PARAMS /** * Command chain processing functions. */ static void next(CommandChain* aChain, bool aError, mozilla::dom::NetworkResultOptions& aResult); static void nextNetdCommand(); static void doCommand(const char* aCommand, CommandChain* aChain, CommandCallback aCallback); /** * Notify broadcast message to main thread. */ void sendBroadcastMessage(uint32_t code, char* reason); /** * Utility functions. */ CommandResult checkUsbRndisState(NetworkParams& aOptions); void dumpParams(NetworkParams& aOptions, const char* aType); static void escapeQuote(nsCString& aString); inline uint32_t netdResponseType(uint32_t code); inline bool isBroadcastMessage(uint32_t code); inline bool isError(uint32_t code); inline bool isComplete(uint32_t code); inline bool isProceeding(uint32_t code); void Shutdown(); static void runNextQueuedCommandChain(); static void finalizeSuccess(CommandChain* aChain, mozilla::dom::NetworkResultOptions& aResult); template<size_t N> static void runChain(const NetworkParams& aParams, const CommandFunc (&aCmds)[N], ErrorCallback aError); static nsCString getSubnetIp(const nsCString& aIp, int aPrefixLength); /** * Callback function to send netd result to main thread. */ MessageCallback mMessageCallback; /* * Utility class to access libnetutils. */ nsAutoPtr<NetUtils> mNetUtils; NetIdManager mNetIdManager; }; #endif