From 73e7302d0eb51bc37660713e5db17687e98a8411 Mon Sep 17 00:00:00 2001 From: Shreesha Date: Fri, 29 Sep 2017 01:15:01 -0400 Subject: [PATCH] Pull data-ipa-cfg-mgr from CAF TAG : LA.UM.6.6.r1-02700-89xx.0 --- data-ipa-cfg-mgr/Android.mk | 18 - data-ipa-cfg-mgr/configure.ac | 1 + data-ipa-cfg-mgr/hal/Android.mk | 29 + data-ipa-cfg-mgr/hal/inc/CtUpdateAmbassador.h | 62 + data-ipa-cfg-mgr/hal/inc/HAL.h | 199 + data-ipa-cfg-mgr/hal/inc/IOffloadManager.h | 350 ++ data-ipa-cfg-mgr/hal/inc/IpaEventRelay.h | 55 + data-ipa-cfg-mgr/hal/inc/LocalLogBuffer.h | 73 + data-ipa-cfg-mgr/hal/inc/OffloadStatistics.h | 49 + data-ipa-cfg-mgr/hal/inc/PrefixParser.h | 79 + .../hal/src/CtUpdateAmbassador.cpp | 123 + data-ipa-cfg-mgr/hal/src/HAL.cpp | 582 ++ data-ipa-cfg-mgr/hal/src/IpaEventRelay.cpp | 83 + data-ipa-cfg-mgr/hal/src/LocalLogBuffer.cpp | 126 + .../hal/src/OffloadStatistics.cpp | 57 + data-ipa-cfg-mgr/hal/src/PrefixParser.cpp | 375 ++ data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h | 8 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h | 88 +- .../ipacm/inc/IPACM_ConntrackClient.h | 22 +- .../ipacm/inc/IPACM_ConntrackListener.h | 28 +- .../ipacm/inc/IPACM_Conntrack_NATApp.h | 11 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h | 220 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h | 5 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h | 24 +- .../ipacm/inc/IPACM_IfaceManager.h | 3 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h | 208 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h | 241 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h | 23 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h | 11 +- .../ipacm/inc/IPACM_OffloadManager.h | 103 + data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h | 7 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Wan.h | 188 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Wlan.h | 104 +- data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h | 118 +- data-ipa-cfg-mgr/ipacm/src/Android.mk | 50 +- data-ipa-cfg-mgr/ipacm/src/IPACM_CmdQueue.cpp | 66 +- data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp | 175 +- .../ipacm/src/IPACM_ConntrackClient.cpp | 246 +- .../ipacm/src/IPACM_ConntrackListener.cpp | 1083 ++-- .../ipacm/src/IPACM_Conntrack_NATApp.cpp | 316 +- .../ipacm/src/IPACM_EvtDispatcher.cpp | 14 +- .../ipacm/src/IPACM_Filtering.cpp | 190 +- data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp | 11 +- data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp | 289 +- .../ipacm/src/IPACM_IfaceManager.cpp | 171 +- data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp | 5106 ++++++++--------- data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp | 2607 +++++---- data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp | 296 +- data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp | 347 +- data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp | 142 +- .../ipacm/src/IPACM_OffloadManager.cpp | 540 ++ data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp | 56 +- data-ipa-cfg-mgr/ipacm/src/IPACM_Wan.cpp | 2314 +++++--- data-ipa-cfg-mgr/ipacm/src/IPACM_Wlan.cpp | 5061 ++++------------ data-ipa-cfg-mgr/ipacm/src/IPACM_Xml.cpp | 581 +- data-ipa-cfg-mgr/ipacm/src/IPACM_cfg.xml | 32 +- data-ipa-cfg-mgr/ipacm/src/Makefile.am | 16 +- data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h | 30 +- data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h | 42 +- data-ipa-cfg-mgr/ipanat/src/Android.mk | 13 +- data-ipa-cfg-mgr/ipanat/src/Makefile.am | 19 +- data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c | 42 +- data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c | 202 +- data-ipa-cfg-mgr/ipanat/test/Android.mk | 3 + 64 files changed, 13294 insertions(+), 10439 deletions(-) delete mode 100644 data-ipa-cfg-mgr/Android.mk create mode 100644 data-ipa-cfg-mgr/hal/Android.mk create mode 100644 data-ipa-cfg-mgr/hal/inc/CtUpdateAmbassador.h create mode 100644 data-ipa-cfg-mgr/hal/inc/HAL.h create mode 100644 data-ipa-cfg-mgr/hal/inc/IOffloadManager.h create mode 100644 data-ipa-cfg-mgr/hal/inc/IpaEventRelay.h create mode 100644 data-ipa-cfg-mgr/hal/inc/LocalLogBuffer.h create mode 100644 data-ipa-cfg-mgr/hal/inc/OffloadStatistics.h create mode 100644 data-ipa-cfg-mgr/hal/inc/PrefixParser.h create mode 100644 data-ipa-cfg-mgr/hal/src/CtUpdateAmbassador.cpp create mode 100644 data-ipa-cfg-mgr/hal/src/HAL.cpp create mode 100644 data-ipa-cfg-mgr/hal/src/IpaEventRelay.cpp create mode 100644 data-ipa-cfg-mgr/hal/src/LocalLogBuffer.cpp create mode 100644 data-ipa-cfg-mgr/hal/src/OffloadStatistics.cpp create mode 100644 data-ipa-cfg-mgr/hal/src/PrefixParser.cpp create mode 100644 data-ipa-cfg-mgr/ipacm/inc/IPACM_OffloadManager.h create mode 100644 data-ipa-cfg-mgr/ipacm/src/IPACM_OffloadManager.cpp diff --git a/data-ipa-cfg-mgr/Android.mk b/data-ipa-cfg-mgr/Android.mk deleted file mode 100644 index 39de8910..00000000 --- a/data-ipa-cfg-mgr/Android.mk +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright (C) 2015 The CyanogenMod Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH := $(call my-dir) - -include $(call first-makefiles-under,$(LOCAL_PATH)) diff --git a/data-ipa-cfg-mgr/configure.ac b/data-ipa-cfg-mgr/configure.ac index 33164c07..6662ef65 100644 --- a/data-ipa-cfg-mgr/configure.ac +++ b/data-ipa-cfg-mgr/configure.ac @@ -24,6 +24,7 @@ AC_ARG_WITH(sanitized-headers, AS_HELP_STRING([--with-sanitized-headers=DIR], [Specify the location of the sanitized Linux headers]), [CPPFLAGS="$CPPFLAGS -idirafter $withval"]) +AM_CONDITIONAL(KERNELMODULES, [test -n -eq 0]) AC_ARG_WITH([glib], AC_HELP_STRING([--with-glib], diff --git a/data-ipa-cfg-mgr/hal/Android.mk b/data-ipa-cfg-mgr/hal/Android.mk new file mode 100644 index 00000000..67e9b073 --- /dev/null +++ b/data-ipa-cfg-mgr/hal/Android.mk @@ -0,0 +1,29 @@ +# LOCAL_PATH := $(call my-dir) +# +# include $(CLEAR_VARS) +# LOCAL_ARM_MODE := arm +# LOCAL_SRC_FILES := src/CtUpdateAmbassador.cpp \ +# src/HAL.cpp \ +# src/IpaEventRelay.cpp \ +# src/LocalLogBuffer.cpp \ +# src/OffloadStatistics.cpp \ +# src/PrefixParser.cpp +# LOCAL_C_INCLUDES := $(LOCAL_PATH)/inc +# LOCAL_MODULE := liboffloadhal +# LOCAL_CPP_FLAGS := -Wall -Werror +# LOCAL_SHARED_LIBRARIES := libhwbinder \ +# libhidlbase \ +# libhidltransport \ +# liblog \ +# libcutils \ +# libdl \ +# libbase \ +# libutils \ +# libhardware_legacy \ +# libhardware \ +# android.hardware.tetheroffload.config@1.0 \ +# android.hardware.tetheroffload.control@1.0 +# LOCAL_VENDOR_MODULE := true +# LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib +# LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64 +# include $(BUILD_SHARED_LIBRARY) diff --git a/data-ipa-cfg-mgr/hal/inc/CtUpdateAmbassador.h b/data-ipa-cfg-mgr/hal/inc/CtUpdateAmbassador.h new file mode 100644 index 00000000..d4890f39 --- /dev/null +++ b/data-ipa-cfg-mgr/hal/inc/CtUpdateAmbassador.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _CT_UPDATE_AMBASSADOR_H_ +#define _CT_UPDATE_AMBASSADOR_H_ +/* External Includes */ +#include + +/* HIDL Includes */ +#include + +/* Internal Includes */ +#include "IOffloadManager.h" + +/* Namespace pollution avoidance */ +using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback; +using ::android::hardware::tetheroffload::control::V1_0::NetworkProtocol; +using HALIpAddrPortPair = ::android::hardware::tetheroffload::control::V1_0::IPv4AddrPortPair; +using HALNatTimeoutUpdate = ::android::hardware::tetheroffload::control::V1_0::NatTimeoutUpdate; + +using IpaIpAddrPortPair = ::IOffloadManager::ConntrackTimeoutUpdater::IpAddrPortPair; +using IpaNatTimeoutUpdate = ::IOffloadManager::ConntrackTimeoutUpdater::NatTimeoutUpdate; +using IpaL4Protocol = ::IOffloadManager::ConntrackTimeoutUpdater::L4Protocol; + + +class CtUpdateAmbassador : public IOffloadManager::ConntrackTimeoutUpdater { +public: + CtUpdateAmbassador(const ::android::sp& /* cb */); + /* ------------------- CONNTRACK TIMEOUT UPDATER ------------------------ */ + void updateTimeout(IpaNatTimeoutUpdate /* update */); +private: + static bool translate(IpaNatTimeoutUpdate /* in */, HALNatTimeoutUpdate& /* out */); + static bool translate(IpaIpAddrPortPair /* in */, HALIpAddrPortPair& /* out */); + static bool L4ToNetwork(IpaL4Protocol /* in */, NetworkProtocol& /* out */); + const ::android::sp& mFramework; +}; /* CtUpdateAmbassador */ +#endif /* _CT_UPDATE_AMBASSADOR_H_ */ \ No newline at end of file diff --git a/data-ipa-cfg-mgr/hal/inc/HAL.h b/data-ipa-cfg-mgr/hal/inc/HAL.h new file mode 100644 index 00000000..622a67ee --- /dev/null +++ b/data-ipa-cfg-mgr/hal/inc/HAL.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _HAL_H_ +#define _HAL_H_ + +/* HIDL Includes */ +#include +#include +#include + +/* External Includes */ +#include +#include + +/* Internal Includes */ +#include "CtUpdateAmbassador.h" +#include "IOffloadManager.h" +#include "IpaEventRelay.h" +#include "LocalLogBuffer.h" + +/* Avoid the namespace litering everywhere */ +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; +using ::android::hardware::Return; +using ::android::hardware::hidl_handle; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; + +using RET = ::IOffloadManager::RET; +using Prefix = ::IOffloadManager::Prefix; + +using ::std::map; +using ::std::string; +using ::std::vector; + +using ::android::hardware::tetheroffload::config::V1_0::IOffloadConfig; +using ::android::hardware::tetheroffload::control::V1_0::IOffloadControl; + +using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback; + + +class HAL : public IOffloadControl, IOffloadConfig { +public: + /* Static Const Definitions */ + static const uint32_t UDP_SUBSCRIPTIONS = + NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY; + static const uint32_t TCP_SUBSCRIPTIONS = + NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY; + + /* Interface to IPACM */ + /** + * @TODO This will likely need to be extended into a proper FactoryPattern + * when version bumps are needed. + * + * This makeIPAHAL function would move to a HALFactory class. Each HAL could + * then be versioned (class HAL_V1, class HAL_V2, etc) and inherit from a base class HAL. + * Then the version number in this function could be used to decide which one to return + * (if any). + * + * IPACM does not need to talk directly back to the returned HAL class. The other methods that + * IPACM needs to call are covered by registering the event listeners. If IPACM did need to + * talk directly back to the HAL object, without HAL registering a callback, these methods would + * need to be defined in the HAL base class. + * + * This would slightly break backwards compatibility so it should be discouraged; however, the + * base class could define a sane default implementation and not require that the child class + * implement this new method. This "sane default implementation" might only be possible in the + * case of listening to async events; if IPACM needs to query something, then this would not + * be backwards compatible and should be done via registering a callback so that IPACM knows + * this version of HAL supports that functionality. + * + * The above statements assume that only one version of the HAL will be instantiated at a time. + * Yet, it seems possible that a HAL_V1 and HAL_V2 service could both be registered, extending + * support to both old and new client implementations. It would be difficult to multiplex + * information from both versions. Additionally, IPACM would be responsible for instantiating + * two HALs (makeIPAHAL(1, ...); makeIPAHAL(2, ...)) which makes signaling between HAL versions + * (see next paragraph) slightly more difficult but not impossible. + * + * If concurrent versions of HAL are required, there will likely need to only be one master. + * Whichever version of HAL receives a client first may be allowed to take over control while + * other versions would be required to return failures (ETRYAGAIN: another version in use) until + * that version of the client relinquishes control. This should work seemlessly because we + * currently have an assumption that only one client will be present in system image. + * Logically, that client will have only a single version (or if it supports multiple, it will + * always attempt the newest version of HAL before falling back) and therefore no version + * collisions could possibly occur. + * + * Dislaimer: + * ========== + * Supporting multiple versions of an interface, in the same code base, at runtime, comes with a + * significant carrying cost and overhead in the form of developer headaches. This should not + * be done lightly and should be extensively scoped before committing to the effort. + * + * Perhaps the notion of minor version could be introduced to bridge the gaps created above. + * For example, 1.x and 1.y could be ran concurrently and supported from the same IPACM code. + * Yet, a major version update, would not be backwards compatible. This means that a 2.x HAL + * could not linked into the same IPACM code base as a 1.x HAL. + */ + static HAL* makeIPAHAL(int /* version */, IOffloadManager* /* mgr */); + + /* IOffloadConfig */ + Return setHandles( + const hidl_handle& /* fd1 */, + const hidl_handle& /* fd2 */, + setHandles_cb /* hidl_cb */); + + /* IOffloadControl */ + Return initOffload( + const ::android::sp& /* cb */, + initOffload_cb /* hidl_cb */); + Return stopOffload( + stopOffload_cb /* hidl_cb */); + Return setLocalPrefixes( + const hidl_vec& /* prefixes */, + setLocalPrefixes_cb /* hidl_cb */); + Return getForwardedStats( + const hidl_string& /* upstream */, + getForwardedStats_cb /* hidl_cb */); + Return setDataLimit( + const hidl_string& /* upstream */, + uint64_t /* limit */, + setDataLimit_cb /* hidl_cb */); + Return setUpstreamParameters( + const hidl_string& /* iface */, + const hidl_string& /* v4Addr */, + const hidl_string& /* v4Gw */, + const hidl_vec& /* v6Gws */, + setUpstreamParameters_cb /* hidl_cb */); + Return addDownstream( + const hidl_string& /* iface */, + const hidl_string& /* prefix */, + addDownstream_cb /* hidl_cb */); + Return removeDownstream( + const hidl_string& /* iface */, + const hidl_string& /* prefix */, + removeDownstream_cb /* hidl_cb */); + +private: + typedef struct BoolResult { + bool success; + string errMsg; + } boolResult_t; + + HAL(IOffloadManager* /* mgr */); + void registerAsSystemService(const char* /* name */); + + void doLogcatDump(); + + static BoolResult makeInputCheckFailure(string /* customErr */); + static BoolResult ipaResultToBoolResult(RET /* in */); + + static vector convertHidlStrToStdStr(hidl_vec /* in */); + + void registerEventListeners(); + void registerIpaCb(); + void registerCtCb(); + void unregisterEventListeners(); + void unregisterIpaCb(); + void unregisterCtCb(); + + void clearHandles(); + + bool isInitialized(); + + IOffloadManager* mIPA; + hidl_handle mHandle1; + hidl_handle mHandle2; + LocalLogBuffer mLogs; + ::android::sp mCb; + IpaEventRelay *mCbIpa; + CtUpdateAmbassador *mCbCt; +}; /* HAL */ +#endif /* _HAL_H_ */ diff --git a/data-ipa-cfg-mgr/hal/inc/IOffloadManager.h b/data-ipa-cfg-mgr/hal/inc/IOffloadManager.h new file mode 100644 index 00000000..6a357b39 --- /dev/null +++ b/data-ipa-cfg-mgr/hal/inc/IOffloadManager.h @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _I_OFFLOAD_MANAGER_H_ +#define _I_OFFLOAD_MANAGER_H_ + +/* External Includes */ +#include + +/* Internal Includes */ +#include "OffloadStatistics.h" + + +class IOffloadManager { +public: + enum RET { + FAIL_TOO_MANY_PREFIXES = -6, + FAIL_UNSUPPORTED = -5, + FAIL_INPUT_CHECK = -4, + FAIL_HARDWARE = -3, + FAIL_UNNEEDED = -2, + FAIL_TRY_AGAIN = -1, + SUCCESS = 0, + SUCCESS_DUPLICATE_CONFIG = 1, + SUCCESS_NO_OP = 2, + SUCCESS_OPTIMIZED = 3 + }; /* RET */ + + enum IP_FAM { + V4 = 0, + V6 = 1, + INVALID = 2 + }; /* IP_FAM */ + + /* Overloading to use for addresses as well */ + typedef struct Prefix { + IP_FAM fam; + uint32_t v4Addr; + uint32_t v4Mask; + uint32_t v6Addr[4]; + uint32_t v6Mask[4]; + } prefix_t; + + /* ---------------------------- LIFECYCLE ------------------------------- */ + virtual ~IOffloadManager(){} + + /* ---------------------- ASYNC EVENT CALLBACKS ------------------------- */ + class IpaEventListener { + public: + enum StoppedReason { + /** + * Offload was stopped due to the configuration being removed via + * setUpstreamParameters/removeDownstream. + */ + REQUESTED, + /** + * Offload was stopped due to an internal (to IPA or modem) error. + * + * Statistics may be temporarily unavailable. + */ + ERROR, + /** + * Offload was stopped because the upstream connection has + * migrated to unsupported radio access technology. + * + * Statistics will still be available. + */ + UNSUPPORTED + }; /* StoppedReason */ + virtual ~IpaEventListener(){} + /** + * Called when Offload first begins to occur on any upstream and + * tether interface pair. It should be paired with an onOffloadStopped + * call. + */ + virtual void onOffloadStarted(){} + /** + * Called when Offload stops occurring on all upstream and tether + * interface pairs. It comes after a call to onOffloadStarted. + * + * @param reason Reason that Offload was stopped + */ + virtual void onOffloadStopped(StoppedReason /* reason */){} + /** + * Called when the hardware can support Offload again. + * + * Any statistics that were previously unavailable, may be queried + * again at this time. + */ + virtual void onOffloadSupportAvailable(){} + /** + * Called when the limit set via setQuota has expired. + * + * It is implied that Offload has been stopped on all upstream and + * tether interface pairs when this callback is called. + */ + virtual void onLimitReached(){} + }; /* IpaEventListener */ + + /** + * Request notifications about asynchronous events that occur in hardware. + * + * The calling client must be able to handle the callback on a separate + * thread (i.e. their implementation of IpaEventListener must be thread + * safe). + * + * @return SUCCESS iff callback successfully registered + * + * Remarks: This can't really be allowed to fail. + */ + virtual RET registerEventListener(IpaEventListener* /* listener */) = 0; + /** + * Unregister a previously registered listener. + * + * @return SUCCESS iff callback successfully unregistered + * FAIL_INPUT_CHECK if callback was never registered + */ + virtual RET unregisterEventListener(IpaEventListener* /* listener */) = 0; + + class ConntrackTimeoutUpdater { + public: + enum L4Protocol { + TCP = 0, + UDP = 1 + }; /* L4Protocol */ + typedef struct IpAddrPortPair { + uint32_t ipAddr; + uint16_t port; + } ipAddrPortPair_t; + typedef struct NatTimeoutUpdate { + IpAddrPortPair src; + IpAddrPortPair dst; + L4Protocol proto; + } natTimeoutUpdate_t; + virtual ~ConntrackTimeoutUpdater(){} + virtual void updateTimeout(NatTimeoutUpdate /* update */) {} + }; /* ConntrackTimeoutUpdater */ + + /** + * Register a callback that may be called if the OffloadManager wants to + * update the timeout value in conntrack of kernel. + * + * The calling client must be able to handle the callback on a separate + * thread (i.e. their implementation of ConntrackTimeoutUpdater must be + * thread safe) + * + * @return SUCCESS iff callback successfully registered + * + * Remarks: This can't really be allowed to fail + */ + virtual RET registerCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */) = 0; + /** + * Unregister a previously registered callback. + * + * @return SUCCESS iff callback successfully unregistered + * FAIL_INPUT_CHECK if callback was never registered + */ + virtual RET unregisterCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */) = 0; + + /* ----------------------------- CONFIG --------------------------------- */ + /** + * Provide a file descriptor for use with conntrack library + * + * @param fd File Descriptor that has been opened and bound to groups + * @param groups Groups (bit mask) that fd has been bound to + * + * @return SUCCESS iff IOffloadManager needed this file descriptor and + * it was properly bound. + * FAIL_INPUT_CHECK if IOffloadManager needed this file descriptor + * but it was found to not be properly bound + * FAIL_UNNEEDED if IOffloadManager determined that it does not need + * a file descriptor bound to these groups. + */ + virtual RET provideFd(int /* fd */, unsigned int /* group */) = 0; + /** + * Indicate that IOffloadManager must cease using all file + * descriptors passed via provideFd API. + * + * After this call returns, the file descriptors will likely be closed by + * the calling client. + * + * @return SUCCESS iff IOffloadManager has stopped using all file + * descriptors + * FAIL_TRY_AGAIN if IOffloadManager needs more time with these + * file descriptors before it can release them + * + * Remarks: Currently, it would be very difficult to handle a FAIL_TRY_AGAIN + * because HAL serivce does not own a thread outside of RPC + * Threadpool to reschedule this call. + */ + virtual RET clearAllFds() = 0; + /** + * Query whether STA+AP offload is supported on this device. + * + * @return true if supported, false otherwise + */ + virtual bool isStaApSupported() = 0; + + /* ------------------------------ ROUTE --------------------------------- */ + /** + * Add a downstream prefix that may be forwarded. + * + * The Prefix may be an IPv4 or IPv6 address to signify which family can be + * offloaded from the specified tether interface. If the given IP family, + * as determined by the Prefix, has a corresponding upstream configured, + * then traffic should be forwarded between the two interfaces. + * + * Only traffic that has a downstream address within the specified Prefix + * can be forwarded. Traffic from the same downstream interface that falls + * outside of the Prefix will be unaffected and can be forwarded iff it was + * previously configured via a separate addDownstream call. + * + * If no upstream has been configured, then this information must be cached + * so that offload may begin once an upstream is configured. + * + * This API does not replace any previously configured downstreams + * and must be explicitly removed by calling removeDownstream or by clearing + * the entire configuration by calling stopAllOffload. + * + * @return SUCCESS The new information was accepted + * FAIL_TOO_MANY_PREFIXES The hardware has already accepted the max + * number of Prefixes that can be supported. + * If offload is desired on this Prefix then + * another must be removed first. + * FAIL_UNSUPPORTED The hardware cannot forward traffic from this + * downstream interface and will never be able to. + */ + virtual RET addDownstream(const char* /* downstream */, + const Prefix& /* prefix */) = 0; + /** + * Remove a downstream Prefix that forwarding was previously requested for. + * + * The Prefix may be an IPv4 or IPv6 address. Traffic outside of this + * Prefix is not affected. + * + * @return SUCCESS iff forwarding was previously occurring and has been + * stopped + * SUCCESS_NO_OP iff forwarding was not previously occurring and + * therefore no action needed to be taken + */ + virtual RET removeDownstream(const char* /* downstream */, + const Prefix& /* prefix */) = 0; + /** + * Indicate that hardware should forward traffic from any configured + * downstreams to the specified upstream. + * + * When iface is non-null and non-empty and v4Gw is valid, then any + * currently configured or future configured IPv4 downstreams should be + * forwarded to this upstream interface. + * + * When iface is non-null and non-empty and v6Gw is valid, then any + * currently configured or future configured IPv6 downstreams should be + * forwarded to this upstream interface. + * + * @param iface Upstream interface name. Only one is needed because IPv4 + * and IPv6 interface names are required to match. + * @param v4Gw The address of the IPv4 Gateway on the iface + * @param v6Gw The address of one of the IPv6 Gateways on the iface + * + * @return SUCCESS iff the specified configuration was applied + * SUCCESS_DUPLICATE_CONFIG if this configuration exactly + * matches a previously provided + * configuration. This means that no + * action has to be taken, but, the + * configuration was previously accepted + * and applied. + * FAIL_UNSUPPORTED if hardware cannot support forwarding to this + * upstream interface + * + * Remarks: This overrides any previously configured parameters + */ + virtual RET setUpstream(const char* /* iface */, const Prefix& /* v4Gw */, + const Prefix& /* v6Gw */) = 0; + /** + * All traffic must be returned to the software path and all configuration + * (including provided file descriptors) must be forgotten. + * + * @return SUCCESS If all offload was successfully stopped and provided + * file descriptors were released. + * + * Remarks: This can't really fail? + */ + virtual RET stopAllOffload() = 0; + + /* --------------------------- STATS/POLICY ----------------------------- */ + /** + * Instruct hardware to stop forwarding traffic and send a callback after + * limit bytes have been transferred in either direction on this upstream + * interface. + * + * @param upstream Upstream interface name that the limit should apply to + * @param limit Bytes limit that can occur before action should be taken + * + * @return SUCCESS If the limit was successfully applied + * SUCCESS_OPTIMIZED If the limit was sufficiently high to be + * interpreted as "no quota". + * FAIL_HARDWARE If the limit was rejected by the hardware + * FAIL_UNSUPPORTED If metering is not supported on this interface + * FAIL_TRY_AGAIN If this upstream has not been previously + * configured to allow offload + * (via setUpstreamParameters) + */ + virtual RET setQuota(const char* /* upstream */, uint64_t /* limit */) = 0; + /** + * Query for statistics counters in hardware. + * + * This returns an aggregate of all hardware accelerated traffic which + * has occurred on this upstream interface. + * + * @param upstream Interface on which traffic entered/exited + * @param reset Whether hardware counters should reset after returning + * current statistics + * @param ret Output variable where statistics are returned + * + * @return SUCCESS If the statistics were successfully populated in ret and + * were successfully reset if requested. + * FAIL_TRY_AGAIN If the statistics are not currently available but + * may be available later. This may occur during + * a subsystem restart. + * FAIL_UNSUPPORTED If statistics are not supported on this upstream + */ + virtual RET getStats(const char* /* upstream */, bool /* reset */, + OffloadStatistics& /* ret */) = 0; +}; /* IOffloadManager */ +#endif /* _I_OFFLOAD_MANAGER_H_ */ diff --git a/data-ipa-cfg-mgr/hal/inc/IpaEventRelay.h b/data-ipa-cfg-mgr/hal/inc/IpaEventRelay.h new file mode 100644 index 00000000..45415104 --- /dev/null +++ b/data-ipa-cfg-mgr/hal/inc/IpaEventRelay.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _IPA_EVENT_RELAY_H_ +#define _IPA_EVENT_RELAY_H_ +/* External Includes */ +#include + +/* HIDL Includes */ +#include + +/* Internal Includes */ +#include "IOffloadManager.h" + +/* Namespace pollution avoidance */ +using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback; + + +class IpaEventRelay : public IOffloadManager::IpaEventListener { +public: + IpaEventRelay(const ::android::sp& /* cb */); + /* ----------------------- IPA EVENT LISTENER --------------------------- */ + void onOffloadStarted(); + void onOffloadStopped(StoppedReason /* reason */); + void onOffloadSupportAvailable(); + void onLimitReached(); +private: + const ::android::sp& mFramework; +}; /* IpaEventRelay */ +#endif /* _IPA_EVENT_RELAY_H_ */ \ No newline at end of file diff --git a/data-ipa-cfg-mgr/hal/inc/LocalLogBuffer.h b/data-ipa-cfg-mgr/hal/inc/LocalLogBuffer.h new file mode 100644 index 00000000..c23ef7d0 --- /dev/null +++ b/data-ipa-cfg-mgr/hal/inc/LocalLogBuffer.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _LOCAL_LOG_BUFFER_H_ +#define _LOCAL_LOG_BUFFER_H_ +/* External Includes */ +#include +#include +#include +#include +#include + +/* Namespace pollution avoidance */ +using ::std::deque; +using ::std::string; +using ::std::stringstream; +using ::std::vector; + + +class LocalLogBuffer { +public: + class FunctionLog { + public: + FunctionLog(string /* funcName */); + FunctionLog(const FunctionLog& /* other */); + void addArg(string /* kw */, string /* arg */); + void addArg(string /* kw */, vector /* args */); + void addArg(string /* kw */, uint64_t /* arg */); + void setResult(bool /* success */, string /* msg */); + void setResult(vector /* ret */); + void setResult(uint64_t /* rx */, uint64_t /* tx */); + string toString(); + private: + void maybeAddArgsComma(); + const string mName; + bool mArgsProvided; + stringstream mSSArgs; + stringstream mSSReturn; + }; /* FunctionLog */ + LocalLogBuffer(string /* name */, int /* maxLogs */); + void addLog(FunctionLog /* log */); + void toLogcat(); +private: + deque mLogs; + const string mName; + const size_t mMaxLogs; +}; /* LocalLogBuffer */ +#endif /* _LOCAL_LOG_BUFFER_H_ */ \ No newline at end of file diff --git a/data-ipa-cfg-mgr/hal/inc/OffloadStatistics.h b/data-ipa-cfg-mgr/hal/inc/OffloadStatistics.h new file mode 100644 index 00000000..226ea72b --- /dev/null +++ b/data-ipa-cfg-mgr/hal/inc/OffloadStatistics.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _OFFLOAD_STATISTICS_H_ +#define _OFFLOAD_STATISTICS_H_ + +#include +#include + + +class OffloadStatistics { +public: + uint64_t rx; + uint64_t tx; + + OffloadStatistics(); + OffloadStatistics(std::string /* upstream */); + + uint64_t getTotalRxBytes(); + uint64_t getTotalTxBytes(); +private: + std::string upstream; +}; /* OffloadStatistics */ +#endif /* _OFFLOAD_STATISTICS_H_ */ diff --git a/data-ipa-cfg-mgr/hal/inc/PrefixParser.h b/data-ipa-cfg-mgr/hal/inc/PrefixParser.h new file mode 100644 index 00000000..4682aa5c --- /dev/null +++ b/data-ipa-cfg-mgr/hal/inc/PrefixParser.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _PREFIX_PARSER_H_ +#define _PREFIX_PARSER_H_ + +/* External Includes */ +#include +#include +#include + +/* Internal Includes */ +#include "IOffloadManager.h" + +/* Avoiding namespace pollution */ +using IP_FAM = ::IOffloadManager::IP_FAM; +using Prefix = ::IOffloadManager::Prefix; + +using ::std::string; +using ::std::vector; + + +class PrefixParser { +public: + PrefixParser(); + bool add(vector /* in */); + bool add(string /* in */); + bool addV4(vector /* in */); + bool addV4(string /* in */); + bool addV6(vector /* in */); + bool addV6(string /* in */); + int size(); + bool allAreFullyQualified(); + Prefix getFirstPrefix(); + string getLastErrAsStr(); +private: + bool add(string /* in */, IP_FAM /* famHint */); + bool add(vector /* in */, IP_FAM /* famHint */); + static IP_FAM guessIPFamily(string /* in */); + static bool splitIntoAddrAndMask(string /* in */, string& /* addr */, + string& /* mask */); + static int parseSubnetMask(string /* in */, IP_FAM /* famHint */); + static bool parseV4Addr(string /* in */, Prefix& /* out */); + static bool parseV6Addr(string /* in */, Prefix& /* out */); + static bool populateV4Mask(int /* mask */, Prefix& /* out */); + static bool populateV6Mask(int /* mask */, Prefix& /* out */); + static uint32_t createMask(int /* mask */); + static Prefix makeBlankPrefix(IP_FAM /* famHint */); + bool isMaskValid(int /* mask */, IP_FAM /* fam */); + static const uint32_t FULLY_QUALIFIED_MASK = ~0; + vector mPrefixes; + string mLastErr; +}; /* PrefixParser */ +#endif /* _PREFIX_PARSER_H_ */ \ No newline at end of file diff --git a/data-ipa-cfg-mgr/hal/src/CtUpdateAmbassador.cpp b/data-ipa-cfg-mgr/hal/src/CtUpdateAmbassador.cpp new file mode 100644 index 00000000..4843fe2d --- /dev/null +++ b/data-ipa-cfg-mgr/hal/src/CtUpdateAmbassador.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef DBG + #define DBG false +#endif /* DBG */ +#define LOG_TAG "IPAHALService/CtUpdateAmbassador" + +/* External Includes */ +#include +#include + +/* HIDL Includes */ +#include + +/* Internal Includes */ +#include "CtUpdateAmbassador.h" + +/* Namespace pollution avoidance */ +using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback; +using ::android::hardware::tetheroffload::control::V1_0::NetworkProtocol; +using HALIpAddrPortPair = ::android::hardware::tetheroffload::control::V1_0::IPv4AddrPortPair; +using HALNatTimeoutUpdate = ::android::hardware::tetheroffload::control::V1_0::NatTimeoutUpdate; + +using IpaIpAddrPortPair = ::IOffloadManager::ConntrackTimeoutUpdater::IpAddrPortPair; +using IpaNatTimeoutUpdate = ::IOffloadManager::ConntrackTimeoutUpdater::NatTimeoutUpdate; +using IpaL4Protocol = ::IOffloadManager::ConntrackTimeoutUpdater::L4Protocol; + + +CtUpdateAmbassador::CtUpdateAmbassador( + const ::android::sp& cb) : mFramework(cb) { +} /* CtUpdateAmbassador */ + +void CtUpdateAmbassador::updateTimeout(IpaNatTimeoutUpdate in) { + if (DBG) { + ALOGD("updateTimeout(src={%#010X, %#04X}, dest={%#010X, %#04X}, Proto=%d)", + in.src.ipAddr, in.src.port, in.dst.ipAddr, in.dst.port, + in.proto); + } + HALNatTimeoutUpdate out; + if (!translate(in, out)) { + /* Cannot log the input outside of DBG flag because it contains sensitive + * information. This will lead to a two step debug if the information + * cannot be gleaned from IPACM logs. The other option is to improve this + * with the use of our local log. That would likely still be hard to + * instruct testers to collect logs, because, assuming timeout updates + * are numerous, it will overrun the ring quickly. Therefore, the tester + * would have to know the exact moment as issue occurred. Or we make the + * ring massive. This would lead to a significant memory overhead. + * Because of this overhead, we would likely not want to check in a change + * with it and once we provide a debug build for increasing buffer size, + * why not just define the DBG flag? + */ + ALOGE("Failed to translate timeout event :("); + } else { + mFramework->updateTimeout(out); + } +} /* updateTimeout */ + +bool CtUpdateAmbassador::translate(IpaNatTimeoutUpdate in, HALNatTimeoutUpdate &out) { + return translate(in.src, out.src) + && translate(in.dst, out.dst) + && L4ToNetwork(in.proto, out.proto); +} /* translate */ + +bool CtUpdateAmbassador::translate(IpaIpAddrPortPair in, HALIpAddrPortPair& out) { + char ipAddrStr[INET_ADDRSTRLEN]; + + if (inet_ntop(AF_INET, &(in.ipAddr), ipAddrStr, INET_ADDRSTRLEN) == nullptr) { + /* errno would be valid here with EAFNOSUPPORT or ENOSPC, neither should really + * be possible in our scenario though. + */ + return false; + } + + out.addr = ipAddrStr; + out.port = in.port; + + return true; +} /* translate */ + +bool CtUpdateAmbassador::L4ToNetwork(IpaL4Protocol in, NetworkProtocol &out) { + bool ret = false; + switch(in) { + case IpaL4Protocol::TCP: + ret = true; + out = NetworkProtocol::TCP; + break; + case IpaL4Protocol::UDP: + ret = true; + out = NetworkProtocol::UDP; + break; + default: + ret = false; + break; + } + return ret; +} /* L4ToNetwork */ diff --git a/data-ipa-cfg-mgr/hal/src/HAL.cpp b/data-ipa-cfg-mgr/hal/src/HAL.cpp new file mode 100644 index 00000000..0d25aa0e --- /dev/null +++ b/data-ipa-cfg-mgr/hal/src/HAL.cpp @@ -0,0 +1,582 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef DBG + #define DBG true +#endif /* DBG */ +#define LOG_TAG "IPAHALService" + +/* HIDL Includes */ +#include +#include + +/* Kernel Includes */ +#include + +/* External Includes */ +#include +#include +#include +#include + +/* Internal Includes */ +#include "HAL.h" +#include "LocalLogBuffer.h" +#include "PrefixParser.h" + +/* Namespace pollution avoidance */ +using ::android::hardware::Void; +using ::android::status_t; + +using RET = ::IOffloadManager::RET; +using Prefix = ::IOffloadManager::Prefix; + +using ::std::map; +using ::std::vector; + + +/* ------------------------------ PUBLIC ------------------------------------ */ +HAL* HAL::makeIPAHAL(int version, IOffloadManager* mgr) { + if (DBG) + ALOGI("makeIPAHAL(%d, %s)", version, + (mgr != nullptr) ? "provided" : "null"); + if (nullptr == mgr) return NULL; + else if (version != 1) return NULL; + HAL* ret = new HAL(mgr); + if (nullptr == ret) return NULL; + configureRpcThreadpool(1, false); + ret->registerAsSystemService("ipacm"); + return ret; +} /* makeIPAHAL */ + + +/* ------------------------------ PRIVATE ----------------------------------- */ +HAL::HAL(IOffloadManager* mgr) : mLogs("HAL Function Calls", 50) { + mIPA = mgr; + mCb.clear(); + mCbIpa = nullptr; + mCbCt = nullptr; +} /* HAL */ + +void HAL::registerAsSystemService(const char* name) { + status_t ret = 0; + + ret = IOffloadControl::registerAsService(name); + if (ret != 0) ALOGE("Failed to register IOffloadControl (%d)", ret); + else if (DBG) { + ALOGI("Successfully registered IOffloadControl (%s)", name); + } + + IOffloadConfig::registerAsService(name); + if (ret != 0) ALOGE("Failed to register IOffloadConfig (%d)", ret); + else if (DBG) { + ALOGI("Successfully registered IOffloadConfig (%s)", name); + } +} /* registerAsSystemService */ + +void HAL::doLogcatDump() { + ALOGD("mHandles"); + ALOGD("========"); + /* @TODO This will segfault if they aren't initialized and I don't currently + * care to check for initialization in a function that isn't used anyways + * ALOGD("fd1->%d", mHandle1->data[0]); + * ALOGD("fd2->%d", mHandle2->data[0]); + */ + ALOGD("========"); +} /* doLogcatDump */ + +HAL::BoolResult HAL::makeInputCheckFailure(string customErr) { + BoolResult ret; + ret.success = false; + ret.errMsg = "Failed Input Checks: " + customErr; + return ret; +} /* makeInputCheckFailure */ + +HAL::BoolResult HAL::ipaResultToBoolResult(RET in) { + BoolResult ret; + ret.success = (in >= RET::SUCCESS); + switch (in) { + case RET::FAIL_TOO_MANY_PREFIXES: + ret.errMsg = "Too Many Prefixes Provided"; + break; + case RET::FAIL_UNSUPPORTED: + ret.errMsg = "Unsupported by Hardware"; + break; + case RET::FAIL_INPUT_CHECK: + ret.errMsg = "Failed Input Checks"; + break; + case RET::FAIL_HARDWARE: + ret.errMsg = "Hardware did not accept"; + break; + case RET::FAIL_TRY_AGAIN: + ret.errMsg = "Try Again"; + break; + case RET::SUCCESS: + ret.errMsg = "Successful"; + break; + case RET::SUCCESS_DUPLICATE_CONFIG: + ret.errMsg = "Successful: Was a duplicate configuration"; + break; + case RET::SUCCESS_NO_OP: + ret.errMsg = "Successful: No action needed"; + break; + case RET::SUCCESS_OPTIMIZED: + ret.errMsg = "Successful: Performed optimized version of action"; + break; + default: + ret.errMsg = "Unknown Error"; + break; + } + return ret; +} /* ipaResultToBoolResult */ + +/* This will likely always result in doubling the number of loops the execution + * goes through. Obviously that is suboptimal. But if we first translate + * away from all HIDL specific code, then we can avoid sprinkling HIDL + * dependencies everywhere. + */ +vector HAL::convertHidlStrToStdStr(hidl_vec in) { + vector ret; + for (size_t i = 0; i < in.size(); i++) { + string add = in[i]; + ret.push_back(add); + } + return ret; +} /* convertHidlStrToStdStr */ + +void HAL::registerEventListeners() { + registerIpaCb(); + registerCtCb(); +} /* registerEventListeners */ + +void HAL::registerIpaCb() { + if (isInitialized() && mCbIpa == nullptr) { + LocalLogBuffer::FunctionLog fl("registerEventListener"); + mCbIpa = new IpaEventRelay(mCb); + mIPA->registerEventListener(mCbIpa); + mLogs.addLog(fl); + } else { + ALOGE("Failed to registerIpaCb (isInitialized()=%s, (mCbIpa == nullptr)=%s)", + isInitialized() ? "true" : "false", + (mCbIpa == nullptr) ? "true" : "false"); + } +} /* registerIpaCb */ + +void HAL::registerCtCb() { + if (isInitialized() && mCbCt == nullptr) { + LocalLogBuffer::FunctionLog fl("registerCtTimeoutUpdater"); + mCbCt = new CtUpdateAmbassador(mCb); + mIPA->registerCtTimeoutUpdater(mCbCt); + mLogs.addLog(fl); + } else { + ALOGE("Failed to registerCtCb (isInitialized()=%s, (mCbCt == nullptr)=%s)", + isInitialized() ? "true" : "false", + (mCbCt == nullptr) ? "true" : "false"); + } +} /* registerCtCb */ + +void HAL::unregisterEventListeners() { + unregisterIpaCb(); + unregisterCtCb(); +} /* unregisterEventListeners */ + +void HAL::unregisterIpaCb() { + if (mCbIpa != nullptr) { + LocalLogBuffer::FunctionLog fl("unregisterEventListener"); + mIPA->unregisterEventListener(mCbIpa); + mCbIpa = nullptr; + mLogs.addLog(fl); + } else { + ALOGE("Failed to unregisterIpaCb"); + } +} /* unregisterIpaCb */ + +void HAL::unregisterCtCb() { + if (mCbCt != nullptr) { + LocalLogBuffer::FunctionLog fl("unregisterCtTimeoutUpdater"); + mIPA->unregisterCtTimeoutUpdater(mCbCt); + mCbCt = nullptr; + mLogs.addLog(fl); + } else { + ALOGE("Failed to unregisterCtCb"); + } +} /* unregisterCtCb */ + +void HAL::clearHandles() { + ALOGI("clearHandles()"); + /* @TODO handle this more gracefully... also remove the log + * + * Things that would be nice, but I can't do: + * [1] Destroy the object (it's on the stack) + * [2] Call freeHandle (it's private) + * + * Things I can do but are hacks: + * [1] Look at code and notice that setTo immediately calls freeHandle + */ + mHandle1.setTo(nullptr, true); + mHandle2.setTo(nullptr, true); +} /* clearHandles */ + +bool HAL::isInitialized() { + return mCb.get() != nullptr; +} /* isInitialized */ + + +/* -------------------------- IOffloadConfig -------------------------------- */ +Return HAL::setHandles( + const hidl_handle &fd1, + const hidl_handle &fd2, + setHandles_cb hidl_cb +) { + LocalLogBuffer::FunctionLog fl(__func__); + + if (fd1->numFds != 1) { + BoolResult res = makeInputCheckFailure("Must provide exactly one FD per handle (fd1)"); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + + mLogs.addLog(fl); + return Void(); + } + + if (fd2->numFds != 1) { + BoolResult res = makeInputCheckFailure("Must provide exactly one FD per handle (fd2)"); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + + mLogs.addLog(fl); + return Void(); + } + + /* The = operator calls freeHandle internally. Therefore, if we were using + * these handles previously, they're now gone... forever. But hopefully the + * new ones kick in very quickly. + * + * After freeing anything previously held, it will dup the FD so we have our + * own copy. + */ + mHandle1 = fd1; + mHandle2 = fd2; + + /* Log the DUPed FD instead of the actual input FD so that we can lookup + * this value in ls -l /proc// + */ + fl.addArg("fd1", mHandle1->data[0]); + fl.addArg("fd2", mHandle2->data[0]); + + /* Try to provide each handle to IPACM. Destroy our DUPed hidl_handles if + * IPACM does not like either input. This keeps us from leaking FDs or + * providing half solutions. + * + * @TODO unfortunately, this does not cover duplicate configs where IPACM + * thinks it is still holding on to a handle that we would have freed above. + * It also probably means that IPACM would not know about the first FD being + * freed if it rejects the second FD. + */ + RET ipaReturn = mIPA->provideFd(mHandle1->data[0], UDP_SUBSCRIPTIONS); + if (ipaReturn == RET::SUCCESS) { + ipaReturn = mIPA->provideFd(mHandle2->data[0], TCP_SUBSCRIPTIONS); + } + + if (ipaReturn != RET::SUCCESS) { + ALOGE("IPACM failed to accept the FDs (%d %d)", mHandle1->data[0], + mHandle2->data[0]); + clearHandles(); + } else { + /* @TODO remove logs after stabilization */ + ALOGI("IPACM was provided two FDs (%d, %d)", mHandle1->data[0], + mHandle2->data[0]); + } + + BoolResult res = ipaResultToBoolResult(ipaReturn); + hidl_cb(res.success, res.errMsg); + + fl.setResult(res.success, res.errMsg); + mLogs.addLog(fl); + return Void(); +} /* setHandles */ + + +/* -------------------------- IOffloadControl ------------------------------- */ +Return HAL::initOffload +( + const ::android::sp& cb, + initOffload_cb hidl_cb +) { + LocalLogBuffer::FunctionLog fl(__func__); + + if (isInitialized()) { + BoolResult res = makeInputCheckFailure("Already initialized"); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + mLogs.addLog(fl); + } else { + /* Should storing the CB be a function? */ + mCb = cb; + registerEventListeners(); + BoolResult res = ipaResultToBoolResult(RET::SUCCESS); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + mLogs.addLog(fl); + } + + return Void(); +} /* initOffload */ + +Return HAL::stopOffload +( + stopOffload_cb hidl_cb +) { + LocalLogBuffer::FunctionLog fl(__func__); + + if (!isInitialized()) { + BoolResult res = makeInputCheckFailure("Was never initialized"); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + mLogs.addLog(fl); + } else { + /* Should removing the CB be a function? */ + mCb.clear(); + unregisterEventListeners(); + + RET ipaReturn = mIPA->stopAllOffload(); + if (ipaReturn != RET::SUCCESS) { + /* Ignore IPAs return value here and provide why stopAllOffload + * failed. However, if IPA failed to clearAllFds, then we can't + * clear our map because they may still be in use. + */ + RET ret = mIPA->clearAllFds(); + if (ret == RET::SUCCESS) { + clearHandles(); + } + } else { + ipaReturn = mIPA->clearAllFds(); + /* If IPA fails, they may still be using these for some reason. */ + if (ipaReturn == RET::SUCCESS) { + clearHandles(); + } else { + ALOGE("IPACM failed to return success for clearAllFds so they will not be released..."); + } + } + + BoolResult res = ipaResultToBoolResult(ipaReturn); + hidl_cb(res.success, res.errMsg); + + fl.setResult(res.success, res.errMsg); + mLogs.addLog(fl); + } + + return Void(); +} /* stopOffload */ + +Return HAL::setLocalPrefixes +( + const hidl_vec& prefixes, + setLocalPrefixes_cb hidl_cb +) { + LocalLogBuffer::FunctionLog fl(__func__); + fl.addArg("prefixes", "unused"); + #pragma unused(prefixes) + + /* Fake Success */ + BoolResult res = ipaResultToBoolResult(RET::SUCCESS); + hidl_cb(res.success, res.errMsg); + + fl.setResult(res.success, res.errMsg); + return Void(); +} /* setLocalPrefixes */ + +Return HAL::getForwardedStats +( + const hidl_string& upstream, + getForwardedStats_cb hidl_cb +) { + LocalLogBuffer::FunctionLog fl(__func__); + fl.addArg("upstream", upstream); + + OffloadStatistics ret; + RET ipaReturn = mIPA->getStats(upstream.c_str(), true, ret); + if (ipaReturn == RET::SUCCESS) { + hidl_cb(ret.getTotalRxBytes(), ret.getTotalTxBytes()); + fl.setResult(ret.getTotalRxBytes(), ret.getTotalTxBytes()); + } else { + /* @TODO Ensure the output is zeroed, but this is probably not enough to + * tell Framework that an error has occurred. If, for example, they had + * not yet polled for statistics previously, they may incorrectly assume + * that simply no statistics have transpired on hardware path. + * + * Maybe ITetheringOffloadCallback:onEvent(OFFLOAD_STOPPED_ERROR) is + * enough to handle this case, time will tell. + */ + hidl_cb(0, 0); + fl.setResult(0, 0); + } + + mLogs.addLog(fl); + return Void(); +} /* getForwardedStats */ + +Return HAL::setDataLimit +( + const hidl_string& upstream, + uint64_t limit, + setDataLimit_cb hidl_cb +) { + LocalLogBuffer::FunctionLog fl(__func__); + fl.addArg("upstream", upstream); + fl.addArg("limit", limit); + + RET ipaReturn = mIPA->setQuota(upstream.c_str(), limit); + BoolResult res = ipaResultToBoolResult(ipaReturn); + hidl_cb(res.success, res.errMsg); + + fl.setResult(res.success, res.errMsg); + mLogs.addLog(fl); + return Void(); +} /* setDataLimit */ + +Return HAL::setUpstreamParameters +( + const hidl_string& iface, + const hidl_string& v4Addr, + const hidl_string& v4Gw, + const hidl_vec& v6Gws, + setUpstreamParameters_cb hidl_cb +) { + vector v6GwStrs = convertHidlStrToStdStr(v6Gws); + + LocalLogBuffer::FunctionLog fl(__func__); + fl.addArg("iface", iface); + fl.addArg("v4Addr", v4Addr); + fl.addArg("v4Gw", v4Gw); + fl.addArg("v6Gws", v6GwStrs); + + PrefixParser v4AddrParser; + PrefixParser v4GwParser; + PrefixParser v6GwParser; + + /* @TODO maybe we should enforce that these addresses and gateways are fully + * qualified here. But then, how do we allow them to be empty/null as well + * while still preserving a sane API on PrefixParser? + */ + if (!v4AddrParser.addV4(v4Addr) && !v4Addr.empty()) { + BoolResult res = makeInputCheckFailure(v4AddrParser.getLastErrAsStr()); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } else if (!v4GwParser.addV4(v4Gw) && !v4Gw.empty()) { + BoolResult res = makeInputCheckFailure(v4GwParser.getLastErrAsStr()); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } else if (v6GwStrs.size() >= 1 && !v6GwParser.addV6(v6GwStrs)) { + BoolResult res = makeInputCheckFailure(v6GwParser.getLastErrAsStr()); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } else if (v6GwParser.size() > 1) { + RET ipaReturn = mIPA->stopAllOffload(); + if (ipaReturn != RET::SUCCESS) { + BoolResult res = + makeInputCheckFailure("Cannot accept more than 1 IPv6 Gateway. Offload still running and may result in data path errors"); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } else { + BoolResult res = + makeInputCheckFailure("Cannot accept more than 1 IPv6 Gateway. In an effort to avoid any data path errors, offload has been stopped"); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } + } else { + RET ipaReturn = mIPA->setUpstream( + iface.c_str(), + v4GwParser.getFirstPrefix(), + v6GwParser.getFirstPrefix()); + BoolResult res = ipaResultToBoolResult(ipaReturn); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } + + mLogs.addLog(fl); + return Void(); +} /* setUpstreamParameters */ + +Return HAL::addDownstream +( + const hidl_string& iface, + const hidl_string& prefix, + addDownstream_cb hidl_cb +) { + LocalLogBuffer::FunctionLog fl(__func__); + fl.addArg("iface", iface); + fl.addArg("prefix", prefix); + + PrefixParser prefixParser; + + if (!prefixParser.add(prefix)) { + BoolResult res = makeInputCheckFailure(prefixParser.getLastErrAsStr()); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } else { + RET ipaReturn = mIPA->addDownstream( + iface.c_str(), + prefixParser.getFirstPrefix()); + BoolResult res = ipaResultToBoolResult(ipaReturn); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } + + mLogs.addLog(fl); + return Void(); +} /* addDownstream */ + +Return HAL::removeDownstream +( + const hidl_string& iface, + const hidl_string& prefix, + removeDownstream_cb hidl_cb +) { + LocalLogBuffer::FunctionLog fl(__func__); + fl.addArg("iface", iface); + fl.addArg("prefix", prefix); + + PrefixParser prefixParser; + + if (!prefixParser.add(prefix)) { + BoolResult res = makeInputCheckFailure(prefixParser.getLastErrAsStr()); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } else { + RET ipaReturn = mIPA->removeDownstream( + iface.c_str(), + prefixParser.getFirstPrefix()); + BoolResult res = ipaResultToBoolResult(ipaReturn); + hidl_cb(res.success, res.errMsg); + fl.setResult(res.success, res.errMsg); + } + + mLogs.addLog(fl); + return Void(); +} /* removeDownstream */ diff --git a/data-ipa-cfg-mgr/hal/src/IpaEventRelay.cpp b/data-ipa-cfg-mgr/hal/src/IpaEventRelay.cpp new file mode 100644 index 00000000..788b1522 --- /dev/null +++ b/data-ipa-cfg-mgr/hal/src/IpaEventRelay.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define LOG_TAG "IPAHALService/IpaEventRelay" +/* External Includes */ +#include + +/* HIDL Includes */ +#include + +/* Internal Includes */ +#include "IpaEventRelay.h" + +/* Namespace pollution avoidance */ +using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback; +using ::android::hardware::tetheroffload::control::V1_0::OffloadCallbackEvent; + + +IpaEventRelay::IpaEventRelay( + const ::android::sp& cb) : mFramework(cb) { +} /* IpaEventRelay */ + +void IpaEventRelay::onOffloadStarted() { + ALOGI("onOffloadStarted()"); + mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_STARTED); +} /* onOffloadStarted */ + +void IpaEventRelay::onOffloadStopped(StoppedReason reason) { + ALOGI("onOffloadStopped(%d)", reason); + switch (reason) { + case REQUESTED: + /* + * No way to communicate this to Framework right now, they make an + * assumption that offload is stopped when they remove the + * configuration. + */ + break; + case ERROR: + mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_STOPPED_ERROR); + break; + case UNSUPPORTED: + mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_STOPPED_UNSUPPORTED); + break; + default: + ALOGE("Unknown stopped reason(%d)", reason); + break; + } +} /* onOffloadStopped */ + +void IpaEventRelay::onOffloadSupportAvailable() { + ALOGI("onOffloadSupportAvailable()"); + mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_SUPPORT_AVAILABLE); +} /* onOffloadSupportAvailable */ + +void IpaEventRelay::onLimitReached() { + ALOGI("onLimitReached()"); + mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_STOPPED_LIMIT_REACHED); +} /* onLimitReached */ diff --git a/data-ipa-cfg-mgr/hal/src/LocalLogBuffer.cpp b/data-ipa-cfg-mgr/hal/src/LocalLogBuffer.cpp new file mode 100644 index 00000000..f556e40c --- /dev/null +++ b/data-ipa-cfg-mgr/hal/src/LocalLogBuffer.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define LOG_TAG "IPAHALService/dump" + +/* External Includes */ +#include +#include +#include +#include +#include + +/* Internal Includes */ +#include "LocalLogBuffer.h" + +/* Namespace pollution avoidance */ +using ::std::deque; +using ::std::string; +using ::std::vector; + + +LocalLogBuffer::FunctionLog::FunctionLog(string funcName) : mName(funcName) { + mArgsProvided = false; +} /* FunctionLog */ + +LocalLogBuffer::FunctionLog::FunctionLog(const FunctionLog& other) : + mName(other.mName) { + mArgsProvided = other.mArgsProvided; + /* Is this right? How do you copy stringstreams without wizardry? */ + mSSArgs.str(other.mSSArgs.str()); + mSSReturn.str(other.mSSReturn.str()); +} /* FunctionLog */ + +void LocalLogBuffer::FunctionLog::addArg(string kw, string arg) { + maybeAddArgsComma(); + mSSArgs << kw << "=" << arg; +} /* addArg */ + +void LocalLogBuffer::FunctionLog::addArg(string kw, vector args) { + maybeAddArgsComma(); + mSSArgs << kw << "=["; + for (size_t i = 0; i < args.size(); i++) { + mSSArgs << args[i]; + if (i < (args.size() - 1)) + mSSArgs << ", "; + } + mSSArgs << "]"; +} /* addArg */ + +void LocalLogBuffer::FunctionLog::addArg(string kw, uint64_t arg) { + maybeAddArgsComma(); + mSSArgs << kw << "=" << arg; +} /* addArg */ + +void LocalLogBuffer::FunctionLog::maybeAddArgsComma() { + if (!mArgsProvided) { + mArgsProvided = true; + } else { + mSSArgs << ", "; + } +} /* maybeAddArgsComma */ + +void LocalLogBuffer::FunctionLog::setResult(bool success, string msg) { + mSSReturn << "[" << ((success) ? "success" : "failure") << ", " << msg + << "]"; +} /* setResult */ + +void LocalLogBuffer::FunctionLog::setResult(vector ret) { + mSSReturn << "["; + for (size_t i = 0; i < ret.size(); i++) { + mSSReturn << ret[i]; + if (i < (ret.size() - 1)) + mSSReturn << ", "; + } + mSSReturn << "]"; +} /* setResult */ + +void LocalLogBuffer::FunctionLog::setResult(uint64_t rx, uint64_t tx) { + mSSReturn << "[rx=" << rx << ", tx=" << tx << "]"; +} /* setResult */ + +string LocalLogBuffer::FunctionLog::toString() { + stringstream ret; + ret << mName << "(" << mSSArgs.str() << ") returned " << mSSReturn.str(); + return ret.str(); +} /* toString */ + +LocalLogBuffer::LocalLogBuffer(string name, int maxLogs) : mName(name), + mMaxLogs(maxLogs) { +} /* LocalLogBuffer */ + +void LocalLogBuffer::addLog(FunctionLog log) { + while (mLogs.size() > mMaxLogs) + mLogs.pop_front(); + mLogs.push_back(log); +} /* addLog */ + +void LocalLogBuffer::toLogcat() { + for (size_t i = 0; i < mLogs.size(); i++) + ALOGD("%s: %s", mName.c_str(), mLogs[i].toString().c_str()); +} /* toLogcat */ diff --git a/data-ipa-cfg-mgr/hal/src/OffloadStatistics.cpp b/data-ipa-cfg-mgr/hal/src/OffloadStatistics.cpp new file mode 100644 index 00000000..8f8beb63 --- /dev/null +++ b/data-ipa-cfg-mgr/hal/src/OffloadStatistics.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include + +#include "OffloadStatistics.h" + + +/* ------------------------------ PUBLIC ------------------------------------ */ +OffloadStatistics::OffloadStatistics() { + this->upstream = "UNSET"; + this->rx = 0; + this->tx = 0; +} /* OffloadStatistics */ + +OffloadStatistics::OffloadStatistics +( + std::string upstream +) { + this->upstream = upstream; + this->rx = 0; + this->tx =0; +} /* OffloadStatistics */ + +uint64_t OffloadStatistics::getTotalRxBytes() { + return rx; +} /* getTotalRxBytes */ + +uint64_t OffloadStatistics::getTotalTxBytes() { + return tx; +} /* getTotalTxBytes */ diff --git a/data-ipa-cfg-mgr/hal/src/PrefixParser.cpp b/data-ipa-cfg-mgr/hal/src/PrefixParser.cpp new file mode 100644 index 00000000..60aae08b --- /dev/null +++ b/data-ipa-cfg-mgr/hal/src/PrefixParser.cpp @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* External Includes */ +#include +#include +#include +#include +#include +#include +#include + +/* Internal Includes */ +#include "IOffloadManager.h" +#include "PrefixParser.h" + +/* Avoiding namespace pollution */ +using IP_FAM = ::IOffloadManager::IP_FAM; +using Prefix = ::IOffloadManager::Prefix; + +using ::std::string; +using ::std::vector; + + +/* ------------------------------ PUBLIC ------------------------------------ */ +PrefixParser::PrefixParser() { + mLastErr = "No Err"; +} /* PrefixParser */ + +bool PrefixParser::add(vector in) { + return add(in, IP_FAM::INVALID); +} /* add */ + +bool PrefixParser::add(string in) { + return add(in, IP_FAM::INVALID); +} /* add */ + +bool PrefixParser::addV4(string in) { + return add(in, IP_FAM::V4); +} /* addV4 */ + +bool PrefixParser::addV4(vector in) { + return add(in, IP_FAM::V4); +} /* addV4 */ + +bool PrefixParser::addV6(string in) { + return add(in, IP_FAM::V6); +} /* addV6 */ + +bool PrefixParser::addV6(vector in) { + for (size_t i = 0; i < in.size(); i++) { + if (!addV6(in[i])) + return false; + } + return true; +} /* addV6 */ + +int PrefixParser::size() { + return mPrefixes.size(); +} /* size */ + +bool PrefixParser::allAreFullyQualified() { + for (size_t i = 0; i < mPrefixes.size(); i++) { + if (mPrefixes[i].fam == IP_FAM::V4) { + uint32_t masked = mPrefixes[i].v4Addr & mPrefixes[i].v4Mask; + if (masked != mPrefixes[i].v4Addr) + return false; + } else { + uint32_t masked[4]; + masked[0] = mPrefixes[i].v6Addr[0] & mPrefixes[i].v6Mask[0]; + masked[1] = mPrefixes[i].v6Addr[1] & mPrefixes[i].v6Mask[1]; + masked[2] = mPrefixes[i].v6Addr[2] & mPrefixes[i].v6Mask[2]; + masked[3] = mPrefixes[i].v6Addr[3] & mPrefixes[i].v6Mask[3]; + for (int j = 0; j < 4; j++) { + if (masked[j] != mPrefixes[i].v6Addr[j]) + return false; + } + } + } + return true; +} /* allAreFullyQualified */ + +Prefix PrefixParser::getFirstPrefix() { + if (size() >= 1) + return mPrefixes[0]; + return makeBlankPrefix(IP_FAM::INVALID); +} /* getFirstPrefix */ + +string PrefixParser::getLastErrAsStr() { + return mLastErr; +} /* getLastErrAsStr */ + + +/* ------------------------------ PRIVATE ----------------------------------- */ +bool PrefixParser::add(vector in, IP_FAM famHint) { + for (size_t i = 0; i < in.size(); i++) { + if (!add(in[i], famHint)) + return false; + } + return true; +} /* add */ + +bool PrefixParser::add(string in, IP_FAM famHint) { + if (famHint == IP_FAM::INVALID) + famHint = guessIPFamily(in); + + string subnet; + string addr; + + if (!splitIntoAddrAndMask(in, addr, subnet)) { + mLastErr = "Failed to split into Address and Mask(" + in + ")"; + return false; + } + + int mask = parseSubnetMask(subnet, famHint); + if (!isMaskValid(mask, famHint)) + return false; + + Prefix pre = makeBlankPrefix(famHint); + + if (famHint == IP_FAM::V4) { + if (!parseV4Addr(addr, pre)) { + mLastErr = "Failed to parse V4 Address(" + addr + ")"; + return false; + } + } else if (!parseV6Addr(addr, pre)) { + mLastErr = "Failed to parse V6 Address(" + addr + ")"; + return false; + } + + if (famHint == IP_FAM::V4 && !populateV4Mask(mask, pre)) { + mLastErr = "Failed to populate IPv4 Mask(" + std::to_string(mask) + + ", " + addr + ")"; + return false; + } else if (!populateV6Mask(mask, pre)) { + mLastErr = "Failed to populate IPv6 Mask(" + std::to_string(mask) + + ", " + addr + ")"; + return false; + } + + mPrefixes.push_back(pre); + return true; +} /* add */ + +/* Assumption (based on man inet_pton) + * + * X represents a hex character + * d represents a base 10 digit + * / represents the start of the subnet mask + * (assume that it can be left off of all below combinations) + * + * IPv4 Addresses always look like the following: + * ddd.ddd.ddd.ddd/dd + * + * IPv6 Addresses can look a few different ways: + * x:x:x:x:x:x:x:x/ddd + * x::x/ddd + * x:x:x:x:x:x:d.d.d.d/ddd + * + * Therefore, if a presentation of an IP Address contains a colon, then it + * may not be a valid IPv6, but, it is definitely not valid IPv4. If a + * presentation of an IP Address does not contain a colon, then it may not be + * a valid IPv4, but, it is definitely not IPv6. + */ +IP_FAM PrefixParser::guessIPFamily(string in) { + size_t found = in.find(":"); + if (found != string::npos) + return IP_FAM::V6; + return IP_FAM::V4; +} /* guessIPFamily */ + +bool PrefixParser::splitIntoAddrAndMask(string in, string &addr, string &mask) { + size_t pos = in.find("/"); + + if (pos != string::npos && pos >= 1) { + /* addr is now everything up until the first / */ + addr = in.substr(0, pos); + } else if (pos == string::npos) { + /* There is no /, so the entire input is an address */ + addr = in; + } else { + /* There was nothing before the /, not recoverable */ + return false; + } + + if (pos != string::npos && pos < in.size()) { + /* There is a / and it is not the last character. Everything after / + * must be the subnet. + */ + mask = in.substr(pos + 1); + } else if (pos != string::npos && pos == in.size()) { + /* There is a /, but it is the last character. This is garbage, but, + * we may still be able to interpret the address so we will throw it + * out. + */ + mask = ""; + } else if (pos == string::npos) { + /* There is no /, therefore, there is no subnet */ + mask = ""; + } else { + /* This really shouldn't be possible because it would imply that find + * returned a position larger than the size of the input. Just + * preserving sanity that mask is always initialized. + */ + mask = ""; + } + + return true; +} /* splitIntoAddrAndMask */ + +int PrefixParser::parseSubnetMask(string in, IP_FAM famHint) { + if (in.empty()) + /* Treat no subnet mask as fully qualified */ + return (famHint == IP_FAM::V6) ? 128 : 32; + return atoi(in.c_str()); +} /* parseSubnetMask */ + +bool PrefixParser::parseV4Addr(string in, Prefix &out) { + struct sockaddr_in sa; + + int ret = inet_pton(AF_INET, in.c_str(), &(sa.sin_addr)); + + if (ret < 0) { + /* errno would be valid */ + return false; + } else if (ret == 0) { + /* input was not a valid IP address */ + return false; + } + + /* Address in network byte order */ + out.v4Addr = htonl(sa.sin_addr.s_addr); + return true; +} /* parseV4Addr */ + +bool PrefixParser::parseV6Addr(string in, Prefix &out) { + struct sockaddr_in6 sa; + + int ret = inet_pton(AF_INET6, in.c_str(), &(sa.sin6_addr)); + + if (ret < 0) { + /* errno would be valid */ + return false; + } else if (ret == 0) { + /* input was not a valid IP address */ + return false; + } + + /* Translate unsigned chars to unsigned ints to match IPA + * + * TODO there must be a better way to do this beyond bit fiddling + * Maybe a Union since we've already made the assumption that the data + * structures match? + */ + out.v6Addr[0] = (sa.sin6_addr.s6_addr[0] << 24) | + (sa.sin6_addr.s6_addr[1] << 16) | + (sa.sin6_addr.s6_addr[2] << 8) | + (sa.sin6_addr.s6_addr[3]); + out.v6Addr[1] = (sa.sin6_addr.s6_addr[4] << 24) | + (sa.sin6_addr.s6_addr[5] << 16) | + (sa.sin6_addr.s6_addr[6] << 8) | + (sa.sin6_addr.s6_addr[7]); + out.v6Addr[2] = (sa.sin6_addr.s6_addr[8] << 24) | + (sa.sin6_addr.s6_addr[9] << 16) | + (sa.sin6_addr.s6_addr[10] << 8) | + (sa.sin6_addr.s6_addr[11]); + out.v6Addr[3] = (sa.sin6_addr.s6_addr[12] << 24) | + (sa.sin6_addr.s6_addr[13] << 16) | + (sa.sin6_addr.s6_addr[14] << 8) | + (sa.sin6_addr.s6_addr[15]); + return true; +} /* parseV6Addr */ + +bool PrefixParser::populateV4Mask(int mask, Prefix &out) { + if (mask < 0 || mask > 32) + return false; + out.v4Mask = createMask(mask); + return true; +} /* populateV4Mask */ + +bool PrefixParser::populateV6Mask(int mask, Prefix &out) { + if (mask < 0 || mask > 128) + return false; + + for (int i = 0; i < 4; i++) { + out.v6Mask[i] = createMask(mask); + mask = (mask > 32) ? mask - 32 : 0; + } + + return true; +} /* populateV6Mask */ + +uint32_t PrefixParser::createMask(int mask) { + uint32_t ret = 0; + + if (mask >= 32) { + ret = ~ret; + return ret; + } + + for (int i = 0; i < 32; i++) { + if (i < mask) + ret = (ret << 1) | 1; + else + ret = (ret << 1); + } + + return ret; +} /* createMask */ + +Prefix PrefixParser::makeBlankPrefix(IP_FAM famHint) { + Prefix ret; + + ret.fam = famHint; + + ret.v4Addr = 0; + ret.v4Mask = 0; + + ret.v6Addr[0] = 0; + ret.v6Addr[1] = 0; + ret.v6Addr[2] = 0; + ret.v6Addr[3] = 0; + + ret.v6Mask[0] = 0; + ret.v6Mask[1] = 0; + ret.v6Mask[2] = 0; + ret.v6Mask[3] = 0; + + return ret; +} /* makeBlankPrefix */ + +bool PrefixParser::isMaskValid(int mask, IP_FAM fam) { + if (mask < 0) { + mLastErr = "Failed parse subnet mask(" + std::to_string(mask) + ")"; + return false; + } else if (mask == 0) { + mLastErr = "Subnet mask cannot be 0(" + std::to_string(mask) + ")"; + return false; + } else if (fam == IP_FAM::V4 && mask > 32) { + mLastErr = "Interpreted address as V4 but mask was too large(" + + std::to_string(mask) + ")"; + return false; + } else if (fam == IP_FAM::V6 && mask > 128) { + mLastErr = "Interpreted address as V6 but mask was too large(" + + std::to_string(mask) + ")"; + return false; + } + + return true; +} /* isMaskValid */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h index 2f7709ac..27d7c8be 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -85,7 +85,8 @@ class MessageQueue Message *Head; Message *Tail; Message* dequeue(void); - static MessageQueue *inst; + static MessageQueue *inst_internal; + static MessageQueue *inst_external; MessageQueue() { @@ -99,7 +100,8 @@ class MessageQueue void enqueue(Message *item); static void* Process(void *); - static MessageQueue* getInstance(); + static MessageQueue* getInstanceInternal(); + static MessageQueue* getInstanceExternal(); }; diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h index 69c34128..1750310b 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -62,7 +62,7 @@ typedef struct _ipa_rm_client bool rx_bypass_ipa; /* support WLAN may not register RX-property, should not add dependency */ }ipa_rm_client; -#define MAX_NUM_EXT_PROPS 15 +#define MAX_NUM_EXT_PROPS 25 /* used to hold extended properties */ typedef struct @@ -113,24 +113,100 @@ class IPACM_Config bool ipacm_odu_enable; + bool ipacm_odu_embms_enable; + + bool ipacm_ip_passthrough_mode; + int ipa_nat_iface_entries; + /* Store the total number of wlan guest ap configured */ + int ipa_num_wlan_guest_ap; + + /* Max valid rm entry */ + int ipa_max_valid_rm_entry; + /* Store SW-enable or not */ bool ipa_sw_rt_enable; + /* Store bridge mode or not */ + bool ipa_bridge_enable; + + /* Store bridge netdev mac */ + uint8_t bridge_mac[IPA_MAC_ADDR_SIZE]; + + /* Store the flt rule count for each producer client*/ + int flt_rule_count_v4[IPA_CLIENT_MAX]; + int flt_rule_count_v6[IPA_CLIENT_MAX]; + /* IPACM routing table name for v4/v6 */ struct ipa_ioc_get_rt_tbl rt_tbl_lan_v4, rt_tbl_wan_v4, rt_tbl_default_v4, rt_tbl_v6, rt_tbl_wan_v6; struct ipa_ioc_get_rt_tbl rt_tbl_wan_dl; - struct ipa_ioc_get_rt_tbl rt_tbl_lan2lan_v4, rt_tbl_lan2lan_v6; - struct ipa_ioc_get_rt_tbl rt_tbl_odu_v4, rt_tbl_odu_v6; - struct ipa_ioc_get_rt_tbl rt_tbl_eth_bridge_usb_wlan_v4, rt_tbl_eth_bridge_wlan_wlan_v4; - struct ipa_ioc_get_rt_tbl rt_tbl_eth_bridge_usb_wlan_v6, rt_tbl_eth_bridge_wlan_wlan_v6; + bool isMCC_Mode; /* To return the instance */ static IPACM_Config* GetInstance(); + const char* getEventName(ipa_cm_event_id event_id); + + inline void increaseFltRuleCount(int index, ipa_ip_type iptype, int increment) + { + if((index >= IPA_CLIENT_MAX) || (index < 0)) + { + IPACMERR("Index is out of range: %d.\n", index); + return; + } + if(iptype == IPA_IP_v4) + { + flt_rule_count_v4[index] += increment; + IPACMDBG_H("Now num of v4 flt rules on client %d is %d.\n", index, flt_rule_count_v4[index]); + } + else + { + flt_rule_count_v6[index] += increment; + IPACMDBG_H("Now num of v6 flt rules on client %d is %d.\n", index, flt_rule_count_v6[index]); + } + return; + } + + inline void decreaseFltRuleCount(int index, ipa_ip_type iptype, int decrement) + { + if((index >= IPA_CLIENT_MAX) || (index < 0)) + { + IPACMERR("Index is out of range: %d.\n", index); + return; + } + if(iptype == IPA_IP_v4) + { + flt_rule_count_v4[index] -= decrement; + IPACMDBG_H("Now num of v4 flt rules on client %d is %d.\n", index, flt_rule_count_v4[index]); + } + else + { + flt_rule_count_v6[index] -= decrement; + IPACMDBG_H("Now num of v6 flt rules on client %d is %d.\n", index, flt_rule_count_v6[index]); + } + return; + } + + inline int getFltRuleCount(int index, ipa_ip_type iptype) + { + if((index >= IPA_CLIENT_MAX) || (index < 0)) + { + IPACMERR("Index is out of range: %d.\n", index); + return -1; + } + if(iptype == IPA_IP_v4) + { + return flt_rule_count_v4[index]; + } + else + { + return flt_rule_count_v6[index]; + } + } + inline int GetAlgPortCnt() { return ipa_num_alg_ports; diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h index ea956daa..16d5b9c3 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h @@ -59,17 +59,6 @@ using namespace std; #define UDP_TIMEOUT_UPDATE 20 #define BROADCAST_IPV4_ADDR 0xFFFFFFFF - -#define IPACM_TCP_UDP_DIR_NAME "/proc/sys/net/ipv4/netfilter" -#define IPACM_TCP_FILE_NAME "ip_conntrack_tcp_timeout_established" -#define IPACM_UDP_FILE_NAME "ip_conntrack_udp_timeout_stream" - -#define IPACM_TCP_FULL_FILE_NAME "/proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_established" -#define IPACM_UDP_FULL_FILE_NAME "/proc/sys/net/ipv4/netfilter/ip_conntrack_udp_timeout_stream" - -#define INOTIFY_EVT_SIZE (sizeof(struct inotify_event)) -#define INOTIFY_BUFFER_LEN (INOTIFY_EVT_SIZE + 2*sizeof(IPACM_TCP_FILE_NAME)) - class IPACM_ConntrackClient { @@ -95,7 +84,6 @@ class IPACM_ConntrackClient static void* TCPRegisterWithConnTrack(void *); static void* UDPRegisterWithConnTrack(void *); static void* UDPConnTimeoutUpdate(void *); - static void* TCPUDP_Timeout_monitor(void *); static void UpdateUDPFilters(void *, bool); static void UpdateTCPFilters(void *, bool); @@ -103,11 +91,21 @@ class IPACM_ConntrackClient static IPACM_ConntrackClient* GetInstance(); + static void UNRegisterWithConnTrack(void); + int fd_tcp; + int fd_udp; + + unsigned int subscrips_tcp; + unsigned int subscrips_udp; + #ifdef IPACM_DEBUG #define iptodot(X,Y) \ IPACMLOG(" %s(0x%x): %d.%d.%d.%d\n", X, Y, ((Y>>24) & 0xFF), ((Y>>16) & 0xFF), ((Y>>8) & 0xFF), (Y & 0xFF)); #endif +#define log_nat(A,B,C,D,E,F) \ + IPACMDBG_H("protocol %d Private IP: %d.%d.%d.%d\t Target IP: %d.%d.%d.%d\t private port: %d public port: %d %s",A,((B>>24) & 0xFF), ((B>>16) & 0xFF), ((B>>8) & 0xFF), (B & 0xFF), ((C>>24) & 0xFF), ((C>>16) & 0xFF),((C>>8) & 0xFF),(C & 0xFF),D,E,F); + }; #endif /* IPACM_CONNTRACK_FILTER_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackListener.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackListener.h index db83598a..d965cf7e 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackListener.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackListener.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -46,11 +46,21 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IPACM_LanToLan.h" #endif -#define MAX_NAT_IFACES 50 +#define MAX_IFACE_ADDRESS 50 #define MAX_STA_CLNT_IFACES 10 +#define STA_CLNT_SUBNET_MASK 0xFFFFFF00 using namespace std; +typedef struct _nat_entry_bundle +{ + struct nf_conntrack *ct; + enum nf_conntrack_msg_type type; + nat_table_entry *rule; + bool isTempEntry; + +}nat_entry_bundle; + class IPACM_ConntrackListener : public IPACM_Listener { @@ -63,8 +73,8 @@ class IPACM_ConntrackListener : public IPACM_Listener int NatIfaceCnt; int StaClntCnt; NatIfaces *pNatIfaces; - uint32_t nat_iface_ipv4_addr[MAX_NAT_IFACES]; - uint32_t nonnat_iface_ipv4_addr[MAX_NAT_IFACES]; + uint32_t nat_iface_ipv4_addr[MAX_IFACE_ADDRESS]; + uint32_t nonnat_iface_ipv4_addr[MAX_IFACE_ADDRESS]; uint32_t sta_clnt_ipv4_addr[MAX_STA_CLNT_IFACES]; IPACM_Config *pConfig; #ifdef CT_OPT @@ -77,10 +87,17 @@ class IPACM_ConntrackListener : public IPACM_Listener void TriggerWANUp(void *); void TriggerWANDown(uint32_t); int CreateNatThreads(void); - int CreateConnTrackThreads(void); + bool AddIface(nat_table_entry *, bool *); + void AddORDeleteNatEntry(const nat_entry_bundle *); + void PopulateTCPorUDPEntry(struct nf_conntrack *, uint32_t, nat_table_entry *); + void CheckSTAClient(const nat_table_entry *, bool *); + int CheckNatIface(ipacm_event_data_all *, bool *); + void HandleNonNatIPAddr(void *, bool); #ifdef CT_OPT void ProcessCTV6Message(void *); + void HandleLan2Lan(struct nf_conntrack *, + enum nf_conntrack_msg_type, nat_table_entry* ); #endif public: @@ -98,6 +115,7 @@ class IPACM_ConntrackListener : public IPACM_Listener void HandleNeighIpAddrDelEvt(uint32_t); void HandleSTAClientAddEvt(uint32_t); void HandleSTAClientDelEvt(uint32_t); + int CreateConnTrackThreads(void); }; extern IPACM_ConntrackListener *CtList; diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h index 1fb12bfd..e50b3168 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -44,6 +44,9 @@ extern "C" #define MAX_TEMP_ENTRIES 25 +#define IPACM_TCP_FULL_FILE_NAME "/proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_established" +#define IPACM_UDP_FULL_FILE_NAME "/proc/sys/net/ipv4/netfilter/ip_conntrack_udp_timeout_stream" + typedef struct _nat_table_entry { uint32_t private_ip; @@ -52,7 +55,7 @@ typedef struct _nat_table_entry uint32_t target_ip; uint16_t target_port; - uint16_t public_ip; + uint32_t public_ip; uint16_t public_port; u_int8_t protocol; @@ -117,12 +120,12 @@ class NatApp int DelEntriesOnClntDiscon(uint32_t); int DelEntriesOnSTAClntDiscon(uint32_t); - void UpdateTcpUdpTo(uint32_t, int proto); + void Read_TcpUdp_Timeout(void); void AddTempEntry(const nat_table_entry *); void CacheEntry(const nat_table_entry *); void DeleteTempEntry(const nat_table_entry *); - void FlushTempEntries(uint32_t, bool); + void FlushTempEntries(uint32_t, bool, bool isDummy = false); }; diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h index c1941a1b..31d85437 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h @@ -1,5 +1,5 @@ -/* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +/* +Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -45,6 +45,12 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "IPACM_Log.h" +#ifdef USE_GLIB +#include +#define strlcpy g_strlcpy +#define strlcat g_strlcat +#endif + extern "C" { #include @@ -57,10 +63,10 @@ extern "C" #define IPA_ALG_PROTOCOL_NAME_LEN 10 #define IPA_WLAN_PARTIAL_HDR_OFFSET 0 // dst mac first then src mac -//#define IPA_ETH_PARTIAL_HDR_OFFSET 8 // dst mac first then src mac #define IPA_ODU_PARTIAL_HDR_OFFSET 8 // dst mac first then src mac #define IPA_WLAN_PARTIAL_HDR_NAME_v4 "IEEE802_3_v4" #define IPA_WLAN_PARTIAL_HDR_NAME_v6 "IEEE802_3_v6" +#define IPA_DUMMY_ETH_HDR_NAME_v6 "ETH_dummy_v6" #define IPA_WAN_PARTIAL_HDR_NAME_v4 "IEEE802_3_STA_v4" #define IPA_WAN_PARTIAL_HDR_NAME_v6 "IEEE802_3_STA_v6" #define IPA_ETH_HDR_NAME_v4 "IPACM_ETH_v4" @@ -69,43 +75,37 @@ extern "C" #define IPA_ODU_HDR_NAME_v6 "IPACM_ODU_v6" -#define IPA_MAX_IFACE_ENTRIES 15 +#define IPA_MAX_IFACE_ENTRIES 20 #define IPA_MAX_PRIVATE_SUBNET_ENTRIES 3 #define IPA_MAX_ALG_ENTRIES 20 #define IPA_MAX_RM_ENTRY 6 +#define IPV4_ADDR_LINKLOCAL 0xA9FE0000 +#define IPV4_ADDR_LINKLOCAL_MASK 0xFFFF0000 + #define V4_DEFAULT_ROUTE_TABLE_NAME "ipa_dflt_rt" #define V4_LAN_ROUTE_TABLE_NAME "COMRTBLLANv4" #define V4_WAN_ROUTE_TABLE_NAME "WANRTBLv4" #define WAN_DL_ROUTE_TABLE_NAME "ipa_dflt_wan_rt" #define V6_COMMON_ROUTE_TABLE_NAME "COMRTBLv6" #define V6_WAN_ROUTE_TABLE_NAME "WANRTBLv6" -#define V4_LAN_TO_LAN_ROUTE_TABLE_NAME "LANTOLANRTBLv4" -#define V6_LAN_TO_LAN_ROUTE_TABLE_NAME "LANTOLANRTBLv6" #define V4_ODU_ROUTE_TABLE_NAME "ODURTBLv4" #define V6_ODU_ROUTE_TABLE_NAME "ODURTBLv6" -#define ETH_BRIDGE_USB_WLAN_ROUTE_TABLE_NAME_V4 "ETH_BRIDGE_USB_WLAN_RTBLv4" -#define ETH_BRIDGE_WLAN_WLAN_ROUTE_TABLE_NAME_V4 "ETH_BRIDGE_WLAN_WLAN_RTBLv4" -#define ETH_BRIDGE_USB_WLAN_ROUTE_TABLE_NAME_V6 "ETH_BRIDGE_USB_WLAN_RTBLv6" -#define ETH_BRIDGE_WLAN_WLAN_ROUTE_TABLE_NAME_V6 "ETH_BRIDGE_WLAN_WLAN_RTBLv6" - #define WWAN_QMI_IOCTL_DEVICE_NAME "/dev/wwan_ioctl" #define IPA_DEVICE_NAME "/dev/ipa" +#define MAX_NUM_PROP 2 + +#ifndef FEATURE_IPA_V3 #define IPA_MAX_FLT_RULE 50 +#else +#define IPA_MAX_FLT_RULE 100 +#endif -#define MAX_OFFLOAD_PAIR 3 -#define MAX_NUM_PROP 8 -#define IPA_LAN_TO_LAN_USB_HDR_NAME_V4 "Lan2Lan_USB_v4" -#define IPA_LAN_TO_LAN_USB_HDR_NAME_V6 "Lan2Lan_USB_v6" -#define IPA_LAN_TO_LAN_WLAN_HDR_NAME_V4 "Lan2Lan_Wlan_v4" -#define IPA_LAN_TO_LAN_WLAN_HDR_NAME_V6 "Lan2Lan_Wlan_v6" -#define IPA_LAN_TO_LAN_MAX_WLAN_CLIENT 32 -#define IPA_LAN_TO_LAN_MAX_USB_CLIENT 1 #define TCP_FIN_SHIFT 16 #define TCP_SYN_SHIFT 17 #define TCP_RST_SHIFT 18 -#define NUM_TCP_CTL_FLT_RULE 3 +#define NUM_IPV6_PREFIX_FLT_RULE 1 /*--------------------------------------------------------------------------- Return values indicating error status @@ -128,65 +128,71 @@ extern "C" ===========================================================================*/ typedef enum { - IPA_CFG_CHANGE_EVENT = 1, /* 1 NULL */ - IPA_LINK_UP_EVENT, /* 2 ipacm_event_data_fid */ - IPA_LINK_DOWN_EVENT, /* 3 ipacm_event_data_fid */ - IPA_ADDR_ADD_EVENT, /* 4 ipacm_event_data_addr */ - IPA_ADDR_DEL_EVENT, /* 5 no use */ - IPA_ROUTE_ADD_EVENT, /* 6 ipacm_event_data_addr */ - IPA_ROUTE_DEL_EVENT, /* 7 ipacm_event_data_addr */ - IPA_FIREWALL_CHANGE_EVENT, /* 8 NULL */ - IPA_WLAN_AP_LINK_UP_EVENT, /* 9 ipacm_event_data_mac */ - IPA_WLAN_STA_LINK_UP_EVENT, /* 10 ipacm_event_data_mac */ - IPA_WLAN_CLIENT_ADD_EVENT, /* 11 ipacm_event_data_mac */ - IPA_WLAN_CLIENT_DEL_EVENT, /* 12 ipacm_event_data_mac */ - IPA_WLAN_CLIENT_POWER_SAVE_EVENT, /* 13 ipacm_event_data_mac */ - IPA_WLAN_CLIENT_RECOVER_EVENT, /* 14 ipacm_event_data_mac */ - IPA_NEW_NEIGH_EVENT, /* 15 ipacm_event_data_all */ - IPA_DEL_NEIGH_EVENT, /* 16 ipacm_event_data_all */ - IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, /* 17 ipacm_event_data_all */ - IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, /* 18 ipacm_event_data_all */ - IPA_SW_ROUTING_ENABLE, /* 19 NULL */ - IPA_SW_ROUTING_DISABLE, /* 20 NULL */ - IPA_PROCESS_CT_MESSAGE, /* 21 ipacm_ct_evt_data */ - IPA_HANDLE_WAN_UP, /* 22 ipacm_event_iface_up */ - IPA_HANDLE_WAN_DOWN, /* 23 ipacm_event_iface_up */ - IPA_HANDLE_WLAN_UP, /* 24 ipacm_event_iface_up */ - IPA_HANDLE_LAN_UP, /* 25 ipacm_event_iface_up */ - IPA_WLAN_CLIENT_ADD_EVENT_EX, /* 26 ipacm_event_data_wlan_ex */ - IPA_HANDLE_WAN_UP_V6, /* 27 NULL */ - IPA_HANDLE_WAN_DOWN_V6, /* 28 NULL */ - IPA_LAN_CLIENT_ACTIVE, /* 29 ipacm_event_lan_client*/ - IPA_LAN_CLIENT_INACTIVE, /* 30 ipacm_event_lan_client*/ - IPA_LAN_CLIENT_DISCONNECT, /* 31 ipacm_event_lan_client*/ - IPA_LAN_CLIENT_POWER_SAVE, /* 32 ipacm_event_lan_client*/ - IPA_LAN_CLIENT_POWER_RECOVER, /* 33 ipacm_event_lan_client*/ - IPA_LAN_TO_LAN_NEW_CONNECTION, /* 34 ipacm_event_connection */ - IPA_LAN_TO_LAN_DEL_CONNECTION, /* 35 ipacm_event_connection */ - IPA_LAN_DELETE_SELF, /* 36 ipacm_event_data_fid */ - IPA_WLAN_LINK_DOWN_EVENT, /* 37 ipacm_event_data_mac */ - IPA_USB_LINK_UP_EVENT, /* 38 ipacm_event_data_fid */ - IPA_PROCESS_CT_MESSAGE_V6, /* 39 ipacm_ct_evt_data */ - IPA_PRIVATE_SUBNET_CHANGE_EVENT, /* 40 ipacm_event_data_fid */ - IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, /* 41 ipacm_event_data_fid */ - IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, /* 42 ipacm_event_data_fid */ - IPA_WAN_EMBMS_LINK_UP_EVENT, /* 43 ipacm_event_data_mac */ - IPA_ETH_BRIDGE_USB_CLIENT_ADD_EVENT, /* 44 ipacm_event_data_mac */ - IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT, /* 45 ipacm_event_data_mac */ - IPA_ETH_BRIDGE_USB_CLIENT_DEL_EVENT, /* 46 ipacm_event_data_mac */ - IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT, /* 47 ipacm_event_data_mac */ - IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT, /* 48 ipacm_event_data_if_cat */ - IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, /* 49 ipacm_event_data_if_cat */ - IPA_WLAN_SWITCH_TO_SCC, /* 50 No Data */ - IPA_WLAN_SWITCH_TO_MCC, /* 51 No Data */ - IPA_CRADLE_WAN_MODE_SWITCH, /* 52 ipacm_event_cradle_wan_mode */ - IPA_WAN_XLAT_CONNECT_EVENT, /* 53 ipacm_event_data_fid */ - IPA_TETHERING_STATS_UPDATE_EVENT, /* 54 ipacm_event_data_fid */ - IPA_NETWORK_STATS_UPDATE_EVENT, /* 55 ipacm_event_data_fid */ - IPA_HANDLE_WAN_UP_TETHER, /* 56 ipacm_event_iface_up_tehter */ - IPA_HANDLE_WAN_DOWN_TETHER, /* 57 ipacm_event_iface_up_tehter */ - IPA_HANDLE_WAN_UP_V6_TETHER, /* 58 ipacm_event_iface_up_tehter */ - IPA_HANDLE_WAN_DOWN_V6_TETHER, /* 59 ipacm_event_iface_up_tehter */ + IPA_CFG_CHANGE_EVENT, /* NULL */ + IPA_PRIVATE_SUBNET_CHANGE_EVENT, /* ipacm_event_data_fid */ + IPA_FIREWALL_CHANGE_EVENT, /* NULL */ + IPA_LINK_UP_EVENT, /* ipacm_event_data_fid */ + IPA_LINK_DOWN_EVENT, /* ipacm_event_data_fid */ + IPA_USB_LINK_UP_EVENT, /* ipacm_event_data_fid */ + IPA_BRIDGE_LINK_UP_EVENT, /* ipacm_event_data_all */ + IPA_WAN_EMBMS_LINK_UP_EVENT, /* ipacm_event_data_mac */ + IPA_ADDR_ADD_EVENT, /* ipacm_event_data_addr */ + IPA_ADDR_DEL_EVENT, /* no use */ + IPA_ROUTE_ADD_EVENT, /* ipacm_event_data_addr */ + IPA_ROUTE_DEL_EVENT, /* ipacm_event_data_addr */ + IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, /* ipacm_event_data_fid */ + IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, /* ipacm_event_data_fid */ + IPA_WLAN_AP_LINK_UP_EVENT, /* ipacm_event_data_mac */ + IPA_WLAN_STA_LINK_UP_EVENT, /* ipacm_event_data_mac */ + IPA_WLAN_LINK_DOWN_EVENT, /* ipacm_event_data_mac */ + IPA_WLAN_CLIENT_ADD_EVENT, /* ipacm_event_data_mac */ + IPA_WLAN_CLIENT_ADD_EVENT_EX, /* ipacm_event_data_wlan_ex */ + IPA_WLAN_CLIENT_DEL_EVENT, /* ipacm_event_data_mac */ + IPA_WLAN_CLIENT_POWER_SAVE_EVENT, /* ipacm_event_data_mac */ + IPA_WLAN_CLIENT_RECOVER_EVENT, /* ipacm_event_data_mac */ + IPA_NEW_NEIGH_EVENT, /* ipacm_event_data_all */ + IPA_DEL_NEIGH_EVENT, /* ipacm_event_data_all */ + IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, /* ipacm_event_data_all */ + IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, /* ipacm_event_data_all */ + IPA_SW_ROUTING_ENABLE, /* NULL */ + IPA_SW_ROUTING_DISABLE, /* NULL */ + IPA_PROCESS_CT_MESSAGE, /* ipacm_ct_evt_data */ + IPA_PROCESS_CT_MESSAGE_V6, /* ipacm_ct_evt_data */ + IPA_LAN_TO_LAN_NEW_CONNECTION, /* ipacm_event_connection */ + IPA_LAN_TO_LAN_DEL_CONNECTION, /* ipacm_event_connection */ + IPA_WLAN_SWITCH_TO_SCC, /* No Data */ + IPA_WLAN_SWITCH_TO_MCC, /* No Data */ + IPA_CRADLE_WAN_MODE_SWITCH, /* ipacm_event_cradle_wan_mode */ + IPA_WAN_XLAT_CONNECT_EVENT, /* ipacm_event_data_fid */ + IPA_TETHERING_STATS_UPDATE_EVENT, /* ipacm_event_data_fid */ + IPA_NETWORK_STATS_UPDATE_EVENT, /* ipacm_event_data_fid */ + + IPA_EXTERNAL_EVENT_MAX, + + IPA_HANDLE_WAN_UP, /* ipacm_event_iface_up */ + IPA_HANDLE_WAN_DOWN, /* ipacm_event_iface_up */ + IPA_HANDLE_WAN_UP_V6, /* NULL */ + IPA_HANDLE_WAN_DOWN_V6, /* NULL */ + IPA_HANDLE_WAN_UP_TETHER, /* ipacm_event_iface_up_tehter */ + IPA_HANDLE_WAN_DOWN_TETHER, /* ipacm_event_iface_up_tehter */ + IPA_HANDLE_WAN_UP_V6_TETHER, /* ipacm_event_iface_up_tehter */ + IPA_HANDLE_WAN_DOWN_V6_TETHER, /* ipacm_event_iface_up_tehter */ + IPA_HANDLE_WLAN_UP, /* ipacm_event_iface_up */ + IPA_HANDLE_LAN_UP, /* ipacm_event_iface_up */ + IPA_ETH_BRIDGE_IFACE_UP, /* ipacm_event_eth_bridge*/ + IPA_ETH_BRIDGE_IFACE_DOWN, /* ipacm_event_eth_bridge*/ + IPA_ETH_BRIDGE_CLIENT_ADD, /* ipacm_event_eth_bridge */ + IPA_ETH_BRIDGE_CLIENT_DEL, /* ipacm_event_eth_bridge*/ + IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, /* ipacm_event_eth_bridge*/ + IPA_LAN_DELETE_SELF, /* ipacm_event_data_fid */ + IPA_DOWNSTREAM_ADD, /* ipacm_event_ipahal_stream */ + IPA_DOWNSTREAM_DEL, /* ipacm_event_ipahal_stream */ + IPA_ADD_VLAN_IFACE, /* ipa_ioc_vlan_iface_info */ + IPA_DEL_VLAN_IFACE, /* ipa_ioc_vlan_iface_info */ + IPA_ADD_L2TP_VLAN_MAPPING, /* ipa_ioc_l2tp_vlan_mapping_info */ + IPA_DEL_L2TP_VLAN_MAPPING, /* ipa_ioc_l2tp_vlan_mapping_info */ + IPA_HANDLE_VLAN_CLIENT_INFO, /* ipacm_event_data_all */ + IPA_HANDLE_VLAN_IFACE_INFO, /* ipacm_event_data_all */ IPACM_EVENT_MAX } ipa_cm_event_id; @@ -208,6 +214,18 @@ typedef enum UNKNOWN_IF } ipacm_iface_type; +typedef enum +{ + ROUTER = 0, + BRIDGE +} ipacm_cradle_iface_mode; + +typedef enum +{ + FULL, + INTERNET +} ipacm_wlan_access_mode; + typedef struct { struct nf_conntrack *ct; @@ -218,6 +236,8 @@ typedef struct { char iface_name[IPA_IFACE_NAME_LEN]; ipacm_iface_type if_cat; + ipacm_cradle_iface_mode if_mode; + ipacm_wlan_access_mode wlan_mode; int netlink_interface_index; } ipa_ifi_dev_name_t; @@ -235,18 +255,23 @@ typedef struct _ipacm_event_data_all uint32_t ipv4_addr; uint32_t ipv6_addr[4]; uint8_t mac_addr[IPA_MAC_ADDR_SIZE]; + char iface_name[IPA_IFACE_NAME_LEN]; } ipacm_event_data_all; class IPACM_Lan; typedef struct { - enum ipa_ip_type iptype; - uint32_t ipv4_addr; - uint32_t ipv6_addr[4]; + ipacm_cradle_iface_mode cradle_wan_mode; +} ipacm_event_cradle_wan_mode; + +typedef struct +{ + IPACM_Lan *p_iface; + ipa_ip_type iptype; uint8_t mac_addr[6]; - IPACM_Lan* p_iface; -} ipacm_event_lan_client; + char iface_name[IPA_IFACE_NAME_LEN]; +} ipacm_event_eth_bridge; typedef struct { @@ -262,27 +287,40 @@ typedef struct _ipacm_event_data_fid int if_index; } ipacm_event_data_fid; +typedef struct +{ + ipacm_iface_type if_cat; +} ipacm_event_data_if_cat; + typedef struct _ipacm_event_data_iptype { int if_index; int if_index_tether; enum ipa_ip_type iptype; +#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN + uint32_t ipv4_addr_gw; + uint32_t ipv6_addr_gw[4]; +#endif } ipacm_event_data_iptype; typedef struct _ipacm_event_data_addr { enum ipa_ip_type iptype; + char iface_name[IPA_IFACE_NAME_LEN]; int if_index; + uint32_t ipv4_addr_gw; uint32_t ipv4_addr; uint32_t ipv4_addr_mask; uint32_t ipv6_addr[4]; uint32_t ipv6_addr_mask[4]; + uint32_t ipv6_addr_gw[4]; } ipacm_event_data_addr; typedef struct _ipacm_event_data_mac { int if_index; + int ipa_if_cate; uint8_t mac_addr[IPA_MAC_ADDR_SIZE]; } ipacm_event_data_mac; @@ -300,6 +338,7 @@ typedef struct _ipacm_event_iface_up uint32_t addr_mask; uint32_t ipv6_prefix[2]; bool is_sta; + uint8_t xlat_mux_id; }ipacm_event_iface_up; typedef struct _ipacm_event_iface_up_tether @@ -323,4 +362,17 @@ typedef struct _ipacm_ifacemgr_data uint8_t mac_addr[IPA_MAC_ADDR_SIZE]; }ipacm_ifacemgr_data; +typedef struct _ipacm_offload_prefix { + enum ipa_ip_type iptype; + uint32_t v4Addr; + uint32_t v4Mask; + uint32_t v6Addr[4]; + uint32_t v6Mask[4]; +} ipacm_offload_prefix; + +typedef struct { + int if_index; + _ipacm_offload_prefix prefix; +} ipacm_event_ipahal_stream; + #endif /* IPA_CM_DEFS_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h index 7554ba90..9bb82478 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h @@ -1,5 +1,5 @@ -/* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +/* +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -53,6 +53,7 @@ class IPACM_Filtering IPACM_Filtering(); ~IPACM_Filtering(); bool AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTable); + bool AddFilteringRuleAfter(struct ipa_ioc_add_flt_rule_after const *ruleTable); bool DeleteFilteringRule(struct ipa_ioc_del_flt_rule *ruleTable); bool Commit(enum ipa_ip_type ip); bool Reset(enum ipa_ip_type ip); diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h index 4cff4c5b..04696993 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -59,9 +59,9 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define IPV4_DEFAULT_FILTERTING_RULES 3 #ifdef FEATURE_IPA_ANDROID -#define IPV6_DEFAULT_FILTERTING_RULES 6 +#define IPV6_DEFAULT_FILTERTING_RULES 7 #else -#define IPV6_DEFAULT_FILTERTING_RULES 3 +#define IPV6_DEFAULT_FILTERTING_RULES 4 #endif #define IPV6_DEFAULT_LAN_FILTERTING_RULES 1 @@ -81,7 +81,7 @@ class IPACM_Iface :public IPACM_Listener int ipa_if_num; /* IPACM interface category */ - int ipa_if_cate; + ipacm_iface_type ipa_if_cate; /* IPACM interface name */ char dev_name[IF_NAME_LEN]; @@ -92,8 +92,6 @@ class IPACM_Iface :public IPACM_Listener /* IPACM interface v6 ip-address*/ uint32_t ipv6_addr[MAX_DEFAULT_v6_ROUTE_RULES][4]; - uint32_t header_hdl; - uint32_t software_routing_fl_rule_hdl[MAX_SOFTWAREROUTING_FILTERTING_RULES]; bool softwarerouting_act; @@ -128,15 +126,12 @@ class IPACM_Iface :public IPACM_Listener /*Query the IPA endpoint property */ int query_iface_property(void); - /*implement IPACM strlcpy */ - size_t strlcpy(char *dest, const char *src, size_t size); - - /*implement IPACM strlcat */ - size_t strlcat(char *dest, const char *src, size_t n); - /*Configure the initial filter rules */ virtual int init_fl_rule(ipa_ip_type iptype); + /* Change IP Type.*/ + void config_ip_type(ipa_ip_type iptype); + /* Get interface index */ virtual int ipa_get_if_index(char * if_name, int * if_index); @@ -150,11 +145,6 @@ class IPACM_Iface :public IPACM_Listener /* software routing disable */ virtual int handle_software_routing_disable(void); - /* used to get filtering rule index in table */ - int flt_rule_count_v4; - - int flt_rule_count_v6; - private: static const char *DEVICE_NAME; diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h index e65c5d5b..c7184f20 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -48,7 +48,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IPACM_Listener.h" #include "IPACM_Iface.h" -#define IPA_MAX_NUM_NEIGHBOR_CLIENTS 17 #define IPA_INSTANCE_NOT_FOUND 0 #define IPA_INSTANCE_FOUND 1 diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h index adbc8380..280c8301 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -53,11 +53,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define IPA_WAN_DEFAULT_FILTER_RULE_HANDLES 1 #define IPA_PRIV_SUBNET_FILTER_RULE_HANDLES 3 #define IPA_NUM_ODU_ROUTE_RULES 2 -#define MAX_WAN_UL_FILTER_RULES 20 -#define NUM_IPV6_PREFIX_FLT_RULE 1 +#define MAX_WAN_UL_FILTER_RULES MAX_NUM_EXT_PROPS +#define NUM_IPV4_ICMP_FLT_RULE 1 #define NUM_IPV6_ICMP_FLT_RULE 1 -/* echo ipatetherstats */ +/* ndc bandwidth ipatetherstats */ /* out_bytes> out_pkts> in_bytes> in_pkts */ #define PIPE_STATS "%s %s %lu %lu %lu %lu" @@ -97,44 +97,6 @@ typedef struct _ipa_eth_client eth_client_rt_hdl eth_rt_hdl[0]; /* depends on number of tx properties */ }ipa_eth_client; -struct lan2lan_flt_rule_hdl -{ - uint32_t rule_hdl; - bool valid; -}; - -struct lan2lan_hdr_hdl -{ - uint32_t hdr_hdl; - bool valid; -}; - -struct eth_bridge_client_flt_info -{ - uint8_t mac[IPA_MAC_ADDR_SIZE]; - uint32_t flt_rule_hdl_v4; - bool flt_rule_set_v4; - uint32_t flt_rule_hdl_v6; - bool flt_rule_set_v6; -}; - -struct eth_bridge_client_rt_info -{ - uint8_t mac[IPA_MAC_ADDR_SIZE]; - uint32_t rt_rule_hdl[0]; -}; - -struct hdr_proc_ctx_info -{ - uint32_t proc_ctx_hdl; - bool valid; -}; - -struct eth_bridge_subnet_client_info -{ - uint8_t mac[IPA_MAC_ADDR_SIZE]; - int ipa_if_num; -}; /* lan iface */ class IPACM_Lan : public IPACM_Iface @@ -151,13 +113,12 @@ class IPACM_Lan : public IPACM_Iface uint32_t private_fl_rule_hdl[IPA_MAX_PRIVATE_SUBNET_ENTRIES]; /* LAN-iface's callback function */ - void event_callback(ipa_cm_event_id event, - void *data); + void event_callback(ipa_cm_event_id event, void *data); virtual int handle_wan_up(ipa_ip_type ip_type); /* configure filter rule for wan_up event*/ - virtual int handle_wan_up_ex(ipacm_ext_prop* ext_prop, ipa_ip_type iptype); + virtual int handle_wan_up_ex(ipacm_ext_prop* ext_prop, ipa_ip_type iptype, uint8_t xlat_mux_id); /* delete filter rule for wan_down event*/ virtual int handle_wan_down(bool is_sta_mode); @@ -173,96 +134,89 @@ class IPACM_Lan : public IPACM_Iface int handle_addr_evt_odu_bridge(ipacm_event_data_addr* data); + int handle_del_ipv6_addr(ipacm_event_data_all *data); + static bool odu_up; /* install UL filter rule from Q6 */ - virtual int handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptype); - - int add_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t src_v4_addr, uint32_t dst_v4_addr, uint32_t* src_v6_addr, uint32_t* dst_v6_addr, uint32_t* rule_hdl); + virtual int handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptype, uint8_t xlat_mux_id); - int del_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl); + int handle_cradle_wan_mode_switch(bool is_wan_bridge_mode); - virtual int add_lan2lan_hdr(ipa_ip_type iptype, uint8_t* src_mac, uint8_t* dst_mac, uint32_t* hdr_hdl); + int install_ipv4_icmp_flt_rule(); - int add_lan2lan_rt_rule(ipa_ip_type iptype, uint32_t src_v4_addr, uint32_t dst_v4_addr, - uint32_t* src_v6_addr, uint32_t* dst_v6_addr, uint32_t hdr_hdl, lan_to_lan_rt_rule_hdl* rule_hdl); - int del_lan2lan_rt_rule(ipa_ip_type iptype, lan_to_lan_rt_rule_hdl); + /* add header processing context and return handle to lan2lan controller */ + int eth_bridge_add_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_hdr_type, uint32_t *hdl); - int del_lan2lan_hdr(ipa_ip_type iptype, uint32_t hdr_hdl); + /* add routing rule and return handle to lan2lan controller */ + int eth_bridge_add_rt_rule(uint8_t *mac, char *rt_tbl_name, uint32_t hdr_proc_ctx_hdl, + ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int *rt_rule_count); + /* modify routing rule*/ + int eth_bridge_modify_rt_rule(uint8_t *mac, uint32_t hdr_proc_ctx_hdl, + ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int rt_rule_count); + /* add filtering rule and return handle to lan2lan controller */ + int eth_bridge_add_flt_rule(uint8_t *mac, uint32_t rt_tbl_hdl, ipa_ip_type iptype, uint32_t *flt_rule_hdl); - static ipa_hdr_l2_type usb_hdr_type; - static ipa_hdr_l2_type wlan_hdr_type; + /* delete filtering rule */ + int eth_bridge_del_flt_rule(uint32_t flt_rule_hdl, ipa_ip_type iptype); - static uint32_t usb_hdr_template_hdl; - static uint32_t wlan_hdr_template_hdl; + /* delete routing rule */ + int eth_bridge_del_rt_rule(uint32_t rt_rule_hdl, ipa_ip_type iptype); - static hdr_proc_ctx_info usb_to_wlan_hdr_proc_ctx, wlan_to_usb_hdr_proc_ctx; - static hdr_proc_ctx_info wlan_to_wlan_hdr_proc_ctx; + /* delete header processing context */ + int eth_bridge_del_hdr_proc_ctx(uint32_t hdr_proc_ctx_hdl); - static eth_bridge_subnet_client_info eth_bridge_wlan_client[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; - static eth_bridge_subnet_client_info eth_bridge_usb_client[IPA_LAN_TO_LAN_MAX_USB_CLIENT]; - - static int num_wlan_client; - static int num_usb_client; - -protected: + /* add l2tp rt rule for l2tp client */ + int add_l2tp_rt_rule(ipa_ip_type iptype, uint8_t *dst_mac, ipa_hdr_l2_type peer_l2_hdr_type, + uint32_t l2tp_session_id, uint32_t vlan_id, uint8_t *vlan_client_mac, uint32_t *vlan_iface_ipv6_addr, + uint32_t *vlan_client_ipv6_addr, uint32_t *first_pass_hdr_hdl, uint32_t *first_pass_hdr_proc_ctx_hdl, + uint32_t *second_pass_hdr_hdl, int *num_rt_hdl, uint32_t *first_pass_rt_rule_hdl, uint32_t *second_pass_rt_rule_hdl); - lan2lan_flt_rule_hdl wlan_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; - lan2lan_flt_rule_hdl wlan_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; + /* delete l2tp rt rule for l2tp client */ + int del_l2tp_rt_rule(ipa_ip_type iptype, uint32_t first_pass_hdr_hdl, uint32_t first_pass_hdr_proc_ctx_hdl, + uint32_t second_pass_hdr_hdl, int num_rt_hdl, uint32_t *first_pass_rt_rule_hdl, uint32_t *second_pass_rt_rule_hdl); - eth_bridge_client_flt_info eth_bridge_wlan_client_flt_info[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; - int wlan_client_flt_info_count; + /* add l2tp rt rule for non l2tp client */ + int add_l2tp_rt_rule(ipa_ip_type iptype, uint8_t *dst_mac, uint32_t *hdr_proc_ctx_hdl, + int *num_rt_hdl, uint32_t *rt_rule_hdl); - eth_bridge_client_rt_info* eth_bridge_usb_client_rt_info_v4; - eth_bridge_client_rt_info* eth_bridge_usb_client_rt_info_v6; - int usb_client_rt_info_count_v4; - int usb_client_rt_info_count_v6; - int client_rt_info_size_v4; - int client_rt_info_size_v6; + /* delete l2tp rt rule for non l2tp client */ + int del_l2tp_rt_rule(ipa_ip_type iptype, int num_rt_hdl, uint32_t *rt_rule_hdl); - int each_client_rt_rule_count_v4; - int each_client_rt_rule_count_v6; + /* add l2tp flt rule on l2tp interface */ + int add_l2tp_flt_rule(uint8_t *dst_mac, uint32_t *flt_rule_hdl); - virtual int eth_bridge_handle_dummy_wlan_client_flt_rule(ipa_ip_type iptype); + /* delete l2tp flt rule on l2tp interface */ + int del_l2tp_flt_rule(uint32_t flt_rule_hdl); - virtual int eth_bridge_add_wlan_guest_ap_flt_rule(ipa_ip_type iptype); + /* add l2tp flt rule on non l2tp interface */ + int add_l2tp_flt_rule(ipa_ip_type iptype, uint8_t *dst_mac, uint32_t *vlan_client_ipv6_addr, + uint32_t *first_pass_flt_rule_hdl, uint32_t *second_pass_flt_rule_hdl); - virtual int eth_bridge_handle_dummy_usb_client_flt_rule(ipa_ip_type iptype); + /* delete l2tp flt rule on non l2tp interface */ + int del_l2tp_flt_rule(ipa_ip_type iptype, uint32_t first_pass_flt_rule_hdl, uint32_t second_pass_flt_rule_hdl); - int eth_bridge_add_wlan_client_flt_rule(uint8_t* mac, ipa_ip_type iptype); - - int eth_bridge_del_wlan_client_flt_rule(uint8_t* mac); - - int eth_bridge_post_lan_client_event(uint8_t* mac_addr, ipa_cm_event_id evt); - - int add_hdr_proc_ctx(); - - int del_hdr_proc_ctx(); - - ipa_hdr_proc_type get_hdr_proc_type(ipa_hdr_l2_type t1, ipa_hdr_l2_type t2); - - virtual int eth_bridge_install_cache_wlan_client_flt_rule(ipa_ip_type iptype); - - virtual int eth_bridge_install_cache_usb_client_flt_rule(ipa_ip_type iptype); - - int eth_bridge_add_usb_client_rt_rule(uint8_t* mac, ipa_ip_type iptype); - - int eth_bridge_del_usb_client_rt_rule(uint8_t* mac); - - eth_bridge_client_rt_info* eth_bridge_get_client_rt_info_ptr(uint8_t index, ipa_ip_type iptype); +protected: - void eth_bridge_add_usb_client(uint8_t* mac); + int each_client_rt_rule_count[IPA_IP_MAX]; - void eth_bridge_del_usb_client(uint8_t* mac); + uint32_t eth_bridge_flt_rule_offset[IPA_IP_MAX]; - int eth_bridge_get_hdr_template_hdl(uint32_t* hdr_hdl); + /* mac address has to be provided for client related events */ + void eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac, + uint32_t *ipv6_addr, char *iface_name); + /* check if the event is associated with vlan interface */ + bool is_vlan_event(char *event_iface_name); + /* check if the event is associated with l2tp interface */ + bool is_l2tp_event(char *event_iface_name); - virtual int add_dummy_lan2lan_flt_rule(ipa_ip_type iptype); + /* check if the IPv6 address is unique local address */ + bool is_unique_local_ipv6_addr(uint32_t *ipv6_addr); virtual int add_dummy_private_subnet_flt_rule(ipa_ip_type iptype); @@ -270,10 +224,9 @@ class IPACM_Lan : public IPACM_Iface int reset_to_dummy_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl); - /*handle lan2lan client active*/ - int handle_lan2lan_client_active(ipacm_event_data_all *data, ipa_cm_event_id event); + virtual int install_ipv6_prefix_flt_rule(uint32_t* prefix); - int install_ipv6_prefix_flt_rule(uint32_t* prefix); + virtual void delete_ipv6_prefix_flt_rule(); int install_ipv6_icmp_flt_rule(); @@ -285,25 +238,13 @@ class IPACM_Lan : public IPACM_Iface /* handle tethering client */ int handle_tethering_client(bool reset, ipacm_client_enum ipa_client); - lan2lan_flt_rule_hdl lan2lan_flt_rule_hdl_v4[MAX_OFFLOAD_PAIR]; - lan2lan_flt_rule_hdl lan2lan_flt_rule_hdl_v6[MAX_OFFLOAD_PAIR]; - - uint8_t num_lan2lan_flt_rule_v4; - uint8_t num_lan2lan_flt_rule_v6; - - lan2lan_hdr_hdl lan2lan_hdr_hdl_v4[MAX_OFFLOAD_PAIR]; - lan2lan_hdr_hdl lan2lan_hdr_hdl_v6[MAX_OFFLOAD_PAIR]; - /* store ipv4 UL filter rule handlers from Q6*/ uint32_t wan_ul_fl_rule_hdl_v4[MAX_WAN_UL_FILTER_RULES]; /* store ipv6 UL filter rule handlers from Q6*/ uint32_t wan_ul_fl_rule_hdl_v6[MAX_WAN_UL_FILTER_RULES]; - virtual void install_tcp_ctl_flt_rule(ipa_ip_type iptype); - - uint32_t tcp_ctl_flt_rule_hdl_v4[NUM_TCP_CTL_FLT_RULE]; - uint32_t tcp_ctl_flt_rule_hdl_v6[NUM_TCP_CTL_FLT_RULE]; + uint32_t ipv4_icmp_flt_rule_hdl[NUM_IPV4_ICMP_FLT_RULE]; uint32_t ipv6_prefix_flt_rule_hdl[NUM_IPV6_PREFIX_FLT_RULE]; uint32_t ipv6_icmp_flt_rule_hdl[NUM_IPV6_ICMP_FLT_RULE]; @@ -315,10 +256,26 @@ class IPACM_Lan : public IPACM_Iface bool modem_ul_v4_set; bool modem_ul_v6_set; + bool sta_ul_v4_set; + bool sta_ul_v6_set; + uint32_t if_ipv4_subnet; + uint32_t ipv6_prefix[2]; + + bool is_upstream_set[IPA_IP_MAX]; + bool is_downstream_set[IPA_IP_MAX]; + _ipacm_offload_prefix prefix[IPA_IP_MAX]; + private: + /* get hdr proc ctx type given source and destination l2 hdr type */ + ipa_hdr_proc_type eth_bridge_get_hdr_proc_type(ipa_hdr_l2_type t1, ipa_hdr_l2_type t2); + + /* get partial header (header template of hdr proc ctx) */ + int eth_bridge_get_hdr_template_hdl(uint32_t* hdr_hdl); + + /* dynamically allocate lan iface's unicast routing rule structure */ bool is_mode_switch; /* indicate mode switch, need post internal up event */ @@ -333,7 +290,7 @@ class IPACM_Lan : public IPACM_Iface NatApp *Nat_App; - int ipv6_set; + int ipv6_set; uint32_t ODU_hdr_hdl_v4, ODU_hdr_hdl_v6; @@ -469,9 +426,6 @@ class IPACM_Lan : public IPACM_Iface /*handle lan iface down event*/ int handle_down_evt(); - /*handle lan2lan internal mesg posting*/ - int post_lan2lan_client_disconnect_msg(ipa_ip_type iptype); - /*handle reset usb-client rt-rules */ int handle_lan_client_reset_rt(ipa_ip_type iptype); }; diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h index 06d5832e..b055cdda 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2014, The Linux Foundation. All rights reserved. +Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -42,7 +42,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IPACM_Iface.h" #include "IPACM_Defs.h" #include "IPACM_Lan.h" -#include #ifdef FEATURE_IPA_ANDROID #include @@ -50,125 +49,229 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #endif /* ndefined(FEATURE_IPA_ANDROID)*/ -struct client_info; +#define MAX_NUM_CACHED_CLIENT_ADD_EVENT 10 +#define MAX_NUM_IFACE 10 +#define MAX_NUM_CLIENT 16 -struct peer_info +struct vlan_iface_info { - struct client_info* peer_pointer; - int num_connection; + char vlan_iface_name[IPA_RESOURCE_NAME_MAX]; + uint8_t vlan_id; + uint32_t vlan_iface_ipv6_addr[4]; + uint8_t vlan_client_mac[6]; + uint32_t vlan_client_ipv6_addr[4]; }; -//used to store rule handles for offload link (one direction) -struct offload_link_info +struct l2tp_vlan_mapping_info { - struct client_info* peer_pointer; - uint32_t flt_rule_hdl; - lan_to_lan_rt_rule_hdl rt_rule_hdl; - uint32_t hdr_hdl; + /* the following are l2tp iface info (name, session id) */ + char l2tp_iface_name[IPA_RESOURCE_NAME_MAX]; + uint8_t l2tp_session_id; + /* the following are mdm vlan iface info (name, vlan id, ipv6 addr) */ + char vlan_iface_name[IPA_RESOURCE_NAME_MAX]; + uint8_t vlan_id; + uint32_t vlan_iface_ipv6_addr[4]; + /* the following are MIB3 vlan client info (mac, ipv6 addr) */ + uint8_t vlan_client_mac[6]; + uint32_t vlan_client_ipv6_addr[4]; + /* the following is MIB3 l2tp client info (mac) */ + uint8_t l2tp_client_mac[6]; }; -typedef list peer_info_list; -typedef list offload_link_info_list; -typedef list connection_list; +struct rt_rule_info +{ + int num_hdl[IPA_IP_MAX]; /* one client may need more than one routing rules on the same routing table depending on tx_prop */ + uint32_t rule_hdl[IPA_IP_MAX][MAX_NUM_PROP]; +}; + +struct l2tp_rt_rule_info +{ + uint32_t first_pass_hdr_hdl; /* first pass hdr template (IPv4 and IPv6 use the same hdr template) */ + uint32_t first_pass_hdr_proc_ctx_hdl[IPA_IP_MAX]; /* first pass hdr proc ctx */ + uint32_t second_pass_hdr_hdl; /* second pass hdr template (IPv4 and IPv6 use the same hdr template) */ + int num_rt_hdl[IPA_IP_MAX]; /* number of TX properties for IPv4 and IPv6 respectively */ + uint32_t first_pass_rt_rule_hdl[IPA_IP_MAX][MAX_NUM_PROP]; /* first pass routing rule */ + uint32_t second_pass_rt_rule_hdl[MAX_NUM_PROP]; /*second pass routing rule (only ipv6 rt rule is needed) */ +}; struct client_info { - union - { - uint32_t ipv4_addr; - uint32_t ipv6_addr[4]; - } ip; uint8_t mac_addr[6]; - bool is_active; - bool is_powersave; - IPACM_Lan* p_iface; - peer_info_list peer; - offload_link_info_list link; + rt_rule_info inter_iface_rt_rule_hdl[IPA_HDR_L2_MAX]; /* routing rule handles of inter interface communication based on source l2 header type */ + rt_rule_info intra_iface_rt_rule_hdl; /* routing rule handles of inter interface communication */ + bool is_l2tp_client; + l2tp_vlan_mapping_info *mapping_info; + l2tp_rt_rule_info l2tp_rt_rule_hdl[IPA_HDR_L2_MAX]; }; -struct v6_addr +struct flt_rule_info { - uint32_t ipv6_addr[4]; + client_info *p_client; + uint32_t flt_rule_hdl[IPA_IP_MAX]; + uint32_t l2tp_first_pass_flt_rule_hdl[IPA_IP_MAX]; /* L2TP filtering rules are destination MAC based */ + uint32_t l2tp_second_pass_flt_rule_hdl; }; -typedef unordered_map client_table_v4; -typedef unordered_map client_table_v6; - - -class IPACM_LanToLan : public IPACM_Listener +struct peer_iface_info { + class IPACM_LanToLan_Iface *peer; + char rt_tbl_name_for_rt[IPA_IP_MAX][IPA_RESOURCE_NAME_MAX]; + char rt_tbl_name_for_flt[IPA_IP_MAX][IPA_RESOURCE_NAME_MAX]; + list flt_rule; +}; +class IPACM_LanToLan_Iface +{ public: + IPACM_LanToLan_Iface(IPACM_Lan *p_iface); + ~IPACM_LanToLan_Iface(); + + void add_client_rt_rule_for_new_iface(); + + void add_all_inter_interface_client_flt_rule(ipa_ip_type iptype); + + void add_all_intra_interface_client_flt_rule(ipa_ip_type iptype); + + void handle_down_event(); + + void handle_wlan_scc_mcc_switch(); + + void handle_intra_interface_info(); + + void handle_new_iface_up(char rt_tbl_name_for_flt[][IPA_RESOURCE_NAME_MAX], char rt_tbl_name_for_rt[][IPA_RESOURCE_NAME_MAX], + IPACM_LanToLan_Iface *peer_iface); + + void handle_client_add(uint8_t *mac, bool is_l2tp_client, l2tp_vlan_mapping_info *mapping_info); + + void handle_client_del(uint8_t *mac); + + void print_data_structure_info(); + + IPACM_Lan* get_iface_pointer(); + + bool get_m_is_ip_addr_assigned(ipa_ip_type iptype); + + void set_m_is_ip_addr_assigned(ipa_ip_type iptype, bool value); + + bool get_m_support_inter_iface_offload(); + + bool get_m_support_intra_iface_offload(); - IPACM_LanToLan(); - ~IPACM_LanToLan(); + void increment_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type); - void handle_new_connection(ipacm_event_connection* new_conn); - void handle_del_connection(ipacm_event_connection* del_conn); + void decrement_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type); - static IPACM_LanToLan* getLan2LanInstance(); + void switch_to_l2tp_iface(); + + bool set_l2tp_iface(char *vlan_iface_name); + + bool is_l2tp_iface(); + + void handle_l2tp_enable(); + + void handle_l2tp_disable(); private: - uint8_t num_offload_pair_v4_; - uint8_t num_offload_pair_v6_; - client_table_v4 client_info_v4_; - client_table_v6 client_info_v6_; + IPACM_Lan *m_p_iface; + bool m_is_ip_addr_assigned[IPA_IP_MAX]; + bool m_support_inter_iface_offload; + bool m_support_intra_iface_offload; + bool m_is_l2tp_iface; + + int ref_cnt_peer_l2_hdr_type[IPA_HDR_L2_MAX]; /* reference count of l2 header type of peer interfaces */ + uint32_t hdr_proc_ctx_for_inter_interface[IPA_HDR_L2_MAX]; + uint32_t hdr_proc_ctx_for_intra_interface; + uint32_t hdr_proc_ctx_for_l2tp; /* uc needs to remove 62 bytes IPv6 + L2TP + inner Ethernet header */ + + list m_client_info; /* client list */ + list m_peer_iface_info; /* peer information list */ + + /* The following members are for intra-interface communication*/ + peer_iface_info m_intra_interface_info; + + void add_one_client_flt_rule(IPACM_LanToLan_Iface *peer_iface, client_info *client); + + void add_client_flt_rule(peer_iface_info *peer, client_info *client, ipa_ip_type iptype); + + void del_one_client_flt_rule(IPACM_LanToLan_Iface *peer_iface, client_info *client); + + void del_client_flt_rule(peer_iface_info *peer, client_info *client); + + void add_client_rt_rule(peer_iface_info *peer, client_info *client); + + void del_client_rt_rule(peer_iface_info *peer, client_info *client); - connection_list connection_v4_; - connection_list connection_v6_; + void add_l2tp_client_rt_rule(peer_iface_info *peer, client_info *client); - static IPACM_LanToLan* p_instance; + void clear_all_flt_rule_for_one_peer_iface(peer_iface_info *peer); - void event_callback(ipa_cm_event_id event, void* param); + void clear_all_rt_rule_for_one_peer_iface(peer_iface_info *peer); - void handle_client_active(ipacm_event_lan_client* data); + void add_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_type); + + void del_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_type); + + void print_peer_info(peer_iface_info *peer_info); + +}; + +class IPACM_LanToLan : public IPACM_Listener +{ + +public: + + static IPACM_LanToLan* p_instance; + static IPACM_LanToLan* get_instance(); + bool has_l2tp_iface(); + +private: - void check_potential_link(ipa_ip_type iptype, client_info* client); + IPACM_LanToLan(); - int add_offload_link(ipa_ip_type iptype, client_info* client, client_info* peer); + ~IPACM_LanToLan(); - void handle_client_inactive(ipacm_event_lan_client* data); + bool m_has_l2tp_iface; - int turnoff_offload_links(ipa_ip_type iptype, client_info* client); + list m_iface; - int del_offload_link(ipa_ip_type iptype, IPACM_Lan* client, IPACM_Lan* peer, offload_link_info* link); + list m_cached_client_add_event; - void handle_client_disconnect(ipacm_event_lan_client* data); + list m_vlan_iface; - int clear_peer_list(client_info* client); + list m_l2tp_vlan_mapping; - void handle_client_power_save(ipacm_event_lan_client* data); + void handle_iface_up(ipacm_event_eth_bridge *data); - void handle_client_power_recover(ipacm_event_lan_client* data); + void handle_iface_down(ipacm_event_eth_bridge *data); - int remove_flt_rules(ipa_ip_type iptype, client_info* client); + void handle_client_add(ipacm_event_eth_bridge *data); - int add_flt_rules(ipa_ip_type iptype, client_info* client); + void handle_client_del(ipacm_event_eth_bridge *data); -//the following are for connections + void handle_wlan_scc_mcc_switch(ipacm_event_eth_bridge *data); - void handle_new_lan2lan_connection(ipacm_event_connection* data); + void handle_add_vlan_iface(ipa_ioc_vlan_iface_info *data); - bool add_connection(client_info* src_client, client_info* dst_client); + void handle_del_vlan_iface(ipa_ioc_vlan_iface_info *data); - void handle_del_lan2lan_connection(ipacm_event_connection* data); + void handle_add_l2tp_vlan_mapping(ipa_ioc_l2tp_vlan_mapping_info *data); - bool remove_connection(client_info* src_client, client_info* dst_client); + void handle_del_l2tp_vlan_mapping(ipa_ioc_l2tp_vlan_mapping_info *data); - void erase_offload_link(ipa_ip_type iptype, client_info* src_client, client_info* dst_client); + void handle_vlan_client_info(ipacm_event_data_all *data); - void generate_new_connection(ipa_ip_type iptype, client_info* client); + void handle_vlan_iface_info(ipacm_event_data_all *data); - bool is_lan2lan_connection(ipacm_event_connection* data); + void handle_new_iface_up(IPACM_LanToLan_Iface *new_iface, IPACM_LanToLan_Iface *exist_iface); - bool is_potential_lan2lan_connection(ipacm_event_connection* new_conn); + void event_callback(ipa_cm_event_id event, void* param); - void cache_new_connection(ipacm_event_connection* new_conn); + void handle_cached_client_add_event(IPACM_Lan *p_iface); - void remove_cache_connection(ipacm_event_connection* del_conn); + void clear_cached_client_add_event(IPACM_Lan *p_iface); - void check_cache_connection(ipa_ip_type iptype, client_info* client); + void print_data_structure_info(); }; diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h index f2ed7737..dab02802 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -65,20 +65,33 @@ typedef struct ipacm_log_buffer_s { void ipacm_log_send( void * user_data); static char buffer_send[MAX_BUF_LEN]; - +static char dmesg_cmd[MAX_BUF_LEN]; + +#define IPACMDBG_DMESG(fmt, ...) memset(buffer_send, 0, MAX_BUF_LEN);\ + snprintf(buffer_send,MAX_BUF_LEN,"%s:%d %s: " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ + ipacm_log_send (buffer_send);\ + printf("%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \ + memset(dmesg_cmd, 0, MAX_BUF_LEN);\ + snprintf(dmesg_cmd, MAX_BUF_LEN, "echo %s > /dev/kmsg", buffer_send);\ + system(dmesg_cmd); +#ifdef DEBUG #define PERROR(fmt) memset(buffer_send, 0, MAX_BUF_LEN);\ snprintf(buffer_send,MAX_BUF_LEN,"%s:%d %s()", __FILE__, __LINE__, __FUNCTION__);\ ipacm_log_send (buffer_send); \ perror(fmt); - #define IPACMERR(fmt, ...) memset(buffer_send, 0, MAX_BUF_LEN);\ - snprintf(buffer_send,MAX_BUF_LEN,"ERR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ + snprintf(buffer_send,MAX_BUF_LEN,"ERROR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ ipacm_log_send (buffer_send);\ - printf("ERR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); + printf("ERROR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); #define IPACMDBG_H(fmt, ...) memset(buffer_send, 0, MAX_BUF_LEN);\ snprintf(buffer_send,MAX_BUF_LEN,"%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ ipacm_log_send (buffer_send);\ printf("%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); +#else +#define PERROR(fmt) perror(fmt) +#define IPACMERR(fmt, ...) printf("ERR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); +#define IPACMDBG_H(fmt, ...) printf("%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); +#endif #define IPACMDBG(fmt, ...) printf("%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); #define IPACMLOG(fmt, ...) printf(fmt, ##__VA_ARGS__); diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h index 55ab92e1..745b145f 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h @@ -1,5 +1,5 @@ -/* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +/* +Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -48,7 +48,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IPACM_Listener.h" #include "IPACM_Iface.h" -#define IPA_MAX_NUM_NEIGHBOR_CLIENTS 17 +#define IPA_MAX_NUM_NEIGHBOR_CLIENTS 100 struct ipa_neighbor_client { @@ -56,6 +56,8 @@ struct ipa_neighbor_client int iface_index; uint32_t v4_addr; int ipa_if_num; + /* add support for handling L2TP clients which associated with eth0 vlan interface */ + char iface_name[IPA_IFACE_NAME_LEN]; }; class IPACM_Neighbor : public IPACM_Listener @@ -72,8 +74,9 @@ class IPACM_Neighbor : public IPACM_Listener int num_neighbor_client; - ipa_neighbor_client neighbor_client[IPA_MAX_NUM_NEIGHBOR_CLIENTS]; + int circular_index; + ipa_neighbor_client neighbor_client[IPA_MAX_NUM_NEIGHBOR_CLIENTS]; }; diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_OffloadManager.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_OffloadManager.h new file mode 100644 index 00000000..85a20630 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_OffloadManager.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _IPACM_OFFLOAD_MANAGER_H_ +#define _IPACM_OFFLOAD_MANAGER_H_ + + +#include +#include +#include "IPACM_Defs.h" + +using RET = ::IOffloadManager::RET; +using Prefix = ::IOffloadManager::Prefix; +using IP_FAM = ::IOffloadManager::IP_FAM; +using L4Protocol = ::IOffloadManager::ConntrackTimeoutUpdater::L4Protocol; +using natTimeoutUpdate_t = ::IOffloadManager::ConntrackTimeoutUpdater::natTimeoutUpdate_t; +//using ipAddrPortPair_t = ::IOffloadManager::ConntrackTimeoutUpdater::ipAddrPortPair_t; +//using UDP = ::IOffloadManager::ConntrackTimeoutUpdater::UDP; +//using TCP = ::IOffloadManager::ConntrackTimeoutUpdater::TCP; + + + +class IPACM_OffloadManager : public IOffloadManager +{ + +public: + + IPACM_OffloadManager(); + static IPACM_OffloadManager* GetInstance(); + + virtual RET registerEventListener(IpaEventListener* /* listener */); + virtual RET unregisterEventListener(IpaEventListener* /* listener */); + virtual RET registerCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */); + virtual RET unregisterCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */); + + virtual RET provideFd(int /* fd */, unsigned int /* group */); + virtual RET clearAllFds(); + virtual bool isStaApSupported(); + + /* ---------------------------- ROUTE ------------------------------- */ + virtual RET setLocalPrefixes(std::vector &/* prefixes */); + virtual RET addDownstream(const char * /* downstream */, + const Prefix & /* prefix */); + virtual RET removeDownstream(const char * /* downstream */, + const Prefix &/* prefix */); + virtual RET setUpstream(const char* /* iface */, const Prefix& /* v4Gw */, const Prefix& /* v6Gw */); + virtual RET stopAllOffload(); + + /* ------------------------- STATS/POLICY --------------------------- */ + virtual RET setQuota(const char * /* upstream */, uint64_t /* limit */); + virtual RET getStats(const char * /* upstream */, bool /* reset */, + OffloadStatistics& /* ret */); + + static IPACM_OffloadManager *pInstance; //sky + + IpaEventListener *elrInstance; + + ConntrackTimeoutUpdater *touInstance; + +private: + + bool upstream_v4_up; + + bool upstream_v6_up; + + int default_gw_index; + + int post_route_evt(enum ipa_ip_type iptype, int index, ipa_cm_event_id event, const Prefix &gw_addr); + + int ipa_get_if_index(const char *if_name, int *if_index); + + int resetTetherStats(const char *upstream_name); + + static const char *DEVICE_NAME; + +}; /* IPACM_OffloadManager */ + +#endif /* _IPACM_OFFLOAD_MANAGER_H_ */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h index ca7a5fd8..b5ffabc2 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -61,14 +61,17 @@ class IPACM_Routing bool Reset(enum ipa_ip_type ip); bool GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable); - bool PutRoutingTable(uint32_t routingTableHandle); bool DeviceNodeIsOpened(); bool DeleteRoutingHdl(uint32_t rt_rule_hdl, ipa_ip_type ip); + bool ModifyRoutingRule(struct ipa_ioc_mdfy_rt_rule *); + private: static const char *DEVICE_NAME; int m_fd; /* File descriptor of the IPA device node /dev/ipa */ + + bool PutRoutingTable(uint32_t routingTableHandle); }; #endif //IPACM_ROUTING_H diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wan.h index e227627f..fde97f69 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wan.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wan.h @@ -94,14 +94,19 @@ class IPACM_Wan : public IPACM_Iface static bool wan_up; static bool wan_up_v6; + static uint8_t xlat_mux_id; /* IPACM interface name */ static char wan_up_dev_name[IF_NAME_LEN]; + static uint32_t curr_wan_ip; IPACM_Wan(int, ipacm_wan_iface_type, uint8_t *); virtual ~IPACM_Wan(); static bool isWanUP(int ipa_if_num_tether) { #ifdef FEATURE_IPA_ANDROID +#ifdef FEATURE_IPACM_HAL + return wan_up; +#else int i; for (i=0; i < ipa_if_num_tether_v4_total;i++) { @@ -114,6 +119,7 @@ class IPACM_Wan : public IPACM_Iface } } return false; +#endif #else return wan_up; #endif @@ -139,6 +145,74 @@ class IPACM_Wan : public IPACM_Iface #endif } +#ifdef FEATURE_IPA_ANDROID + static int delete_tether_iface(ipa_ip_type iptype, int ipa_if_num_tether) + { + int i, j; + + if (iptype == IPA_IP_v4) + { + /* delete support tether ifaces to its array*/ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++) + { + if(IPACM_Wan::ipa_if_num_tether_v4[i] == ipa_if_num_tether) + { + IPACMDBG_H("Found tether client at position %d name(%s)\n", i, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); + break; + } + } + if(i == IPACM_Wan::ipa_if_num_tether_v4_total) + { + IPACMDBG_H("Not finding the tethered ipv4 client.\n"); + return IPACM_FAILURE; + } + for(j = i+1; j < IPACM_Wan::ipa_if_num_tether_v4_total; j++) + { + IPACM_Wan::ipa_if_num_tether_v4[j-1] = IPACM_Wan::ipa_if_num_tether_v4[j]; + } + IPACM_Wan::ipa_if_num_tether_v4_total--; + IPACMDBG_H("Now the total num of ipa_if_num_tether_v4_total is %d\n", + IPACM_Wan::ipa_if_num_tether_v4_total); + } + else + { + /* delete support tether ifaces to its array*/ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++) + { + if(IPACM_Wan::ipa_if_num_tether_v6[i] == ipa_if_num_tether) + { + IPACMDBG_H("Found tether client at position %d name(%s)\n", i, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); + break; + } + } + if(i == IPACM_Wan::ipa_if_num_tether_v6_total) + { + IPACMDBG_H("Not finding the tethered ipv6 client.\n"); + return IPACM_FAILURE; + } + for(j = i+1; j < IPACM_Wan::ipa_if_num_tether_v6_total; j++) + { + IPACM_Wan::ipa_if_num_tether_v6[j-1] = IPACM_Wan::ipa_if_num_tether_v6[j]; + } + IPACM_Wan::ipa_if_num_tether_v6_total--; + IPACMDBG_H("Now the total num of ipa_if_num_tether_v6_total is %d\n", + IPACM_Wan::ipa_if_num_tether_v6_total); + } + return IPACM_SUCCESS; + } +#endif + + static uint32_t getWANIP() + { + return curr_wan_ip; + } + + static bool getXlat_Mux_Id() + { + return xlat_mux_id; + } void event_callback(ipa_cm_event_id event, void *data); @@ -155,6 +229,12 @@ class IPACM_Wan : public IPACM_Iface static uint32_t backhaul_ipv6_prefix[2]; static bool embms_is_on; + static bool backhaul_is_wan_bridge; + + static bool isWan_Bridge_Mode() + { + return backhaul_is_wan_bridge; + } #ifdef FEATURE_IPA_ANDROID /* IPACM interface id */ static int ipa_if_num_tether_v4_total; @@ -165,6 +245,7 @@ class IPACM_Wan : public IPACM_Iface private: + bool is_ipv6_frag_firewall_flt_rule_installed; uint32_t ipv6_frag_firewall_flt_rule_hdl; uint32_t *wan_route_rule_v4_hdl; uint32_t *wan_route_rule_v6_hdl; @@ -179,6 +260,11 @@ class IPACM_Wan : public IPACM_Iface uint32_t ODU_fl_hdl[IPA_NUM_DEFAULT_WAN_FILTER_RULES]; int num_firewall_v4,num_firewall_v6; uint32_t wan_v4_addr; + uint32_t wan_v4_addr_gw; + uint32_t wan_v6_addr_gw[4]; + bool wan_v4_addr_set; + bool wan_v4_addr_gw_set; + bool wan_v6_addr_gw_set; bool active_v4; bool active_v6; bool header_set_v4; @@ -186,8 +272,7 @@ class IPACM_Wan : public IPACM_Iface bool header_partial_default_wan_v4; bool header_partial_default_wan_v6; uint8_t ext_router_mac_addr[IPA_MAC_ADDR_SIZE]; - uint16_t eth2_ofst_v4; - uint16_t eth2_ofst_v6; + uint8_t netdev_mac[IPA_MAC_ADDR_SIZE]; static int num_ipv4_modem_pdn; @@ -210,8 +295,12 @@ class IPACM_Wan : public IPACM_Iface int header_name_count; int num_wan_client; uint8_t invalid_mac[IPA_MAC_ADDR_SIZE]; + bool is_xlat; + /* update network stats for CNE */ int ipa_network_stats_fd; + uint32_t hdr_hdl_dummy_v6; + uint32_t hdr_proc_hdl_dummy_v6; inline ipa_wan_client* get_client_memptr(ipa_wan_client *param, int cnt) { @@ -250,6 +339,82 @@ class IPACM_Wan : public IPACM_Iface return IPACM_INVALID_INDEX; } + inline int get_wan_client_index_ipv4(uint32_t ipv4_addr) + { + int cnt; + int num_wan_client_tmp = num_wan_client; + + IPACMDBG_H("Passed IPv4 %x\n", ipv4_addr); + + for(cnt = 0; cnt < num_wan_client_tmp; cnt++) + { + if (get_client_memptr(wan_client, cnt)->ipv4_set) + { + IPACMDBG_H("stored IPv4 %x\n", get_client_memptr(wan_client, cnt)->v4_addr); + + if(ipv4_addr == get_client_memptr(wan_client, cnt)->v4_addr) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + IPACMDBG_H("The MAC is %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, cnt)->mac[0], + get_client_memptr(wan_client, cnt)->mac[1], + get_client_memptr(wan_client, cnt)->mac[2], + get_client_memptr(wan_client, cnt)->mac[3], + get_client_memptr(wan_client, cnt)->mac[4], + get_client_memptr(wan_client, cnt)->mac[5]); + IPACMDBG_H("header set ipv4(%d) ipv6(%d)\n", + get_client_memptr(wan_client, cnt)->ipv4_header_set, + get_client_memptr(wan_client, cnt)->ipv6_header_set); + return cnt; + } + } + } + return IPACM_INVALID_INDEX; + } + + inline int get_wan_client_index_ipv6(uint32_t* ipv6_addr) + { + int cnt, v6_num; + int num_wan_client_tmp = num_wan_client; + + IPACMDBG_H("Get ipv6 address 0x%08x.0x%08x.0x%08x.0x%08x\n", ipv6_addr[0], ipv6_addr[1], ipv6_addr[2], ipv6_addr[3]); + + for(cnt = 0; cnt < num_wan_client_tmp; cnt++) + { + if (get_client_memptr(wan_client, cnt)->ipv6_set) + { + for(v6_num=0;v6_num < get_client_memptr(wan_client, cnt)->ipv6_set;v6_num++) + { + + IPACMDBG_H("stored IPv6 0x%08x.0x%08x.0x%08x.0x%08x\n", get_client_memptr(wan_client, cnt)->v6_addr[v6_num][0], + get_client_memptr(wan_client, cnt)->v6_addr[v6_num][1], + get_client_memptr(wan_client, cnt)->v6_addr[v6_num][2], + get_client_memptr(wan_client, cnt)->v6_addr[v6_num][3]); + + if(ipv6_addr[0] == get_client_memptr(wan_client, cnt)->v6_addr[v6_num][0] && + ipv6_addr[1] == get_client_memptr(wan_client, cnt)->v6_addr[v6_num][1] && + ipv6_addr[2]== get_client_memptr(wan_client, cnt)->v6_addr[v6_num][2] && + ipv6_addr[3] == get_client_memptr(wan_client, cnt)->v6_addr[v6_num][3]) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + IPACMDBG_H("The MAC is %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, cnt)->mac[0], + get_client_memptr(wan_client, cnt)->mac[1], + get_client_memptr(wan_client, cnt)->mac[2], + get_client_memptr(wan_client, cnt)->mac[3], + get_client_memptr(wan_client, cnt)->mac[4], + get_client_memptr(wan_client, cnt)->mac[5]); + IPACMDBG_H("header set ipv4(%d) ipv6(%d)\n", + get_client_memptr(wan_client, cnt)->ipv4_header_set, + get_client_memptr(wan_client, cnt)->ipv6_header_set); + return cnt; + } + } + } + } + return IPACM_INVALID_INDEX; + } + inline int delete_wan_rtrules(int clt_indx, ipa_ip_type iptype) { uint32_t tx_index; @@ -325,11 +490,17 @@ class IPACM_Wan : public IPACM_Iface /* wan default route/filter rule configuration */ int handle_route_add_evt(ipa_ip_type iptype); - /* construct complete ethernet header */ - int handle_header_add_evt(uint8_t *mac_addr); + /* construct complete STA ethernet header */ + int handle_sta_header_add_evt(); + + bool check_dft_firewall_rules_attr_mask(IPACM_firewall_conf_t *firewall_config); + +#ifdef FEATURE_IPA_ANDROID /* wan posting supported tether_iface */ int post_wan_up_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether); + int post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether); +#endif int config_dft_firewall_rules(ipa_ip_type iptype); /* configure the initial firewall filter rules */ @@ -337,8 +508,6 @@ class IPACM_Wan : public IPACM_Iface int handle_route_del_evt(ipa_ip_type iptype); - int post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether); - int del_dft_firewall_rules(ipa_ip_type iptype); int handle_down_evt(); @@ -376,11 +545,18 @@ class IPACM_Wan : public IPACM_Iface bool is_global_ipv6_addr(uint32_t* ipv6_addr); + void handle_wlan_SCC_MCC_switch(bool, ipa_ip_type); + + void handle_wan_client_SCC_MCC_switch(bool, ipa_ip_type); + int handle_network_stats_evt(); int m_fd_ipa; int handle_network_stats_update(ipa_get_apn_data_stats_resp_msg_v01 *data); + + /* construct dummy ethernet header */ + int add_dummy_rx_hdr(); }; #endif /* IPACM_WAN_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wlan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wlan.h index 6d602a61..eb911ac6 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wlan.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wlan.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -74,13 +74,6 @@ typedef struct _ipa_wlan_client wlan_client_rt_hdl wifi_rt_hdl[0]; /* depends on number of tx properties */ }ipa_wlan_client; -typedef enum -{ - SRC_WLAN, - SRC_USB -} eth_bridge_src_iface; - - /* wlan iface */ class IPACM_Wlan : public IPACM_Lan { @@ -92,67 +85,16 @@ class IPACM_Wlan : public IPACM_Lan static int total_num_wifi_clients; - void event_callback(ipa_cm_event_id event, - void *data); + void event_callback(ipa_cm_event_id event, void *data); - virtual int add_lan2lan_hdr(ipa_ip_type iptype, uint8_t* src_mac, uint8_t* dst_mac, uint32_t* hdr_hdl); + bool is_guest_ap(); private: - eth_bridge_client_flt_info eth_bridge_usb_client_flt_info[IPA_LAN_TO_LAN_MAX_USB_CLIENT]; - int num_usb_client; - - uint32_t wlan_guest_ap_flt_rule_hdl_v4[IPA_MAX_PRIVATE_SUBNET_ENTRIES]; - - uint32_t wlan_guest_ap_flt_rule_hdl_v6; - - static lan2lan_flt_rule_hdl self_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; - static lan2lan_flt_rule_hdl self_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; - - static lan2lan_flt_rule_hdl usb_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_USB_CLIENT]; - static lan2lan_flt_rule_hdl usb_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_USB_CLIENT]; - - bool is_guest_ap; - - eth_bridge_client_rt_info* eth_bridge_wlan_client_rt_from_usb_info_v4; - int wlan_client_rt_from_usb_info_count_v4; - eth_bridge_client_rt_info* eth_bridge_wlan_client_rt_from_usb_info_v6; - int wlan_client_rt_from_usb_info_count_v6; - - eth_bridge_client_rt_info* eth_bridge_wlan_client_rt_from_wlan_info_v4; - int wlan_client_rt_from_wlan_info_count_v4; - eth_bridge_client_rt_info* eth_bridge_wlan_client_rt_from_wlan_info_v6; - int wlan_client_rt_from_wlan_info_count_v6; - - virtual int eth_bridge_add_wlan_guest_ap_flt_rule(ipa_ip_type iptype); - - int eth_bridge_install_wlan_guest_ap_ipv6_flt_rule(); - - virtual int eth_bridge_handle_dummy_wlan_client_flt_rule(ipa_ip_type iptype); - - virtual int eth_bridge_handle_dummy_usb_client_flt_rule(ipa_ip_type iptype); - - int eth_bridge_add_usb_client_flt_rule(uint8_t* mac, ipa_ip_type iptype); - - int eth_bridge_del_usb_client_flt_rule(uint8_t* mac); - - int eth_bridge_add_self_client_flt_rule(uint8_t* mac, ipa_ip_type iptype); - - int eth_bridge_del_self_client_flt_rule(uint8_t* mac); - - virtual int eth_bridge_install_cache_wlan_client_flt_rule(ipa_ip_type iptype); + bool m_is_guest_ap; - virtual int eth_bridge_install_cache_usb_client_flt_rule(ipa_ip_type iptype); - - int eth_bridge_add_wlan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src, ipa_ip_type iptype); - - int eth_bridge_del_wlan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src); - - eth_bridge_client_rt_info* eth_bridge_get_client_rt_info_ptr(uint8_t index, eth_bridge_src_iface src, ipa_ip_type iptype); - - void eth_bridge_add_wlan_client(uint8_t* mac, int if_num); - - void eth_bridge_del_wlan_client(uint8_t* mac); + /* handle wlan access mode switch in ethernet bridging*/ + void eth_bridge_handle_wlan_mode_switch(); int wlan_client_len; @@ -163,9 +105,6 @@ class IPACM_Wlan : public IPACM_Lan int wlan_ap_index; - static uint32_t* dummy_flt_rule_hdl_v4; - static uint32_t* dummy_flt_rule_hdl_v6; - static int num_wlan_ap_iface; NatApp *Nat_App; @@ -275,9 +214,6 @@ class IPACM_Wlan : public IPACM_Lan /* for handle wifi client initial,copy all partial headers (tx property) */ int handle_wlan_client_init_ex(ipacm_event_data_wlan_ex *data); - /*handle lan2lan internal mesg posting*/ - int handle_lan2lan_msg_post(uint8_t *mac_addr, ipa_cm_event_id event, ipa_ip_type iptype); - /*handle wifi client */ int handle_wlan_client_ipaddr(ipacm_event_data_all *data); @@ -293,33 +229,11 @@ class IPACM_Wlan : public IPACM_Lan /*handle wlan iface down event*/ int handle_down_evt(); - /* add dummy filtering rules for WLAN AP-AP mode support */ - void add_dummy_flt_rule(); - - /* install dummy filtering rules for WLAN AP-AP mode support */ - int install_dummy_flt_rule(ipa_ip_type iptype, int num_rule); - - /* delete dummy flt rule for WLAN AP-AP mode support*/ - void del_dummy_flt_rule(); - - /*Configure the initial filter rules */ - virtual int init_fl_rule(ipa_ip_type iptype); - - virtual int add_dummy_lan2lan_flt_rule(ipa_ip_type iptype); - - virtual int add_dummy_private_subnet_flt_rule(ipa_ip_type iptype); - - /*configure private subnet filter rules*/ - virtual int handle_private_subnet(ipa_ip_type iptype); - - /* install UL filter rule from Q6 */ - virtual int handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptype); - - /* install TCP control filter rules */ - virtual void install_tcp_ctl_flt_rule(ipa_ip_type iptype); - /*handle reset wifi-client rt-rules */ int handle_wlan_client_reset_rt(ipa_ip_type iptype); + + void handle_SCC_MCC_switch(ipa_ip_type); + }; diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h index 197d1a78..64c00ede 100644 --- a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h @@ -54,12 +54,12 @@ extern "C" { #endif -#define IPACM_ASSERT(a) \ -if (!(a)) { \ - fprintf(stderr, "%s, %d: assertion (a) failed!", \ - __FILE__, \ - __LINE__); \ - abort(); \ +#define IPACM_ASSERT(a) \ +if (!(a)) { \ + fprintf(stderr, "%s, %d: assertion (a) failed!", \ + __FILE__, \ + __LINE__); \ + abort(); \ } /* Max allowed size of the XML file (2 MB) */ @@ -76,7 +76,8 @@ if (!(a)) { \ /* IPA Config Entries */ #define system_TAG "system" #define ODU_TAG "ODUCFG" -#define ODUMODE_TAG "Mode" +#define ODUMODE_TAG "OduMode" +#define ODUEMBMS_OFFLOAD_TAG "eMBMS_offload" #define ODU_ROUTER_TAG "router" #define ODU_BRIDGE_TAG "bridge" #define IPACMCFG_TAG "IPACM" @@ -84,6 +85,7 @@ if (!(a)) { \ #define IFACE_TAG "Iface" #define NAME_TAG "Name" #define CATEGORY_TAG "Category" +#define MODE_TAG "Mode" #define IPACMPRIVATESUBNETCFG_TAG "IPACMPrivateSubnet" #define SUBNET_TAG "Subnet" #define SUBNETADDRESS_TAG "SubnetAddress" @@ -91,11 +93,16 @@ if (!(a)) { \ #define WANIF_TAG "WAN" #define LANIF_TAG "LAN" #define WLANIF_TAG "WLAN" +#define WLAN_FULL_MODE_TAG "full" +#define WLAN_INTERNET_MODE_TAG "internet" +#define WLAN_MODE_TAG "WlanMode" #define VIRTUALIF_TAG "VIRTUAL" #define UNKNOWNIF_TAG "UNKNOWN" #define ODUIF_TAG "ODU" #define EMBMSIF_TAG "EMBMS" #define ETHIF_TAG "ETH" +#define IFACE_ROUTER_MODE_TAG "ROUTER" +#define IFACE_BRIDGE_MODE_TAG "BRIDGE" #define IPACMALG_TAG "IPACMALG" #define ALG_TAG "ALG" #define Protocol_TAG "Protocol" @@ -171,37 +178,40 @@ if (!(a)) { \ #define IPACMNat_TAG "IPACMNAT" #define NAT_MaxEntries_TAG "MaxNatEntries" +#define IP_PassthroughFlag_TAG "IPPassthroughFlag" +#define IP_PassthroughMode_TAG "IPPassthroughMode" + /*--------------------------------------------------------------------------- IP protocol numbers - use in dss_socket() to identify protocols. Also contains the extension header types for IPv6. ---------------------------------------------------------------------------*/ typedef enum { - IPACM_FIREWALL_IPV6_BASE_HDR = 4, /* IPv6 Base Header */ - IPACM_FIREWALL_IPPROTO_HOP_BY_HOP_OPT_HDR = 0, /* Hop-by-hop Option Header */ - IPACM_FIREWALL_IPPROTO_ICMP = 1, /* ICMP protocol */ - IPACM_FIREWALL_IPPROTO_IGMP = 2, /* IGMP protocol */ - IPACM_FIREWALL_IPPROTO_IP = IPACM_FIREWALL_IPV6_BASE_HDR, /* IPv4 */ - IPACM_FIREWALL_IPPROTO_TCP = 6, /* TCP Protocol */ - IPACM_FIREWALL_IPPROTO_UDP = 17, /* UDP Protocol */ - IPACM_FIREWALL_IPPROTO_IPV6 = 41, /* IPv6 */ - IPACM_FIREWALL_IPPROTO_ROUTING_HDR = 43, /* Routing Header */ - IPACM_FIREWALL_IPPROTO_FRAG_HDR = 44, /* Fragmentation Header */ - IPACM_FIREWALL_IPPROTO_GRE = 47, /* GRE Protocol */ - IPACM_FIREWALL_IPPROTO_ESP = 50, /* ESP Protocol */ - IPACM_FIREWALL_IPPROTO_AH = 51, /* Authentication Header */ - IPACM_FIREWALL_IPPROTO_ICMP6 = 58, /* ICMPv6 */ - IPACM_FIREWALL_NO_NEXT_HDR = 59, /* No Next Header for IPv6 */ - IPACM_FIREWALL_IPPROTO_DEST_OPT_HDR = 60, /* Destination Options Header */ - IPACM_FIREWALL_IPPROTO_MOBILITY_HDR = 135, /* Mobility Header */ - IPACM_FIREWALL_IPPROTO_TCP_UDP = 253 /* Unspecified protocol used for IPACM */ + IPACM_FIREWALL_IPV6_BASE_HDR = 4, /* IPv6 Base Header */ + IPACM_FIREWALL_IPPROTO_HOP_BY_HOP_OPT_HDR = 0, /* Hop-by-hop Option Header */ + IPACM_FIREWALL_IPPROTO_ICMP = 1, /* ICMP protocol */ + IPACM_FIREWALL_IPPROTO_IGMP = 2, /* IGMP protocol */ + IPACM_FIREWALL_IPPROTO_IP = IPACM_FIREWALL_IPV6_BASE_HDR, /* IPv4 */ + IPACM_FIREWALL_IPPROTO_TCP = 6, /* TCP Protocol */ + IPACM_FIREWALL_IPPROTO_UDP = 17, /* UDP Protocol */ + IPACM_FIREWALL_IPPROTO_IPV6 = 41, /* IPv6 */ + IPACM_FIREWALL_IPPROTO_ROUTING_HDR = 43, /* Routing Header */ + IPACM_FIREWALL_IPPROTO_FRAG_HDR = 44, /* Fragmentation Header */ + IPACM_FIREWALL_IPPROTO_GRE = 47, /* GRE Protocol */ + IPACM_FIREWALL_IPPROTO_ESP = 50, /* ESP Protocol */ + IPACM_FIREWALL_IPPROTO_AH = 51, /* Authentication Header */ + IPACM_FIREWALL_IPPROTO_ICMP6 = 58, /* ICMPv6 */ + IPACM_FIREWALL_NO_NEXT_HDR = 59, /* No Next Header for IPv6 */ + IPACM_FIREWALL_IPPROTO_DEST_OPT_HDR = 60, /* Destination Options Header */ + IPACM_FIREWALL_IPPROTO_MOBILITY_HDR = 135, /* Mobility Header */ + IPACM_FIREWALL_IPPROTO_TCP_UDP = 253 /* Unspecified protocol used for IPACM */ } ipacm_firewall_ip_protocol_enum_type; /* define as mobileap firewall rule format*/ typedef enum { - IP_V4 = 4, - IP_V6 = 6 + IP_V4 = 4, + IP_V6 = 6 } firewall_ip_version_enum; /*--------------------------------------------------------------------------- @@ -209,8 +219,8 @@ typedef enum ---------------------------------------------------------------------------*/ typedef struct { - struct ipa_rule_attrib attrib; - firewall_ip_version_enum ip_vsn; + struct ipa_rule_attrib attrib; + firewall_ip_version_enum ip_vsn; } IPACM_extd_firewall_entry_conf_t; @@ -219,71 +229,73 @@ typedef struct ---------------------------------------------------------------------------*/ typedef union { - IPACM_extd_firewall_entry_conf_t extd_firewall_entry; + IPACM_extd_firewall_entry_conf_t extd_firewall_entry; } IPACM_extd_firewall_conf_t; typedef struct { - char firewall_config_file[IPA_MAX_FILE_LEN]; - uint8_t num_extd_firewall_entries; - IPACM_extd_firewall_entry_conf_t extd_firewall_entries[IPACM_MAX_FIREWALL_ENTRIES]; - bool rule_action_accept; - bool firewall_enable; + char firewall_config_file[IPA_MAX_FILE_LEN]; + uint8_t num_extd_firewall_entries; + IPACM_extd_firewall_entry_conf_t extd_firewall_entries[IPACM_MAX_FIREWALL_ENTRIES]; + bool rule_action_accept; + bool firewall_enable; } IPACM_firewall_conf_t; typedef struct { - uint8_t num_iface_entries; - ipa_ifi_dev_name_t iface_entries[IPA_MAX_IFACE_ENTRIES]; + uint8_t num_iface_entries; + ipa_ifi_dev_name_t iface_entries[IPA_MAX_IFACE_ENTRIES]; } ipacm_iface_conf_t; typedef struct { - uint8_t num_subnet_entries; - ipa_private_subnet private_subnet_entries[IPA_MAX_PRIVATE_SUBNET_ENTRIES]; + uint8_t num_subnet_entries; + ipa_private_subnet private_subnet_entries[IPA_MAX_PRIVATE_SUBNET_ENTRIES]; } ipacm_private_subnet_conf_t; typedef struct { - uint8_t protocol; - uint16_t port; + uint8_t protocol; + uint16_t port; } ipacm_alg; typedef struct { - uint8_t num_alg_entries; - ipacm_alg alg_entries[IPA_MAX_ALG_ENTRIES]; + uint8_t num_alg_entries; + ipacm_alg alg_entries[IPA_MAX_ALG_ENTRIES]; } ipacm_alg_conf_t; typedef struct _IPACM_conf_t { - ipacm_iface_conf_t iface_config; - ipacm_private_subnet_conf_t private_subnet_config; - ipacm_alg_conf_t alg_config; + ipacm_iface_conf_t iface_config; + ipacm_private_subnet_conf_t private_subnet_config; + ipacm_alg_conf_t alg_config; int nat_max_entries; - bool odu_enable; - bool router_mode_enable; + bool odu_enable; + bool router_mode_enable; + bool odu_embms_enable; + int num_wlan_guest_ap; + bool ip_passthrough_mode; } IPACM_conf_t; /* This function read IPACM XML configuration*/ int ipacm_read_cfg_xml ( - char *xml_file, /* Filename and path */ - IPACM_conf_t *config /* Mobile AP config data */ + char *xml_file, /* Filename and path */ + IPACM_conf_t *config /* Mobile AP config data */ ); /* This function reads QCMAP Firewall XML and store in IPACM Firewall stucture */ int IPACM_read_firewall_xml ( - char *xml_file, /* Filename and path */ - IPACM_firewall_conf_t *config /* Mobile AP config data */ + char *xml_file, /* Filename and path */ + IPACM_firewall_conf_t *config /* Mobile AP config data */ ); - #ifdef __cplusplus } #endif diff --git a/data-ipa-cfg-mgr/ipacm/src/Android.mk b/data-ipa-cfg-mgr/ipacm/src/Android.mk index 6720a17c..bcb83324 100644 --- a/data-ipa-cfg-mgr/ipacm/src/Android.mk +++ b/data-ipa-cfg-mgr/ipacm/src/Android.mk @@ -1,3 +1,10 @@ +BOARD_PLATFORM_LIST := test +BOARD_IPAv3_LIST := msm8998 +BOARD_IPAv3_LIST += sdm845 +ifeq ($(call is-board-platform-in-list,$(BOARD_PLATFORM_LIST)),true) +ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM))) +ifneq (, $(filter aarch64 arm arm64, $(TARGET_ARCH))) + LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) @@ -5,11 +12,13 @@ include $(CLEAR_VARS) LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src LOCAL_C_INCLUDES += $(LOCAL_PATH)/../inc LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../ipanat/inc +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../hal/inc ifeq ($(call is-platform-sdk-version-at-least,20),true) LOCAL_C_INCLUDES += external/icu/icu4c/source/common else LOCAL_C_INCLUDES += external/icu4c/common endif +#LOCAL_C_INCLUDES += external/dhcpcd LOCAL_C_INCLUDES += external/libxml2/include LOCAL_C_INCLUDES += external/libnetfilter_conntrack/include LOCAL_C_INCLUDES += external/libnfnetlink/include @@ -17,16 +26,22 @@ LOCAL_C_INCLUDES += external/libnfnetlink/include LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr - LOCAL_CFLAGS := -v LOCAL_CFLAGS += -DFEATURE_IPA_ANDROID +LOCAL_CFLAGS += -DFEATURE_IPACM_HAL +ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT))) LOCAL_CFLAGS += -DDEBUG +endif -ifeq ($(TARGET_ARCH),arm) -LOCAL_CFLAGS += -include bionic/libc/kernel/arch-arm/asm/posix_types.h -LOCAL_CFLAGS += -include bionic/libc/kernel/arch-arm/asm/byteorder.h +ifeq ($(call is-board-platform-in-list,$(BOARD_IPAv3_LIST)),true) +LOCAL_CFLAGS += -DFEATURE_IPA_V3 endif +filetoadd = bionic/libc/kernel/arch-arm/asm/posix_types.h +LOCAL_CFLAGS += $(shell if [ -a $(filetoadd) ] ; then echo -include $(filetoadd) ; fi ;) +filetoadd = bionic/libc/kernel/arch-arm/asm/byteorder.h +LOCAL_CFLAGS += $(shell if [ -a $(filetoadd) ] ; then echo -include $(filetoadd) ; fi ;) + LOCAL_SRC_FILES := IPACM_Main.cpp \ IPACM_EvtDispatcher.cpp \ IPACM_Config.cpp \ @@ -45,15 +60,34 @@ LOCAL_SRC_FILES := IPACM_Main.cpp \ IPACM_Conntrack_NATApp.cpp\ IPACM_ConntrackClient.cpp \ IPACM_ConntrackListener.cpp \ - IPACM_Log.cpp + IPACM_Log.cpp \ + IPACM_OffloadManager.cpp LOCAL_MODULE := ipacm +LOCAL_CLANG := false LOCAL_MODULE_TAGS := optional -LOCAL_SHARED_LIBRARIES := libipanat +LOCAL_SHARED_LIBRARIES := liboffloadhal +LOCAL_SHARED_LIBRARIES += libipanat LOCAL_SHARED_LIBRARIES += libxml2 LOCAL_SHARED_LIBRARIES += libnfnetlink LOCAL_SHARED_LIBRARIES += libnetfilter_conntrack +LOCAL_SHARED_LIBRARIES += libhwbinder \ + libhidlbase \ + libhidltransport \ + liblog \ + libcutils \ + libdl \ + libbase \ + libutils \ + libhardware_legacy \ + libhardware \ + android.hardware.tetheroffload.config@1.0 \ + android.hardware.tetheroffload.control@1.0 + +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES) + +LOCAL_CLANG := true include $(BUILD_EXECUTABLE) ################################################################################ @@ -78,3 +112,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(LOCAL_MODULE) LOCAL_MODULE_OWNER := ipacm include $(BUILD_PREBUILT) + +endif # $(TARGET_ARCH) +endif +endif diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_CmdQueue.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_CmdQueue.cpp index 7e48546a..a17fb08e 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_CmdQueue.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_CmdQueue.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -40,24 +40,42 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "IPACM_CmdQueue.h" #include "IPACM_Log.h" +#include "IPACM_Iface.h" pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER; -MessageQueue* MessageQueue::inst = NULL; -MessageQueue* MessageQueue::getInstance() +MessageQueue* MessageQueue::inst_internal = NULL; +MessageQueue* MessageQueue::inst_external = NULL; + +MessageQueue* MessageQueue::getInstanceInternal() { - if(inst == NULL) + if(inst_internal == NULL) { - inst = new MessageQueue(); - if(inst == NULL) + inst_internal = new MessageQueue(); + if(inst_internal == NULL) { - IPACMERR("unable to create Message Queue instance\n"); + IPACMERR("unable to create internal Message Queue instance\n"); return NULL; } } - return inst; + return inst_internal; +} + +MessageQueue* MessageQueue::getInstanceExternal() +{ + if(inst_external == NULL) + { + inst_external = new MessageQueue(); + if(inst_external == NULL) + { + IPACMERR("unable to create external Message Queue instance\n"); + return NULL; + } + } + + return inst_external; } void MessageQueue::enqueue(Message *item) @@ -101,14 +119,22 @@ Message* MessageQueue::dequeue(void) void* MessageQueue::Process(void *param) { - MessageQueue *MsgQueue = NULL; + MessageQueue *MsgQueueInternal = NULL; + MessageQueue *MsgQueueExternal = NULL; Message *item = NULL; IPACMDBG("MessageQueue::Process()\n"); - MsgQueue = MessageQueue::getInstance(); - if(MsgQueue == NULL) + MsgQueueInternal = MessageQueue::getInstanceInternal(); + if(MsgQueueInternal == NULL) + { + IPACMERR("unable to start internal cmd queue process\n"); + return NULL; + } + + MsgQueueExternal = MessageQueue::getInstanceExternal(); + if(MsgQueueExternal == NULL) { - IPACMERR("unable to start cmd queue process\n"); + IPACMERR("unable to start external cmd queue process\n"); return NULL; } @@ -120,7 +146,21 @@ void* MessageQueue::Process(void *param) return NULL; } - item = MsgQueue->dequeue(); + item = MsgQueueInternal->dequeue(); + if(item == NULL) + { + item = MsgQueueExternal->dequeue(); + if(item) + { + IPACMDBG("Get event %s from external queue.\n", + IPACM_Iface::ipacmcfg->getEventName(item->evt.data.event)); + } + } + else + { + IPACMDBG("Get event %s from internal queue.\n", + IPACM_Iface::ipacmcfg->getEventName(item->evt.data.event)); + } if(item == NULL) { diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp index 99080e9c..52cc9851 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -47,15 +47,84 @@ IPACM_Config *IPACM_Config::pInstance = NULL; const char *IPACM_Config::DEVICE_NAME = "/dev/ipa"; const char *IPACM_Config::DEVICE_NAME_ODU = "/dev/odu_ipa_bridge"; +#define __stringify(x...) #x + +const char *ipacm_event_name[] = { + __stringify(IPA_CFG_CHANGE_EVENT), /* NULL */ + __stringify(IPA_PRIVATE_SUBNET_CHANGE_EVENT), /* ipacm_event_data_fid */ + __stringify(IPA_FIREWALL_CHANGE_EVENT), /* NULL */ + __stringify(IPA_LINK_UP_EVENT), /* ipacm_event_data_fid */ + __stringify(IPA_LINK_DOWN_EVENT), /* ipacm_event_data_fid */ + __stringify(IPA_USB_LINK_UP_EVENT), /* ipacm_event_data_fid */ + __stringify(IPA_BRIDGE_LINK_UP_EVENT), /* ipacm_event_data_all */ + __stringify(IPA_WAN_EMBMS_LINK_UP_EVENT), /* ipacm_event_data_mac */ + __stringify(IPA_ADDR_ADD_EVENT), /* ipacm_event_data_addr */ + __stringify(IPA_ADDR_DEL_EVENT), /* no use */ + __stringify(IPA_ROUTE_ADD_EVENT), /* ipacm_event_data_addr */ + __stringify(IPA_ROUTE_DEL_EVENT), /* ipacm_event_data_addr */ + __stringify(IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT), /* ipacm_event_data_fid */ + __stringify(IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT), /* ipacm_event_data_fid */ + __stringify(IPA_WLAN_AP_LINK_UP_EVENT), /* ipacm_event_data_mac */ + __stringify(IPA_WLAN_STA_LINK_UP_EVENT), /* ipacm_event_data_mac */ + __stringify(IPA_WLAN_LINK_DOWN_EVENT), /* ipacm_event_data_mac */ + __stringify(IPA_WLAN_CLIENT_ADD_EVENT), /* ipacm_event_data_mac */ + __stringify(IPA_WLAN_CLIENT_ADD_EVENT_EX), /* ipacm_event_data_wlan_ex */ + __stringify(IPA_WLAN_CLIENT_DEL_EVENT), /* ipacm_event_data_mac */ + __stringify(IPA_WLAN_CLIENT_POWER_SAVE_EVENT), /* ipacm_event_data_mac */ + __stringify(IPA_WLAN_CLIENT_RECOVER_EVENT), /* ipacm_event_data_mac */ + __stringify(IPA_NEW_NEIGH_EVENT), /* ipacm_event_data_all */ + __stringify(IPA_DEL_NEIGH_EVENT), /* ipacm_event_data_all */ + __stringify(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT), /* ipacm_event_data_all */ + __stringify(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT), /* ipacm_event_data_all */ + __stringify(IPA_SW_ROUTING_ENABLE), /* NULL */ + __stringify(IPA_SW_ROUTING_DISABLE), /* NULL */ + __stringify(IPA_PROCESS_CT_MESSAGE), /* ipacm_ct_evt_data */ + __stringify(IPA_PROCESS_CT_MESSAGE_V6), /* ipacm_ct_evt_data */ + __stringify(IPA_LAN_TO_LAN_NEW_CONNECTION), /* ipacm_event_connection */ + __stringify(IPA_LAN_TO_LAN_DEL_CONNECTION), /* ipacm_event_connection */ + __stringify(IPA_WLAN_SWITCH_TO_SCC), /* No Data */ + __stringify(IPA_WLAN_SWITCH_TO_MCC), /* No Data */ + __stringify(IPA_CRADLE_WAN_MODE_SWITCH), /* ipacm_event_cradle_wan_mode */ + __stringify(IPA_WAN_XLAT_CONNECT_EVENT), /* ipacm_event_data_fid */ + __stringify(IPA_TETHERING_STATS_UPDATE_EVENT), /* ipacm_event_data_fid */ + __stringify(IPA_NETWORK_STATS_UPDATE_EVENT), /* ipacm_event_data_fid */ + __stringify(IPA_EXTERNAL_EVENT_MAX), + __stringify(IPA_HANDLE_WAN_UP), /* ipacm_event_iface_up */ + __stringify(IPA_HANDLE_WAN_DOWN), /* ipacm_event_iface_up */ + __stringify(IPA_HANDLE_WAN_UP_V6), /* NULL */ + __stringify(IPA_HANDLE_WAN_DOWN_V6), /* NULL */ + __stringify(IPA_HANDLE_WAN_UP_TETHER), /* ipacm_event_iface_up_tehter */ + __stringify(IPA_HANDLE_WAN_DOWN_TETHER), /* ipacm_event_iface_up_tehter */ + __stringify(IPA_HANDLE_WAN_UP_V6_TETHER), /* ipacm_event_iface_up_tehter */ + __stringify(IPA_HANDLE_WAN_DOWN_V6_TETHER), /* ipacm_event_iface_up_tehter */ + __stringify(IPA_HANDLE_WLAN_UP), /* ipacm_event_iface_up */ + __stringify(IPA_HANDLE_LAN_UP), /* ipacm_event_iface_up */ + __stringify(IPA_ETH_BRIDGE_IFACE_UP), /* ipacm_event_eth_bridge*/ + __stringify(IPA_ETH_BRIDGE_IFACE_DOWN), /* ipacm_event_eth_bridge*/ + __stringify(IPA_ETH_BRIDGE_CLIENT_ADD), /* ipacm_event_eth_bridge*/ + __stringify(IPA_ETH_BRIDGE_CLIENT_DEL), /* ipacm_event_eth_bridge*/ + __stringify(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH), /* ipacm_event_eth_bridge*/ + __stringify(IPA_LAN_DELETE_SELF), /* ipacm_event_data_fid */ + __stringify(IPA_ADD_VLAN_IFACE), /* ipa_ioc_vlan_iface_info */ + __stringify(IPA_DEL_VLAN_IFACE), /* ipa_ioc_vlan_iface_info */ + __stringify(IPA_ADD_L2TP_VLAN_MAPPING), /* ipa_ioc_l2tp_vlan_mapping_info */ + __stringify(IPA_DEL_L2TP_VLAN_MAPPING), /* ipa_ioc_l2tp_vlan_mapping_info */ + __stringify(IPA_VLAN_CLIENT_INFO), /* ipacm_event_data_all */ + __stringify(IPA_VLAN_IFACE_INFO), /* ipacm_event_data_all */ + __stringify(IPACM_EVENT_MAX), +}; + IPACM_Config::IPACM_Config() { iface_table = NULL; alg_table = NULL; + pNatIfaces = NULL; memset(&ipa_client_rm_map_tbl, 0, sizeof(ipa_client_rm_map_tbl)); memset(&ipa_rm_tbl, 0, sizeof(ipa_rm_tbl)); - ipa_rm_a2_check=0; + ipa_rm_a2_check=0; ipacm_odu_enable = false; ipacm_odu_router_mode = false; + ipa_num_wlan_guest_ap = 0; ipa_num_ipa_interfaces = 0; ipa_num_private_subnet = 0; @@ -63,6 +132,9 @@ IPACM_Config::IPACM_Config() ipa_nat_max_entries = 0; ipa_nat_iface_entries = 0; ipa_sw_rt_enable = false; + ipa_bridge_enable = false; + isMCC_Mode = false; + ipa_max_valid_rm_entry = 0; memset(&rt_tbl_default_v4, 0, sizeof(rt_tbl_default_v4)); memset(&rt_tbl_lan_v4, 0, sizeof(rt_tbl_lan_v4)); @@ -76,13 +148,12 @@ IPACM_Config::IPACM_Config() memset(&ext_prop_v4, 0, sizeof(ext_prop_v4)); memset(&ext_prop_v6, 0, sizeof(ext_prop_v6)); - memset(&rt_tbl_eth_bridge_usb_wlan_v4, 0, sizeof(rt_tbl_eth_bridge_usb_wlan_v4)); - memset(&rt_tbl_eth_bridge_wlan_wlan_v4, 0, sizeof(rt_tbl_eth_bridge_wlan_wlan_v4)); - memset(&rt_tbl_eth_bridge_usb_wlan_v6, 0, sizeof(rt_tbl_eth_bridge_usb_wlan_v6)); - memset(&rt_tbl_eth_bridge_wlan_wlan_v6, 0, sizeof(rt_tbl_eth_bridge_wlan_wlan_v6)); - qmap_id = ~0; + memset(flt_rule_count_v4, 0, IPA_CLIENT_MAX*sizeof(int)); + memset(flt_rule_count_v6, 0, IPA_CLIENT_MAX*sizeof(int)); + memset(bridge_mac, 0, IPA_MAC_ADDR_SIZE*sizeof(uint8_t)); + IPACMDBG_H(" create IPACM_Config constructor\n"); return; } @@ -143,11 +214,14 @@ int IPACM_Config::Init(void) { strncpy(iface_table[i].iface_name, cfg->iface_config.iface_entries[i].iface_name, sizeof(iface_table[i].iface_name)); iface_table[i].if_cat = cfg->iface_config.iface_entries[i].if_cat; - IPACMDBG_H("IPACM_Config::iface_table[%d] = %s, cat=%d\n", i, iface_table[i].iface_name, iface_table[i].if_cat); + iface_table[i].if_mode = cfg->iface_config.iface_entries[i].if_mode; + iface_table[i].wlan_mode = cfg->iface_config.iface_entries[i].wlan_mode; + IPACMDBG_H("IPACM_Config::iface_table[%d] = %s, cat=%d, mode=%d wlan-mode=%d \n", i, iface_table[i].iface_name, + iface_table[i].if_cat, iface_table[i].if_mode, iface_table[i].wlan_mode); /* copy bridge interface name to ipacmcfg */ if( iface_table[i].if_cat == VIRTUAL_IF) { - memcpy(ipa_virtual_iface_name, iface_table[i].iface_name, sizeof(ipa_virtual_iface_name)); + strlcpy(ipa_virtual_iface_name, iface_table[i].iface_name, sizeof(ipa_virtual_iface_name)); IPACMDBG_H("ipa_virtual_iface_name(%s) \n", ipa_virtual_iface_name); } } @@ -207,8 +281,16 @@ int IPACM_Config::Init(void) /* Find ODU is either router mode or bridge mode*/ ipacm_odu_enable = cfg->odu_enable; ipacm_odu_router_mode = cfg->router_mode_enable; + ipacm_odu_embms_enable = cfg->odu_embms_enable; IPACMDBG_H("ipacm_odu_enable %d\n", ipacm_odu_enable); IPACMDBG_H("ipacm_odu_mode %d\n", ipacm_odu_router_mode); + IPACMDBG_H("ipacm_odu_embms_enable %d\n", ipacm_odu_embms_enable); + + ipacm_ip_passthrough_mode = cfg->ip_passthrough_mode; + IPACMDBG_H("ipacm_ip_passthrough_mode %d. \n", ipacm_ip_passthrough_mode); + + ipa_num_wlan_guest_ap = cfg->num_wlan_guest_ap; + IPACMDBG_H("ipa_num_wlan_guest_ap %d\n",ipa_num_wlan_guest_ap); /* Allocate more non-nat entries if the monitored iface dun have Tx/Rx properties */ if (pNatIfaces != NULL) @@ -217,6 +299,7 @@ int IPACM_Config::Init(void) pNatIfaces = NULL; IPACMDBG_H("RESET IPACM_Config::pNatIfaces \n"); } + ipa_nat_iface_entries = 0; pNatIfaces = (NatIfaces *)calloc(ipa_num_ipa_interfaces, sizeof(NatIfaces)); if (pNatIfaces == NULL) { @@ -252,24 +335,6 @@ int IPACM_Config::Init(void) rt_tbl_wan_dl.ip = IPA_IP_MAX; strncpy(rt_tbl_wan_dl.name, WAN_DL_ROUTE_TABLE_NAME, sizeof(rt_tbl_wan_dl.name)); - rt_tbl_lan2lan_v4.ip = IPA_IP_v4; - strncpy(rt_tbl_lan2lan_v4.name, V4_LAN_TO_LAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_lan2lan_v4.name)); - - rt_tbl_lan2lan_v6.ip = IPA_IP_v6; - strncpy(rt_tbl_lan2lan_v6.name, V6_LAN_TO_LAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_lan2lan_v6.name)); - - rt_tbl_eth_bridge_usb_wlan_v4.ip = IPA_IP_v4; - strncpy(rt_tbl_eth_bridge_usb_wlan_v4.name, ETH_BRIDGE_USB_WLAN_ROUTE_TABLE_NAME_V4, sizeof(rt_tbl_eth_bridge_usb_wlan_v4.name)); - - rt_tbl_eth_bridge_wlan_wlan_v4.ip = IPA_IP_v4; - strncpy(rt_tbl_eth_bridge_wlan_wlan_v4.name, ETH_BRIDGE_WLAN_WLAN_ROUTE_TABLE_NAME_V4, sizeof(rt_tbl_eth_bridge_wlan_wlan_v4.name)); - - rt_tbl_eth_bridge_usb_wlan_v6.ip = IPA_IP_v6; - strncpy(rt_tbl_eth_bridge_usb_wlan_v6.name, ETH_BRIDGE_USB_WLAN_ROUTE_TABLE_NAME_V6, sizeof(rt_tbl_eth_bridge_usb_wlan_v6.name)); - - rt_tbl_eth_bridge_wlan_wlan_v6.ip = IPA_IP_v6; - strncpy(rt_tbl_eth_bridge_wlan_wlan_v6.name, ETH_BRIDGE_WLAN_WLAN_ROUTE_TABLE_NAME_V6, sizeof(rt_tbl_eth_bridge_wlan_wlan_v6.name)); - /* Construct IPACM ipa_client map to rm_resource table */ ipa_client_rm_map_tbl[IPA_CLIENT_WLAN1_PROD]= IPA_RM_RESOURCE_WLAN_PROD; ipa_client_rm_map_tbl[IPA_CLIENT_USB_PROD]= IPA_RM_RESOURCE_USB_PROD; @@ -285,6 +350,9 @@ int IPACM_Config::Init(void) ipa_client_rm_map_tbl[IPA_CLIENT_A2_EMBEDDED_CONS]= IPA_RM_RESOURCE_Q6_CONS; ipa_client_rm_map_tbl[IPA_CLIENT_A2_TETHERED_CONS]= IPA_RM_RESOURCE_Q6_CONS; ipa_client_rm_map_tbl[IPA_CLIENT_APPS_WAN_CONS]= IPA_RM_RESOURCE_Q6_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_ODU_PROD]= IPA_RM_RESOURCE_ODU_ADAPT_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_ODU_EMB_CONS]= IPA_RM_RESOURCE_ODU_ADAPT_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_ODU_TETH_CONS]= IPA_RM_RESOURCE_ODU_ADAPT_CONS; /* Create the entries which IPACM wants to add dependencies on */ ipa_rm_tbl[0].producer_rm1 = IPA_RM_RESOURCE_WLAN_PROD; @@ -302,9 +370,28 @@ int IPACM_Config::Init(void) ipa_rm_tbl[2].producer_rm2 = IPA_RM_RESOURCE_USB_PROD; ipa_rm_tbl[2].consumer_rm2 = IPA_RM_RESOURCE_WLAN_CONS; + ipa_rm_tbl[3].producer_rm1 = IPA_RM_RESOURCE_ODU_ADAPT_PROD; + ipa_rm_tbl[3].consumer_rm1 = IPA_RM_RESOURCE_Q6_CONS; + ipa_rm_tbl[3].producer_rm2 = IPA_RM_RESOURCE_Q6_PROD; + ipa_rm_tbl[3].consumer_rm2 = IPA_RM_RESOURCE_ODU_ADAPT_CONS; + + ipa_rm_tbl[4].producer_rm1 = IPA_RM_RESOURCE_WLAN_PROD; + ipa_rm_tbl[4].consumer_rm1 = IPA_RM_RESOURCE_ODU_ADAPT_CONS; + ipa_rm_tbl[4].producer_rm2 = IPA_RM_RESOURCE_ODU_ADAPT_PROD; + ipa_rm_tbl[4].consumer_rm2 = IPA_RM_RESOURCE_WLAN_CONS; + + ipa_rm_tbl[5].producer_rm1 = IPA_RM_RESOURCE_ODU_ADAPT_PROD; + ipa_rm_tbl[5].consumer_rm1 = IPA_RM_RESOURCE_USB_CONS; + ipa_rm_tbl[5].producer_rm2 = IPA_RM_RESOURCE_USB_PROD; + ipa_rm_tbl[5].consumer_rm2 = IPA_RM_RESOURCE_ODU_ADAPT_CONS; + ipa_max_valid_rm_entry = 6; /* max is IPA_MAX_RM_ENTRY (6)*/ + IPACMDBG_H(" depend MAP-0 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_WLAN_PROD, IPA_RM_RESOURCE_Q6_CONS); IPACMDBG_H(" depend MAP-1 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_USB_PROD, IPA_RM_RESOURCE_Q6_CONS); IPACMDBG_H(" depend MAP-2 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_WLAN_PROD, IPA_RM_RESOURCE_USB_CONS); + IPACMDBG_H(" depend MAP-3 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_ODU_ADAPT_PROD, IPA_RM_RESOURCE_Q6_CONS); + IPACMDBG_H(" depend MAP-4 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_WLAN_PROD, IPA_RM_RESOURCE_ODU_ADAPT_CONS); + IPACMDBG_H(" depend MAP-5 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_ODU_ADAPT_PROD, IPA_RM_RESOURCE_USB_CONS); fail: if (cfg != NULL) @@ -374,13 +461,26 @@ int IPACM_Config::GetNatIfaces(int nIfaces, NatIfaces *pIfaces) int IPACM_Config::AddNatIfaces(char *dev_name) { + int i; + /* Check if this iface already in NAT-iface*/ + for(i = 0; i < ipa_nat_iface_entries; i++) + { + if(strncmp(dev_name, + pNatIfaces[i].iface_name, + sizeof(pNatIfaces[i].iface_name)) == 0) + { + IPACMDBG("Interface (%s) is add to nat iface already\n", dev_name); + return 0; + } + } + IPACMDBG_H("Add iface %s to NAT-ifaces, origin it has %d nat ifaces\n", dev_name, ipa_nat_iface_entries); ipa_nat_iface_entries++; if (ipa_nat_iface_entries < ipa_num_ipa_interfaces) { - memcpy(pNatIfaces[ipa_nat_iface_entries - 1].iface_name, + strlcpy(pNatIfaces[ipa_nat_iface_entries - 1].iface_name, dev_name, IPA_IFACE_NAME_LEN); IPACMDBG_H("Add Nat IfaceName: %s ,update nat-ifaces number: %d\n", @@ -442,7 +542,7 @@ void IPACM_Config::AddRmDepend(ipa_rm_resource_name rm1,bool rx_bypass_ipa) IPACMDBG_H("got %d times default RT routing from A2 \n", ipa_rm_a2_check); } - for(int i=0;i= MAX_NUM_EXT_PROPS) { - IPACMDBG_H("IPv4 extended property table is full!\n"); + IPACMERR("IPv4 extended property table is full!\n"); continue; } memcpy(&ext_prop_v4.prop[ext_prop_v4.num_ext_props], &prop->ext[i], sizeof(struct ipa_ioc_ext_intf_prop)); @@ -664,7 +764,7 @@ int IPACM_Config::SetExtProp(ipa_ioc_query_intf_ext_props *prop) { if(ext_prop_v6.num_ext_props >= MAX_NUM_EXT_PROPS) { - IPACMDBG_H("IPv6 extended property table is full!\n"); + IPACMERR("IPv6 extended property table is full!\n"); continue; } memcpy(&ext_prop_v6.prop[ext_prop_v6.num_ext_props], &prop->ext[i], sizeof(struct ipa_ioc_ext_intf_prop)); @@ -709,3 +809,14 @@ int IPACM_Config::DelExtProp(ipa_ip_type ip_type) return IPACM_SUCCESS; } + +const char* IPACM_Config::getEventName(ipa_cm_event_id event_id) +{ + if(event_id >= sizeof(ipacm_event_name)/sizeof(ipacm_event_name[0])) + { + IPACMERR("Event name array is not consistent with event array!\n"); + return NULL; + } + + return ipacm_event_name[event_id]; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackClient.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackClient.cpp index 9de5911b..ffb0088e 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackClient.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackClient.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -60,6 +60,10 @@ IPACM_ConntrackClient::IPACM_ConntrackClient() udp_hdl = NULL; tcp_filter = NULL; udp_filter = NULL; + fd_tcp = -1; + fd_udp = -1; + subscrips_tcp = NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY; + subscrips_udp = NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY; } IPACM_ConntrackClient* IPACM_ConntrackClient::GetInstance() @@ -169,10 +173,18 @@ int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Bridge_Addrs uint32_t ipv4_addr; struct ifreq ifr; + if(strlen(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name) >= sizeof(ifr.ifr_name)) + { + IPACMERR("interface name overflows: len %d\n", + strlen(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name)); + close(fd); + return -1; + } + /* retrieve bridge interface ipv4 address */ memset(&ifr, 0, sizeof(struct ifreq)); ifr.ifr_addr.sa_family = AF_INET; - (void)strncpy(ifr.ifr_name, IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, sizeof(ifr.ifr_name)); + (void)strlcpy(ifr.ifr_name, IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, sizeof(ifr.ifr_name)); IPACMDBG("bridge interface name (%s)\n", ifr.ifr_name); ret = ioctl(fd, SIOCGIFADDR, &ifr); @@ -421,10 +433,20 @@ void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *) subscrips |= NF_NETLINK_CONNTRACK_NEW; #endif +#ifdef FEATURE_IPACM_HAL + if (pClient->fd_tcp < 0) { + IPACMERR("unable to get conntrack TCP handle due to fd_tcp is invalid \n"); + return NULL; + } else { + pClient->tcp_hdl = nfct_open2(CONNTRACK, subscrips, pClient->fd_tcp); + } +#else pClient->tcp_hdl = nfct_open(CONNTRACK, subscrips); +#endif + if(pClient->tcp_hdl == NULL) { - PERROR("nfct_open\n"); + PERROR("nfct_open failed on getting tcp_hdl\n"); return NULL; } @@ -445,7 +467,7 @@ void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *) } /* Register callback with netfilter handler */ - IPACMDBG("tcp handle:%p, fd:%d\n", pClient->tcp_hdl, nfct_fd(pClient->tcp_hdl)); + IPACMDBG_H("tcp handle:%p, fd:%d\n", pClient->tcp_hdl, nfct_fd(pClient->tcp_hdl)); #ifndef CT_OPT nfct_callback_register(pClient->tcp_hdl, (nf_conntrack_msg_type) (NFCT_T_UPDATE | NFCT_T_DESTROY | NFCT_T_NEW), @@ -475,8 +497,12 @@ void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *) /* de-register the callback */ nfct_callback_unregister(pClient->tcp_hdl); /* close the handle */ +#ifdef FEATURE_IPACM_HAL + nfct_close2(pClient->tcp_hdl, true); +#else nfct_close(pClient->tcp_hdl); - pClient->tcp_hdl = NULL; +#endif + pClient->tcp_hdl = NULL; pthread_exit(NULL); return NULL; @@ -497,11 +523,21 @@ void* IPACM_ConntrackClient::UDPRegisterWithConnTrack(void *) return NULL; } +#ifdef FEATURE_IPACM_HAL + if (pClient->fd_udp < 0) { + IPACMERR("unable to get conntrack UDP handle due to fd_udp is invalid \n"); + return NULL; + } else { + pClient->udp_hdl = nfct_open2(CONNTRACK, + (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY), pClient->fd_udp); + } +#else pClient->udp_hdl = nfct_open(CONNTRACK, (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY)); +#endif if(pClient->udp_hdl == NULL) { - PERROR("nfct_open\n"); + PERROR("nfct_open failed on getting udp_hdl\n"); return NULL; } @@ -522,11 +558,11 @@ void* IPACM_ConntrackClient::UDPRegisterWithConnTrack(void *) } /* Register callback with netfilter handler */ - IPACMDBG("udp handle:%p, fd:%d\n", pClient->udp_hdl, nfct_fd(pClient->udp_hdl)); + IPACMDBG_H("udp handle:%p, fd:%d\n", pClient->udp_hdl, nfct_fd(pClient->udp_hdl)); nfct_callback_register(pClient->udp_hdl, - (nf_conntrack_msg_type)(NFCT_T_NEW | NFCT_T_DESTROY), - IPAConntrackEventCB, - NULL); + (nf_conntrack_msg_type)(NFCT_T_NEW | NFCT_T_DESTROY), + IPAConntrackEventCB, + NULL); /* Block to catch events from net filter connection track */ ctcatch: @@ -551,13 +587,66 @@ void* IPACM_ConntrackClient::UDPRegisterWithConnTrack(void *) /* de-register the callback */ nfct_callback_unregister(pClient->udp_hdl); /* close the handle */ +#ifdef FEATURE_IPACM_HAL + nfct_close2(pClient->udp_hdl, true); +#else nfct_close(pClient->udp_hdl); +#endif pClient->udp_hdl = NULL; pthread_exit(NULL); return NULL; } +/* Thread to initialize TCP Conntrack Filters*/ +void IPACM_ConntrackClient::UNRegisterWithConnTrack(void) +{ + int ret; + IPACM_ConntrackClient *pClient = NULL; + + IPACMDBG("\n"); + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to retrieve instance of conntrack client\n"); + return; + } + + /* destroy the TCP filter.. this will not detach the filter */ + if (pClient->tcp_filter) { + nfct_filter_destroy(pClient->tcp_filter); + pClient->tcp_filter = NULL; + } + + /* de-register the callback */ + if (pClient->tcp_hdl) { + nfct_callback_unregister(pClient->tcp_hdl); + /* close the handle */ + nfct_close(pClient->tcp_hdl); + pClient->tcp_hdl = NULL; + } + + /* destroy the filter.. this will not detach the filter */ + if (pClient->udp_filter) { + nfct_filter_destroy(pClient->udp_filter); + pClient->udp_filter = NULL; + } + + /* de-register the callback */ + if (pClient->udp_hdl) { + nfct_callback_unregister(pClient->udp_hdl); + /* close the handle */ + nfct_close(pClient->udp_hdl); + pClient->udp_hdl = NULL; + } + + pClient->fd_tcp = -1; + pClient->fd_udp = -1; + + return; +} + void IPACM_ConntrackClient::UpdateUDPFilters(void *param, bool isWan) { static bool isIgnore = false; @@ -650,140 +739,3 @@ void IPACM_ConntrackClient::UpdateTCPFilters(void *param, bool isWan) return; } -void IPACM_ConntrackClient::Read_TcpUdp_Timeout(char *in, int len) -{ - int proto; - FILE *fd = NULL; - char to_str[10]; - uint32_t value; - NatApp *nat_inst = NULL; - - nat_inst = NatApp::GetInstance(); - if(nat_inst == NULL) - { - IPACMERR("unable to create nat instance\n"); - return; - } - - if(!strncmp(in, IPACM_TCP_FILE_NAME, len)) - { - proto = IPPROTO_TCP; - } - else if(!strncmp(in, IPACM_UDP_FILE_NAME, len)) - { - proto = IPPROTO_UDP; - } - else - { - return; - } - - if(proto == IPPROTO_TCP) - { - fd = fopen(IPACM_TCP_FULL_FILE_NAME, "r"); - } - else - { - fd = fopen(IPACM_UDP_FULL_FILE_NAME, "r"); - } - if(fd == NULL) - { - PERROR("unable to open file"); - return; - } - - fgets(to_str, sizeof(to_str), fd); - value = atoi(to_str); - IPACMDBG("Protocol %d file \"%s\" value: %d\n", proto, in, value); - nat_inst->UpdateTcpUdpTo(value, proto); - - fclose(fd); - return; -} - -void *IPACM_ConntrackClient::TCPUDP_Timeout_monitor(void *) -{ - int length; - int wd; - char buffer[INOTIFY_BUFFER_LEN]; - int inotify_fd; - uint32_t mask = IN_MODIFY; - FILE *to_fd = NULL; - char to_str[10]; - uint32_t value=0; - NatApp *nat_inst = NULL; - - nat_inst = NatApp::GetInstance(); - if(nat_inst == NULL) - { - IPACMERR("unable to create nat instance\n"); - return NULL; - } - - to_fd = fopen(IPACM_TCP_FULL_FILE_NAME, "r"); - if(to_fd == NULL) - { - PERROR("unable to open file \"ip_conntrack_tcp_timeout_established\" "); - return NULL; - } - memset(to_str, 0, sizeof(to_str)); - fgets(to_str, sizeof(to_str), to_fd); - value = atoi(to_str); - IPACMDBG("ip conntrack tcp timeout initial value:%d\n", value); - nat_inst->UpdateTcpUdpTo(value, IPPROTO_TCP); - fclose(to_fd); - - to_fd = fopen(IPACM_UDP_FULL_FILE_NAME, "r"); - if(to_fd == NULL) - { - PERROR("unable to open file \"ip_conntrack_udp_timeout_stream\" "); - return NULL; - } - memset(to_str, 0, sizeof(to_str)); - fgets(to_str, sizeof(to_str), to_fd); - value = atoi(to_str); - IPACMDBG("ip conntrack udp timeout:%d\n", value); - nat_inst->UpdateTcpUdpTo(value, IPPROTO_UDP); - fclose(to_fd); - - inotify_fd = inotify_init(); - if (inotify_fd < 0) - { - PERROR("inotify_init"); - return NULL; - } - - IPACMDBG("Waiting for nofications in dir %s with mask: 0x%x\n", - IPACM_TCP_UDP_DIR_NAME, mask); - - wd = inotify_add_watch(inotify_fd, - IPACM_TCP_UDP_DIR_NAME, - mask); - - while (1) - { - length = read(inotify_fd, buffer, INOTIFY_BUFFER_LEN); - struct inotify_event *event = (struct inotify_event *)buffer; - - if (length < 0) - { - IPACMERR("inotify read() error return length: %d and mask: 0x%x 0x%x\n", - length, event->mask, mask); - return NULL; - } - - if( (event->len > 0) && (event->mask & IN_MODIFY) ) - { - if(!(event->mask & IN_ISDIR)) - { - IPACMDBG("Received inotify event for file %s with mask %x value", - event->name, event->mask); - Read_TcpUdp_Timeout(event->name, event->len); - } - } - } - - (void)inotify_rm_watch(inotify_fd, wd); - (void)close(inotify_fd); - return NULL; -} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp index 1fbde656..de0e7e70 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -33,6 +33,8 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IPACM_ConntrackListener.h" #include "IPACM_ConntrackClient.h" #include "IPACM_EvtDispatcher.h" +#include "IPACM_Iface.h" +#include "IPACM_Wan.h" IPACM_ConntrackListener::IPACM_ConntrackListener() { @@ -46,7 +48,7 @@ IPACM_ConntrackListener::IPACM_ConntrackListener() NatIfaceCnt = 0; StaClntCnt = 0; pNatIfaces = NULL; - pConfig = NULL; + pConfig = IPACM_Config::GetInstance();; memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr)); memset(nonnat_iface_ipv4_addr, 0, sizeof(nonnat_iface_ipv4_addr)); @@ -58,6 +60,8 @@ IPACM_ConntrackListener::IPACM_ConntrackListener() IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE_V6, this); IPACM_EvtDispatcher::registr(IPA_HANDLE_WLAN_UP, this); IPACM_EvtDispatcher::registr(IPA_HANDLE_LAN_UP, this); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, this); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, this); #ifdef CT_OPT p_lan2lan = IPACM_LanToLan::getLan2LanInstance(); @@ -65,7 +69,7 @@ IPACM_ConntrackListener::IPACM_ConntrackListener() } void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt, - void *data) + void *data) { ipacm_event_iface_up *wan_down = NULL; @@ -90,16 +94,13 @@ void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt, #endif case IPA_HANDLE_WAN_UP: - IPACMDBG("Received IPA_HANDLE_WAN_UP event\n"); + IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); CreateConnTrackThreads(); - if(!isWanUp()) - { - TriggerWANUp(data); - } + TriggerWANUp(data); break; case IPA_HANDLE_WAN_DOWN: - IPACMDBG("Received IPA_HANDLE_WAN_DOWN event\n"); + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n"); wan_down = (ipacm_event_iface_up *)data; if(isWanUp()) { @@ -111,177 +112,233 @@ void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt, tcp/udp filters to ignore local wlan or lan connections */ case IPA_HANDLE_WLAN_UP: case IPA_HANDLE_LAN_UP: - IPACMDBG("Received event: %d with ifname: %s and address: 0x%x\n", + IPACMDBG_H("Received event: %d with ifname: %s and address: 0x%x\n", evt, ((ipacm_event_iface_up *)data)->ifname, ((ipacm_event_iface_up *)data)->ipv4_addr); - CreateConnTrackThreads(); - IPACM_ConntrackClient::UpdateUDPFilters(data, false); - IPACM_ConntrackClient::UpdateTCPFilters(data, false); + if(isWanUp()) + { + CreateConnTrackThreads(); + IPACM_ConntrackClient::UpdateUDPFilters(data, false); + IPACM_ConntrackClient::UpdateTCPFilters(data, false); + } break; + case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT: + IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event\n"); + HandleNonNatIPAddr(data, true); + break; + + case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT: + IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event\n"); + HandleNonNatIPAddr(data, false); + break; + default: IPACMDBG("Ignore cmd %d\n", evt); break; } } -void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(ipacm_event_data_all *data) + +int IPACM_ConntrackListener::CheckNatIface( + ipacm_event_data_all *data, bool *NatIface) { int fd = 0, len = 0, cnt, i, j; struct ifreq ifr; - bool isNatIface = false; + *NatIface = false; - if(data->ipv4_addr == 0 || data->iptype != IPA_IP_v4) + if (data->ipv4_addr == 0 || data->iptype != IPA_IP_v4) { - IPACMDBG("Ignoring IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT EVENT\n"); - return; + IPACMDBG("Ignoring\n"); + return IPACM_FAILURE; } - IPACMDBG("\n"); IPACMDBG("Received interface index %d with ip type: %d", data->if_index, data->iptype); iptodot(" and ipv4 address", data->ipv4_addr); - if(pConfig == NULL) + if (pConfig == NULL) { pConfig = IPACM_Config::GetInstance(); - if(pConfig == NULL) + if (pConfig == NULL) { IPACMERR("Unable to get Config instance\n"); - return; + return IPACM_FAILURE; } } - cnt = pConfig->GetNatIfacesCnt(); - NatIfaceCnt = cnt; - if(pNatIfaces != NULL) - { - free(pNatIfaces); - pNatIfaces = NULL; - } - - len = (sizeof(NatIfaces) * NatIfaceCnt); - pNatIfaces = (NatIfaces *)malloc(len); - if(pNatIfaces == NULL) - { - IPACMERR("Unable to allocate memory for non nat ifaces\n"); - return; - } - memset(pNatIfaces, 0, len); + NatIfaceCnt = cnt; + IPACMDBG("Total Nat ifaces: %d\n", NatIfaceCnt); + if (pNatIfaces != NULL) + { + free(pNatIfaces); + pNatIfaces = NULL; + } - if(pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0) - { - IPACMERR("Unable to retrieve non nat ifaces\n"); - return; - } - IPACMDBG("Update %d Nat ifaces\n", NatIfaceCnt); + len = (sizeof(NatIfaces) * NatIfaceCnt); + pNatIfaces = (NatIfaces *)malloc(len); + if (pNatIfaces == NULL) + { + IPACMERR("Unable to allocate memory for non nat ifaces\n"); + return IPACM_FAILURE; + } + memset(pNatIfaces, 0, len); + if (pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0) + { + IPACMERR("Unable to retrieve non nat ifaces\n"); + return IPACM_FAILURE; + } /* Search/Configure linux interface-index and map it to IPA interface-index */ - if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { PERROR("get interface name socket create failed"); - return; + return IPACM_FAILURE; } memset(&ifr, 0, sizeof(struct ifreq)); ifr.ifr_ifindex = data->if_index; - - if(ioctl(fd, SIOCGIFNAME, &ifr) < 0) + if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) { PERROR("call_ioctl_on_dev: ioctl failed:"); close(fd); - return; + return IPACM_FAILURE; } close(fd); - for(i = 0; i < NatIfaceCnt; i++) + for (i = 0; i < NatIfaceCnt; i++) { - if(strncmp(ifr.ifr_name, - pNatIfaces[i].iface_name, - sizeof(pNatIfaces[i].iface_name)) == 0) + if (strncmp(ifr.ifr_name, + pNatIfaces[i].iface_name, + sizeof(pNatIfaces[i].iface_name)) == 0) { - /* copy the ipv4 address to filter out downlink connections - ignore downlink after listening connection event from - conntrack as it is not destinated to private ip address */ - IPACMDBG("Interface (%s) is nat\n", ifr.ifr_name); - for(j = 0; j < MAX_NAT_IFACES; j++) - { - /* check if duplicate NAT ip */ - if(nat_iface_ipv4_addr[j] == data->ipv4_addr) - break; + IPACMDBG_H("Nat iface (%s), entry (%d), dont cache", + pNatIfaces[i].iface_name, i); + iptodot("with ipv4 address: ", nat_iface_ipv4_addr[i]); + *NatIface = true; + return IPACM_SUCCESS; + } + } - if(nat_iface_ipv4_addr[j] == 0) + return IPACM_SUCCESS; +} + +void IPACM_ConntrackListener::HandleNonNatIPAddr( + void *inParam, bool AddOp) +{ + ipacm_event_data_all *data = (ipacm_event_data_all *)inParam; + bool NatIface = false; + int cnt, ret; + + if (isStaMode) + { + IPACMDBG("In STA mode, don't add dummy rules for non nat ifaces\n"); + return; + } + + /* Handle only non nat ifaces, NAT iface should be handle + separately to avoid race conditions between route/nat + rules add/delete operations */ + if (AddOp) + { + ret = CheckNatIface(data, &NatIface); + if (!NatIface && ret == IPACM_SUCCESS) + { + /* Cache the non nat iface ip address */ + for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++) + { + if (nonnat_iface_ipv4_addr[cnt] == 0) { - nat_iface_ipv4_addr[j] = data->ipv4_addr; - nat_inst->ResetPwrSaveIf(data->ipv4_addr); - nat_inst->FlushTempEntries(data->ipv4_addr, true); - break; + nonnat_iface_ipv4_addr[cnt] = data->ipv4_addr; + IPACMDBG("Add ip addr to non nat list (%d) ", cnt); + iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]); + + /* Add dummy nat rule for non nat ifaces */ + nat_inst->FlushTempEntries(data->ipv4_addr, true, true); + return; } } - - if(j == MAX_NAT_IFACES) + } + } + else + { + /* for delete operation */ + for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++) + { + if (nonnat_iface_ipv4_addr[cnt] == data->ipv4_addr) { - IPACMERR("Nat ifaces(%d) exceed maximum\n", j); - break; + IPACMDBG("Reseting ct filters, entry (%d) ", cnt); + iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]); + nonnat_iface_ipv4_addr[cnt] = 0; + nat_inst->FlushTempEntries(data->ipv4_addr, false); + nat_inst->DelEntriesOnClntDiscon(data->ipv4_addr); + return; } - - - isNatIface = true; - IPACMDBG("Nating connections of Interface (%s), entry (%d) ", pNatIfaces[i].iface_name, j); - iptodot("with ipv4 address", nat_iface_ipv4_addr[j]); - break; } + } - /* Cache the non nat iface ip address */ - if(isNatIface != true) + return; +} + +void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt( + ipacm_event_data_all *data) +{ + bool NatIface = false; + int j, ret; + + ret = CheckNatIface(data, &NatIface); + if (NatIface && ret == IPACM_SUCCESS) { - for(i = 0; i < MAX_NAT_IFACES; i++) + for (j = 0; j < MAX_IFACE_ADDRESS; j++) { - if(nonnat_iface_ipv4_addr[i] == 0) + /* check if duplicate NAT ip */ + if (nat_iface_ipv4_addr[j] == data->ipv4_addr) + break; + + /* Cache the new nat iface address */ + if (nat_iface_ipv4_addr[j] == 0) { - nonnat_iface_ipv4_addr[i] = data->ipv4_addr; - nat_inst->FlushTempEntries(data->ipv4_addr, false); + nat_iface_ipv4_addr[j] = data->ipv4_addr; + iptodot("Nating connections of addr: ", nat_iface_ipv4_addr[j]); break; } } - } + /* Add the cached temp entries to NAT table */ + if (j != MAX_IFACE_ADDRESS) + { + nat_inst->ResetPwrSaveIf(data->ipv4_addr); + nat_inst->FlushTempEntries(data->ipv4_addr, true); + } + } + return; } -void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(uint32_t ipv4_addr) +void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt( + uint32_t ipv4_addr) { int cnt; if(ipv4_addr == 0) { - IPACMDBG("Ignoring IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT EVENT\n"); + IPACMDBG("Ignoring\n"); return; } - IPACMDBG("\n"); - iptodot("Received ip addr", ipv4_addr); - IPACMDBG("Entering NAT entry deletion checking\n"); - - for(cnt = 0; cntFlushTempEntries(ipv4_addr, false); + nat_inst->DelEntriesOnClntDiscon(ipv4_addr); } } - nat_inst->FlushTempEntries(ipv4_addr, false); - nat_inst->DelEntriesOnClntDiscon(ipv4_addr); return; } @@ -289,8 +346,8 @@ void IPACM_ConntrackListener::TriggerWANUp(void *in_param) { ipacm_event_iface_up *wanup_data = (ipacm_event_iface_up *)in_param; - IPACMDBG("Recevied below information during wanup,\n"); - IPACMDBG("if_name:%s, ipv4_address:0x%x\n", + IPACMDBG_H("Recevied below information during wanup,\n"); + IPACMDBG_H("if_name:%s, ipv4_address:0x%x\n", wanup_data->ifname, wanup_data->ipv4_addr); if(wanup_data->ipv4_addr == 0) @@ -299,6 +356,14 @@ void IPACM_ConntrackListener::TriggerWANUp(void *in_param) return; } + if(isWanUp()) + { + if (wan_ipaddr != wanup_data->ipv4_addr) + TriggerWANDown(wan_ipaddr); + else + return; + } + WanUp = true; isStaMode = wanup_data->is_sta; IPACMDBG("isStaMode: %d\n", isStaMode); @@ -317,97 +382,101 @@ void IPACM_ConntrackListener::TriggerWANUp(void *in_param) int IPACM_ConntrackListener::CreateConnTrackThreads(void) { - int ret; - pthread_t tcp_thread = 0, udp_thread = 0; + int ret; + pthread_t tcp_thread = 0, udp_thread = 0; - if(isCTReg == false) - { + if(isCTReg == false) + { + if(!tcp_thread) + { + ret = pthread_create(&tcp_thread, NULL, IPACM_ConntrackClient::TCPRegisterWithConnTrack, NULL); + if(0 != ret) + { + IPACMERR("unable to create TCP conntrack event listner thread\n"); + PERROR("unable to create TCP conntrack\n"); + return -1; + } - if(!tcp_thread) + IPACMDBG("created TCP conntrack event listner thread\n"); + if(pthread_setname_np(tcp_thread, "tcp ct listener") != 0) { - ret = pthread_create(&tcp_thread, NULL, IPACM_ConntrackClient::TCPRegisterWithConnTrack, NULL); - if(0 != ret) - { - IPACMERR("unable to create TCP conntrack event listner thread\n"); - PERROR("unable to create TCP conntrack\n"); - return -1; - } - - IPACMDBG("created TCP conntrack event listner thread\n"); + IPACMERR("unable to set thread name\n"); } + } - if(!udp_thread) + if(!udp_thread) + { + ret = pthread_create(&udp_thread, NULL, IPACM_ConntrackClient::UDPRegisterWithConnTrack, NULL); + if(0 != ret) { - ret = pthread_create(&udp_thread, NULL, IPACM_ConntrackClient::UDPRegisterWithConnTrack, NULL); - if(0 != ret) - { - IPACMERR("unable to create UDP conntrack event listner thread\n"); - PERROR("unable to create UDP conntrack\n"); - goto error; - } - - IPACMDBG("created UDP conntrack event listner thread\n"); + IPACMERR("unable to create UDP conntrack event listner thread\n"); + PERROR("unable to create UDP conntrack\n"); + goto error; } - isCTReg = true; - } + IPACMDBG("created UDP conntrack event listner thread\n"); + if(pthread_setname_np(udp_thread, "udp ct listener") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + isCTReg = true; + } - return 0; + return 0; error: - return -1; + return -1; } int IPACM_ConntrackListener::CreateNatThreads(void) { - int ret; - pthread_t udpcto_thread = 0, to_monitor_thread = 0; + int ret; + pthread_t udpcto_thread = 0; - if(isNatThreadStart == false) - { - - if(!udpcto_thread) + if(isNatThreadStart == false) + { + if(!udpcto_thread) + { + ret = pthread_create(&udpcto_thread, NULL, IPACM_ConntrackClient::UDPConnTimeoutUpdate, NULL); + if(0 != ret) { - ret = pthread_create(&udpcto_thread, NULL, IPACM_ConntrackClient::UDPConnTimeoutUpdate, NULL); - if(0 != ret) - { - IPACMERR("unable to create udp conn timeout thread\n"); - PERROR("unable to create udp conn timeout\n"); - goto error; - } - - IPACMDBG("created upd conn timeout thread\n"); + IPACMERR("unable to create udp conn timeout thread\n"); + PERROR("unable to create udp conn timeout\n"); + goto error; } - if(!to_monitor_thread) + IPACMDBG("created upd conn timeout thread\n"); + if(pthread_setname_np(udpcto_thread, "udp conn timeout") != 0) { - ret = pthread_create(&to_monitor_thread, NULL, IPACM_ConntrackClient::TCPUDP_Timeout_monitor, NULL); - if(0 != ret) - { - IPACMERR("unable to create tcp/udp timeout monitor thread\n"); - PERROR("unable to create tcp/udp timeout monitor\n"); - goto error; - } - - IPACMDBG("created tcp/udp timeout monitor thread\n"); + IPACMERR("unable to set thread name\n"); } + } - isNatThreadStart = true; - } - return 0; + isNatThreadStart = true; + } + return 0; error: - return -1; + return -1; } void IPACM_ConntrackListener::TriggerWANDown(uint32_t wan_addr) { - IPACMDBG("Deleting ipv4 nat table with"); - iptodot("public ip address", wan_addr); - WanUp = false; + int ret = 0; + IPACMDBG_H("Deleting ipv4 nat table with"); + IPACMDBG_H(" public ip address(0x%x): %d.%d.%d.%d\n", wan_addr, + ((wan_addr>>24) & 0xFF), ((wan_addr>>16) & 0xFF), + ((wan_addr>>8) & 0xFF), (wan_addr & 0xFF)); if(nat_inst != NULL) { - nat_inst->DeleteTable(wan_addr); + ret = nat_inst->DeleteTable(wan_addr); + if (ret) + return; + + WanUp = false; + wan_ipaddr = 0; } } @@ -468,7 +537,7 @@ void ParseCTMessage(struct nf_conntrack *ct) void ParseCTV6Message(struct nf_conntrack *ct) { - uint32_t status, timeout, secmark; + uint32_t status, timeout; struct nfct_attr_grp_ipv6 orig_params; uint8_t l4proto, tcp_flags, tcp_state; @@ -609,8 +678,7 @@ void IPACM_ConntrackListener::ProcessCTMessage(void *param) out_flags = (NFCT_OF_SHOW_LAYER3 | NFCT_OF_TIME | NFCT_OF_ID); nfct_snprintf(buf, sizeof(buf), evt_data->ct, evt_data->type, NFCT_O_PLAIN, out_flags); - IPACMDBG("%s\n", buf); - IPACMDBG("\n"); + IPACMDBG_H("%s\n", buf); ParseCTMessage(evt_data->ct); #endif @@ -630,6 +698,337 @@ void IPACM_ConntrackListener::ProcessCTMessage(void *param) return; } +bool IPACM_ConntrackListener::AddIface( + nat_table_entry *rule, bool *isTempEntry) +{ + int cnt; + + *isTempEntry = false; + + /* Special handling for Passthrough IP. */ + if (IPACM_Iface::ipacmcfg->ipacm_ip_passthrough_mode) + { + if (rule->private_ip == IPACM_Wan::getWANIP()) + { + IPACMDBG("In Passthrough mode and entry matched with Wan IP (0x%x)\n", + rule->private_ip); + return true; + } + } + + /* check whether nat iface or not */ + for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++) + { + if (nat_iface_ipv4_addr[cnt] != 0) + { + if (rule->private_ip == nat_iface_ipv4_addr[cnt] || + rule->target_ip == nat_iface_ipv4_addr[cnt]) + { + IPACMDBG("matched nat_iface_ipv4_addr entry(%d)\n", cnt); + iptodot("AddIface(): Nat entry match with ip addr", + nat_iface_ipv4_addr[cnt]); + return true; + } + } + } + + if (!isStaMode) + { + /* check whether non nat iface or not, on Non Nat iface + add dummy rule by copying public ip to private ip */ + for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++) + { + if (nonnat_iface_ipv4_addr[cnt] != 0) + { + if (rule->private_ip == nonnat_iface_ipv4_addr[cnt] || + rule->target_ip == nonnat_iface_ipv4_addr[cnt]) + { + IPACMDBG("matched non_nat_iface_ipv4_addr entry(%d)\n", cnt); + iptodot("AddIface(): Non Nat entry match with ip addr", + nonnat_iface_ipv4_addr[cnt]); + + rule->private_ip = rule->public_ip; + rule->private_port = rule->public_port; + return true; + } + } + } + IPACMDBG_H("Not mtaching with non-nat ifaces\n"); + } + else + IPACMDBG("In STA mode, don't compare against non nat ifaces\n"); + + if(pConfig == NULL) + { + pConfig = IPACM_Config::GetInstance(); + if(pConfig == NULL) + { + IPACMERR("Unable to get Config instance\n"); + return false; + } + } + + if (pConfig->isPrivateSubnet(rule->private_ip) || + pConfig->isPrivateSubnet(rule->target_ip)) + { + IPACMDBG("Matching with Private subnet\n"); + *isTempEntry = true; + return true; + } + + return false; +} + +void IPACM_ConntrackListener::AddORDeleteNatEntry(const nat_entry_bundle *input) +{ + u_int8_t tcp_state; + + if (nat_inst == NULL) + { + IPACMERR("Nat instance is NULL, unable to add or delete\n"); + return; + } + + IPACMDBG_H("Below Nat Entry will either be added or deleted\n"); + iptodot("AddORDeleteNatEntry(): target ip or dst ip", + input->rule->target_ip); + IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", + input->rule->target_port, input->rule->target_port); + iptodot("AddORDeleteNatEntry(): private ip or src ip", + input->rule->private_ip); + IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", + input->rule->private_port, input->rule->private_port); + IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", + input->rule->public_port, input->rule->public_port); + IPACMDBG("Protocol: %d, destination nat flag: %d\n", + input->rule->protocol, input->rule->dst_nat); + + if (IPPROTO_TCP == input->rule->protocol) + { + tcp_state = nfct_get_attr_u8(input->ct, ATTR_TCP_STATE); + if (TCP_CONNTRACK_ESTABLISHED == tcp_state) + { + IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state); + if (!CtList->isWanUp()) + { + IPACMDBG("Wan is not up, cache connections\n"); + nat_inst->CacheEntry(input->rule); + } + else if (input->isTempEntry) + { + nat_inst->AddTempEntry(input->rule); + } + else + { + nat_inst->AddEntry(input->rule); + } + } + else if (TCP_CONNTRACK_FIN_WAIT == tcp_state || + input->type == NFCT_T_DESTROY) + { + IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) " + "or type NFCT_T_DESTROY(%d)\n", tcp_state, input->type); + + nat_inst->DeleteEntry(input->rule); + nat_inst->DeleteTempEntry(input->rule); + } + else + { + IPACMDBG("Ignore tcp state: %d and type: %d\n", + tcp_state, input->type); + } + + } + else if (IPPROTO_UDP == input->rule->protocol) + { + if (NFCT_T_NEW == input->type) + { + IPACMDBG("New UDP connection at time %ld\n", time(NULL)); + if (!CtList->isWanUp()) + { + IPACMDBG("Wan is not up, cache connections\n"); + nat_inst->CacheEntry(input->rule); + } + else if (input->isTempEntry) + { + nat_inst->AddTempEntry(input->rule); + } + else + { + nat_inst->AddEntry(input->rule); + } + } + else if (NFCT_T_DESTROY == input->type) + { + IPACMDBG("UDP connection close at time %ld\n", time(NULL)); + nat_inst->DeleteEntry(input->rule); + nat_inst->DeleteTempEntry(input->rule); + } + } + + return; +} + +void IPACM_ConntrackListener::PopulateTCPorUDPEntry( + struct nf_conntrack *ct, + uint32_t status, + nat_table_entry *rule) +{ + if (IPS_DST_NAT == status) + { + IPACMDBG("Destination NAT\n"); + rule->dst_nat = true; + + IPACMDBG("Parse reply tuple\n"); + rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); + rule->target_ip = ntohl(rule->target_ip); + iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip); + + /* Retriev target/dst port */ + rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC); + rule->target_port = ntohs(rule->target_port); + if (0 == rule->target_port) + { + IPACMDBG("unable to retrieve target port\n"); + } + + rule->public_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST); + rule->public_port = ntohs(rule->public_port); + + /* Retriev src/private ip address */ + rule->private_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC); + rule->private_ip = ntohl(rule->private_ip); + iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip); + if (0 == rule->private_ip) + { + IPACMDBG("unable to retrieve private ip address\n"); + } + + /* Retriev src/private port */ + rule->private_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC); + rule->private_port = ntohs(rule->private_port); + if (0 == rule->private_port) + { + IPACMDBG("unable to retrieve private port\n"); + } + } + else if (IPS_SRC_NAT == status) + { + IPACMDBG("Source NAT\n"); + rule->dst_nat = false; + + /* Retriev target/dst ip address */ + IPACMDBG("Parse source tuple\n"); + rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST); + rule->target_ip = ntohl(rule->target_ip); + iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip); + if (0 == rule->target_ip) + { + IPACMDBG("unable to retrieve target ip address\n"); + } + /* Retriev target/dst port */ + rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST); + rule->target_port = ntohs(rule->target_port); + if (0 == rule->target_port) + { + IPACMDBG("unable to retrieve target port\n"); + } + + /* Retriev public port */ + rule->public_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST); + rule->public_port = ntohs(rule->public_port); + if (0 == rule->public_port) + { + IPACMDBG("unable to retrieve public port\n"); + } + + /* Retriev src/private ip address */ + rule->private_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); + rule->private_ip = ntohl(rule->private_ip); + iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip); + if (0 == rule->private_ip) + { + IPACMDBG("unable to retrieve private ip address\n"); + } + + /* Retriev src/private port */ + rule->private_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC); + rule->private_port = ntohs(rule->private_port); + if (0 == rule->private_port) + { + IPACMDBG("unable to retrieve private port\n"); + } + } + + return; +} + +#ifdef CT_OPT +void IPACM_ConntrackListener::HandleLan2Lan(struct nf_conntrack *ct, + enum nf_conntrack_msg_type type, + nat_table_entry *rule) +{ + ipacm_event_connection lan2lan_conn = { 0 }; + + if (p_lan2lan == NULL) + { + IPACMERR("Lan2Lan Instance is null\n"); + return; + } + + lan2lan_conn.iptype = IPA_IP_v4; + lan2lan_conn.src_ipv4_addr = orig_src_ip; + lan2lan_conn.dst_ipv4_addr = orig_dst_ip; + + if (((IPPROTO_UDP == rule->protocol) && (NFCT_T_NEW == type)) || + ((IPPROTO_TCP == rule->protocol) && (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED))) + { + p_lan2lan->handle_new_connection(&lan2lan_conn); + } + else if ((IPPROTO_UDP == rule->protocol && NFCT_T_DESTROY == type) || + (IPPROTO_TCP == rule->protocol && + nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT)) + { + p_lan2lan->handle_del_connection(&lan2lan_conn); + } +} +#endif + +void IPACM_ConntrackListener::CheckSTAClient( + const nat_table_entry *rule, bool *isTempEntry) +{ + int nCnt; + + /* Check whether target is in STA client list or not + if not ignore the connection */ + if(!isStaMode || (StaClntCnt == 0)) + { + return; + } + + if((sta_clnt_ipv4_addr[0] & STA_CLNT_SUBNET_MASK) != + (rule->target_ip & STA_CLNT_SUBNET_MASK)) + { + IPACMDBG("STA client subnet mask not matching\n"); + return; + } + + IPACMDBG("StaClntCnt %d\n", StaClntCnt); + for(nCnt = 0; nCnt < StaClntCnt; nCnt++) + { + IPACMDBG("Comparing trgt_ip 0x%x with sta clnt ip: 0x%x\n", + rule->target_ip, sta_clnt_ipv4_addr[nCnt]); + if(rule->target_ip == sta_clnt_ipv4_addr[nCnt]) + { + IPACMDBG("Match index %d\n", nCnt); + return; + } + } + + IPACMDBG_H("Not matching with STA Clnt Ip Addrs 0x%x\n", + rule->target_ip); + *isTempEntry = true; +} /* conntrack send in host order and ipa expects in host order */ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( @@ -638,19 +1037,16 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( u_int8_t l4proto) { nat_table_entry rule; - u_int8_t tcp_state; uint32_t status = 0; - IPACM_Config *pConfig; uint32_t orig_src_ip, orig_dst_ip; - bool isTempEntry = false; + bool isAdd = false; - memset(&rule, 0, sizeof(rule)); - pConfig = IPACM_Config::GetInstance(); - if(pConfig == NULL) - { - IPACMERR("Unable to get Config instance\n"); - } + nat_entry_bundle nat_entry; + nat_entry.isTempEntry = false; + nat_entry.ct = ct; + nat_entry.type = type; + memset(&rule, 0, sizeof(rule)); IPACMDBG("Received type:%d with proto:%d\n", type, l4proto); status = nfct_get_attr_u32(ct, ATTR_STATUS); @@ -684,131 +1080,32 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( return; } - if(orig_src_ip == wan_ipaddr) - { - IPACMDBG("orig src ip:0x%x equal to wan ip\n",orig_src_ip); - status = IPS_SRC_NAT; - rule.public_ip = wan_ipaddr; - } - else if(orig_dst_ip == wan_ipaddr) - { - IPACMDBG("orig Dst IP:0x%x equal to wan ip\n",orig_dst_ip); - status = IPS_DST_NAT; - rule.public_ip = wan_ipaddr; - } - else - { - IPACMDBG("Neither orig src ip:0x%x Nor orig Dst IP:0x%x equal to wan ip:0x%x\n", - orig_src_ip, orig_dst_ip, wan_ipaddr); - -#ifdef CT_OPT - if(p_lan2lan == NULL) + if(orig_src_ip == wan_ipaddr) { - IPACMERR("Lan2Lan Instance is null\n"); - goto IGNORE; + IPACMDBG("orig src ip:0x%x equal to wan ip\n",orig_src_ip); + status = IPS_SRC_NAT; } + else if(orig_dst_ip == wan_ipaddr) + { + IPACMDBG("orig Dst IP:0x%x equal to wan ip\n",orig_dst_ip); + status = IPS_DST_NAT; + } + else + { + IPACMDBG_H("Neither orig src ip:0x%x Nor orig Dst IP:0x%x equal to wan ip:0x%x\n", + orig_src_ip, orig_dst_ip, wan_ipaddr); - ipacm_event_connection lan2lan_conn = { 0 }; - lan2lan_conn.iptype = IPA_IP_v4; - lan2lan_conn.src_ipv4_addr = orig_src_ip; - lan2lan_conn.dst_ipv4_addr = orig_dst_ip; - - if(((IPPROTO_UDP == rule.protocol) && (NFCT_T_NEW == type)) || - ((IPPROTO_TCP == rule.protocol) && (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED))) - { - p_lan2lan->handle_new_connection(&lan2lan_conn); - } - else if((IPPROTO_UDP == rule.protocol && NFCT_T_DESTROY == type) || - (IPPROTO_TCP == rule.protocol && - nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT)) - { - p_lan2lan->handle_del_connection(&lan2lan_conn); - } +#ifdef CT_OPT + HandleLan2Lan(ct, type, &rule); #endif - return; - } + return; + } } - if(IPS_DST_NAT == status) + if(IPS_DST_NAT == status || IPS_SRC_NAT == status) { - IPACMDBG("Destination NAT\n"); - rule.dst_nat = true; - - IPACMDBG("Parse reply tuple\n"); - rule.target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); - rule.target_ip = ntohl(rule.target_ip); - - /* Retriev target/dst port */ - rule.target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC); - rule.target_port = ntohs(rule.target_port); - if(0 == rule.target_port) - { - IPACMDBG("unable to retrieve target port\n"); - } - - rule.public_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST); - rule.public_port = ntohs(rule.public_port); - - /* Retriev src/private ip address */ - rule.private_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC); - rule.private_ip = ntohl(rule.private_ip); - if(0 == rule.private_ip) - { - IPACMDBG("unable to retrieve private ip address\n"); - } - - /* Retriev src/private port */ - rule.private_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC); - rule.private_port = ntohs(rule.private_port); - if(0 == rule.private_port) - { - IPACMDBG("unable to retrieve private port\n"); - } - } - else if(IPS_SRC_NAT == status) - { - IPACMDBG("Source NAT\n"); - rule.dst_nat = false; - - /* Retriev target/dst ip address */ - IPACMDBG("Parse source tuple\n"); - rule.target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST); - rule.target_ip = ntohl(rule.target_ip); - if(0 == rule.target_ip) - { - IPACMDBG("unable to retrieve target ip address\n"); - } - /* Retriev target/dst port */ - rule.target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST); - rule.target_port = ntohs(rule.target_port); - if(0 == rule.target_port) - { - IPACMDBG("unable to retrieve target port\n"); - } - - /* Retriev public port */ - rule.public_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST); - rule.public_port = ntohs(rule.public_port); - if(0 == rule.public_port) - { - IPACMDBG("unable to retrieve public port\n"); - } - - /* Retriev src/private ip address */ - rule.private_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); - rule.private_ip = ntohl(rule.private_ip); - if(0 == rule.private_ip) - { - IPACMDBG("unable to retrieve private ip address\n"); - } - - /* Retriev src/private port */ - rule.private_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC); - rule.private_port = ntohs(rule.private_port); - if(0 == rule.private_port) - { - IPACMDBG("unable to retrieve private port\n"); - } + PopulateTCPorUDPEntry(ct, status, &rule); + rule.public_ip = wan_ipaddr; } else { @@ -816,206 +1113,48 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( goto IGNORE; } - if(rule.private_ip != wan_ipaddr) + if (rule.private_ip != wan_ipaddr) { - int cnt; - for(cnt = 0; cnt < MAX_NAT_IFACES; cnt++) - { - if(nat_iface_ipv4_addr[cnt] != 0) - { - if(rule.private_ip == nat_iface_ipv4_addr[cnt] || - rule.target_ip == nat_iface_ipv4_addr[cnt]) - { - IPACMDBG("matched nat_iface_ipv4_addr entry(%d)\n", cnt); - iptodot("ProcessTCPorUDPMsg(): Nat entry match with ip addr", - nat_iface_ipv4_addr[cnt]); - break; - } - } - } - - if(cnt == MAX_NAT_IFACES) + isAdd = AddIface(&rule, &nat_entry.isTempEntry); + if (!isAdd) { - IPACMDBG("Not mtaching with nat ifaces\n") - if(pConfig == NULL) - { - goto IGNORE; - } - - if(pConfig->isPrivateSubnet(rule.private_ip) || - pConfig->isPrivateSubnet(rule.target_ip)) - { - IPACMDBG("Matching with Private subnet\n"); - isTempEntry = true; - } - else - { - goto IGNORE; - } + goto IGNORE; } - } else { - if(isStaMode) { + if (isStaMode) + { IPACMDBG("In STA mode, ignore connections destinated to STA interface\n"); goto IGNORE; } - IPACMDBG("For embedded connections add dummy nat rule\n"); - IPACMDBG("Change private port %d to %d\n", - rule.private_port, rule.public_port); - rule.private_port = rule.public_port; - } - - /* Check whether target is in STA client list or not - if not ignore the connection */ - int nCnt; - - if(!isStaMode || (StaClntCnt == 0)) - { - goto ADD; - } - - if((sta_clnt_ipv4_addr[0] & 0xFFFFFF00) != - (rule.target_ip & 0xFFFFFF00)) - { - IPACMDBG("STA client subnet mask not matching\n"); - goto ADD; - } - - IPACMDBG("StaClntCnt %d\n", StaClntCnt); - for(nCnt = 0; nCnt < StaClntCnt; nCnt++) - { - IPACMDBG("Comparing trgt_ip 0x%x with sta clnt ip: 0x%x\n", - rule.target_ip, sta_clnt_ipv4_addr[nCnt]); - if(rule.target_ip == sta_clnt_ipv4_addr[nCnt]) - { - IPACMDBG("Match index %d\n", nCnt); - goto ADD; - } - } - - IPACMDBG("Not matching with STA Clnt Ip Addrs 0x%x\n", - rule.target_ip); - goto IGNORE; - - -ADD: - IPACMDBG("Nat Entry with below information will either be added or deleted\n"); - iptodot("target ip or dst ip", rule.target_ip); - IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", rule.target_port, rule.target_port); - iptodot("private ip or src ip", rule.private_ip); - IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port); - IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port); - IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat); - - if(IPPROTO_TCP == rule.protocol) - { - if(nat_inst == NULL) - { - return; - } - - tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); - if(TCP_CONNTRACK_ESTABLISHED == tcp_state) - { - IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state); - if(!CtList->isWanUp()) - { - IPACMDBG("Wan is not up, cache connections\n"); - nat_inst->CacheEntry(&rule); - } - else if(isTempEntry) - { - nat_inst->AddTempEntry(&rule); - } - else - { - nat_inst->AddEntry(&rule); - } - } - else if(TCP_CONNTRACK_FIN_WAIT == tcp_state || - type == NFCT_T_DESTROY) - { - IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) " - "or type NFCT_T_DESTROY(%d)\n", tcp_state, type); - - if(isTempEntry) - { - nat_inst->DeleteTempEntry(&rule); - } - else - { - nat_inst->DeleteEntry(&rule); - } - } - else - { - IPACMDBG("Ignore tcp state: %d and type: %d\n", tcp_state, type); - } - - } - else if(IPPROTO_UDP == rule.protocol) - { - if(nat_inst == NULL) - { - return; - } - - if(NFCT_T_NEW == type) - { - IPACMDBG("New UDP connection at time %ld\n", time(NULL)); - if(!CtList->isWanUp()) - { - IPACMDBG("Wan is not up, cache connections\n"); - nat_inst->CacheEntry(&rule); - } - else if(isTempEntry) - { - nat_inst->AddTempEntry(&rule); - } - else - { - nat_inst->AddEntry(&rule); - } - } - else if(NFCT_T_DESTROY == type) - { - IPACMDBG("UDP connection close at time %ld\n", time(NULL)); - if(isTempEntry) - { - nat_inst->DeleteTempEntry(&rule); - } - else - { - nat_inst->DeleteEntry(&rule); - } - } - } - else - { - IPACMDBG("Ignore protocol: %d and type: %d\n", rule.protocol, type); + IPACMDBG("For embedded connections add dummy nat rule\n"); + IPACMDBG("Change private port %d to %d\n", + rule.private_port, rule.public_port); + rule.private_port = rule.public_port; } + CheckSTAClient(&rule, &nat_entry.isTempEntry); + nat_entry.rule = &rule; + AddORDeleteNatEntry(&nat_entry); return; IGNORE: - IPACMDBG("ignoring below Nat Entry\n"); - iptodot("target ip or dst ip", rule.target_ip); + IPACMDBG_H("ignoring below Nat Entry\n"); + iptodot("ProcessTCPorUDPMsg(): target ip or dst ip", rule.target_ip); IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", rule.target_port, rule.target_port); - iptodot("private ip or src ip", rule.private_ip); + iptodot("ProcessTCPorUDPMsg(): private ip or src ip", rule.private_ip); IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port); IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port); IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat); - return; } void IPACM_ConntrackListener::HandleSTAClientAddEvt(uint32_t clnt_ip_addr) { int cnt; - IPACMDBG("Received STA client 0x%x\n", clnt_ip_addr); + IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr); if(StaClntCnt >= MAX_STA_CLNT_IFACES) { @@ -1044,13 +1183,14 @@ void IPACM_ConntrackListener::HandleSTAClientAddEvt(uint32_t clnt_ip_addr) } + nat_inst->FlushTempEntries(clnt_ip_addr, true); return; } void IPACM_ConntrackListener::HandleSTAClientDelEvt(uint32_t clnt_ip_addr) { int cnt; - IPACMDBG("Received STA client 0x%x\n", clnt_ip_addr); + IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr); for(cnt=0; cntFlushTempEntries(clnt_ip_addr, false); + return; } diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp index aa1f4783..c020574d 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -28,6 +28,9 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "IPACM_Conntrack_NATApp.h" #include "IPACM_ConntrackClient.h" +#ifdef FEATURE_IPACM_HAL +#include "IPACM_OffloadManager.h" +#endif #define INVALID_IP_ADDR 0x0 @@ -77,24 +80,27 @@ int NatApp::Init(void) memset(cache, 0, size); nALGPort = pConfig->GetAlgPortCnt(); - pALGPorts = (ipacm_alg *)malloc(sizeof(ipacm_alg) * nALGPort); - if(pALGPorts == NULL) + if(nALGPort > 0) { - IPACMERR("Unable to allocate memory for alg prots\n"); - goto fail; - } - memset(pALGPorts, 0, sizeof(ipacm_alg) * nALGPort); + pALGPorts = (ipacm_alg *)malloc(sizeof(ipacm_alg) * nALGPort); + if(pALGPorts == NULL) + { + IPACMERR("Unable to allocate memory for alg prots\n"); + goto fail; + } + memset(pALGPorts, 0, sizeof(ipacm_alg) * nALGPort); - if(pConfig->GetAlgPorts(nALGPort, pALGPorts) != 0) - { - IPACMERR("Unable to retrieve ALG prots\n"); - goto fail; - } + if(pConfig->GetAlgPorts(nALGPort, pALGPorts) != 0) + { + IPACMERR("Unable to retrieve ALG prots\n"); + goto fail; + } - IPACMDBG("Printing %d alg ports information\n", nALGPort); - for(int cnt=0; cnttarget_port && cache[cnt].protocol == rule->protocol) { - IPACMDBG("Duplicate Rule\n"); - iptodot("Private IP", rule->private_ip); - iptodot("Target IP", rule->target_ip); - IPACMDBG("Private Port: %d\t Target Port: %d\t", rule->private_port, rule->target_port); - IPACMDBG("protocolcol: %d\n", rule->protocol); + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"Duplicate Rule\n"); return true; } } @@ -256,11 +259,9 @@ int NatApp::DeleteEntry(const nat_table_entry *rule) int cnt = 0; IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); - IPACMDBG("Received below nat entry for deletion\n"); - iptodot("Private IP", rule->private_ip); - iptodot("Target IP", rule->target_ip); - IPACMDBG("Private Port: %d\t Target Port: %d\t", rule->private_port, rule->target_port); - IPACMDBG("protocolcol: %d\n", rule->protocol); + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"for deletion\n"); + for(; cnt < max_entries; cnt++) { @@ -278,11 +279,11 @@ int NatApp::DeleteEntry(const nat_table_entry *rule) IPACMERR("%s() %d deletion failed\n", __FUNCTION__, __LINE__); } - IPACMDBG("Deleted Nat entry(%d) Successfully\n", cnt); + IPACMDBG_H("Deleted Nat entry(%d) Successfully\n", cnt); } else { - IPACMDBG("Deleted Nat entry(%d) only from cache\n", cnt); + IPACMDBG_H("Deleted Nat entry(%d) only from cache\n", cnt); } memset(&cache[cnt], 0, sizeof(cache[cnt])); @@ -297,23 +298,18 @@ int NatApp::DeleteEntry(const nat_table_entry *rule) /* Add new entry to the nat table on new connection */ int NatApp::AddEntry(const nat_table_entry *rule) { - int cnt = 0; ipa_nat_ipv4_rule nat_rule; + IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); CHK_TBL_HDL(); - - IPACMDBG("Received below nat entry for addition\n"); - iptodot("Private IP", rule->private_ip); - iptodot("Target IP", rule->target_ip); - IPACMDBG("Private Port: %d\t Target Port: %d\t", rule->private_port, rule->target_port); - IPACMDBG("protocolcol: %d\n", rule->protocol); - + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"for addition\n"); if(isAlgPort(rule->protocol, rule->private_port) || isAlgPort(rule->protocol, rule->target_port)) { - IPACMERR("connection using ALG Port. Dont insert into nat table\n"); + IPACMERR("connection using ALG Port, ignore\n"); return -1; } @@ -348,6 +344,7 @@ int NatApp::AddEntry(const nat_table_entry *rule) } else { + memset(&nat_rule, 0, sizeof(nat_rule)); nat_rule.private_ip = rule->private_ip; nat_rule.target_ip = rule->target_ip; nat_rule.target_port = rule->target_port; @@ -394,11 +391,11 @@ int NatApp::AddEntry(const nat_table_entry *rule) if(cache[cnt].enabled == true) { - IPACMDBG("Added rule(%d) successfully\n", cnt); + IPACMDBG_H("Added rule(%d) successfully\n", cnt); } else { - IPACMDBG("Cached rule(%d) successfully\n", cnt); + IPACMDBG_H("Cached rule(%d) successfully\n", cnt); } return 0; @@ -407,11 +404,16 @@ int NatApp::AddEntry(const nat_table_entry *rule) void NatApp::UpdateCTUdpTs(nat_table_entry *rule, uint32_t new_ts) { int ret; +#ifdef FEATURE_IPACM_HAL + IOffloadManager::ConntrackTimeoutUpdater::natTimeoutUpdate_t entry; + IPACM_OffloadManager* OffloadMng; +#endif iptodot("Private IP:", rule->private_ip); iptodot("Target IP:", rule->target_ip); IPACMDBG("Private Port: %d, Target Port: %d\n", rule->private_port, rule->target_port); +#ifndef FEATURE_IPACM_HAL if(!ct_hdl) { ct_hdl = nfct_open(CONNTRACK, 0); @@ -476,14 +478,55 @@ void NatApp::UpdateCTUdpTs(nat_table_entry *rule, uint32_t new_ts) ret = nfct_query(ct_hdl, NFCT_Q_UPDATE, ct); if(ret == -1) { - PERROR("unable to update time stamp"); + IPACMERR("unable to update time stamp"); + DeleteEntry(rule); } else { rule->timestamp = new_ts; IPACMDBG("Updated time stamp successfully\n"); } +#else + if(rule->protocol == IPPROTO_UDP) + { + entry.proto = IOffloadManager::ConntrackTimeoutUpdater::UDP;; + } + else + { + entry.proto = IOffloadManager::ConntrackTimeoutUpdater::TCP; + } + + if(rule->dst_nat == false) + { + entry.src.ipAddr = htonl(rule->private_ip); + entry.src.port = rule->private_port; + entry.dst.ipAddr = htonl(rule->target_ip); + entry.dst.port = rule->target_port; + IPACMDBG("dst nat is not set\n"); + } + else + { + entry.src.ipAddr = htonl(rule->target_ip); + entry.src.port = rule->target_port; + entry.dst.ipAddr = htonl(pub_ip_addr); + entry.dst.port = rule->public_port; + IPACMDBG("dst nat is set\n"); + } + + iptodot("Source IP:", entry.src.ipAddr); + iptodot("Destination IP:", entry.dst.ipAddr); + IPACMDBG("Source Port: %d, Destination Port: %d\n", + entry.src.port, entry.dst.port); + OffloadMng = IPACM_OffloadManager::GetInstance(); + if (OffloadMng->touInstance == NULL) { + IPACMERR("OffloadMng->touInstance is NULL, can't forward to framework!\n"); + } else { + OffloadMng->touInstance->updateTimeout(entry); + IPACMDBG("Updated time stamp successfully\n"); + rule->timestamp = new_ts; + } +#endif return; } @@ -491,11 +534,13 @@ void NatApp::UpdateUDPTimeStamp() { int cnt; uint32_t ts; + bool read_to = false; for(cnt = 0; cnt < max_entries; cnt++) { ts = 0; - if(cache[cnt].enabled == true) + if(cache[cnt].enabled == true && + (cache[cnt].private_ip != cache[cnt].public_ip)) { IPACMDBG("\n"); if(ipa_nat_query_timestamp(nat_table_hdl, cache[cnt].rule_hdl, &ts) < 0) @@ -511,6 +556,11 @@ void NatApp::UpdateUDPTimeStamp() continue; } + if (read_to == false) { + read_to = true; + Read_TcpUdp_Timeout(); + } + UpdateCTUdpTs(&cache[cnt], ts); } /* end of outer if */ @@ -552,7 +602,7 @@ bool NatApp::isPwrSaveIf(uint32_t ip_addr) int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip) { int cnt; - IPACMDBG("Received IP address: 0x%x\n", client_lan_ip); + IPACMDBG_H("Received IP address: 0x%x\n", client_lan_ip); if(client_lan_ip == INVALID_IP_ADDR) { @@ -570,7 +620,6 @@ int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip) } } - for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) { if(PwrSaveIfs[cnt] == 0) @@ -604,7 +653,7 @@ int NatApp::ResetPwrSaveIf(uint32_t client_lan_ip) int cnt; ipa_nat_ipv4_rule nat_rule; - IPACMDBG("Received ip address: 0x%x\n", client_lan_ip); + IPACMDBG_H("Received ip address: 0x%x\n", client_lan_ip); if(client_lan_ip == INVALID_IP_ADDR) { @@ -658,20 +707,6 @@ int NatApp::ResetPwrSaveIf(uint32_t client_lan_ip) return -1; } -void NatApp::UpdateTcpUdpTo(uint32_t new_value, int proto) -{ - if(proto == IPPROTO_TCP) - { - tcp_timeout = new_value; - IPACMDBG("new nat tcp timeout value: %d\n", tcp_timeout); - } - else if(proto == IPPROTO_UDP) - { - udp_timeout = new_value; - IPACMDBG("new nat udp timeout value: %d\n", udp_timeout); - } -} - uint32_t NatApp::GetTableHdl(uint32_t in_ip_addr) { if(in_ip_addr == pub_ip_addr) @@ -686,12 +721,37 @@ void NatApp::AddTempEntry(const nat_table_entry *new_entry) { int cnt; - IPACMDBG("Received below nat entry\n"); + IPACMDBG("Received below Temp Nat entry\n"); iptodot("Private IP", new_entry->private_ip); iptodot("Target IP", new_entry->target_ip); IPACMDBG("Private Port: %d\t Target Port: %d\t", new_entry->private_port, new_entry->target_port); IPACMDBG("protocolcol: %d\n", new_entry->protocol); + if(isAlgPort(new_entry->protocol, new_entry->private_port) || + isAlgPort(new_entry->protocol, new_entry->target_port)) + { + IPACMDBG("connection using ALG Port. Dont insert into nat cache\n"); + return; + } + + if(ChkForDup(new_entry)) + { + return; + } + + for(cnt=0; cntprivate_ip && + temp[cnt].target_ip == new_entry->target_ip && + temp[cnt].private_port == new_entry->private_port && + temp[cnt].target_port == new_entry->target_port && + temp[cnt].protocol == new_entry->protocol) + { + IPACMDBG("Received duplicate Temp entry\n"); + return; + } + } + for(cnt=0; cntprivate_ip); iptodot("Target IP", entry->target_ip); - IPACMDBG("Private Port: %d\t Target Port: %d\t", entry->private_port, entry->target_port); - IPACMDBG("protocolcol: %d\n", entry->protocol); + IPACMDBG("Private Port: %d\t Target Port: %d\n", entry->private_port, entry->target_port); + IPACMDBG("protocol: %d\n", entry->protocol); for(cnt=0; cntprivate_ip == 0 || rule->target_ip == 0 || rule->private_port == 0 || @@ -862,7 +933,7 @@ void NatApp::CacheEntry(const nat_table_entry *rule) if(!ChkForDup(rule)) { - for(; cnt < max_entries; cnt++) + for(cnt=0; cnt < max_entries; cnt++) { if(cache[cnt].private_ip == 0 && cache[cnt].target_ip == 0 && @@ -890,6 +961,7 @@ void NatApp::CacheEntry(const nat_table_entry *rule) cache[cnt].protocol = rule->protocol; cache[cnt].timestamp = 0; cache[cnt].public_port = rule->public_port; + cache[cnt].public_ip = rule->public_ip; cache[cnt].dst_nat = rule->dst_nat; curCnt++; } @@ -904,3 +976,43 @@ void NatApp::CacheEntry(const nat_table_entry *rule) IPACMDBG("Cached rule(%d) successfully\n", cnt); return; } + +void NatApp::Read_TcpUdp_Timeout(void) { + FILE *udp_fd = NULL, *tcp_fd = NULL; + + /* Read UDP timeout value */ + udp_fd = fopen(IPACM_UDP_FULL_FILE_NAME, "r"); + if (udp_fd == NULL) { + IPACMERR("unable to open %s\n", IPACM_UDP_FULL_FILE_NAME); + goto fail; + } + + if (fscanf(udp_fd, "%d", &udp_timeout) != 1) { + IPACMERR("Error reading udp timeout\n"); + } + IPACMDBG_H("udp timeout value: %d\n", udp_timeout); + + + /* Read TCP timeout value */ + tcp_fd = fopen(IPACM_TCP_FULL_FILE_NAME, "r"); + if (tcp_fd == NULL) { + IPACMERR("unable to open %s\n", IPACM_TCP_FULL_FILE_NAME); + goto fail; + } + + + if (fscanf(tcp_fd, "%d", &tcp_timeout) != 1) { + IPACMERR("Error reading tcp timeout\n"); + } + IPACMDBG_H("tcp timeout value: %d\n", tcp_timeout); + +fail: + if (udp_fd) { + fclose(udp_fd); + } + if (tcp_fd) { + fclose(tcp_fd); + } + + return; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_EvtDispatcher.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_EvtDispatcher.cpp index 11782dfb..edb5901d 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_EvtDispatcher.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_EvtDispatcher.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -58,7 +58,16 @@ int IPACM_EvtDispatcher::PostEvt Message *item = NULL; MessageQueue *MsgQueue = NULL; - MsgQueue = MessageQueue::getInstance(); + if(data->event < IPA_EXTERNAL_EVENT_MAX) + { + IPACMDBG("Insert event into external queue.\n"); + MsgQueue = MessageQueue::getInstanceExternal(); + } + else + { + IPACMDBG("Insert event into internal queue.\n"); + MsgQueue = MessageQueue::getInstanceInternal(); + } if(MsgQueue == NULL) { IPACMERR("unable to retrieve MsgQueue instance\n"); @@ -72,7 +81,6 @@ int IPACM_EvtDispatcher::PostEvt return IPACM_FAILURE; } - IPACMDBG("Populating item to post to queue\n"); item->evt.callback_ptr = IPACM_EvtDispatcher::ProcessEvt; memcpy(&item->evt.data, data, sizeof(ipacm_cmd_q_data)); diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp index 931aff4d..22eb19cb 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp @@ -1,5 +1,5 @@ -/* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +/* +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -80,9 +80,8 @@ bool IPACM_Filtering::AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTa IPACMDBG("commit value: %d\n", ruleTable->commit); for (int cnt=0; cntnum_rules; cnt++) { - IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", - cnt, - ruleTable->rules[cnt].rule.attrib.attrib_mask); + IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", cnt, + ruleTable->rules[cnt].rule.attrib.attrib_mask); } retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE, ruleTable); @@ -115,6 +114,38 @@ bool IPACM_Filtering::AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTa return true; } +bool IPACM_Filtering::AddFilteringRuleAfter(struct ipa_ioc_add_flt_rule_after const *ruleTable) +{ +#ifdef FEATURE_IPA_V3 + int retval = 0; + + IPACMDBG("Printing filter add attributes\n"); + IPACMDBG("ip type: %d\n", ruleTable->ip); + IPACMDBG("Number of rules: %d\n", ruleTable->num_rules); + IPACMDBG("End point: %d\n", ruleTable->ep); + IPACMDBG("commit value: %d\n", ruleTable->commit); + + retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_AFTER, ruleTable); + + for (int cnt = 0; cntnum_rules; cnt++) + { + if(ruleTable->rules[cnt].status != 0) + { + IPACMERR("Adding Filter rule:%d failed with status:%d\n", + cnt, ruleTable->rules[cnt].status); + } + } + + if (retval != 0) + { + IPACMERR("Failed adding Filtering rule %p\n", ruleTable); + return false; + } + IPACMDBG("Added Filtering rule %p\n", ruleTable); +#endif + return true; +} + bool IPACM_Filtering::DeleteFilteringRule(struct ipa_ioc_del_flt_rule *ruleTable) { int retval = 0; @@ -215,8 +246,7 @@ bool IPACM_Filtering::DeleteFilteringHdls res = false; goto fail; } - - } + } } } @@ -230,6 +260,9 @@ bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *r { int ret = 0, cnt, num_rules = 0, pos = 0; ipa_install_fltr_rule_req_msg_v01 qmi_rule_msg; +#ifdef FEATURE_IPA_V3 + ipa_install_fltr_rule_req_ex_msg_v01 qmi_rule_ex_msg; +#endif int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); if(fd_wwan_ioctl < 0) @@ -249,6 +282,8 @@ bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *r IPACMDBG_H("Get %d WAN DL IPv6 filtering rules.\n", rule_table_v6->num_rules); } + /* if it is not IPA v3, use old QMI format */ +#ifndef FEATURE_IPA_V3 if(num_rules > QMI_IPA_MAX_FILTERS_V01) { IPACMERR("The number of filtering rules exceed limit.\n"); @@ -267,29 +302,30 @@ bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *r { qmi_rule_msg.filter_spec_list_valid = false; } + qmi_rule_msg.filter_spec_list_len = num_rules; qmi_rule_msg.source_pipe_index_valid = 0; IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules); - + if(rule_table_v4 != NULL) { for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--) { if (pos < QMI_IPA_MAX_FILTERS_V01) { - qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos; - qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01; - qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action); - qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1; - qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx; - qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1; - qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id; - - memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule, &rule_table_v4->rules[cnt].rule.eq_attrib, - sizeof(struct ipa_filter_rule_type_v01)); - pos++; - } + qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos; + qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01; + qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action); + qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1; + qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx; + qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1; + qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id; + memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule, + &rule_table_v4->rules[cnt].rule.eq_attrib, + sizeof(struct ipa_filter_rule_type_v01)); + pos++; + } else { IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos); @@ -303,18 +339,18 @@ bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *r { if (pos < QMI_IPA_MAX_FILTERS_V01) { - qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos; - qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01; - qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action); - qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1; - qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx; - qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1; - qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id; - - memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule, &rule_table_v6->rules[cnt].rule.eq_attrib, - sizeof(struct ipa_filter_rule_type_v01)); - pos++; - } + qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos; + qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01; + qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action); + qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1; + qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx; + qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1; + qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id; + memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule, + &rule_table_v6->rules[cnt].rule.eq_attrib, + sizeof(struct ipa_filter_rule_type_v01)); + pos++; + } else { IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos); @@ -330,7 +366,95 @@ bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *r return false; } } - IPACMDBG("Added Filtering rule %p\n", &qmi_rule_msg); + /* if it is IPA v3, use new QMI format */ +#else + if(num_rules > QMI_IPA_MAX_FILTERS_EX_V01) + { + IPACMERR("The number of filtering rules exceed limit.\n"); + close(fd_wwan_ioctl); + return false; + } + else + { + memset(&qmi_rule_ex_msg, 0, sizeof(qmi_rule_ex_msg)); + + if (num_rules > 0) + { + qmi_rule_ex_msg.filter_spec_ex_list_valid = true; + } + else + { + qmi_rule_ex_msg.filter_spec_ex_list_valid = false; + } + qmi_rule_ex_msg.filter_spec_ex_list_len = num_rules; + qmi_rule_ex_msg.source_pipe_index_valid = 0; + + IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules); + + if(rule_table_v4 != NULL) + { + for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--) + { + if (pos < QMI_IPA_MAX_FILTERS_EX_V01) + { + qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01; + qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action); + qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1; + qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx; + qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1; + qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id; + qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v4->rules[cnt].rule.rule_id; + qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v4->rules[cnt].rule.hashable; + memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule, + &rule_table_v4->rules[cnt].rule.eq_attrib, + sizeof(struct ipa_filter_rule_type_v01)); + + pos++; + } + else + { + IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos); + } + } + } + + if(rule_table_v6 != NULL) + { + for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--) + { + if (pos < QMI_IPA_MAX_FILTERS_EX_V01) + { + qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01; + qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action); + qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1; + qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx; + qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1; + qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id; + qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v6->rules[cnt].rule.rule_id; + qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v6->rules[cnt].rule.hashable; + memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule, + &rule_table_v6->rules[cnt].rule.eq_attrib, + sizeof(struct ipa_filter_rule_type_v01)); + + pos++; + } + else + { + IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos); + } + } + } + + ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_EX, &qmi_rule_ex_msg); + if (ret != 0) + { + IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_ex_msg, ret); + close(fd_wwan_ioctl); + return false; + } + } +#endif + close(fd_wwan_ioctl); return true; } diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp index 5e56a497..c77c69c4 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -203,7 +203,7 @@ bool IPACM_Header::AddHeaderProcCtx(struct ipa_ioc_add_hdr_proc_ctx* pHeader) int ret = 0; //call the Driver ioctl to add header processing context ret = ioctl(m_fd, IPA_IOC_ADD_HDR_PROC_CTX, pHeader); - return (ret != -1); + return (ret == 0); } bool IPACM_Header::DeleteHeaderProcCtx(uint32_t hdl) @@ -225,7 +225,12 @@ bool IPACM_Header::DeleteHeaderProcCtx(uint32_t hdl) pHeaderTable->hdl[0].hdl = hdl; ret = ioctl(m_fd, IPA_IOC_DEL_HDR_PROC_CTX, pHeaderTable); + if(ret != 0) + { + IPACMERR("Failed to delete hdr proc ctx: return value %d, status %d\n", + ret, pHeaderTable->hdl[0].status); + } free(pHeaderTable); - return (ret != -1); + return (ret == 0); } diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp index 8920cfd0..717f6aaf 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp @@ -82,8 +82,6 @@ IPACM_Iface::IPACM_Iface(int iface_index) memset(software_routing_fl_rule_hdl, 0, sizeof(software_routing_fl_rule_hdl)); memset(ipv6_addr, 0, sizeof(ipv6_addr)); - flt_rule_count_v4 = 0; - flt_rule_count_v6 = 0; query_iface_property(); IPACMDBG_H(" create iface-index(%d) constructor\n", ipa_if_num); return; @@ -135,6 +133,9 @@ int IPACM_Iface::handle_software_routing_enable(void) flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); @@ -159,6 +160,7 @@ int IPACM_Iface::handle_software_routing_enable(void) goto fail; } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); /* copy filter hdls */ software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; @@ -179,6 +181,7 @@ int IPACM_Iface::handle_software_routing_enable(void) goto fail; } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); /* copy filter hdls */ software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; @@ -209,6 +212,7 @@ int IPACM_Iface::handle_software_routing_enable(void) goto fail; } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, ip_type, 1); IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); /* copy filter hdls */ if (ip_type == IPA_IP_v4) @@ -258,6 +262,7 @@ int IPACM_Iface::handle_software_routing_disable(void) res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); /* ipv6 case */ if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[1], @@ -267,6 +272,7 @@ int IPACM_Iface::handle_software_routing_disable(void) res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); softwarerouting_act = false; #if 0 } @@ -297,6 +303,7 @@ int IPACM_Iface::handle_software_routing_disable(void) res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, ip, 1); softwarerouting_act = false; } #endif @@ -443,12 +450,15 @@ void IPACM_Iface::iface_addr_query freeifaddrs(myaddrs); return ; } + memset(data_addr, 0, sizeof(ipacm_event_data_addr)); data_addr->iptype = IPA_IP_v4; data_addr->if_index = interface_index; data_addr->ipv4_addr = iface_ipv4.s_addr; data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr); - IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv4 addr:0x%x\n", + strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name)); + IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv4 addr:0x%x\n", data_addr->if_index, + data_addr->iface_name, data_addr->ipv4_addr); evt_data.event = IPA_ADDR_ADD_EVENT; @@ -468,6 +478,7 @@ void IPACM_Iface::iface_addr_query freeifaddrs(myaddrs); return ; } + memset(data_addr, 0, sizeof(ipacm_event_data_addr)); data_addr->iptype = IPA_IP_v6; data_addr->if_index = interface_index; memcpy(data_addr->ipv6_addr, @@ -477,8 +488,10 @@ void IPACM_Iface::iface_addr_query data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); - IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n", + strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name)); + IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv6 addr:0x%x:%x:%x:%x\n", data_addr->if_index, + data_addr->iface_name, data_addr->ipv6_addr[0], data_addr->ipv6_addr[1], data_addr->ipv6_addr[2], data_addr->ipv6_addr[3]); evt_data.event = IPA_ADDR_ADD_EVENT; @@ -539,28 +552,47 @@ int IPACM_Iface::query_iface_property(void) close(fd); return IPACM_FAILURE; } - memcpy(tx_prop->name, dev_name, sizeof(tx_prop->name)); - tx_prop->num_tx_props = iface_query->num_tx_props; + memcpy(tx_prop->name, dev_name, sizeof(tx_prop->name)); + tx_prop->num_tx_props = iface_query->num_tx_props; - if (ioctl(fd, IPA_IOC_QUERY_INTF_TX_PROPS, tx_prop) < 0) - { - PERROR("ioctl IPA_IOC_QUERY_INTF_TX_PROPS failed\n"); - /* tx_prop memory will free when iface-down*/ - res = IPACM_FAILURE; - } + if (ioctl(fd, IPA_IOC_QUERY_INTF_TX_PROPS, tx_prop) < 0) + { + PERROR("ioctl IPA_IOC_QUERY_INTF_TX_PROPS failed\n"); + /* tx_prop memory will free when iface-down*/ + res = IPACM_FAILURE; + } if (res != IPACM_FAILURE) { for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++) { - IPACMDBG_H("Tx(%d):attrib-mask:0x%x, ip-type: %d, dst_pipe: %d, header: %s\n", - cnt, tx_prop->tx[cnt].attrib.attrib_mask, tx_prop->tx[cnt].ip, tx_prop->tx[cnt].dst_pipe, tx_prop->tx[cnt].hdr_name); + IPACMDBG_H("Tx(%d):attrib-mask:0x%x, ip-type: %d, dst_pipe: %d, alt_dst_pipe: %d, header: %s\n", + cnt, tx_prop->tx[cnt].attrib.attrib_mask, + tx_prop->tx[cnt].ip, tx_prop->tx[cnt].dst_pipe, + tx_prop->tx[cnt].alt_dst_pipe, + tx_prop->tx[cnt].hdr_name); + + if (tx_prop->tx[cnt].dst_pipe == 0) + { + IPACMERR("Tx(%d): wrong tx property: dst_pipe: 0.\n", cnt); + close(fd); + return IPACM_FAILURE; + } + if (tx_prop->tx[cnt].alt_dst_pipe == 0 && + ((memcmp(dev_name, "wlan0", sizeof("wlan0")) == 0) || + (memcmp(dev_name, "wlan1", sizeof("wlan1")) == 0))) + { + IPACMERR("Tx(%d): wrong tx property: alt_dst_pipe: 0. \n", cnt); + close(fd); + return IPACM_FAILURE; + } + } } } - if (iface_query->num_rx_props > 0) + if (iface_query->num_rx_props > 0) { rx_prop = (struct ipa_ioc_query_intf_rx_props *) calloc(1, sizeof(struct ipa_ioc_query_intf_rx_props) + @@ -571,16 +603,16 @@ int IPACM_Iface::query_iface_property(void) close(fd); return IPACM_FAILURE; } - memcpy(rx_prop->name, dev_name, + memcpy(rx_prop->name, dev_name, sizeof(rx_prop->name)); - rx_prop->num_rx_props = iface_query->num_rx_props; + rx_prop->num_rx_props = iface_query->num_rx_props; - if (ioctl(fd, IPA_IOC_QUERY_INTF_RX_PROPS, rx_prop) < 0) - { - PERROR("ioctl IPA_IOC_QUERY_INTF_RX_PROPS failed\n"); - /* rx_prop memory will free when iface-down*/ - res = IPACM_FAILURE; - } + if (ioctl(fd, IPA_IOC_QUERY_INTF_RX_PROPS, rx_prop) < 0) + { + PERROR("ioctl IPA_IOC_QUERY_INTF_RX_PROPS failed\n"); + /* rx_prop memory will free when iface-down*/ + res = IPACM_FAILURE; + } if (res != IPACM_FAILURE) { @@ -616,48 +648,6 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) const char *dev_wlan1="wlan1"; const char *dev_ecm0="ecm0"; - /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/ - if (iptype == IPA_IP_v4) - { - - if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX)) - { - IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); - return res; - } - - if (ip_type == IPA_IP_v6) - { - ip_type = IPA_IP_MAX; - } - else - { - ip_type = IPA_IP_v4; - } - - IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); - } - else - { - - if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX)) - { - IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); - return res; - } - - if (ip_type == IPA_IP_v4) - { - ip_type = IPA_IP_MAX; - } - else - { - ip_type = IPA_IP_v6; - } - - IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); - } - /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */ if((IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat== WAN_IF) || (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat== EMBMS_IF)) { @@ -721,6 +711,10 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = false; + flt_rule_entry.rule.hashable = false; +#endif IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, @@ -736,11 +730,19 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000; flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.hashable = true; +#endif memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); /* Configuring Broadcast Filtering Rule */ flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.hashable = true; +#endif memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) @@ -751,7 +753,7 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) } else { - flt_rule_count_v4 += IPV4_DEFAULT_FILTERTING_RULES; + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES); /* copy filter hdls */ for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++) { @@ -792,7 +794,6 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; - /* Configuring Multicast Filtering Rule */ memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, @@ -806,6 +807,10 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.hashable = true; +#endif memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); /* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */ @@ -817,6 +822,10 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.hashable = true; +#endif memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); /* Configuring fec0::/10 Reserved by IETF Filtering Rule */ @@ -828,8 +837,27 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.hashable = true; +#endif memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + /* Configuring fd00::/8 Unique Local Ipv6 Address */ + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFD000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.hashable = true; +#endif + memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + #ifdef FEATURE_IPA_ANDROID IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES); memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); @@ -842,7 +870,6 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; flt_rule_entry.rule.eq_attrib_type = 1; - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0; if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA) @@ -865,17 +892,17 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) /* add TCP FIN rule*/ flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); /* add TCP SYN rule*/ flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); /* add TCP RST rule*/ flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + memcpy(&(m_pFilteringTable->rules[6]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); #endif if (m_filtering.AddFilteringRule(m_pFilteringTable) == false) { @@ -885,7 +912,7 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) } else { - flt_rule_count_v6 += IPV6_DEFAULT_FILTERTING_RULES; + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES); /* copy filter hdls */ for (int i = 0; i < IPV6_DEFAULT_FILTERTING_RULES; @@ -918,73 +945,79 @@ int IPACM_Iface::ipa_get_if_index int * if_index ) { - int fd; - struct ifreq ifr; - - if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { - IPACMERR("get interface index socket create failed \n"); - return IPACM_FAILURE; - } - - memset(&ifr, 0, sizeof(struct ifreq)); - (void)strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); - IPACMDBG_H("interface name (%s)\n", if_name); - - if (ioctl(fd,SIOCGIFINDEX , &ifr) < 0) - { - IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name); - close(fd); - return IPACM_FAILURE; - } - - *if_index = ifr.ifr_ifindex; - IPACMDBG_H("Interface index %d\n", *if_index); - close(fd); - return IPACM_SUCCESS; + int fd; + struct ifreq ifr; + + if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + IPACMERR("get interface index socket create failed \n"); + return IPACM_FAILURE; + } + + if(strlen(if_name) >= sizeof(ifr.ifr_name)) + { + IPACMERR("interface name overflows: len %d\n", strlen(if_name)); + close(fd); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + (void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); + IPACMDBG_H("interface name (%s)\n", if_name); + + if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0) + { + IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name); + close(fd); + return IPACM_FAILURE; + } + + *if_index = ifr.ifr_ifindex; + IPACMDBG_H("Interface index %d\n", *if_index); + close(fd); + return IPACM_SUCCESS; } -size_t IPACM_Iface::strlcpy(char *dest, const char *src, size_t n) +void IPACM_Iface::config_ip_type(ipa_ip_type iptype) { - size_t ret = strlen(src); - size_t len = 0; - if (n > 0) { - if(ret >= n) + /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/ + if (iptype == IPA_IP_v4) + { + if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX)) { - len = n-1; - IPACMERR(" overflow detected \n"); + IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); + return; } - else + + if (ip_type == IPA_IP_v6) { - len = ret; + ip_type = IPA_IP_MAX; } - dest[len] = '\0'; - memcpy(dest, src, len); - } - return ret; -} - -size_t IPACM_Iface::strlcat(char *dest, const char *src, size_t n) -{ - size_t dsize = strlen(dest); - size_t len = strlen(src); - size_t ret = dsize + len; - - if (dsize < n) - { - dest += dsize; - n -= dsize; - if (len >= n) + else { - len = n - 1; - IPACMERR(" overflow detected \n"); + ip_type = IPA_IP_v4; } - dest[len] = '\0'; - memcpy(dest, src, len); + IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); } else { - IPACMERR(" dest buffer full\n"); + if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX)) + { + IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); + return; + } + + if (ip_type == IPA_IP_v4) + { + ip_type = IPA_IP_MAX; + } + else + { + ip_type = IPA_IP_v6; + } + + IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); } - return ret; + + return; } diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp index fe1e5b10..eab43fd4 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -56,10 +56,12 @@ IPACM_IfaceManager::IPACM_IfaceManager() IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, this); // register for IPA_CFG_CHANGE event IPACM_EvtDispatcher::registr(IPA_LINK_UP_EVENT, this); IPACM_EvtDispatcher::registr(IPA_WLAN_AP_LINK_UP_EVENT, this); // register for wlan AP-iface -#ifndef FEATURE_IPA_ANDROID IPACM_EvtDispatcher::registr(IPA_WLAN_STA_LINK_UP_EVENT, this); // register for wlan STA-iface +#ifndef FEATURE_IPA_ANDROID + /* only MDM targets support device on bridge mode */ + IPACM_EvtDispatcher::registr(IPA_BRIDGE_LINK_UP_EVENT, this); // register for IPA_BRIDGE_LINK_UP_EVENT event #endif /* not defined(FEATURE_IPA_ANDROID)*/ - IPACM_EvtDispatcher::registr(IPA_USB_LINK_UP_EVENT, this); // register for wlan STA-iface + IPACM_EvtDispatcher::registr(IPA_USB_LINK_UP_EVENT, this); // register for USB-iface IPACM_EvtDispatcher::registr(IPA_WAN_EMBMS_LINK_UP_EVENT, this); // register for wan eMBMS-iface return; } @@ -69,6 +71,7 @@ void IPACM_IfaceManager::event_callback(ipa_cm_event_id event, void *param) int ipa_interface_index; ipacm_event_data_fid *evt_data = (ipacm_event_data_fid *)param; ipacm_event_data_mac *StaData = (ipacm_event_data_mac *)param; + ipacm_event_data_all *data_all = (ipacm_event_data_all *)param; ipacm_ifacemgr_data ifmgr_data = {0}; switch(event) @@ -77,9 +80,34 @@ void IPACM_IfaceManager::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H(" RESET IPACM_cfg \n"); IPACM_Iface::ipacmcfg->Init(); break; + case IPA_BRIDGE_LINK_UP_EVENT: + IPACMDBG_H(" Save the bridge0 mac info in IPACM_cfg \n"); + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("IPA_BRIDGE_LINK_UP_EVENT: not supported iface id: %d\n", data_all->if_index); + break; + } + /* check if iface is bridge interface*/ + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0) + { + IPACM_Iface::ipacmcfg->ipa_bridge_enable = true; + memcpy(IPACM_Iface::ipacmcfg->bridge_mac, + data_all->mac_addr, + sizeof(IPACM_Iface::ipacmcfg->bridge_mac)); + IPACMDBG_H("cached bridge0 MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + IPACM_Iface::ipacmcfg->bridge_mac[0], IPACM_Iface::ipacmcfg->bridge_mac[1], IPACM_Iface::ipacmcfg->bridge_mac[2], + IPACM_Iface::ipacmcfg->bridge_mac[3], IPACM_Iface::ipacmcfg->bridge_mac[4], IPACM_Iface::ipacmcfg->bridge_mac[5]); + } + break; case IPA_LINK_UP_EVENT: - IPACMDBG_H("link up %d: \n", evt_data->if_index); + IPACMDBG_H("Recieved IPA_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index); ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("IPA_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); + break; + } /* LTE-backhaul */ if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == EMBMS_IF) { @@ -95,7 +123,13 @@ void IPACM_IfaceManager::event_callback(ipa_cm_event_id event, void *param) break; case IPA_USB_LINK_UP_EVENT: + IPACMDBG_H("Recieved IPA_USB_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index); ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("IPA_USB_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); + break; + } /* check if it's WAN_IF */ if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) { @@ -115,6 +149,11 @@ void IPACM_IfaceManager::event_callback(ipa_cm_event_id event, void *param) case IPA_WLAN_AP_LINK_UP_EVENT: ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("IPA_WLAN_AP_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); + break; + } /* change iface category from unknown to WLAN_IF */ if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == UNKNOWN_IF) { @@ -132,6 +171,11 @@ void IPACM_IfaceManager::event_callback(ipa_cm_event_id event, void *param) case IPA_WLAN_STA_LINK_UP_EVENT: ipa_interface_index = IPACM_Iface::iface_ipa_index_query(StaData->if_index); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("IPA_WLAN_STA_LINK_UP_EVENT: not supported iface id: %d\n", StaData->if_index); + break; + } /* change iface category from unknown to WAN_IF */ if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == UNKNOWN_IF) { @@ -156,22 +200,27 @@ void IPACM_IfaceManager::event_callback(ipa_cm_event_id event, void *param) /* Add new instance open for eMBMS iface and wan iface */ case IPA_WAN_EMBMS_LINK_UP_EVENT: ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("IPA_WAN_EMBMS_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); + break; + } /* change iface category from unknown to EMBMS_IF */ - if (IPACM_Iface::ipacmcfg->ipacm_odu_enable == true) + if ((IPACM_Iface::ipacmcfg->ipacm_odu_enable == true) && (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true)) { IPACMDBG(" ODU-mode enable or not (%d) \n",IPACM_Iface::ipacmcfg->ipacm_odu_enable); - if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) - { - IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat=EMBMS_IF; - IPACMDBG("WAN eMBMS (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); - ifmgr_data.if_index = StaData->if_index; - ifmgr_data.if_type = Q6_WAN; - create_iface_instance(&ifmgr_data); - } - else - { - IPACMDBG("iface %s already up and act as %d mode: \n",IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); - } + if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) + { + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat=EMBMS_IF; + IPACMDBG("WAN eMBMS (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); + ifmgr_data.if_index = StaData->if_index; + ifmgr_data.if_type = Q6_WAN; + create_iface_instance(&ifmgr_data); + } + else + { + IPACMDBG("iface %s already up and act as %d mode: \n",IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); + } } break; @@ -210,7 +259,7 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) //IPACM_EvtDispatcher::registr(IPA_ROUTE_ADD_EVENT, lan); //IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, lan); IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, lan); - //IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, lan); IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, lan); IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, lan); #ifdef FEATURE_IPA_ANDROID @@ -218,6 +267,10 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6_TETHER, lan); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_TETHER, lan); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6_TETHER, lan); +#ifdef FEATURE_IPACM_HAL + IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_ADD, lan); + IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_DEL, lan); +#endif #else IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, lan); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, lan); @@ -226,16 +279,12 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) #endif IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, lan); // register for IPA_CFG_CHANGE event IPACM_EvtDispatcher::registr(IPA_PRIVATE_SUBNET_CHANGE_EVENT, lan); // register for IPA_PRIVATE_SUBNET_CHANGE_EVENT event -#ifdef FEATURE_ETH_BRIDGE_LE - IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT, lan); - IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT, lan); - IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT, lan); - IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, lan); -#endif #ifdef FEATURE_IPA_ANDROID IPACM_EvtDispatcher::registr(IPA_TETHERING_STATS_UPDATE_EVENT, lan); #endif + IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, lan); IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, lan); + /* IPA_LAN_DELETE_SELF should be always last */ IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, lan); IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", lan->dev_name, lan->ipa_if_num); registr(ipa_interface_index, lan); @@ -246,22 +295,24 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) case ETH_IF: { - IPACMDBG_H("Creating ETH interface in router mode\n"); - IPACM_Lan *ETH = new IPACM_Lan(ipa_interface_index); - IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, ETH); - IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, ETH); - IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, ETH); - IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, ETH); - IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, ETH); - IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, ETH); - IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, ETH); - IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, ETH); - IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, ETH); - IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, ETH); - IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", ETH->dev_name, ETH->ipa_if_num); - registr(ipa_interface_index, ETH); - /* solve the new_addr comes earlier issue */ - IPACM_Iface::iface_addr_query(if_index); + IPACMDBG_H("Creating ETH interface in router mode\n"); + IPACM_Lan *ETH = new IPACM_Lan(ipa_interface_index); + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, ETH); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, ETH); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, ETH); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, ETH); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, ETH); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, ETH); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, ETH); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, ETH); + IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, ETH); + IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, ETH); + /* IPA_LAN_DELETE_SELF should be always last */ + IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, ETH); + IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", ETH->dev_name, ETH->ipa_if_num); + registr(ipa_interface_index, ETH); + /* solve the new_addr comes earlier issue */ + IPACM_Iface::iface_addr_query(if_index); } break; @@ -269,34 +320,38 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) { if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true) { - IPACMDBG("Creating ODU interface in router mode\n"); + IPACMDBG_H("Creating ODU interface in router mode\n"); IPACM_Lan *odu = new IPACM_Lan(ipa_interface_index); IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, odu); IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, odu); IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, odu); IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, odu); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, odu); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, odu); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, odu); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, odu); + IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, odu); IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, odu); + /* IPA_LAN_DELETE_SELF should be always last */ IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, odu); - IPACMDBG("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", odu->dev_name, odu->ipa_if_num); + IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", odu->dev_name, odu->ipa_if_num); registr(ipa_interface_index, odu); /* solve the new_addr comes earlier issue */ IPACM_Iface::iface_addr_query(if_index); } else { - IPACMDBG("Creating ODU interface in bridge mode\n"); + IPACMDBG_H("Creating ODU interface in bridge mode\n"); IPACM_Lan *odu = new IPACM_Lan(ipa_interface_index); IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, odu); IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, odu); IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, odu); IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, odu); IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, odu); + /* IPA_LAN_DELETE_SELF should be always last */ IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, odu); - IPACMDBG("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", odu->dev_name, odu->ipa_if_num); + IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", odu->dev_name, odu->ipa_if_num); registr(ipa_interface_index, odu); /* solve the new_addr comes earlier issue */ IPACM_Iface::iface_addr_query(if_index); @@ -323,6 +378,10 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6_TETHER, wl); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_TETHER, wl); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6_TETHER, wl); +#ifdef FEATURE_IPACM_HAL + IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_ADD, wl); + IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_DEL, wl); +#endif #else IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, wl); IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, wl); @@ -331,20 +390,22 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) #endif IPACM_EvtDispatcher::registr(IPA_PRIVATE_SUBNET_CHANGE_EVENT, wl); // register for IPA_PRIVATE_SUBNET_CHANGE_EVENT event #ifdef FEATURE_ETH_BRIDGE_LE - IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_USB_CLIENT_ADD_EVENT, wl); - IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_USB_CLIENT_DEL_EVENT, wl); - IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT, wl); - IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, wl); #endif + IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, wl); IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, wl); - IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, wl); -#ifdef FEATURE_IPA_ANDROID +#ifndef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_SCC, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_MCC, wl); +#else IPACM_EvtDispatcher::registr(IPA_TETHERING_STATS_UPDATE_EVENT, wl); #endif + /* IPA_LAN_DELETE_SELF should be always last */ + IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, wl); IPACMDBG_H("ipa_WLAN (%s):ipa_index (%d) instance open/registr ok\n", wl->dev_name, wl->ipa_if_num); registr(ipa_interface_index, wl); /* solve the new_addr comes earlier issue */ - IPACM_Iface::iface_addr_query(if_index); + IPACM_Iface::iface_addr_query(if_index); } break; @@ -379,18 +440,24 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, w); IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, w); IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, w); // register for IPA_CFG_CHANGE event + IPACM_EvtDispatcher::registr(IPA_WAN_XLAT_CONNECT_EVENT, w); if(is_sta_mode == WLAN_WAN) { IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, w); // for STA mode +#ifndef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_SCC, w); + IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_MCC, w); +#endif } else { IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, w); } + IPACMDBG_H("ipa_WAN (%s):ipa_index (%d) instance open/registr ok\n", w->dev_name, w->ipa_if_num); registr(ipa_interface_index, w); /* solve the new_addr comes earlier issue */ - IPACM_Iface::iface_addr_query(if_index); + IPACM_Iface::iface_addr_query(if_index); } } break; diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp index 4b36c424..33ee4e81 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -55,22 +55,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. bool IPACM_Lan::odu_up = false; -ipa_hdr_l2_type IPACM_Lan::usb_hdr_type = IPA_HDR_L2_NONE; -ipa_hdr_l2_type IPACM_Lan::wlan_hdr_type = IPA_HDR_L2_NONE; - -uint32_t IPACM_Lan::usb_hdr_template_hdl = 0; -uint32_t IPACM_Lan::wlan_hdr_template_hdl = 0; - -hdr_proc_ctx_info IPACM_Lan::usb_to_wlan_hdr_proc_ctx; -hdr_proc_ctx_info IPACM_Lan::wlan_to_usb_hdr_proc_ctx; -hdr_proc_ctx_info IPACM_Lan::wlan_to_wlan_hdr_proc_ctx; - -eth_bridge_subnet_client_info IPACM_Lan::eth_bridge_wlan_client[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; -eth_bridge_subnet_client_info IPACM_Lan::eth_bridge_usb_client[IPA_LAN_TO_LAN_MAX_USB_CLIENT]; - -int IPACM_Lan::num_wlan_client = 0; -int IPACM_Lan::num_usb_client = 0; - IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) { num_eth_client = 0; @@ -81,7 +65,7 @@ IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) odu_route_rule_v4_hdl = NULL; odu_route_rule_v6_hdl = NULL; eth_client = NULL; - int m_fd_odu, ret = IPACM_SUCCESS; + int i, m_fd_odu, ret = IPACM_SUCCESS; Nat_App = NatApp::GetInstance(); if (Nat_App == NULL) @@ -90,46 +74,40 @@ IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) return; } + num_wan_ul_fl_rule_v4 = 0; + num_wan_ul_fl_rule_v6 = 0; + is_active = true; + modem_ul_v4_set = false; + modem_ul_v6_set = false; + + sta_ul_v4_set = false; + sta_ul_v6_set = false; + + is_mode_switch = false; + if_ipv4_subnet =0; + each_client_rt_rule_count[IPA_IP_v4] = 0; + each_client_rt_rule_count[IPA_IP_v6] = 0; + eth_client_len = 0; + /* support eth multiple clients */ if(iface_query != NULL) { - - if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != WLAN_IF) - { - eth_client_len = (sizeof(ipa_eth_client)) + (iface_query->num_tx_props * sizeof(eth_client_rt_hdl)); - eth_client = (ipa_eth_client *)calloc(IPA_MAX_NUM_ETH_CLIENTS, eth_client_len); - if (eth_client == NULL) - { - IPACMERR("unable to allocate memory\n"); - return; - } - } - - IPACMDBG_H(" IPACM->IPACM_Lan(%d) constructor: Tx:%d Rx:%d\n", ipa_if_num, - iface_query->num_tx_props, iface_query->num_rx_props); -#ifdef FEATURE_ETH_BRIDGE_LE - if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF && tx_prop != NULL) + if(ipa_if_cate != WLAN_IF) { - if(IPACM_Lan::usb_hdr_type != IPA_HDR_L2_NONE && tx_prop->tx[0].hdr_l2_type != IPACM_Lan::usb_hdr_type) - { - IPACMERR("The USB header format is not consistent! Now header format is %d.\n", tx_prop->tx[0].hdr_l2_type); - } - else + eth_client_len = (sizeof(ipa_eth_client)) + (iface_query->num_tx_props * sizeof(eth_client_rt_hdl)); + eth_client = (ipa_eth_client *)calloc(IPA_MAX_NUM_ETH_CLIENTS, eth_client_len); + if (eth_client == NULL) { - if(eth_bridge_get_hdr_template_hdl(&IPACM_Lan::usb_hdr_template_hdl) == IPACM_FAILURE) - { - IPACMERR("Failed to setup usb hdr template.\n"); - } - else - { - IPACM_Lan::usb_hdr_type = tx_prop->tx[0].hdr_l2_type; - add_hdr_proc_ctx(); - } + IPACMERR("unable to allocate memory\n"); + return; } } -#endif + + IPACMDBG_H(" IPACM->IPACM_Lan(%d) constructor: Tx:%d Rx:%d \n", ipa_if_num, + iface_query->num_tx_props, iface_query->num_rx_props); + /* ODU routing table initilization */ - if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + if(ipa_if_cate == ODU_IF) { odu_route_rule_v4_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); odu_route_rule_v6_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); @@ -141,39 +119,19 @@ IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) } } - num_wan_ul_fl_rule_v4 = 0; - num_wan_ul_fl_rule_v6 = 0; - memset(wan_ul_fl_rule_hdl_v4, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); memset(wan_ul_fl_rule_hdl_v6, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); - memset(lan2lan_flt_rule_hdl_v4, 0, MAX_OFFLOAD_PAIR * sizeof(lan2lan_flt_rule_hdl)); - num_lan2lan_flt_rule_v4 = 0; + memset(ipv4_icmp_flt_rule_hdl, 0, NUM_IPV4_ICMP_FLT_RULE * sizeof(uint32_t)); - memset(lan2lan_flt_rule_hdl_v6, 0, MAX_OFFLOAD_PAIR * sizeof(lan2lan_flt_rule_hdl)); - num_lan2lan_flt_rule_v6 = 0; - - memset(lan2lan_hdr_hdl_v4, 0, MAX_OFFLOAD_PAIR*sizeof(lan2lan_hdr_hdl)); - memset(lan2lan_hdr_hdl_v6, 0, MAX_OFFLOAD_PAIR*sizeof(lan2lan_hdr_hdl)); - - memset(wlan_client_flt_rule_hdl_v4, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); - memset(wlan_client_flt_rule_hdl_v6, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); - - is_active = true; - memset(tcp_ctl_flt_rule_hdl_v4, 0, NUM_TCP_CTL_FLT_RULE*sizeof(uint32_t)); - memset(tcp_ctl_flt_rule_hdl_v6, 0, NUM_TCP_CTL_FLT_RULE*sizeof(uint32_t)); - is_mode_switch = false; - if_ipv4_subnet =0; memset(private_fl_rule_hdl, 0, IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(uint32_t)); memset(ipv6_prefix_flt_rule_hdl, 0, NUM_IPV6_PREFIX_FLT_RULE * sizeof(uint32_t)); memset(ipv6_icmp_flt_rule_hdl, 0, NUM_IPV6_ICMP_FLT_RULE * sizeof(uint32_t)); - modem_ul_v4_set = false; - modem_ul_v6_set = false; + memset(ipv6_prefix, 0, sizeof(ipv6_prefix)); /* ODU routing table initilization */ - if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + if(ipa_if_cate == ODU_IF) { - /* only do one time ioctl to odu-driver to infrom in router or bridge mode*/ if (IPACM_Lan::odu_up != true) { @@ -200,53 +158,34 @@ IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) IPACMERR("Failed tell odu-driver the mode\n"); } IPACMDBG("Tell odu-driver in router-mode(%d)\n", IPACM_Iface::ipacmcfg->ipacm_odu_router_mode); + IPACMDBG_H("odu is up: odu-driver in router-mode(%d) \n", IPACM_Iface::ipacmcfg->ipacm_odu_router_mode); close(m_fd_odu); IPACM_Lan::odu_up = true; } } - int i; - each_client_rt_rule_count_v4 = 0; - each_client_rt_rule_count_v6 = 0; if(iface_query != NULL && tx_prop != NULL) { for(i=0; inum_tx_props; i++) - { - if(tx_prop->tx[i].ip == IPA_IP_v4) - { - each_client_rt_rule_count_v4++; - } - else - { - each_client_rt_rule_count_v6++; - } - } - } - IPACMDBG_H("Need to add %d IPv4 and %d IPv6 routing rules for eth bridge for each client.\n", each_client_rt_rule_count_v4, each_client_rt_rule_count_v6); - - memset(eth_bridge_wlan_client_flt_info, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(eth_bridge_client_flt_info)); - wlan_client_flt_info_count = 0; - eth_bridge_usb_client_rt_info_v4 = NULL; - eth_bridge_usb_client_rt_info_v6 = NULL; -#ifdef FEATURE_ETH_BRIDGE_LE - if(tx_prop != NULL) - { - client_rt_info_size_v4 = sizeof(eth_bridge_client_rt_info) + each_client_rt_rule_count_v4 * sizeof(uint32_t); - eth_bridge_usb_client_rt_info_v4 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_USB_CLIENT, client_rt_info_size_v4); - client_rt_info_size_v6 = sizeof(eth_bridge_client_rt_info) + each_client_rt_rule_count_v6 * sizeof(uint32_t); - eth_bridge_usb_client_rt_info_v6 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_USB_CLIENT, client_rt_info_size_v6); + each_client_rt_rule_count[tx_prop->tx[i].ip]++; } -#endif - usb_client_rt_info_count_v4 = 0; - usb_client_rt_info_count_v6 = 0; + IPACMDBG_H("Need to add %d IPv4 and %d IPv6 routing rules for eth bridge for each client.\n", each_client_rt_rule_count[IPA_IP_v4], each_client_rt_rule_count[IPA_IP_v6]); #ifdef FEATURE_IPA_ANDROID /* set the IPA-client pipe enum */ - if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + if(ipa_if_cate == LAN_IF) { +#ifdef FEATURE_IPACM_HAL + handle_tethering_client(false, IPACM_CLIENT_MAX); +#else handle_tethering_client(false, IPACM_CLIENT_USB); +#endif } #endif + + memset(is_downstream_set, 0, sizeof(is_downstream_set)); + memset(is_upstream_set, 0, sizeof(is_upstream_set)); + memset(&prefix, 0, sizeof(prefix)); return; } @@ -299,6 +238,12 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) is_mode_switch = true; // need post internal usb-link up event return; } + /* Add Natting iface to IPACM_Config if there is Rx/Tx property */ + if (rx_prop != NULL || tx_prop != NULL) + { + IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name); + IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name); + } } break; @@ -353,6 +298,21 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) //IPACMDBG_H("Posting event:%d\n", evt_data.event); IPACM_EvtDispatcher::PostEvt(&evt_data); } +#ifndef FEATURE_IPA_ANDROID + if(rx_prop != NULL) + { + if(IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4) != 0) + { + IPACMDBG_DMESG("### WARNING ### num ipv4 flt rules on client %d is not expected: %d expected value: 0", + rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4)); + } + if(IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6) != 0) + { + IPACMDBG_DMESG("### WARNING ### num ipv6 flt rules on client %d is not expected: %d expected value: 0", + rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6)); + } + } +#endif delete this; } break; @@ -371,15 +331,21 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n"); return; } - - +#ifdef FEATURE_L2TP + if(data->iptype == IPA_IP_v6 && is_vlan_event(data->iface_name) && is_unique_local_ipv6_addr(data->ipv6_addr)) + { + IPACMDBG_H("Got IPv6 new addr event for a vlan iface %s.\n", data->iface_name); + eth_bridge_post_event(IPA_HANDLE_VLAN_IFACE_INFO, data->iptype, NULL, + data->ipv6_addr, data->iface_name); + } +#endif if (ipa_interface_index == ipa_if_num) { IPACMDBG_H("Received IPA_ADDR_ADD_EVENT\n"); /* only call ioctl for ODU iface with bridge mode */ - if((IPACM_Iface::ipacmcfg->ipacm_odu_enable == true) && (IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false) - && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF)) + if(IPACM_Iface::ipacmcfg->ipacm_odu_enable == true && IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false + && ipa_if_cate == ODU_IF) { if((data->iptype == IPA_IP_v6) && (num_dft_rt_v6 == 0)) { @@ -400,16 +366,17 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES))) { IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); - /* ADD ipv6 icmp rule */ - if ((num_dft_rt_v6 == 0) && (data->iptype == IPA_IP_v6)) - { - install_ipv6_icmp_flt_rule(); - } if(handle_addr_evt(data) == IPACM_FAILURE) { return; } + +#ifdef FEATURE_IPA_ANDROID + add_dummy_private_subnet_flt_rule(data->iptype); + handle_private_subnet_android(data->iptype); +#else handle_private_subnet(data->iptype); +#endif if (IPACM_Wan::isWanUP(ipa_if_num)) { @@ -418,30 +385,38 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) if(IPACM_Wan::backhaul_is_sta_mode == false) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); - handle_wan_up_ex(ext_prop, IPA_IP_v4); + handle_wan_up_ex(ext_prop, IPA_IP_v4, + IPACM_Wan::getXlat_Mux_Id()); } else { handle_wan_up(IPA_IP_v4); } } + IPACMDBG_H("Finished checking wan_up\n"); + } else { + IPACMDBG_H("Wan_V4 haven't up yet\n"); } if(IPACM_Wan::isWanUP_V6(ipa_if_num)) { if((data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX) && num_dft_rt_v6 == 1) { + memcpy(ipv6_prefix, IPACM_Wan::backhaul_ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); if(IPACM_Wan::backhaul_is_sta_mode == false) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); - handle_wan_up_ex(ext_prop, IPA_IP_v6); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); } else { handle_wan_up(IPA_IP_v6); } } + IPACMDBG_H("Finished checking wan_up_v6\n"); + } else { + IPACMDBG_H("Wan_V6 haven't up yet\n"); } /* Post event to NAT */ @@ -500,20 +475,41 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); - if (data_wan_tether->if_index_tether == ipa_if_num) +#ifndef FEATURE_IPACM_HAL + if (data_wan_tether->if_index_tether != ipa_if_num) + { + IPACMERR("IPA_HANDLE_WAN_UP_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); + return; + } +#endif + if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { - if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) +#ifdef FEATURE_IPACM_HAL + if (is_upstream_set[IPA_IP_v4] == false) { - if(data_wan_tether->is_sta == false) + IPACMDBG_H("Add upstream for IPv4.\n"); + is_upstream_set[IPA_IP_v4] = true; + if (is_downstream_set[IPA_IP_v4] == true) { - ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); - handle_wan_up_ex(ext_prop, IPA_IP_v4); + IPACMDBG_H("Downstream was set before, adding UL rules.\n"); + if (data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + handle_wan_up_ex(ext_prop, IPA_IP_v4, 0); + } else { + handle_wan_up(IPA_IP_v4); + } } - else - { + } +#else + if (data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + handle_wan_up_ex(ext_prop, IPA_IP_v4, 0); + } else { handle_wan_up(IPA_IP_v4); - } } +#endif } break; @@ -521,7 +517,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6_TETHER event\n"); data_wan_tether = (ipacm_event_iface_up_tehter*)param; - if(data_wan_tether == NULL) + if (data_wan_tether == NULL) { IPACMERR("No event data is found.\n"); return; @@ -529,28 +525,53 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); - if (data_wan_tether->if_index_tether == ipa_if_num) +#ifndef FEATURE_IPACM_HAL + if (data_wan_tether->if_index_tether != ipa_if_num) + { + IPACMERR("IPA_HANDLE_WAN_UP_V6_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); + return; + } +#endif + if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { - if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) +#ifdef FEATURE_IPACM_HAL + if (is_upstream_set[IPA_IP_v6] == false) { + IPACMDBG_H("Add upstream for IPv6.\n"); + is_upstream_set[IPA_IP_v6] = true; + + if (is_downstream_set[IPA_IP_v6] == true) + { + IPACMDBG_H("Downstream was set before, adding UL rules.\n"); + memcpy(ipv6_prefix, data_wan_tether->ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(data_wan_tether->ipv6_prefix); - if(data_wan_tether->is_sta == false) + if (data_wan_tether->is_sta == false) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); - handle_wan_up_ex(ext_prop, IPA_IP_v6); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); } else { handle_wan_up(IPA_IP_v6); } + } + } +#else + if (data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } else { + handle_wan_up(IPA_IP_v6); } +#endif } break; case IPA_HANDLE_WAN_DOWN_TETHER: IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_TETHER event\n"); data_wan_tether = (ipacm_event_iface_up_tehter*)param; - if(data_wan_tether == NULL) + if (data_wan_tether == NULL) { IPACMERR("No event data is found.\n"); return; @@ -558,12 +579,29 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); - if (data_wan_tether->if_index_tether == ipa_if_num) +#ifndef FEATURE_IPACM_HAL + if (data_wan_tether->if_index_tether != ipa_if_num) + { + IPACMERR("IPA_HANDLE_WAN_DOWN_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); + return; + } +#endif + if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { - if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) +#ifdef FEATURE_IPACM_HAL + if(is_upstream_set[IPA_IP_v4] == true) { - handle_wan_down(data_wan_tether->is_sta); + IPACMDBG_H("Del upstream for IPv4.\n"); + is_upstream_set[IPA_IP_v4] = false; + if(is_downstream_set[IPA_IP_v4] == true) + { + IPACMDBG_H("Downstream was set before, deleting UL rules.\n"); + handle_wan_down(data_wan_tether->is_sta); + } } +#else + handle_wan_down(data_wan_tether->is_sta); +#endif } break; @@ -578,37 +616,120 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); - if (data_wan_tether->if_index_tether == ipa_if_num) +#ifndef FEATURE_IPACM_HAL + if (data_wan_tether->if_index_tether != ipa_if_num) + { + IPACMERR("IPA_HANDLE_WAN_DOWN_V6_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); + return; + } +#endif + if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { - /* clean up v6 RT rules*/ - IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6_TETHER in LAN-instance and need clean up client IPv6 address \n"); +#ifdef FEATURE_IPACM_HAL + if (is_upstream_set[IPA_IP_v6] == true) + { + IPACMDBG_H("Del upstream for IPv6.\n"); + is_upstream_set[IPA_IP_v6] = false; + if(is_downstream_set[IPA_IP_v6] == true) + { + IPACMDBG_H("Downstream was set before, deleting UL rules.\n"); + /* reset usb-client ipv6 rt-rules */ + handle_lan_client_reset_rt(IPA_IP_v6); + handle_wan_down_v6(data_wan_tether->is_sta); + } + } +#else /* reset usb-client ipv6 rt-rules */ handle_lan_client_reset_rt(IPA_IP_v6); + handle_wan_down_v6(data_wan_tether->is_sta); +#endif + } + break; + + case IPA_DOWNSTREAM_ADD: + { + ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_DOWNSTREAM_ADD event.\n"); + if (is_downstream_set[data->prefix.iptype] == false) + { + IPACMDBG_H("Add downstream for IP iptype %d\n", data->prefix.iptype); + is_downstream_set[data->prefix.iptype] = true; + memcpy(&prefix[data->prefix.iptype], &data->prefix, + sizeof(prefix[data->prefix.iptype])); + + if (is_upstream_set[data->prefix.iptype] == true) + { + IPACMDBG_H("Upstream was set before, adding UL rules.\n"); + if (ip_type == IPA_IP_MAX || ip_type == data->prefix.iptype) + { + if (data->prefix.iptype == IPA_IP_v6) /* ipv6 only */ + install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); + + if (IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */ + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(data->prefix.iptype); + handle_wan_up_ex(ext_prop, data->prefix.iptype, 0); + } else { + handle_wan_up(data->prefix.iptype); /* STA */ + } + } + } + } else { + IPACMDBG_H("downstream for IP iptype %d already set \n", data->prefix.iptype); + } + } + break; + } - if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + case IPA_DOWNSTREAM_DEL: + { + ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_DOWNSTREAM_DEL event.\n"); + if (is_downstream_set[data->prefix.iptype] == true) { - handle_wan_down_v6(data_wan_tether->is_sta); + IPACMDBG_H("Del downstream for IP iptype %d.\n", data->prefix.iptype); + is_downstream_set[data->prefix.iptype] = false; + + if (is_upstream_set[data->prefix.iptype] == true) + { + IPACMDBG_H("Upstream was set before, deleting UL rules.\n"); + if (data->prefix.iptype == IPA_IP_v4) + { + handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */ + } else { + handle_lan_client_reset_rt(IPA_IP_v6); + handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */ + } + } } } break; + } + #else case IPA_HANDLE_WAN_UP: IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); data_wan = (ipacm_event_iface_up*)param; - if(data_wan == NULL) + if (data_wan == NULL) { IPACMERR("No event data is found.\n"); return; } IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); - if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { - if(data_wan->is_sta == false) + if (data_wan->is_sta == false) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); - handle_wan_up_ex(ext_prop, IPA_IP_v4); - } + handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan->xlat_mux_id); + } else { handle_wan_up(IPA_IP_v4); @@ -620,37 +741,38 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6 event\n"); data_wan = (ipacm_event_iface_up*)param; - if(data_wan == NULL) + if (data_wan == NULL) { IPACMERR("No event data is found.\n"); return; } IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); - if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { + memcpy(ipv6_prefix, data_wan->ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix); - if(data_wan->is_sta == false) - { + if (data_wan->is_sta == false) + { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); - handle_wan_up_ex(ext_prop, IPA_IP_v6); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + handle_wan_up(IPA_IP_v6); } - else - { - handle_wan_up(IPA_IP_v6); - } } break; case IPA_HANDLE_WAN_DOWN: IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n"); data_wan = (ipacm_event_iface_up*)param; - if(data_wan == NULL) + if (data_wan == NULL) { IPACMERR("No event data is found.\n"); return; } IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); - if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { handle_wan_down(data_wan->is_sta); } @@ -659,7 +781,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) case IPA_HANDLE_WAN_DOWN_V6: IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6 event\n"); data_wan = (ipacm_event_iface_up*)param; - if(data_wan == NULL) + if (data_wan == NULL) { IPACMERR("No event data is found.\n"); return; @@ -670,7 +792,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) handle_lan_client_reset_rt(IPA_IP_v6); IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); - if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { handle_wan_down_v6(data_wan->is_sta); } @@ -681,52 +803,74 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) { ipacm_event_data_all *data = (ipacm_event_data_all *)param; ipa_interface_index = iface_ipa_index_query(data->if_index); - IPACMDBG_H("check iface %s category: %d\n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat); + IPACMDBG_H("Recieved IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event \n"); + IPACMDBG_H("check iface %s category: %d\n", dev_name, ipa_if_cate); - if ((ipa_interface_index == ipa_if_num) && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF)) + if (ipa_interface_index == ipa_if_num && ipa_if_cate == ODU_IF) { - IPACMDBG("ODU iface got v4-ip \n"); + IPACMDBG_H("ODU iface got v4-ip \n"); /* first construc ODU full header */ if ((ipv4_header_set == false) && (ipv6_header_set == false)) { + /* construct ODU RT tbl */ handle_odu_hdr_init(data->mac_addr); - handle_odu_route_add(); /* construct ODU RT tbl*/ - IPACMDBG("construct ODU header and route rules \n"); + if (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true) + { + handle_odu_route_add(); + IPACMDBG_H("construct ODU header and route rules, embms_flag (%d) \n", IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable); + } + else + { + IPACMDBG_H("construct ODU header only, embms_flag (%d) \n", IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable); + } } /* if ODU in bridge mode, directly return */ if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false) { - return; + IPACMDBG_H("ODU is in bridge mode, no action \n"); + return; } - } - if (ipa_interface_index == ipa_if_num) + if (ipa_interface_index == ipa_if_num || is_vlan_event(data->iface_name) + || (is_l2tp_event(data->iface_name) && ipa_if_cate == ODU_IF)) { IPACMDBG_H("ETH iface got client \n"); - /* first construc ETH full header */ - handle_eth_hdr_init(data->mac_addr); - handle_lan2lan_client_active(data, IPA_LAN_CLIENT_ACTIVE); - IPACMDBG_H("construct ETH header and route rules \n"); - /* Associate with IP and construct RT-rule */ - if (handle_eth_client_ipaddr(data) == IPACM_FAILURE) + if(ipa_interface_index == ipa_if_num) { - return; + /* first construc ETH full header */ + handle_eth_hdr_init(data->mac_addr); + IPACMDBG_H("construct ETH header and route rules \n"); + /* Associate with IP and construct RT-rule */ + if (handle_eth_client_ipaddr(data) == IPACM_FAILURE) + { + return; + } + handle_eth_client_route_rule(data->mac_addr, data->iptype); + if (data->iptype == IPA_IP_v4) + { + /* Add NAT rules after ipv4 RT rules are set */ + CtList->HandleNeighIpAddrAddEvt(data); + } + eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name); } - handle_eth_client_route_rule(data->mac_addr, data->iptype); - if (data->iptype == IPA_IP_v4) +#ifdef FEATURE_L2TP + else if(is_l2tp_event(data->iface_name) && ipa_if_cate == ODU_IF) { - /* Add NAT rules after ipv4 RT rules are set */ - CtList->HandleNeighIpAddrAddEvt(data); + if(tx_prop != NULL) + { + IPACMDBG_H("add rm dependency for L2TP interface.\n"); + IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); + } + eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name); } -#ifdef FEATURE_ETH_BRIDGE_LE - if(IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == true) + else { - eth_bridge_add_usb_client_rt_rule(data->mac_addr, IPA_IP_v4); - eth_bridge_add_usb_client_rt_rule(data->mac_addr, IPA_IP_v6); + if(data->iptype == IPA_IP_v6 && is_unique_local_ipv6_addr(data->ipv6_addr)) + { + eth_bridge_post_event(IPA_HANDLE_VLAN_CLIENT_INFO, IPA_IP_MAX, data->mac_addr, data->ipv6_addr, data->iface_name); + } } - eth_bridge_post_lan_client_event(data->mac_addr, IPA_ETH_BRIDGE_USB_CLIENT_ADD_EVENT); - eth_bridge_add_usb_client(data->mac_addr); #endif return; } @@ -738,12 +882,32 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) ipacm_event_data_all *data = (ipacm_event_data_all *)param; ipa_interface_index = iface_ipa_index_query(data->if_index); - IPACMDBG_H("check iface %s category: %d\n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat); - if (ipa_interface_index == ipa_if_num) + IPACMDBG_H("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event. \n"); + IPACMDBG_H("check iface %s category: %d\n", dev_name, ipa_if_cate); + /* if ODU in bridge mode, directly return */ + if (ipa_if_cate == ODU_IF && IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false) + { + IPACMDBG_H("ODU is in bridge mode, no action \n"); + return; + } + + if (ipa_interface_index == ipa_if_num + || (is_l2tp_event(data->iface_name) && ipa_if_cate == ODU_IF)) { - IPACMDBG_H("ETH iface delete client \n"); - handle_eth_client_down_evt(data->mac_addr); - handle_lan2lan_client_active(data, IPA_LAN_CLIENT_INACTIVE); + if(ipa_interface_index == ipa_if_num) + { + if (data->iptype == IPA_IP_v6) + { + handle_del_ipv6_addr(data); + return; + } + IPACMDBG_H("LAN iface delete client \n"); + handle_eth_client_down_evt(data->mac_addr); + } + else + { + eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name); + } return; } } @@ -761,89 +925,23 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) handle_software_routing_disable(); break; - case IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT: - { - IPACMDBG_H("Received IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT event.\n"); - ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; - if(mac != NULL) - { - if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) - { - eth_bridge_add_wlan_client_flt_rule(mac->mac_addr, IPA_IP_v4); - } - if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) - { - eth_bridge_add_wlan_client_flt_rule(mac->mac_addr, IPA_IP_v6); - } - } - else - { - IPACMERR("Event MAC is empty.\n"); - } - } - break; - - case IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT: - { - IPACMDBG_H("Received IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT event.\n"); - ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; - if(mac != NULL) - { - if(eth_bridge_del_wlan_client_flt_rule(mac->mac_addr) == IPACM_FAILURE) - { - IPACMDBG_H("Failed to delete wlan client MAC based flt rule.\n"); - } - } - else - { - IPACMERR("Event MAC is empty.\n"); - } - } - break; - - case IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT: + case IPA_CRADLE_WAN_MODE_SWITCH: { - IPACMDBG_H("Received IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT event.\n"); - int i; - ipacm_event_data_fid* fid = (ipacm_event_data_fid*)param; - if(fid == NULL) + IPACMDBG_H("Received IPA_CRADLE_WAN_MODE_SWITCH event.\n"); + ipacm_event_cradle_wan_mode* wan_mode = (ipacm_event_cradle_wan_mode*)param; + if(wan_mode == NULL) { IPACMERR("Event data is empty.\n"); return; } - if(fid->if_index == ipa_if_num) - { - IPACMDBG_H("The event was sent by the same interface, ignore.\n"); - return; - } - - for(i=0; icradle_wan_mode == BRIDGE) { - IPACMERR("Event data is empty.\n"); - return; - } - if(fid->if_index == ipa_if_num) - { - IPACMDBG_H("The event was sent by the same interface, ignore.\n"); - return; + handle_cradle_wan_mode_switch(true); } - - for(i=0; imac_addr); + if (clnt_indx == IPACM_INVALID_INDEX) { - IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + IPACMERR("eth client not found/attached \n"); return IPACM_FAILURE; } -#ifdef FEATURE_ETH_BRIDGE_LE - flt_rule_count_v4 = IPV4_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; -#else -#ifdef CT_OPT - flt_rule_count_v4 = IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR - + NUM_TCP_CTL_FLT_RULE + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; -#else - flt_rule_count_v4 = IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR - + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; -#endif -#ifdef FEATURE_IPA_ANDROID - flt_rule_count_v4 = flt_rule_count_v4 - IPACM_Iface::ipacmcfg->ipa_num_private_subnet + IPA_MAX_PRIVATE_SUBNET_ENTRIES; -#endif -#endif - if(is_sta_mode == false) + if(data->iptype == IPA_IP_v6) + { + if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) || + (data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) + { + IPACMDBG_H("ipv6 address got: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + for(num_v6=0;num_v6 < get_client_memptr(eth_client, clnt_indx)->ipv6_set;num_v6++) + { + if( data->ipv6_addr[0] == get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][0] && + data->ipv6_addr[1] == get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][1] && + data->ipv6_addr[2]== get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][2] && + data->ipv6_addr[3] == get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][3]) + { + IPACMDBG_H("ipv6 addr is found at position:%d for client:%d\n", num_v6, clnt_indx); + break; + } + } + } + if (num_v6 == IPV6_NUM_ADDR) + { + IPACMDBG_H("ipv6 addr is not found. \n"); + return IPACM_FAILURE; + } + + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if((tx_prop->tx[tx_index].ip == IPA_IP_v6) && (get_client_memptr(eth_client, clnt_indx)->route_rule_set_v6 != 0)) + { + IPACMDBG_H("Delete client index %d ipv6 RT-rules for %d-st ipv6 for tx:%d\n", clnt_indx, num_v6, tx_index); + rt_hdl = get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + rt_hdl = get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + get_client_memptr(eth_client, clnt_indx)->ipv6_set--; + get_client_memptr(eth_client, clnt_indx)->route_rule_set_v6--; + + for(num_v6;num_v6< get_client_memptr(eth_client, clnt_indx)->ipv6_set;num_v6++) + { + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][0] = + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][0]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][1] = + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][1]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][2] = + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][2]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][3] = + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][3]; + get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6] = + get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6+1]; + get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6] = + get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6+1]; + } + } + } + } + return IPACM_SUCCESS; +} + +/* delete filter rule for wan_down event for IPv4*/ +int IPACM_Lan::handle_wan_down(bool is_sta_mode) +{ + ipa_fltr_installed_notif_req_msg_v01 flt_index; + int fd; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (0 == fd) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + if(is_sta_mode == false) { if (num_wan_ul_fl_rule_v4 > MAX_WAN_UL_FILTER_RULES) { @@ -919,6 +1080,7 @@ int IPACM_Lan::handle_wan_down(bool is_sta_mode) close(fd); return IPACM_FAILURE; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, num_wan_ul_fl_rule_v4); memset(wan_ul_fl_rule_hdl_v4, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); num_wan_ul_fl_rule_v4 = 0; @@ -927,7 +1089,12 @@ int IPACM_Lan::handle_wan_down(bool is_sta_mode) memset(&flt_index, 0, sizeof(flt_index)); flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; +#ifndef FEATURE_IPA_V3 flt_index.filter_index_list_len = 0; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id_valid = 1; + flt_index.rule_id_len = 0; +#endif flt_index.embedded_pipe_index_valid = 1; flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); flt_index.retain_header_valid = 1; @@ -950,6 +1117,8 @@ int IPACM_Lan::handle_wan_down(bool is_sta_mode) close(fd); return IPACM_FAILURE; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + sta_ul_v4_set = false; } close(fd); @@ -969,18 +1138,21 @@ int IPACM_Lan::handle_addr_evt(ipacm_event_data_addr *data) /* Add private subnet*/ #ifdef FEATURE_IPA_ANDROID -if (data->iptype == IPA_IP_v4) -{ - IPACMDBG_H("current IPACM private subnet_addr number(%d)\n", IPACM_Iface::ipacmcfg->ipa_num_private_subnet); - if_ipv4_subnet = (data->ipv4_addr >> 8) << 8; - IPACMDBG_H(" Add IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); - if(IPACM_Iface::ipacmcfg->AddPrivateSubnet(if_ipv4_subnet, ipa_if_num) == false) + if (data->iptype == IPA_IP_v4) { - IPACMERR(" can't Add IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + IPACMDBG_H("current IPACM private subnet_addr number(%d)\n", IPACM_Iface::ipacmcfg->ipa_num_private_subnet); + if_ipv4_subnet = (data->ipv4_addr >> 8) << 8; + IPACMDBG_H(" Add IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + if(IPACM_Iface::ipacmcfg->AddPrivateSubnet(if_ipv4_subnet, ipa_if_num) == false) + { + IPACMERR(" can't Add IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + } } -} #endif /* defined(FEATURE_IPA_ANDROID)*/ + /* Update the IP Type. */ + config_ip_type(data->iptype); + if (data->iptype == IPA_IP_v4) { rt_rule = (struct ipa_ioc_add_rt_rule *) @@ -1000,38 +1172,34 @@ if (data->iptype == IPA_IP_v4) rt_rule_entry->at_rear = false; rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; //go to A5 rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name); + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name)); rt_rule_entry->rule.attrib.u.v4.dst_addr = data->ipv4_addr; rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; - if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - res = IPACM_FAILURE; - goto fail; - } - else if (rt_rule_entry->status) - { - IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); - res = rt_rule_entry->status; - goto fail; - } +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; - IPACMDBG_H("ipv4 iface rt-rule hdl1=0x%x\n", dft_rt_rule_hdl[0]); + IPACMDBG_H("ipv4 iface rt-rule hdl1=0x%x\n", dft_rt_rule_hdl[0]); /* initial multicast/broadcast/fragment filter rule */ -#ifdef FEATURE_ETH_BRIDGE_LE - init_fl_rule(data->iptype); - eth_bridge_add_wlan_guest_ap_flt_rule(data->iptype); - eth_bridge_handle_dummy_wlan_client_flt_rule(data->iptype); - eth_bridge_handle_dummy_usb_client_flt_rule(data->iptype); - eth_bridge_install_cache_wlan_client_flt_rule(data->iptype); - eth_bridge_install_cache_usb_client_flt_rule(data->iptype); -#else -#ifdef CT_OPT - install_tcp_ctl_flt_rule(IPA_IP_v4); -#endif + init_fl_rule(data->iptype); - add_dummy_lan2lan_flt_rule(data->iptype); -#endif + install_ipv4_icmp_flt_rule(); + + /* populate the flt rule offset for eth bridge */ + eth_bridge_flt_rule_offset[data->iptype] = ipv4_icmp_flt_rule_hdl[0]; + eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL, NULL, NULL); } else { @@ -1061,12 +1229,12 @@ if (data->iptype == IPA_IP_v4) rt_rule->commit = 1; rt_rule->num_rules = NUM_RULES; rt_rule->ip = data->iptype; - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name); + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name)); - rt_rule_entry = &rt_rule->rules[0]; - rt_rule_entry->at_rear = false; - rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; //go to A5 - rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; //go to A5 + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2]; @@ -1079,7 +1247,9 @@ if (data->iptype == IPA_IP_v4) ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1]; ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2]; ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3]; - +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) { IPACMERR("Routing rule addition failed!\n"); @@ -1094,20 +1264,20 @@ if (data->iptype == IPA_IP_v4) } dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl; - /* setup same rule for v6_wan table*/ - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name); - if (false == m_routing.AddRoutingRule(rt_rule)) + /* setup same rule for v6_wan table*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + if (false == m_routing.AddRoutingRule(rt_rule)) { - IPACMERR("Routing rule addition failed!\n"); - res = IPACM_FAILURE; - goto fail; + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; } - else if (rt_rule_entry->status) + else if (rt_rule_entry->status) { - IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); - res = rt_rule_entry->status; - goto fail; - } + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl; IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, num_dft_rt_v6: %d \n", @@ -1116,21 +1286,13 @@ if (data->iptype == IPA_IP_v4) if (num_dft_rt_v6 == 0) { - /* initial multicast/broadcast/fragment filter rule */ -#ifdef FEATURE_ETH_BRIDGE_LE - eth_bridge_add_wlan_guest_ap_flt_rule(data->iptype); - eth_bridge_handle_dummy_wlan_client_flt_rule(data->iptype); - eth_bridge_handle_dummy_usb_client_flt_rule(data->iptype); - eth_bridge_install_cache_wlan_client_flt_rule(data->iptype); - eth_bridge_install_cache_usb_client_flt_rule(data->iptype); - init_fl_rule(data->iptype); -#else -#ifdef CT_OPT - install_tcp_ctl_flt_rule(IPA_IP_v6); -#endif - add_dummy_lan2lan_flt_rule(data->iptype); + install_ipv6_icmp_flt_rule(); + + /* populate the flt rule offset for eth bridge */ + eth_bridge_flt_rule_offset[data->iptype] = ipv6_icmp_flt_rule_hdl[0]; + eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL, NULL, NULL); + init_fl_rule(data->iptype); -#endif } num_dft_rt_v6++; IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6); @@ -1178,13 +1340,6 @@ int IPACM_Lan::handle_private_subnet(ipa_ip_type iptype) m_pFilteringTable->ip = IPA_IP_v4; m_pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet; - if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4)) - { - IPACMERR("LAN m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_lan_v4); - free(m_pFilteringTable); - return IPACM_FAILURE; - } - /* Make LAN-traffic always go A5, use default IPA-RT table */ if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4)) { @@ -1201,8 +1356,10 @@ int IPACM_Lan::handle_private_subnet(ipa_ip_type iptype) flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; - - /* Support priave subnet feature including guest-AP can't talk to primary AP etc */ +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + /* Support private subnet feature including guest-AP can't talk to primary AP etc */ flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl; IPACMDBG_H(" private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name); @@ -1222,8 +1379,7 @@ int IPACM_Lan::handle_private_subnet(ipa_ip_type iptype) free(m_pFilteringTable); return IPACM_FAILURE; } - - flt_rule_count_v4 += IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet); /* copy filter rule hdls */ for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++) @@ -1257,6 +1413,11 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) if(ip_type == IPA_IP_v4) { + if(sta_ul_v4_set == true) + { + IPACMDBG_H("Filetring rule for IPV4 of STA mode is already configured, sta_ul_v4_set: %d\n",sta_ul_v4_set); + return IPACM_FAILURE; + } len = sizeof(struct ipa_ioc_add_flt_rule) + (1 * sizeof(struct ipa_flt_rule_add)); m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len); if (m_pFilteringTable == NULL) @@ -1287,7 +1448,17 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) flt_rule_entry.at_rear = true; flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; - flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; //IPA_PASS_TO_ROUTING + if(IPACM_Wan::isWan_Bridge_Mode()) + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; //IPA_PASS_TO_ROUTING + } +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl; memcpy(&flt_rule_entry.rule.attrib, @@ -1298,6 +1469,12 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0; flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0; +/* only offload UL traffic of certain clients */ +#ifdef FEATURE_IPACM_HAL + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = prefix[IPA_IP_v4].v4Mask; + flt_rule_entry.rule.attrib.u.v4.dst_addr = prefix[IPA_IP_v4].v4Addr; +#endif memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry)); if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) { @@ -1307,18 +1484,24 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); } - + sta_ul_v4_set = true; /* copy filter hdls */ lan_wan_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; free(m_pFilteringTable); } else if(ip_type == IPA_IP_v6) { + if(sta_ul_v6_set == true) + { + IPACMDBG_H("Filetring rule for IPV6 of STA mode is already configured, sta_ul_v6_set: %d\n",sta_ul_v6_set); + return IPACM_FAILURE; + } /* add default v6 filter rule */ m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) calloc(1, sizeof(struct ipa_ioc_add_flt_rule) + @@ -1349,7 +1532,10 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; - flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_v6.hdl; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_v6.hdl; memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, @@ -1365,6 +1551,19 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; +/* only offload UL traffic of certain clients */ +#ifdef FEATURE_IPACM_HAL + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = prefix[IPA_IP_v6].v6Mask[0]; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = prefix[IPA_IP_v6].v6Mask[1]; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = prefix[IPA_IP_v6].v6Mask[2]; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = prefix[IPA_IP_v6].v6Mask[3]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = prefix[IPA_IP_v6].v6Addr[0]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = prefix[IPA_IP_v6].v6Addr[1]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = prefix[IPA_IP_v6].v6Addr[2]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = prefix[IPA_IP_v6].v6Addr[3]; + +#endif memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) { @@ -1374,9 +1573,11 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); } + sta_ul_v6_set = true; /* copy filter hdls */ dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES] = m_pFilteringTable->rules[0].flt_rule_hdl; free(m_pFilteringTable); @@ -1385,7 +1586,7 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) return IPACM_SUCCESS; } -int IPACM_Lan::handle_wan_up_ex(ipacm_ext_prop* ext_prop, ipa_ip_type iptype) +int IPACM_Lan::handle_wan_up_ex(ipacm_ext_prop *ext_prop, ipa_ip_type iptype, uint8_t xlat_mux_id) { int fd, ret = IPACM_SUCCESS, cnt; IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg; @@ -1419,12 +1620,12 @@ int IPACM_Lan::handle_wan_up_ex(ipacm_ext_prop* ext_prop, ipa_ip_type iptype) /* check only add static UL filter rule once */ if (num_dft_rt_v6 ==1 && iptype ==IPA_IP_v6 && modem_ul_v6_set == false) { - IPACMDBG_H("IPA_IP_v6 num_dft_rt_v6 %d modem_ul_v6_set: %d\n", num_dft_rt_v6, modem_ul_v6_set); - ret = handle_uplink_filter_rule(ext_prop, iptype); + IPACMDBG_H("IPA_IP_v6 num_dft_rt_v6 %d xlat_mux_id: %d modem_ul_v6_set: %d\n", num_dft_rt_v6, xlat_mux_id, modem_ul_v6_set); + ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id); modem_ul_v6_set = true; } else if (iptype ==IPA_IP_v4 && modem_ul_v4_set == false) { - IPACMDBG_H("IPA_IP_v4 modem_ul_v4_set %d\n", modem_ul_v4_set); - ret = handle_uplink_filter_rule(ext_prop, iptype); + IPACMDBG_H("IPA_IP_v4 xlat_mux_id: %d, modem_ul_v4_set %d\n", xlat_mux_id, modem_ul_v4_set); + ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id); modem_ul_v4_set = true; } else { IPACMDBG_H("ip-type: %d modem_ul_v4_set: %d, modem_ul_v6_set %d\n", iptype, modem_ul_v4_set, modem_ul_v6_set); @@ -1442,7 +1643,7 @@ int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr) char index[ETH_IFACE_INDEX_LEN]; struct ipa_ioc_copy_hdr sCopyHeader; struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; - uint32_t cnt; + uint32_t cnt; int clnt_indx; clnt_indx = get_eth_client_index(mac_addr); @@ -1531,6 +1732,14 @@ int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr) mac_addr, IPA_MAC_ADDR_SIZE); } + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } pHeaderDescriptor->commit = true; pHeaderDescriptor->num_hdrs = 1; @@ -1540,7 +1749,7 @@ int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr) snprintf(index,sizeof(index), "%d", ipa_if_num); strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); - + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_ETH_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) { IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); @@ -1623,6 +1832,15 @@ int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr) mac_addr, IPA_MAC_ADDR_SIZE); } + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } + pHeaderDescriptor->commit = true; pHeaderDescriptor->num_hdrs = 1; @@ -1631,7 +1849,7 @@ int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr) snprintf(index,sizeof(index), "%d", ipa_if_num); strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); - + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_ETH_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) { IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); @@ -1687,7 +1905,6 @@ int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr) } fail: free(pHeaderDescriptor); - return res; } @@ -1696,9 +1913,11 @@ int IPACM_Lan::handle_eth_client_ipaddr(ipacm_event_data_all *data) { int clnt_indx; int v6_num; + uint32_t ipv6_link_local_prefix = 0xFE800000; + uint32_t ipv6_link_local_prefix_mask = 0xFFC00000; IPACMDBG_H("number of eth clients: %d\n", num_eth_client); - IPACMDBG_H(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + IPACMDBG_H("event MAC %02x:%02x:%02x:%02x:%02x:%02x\n", data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], @@ -1730,7 +1949,7 @@ int IPACM_Lan::handle_eth_client_ipaddr(ipacm_event_data_all *data) /* check if client got new IPv4 address*/ if(data->ipv4_addr == get_client_memptr(eth_client, clnt_indx)->v4_addr) { - IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx); + IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx); return IPACM_FAILURE; } else @@ -1742,10 +1961,10 @@ int IPACM_Lan::handle_eth_client_ipaddr(ipacm_event_data_all *data) get_client_memptr(eth_client, clnt_indx)->route_rule_set_v4 = false; get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr; } + } } - } - else - { + else + { IPACMDBG_H("Invalid client IPv4 address \n"); return IPACM_FAILURE; } @@ -1755,22 +1974,28 @@ int IPACM_Lan::handle_eth_client_ipaddr(ipacm_event_data_all *data) if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) || (data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) /* check if all 0 not valid ipv6 address */ { - IPACMDBG_H("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); - if(get_client_memptr(eth_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR) - { + IPACMDBG_H("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + if( (data->ipv6_addr[0] & ipv6_link_local_prefix_mask) != (ipv6_link_local_prefix & ipv6_link_local_prefix_mask) && + memcmp(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix)) != 0) + { + IPACMDBG_H("This IPv6 address is not global IPv6 address with correct prefix, ignore.\n"); + return IPACM_FAILURE; + } + + if(get_client_memptr(eth_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR) + { for(v6_num=0;v6_num < get_client_memptr(eth_client, clnt_indx)->ipv6_set;v6_num++) - { - if( data->ipv6_addr[0] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][0] && + { + if( data->ipv6_addr[0] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][0] && data->ipv6_addr[1] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][1] && data->ipv6_addr[2]== get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][2] && data->ipv6_addr[3] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][3]) - { - IPACMDBG_H("Already see this ipv6 addr for client:%d\n", clnt_indx); - return IPACM_FAILURE; /* not setup the RT rules*/ - break; - } - } + { + IPACMDBG_H("Already see this ipv6 addr at position: %d for client:%d\n", v6_num, clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ + } + } /* not see this ipv6 before for wifi client*/ get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0]; @@ -1781,8 +2006,8 @@ int IPACM_Lan::handle_eth_client_ipaddr(ipacm_event_data_all *data) } else { - IPACMDBG_H("Already got 3 ipv6 addr for client:%d\n", clnt_indx); - return IPACM_FAILURE; /* not setup the RT rules*/ + IPACMDBG_H("Already got %d ipv6 addr for client:%d\n", IPV6_NUM_ADDR, clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ } } } @@ -1825,7 +2050,6 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp get_client_memptr(eth_client, eth_index)->ipv6_set, get_client_memptr(eth_client, eth_index)->route_rule_set_v6); } - /* Add default routing rules if not set yet */ if ((iptype == IPA_IP_v4 && get_client_memptr(eth_client, eth_index)->route_rule_set_v4 == false @@ -1876,11 +2100,10 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", eth_index, get_client_memptr(eth_client, eth_index)->hdr_hdl_v4); - strncpy(rt_rule->rt_tbl_name, + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name)); - - + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[tx_index].attrib, @@ -1889,11 +2112,9 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp rt_rule_entry->rule.hdr_hdl = get_client_memptr(eth_client, eth_index)->hdr_hdl_v4; rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(eth_client, eth_index)->v4_addr; rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; - - /* Replace the v4 header in ODU interface */ - if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) - rt_rule_entry->rule.hdr_hdl = ODU_hdr_hdl_v4; - +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = false; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) { IPACMERR("Routing rule addition failed!\n"); @@ -1916,14 +2137,10 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp get_client_memptr(eth_client, eth_index)->hdr_hdl_v6); /* v6 LAN_RT_TBL */ - strncpy(rt_rule->rt_tbl_name, + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name)); - - /* Replace v6 header in ODU interface */ - if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) - rt_rule_entry->rule.hdr_hdl = ODU_hdr_hdl_v6; - + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; /* Support QCMAP LAN traffic feature, send to A5 */ rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib)); @@ -1937,7 +2154,9 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; - +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) { IPACMERR("Routing rule addition failed!\n"); @@ -1950,11 +2169,9 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[v6_num], iptype); /*Copy same rule to v6 WAN RT TBL*/ - strncpy(rt_rule->rt_tbl_name, - IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, - sizeof(rt_rule->rt_tbl_name)); - - /* Downlink traffic from Wan iface, directly through IPA */ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Downlink traffic from Wan iface, directly through IPA */ rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[tx_index].attrib, @@ -1969,7 +2186,9 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; - +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) { IPACMERR("Routing rule addition failed!\n"); @@ -1996,7 +2215,6 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp get_client_memptr(eth_client, eth_index)->route_rule_set_v6 = get_client_memptr(eth_client, eth_index)->ipv6_set; } } - return IPACM_SUCCESS; } @@ -2006,7 +2224,7 @@ int IPACM_Lan::handle_odu_hdr_init(uint8_t *mac_addr) int res = IPACM_SUCCESS, len = 0; struct ipa_ioc_copy_hdr sCopyHeader; struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; - uint32_t cnt; + uint32_t cnt; IPACMDBG("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac_addr[0], mac_addr[1], mac_addr[2], @@ -2060,14 +2278,21 @@ int IPACM_Lan::handle_odu_hdr_init(uint8_t *mac_addr) mac_addr, IPA_MAC_ADDR_SIZE); } - + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } pHeaderDescriptor->commit = true; pHeaderDescriptor->num_hdrs = 1; memset(pHeaderDescriptor->hdr[0].name, 0, sizeof(pHeaderDescriptor->hdr[0].name)); - strcpy(pHeaderDescriptor->hdr[0].name, IPA_ODU_HDR_NAME_v4); + strlcpy(pHeaderDescriptor->hdr[0].name, IPA_ODU_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)); pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; pHeaderDescriptor->hdr[0].hdr_hdl = -1; pHeaderDescriptor->hdr[0].is_partial = 0; @@ -2132,6 +2357,14 @@ int IPACM_Lan::handle_odu_hdr_init(uint8_t *mac_addr) mac_addr, IPA_MAC_ADDR_SIZE); } + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } pHeaderDescriptor->commit = true; pHeaderDescriptor->num_hdrs = 1; @@ -2139,7 +2372,7 @@ int IPACM_Lan::handle_odu_hdr_init(uint8_t *mac_addr) memset(pHeaderDescriptor->hdr[0].name, 0, sizeof(pHeaderDescriptor->hdr[0].name)); - strcpy(pHeaderDescriptor->hdr[0].name, IPA_ODU_HDR_NAME_v6); + strlcpy(pHeaderDescriptor->hdr[0].name, IPA_ODU_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)); pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; pHeaderDescriptor->hdr[0].hdr_hdl = -1; pHeaderDescriptor->hdr[0].is_partial = 0; @@ -2164,7 +2397,6 @@ int IPACM_Lan::handle_odu_hdr_init(uint8_t *mac_addr) } fail: free(pHeaderDescriptor); - return res; } @@ -2180,7 +2412,7 @@ int IPACM_Lan::handle_odu_route_add() if(tx_prop == NULL) { - IPACMDBG("No tx properties, ignore default route setting\n"); + IPACMDBG_H("No tx properties, ignore default route setting\n"); return IPACM_SUCCESS; } @@ -2198,25 +2430,25 @@ int IPACM_Lan::handle_odu_route_add() rt_rule->num_rules = (uint8_t)NUM; - IPACMDBG(" WAN table created %s \n", rt_rule->rt_tbl_name); + IPACMDBG_H("WAN table created %s \n", rt_rule->rt_tbl_name); rt_rule_entry = &rt_rule->rules[0]; rt_rule_entry->at_rear = true; for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) { - if (IPA_IP_v4 == tx_prop->tx[tx_index].ip) - { - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v4.name); + if (IPA_IP_v4 == tx_prop->tx[tx_index].ip) + { + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v4.name, sizeof(rt_rule->rt_tbl_name)); rt_rule_entry->rule.hdr_hdl = ODU_hdr_hdl_v4; rt_rule->ip = IPA_IP_v4; - } - else - { - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v6.name); + } + else + { + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v6.name, sizeof(rt_rule->rt_tbl_name)); rt_rule_entry->rule.hdr_hdl = ODU_hdr_hdl_v6; rt_rule->ip = IPA_IP_v6; - } + } rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; memcpy(&rt_rule_entry->rule.attrib, @@ -2228,15 +2460,17 @@ int IPACM_Lan::handle_odu_route_add() { rt_rule_entry->rule.attrib.u.v4.dst_addr = 0; rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0; - +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - free(rt_rule); - return IPACM_FAILURE; - } + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } odu_route_rule_v4_hdl[tx_index] = rt_rule_entry->rt_rule_hdl; - IPACMDBG("Got ipv4 ODU-route rule hdl:0x%x,tx:%d,ip-type: %d \n", + IPACMDBG_H("Got ipv4 ODU-route rule hdl:0x%x,tx:%d,ip-type: %d \n", odu_route_rule_v4_hdl[tx_index], tx_index, IPA_IP_v4); @@ -2251,20 +2485,21 @@ int IPACM_Lan::handle_odu_route_add() rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0; - +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - free(rt_rule); - return IPACM_FAILURE; + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; } odu_route_rule_v6_hdl[tx_index] = rt_rule_entry->rt_rule_hdl; - IPACMDBG("Set ipv6 ODU-route rule hdl for v6_lan_table:0x%x,tx:%d,ip-type: %d \n", - odu_route_rule_v6_hdl[tx_index], - tx_index, - IPA_IP_v6); + IPACMDBG_H("Set ipv6 ODU-route rule hdl for v6_lan_table:0x%x,tx:%d,ip-type: %d \n", + odu_route_rule_v6_hdl[tx_index], + tx_index, + IPA_IP_v6); } - } free(rt_rule); return IPACM_SUCCESS; @@ -2277,37 +2512,37 @@ int IPACM_Lan::handle_odu_route_del() if(tx_prop == NULL) { - IPACMDBG("No tx properties, ignore delete default route setting\n"); - return IPACM_SUCCESS; + IPACMDBG_H("No tx properties, ignore delete default route setting\n"); + return IPACM_SUCCESS; } - for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if (tx_prop->tx[tx_index].ip == IPA_IP_v4) { - if (tx_prop->tx[tx_index].ip == IPA_IP_v4) - { - IPACMDBG("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", - tx_index, tx_prop->tx[tx_index].ip,IPA_IP_v4); + IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", + tx_index, tx_prop->tx[tx_index].ip,IPA_IP_v4); - if (m_routing.DeleteRoutingHdl(odu_route_rule_v4_hdl[tx_index], IPA_IP_v4) - == false) - { - IPACMDBG("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v4, odu_route_rule_v4_hdl[tx_index], tx_index); - return IPACM_FAILURE; - } - } - else + if (m_routing.DeleteRoutingHdl(odu_route_rule_v4_hdl[tx_index], IPA_IP_v4) + == false) { - IPACMDBG("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", - tx_index, tx_prop->tx[tx_index].ip,IPA_IP_v6); + IPACMERR("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v4, odu_route_rule_v4_hdl[tx_index], tx_index); + return IPACM_FAILURE; + } + } + else + { + IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", + tx_index, tx_prop->tx[tx_index].ip,IPA_IP_v6); - if (m_routing.DeleteRoutingHdl(odu_route_rule_v6_hdl[tx_index], IPA_IP_v6) - == false) - { - IPACMDBG("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v6, odu_route_rule_v6_hdl[tx_index], tx_index); - return IPACM_FAILURE; - } + if (m_routing.DeleteRoutingHdl(odu_route_rule_v6_hdl[tx_index], IPA_IP_v6) + == false) + { + IPACMERR("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v6, odu_route_rule_v6_hdl[tx_index], tx_index); + return IPACM_FAILURE; } } + } return IPACM_SUCCESS; } @@ -2442,12 +2677,16 @@ int IPACM_Lan::handle_down_evt() { int i; int res = IPACM_SUCCESS; - uint32_t temp_eth_bridge_flt_rule[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; - if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + IPACMDBG_H("lan handle_down_evt\n "); + if (ipa_if_cate == ODU_IF) { /* delete ODU default RT rules */ - handle_odu_route_del(); + if (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true) + { + IPACMDBG_H("eMBMS enable, delete eMBMS DL RT rule\n"); + handle_odu_route_del(); + } /* delete full header */ if (ipv4_header_set) @@ -2455,11 +2694,11 @@ int IPACM_Lan::handle_down_evt() if (m_header.DeleteHeaderHdl(ODU_hdr_hdl_v4) == false) { - IPACMDBG("ODU ipv4 header delete fail\n"); + IPACMERR("ODU ipv4 header delete fail\n"); res = IPACM_FAILURE; goto fail; } - IPACMDBG("ODU ipv4 header delete success\n"); + IPACMDBG_H("ODU ipv4 header delete success\n"); } if (ipv6_header_set) @@ -2467,11 +2706,11 @@ int IPACM_Lan::handle_down_evt() if (m_header.DeleteHeaderHdl(ODU_hdr_hdl_v6) == false) { - IPACMDBG("ODU ipv6 header delete fail\n"); + IPACMERR("ODU ipv6 header delete fail\n"); res = IPACM_FAILURE; goto fail; } - IPACMDBG("ODU ipv6 header delete success\n"); + IPACMERR("ODU ipv6 header delete success\n"); } } @@ -2480,74 +2719,50 @@ int IPACM_Lan::handle_down_evt() { goto fail; } - IPACMDBG_H("lan handle_down_evt\n "); - -#ifdef FEATURE_ETH_BRIDGE_LE - IPACM_Lan::usb_hdr_type = IPA_HDR_L2_NONE; - IPACM_Lan::usb_hdr_template_hdl = 0; - del_hdr_proc_ctx(); -#endif /* delete wan filter rule */ if (IPACM_Wan::isWanUP(ipa_if_num) && rx_prop != NULL) { IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); +#ifdef FEATURE_IPA_ANDROID + /* Clean-up tethered-iface list */ + IPACM_Wan::delete_tether_iface(IPA_IP_v4, ipa_if_num); +#endif } if (IPACM_Wan::isWanUP_V6(ipa_if_num) && rx_prop != NULL) { IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); +#ifdef FEATURE_IPA_ANDROID + /* Clean-up tethered-iface list */ + IPACM_Wan::delete_tether_iface(IPA_IP_v6, ipa_if_num); +#endif } /* delete default filter rules */ if (ip_type != IPA_IP_v6 && rx_prop != NULL) { - if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES) == false) + if(m_filtering.DeleteFilteringHdls(ipv4_icmp_flt_rule_hdl, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE) == false) { - IPACMERR("Error Deleting Filtering Rule, aborting...\n"); + IPACMERR("Error Deleting ICMPv4 Filtering Rule, aborting...\n"); res = IPACM_FAILURE; goto fail; } -#ifdef FEATURE_ETH_BRIDGE_LE - for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE); + + if(dft_v4fl_rule_hdl[0] != 0) { - if(m_filtering.DeleteFilteringHdls(&(lan2lan_flt_rule_hdl_v4[i].rule_hdl), IPA_IP_v4, 1) == false) - { - IPACMERR("Error deleting lan2lan IPv4 flt rules.\n"); - res = IPACM_FAILURE; - goto fail; - } + if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, IPA_IP_v4, + IPV4_DEFAULT_FILTERTING_RULES) == false) + { + IPACMERR("Error Deleting Filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES); } - IPACMDBG_H("Deleted lan2lan IPv4 flt rules.\n"); -#endif /* free private-subnet ipv4 filter rules */ if (IPACM_Iface::ipacmcfg->ipa_num_private_subnet > IPA_PRIV_SUBNET_FILTER_RULE_HANDLES) @@ -2564,61 +2779,42 @@ int IPACM_Lan::handle_down_evt() res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES); #else if (m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet) == false) { - IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n"); + IPACMERR("Error deleting private subnet IPv4 flt rules.\n"); res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet); #endif + IPACMDBG_H("Deleted private subnet v4 filter rules successfully.\n"); } - IPACMDBG_H("Finished delete default iface ipv4 filtering rules \n "); + IPACMDBG_H("Finished delete default iface ipv4 filtering rules \n "); if (ip_type != IPA_IP_v4 && rx_prop != NULL) { - if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, - IPA_IP_v6, - (IPV6_DEFAULT_FILTERTING_RULES + IPV6_DEFAULT_LAN_FILTERTING_RULES)) == false) + if(m_filtering.DeleteFilteringHdls(ipv6_icmp_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE) == false) { - IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); - res = IPACM_FAILURE; - goto fail; - } -#ifdef FEATURE_ETH_BRIDGE_LE - for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE); + + if (dft_v6fl_rule_hdl[0] != 0) { - if(m_filtering.DeleteFilteringHdls(&(lan2lan_flt_rule_hdl_v6[i].rule_hdl), IPA_IP_v6, 1) == false) + if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES) == false) { - IPACMERR("Error deleting lan2lan IPv4 flt rules.\n"); + IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES); } - IPACMDBG_H("Deleted lan2lan IPv6 flt rules.\n"); -#endif } - IPACMDBG_H("Finished delete default iface ipv6 filtering rules \n "); + IPACMDBG_H("Finished delete default iface ipv6 filtering rules \n "); if (ip_type != IPA_IP_v6) { @@ -2649,60 +2845,6 @@ int IPACM_Lan::handle_down_evt() } IPACMDBG_H("Finished delete default iface ipv6 rules \n "); - /* clean eth-client header, routing rules */ - IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client); - for (i = 0; i < num_eth_client; i++) - { -#ifdef FEATURE_ETH_BRIDGE_LE - eth_bridge_del_usb_client_rt_rule(get_client_memptr(eth_client, i)->mac); - eth_bridge_post_lan_client_event(get_client_memptr(eth_client, i)->mac, IPA_ETH_BRIDGE_USB_CLIENT_DEL_EVENT); - eth_bridge_del_usb_client(get_client_memptr(eth_client, i)->mac); -#endif - - /* First reset nat rules and then route rules */ - if(get_client_memptr(eth_client, i)->ipv4_set == true) - { - IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(eth_client, i)->v4_addr); - CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, i)->v4_addr); - } - - if (delete_eth_rtrules(i, IPA_IP_v4)) - { - IPACMERR("unbale to delete ecm-client v4 route rules for index %d\n", i); - res = IPACM_FAILURE; - goto fail; - } - - if (delete_eth_rtrules(i, IPA_IP_v6)) - { - IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i); - res = IPACM_FAILURE; - goto fail; - } - - IPACMDBG_H("Delete %d client header\n", num_eth_client); - - - if(get_client_memptr(eth_client, i)->ipv4_header_set == true) - { - if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v4) - == false) - { - res = IPACM_FAILURE; - goto fail; - } - } - - if(get_client_memptr(eth_client, i)->ipv6_header_set == true) - { - if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v6) - == false) - { - res = IPACM_FAILURE; - goto fail; - } - } - } /* end of for loop */ /* free the edm clients cache */ IPACMDBG_H("Free ecm clients cache\n"); @@ -2714,15 +2856,8 @@ int IPACM_Lan::handle_down_evt() IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); } - /* check software routing fl rule hdl */ - if (softwarerouting_act == true && rx_prop != NULL) - { - handle_software_routing_disable(); - } - /* posting ip to lan2lan module to delete RT/FILTER rules*/ - post_lan2lan_client_disconnect_msg(IPA_IP_v4); - post_lan2lan_client_disconnect_msg(IPA_IP_v6); + eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL); /* Delete private subnet*/ #ifdef FEATURE_IPA_ANDROID @@ -2737,12 +2872,66 @@ int IPACM_Lan::handle_down_evt() } /* reset the IPA-client pipe enum */ - if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != WAN_IF) + if(ipa_if_cate != WAN_IF) { +#ifdef FEATURE_IPACM_HAL + handle_tethering_client(true, IPACM_CLIENT_MAX); +#else handle_tethering_client(true, IPACM_CLIENT_USB); +#endif } #endif /* defined(FEATURE_IPA_ANDROID)*/ fail: + /* clean eth-client header, routing rules */ + IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client); + for (i = 0; i < num_eth_client; i++) + { + /* First reset nat rules and then route rules */ + if(get_client_memptr(eth_client, i)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(eth_client, i)->v4_addr); + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, i)->v4_addr); + } + + if (delete_eth_rtrules(i, IPA_IP_v4)) + { + IPACMERR("unbale to delete ecm-client v4 route rules for index %d\n", i); + res = IPACM_FAILURE; + } + + if (delete_eth_rtrules(i, IPA_IP_v6)) + { + IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i); + res = IPACM_FAILURE; + } + + IPACMDBG_H("Delete %d client header\n", num_eth_client); + + if(get_client_memptr(eth_client, i)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v4) + == false) + { + res = IPACM_FAILURE; + } + } + + if(get_client_memptr(eth_client, i)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v6) + == false) + { + res = IPACM_FAILURE; + } + } + } /* end of for loop */ + + /* check software routing fl rule hdl */ + if (softwarerouting_act == true && rx_prop != NULL) + { + handle_software_routing_disable(); + } + if (odu_route_rule_v4_hdl != NULL) { free(odu_route_rule_v4_hdl); @@ -2774,16 +2963,7 @@ int IPACM_Lan::handle_down_evt() { free(iface_query); } -#ifdef FEATURE_ETH_BRIDGE_LE - if(eth_bridge_usb_client_rt_info_v4 != NULL) - { - free(eth_bridge_usb_client_rt_info_v4); - } - if(eth_bridge_usb_client_rt_info_v6 != NULL) - { - free(eth_bridge_usb_client_rt_info_v6); - } -#endif + is_active = false; post_del_self_evt(); @@ -2791,16 +2971,17 @@ int IPACM_Lan::handle_down_evt() } /* install UL filter rule from Q6 */ -int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptype) +int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptype, uint8_t xlat_mux_id) { ipa_flt_rule_add flt_rule_entry; int len = 0, cnt, ret = IPACM_SUCCESS; ipa_ioc_add_flt_rule *pFilteringTable; ipa_fltr_installed_notif_req_msg_v01 flt_index; int fd; - int i; + int i, index, eq_index; + uint32_t value = 0; - IPACMDBG_H("Set extended property rules in LAN\n"); + IPACMDBG_H("Set modem UL flt rules\n"); if (rx_prop == NULL) { @@ -2818,22 +2999,37 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptyp if (0 == fd) { IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + if (prop->num_ext_props > MAX_WAN_UL_FILTER_RULES) + { + IPACMERR("number of modem UL rules > MAX_WAN_UL_FILTER_RULES, aborting...\n"); + close(fd); + return IPACM_FAILURE; } memset(&flt_index, 0, sizeof(flt_index)); flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; +#ifndef FEATURE_IPA_V3 flt_index.filter_index_list_len = prop->num_ext_props; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id_valid = 1; + flt_index.rule_id_len = prop->num_ext_props; +#endif flt_index.embedded_pipe_index_valid = 1; flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); flt_index.retain_header_valid = 1; flt_index.retain_header = 0; flt_index.embedded_call_mux_id_valid = 1; flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); - - IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", flt_index.source_pipe_index, - flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); - +#ifndef FEATURE_IPA_V3 + IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", + flt_index.source_pipe_index, flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); +#else /* defined (FEATURE_IPA_V3) */ + IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", + flt_index.source_pipe_index, flt_index.rule_id_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); +#endif len = sizeof(struct ipa_ioc_add_flt_rule) + prop->num_ext_props * sizeof(struct ipa_flt_rule_add); pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); if (pFilteringTable == NULL) @@ -2852,6 +3048,10 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptyp memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields flt_rule_entry.at_rear = 1; +#ifdef FEATURE_IPA_V3 + if (flt_rule_entry.rule.eq_attrib.ipv4_frag_eq_present) + flt_rule_entry.at_rear = 0; +#endif flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; @@ -2859,7 +3059,17 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptyp flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; if(iptype == IPA_IP_v4) - flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + { + if (ipa_if_cate == ODU_IF && IPACM_Wan::isWan_Bridge_Mode()) + { + IPACMDBG_H("WAN, ODU are in bridge mode \n"); + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + } + } else if(iptype == IPA_IP_v6) flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; else @@ -2869,27 +3079,116 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptyp goto fail; } + index = IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, iptype); + for(cnt=0; cntnum_ext_props; cnt++) { memcpy(&flt_rule_entry.rule.eq_attrib, &prop->prop[cnt].eq_attrib, sizeof(prop->prop[cnt].eq_attrib)); flt_rule_entry.rule.rt_tbl_idx = prop->prop[cnt].rt_tbl_idx; - memcpy(&pFilteringTable->rules[cnt], &flt_rule_entry, sizeof(flt_rule_entry)); + /* Handle XLAT configuration */ + if ((iptype == IPA_IP_v4) && prop->prop[cnt].is_xlat_rule && (xlat_mux_id != 0)) + { + /* fill the value of meta-data */ + value = xlat_mux_id; + flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1; + flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0; + flt_rule_entry.rule.eq_attrib.metadata_meq32.value = (value & 0xFF) << 16; + flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = 0x00FF0000; + IPACMDBG_H("xlat meta-data is modified for rule: %d has index %d with xlat_mux_id: %d\n", + cnt, index, xlat_mux_id); + } + +#ifdef FEATURE_IPACM_HAL + /* add prefix equation in modem UL rules */ if(iptype == IPA_IP_v4) { - IPACMDBG_H("Filtering rule %d has index %d\n", cnt, flt_rule_count_v4); - flt_index.filter_index_list[cnt].filter_index = flt_rule_count_v4; - flt_rule_count_v4++; + flt_rule_entry.rule.eq_attrib.num_offset_meq_32++; + if(flt_rule_entry.rule.eq_attrib.num_offset_meq_32 <= IPA_IPFLTR_NUM_MEQ_32_EQNS) + { + eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_32 - 1; + if(eq_index == 0) + { + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<5); + } + else + { + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<6); + } + flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].offset = 12; + flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].mask = prefix[IPA_IP_v4].v4Mask; + flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].value = prefix[IPA_IP_v4].v4Addr; + } + else + { + IPACMERR("Run out of MEQ32 equation.\n"); + flt_rule_entry.rule.eq_attrib.num_offset_meq_32--; + } + } + else + { + flt_rule_entry.rule.eq_attrib.num_offset_meq_128++; + if(flt_rule_entry.rule.eq_attrib.num_offset_meq_128 <= IPA_IPFLTR_NUM_MEQ_128_EQNS) + { + eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_128 - 1; + if(eq_index == 0) + { + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<3); + } + else + { + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<4); + } + flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].offset = 8; + *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 0) + = prefix[IPA_IP_v6].v6Mask[0]; + *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 4) + = prefix[IPA_IP_v6].v6Mask[1]; + *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 8) + = prefix[IPA_IP_v6].v6Mask[2]; + *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 12) + = prefix[IPA_IP_v6].v6Mask[3]; + *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 0) + = prefix[IPA_IP_v6].v6Addr[0]; + *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 4) + = prefix[IPA_IP_v6].v6Addr[1]; + *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 8) + = prefix[IPA_IP_v6].v6Addr[2]; + *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 12) + = prefix[IPA_IP_v6].v6Addr[3]; + } + else + { + IPACMERR("Run out of MEQ128 equation.\n"); + flt_rule_entry.rule.eq_attrib.num_offset_meq_128--; + } } - if(iptype == IPA_IP_v6) +#endif + +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = prop->prop[cnt].is_rule_hashable; + flt_rule_entry.rule.rule_id = prop->prop[cnt].rule_id; + if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA) //turn on meta-data equation { - IPACMDBG_H("Filtering rule %d has index %d\n", cnt, flt_rule_count_v6); - flt_index.filter_index_list[cnt].filter_index = flt_rule_count_v6; - flt_rule_count_v6++; + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9); + flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1; + flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0; + flt_rule_entry.rule.eq_attrib.metadata_meq32.value |= rx_prop->rx[0].attrib.meta_data; + flt_rule_entry.rule.eq_attrib.metadata_meq32.mask |= rx_prop->rx[0].attrib.meta_data_mask; } +#endif + memcpy(&pFilteringTable->rules[cnt], &flt_rule_entry, sizeof(flt_rule_entry)); + + IPACMDBG_H("Modem UL filtering rule %d has index %d\n", cnt, index); +#ifndef FEATURE_IPA_V3 + flt_index.filter_index_list[cnt].filter_index = index; flt_index.filter_index_list[cnt].filter_handle = prop->prop[cnt].filter_hdl; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id[cnt] = prop->prop[cnt].rule_id; +#endif + index++; } if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) @@ -2914,6 +3213,7 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptyp wan_ul_fl_rule_hdl_v4[num_wan_ul_fl_rule_v4] = pFilteringTable->rules[i].flt_rule_hdl; num_wan_ul_fl_rule_v4++; } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules); } else if(iptype == IPA_IP_v6) { @@ -2922,6 +3222,7 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptyp wan_ul_fl_rule_hdl_v6[num_wan_ul_fl_rule_v6] = pFilteringTable->rules[i].flt_rule_hdl; num_wan_ul_fl_rule_v6++; } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules); } else { @@ -2948,21 +3249,9 @@ int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode) return IPACM_FAILURE; } -#ifdef FEATURE_ETH_BRIDGE_LE - flt_rule_count_v6 = IPV6_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + NUM_IPV6_ICMP_FLT_RULE; -#else -#ifdef CT_OPT - flt_rule_count_v6 = IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + NUM_IPV6_ICMP_FLT_RULE; -#else - flt_rule_count_v6 = IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + NUM_IPV6_ICMP_FLT_RULE; -#endif -#endif + delete_ipv6_prefix_flt_rule(); - if(m_filtering.DeleteFilteringHdls(ipv6_prefix_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE) == false) - { - close(fd); - return IPACM_FAILURE; - } + memset(ipv6_prefix, 0, sizeof(ipv6_prefix)); if(is_sta_mode == false) { @@ -2972,6 +3261,13 @@ int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode) close(fd); return IPACM_FAILURE; } + if (num_wan_ul_fl_rule_v6 == 0) + { + IPACMERR("No modem UL rules were installed, return...\n"); + close(fd); + return IPACM_FAILURE; + } + if (m_filtering.DeleteFilteringHdls(wan_ul_fl_rule_hdl_v6, IPA_IP_v6, num_wan_ul_fl_rule_v6) == false) { @@ -2979,7 +3275,7 @@ int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode) close(fd); return IPACM_FAILURE; } - + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_wan_ul_fl_rule_v6); memset(wan_ul_fl_rule_hdl_v6, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); num_wan_ul_fl_rule_v6 = 0; modem_ul_v6_set = false; @@ -2987,7 +3283,12 @@ int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode) memset(&flt_index, 0, sizeof(flt_index)); flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; +#ifndef FEATURE_IPA_V3 flt_index.filter_index_list_len = 0; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id_valid = 1; + flt_index.rule_id_len = 0; +#endif flt_index.embedded_pipe_index_valid = 1; flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); flt_index.retain_header_valid = 1; @@ -3010,83 +3311,26 @@ int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode) close(fd); return IPACM_FAILURE; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + sta_ul_v6_set = false; } close(fd); return IPACM_SUCCESS; } - -/*handle lan2lan client active*/ -int IPACM_Lan::handle_lan2lan_client_active(ipacm_event_data_all *data, ipa_cm_event_id event) -{ - if(data == NULL) - { - IPACMERR("Event data is empty.\n"); - return IPACM_FAILURE; - } - - if(data->iptype == IPA_IP_v4 && ip_type != IPA_IP_v4 && ip_type != IPA_IP_MAX) - { - IPACMERR("Client has IPv4 addr but iface does not have IPv4 up.\n"); - return IPACM_FAILURE; - } - if(data->iptype == IPA_IP_v6 && ip_type != IPA_IP_v6 && ip_type != IPA_IP_MAX) - { - IPACMERR("Client has IPv6 addr but iface does not have IPv6 up.\n"); - return IPACM_FAILURE; - } - - ipacm_cmd_q_data evt_data; - memset(&evt_data, 0, sizeof(evt_data)); - - ipacm_event_lan_client* lan_client; - lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); - if(lan_client == NULL) - { - IPACMERR("Unable to allocate memory.\n"); - return IPACM_FAILURE; - } - memset(lan_client, 0, sizeof(ipacm_event_lan_client)); - lan_client->iptype = data->iptype; - lan_client->ipv4_addr = data->ipv4_addr; - memcpy(lan_client->ipv6_addr, data->ipv6_addr, 4 * sizeof(uint32_t)); - memcpy(lan_client->mac_addr, data->mac_addr, 6 * sizeof(uint8_t)); - lan_client->p_iface = this; - - evt_data.event = event; - evt_data.evt_data = (void*)lan_client; - - IPACMDBG_H("Posting event: %d\n", event); - IPACM_EvtDispatcher::PostEvt(&evt_data); - return IPACM_SUCCESS; -} - -int IPACM_Lan::add_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t src_v4_addr, uint32_t dst_v4_addr, uint32_t* src_v6_addr, uint32_t* dst_v6_addr, uint32_t* rule_hdl) +int IPACM_Lan::reset_to_dummy_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl) { - if(rx_prop == NULL) - { - IPACMERR("There is no rx_prop for iface %s, not able to add lan2lan filtering rule.\n", dev_name); - return IPACM_FAILURE; - } - if(rule_hdl == NULL) - { - IPACMERR("Filteing rule handle is empty.\n"); - return IPACM_FAILURE; - } - - IPACMDBG_H("Got a new lan2lan flt rule with IP type: %d\n", iptype); - - int i, len, res = IPACM_SUCCESS; + int len, res = IPACM_SUCCESS; struct ipa_flt_rule_mdfy flt_rule; struct ipa_ioc_mdfy_flt_rule* pFilteringTable; + IPACMDBG_H("Reset flt rule to dummy, IP type: %d, hdl: %d\n", iptype, rule_hdl); len = sizeof(struct ipa_ioc_mdfy_flt_rule) + sizeof(struct ipa_flt_rule_mdfy); - pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); if (pFilteringTable == NULL) { - IPACMERR("Error allocate lan2lan flt rule memory...\n"); + IPACMERR("Error allocate flt rule memory...\n"); return IPACM_FAILURE; } memset(pFilteringTable, 0, len); @@ -3096,60 +3340,21 @@ int IPACM_Lan::add_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t src_v4_addr, ui pFilteringTable->num_rules = 1; memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + flt_rule.rule_hdl = rule_hdl; + + flt_rule.rule.retain_hdr = 0; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; if(iptype == IPA_IP_v4) { - IPACMDBG_H("src_v4_addr: %d dst_v4_addr: %d\n", src_v4_addr, dst_v4_addr); - - if(num_lan2lan_flt_rule_v4 >= MAX_OFFLOAD_PAIR) - { - IPACMERR("Lan2lan flt rule table is full, not able to add.\n"); - res = IPACM_FAILURE; - goto fail; - } - - if(false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4)) - { - IPACMERR("Failed to get routing table %s handle.\n", IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4.name); - res = IPACM_FAILURE; - goto fail; - } - IPACMDBG_H("Routing handle for table %s: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4.name, - IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4.hdl); - - flt_rule.status = -1; - for(i=0; irt_tbl_lan2lan_v4.hdl; - - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, - sizeof(flt_rule.rule.attrib)); - IPACMDBG_H("Rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); - - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; - flt_rule.rule.attrib.u.v4.src_addr = src_v4_addr; - flt_rule.rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF; + IPACMDBG_H("Reset IPv4 flt rule to dummy\n"); - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v4.dst_addr = dst_v4_addr; - flt_rule.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v4.dst_addr = ~0; + flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.src_addr = ~0; + flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) @@ -3160,127 +3365,246 @@ int IPACM_Lan::add_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t src_v4_addr, ui } else { - lan2lan_flt_rule_hdl_v4[i].valid = true; - *rule_hdl = lan2lan_flt_rule_hdl_v4[i].rule_hdl; - num_lan2lan_flt_rule_v4++; - IPACMDBG_H("Flt rule modified, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, + IPACMDBG_H("Flt rule reset to dummy, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, pFilteringTable->rules[0].status); } } else if(iptype == IPA_IP_v6) { - if(num_lan2lan_flt_rule_v6 >= MAX_OFFLOAD_PAIR) - { - IPACMERR("Lan2lan flt rule table is full, not able to add.\n"); - res = IPACM_FAILURE; - goto fail; - } - if(src_v6_addr == NULL || dst_v6_addr == NULL) + IPACMDBG_H("Reset IPv6 flt rule to dummy\n"); + + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; + + + memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) { - IPACMERR("Got IPv6 flt rule but without IPv6 src/dst addr.\n"); + IPACMERR("Error modifying filtering rule.\n"); res = IPACM_FAILURE; goto fail; } - IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x\n", src_v6_addr[0], src_v6_addr[1], - src_v6_addr[2], src_v6_addr[3], dst_v6_addr[0], dst_v6_addr[1], dst_v6_addr[2], dst_v6_addr[3]); + else + { + IPACMDBG_H("Flt rule reset to dummy, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, + pFilteringTable->rules[0].status); + } + } + else + { + IPACMERR("IP type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + +fail: + free(pFilteringTable); + return res; +} + +void IPACM_Lan::post_del_self_evt() +{ + ipacm_cmd_q_data evt; + ipacm_event_data_fid* fid; + fid = (ipacm_event_data_fid*)malloc(sizeof(ipacm_event_data_fid)); + if(fid == NULL) + { + IPACMERR("Failed to allocate fid memory.\n"); + return; + } + memset(fid, 0, sizeof(ipacm_event_data_fid)); + memset(&evt, 0, sizeof(ipacm_cmd_q_data)); + + fid->if_index = ipa_if_num; + + evt.evt_data = (void*)fid; + evt.event = IPA_LAN_DELETE_SELF; + + IPACMDBG_H("Posting event IPA_LAN_DELETE_SELF\n"); + IPACM_EvtDispatcher::PostEvt(&evt); +} + +/*handle reset usb-client rt-rules */ +int IPACM_Lan::handle_lan_client_reset_rt(ipa_ip_type iptype) +{ + int i, res = IPACM_SUCCESS; - if(false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6)) + /* clean eth-client routing rules */ + IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client); + for (i = 0; i < num_eth_client; i++) + { + res = delete_eth_rtrules(i, iptype); + if (res != IPACM_SUCCESS) { - IPACMERR("Failed to get routing table %s handle.\n", IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6.name); - res = IPACM_FAILURE; - goto fail; + IPACMERR("Failed to delete old iptype(%d) rules.\n", iptype); + return res; } - IPACMDBG_H("Routing handle for table %s: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6.name, - IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6.hdl); + } /* end of for loop */ - flt_rule.status = -1; - for(i=0; iipv4_set = false; } - if(i == MAX_OFFLOAD_PAIR) + else { - IPACMERR("Failed to find a filtering rule handle.\n"); - res = IPACM_FAILURE; - goto fail; + get_client_memptr(eth_client, i)->ipv6_set = 0; } + } /* end of for loop */ + return res; +} - flt_rule.rule.retain_hdr = 0; - flt_rule.rule.to_uc = 0; - flt_rule.rule.eq_attrib_type = 0; - flt_rule.rule.action = IPA_PASS_TO_ROUTING; - flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6.hdl; +int IPACM_Lan::install_ipv4_icmp_flt_rule() +{ + int len; + struct ipa_ioc_add_flt_rule* flt_rule; + struct ipa_flt_rule_add flt_rule_entry; - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, - sizeof(flt_rule.rule.attrib)); - IPACMDBG_H("Rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + if(rx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; - flt_rule.rule.attrib.u.v6.src_addr[0] = src_v6_addr[0]; - flt_rule.rule.attrib.u.v6.src_addr[1] = src_v6_addr[1]; - flt_rule.rule.attrib.u.v6.src_addr[2] = src_v6_addr[2]; - flt_rule.rule.attrib.u.v6.src_addr[3] = src_v6_addr[3]; - flt_rule.rule.attrib.u.v6.src_addr_mask[0] = 0xFFFFFFFF; - flt_rule.rule.attrib.u.v6.src_addr_mask[1] = 0xFFFFFFFF; - flt_rule.rule.attrib.u.v6.src_addr_mask[2] = 0xFFFFFFFF; - flt_rule.rule.attrib.u.v6.src_addr_mask[3] = 0xFFFFFFFF; + flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!flt_rule) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + flt_rule->commit = 1; + flt_rule->ep = rx_prop->rx[0].src_pipe; + flt_rule->global = false; + flt_rule->ip = IPA_IP_v4; + flt_rule->num_rules = 1; - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v6.dst_addr[0] = dst_v6_addr[0]; - flt_rule.rule.attrib.u.v6.dst_addr[1] = dst_v6_addr[1]; - flt_rule.rule.attrib.u.v6.dst_addr[2] = dst_v6_addr[2]; - flt_rule.rule.attrib.u.v6.dst_addr[3] = dst_v6_addr[3]; - flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; - flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; - flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; - flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); - memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP; + memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (m_filtering.AddFilteringRule(flt_rule) == false) { - IPACMERR("Error modifying filtering rule.\n"); - res = IPACM_FAILURE; - goto fail; + IPACMERR("Error Adding Filtering rule, aborting...\n"); + free(flt_rule); + return IPACM_FAILURE; } else { - lan2lan_flt_rule_hdl_v6[i].valid = true; - *rule_hdl = lan2lan_flt_rule_hdl_v6[i].rule_hdl; - num_lan2lan_flt_rule_v6++; - IPACMDBG_H("Flt rule modified, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, - pFilteringTable->rules[0].status); + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + ipv4_icmp_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl; + IPACMDBG_H("IPv4 icmp filter rule HDL:0x%x\n", ipv4_icmp_flt_rule_hdl[0]); + free(flt_rule); } } - else + return IPACM_SUCCESS; +} + +int IPACM_Lan::install_ipv6_icmp_flt_rule() +{ + + int len; + struct ipa_ioc_add_flt_rule* flt_rule; + struct ipa_flt_rule_add flt_rule_entry; + + if(rx_prop != NULL) { - IPACMERR("IP type is not expected.\n"); - res = IPACM_FAILURE; - goto fail; - } + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); -fail: - free(pFilteringTable); - return res; + flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!flt_rule) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + flt_rule->commit = 1; + flt_rule->ep = rx_prop->rx[0].src_pipe; + flt_rule->global = false; + flt_rule->ip = IPA_IP_v6; + flt_rule->num_rules = 1; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = false; +#endif + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; + flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; + memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (m_filtering.AddFilteringRule(flt_rule) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + free(flt_rule); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + ipv6_icmp_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl; + IPACMDBG_H("IPv6 icmp filter rule HDL:0x%x\n", ipv6_icmp_flt_rule_hdl[0]); + free(flt_rule); + } + } + return IPACM_SUCCESS; } -int IPACM_Lan::add_dummy_lan2lan_flt_rule(ipa_ip_type iptype) +int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype) { if(rx_prop == NULL) { - IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy lan2lan filtering rule.\n", dev_name); + IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy private subnet filtering rule.\n", dev_name); return 0; } + if(iptype == IPA_IP_v6) + { + IPACMDBG_H("There is no ipv6 dummy filter rules needed for iface %s\n", dev_name); + return 0; + } int i, len, res = IPACM_SUCCESS; struct ipa_flt_rule_add flt_rule; ipa_ioc_add_flt_rule* pFilteringTable; - len = sizeof(struct ipa_ioc_add_flt_rule) + MAX_OFFLOAD_PAIR * sizeof(struct ipa_flt_rule_add); + len = sizeof(struct ipa_ioc_add_flt_rule) + IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(struct ipa_flt_rule_add); pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); if (pFilteringTable == NULL) @@ -3294,7 +3618,7 @@ int IPACM_Lan::add_dummy_lan2lan_flt_rule(ipa_ip_type iptype) pFilteringTable->ep = rx_prop->rx[0].src_pipe; pFilteringTable->global = false; pFilteringTable->ip = iptype; - pFilteringTable->num_rules = MAX_OFFLOAD_PAIR; + pFilteringTable->num_rules = IPA_MAX_PRIVATE_SUBNET_ENTRIES; memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); @@ -3303,7 +3627,9 @@ int IPACM_Lan::add_dummy_lan2lan_flt_rule(ipa_ip_type iptype) flt_rule.flt_rule_hdl = -1; flt_rule.status = -1; flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - +#ifdef FEATURE_IPA_V3 + flt_rule.rule.hashable = true; +#endif memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); @@ -3315,27 +3641,27 @@ int IPACM_Lan::add_dummy_lan2lan_flt_rule(ipa_ip_type iptype) flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; flt_rule.rule.attrib.u.v4.dst_addr = ~0; - for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); } if (false == m_filtering.AddFilteringRule(pFilteringTable)) { - IPACMERR("Error adding dummy lan2lan v4 flt rule\n"); + IPACMERR("Error adding dummy private subnet v4 flt rule\n"); res = IPACM_FAILURE; goto fail; } else { - flt_rule_count_v4 += MAX_OFFLOAD_PAIR; + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES); /* copy filter rule hdls */ - for (int i = 0; i < MAX_OFFLOAD_PAIR; i++) + for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++) { if (pFilteringTable->rules[i].status == 0) { - lan2lan_flt_rule_hdl_v4[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; - IPACMDBG_H("Lan2lan v4 flt rule %d hdl:0x%x\n", i, lan2lan_flt_rule_hdl_v4[i].rule_hdl); + private_fl_rule_hdl[i] = pFilteringTable->rules[i].flt_rule_hdl; + IPACMDBG_H("Private subnet v4 flt rule %d hdl:0x%x\n", i, private_fl_rule_hdl[i]); } else { @@ -3346,992 +3672,16 @@ int IPACM_Lan::add_dummy_lan2lan_flt_rule(ipa_ip_type iptype) } } } - else if(iptype == IPA_IP_v6) - { - flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; +fail: + free(pFilteringTable); + return res; +} - for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); - } - - if (false == m_filtering.AddFilteringRule(pFilteringTable)) - { - IPACMERR("Error adding dummy lan2lan v6 flt rule\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - flt_rule_count_v6 += MAX_OFFLOAD_PAIR; - /* copy filter rule hdls */ - for (int i = 0; i < MAX_OFFLOAD_PAIR; i++) - { - if (pFilteringTable->rules[i].status == 0) - { - lan2lan_flt_rule_hdl_v6[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; - IPACMDBG_H("Lan2lan v6 flt rule %d hdl:0x%x\n", i, lan2lan_flt_rule_hdl_v6[i].rule_hdl); - } - else - { - IPACMERR("Failed adding lan2lan v6 flt rule %d\n", i); - res = IPACM_FAILURE; - goto fail; - } - } - } - } - else - { - IPACMERR("IP type is not expected.\n"); - goto fail; - } - -fail: - free(pFilteringTable); - return res; -} - -int IPACM_Lan::del_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl) -{ - int i; - - IPACMDBG_H("Del lan2lan flt rule with IP type: %d hdl: %d\n", iptype, rule_hdl); - if(iptype == IPA_IP_v4) - { - for(i=0; icommit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = 1; - - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - flt_rule.status = -1; - flt_rule.rule_hdl = rule_hdl; - - flt_rule.rule.retain_hdr = 0; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - - if(iptype == IPA_IP_v4) - { - IPACMDBG_H("Reset IPv4 flt rule to dummy\n"); - - flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v4.dst_addr = ~0; - flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; - flt_rule.rule.attrib.u.v4.src_addr = ~0; - flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; - - memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) - { - IPACMERR("Error modifying filtering rule.\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - IPACMDBG_H("Flt rule reset to dummy, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, - pFilteringTable->rules[0].status); - } - } - else if(iptype == IPA_IP_v6) - { - IPACMDBG_H("Reset IPv6 flt rule to dummy\n"); - - flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; - - - memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) - { - IPACMERR("Error modifying filtering rule.\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - IPACMDBG_H("Flt rule reset to dummy, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, - pFilteringTable->rules[0].status); - } - } - else - { - IPACMERR("IP type is not expected.\n"); - res = IPACM_FAILURE; - goto fail; - } - -fail: - free(pFilteringTable); - return res; -} - -int IPACM_Lan::add_lan2lan_hdr(ipa_ip_type iptype, uint8_t* src_mac, uint8_t* dst_mac, uint32_t* hdr_hdl) -{ - if(tx_prop == NULL) - { - IPACMERR("There is no tx_prop, cannot add header.\n"); - return IPACM_FAILURE; - } - if(src_mac == NULL || dst_mac == NULL) - { - IPACMERR("Either src_mac or dst_mac is null, cannot add header.\n"); - return IPACM_FAILURE; - } - if(hdr_hdl == NULL) - { - IPACMERR("Header handle is empty.\n"); - return IPACM_FAILURE; - } - - int i, j, len; - int res = IPACM_SUCCESS; - char index[4]; - struct ipa_ioc_copy_hdr sCopyHeader; - struct ipa_ioc_add_hdr *pHeader; - - IPACMDBG_H("Get lan2lan header request, src_mac: 0x%02x%02x%02x%02x%02x%02x dst_mac: 0x%02x%02x%02x%02x%02x%02x\n", - src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], dst_mac[0], dst_mac[1], - dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]); - - len = sizeof(struct ipa_ioc_add_hdr) + sizeof(struct ipa_hdr_add); - pHeader = (struct ipa_ioc_add_hdr *)malloc(len); - if (pHeader == NULL) - { - IPACMERR("Failed to allocate header\n"); - return IPACM_FAILURE; - } - memset(pHeader, 0, len); - - if(iptype == IPA_IP_v4) - { /* copy partial header for v4*/ - for(i=0; inum_tx_props; i++) - { - if(tx_prop->tx[i].ip == IPA_IP_v4) - { - IPACMDBG_H("Got v4-header name from %d tx props\n", i); - memset(&sCopyHeader, 0, sizeof(sCopyHeader)); - memcpy(sCopyHeader.name, tx_prop->tx[i].hdr_name, sizeof(sCopyHeader.name)); - - IPACMDBG_H("Header name: %s\n", sCopyHeader.name); - if(m_header.CopyHeader(&sCopyHeader) == false) - { - IPACMERR("Copy header failed\n"); - res = IPACM_FAILURE; - goto fail; - } - - IPACMDBG_H("Header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); - if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) - { - IPACMERR("Header oversize\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - memcpy(pHeader->hdr[0].hdr, sCopyHeader.hdr, sCopyHeader.hdr_len); - } - - if(sCopyHeader.is_eth2_ofst_valid) - { - memcpy(&pHeader->hdr[0].hdr[sCopyHeader.eth2_ofst], dst_mac, IPA_MAC_ADDR_SIZE); - memcpy(&pHeader->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], src_mac, IPA_MAC_ADDR_SIZE); - } - else - { - IPACMERR("Ethernet 2 header offset is invalid.\n"); - } - - pHeader->commit = true; - pHeader->num_hdrs = 1; - - memset(pHeader->hdr[0].name, 0, sizeof(pHeader->hdr[0].name)); - strlcpy(pHeader->hdr[0].name, IPA_LAN_TO_LAN_USB_HDR_NAME_V4, sizeof(pHeader->hdr[0].name)); - - for(j=0; jhdr[0].name, index, sizeof(pHeader->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) - { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeader->hdr[0].name)); - res = IPACM_FAILURE; - goto fail; - } - - pHeader->hdr[0].hdr_len = sCopyHeader.hdr_len; - pHeader->hdr[0].is_partial = 0; - pHeader->hdr[0].hdr_hdl = -1; - pHeader->hdr[0].status = -1; - - if (m_header.AddHeader(pHeader) == false || pHeader->hdr[0].status != 0) - { - IPACMERR("Ioctl IPA_IOC_ADD_HDR failed with status: %d\n", pHeader->hdr[0].status); - res = IPACM_FAILURE; - goto fail; - } - IPACMDBG_H("Installed v4 full header %s header handle 0x%08x\n", pHeader->hdr[0].name, - pHeader->hdr[0].hdr_hdl); - *hdr_hdl = pHeader->hdr[0].hdr_hdl; - lan2lan_hdr_hdl_v4[j].hdr_hdl = pHeader->hdr[0].hdr_hdl; - break; - } - } - } - else if(iptype == IPA_IP_v6) - { /* copy partial header for v6*/ - for(i=0; inum_tx_props; i++) - { - if(tx_prop->tx[i].ip == IPA_IP_v6) - { - IPACMDBG_H("Got v6-header name from %d tx props\n", i); - memset(&sCopyHeader, 0, sizeof(sCopyHeader)); - memcpy(sCopyHeader.name, tx_prop->tx[i].hdr_name, sizeof(sCopyHeader.name)); - - IPACMDBG_H("Header name: %s\n", sCopyHeader.name); - if(m_header.CopyHeader(&sCopyHeader) == false) - { - IPACMERR("Copy header failed\n"); - res = IPACM_FAILURE; - goto fail; - } - - IPACMDBG_H("Header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); - if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) - { - IPACMERR("Header oversize\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - memcpy(pHeader->hdr[0].hdr, sCopyHeader.hdr, sCopyHeader.hdr_len); - } - if(sCopyHeader.is_eth2_ofst_valid) - { - memcpy(&pHeader->hdr[0].hdr[sCopyHeader.eth2_ofst], dst_mac, IPA_MAC_ADDR_SIZE); - memcpy(&pHeader->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], src_mac, IPA_MAC_ADDR_SIZE); - } - else - { - IPACMERR("Ethernet 2 header offset is invalid.\n"); - } - - pHeader->commit = true; - pHeader->num_hdrs = 1; - - memset(pHeader->hdr[0].name, 0, sizeof(pHeader->hdr[0].name)); - strlcpy(pHeader->hdr[0].name, IPA_LAN_TO_LAN_USB_HDR_NAME_V6, sizeof(pHeader->hdr[0].name)); - - for(j=0; jhdr[0].name, index, sizeof(pHeader->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) - { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeader->hdr[0].name)); - res = IPACM_FAILURE; - goto fail; - } - - pHeader->hdr[0].hdr_len = sCopyHeader.hdr_len; - pHeader->hdr[0].is_partial = 0; - pHeader->hdr[0].hdr_hdl = -1; - pHeader->hdr[0].status = -1; - - if (m_header.AddHeader(pHeader) == false || pHeader->hdr[0].status != 0) - { - IPACMERR("Ioctl IPA_IOC_ADD_HDR failed with status: %d\n", pHeader->hdr[0].status); - res = IPACM_FAILURE; - goto fail; - } - IPACMDBG_H("Installed v6 full header %s header handle 0x%08x\n", pHeader->hdr[0].name, - pHeader->hdr[0].hdr_hdl); - *hdr_hdl = pHeader->hdr[0].hdr_hdl; - lan2lan_hdr_hdl_v6[j].hdr_hdl = pHeader->hdr[0].hdr_hdl; - break; - } - } - } - else - { - IPACMERR("IP type is not expected.\n"); - } - -fail: - free(pHeader); - return res; -} - -int IPACM_Lan::del_lan2lan_hdr(ipa_ip_type iptype, uint32_t hdr_hdl) -{ - int i; - if (m_header.DeleteHeaderHdl(hdr_hdl) == false) - { - IPACMERR("Failed to delete header %d\n", hdr_hdl); - return IPACM_FAILURE; - } - IPACMDBG_H("Deleted header %d\n", hdr_hdl); - - if(iptype == IPA_IP_v4) - { - for(i=0; icommit = 1; - rt_rule->num_rules = 1; - rt_rule->ip = iptype; - - if(iptype == IPA_IP_v4) - { - IPACMDBG_H("src_v4_addr: 0x%08x dst_v4_addr: 0x%08x\n", src_v4_addr, dst_v4_addr); - - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4.name); - rt_rule_entry = &rt_rule->rules[0]; - rt_rule_entry->at_rear = false; - rt_rule_entry->rt_rule_hdl = 0; - rt_rule_entry->status = -1; - - for (tx_index = 0; tx_indexnum_tx_props; tx_index++) - { - if(tx_prop->tx[tx_index].ip != IPA_IP_v4) - { - IPACMDBG_H("Tx:%d, iptype: %d conflict ip-type: %d bypass\n", - tx_index, tx_prop->tx[tx_index].ip, IPA_IP_v4); - continue; - } - - rt_rule_entry->rule.hdr_hdl = hdr_hdl; - rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; - memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[tx_index].attrib, - sizeof(rt_rule_entry->rule.attrib)); - - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; - rt_rule_entry->rule.attrib.u.v4.src_addr = src_v4_addr; - rt_rule_entry->rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF; - - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - rt_rule_entry->rule.attrib.u.v4.dst_addr = dst_v4_addr; - rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; - - if(m_routing.AddRoutingRule(rt_rule) == false) - { - IPACMERR("Routing rule addition failed\n"); - res = IPACM_FAILURE; - goto fail; - } - IPACMDBG_H("Added rt rule hdl: 0x%08x\n", rt_rule_entry->rt_rule_hdl); - rule_hdl->rule_hdl[rule_hdl->num_rule] = rt_rule_entry->rt_rule_hdl; - rule_hdl->num_rule++; - } - } - else if(iptype == IPA_IP_v6) - { - if(src_v6_addr == NULL || dst_v6_addr == NULL) - { - IPACMERR("Got IPv6 rt rule but without IPv6 src/dst addr.\n"); - res = IPACM_FAILURE; - goto fail; - } - IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x\n", src_v6_addr[0], src_v6_addr[1], - src_v6_addr[2], src_v6_addr[3], dst_v6_addr[0], dst_v6_addr[1], dst_v6_addr[2], dst_v6_addr[3]); - - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6.name); - rt_rule_entry = &rt_rule->rules[0]; - rt_rule_entry->at_rear = false; - rt_rule_entry->rt_rule_hdl = 0; - rt_rule_entry->status = -1; - - for (tx_index = 0; tx_indexnum_tx_props; tx_index++) - { - if(tx_prop->tx[tx_index].ip != IPA_IP_v6) - { - IPACMDBG_H("Tx:%d, iptype: %d conflict ip-type: %d bypass\n", - tx_index, tx_prop->tx[tx_index].ip, IPA_IP_v6); - continue; - } - - rt_rule_entry->rule.hdr_hdl = hdr_hdl; - rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; - memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[tx_index].attrib, - sizeof(rt_rule_entry->rule.attrib)); - - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; - rt_rule_entry->rule.attrib.u.v6.src_addr[0] = src_v6_addr[0]; - rt_rule_entry->rule.attrib.u.v6.src_addr[1] = src_v6_addr[1]; - rt_rule_entry->rule.attrib.u.v6.src_addr[2] = src_v6_addr[2]; - rt_rule_entry->rule.attrib.u.v6.src_addr[3] = src_v6_addr[3]; - rt_rule_entry->rule.attrib.u.v6.src_addr_mask[0] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.src_addr_mask[1] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.src_addr_mask[2] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.src_addr_mask[3] = 0xFFFFFFFF; - - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = dst_v6_addr[0]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = dst_v6_addr[1]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = dst_v6_addr[2]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = dst_v6_addr[3]; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; - - if(m_routing.AddRoutingRule(rt_rule) == false) - { - IPACMERR("Routing rule addition failed\n"); - res = IPACM_FAILURE; - goto fail; - } - IPACMDBG_H("Added rt rule hdl: 0x%08x\n", rt_rule_entry->rt_rule_hdl); - rule_hdl->rule_hdl[rule_hdl->num_rule] = rt_rule_entry->rt_rule_hdl; - rule_hdl->num_rule++; - } - } - else - { - IPACMERR("IP type is not expected.\n"); - } - -fail: - free(rt_rule); - return res; -} - -int IPACM_Lan::del_lan2lan_rt_rule(ipa_ip_type iptype, lan_to_lan_rt_rule_hdl rule_hdl) -{ - if(rule_hdl.num_rule <= 0 || rule_hdl.num_rule > MAX_NUM_PROP) - { - IPACMERR("The number of rule handles are not correct.\n"); - return IPACM_FAILURE; - } - - int i, res = IPACM_SUCCESS; - - IPACMDBG_H("Get %d rule handles with IP type %d\n", rule_hdl.num_rule, iptype); - for(i=0; iif_index = ipa_if_num; - - evt.evt_data = (void*)fid; - evt.event = IPA_LAN_DELETE_SELF; - - IPACMDBG_H("Posting event IPA_LAN_DELETE_SELF\n"); - IPACM_EvtDispatcher::PostEvt(&evt); -} - -/*handle reset usb-client rt-rules */ -int IPACM_Lan::handle_lan_client_reset_rt(ipa_ip_type iptype) -{ - int i, res = IPACM_SUCCESS; - - /* clean eth-client routing rules */ - IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client); - for (i = 0; i < num_eth_client; i++) - { - res = delete_eth_rtrules(i, iptype); - if (res != IPACM_SUCCESS) - { - IPACMERR("Failed to delete old iptype(%d) rules.\n", iptype); - return res; - } - } /* end of for loop */ - - /* Pass info to LAN2LAN module */ - res = post_lan2lan_client_disconnect_msg(iptype); - if (res != IPACM_SUCCESS) - { - IPACMERR("Failed to posting delete old iptype(%d) address.\n", iptype); - return res; - } - /* Reset ip-address */ - for (i = 0; i < num_eth_client; i++) - { - if(iptype == IPA_IP_v4) - { - get_client_memptr(eth_client, i)->ipv4_set = false; - } - else - { - get_client_memptr(eth_client, i)->ipv6_set = 0; - } - } /* end of for loop */ - return res; -} - -/*handle lan2lan internal mesg posting*/ -int IPACM_Lan::post_lan2lan_client_disconnect_msg(ipa_ip_type iptype) -{ - int i, j; - ipacm_cmd_q_data evt_data; - ipacm_event_lan_client* lan_client; - - for (i = 0; i < num_eth_client; i++) - { - if((get_client_memptr(eth_client, i)->ipv4_set == true) - && (iptype == IPA_IP_v4)) - { - lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); - if(lan_client == NULL) - { - IPACMERR("Failed to allocate memory.\n"); - return IPACM_FAILURE; - } - memset(lan_client, 0, sizeof(ipacm_event_lan_client)); - lan_client->iptype = IPA_IP_v4; - lan_client->ipv4_addr = get_client_memptr(eth_client, i)->v4_addr; - lan_client->p_iface = this; - - memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); - evt_data.evt_data = (void*)lan_client; - evt_data.event = IPA_LAN_CLIENT_DISCONNECT; - - IPACMDBG_H("Posting event IPA_LAN_CLIENT_DISCONNECT\n"); - IPACM_EvtDispatcher::PostEvt(&evt_data); - } - - if((get_client_memptr(eth_client, i)->ipv6_set > 0) - && (iptype == IPA_IP_v6)) - { - for (j = 0; j < get_client_memptr(eth_client, i)->ipv6_set; j++) - { - lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); - if(lan_client == NULL) - { - IPACMERR("Failed to allocate memory.\n"); - return IPACM_FAILURE; - } - memset(lan_client, 0, sizeof(ipacm_event_lan_client)); - lan_client->iptype = IPA_IP_v6; - lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0]; - lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0]; - lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0]; - lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0]; - lan_client->p_iface = this; - - memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); - evt_data.evt_data = (void*)lan_client; - evt_data.event = IPA_LAN_CLIENT_DISCONNECT; - - IPACMDBG_H("Posting event IPA_LAN_CLIENT_DISCONNECT\n"); - IPACM_EvtDispatcher::PostEvt(&evt_data); - } - } - } /* end of for loop */ - return IPACM_SUCCESS; -} - -void IPACM_Lan::install_tcp_ctl_flt_rule(ipa_ip_type iptype) -{ - if (rx_prop == NULL) - { - IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); - return; - } - - int len, i; - struct ipa_flt_rule_add flt_rule; - ipa_ioc_add_flt_rule* pFilteringTable; - - len = sizeof(struct ipa_ioc_add_flt_rule) + NUM_TCP_CTL_FLT_RULE * sizeof(struct ipa_flt_rule_add); - - pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); - if (pFilteringTable == NULL) - { - IPACMERR("Error allocate flt table memory...\n"); - return; - } - memset(pFilteringTable, 0, len); - - pFilteringTable->commit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->ep = rx_prop->rx[0].src_pipe; - pFilteringTable->global = false; - pFilteringTable->num_rules = NUM_TCP_CTL_FLT_RULE; - - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); - - flt_rule.at_rear = true; - flt_rule.flt_rule_hdl = -1; - flt_rule.status = -1; - - flt_rule.rule.retain_hdr = 1; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - flt_rule.rule.eq_attrib_type = 1; - - flt_rule.rule.eq_attrib.rule_eq_bitmap = 0; - - flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<14); - flt_rule.rule.eq_attrib.metadata_meq32_present = 1; - flt_rule.rule.eq_attrib.metadata_meq32.offset = 0; - flt_rule.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data; - flt_rule.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask; - - flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<1); - flt_rule.rule.eq_attrib.protocol_eq_present = 1; - flt_rule.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; - - flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<8); - flt_rule.rule.eq_attrib.num_ihl_offset_meq_32 = 1; - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; - - /* add TCP FIN rule*/ - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_add)); - - /* add TCP SYN rule*/ - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[1]), &flt_rule, sizeof(struct ipa_flt_rule_add)); - - /* add TCP RST rule*/ - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[2]), &flt_rule, sizeof(struct ipa_flt_rule_add)); - - if (false == m_filtering.AddFilteringRule(pFilteringTable)) - { - IPACMERR("Error adding tcp control flt rule\n"); - goto fail; - } - else - { - if(iptype == IPA_IP_v4) - { - for(i=0; irules[i].flt_rule_hdl; - } - } - else - { - for(i=0; irules[i].flt_rule_hdl; - } - } - } - -fail: - free(pFilteringTable); - return; -} - -int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype) -{ - if(rx_prop == NULL) - { - IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy private subnet filtering rule.\n", dev_name); - return 0; - } - - if(iptype == IPA_IP_v6) - { - IPACMDBG_H("There is no ipv6 dummy filter rules needed for iface %s\n", dev_name); - return 0; - } - int i, len, res = IPACM_SUCCESS; - struct ipa_flt_rule_add flt_rule; - ipa_ioc_add_flt_rule* pFilteringTable; - - len = sizeof(struct ipa_ioc_add_flt_rule) + IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(struct ipa_flt_rule_add); - - pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); - if (pFilteringTable == NULL) - { - IPACMERR("Error allocate flt table memory...\n"); - return IPACM_FAILURE; - } - memset(pFilteringTable, 0, len); - - pFilteringTable->commit = 1; - pFilteringTable->ep = rx_prop->rx[0].src_pipe; - pFilteringTable->global = false; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = IPA_MAX_PRIVATE_SUBNET_ENTRIES; - - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); - - flt_rule.rule.retain_hdr = 0; - flt_rule.at_rear = true; - flt_rule.flt_rule_hdl = -1; - flt_rule.status = -1; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, - sizeof(flt_rule.rule.attrib)); - - if(iptype == IPA_IP_v4) - { - flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; - flt_rule.rule.attrib.u.v4.src_addr = ~0; - flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; - flt_rule.rule.attrib.u.v4.dst_addr = ~0; - - for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); - } - - if (false == m_filtering.AddFilteringRule(pFilteringTable)) - { - IPACMERR("Error adding dummy private subnet v4 flt rule\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - flt_rule_count_v4 += IPA_MAX_PRIVATE_SUBNET_ENTRIES; - /* copy filter rule hdls */ - for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++) - { - if (pFilteringTable->rules[i].status == 0) - { - private_fl_rule_hdl[i] = pFilteringTable->rules[i].flt_rule_hdl; - IPACMDBG_H("Private subnet v4 flt rule %d hdl:0x%x\n", i, private_fl_rule_hdl[i]); - } - else - { - IPACMERR("Failed adding lan2lan v4 flt rule %d\n", i); - res = IPACM_FAILURE; - goto fail; - } - } - } - } -fail: - free(pFilteringTable); - return res; -} - -int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype) -{ - int i, len, res = IPACM_SUCCESS; - struct ipa_flt_rule_mdfy flt_rule; - struct ipa_ioc_mdfy_flt_rule* pFilteringTable; +int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype) +{ + int i, len, res = IPACM_SUCCESS; + struct ipa_flt_rule_mdfy flt_rule; + struct ipa_ioc_mdfy_flt_rule* pFilteringTable; if (rx_prop == NULL) { @@ -4448,9 +3798,10 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix) flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); - flt_rule_entry.rule.attrib.attrib_mask = flt_rule_entry.rule.attrib.attrib_mask & ~((uint32_t)IPA_FLT_META_DATA); flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = prefix[0]; flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = prefix[1]; @@ -4470,1274 +3821,1577 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); ipv6_prefix_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl; IPACMDBG_H("IPv6 prefix filter rule HDL:0x%x\n", ipv6_prefix_flt_rule_hdl[0]); - flt_rule_count_v6++; free(flt_rule); } } return IPACM_SUCCESS; } -int IPACM_Lan::install_ipv6_icmp_flt_rule() +void IPACM_Lan::delete_ipv6_prefix_flt_rule() { + if(m_filtering.DeleteFilteringHdls(ipv6_prefix_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE) == false) + { + IPACMERR("Failed to delete ipv6 prefix flt rule.\n"); + return; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE); + return; +} - int len; - struct ipa_ioc_add_flt_rule* flt_rule; - struct ipa_flt_rule_add flt_rule_entry; - - if(rx_prop != NULL) +int IPACM_Lan::handle_addr_evt_odu_bridge(ipacm_event_data_addr* data) +{ + int fd, res = IPACM_SUCCESS; + struct in6_addr ipv6_addr; + if(data == NULL) { - len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + IPACMERR("Failed to get interface IP address.\n"); + return IPACM_FAILURE; + } - flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len); - if (!flt_rule) + if(data->iptype == IPA_IP_v6) + { + fd = open(IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU, O_RDWR); + if(fd == 0) { - IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + IPACMERR("Failed to open %s.\n", IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU); return IPACM_FAILURE; } - flt_rule->commit = 1; - flt_rule->ep = rx_prop->rx[0].src_pipe; - flt_rule->global = false; - flt_rule->ip = IPA_IP_v6; - flt_rule->num_rules = 1; + memcpy(&ipv6_addr, data->ipv6_addr, sizeof(struct in6_addr)); - memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + if( ioctl(fd, ODU_BRIDGE_IOC_SET_LLV6_ADDR, &ipv6_addr) ) + { + IPACMERR("Failed to write IPv6 address to odu driver.\n"); + res = IPACM_FAILURE; + } + num_dft_rt_v6++; + close(fd); + } - flt_rule_entry.rule.retain_hdr = 1; - flt_rule_entry.rule.to_uc = 0; - flt_rule_entry.rule.eq_attrib_type = 0; - flt_rule_entry.at_rear = true; - flt_rule_entry.flt_rule_hdl = -1; - flt_rule_entry.status = -1; - flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + return res; +} - memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); - flt_rule_entry.rule.attrib.attrib_mask = flt_rule_entry.rule.attrib.attrib_mask & ~((uint32_t)IPA_FLT_META_DATA); - flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; - flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; - memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); +ipa_hdr_proc_type IPACM_Lan::eth_bridge_get_hdr_proc_type(ipa_hdr_l2_type t1, ipa_hdr_l2_type t2) +{ + if(t1 == IPA_HDR_L2_ETHERNET_II) + { + if(t2 == IPA_HDR_L2_ETHERNET_II) + { + return IPA_HDR_PROC_ETHII_TO_ETHII; + } + if(t2 == IPA_HDR_L2_802_3) + { + return IPA_HDR_PROC_ETHII_TO_802_3; + } + } - if (m_filtering.AddFilteringRule(flt_rule) == false) + if(t1 == IPA_HDR_L2_802_3) + { + if(t2 == IPA_HDR_L2_ETHERNET_II) { - IPACMERR("Error Adding Filtering rule, aborting...\n"); - free(flt_rule); - return IPACM_FAILURE; + return IPA_HDR_PROC_802_3_TO_ETHII; } - else + if(t2 == IPA_HDR_L2_802_3) { - ipv6_icmp_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl; - IPACMDBG_H("IPv6 icmp filter rule HDL:0x%x\n", ipv6_icmp_flt_rule_hdl[0]); - flt_rule_count_v6++; - free(flt_rule); + return IPA_HDR_PROC_802_3_TO_802_3; } } + + return IPA_HDR_PROC_NONE; +} + +int IPACM_Lan::eth_bridge_get_hdr_template_hdl(uint32_t* hdr_hdl) +{ + if(hdr_hdl == NULL) + { + IPACMDBG_H("Hdr handle pointer is empty.\n"); + return IPACM_FAILURE; + } + + struct ipa_ioc_get_hdr hdr; + memset(&hdr, 0, sizeof(hdr)); + + memcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get template hdr hdl.\n"); + return IPACM_FAILURE; + } + + *hdr_hdl = hdr.hdl; return IPACM_SUCCESS; } -int IPACM_Lan::handle_addr_evt_odu_bridge(ipacm_event_data_addr* data) +int IPACM_Lan::handle_cradle_wan_mode_switch(bool is_wan_bridge_mode) { - int fd, res = IPACM_SUCCESS; - struct in6_addr ipv6_addr; - if(data == NULL) + struct ipa_flt_rule_mdfy flt_rule_entry; + int len = 0; + ipa_ioc_mdfy_flt_rule *m_pFilteringTable; + + IPACMDBG_H("Handle wan mode swtich: is wan bridge mode?%d\n", is_wan_bridge_mode); + + if (rx_prop == NULL) { - IPACMERR("Failed to get interface IP address.\n"); - return IPACM_FAILURE; + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; } - if(data->iptype == IPA_IP_v6) + len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (1 * sizeof(struct ipa_flt_rule_mdfy)); + m_pFilteringTable = (struct ipa_ioc_mdfy_flt_rule *)calloc(1, len); + if (m_pFilteringTable == NULL) { - fd = open(IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU, O_RDWR); - if(fd == 0) - { - IPACMERR("Failed to open %s.\n", IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU); - return IPACM_FAILURE; - } + PERROR("Error Locate ipa_ioc_mdfy_flt_rule memory...\n"); + return IPACM_FAILURE; + } - memcpy(&ipv6_addr, data->ipv6_addr, sizeof(struct in6_addr)); + m_pFilteringTable->commit = 1; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)1; - if( ioctl(fd, ODU_BRIDGE_IOC_SET_LLV6_ADDR, &ipv6_addr) ) - { - IPACMERR("Failed to write IPv6 address to odu driver.\n"); - res = IPACM_FAILURE; - } - num_dft_rt_v6++; - close(fd); + IPACMDBG_H("Retrieving routing hanle for table: %s\n", + IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name); + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4)) + { + IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4=0x%p) Failed.\n", + &IPACM_Iface::ipacmcfg->rt_tbl_wan_v4); + free(m_pFilteringTable); + return IPACM_FAILURE; } + IPACMDBG_H("Routing handle for table: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl); - return res; -} -int IPACM_Lan::eth_bridge_handle_dummy_wlan_client_flt_rule(ipa_ip_type iptype) -{ - if(rx_prop == NULL) + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_mdfy)); // Zero All Fields + flt_rule_entry.status = -1; + flt_rule_entry.rule_hdl = lan_wan_fl_rule_hdl[0]; + + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + if(is_wan_bridge_mode) { - IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy wlan client specific filtering rule.\n", dev_name); - return 0; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; } + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl; - int i, len, res = IPACM_SUCCESS; - struct ipa_flt_rule_add flt_rule; - ipa_ioc_add_flt_rule* pFilteringTable; + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); - len = sizeof(struct ipa_ioc_add_flt_rule) + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(struct ipa_flt_rule_add); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0; - pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); - if (pFilteringTable == NULL) + memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry)); + if (false == m_filtering.ModifyFilteringRule(m_pFilteringTable)) { - IPACMERR("Error allocate flt table memory...\n"); + IPACMERR("Error Modifying RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); return IPACM_FAILURE; } - memset(pFilteringTable, 0, len); + else + { + IPACMDBG_H("flt rule hdl = %d, status = %d\n", + m_pFilteringTable->rules[0].rule_hdl, + m_pFilteringTable->rules[0].status); + } + free(m_pFilteringTable); + return IPACM_SUCCESS; +} - pFilteringTable->commit = 1; - pFilteringTable->ep = rx_prop->rx[0].src_pipe; - pFilteringTable->global = false; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; +/*handle reset usb-client rt-rules */ +int IPACM_Lan::handle_tethering_stats_event(ipa_get_data_stats_resp_msg_v01 *data) +{ + int cnt, pipe_len, fd; + uint64_t num_ul_packets, num_ul_bytes; + uint64_t num_dl_packets, num_dl_bytes; + bool ul_pipe_found, dl_pipe_found; + FILE *fp = NULL; - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } - flt_rule.rule.retain_hdr = 0; - flt_rule.at_rear = true; - flt_rule.flt_rule_hdl = -1; - flt_rule.status = -1; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, - sizeof(flt_rule.rule.attrib)); + ul_pipe_found = false; + dl_pipe_found = false; + num_ul_packets = 0; + num_dl_packets = 0; + num_ul_bytes = 0; + num_dl_bytes = 0; - if(iptype == IPA_IP_v4) + if (data->dl_dst_pipe_stats_list_valid) { - flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; - flt_rule.rule.attrib.u.v4.src_addr = ~0; - flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; - flt_rule.rule.attrib.u.v4.dst_addr = ~0; - - for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); - } - - if (false == m_filtering.AddFilteringRule(pFilteringTable)) - { - IPACMERR("Error adding dummy lan2lan v4 flt rule\n"); - res = IPACM_FAILURE; - goto fail; - } - else + if(tx_prop != NULL) { - flt_rule_count_v4 += IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; - /* copy filter rule hdls */ - for (int i = 0; i < IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; i++) + for (pipe_len = 0; pipe_len < data->dl_dst_pipe_stats_list_len; pipe_len++) { - if (pFilteringTable->rules[i].status == 0) - { - wlan_client_flt_rule_hdl_v4[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; - wlan_client_flt_rule_hdl_v4[i].valid = true; - IPACMDBG_H("Wlan client v4 flt rule %d hdl:0x%x\n", i, wlan_client_flt_rule_hdl_v4[i].rule_hdl); - } - else + IPACMDBG_H("Check entry(%d) dl_dst_pipe(%d)\n", pipe_len, data->dl_dst_pipe_stats_list[pipe_len].pipe_index); + for (cnt=0; cntnum_tx_props; cnt++) { - IPACMERR("Failed adding wlan client v4 flt rule %d\n", i); - res = IPACM_FAILURE; - goto fail; + IPACMDBG_H("Check Tx_prop_entry(%d) pipe(%d)\n", cnt, ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe)); + if(ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe) == data->dl_dst_pipe_stats_list[pipe_len].pipe_index) + { + /* update the DL stats */ + dl_pipe_found = true; + num_dl_packets += data->dl_dst_pipe_stats_list[pipe_len].num_ipv4_packets; + num_dl_packets += data->dl_dst_pipe_stats_list[pipe_len].num_ipv6_packets; + num_dl_bytes += data->dl_dst_pipe_stats_list[pipe_len].num_ipv4_bytes; + num_dl_bytes += data->dl_dst_pipe_stats_list[pipe_len].num_ipv6_bytes; + IPACMDBG_H("Got matched dst-pipe (%d) from %d tx props\n", data->dl_dst_pipe_stats_list[pipe_len].pipe_index, cnt); + IPACMDBG_H("DL_packets:(%lu) DL_bytes:(%lu) \n", num_dl_packets, num_dl_bytes); + break; + } } } } } - else if(iptype == IPA_IP_v6) - { - flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; - for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); - } - - if (false == m_filtering.AddFilteringRule(pFilteringTable)) - { - IPACMERR("Error adding dummy lan2lan v6 flt rule\n"); - res = IPACM_FAILURE; - goto fail; - } - else + if (data->ul_src_pipe_stats_list_valid) + { + if(rx_prop != NULL) { - flt_rule_count_v6 += IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; - /* copy filter rule hdls */ - for (int i = 0; i < IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; i++) + for (pipe_len = 0; pipe_len < data->ul_src_pipe_stats_list_len; pipe_len++) { - if (pFilteringTable->rules[i].status == 0) - { - wlan_client_flt_rule_hdl_v6[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; - wlan_client_flt_rule_hdl_v6[i].valid = true; - IPACMDBG_H("Wlan client v6 flt rule %d hdl:0x%x\n", i, wlan_client_flt_rule_hdl_v6[i].rule_hdl); - } - else + IPACMDBG_H("Check entry(%d) dl_dst_pipe(%d)\n", pipe_len, data->ul_src_pipe_stats_list[pipe_len].pipe_index); + for (cnt=0; cnt < rx_prop->num_rx_props; cnt++) { - IPACMERR("Failed adding wlan client v6 flt rule %d\n", i); - res = IPACM_FAILURE; - goto fail; + IPACMDBG_H("Check Rx_prop_entry(%d) pipe(%d)\n", cnt, ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe)); + if(ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe) == data->ul_src_pipe_stats_list[pipe_len].pipe_index) + { + /* update the UL stats */ + ul_pipe_found = true; + num_ul_packets += data->ul_src_pipe_stats_list[pipe_len].num_ipv4_packets; + num_ul_packets += data->ul_src_pipe_stats_list[pipe_len].num_ipv6_packets; + num_ul_bytes += data->ul_src_pipe_stats_list[pipe_len].num_ipv4_bytes; + num_ul_bytes += data->ul_src_pipe_stats_list[pipe_len].num_ipv6_bytes; + IPACMDBG_H("Got matched dst-pipe (%d) from %d tx props\n", data->ul_src_pipe_stats_list[pipe_len].pipe_index, cnt); + IPACMDBG_H("UL_packets:(%lu) UL_bytes:(%lu) \n", num_ul_packets, num_ul_bytes); + break; + } } } } } - else - { - IPACMERR("IP type is not expected.\n"); - goto fail; - } + close(fd); -fail: - free(pFilteringTable); - return res; -} + if (ul_pipe_found || dl_pipe_found) + { + IPACMDBG_H("Update IPA_TETHERING_STATS_UPDATE_EVENT, TX(P%lu/B%lu) RX(P%lu/B%lu) DEV(%s) to LTE(%s) \n", + num_ul_packets, + num_ul_bytes, + num_dl_packets, + num_dl_bytes, + dev_name, + IPACM_Wan::wan_up_dev_name); + fp = fopen(IPA_PIPE_STATS_FILE_NAME, "w"); + if ( fp == NULL ) + { + IPACMERR("Failed to write pipe stats to %s, error is %d - %s\n", + IPA_PIPE_STATS_FILE_NAME, errno, strerror(errno)); + return IPACM_FAILURE; + } -int IPACM_Lan::eth_bridge_add_wlan_guest_ap_flt_rule(ipa_ip_type iptype) -{ - IPACMDBG_H("No need to add WLAN guest AP flt rule on USB pipe.\n"); + fprintf(fp, PIPE_STATS, + dev_name, + IPACM_Wan::wan_up_dev_name, + num_ul_bytes, + num_ul_packets, + num_dl_bytes, + num_dl_packets); + fclose(fp); + } return IPACM_SUCCESS; } -int IPACM_Lan::eth_bridge_handle_dummy_usb_client_flt_rule(ipa_ip_type iptype) +/*handle tether client */ +int IPACM_Lan::handle_tethering_client(bool reset, ipacm_client_enum ipa_client) { - IPACMDBG_H("No need to add USB client specific flt rule on USB pipe.\n"); - return IPACM_SUCCESS; -} + int cnt, fd, ret = IPACM_SUCCESS; + int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); + wan_ioctl_set_tether_client_pipe tether_client; -int IPACM_Lan::eth_bridge_post_lan_client_event(uint8_t* mac_addr, ipa_cm_event_id evt) -{ - if(mac_addr == NULL) + if(fd_wwan_ioctl < 0) { - IPACMERR("Event mac is empty.\n"); + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); return IPACM_FAILURE; } - ipacm_cmd_q_data evt_data; - memset(&evt_data, 0, sizeof(evt_data)); - - ipacm_event_data_mac* mac; - mac = (ipacm_event_data_mac*)malloc(sizeof(ipacm_event_data_mac)); - if(mac == NULL) + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) { - IPACMERR("Unable to allocate memory.\n"); + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + close(fd_wwan_ioctl); return IPACM_FAILURE; } - memset(mac, 0, sizeof(ipacm_event_data_mac)); - memcpy(mac->mac_addr, mac_addr, 6 * sizeof(uint8_t)); - - evt_data.event = evt; - evt_data.evt_data = (void*)mac; - IPACMDBG_H("Posting event: %d\n", evt); - IPACM_EvtDispatcher::PostEvt(&evt_data); - return IPACM_SUCCESS; -} -int IPACM_Lan::eth_bridge_add_wlan_client_flt_rule(uint8_t* mac, ipa_ip_type iptype) -{ - int i, len, res = IPACM_SUCCESS, client_position; - struct ipa_flt_rule_mdfy flt_rule; - struct ipa_ioc_mdfy_flt_rule* pFilteringTable = NULL; - bool client_is_found = false; + memset(&tether_client, 0, sizeof(tether_client)); + tether_client.reset_client = reset; + tether_client.ipa_client = ipa_client; - if (rx_prop == NULL) - { - IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); - return IPACM_FAILURE; - } - if(mac == NULL) - { - IPACMERR("MAC address is empty.\n"); - return IPACM_FAILURE; - } - if(IPACM_Lan::usb_to_wlan_hdr_proc_ctx.valid == false) + if(tx_prop != NULL) { - IPACMDBG_H("USB to WLAN hdr proc ctx has not been set, don't add client specific flt rule.\n"); - return IPACM_FAILURE; + tether_client.dl_dst_pipe_len = tx_prop->num_tx_props; + for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++) + { + IPACMDBG_H("Tx(%d), dst_pipe: %d, ipa_pipe: %d\n", + cnt, tx_prop->tx[cnt].dst_pipe, + ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe)); + tether_client.dl_dst_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe); + } } - for(i=0; inum_rx_props; + for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++) { - client_is_found = true; - client_position = i; - if( (iptype == IPA_IP_v4 && eth_bridge_wlan_client_flt_info[i].flt_rule_set_v4 == true) - || (iptype == IPA_IP_v6 && eth_bridge_wlan_client_flt_info[i].flt_rule_set_v6 == true)) - { - IPACMDBG_H("Flt rule for iptype %d has been set.\n", iptype); - return IPACM_SUCCESS; - } - break; + IPACMDBG_H("Rx(%d), src_pipe: %d, ipa_pipe: %d\n", + cnt, rx_prop->rx[cnt].src_pipe, + ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe)); + tether_client.ul_src_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe); } } - if(client_is_found == false && wlan_client_flt_info_count == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT) - { - IPACMDBG_H("The wlan client flt table is already full.\n"); - return IPACM_FAILURE; - } - - len = sizeof(struct ipa_ioc_mdfy_flt_rule) + sizeof(struct ipa_flt_rule_mdfy); - pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); - if (!pFilteringTable) + ret = ioctl(fd_wwan_ioctl, WAN_IOC_SET_TETHER_CLIENT_PIPE, &tether_client); + if (ret != 0) { - IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); - return IPACM_FAILURE; + IPACMERR("Failed set tether-client-pipe %p with ret %d\n ", &tether_client, ret); } - memset(pFilteringTable, 0, len); - - IPACMDBG_H("Receive WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - - /* add mac based rule*/ - pFilteringTable->commit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = 1; + IPACMDBG("Set tether-client-pipe %p\n", &tether_client); + close(fd); + close(fd_wwan_ioctl); + return ret; +} - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - flt_rule.status = -1; +/* mac address has to be provided for client related events */ +void IPACM_Lan::eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac, uint32_t *ipv6_addr, char *iface_name) +{ + ipacm_cmd_q_data eth_bridge_evt; + ipacm_event_eth_bridge *evt_data_eth_bridge; + ipacm_event_data_all *evt_data_all; - flt_rule.rule.retain_hdr = 0; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_ROUTING; - flt_rule.rule.eq_attrib_type = 0; + memset(ð_bridge_evt, 0, sizeof(ipacm_cmd_q_data)); + eth_bridge_evt.event = evt; - /* point to USB-WLAN routing table */ - if(iptype == IPA_IP_v4) + if(evt == IPA_HANDLE_VLAN_CLIENT_INFO || evt == IPA_HANDLE_VLAN_IFACE_INFO) { - if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v4)) + evt_data_all = (ipacm_event_data_all*)malloc(sizeof(*evt_data_all)); + if(evt_data_all == NULL) { - IPACMERR("Failed to get routing table handle.\n"); - res = IPACM_FAILURE; - goto fail; + IPACMERR("Failed to allocate memory.\n"); + return; + } + memset(evt_data_all, 0, sizeof(*evt_data_all)); + + if(ipv6_addr) + { + IPACMDBG_H("IPv6 addr: %08x:%08x:%08x:%08x \n", ipv6_addr[0], + ipv6_addr[1], ipv6_addr[2], ipv6_addr[3]); + memcpy(evt_data_all->ipv6_addr, ipv6_addr, sizeof(evt_data_all->ipv6_addr)); + } + if(mac) + { + IPACMDBG_H("Mac: 0x%02x%02x%02x%02x%02x%02x \n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + memcpy(evt_data_all->mac_addr, mac, sizeof(evt_data_all->mac_addr)); } - flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v4.hdl; - IPACMDBG_H("USB->WLAN filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v4.name); + if(iface_name) + { + IPACMDBG_H("Iface: %s\n", iface_name); + memcpy(evt_data_all->iface_name, iface_name, sizeof(evt_data_all->iface_name)); + } + eth_bridge_evt.evt_data = (void*)evt_data_all; } else { - if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v6)) + evt_data_eth_bridge = (ipacm_event_eth_bridge*)malloc(sizeof(*evt_data_eth_bridge)); + if(evt_data_eth_bridge == NULL) { - IPACMERR("Failed to get routing table handle.\n"); - res = IPACM_FAILURE; - goto fail; + IPACMERR("Failed to allocate memory.\n"); + return; + } + memset(evt_data_eth_bridge, 0, sizeof(*evt_data_eth_bridge)); + + evt_data_eth_bridge->p_iface = this; + evt_data_eth_bridge->iptype = iptype; + if(mac) + { + IPACMDBG_H("Mac: 0x%02x%02x%02x%02x%02x%02x \n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + memcpy(evt_data_eth_bridge->mac_addr, mac, sizeof(evt_data_eth_bridge->mac_addr)); + } + if(iface_name) + { + IPACMDBG_H("Iface: %s\n", iface_name); + memcpy(evt_data_eth_bridge->iface_name, iface_name, + sizeof(evt_data_eth_bridge->iface_name)); } - flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v6.hdl; - IPACMDBG_H("USB->WLAN filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v6.name); + eth_bridge_evt.evt_data = (void*)evt_data_eth_bridge; } - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); - if(IPACM_Lan::usb_hdr_type == IPA_HDR_L2_ETHERNET_II) + IPACMDBG_H("Posting event %s\n", + IPACM_Iface::ipacmcfg->getEventName(evt)); + IPACM_EvtDispatcher::PostEvt(ð_bridge_evt); +} + +/* add header processing context and return handle to lan2lan controller */ +int IPACM_Lan::eth_bridge_add_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_hdr_type, uint32_t *hdl) +{ + int len, res = IPACM_SUCCESS; + uint32_t hdr_template; + ipa_ioc_add_hdr_proc_ctx* pHeaderProcTable = NULL; + + if(tx_prop == NULL) { - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + IPACMERR("No tx prop.\n"); + return IPACM_FAILURE; } - else if(IPACM_Lan::usb_hdr_type == IPA_HDR_L2_802_3) + + len = sizeof(struct ipa_ioc_add_hdr_proc_ctx) + sizeof(struct ipa_hdr_proc_ctx_add); + pHeaderProcTable = (ipa_ioc_add_hdr_proc_ctx*)malloc(len); + if(pHeaderProcTable == NULL) { - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + IPACMERR("Cannot allocate header processing context table.\n"); + return IPACM_FAILURE; } - else + + memset(pHeaderProcTable, 0, len); + pHeaderProcTable->commit = 1; + pHeaderProcTable->num_proc_ctxs = 1; + pHeaderProcTable->proc_ctx[0].type = eth_bridge_get_hdr_proc_type(peer_l2_hdr_type, tx_prop->tx[0].hdr_l2_type); + eth_bridge_get_hdr_template_hdl(&hdr_template); + pHeaderProcTable->proc_ctx[0].hdr_hdl = hdr_template; + if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) { - IPACMERR("USB hdr type is not expected.\n"); + IPACMERR("Adding hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); res = IPACM_FAILURE; - goto fail; + goto end; } - memcpy(flt_rule.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule.rule.attrib.dst_mac_addr)); - memset(flt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule.rule.attrib.dst_mac_addr_mask)); - if(iptype == IPA_IP_v4) + *hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; + +end: + free(pHeaderProcTable); + return res; +} + +/* add routing rule and return handle to lan2lan controller */ +int IPACM_Lan::eth_bridge_add_rt_rule(uint8_t *mac, char *rt_tbl_name, uint32_t hdr_proc_ctx_hdl, + ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int *rt_rule_count) +{ + int i, len, res = IPACM_SUCCESS; + struct ipa_ioc_add_rt_rule* rt_rule_table = NULL; + struct ipa_rt_rule_add rt_rule; + int position, num_rt_rule; + + IPACMDBG_H("Received client MAC 0x%02x%02x%02x%02x%02x%02x.\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + num_rt_rule = each_client_rt_rule_count[iptype]; + + len = sizeof(ipa_ioc_add_rt_rule) + num_rt_rule * sizeof(ipa_rt_rule_add); + rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(len); + if (rt_rule_table == NULL) { - for(i=0; icommit = 1; + rt_rule_table->ip = iptype; + rt_rule_table->num_rules = num_rt_rule; + strlcpy(rt_rule_table->rt_tbl_name, rt_tbl_name, sizeof(rt_rule_table->rt_tbl_name)); + rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = 0; + + memset(&rt_rule, 0, sizeof(ipa_rt_rule_add)); + rt_rule.at_rear = false; + rt_rule.status = -1; + rt_rule.rt_rule_hdl = -1; +#ifdef FEATURE_IPA_V3 + rt_rule.rule.hashable = true; +#endif + rt_rule.rule.hdr_hdl = 0; + rt_rule.rule.hdr_proc_ctx_hdl = hdr_proc_ctx_hdl; + + position = 0; + for(i=0; inum_tx_props; i++) { - for(i=0; itx[i].ip == iptype) { - if(wlan_client_flt_rule_hdl_v6[i].valid == true) + if(position >= num_rt_rule || position >= MAX_NUM_PROP) { - flt_rule.rule_hdl = wlan_client_flt_rule_hdl_v6[i].rule_hdl; - wlan_client_flt_rule_hdl_v6[i].valid = false; - break; + IPACMERR("Number of routing rules already exceeds limit.\n"); + res = IPACM_FAILURE; + goto end; } - } - if(i == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT) - { - IPACMDBG_H("Cannot find a valid flt rule hdl.\n"); - res = IPACM_FAILURE; - goto fail; - } - } - memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) - { - IPACMERR("Failed to add wlan client filtering rules.\n"); - res = IPACM_FAILURE; - goto fail; - } + if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->isMCC_Mode) + { + IPACMDBG_H("In WLAN MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[i].alt_dst_pipe); + rt_rule.rule.dst = tx_prop->tx[i].alt_dst_pipe; + } + else + { + IPACMDBG_H("It is not WLAN MCC mode, use dst pipe: %d\n", + tx_prop->tx[i].dst_pipe); + rt_rule.rule.dst = tx_prop->tx[i].dst_pipe; + } - if(client_is_found == false) - { - client_position = wlan_client_flt_info_count; - wlan_client_flt_info_count++; - } + memcpy(&rt_rule.rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule.rule.attrib)); + if(peer_l2_hdr_type == IPA_HDR_L2_ETHERNET_II) + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + else + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + memcpy(rt_rule.rule.attrib.dst_mac_addr, mac, sizeof(rt_rule.rule.attrib.dst_mac_addr)); + memset(rt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule.rule.attrib.dst_mac_addr_mask)); - memcpy(eth_bridge_wlan_client_flt_info[client_position].mac, mac, sizeof(eth_bridge_wlan_client_flt_info[client_position].mac)); - if(iptype == IPA_IP_v4) + memcpy(&(rt_rule_table->rules[position]), &rt_rule, sizeof(rt_rule_table->rules[position])); + position++; + } + } + if(false == m_routing.AddRoutingRule(rt_rule_table)) { - eth_bridge_wlan_client_flt_info[client_position].flt_rule_set_v4 = true; - eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v4 = wlan_client_flt_rule_hdl_v4[i].rule_hdl; + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto end; } else { - eth_bridge_wlan_client_flt_info[client_position].flt_rule_set_v6 = true; - eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v6 = wlan_client_flt_rule_hdl_v6[i].rule_hdl; + *rt_rule_count = position; + for(i=0; irules[i].rt_rule_hdl; } -fail: - if(pFilteringTable == NULL) - { - free(pFilteringTable); - } +end: + free(rt_rule_table); return res; } -int IPACM_Lan::eth_bridge_del_wlan_client_flt_rule(uint8_t* mac) +/* modify routing rule*/ +int IPACM_Lan::eth_bridge_modify_rt_rule(uint8_t *mac, uint32_t hdr_proc_ctx_hdl, + ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int rt_rule_count) { - if(mac == NULL) + struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_mdfy *rt_rule_entry; + int len, index, res = IPACM_SUCCESS; + + if(tx_prop == NULL) { - IPACMERR("Client MAC address is empty.\n"); + IPACMDBG_H("No tx properties \n"); return IPACM_FAILURE; } - IPACMDBG_H("Receive WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - - int i, j, res = IPACM_SUCCESS; - for(i=0; icommit = 1; + rt_rule->num_rules = 0; + rt_rule->ip = iptype; + + for (index = 0; index < tx_prop->num_tx_props; index++) { - if(reset_to_dummy_flt_rule(IPA_IP_v4, eth_bridge_wlan_client_flt_info[i].flt_rule_hdl_v4) == IPACM_SUCCESS) + if (tx_prop->tx[index].ip == iptype) { - for(j=0; jnum_rules >= rt_rule_count || + rt_rule->num_rules >= MAX_NUM_PROP) { - IPACMERR("Not finding the rule handle in handle pool.\n"); - return IPACM_FAILURE; + IPACMERR("Number of routing rules exceeds limit.\n"); + res = IPACM_FAILURE; + goto end; } - } - else - { - IPACMERR("Failed to delete the wlan client specific flt rule.\n"); - return IPACM_FAILURE; - } - } - if(eth_bridge_wlan_client_flt_info[i].flt_rule_set_v6 == true) - { - if(reset_to_dummy_flt_rule(IPA_IP_v6, eth_bridge_wlan_client_flt_info[i].flt_rule_hdl_v6) == IPACM_SUCCESS) - { - for(j=0; jrules[rt_rule->num_rules]; + + if (IPACM_Iface::ipacmcfg->isMCC_Mode) { - if(wlan_client_flt_rule_hdl_v6[j].rule_hdl == eth_bridge_wlan_client_flt_info[i].flt_rule_hdl_v6) - { - wlan_client_flt_rule_hdl_v6[j].valid = true; - break; - } + IPACMDBG_H("In WLAN MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[index].alt_dst_pipe; } - if(j == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT) + else { - IPACMERR("Not finding the rule handle in handle pool.\n"); - return IPACM_FAILURE; + IPACMDBG_H("In WLAN SCC mode, use dst pipe: %d\n", + tx_prop->tx[index].dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[index].dst_pipe; } - } - else - { - IPACMERR("Failed to delete the wlan client specific flt rule.\n"); - return IPACM_FAILURE; + + rt_rule_entry->rule.hdr_hdl = 0; + rt_rule_entry->rule.hdr_proc_ctx_hdl = hdr_proc_ctx_hdl; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif + memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + if(peer_l2_hdr_type == IPA_HDR_L2_ETHERNET_II) + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + else + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + memcpy(rt_rule_entry->rule.attrib.dst_mac_addr, mac, + sizeof(rt_rule_entry->rule.attrib.dst_mac_addr)); + memset(rt_rule_entry->rule.attrib.dst_mac_addr_mask, 0xFF, + sizeof(rt_rule_entry->rule.attrib.dst_mac_addr_mask)); + + rt_rule_entry->rt_rule_hdl = rt_rule_hdl[rt_rule->num_rules]; + rt_rule->num_rules++; } } - for(j=i+1; jiface_table[ipa_if_num].if_cat == WLAN_IF) - { - if(IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid == false) - { - memset(pHeaderProcTable, 0, len); - pHeaderProcTable->commit = 1; - pHeaderProcTable->num_proc_ctxs = 1; - pHeaderProcTable->proc_ctx[0].type = get_hdr_proc_type(IPACM_Lan::wlan_hdr_type, IPACM_Lan::wlan_hdr_type); - pHeaderProcTable->proc_ctx[0].hdr_hdl = IPACM_Lan::wlan_hdr_template_hdl; - if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) - { - IPACMERR("Adding WLAN to WLAN hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); - res = IPACM_FAILURE; - } - else - { - IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.proc_ctx_hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; - IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid = true; - } - } - } - - if(IPACM_Lan::usb_hdr_type != IPA_HDR_L2_NONE) - { - if(IPACM_Lan::usb_to_wlan_hdr_proc_ctx.valid == false) - { - memset(pHeaderProcTable, 0, len); - pHeaderProcTable->commit = 1; - pHeaderProcTable->num_proc_ctxs = 1; - pHeaderProcTable->proc_ctx[0].type = get_hdr_proc_type(IPACM_Lan::usb_hdr_type, IPACM_Lan::wlan_hdr_type); - pHeaderProcTable->proc_ctx[0].hdr_hdl = IPACM_Lan::wlan_hdr_template_hdl; - if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) - { - IPACMERR("Adding USB to WLAN hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); - res = IPACM_FAILURE; - goto fail; - } - else - { - IPACM_Lan::usb_to_wlan_hdr_proc_ctx.proc_ctx_hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; - IPACM_Lan::usb_to_wlan_hdr_proc_ctx.valid = true; - } - - ipacm_cmd_q_data evt_data; - memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); + IPACMDBG_H("Received client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - ipacm_event_data_fid* fid; - fid = (ipacm_event_data_fid*)malloc(sizeof(ipacm_event_data_fid)); - if(fid == NULL) - { - IPACMERR("Unable to allocate memory.\n"); - return IPACM_FAILURE; - } - memset(fid, 0, sizeof(ipacm_event_data_fid)); - fid->if_index = ipa_if_num; + len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add); + pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len); + if (!pFilteringTable) + { + IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); - evt_data.evt_data = fid; - evt_data.event = IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT; - IPACMDBG_H("Posting event IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT\n"); - IPACM_EvtDispatcher::PostEvt(&evt_data); - } + /* add mac based rule*/ + pFilteringTable->commit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = 1; + pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[iptype]; - if(IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == false) - { - memset(pHeaderProcTable, 0, len); - pHeaderProcTable->commit = 1; - pHeaderProcTable->num_proc_ctxs = 1; - pHeaderProcTable->proc_ctx[0].type = get_hdr_proc_type(IPACM_Lan::wlan_hdr_type, IPACM_Lan::usb_hdr_type); - pHeaderProcTable->proc_ctx[0].hdr_hdl = IPACM_Lan::usb_hdr_template_hdl; - if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) - { - IPACMERR("Adding WLAN to USB hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); - m_header.DeleteHeaderProcCtx(IPACM_Lan::usb_to_wlan_hdr_proc_ctx.proc_ctx_hdl); - IPACM_Lan::usb_to_wlan_hdr_proc_ctx.valid = false; - res = IPACM_FAILURE; - goto fail; - } - else - { - IPACM_Lan::wlan_to_usb_hdr_proc_ctx.proc_ctx_hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; - IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid = true; - } - } - } + memset(&flt_rule_entry, 0, sizeof(flt_rule_entry)); + flt_rule_entry.at_rear = 1; + + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.rule.rt_tbl_hdl = rt_tbl_hdl; + flt_rule_entry.rule.hashable = true; + + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + if(tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_ETHERNET_II) + { + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; } else { - IPACMDBG_H("Not adding header processing context.\n"); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; } -fail: - free(pHeaderProcTable); + memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr)); + memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask)); + + memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry)); + if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable)) + { + IPACMERR("Failed to add client filtering rules.\n"); + res = IPACM_FAILURE; + goto end; + } + *flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl; + +end: + free(pFilteringTable); +#endif return res; } -ipa_hdr_proc_type IPACM_Lan::get_hdr_proc_type(ipa_hdr_l2_type t1, ipa_hdr_l2_type t2) +int IPACM_Lan::eth_bridge_del_flt_rule(uint32_t flt_rule_hdl, ipa_ip_type iptype) { - if(t1 == IPA_HDR_L2_ETHERNET_II) + if(m_filtering.DeleteFilteringHdls(&flt_rule_hdl, iptype, 1) == false) { - if(t2 == IPA_HDR_L2_ETHERNET_II) - { - return IPA_HDR_PROC_ETHII_TO_ETHII; - } - if(t2 == IPA_HDR_L2_802_3) - { - return IPA_HDR_PROC_ETHII_TO_802_3; - } + IPACMERR("Failed to delete the client specific flt rule.\n"); + return IPACM_FAILURE; } + return IPACM_SUCCESS; +} - if(t1 == IPA_HDR_L2_802_3) +int IPACM_Lan::eth_bridge_del_rt_rule(uint32_t rt_rule_hdl, ipa_ip_type iptype) +{ + if(m_routing.DeleteRoutingHdl(rt_rule_hdl, iptype) == false) { - if(t2 == IPA_HDR_L2_ETHERNET_II) - { - return IPA_HDR_PROC_802_3_TO_ETHII; - } - if(t2 == IPA_HDR_L2_802_3) - { - return IPA_HDR_PROC_802_3_TO_802_3; - } + IPACMERR("Failed to delete routing rule.\n"); + return IPACM_FAILURE; } + return IPACM_SUCCESS; +} - return IPA_HDR_PROC_NONE; +/* delete header processing context */ +int IPACM_Lan::eth_bridge_del_hdr_proc_ctx(uint32_t hdr_proc_ctx_hdl) +{ + if(m_header.DeleteHeaderProcCtx(hdr_proc_ctx_hdl) == false) + { + IPACMERR("Failed to delete hdr proc ctx.\n"); + return IPACM_FAILURE; + } + return IPACM_SUCCESS; } -int IPACM_Lan::eth_bridge_install_cache_wlan_client_flt_rule(ipa_ip_type iptype) +/* check if the event is associated with vlan interface */ +bool IPACM_Lan::is_vlan_event(char *event_iface_name) { - int i; + int self_name_len, event_iface_name_len; + if(event_iface_name == NULL) + { + IPACMERR("Invalid input\n"); + return false; + } - IPACMDBG_H("There are %d wlan clients cached.\n",IPACM_Lan::num_wlan_client); - for(i=0; i self_name_len && strncmp(dev_name, event_iface_name, self_name_len) == 0) { - eth_bridge_add_wlan_client_flt_rule(IPACM_Lan::eth_bridge_wlan_client[i].mac, iptype); + IPACMDBG_H("This is vlan event.\n"); + return true; } - return IPACM_SUCCESS; + return false; } -int IPACM_Lan::eth_bridge_install_cache_usb_client_flt_rule(ipa_ip_type iptype) +/* check if the event is associated with l2tp interface */ +bool IPACM_Lan::is_l2tp_event(char *event_iface_name) { - IPACMDBG_H("No need to install usb client specific flt rules on usb pipe.\n"); - return IPACM_SUCCESS; + if(event_iface_name == NULL) + { + IPACMERR("Invalid input\n"); + return false; + } + + IPACMDBG_H("Self iface %s, event iface %s\n", dev_name, event_iface_name); + if(strncmp(event_iface_name, "l2tp", 4) == 0) + { + IPACMDBG_H("This is l2tp event.\n"); + return true; + } + return false; } -int IPACM_Lan::eth_bridge_add_usb_client_rt_rule(uint8_t* mac, ipa_ip_type iptype) +/* add l2tp rt rule for l2tp client */ +int IPACM_Lan::add_l2tp_rt_rule(ipa_ip_type iptype, uint8_t *dst_mac, ipa_hdr_l2_type peer_l2_hdr_type, + uint32_t l2tp_session_id, uint32_t vlan_id, uint8_t *vlan_client_mac, uint32_t *vlan_iface_ipv6_addr, + uint32_t *vlan_client_ipv6_addr, uint32_t *first_pass_hdr_hdl, uint32_t *first_pass_hdr_proc_ctx_hdl, + uint32_t *second_pass_hdr_hdl, int *num_rt_hdl, uint32_t *first_pass_rt_rule_hdl, uint32_t *second_pass_rt_rule_hdl) { + int i, size, position; + uint32_t vlan_iface_ipv6_addr_network[4], vlan_client_ipv6_addr_network[4]; + ipa_ioc_add_hdr *hdr_table; + ipa_hdr_add *hdr; + ipa_ioc_add_hdr_proc_ctx *hdr_proc_ctx_table; + ipa_hdr_proc_ctx_add *hdr_proc_ctx; + ipa_ioc_add_rt_rule* rt_rule_table; + ipa_rt_rule_add *rt_rule; + ipa_ioc_copy_hdr copy_hdr; + if(tx_prop == NULL) { - IPACMDBG_H("Tx prop is empty, not adding routing rule.\n"); - return IPACM_SUCCESS; + IPACMERR("No tx prop.\n"); + return IPACM_FAILURE; + } + + /* =========== install first pass hdr template (IPv6 + L2TP + inner ETH header = 62 bytes) ============= */ + if(*first_pass_hdr_hdl != 0) + { + IPACMDBG_H("First pass hdr template was added before.\n"); } - if(mac == NULL) + else { - IPACMERR("Client MAC address is empty.\n"); - return IPACM_FAILURE; + size = sizeof(ipa_ioc_add_hdr) + sizeof(ipa_hdr_add); + hdr_table = (ipa_ioc_add_hdr*)malloc(size); + if(hdr_table == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(hdr_table, 0, size); + + hdr_table->commit = 1; + hdr_table->num_hdrs = 1; + hdr = &hdr_table->hdr[0]; + + if(iptype == IPA_IP_v4) + { + snprintf(hdr->name, sizeof(hdr->name), "vlan_%d_l2tp_%d_v4", vlan_id, l2tp_session_id); + } + else + { + snprintf(hdr->name, sizeof(hdr->name), "vlan_%d_l2tp_%d_v6", vlan_id, l2tp_session_id); + } + hdr->hdr_len = 62; + hdr->type = IPA_HDR_L2_ETHERNET_II; + hdr->is_partial = 0; + + hdr->hdr[0] = 0x60; /* version */ + hdr->hdr[6] = 0x73; /* next header = L2TP */ + hdr->hdr[7] = 0x40; /* hop limit = 64 */ + for(i = 0; i < 4; i++) + { + vlan_iface_ipv6_addr_network[i] = htonl(vlan_iface_ipv6_addr[i]); + vlan_client_ipv6_addr_network[i] = htonl(vlan_client_ipv6_addr[i]); + } + memcpy(hdr->hdr + 8, vlan_iface_ipv6_addr_network, 16); /* source IPv6 addr */ + memcpy(hdr->hdr + 24, vlan_client_ipv6_addr_network, 16); /* dest IPv6 addr */ + hdr->hdr[43] = (uint8_t)(l2tp_session_id & 0xFF); /* l2tp header */ + hdr->hdr[42] = (uint8_t)(l2tp_session_id >> 8 & 0xFF); + hdr->hdr[41] = (uint8_t)(l2tp_session_id >> 16 & 0xFF); + hdr->hdr[40] = (uint8_t)(l2tp_session_id >> 24 & 0xFF); + + if(m_header.AddHeader(hdr_table) == false) + { + IPACMERR("Failed to add hdr with status: %d\n", hdr_table->hdr[0].status); + free(hdr_table); + return IPACM_FAILURE; + } + *first_pass_hdr_hdl = hdr_table->hdr[0].hdr_hdl; + IPACMDBG_H("Installed first pass hdr: hdl %d\n", *first_pass_hdr_hdl); + free(hdr_table); } - if( (iptype == IPA_IP_v4 && usb_client_rt_info_count_v4 == IPA_LAN_TO_LAN_MAX_USB_CLIENT) - || (iptype == IPA_IP_v6 && usb_client_rt_info_count_v6 == IPA_LAN_TO_LAN_MAX_USB_CLIENT)) + + /* =========== install first pass hdr proc ctx (populate src/dst MAC and Ether type) ============= */ + size = sizeof(ipa_ioc_add_hdr_proc_ctx) + sizeof(ipa_hdr_proc_ctx_add); + hdr_proc_ctx_table = (ipa_ioc_add_hdr_proc_ctx*)malloc(size); + if(hdr_proc_ctx_table == NULL) { - IPACMDBG_H("USB client number has reached maximum.\n"); + IPACMERR("Failed to allocate memory.\n"); return IPACM_FAILURE; } - if(IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == false) + memset(hdr_proc_ctx_table, 0, size); + + hdr_proc_ctx_table->commit = 1; + hdr_proc_ctx_table->num_proc_ctxs = 1; + hdr_proc_ctx = &hdr_proc_ctx_table->proc_ctx[0]; + + hdr_proc_ctx->type = IPA_HDR_PROC_L2TP_HEADER_ADD; + hdr_proc_ctx->hdr_hdl = *first_pass_hdr_hdl; + hdr_proc_ctx->l2tp_params.hdr_add_param.eth_hdr_retained = 1; + hdr_proc_ctx->l2tp_params.hdr_add_param.input_ip_version = iptype; + hdr_proc_ctx->l2tp_params.hdr_add_param.output_ip_version = IPA_IP_v6; + if(m_header.AddHeaderProcCtx(hdr_proc_ctx_table) == false) { - IPACMDBG_H("WLAN to USB hdr proc ctx has not been set, don't add USB routing rule.\n"); + IPACMERR("Failed to add hdr proc ctx with status: %d\n", hdr_proc_ctx_table->proc_ctx[0].status); + free(hdr_proc_ctx_table); return IPACM_FAILURE; } + *first_pass_hdr_proc_ctx_hdl = hdr_proc_ctx_table->proc_ctx[0].proc_ctx_hdl; + IPACMDBG_H("Installed first pass hdr proc ctx: hdl %d\n", *first_pass_hdr_proc_ctx_hdl); + free(hdr_proc_ctx_table); - IPACMDBG_H("Receive USB client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + /* =========== install first pass rt rules (match dst MAC then doing UCP) ============= */ + *num_rt_hdl = each_client_rt_rule_count[iptype]; + size = sizeof(ipa_ioc_add_rt_rule) + (*num_rt_hdl) * sizeof(ipa_rt_rule_add); + rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(size); + if (rt_rule_table == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(rt_rule_table, 0, size); - int i, len, res = IPACM_SUCCESS; - struct ipa_ioc_add_rt_rule* rt_rule_table = NULL; - struct ipa_rt_rule_add rt_rule; - int position, num_rt_rule; + rt_rule_table->commit = 1; + rt_rule_table->ip = iptype; + rt_rule_table->num_rules = *num_rt_hdl; + snprintf(rt_rule_table->rt_tbl_name, sizeof(rt_rule_table->rt_tbl_name), "l2tp"); + rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = 0; - if(iptype == IPA_IP_v4) + position = 0; + for(i = 0; i < iface_query->num_tx_props; i++) { - for(i=0; itx[i].ip == iptype) { - if(memcmp(eth_bridge_get_client_rt_info_ptr(i, iptype)->mac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, iptype)->mac)) == 0) + if(position >= *num_rt_hdl || position >= MAX_NUM_PROP) { - IPACMDBG_H("The client's routing rule was added before.\n"); - return IPACM_SUCCESS; + IPACMERR("Number of routing rules already exceeds limit.\n"); + free(rt_rule_table); + return IPACM_FAILURE; } + + rt_rule = &rt_rule_table->rules[position]; + rt_rule->at_rear = false; + rt_rule->status = -1; + rt_rule->rt_rule_hdl = -1; + rt_rule->rule.hashable = false; //WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction + rt_rule->rule.hdr_hdl = 0; + rt_rule->rule.hdr_proc_ctx_hdl = *first_pass_hdr_proc_ctx_hdl; + rt_rule->rule.dst = IPA_CLIENT_DUMMY_CONS; + + memcpy(&rt_rule->rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule->rule.attrib)); + if(peer_l2_hdr_type == IPA_HDR_L2_ETHERNET_II) + rt_rule->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + else + rt_rule->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + memcpy(rt_rule->rule.attrib.dst_mac_addr, dst_mac, sizeof(rt_rule->rule.attrib.dst_mac_addr)); + memset(rt_rule->rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule->rule.attrib.dst_mac_addr_mask)); + position++; } - memcpy(eth_bridge_get_client_rt_info_ptr(usb_client_rt_info_count_v4, iptype)->mac, mac, - sizeof(eth_bridge_get_client_rt_info_ptr(usb_client_rt_info_count_v4, iptype)->mac)); + } + if(m_routing.AddRoutingRule(rt_rule_table) == false) + { + IPACMERR("Failed to add first pass rt rules.\n"); + free(rt_rule_table); + return IPACM_FAILURE; + } + for(i = 0; i < position; i++) + { + first_pass_rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + free(rt_rule_table); + + /* =========== install second pass hdr (Ethernet header with L2TP tag = 18 bytes) ============= */ + if(*second_pass_hdr_hdl != 0) + { + IPACMDBG_H("Second pass hdr was added before.\n"); } else { - for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, iptype)->mac)) == 0) + IPACMERR("Failed to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(hdr_table, 0, size); + + hdr_table->commit = 1; + hdr_table->num_hdrs = 1; + hdr = &hdr_table->hdr[0]; + + if(iptype == IPA_IP_v4) + { + snprintf(hdr->name, sizeof(hdr->name), "vlan_%d_v4", vlan_id); + } + else + { + snprintf(hdr->name, sizeof(hdr->name), "vlan_%d_v6", vlan_id); + } + hdr->type = IPA_HDR_L2_ETHERNET_II; + hdr->is_partial = 0; + for(i = 0; i < tx_prop->num_tx_props; i++) + { + if(tx_prop->tx[i].ip == IPA_IP_v6) { - IPACMDBG_H("The client's routing rule was added before.\n"); - return IPACM_SUCCESS; + memset(©_hdr, 0, sizeof(copy_hdr)); + strlcpy(copy_hdr.name, tx_prop->tx[i].hdr_name, + sizeof(copy_hdr.name)); + IPACMDBG_H("Header name: %s in tx:%d\n", copy_hdr.name, i); + if(m_header.CopyHeader(©_hdr) == false) + { + IPACMERR("Failed to get partial header.\n"); + free(hdr_table); + return IPACM_FAILURE; + } + IPACMDBG_H("Header length: %d\n", copy_hdr.hdr_len); + hdr->hdr_len = copy_hdr.hdr_len; + memcpy(hdr->hdr, copy_hdr.hdr, hdr->hdr_len); + break; } } - memcpy(eth_bridge_get_client_rt_info_ptr(usb_client_rt_info_count_v6, iptype)->mac, mac, - sizeof(eth_bridge_get_client_rt_info_ptr(usb_client_rt_info_count_v6, iptype)->mac)); - } + /* copy vlan client mac */ + memcpy(hdr->hdr + hdr->hdr_len - 18, vlan_client_mac, 6); + hdr->hdr[hdr->hdr_len - 3] = (uint8_t)vlan_id & 0xFF; + hdr->hdr[hdr->hdr_len - 4] = (uint8_t)(vlan_id >> 8) & 0xFF; - if(iptype == IPA_IP_v4) - { - num_rt_rule = each_client_rt_rule_count_v4; + if(m_header.AddHeader(hdr_table) == false) + { + IPACMERR("Failed to add hdr with status: %d\n", hdr->status); + free(hdr_table); + return IPACM_FAILURE; + } + *second_pass_hdr_hdl = hdr->hdr_hdl; + IPACMDBG_H("Installed second pass hdr: hdl %d\n", *second_pass_hdr_hdl); + free(hdr_table); } - else + + /* =========== install second pass rt rules (match VLAN interface IPv6 address at dst client side) ============= */ + if(second_pass_rt_rule_hdl[0] != 0) { - num_rt_rule = each_client_rt_rule_count_v6; + IPACMDBG_H("Second pass rt rule was added before, return.\n"); + return IPACM_SUCCESS; } - len = sizeof(ipa_ioc_add_rt_rule) + num_rt_rule * sizeof(ipa_rt_rule_add); - rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(len); - if(rt_rule_table == NULL) + *num_rt_hdl = each_client_rt_rule_count[IPA_IP_v6]; + size = sizeof(ipa_ioc_add_rt_rule) + (*num_rt_hdl) * sizeof(ipa_rt_rule_add); + rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(size); + if (rt_rule_table == NULL) { IPACMERR("Failed to allocate memory.\n"); return IPACM_FAILURE; } - memset(rt_rule_table, 0, len); + memset(rt_rule_table, 0, size); rt_rule_table->commit = 1; - rt_rule_table->ip = iptype; - rt_rule_table->num_rules = num_rt_rule; - - if(iptype == IPA_IP_v4) - { - strncpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v4.name, sizeof(rt_rule_table->rt_tbl_name)); - } - else - { - strncpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v6.name, sizeof(rt_rule_table->rt_tbl_name)); - } - - memset(&rt_rule, 0, sizeof(ipa_rt_rule_add)); - rt_rule.at_rear = false; - rt_rule.status = -1; - rt_rule.rt_rule_hdl = -1; + rt_rule_table->ip = IPA_IP_v6; + rt_rule_table->num_rules = *num_rt_hdl; + snprintf(rt_rule_table->rt_tbl_name, sizeof(rt_rule_table->rt_tbl_name), "l2tp"); + rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = 0; - rt_rule.rule.hdr_hdl = 0; - rt_rule.rule.hdr_proc_ctx_hdl = IPACM_Lan::wlan_to_usb_hdr_proc_ctx.proc_ctx_hdl; position = 0; - for(i=0; inum_tx_props; i++) + for(i = 0; i < iface_query->num_tx_props; i++) { - if(tx_prop->tx[i].ip == iptype) + if(tx_prop->tx[i].ip == IPA_IP_v6) { - if(position >= num_rt_rule) - { - IPACMERR("Number of routing rules already exceeds limit for iptype %d.\n", iptype); - res = IPACM_FAILURE; - goto fail; - } - - rt_rule.rule.dst = tx_prop->tx[i].dst_pipe; - memcpy(&rt_rule.rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule.rule.attrib)); - if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) - { - rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; - } - else if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_802_3) - { - rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; - } - else + if(position >= *num_rt_hdl || position >= MAX_NUM_PROP) { - IPACMERR("WLAN header type is not expected.\n"); - res = IPACM_FAILURE; - goto fail; + IPACMERR("Number of routing rules already exceeds limit.\n"); + free(rt_rule_table); + return IPACM_FAILURE; } - memcpy(rt_rule.rule.attrib.dst_mac_addr, mac, sizeof(rt_rule.rule.attrib.dst_mac_addr)); - memset(rt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule.rule.attrib.dst_mac_addr_mask)); - memcpy(&(rt_rule_table->rules[position]), &rt_rule, sizeof(rt_rule_table->rules[position])); + rt_rule = &rt_rule_table->rules[position]; + rt_rule->at_rear = false; + rt_rule->status = -1; + rt_rule->rt_rule_hdl = -1; + rt_rule->rule.hashable = false; //WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction + rt_rule->rule.hdr_hdl = *second_pass_hdr_hdl; + rt_rule->rule.hdr_proc_ctx_hdl = 0; + rt_rule->rule.dst = tx_prop->tx[i].dst_pipe; + + memcpy(&rt_rule->rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule->rule.attrib)); + rt_rule->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + memcpy(rt_rule->rule.attrib.u.v6.dst_addr, vlan_client_ipv6_addr, + sizeof(rt_rule->rule.attrib.u.v6.dst_addr)); + memset(rt_rule->rule.attrib.u.v6.dst_addr_mask, 0xFF, sizeof(rt_rule->rule.attrib.u.v6.dst_addr_mask)); position++; } } + if(m_routing.AddRoutingRule(rt_rule_table) == false) + { + IPACMERR("Failed to add second pass rt rules.\n"); + free(rt_rule_table); + return IPACM_FAILURE; + } + for(i = 0; i < position; i++) + { + second_pass_rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + free(rt_rule_table); - if(false == m_routing.AddRoutingRule(rt_rule_table)) + return IPACM_SUCCESS; +} + +/* delete l2tp rt rule for l2tp client */ +int IPACM_Lan::del_l2tp_rt_rule(ipa_ip_type iptype, uint32_t first_pass_hdr_hdl, uint32_t first_pass_hdr_proc_ctx_hdl, + uint32_t second_pass_hdr_hdl, int num_rt_hdl, uint32_t *first_pass_rt_rule_hdl, uint32_t *second_pass_rt_rule_hdl) +{ + int i; + + if(num_rt_hdl < 0) { - IPACMERR("Routing rule addition failed!\n"); - res = IPACM_FAILURE; - goto fail; + IPACMERR("Invalid num rt rule: %d\n", num_rt_hdl); + return IPACM_FAILURE; } - else + + for(i = 0; i < num_rt_hdl; i++) { - for(i=0; irt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + return IPACM_FAILURE; } - else + } + if(second_pass_rt_rule_hdl != NULL) + { + if(m_routing.DeleteRoutingHdl(second_pass_rt_rule_hdl[i], IPA_IP_v6) == false) { - eth_bridge_get_client_rt_info_ptr(usb_client_rt_info_count_v6, iptype)->rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + return IPACM_FAILURE; } } } - if(iptype == IPA_IP_v4) + if(first_pass_hdr_proc_ctx_hdl != 0) { - usb_client_rt_info_count_v4++; - IPACMDBG_H("Now the number of IPv4 rt rule info is %d.\n", usb_client_rt_info_count_v4); + if(m_header.DeleteHeaderProcCtx(first_pass_hdr_proc_ctx_hdl) == false) + { + return IPACM_FAILURE; + } } - else + + if(first_pass_hdr_hdl != 0) { - usb_client_rt_info_count_v6++; - IPACMDBG_H("Now the number of IPv6 rt rule info is %d.\n", usb_client_rt_info_count_v6); + if(m_header.DeleteHeaderHdl(first_pass_hdr_hdl) == false) + { + return IPACM_FAILURE; + } } - -fail: - if(rt_rule_table != NULL) + if(second_pass_hdr_hdl != 0) { - free(rt_rule_table); + if(m_header.DeleteHeaderHdl(second_pass_hdr_hdl) == false) + { + return IPACM_FAILURE; + } } - return res; + + return IPACM_SUCCESS; } -int IPACM_Lan::eth_bridge_del_usb_client_rt_rule(uint8_t* mac) +/* add l2tp rt rule for non l2tp client */ +int IPACM_Lan::add_l2tp_rt_rule(ipa_ip_type iptype, uint8_t *dst_mac, uint32_t *hdr_proc_ctx_hdl, + int *num_rt_hdl, uint32_t *rt_rule_hdl) { + int i, size, position; + ipa_ioc_add_hdr_proc_ctx *hdr_proc_ctx_table; + ipa_hdr_proc_ctx_add *hdr_proc_ctx; + ipa_ioc_add_rt_rule* rt_rule_table; + ipa_rt_rule_add *rt_rule; + ipa_ioc_get_hdr hdr; + if(tx_prop == NULL) { - IPACMDBG_H("Tx prop is empty, not deleting routing rule.\n"); - return IPACM_SUCCESS; - } - if(mac == NULL) - { - IPACMERR("Client MAC address is empty.\n"); + IPACMERR("No tx prop.\n"); return IPACM_FAILURE; } - IPACMDBG_H("Receive USB client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - - int i, position; - /* delete rule from IPv4 rt table first */ - for(i=0; inum_tx_props; i++) { - if(memcmp(eth_bridge_get_client_rt_info_ptr(i, IPA_IP_v4)->mac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, IPA_IP_v4)->mac)) == 0) + if(tx_prop->tx[i].ip == iptype) { - position = i; - IPACMDBG_H("The client is found at position %d.\n", position); + strlcpy(hdr.name, tx_prop->tx[i].hdr_name, + sizeof(hdr.name)); break; } } - if(i == usb_client_rt_info_count_v4) + if(m_header.GetHeaderHandle(&hdr) == false) { - IPACMERR("The client is not found.\n"); + IPACMERR("Failed to get template hdr hdl.\n"); return IPACM_FAILURE; } - for(i=0; irt_rule_hdl[i], IPA_IP_v4) == false) + size = sizeof(ipa_ioc_add_hdr_proc_ctx) + sizeof(ipa_hdr_proc_ctx_add); + hdr_proc_ctx_table = (ipa_ioc_add_hdr_proc_ctx*)malloc(size); + if(hdr_proc_ctx_table == NULL) { - IPACMERR("Failed to delete routing rule %d.\n", i); + IPACMERR("Failed to allocate memory.\n"); return IPACM_FAILURE; } - } + memset(hdr_proc_ctx_table, 0, size); - for(i=position+1; icommit = 1; + hdr_proc_ctx_table->num_proc_ctxs = 1; + hdr_proc_ctx = &hdr_proc_ctx_table->proc_ctx[0]; - /*delete rule from IPv6 rt table */ - for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, IPA_IP_v6)->mac)) == 0) + hdr_proc_ctx->type = IPA_HDR_PROC_L2TP_HEADER_REMOVE; + hdr_proc_ctx->hdr_hdl = hdr.hdl; + hdr_proc_ctx->l2tp_params.hdr_remove_param.hdr_len_remove = 62; + hdr_proc_ctx->l2tp_params.hdr_remove_param.eth_hdr_retained = 1; + if(m_header.AddHeaderProcCtx(hdr_proc_ctx_table) == false) { - position = i; - IPACMDBG_H("The client is found at position %d.\n", position); - break; + IPACMERR("Failed to add hdr proc ctx with status: %d\n", hdr_proc_ctx_table->proc_ctx[0].status); + free(hdr_proc_ctx_table); + return IPACM_FAILURE; } + *hdr_proc_ctx_hdl = hdr_proc_ctx_table->proc_ctx[0].proc_ctx_hdl; + IPACMDBG_H("Installed hdr proc ctx: hdl %d\n", *hdr_proc_ctx_hdl); + free(hdr_proc_ctx_table); } - if(i == usb_client_rt_info_count_v6) + + /* =========== install rt rules (match dst MAC within 62 bytes header) ============= */ + *num_rt_hdl = each_client_rt_rule_count[iptype]; + size = sizeof(ipa_ioc_add_rt_rule) + (*num_rt_hdl) * sizeof(ipa_rt_rule_add); + rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(size); + if (rt_rule_table == NULL) { - IPACMERR("The client is not found.\n"); + IPACMERR("Failed to allocate memory.\n"); return IPACM_FAILURE; } + memset(rt_rule_table, 0, size); + + rt_rule_table->commit = 1; + rt_rule_table->ip = iptype; + rt_rule_table->num_rules = *num_rt_hdl; + snprintf(rt_rule_table->rt_tbl_name, sizeof(rt_rule_table->rt_tbl_name), "l2tp"); + rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = 0; - for(i=0; inum_tx_props; i++) { - if(m_routing.DeleteRoutingHdl(eth_bridge_get_client_rt_info_ptr(position, IPA_IP_v6)->rt_rule_hdl[i], IPA_IP_v6) == false) + if(tx_prop->tx[i].ip == iptype) { - IPACMERR("Failed to delete routing rule %d.\n", i); - return IPACM_FAILURE; + if(position >= *num_rt_hdl || position >= MAX_NUM_PROP) + { + IPACMERR("Number of routing rules already exceeds limit.\n"); + free(rt_rule_table); + return IPACM_FAILURE; + } + + rt_rule = &rt_rule_table->rules[position]; + rt_rule->at_rear = false; + rt_rule->status = -1; + rt_rule->rt_rule_hdl = -1; + rt_rule->rule.hashable = false; //ETH->WLAN direction rules need to be non-hashable due to encapsulation + + rt_rule->rule.hdr_hdl = 0; + rt_rule->rule.hdr_proc_ctx_hdl = *hdr_proc_ctx_hdl; + rt_rule->rule.dst = tx_prop->tx[i].dst_pipe; + + memcpy(&rt_rule->rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule->rule.attrib)); + + rt_rule->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_L2TP; + memset(rt_rule->rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule->rule.attrib.dst_mac_addr_mask)); + memcpy(rt_rule->rule.attrib.dst_mac_addr, dst_mac, sizeof(rt_rule->rule.attrib.dst_mac_addr)); + + position++; } } - - for(i=position+1; irules[i].rt_rule_hdl; + free(rt_rule_table); return IPACM_SUCCESS; } -eth_bridge_client_rt_info* IPACM_Lan::eth_bridge_get_client_rt_info_ptr(uint8_t index, ipa_ip_type iptype) +int IPACM_Lan::del_l2tp_rt_rule(ipa_ip_type iptype, int num_rt_hdl, uint32_t *rt_rule_hdl) { - void* result; - if(iptype == IPA_IP_v4) - { - result = (void*)((char*)eth_bridge_usb_client_rt_info_v4 + index * client_rt_info_size_v4); - } - else - { - result = (void*)((char*)eth_bridge_usb_client_rt_info_v6 + index * client_rt_info_size_v6); - } - return (eth_bridge_client_rt_info*)result; -} + int i; -void IPACM_Lan::eth_bridge_add_usb_client(uint8_t* mac) -{ - if(IPACM_Lan::num_usb_client == IPA_LAN_TO_LAN_MAX_USB_CLIENT) + if(num_rt_hdl < 0) { - IPACMDBG_H("USB client table is already full.\n"); - return; + IPACMERR("Invalid num rt rule: %d\n", num_rt_hdl); + return IPACM_FAILURE; } - if(mac == NULL) + for(i = 0; i < num_rt_hdl; i++) { - IPACMERR("Mac address is empty.\n"); - return; + if(m_routing.DeleteRoutingHdl(rt_rule_hdl[i], iptype) == false) + { + return IPACM_FAILURE; + } } - memcpy(IPACM_Lan::eth_bridge_usb_client[IPACM_Lan::num_usb_client].mac, mac, sizeof(IPACM_Lan::eth_bridge_usb_client[IPACM_Lan::num_usb_client].mac)); - IPACM_Lan::num_usb_client++; - return; + return IPACM_SUCCESS; } -void IPACM_Lan::eth_bridge_del_usb_client(uint8_t* mac) +/* add l2tp flt rule on l2tp interface */ +int IPACM_Lan::add_l2tp_flt_rule(uint8_t *dst_mac, uint32_t *flt_rule_hdl) { - if(mac == NULL) - { - IPACMERR("Mac address is empty.\n"); - return; - } + int len; + int fd_ipa; + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL; + ipa_ioc_get_rt_tbl rt_tbl; - int i, j; - for(i=0; icommit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->ip = IPA_IP_v6; + pFilteringTable->num_rules = 1; + pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[IPA_IP_v6]; - for(j=i+1; jtx[0].hdr_name, sizeof(hdr.name)); - if(m_header.GetHeaderHandle(&hdr) == false) + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl; + flt_rule_entry.rule.hashable = false; //ETH->WLAN direction rules need to be non-hashable due to encapsulation + + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + + /* flt rule is matching dst MAC within 62 bytes header */ + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_L2TP; + memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask)); + memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, dst_mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr)); + + memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry)); + if(m_filtering.AddFilteringRuleAfter(pFilteringTable) == false) { - IPACMERR("Failed to get template hdr hdl.\n"); + IPACMERR("Failed to add client filtering rules.\n"); + free(pFilteringTable); + close(fd_ipa); return IPACM_FAILURE; } + *flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl; - *hdr_hdl = hdr.hdl; + free(pFilteringTable); + close(fd_ipa); +#endif return IPACM_SUCCESS; } -int IPACM_Lan::del_hdr_proc_ctx() +/* delete l2tp flt rule on l2tp interface */ +int IPACM_Lan::del_l2tp_flt_rule(uint32_t flt_rule_hdl) { - if(IPACM_Lan::usb_to_wlan_hdr_proc_ctx.valid == true) + if(m_filtering.DeleteFilteringHdls(&flt_rule_hdl, IPA_IP_v6, 1) == false) { - if(m_header.DeleteHeaderProcCtx(IPACM_Lan::usb_to_wlan_hdr_proc_ctx.proc_ctx_hdl) == false) - { - IPACMERR("Failed to delete usb to wlan hdr proc ctx.\n"); - return IPACM_FAILURE; - } - IPACM_Lan::usb_to_wlan_hdr_proc_ctx.valid = false; - - ipacm_cmd_q_data evt_data; - memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); + return IPACM_FAILURE; + } - ipacm_event_data_fid* fid; - fid = (ipacm_event_data_fid*)malloc(sizeof(ipacm_event_data_fid)); - if(fid == NULL) - { - IPACMERR("Unable to allocate memory.\n"); - return IPACM_FAILURE; - } - memset(fid, 0, sizeof(ipacm_event_data_fid)); - fid->if_index = ipa_if_num; + return IPACM_SUCCESS; +} - evt_data.evt_data = fid; - evt_data.event = IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT; - IPACMDBG_H("Posting event IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT\n"); - IPACM_EvtDispatcher::PostEvt(&evt_data); - } +/* add l2tp flt rule on non l2tp interface */ +int IPACM_Lan::add_l2tp_flt_rule(ipa_ip_type iptype, uint8_t *dst_mac, uint32_t *vlan_client_ipv6_addr, + uint32_t *first_pass_flt_rule_hdl, uint32_t *second_pass_flt_rule_hdl) +{ + int len; + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL; + ipa_ioc_get_rt_tbl rt_tbl; - if(IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == true) +#ifdef FEATURE_IPA_V3 + if (rx_prop == NULL || tx_prop == NULL) { - if(m_header.DeleteHeaderProcCtx(IPACM_Lan::wlan_to_usb_hdr_proc_ctx.proc_ctx_hdl) == false) - { - IPACMERR("Failed to delete wlan to usb hdr proc ctx.\n"); - return IPACM_FAILURE; - } - IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid = false; + IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name); + return IPACM_FAILURE; } - if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == WLAN_IF) + IPACMDBG_H("Dst client MAC 0x%02x%02x%02x%02x%02x%02x.\n", dst_mac[0], dst_mac[1], + dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]); + + len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add); + pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len); + if (!pFilteringTable) { - if(IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid == true) - { - if(m_header.DeleteHeaderProcCtx(IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.proc_ctx_hdl) == false) - { - IPACMERR("Failed to delete wlan to wlan hdr proc ctx.\n"); - return IPACM_FAILURE; - } - IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid = false; - } + IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n"); + return IPACM_FAILURE; } - return IPACM_SUCCESS; -} + memset(pFilteringTable, 0, len); -/*handle reset usb-client rt-rules */ -int IPACM_Lan::handle_tethering_stats_event(ipa_get_data_stats_resp_msg_v01 *data) -{ - int cnt, pipe_len, fd; - uint64_t num_ul_packets, num_ul_bytes; - uint64_t num_dl_packets, num_dl_bytes; - bool ul_pipe_found, dl_pipe_found; - FILE *fp = NULL; + pFilteringTable->commit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = 1; + pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[iptype]; - fd = open(IPA_DEVICE_NAME, O_RDWR); - if (fd < 0) + /* =========== add first pass flt rule (match dst MAC) ============= */ + rt_tbl.ip = iptype; + snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp"); + IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name); + + if(m_routing.GetRoutingTable(&rt_tbl) == false) { - IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + IPACMERR("Failed to get routing table.\n"); return IPACM_FAILURE; } + memset(&flt_rule_entry, 0, sizeof(flt_rule_entry)); + flt_rule_entry.at_rear = 1; - ul_pipe_found = false; - dl_pipe_found = false; - num_ul_packets = 0; - num_dl_packets = 0; - num_ul_bytes = 0; - num_dl_bytes = 0; + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl; + flt_rule_entry.rule.hashable = false; //WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction - if (data->dl_dst_pipe_stats_list_valid) + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + if(tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_ETHERNET_II) { - if(tx_prop != NULL) - { - for (pipe_len = 0; pipe_len < data->dl_dst_pipe_stats_list_len; pipe_len++) - { - IPACMDBG_H("Check entry(%d) dl_dst_pipe(%d)\n", pipe_len, data->dl_dst_pipe_stats_list[pipe_len].pipe_index); - for (cnt=0; cntnum_tx_props; cnt++) - { - IPACMDBG_H("Check Tx_prop_entry(%d) pipe(%d)\n", cnt, ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe)); - if(ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe) == data->dl_dst_pipe_stats_list[pipe_len].pipe_index) - { - /* update the DL stats */ - dl_pipe_found = true; - num_dl_packets += data->dl_dst_pipe_stats_list[pipe_len].num_ipv4_packets; - num_dl_packets += data->dl_dst_pipe_stats_list[pipe_len].num_ipv6_packets; - num_dl_bytes += data->dl_dst_pipe_stats_list[pipe_len].num_ipv4_bytes; - num_dl_bytes += data->dl_dst_pipe_stats_list[pipe_len].num_ipv6_bytes; - IPACMDBG_H("Got matched dst-pipe (%d) from %d tx props\n", data->dl_dst_pipe_stats_list[pipe_len].pipe_index, cnt); - IPACMDBG_H("DL_packets:(%lu) DL_bytes:(%lu) \n", num_dl_packets, num_dl_bytes); - break; - } - } - } - } + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; } - - if (data->ul_src_pipe_stats_list_valid) + else { - if(rx_prop != NULL) - { - for (pipe_len = 0; pipe_len < data->ul_src_pipe_stats_list_len; pipe_len++) - { - IPACMDBG_H("Check entry(%d) dl_dst_pipe(%d)\n", pipe_len, data->ul_src_pipe_stats_list[pipe_len].pipe_index); - for (cnt=0; cnt < rx_prop->num_rx_props; cnt++) - { - IPACMDBG_H("Check Rx_prop_entry(%d) pipe(%d)\n", cnt, ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe)); - if(ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe) == data->ul_src_pipe_stats_list[pipe_len].pipe_index) - { - /* update the UL stats */ - ul_pipe_found = true; - num_ul_packets += data->ul_src_pipe_stats_list[pipe_len].num_ipv4_packets; - num_ul_packets += data->ul_src_pipe_stats_list[pipe_len].num_ipv6_packets; - num_ul_bytes += data->ul_src_pipe_stats_list[pipe_len].num_ipv4_bytes; - num_ul_bytes += data->ul_src_pipe_stats_list[pipe_len].num_ipv6_bytes; - IPACMDBG_H("Got matched dst-pipe (%d) from %d tx props\n", data->ul_src_pipe_stats_list[pipe_len].pipe_index, cnt); - IPACMDBG_H("UL_packets:(%lu) UL_bytes:(%lu) \n", num_ul_packets, num_ul_bytes); - break; - } - } - } - } + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; } - close(fd); - if (ul_pipe_found || dl_pipe_found) + memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, dst_mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr)); + memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask)); + + memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry)); + if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable)) { - IPACMDBG_H("Update IPA_TETHERING_STATS_UPDATE_EVENT, TX(P%lu/B%lu) RX(P%lu/B%lu) DEV(%s) to LTE(%s) \n", - num_ul_packets, - num_ul_bytes, - num_dl_packets, - num_dl_bytes, - dev_name, - IPACM_Wan::wan_up_dev_name); - fp = fopen(IPA_PIPE_STATS_FILE_NAME, "w"); - if ( fp == NULL ) - { - IPACMERR("Failed to write pipe stats to %s, error is %d - %s\n", - IPA_PIPE_STATS_FILE_NAME, errno, strerror(errno)); - return IPACM_FAILURE; - } + IPACMERR("Failed to add first pass filtering rules.\n"); + free(pFilteringTable); + return IPACM_FAILURE; + } + *first_pass_flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl; - fprintf(fp, PIPE_STATS, - dev_name, - IPACM_Wan::wan_up_dev_name, - num_ul_bytes, - num_ul_packets, - num_dl_bytes, - num_dl_packets); - fclose(fp); + /* =========== add second pass flt rule (match VLAN interface IPv6 address at client side) ============= */ + if(*second_pass_flt_rule_hdl != 0) + { + IPACMDBG_H("Second pass flt rule was added before, return.\n"); + free(pFilteringTable); + return IPACM_SUCCESS; } - return IPACM_SUCCESS; -} -/*handle tether client */ -int IPACM_Lan::handle_tethering_client(bool reset, ipacm_client_enum ipa_client) -{ - int cnt, fd, ret = IPACM_SUCCESS; - int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); - wan_ioctl_set_tether_client_pipe tether_client; + rt_tbl.ip = IPA_IP_v6; + snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp"); + IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name); - if(fd_wwan_ioctl < 0) + if(m_routing.GetRoutingTable(&rt_tbl) == false) { - IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + IPACMERR("Failed to get routing table.\n"); return IPACM_FAILURE; } - fd = open(IPA_DEVICE_NAME, O_RDWR); - if (fd < 0) + pFilteringTable->ip = IPA_IP_v6; + pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[IPA_IP_v6]; + + memset(&flt_rule_entry, 0, sizeof(flt_rule_entry)); + flt_rule_entry.at_rear = 1; + + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl; + flt_rule_entry.rule.hashable = false; //WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction + + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + + memcpy(flt_rule_entry.rule.attrib.u.v6.dst_addr, vlan_client_ipv6_addr, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr)); + memset(flt_rule_entry.rule.attrib.u.v6.dst_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr_mask)); + + memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry)); + if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable)) { - IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); - close(fd_wwan_ioctl); + IPACMERR("Failed to add client filtering rules.\n"); + free(pFilteringTable); return IPACM_FAILURE; } + *second_pass_flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl; - memset(&tether_client, 0, sizeof(tether_client)); - tether_client.reset_client = reset; - tether_client.ipa_client = ipa_client; + free(pFilteringTable); +#endif + return IPACM_SUCCESS; +} - if(tx_prop != NULL) +/* delete l2tp flt rule on non l2tp interface */ +int IPACM_Lan::del_l2tp_flt_rule(ipa_ip_type iptype, uint32_t first_pass_flt_rule_hdl, uint32_t second_pass_flt_rule_hdl) +{ + if(first_pass_flt_rule_hdl != 0) { - tether_client.dl_dst_pipe_len = tx_prop->num_tx_props; - for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++) + if(m_filtering.DeleteFilteringHdls(&first_pass_flt_rule_hdl, iptype, 1) == false) { - IPACMDBG_H("Tx(%d), dst_pipe: %d, ipa_pipe: %d\n", - cnt, tx_prop->tx[cnt].dst_pipe, - ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe)); - tether_client.dl_dst_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe); + return IPACM_FAILURE; } } - if(rx_prop != NULL) + if(second_pass_flt_rule_hdl != 0) { - tether_client.ul_src_pipe_len = rx_prop->num_rx_props; - for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++) + if(m_filtering.DeleteFilteringHdls(&second_pass_flt_rule_hdl, iptype, 1) == false) { - IPACMDBG_H("Rx(%d), src_pipe: %d, ipa_pipe: %d\n", - cnt, rx_prop->rx[cnt].src_pipe, - ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe)); - tether_client.ul_src_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe); + return IPACM_FAILURE; } } - ret = ioctl(fd_wwan_ioctl, WAN_IOC_SET_TETHER_CLIENT_PIPE, &tether_client); - if (ret != 0) + return IPACM_SUCCESS; +} + +bool IPACM_Lan::is_unique_local_ipv6_addr(uint32_t* ipv6_addr) +{ + uint32_t ipv6_unique_local_prefix, ipv6_unique_local_prefix_mask; + + if(ipv6_addr == NULL) { - IPACMERR("Failed set tether-client-pipe %p with ret %d\n ", &tether_client, ret); + IPACMERR("IPv6 address is empty.\n"); + return false; } - IPACMDBG("Set tether-client-pipe %p\n", &tether_client); - close(fd); - close(fd_wwan_ioctl); - return ret; + IPACMDBG_H("Get ipv6 address with first word 0x%08x.\n", ipv6_addr[0]); + + ipv6_unique_local_prefix = 0xFD000000; + ipv6_unique_local_prefix_mask = 0xFF000000; + if((ipv6_addr[0] & ipv6_unique_local_prefix_mask) == (ipv6_unique_local_prefix & ipv6_unique_local_prefix_mask)) + { + IPACMDBG_H("This IPv6 address is unique local IPv6 address.\n"); + return true; + } + return false; } diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp index c3c589b2..799dfee5 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2014, The Linux Foundation. All rights reserved. +Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -39,1567 +39,2010 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include -#include #include "IPACM_LanToLan.h" #include "IPACM_Wlan.h" -#define ipv6_multicast_addr 0xff000000 -#define ipv6_multicast_mask 0xff000000 +#define __stringify(x...) #x -#define max_cache_connection 20 +const char *ipa_l2_hdr_type[] = { + __stringify(NONE), + __stringify(ETH_II), + __stringify(802_3), + __stringify(L2_MAX) +}; -IPACM_LanToLan* IPACM_LanToLan::p_instance = NULL; +IPACM_LanToLan* IPACM_LanToLan::p_instance; + +IPACM_LanToLan_Iface::IPACM_LanToLan_Iface(IPACM_Lan *p_iface) +{ + int i; + + m_p_iface = p_iface; + memset(m_is_ip_addr_assigned, 0, sizeof(m_is_ip_addr_assigned)); + m_support_inter_iface_offload = true; + m_support_intra_iface_offload = false; + m_is_l2tp_iface = false; + for(i = 0; i < IPA_HDR_L2_MAX; i++) + { + ref_cnt_peer_l2_hdr_type[i] = 0; + hdr_proc_ctx_for_inter_interface[i] = 0; + } + hdr_proc_ctx_for_intra_interface = 0; + hdr_proc_ctx_for_l2tp = 0; + + if(p_iface->ipa_if_cate == WLAN_IF) + { + IPACMDBG_H("Interface %s is WLAN interface.\n", p_iface->dev_name); + m_support_intra_iface_offload = true; + if( ((IPACM_Wlan*)p_iface)->is_guest_ap() ) + { + IPACMDBG_H("Interface %s is guest AP.\n", p_iface->dev_name); + m_support_inter_iface_offload = false; + } + } + return; +} + +IPACM_LanToLan_Iface::~IPACM_LanToLan_Iface() +{ +} IPACM_LanToLan::IPACM_LanToLan() { - num_offload_pair_v4_ = 0; - num_offload_pair_v6_ = 0; - client_info_v4_.reserve(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT); - client_info_v6_.reserve(3*(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT)); - p_instance = this; - - IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_ACTIVE, this); - IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_INACTIVE, this); - IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_DISCONNECT, this); - IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_POWER_SAVE, this); - IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_POWER_RECOVER, this); - IPACM_EvtDispatcher::registr(IPA_LAN_TO_LAN_NEW_CONNECTION, this); - IPACM_EvtDispatcher::registr(IPA_LAN_TO_LAN_DEL_CONNECTION, this); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_IFACE_UP, this); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_IFACE_DOWN, this); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_CLIENT_ADD, this); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_CLIENT_DEL, this); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, this); + IPACM_EvtDispatcher::registr(IPA_ADD_VLAN_IFACE, this); + IPACM_EvtDispatcher::registr(IPA_DEL_VLAN_IFACE, this); + IPACM_EvtDispatcher::registr(IPA_ADD_L2TP_VLAN_MAPPING, this); + IPACM_EvtDispatcher::registr(IPA_DEL_L2TP_VLAN_MAPPING, this); + IPACM_EvtDispatcher::registr(IPA_HANDLE_VLAN_CLIENT_INFO, this); + IPACM_EvtDispatcher::registr(IPA_HANDLE_VLAN_IFACE_INFO, this); + + m_has_l2tp_iface = false; + return; } IPACM_LanToLan::~IPACM_LanToLan() { - client_table_v4::iterator it_v4; - for(it_v4 = client_info_v4_.begin(); it_v4 != client_info_v4_.end(); it_v4++) + IPACMDBG_DMESG("WARNING: UNEXPECTEDLY KILL LAN2LAN CONTROLLER!\n"); + return; +} + +IPACM_LanToLan* IPACM_LanToLan::get_instance() +{ + if(p_instance == NULL) { - turnoff_offload_links(IPA_IP_v4, &(it_v4->second)); - clear_peer_list(&(it_v4->second)); + p_instance = new IPACM_LanToLan(); + IPACMDBG_H("Created LanToLan instance.\n"); } - client_info_v4_.clear(); - IPACMDBG("Clear IPv4 hash table in Lan2Lan distructor.\n"); + return p_instance; +} + +bool IPACM_LanToLan::has_l2tp_iface() +{ + list::iterator it; + bool has_l2tp_iface = false; - client_table_v6::iterator it_v6; - for(it_v6 = client_info_v6_.begin(); it_v6 != client_info_v6_.end(); it_v6++) + for(it = m_iface.begin(); it != m_iface.end(); it++) { - turnoff_offload_links(IPA_IP_v6, &(it_v6->second)); - clear_peer_list(&(it_v6->second)); + if(it->is_l2tp_iface() == true) + { + has_l2tp_iface = true; + break; + } } - client_info_v6_.clear(); - IPACMDBG("Clear IPv6 hash table in Lan2Lan distructor.\n"); - - return; + return has_l2tp_iface; } void IPACM_LanToLan::event_callback(ipa_cm_event_id event, void* param) { + ipacm_event_eth_bridge *eth_bridge_data; + ipa_ioc_vlan_iface_info *vlan_iface_data; + ipa_ioc_l2tp_vlan_mapping_info *l2tp_vlan_mapping_data; + ipacm_event_data_all *vlan_data; + + IPACMDBG_H("Get %s event.\n", IPACM_Iface::ipacmcfg->getEventName(event)); + switch(event) { - case IPA_LAN_CLIENT_ACTIVE: + case IPA_ETH_BRIDGE_IFACE_UP: + { + eth_bridge_data = (ipacm_event_eth_bridge*)param; + handle_iface_up(eth_bridge_data); + break; + } + + case IPA_ETH_BRIDGE_IFACE_DOWN: { - IPACMDBG_H("Get IPA_LAN_CLIENT_ACTIVE event.\n"); - ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; - handle_client_active(data); + eth_bridge_data = (ipacm_event_eth_bridge*)param; + handle_iface_down(eth_bridge_data); break; } - case IPA_LAN_CLIENT_INACTIVE: + case IPA_ETH_BRIDGE_CLIENT_ADD: { - IPACMDBG_H("Get IPA_LAN_CLIENT_INACTIVE event.\n"); - ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; - handle_client_inactive(data); + eth_bridge_data = (ipacm_event_eth_bridge*)param; + handle_client_add(eth_bridge_data); break; } - case IPA_LAN_CLIENT_DISCONNECT: + case IPA_ETH_BRIDGE_CLIENT_DEL: { - IPACMDBG_H("Get IPA_LAN_CLIENT_DISCONNECT event.\n"); - ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; - handle_client_disconnect(data); + eth_bridge_data = (ipacm_event_eth_bridge*)param; + handle_client_del(eth_bridge_data); break; } - case IPA_LAN_TO_LAN_NEW_CONNECTION: + case IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH: { - IPACMDBG_H("Get IPA_LAN_TO_LAN_NEW_CONNECTION event.\n"); - ipacm_event_connection* data = (ipacm_event_connection*)param; - handle_new_lan2lan_connection(data); + eth_bridge_data = (ipacm_event_eth_bridge*)param; + handle_wlan_scc_mcc_switch(eth_bridge_data); break; } - case IPA_LAN_TO_LAN_DEL_CONNECTION: + case IPA_ADD_VLAN_IFACE: { - IPACMDBG_H("Get IPA_LAN_TO_LAN_DEL_CONNECTION event.\n"); - ipacm_event_connection* data = (ipacm_event_connection*)param; - handle_del_lan2lan_connection(data); + vlan_iface_data = (ipa_ioc_vlan_iface_info*)param; + handle_add_vlan_iface(vlan_iface_data); break; } - case IPA_LAN_CLIENT_POWER_SAVE: + + case IPA_DEL_VLAN_IFACE: { - IPACMDBG_H("Get IPA_LAN_CLIENT_POWER_SAVE event.\n"); - ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; - handle_client_power_save(data); + vlan_iface_data = (ipa_ioc_vlan_iface_info*)param; + handle_del_vlan_iface(vlan_iface_data); break; } - case IPA_LAN_CLIENT_POWER_RECOVER: + + case IPA_ADD_L2TP_VLAN_MAPPING: + { + l2tp_vlan_mapping_data = (ipa_ioc_l2tp_vlan_mapping_info*)param; + handle_add_l2tp_vlan_mapping(l2tp_vlan_mapping_data); + break; + } + + case IPA_DEL_L2TP_VLAN_MAPPING: { - IPACMDBG_H("Get IPA_LAN_CLIENT_POWER_RECOVER event.\n"); - ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; - handle_client_power_recover(data); + l2tp_vlan_mapping_data = (ipa_ioc_l2tp_vlan_mapping_info*)param; + handle_del_l2tp_vlan_mapping(l2tp_vlan_mapping_data); + break; + } + case IPA_HANDLE_VLAN_CLIENT_INFO: + { + vlan_data = (ipacm_event_data_all*)param; + handle_vlan_client_info(vlan_data); + break; + } + case IPA_HANDLE_VLAN_IFACE_INFO: + { + vlan_data = (ipacm_event_data_all*)param; + handle_vlan_iface_info(vlan_data); break; } default: break; } + + print_data_structure_info(); return; } -void IPACM_LanToLan::handle_client_active(ipacm_event_lan_client* data) +void IPACM_LanToLan::handle_iface_up(ipacm_event_eth_bridge *data) { - if(data == NULL) - { - IPACMERR("No client info is found.\n"); - return; - } - if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) - { - IPACMERR("Event data is not populated properly.\n"); - return; - } - if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) - { - IPACMERR("IP type is not expected.\n"); - return; - } - - IPACMDBG_H("New client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", - data->p_iface->dev_name, data->iptype, - data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], - data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + list::iterator it; + list::iterator it_mapping; + bool has_l2tp_iface = false; - bool client_not_found; - client_info* client_ptr; - - if(data->iptype == IPA_IP_v4) - { - client_not_found = (client_info_v4_.count(data->ipv4_addr) == 0); - IPACMDBG_H("Is the client not found? %d\n", client_not_found); - client_info& client = client_info_v4_[data->ipv4_addr]; - client_ptr = &client; - } - else + IPACMDBG_H("Interface name: %s IP type: %d\n", data->p_iface->dev_name, data->iptype); + for(it = m_iface.begin(); it != m_iface.end(); it++) { - uint64_t v6_addr; - memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); + if(it->get_iface_pointer() == data->p_iface) + { + IPACMDBG_H("Found the interface.\n"); + if(it->get_m_is_ip_addr_assigned(data->iptype) == false) + { + IPACMDBG_H("IP type %d was not active before, activating it now.\n", data->iptype); + it->set_m_is_ip_addr_assigned(data->iptype, true); + + /* install inter-interface rules */ + if(it->get_m_support_inter_iface_offload()) + it->add_all_inter_interface_client_flt_rule(data->iptype); - client_not_found = (client_info_v6_.count(v6_addr) == 0); - IPACMDBG_H("Is the client not found? %d\n", client_not_found); - client_info& client = client_info_v6_[v6_addr]; - client_ptr = &client; + /* install intra-BSS rules */ + if(it->get_m_support_intra_iface_offload()) + it->add_all_intra_interface_client_flt_rule(data->iptype); + } + break; + } } - if(client_not_found == true) + if(it == m_iface.end()) //If the interface has not been created before { - if(data->iptype == IPA_IP_v4) + if(m_iface.size() == MAX_NUM_IFACE) { - client_ptr->ip.ipv4_addr = data->ipv4_addr; + IPACMERR("The number of interfaces has reached maximum %d.\n", MAX_NUM_IFACE); + return; } - else + + if(!data->p_iface->tx_prop || !data->p_iface->rx_prop) { - memcpy(client_ptr->ip.ipv6_addr, data->ipv6_addr, sizeof(client_ptr->ip.ipv6_addr)); + IPACMERR("The interface %s does not have tx_prop or rx_prop.\n", data->p_iface->dev_name); + return; } - memcpy(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)); - client_ptr->is_active = true; - client_ptr->is_powersave = false; - client_ptr->p_iface = data->p_iface; - generate_new_connection(data->iptype, client_ptr); - check_cache_connection(data->iptype, client_ptr); - } - else //the client is found - { - if(client_ptr->is_active == true) //the client is active + if(data->p_iface->tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_NONE || data->p_iface->tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_MAX) { - IPACMDBG_H("The client is active.\n"); - if(memcmp(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)) == 0) + IPACMERR("Invalid l2 header type %s!\n", ipa_l2_hdr_type[data->p_iface->tx_prop->tx[0].hdr_l2_type]); + return; + } + + IPACMDBG_H("Does not find the interface, insert a new one.\n"); + IPACM_LanToLan_Iface new_iface(data->p_iface); + new_iface.set_m_is_ip_addr_assigned(data->iptype, true); + + m_iface.push_front(new_iface); + IPACMDBG_H("Now the total number of interfaces is %d.\n", m_iface.size()); + + IPACM_LanToLan_Iface &front_iface = m_iface.front(); +#ifdef FEATURE_L2TP + for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++) + { + if(front_iface.set_l2tp_iface(it_mapping->vlan_iface_name) == true) { - IPACMDBG_H("Mac addr is the same, do nothing.\n"); + has_l2tp_iface = true; } - else - { - IPACMERR("The new client has same IP but differenc mac.\n"); - turnoff_offload_links(data->iptype, client_ptr); - clear_peer_list(client_ptr); + } - if(data->iptype == IPA_IP_v4) - { - client_ptr->ip.ipv4_addr = data->ipv4_addr; - } - else + if(m_has_l2tp_iface == false && has_l2tp_iface == true) + { + IPACMDBG_H("There is l2tp iface, add rt rules for l2tp iface.\n"); + m_has_l2tp_iface = true; + for(it = ++m_iface.begin(); it != m_iface.end(); it++) + { + if(it->is_l2tp_iface() == false) { - memcpy(client_ptr->ip.ipv6_addr, data->ipv6_addr, sizeof(client_ptr->ip.ipv6_addr)); + it->handle_l2tp_enable(); } - memcpy(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)); - client_ptr->is_active = true; - client_ptr->is_powersave = false; - client_ptr->p_iface = data->p_iface; - - generate_new_connection(data->iptype, client_ptr); - check_cache_connection(data->iptype, client_ptr); } } - else //the client is inactive +#endif + /* install inter-interface rules */ + if(front_iface.get_m_support_inter_iface_offload()) { - IPACMDBG_H("The client is inactive.\n"); - if(data->iptype == IPA_IP_v4) - { - client_ptr->ip.ipv4_addr = data->ipv4_addr; - } - else + for(it = ++m_iface.begin(); it != m_iface.end(); it++) { - memcpy(client_ptr->ip.ipv6_addr, data->ipv6_addr, sizeof(client_ptr->ip.ipv6_addr)); + /* add peer info only when both interfaces support inter-interface communication */ + if(it->get_m_support_inter_iface_offload()) + { + /* populate hdr_proc_ctx and routing table handle */ + handle_new_iface_up(&front_iface, &(*it)); + + /* add client specific routing rule on existing interface */ + it->add_client_rt_rule_for_new_iface(); + } } - memcpy(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)); - client_ptr->is_active = true; - client_ptr->is_powersave = false; - client_ptr->p_iface = data->p_iface; - check_potential_link(data->iptype, client_ptr); - generate_new_connection(data->iptype, client_ptr); - check_cache_connection(data->iptype, client_ptr); + /* add client specific filtering rule on new interface */ + front_iface.add_all_inter_interface_client_flt_rule(data->iptype); } + + /* populate the intra-interface information */ + if(front_iface.get_m_support_intra_iface_offload()) + { + front_iface.handle_intra_interface_info(); + } + + /* handle cached client add event */ + handle_cached_client_add_event(front_iface.get_iface_pointer()); } - IPACMDBG_H("There are %d clients in v4 table and %d clients in v6 table.\n", client_info_v4_.size(), client_info_v6_.size()); return; } -void IPACM_LanToLan::check_potential_link(ipa_ip_type iptype, client_info* client) +void IPACM_LanToLan::handle_iface_down(ipacm_event_eth_bridge *data) { - if(client == NULL) + list::iterator it_target_iface; + bool has_l2tp_iface = false; + + IPACMDBG_H("Interface name: %s\n", data->p_iface->dev_name); + + for(it_target_iface = m_iface.begin(); it_target_iface != m_iface.end(); it_target_iface++) { - IPACMERR("Client is NULL.\n"); - return; + if(it_target_iface->get_iface_pointer() == data->p_iface) + { + IPACMDBG_H("Found the interface.\n"); + break; + } } - IPACMDBG_H("Check client's peer list.\n"); - IPACMDBG_H("Client: IP type: %d, IPv4 addr: 0x%08x, IPv6 addr: 0x%08x%08x%08x%08x\n", iptype, client->ip.ipv4_addr, - client->ip.ipv6_addr[0], client->ip.ipv6_addr[1], client->ip.ipv6_addr[2], client->ip.ipv6_addr[3]); + if(it_target_iface == m_iface.end()) + { + IPACMDBG_H("The interface has not been found.\n"); + /* clear cached client add event for the unfound interface*/ + clear_cached_client_add_event(data->p_iface); + return; + } - peer_info_list::iterator peer_it; - int res, num = 0; + it_target_iface->handle_down_event(); + m_iface.erase(it_target_iface); +#ifdef FEATURE_L2TP + for(it_target_iface = m_iface.begin(); it_target_iface != m_iface.end(); it_target_iface++) + { + if(it_target_iface->is_l2tp_iface() == true) + { + has_l2tp_iface = true; + break; + } + } - for(peer_it = client->peer.begin(); peer_it != client->peer.end(); peer_it++) + if(m_has_l2tp_iface == true && has_l2tp_iface == false) { - if(peer_it->peer_pointer->is_active == true && peer_it->num_connection > 0) + IPACMDBG_H("There is no l2tp iface now, delete rt rules for l2tp iface.\n"); + m_has_l2tp_iface = false; + for(it_target_iface = m_iface.begin(); it_target_iface != m_iface.end(); it_target_iface++) { - res = IPACM_SUCCESS; - res = add_offload_link(iptype, client, peer_it->peer_pointer); - res = add_offload_link(iptype, peer_it->peer_pointer, client); - if(res == IPACM_SUCCESS) + if(it_target_iface->is_l2tp_iface() == false) { - if(iptype == IPA_IP_v4) - { - num_offload_pair_v4_ ++; - IPACMDBG_H("Now the number of v4 offload links is %d.\n", num_offload_pair_v4_); - } - else - { - num_offload_pair_v6_ ++; - IPACMDBG_H("Now the number of v6 offload links is %d.\n", num_offload_pair_v6_); - } - num++; + it_target_iface->handle_l2tp_disable(); } } } - IPACMDBG_H("Added %d offload links in total.\n", num); +#endif return; } -int IPACM_LanToLan::add_offload_link(ipa_ip_type iptype, client_info* client, client_info* peer) +void IPACM_LanToLan::handle_new_iface_up(IPACM_LanToLan_Iface *new_iface, IPACM_LanToLan_Iface *exist_iface) { - if( (iptype == IPA_IP_v4 && num_offload_pair_v4_ >= MAX_OFFLOAD_PAIR) - || (iptype == IPA_IP_v6 && num_offload_pair_v6_ >= MAX_OFFLOAD_PAIR) ) - { - IPACMDBG_H("The number of offload pairs already reaches maximum.\n"); - return IPACM_FAILURE; - } - if(client == NULL || peer == NULL) - { - IPACMERR("Either client or peer is NULL.\n"); - return IPACM_FAILURE; - } + char rt_tbl_name_for_flt[IPA_IP_MAX][IPA_RESOURCE_NAME_MAX]; + char rt_tbl_name_for_rt[IPA_IP_MAX][IPA_RESOURCE_NAME_MAX]; - uint32_t hdr_hdl, flt_hdl; - lan_to_lan_rt_rule_hdl rt_rule_hdl; + IPACMDBG_H("Populate peer info between: new_iface %s, existing iface %s\n", new_iface->get_iface_pointer()->dev_name, + exist_iface->get_iface_pointer()->dev_name); - offload_link_info link_info; + /* populate the routing table information */ + snprintf(rt_tbl_name_for_flt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX, "eth_v4_%s_to_%s", + ipa_l2_hdr_type[exist_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type], + ipa_l2_hdr_type[new_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type]); + IPACMDBG_H("IPv4 routing table for flt name: %s\n", rt_tbl_name_for_flt[IPA_IP_v4]); + snprintf(rt_tbl_name_for_flt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX, "eth_v6_%s_to_%s", + ipa_l2_hdr_type[exist_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type], + ipa_l2_hdr_type[new_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type]); + IPACMDBG_H("IPv6 routing table for flt name: %s\n", rt_tbl_name_for_flt[IPA_IP_v6]); - if(iptype == IPA_IP_v4) - { - IPACMDBG_H("Add offload link for IPv4, client IP: 0x%08x, peer IP: 0x%08x \n", client->ip.ipv4_addr, peer->ip.ipv4_addr); - } - else if(iptype == IPA_IP_v6) - { - IPACMDBG_H("Add offload link for IPv6, client IP: 0x%08x%08x%08x%08x, peer IP: 0x%08x%08x%08x%08x \n", - client->ip.ipv6_addr[0], client->ip.ipv6_addr[1], client->ip.ipv6_addr[2], client->ip.ipv6_addr[3], - peer->ip.ipv6_addr[0], peer->ip.ipv6_addr[1], peer->ip.ipv6_addr[2], peer->ip.ipv6_addr[3]); - } - else - { - IPACMERR("IP type is not expected.\n"); - return IPACM_FAILURE; - } + snprintf(rt_tbl_name_for_rt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX, "eth_v4_%s_to_%s", + ipa_l2_hdr_type[new_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type], + ipa_l2_hdr_type[exist_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type]); + IPACMDBG_H("IPv4 routing table for rt name: %s\n", rt_tbl_name_for_rt[IPA_IP_v4]); - //add lan2lan header - if(peer->p_iface->add_lan2lan_hdr(iptype, client->mac_addr, peer->mac_addr, &hdr_hdl) == IPACM_FAILURE) - { - IPACMERR("Failed to create lan2lan header.\n"); - return IPACM_FAILURE; - } - IPACMDBG_H("Created lan2lan hdr with hdl %d.\n", hdr_hdl); + snprintf(rt_tbl_name_for_rt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX, "eth_v6_%s_to_%s", + ipa_l2_hdr_type[new_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type], + ipa_l2_hdr_type[exist_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type]); + IPACMDBG_H("IPv6 routing table for rt name: %s\n", rt_tbl_name_for_rt[IPA_IP_v6]); + + /* add new peer info in both new iface and existing iface */ + exist_iface->handle_new_iface_up(rt_tbl_name_for_flt, rt_tbl_name_for_rt, new_iface); - //add lan2lan routing/filtering rules - if(peer->p_iface->add_lan2lan_rt_rule(iptype, client->ip.ipv4_addr, peer->ip.ipv4_addr, - client->ip.ipv6_addr, peer->ip.ipv6_addr, hdr_hdl, &rt_rule_hdl) == IPACM_FAILURE) + new_iface->handle_new_iface_up(rt_tbl_name_for_rt, rt_tbl_name_for_flt, exist_iface); + + return; +} + +void IPACM_LanToLan::handle_client_add(ipacm_event_eth_bridge *data) +{ + list::iterator it_iface; + list::iterator it_mapping; + l2tp_vlan_mapping_info *mapping_info = NULL; + bool is_l2tp_client = false; + + IPACMDBG_H("Incoming client MAC: 0x%02x%02x%02x%02x%02x%02x, interface: %s\n", data->mac_addr[0], data->mac_addr[1], + data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], data->p_iface->dev_name); +#ifdef FEATURE_L2TP + for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++) + { + if(strncmp(it_mapping->l2tp_iface_name, data->iface_name, + sizeof(it_mapping->l2tp_iface_name)) == 0) + { + IPACMDBG_H("Found l2tp iface %s with l2tp client MAC 0x%02x%02x%02x%02x%02x%02x\n", + it_mapping->l2tp_iface_name, it_mapping->l2tp_client_mac[0], it_mapping->l2tp_client_mac[1], + it_mapping->l2tp_client_mac[2], it_mapping->l2tp_client_mac[3], it_mapping->l2tp_client_mac[4], + it_mapping->l2tp_client_mac[5]); + memcpy(it_mapping->l2tp_client_mac, data->mac_addr, sizeof(it_mapping->l2tp_client_mac)); + mapping_info = &(*it_mapping); + is_l2tp_client = true; + break; + } + } +#endif + for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++) { - IPACMERR("Failed to create lan2lan rt rule.\n"); - goto rt_fail; + if(it_iface->get_iface_pointer() == data->p_iface) //find the interface + { + IPACMDBG_H("Found the interface.\n"); + it_iface->handle_client_add(data->mac_addr, is_l2tp_client, mapping_info); + break; + } } - IPACMDBG_H("Created %d lan2lan rt rules.\n", rt_rule_hdl.num_rule); - IPACMDBG_H("Created lan2lan rt rules with hdl: %d.\n", rt_rule_hdl.rule_hdl[0]); - if(client->p_iface->add_lan2lan_flt_rule(iptype, client->ip.ipv4_addr, peer->ip.ipv4_addr, - client->ip.ipv6_addr, peer->ip.ipv6_addr, &flt_hdl) == IPACM_FAILURE) + /* if the iface was not found, cache the client add event */ + if(it_iface == m_iface.end()) { - IPACMERR("Failed to create lan2lan flt rule.\n"); - goto flt_fail; + IPACMDBG_H("The interface is not found.\n"); + if(m_cached_client_add_event.size() < MAX_NUM_CACHED_CLIENT_ADD_EVENT) + { + IPACMDBG_H("Cached the client information.\n"); + m_cached_client_add_event.push_front(*data); + } + else + { + IPACMDBG_H("Cached client add event has reached maximum number.\n"); + } } - IPACMDBG_H("Created lan2lan flt rule with hdl %d.\n", flt_hdl); - - link_info.peer_pointer = peer; - link_info.flt_rule_hdl = flt_hdl; - link_info.hdr_hdl = hdr_hdl; - memcpy(&link_info.rt_rule_hdl, &rt_rule_hdl, sizeof(lan_to_lan_rt_rule_hdl)); - - client->link.push_back(link_info); - - return IPACM_SUCCESS; - -flt_fail: - peer->p_iface->del_lan2lan_rt_rule(iptype, rt_rule_hdl); - -rt_fail: - peer->p_iface->del_lan2lan_hdr(iptype, hdr_hdl); - - return IPACM_FAILURE; + return; } -void IPACM_LanToLan::handle_client_inactive(ipacm_event_lan_client* data) +void IPACM_LanToLan::handle_client_del(ipacm_event_eth_bridge *data) { - if(data == NULL) - { - IPACMERR("No client info is found.\n"); - return; - } - if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) + list::iterator it_iface; + + IPACMDBG_H("Incoming client MAC: 0x%02x%02x%02x%02x%02x%02x, interface: %s\n", data->mac_addr[0], data->mac_addr[1], + data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], data->p_iface->dev_name); + + for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++) { - IPACMERR("Event data is not populated properly.\n"); - return; + if(it_iface->get_iface_pointer() == data->p_iface) //found the interface + { + IPACMDBG_H("Found the interface.\n"); + it_iface->handle_client_del(data->mac_addr); + break; + } } - if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) + + if(it_iface == m_iface.end()) { - IPACMERR("IP type is not expected: %d.\n", data->iptype); - return; + IPACMDBG_H("The interface is not found.\n"); } - IPACMDBG_H("Del client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", - data->p_iface->dev_name, data->iptype, - data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], - data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + return; +} - client_info* client_ptr; - uint64_t v6_addr; +void IPACM_LanToLan::handle_wlan_scc_mcc_switch(ipacm_event_eth_bridge *data) +{ + list::iterator it_iface; - if(data->iptype == IPA_IP_v4) + IPACMDBG_H("Incoming interface: %s\n", data->p_iface->dev_name); + for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++) { - if(client_info_v4_.count(data->ipv4_addr) == 0)//if not found the client, return + if(it_iface->get_iface_pointer() == data->p_iface) { - IPACMERR("The client is not found the client, return.\n"); - return; + it_iface->handle_wlan_scc_mcc_switch(); + break; } - IPACMDBG_H("The client is found.\n"); - client_info& client = client_info_v4_[data->ipv4_addr]; - client_ptr = &client; } - else + return; +} + +void IPACM_LanToLan::handle_add_vlan_iface(ipa_ioc_vlan_iface_info *data) +{ + list::iterator it_vlan; + list::iterator it_mapping; + vlan_iface_info new_vlan_info; + + IPACMDBG_H("Vlan iface: %s vlan id: %d\n", data->name, data->vlan_id); + for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++) { - memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); - if(client_info_v6_.count(v6_addr) == 0) //if not found the client, insert it in table + if(strncmp(it_vlan->vlan_iface_name, data->name, sizeof(it_vlan->vlan_iface_name)) == 0) { - IPACMERR("The client is not found the client, return.\n"); + IPACMERR("The vlan iface was added before with id %d\n", it_vlan->vlan_id); return; } - IPACMDBG_H("The client is found.\n"); - client_info& client = client_info_v6_[v6_addr]; - client_ptr = &client; } - turnoff_offload_links(data->iptype, client_ptr); - client_ptr->is_active = false; - if(client_ptr->peer.size() == 0) + for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++) { - IPACMDBG_H("Peer list is empty, remove client entry.\n"); - if(data->iptype == IPA_IP_v4) + if(strncmp(data->name, it_mapping->vlan_iface_name, sizeof(data->name)) == 0) { - client_info_v4_.erase(data->ipv4_addr); - } - else - { - client_info_v6_.erase(v6_addr); + IPACMDBG_H("Found a mapping: l2tp iface %s.\n", it_mapping->l2tp_iface_name); + it_mapping->vlan_id = data->vlan_id; } } + + memset(&new_vlan_info, 0 , sizeof(new_vlan_info)); + strlcpy(new_vlan_info.vlan_iface_name, data->name, sizeof(new_vlan_info.vlan_iface_name)); + new_vlan_info.vlan_id = data->vlan_id; + m_vlan_iface.push_front(new_vlan_info); return; } -int IPACM_LanToLan::turnoff_offload_links(ipa_ip_type iptype, client_info* client) +void IPACM_LanToLan::handle_del_vlan_iface(ipa_ioc_vlan_iface_info *data) { - if(client == NULL) - { - IPACMERR("Client is NULL.\n"); - return IPACM_FAILURE; - } - - bool err_flag; - offload_link_info_list::iterator client_it; - offload_link_info_list::iterator peer_it; - client_info* peer; + list::iterator it_vlan; + list::iterator it_mapping; - for(client_it = client->link.begin(); client_it != client->link.end(); client_it++) + IPACMDBG_H("Vlan iface: %s vlan id: %d\n", data->name, data->vlan_id); + for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++) { - peer = client_it->peer_pointer; - if(del_offload_link(iptype, client->p_iface, peer->p_iface, &(*client_it)) == IPACM_FAILURE) + if(strncmp(it_vlan->vlan_iface_name, data->name, sizeof(it_vlan->vlan_iface_name)) == 0) { - IPACMERR("Failed to delete client's offload link.\n"); - return IPACM_FAILURE; + IPACMDBG_H("Found the vlan interface\n"); + m_vlan_iface.erase(it_vlan); + break; } + } - err_flag = true; - for(peer_it = peer->link.begin(); peer_it != peer->link.end(); peer_it++) - { - if(peer_it->peer_pointer == client) - { - if(del_offload_link(iptype, peer->p_iface, client->p_iface, &(*peer_it)) == IPACM_FAILURE) - { - IPACMERR("Failed to delete peer's offload link.\n"); - return IPACM_FAILURE; - } - peer->link.erase(peer_it); - err_flag = false; - break; - } - } - if(err_flag) - { - IPACMERR("Unable to find corresponding offload link in peer's entry.\n"); - return IPACM_FAILURE; - } - if(iptype == IPA_IP_v4) + it_mapping = m_l2tp_vlan_mapping.begin(); + while(it_mapping != m_l2tp_vlan_mapping.end()) + { + if(strncmp(data->name, it_mapping->vlan_iface_name, sizeof(data->name)) == 0) { - num_offload_pair_v4_ --; - IPACMDBG_H("Now the number of v4 offload pair is %d\n", num_offload_pair_v4_); + IPACMDBG_H("Delete mapping with l2tp iface %s\n", it_mapping->l2tp_iface_name); + it_mapping = m_l2tp_vlan_mapping.erase(it_mapping); } else { - num_offload_pair_v6_ --; - IPACMDBG_H("Now the number of v6 offload pair is %d\n", num_offload_pair_v6_); + it_mapping++; } } - - client->link.clear(); - return IPACM_SUCCESS; + return; } -int IPACM_LanToLan::del_offload_link(ipa_ip_type iptype, IPACM_Lan* client, IPACM_Lan* peer, offload_link_info* link) +void IPACM_LanToLan::handle_add_l2tp_vlan_mapping(ipa_ioc_l2tp_vlan_mapping_info *data) { - if(client == NULL || peer == NULL || link == NULL) + list::iterator it_mapping; + list::iterator it_vlan; + list::iterator it_iface; + l2tp_vlan_mapping_info new_mapping; + bool has_l2tp_iface = false; + + IPACMDBG_H("L2tp iface: %s session id: %d vlan iface: %s \n", + data->l2tp_iface_name, data->l2tp_session_id, data->vlan_iface_name); + for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++) { - IPACMERR("Either iface or link is NULL.\n"); - return IPACM_FAILURE; + if(strncmp(data->l2tp_iface_name, it_mapping->l2tp_iface_name, + sizeof(data->l2tp_iface_name)) == 0) + { + IPACMERR("L2tp mapping was added before mapped to vlan %s.\n", it_mapping->vlan_iface_name); + return; + } } + memset(&new_mapping, 0, sizeof(new_mapping)); + strlcpy(new_mapping.l2tp_iface_name, data->l2tp_iface_name, + sizeof(new_mapping.l2tp_iface_name)); + strlcpy(new_mapping.vlan_iface_name, data->vlan_iface_name, + sizeof(new_mapping.vlan_iface_name)); + new_mapping.l2tp_session_id = data->l2tp_session_id; - IPACMDBG_H("Delete an offload link for IP type: %d\n", iptype); - - int res = IPACM_SUCCESS; - - if(client->del_lan2lan_flt_rule(iptype, link->flt_rule_hdl) == IPACM_FAILURE) + for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++) { - IPACMERR("Failed to delete flt rule.\n"); - res = IPACM_FAILURE; + if(strncmp(it_vlan->vlan_iface_name, data->vlan_iface_name, sizeof(it_vlan->vlan_iface_name)) == 0) + { + IPACMDBG_H("Found vlan iface with id %d\n", it_vlan->vlan_id); + new_mapping.vlan_id = it_vlan->vlan_id; + memcpy(new_mapping.vlan_iface_ipv6_addr, it_vlan->vlan_iface_ipv6_addr, + sizeof(new_mapping.vlan_iface_ipv6_addr)); + memcpy(new_mapping.vlan_client_mac, it_vlan->vlan_client_mac, + sizeof(new_mapping.vlan_client_mac)); + memcpy(new_mapping.vlan_client_ipv6_addr, it_vlan->vlan_client_ipv6_addr, + sizeof(new_mapping.vlan_client_ipv6_addr)); + break; + } } + m_l2tp_vlan_mapping.push_front(new_mapping); - if(peer->del_lan2lan_rt_rule(iptype, link->rt_rule_hdl) == IPACM_FAILURE) + for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++) { - IPACMERR("Failed to delete rt rules.\n"); - res = IPACM_FAILURE; + if(it_iface->set_l2tp_iface(data->vlan_iface_name) == true) + { + has_l2tp_iface = true; + } } - if(peer->del_lan2lan_hdr(iptype, link->hdr_hdl) == IPACM_FAILURE) + if(m_has_l2tp_iface == false && has_l2tp_iface == true) { - IPACMERR("Failed to delete header.\n"); - res = IPACM_FAILURE; + IPACMDBG_H("There is l2tp iface, add rt rules for l2tp iface.\n"); + m_has_l2tp_iface = true; + for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++) + { + if(it_iface->is_l2tp_iface() == false) + { + it_iface->handle_l2tp_enable(); + } + } } - - return res; + return; } -void IPACM_LanToLan::handle_client_disconnect(ipacm_event_lan_client* data) +void IPACM_LanToLan::handle_del_l2tp_vlan_mapping(ipa_ioc_l2tp_vlan_mapping_info *data) { - if(data == NULL) - { - IPACMERR("No client info is found.\n"); - return; - } - if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) - { - IPACMERR("Event data is not populated properly.\n"); - return; - } - if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) + list::iterator it; + list::iterator it_iface; + + IPACMDBG_H("L2tp iface: %s session id: %d vlan iface: %s \n", + data->l2tp_iface_name, data->l2tp_session_id, data->vlan_iface_name); + for(it = m_l2tp_vlan_mapping.begin(); it != m_l2tp_vlan_mapping.end(); it++) { - IPACMERR("IP type is not expected: %d.\n", data->iptype); - return; + if(strncmp(data->l2tp_iface_name, it->l2tp_iface_name, + sizeof(data->l2tp_iface_name)) == 0) + { + IPACMDBG_H("Found l2tp iface mapped to vlan %s.\n", it->vlan_iface_name); + if(strncmp(data->vlan_iface_name, it->vlan_iface_name, + sizeof(data->vlan_iface_name)) == 0) + { + m_l2tp_vlan_mapping.erase(it); + } + else + { + IPACMERR("Incoming mapping is incorrect.\n"); + } + break; + } } + return; +} - IPACMDBG_H("Del client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", - data->p_iface->dev_name, data->iptype, - data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], - data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); +void IPACM_LanToLan::handle_vlan_client_info(ipacm_event_data_all *data) +{ + list::iterator it_mapping; + list::iterator it_vlan; + + IPACMDBG_H("Incoming vlan client iface: %s IPv6 address: 0x%08x%08x%08x%08x\n", data->iface_name, + data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + IPACMDBG_H("MAC address: 0x%02x%02x%02x%02x%02x%02x\n", data->mac_addr[0], data->mac_addr[1], + data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5]); - client_info* client_ptr; - uint64_t v6_addr; - if(data->iptype == IPA_IP_v4) + for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++) { - if(client_info_v4_.count(data->ipv4_addr) == 0) //if not found the client, return + if(strncmp(it_vlan->vlan_iface_name, data->iface_name, sizeof(it_vlan->vlan_iface_name)) == 0) { - IPACMERR("The client is not found the client, return.\n"); - return; + IPACMDBG_H("Found vlan iface in vlan list: %s\n", it_vlan->vlan_iface_name); + if(it_vlan->vlan_client_ipv6_addr[0] > 0 || it_vlan->vlan_client_ipv6_addr[1] > 0 || + it_vlan->vlan_client_ipv6_addr[2] > 0 || it_vlan->vlan_client_ipv6_addr[3] > 0) + { + IPACMDBG_H("Vlan client info has been populated before, return.\n"); + return; + } + memcpy(it_vlan->vlan_client_mac, data->mac_addr, sizeof(it_vlan->vlan_client_mac)); + memcpy(it_vlan->vlan_client_ipv6_addr, data->ipv6_addr, sizeof(it_vlan->vlan_client_ipv6_addr)); } - IPACMDBG_H("The client is found.\n"); - client_info& client = client_info_v4_[data->ipv4_addr]; - client_ptr = &client; } - else + + for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++) { - memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); - if(client_info_v6_.count(v6_addr) == 0) //if not found the client, insert it in table + if(strncmp(it_mapping->vlan_iface_name, data->iface_name, sizeof(it_mapping->vlan_iface_name)) == 0) { - IPACMERR("The client is not found the client, return.\n"); - return; + IPACMDBG_H("Found vlan iface in l2tp mapping list: %s, l2tp iface: %s\n", it_mapping->vlan_iface_name, + it_mapping->l2tp_iface_name); + memcpy(it_mapping->vlan_client_mac, data->mac_addr, sizeof(it_mapping->vlan_client_mac)); + memcpy(it_mapping->vlan_client_ipv6_addr, data->ipv6_addr, sizeof(it_mapping->vlan_client_ipv6_addr)); } - IPACMDBG_H("The client is found.\n"); - client_info& client = client_info_v6_[v6_addr]; - client_ptr = &client; } + return; +} + +void IPACM_LanToLan::handle_vlan_iface_info(ipacm_event_data_all *data) +{ + list::iterator it_vlan; + list::iterator it_mapping; + + IPACMDBG_H("Incoming vlan iface: %s IPv6 address: 0x%08x%08x%08x%08x\n", data->iface_name, + data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); - turnoff_offload_links(data->iptype, client_ptr); - clear_peer_list(client_ptr); - if(data->iptype == IPA_IP_v4) + for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++) { - client_info_v4_.erase(data->ipv4_addr); + if(strncmp(it_vlan->vlan_iface_name, data->iface_name, + sizeof(it_vlan->vlan_iface_name)) == 0) + { + IPACMDBG_H("Found vlan iface: %s\n", it_vlan->vlan_iface_name); + memcpy(it_vlan->vlan_iface_ipv6_addr, data->ipv6_addr, + sizeof(it_vlan->vlan_iface_ipv6_addr)); + + for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++) + { + if(strncmp(it_mapping->vlan_iface_name, it_vlan->vlan_iface_name, + sizeof(it_mapping->vlan_iface_name)) == 0) + { + IPACMDBG_H("Found the l2tp-vlan mapping: l2tp %s\n", it_mapping->l2tp_iface_name); + memcpy(it_mapping->vlan_iface_ipv6_addr, data->ipv6_addr, + sizeof(it_mapping->vlan_iface_ipv6_addr)); + } + } + break; + } } - else + + if(it_vlan == m_vlan_iface.end()) { - client_info_v6_.erase(v6_addr); + IPACMDBG_H("Failed to find the vlan iface: %s\n", data->iface_name); } return; } -int IPACM_LanToLan::clear_peer_list(client_info* client) +void IPACM_LanToLan::handle_cached_client_add_event(IPACM_Lan *p_iface) { - if(client == NULL) + list::iterator it; + + it = m_cached_client_add_event.begin(); + while(it != m_cached_client_add_event.end()) { - IPACMERR("Client is NULL.\n"); - return IPACM_FAILURE; + if(it->p_iface == p_iface) + { + IPACMDBG_H("Found client with MAC: 0x%02x%02x%02x%02x%02x%02x\n", it->mac_addr[0], it->mac_addr[1], + it->mac_addr[2], it->mac_addr[3], it->mac_addr[4], it->mac_addr[5]); + handle_client_add(&(*it)); + it = m_cached_client_add_event.erase(it); + } + else + { + it++; + } } + return; +} - bool err_flag; - peer_info_list::iterator client_it; - peer_info_list::iterator peer_it; - client_info* peer; +void IPACM_LanToLan::clear_cached_client_add_event(IPACM_Lan *p_iface) +{ + list::iterator it; - for(client_it = client->peer.begin(); client_it != client->peer.end(); client_it++) + it = m_cached_client_add_event.begin(); + while(it != m_cached_client_add_event.end()) { - err_flag = true; - peer = client_it->peer_pointer; - for(peer_it = peer->peer.begin(); peer_it != peer->peer.end(); peer_it++) + if(it->p_iface == p_iface) { - if(peer_it->peer_pointer == client) - { - peer->peer.erase(peer_it); - err_flag = false; - break; - } + IPACMDBG_H("Found client with MAC: 0x%02x%02x%02x%02x%02x%02x\n", it->mac_addr[0], it->mac_addr[1], + it->mac_addr[2], it->mac_addr[3], it->mac_addr[4], it->mac_addr[5]); + it = m_cached_client_add_event.erase(it); } - if(err_flag == true) + else { - IPACMERR("Failed to find peer info.\n"); - return IPACM_FAILURE; + it++; } } - client->peer.clear(); - return IPACM_SUCCESS; + return; } -void IPACM_LanToLan::handle_client_power_save(ipacm_event_lan_client* data) +void IPACM_LanToLan::print_data_structure_info() { - if(data == NULL) + list::iterator it; + list::iterator it_event; + list::iterator it_vlan; + list::iterator it_mapping; + int i; + + IPACMDBG_H("Is there l2tp interface? %d\n", m_has_l2tp_iface); + + IPACMDBG_H("There are %d vlan interfaces.\n", m_vlan_iface.size()); + for(it_vlan = m_vlan_iface.begin(); it_vlan != m_vlan_iface.end(); it_vlan++) { - IPACMERR("No client info is found.\n"); - return; + IPACMDBG_H("Vlan iface: %s, id: %d, ipv6 addr: 0x%08x%08x%08x%08x\n", it_vlan->vlan_iface_name, + it_vlan->vlan_id, it_vlan->vlan_iface_ipv6_addr[0], it_vlan->vlan_iface_ipv6_addr[1], + it_vlan->vlan_iface_ipv6_addr[2], it_vlan->vlan_iface_ipv6_addr[3]); + IPACMDBG_H("Vlan client mac: 0x%02x%02x%02x%02x%02x%02x, ipv6 addr: 0x%08x%08x%08x%08x\n", + it_vlan->vlan_client_mac[0], it_vlan->vlan_client_mac[1], it_vlan->vlan_client_mac[2], + it_vlan->vlan_client_mac[3], it_vlan->vlan_client_mac[4], it_vlan->vlan_client_mac[5], + it_vlan->vlan_client_ipv6_addr[0], it_vlan->vlan_client_ipv6_addr[1], it_vlan->vlan_client_ipv6_addr[2], + it_vlan->vlan_client_ipv6_addr[3]); } - if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) + + IPACMDBG_H("There are %d vlan-l2tp mapping.\n", m_l2tp_vlan_mapping.size()); + for(it_mapping = m_l2tp_vlan_mapping.begin(); it_mapping != m_l2tp_vlan_mapping.end(); it_mapping++) { - IPACMERR("Event data is not populated properly.\n"); - return; + IPACMDBG_H("L2tp iface: %s, session id: %d\n", it_mapping->l2tp_iface_name, it_mapping->l2tp_session_id); + IPACMDBG_H("Vlan iface: %s, id: %d, ipv6 addr: 0x%08x%08x%08x%08x\n", it_mapping->vlan_iface_name, + it_mapping->vlan_id, it_mapping->vlan_iface_ipv6_addr[0], it_mapping->vlan_iface_ipv6_addr[1], + it_mapping->vlan_iface_ipv6_addr[2], it_mapping->vlan_iface_ipv6_addr[3]); + IPACMDBG_H("Vlan client mac: 0x%02x%02x%02x%02x%02x%02x, ipv6 addr: 0x%08x%08x%08x%08x\n", + it_mapping->vlan_client_mac[0], it_mapping->vlan_client_mac[1], it_mapping->vlan_client_mac[2], + it_mapping->vlan_client_mac[3], it_mapping->vlan_client_mac[4], it_mapping->vlan_client_mac[5], + it_mapping->vlan_client_ipv6_addr[0], it_mapping->vlan_client_ipv6_addr[1], it_mapping->vlan_client_ipv6_addr[2], + it_mapping->vlan_client_ipv6_addr[3]); + IPACMDBG_H("L2tp client mac: 0x%02x%02x%02x%02x%02x%02x\n", it_mapping->l2tp_client_mac[0], it_mapping->l2tp_client_mac[1], + it_mapping->l2tp_client_mac[2], it_mapping->l2tp_client_mac[3], it_mapping->l2tp_client_mac[4], it_mapping->l2tp_client_mac[5]); } - if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) + + IPACMDBG_H("There are %d interfaces in total.\n", m_iface.size()); + for(it = m_iface.begin(); it != m_iface.end(); it++) { - IPACMERR("IP type is not expected: %d.\n", data->iptype); - return; + it->print_data_structure_info(); } - IPACMDBG_H("Client power save info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", - data->p_iface->dev_name, data->iptype, - data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], - data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); - - client_info* client_ptr; - uint64_t v6_addr; + IPACMDBG_H("There are %d cached client add events in total.\n", m_cached_client_add_event.size()); - if(data->iptype == IPA_IP_v4) + i = 1; + for(it_event = m_cached_client_add_event.begin(); it_event != m_cached_client_add_event.end(); it_event++) { - if(client_info_v4_.count(data->ipv4_addr) == 0)//if not found the client, return - { - IPACMERR("The client is not found the client, return.\n"); - return; - } - IPACMDBG_H("The client is found.\n"); - client_info& client = client_info_v4_[data->ipv4_addr]; - client_ptr = &client; + IPACMDBG_H("Client %d MAC: 0x%02x%02x%02x%02x%02x%02x, interface: %s\n", i, it_event->mac_addr[0], it_event->mac_addr[1], it_event->mac_addr[2], + it_event->mac_addr[3], it_event->mac_addr[4], it_event->mac_addr[5], it_event->p_iface->dev_name); + i++; } - else + + return; +} + +void IPACM_LanToLan_Iface::add_client_rt_rule_for_new_iface() +{ + list::iterator it; + ipa_hdr_l2_type peer_l2_type; + peer_iface_info &peer = m_peer_iface_info.front(); + + peer_l2_type = peer.peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type; + if(ref_cnt_peer_l2_hdr_type[peer_l2_type] == 1) { - memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); - if(client_info_v6_.count(v6_addr) == 0) //if not found the client, insert it in table + for(it = m_client_info.begin(); it != m_client_info.end(); it++) { - IPACMERR("The client is not found the client, return.\n"); - return; +#ifdef FEATURE_L2TP + if(it->is_l2tp_client == false) + { + add_client_rt_rule(&peer, &(*it)); + } + /* add l2tp rt rules */ + add_l2tp_client_rt_rule(&peer, &(*it)); +#else + add_client_rt_rule(&peer, &(*it)); +#endif } - IPACMDBG_H("The client is found.\n"); - client_info& client = client_info_v6_[v6_addr]; - client_ptr = &client; } - if(remove_flt_rules(data->iptype, client_ptr) == IPACM_FAILURE) - { - IPACMERR("Failed to remove flt rules when power save.\n"); - return; - } - client_ptr->is_active = false; - client_ptr->is_powersave = true; return; } -void IPACM_LanToLan::handle_new_lan2lan_connection(ipacm_event_connection* data) +void IPACM_LanToLan_Iface::add_client_rt_rule(peer_iface_info *peer_info, client_info *client) { - IPACMDBG_H("New lan2lan connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", data->iptype, data->src_ipv4_addr, data->dst_ipv4_addr); - IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", data->src_ipv6_addr[0], data->src_ipv6_addr[1], data->src_ipv6_addr[2], - data->src_ipv6_addr[3], data->dst_ipv6_addr[0], data->dst_ipv6_addr[1], data->dst_ipv6_addr[2], data->dst_ipv6_addr[3]); + int i, num_rt_rule; + uint32_t rt_rule_hdl[MAX_NUM_PROP]; + ipa_hdr_l2_type peer_l2_hdr_type; - client_info* src_client_ptr; - client_info* dst_client_ptr; + peer_l2_hdr_type = peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type; - if(data->iptype == IPA_IP_v4) + /* if the peer info is not for intra interface communication */ + if(peer_info->peer != this) { - if(client_info_v4_.count(data->src_ipv4_addr) == 0 || client_info_v4_.count(data->dst_ipv4_addr) == 0) + IPACMDBG_H("This is for inter interface communication.\n"); + + m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v4], hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type], + peer_l2_hdr_type, IPA_IP_v4, rt_rule_hdl, &num_rt_rule); + + client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4] = num_rt_rule; + IPACMDBG_H("Number of IPv4 routing rule is %d.\n", num_rt_rule); + for(i=0; iinter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i] = rt_rule_hdl[i]; } - client_info& src_client = client_info_v4_[data->src_ipv4_addr]; - src_client_ptr = &src_client; - client_info& dst_client = client_info_v4_[data->dst_ipv4_addr]; - dst_client_ptr = &dst_client; - } - else //ipv6 case - { - uint64_t src_ipv6_addr; - uint64_t dst_ipv6_addr; - memcpy(&src_ipv6_addr, &(data->src_ipv6_addr[2]), sizeof(uint64_t)); - memcpy(&dst_ipv6_addr, &(data->dst_ipv6_addr[2]), sizeof(uint64_t)); - if(client_info_v6_.count(src_ipv6_addr) == 0 || client_info_v6_.count(dst_ipv6_addr) == 0) + m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v6], hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type], + peer_l2_hdr_type, IPA_IP_v6, rt_rule_hdl, &num_rt_rule); + + client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6] = num_rt_rule; + IPACMDBG_H("Number of IPv6 routing rule is %d.\n", num_rt_rule); + for(i=0; iinter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i] = rt_rule_hdl[i]; } - client_info& src_client = client_info_v6_[src_ipv6_addr]; - src_client_ptr = &src_client; - client_info& dst_client = client_info_v6_[dst_ipv6_addr]; - dst_client_ptr = &dst_client; } - - IPACMDBG_H("Both src and dst are already in table.\n"); - bool is_first_connection; - is_first_connection = add_connection(src_client_ptr, dst_client_ptr); - - if(is_first_connection && src_client_ptr->is_active && dst_client_ptr->is_active) + else { - IPACMDBG_H("This is first connection, add offload links.\n"); + IPACMDBG_H("This is for intra interface communication.\n"); + m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v4], hdr_proc_ctx_for_intra_interface, + peer_l2_hdr_type, IPA_IP_v4, rt_rule_hdl, &num_rt_rule); - if(add_offload_link(data->iptype, src_client_ptr, dst_client_ptr) == IPACM_FAILURE) + client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4] = num_rt_rule; + IPACMDBG_H("Number of IPv4 routing rule is %d.\n", num_rt_rule); + for(i=0; idst direction.\n"); - return; + IPACMDBG_H("Routing rule %d handle %d\n", i, rt_rule_hdl[i]); + client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][i] = rt_rule_hdl[i]; } - if(add_offload_link(data->iptype, dst_client_ptr, src_client_ptr) == IPACM_FAILURE) + + m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v6], hdr_proc_ctx_for_intra_interface, + peer_l2_hdr_type, IPA_IP_v6, rt_rule_hdl, &num_rt_rule); + + client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6] = num_rt_rule; + IPACMDBG_H("Number of IPv6 routing rule is %d.\n", num_rt_rule); + for(i=0; isrc direction.\n"); - return; + IPACMDBG_H("Routing rule %d handle %d\n", i, rt_rule_hdl[i]); + client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][i] = rt_rule_hdl[i]; } + } - if(data->iptype == IPA_IP_v4) + return; +} + +void IPACM_LanToLan_Iface::add_l2tp_client_rt_rule(peer_iface_info *peer, client_info *client) +{ + ipa_hdr_l2_type peer_l2_hdr_type; + l2tp_vlan_mapping_info *mapping_info; + + peer_l2_hdr_type = peer->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type; + mapping_info = client->mapping_info; + if(client->is_l2tp_client) + { + m_p_iface->add_l2tp_rt_rule(IPA_IP_v4, client->mac_addr, peer_l2_hdr_type, mapping_info->l2tp_session_id, + mapping_info->vlan_id, mapping_info->vlan_client_mac, mapping_info->vlan_iface_ipv6_addr, + mapping_info->vlan_client_ipv6_addr, &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_hdl, + &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_proc_ctx_hdl[IPA_IP_v4], &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_hdr_hdl, + &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v4], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v4], + client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_rt_rule_hdl); + + m_p_iface->add_l2tp_rt_rule(IPA_IP_v6, client->mac_addr, peer_l2_hdr_type, mapping_info->l2tp_session_id, + mapping_info->vlan_id, mapping_info->vlan_client_mac, mapping_info->vlan_iface_ipv6_addr, + mapping_info->vlan_client_ipv6_addr, &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_hdl, + &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_proc_ctx_hdl[IPA_IP_v6], &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_hdr_hdl, + &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v6], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v6], + client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_rt_rule_hdl); + } + else + { + if(IPACM_LanToLan::get_instance()->has_l2tp_iface() == true) { - num_offload_pair_v4_ ++; - IPACMDBG_H("Added offload links, now num_offload_pair_v4_: %d\n", num_offload_pair_v4_); + m_p_iface->add_l2tp_rt_rule(IPA_IP_v6, client->mac_addr, &hdr_proc_ctx_for_l2tp, &client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v6], + client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v6]); } - else + } + return; +} + +void IPACM_LanToLan_Iface::add_all_inter_interface_client_flt_rule(ipa_ip_type iptype) +{ + list::iterator it_iface; + list::iterator it_client; + + for(it_iface = m_peer_iface_info.begin(); it_iface != m_peer_iface_info.end(); it_iface++) + { + IPACMDBG_H("Add flt rules for clients of interface %s.\n", it_iface->peer->get_iface_pointer()->dev_name); + for(it_client = it_iface->peer->m_client_info.begin(); it_client != it_iface->peer->m_client_info.end(); it_client++) { - num_offload_pair_v6_ ++; - IPACMDBG_H("Added offload links, now num_offload_pair_v6_: %d\n", num_offload_pair_v6_); + add_client_flt_rule(&(*it_iface), &(*it_client), iptype); } } return; } -//If need to insert an entry in peer list, return true, otherwise return false -bool IPACM_LanToLan::add_connection(client_info* src_client, client_info* dst_client) +void IPACM_LanToLan_Iface::add_all_intra_interface_client_flt_rule(ipa_ip_type iptype) { - if(src_client == NULL || dst_client == NULL) + list::iterator it_client; + + IPACMDBG_H("Add flt rules for own clients.\n"); + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) { - IPACMERR("Either source or dest client is NULL.\n"); - return false; + add_client_flt_rule(&m_intra_interface_info, &(*it_client), iptype); } - peer_info_list::iterator it; - peer_info new_peer; - bool ret = false; + return; +} + +void IPACM_LanToLan_Iface::add_one_client_flt_rule(IPACM_LanToLan_Iface *peer_iface, client_info *client) +{ + list::iterator it; - for(it = src_client->peer.begin(); it != src_client->peer.end(); it++) + for(it = m_peer_iface_info.begin(); it != m_peer_iface_info.end(); it++) { - if(it->peer_pointer == dst_client) + if(it->peer == peer_iface) { - it->num_connection++; - IPACMDBG_H("Find dst client entry in peer list, connection count: %d\n", it->num_connection); + IPACMDBG_H("Found the peer iface info.\n"); + if(m_is_ip_addr_assigned[IPA_IP_v4]) + { + add_client_flt_rule(&(*it), client, IPA_IP_v4); + } + if(m_is_ip_addr_assigned[IPA_IP_v6]) + { + add_client_flt_rule(&(*it), client, IPA_IP_v6); + } + break; } } - if(it == src_client->peer.end()) + return; +} + +void IPACM_LanToLan_Iface::add_client_flt_rule(peer_iface_info *peer, client_info *client, ipa_ip_type iptype) +{ + list::iterator it_flt; + uint32_t flt_rule_hdl; + uint32_t l2tp_first_pass_flt_rule_hdl = 0, l2tp_second_pass_flt_rule_hdl = 0; + flt_rule_info new_flt_info; + ipa_ioc_get_rt_tbl rt_tbl; + + if(m_is_l2tp_iface && iptype == IPA_IP_v4) { - IPACMDBG_H("Not finding dst client entry, insert a new one in peer list.\n"); - new_peer.peer_pointer = dst_client; - new_peer.num_connection = 1; - src_client->peer.push_back(new_peer); - ret = true; + IPACMDBG_H("No need to install IPv4 flt rule on l2tp interface.\n"); + return; } - for(it = dst_client->peer.begin(); it != dst_client->peer.end(); it++) + for(it_flt = peer->flt_rule.begin(); it_flt != peer->flt_rule.end(); it_flt++) { - if(it->peer_pointer == src_client) + if(it_flt->p_client == client) //the client is already in the flt info list { - it->num_connection++; - IPACMDBG_H("Find dst client entry in peer list, connection count: %d\n", it->num_connection); + IPACMDBG_H("The client is found in flt info list.\n"); break; } } - if(it == dst_client->peer.end()) + + if(it_flt != peer->flt_rule.end()) + { + l2tp_first_pass_flt_rule_hdl = it_flt->l2tp_first_pass_flt_rule_hdl[iptype]; + l2tp_second_pass_flt_rule_hdl = it_flt->l2tp_second_pass_flt_rule_hdl; + } + + if(m_is_l2tp_iface) { - IPACMDBG_H("Not finding src client entry, insert a new one in peer list.\n"); - new_peer.peer_pointer = src_client; - new_peer.num_connection = 1; - dst_client->peer.push_back(new_peer); - ret = true; + m_p_iface->add_l2tp_flt_rule(client->mac_addr, &l2tp_first_pass_flt_rule_hdl); } - return ret; + else + { + if(client->is_l2tp_client) + { + m_p_iface->add_l2tp_flt_rule(iptype, client->mac_addr, client->mapping_info->vlan_client_ipv6_addr, + &l2tp_first_pass_flt_rule_hdl, &l2tp_second_pass_flt_rule_hdl); + } + else + { + rt_tbl.ip = iptype; + memcpy(rt_tbl.name, peer->rt_tbl_name_for_flt[iptype], sizeof(rt_tbl.name)); + IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name); + + if(IPACM_Iface::m_routing.GetRoutingTable(&rt_tbl) == false) + { + IPACMERR("Failed to get routing table.\n"); + return; + } + + m_p_iface->eth_bridge_add_flt_rule(client->mac_addr, rt_tbl.hdl, + iptype, &flt_rule_hdl); + IPACMDBG_H("Installed flt rule for IP type %d: handle %d\n", iptype, flt_rule_hdl); + } + } + + if(it_flt != peer->flt_rule.end()) + { + it_flt->flt_rule_hdl[iptype] = flt_rule_hdl; + it_flt->l2tp_first_pass_flt_rule_hdl[iptype] = l2tp_first_pass_flt_rule_hdl; + it_flt->l2tp_second_pass_flt_rule_hdl = l2tp_second_pass_flt_rule_hdl; + } + else + { + IPACMDBG_H("The client is not found in flt info list, insert a new one.\n"); + memset(&new_flt_info, 0, sizeof(new_flt_info)); + new_flt_info.p_client = client; + new_flt_info.flt_rule_hdl[iptype] = flt_rule_hdl; + new_flt_info.l2tp_first_pass_flt_rule_hdl[iptype] = l2tp_first_pass_flt_rule_hdl; + new_flt_info.l2tp_second_pass_flt_rule_hdl = l2tp_second_pass_flt_rule_hdl; + + peer->flt_rule.push_front(new_flt_info); + } + + return; } -void IPACM_LanToLan::handle_del_lan2lan_connection(ipacm_event_connection* data) +void IPACM_LanToLan_Iface::del_one_client_flt_rule(IPACM_LanToLan_Iface *peer_iface, client_info *client) { - IPACMDBG_H("Del lan2lan connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", data->iptype, data->src_ipv4_addr, data->dst_ipv4_addr); - IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", data->src_ipv6_addr[0], data->src_ipv6_addr[1], data->src_ipv6_addr[2], - data->src_ipv6_addr[3], data->dst_ipv6_addr[0], data->dst_ipv6_addr[1], data->dst_ipv6_addr[2], data->dst_ipv6_addr[3]); - - bool res; - uint64_t src_ipv6_addr, dst_ipv6_addr; - client_info* src_client_ptr; - client_info* dst_client_ptr; + list::iterator it; - if(data->iptype == IPA_IP_v4) + for(it = m_peer_iface_info.begin(); it != m_peer_iface_info.end(); it++) { - if(client_info_v4_.count(data->src_ipv4_addr) == 0 - || client_info_v4_.count(data->dst_ipv4_addr) == 0) //if not found the client + if(it->peer == peer_iface) { - IPACMDBG_H("Not found either source or dest client, return.\n"); - return; + IPACMDBG_H("Found the peer iface info.\n"); + del_client_flt_rule(&(*it), client); + break; } - client_info& src_client = client_info_v4_[data->src_ipv4_addr]; - client_info& dst_client = client_info_v4_[data->dst_ipv4_addr]; - src_client_ptr = &src_client; - dst_client_ptr = &dst_client; } - else + return; +} + +void IPACM_LanToLan_Iface::del_client_flt_rule(peer_iface_info *peer, client_info *client) +{ + list::iterator it_flt; + + for(it_flt = peer->flt_rule.begin(); it_flt != peer->flt_rule.end(); it_flt++) { - memcpy(&src_ipv6_addr, &(data->src_ipv6_addr[2]), sizeof(uint64_t)); - memcpy(&dst_ipv6_addr, &(data->dst_ipv6_addr[2]), sizeof(uint64_t)); - if(client_info_v6_.count(src_ipv6_addr) == 0 - || client_info_v6_.count(dst_ipv6_addr) == 0)//if not found the client + if(it_flt->p_client == client) //found the client in flt info list { - IPACMDBG_H("Not found either source or dest client, return.\n"); - return; + IPACMDBG_H("Found the client in flt info list.\n"); + if(m_is_ip_addr_assigned[IPA_IP_v4]) + { + if(m_is_l2tp_iface) + { + IPACMDBG_H("No IPv4 client flt rule on l2tp iface.\n"); + } + else + { + if(client->is_l2tp_client) + { + m_p_iface->del_l2tp_flt_rule(IPA_IP_v4, it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4], + it_flt->l2tp_second_pass_flt_rule_hdl); + it_flt->l2tp_second_pass_flt_rule_hdl = 0; + IPACMDBG_H("Deleted IPv4 first pass flt rule %d and second pass flt rule %d.\n", + it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4], it_flt->l2tp_second_pass_flt_rule_hdl); + } + else + { + m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4); + IPACMDBG_H("Deleted IPv4 flt rule %d.\n", it_flt->flt_rule_hdl[IPA_IP_v4]); + } + } + } + if(m_is_ip_addr_assigned[IPA_IP_v6]) + { + if(m_is_l2tp_iface) + { + m_p_iface->del_l2tp_flt_rule(it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]); + IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]); + } + else + { + if(client->is_l2tp_client) + { + m_p_iface->del_l2tp_flt_rule(IPA_IP_v6, it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6], + it_flt->l2tp_second_pass_flt_rule_hdl); + IPACMDBG_H("Deleted IPv6 first pass flt rule %d and second pass flt rule %d.\n", + it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6], it_flt->l2tp_second_pass_flt_rule_hdl); + } + else + { + m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6); + IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it_flt->flt_rule_hdl[IPA_IP_v6]); + } + } + } + peer->flt_rule.erase(it_flt); + break; } - client_info& src_client = client_info_v6_[src_ipv6_addr]; - client_info& dst_client = client_info_v6_[dst_ipv6_addr]; - src_client_ptr = &src_client; - dst_client_ptr = &dst_client; } + return; +} - res = remove_connection(src_client_ptr, dst_client_ptr); +void IPACM_LanToLan_Iface::del_client_rt_rule(peer_iface_info *peer, client_info *client) +{ + ipa_hdr_l2_type peer_l2_hdr_type; + int i, num_rules; - if(res && src_client_ptr->is_active && dst_client_ptr->is_active) + peer_l2_hdr_type = peer->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type; + /* if the peer info is not for intra interface communication */ + if(peer->peer != this) { - IPACMDBG_H("Erase link info for both src and dst entries.\n"); - erase_offload_link(data->iptype, src_client_ptr, dst_client_ptr); + IPACMDBG_H("Delete routing rules for inter interface communication.\n"); + + if(client->is_l2tp_client == false) + { + num_rules = client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4]; + for(i = 0; i < num_rules; i++) + { + m_p_iface->eth_bridge_del_rt_rule(client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i], IPA_IP_v4); + IPACMDBG_H("IPv4 rt rule %d is deleted.\n", client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i]); + } + client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4] = 0; + + num_rules = client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6]; + for(i = 0; i < num_rules; i++) + { + m_p_iface->eth_bridge_del_rt_rule(client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i], IPA_IP_v6); + IPACMDBG_H("IPv6 rt rule %d is deleted.\n", client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i]); + } + client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6] = 0; + + if(IPACM_LanToLan::get_instance()->has_l2tp_iface() == true) + { + m_p_iface->del_l2tp_rt_rule(IPA_IP_v6, client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v6], + client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v6]); + } + } + else + { + m_p_iface->del_l2tp_rt_rule(IPA_IP_v4, client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_hdl, + client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_proc_ctx_hdl[IPA_IP_v4], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_hdr_hdl, + client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v4], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v4], + client->l2tp_rt_rule_hdl[peer_l2_hdr_type].second_pass_rt_rule_hdl); + + m_p_iface->del_l2tp_rt_rule(IPA_IP_v6, 0, client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_hdr_proc_ctx_hdl[IPA_IP_v6], + 0, client->l2tp_rt_rule_hdl[peer_l2_hdr_type].num_rt_hdl[IPA_IP_v6], client->l2tp_rt_rule_hdl[peer_l2_hdr_type].first_pass_rt_rule_hdl[IPA_IP_v6], + NULL); + } } else { - if(res && src_client_ptr->is_powersave && (dst_client_ptr->is_active || dst_client_ptr->is_powersave)) + IPACMDBG_H("Delete routing rules for intra interface communication.\n"); + num_rules = client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4]; + for(i = 0; i < num_rules; i++) { - IPACMDBG_H("Erase link info for both src and dst entries due to src powersave.\n"); - erase_offload_link(data->iptype, src_client_ptr, dst_client_ptr); + m_p_iface->eth_bridge_del_rt_rule(client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][i], IPA_IP_v4); + IPACMDBG_H("IPv4 rt rule %d is deleted.\n", client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][i]); } - if(res && dst_client_ptr->is_powersave && (src_client_ptr->is_active || src_client_ptr->is_powersave)) + client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4] = 0; + + num_rules = client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6]; + for(i = 0; i < num_rules; i++) { - IPACMDBG_H("Erase link info for both src and dst entries due to dst powersave.\n"); - erase_offload_link(data->iptype, dst_client_ptr, src_client_ptr); + m_p_iface->eth_bridge_del_rt_rule(client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][i], IPA_IP_v6); + IPACMDBG_H("IPv6 rt rule %d is deleted.\n", client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][i]); + } + client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6] = 0; + } + + return; +} + +void IPACM_LanToLan_Iface::handle_down_event() +{ + list::iterator it_other_iface; + list::iterator it_own_peer_info, it_other_iface_peer_info; + IPACM_LanToLan_Iface *other_iface; + + /* clear inter-interface rules */ + if(m_support_inter_iface_offload) + { + for(it_own_peer_info = m_peer_iface_info.begin(); it_own_peer_info != m_peer_iface_info.end(); + it_own_peer_info++) + { + /* decrement reference count of peer l2 header type on both interfaces*/ + decrement_ref_cnt_peer_l2_hdr_type(it_own_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type); + it_own_peer_info->peer->decrement_ref_cnt_peer_l2_hdr_type(m_p_iface->tx_prop->tx[0].hdr_l2_type); + + /* first clear all flt rule on target interface */ + IPACMDBG_H("Clear all flt rule on target interface.\n"); + clear_all_flt_rule_for_one_peer_iface(&(*it_own_peer_info)); + + other_iface = it_own_peer_info->peer; + /* then clear all flt/rt rule and hdr proc ctx for target interface on peer interfaces */ + IPACMDBG_H("Clear all flt/rt rules and hdr proc ctx for target interface on peer interfaces %s.\n", + it_own_peer_info->peer->get_iface_pointer()->dev_name); + for(it_other_iface_peer_info = other_iface->m_peer_iface_info.begin(); + it_other_iface_peer_info != other_iface->m_peer_iface_info.end(); + it_other_iface_peer_info++) + { + if(it_other_iface_peer_info->peer == this) //found myself in other iface's peer info list + { + IPACMDBG_H("Found the right peer info on other iface.\n"); + other_iface->clear_all_flt_rule_for_one_peer_iface(&(*it_other_iface_peer_info)); + other_iface->clear_all_rt_rule_for_one_peer_iface(&(*it_other_iface_peer_info)); + /* remove the peer info from the list */ + other_iface->m_peer_iface_info.erase(it_other_iface_peer_info); + other_iface->del_hdr_proc_ctx(m_p_iface->tx_prop->tx[0].hdr_l2_type); + break; + } + } + + /* then clear rt rule and hdr proc ctx and release rt table on target interface */ + IPACMDBG_H("Clear rt rules and hdr proc ctx and release rt table on target interface.\n"); + clear_all_rt_rule_for_one_peer_iface(&(*it_own_peer_info)); + del_hdr_proc_ctx(it_own_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type); } + m_peer_iface_info.clear(); + } + + /* clear intra interface rules */ + if(m_support_intra_iface_offload) + { + IPACMDBG_H("Clear intra interface flt/rt rules and hdr proc ctx, release rt tables.\n"); + clear_all_flt_rule_for_one_peer_iface(&m_intra_interface_info); + clear_all_rt_rule_for_one_peer_iface(&m_intra_interface_info); + m_p_iface->eth_bridge_del_hdr_proc_ctx(hdr_proc_ctx_for_intra_interface); + IPACMDBG_H("Hdr proc ctx with hdl %d is deleted.\n", hdr_proc_ctx_for_intra_interface); } - //if the src client is not active and not powersave mode, if peer list is empty, remove client entry - if(res && src_client_ptr->is_active == false && src_client_ptr->is_powersave == false && src_client_ptr->peer.size() == 0) + /* then clear the client info list */ + m_client_info.clear(); + + return; +} + +void IPACM_LanToLan_Iface::clear_all_flt_rule_for_one_peer_iface(peer_iface_info *peer) +{ + list::iterator it; + + for(it = peer->flt_rule.begin(); it != peer->flt_rule.end(); it++) { - IPACMDBG_H("Peer list of src is empty, remove src entry.\n"); - if(data->iptype == IPA_IP_v4) + if(m_is_ip_addr_assigned[IPA_IP_v4]) { - client_info_v4_.erase(data->src_ipv4_addr); + if(m_is_l2tp_iface) + { + IPACMDBG_H("No IPv4 client flt rule on l2tp iface.\n"); + } + else + { + if(it->p_client->is_l2tp_client) + { + m_p_iface->del_l2tp_flt_rule(IPA_IP_v4, it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4], + it->l2tp_second_pass_flt_rule_hdl); + it->l2tp_second_pass_flt_rule_hdl = 0; + IPACMDBG_H("Deleted IPv4 first pass flt rule %d and second pass flt rule %d.\n", + it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4], it->l2tp_second_pass_flt_rule_hdl); + } + else + { + m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4); + IPACMDBG_H("Deleted IPv4 flt rule %d.\n", it->flt_rule_hdl[IPA_IP_v4]); + } + } } - else + if(m_is_ip_addr_assigned[IPA_IP_v6]) { - client_info_v6_.erase(src_ipv6_addr); + if(m_is_l2tp_iface) + { + m_p_iface->del_l2tp_flt_rule(it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]); + IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]); + } + else + { + if(it->p_client->is_l2tp_client) + { + m_p_iface->del_l2tp_flt_rule(IPA_IP_v6, it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6], + it->l2tp_second_pass_flt_rule_hdl); + IPACMDBG_H("Deleted IPv6 first pass flt rule %d and second pass flt rule %d.\n", + it->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6], it->l2tp_second_pass_flt_rule_hdl); + } + else + { + m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6); + IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it->flt_rule_hdl[IPA_IP_v6]); + } + } } } + peer->flt_rule.clear(); + return; +} - //if the dst client is not active and not powersave mode, if peer list is empty, remove client entry - if(res && dst_client_ptr->is_active == false && dst_client_ptr->is_powersave == false && dst_client_ptr->peer.size() == 0) +void IPACM_LanToLan_Iface::clear_all_rt_rule_for_one_peer_iface(peer_iface_info *peer) +{ + list::iterator it; + ipa_hdr_l2_type peer_l2_type; + + peer_l2_type = peer->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type; + if(ref_cnt_peer_l2_hdr_type[peer_l2_type] == 0) { - IPACMDBG_H("Peer list of dst is empty, remove dst entry.\n"); - if(data->iptype == IPA_IP_v4) + for(it = m_client_info.begin(); it != m_client_info.end(); it++) { - client_info_v4_.erase(data->dst_ipv4_addr); + del_client_rt_rule(peer, &(*it)); } - else + if(IPACM_LanToLan::get_instance()->has_l2tp_iface() == true) { - client_info_v6_.erase(dst_ipv6_addr); + m_p_iface->eth_bridge_del_hdr_proc_ctx(hdr_proc_ctx_for_l2tp); + hdr_proc_ctx_for_l2tp = 0; } } + return; } -//If need to remove an entry in peer list, return true, otherwise return false -bool IPACM_LanToLan::remove_connection(client_info* src_client, client_info* dst_client) +void IPACM_LanToLan_Iface::handle_wlan_scc_mcc_switch() { - if(src_client == NULL || dst_client == NULL) - { - IPACMERR("Either source or dest client is NULL.\n"); - return false; - } + list::iterator it_peer_info; + list::iterator it_client; + ipa_hdr_l2_type peer_l2_hdr_type; + bool flag[IPA_HDR_L2_MAX]; + int i; - peer_info_list::iterator it; - bool ret = false; - - for(it = src_client->peer.begin(); it != src_client->peer.end(); it++) + /* modify inter-interface routing rules */ + if(m_support_inter_iface_offload) { - if(it->peer_pointer == dst_client) + IPACMDBG_H("Modify rt rules for peer interfaces.\n"); + memset(flag, 0, sizeof(flag)); + for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end(); it_peer_info++) { - it->num_connection--; - IPACMDBG_H("Find dst client entry in src peer list, connection count: %d\n", it->num_connection); - if(it->num_connection == 0) + peer_l2_hdr_type = it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type; + if(flag[peer_l2_hdr_type] == false) { - IPACMDBG_H("Need to remove dst entry in src peer list.\n"); - ret = true; + flag[peer_l2_hdr_type] = true; + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) + { + m_p_iface->eth_bridge_modify_rt_rule(it_client->mac_addr, hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type], + peer_l2_hdr_type, IPA_IP_v4, it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4], + it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4]); + IPACMDBG_H("The following IPv4 routing rules are modified:\n"); + for(i = 0; i < it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4]; i++) + { + IPACMDBG_H("%d\n", it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i]); + } + + m_p_iface->eth_bridge_modify_rt_rule(it_client->mac_addr, hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type], + peer_l2_hdr_type, IPA_IP_v6, it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6], + it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6]); + IPACMDBG_H("The following IPv6 routing rules are modified:\n"); + for(i = 0; i < it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6]; i++) + { + IPACMDBG_H("%d\n", it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i]); + } + } } - break; } } - if(ret == true) - { - src_client->peer.erase(it); - } - ret = false; - for(it = dst_client->peer.begin(); it != dst_client->peer.end(); it++) + /* modify routing rules for intra-interface communication */ + IPACMDBG_H("Modify rt rules for intra-interface communication.\n"); + if(m_support_intra_iface_offload) { - if(it->peer_pointer == src_client) + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) { - it->num_connection--; - IPACMDBG_H("Find src client entry in dst peer list, connection count: %d\n", it->num_connection); - if(it->num_connection == 0) + m_p_iface->eth_bridge_modify_rt_rule(it_client->mac_addr, hdr_proc_ctx_for_intra_interface, + m_p_iface->tx_prop->tx[0].hdr_l2_type, IPA_IP_v4, it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4], + it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4]); + IPACMDBG_H("The following IPv4 routing rules are modified:\n"); + for(i = 0; i < it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4]; i++) { - IPACMDBG_H("Need to remove src entry in dst peer list.\n"); - ret = true; + IPACMDBG_H("%d\n", it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][i]); + } + + m_p_iface->eth_bridge_modify_rt_rule(it_client->mac_addr, hdr_proc_ctx_for_intra_interface, + m_p_iface->tx_prop->tx[0].hdr_l2_type, IPA_IP_v6, it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6], + it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6]); + IPACMDBG_H("The following IPv6 routing rules are modified:\n"); + for(i = 0; i < it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6]; i++) + { + IPACMDBG_H("%d\n", it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][i]); } - break; } } - if(ret == true) - { - dst_client->peer.erase(it); - } - return ret; + + return; } -void IPACM_LanToLan::erase_offload_link(ipa_ip_type iptype, client_info* src_client, client_info* dst_client) +void IPACM_LanToLan_Iface::handle_intra_interface_info() { - if(src_client == NULL || dst_client == NULL) + uint32_t hdr_proc_ctx_hdl; + + if(m_p_iface->tx_prop == NULL) { - IPACMERR("Either source or dest client is NULL.\n"); + IPACMERR("No tx prop.\n"); return; } - offload_link_info_list::iterator it; - int res_src = IPACM_FAILURE, res_dst = IPACM_FAILURE; + m_intra_interface_info.peer = this; + + snprintf(m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX, + "eth_v4_intra_interface"); + IPACMDBG_H("IPv4 routing table for flt name: %s\n", m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v4]); + snprintf(m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX, + "eth_v6_intra_interface"); + IPACMDBG_H("IPv6 routing table for flt name: %s\n", m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v6]); + + memcpy(m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v4], m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v4], + IPA_RESOURCE_NAME_MAX); + IPACMDBG_H("IPv4 routing table for rt name: %s\n", m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v4]); + memcpy(m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v6], m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v6], + IPA_RESOURCE_NAME_MAX); + IPACMDBG_H("IPv6 routing table for rt name: %s\n", m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v6]); + + m_p_iface->eth_bridge_add_hdr_proc_ctx(m_p_iface->tx_prop->tx[0].hdr_l2_type, + &hdr_proc_ctx_hdl); + hdr_proc_ctx_for_intra_interface = hdr_proc_ctx_hdl; + IPACMDBG_H("Hdr proc ctx for intra-interface communication: hdl %d\n", hdr_proc_ctx_hdl); + + return; +} + +void IPACM_LanToLan_Iface::handle_new_iface_up(char rt_tbl_name_for_flt[][IPA_RESOURCE_NAME_MAX], char rt_tbl_name_for_rt[][IPA_RESOURCE_NAME_MAX], + IPACM_LanToLan_Iface *peer_iface) +{ + peer_iface_info new_peer; + ipa_hdr_l2_type peer_l2_hdr_type; + + new_peer.peer = peer_iface; + memcpy(new_peer.rt_tbl_name_for_rt[IPA_IP_v4], rt_tbl_name_for_rt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX); + memcpy(new_peer.rt_tbl_name_for_rt[IPA_IP_v6], rt_tbl_name_for_rt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX); + memcpy(new_peer.rt_tbl_name_for_flt[IPA_IP_v4], rt_tbl_name_for_flt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX); + memcpy(new_peer.rt_tbl_name_for_flt[IPA_IP_v6], rt_tbl_name_for_flt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX); + + peer_l2_hdr_type = peer_iface->m_p_iface->tx_prop->tx[0].hdr_l2_type; + increment_ref_cnt_peer_l2_hdr_type(peer_l2_hdr_type); + add_hdr_proc_ctx(peer_l2_hdr_type); + + /* push the new peer_iface_info into the list */ + m_peer_iface_info.push_front(new_peer); + + return; +} + +void IPACM_LanToLan_Iface::handle_client_add(uint8_t *mac, bool is_l2tp_client, l2tp_vlan_mapping_info *mapping_info) +{ + list::iterator it_client; + list::iterator it_peer_info; + client_info new_client; + bool flag[IPA_HDR_L2_MAX]; - for(it = src_client->link.begin(); it != src_client->link.end(); it++) + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) { - if(it->peer_pointer == dst_client) + if(memcmp(it_client->mac_addr, mac, sizeof(it_client->mac_addr)) == 0) { - res_src = IPACM_SUCCESS; - IPACMDBG_H("Find dst client entry in src link list\n"); - res_src = del_offload_link(iptype, src_client->p_iface, dst_client->p_iface, &(*it)); - src_client->link.erase(it); - break; + IPACMDBG_H("This client has been added before.\n"); + return; } } - for(it = dst_client->link.begin(); it != dst_client->link.end(); it++) + if(m_client_info.size() == MAX_NUM_CLIENT) + { + IPACMDBG_H("The number of clients has reached maximum %d.\n", MAX_NUM_CLIENT); + return; + } + + IPACMDBG_H("is_l2tp_client: %d, mapping_info: %p\n", is_l2tp_client, mapping_info); + memset(&new_client, 0, sizeof(new_client)); + memcpy(new_client.mac_addr, mac, sizeof(new_client.mac_addr)); + new_client.is_l2tp_client = is_l2tp_client; + new_client.mapping_info = mapping_info; + m_client_info.push_front(new_client); + + client_info &front_client = m_client_info.front(); + + /* install inter-interface rules */ + if(m_support_inter_iface_offload) { - if(it->peer_pointer == src_client) + memset(flag, 0, sizeof(flag)); + for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end(); it_peer_info++) { - res_dst = IPACM_SUCCESS; - IPACMDBG_H("Find src client entry in dst link list\n"); - res_dst = del_offload_link(iptype, dst_client->p_iface, src_client->p_iface, &(*it)); - dst_client->link.erase(it); - break; + /* make sure add routing rule only once for each peer l2 header type */ + if(flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] == false) + { + /* add client routing rule for each peer interface */ + if(front_client.is_l2tp_client == false) + { + add_client_rt_rule(&(*it_peer_info), &front_client); + } +#ifdef FEATURE_L2TP + /* add l2tp rt rules */ + add_l2tp_client_rt_rule(&(*it_peer_info), &front_client); +#endif + flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] = true; + } + + /* add client filtering rule on peer interfaces */ + it_peer_info->peer->add_one_client_flt_rule(this, &front_client); } } - if(res_src == IPACM_SUCCESS && res_dst == IPACM_SUCCESS) + /* install intra-interface rules */ + if(m_support_intra_iface_offload) { - if(iptype == IPA_IP_v4) + /* add routing rule first */ + add_client_rt_rule(&m_intra_interface_info, &front_client); + + /* add filtering rule */ + if(m_is_ip_addr_assigned[IPA_IP_v4]) { - num_offload_pair_v4_ --; - IPACMDBG_H("Decrease num of v4 offload pairs to %d\n", num_offload_pair_v4_); + add_client_flt_rule(&m_intra_interface_info, &front_client, IPA_IP_v4); } - else + if(m_is_ip_addr_assigned[IPA_IP_v6]) { - num_offload_pair_v6_ --; - IPACMDBG_H("Decrease num of v6 offload pairs to %d\n", num_offload_pair_v6_); + add_client_flt_rule(&m_intra_interface_info, &front_client, IPA_IP_v6); } } + return; } -void IPACM_LanToLan::generate_new_connection(ipa_ip_type iptype, client_info* client) +void IPACM_LanToLan_Iface::handle_client_del(uint8_t *mac) { -#ifndef CT_OPT - if(client == NULL) - { - IPACMERR("Client is NULL.\n"); - return; - } - - IPACMDBG_H("Generate new connection events for IP type %d\n", iptype); - - int num = 0; - ipacm_cmd_q_data evt; - ipacm_event_connection* new_conn; - ipacm_iface_type client_type, peer_type; - client_type = IPACM_Iface::ipacmcfg->iface_table[client->p_iface->ipa_if_num].if_cat; + list::iterator it_client; + list::iterator it_peer_info; + bool flag[IPA_HDR_L2_MAX]; - IPACMDBG_H("Client's iface type is %d.\n", client_type); - - if(iptype == IPA_IP_v4) + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) { - client_table_v4::iterator it; - for(it = client_info_v4_.begin(); it != client_info_v4_.end(); it++) + if(memcmp(it_client->mac_addr, mac, sizeof(it_client->mac_addr)) == 0) //found the client { - peer_type = IPACM_Iface::ipacmcfg->iface_table[it->second.p_iface->ipa_if_num].if_cat; - if(peer_type != client_type && it->second.is_active == true) - { - IPACMDBG_H("Find a qualified peer to generate new_conn event.\n"); - IPACMDBG_H("Peer's iface type is %d.\n", peer_type); - new_conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); - if(new_conn == NULL) - { - IPACMERR("Failed to allocate memory for new_connection event.\n"); - return; - } - memset(new_conn, 0, sizeof(ipacm_event_connection)); - new_conn->iptype = IPA_IP_v4; - new_conn->src_ipv4_addr = client->ip.ipv4_addr; - new_conn->dst_ipv4_addr = it->second.ip.ipv4_addr; - - memset(&evt, 0, sizeof(evt)); - evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; - evt.evt_data = (void*)new_conn; - IPACM_EvtDispatcher::PostEvt(&evt); - num++; - } + IPACMDBG_H("Found the client.\n"); + break; } } - else if(iptype == IPA_IP_v6) + + if(it_client != m_client_info.end()) //if we found the client { - client_table_v6::iterator it; - for(it = client_info_v6_.begin(); it != client_info_v6_.end(); it++) + /* uninstall inter-interface rules */ + if(m_support_inter_iface_offload) { - peer_type = IPACM_Iface::ipacmcfg->iface_table[it->second.p_iface->ipa_if_num].if_cat; - if(peer_type != client_type && it->second.is_active == true) + memset(flag, 0, sizeof(flag)); + for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end(); + it_peer_info++) { - IPACMDBG_H("Find a qualified peer to generate new_conn event.\n"); - IPACMDBG_H("Peer's iface type is %d.\n", peer_type); - new_conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); - if(new_conn == NULL) + IPACMDBG_H("Delete client filtering rule on peer interface.\n"); + it_peer_info->peer->del_one_client_flt_rule(this, &(*it_client)); + + /* make sure to delete routing rule only once for each peer l2 header type */ + if(flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] == false) { - IPACMERR("Failed to allocate memory for new_connection event.\n"); - return; + IPACMDBG_H("Delete client routing rule for peer interface.\n"); + del_client_rt_rule(&(*it_peer_info), &(*it_client)); + if(it_client->is_l2tp_client == false && IPACM_LanToLan::get_instance()->has_l2tp_iface() == true + && m_client_info.size() == 1) + { + m_p_iface->eth_bridge_del_hdr_proc_ctx(hdr_proc_ctx_for_l2tp); + hdr_proc_ctx_for_l2tp = 0; + } + flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] = true; } - memset(new_conn, 0, sizeof(ipacm_event_connection)); - new_conn->iptype = IPA_IP_v6; - memcpy(new_conn->src_ipv6_addr, client->ip.ipv6_addr, sizeof(new_conn->src_ipv6_addr)); - memcpy(new_conn->dst_ipv6_addr, it->second.ip.ipv6_addr, sizeof(new_conn->dst_ipv6_addr)); - - memset(&evt, 0, sizeof(evt)); - evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; - evt.evt_data = (void*)new_conn; - IPACM_EvtDispatcher::PostEvt(&evt); - num++; } } + + /* uninstall intra-interface rules */ + if(m_support_intra_iface_offload) + { + /* delete filtering rule first */ + IPACMDBG_H("Delete client filtering rule for intra-interface communication.\n"); + del_client_flt_rule(&m_intra_interface_info, &(*it_client)); + + /* delete routing rule */ + IPACMDBG_H("Delete client routing rule for intra-interface communication.\n"); + del_client_rt_rule(&m_intra_interface_info, &(*it_client)); + } + + /* erase the client from client info list */ + m_client_info.erase(it_client); } else { - IPACMERR("IP type is not expected.\n"); + IPACMDBG_H("The client is not found.\n"); } - IPACMDBG_H("Generate %d new connection events in total.\n", num); -#endif + return; } -void IPACM_LanToLan::handle_client_power_recover(ipacm_event_lan_client* data) +void IPACM_LanToLan_Iface::add_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_type) { - if(data == NULL) - { - IPACMERR("No client info is found.\n"); - return; - } - if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) - { - IPACMERR("Event data is not populated properly.\n"); - return; - } - if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) - { - IPACMERR("IP type is not expected: %d\n", data->iptype); - return; - } + uint32_t hdr_proc_ctx_hdl; - IPACMDBG_H("New client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", - data->p_iface->dev_name, data->iptype, - data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], - data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); - - client_info* client_ptr; - if(data->iptype == IPA_IP_v4) - { - if(client_info_v4_.count(data->ipv4_addr) == 0) - { - IPACMERR("Client is not found.\n"); - return; - } - client_info& client = client_info_v4_[data->ipv4_addr]; - client_ptr = &client; - } - else + if(ref_cnt_peer_l2_hdr_type[peer_l2_type] == 1) { - uint64_t v6_addr; - memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); - if(client_info_v6_.count(v6_addr) == 0) - { - IPACMERR("Client is not found.\n"); - return; - } - client_info& client = client_info_v6_[v6_addr]; - client_ptr = &client; + m_p_iface->eth_bridge_add_hdr_proc_ctx(peer_l2_type, &hdr_proc_ctx_hdl); + hdr_proc_ctx_for_inter_interface[peer_l2_type] = hdr_proc_ctx_hdl; + IPACMDBG_H("Installed inter-interface hdr proc ctx on iface %s: handle %d\n", m_p_iface->dev_name, hdr_proc_ctx_hdl); } + return; +} - if(client_ptr->is_active == true || client_ptr->is_powersave != true) //the client is in wrong state - { - IPACMERR("The client is in wrong state: active %d, powersave %d.\n", client_ptr->is_active, client_ptr->is_powersave); - return; - } - else +void IPACM_LanToLan_Iface::del_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_type) +{ + if(ref_cnt_peer_l2_hdr_type[peer_l2_type] == 0) { - if(add_flt_rules(data->iptype, client_ptr) == IPACM_FAILURE) - { - IPACMERR("Failed to add back flt rules when power recovery.\n"); - return; - } - client_ptr->is_active = true; - client_ptr->is_powersave = false; - - check_potential_link(data->iptype, client_ptr); - generate_new_connection(data->iptype, client_ptr); + m_p_iface->eth_bridge_del_hdr_proc_ctx(hdr_proc_ctx_for_inter_interface[peer_l2_type]); + IPACMDBG_H("Hdr proc ctx with hdl %d is deleted.\n", hdr_proc_ctx_for_inter_interface[peer_l2_type]); } - IPACMDBG_H("There are %d clients in v4 table and %d clients in v6 table.\n", client_info_v4_.size(), client_info_v6_.size()); return; } -//This function is called when power save: remove filtering rules only -int IPACM_LanToLan::remove_flt_rules(ipa_ip_type iptype, client_info* client) +void IPACM_LanToLan_Iface::print_data_structure_info() { - if(client == NULL) - { - IPACMERR("No client info is found.\n"); - return IPACM_FAILURE; - } + list::iterator it_peer; + list::iterator it_client; + int i, j, k; - bool err_flag; - offload_link_info_list::iterator client_it; - offload_link_info_list::iterator peer_it; - client_info* peer; + IPACMDBG_H("\n"); + IPACMDBG_H("Interface %s:\n", m_p_iface->dev_name); + IPACMDBG_H("Is IPv4 addr assigned? %d\n", m_is_ip_addr_assigned[IPA_IP_v4]); + IPACMDBG_H("Is IPv6 addr assigned? %d\n", m_is_ip_addr_assigned[IPA_IP_v6]); + IPACMDBG_H("Support inter interface offload? %d\n", m_support_inter_iface_offload); + IPACMDBG_H("Support intra interface offload? %d\n", m_support_intra_iface_offload); + IPACMDBG_H("Is l2tp interface? %d\n", m_is_l2tp_iface); - for(client_it = client->link.begin(); client_it != client->link.end(); client_it++) + if(m_support_inter_iface_offload) { - if(client->p_iface->del_lan2lan_flt_rule(iptype, client_it->flt_rule_hdl) == IPACM_FAILURE) - { - IPACMERR("Failed to delete client's filtering rule.\n"); - } - - err_flag = true; - peer = client_it->peer_pointer; - for(peer_it = peer->link.begin(); peer_it != peer->link.end(); peer_it++) + for(i = 0; i < IPA_HDR_L2_MAX; i++) { - if(peer_it->peer_pointer == client) + IPACMDBG_H("Ref_cnt of peer l2 type %s is %d.\n", ipa_l2_hdr_type[i], ref_cnt_peer_l2_hdr_type[i]); + if(ref_cnt_peer_l2_hdr_type[i] > 0) { - if(peer->p_iface->del_lan2lan_flt_rule(iptype, peer_it->flt_rule_hdl) == IPACM_FAILURE) - { - IPACMERR("Failed to delete peer's offload link.\n"); - } - err_flag = false; - break; + IPACMDBG_H("Hdr proc ctx for peer l2 type %s: %d\n", ipa_l2_hdr_type[i], hdr_proc_ctx_for_inter_interface[i]); } } - if(err_flag) - { - IPACMERR("Unable to find corresponding offload link in peer's entry.\n"); - return IPACM_FAILURE; - } } - return IPACM_SUCCESS; -} -int IPACM_LanToLan::add_flt_rules(ipa_ip_type iptype, client_info* client) -{ - if(client == NULL) + if(m_support_intra_iface_offload) { - IPACMERR("No client info is found.\n"); - return IPACM_FAILURE; + IPACMDBG_H("Hdr proc ctx for intra-interface: %d\n", hdr_proc_ctx_for_intra_interface); } - bool err_flag; - offload_link_info_list::iterator client_it; - offload_link_info_list::iterator peer_it; - client_info* peer; + IPACMDBG_H("Hdr proc ctx for l2tp: %d\n", hdr_proc_ctx_for_l2tp); - for(client_it = client->link.begin(); client_it != client->link.end(); client_it++) + i = 1; + IPACMDBG_H("There are %d clients in total.\n", m_client_info.size()); + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) { - peer = client_it->peer_pointer; - if(client->p_iface->add_lan2lan_flt_rule(iptype, client->ip.ipv4_addr, peer->ip.ipv4_addr, - client->ip.ipv6_addr, peer->ip.ipv6_addr, &(client_it->flt_rule_hdl)) == IPACM_FAILURE) + IPACMDBG_H("Client %d MAC: 0x%02x%02x%02x%02x%02x%02x Pointer: 0x%08x\n", i, it_client->mac_addr[0], it_client->mac_addr[1], + it_client->mac_addr[2], it_client->mac_addr[3], it_client->mac_addr[4], it_client->mac_addr[5], &(*it_client)); + IPACMDBG_H("Is l2tp client? %d\n", it_client->is_l2tp_client); + if(it_client->is_l2tp_client && it_client->mapping_info) { - IPACMERR("Failed to add client's filtering rule.\n"); - return IPACM_FAILURE; + IPACMDBG_H("Vlan iface associated with this client: %s\n", it_client->mapping_info->vlan_iface_name); } - err_flag = true; - for(peer_it = peer->link.begin(); peer_it != peer->link.end(); peer_it++) + if(m_support_inter_iface_offload) { - if(peer_it->peer_pointer == client) + for(j = 0; j < IPA_HDR_L2_MAX; j++) { - if(peer->p_iface->add_lan2lan_flt_rule(iptype, peer->ip.ipv4_addr, client->ip.ipv4_addr, - peer->ip.ipv6_addr, client->ip.ipv6_addr, &(peer_it->flt_rule_hdl)) == IPACM_FAILURE) + if(ref_cnt_peer_l2_hdr_type[j] > 0) { - IPACMERR("Failed to delete peer's offload link.\n"); - return IPACM_FAILURE; + IPACMDBG_H("Printing routing rule info for inter-interface communication for peer l2 type %s.\n", + ipa_l2_hdr_type[j]); + IPACMDBG_H("Number of IPv4 routing rules is %d, handles:\n", it_client->inter_iface_rt_rule_hdl[j].num_hdl[IPA_IP_v4]); + for(k = 0; k < it_client->inter_iface_rt_rule_hdl[j].num_hdl[IPA_IP_v4]; k++) + { + IPACMDBG_H("%d\n", it_client->inter_iface_rt_rule_hdl[j].rule_hdl[IPA_IP_v4][k]); + } + + IPACMDBG_H("Number of IPv6 routing rules is %d, handles:\n", it_client->inter_iface_rt_rule_hdl[j].num_hdl[IPA_IP_v6]); + for(k = 0; k < it_client->inter_iface_rt_rule_hdl[j].num_hdl[IPA_IP_v6]; k++) + { + IPACMDBG_H("%d\n", it_client->inter_iface_rt_rule_hdl[j].rule_hdl[IPA_IP_v6][k]); + } + + if(it_client->is_l2tp_client) + { + IPACMDBG_H("Printing l2tp hdr info for l2tp client.\n"); + IPACMDBG_H("First pass hdr hdl: %d, IPv4 hdr proc ctx hdl: IPv6 hdr proc ctx hdl: %d\n", + it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_hdl, it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_proc_ctx_hdl[IPA_IP_v4], + it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_proc_ctx_hdl[IPA_IP_v6]); + IPACMDBG_H("Second pass hdr hdl: %d\n", it_client->l2tp_rt_rule_hdl[j].second_pass_hdr_hdl); + + IPACMDBG_H("Printing l2tp routing rule info for l2tp client.\n"); + IPACMDBG_H("Number of IPv4 routing rules is %d, first pass handles:\n", it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v4]); + for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v4]; k++) + { + IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].first_pass_rt_rule_hdl[IPA_IP_v4][k]); + } + IPACMDBG_H("Number of IPv6 routing rules is %d, first pass handles:\n", it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]); + for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]; k++) + { + IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].first_pass_rt_rule_hdl[IPA_IP_v6][k]); + } + IPACMDBG_H("Second pass handles:\n"); + for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]; k++) + { + IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].second_pass_rt_rule_hdl[k]); + } + } + else + { + if(IPACM_LanToLan::get_instance()->has_l2tp_iface()) + { + IPACMDBG_H("Printing l2tp hdr info for non l2tp client.\n"); + IPACMDBG_H("Hdr hdl: %d, IPv4 hdr proc ctx hdl: IPv6 hdr proc ctx hdl: %d\n", + it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_hdl, it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_proc_ctx_hdl[IPA_IP_v4], + it_client->l2tp_rt_rule_hdl[j].first_pass_hdr_proc_ctx_hdl[IPA_IP_v6]); + + IPACMDBG_H("Printing l2tp routing rule info for non l2tp client.\n"); + IPACMDBG_H("Number of IPv4 routing rules is %d, handles:\n", it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v4]); + for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v4]; k++) + { + IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].first_pass_rt_rule_hdl[IPA_IP_v4][k]); + } + IPACMDBG_H("Number of IPv6 routing rules is %d, handles:\n", it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]); + for(k = 0; k < it_client->l2tp_rt_rule_hdl[j].num_rt_hdl[IPA_IP_v6]; k++) + { + IPACMDBG_H("%d\n", it_client->l2tp_rt_rule_hdl[j].first_pass_rt_rule_hdl[IPA_IP_v6][k]); + } + } + } } - err_flag = false; - break; } } - if(err_flag) + + if(m_support_intra_iface_offload) { - IPACMERR("Unable to find corresponding offload link in peer's entry.\n"); - return IPACM_FAILURE; - } - } - return IPACM_SUCCESS; -} + IPACMDBG_H("Printing routing rule info for intra-interface communication.\n"); + IPACMDBG_H("Number of IPv4 routing rules is %d, handles:\n", it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4]); + for(j = 0; j < it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4]; j++) + { + IPACMDBG_H("%d\n", it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][j]); + } -void IPACM_LanToLan::handle_new_connection(ipacm_event_connection* new_conn) -{ -#ifdef CT_OPT - if(new_conn == NULL) - { - IPACMERR("No connection info is found.\n"); - return; - } - if(new_conn->iptype != IPA_IP_v4 && new_conn->iptype != IPA_IP_v6) - { - IPACMERR("IP type is not expected: %d.\n", new_conn->iptype); - return; + IPACMDBG_H("Number of IPv6 routing rules is %d, handles:\n", it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6]); + for(j = 0; j < it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6]; j++) + { + IPACMDBG_H("%d\n", it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][j]); + } + } + i++; } - IPACMDBG_H("New connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", new_conn->iptype, new_conn->src_ipv4_addr, new_conn->dst_ipv4_addr); - IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", new_conn->src_ipv6_addr[0], new_conn->src_ipv6_addr[1], new_conn->src_ipv6_addr[2], - new_conn->src_ipv6_addr[3], new_conn->dst_ipv6_addr[0], new_conn->dst_ipv6_addr[1], new_conn->dst_ipv6_addr[2], new_conn->dst_ipv6_addr[3]); - - if(is_lan2lan_connection(new_conn) == false) + IPACMDBG_H("There are %d peer interfaces in total.\n", m_peer_iface_info.size()); + for(it_peer = m_peer_iface_info.begin(); it_peer != m_peer_iface_info.end(); it_peer++) { - IPACMDBG_H("The connection is not lan2lan connection.\n"); - cache_new_connection(new_conn); - return; + print_peer_info(&(*it_peer)); } - ipacm_cmd_q_data evt; - ipacm_event_connection* conn; - - conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); - if(conn == NULL) + if(m_support_intra_iface_offload) { - IPACMERR("Failed to allocate memory for new_connection event.\n"); - return; + IPACMDBG_H("This interface supports intra-interface communication, printing info:\n"); + print_peer_info(&m_intra_interface_info); } - memcpy(conn, new_conn, sizeof(ipacm_event_connection)); - memset(&evt, 0, sizeof(evt)); - evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; - evt.evt_data = (void*)conn; - IPACM_EvtDispatcher::PostEvt(&evt); -#endif return; } -void IPACM_LanToLan::handle_del_connection(ipacm_event_connection* new_conn) +void IPACM_LanToLan_Iface::print_peer_info(peer_iface_info *peer_info) { -#ifdef CT_OPT - if(new_conn == NULL) - { - IPACMERR("No connection info is found.\n"); - return; - } - if(new_conn->iptype != IPA_IP_v4 && new_conn->iptype != IPA_IP_v6) - { - IPACMERR("IP type is not expected: %d.\n", new_conn->iptype); - return; - } - - IPACMDBG_H("Del connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", new_conn->iptype, new_conn->src_ipv4_addr, new_conn->dst_ipv4_addr); - IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", new_conn->src_ipv6_addr[0], new_conn->src_ipv6_addr[1], new_conn->src_ipv6_addr[2], - new_conn->src_ipv6_addr[3], new_conn->dst_ipv6_addr[0], new_conn->dst_ipv6_addr[1], new_conn->dst_ipv6_addr[2], new_conn->dst_ipv6_addr[3]); - - if(is_lan2lan_connection(new_conn) == false) - { - IPACMDBG_H("The connection is not lan2lan connection.\n"); - remove_cache_connection(new_conn); - return; - } + list::iterator it_flt; + list::iterator it_rt; - ipacm_cmd_q_data evt; - ipacm_event_connection* conn; + IPACMDBG_H("Printing peer info for iface %s:\n", peer_info->peer->m_p_iface->dev_name); - conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); - if(conn == NULL) + IPACMDBG_H("There are %d flt info in total.\n", peer_info->flt_rule.size()); + for(it_flt = peer_info->flt_rule.begin(); it_flt != peer_info->flt_rule.end(); it_flt++) { - IPACMERR("Failed to allocate memory for del_connection event.\n"); - return; + IPACMDBG_H("Flt rule handle for client 0x%08x:\n", it_flt->p_client); + if(m_is_ip_addr_assigned[IPA_IP_v4]) + { + IPACMDBG_H("IPv4 %d\n", it_flt->flt_rule_hdl[IPA_IP_v4]); + IPACMDBG_H("IPv4 l2tp first pass flt rule: %d\n", it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v4]); + } + if(m_is_ip_addr_assigned[IPA_IP_v6]) + { + IPACMDBG_H("IPv6 %d\n", it_flt->flt_rule_hdl[IPA_IP_v6]); + IPACMDBG_H("IPv6 l2tp first pass flt rule: %d\n", it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]); + } + IPACMDBG_H("L2tp second pass flt rule: %d\n", it_flt->l2tp_second_pass_flt_rule_hdl); } - memcpy(conn, new_conn, sizeof(ipacm_event_connection)); - memset(&evt, 0, sizeof(evt)); - evt.event = IPA_LAN_TO_LAN_DEL_CONNECTION; - evt.evt_data = (void*)conn; - IPACM_EvtDispatcher::PostEvt(&evt); -#endif return; } -bool IPACM_LanToLan::is_lan2lan_connection(ipacm_event_connection* data) +IPACM_Lan* IPACM_LanToLan_Iface::get_iface_pointer() { - if(data->iptype == IPA_IP_v4) - { - if(client_info_v4_.count(data->src_ipv4_addr) == 0 || client_info_v4_.count(data->dst_ipv4_addr) == 0) - { - IPACMDBG("Either source or destination is not in client table\n"); - return false; - } - - ipacm_iface_type src_type, dst_type; - src_type = IPACM_Iface::ipacmcfg->iface_table[client_info_v4_[data->src_ipv4_addr].p_iface->ipa_if_num].if_cat; - dst_type = IPACM_Iface::ipacmcfg->iface_table[client_info_v4_[data->dst_ipv4_addr].p_iface->ipa_if_num].if_cat; + return m_p_iface; +} - return (src_type != dst_type); - } - else - { - uint64_t src_v6_addr, dst_v6_addr; - memcpy(&src_v6_addr, &(data->src_ipv6_addr[2]), sizeof(uint64_t)); - memcpy(&dst_v6_addr, &(data->dst_ipv6_addr[2]), sizeof(uint64_t)); +bool IPACM_LanToLan_Iface::get_m_is_ip_addr_assigned(ipa_ip_type iptype) +{ + IPACMDBG_H("Has IP address been assigned to interface %s for IP type %d? %d\n", + m_p_iface->dev_name, iptype, m_is_ip_addr_assigned[iptype]); + return m_is_ip_addr_assigned[iptype]; +} - if(client_info_v6_.count(src_v6_addr) == 0 || client_info_v6_.count(dst_v6_addr) == 0) - { - IPACMDBG("Either source or destination is not in client table\n"); - return false; - } +void IPACM_LanToLan_Iface::set_m_is_ip_addr_assigned(ipa_ip_type iptype, bool value) +{ + IPACMDBG_H("Is IP address of IP type %d assigned to interface %s? %d\n", iptype, + m_p_iface->dev_name, value); + m_is_ip_addr_assigned[iptype] = value; +} - ipacm_iface_type src_type, dst_type; - src_type = IPACM_Iface::ipacmcfg->iface_table[client_info_v6_[src_v6_addr].p_iface->ipa_if_num].if_cat; - dst_type = IPACM_Iface::ipacmcfg->iface_table[client_info_v6_[dst_v6_addr].p_iface->ipa_if_num].if_cat; +bool IPACM_LanToLan_Iface::get_m_support_inter_iface_offload() +{ + IPACMDBG_H("Support inter interface offload on %s? %d\n", m_p_iface->dev_name, + m_support_inter_iface_offload); + return m_support_inter_iface_offload; +} - return (src_type != dst_type); - } +bool IPACM_LanToLan_Iface::get_m_support_intra_iface_offload() +{ + IPACMDBG_H("Support intra interface offload on %s? %d\n", m_p_iface->dev_name, + m_support_intra_iface_offload); + return m_support_intra_iface_offload; } -IPACM_LanToLan* IPACM_LanToLan::getLan2LanInstance() +void IPACM_LanToLan_Iface::increment_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type) { - return p_instance; + ref_cnt_peer_l2_hdr_type[peer_l2_type]++; + IPACMDBG_H("Now the ref_cnt of peer l2 hdr type %s is %d.\n", ipa_l2_hdr_type[peer_l2_type], + ref_cnt_peer_l2_hdr_type[peer_l2_type]); + + return; } -bool IPACM_LanToLan::is_potential_lan2lan_connection(ipacm_event_connection* new_conn) +void IPACM_LanToLan_Iface::decrement_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type) { - int i, num_private_subnet; - bool src_is_valid = false; - bool dst_is_valid = false; + ref_cnt_peer_l2_hdr_type[peer_l2_type]--; + IPACMDBG_H("Now the ref_cnt of peer l2 hdr type %s is %d.\n", ipa_l2_hdr_type[peer_l2_type], + ref_cnt_peer_l2_hdr_type[peer_l2_type]); - if(new_conn->iptype == IPA_IP_v4) - { - num_private_subnet = IPACM_Iface::ipacmcfg->ipa_num_private_subnet; - for(i=0; isrc_ipv4_addr & IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask) - == (IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr & IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask) ) - { - src_is_valid = true; - } - if( (new_conn->dst_ipv4_addr & IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask) - == (IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr & IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask) ) - { - dst_is_valid = true; - } - } + return; +} - if(src_is_valid && dst_is_valid) - { - IPACMDBG("Both src and dst are potentially in subnet.\n"); - return true; - } - } - else - { - if( (new_conn->src_ipv6_addr[0] & ipv6_multicast_mask) != (ipv6_multicast_addr & ipv6_multicast_mask) ) - { - src_is_valid = true; - } - if( (new_conn->dst_ipv6_addr[0] & ipv6_multicast_mask) != (ipv6_multicast_addr & ipv6_multicast_mask) ) - { - dst_is_valid = true; - } +bool IPACM_LanToLan_Iface::set_l2tp_iface(char *vlan_iface_name) +{ + IPACMDBG_H("Self iface %s, vlan iface %s\n", m_p_iface->dev_name, + vlan_iface_name); - if(src_is_valid && dst_is_valid) + if(m_is_l2tp_iface == false) + { + if(strncmp(m_p_iface->dev_name, vlan_iface_name, strlen(m_p_iface->dev_name)) == 0) { - IPACMDBG("Both src and dst are potentially in subnet.\n"); - return true; + IPACMDBG_H("This interface is l2tp interface.\n"); + m_is_l2tp_iface = true; + switch_to_l2tp_iface(); } } + return m_is_l2tp_iface; +} - IPACMDBG("This connection is not a lan2lan connection potentially.\n"); - return false; +bool IPACM_LanToLan_Iface::is_l2tp_iface() +{ + return m_is_l2tp_iface; } -void IPACM_LanToLan::cache_new_connection(ipacm_event_connection* new_conn) +void IPACM_LanToLan_Iface::switch_to_l2tp_iface() { - if(is_potential_lan2lan_connection(new_conn) == true) + list::iterator it_peer; + list::iterator it_flt; + + for(it_peer = m_peer_iface_info.begin(); it_peer != m_peer_iface_info.end(); it_peer++) { - if(new_conn->iptype == IPA_IP_v4) + for(it_flt = it_peer->flt_rule.begin(); it_flt != it_peer->flt_rule.end(); it_flt++) { - if(connection_v4_.size() == max_cache_connection) + if(m_is_ip_addr_assigned[IPA_IP_v4]) { - IPACMDBG_H("Cached ipv4 connections already reach maximum, clear up the list.\n"); - connection_v4_.clear(); + m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4); + IPACMDBG_H("Deleted IPv4 flt rule %d.\n", it_flt->flt_rule_hdl[IPA_IP_v4]); } - - connection_v4_.push_back(*new_conn); - IPACMDBG_H("Cache an ipv4 connection, now the number of ipv4 cache connection is %d.\n", connection_v4_.size()); - } - else - { - if(connection_v6_.size() == max_cache_connection) + if(m_is_ip_addr_assigned[IPA_IP_v6]) { - IPACMDBG_H("Cached ipv6 connections already reach maximum, clear up the list.\n"); - connection_v6_.clear(); + m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6); + m_p_iface->add_l2tp_flt_rule(it_flt->p_client->mac_addr, &it_flt->l2tp_first_pass_flt_rule_hdl[IPA_IP_v6]); + IPACMDBG_H("Deleted IPv6 flt rule %d.\n", it_flt->flt_rule_hdl[IPA_IP_v6]); } - - connection_v6_.push_back(*new_conn); - IPACMDBG_H("Cache an ipv6 connection, now the number of ipv6 cache connection is %d.\n", connection_v6_.size()); } } return; } -void IPACM_LanToLan::remove_cache_connection(ipacm_event_connection* del_conn) +void IPACM_LanToLan_Iface::handle_l2tp_enable() { - connection_list::iterator it; - if(is_potential_lan2lan_connection(del_conn) == true) + int i; + ipa_hdr_l2_type peer_l2_hdr_type; + list::iterator it_peer_info; + list::iterator it_client; + bool flag[IPA_HDR_L2_MAX]; + + if(m_support_inter_iface_offload) { - if(del_conn->iptype == IPA_IP_v4) + memset(flag, 0, sizeof(flag)); + for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end(); it_peer_info++) { - for(it = connection_v4_.begin(); it != connection_v4_.end(); it++) + if(it_peer_info->peer->is_l2tp_iface()) { - if(it->src_ipv4_addr == del_conn->src_ipv4_addr && it->dst_ipv4_addr == del_conn->dst_ipv4_addr) - { - IPACMDBG("Find the cached ipv4 connection, remove it from list.\n"); - connection_v4_.erase(it); - IPACMDBG_H("Now the number of ipv4 cache connection is %d.\n", connection_v4_.size()); - return; - } + peer_l2_hdr_type = it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type; + flag[peer_l2_hdr_type] = true; } - IPACMDBG_H("Do not find the cached ipv4 connection, do nothing.\n"); } - else + + for(i = 0; i < IPA_HDR_L2_MAX; i++) { - for(it = connection_v6_.begin(); it != connection_v6_.end(); it++) + if(flag[i] == true) { - if(memcmp(it->src_ipv6_addr, del_conn->src_ipv6_addr, 4*sizeof(uint32_t)) == 0 - && memcmp(it->dst_ipv6_addr, del_conn->dst_ipv6_addr, 4*sizeof(uint32_t)) == 0 ) + IPACMDBG_H("Add rt rule for peer l2 type %s\n", ipa_l2_hdr_type[i]); + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) { - IPACMDBG("Find the cached ipv6 connection, remove it from list.\n"); - connection_v6_.erase(it); - IPACMDBG_H("Now the number of ipv6 cache connection is %d.\n", connection_v6_.size()); - return; + m_p_iface->add_l2tp_rt_rule(IPA_IP_v6, it_client->mac_addr, &hdr_proc_ctx_for_l2tp, + &it_client->l2tp_rt_rule_hdl[i].num_rt_hdl[IPA_IP_v6], + it_client->l2tp_rt_rule_hdl[i].first_pass_rt_rule_hdl[IPA_IP_v6]); } } - IPACMDBG_H("Do not find the cached ipv6 connection, do nothing.\n"); } } return; } -void IPACM_LanToLan::check_cache_connection(ipa_ip_type iptype, client_info* client) +void IPACM_LanToLan_Iface::handle_l2tp_disable() { -#ifdef CT_OPT - connection_list::iterator it; - if(iptype == IPA_IP_v4) + int i; + ipa_hdr_l2_type peer_l2_hdr_type; + list::iterator it_peer_info; + list::iterator it_client; + bool flag[IPA_HDR_L2_MAX]; + + if(m_support_inter_iface_offload) { - it = connection_v4_.begin(); - while(it != connection_v4_.end()) + memset(flag, 0, sizeof(flag)); + for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end(); it_peer_info++) { - if( (it->src_ipv4_addr == client->ip.ipv4_addr && client_info_v4_.count(it->dst_ipv4_addr) > 0) - || (it->dst_ipv4_addr == client->ip.ipv4_addr && client_info_v4_.count(it->src_ipv4_addr) > 0) ) - { - IPACMDBG("Found a cache connection for src client 0x%08x and dst client 0x%08x.\n", it->src_ipv4_addr, it->dst_ipv4_addr); - ipacm_cmd_q_data evt; - ipacm_event_connection* conn; - - conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); - if(conn == NULL) - { - IPACMERR("Failed to allocate memory for new_connection event.\n"); - return; - } - memcpy(conn, &(*it), sizeof(ipacm_event_connection)); - - memset(&evt, 0, sizeof(evt)); - evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; - evt.evt_data = (void*)conn; - IPACM_EvtDispatcher::PostEvt(&evt); - - it = connection_v4_.erase(it); - IPACMDBG_H("Now the number of cache connections is %d.\n", connection_v4_.size()); - } - else - { - it++; - } + peer_l2_hdr_type = it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type; + flag[peer_l2_hdr_type] = true; } - } - else - { - uint64_t src_v6_addr, dst_v6_addr; - it = connection_v6_.begin(); - while(it != connection_v6_.end()) + + for(i = 0; i < IPA_HDR_L2_MAX; i++) { - memcpy(&src_v6_addr, &(it->src_ipv6_addr[2]), sizeof(uint64_t)); - memcpy(&dst_v6_addr, &(it->dst_ipv6_addr[2]), sizeof(uint64_t)); - if( (memcmp(it->src_ipv6_addr, client->ip.ipv6_addr, 4*sizeof(uint32_t)) == 0 && client_info_v6_.count(dst_v6_addr) > 0) - || (memcmp(it->dst_ipv6_addr, client->ip.ipv6_addr, 4*sizeof(uint32_t)) == 0 && client_info_v6_.count(src_v6_addr) > 0) ) + if(flag[i] == true) { - IPACMDBG("Found a cache connection with src client 0x%08x%08x%08x%08x and dst client 0x%08x%08x%08x%08x.\n", it->src_ipv6_addr[0], - it->src_ipv6_addr[1], it->src_ipv6_addr[2], it->src_ipv6_addr[3], it->dst_ipv6_addr[0], it->dst_ipv6_addr[1], - it->dst_ipv6_addr[2], it->dst_ipv6_addr[3]); - ipacm_cmd_q_data evt; - ipacm_event_connection* conn; - - conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); - if(conn == NULL) + IPACMDBG_H("Delete rt rule for peer l2 type %s\n", ipa_l2_hdr_type[i]); + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) { - IPACMERR("Failed to allocate memory for new_connection event.\n"); - return; + m_p_iface->del_l2tp_rt_rule(IPA_IP_v6, it_client->l2tp_rt_rule_hdl[i].num_rt_hdl[IPA_IP_v6], + it_client->l2tp_rt_rule_hdl[i].first_pass_rt_rule_hdl[IPA_IP_v6]); } - memcpy(conn, &(*it), sizeof(ipacm_event_connection)); - - memset(&evt, 0, sizeof(evt)); - evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; - evt.evt_data = (void*)conn; - IPACM_EvtDispatcher::PostEvt(&evt); - - it = connection_v6_.erase(it); - IPACMDBG_H("Now the number of cache connections is %d.\n", connection_v6_.size()); - } - else - { - it++; } } } -#endif return; } diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp index 213b30c0..6bd0cbdb 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -39,7 +39,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /****************************************************************************** - IP_MAIN.C + IPCM_MAIN.C ******************************************************************************/ @@ -57,9 +57,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "linux/ipa_qmi_service_v01.h" -#define __stringify_1(x...) #x -#define __stringify(x...) __stringify_1(x) - #include "IPACM_CmdQueue.h" #include "IPACM_EvtDispatcher.h" #include "IPACM_Defs.h" @@ -71,63 +68,22 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IPACM_ConntrackClient.h" #include "IPACM_Netlink.h" +#ifdef FEATURE_IPACM_HAL +#include "IPACM_OffloadManager.h" +#include +#endif + /* not defined(FEATURE_IPA_ANDROID)*/ #ifndef FEATURE_IPA_ANDROID #include "IPACM_LanToLan.h" #endif - -const char *ipacm_event_name[] = { - __stringify(IPA_CFG_CHANGE_EVENT), /* 1 NULL */ - __stringify(IPA_LINK_UP_EVENT), /* 2 ipacm_event_data_fid */ - __stringify(IPA_LINK_DOWN_EVENT), /* 3 ipacm_event_data_fid */ - __stringify(IPA_ADDR_ADD_EVENT), /* 4 ipacm_event_data_addr */ - __stringify(IPA_ADDR_DEL_EVENT), /* 5 no use */ - __stringify(IPA_ROUTE_ADD_EVENT), /* 6 ipacm_event_data_addr */ - __stringify(IPA_ROUTE_DEL_EVENT), /* 7 ipacm_event_data_addr */ - __stringify(IPA_FIREWALL_CHANGE_EVENT), /* 8 NULL */ - __stringify(IPA_WLAN_AP_LINK_UP_EVENT), /* 9 ipacm_event_data_mac */ - __stringify(IPA_WLAN_STA_LINK_UP_EVENT), /* 10 ipacm_event_data_mac */ - __stringify(IPA_WLAN_CLIENT_ADD_EVENT), /* 11 ipacm_event_data_mac */ - __stringify(IPA_WLAN_CLIENT_DEL_EVENT), /* 12 ipacm_event_data_mac */ - __stringify(IPA_WLAN_CLIENT_POWER_SAVE_EVENT), /* 13 ipacm_event_data_mac */ - __stringify(IPA_WLAN_CLIENT_RECOVER_EVENT), /* 14 ipacm_event_data_mac */ - __stringify(IPA_NEW_NEIGH_EVENT), /* 15 ipacm_event_data_all */ - __stringify(IPA_DEL_NEIGH_EVENT), /* 16 ipacm_event_data_all */ - __stringify(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT), /* 17 ipacm_event_data_all */ - __stringify(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT), /* 18 ipacm_event_data_all */ - __stringify(IPA_SW_ROUTING_ENABLE), /* 19 NULL */ - __stringify(IPA_SW_ROUTING_DISABLE), /* 20 NULL */ - __stringify(IPA_PROCESS_CT_MESSAGE), /* 21 ipacm_ct_evt_data */ - __stringify(IPA_HANDLE_WAN_UP), /* 22 ipacm_event_iface_up */ - __stringify(IPA_HANDLE_WAN_DOWN), /* 23 ipacm_event_iface_up */ - __stringify(IPA_HANDLE_WLAN_UP), /* 24 ipacm_event_iface_up */ - __stringify(IPA_HANDLE_LAN_UP), /* 25 ipacm_event_iface_up */ - __stringify(IPA_WLAN_CLIENT_ADD_EVENT_EX), /* 26 ipacm_event_data_wlan_ex */ - __stringify(IPA_HANDLE_WAN_UP_V6), /* 27 NULL */ - __stringify(IPA_HANDLE_WAN_DOWN_V6), /* 28 NULL */ - __stringify(IPA_LAN_CLIENT_ACTIVE), /* 29 ipacm_event_lan_client*/ - __stringify(IPA_LAN_CLIENT_INACTIVE), /* 30 ipacm_event_lan_client*/ - __stringify(IPA_LAN_CLIENT_DISCONNECT), /* 31 ipacm_event_lan_client*/ - __stringify(IPA_LAN_CLIENT_POWER_SAVE), /* 32 ipacm_event_lan_client*/ - __stringify(IPA_LAN_CLIENT_POWER_RECOVER), /* 33 ipacm_event_lan_client*/ - __stringify(IPA_LAN_TO_LAN_NEW_CONNECTION), /* 34 ipacm_event_connection */ - __stringify(IPA_LAN_TO_LAN_DEL_CONNECTION), /* 35 ipacm_event_connection */ - __stringify(IPA_LAN_DELETE_SELF), /* 36 ipacm_event_data_fid */ - __stringify(IPA_WLAN_LINK_DOWN_EVENT), /* 37 ipacm_event_data_mac */ - __stringify(IPA_USB_LINK_UP_EVENT), /* 38 ipacm_event_data_fid */ - __stringify(IPA_PROCESS_CT_MESSAGE_V6), /* 39 ipacm_ct_evt_data */ - __stringify(IPA_PRIVATE_SUBNET_CHANGE_EVENT), /* 40 ipacm_event_data_fid */ - __stringify(IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT), /* 41 ipacm_event_data_fid */ - __stringify(IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT), /* 42 ipacm_event_data_fid */ -}; - #define IPA_DRIVER "/dev/ipa" #define IPACM_FIREWALL_FILE_NAME "mobileap_firewall.xml" #define IPACM_CFG_FILE_NAME "IPACM_cfg.xml" #ifdef FEATURE_IPA_ANDROID -#define IPACM_PID_FILE "/data/misc/ipa/ipacm.pid" +#define IPACM_PID_FILE "/data/vendor/ipa/ipacm.pid" #define IPACM_DIR_NAME "/data" #else/* defined(FEATURE_IPA_ANDROID) */ #define IPACM_PID_FILE "/etc/ipacm.pid" @@ -254,8 +210,8 @@ void* firewall_monitor(void *param) } -/* start IPACM WLAN-driver notifier */ -void* ipa_driver_wlan_notifier(void *param) +/* start IPACM wan-driver notifier */ +void* ipa_driver_msg_notifier(void *param) { int length, fd, cnt; char buffer[IPA_DRIVER_WLAN_BUF_LEN]; @@ -267,17 +223,23 @@ void* ipa_driver_wlan_notifier(void *param) struct ipa_wlan_msg_ex *event_ex= NULL; struct ipa_get_data_stats_resp_msg_v01 event_data_stats; struct ipa_get_apn_data_stats_resp_msg_v01 event_network_stats; + IPACM_OffloadManager* OffloadMng; ipacm_cmd_q_data evt_data; ipacm_event_data_mac *data = NULL; - ipacm_event_data_fid *data_fid = NULL; + ipacm_event_data_fid *data_fid = NULL; ipacm_event_data_iptype *data_iptype = NULL; ipacm_event_data_wlan_ex *data_ex; ipa_get_data_stats_resp_msg_v01 *data_tethering_stats = NULL; ipa_get_apn_data_stats_resp_msg_v01 *data_network_stats = NULL; + ipa_ioc_vlan_iface_info *vlan_info = NULL; + ipa_ioc_l2tp_vlan_mapping_info *mapping = NULL; + + ipacm_cmd_q_data new_neigh_evt; + ipacm_event_data_all* new_neigh_data; fd = open(IPA_DRIVER, O_RDWR); - if (fd == 0) + if (fd < 0) { IPACMERR("Failed opening %s.\n", IPA_DRIVER); return NULL; @@ -288,6 +250,8 @@ void* ipa_driver_wlan_notifier(void *param) IPACMDBG_H("Waiting for nofications from IPA driver \n"); memset(buffer, 0, sizeof(buffer)); memset(&evt_data, 0, sizeof(evt_data)); + memset(&new_neigh_evt, 0, sizeof(ipacm_cmd_q_data)); + new_neigh_data = NULL; data = NULL; data_fid = NULL; data_tethering_stats = NULL; @@ -412,6 +376,7 @@ void* ipa_driver_wlan_notifier(void *param) case WLAN_CLIENT_CONNECT_EX: IPACMDBG_H("Received WLAN_CLIENT_CONNECT_EX\n"); + memcpy(&event_ex_o, buffer + sizeof(struct ipa_msg_meta),sizeof(struct ipa_wlan_msg_ex)); if(event_ex_o.num_of_attribs > IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS) { @@ -438,10 +403,25 @@ void* ipa_driver_wlan_notifier(void *param) memcpy(data_ex->attribs, event_ex->attribs, event_ex->num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val)); + + ipa_get_if_index(event_ex->name, &(data_ex->if_index)); + evt_data.event = IPA_WLAN_CLIENT_ADD_EVENT_EX; + evt_data.evt_data = data_ex; + + /* Construct new_neighbor msg with netdev device internally */ + new_neigh_data = (ipacm_event_data_all*)malloc(sizeof(ipacm_event_data_all)); + if(new_neigh_data == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memset(new_neigh_data, 0, sizeof(ipacm_event_data_all)); + new_neigh_data->iptype = IPA_IP_v6; for(cnt = 0; cnt < event_ex->num_of_attribs; cnt++) { if(event_ex->attribs[cnt].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) { + memcpy(new_neigh_data->mac_addr, event_ex->attribs[cnt].u.mac_addr, sizeof(new_neigh_data->mac_addr)); IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", event_ex->attribs[cnt].u.mac_addr[0], event_ex->attribs[cnt].u.mac_addr[1], event_ex->attribs[cnt].u.mac_addr[2], event_ex->attribs[cnt].u.mac_addr[3], event_ex->attribs[cnt].u.mac_addr[4], event_ex->attribs[cnt].u.mac_addr[5]); @@ -455,10 +435,9 @@ void* ipa_driver_wlan_notifier(void *param) IPACMDBG_H("Wlan message has unexpected type!\n"); } } - - ipa_get_if_index(event_ex->name, &(data_ex->if_index)); - evt_data.event = IPA_WLAN_CLIENT_ADD_EVENT_EX; - evt_data.evt_data = data_ex; + new_neigh_data->if_index = data_ex->if_index; + new_neigh_evt.evt_data = (void*)new_neigh_data; + new_neigh_evt.event = IPA_NEW_NEIGH_EVENT; free(event_ex); break; @@ -525,7 +504,7 @@ void* ipa_driver_wlan_notifier(void *param) case ECM_CONNECT: memcpy(&event_ecm, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_ecm_msg)); IPACMDBG_H("Received ECM_CONNECT name: %s\n",event_ecm.name); - data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); if(data_fid == NULL) { IPACMERR("unable to allocate memory for event_ecm data_fid\n"); @@ -553,7 +532,7 @@ void* ipa_driver_wlan_notifier(void *param) case WAN_UPSTREAM_ROUTE_ADD: memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg)); IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_ADD name: %s, tethered name: %s\n", event_wan.upstream_ifname, event_wan.tethered_ifname); - data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype)); + data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype)); if(data_iptype == NULL) { IPACMERR("unable to allocate memory for event_ecm data_iptype\n"); @@ -562,6 +541,16 @@ void* ipa_driver_wlan_notifier(void *param) ipa_get_if_index(event_wan.upstream_ifname, &(data_iptype->if_index)); ipa_get_if_index(event_wan.tethered_ifname, &(data_iptype->if_index_tether)); data_iptype->iptype = event_wan.ip; +#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN + data_iptype->ipv4_addr_gw = event_wan.ipv4_addr_gw; + data_iptype->ipv6_addr_gw[0] = event_wan.ipv6_addr_gw[0]; + data_iptype->ipv6_addr_gw[1] = event_wan.ipv6_addr_gw[1]; + data_iptype->ipv6_addr_gw[2] = event_wan.ipv6_addr_gw[2]; + data_iptype->ipv6_addr_gw[3] = event_wan.ipv6_addr_gw[3]; + IPACMDBG_H("default gw ipv4 (%x)\n", data_iptype->ipv4_addr_gw); + IPACMDBG_H("IPV6 gateway: %08x:%08x:%08x:%08x \n", + data_iptype->ipv6_addr_gw[0], data_iptype->ipv6_addr_gw[1], data_iptype->ipv6_addr_gw[2], data_iptype->ipv6_addr_gw[3]); +#endif IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_ADD: fid(%d) tether_fid(%d) ip-type(%d)\n", data_iptype->if_index, data_iptype->if_index_tether, data_iptype->iptype); evt_data.event = IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT; @@ -570,7 +559,7 @@ void* ipa_driver_wlan_notifier(void *param) case WAN_UPSTREAM_ROUTE_DEL: memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg)); IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_DEL name: %s, tethered name: %s\n", event_wan.upstream_ifname, event_wan.tethered_ifname); - data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype)); + data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype)); if(data_iptype == NULL) { IPACMERR("unable to allocate memory for event_ecm data_iptype\n"); @@ -600,6 +589,64 @@ void* ipa_driver_wlan_notifier(void *param) evt_data.evt_data = data_fid; break; + case WLAN_SWITCH_TO_SCC: + IPACMDBG_H("Received WLAN_SWITCH_TO_SCC\n"); + case WLAN_WDI_ENABLE: + IPACMDBG_H("Received WLAN_WDI_ENABLE\n"); + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACM_Iface::ipacmcfg->isMCC_Mode = false; + evt_data.event = IPA_WLAN_SWITCH_TO_SCC; + break; + } + continue; + case WLAN_SWITCH_TO_MCC: + IPACMDBG_H("Received WLAN_SWITCH_TO_MCC\n"); + case WLAN_WDI_DISABLE: + IPACMDBG_H("Received WLAN_WDI_DISABLE\n"); + if (IPACM_Iface::ipacmcfg->isMCC_Mode == false) + { + IPACM_Iface::ipacmcfg->isMCC_Mode = true; + evt_data.event = IPA_WLAN_SWITCH_TO_MCC; + break; + } + continue; + + case WAN_XLAT_CONNECT: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), + sizeof(struct ipa_wan_msg)); + IPACMDBG_H("Received WAN_XLAT_CONNECT name: %s\n", + event_wan.upstream_ifname); + + /* post IPA_LINK_UP_EVENT event + * may be WAN interface is not up + */ + data_fid = (ipacm_event_data_fid *)calloc(1, sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for xlat event\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_fid->if_index)); + evt_data.event = IPA_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + IPACMDBG_H("Posting IPA_LINK_UP_EVENT event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + + /* post IPA_WAN_XLAT_CONNECT_EVENT event */ + memset(&evt_data, 0, sizeof(evt_data)); + data_fid = (ipacm_event_data_fid *)calloc(1, sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for xlat event\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_fid->if_index)); + evt_data.event = IPA_WAN_XLAT_CONNECT_EVENT; + evt_data.evt_data = data_fid; + IPACMDBG_H("Posting IPA_WAN_XLAT_CONNECT_EVENT event:%d\n", evt_data.event); + break; + case IPA_TETHERING_STATS_UPDATE_STATS: memcpy(&event_data_stats, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_get_data_stats_resp_msg_v01)); data_tethering_stats = (ipa_get_data_stats_resp_msg_v01 *)malloc(sizeof(struct ipa_get_data_stats_resp_msg_v01)); @@ -633,6 +680,84 @@ void* ipa_driver_wlan_notifier(void *param) evt_data.evt_data = data_network_stats; break; +#ifdef FEATURE_IPACM_HAL + case IPA_QUOTA_REACH: + IPACMDBG_H("Received IPA_QUOTA_REACH\n"); + OffloadMng = IPACM_OffloadManager::GetInstance(); + if (OffloadMng->elrInstance == NULL) { + IPACMERR("OffloadMng->elrInstance is NULL, can't forward to framework!\n"); + } else { + OffloadMng->elrInstance->onLimitReached(); + } + break; + case IPA_SSR_BEFORE_SHUTDOWN: + IPACMDBG_H("Received IPA_SSR_BEFORE_SHUTDOWN\n"); + OffloadMng = IPACM_OffloadManager::GetInstance(); + if (OffloadMng->elrInstance == NULL) { + IPACMERR("OffloadMng->elrInstance is NULL, can't forward to framework!\n"); + } else { + OffloadMng->elrInstance->onOffloadStopped(IpaEventRelay::ERROR); + } + break; + case IPA_SSR_AFTER_POWERUP: + IPACMDBG_H("Received IPA_SSR_AFTER_POWERUP\n"); + OffloadMng = IPACM_OffloadManager::GetInstance(); + if (OffloadMng->elrInstance == NULL) { + IPACMERR("OffloadMng->elrInstance is NULL, can't forward to framework!\n"); + } else { + OffloadMng->elrInstance->onOffloadSupportAvailable(); + } + break; +#endif +#ifdef FEATURE_L2TP + case ADD_VLAN_IFACE: + vlan_info = (ipa_ioc_vlan_iface_info *)malloc(sizeof(*vlan_info)); + if(vlan_info == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memcpy(vlan_info, buffer + sizeof(struct ipa_msg_meta), sizeof(*vlan_info)); + evt_data.event = IPA_ADD_VLAN_IFACE; + evt_data.evt_data = vlan_info; + break; + + case DEL_VLAN_IFACE: + vlan_info = (ipa_ioc_vlan_iface_info *)malloc(sizeof(*vlan_info)); + if(vlan_info == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memcpy(vlan_info, buffer + sizeof(struct ipa_msg_meta), sizeof(*vlan_info)); + evt_data.event = IPA_DEL_VLAN_IFACE; + evt_data.evt_data = vlan_info; + break; + + case ADD_L2TP_VLAN_MAPPING: + mapping = (ipa_ioc_l2tp_vlan_mapping_info *)malloc(sizeof(*mapping)); + if(mapping == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memcpy(mapping, buffer + sizeof(struct ipa_msg_meta), sizeof(*mapping)); + evt_data.event = IPA_ADD_L2TP_VLAN_MAPPING; + evt_data.evt_data = mapping; + break; + + case DEL_L2TP_VLAN_MAPPING: + mapping = (ipa_ioc_l2tp_vlan_mapping_info *)malloc(sizeof(*mapping)); + if(mapping == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memcpy(mapping, buffer + sizeof(struct ipa_msg_meta), sizeof(*mapping)); + evt_data.event = IPA_DEL_L2TP_VLAN_MAPPING; + evt_data.evt_data = mapping; + break; +#endif default: IPACMDBG_H("Unhandled message type: %d\n", event_hdr.msg_type); continue; @@ -641,6 +766,12 @@ void* ipa_driver_wlan_notifier(void *param) /* finish command queue */ IPACMDBG_H("Posting event:%d\n", evt_data.event); IPACM_EvtDispatcher::PostEvt(&evt_data); + /* push new_neighbor with netdev device internally */ + if(new_neigh_data != NULL) + { + IPACMDBG_H("Internally post event IPA_NEW_NEIGH_EVENT\n"); + IPACM_EvtDispatcher::PostEvt(&new_neigh_evt); + } } (void)close(fd); @@ -688,6 +819,7 @@ int main(int argc, char **argv) int ret; pthread_t netlink_thread = 0, monitor_thread = 0, ipa_driver_thread = 0; pthread_t cmd_queue_thread = 0; + IPACM_OffloadManager* OffloadMng; /* check if ipacm is already running or not */ ipa_is_ipacm_running(); @@ -695,12 +827,16 @@ int main(int argc, char **argv) IPACMDBG_H("In main()\n"); IPACM_Neighbor *neigh = new IPACM_Neighbor(); IPACM_IfaceManager *ifacemgr = new IPACM_IfaceManager(); -#ifndef FEATURE_ETH_BRIDGE_LE -#ifndef FEATURE_IPA_ANDROID - IPACM_LanToLan* lan2lan = new IPACM_LanToLan(); -#endif /* defined(FEATURE_IPA_ANDROID)*/ +#ifdef FEATURE_IPACM_HAL + OffloadMng = IPACM_OffloadManager::GetInstance(); + HAL *hal = HAL::makeIPAHAL(1, OffloadMng); + IPACMDBG_H(" START IPACM_OffloadManager and link to android framework\n"); +#endif + +#ifdef FEATURE_ETH_BRIDGE_LE + IPACM_LanToLan* lan2lan = IPACM_LanToLan::get_instance(); #endif - IPACM_ConntrackClient *cc = IPACM_ConntrackClient::GetInstance(); + CtList = new IPACM_ConntrackListener(); IPACMDBG_H("Staring IPA main\n"); @@ -718,6 +854,10 @@ int main(int argc, char **argv) return ret; } IPACMDBG_H("created command queue thread\n"); + if(pthread_setname_np(cmd_queue_thread, "cmd queue process") != 0) + { + IPACMERR("unable to set thread name\n"); + } } if (IPACM_SUCCESS == netlink_thread) @@ -729,9 +869,14 @@ int main(int argc, char **argv) return ret; } IPACMDBG_H("created netlink thread\n"); + if(pthread_setname_np(netlink_thread, "netlink socket") != 0) + { + IPACMERR("unable to set thread name\n"); + } } - + /* Enable Firewall support only on MDM targets */ +#ifndef FEATURE_IPA_ANDROID if (IPACM_SUCCESS == monitor_thread) { ret = pthread_create(&monitor_thread, NULL, firewall_monitor, NULL); @@ -741,17 +886,26 @@ int main(int argc, char **argv) return ret; } IPACMDBG_H("created firewall monitor thread\n"); + if(pthread_setname_np(monitor_thread, "firewall cfg process") != 0) + { + IPACMERR("unable to set thread name\n"); + } } +#endif if (IPACM_SUCCESS == ipa_driver_thread) { - ret = pthread_create(&ipa_driver_thread, NULL, ipa_driver_wlan_notifier, NULL); + ret = pthread_create(&ipa_driver_thread, NULL, ipa_driver_msg_notifier, NULL); if (IPACM_SUCCESS != ret) { IPACMERR("unable to create ipa_driver_wlan thread\n"); return ret; } IPACMDBG_H("created ipa_driver_wlan thread\n"); + if(pthread_setname_np(ipa_driver_thread, "ipa driver ntfy") != 0) + { + IPACMERR("unable to set thread name\n"); + } } pthread_join(cmd_queue_thread, NULL); @@ -860,7 +1014,7 @@ int ipa_get_if_index memset(&ifr, 0, sizeof(struct ifreq)); - (void)strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); + (void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp index d122b923..8d5a16ff 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -48,6 +48,8 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IPACM_Neighbor::IPACM_Neighbor() { num_neighbor_client = 0; + circular_index = 0; + memset(neighbor_client, 0, IPA_MAX_NUM_NEIGHBOR_CLIENTS * sizeof(ipa_neighbor_client)); IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_ADD_EVENT_EX, this); IPACM_EvtDispatcher::registr(IPA_NEW_NEIGH_EVENT, this); IPACM_EvtDispatcher::registr(IPA_DEL_NEIGH_EVENT, this); @@ -69,7 +71,12 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) { ipacm_event_data_wlan_ex *data = (ipacm_event_data_wlan_ex *)param; ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index); - uint8_t client_mac_addr[6]; + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("IPA_WLAN_CLIENT_ADD_EVENT_EX: not supported iface id: %d\n", data->if_index); + break; + } + uint8_t client_mac_addr[6] = {0}; IPACMDBG_H("Received IPA_WLAN_CLIENT_ADD_EVENT\n"); for(i = 0; i < data->num_of_attribs; i++) @@ -126,13 +133,22 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) memcpy(data_all->mac_addr, neighbor_client[i].mac_addr, sizeof(data_all->mac_addr)); +#ifdef FEATURE_L2TP + memcpy(data_all->iface_name, neighbor_client[i].iface_name, + sizeof(data_all->iface_name)); +#endif evt_data.evt_data = (void *)data_all; IPACM_EvtDispatcher::PostEvt(&evt_data); /* ask for replaced iface name*/ ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); - IPACMDBG_H("Posted event %d, with %s for ipv4 client re-connect\n", - evt_data.event, - IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("not supported iface id: %d\n", data_all->if_index); + } else { + IPACMDBG_H("Posted event %d, with %s for ipv4 client re-connect\n", + evt_data.event, + data_all->iface_name); + } } } break; @@ -143,16 +159,37 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) default: { + if (event == IPA_NEW_NEIGH_EVENT) + { + IPACMDBG_H("Received IPA_NEW_NEIGH_EVENT\n"); + } + else + { + IPACMDBG_H("Received IPA_DEL_NEIGH_EVENT\n"); + } + ipacm_event_data_all *data = (ipacm_event_data_all *)param; ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index); - +#ifndef FEATURE_L2TP + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("not supported iface id: %d\n", data->if_index); + break; + } +#endif if (data->iptype == IPA_IP_v4) { if (data->ipv4_addr != 0) /* not 0.0.0.0 */ { - IPACMDBG(" Got New_Neighbor event with ipv4 address \n"); + IPACMDBG("Got Neighbor event with ipv4 address: 0x%x \n", data->ipv4_addr); + /* check if ipv4 address is link local(169.254.xxx.xxx) */ + if ((data->ipv4_addr & IPV4_ADDR_LINKLOCAL_MASK) == IPV4_ADDR_LINKLOCAL) + { + IPACMDBG_H("This is link local ipv4 address: 0x%x : ignore this NEIGH_EVENT\n", data->ipv4_addr); + return; + } /* check if iface is bridge interface*/ - if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0) + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) == 0) { /* searh if seen this client or not*/ for (i = 0; i < num_neighbor_client_temp; i++) @@ -160,13 +197,14 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) { data->if_index = neighbor_client[i].iface_index; + strlcpy(data->iface_name, neighbor_client[i].iface_name, sizeof(data->iface_name)); neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address /* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */ if (event == IPA_NEW_NEIGH_EVENT) evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; else + /* not to clean-up the client mac cache on bridge0 delneigh */ evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; - data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); if (data_all == NULL) { @@ -179,64 +217,58 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) /* ask for replaced iface name*/ ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); - IPACMDBG_H("Posted event %d, with %s for ipv4\n", - evt_data.event, - IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("not supported iface id: %d\n", data_all->if_index); + } else { + IPACMDBG_H("Posted event %d,\ + with %s for ipv4\n", + evt_data.event, + data->iface_name); + } break; - }; + } } } else { /* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */ if (event == IPA_NEW_NEIGH_EVENT) - evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; - else - evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; - - data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); - if (data_all == NULL) - { - IPACMERR("Unable to allocate memory\n"); - return; - } - memcpy(data_all, data, sizeof(ipacm_event_data_all)); - evt_data.evt_data = (void *)data_all; - IPACM_EvtDispatcher::PostEvt(&evt_data); - IPACMDBG_H("Posted event %d with %s for ipv4\n", - evt_data.event, - IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); - /* Also save to cache for ipv4 */ - /*searh if seen this client or not*/ - for (i = 0; i < num_neighbor_client_temp; i++) { - /* find the client */ - if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + /* Also save to cache for ipv4 */ + /*searh if seen this client or not*/ + for (i = 0; i < num_neighbor_client_temp; i++) { - /* update the network interface client associated */ - neighbor_client[i].iface_index = data->if_index; - neighbor_client[i].ipa_if_num = ipa_interface_index; - neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address - IPACMDBG_H("update cache %d-entry, with %s iface, ipv4 address: 0x%x\n", - i, - IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, - data->ipv4_addr); - break; + /* find the client */ + if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + { + /* update the network interface client associated */ + neighbor_client[i].iface_index = data->if_index; + neighbor_client[i].ipa_if_num = ipa_interface_index; + neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address + strlcpy(neighbor_client[i].iface_name, data->iface_name, sizeof(neighbor_client[i].iface_name)); + IPACMDBG_H("update cache %d-entry, with %s iface, ipv4 address: 0x%x\n", + i, data->iface_name, data->ipv4_addr); + break; + } } - } - /* not find client */ - if (i == num_neighbor_client_temp) - { - if (num_neighbor_client_temp < IPA_MAX_NUM_NEIGHBOR_CLIENTS) + /* not find client */ + if (i == num_neighbor_client_temp) { - memcpy(neighbor_client[num_neighbor_client_temp].mac_addr, - data->mac_addr, - sizeof(data->mac_addr)); - neighbor_client[num_neighbor_client_temp].iface_index = data->if_index; - /* cache the network interface client associated */ - neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index; - neighbor_client[num_neighbor_client_temp].v4_addr = data->ipv4_addr; - IPACMDBG_H("Cache wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + if (num_neighbor_client_temp < IPA_MAX_NUM_NEIGHBOR_CLIENTS) + { + memcpy(neighbor_client[num_neighbor_client_temp].mac_addr, + data->mac_addr, + sizeof(data->mac_addr)); + neighbor_client[num_neighbor_client_temp].iface_index = data->if_index; + /* cache the network interface client associated */ + neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index; + neighbor_client[num_neighbor_client_temp].v4_addr = data->ipv4_addr; + strlcpy(neighbor_client[num_neighbor_client_temp].iface_name, + data->iface_name, sizeof(neighbor_client[num_neighbor_client_temp].iface_name)); + num_neighbor_client++; + IPACMDBG_H("Cache client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", neighbor_client[num_neighbor_client_temp].mac_addr[0], neighbor_client[num_neighbor_client_temp].mac_addr[1], neighbor_client[num_neighbor_client_temp].mac_addr[2], @@ -244,15 +276,87 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) neighbor_client[num_neighbor_client_temp].mac_addr[4], neighbor_client[num_neighbor_client_temp].mac_addr[5], num_neighbor_client); - num_neighbor_client++; - return; + } + else + { + + IPACMERR("error: neighbor client oversize! recycle %d-st entry ! \n", circular_index); + memcpy(neighbor_client[circular_index].mac_addr, + data->mac_addr, + sizeof(data->mac_addr)); + neighbor_client[circular_index].iface_index = data->if_index; + /* cache the network interface client associated */ + neighbor_client[circular_index].ipa_if_num = ipa_interface_index; + neighbor_client[circular_index].v4_addr = 0; + strlcpy(neighbor_client[circular_index].iface_name, + data->iface_name, sizeof(neighbor_client[circular_index].iface_name)); + IPACMDBG_H("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d, circular %d\n", + neighbor_client[circular_index].mac_addr[0], + neighbor_client[circular_index].mac_addr[1], + neighbor_client[circular_index].mac_addr[2], + neighbor_client[circular_index].mac_addr[3], + neighbor_client[circular_index].mac_addr[4], + neighbor_client[circular_index].mac_addr[5], + num_neighbor_client, + circular_index); + circular_index = (circular_index + 1) % IPA_MAX_NUM_NEIGHBOR_CLIENTS; + } } - else + } + else + { + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; + /*searh if seen this client or not*/ + for (i = 0; i < num_neighbor_client_temp; i++) { - IPACMERR("error: neighbor client oversize!"); - return; + /* find the client */ + if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + { + IPACMDBG_H("Clean %d-st Cached client-MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + i, + neighbor_client[i].mac_addr[0], + neighbor_client[i].mac_addr[1], + neighbor_client[i].mac_addr[2], + neighbor_client[i].mac_addr[3], + neighbor_client[i].mac_addr[4], + neighbor_client[i].mac_addr[5], + num_neighbor_client); + + memset(neighbor_client[i].mac_addr, 0, sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = 0; + neighbor_client[i].v4_addr = 0; + neighbor_client[i].ipa_if_num = 0; + memset(neighbor_client[i].iface_name, 0, sizeof(neighbor_client[i].iface_name)); + for (; i < num_neighbor_client_temp - 1; i++) + { + memcpy(neighbor_client[i].mac_addr, + neighbor_client[i+1].mac_addr, + sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = neighbor_client[i+1].iface_index; + neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr; + neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num; + strlcpy(neighbor_client[i].iface_name, neighbor_client[i+1].iface_name, + sizeof(neighbor_client[i].iface_name)); + } + num_neighbor_client--; + IPACMDBG_H(" total number of left cased clients: %d\n", num_neighbor_client); + break; + } } + /* not find client, no need clean-up */ } + + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if (data_all == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + memcpy(data_all, data, sizeof(ipacm_event_data_all)); + evt_data.evt_data = (void *)data_all; + IPACM_EvtDispatcher::PostEvt(&evt_data); + IPACMDBG_H("Posted event %d with %s for ipv4\n", + evt_data.event, data->iface_name); } } } @@ -261,9 +365,9 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) if ((data->ipv6_addr[0]) || (data->ipv6_addr[1]) || (data->ipv6_addr[2]) || (data->ipv6_addr[3])) { - IPACMDBG(" Got New_Neighbor event with ipv6 address \n"); + IPACMDBG("Got New_Neighbor event with ipv6 address \n"); /* check if iface is bridge interface*/ - if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0) + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) == 0) { /* searh if seen this client or not*/ for (i = 0; i < num_neighbor_client_temp; i++) @@ -271,6 +375,7 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) { data->if_index = neighbor_client[i].iface_index; + strlcpy(data->iface_name, neighbor_client[i].iface_name, sizeof(data->iface_name)); /* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */ if (event == IPA_NEW_NEIGH_EVENT) evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; else evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; @@ -285,9 +390,15 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) IPACM_EvtDispatcher::PostEvt(&evt_data); /* ask for replaced iface name*/ ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); - IPACMDBG_H("Posted event %d, with %s for ipv6\n", - evt_data.event, - IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("not supported iface id: %d\n", data_all->if_index); + } else { + IPACMDBG_H("Posted event %d,\ + with %s for ipv6\n", + evt_data.event, + data->iface_name); + } break; }; } @@ -309,39 +420,51 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) evt_data.evt_data = (void *)data_all; IPACM_EvtDispatcher::PostEvt(&evt_data); IPACMDBG_H("Posted event %d with %s for ipv6\n", - evt_data.event, - IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + evt_data.event, data->iface_name); } } else { - IPACMDBG(" Got New_Neighbor event with no ipv6/ipv4 address \n"); + IPACMDBG(" Got Neighbor event with no ipv6/ipv4 address \n"); /*no ipv6 in data searh if seen this client or not*/ for (i = 0; i < num_neighbor_client_temp; i++) { /* find the client */ if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) { + IPACMDBG_H(" find %d-st client, MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + i, + neighbor_client[i].mac_addr[0], + neighbor_client[i].mac_addr[1], + neighbor_client[i].mac_addr[2], + neighbor_client[i].mac_addr[3], + neighbor_client[i].mac_addr[4], + neighbor_client[i].mac_addr[5], + num_neighbor_client); /* check if iface is not bridge interface*/ - if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0) + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) != 0) { /* use previous ipv4 first */ if(data->if_index != neighbor_client[i].iface_index) { - IPACMERR("update new kernel iface index \n"); + IPACMDBG_H("update new kernel iface index \n"); neighbor_client[i].iface_index = data->if_index; + strlcpy(neighbor_client[i].iface_name, data->iface_name, sizeof(neighbor_client[i].iface_name)); } /* check if client associated with previous network interface */ if(ipa_interface_index != neighbor_client[i].ipa_if_num) { - IPACMERR("client associate to different AP \n"); - return; + IPACMDBG_H("client associate to different AP \n"); } if (neighbor_client[i].v4_addr != 0) /* not 0.0.0.0 */ { - evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + /* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */ + if (event == IPA_NEW_NEIGH_EVENT) + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + else + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); if (data_all == NULL) { @@ -351,26 +474,55 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) data_all->iptype = IPA_IP_v4; data_all->if_index = neighbor_client[i].iface_index; data_all->ipv4_addr = neighbor_client[i].v4_addr; //use previous ipv4 address - memcpy(data_all->mac_addr, - neighbor_client[i].mac_addr, - sizeof(data_all->mac_addr)); + memcpy(data_all->mac_addr, neighbor_client[i].mac_addr, + sizeof(data_all->mac_addr)); + strlcpy(data_all->iface_name, neighbor_client[i].iface_name, sizeof(data_all->iface_name)); evt_data.evt_data = (void *)data_all; IPACM_EvtDispatcher::PostEvt(&evt_data); - /* ask for replaced iface name*/ - ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); - IPACMDBG_H("Posted event %d, with %s for ipv4 client re-connect\n", - evt_data.event, - IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + IPACMDBG_H("Posted event %d with %s for ipv4\n", + evt_data.event, data_all->iface_name); + } + } + /* delete cache neighbor entry */ + if (event == IPA_DEL_NEIGH_EVENT) + { + IPACMDBG_H("Clean %d-st Cached client-MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + i, + neighbor_client[i].mac_addr[0], + neighbor_client[i].mac_addr[1], + neighbor_client[i].mac_addr[2], + neighbor_client[i].mac_addr[3], + neighbor_client[i].mac_addr[4], + neighbor_client[i].mac_addr[5], + num_neighbor_client); + + memset(neighbor_client[i].mac_addr, 0, sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = 0; + neighbor_client[i].v4_addr = 0; + neighbor_client[i].ipa_if_num = 0; + memset(neighbor_client[i].iface_name, 0, sizeof(neighbor_client[i].iface_name)); + for (; i < num_neighbor_client_temp - 1; i++) + { + memcpy(neighbor_client[i].mac_addr, + neighbor_client[i+1].mac_addr, + sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = neighbor_client[i+1].iface_index; + neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr; + neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num; + strlcpy(neighbor_client[i].iface_name, neighbor_client[i+1].iface_name, + sizeof(neighbor_client[i].iface_name)); } + num_neighbor_client--; + IPACMDBG_H(" total number of left cased clients: %d\n", num_neighbor_client); } break; } } /* not find client */ - if (i == num_neighbor_client_temp) + if ((i == num_neighbor_client_temp) && (event == IPA_NEW_NEIGH_EVENT)) { /* check if iface is not bridge interface*/ - if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0) + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) != 0) { if (num_neighbor_client_temp < IPA_MAX_NUM_NEIGHBOR_CLIENTS) { @@ -381,7 +533,10 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) /* cache the network interface client associated */ neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index; neighbor_client[num_neighbor_client_temp].v4_addr = 0; - IPACMDBG_H("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + strlcpy(neighbor_client[num_neighbor_client_temp].iface_name, data->iface_name, + sizeof(neighbor_client[num_neighbor_client_temp].iface_name)); + num_neighbor_client++; + IPACMDBG_H("Copy client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", neighbor_client[num_neighbor_client_temp].mac_addr[0], neighbor_client[num_neighbor_client_temp].mac_addr[1], neighbor_client[num_neighbor_client_temp].mac_addr[2], @@ -389,12 +544,30 @@ void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) neighbor_client[num_neighbor_client_temp].mac_addr[4], neighbor_client[num_neighbor_client_temp].mac_addr[5], num_neighbor_client); - num_neighbor_client++; return; } else { - IPACMERR("error: neighbor client oversize!"); + IPACMERR("error: neighbor client oversize! recycle %d-st entry ! \n", circular_index); + memcpy(neighbor_client[circular_index].mac_addr, + data->mac_addr, + sizeof(data->mac_addr)); + neighbor_client[circular_index].iface_index = data->if_index; + /* cache the network interface client associated */ + neighbor_client[circular_index].ipa_if_num = ipa_interface_index; + neighbor_client[circular_index].v4_addr = 0; + strlcpy(neighbor_client[circular_index].iface_name, data->iface_name, + sizeof(neighbor_client[circular_index].iface_name)); + IPACMDBG_H("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d, circular %d\n", + neighbor_client[circular_index].mac_addr[0], + neighbor_client[circular_index].mac_addr[1], + neighbor_client[circular_index].mac_addr[2], + neighbor_client[circular_index].mac_addr[3], + neighbor_client[circular_index].mac_addr[4], + neighbor_client[circular_index].mac_addr[5], + num_neighbor_client, + circular_index); + circular_index = (circular_index + 1) % IPA_MAX_NUM_NEIGHBOR_CLIENTS; return; } } diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp index 9db578c1..b5fadcb0 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -610,7 +610,7 @@ static int ipa_nl_decode_nlmsg int ret_val, mask_value, mask_index, mask_value_v6; struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; - uint32_t if_ipv4_addr =0, if_ipipv4_addr_mask =0, temp =0; + uint32_t if_ipv4_addr =0, if_ipipv4_addr_mask =0, temp =0, if_ipv4_addr_gw =0; ipacm_cmd_q_data evt_data; ipacm_event_data_all *data_all; @@ -639,13 +639,16 @@ static int ipa_nl_decode_nlmsg IPACMDBG("RTM_NEWLINK, ifi_flags:%d\n", msg_ptr->nl_link_info.metainfo.ifi_flags); IPACMDBG("RTM_NEWLINK, ifi_index:%d\n", msg_ptr->nl_link_info.metainfo.ifi_index); IPACMDBG("RTM_NEWLINK, family:%d\n", msg_ptr->nl_link_info.metainfo.ifi_family); - + /* RTM_NEWLINK event with AF_BRIDGE family should be ignored in Android + but this should be processed in case of MDM for Ehernet interface. + */ +#ifdef FEATURE_IPA_ANDROID if (msg_ptr->nl_link_info.metainfo.ifi_family == AF_BRIDGE) { IPACMERR(" ignore this RTM_NEWLINK msg \n"); return IPACM_SUCCESS; } - +#endif if(IFF_UP & msg_ptr->nl_link_info.metainfo.ifi_change) { IPACMDBG("GOT useful newlink event\n"); @@ -686,12 +689,12 @@ static int ipa_nl_decode_nlmsg /* Add IPACM support for ECM plug-in/plug_out */ /*-------------------------------------------------------------------------- - Check if the interface is running.If its a RTM_NEWLINK and the interface - is running then it means that its a link up event - ---------------------------------------------------------------------------*/ - if((msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_RUNNING) && - (msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP)) - { + Check if the interface is running.If its a RTM_NEWLINK and the interface + is running then it means that its a link up event + ---------------------------------------------------------------------------*/ + if((msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_RUNNING) && + (msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP)) + { data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); if(data_fid == NULL) @@ -707,19 +710,19 @@ static int ipa_nl_decode_nlmsg IPACMERR("Error while getting interface name\n"); return IPACM_FAILURE; } - IPACMDBG("Got a usb link_up event (Interface %s, %d) \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); + IPACMDBG("Got a usb link_up event (Interface %s, %d) \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); - /*-------------------------------------------------------------------------- - Post LAN iface (ECM) link up event - ---------------------------------------------------------------------------*/ - evt_data.event = IPA_USB_LINK_UP_EVENT; + /*-------------------------------------------------------------------------- + Post LAN iface (ECM) link up event + ---------------------------------------------------------------------------*/ + evt_data.event = IPA_USB_LINK_UP_EVENT; evt_data.evt_data = data_fid; - IPACM_EvtDispatcher::PostEvt(&evt_data); - IPACMDBG("Posting usb IPA_LINK_UP_EVENT with if index: %d\n", + IPACMDBG_H("Posting usb IPA_LINK_UP_EVENT with if index: %d\n", data_fid->if_index); - } - else if(!(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP)) - { + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + else if (!(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP)) + { data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); if(data_fid == NULL) { @@ -734,18 +737,17 @@ static int ipa_nl_decode_nlmsg IPACMERR("Error while getting interface name\n"); return IPACM_FAILURE; } - IPACMDBG_H("Got a usb link_down event (Interface %s) \n", dev_name); + IPACMDBG_H("Got a usb link_down event (Interface %s) \n", dev_name); - /*-------------------------------------------------------------------------- - Post LAN iface (ECM) link down event - ---------------------------------------------------------------------------*/ - evt_data.event = IPA_LINK_DOWN_EVENT; + /*-------------------------------------------------------------------------- + Post LAN iface (ECM) link down event + ---------------------------------------------------------------------------*/ + evt_data.event = IPA_LINK_DOWN_EVENT; evt_data.evt_data = data_fid; - IPACM_EvtDispatcher::PostEvt(&evt_data); IPACMDBG_H("Posting usb IPA_LINK_DOWN_EVENT with if index: %d\n", data_fid->if_index); - - } + IPACM_EvtDispatcher::PostEvt(&evt_data); + } } break; @@ -766,13 +768,16 @@ static int ipa_nl_decode_nlmsg IPACMDBG("RTM_DELLINK, ifi_flags:%d\n", msg_ptr->nl_link_info.metainfo.ifi_flags); IPACMDBG("RTM_DELLINK, ifi_index:%d\n", msg_ptr->nl_link_info.metainfo.ifi_index); IPACMDBG("RTM_DELLINK, family:%d\n", msg_ptr->nl_link_info.metainfo.ifi_family); - + /* RTM_NEWLINK event with AF_BRIDGE family should be ignored in Android + but this should be processed in case of MDM for Ehernet interface. + */ +#ifdef FEATURE_IPA_ANDROID if (msg_ptr->nl_link_info.metainfo.ifi_family == AF_BRIDGE) { IPACMERR(" ignore this RTM_DELLINK msg \n"); return IPACM_SUCCESS; } - +#endif ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); if(ret_val != IPACM_SUCCESS) { @@ -844,6 +849,9 @@ static int ipa_nl_decode_nlmsg evt_data.event = IPA_ADDR_ADD_EVENT; data_addr->if_index = msg_ptr->nl_addr_info.metainfo.ifa_index; +#ifdef FEATURE_L2TP + strlcpy(data_addr->iface_name, dev_name, sizeof(data_addr->iface_name)); +#endif if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family) { IPACMDBG("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n", @@ -874,7 +882,6 @@ static int ipa_nl_decode_nlmsg IPACMDBG("In case RTM_NEWROUTE\n"); IPACMDBG("rtm_type: %d\n", msg_ptr->nl_route_info.metainfo.rtm_type); - IPACMDBG("rtm_type: %d\n", msg_ptr->nl_route_info.metainfo.rtm_type); IPACMDBG("protocol: %d\n", msg_ptr->nl_route_info.metainfo.rtm_protocol); IPACMDBG("rtm_scope: %d\n", msg_ptr->nl_route_info.metainfo.rtm_scope); IPACMDBG("rtm_table: %d\n", msg_ptr->nl_route_info.metainfo.rtm_table); @@ -883,7 +890,8 @@ static int ipa_nl_decode_nlmsg /* take care of route add default route & uniroute */ if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && - (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) && + ((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) || + (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) && (msg_ptr->nl_route_info.metainfo.rtm_scope == RT_SCOPE_UNIVERSE) && (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) { @@ -962,13 +970,20 @@ static int ipa_nl_decode_nlmsg data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); - IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr); + data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]); + data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]); + data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]); + data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]); + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr); + evt_data.event = IPA_ROUTE_ADD_EVENT; data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; data_addr->iptype = IPA_IP_v6; @@ -996,17 +1011,20 @@ static int ipa_nl_decode_nlmsg IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); IPACM_EVENT_COPY_ADDR_v4( if_ipipv4_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); + IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr); evt_data.event = IPA_ROUTE_ADD_EVENT; data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; data_addr->iptype = IPA_IP_v4; data_addr->ipv4_addr = ntohl(if_ipv4_addr); + data_addr->ipv4_addr_gw = ntohl(if_ipv4_addr_gw); data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask); - IPACMDBG_H("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv4 addr:0x%x and maxk: 0x%x\n", + IPACMDBG_H("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv4 addr:0x%x, mask: 0x%x and gw: 0x%x\n", data_addr->if_index, data_addr->ipv4_addr, - data_addr->ipv4_addr_mask); + data_addr->ipv4_addr_mask, + data_addr->ipv4_addr_gw); evt_data.evt_data = data_addr; IPACM_EvtDispatcher::PostEvt(&evt_data); /* finish command queue */ @@ -1138,7 +1156,8 @@ static int ipa_nl_decode_nlmsg } /* take care of route delete of default route & uniroute */ if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && - (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) && + ((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) || + (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) && (msg_ptr->nl_route_info.metainfo.rtm_scope == 0) && (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) { @@ -1209,19 +1228,24 @@ static int ipa_nl_decode_nlmsg { IPACMDBG("ip -6 route del default dev %s\n", dev_name); } - IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); - + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); - data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr); + data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]); + data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]); + data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]); + data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]); + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr); data_addr->iptype = IPA_IP_v6; } else @@ -1355,13 +1379,13 @@ static int ipa_nl_decode_nlmsg IPACMDBG("\n GOT RTM_NEWNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); } - /* insert to command queue */ + /* insert to command queue */ data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); if(data_all == NULL) - { + { IPACMERR("unable to allocate memory for event data_all\n"); return IPACM_FAILURE; - } + } memset(data_all, 0, sizeof(ipacm_event_data_all)); if(msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET6) @@ -1369,11 +1393,11 @@ static int ipa_nl_decode_nlmsg IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); IPACM_EVENT_COPY_ADDR_v6( data_all->ipv6_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); - data_all->ipv6_addr[0]=ntohl(data_all->ipv6_addr[0]); - data_all->ipv6_addr[1]=ntohl(data_all->ipv6_addr[1]); - data_all->ipv6_addr[2]=ntohl(data_all->ipv6_addr[2]); - data_all->ipv6_addr[3]=ntohl(data_all->ipv6_addr[3]); - data_all->iptype = IPA_IP_v6; + data_all->ipv6_addr[0]=ntohl(data_all->ipv6_addr[0]); + data_all->ipv6_addr[1]=ntohl(data_all->ipv6_addr[1]); + data_all->ipv6_addr[2]=ntohl(data_all->ipv6_addr[2]); + data_all->ipv6_addr[3]=ntohl(data_all->ipv6_addr[3]); + data_all->iptype = IPA_IP_v6; } else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET) { @@ -1399,13 +1423,29 @@ static int ipa_nl_decode_nlmsg memcpy(data_all->mac_addr, msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data, sizeof(data_all->mac_addr)); - evt_data.event = IPA_NEW_NEIGH_EVENT; - data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex; - - IPACMDBG_H("posting IPA_NEW_NEIGH_EVENT (%s):index:%d ip-family: %d\n", + data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex; +#ifdef FEATURE_L2TP + strlcpy(data_all->iface_name, dev_name, sizeof(data_all->iface_name)); +#endif + /* Add support to replace src-mac as bridge0 mac */ + if((msg_ptr->nl_neigh_info.metainfo.ndm_family == AF_BRIDGE) && + (msg_ptr->nl_neigh_info.metainfo.ndm_state == NUD_PERMANENT)) + { + /* Posting IPA_BRIDGE_LINK_UP_EVENT event */ + evt_data.event = IPA_BRIDGE_LINK_UP_EVENT; + IPACMDBG_H("posting IPA_BRIDGE_LINK_UP_EVENT (%s):index:%d \n", + dev_name, + data_all->if_index); + } + else + { + /* Posting new_neigh events for all LAN/WAN clients */ + evt_data.event = IPA_NEW_NEIGH_EVENT; + IPACMDBG_H("posting IPA_NEW_NEIGH_EVENT (%s):index:%d ip-family: %d\n", dev_name, data_all->if_index, msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); + } evt_data.evt_data = data_all; IPACM_EvtDispatcher::PostEvt(&evt_data); /* finish command queue */ diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_OffloadManager.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_OffloadManager.cpp new file mode 100644 index 00000000..332abd51 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_OffloadManager.cpp @@ -0,0 +1,540 @@ +/* +Copyright (c) 2017, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +* Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.Z +*/ +/*! + @file + IPACM_OffloadManager.cpp + + @brief + This file implements the basis Iface functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include "IPACM_ConntrackClient.h" +#include "IPACM_ConntrackListener.h" +#include "IPACM_Iface.h" +#include "IPACM_Config.h" + +const char *IPACM_OffloadManager::DEVICE_NAME = "/dev/wwan_ioctl"; + +/* NatApp class Implementation */ +IPACM_OffloadManager *IPACM_OffloadManager::pInstance = NULL; + +IPACM_OffloadManager::IPACM_OffloadManager() +{ + default_gw_index = INVALID_IFACE; + upstream_v4_up = false; + upstream_v6_up = false; + return ; +} + +RET IPACM_OffloadManager::registerEventListener(IpaEventListener* eventlistener) +{ + RET result = SUCCESS; + if (elrInstance == NULL) + elrInstance = eventlistener; + else { + IPACMDBG_H("already register EventListener previously \n"); + result = FAIL_INPUT_CHECK; + } + return SUCCESS; +} + +RET IPACM_OffloadManager::unregisterEventListener(IpaEventListener* ) +{ + RET result = SUCCESS; + if (elrInstance) + elrInstance = NULL; + else { + IPACMDBG_H("already unregisterEventListener previously \n"); + result = SUCCESS_DUPLICATE_CONFIG; + } + return SUCCESS; +} + +RET IPACM_OffloadManager::registerCtTimeoutUpdater(ConntrackTimeoutUpdater* timeoutupdater) +{ + RET result = SUCCESS; + if (touInstance == NULL) + touInstance = timeoutupdater; + else { + IPACMDBG_H("already register ConntrackTimeoutUpdater previously \n"); + result = FAIL_INPUT_CHECK; + } + return SUCCESS; +} + +RET IPACM_OffloadManager::unregisterCtTimeoutUpdater(ConntrackTimeoutUpdater* ) +{ + RET result = SUCCESS; + if (touInstance) + touInstance = NULL; + else { + IPACMDBG_H("already unregisterCtTimeoutUpdater previously \n"); + result = SUCCESS_DUPLICATE_CONFIG; + } + return SUCCESS; +} + +RET IPACM_OffloadManager::provideFd(int fd, unsigned int groups) +{ + IPACM_ConntrackClient *cc; + int on = 1, rel; + + cc = IPACM_ConntrackClient::GetInstance(); + + if(!cc) + { + IPACMERR("Init failed: cc %p\n", cc); + return FAIL_HARDWARE; + } + + if (groups == cc->subscrips_tcp) { + cc->fd_tcp = fd; + IPACMDBG_H("Received fd %d with groups %d.\n", fd, groups); + /* set netlink buf */ + rel = setsockopt(cc->fd_tcp, SOL_NETLINK, NETLINK_NO_ENOBUFS, &on, sizeof(int) ); + if (rel == -1) + { + IPACMERR( "setsockopt returned error code %d ( %s )", errno, strerror( errno ) ); + } + } else if (groups == cc->subscrips_udp) { + cc->fd_udp = fd; + IPACMDBG_H("Received fd %d with groups %d.\n", fd, groups); + /* set netlink buf */ + rel = setsockopt(cc->fd_tcp, SOL_NETLINK, NETLINK_NO_ENOBUFS, &on, sizeof(int) ); + if (rel == -1) + { + IPACMERR( "setsockopt returned error code %d ( %s )", errno, strerror( errno ) ); + } + } else { + IPACMERR("Received unexpected fd with groups %d.\n", groups); + } + if(cc->fd_tcp >0 && cc->fd_udp >0) { + IPACMDBG_H(" Got both fds from framework, start conntrack listener thread.\n"); + CtList->CreateConnTrackThreads(); + } + return SUCCESS; +} + +RET IPACM_OffloadManager::clearAllFds() +{ + IPACM_ConntrackClient *cc; + + cc = IPACM_ConntrackClient::GetInstance(); + if(!cc) + { + IPACMERR("Init clear: cc %p \n", cc); + return FAIL_HARDWARE; + } + cc->UNRegisterWithConnTrack(); + + return SUCCESS; +} + +bool IPACM_OffloadManager::isStaApSupported() +{ + return true; +} + + +RET IPACM_OffloadManager::setLocalPrefixes(std::vector &/* prefixes */) +{ + return SUCCESS; +} + +RET IPACM_OffloadManager::addDownstream(const char * downstream_name, const Prefix &prefix) +{ + int index; + ipacm_cmd_q_data evt; + ipacm_event_ipahal_stream *evt_data; + + IPACMDBG_H("addDownstream name(%s), ip-family(%d) \n", downstream_name, prefix.fam); + if (prefix.fam == V4) { + IPACMDBG_H("subnet info v4Addr (%x) v4Mask (%x)\n", prefix.v4Addr, prefix.v4Mask); + } else { + IPACMDBG_H("subnet info v6Addr: %08x:%08x:%08x:%08x \n", + prefix.v6Addr[0], prefix.v6Addr[1], prefix.v6Addr[2], prefix.v6Addr[3]); + IPACMDBG_H("subnet info v6Mask: %08x:%08x:%08x:%08x \n", + prefix.v6Mask[0], prefix.v6Mask[1], prefix.v6Mask[2], prefix.v6Mask[3]); + } + + if(ipa_get_if_index(downstream_name, &index)) + { + IPACMERR("fail to get iface index.\n"); + return FAIL_HARDWARE; + } + + evt_data = (ipacm_event_ipahal_stream*)malloc(sizeof(ipacm_event_ipahal_stream)); + if(evt_data == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return FAIL_HARDWARE; + } + memset(evt_data, 0, sizeof(*evt_data)); + + evt_data->if_index = index; + memcpy(&evt_data->prefix, &prefix, sizeof(evt_data->prefix)); + + memset(&evt, 0, sizeof(ipacm_cmd_q_data)); + evt.evt_data = (void*)evt_data; + evt.event = IPA_DOWNSTREAM_ADD; + + IPACMDBG_H("Posting event IPA_DOWNSTREAM_ADD\n"); + IPACM_EvtDispatcher::PostEvt(&evt); + + return SUCCESS; +} + +RET IPACM_OffloadManager::removeDownstream(const char * downstream_name, const Prefix &prefix) +{ + int index; + ipacm_cmd_q_data evt; + ipacm_event_ipahal_stream *evt_data; + + IPACMDBG_H("removeDownstream name(%s), ip-family(%d) \n", downstream_name, prefix.fam); + if(ipa_get_if_index(downstream_name, &index)) + { + IPACMERR("fail to get iface index.\n"); + return FAIL_HARDWARE; + } + + evt_data = (ipacm_event_ipahal_stream*)malloc(sizeof(ipacm_event_ipahal_stream)); + if(evt_data == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return FAIL_HARDWARE; + } + memset(evt_data, 0, sizeof(*evt_data)); + + evt_data->if_index = index; + memcpy(&evt_data->prefix, &prefix, sizeof(evt_data->prefix)); + + memset(&evt, 0, sizeof(ipacm_cmd_q_data)); + evt.evt_data = (void*)evt_data; + evt.event = IPA_DOWNSTREAM_DEL; + + IPACMDBG_H("Posting event IPA_DOWNSTREAM_DEL\n"); + IPACM_EvtDispatcher::PostEvt(&evt); + + return SUCCESS; +} + +RET IPACM_OffloadManager::setUpstream(const char *upstream_name, const Prefix& gw_addr_v4 , const Prefix& gw_addr_v6) +{ + int index; + ipacm_cmd_q_data evt; + ipacm_event_data_addr *evt_data_addr; + RET result = SUCCESS; + + /* if interface name is NULL, default route is removed */ + IPACMDBG_H("setUpstream upstream_name(%s), ipv4-fam(%d) ipv6-fam(%d)\n", upstream_name, gw_addr_v4.fam, gw_addr_v6.fam); + + if(upstream_name == NULL) + { + if (default_gw_index == INVALID_IFACE) { + IPACMERR("no previous upstream set before\n"); + return FAIL_INPUT_CHECK; + } + + if (gw_addr_v4.fam == V4 && upstream_v4_up == true) { + IPACMDBG_H("clean upstream(%s) for ipv4-fam(%d) upstream_v4_up(%d)\n", upstream_name, gw_addr_v4.fam, upstream_v4_up); + post_route_evt(IPA_IP_v4, default_gw_index, IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, gw_addr_v4); + upstream_v4_up = false; + } + if (gw_addr_v6.fam == V6 && upstream_v6_up == true) { + IPACMDBG_H("clean upstream(%s) for ipv6-fam(%d) upstream_v6_up(%d)\n", upstream_name, gw_addr_v6.fam, upstream_v6_up); + post_route_evt(IPA_IP_v6, default_gw_index, IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, gw_addr_v6); + upstream_v6_up = false; + } + default_gw_index = INVALID_IFACE; + } + else + { + if(ipa_get_if_index(upstream_name, &index)) + { + IPACMERR("fail to get iface index.\n"); + return FAIL_INPUT_CHECK; + } + + /* reset the stats when switch from LTE->STA */ + if (index != default_gw_index) { + IPACMDBG_H(" interface switched to %s\n", upstream_name); + if(memcmp(upstream_name, "wlan0", sizeof("wlan0")) == 0) + { + IPACMDBG_H("switch to STA mode, need reset wlan-fw stats\n"); + resetTetherStats(upstream_name); + } + } + + if (gw_addr_v4.fam == V4 && gw_addr_v6.fam == V6) { + + if (upstream_v4_up == false) { + IPACMDBG_H("IPV4 gateway: 0x%x \n", gw_addr_v4.v4Addr); + /* posting route add event for both IPv4 and IPv6 */ + post_route_evt(IPA_IP_v4, index, IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, gw_addr_v4); + upstream_v4_up = true; + } else { + IPACMDBG_H("already setupstream iface(%s) ipv4 previously\n", upstream_name); + } + + if (upstream_v6_up == false) { + IPACMDBG_H("IPV6 gateway: %08x:%08x:%08x:%08x \n", + gw_addr_v6.v6Addr[0], gw_addr_v6.v6Addr[1], gw_addr_v6.v6Addr[2], gw_addr_v6.v6Addr[3]); + post_route_evt(IPA_IP_v6, index, IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, gw_addr_v6); + upstream_v6_up = true; + } else { + IPACMDBG_H("already setupstream iface(%s) ipv6 previously\n", upstream_name); + } + } else if (gw_addr_v4.fam == V4 ) { + IPACMDBG_H("check upstream_v6_up (%d) v4_up (%d), default gw index (%d)\n", upstream_v6_up, upstream_v4_up, default_gw_index); + if (upstream_v6_up == true && default_gw_index != INVALID_IFACE ) { + /* clean up previous V6 upstream event */ + IPACMDBG_H(" Post clean-up v6 default gw on iface %d\n", default_gw_index); + post_route_evt(IPA_IP_v6, default_gw_index, IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, gw_addr_v6); + upstream_v6_up = false; + } + + if (upstream_v4_up == false) { + IPACMDBG_H("IPV4 gateway: %x \n", gw_addr_v4.v4Addr); + /* posting route add event for both IPv4 and IPv6 */ + post_route_evt(IPA_IP_v4, index, IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, gw_addr_v4); + upstream_v4_up = true; + } else { + IPACMDBG_H("already setupstream iface(%s) ipv4 previously\n", upstream_name); + result = SUCCESS_DUPLICATE_CONFIG; + } + } else if (gw_addr_v6.fam == V6) { + IPACMDBG_H("check upstream_v6_up (%d) v4_up (%d), default gw index (%d)\n", upstream_v6_up, upstream_v4_up, default_gw_index); + if (upstream_v4_up == true && default_gw_index != INVALID_IFACE ) { + /* clean up previous V4 upstream event */ + IPACMDBG_H(" Post clean-up v4 default gw on iface %d\n", default_gw_index); + post_route_evt(IPA_IP_v4, default_gw_index, IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, gw_addr_v4); + upstream_v4_up = false; + } + + if (upstream_v6_up == false) { + IPACMDBG_H("IPV6 gateway: %08x:%08x:%08x:%08x \n", + gw_addr_v6.v6Addr[0], gw_addr_v6.v6Addr[1], gw_addr_v6.v6Addr[2], gw_addr_v6.v6Addr[3]); + post_route_evt(IPA_IP_v6, index, IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, gw_addr_v6); + upstream_v6_up = true; + } else { + IPACMDBG_H("already setupstream iface(%s) ipv6 previously\n", upstream_name); + result = SUCCESS_DUPLICATE_CONFIG; + } + } + default_gw_index = index; + IPACMDBG_H("Change degault_gw netdev to (%s)\n", upstream_name); + } + return result; +} + +RET IPACM_OffloadManager::stopAllOffload() +{ + return SUCCESS; +} + +RET IPACM_OffloadManager::setQuota(const char * upstream_name /* upstream */, uint64_t mb/* limit */) +{ + wan_ioctl_set_data_quota quota; + int fd = -1; + + if ((fd = open(DEVICE_NAME, O_RDWR)) < 0) + { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + return FAIL_HARDWARE; + } + + quota.quota_mbytes = mb; + quota.set_quota = true; + + memset(quota.interface_name, 0, IFNAMSIZ); + if (strlcpy(quota.interface_name, upstream_name, IFNAMSIZ) >= IFNAMSIZ) { + IPACMERR("String truncation occurred on upstream"); + close(fd); + return FAIL_INPUT_CHECK; + } + + IPACMDBG_H("SET_DATA_QUOTA %s %lld", quota.interface_name, mb); + + if (ioctl(fd, WAN_IOC_SET_DATA_QUOTA, "a) < 0) { + IPACMERR("IOCTL WAN_IOCTL_SET_DATA_QUOTA call failed: %s", strerror(errno)); + close(fd); + return FAIL_TRY_AGAIN; + } + + close(fd); + return SUCCESS; +} + +RET IPACM_OffloadManager::getStats(const char * upstream_name /* upstream */, + bool reset /* reset */, OffloadStatistics& offload_stats/* ret */) +{ + int fd = -1; + wan_ioctl_query_tether_stats_all stats; + + if ((fd = open(DEVICE_NAME, O_RDWR)) < 0) { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + return FAIL_HARDWARE; + } + + memset(&stats, 0, sizeof(stats)); + if (strlcpy(stats.upstreamIface, upstream_name, IFNAMSIZ) >= IFNAMSIZ) { + IPACMERR("String truncation occurred on upstream\n"); + close(fd); + return FAIL_INPUT_CHECK; + } + stats.reset_stats = reset; + stats.ipa_client = IPACM_CLIENT_MAX; + + if (ioctl(fd, WAN_IOC_QUERY_TETHER_STATS_ALL, &stats) < 0) { + IPACMERR("IOCTL WAN_IOC_QUERY_TETHER_STATS_ALL call failed: %s \n", strerror(errno)); + close(fd); + return FAIL_TRY_AGAIN; + } + /* feedback to IPAHAL*/ + offload_stats.tx = stats.tx_bytes; + offload_stats.rx = stats.rx_bytes; + + IPACMDBG_H("send getStats tx:%lld rx:%lld \n", offload_stats.tx, offload_stats.rx); + return SUCCESS; +} + +int IPACM_OffloadManager::post_route_evt(enum ipa_ip_type iptype, int index, ipa_cm_event_id event, const Prefix &gw_addr) +{ + ipacm_cmd_q_data evt; + ipacm_event_data_iptype *evt_data_route; + + evt_data_route = (ipacm_event_data_iptype*)malloc(sizeof(ipacm_event_data_iptype)); + if(evt_data_route == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return -EFAULT; + } + memset(evt_data_route, 0, sizeof(*evt_data_route)); + + evt_data_route->if_index = index; + evt_data_route->if_index_tether = 0; + evt_data_route->iptype = iptype; + +#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN + evt_data_route->ipv4_addr_gw = gw_addr.v4Addr; + evt_data_route->ipv6_addr_gw[0] = gw_addr.v6Addr[0]; + evt_data_route->ipv6_addr_gw[1] = gw_addr.v6Addr[1]; + evt_data_route->ipv6_addr_gw[2] = gw_addr.v6Addr[2]; + evt_data_route->ipv6_addr_gw[3] = gw_addr.v6Addr[3]; + IPACMDBG_H("default gw ipv4 (%x)\n", evt_data_route->ipv4_addr_gw); + IPACMDBG_H("IPV6 gateway: %08x:%08x:%08x:%08x \n", + evt_data_route->ipv6_addr_gw[0], evt_data_route->ipv6_addr_gw[1], evt_data_route->ipv6_addr_gw[2], evt_data_route->ipv6_addr_gw[3]); +#endif + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_ADD: fid(%d) tether_fid(%d) ip-type(%d)\n", evt_data_route->if_index, + evt_data_route->if_index_tether, evt_data_route->iptype); + + memset(&evt, 0, sizeof(evt)); + evt.evt_data = (void*)evt_data_route; + evt.event = event; + + IPACM_EvtDispatcher::PostEvt(&evt); + + return 0; +} + +int IPACM_OffloadManager::ipa_get_if_index(const char * if_name, int * if_index) +{ + int fd; + struct ifreq ifr; + + if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + IPACMERR("get interface index socket create failed \n"); + return IPACM_FAILURE; + } + + if(strnlen(if_name, sizeof(if_name)) >= sizeof(ifr.ifr_name)) { + IPACMERR("interface name overflows: len %d\n", strnlen(if_name, sizeof(if_name))); + close(fd); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + (void)strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); + IPACMDBG_H("interface name (%s)\n", if_name); + + if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0) + { + IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name); + close(fd); + return IPACM_FAILURE; + } + + *if_index = ifr.ifr_ifindex; + IPACMDBG_H("Interface netdev index %d\n", *if_index); + close(fd); + return IPACM_SUCCESS; +} + +int IPACM_OffloadManager::resetTetherStats(const char * upstream_name /* upstream */) +{ + int fd = -1; + wan_ioctl_reset_tether_stats stats; + + if ((fd = open(DEVICE_NAME, O_RDWR)) < 0) { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + return FAIL_HARDWARE; + } + + memset(stats.upstreamIface, 0, IFNAMSIZ); + if (strlcpy(stats.upstreamIface, upstream_name, IFNAMSIZ) >= IFNAMSIZ) { + IPACMERR("String truncation occurred on upstream\n"); + close(fd); + return FAIL_INPUT_CHECK; + } + stats.reset_stats = true; + + if (ioctl(fd, WAN_IOC_RESET_TETHER_STATS, &stats) < 0) { + IPACMERR("IOCTL WAN_IOC_RESET_TETHER_STATS call failed: %s", strerror(errno)); + close(fd); + return FAIL_HARDWARE; + } + IPACMDBG_H("Reset Interface %s stats\n", upstream_name); + return IPACM_SUCCESS; +} + +IPACM_OffloadManager* IPACM_OffloadManager::GetInstance() +{ + if(pInstance == NULL) + pInstance = new IPACM_OffloadManager(); + + return pInstance; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp index d6cafa04..2a2555a7 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -73,7 +73,8 @@ bool IPACM_Routing::DeviceNodeIsOpened() bool IPACM_Routing::AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable) { - int retval = 0; + int retval = 0, cnt=0; + bool isInvalid = false; if (!DeviceNodeIsOpened()) { @@ -81,6 +82,20 @@ bool IPACM_Routing::AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable) return false; } + for(cnt=0; cntnum_rules; cnt++) + { + if(ruleTable->rules[cnt].rule.dst > IPA_CLIENT_MAX) + { + IPACMERR("Invalid dst pipe, Rule:%d dst_pipe:%d\n", cnt, ruleTable->rules[cnt].rule.dst); + isInvalid = true; + } + } + + if(isInvalid) + { + return false; + } + retval = ioctl(m_fd, IPA_IOC_ADD_RT_RULE, ruleTable); if (retval) { @@ -88,6 +103,11 @@ bool IPACM_Routing::AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable) return false; } + for(cnt=0; cntnum_rules; cnt++) + { + IPACMDBG("Rule:%d dst_pipe:%d\n", cnt, ruleTable->rules[cnt].rule.dst); + } + IPACMDBG_H("Added routing rule %p\n", ruleTable); return true; } @@ -156,8 +176,10 @@ bool IPACM_Routing::GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable) IPACMERR("IPA_IOCTL_GET_RT_TBL ioctl failed, routingTable =0x%p, retval=0x%x.\n", routingTable, retval); return false; } - IPACMDBG_H("IPA_IOCTL_GET_RT_TBL ioctl issued to IPA routing block.\n"); + /* put routing table right after successfully get routing table */ + PutRoutingTable(routingTable->hdl); + return true; } @@ -224,3 +246,31 @@ bool IPACM_Routing::DeleteRoutingHdl(uint32_t rt_rule_hdl, ipa_ip_type ip) return res; } +bool IPACM_Routing::ModifyRoutingRule(struct ipa_ioc_mdfy_rt_rule *mdfyRules) +{ + int retval = 0, cnt; + + if (!DeviceNodeIsOpened()) + { + IPACMERR("Device is not opened\n"); + return false; + } + + retval = ioctl(m_fd, IPA_IOC_MDFY_RT_RULE, mdfyRules); + if (retval) + { + IPACMERR("Failed modifying routing rules %p\n", mdfyRules); + return false; + } + + for(cnt=0; cntnum_rules; cnt++) + { + if(mdfyRules->rules[cnt].status != 0) + { + IPACMERR("Unable to modify rule: %d\n", cnt); + } + } + + IPACMDBG_H("Modified routing rules %p\n", mdfyRules); + return true; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Wan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wan.cpp index f7e6c382..d0a0ab53 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Wan.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wan.cpp @@ -53,7 +53,9 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. bool IPACM_Wan::wan_up = false; bool IPACM_Wan::wan_up_v6 = false; +uint8_t IPACM_Wan::xlat_mux_id = 0; +uint32_t IPACM_Wan::curr_wan_ip = 0; int IPACM_Wan::num_v4_flt_rule = 0; int IPACM_Wan::num_v6_flt_rule = 0; @@ -69,6 +71,7 @@ int IPACM_Wan::num_ipv4_modem_pdn = 0; int IPACM_Wan::num_ipv6_modem_pdn = 0; bool IPACM_Wan::embms_is_on = false; +bool IPACM_Wan::backhaul_is_wan_bridge = false; uint32_t IPACM_Wan::backhaul_ipv6_prefix[2]; @@ -81,8 +84,8 @@ int IPACM_Wan::ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES]; #endif IPACM_Wan::IPACM_Wan(int iface_index, - ipacm_wan_iface_type is_sta_mode, - uint8_t *mac_addr) : IPACM_Iface(iface_index) + ipacm_wan_iface_type is_sta_mode, + uint8_t *mac_addr) : IPACM_Iface(iface_index) { num_firewall_v4 = 0; num_firewall_v6 = 0; @@ -100,6 +103,9 @@ IPACM_Wan::IPACM_Wan(int iface_index, } m_is_sta_mode = is_sta_mode; + wan_v4_addr_set = false; + wan_v4_addr_gw_set = false; + wan_v6_addr_gw_set = false; active_v4 = false; active_v6 = false; header_set_v4 = false; @@ -111,11 +117,22 @@ IPACM_Wan::IPACM_Wan(int iface_index, num_ipv6_dest_flt_rule = 0; memset(ipv6_dest_flt_rule_hdl, 0, MAX_DEFAULT_v6_ROUTE_RULES*sizeof(uint32_t)); memset(ipv6_prefix, 0, sizeof(ipv6_prefix)); + memset(wan_v6_addr_gw, 0, sizeof(wan_v6_addr_gw)); ext_prop = NULL; + is_ipv6_frag_firewall_flt_rule_installed = false; + ipv6_frag_firewall_flt_rule_hdl = 0; num_wan_client = 0; header_name_count = 0; memset(invalid_mac, 0, sizeof(invalid_mac)); + + is_xlat = false; + hdr_hdl_dummy_v6 = 0; + hdr_proc_hdl_dummy_v6 = 0; + is_default_gateway = false; + m_fd_ipa = 0; + wan_client_len = 0; + if(iface_query != NULL) { wan_client_len = (sizeof(ipa_wan_client)) + (iface_query->num_tx_props * sizeof(wan_client_rt_hdl)); @@ -140,12 +157,6 @@ IPACM_Wan::IPACM_Wan(int iface_index, IPACMDBG_H("The new WAN interface is WLAN STA.\n"); } - if(m_is_sta_mode == WLAN_WAN) - { - memcpy(ext_router_mac_addr, mac_addr, - sizeof(ext_router_mac_addr)); - } - m_fd_ipa = open(IPA_DEVICE_NAME, O_RDWR); if(0 == m_fd_ipa) { @@ -186,93 +197,125 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) struct ipa_rt_rule_add *rt_rule_entry; struct ipa_ioc_add_flt_rule *flt_rule; struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_get_hdr hdr; const int NUM_RULES = 1; int num_ipv6_addr, len; int res = IPACM_SUCCESS; + memset(&hdr, 0, sizeof(hdr)); + if(tx_prop == NULL || rx_prop == NULL) + { + IPACMDBG_H("Either tx or rx property is NULL, return.\n"); + return IPACM_SUCCESS; + } + + /* Update the IP Type. */ + config_ip_type(data->iptype); + if (data->iptype == IPA_IP_v6) { - for(num_ipv6_addr=0;num_ipv6_addripv6_addr[0]) && - (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) && - (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) && - (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3])) - { - IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr); - return IPACM_SUCCESS; - break; - } - } - rt_rule = (struct ipa_ioc_add_rt_rule *) - calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + - NUM_RULES * sizeof(struct ipa_rt_rule_add)); + for(num_ipv6_addr=0;num_ipv6_addripv6_addr[0]) && + (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) && + (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) && + (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3])) + { + IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr); + return IPACM_SUCCESS; + break; + } + } + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES * sizeof(struct ipa_rt_rule_add)); - if (!rt_rule) - { - IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); - return IPACM_FAILURE; - } + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } - rt_rule->commit = 1; - rt_rule->num_rules = NUM_RULES; - rt_rule->ip = data->iptype; - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name); - - rt_rule_entry = &rt_rule->rules[0]; - rt_rule_entry->at_rear = false; - rt_rule_entry->rule.dst = iface_query->excp_pipe; //go to A5 - rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; - rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3]; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; - ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0]; - ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1]; - ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2]; - ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3]; - - if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - res = IPACM_FAILURE; - goto fail; - } - else if (rt_rule_entry->status) - { - IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); - res = rt_rule_entry->status; - goto fail; - } - dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl; - - /* setup same rule for v6_wan table*/ - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name); - if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - res = IPACM_FAILURE; - goto fail; - } - else if (rt_rule_entry->status) - { - IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); - res = rt_rule_entry->status; - goto fail; - } - dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl; + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = data->iptype; + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name)); - IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, num_dft_rt_v6: %d \n", - dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6], - dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],num_dft_rt_v6); + rt_rule_entry = &rt_rule->rules[0]; + if(m_is_sta_mode == Q6_WAN) + { + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + } + rt_rule_entry->at_rear = false; + if(m_is_sta_mode == Q6_WAN) + { + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + } + else + { + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + } + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0]; + ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1]; + ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2]; + ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3]; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl; - if (num_dft_rt_v6 == 0) - { + /* setup same rule for v6_wan table*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl; + + IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, num_dft_rt_v6: %d \n", + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6], + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],num_dft_rt_v6); + + /* add default filtering rules when wan-iface get global v6-prefix */ + if (num_dft_rt_v6 == 1) + { if(m_is_sta_mode == Q6_WAN) { modem_ipv6_pdn_index = num_ipv6_modem_pdn; @@ -284,7 +327,7 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) { init_fl_rule(data->iptype); } - } + } /* add WAN DL interface IP specific flt rule for IPv6 when backhaul is not Q6 */ if(m_is_sta_mode != Q6_WAN) @@ -316,7 +359,9 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; @@ -336,6 +381,7 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); ipv6_dest_flt_rule_hdl[num_ipv6_dest_flt_rule] = flt_rule->rules[0].flt_rule_hdl; IPACMDBG_H("IPv6 dest filter rule %d HDL:0x%x\n", num_ipv6_dest_flt_rule, ipv6_dest_flt_rule_hdl[num_ipv6_dest_flt_rule]); num_ipv6_dest_flt_rule++; @@ -352,13 +398,35 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) } else { + if(wan_v4_addr_set) + { + /* check iface ipv4 same or not */ + if(data->ipv4_addr == wan_v4_addr) + { + IPACMDBG_H("Already setup device (%s) ipv4 and it didn't change(0x%x)\n", dev_name, data->ipv4_addr); + return IPACM_SUCCESS; + } + else + { + IPACMDBG_H(" device (%s) ipv4 addr is changed\n", dev_name); + /* Delete default v4 RT rule */ + IPACMDBG_H("Delete default v4 routing rules\n"); + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing old RT rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + rt_rule = (struct ipa_ioc_add_rt_rule *) calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + NUM_RULES * sizeof(struct ipa_rt_rule_add)); if (!rt_rule) { - IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); return IPACM_FAILURE; } @@ -366,14 +434,31 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) rt_rule->num_rules = NUM_RULES; rt_rule->ip = data->iptype; rt_rule_entry = &rt_rule->rules[0]; + if(m_is_sta_mode == Q6_WAN) + { + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + } + else + { + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + } rt_rule_entry->at_rear = false; - rt_rule_entry->rule.dst = iface_query->excp_pipe; //go to A5 rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; /* still need setup v4 default routing rule to A5*/ - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name); + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name)); rt_rule_entry->rule.attrib.u.v4.dst_addr = data->ipv4_addr; rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; - +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = false; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) { IPACMERR("Routing rule addition failed!\n"); @@ -390,20 +475,30 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]); /* initial multicast/broadcast/fragment filter rule */ - if(m_is_sta_mode == Q6_WAN) + /* only do one time */ + if(!wan_v4_addr_set) { - modem_ipv4_pdn_index = num_ipv4_modem_pdn; - num_ipv4_modem_pdn++; - IPACMDBG_H("Now the number of modem ipv4 pdn is %d.\n", num_ipv4_modem_pdn); - init_fl_rule_ex(data->iptype); - } - else - { - init_fl_rule(data->iptype); + /* initial multicast/broadcast/fragment filter rule */ + if(m_is_sta_mode == Q6_WAN) + { + modem_ipv4_pdn_index = num_ipv4_modem_pdn; + num_ipv4_modem_pdn++; + IPACMDBG_H("Now the number of modem ipv4 pdn is %d.\n", num_ipv4_modem_pdn); + init_fl_rule_ex(data->iptype); + } + else + { + init_fl_rule(data->iptype); + } } wan_v4_addr = data->ipv4_addr; - IPACMDBG_H("Receved wan address:0x%x\n",wan_v4_addr); + wan_v4_addr_set = true; + + if (m_is_sta_mode == Q6_WAN) + curr_wan_ip = data->ipv4_addr; + + IPACMDBG_H("Receved wan ipv4-addr:0x%x\n",wan_v4_addr); } IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6); @@ -441,9 +536,81 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) } break; + case IPA_WAN_XLAT_CONNECT_EVENT: + { + IPACMDBG_H("Recieved IPA_WAN_XLAT_CONNECT_EVENT\n"); + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index); + if ((ipa_interface_index == ipa_if_num) && (m_is_sta_mode == Q6_WAN)) + { + is_xlat = true; + IPACMDBG_H("WAN-LTE (%s) link up, iface: %d is_xlat: \n", + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,data->if_index, is_xlat); + } + break; + } case IPA_CFG_CHANGE_EVENT: { - if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) && + if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ipa_if_cate) && + (m_is_sta_mode ==ECM_WAN)) + { + IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category did not change(wan_mode:%d)\n", m_is_sta_mode); + IPACMDBG_H("Now the cradle wan mode is %d.\n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode); + if(is_default_gateway == true) + { + if(backhaul_is_wan_bridge == false && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE) + { + IPACMDBG_H("Cradle wan mode switch to bridge mode.\n"); + backhaul_is_wan_bridge = true; + } + else if(backhaul_is_wan_bridge == true && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + IPACMDBG_H("Cradle wan mode switch to router mode.\n"); + backhaul_is_wan_bridge = false; + } + else + { + IPACMDBG_H("No cradle mode switch, return.\n"); + return; + } + /* post wan mode change event to LAN/WLAN */ + if(IPACM_Wan::wan_up == true) + { + IPACMDBG_H("This interface is default GW.\n"); + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(evt_data)); + + ipacm_event_cradle_wan_mode *data_wan_mode = NULL; + data_wan_mode = (ipacm_event_cradle_wan_mode *)malloc(sizeof(ipacm_event_cradle_wan_mode)); + if(data_wan_mode == NULL) + { + IPACMERR("unable to allocate memory.\n"); + return; + } + data_wan_mode->cradle_wan_mode = IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode; + evt_data.event = IPA_CRADLE_WAN_MODE_SWITCH; + evt_data.evt_data = data_wan_mode; + IPACMDBG_H("Posting IPA_CRADLE_WAN_MODE_SWITCH event.\n"); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + /* update the firewall flt rule actions */ + if(active_v4) + { + del_dft_firewall_rules(IPA_IP_v4); + config_dft_firewall_rules(IPA_IP_v4); + } + if(active_v6) + { + del_dft_firewall_rules(IPA_IP_v6); + config_dft_firewall_rules(IPA_IP_v6); + } + } + else + { + IPACMDBG_H("This interface is not default GW, ignore.\n"); + } + } + else if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) && (m_is_sta_mode ==ECM_WAN)) { IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category changed(wan_mode:%d)\n", m_is_sta_mode); @@ -478,30 +645,30 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) case IPA_LINK_DOWN_EVENT: { - if(m_is_sta_mode == Q6_WAN) + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) { - ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; - ipa_interface_index = iface_ipa_index_query(data->if_index); - if (ipa_interface_index == ipa_if_num) + if(m_is_sta_mode == Q6_WAN) { - IPACMDBG_H("Received IPA_LINK_DOWN_EVENT\n"); - handle_down_evt_ex(); - IPACMDBG_H("IPA_WAN_Q6 (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); + IPACMDBG_H("Received IPA_LINK_DOWN_EVENT\n"); + handle_down_evt_ex(); + IPACMDBG_H("IPA_WAN_Q6 (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + delete this; + return; + } + else if (m_is_sta_mode == ECM_WAN) + { + IPACMDBG_H("Received IPA_LINK_DOWN_EVENT(wan_mode:%d)\n", m_is_sta_mode); + /* delete previous instance */ + handle_down_evt(); + IPACMDBG_H("IPA_WAN_CRADLE (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface delete this; return; } } - else if (m_is_sta_mode == ECM_WAN) - { - IPACMDBG_H("Received IPA_LINK_DOWN_EVENT(wan_mode:%d)\n", m_is_sta_mode); - /* delete previous instance */ - handle_down_evt(); - IPACMDBG_H("IPA_WAN_CRADLE (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); - IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface - delete this; - return; - } } break; @@ -523,7 +690,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) { IPACMDBG_H("Get IPA_ADDR_ADD_EVENT: IF ip type %d, incoming ip type %d\n", ip_type, data->iptype); /* check v4 not setup before, v6 can have 2 iface ip */ - if( ((data->iptype != ip_type) && (ip_type != IPA_IP_MAX)) + if( (data->iptype == IPA_IP_v4) || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES))) { IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); @@ -547,6 +714,14 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) { ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param; ipa_interface_index = iface_ipa_index_query(data->if_index); +#ifndef FEATURE_IPACM_HAL + /* add the check see if tether_iface is valid or not */ + if (iface_ipa_index_query(data->if_index_tether) == INVALID_IFACE) + { + IPACMERR("UPSTREAM_ROUTE_ADD tether_if(%d), not valid ignore\n", INVALID_IFACE); + return; + } +#endif if (ipa_interface_index == ipa_if_num) { IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT (Android) for ip-type (%d)\n", data->iptype); @@ -555,24 +730,57 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) { if (active_v4 == false) { +#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN + IPACMDBG_H("adding routing table(upstream), dev (%s) ip-type(%d) default gw (%x)\n", dev_name,data->iptype, wan_v4_addr_gw); + wan_v4_addr_gw = data->ipv4_addr_gw; + wan_v4_addr_gw_set = true; + /* Check & construct STA header */ + handle_sta_header_add_evt(); +#else IPACMDBG_H("adding routing table(upstream), dev (%s) ip-type(%d)\n", dev_name,data->iptype); - handle_route_add_evt(data->iptype); +#endif + handle_route_add_evt(data->iptype); //sky } #ifdef FEATURE_IPA_ANDROID +#ifdef FEATURE_IPACM_HAL + post_wan_up_tether_evt(data->iptype, 0); +#else /* using ipa_if_index, not netdev_index */ post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); +#endif #endif } else if ((data->iptype == IPA_IP_v6) && (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)) { + if(ipv6_prefix[0] == 0 && ipv6_prefix[1] == 0) + { + IPACMDBG_H("IPv6 default route comes earlier than global IP, ignore.\n"); + return; + } + if (active_v6 == false) { IPACMDBG_H("\n get default v6 route (dst:00.00.00.00) upstream\n"); +#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN + IPACMDBG_H(" IPV6 gateway: %08x:%08x:%08x:%08x \n", + data->ipv6_addr_gw[0], data->ipv6_addr_gw[1], data->ipv6_addr_gw[2], data->ipv6_addr_gw[3]); + wan_v6_addr_gw[0] = data->ipv6_addr_gw[0]; + wan_v6_addr_gw[1] = data->ipv6_addr_gw[1]; + wan_v6_addr_gw[2] = data->ipv6_addr_gw[2]; + wan_v6_addr_gw[3] = data->ipv6_addr_gw[3]; + wan_v6_addr_gw_set = true; + /* Check & construct STA header */ + handle_sta_header_add_evt(); +#endif handle_route_add_evt(data->iptype); } #ifdef FEATURE_IPA_ANDROID +#ifdef FEATURE_IPACM_HAL + post_wan_up_tether_evt(data->iptype, 0); +#else /* using ipa_if_index, not netdev_index */ post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); +#endif #endif } } @@ -582,6 +790,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) { IPACMDBG_H("Received v4 IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); IPACMDBG_H("need clean default v4 route (dst:0.0.0.0) for old iface (%s)\n", dev_name); + wan_v4_addr_gw_set = false; if(m_is_sta_mode == Q6_WAN) { del_wan_firewall_rule(IPA_IP_v4); @@ -618,14 +827,25 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) { ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param; ipa_interface_index = iface_ipa_index_query(data->if_index); +#ifndef FEATURE_IPACM_HAL + /* add the check see if tether_iface is valid or not */ + if (iface_ipa_index_query(data->if_index_tether) == INVALID_IFACE) + { + IPACMERR("UPSTREAM_ROUTE_DEL tether_if(%d), not valid ignore\n", INVALID_IFACE); + return; + } +#endif if (ipa_interface_index == ipa_if_num) { IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT\n"); if ((data->iptype == IPA_IP_v4) && (active_v4 == true)) { IPACMDBG_H("get del default v4 route (dst:0.0.0.0)\n"); -// wan_v4_addr_gw_set = false; /* android requires CnE change too */ + wan_v4_addr_gw_set = false; #ifdef FEATURE_IPA_ANDROID +#ifdef FEATURE_IPACM_HAL + post_wan_down_tether_evt(data->iptype, 0); +#else /* using ipa_if_index, not netdev_index */ post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); /* no any ipv4 tether iface support*/ @@ -634,6 +854,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("still have tether ipv4 client on upsteam iface\n"); return; } +#endif #endif if(m_is_sta_mode == Q6_WAN) { @@ -650,6 +871,10 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) else if ((data->iptype == IPA_IP_v6) && (active_v6 == true)) { #ifdef FEATURE_IPA_ANDROID +#ifdef FEATURE_IPACM_HAL + post_wan_down_tether_evt(data->iptype, 0); +#else + /* using ipa_if_index, not netdev_index */ post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); /* no any ipv6 tether iface support*/ @@ -658,6 +883,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("still have tether ipv6 client on upsteam iface\n"); return; } +#endif #endif if(m_is_sta_mode == Q6_WAN) { @@ -702,17 +928,42 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == false) && (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)) { - IPACMDBG_H("adding routing table, dev (%s) ip-type(%d)\n", dev_name,data->iptype); + wan_v4_addr_gw = data->ipv4_addr_gw; + wan_v4_addr_gw_set = true; + IPACMDBG_H("adding routing table, dev (%s) ip-type(%d), default gw (%x)\n", dev_name,data->iptype, wan_v4_addr_gw); + /* Check & construct STA header */ + handle_sta_header_add_evt(); handle_route_add_evt(data->iptype); + /* Add IPv6 routing table if XLAT is enabled */ + if(is_xlat && (m_is_sta_mode == Q6_WAN) && (active_v6 == false)) + { + IPACMDBG_H("XLAT enabled: adding IPv6 routing table dev (%s)\n", dev_name); + handle_route_add_evt(IPA_IP_v6); + } } else if ((data->iptype == IPA_IP_v6) && - (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && (active_v6 == false) - && (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)) + (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && + (active_v6 == false) && (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)) { + if(ipv6_prefix[0] == 0 && ipv6_prefix[1] == 0) + { + IPACMDBG_H("IPv6 default route comes earlier than global IP, ignore.\n"); + return; + } + IPACMDBG_H("\n get default v6 route (dst:00.00.00.00)\n"); - IPACMDBG_H(" IPV6 value: %08x:%08x:%08x:%08x \n", - data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); - handle_route_add_evt(data->iptype); + IPACMDBG_H(" IPV6 dst: %08x:%08x:%08x:%08x \n", + data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + IPACMDBG_H(" IPV6 gateway: %08x:%08x:%08x:%08x \n", + data->ipv6_addr_gw[0], data->ipv6_addr_gw[1], data->ipv6_addr_gw[2], data->ipv6_addr_gw[3]); + wan_v6_addr_gw[0] = data->ipv6_addr_gw[0]; + wan_v6_addr_gw[1] = data->ipv6_addr_gw[1]; + wan_v6_addr_gw[2] = data->ipv6_addr_gw[2]; + wan_v6_addr_gw[3] = data->ipv6_addr_gw[3]; + wan_v6_addr_gw_set = true; + /* Check & construct STA header */ + handle_sta_header_add_evt(); + handle_route_add_evt(data->iptype); } } else /* double check if current default iface is not itself */ @@ -723,6 +974,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("ipv4 addr 0x%x\n", data->ipv4_addr); IPACMDBG_H("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask); IPACMDBG_H("need clean default v4 route (dst:0.0.0.0) for old iface (%s)\n", dev_name); + wan_v4_addr_gw_set = false; if(m_is_sta_mode == Q6_WAN) { del_wan_firewall_rule(IPA_IP_v4); @@ -765,11 +1017,20 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true)) { IPACMDBG_H("get del default v4 route (dst:0.0.0.0)\n"); + wan_v4_addr_gw_set = false; if(m_is_sta_mode == Q6_WAN) { del_wan_firewall_rule(IPA_IP_v4); install_wan_filtering_rule(false); handle_route_del_evt_ex(IPA_IP_v4); + + if(is_xlat && active_v6 == true) + { + IPACMDBG_H("XLAT enabled: Delete IPv6 routing table dev (%s)\n", dev_name); + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } } else { @@ -780,7 +1041,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) else if ((data->iptype == IPA_IP_v6) && (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && (active_v6 == true)) { - IPACMDBG_H("get del default v6 route (dst:00.00.00.00)\n"); + IPACMDBG_H("get del default v6 route (dst:00.00.00.00)\n"); if(m_is_sta_mode == Q6_WAN) { del_wan_firewall_rule(IPA_IP_v6); @@ -808,7 +1069,6 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) if (m_is_sta_mode == WLAN_WAN) { - handle_header_add_evt(ext_router_mac_addr); if (data->iptype == IPA_IP_v4 && data->ipv4_addr == wan_v4_addr) { IPACMDBG_H("Ignore IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n"); @@ -844,18 +1104,17 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) return; } - handle_header_add_evt(data->mac_addr); - handle_wan_hdr_init(data->mac_addr); - IPACMDBG_H("construct wan header and route rules \n"); + IPACMDBG_H("construct wan-client header and route rules \n"); /* Associate with IP and construct RT-rule */ if (handle_wan_client_ipaddr(data) == IPACM_FAILURE) { return; } handle_wan_client_route_rule(data->mac_addr, data->iptype); + /* Check & construct STA header */ + handle_sta_header_add_evt(); return; - } } break; @@ -941,6 +1200,44 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) } break; + case IPA_WLAN_SWITCH_TO_SCC: + if(IPACM_Wan::backhaul_is_sta_mode == true) + { + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_SCC\n"); + if(ip_type == IPA_IP_MAX) + { + handle_wlan_SCC_MCC_switch(true, IPA_IP_v4); + handle_wlan_SCC_MCC_switch(true, IPA_IP_v6); + handle_wan_client_SCC_MCC_switch(true, IPA_IP_v4); + handle_wan_client_SCC_MCC_switch(true, IPA_IP_v6); + } + else + { + handle_wlan_SCC_MCC_switch(true, ip_type); + handle_wan_client_SCC_MCC_switch(true, ip_type); + } + } + break; + + case IPA_WLAN_SWITCH_TO_MCC: + if(IPACM_Wan::backhaul_is_sta_mode == true) + { + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_MCC\n"); + if(ip_type == IPA_IP_MAX) + { + handle_wlan_SCC_MCC_switch(false, IPA_IP_v4); + handle_wlan_SCC_MCC_switch(false, IPA_IP_v6); + handle_wan_client_SCC_MCC_switch(false, IPA_IP_v4); + handle_wan_client_SCC_MCC_switch(false, IPA_IP_v6); + } + else + { + handle_wlan_SCC_MCC_switch(false, ip_type); + handle_wan_client_SCC_MCC_switch(false, ip_type); + } + } + break; + default: break; } @@ -953,13 +1250,14 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) { /* add default WAN route */ - struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_ioc_add_rt_rule *rt_rule = NULL; struct ipa_rt_rule_add *rt_rule_entry; struct ipa_ioc_get_hdr sRetHeader; uint32_t cnt, tx_index = 0; const int NUM = 1; ipacm_cmd_q_data evt_data; struct ipa_ioc_copy_hdr sCopyHeader; /* checking if partial header*/ + struct ipa_ioc_get_hdr hdr; IPACMDBG_H("ip-type:%d\n", iptype); @@ -974,8 +1272,16 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) is_default_gateway = true; IPACMDBG_H("Default route is added to iface %s.\n", dev_name); - memcpy(backhaul_ipv6_prefix, ipv6_prefix, sizeof(backhaul_ipv6_prefix)); - IPACMDBG_H("Setup backhaul ipv6 prefix to be 0x%08x%08x.\n", backhaul_ipv6_prefix[0], backhaul_ipv6_prefix[1]); + + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE) + { + IPACM_Wan::backhaul_is_wan_bridge = true; + } + else + { + IPACM_Wan::backhaul_is_wan_bridge = false; + } + IPACMDBG_H("backhaul_is_wan_bridge ?: %d \n", IPACM_Wan::backhaul_is_wan_bridge); if (m_is_sta_mode !=Q6_WAN) { @@ -1017,14 +1323,14 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) return IPACM_FAILURE; } } - +#if 0 for (cnt=0; cntnum_tx_props; cnt++) { if(tx_prop->tx[cnt].ip==iptype) break; } - //if(tx_prop->tx[cnt].hdr_name != NULL) + if(tx_prop->tx[cnt].hdr_name != NULL) { memset(&sCopyHeader, 0, sizeof(sCopyHeader)); memcpy(sCopyHeader.name, @@ -1063,6 +1369,7 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) } } } +#endif rt_rule = (struct ipa_ioc_add_rt_rule *) calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + @@ -1095,32 +1402,28 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) continue; } + /* use the STA-header handler */ if (iptype == IPA_IP_v4) { - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name); + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v4; } else { - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name); + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v6; } - //if (tx_prop->tx[tx_index].hdr_name != NULL) + if(IPACM_Iface::ipacmcfg->isMCC_Mode == true) { - IPACMDBG_H(" TX- header hdl %s \n", tx_prop->tx[tx_index].hdr_name); - memset(&sRetHeader, 0, sizeof(sRetHeader)); - strncpy(sRetHeader.name, - tx_prop->tx[tx_index].hdr_name, - sizeof(tx_prop->tx[tx_index].hdr_name)); - if (false == m_header.GetHeaderHandle(&sRetHeader)) - { - IPACMERR("\n ioctl failed\n"); - free(rt_rule); - return IPACM_FAILURE; - } - rt_rule_entry->rule.hdr_hdl = sRetHeader.hdl; + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; } - - rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[tx_index].attrib, sizeof(rt_rule_entry->rule.attrib)); @@ -1130,7 +1433,10 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) { rt_rule_entry->rule.attrib.u.v4.dst_addr = 0; rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) { IPACMERR("Routing rule addition failed!\n"); @@ -1153,7 +1459,9 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0; - +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) { IPACMERR("Routing rule addition failed!\n"); @@ -1173,45 +1481,71 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) if (iptype == IPA_IP_v6) { - strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name); - memset(rt_rule_entry, 0, sizeof(struct ipa_rt_rule_add)); - rt_rule_entry->at_rear = true; - rt_rule_entry->rule.dst = iface_query->excp_pipe; //go to A5 - rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; - rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0; - rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0; - rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0; - rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0; - - if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - free(rt_rule); - return IPACM_FAILURE; - } - wan_route_rule_v6_hdl_a5[0] = rt_rule_entry->rt_rule_hdl; - IPACMDBG_H("Set ipv6 wan-route rule hdl for v6_wan_table:0x%x,tx:%d,ip-type: %d \n", - wan_route_rule_v6_hdl_a5[0], - 0, - iptype); - } - - ipacm_event_iface_up *wanup_data; - wanup_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up)); - if (wanup_data == NULL) - { - IPACMERR("Unable to allocate memory\n"); - return IPACM_FAILURE; - } - memset(wanup_data, 0, sizeof(ipacm_event_iface_up)); + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + memset(rt_rule_entry, 0, sizeof(struct ipa_rt_rule_add)); + rt_rule_entry->at_rear = true; + if(m_is_sta_mode == Q6_WAN) + { + memset(&hdr, 0, sizeof(hdr)); + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + } + else + { + /* create dummy ethernet header for v6 RX path */ + IPACMDBG_H("Construct dummy ethernet_header\n"); + if (add_dummy_rx_hdr()) + { + IPACMERR("Construct dummy ethernet_header failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_proc_ctx_hdl = hdr_proc_hdl_dummy_v6; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + } + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + wan_route_rule_v6_hdl_a5[0] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("Set ipv6 wan-route rule hdl for v6_wan_table:0x%x,tx:%d,ip-type: %d \n", + wan_route_rule_v6_hdl_a5[0], 0, iptype); + } + + ipacm_event_iface_up *wanup_data; + wanup_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up)); + if (wanup_data == NULL) + { + IPACMERR("Unable to allocate memory\n"); + free(rt_rule); + return IPACM_FAILURE; + } + memset(wanup_data, 0, sizeof(ipacm_event_iface_up)); if (iptype == IPA_IP_v4) { - IPACM_Wan::wan_up = true; + IPACM_Wan::wan_up = true; active_v4 = true; memcpy(IPACM_Wan::wan_up_dev_name, dev_name, @@ -1239,14 +1573,33 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) } IPACMDBG_H("Posting IPA_HANDLE_WAN_UP with below information:\n"); IPACMDBG_H("if_name:%s, ipv4_address:0x%x, is sta mode:%d\n", - wanup_data->ifname, wanup_data->ipv4_addr, wanup_data->is_sta); + wanup_data->ifname, wanup_data->ipv4_addr, wanup_data->is_sta); memset(&evt_data, 0, sizeof(evt_data)); + + /* send xlat configuration for installing uplink rules */ + if(is_xlat && (m_is_sta_mode == Q6_WAN)) + { + IPACM_Wan::xlat_mux_id = ext_prop->ext[0].mux_id; + wanup_data->xlat_mux_id = IPACM_Wan::xlat_mux_id; + IPACMDBG_H("Set xlat configuraiton with below information:\n"); + IPACMDBG_H("xlat_enabled: xlat_mux_id: %d \n", + is_xlat, xlat_mux_id); + } + else + { + IPACM_Wan::xlat_mux_id = 0; + wanup_data->xlat_mux_id = 0; + IPACMDBG_H("No xlat configuratio:\n"); + } evt_data.event = IPA_HANDLE_WAN_UP; evt_data.evt_data = (void *)wanup_data; IPACM_EvtDispatcher::PostEvt(&evt_data); } else { + memcpy(backhaul_ipv6_prefix, ipv6_prefix, sizeof(backhaul_ipv6_prefix)); + IPACMDBG_H("Setup backhaul ipv6 prefix to be 0x%08x%08x.\n", backhaul_ipv6_prefix[0], backhaul_ipv6_prefix[1]); + IPACM_Wan::wan_up_v6 = true; active_v6 = true; memcpy(IPACM_Wan::wan_up_dev_name, @@ -1287,9 +1640,14 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); + if(rt_rule != NULL) + { + free(rt_rule); + } return IPACM_SUCCESS; } +#ifdef FEATURE_IPA_ANDROID /* wan default route/filter rule configuration */ int IPACM_Wan::post_wan_up_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether) { @@ -1347,12 +1705,12 @@ int IPACM_Wan::post_wan_up_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether) return IPACM_SUCCESS; } + /* wan default route/filter rule configuration */ int IPACM_Wan::post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether) { ipacm_cmd_q_data evt_data; ipacm_event_iface_up_tehter *wandown_data; - int i, j; wandown_data = (ipacm_event_iface_up_tehter *)malloc(sizeof(ipacm_event_iface_up_tehter)); if (wandown_data == NULL) @@ -1378,294 +1736,174 @@ int IPACM_Wan::post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tethe if (iptype == IPA_IP_v4) { - evt_data.event = IPA_HANDLE_WAN_DOWN_TETHER; - /* delete support tether ifaces to its array*/ - for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++) - { - if(IPACM_Wan::ipa_if_num_tether_v4[i] == ipa_if_num_tether) - { - IPACMDBG_H("Found tether client at position %d name(%s)\n", i, - IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); - break; - } - } - if(i == IPACM_Wan::ipa_if_num_tether_v4_total) + if(delete_tether_iface(iptype, ipa_if_num_tether)) { - IPACMDBG_H("Not finding the tether client.\n"); + IPACMDBG_H("Not finding the tethered client on ipv4.\n"); free(wandown_data); return IPACM_SUCCESS; } - for(j = i+1; j < IPACM_Wan::ipa_if_num_tether_v4_total; j++) - { - IPACM_Wan::ipa_if_num_tether_v4[j-1] = IPACM_Wan::ipa_if_num_tether_v4[j]; - } - IPACM_Wan::ipa_if_num_tether_v4_total--; - IPACMDBG_H("Now the total num of ipa_if_num_tether_v4_total is %d on wan-iface(%s)\n", - IPACM_Wan::ipa_if_num_tether_v4_total, - IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + evt_data.event = IPA_HANDLE_WAN_DOWN_TETHER; } else { - evt_data.event = IPA_HANDLE_WAN_DOWN_V6_TETHER; - /* delete support tether ifaces to its array*/ - for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++) - { - if(IPACM_Wan::ipa_if_num_tether_v6[i] == ipa_if_num_tether) - { - IPACMDBG_H("Found tether client at position %d name(%s)\n", i, - IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); - break; - } - } - if(i == IPACM_Wan::ipa_if_num_tether_v6_total) + if(delete_tether_iface(iptype, ipa_if_num_tether)) { - IPACMDBG_H("Not finding the tether client.\n"); + IPACMDBG_H("Not finding the tethered client on ipv6.\n"); free(wandown_data); return IPACM_SUCCESS; } - for(j = i+1; j < IPACM_Wan::ipa_if_num_tether_v6_total; j++) - { - IPACM_Wan::ipa_if_num_tether_v6[j-1] = IPACM_Wan::ipa_if_num_tether_v6[j]; - } - IPACM_Wan::ipa_if_num_tether_v6_total--; - IPACMDBG_H("Now the total num of ipa_if_num_tether_v6_total is %d on wan-iface(%s)\n", - IPACM_Wan::ipa_if_num_tether_v6_total, - IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + evt_data.event = IPA_HANDLE_WAN_DOWN_V6_TETHER; } evt_data.evt_data = (void *)wandown_data; IPACM_EvtDispatcher::PostEvt(&evt_data); return IPACM_SUCCESS; } +#endif /* construct complete ethernet header */ -int IPACM_Wan::handle_header_add_evt(uint8_t *mac_addr) +int IPACM_Wan::handle_sta_header_add_evt() { - #define WAN_IFACE_INDEX_LEN 2 - - uint32_t tx_index,cnt; - int res = IPACM_SUCCESS, len = 0; - char index[WAN_IFACE_INDEX_LEN]; - struct ipa_ioc_copy_hdr sCopyHeader; - struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; - - /* start of adding header */ - - IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - mac_addr[0], mac_addr[1], mac_addr[2], - mac_addr[3], mac_addr[4], mac_addr[5]); - + int res = IPACM_SUCCESS, index = IPACM_INVALID_INDEX; if((header_set_v4 == true) || (header_set_v6 == true)) { IPACMDBG_H("Already add STA full header\n"); return IPACM_SUCCESS; } - /* add header to IPA */ - len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add)); - pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len); - if (pHeaderDescriptor == NULL) - { - IPACMERR("calloc failed to allocate pHeaderDescriptor\n"); - return IPACM_FAILURE; - } - - /* copy partial header for v4 */ - for (cnt=0; cntnum_tx_props; cnt++) - { - if(tx_prop->tx[cnt].ip==IPA_IP_v4) - { - memset(&sCopyHeader, 0, sizeof(sCopyHeader)); - memcpy(sCopyHeader.name, - tx_prop->tx[cnt].hdr_name, - sizeof(sCopyHeader.name)); - - IPACMDBG_H("header name: %s from tx: %d\n", sCopyHeader.name,cnt); - if (m_header.CopyHeader(&sCopyHeader) == false) - { - IPACMERR("ioctl copy header failed"); - res = IPACM_FAILURE; - goto fail; - } - - if(sCopyHeader.is_eth2_ofst_valid == false) - { - eth2_ofst_v4 = 0; - } - else - { - eth2_ofst_v4 = sCopyHeader.eth2_ofst; - } - - IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); - if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) - { - IPACMERR("header oversize\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - memcpy(pHeaderDescriptor->hdr[0].hdr, - sCopyHeader.hdr, - sCopyHeader.hdr_len); - } - - /* copy client mac_addr to partial header */ - memcpy(&pHeaderDescriptor->hdr[0].hdr[eth2_ofst_v4], mac_addr, - IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */ - - pHeaderDescriptor->commit = true; - pHeaderDescriptor->num_hdrs = 1; - memset(pHeaderDescriptor->hdr[0].name, 0, - sizeof(pHeaderDescriptor->hdr[0].name)); - - snprintf(index,sizeof(index), "%d", ipa_if_num); - strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); - if ( strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + /* checking if the ipv4 same as default route */ + if(wan_v4_addr_gw_set) { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); - res = IPACM_FAILURE; - goto fail; - } - - pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; - pHeaderDescriptor->hdr[0].hdr_hdl = -1; - pHeaderDescriptor->hdr[0].is_partial = 0; - pHeaderDescriptor->hdr[0].status = -1; + index = get_wan_client_index_ipv4(wan_v4_addr_gw); + if (index != IPACM_INVALID_INDEX) + { + IPACMDBG_H("Matched client index: %d\n", index); + IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, index)->mac[0], + get_client_memptr(wan_client, index)->mac[1], + get_client_memptr(wan_client, index)->mac[2], + get_client_memptr(wan_client, index)->mac[3], + get_client_memptr(wan_client, index)->mac[4], + get_client_memptr(wan_client, index)->mac[5]); - if (m_header.AddHeader(pHeaderDescriptor) == false || - pHeaderDescriptor->hdr[0].status != 0) - { - IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); - res = IPACM_FAILURE; - goto fail; - } - else - { - hdr_hdl_sta_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; - header_set_v4 = true; - IPACMDBG_H("add full header name: %s (%x)\n", pHeaderDescriptor->hdr[0].name, pHeaderDescriptor->hdr[0].hdr_hdl); - } + if(get_client_memptr(wan_client, index)->ipv4_header_set) + { + hdr_hdl_sta_v4 = get_client_memptr(wan_client, index)->hdr_hdl_v4; + header_set_v4 = true; + IPACMDBG_H("add full ipv4 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v4); + /* store external_ap's MAC */ + memcpy(ext_router_mac_addr, get_client_memptr(wan_client, index)->mac, sizeof(ext_router_mac_addr)); + } + else + { + IPACMERR(" wan-client got ipv4 however didn't construct complete ipv4 header \n"); + return IPACM_FAILURE; + } - /* copy ipv4 full header to each TX endpoint property*/ - for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) - { - if(tx_prop->tx[tx_index].ip==IPA_IP_v4) - { - memcpy(tx_prop->tx[tx_index].hdr_name, pHeaderDescriptor->hdr[0].name, - sizeof(tx_prop->tx[tx_index].hdr_name)); - IPACMDBG_H("replace full header name: %s (%x) in tx:%d\n", tx_prop->tx[tx_index].hdr_name, pHeaderDescriptor->hdr[0].hdr_hdl,tx_index); - } - } - break; - } + if(get_client_memptr(wan_client, index)->ipv6_header_set) + { + hdr_hdl_sta_v6 = get_client_memptr(wan_client, index)->hdr_hdl_v6; + header_set_v6 = true; + IPACMDBG_H("add full ipv6 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v6); + } + else + { + IPACMERR(" wan-client got ipv6 however didn't construct complete ipv6 header \n"); + return IPACM_FAILURE; + } + } + else + { + IPACMDBG_H(" currently can't find matched wan-client's MAC-addr, waiting for header construction\n"); + return IPACM_SUCCESS; + } } - /* copy partial header for v6 */ - for (cnt=0; cntnum_tx_props; cnt++) + /* checking if the ipv4 same as default route */ + if(wan_v6_addr_gw_set) { - if(tx_prop->tx[cnt].ip == IPA_IP_v6) - { - IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt); - memset(&sCopyHeader, 0, sizeof(sCopyHeader)); - memcpy(sCopyHeader.name, - tx_prop->tx[cnt].hdr_name, - sizeof(sCopyHeader.name)); + index = get_wan_client_index_ipv6(wan_v6_addr_gw); + if (index != IPACM_INVALID_INDEX) + { + IPACMDBG_H("Matched client index: %d\n", index); + IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, index)->mac[0], + get_client_memptr(wan_client, index)->mac[1], + get_client_memptr(wan_client, index)->mac[2], + get_client_memptr(wan_client, index)->mac[3], + get_client_memptr(wan_client, index)->mac[4], + get_client_memptr(wan_client, index)->mac[5]); - IPACMDBG_H("header name: %s from tx: %d\n", sCopyHeader.name,cnt); - if (m_header.CopyHeader(&sCopyHeader) == false) + if(get_client_memptr(wan_client, index)->ipv6_header_set) { - IPACMERR("ioctl copy header failed"); - res = IPACM_FAILURE; - goto fail; + hdr_hdl_sta_v6 = get_client_memptr(wan_client, index)->hdr_hdl_v6; + header_set_v6 = true; + IPACMDBG_H("add full ipv6 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v6); + /* store external_ap's MAC */ + memcpy(ext_router_mac_addr, get_client_memptr(wan_client, index)->mac, sizeof(ext_router_mac_addr)); + } + else + { + IPACMERR(" wan-client got ipv6 however didn't construct complete ipv4 header \n"); + return IPACM_FAILURE; } - if(sCopyHeader.is_eth2_ofst_valid == false) + if(get_client_memptr(wan_client, index)->ipv4_header_set) { - eth2_ofst_v6 = 0; + hdr_hdl_sta_v4 = get_client_memptr(wan_client, index)->hdr_hdl_v4; + header_set_v4 = true; + IPACMDBG_H("add full ipv4 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v4); } else { - eth2_ofst_v6 = sCopyHeader.eth2_ofst; - } - IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); - if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) - { - IPACMERR("header oversize\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - memcpy(pHeaderDescriptor->hdr[0].hdr, - sCopyHeader.hdr, - sCopyHeader.hdr_len); - } - - /* copy client mac_addr to partial header */ - memcpy(&pHeaderDescriptor->hdr[0].hdr[eth2_ofst_v6], mac_addr, - IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */ - pHeaderDescriptor->commit = true; - pHeaderDescriptor->num_hdrs = 1; - - memset(pHeaderDescriptor->hdr[0].name, 0, - sizeof(pHeaderDescriptor->hdr[0].name)); - - snprintf(index,sizeof(index), "%d", ipa_if_num); - strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); - if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) - { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); - res = IPACM_FAILURE; - goto fail; - } - pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; - pHeaderDescriptor->hdr[0].hdr_hdl = -1; - pHeaderDescriptor->hdr[0].is_partial = 0; - pHeaderDescriptor->hdr[0].status = -1; - - if (m_header.AddHeader(pHeaderDescriptor) == false || - pHeaderDescriptor->hdr[0].status != 0) - { - IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); - res = IPACM_FAILURE; - goto fail; - } - else - { - header_set_v6 = true; - hdr_hdl_sta_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; - IPACMDBG_H("add full header name: %s (%x)\n", pHeaderDescriptor->hdr[0].name, pHeaderDescriptor->hdr[0].hdr_hdl); - } - /* copy ipv6 full header to each TX endpoint property*/ - for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) - { - if(tx_prop->tx[tx_index].ip==IPA_IP_v6) - { - memcpy(tx_prop->tx[tx_index].hdr_name, pHeaderDescriptor->hdr[0].name, - sizeof(tx_prop->tx[tx_index].hdr_name)); - IPACMDBG_H("replace full header name: %s (%x) in tx:%d\n", tx_prop->tx[tx_index].hdr_name, pHeaderDescriptor->hdr[0].hdr_hdl,tx_index); - } - } - break; - } + IPACMERR(" wan-client got ipv4 however didn't construct complete ipv4 header \n"); + return IPACM_FAILURE; + } + } + else + { + IPACMDBG_H(" currently can't find matched wan-client's MAC-addr, waiting for header construction\n"); + return IPACM_SUCCESS; + } } - /* see if default routes are setup before constructing full header */ - if(header_partial_default_wan_v4 == true) + /* see if default routes are setup before constructing full header */ + if(header_partial_default_wan_v4 == true) { handle_route_add_evt(IPA_IP_v4); } - if(header_partial_default_wan_v6 == true) + if(header_partial_default_wan_v6 == true) { handle_route_add_evt(IPA_IP_v6); } + return res; +} -fail: - free(pHeaderDescriptor); +/* For checking attribute mask field in firewall rules for IPv6 only */ +bool IPACM_Wan::check_dft_firewall_rules_attr_mask(IPACM_firewall_conf_t *firewall_config) +{ + uint32_t attrib_mask = 0ul; + attrib_mask = IPA_FLT_SRC_PORT_RANGE | + IPA_FLT_DST_PORT_RANGE | + IPA_FLT_TYPE | + IPA_FLT_CODE | + IPA_FLT_SPI | + IPA_FLT_SRC_PORT | + IPA_FLT_DST_PORT; - return res; + for (int i = 0; i < firewall_config->num_extd_firewall_entries; i++) + { + if (firewall_config->extd_firewall_entries[i].ip_vsn == 6) + { + if (firewall_config->extd_firewall_entries[i].attrib.attrib_mask & attrib_mask) + { + IPACMDBG_H("IHL based attribute mask is found: install IPv6 frag firewall rule \n"); + return true; + } + } + } + IPACMDBG_H("IHL based attribute mask is not found: no IPv6 frag firewall rule \n"); + return false; } /* for STA mode: add firewall rules */ @@ -1684,38 +1922,30 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) /* default firewall is disable and the rule action is drop */ memset(&firewall_config, 0, sizeof(firewall_config)); - strncpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file)); + strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file)); - //if (firewall_config.firewall_config_file) - { - IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file); - if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config)) - { - IPACMDBG_H("QCMAP Firewall XML read OK \n"); - /* find the number of v4/v6 firewall rules */ - for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file); + if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config)) { - if (firewall_config.extd_firewall_entries[i].ip_vsn == 4) + IPACMDBG_H("QCMAP Firewall XML read OK \n"); + /* find the number of v4/v6 firewall rules */ + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) { - rule_v4++; - } - else - { - rule_v6++; - } - } - IPACMDBG_H("firewall rule v4:%d v6:%d total:%d\n", rule_v4, rule_v6, firewall_config.num_extd_firewall_entries); - } - else - { - IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n"); + if (firewall_config.extd_firewall_entries[i].ip_vsn == 4) + { + rule_v4++; + } + else + { + rule_v6++; + } } + IPACMDBG_H("firewall rule v4:%d v6:%d total:%d\n", rule_v4, rule_v6, firewall_config.num_extd_firewall_entries); } - /*else + else { - IPACMERR("No firewall xml mentioned \n"); - return IPACM_FAILURE; - }*/ + IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n"); + } /* construct ipa_ioc_add_flt_rule with N firewall rules */ ipa_ioc_add_flt_rule *m_pFilteringTable = NULL; @@ -1727,7 +1957,9 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) return IPACM_FAILURE; } - if(iptype == IPA_IP_v6 && firewall_config.firewall_enable == true) + if(iptype == IPA_IP_v6 && + firewall_config.firewall_enable == true && + check_dft_firewall_rules_attr_mask(&firewall_config)) { m_pFilteringTable->commit = 1; m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; @@ -1737,13 +1969,15 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); flt_rule_entry.at_rear = true; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = false; + flt_rule_entry.rule.hashable = false; +#endif flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(struct ipa_rule_attrib)); - flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; - flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_FRAG_HDR; - + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) { @@ -1753,7 +1987,9 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); ipv6_frag_firewall_flt_rule_hdl = m_pFilteringTable->rules[0].flt_rule_hdl; + is_ipv6_frag_firewall_flt_rule_installed = true; IPACMDBG_H("Installed IPv6 frag firewall rule, handle %d.\n", ipv6_frag_firewall_flt_rule_hdl); } } @@ -1783,26 +2019,43 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.status = -1; /* firewall disable, all traffic are allowed */ - if(firewall_config.firewall_enable == true) + if(firewall_config.firewall_enable == true) { - flt_rule_entry.at_rear = true; + flt_rule_entry.at_rear = true; - /* default action for v4 is go DST_NAT unless user set to exception*/ - if(firewall_config.rule_action_accept == true) - { - flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; - } - else - { - flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; - } - } + /* default action for v4 is go DST_NAT unless user set to exception*/ + if(firewall_config.rule_action_accept == true) + { + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + } + else + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } + } else { - flt_rule_entry.at_rear = true; - flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; - } - + flt_rule_entry.at_rear = true; + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl; memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, @@ -1821,6 +2074,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); } @@ -1862,15 +2116,24 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl; /* Accept v4 matched rules*/ - if(firewall_config.rule_action_accept == true) - { - flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; - } - else - { - flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; - } - + if(firewall_config.rule_action_accept == true) + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + } +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memcpy(&flt_rule_entry.rule.attrib, &firewall_config.extd_firewall_entries[i].attrib, sizeof(struct ipa_rule_attrib)); @@ -1898,6 +2161,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); /* save v4 firewall filter rule handler */ IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[rule_v4].flt_rule_hdl, @@ -1921,6 +2185,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); /* save v4 firewall filter rule handler */ IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[rule_v4].flt_rule_hdl, @@ -1944,6 +2209,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); /* save v4 firewall filter rule handler */ IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[rule_v4].flt_rule_hdl, @@ -1963,7 +2229,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.status = -1; /* firewall disable, all traffic are allowed */ - if(firewall_config.firewall_enable == true) + if(firewall_config.firewall_enable == true) { flt_rule_entry.at_rear = true; @@ -1974,20 +2240,36 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { - flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; - } - } + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } + } else { flt_rule_entry.at_rear = true; - flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; - } - - flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl; - memcpy(&flt_rule_entry.rule.attrib, - &rx_prop->rx[0].attrib, - sizeof(struct ipa_rule_attrib)); - flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl; + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; @@ -2003,6 +2285,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); } @@ -2031,6 +2314,9 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.rule.retain_hdr = 1; flt_rule_entry.rule.eq_attrib_type = 0; flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(struct ipa_rule_attrib)); @@ -2046,6 +2332,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); } /* copy filter hdls */ @@ -2086,7 +2373,9 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.at_rear = true; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; } - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(struct ipa_rule_attrib)); @@ -2110,6 +2399,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); } @@ -2155,7 +2445,9 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) { flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; } - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl; memcpy(&flt_rule_entry.rule.attrib, &firewall_config.extd_firewall_entries[i].attrib, @@ -2178,6 +2470,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); /* save v4 firewall filter rule handler */ IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl; @@ -2196,6 +2489,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); /* save v6 firewall filter rule handler */ IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl; @@ -2205,7 +2499,6 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { - memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) { @@ -2215,6 +2508,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); /* save v6 firewall filter rule handler */ IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl; @@ -2234,6 +2528,9 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.rule.retain_hdr = 1; flt_rule_entry.rule.eq_attrib_type = 0; flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(struct ipa_rule_attrib)); @@ -2249,6 +2546,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); } /* copy filter hdls */ @@ -2282,7 +2580,9 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.at_rear = true; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; } - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(struct ipa_rule_attrib)); @@ -2306,6 +2606,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) } else { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); } /* copy filter hdls*/ @@ -2346,32 +2647,28 @@ int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int /* default firewall is disable and the rule action is drop */ memset(&firewall_config, 0, sizeof(firewall_config)); - strncpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file)); + strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file)); - //if (firewall_config.firewall_config_file) + IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file); + if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config)) { - IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file); - if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config)) - { - IPACMDBG_H("QCMAP Firewall XML read OK \n"); - } - else - { - IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n"); - } + IPACMDBG_H("QCMAP Firewall XML read OK \n"); + } + else + { + IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n"); } - /*else - //{ - IPACMERR("No firewall xml mentioned \n"); - return IPACM_FAILURE; - }*/ /* add IPv6 frag rule when firewall is enabled*/ - if(iptype == IPA_IP_v6 && firewall_config.firewall_enable == true) + if(iptype == IPA_IP_v6 && + firewall_config.firewall_enable == true && + check_dft_firewall_rules_attr_mask(&firewall_config)) { memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); - flt_rule_entry.at_rear = true; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = false; +#endif flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; @@ -2379,10 +2676,14 @@ int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = false; + flt_rule_entry.rule.hashable = false; +#endif memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); rt_tbl_idx.ip = IPA_IP_v6; - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { IPACMERR("Failed to get routing table index from name\n"); @@ -2395,8 +2696,7 @@ int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask; flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data; - flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; - flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_FRAG_HDR; + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); @@ -2445,18 +2745,20 @@ int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int { flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; } - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); rt_tbl_idx.ip = iptype; if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING) { - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); } else /*pass to dst nat*/ { - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX); } - + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { IPACMERR("Failed to get routing table index from name\n"); @@ -2570,20 +2872,31 @@ int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int } else { - flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + if(isWan_Bridge_Mode()) + { + IPACMDBG_H("ODU is in bridge mode. \n"); + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } } - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); rt_tbl_idx.ip = iptype; if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING) { - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); } else /*pass to dst nat*/ { - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX); } + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { @@ -2644,19 +2957,23 @@ int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); rt_tbl_idx.ip = iptype; /* matched rules for v6 go PASS_TO_ROUTE */ if(firewall_config.rule_action_accept == true) { - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); } else { - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); } + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { IPACMERR("Failed to get routing table index from name\n"); @@ -2753,7 +3070,9 @@ int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; - +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); rt_tbl_idx.ip = iptype; /* firewall disable, all traffic are allowed */ @@ -2762,17 +3081,18 @@ int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/ if(firewall_config.rule_action_accept == true) { - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); } else { - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); } } else { - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); } + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { IPACMERR("Failed to get routing table index from name\n"); @@ -2827,52 +3147,12 @@ int IPACM_Wan::init_fl_rule_ex(ipa_ip_type iptype) char *dev_wlan1="wlan1"; char *dev_ecm0="ecm0"; - /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/ - if (iptype == IPA_IP_v4) - { - - if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX)) - { - IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); - return res; - } - - if (ip_type == IPA_IP_v6) - { - ip_type = IPA_IP_MAX; - } - else - { - ip_type = IPA_IP_v4; - } - IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); - } - else - { - if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX)) - { - IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); - return res; - } - - if (ip_type == IPA_IP_v4) - { - ip_type = IPA_IP_MAX; - } - else - { - ip_type = IPA_IP_v6; - } - - IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); - } - /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */ IPACMDBG_H(" dun add producer dependency from %s with registered rx-prop\n", dev_name); if(iptype == IPA_IP_v4) { - if(modem_ipv4_pdn_index == 0) //install ipv4 default modem DL filtering rules only once + if(modem_ipv4_pdn_index == 0) /* install ipv4 default modem DL filtering rules only once */ { /* reset the num_v4_flt_rule*/ IPACM_Wan::num_v4_flt_rule = 0; @@ -2881,7 +3161,7 @@ int IPACM_Wan::init_fl_rule_ex(ipa_ip_type iptype) } else if(iptype == IPA_IP_v6) { - if(modem_ipv6_pdn_index == 0) //install ipv6 default modem DL filtering rules only once + if(modem_ipv6_pdn_index == 0) /* install ipv6 default modem DL filtering rules only once */ { /* reset the num_v6_flt_rule*/ IPACM_Wan::num_v6_flt_rule = 0; @@ -2919,7 +3199,8 @@ int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offse original_num_rules = IPACM_Wan::num_v4_flt_rule; memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; rt_tbl_idx.ip = iptype; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { @@ -2940,14 +3221,16 @@ int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offse flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; /* Configuring ICMP filtering rule */ memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); - /* remove meta data mask */ - flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + /* Multiple PDNs may exist so keep meta-data */ flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP; @@ -2970,11 +3253,10 @@ int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offse IPACM_Wan::num_v4_flt_rule++; /* Configure ALG filtering rules */ + /* maintain meta data mask */ memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); - /* remove meta data mask */ - flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_PORT; flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++) @@ -2998,11 +3280,10 @@ int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offse IPACM_Wan::num_v4_flt_rule++; } + /* maintain meta data mask */ memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); - /* remove meta data mask */ - flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_PORT; flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++) @@ -3036,7 +3317,8 @@ int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offse original_num_rules = IPACM_Wan::num_v6_flt_rule; memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; rt_tbl_idx.ip = iptype; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { @@ -3057,14 +3339,16 @@ int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offse flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; /* Configuring ICMP filtering rule */ memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[1].attrib, sizeof(flt_rule_entry.rule.attrib)); - /* remove meta data mask */ - flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + /* Multiple PDNs may exist so keep meta-data */ flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; @@ -3131,12 +3415,20 @@ int IPACM_Wan::query_ext_prop() return ret; } - IPACMDBG_H("Wan interface has %d tx props, %d rx props and %d ext props\n", iface_query->num_tx_props, iface_query->num_rx_props, iface_query->num_ext_props); + IPACMDBG_H("Wan interface has %d tx props, %d rx props and %d ext props\n", + iface_query->num_tx_props, iface_query->num_rx_props, iface_query->num_ext_props); for (cnt = 0; cnt < ext_prop->num_ext_props; cnt++) { - IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, flt_hdr: %d \n", - cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action, ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].filter_hdl); +#ifndef FEATURE_IPA_V3 + IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d flt_hdl: %d\n", + cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action, + ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].filter_hdl); +#else /* defined (FEATURE_IPA_V3) */ + IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d rule_id: %d\n", + cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action, + ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].rule_id); +#endif } if(IPACM_Wan::is_ext_prop_set == false) @@ -3224,7 +3516,8 @@ int IPACM_Wan::add_dft_filtering_rule(struct ipa_flt_rule_add *rules, int rule_o if (iptype == IPA_IP_v4) { memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; rt_tbl_idx.ip = iptype; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { @@ -3245,6 +3538,9 @@ int IPACM_Wan::add_dft_filtering_rule(struct ipa_flt_rule_add *rules, int rule_o flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); @@ -3303,7 +3599,8 @@ int IPACM_Wan::add_dft_filtering_rule(struct ipa_flt_rule_add *rules, int rule_o else /*insert rules for ipv6*/ { memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; rt_tbl_idx.ip = iptype; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { @@ -3324,6 +3621,9 @@ int IPACM_Wan::add_dft_filtering_rule(struct ipa_flt_rule_add *rules, int rule_o flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; /* Configuring Multicast Filtering Rule */ @@ -3511,6 +3811,7 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) IPACMERR("Error Deleting Filtering rules, aborting...\n"); return IPACM_FAILURE; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, num_firewall_v4); } else { @@ -3523,6 +3824,7 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) IPACMERR("Error Deleting Filtering rules, aborting...\n"); return IPACM_FAILURE; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); num_firewall_v4 = 0; } @@ -3543,6 +3845,7 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) IPACMERR("Error Deleting Filtering rules, aborting...\n"); return IPACM_FAILURE; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_firewall_v6); } else { @@ -3555,15 +3858,25 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) IPACMERR("Error Deleting Filtering rules, aborting...\n"); return IPACM_FAILURE; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[2], IPA_IP_v6, 1) == false) { IPACMERR("Error Deleting Filtering rules, aborting...\n"); return IPACM_FAILURE; } - if (m_filtering.DeleteFilteringHdls(&ipv6_frag_firewall_flt_rule_hdl, IPA_IP_v6, 1) == false) + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + + if (is_ipv6_frag_firewall_flt_rule_installed && + check_dft_firewall_rules_attr_mask(&firewall_config)) { - IPACMERR("Error deleting IPv6 frag filtering rules.\n"); + if (m_filtering.DeleteFilteringHdls(&ipv6_frag_firewall_flt_rule_hdl, IPA_IP_v6, 1) == false) + { + IPACMERR("Error deleting IPv6 frag filtering rules.\n"); + return IPACM_FAILURE; + } + is_ipv6_frag_firewall_flt_rule_installed = false; + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); } num_firewall_v6 = 0; } @@ -3577,7 +3890,7 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) uint32_t tx_index; ipacm_cmd_q_data evt_data; - IPACMDBG_H("got handle_route_del_evt with ip-family:%d \n", iptype); + IPACMDBG_H("got handle_route_del_evt for STA-mode with ip-family:%d \n", iptype); if(tx_prop == NULL) { @@ -3851,7 +4164,8 @@ int IPACM_Wan::config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, /* get eMBMS ODU tbl index*/ memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v4.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v4.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; rt_tbl_idx.ip = IPA_IP_v4; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { @@ -3869,6 +4183,9 @@ int IPACM_Wan::config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; memcpy(&flt_rule_entry.rule.attrib, @@ -3896,7 +4213,8 @@ int IPACM_Wan::config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); /* get eMBMS ODU tbl*/ memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v6.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v6.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; rt_tbl_idx.ip = IPA_IP_v6; if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) { @@ -3914,6 +4232,9 @@ int IPACM_Wan::config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, flt_rule_entry.rule.to_uc = 0; flt_rule_entry.rule.eq_attrib_type = 1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; memcpy(&flt_rule_entry.rule.attrib, @@ -4079,31 +4400,38 @@ int IPACM_Wan::handle_down_evt() handle_software_routing_disable(); } - /* free filter rule handlers */ + /* free dft ipv4 filter rule handlers if any */ if (ip_type != IPA_IP_v6 && rx_prop != NULL) { - if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, - IPA_IP_v4, - IPV4_DEFAULT_FILTERTING_RULES) == false) + if (dft_v4fl_rule_hdl[0] != 0) { - IPACMERR("Error Delete Filtering rules, aborting...\n"); - res = IPACM_FAILURE; - goto fail; + if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, + IPA_IP_v4, + IPV4_DEFAULT_FILTERTING_RULES) == false) + { + IPACMERR("Error Delete Filtering rules, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES); + IPACMDBG_H("finished delete default v4 filtering rules\n "); } - - IPACMDBG_H("finished delete default v4 filtering rules\n "); } - + /* free dft ipv6 filter rule handlers if any */ if (ip_type != IPA_IP_v4 && rx_prop != NULL) { - if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, - IPA_IP_v6, - IPV6_DEFAULT_FILTERTING_RULES) == false) + if (dft_v6fl_rule_hdl[0] != 0) { - IPACMERR("ErrorDeleting Filtering rule, aborting...\n"); - res = IPACM_FAILURE; - goto fail; + if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, + IPA_IP_v6, + IPV6_DEFAULT_FILTERTING_RULES) == false) + { + IPACMERR("ErrorDeleting Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES); } if(num_ipv6_dest_flt_rule > 0 && num_ipv6_dest_flt_rule <= MAX_DEFAULT_v6_ROUTE_RULES) @@ -4114,28 +4442,28 @@ int IPACM_Wan::handle_down_evt() res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_ipv6_dest_flt_rule); } IPACMDBG_H("finished delete default v6 filtering rules\n "); } - - /* delete the complete header for STA mode*/ - if((header_set_v4 == true) || (header_set_v6 == true)) - { - if (m_header.DeleteHeaderHdl(hdr_hdl_sta_v4) == false) + if(hdr_proc_hdl_dummy_v6) + { + if(m_header.DeleteHeaderProcCtx(hdr_proc_hdl_dummy_v6) == false) { - IPACMERR("ErrorDeleting STA header for v4, aborting...\n"); - res = IPACM_FAILURE; - goto fail; + IPACMERR("Failed to delete hdr_proc_hdl_dummy_v6\n"); + res = IPACM_FAILURE; + goto fail; } - - if (m_header.DeleteHeaderHdl(hdr_hdl_sta_v6) == false) + } + if(hdr_hdl_dummy_v6) + { + if (m_header.DeleteHeaderHdl(hdr_hdl_dummy_v6) == false) { - IPACMERR("ErrorDeleting STA header for v6, aborting...\n"); + IPACMERR("Failed to delete hdr_hdl_dummy_v6\n"); res = IPACM_FAILURE; goto fail; } } - fail: if (tx_prop != NULL) { @@ -4177,12 +4505,6 @@ int IPACM_Wan::handle_down_evt_ex() IPACMDBG_H(" wan handle_down_evt \n"); - /* no iface address up, directly close iface*/ - if (ip_type == IPACM_IP_NULL) - { - goto fail; - } - /* free ODU filter rule handlers */ if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == EMBMS_IF) { @@ -4203,6 +4525,12 @@ int IPACM_Wan::handle_down_evt_ex() goto fail; } + /* no iface address up, directly close iface*/ + if (ip_type == IPACM_IP_NULL) + { + goto fail; + } + if(ip_type == IPA_IP_v4) { num_ipv4_modem_pdn--; @@ -4266,7 +4594,7 @@ int IPACM_Wan::handle_down_evt_ex() del_wan_firewall_rule(IPA_IP_v6); install_wan_filtering_rule(false); handle_route_del_evt_ex(IPA_IP_v6); -#ifdef FEATURE_IPA_ANDROID //sky +#ifdef FEATURE_IPA_ANDROID /* posting wan_down_tether for all lan clients */ for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++) { @@ -4399,24 +4727,6 @@ int IPACM_Wan::handle_down_evt_ex() handle_software_routing_disable(); } - /* delete the complete header for STA mode*/ - if((header_set_v4 == true) || (header_set_v6 == true)) - { - if (m_header.DeleteHeaderHdl(hdr_hdl_sta_v4) == false) - { - IPACMERR("ErrorDeleting STA header for v4, aborting...\n"); - res = IPACM_FAILURE; - goto fail; - } - - if (m_header.DeleteHeaderHdl(hdr_hdl_sta_v6) == false) - { - IPACMERR("ErrorDeleting STA header for v6, aborting...\n"); - res = IPACM_FAILURE; - goto fail; - } - } - fail: if (tx_prop != NULL) { @@ -4502,7 +4812,8 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) /* Configuring Software-Routing Filtering Rule */ memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; rt_tbl_idx.ip = IPA_IP_v4; if(ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx) < 0) { @@ -4516,6 +4827,10 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; memcpy(&flt_rule_entry.rule.attrib, @@ -4531,7 +4846,8 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) { IPACMERR("Failed to get eq_attrib\n"); - return IPACM_FAILURE; + res = IPACM_FAILURE; + goto fail; } memcpy(&flt_rule_entry.rule.eq_attrib, &flt_eq.eq_attrib, @@ -4558,13 +4874,14 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) /* Configuring Software-Routing Filtering Rule */ memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); - strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; rt_tbl_idx.ip = IPA_IP_v6; if(ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx) < 0) { IPACMERR("Failed to get routing table index from name\n"); - free(pFilteringTable_v4); - return IPACM_FAILURE; + res = IPACM_FAILURE; + goto fail; } IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); @@ -4572,6 +4889,9 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) flt_rule_entry.flt_rule_hdl = -1; flt_rule_entry.status = -1; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, @@ -4586,7 +4906,8 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) { IPACMERR("Failed to get eq_attrib\n"); - return IPACM_FAILURE; + res = IPACM_FAILURE; + goto fail; } memcpy(&flt_rule_entry.rule.eq_attrib, &flt_eq.eq_attrib, @@ -4611,6 +4932,7 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); return IPACM_FAILURE; } + memset(pFilteringTable_v4, 0, len); pFilteringTable_v4->commit = 1; pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe; pFilteringTable_v4->global = false; @@ -4633,6 +4955,7 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) free(pFilteringTable_v4); return IPACM_FAILURE; } + memset(pFilteringTable_v6, 0, len); pFilteringTable_v6->commit = 1; pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe; pFilteringTable_v6->global = false; @@ -4653,6 +4976,7 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); return IPACM_FAILURE; } + memset(pFilteringTable_v4, 0, len); pFilteringTable_v4->commit = 1; pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe; pFilteringTable_v4->global = false; @@ -4669,6 +4993,7 @@ int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) free(pFilteringTable_v4); return IPACM_FAILURE; } + memset(pFilteringTable_v6, 0, len); pFilteringTable_v6->commit = 1; pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe; pFilteringTable_v6->global = false; @@ -4793,7 +5118,6 @@ int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) mac_addr, sizeof(get_client_memptr(wan_client, num_wan_client)->mac)); - IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); @@ -4854,7 +5178,19 @@ int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) /* copy client mac_addr to partial header */ IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst); - memcpy(&pHeaderDescriptor->hdr[0].hdr[eth2_ofst_v4], mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */ + + /* only copy 6 bytes mac-address */ + if(sCopyHeader.is_eth2_ofst_valid == false) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[0], + mac_addr, IPA_MAC_ADDR_SIZE); + } + else + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + mac_addr, IPA_MAC_ADDR_SIZE); + } + pHeaderDescriptor->commit = true; pHeaderDescriptor->num_hdrs = 1; @@ -4864,7 +5200,7 @@ int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) snprintf(index,sizeof(index), "%d", ipa_if_num); strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); - + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) { IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); @@ -4937,11 +5273,21 @@ int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) { memcpy(pHeaderDescriptor->hdr[0].hdr, sCopyHeader.hdr, - sCopyHeader.hdr_len); + sCopyHeader.hdr_len); } /* copy client mac_addr to partial header */ - memcpy(&pHeaderDescriptor->hdr[0].hdr[eth2_ofst_v6], mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */ + if(sCopyHeader.is_eth2_ofst_valid == false) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[0], + mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */ + } + else + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */ + } + pHeaderDescriptor->commit = true; pHeaderDescriptor->num_hdrs = 1; @@ -4951,7 +5297,7 @@ int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) snprintf(index,sizeof(index), "%d", ipa_if_num); strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); - + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) { IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); @@ -5129,8 +5475,8 @@ int IPACM_Wan::handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp } IPACMDBG_H("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - mac_addr[0], mac_addr[1], mac_addr[2], - mac_addr[3], mac_addr[4], mac_addr[5]); + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); wan_index = get_wan_client_index(mac_addr); if (wan_index == IPACM_INVALID_INDEX) @@ -5141,31 +5487,31 @@ int IPACM_Wan::handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp if (iptype==IPA_IP_v4) { IPACMDBG_H("wan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", wan_index, iptype, - get_client_memptr(wan_client, wan_index)->ipv4_set, - get_client_memptr(wan_client, wan_index)->route_rule_set_v4); + get_client_memptr(wan_client, wan_index)->ipv4_set, + get_client_memptr(wan_client, wan_index)->route_rule_set_v4); } else { IPACMDBG_H("wan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wan_index, iptype, - get_client_memptr(wan_client, wan_index)->ipv6_set, - get_client_memptr(wan_client, wan_index)->route_rule_set_v6); + get_client_memptr(wan_client, wan_index)->ipv6_set, + get_client_memptr(wan_client, wan_index)->route_rule_set_v6); } /* Add default routing rules if not set yet */ if ((iptype == IPA_IP_v4 - && get_client_memptr(wan_client, wan_index)->route_rule_set_v4 == false - && get_client_memptr(wan_client, wan_index)->ipv4_set == true) + && get_client_memptr(wan_client, wan_index)->route_rule_set_v4 == false + && get_client_memptr(wan_client, wan_index)->ipv4_set == true) || (iptype == IPA_IP_v6 - && get_client_memptr(wan_client, wan_index)->route_rule_set_v6 < get_client_memptr(wan_client, wan_index)->ipv6_set - )) + && get_client_memptr(wan_client, wan_index)->route_rule_set_v6 < get_client_memptr(wan_client, wan_index)->ipv6_set + )) { - /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */ + /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */ IPACMDBG_H("dev %s add producer dependency\n", dev_name); IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); rt_rule = (struct ipa_ioc_add_rt_rule *) - calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + - NUM * sizeof(struct ipa_rt_rule_add)); + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_add)); if (rt_rule == NULL) { @@ -5180,118 +5526,139 @@ int IPACM_Wan::handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) { if(iptype != tx_prop->tx[tx_index].ip) - { + { IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", tx_index, tx_prop->tx[tx_index].ip,iptype); - continue; - } + continue; + } rt_rule_entry = &rt_rule->rules[0]; rt_rule_entry->at_rear = 0; if (iptype == IPA_IP_v4) { - IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wan_index, - get_client_memptr(wan_client, wan_index)->v4_addr); + IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wan_index, + get_client_memptr(wan_client, wan_index)->v4_addr); - IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", - wan_index, - get_client_memptr(wan_client, wan_index)->hdr_hdl_v4); - strncpy(rt_rule->rt_tbl_name, - IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name, - sizeof(rt_rule->rt_tbl_name)); - - rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; - memcpy(&rt_rule_entry->rule.attrib, - &tx_prop->tx[tx_index].attrib, - sizeof(rt_rule_entry->rule.attrib)); - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v4; + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + wan_index, + get_client_memptr(wan_client, wan_index)->hdr_hdl_v4); + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v4; rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, wan_index)->v4_addr; rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; - - if (false == m_routing.AddRoutingRule(rt_rule)) +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) { IPACMERR("Routing rule addition failed!\n"); free(rt_rule); return IPACM_FAILURE; } - /* copy ipv4 RT hdl */ + /* copy ipv4 RT hdl */ get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4 = - rt_rule->rules[0].rt_rule_hdl; - IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, - get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4, iptype); - } else { - - for(v6_num = get_client_memptr(wan_client, wan_index)->route_rule_set_v6;v6_num < get_client_memptr(wan_client, wan_index)->ipv6_set;v6_num++) - { - IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", - wan_index, - get_client_memptr(wan_client, wan_index)->hdr_hdl_v6); - - /* v6 LAN_RT_TBL */ - strncpy(rt_rule->rt_tbl_name, - IPACM_Iface::ipacmcfg->rt_tbl_v6.name, - sizeof(rt_rule->rt_tbl_name)); - - /* Support QCMAP LAN traffic feature, send to A5 */ - rt_rule_entry->rule.dst = iface_query->excp_pipe; - memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib)); - rt_rule_entry->rule.hdr_hdl = 0; - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3]; + rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4, iptype); + } else { + + for(v6_num = get_client_memptr(wan_client, wan_index)->route_rule_set_v6;v6_num < get_client_memptr(wan_client, wan_index)->ipv6_set;v6_num++) + { + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + wan_index, + get_client_memptr(wan_client, wan_index)->hdr_hdl_v6); + + /* v6 LAN_RT_TBL */ + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_v6.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Uplink going to wan clients should go to IPA */ + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v6;; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3]; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; - +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) { - IPACMERR("Routing rule addition failed!\n"); - free(rt_rule); - return IPACM_FAILURE; + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; } - get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl; - IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, - get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num], iptype); - - /*Copy same rule to v6 WAN RT TBL*/ - strncpy(rt_rule->rt_tbl_name, - IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, - sizeof(rt_rule->rt_tbl_name)); - - /* Downlink traffic from Wan iface, directly through IPA */ - rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; - memcpy(&rt_rule_entry->rule.attrib, - &tx_prop->tx[tx_index].attrib, - sizeof(rt_rule_entry->rule.attrib)); - rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v6; - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3]; + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num], iptype); + + /*Copy same rule to v6 WAN RT TBL*/ + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Downlink traffic from Wan clients, should go exception */ + rt_rule_entry->rule.dst = iface_query->excp_pipe; + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = 0; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3]; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } - if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - free(rt_rule); - return IPACM_FAILURE; - } - - get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl; + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl; IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, - get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num], iptype); - } + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num], iptype); + } } } /* end of for loop */ @@ -5311,6 +5678,298 @@ int IPACM_Wan::handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp return IPACM_SUCCESS; } +/* TODO Handle wan client routing rules also */ +void IPACM_Wan::handle_wlan_SCC_MCC_switch(bool isSCCMode, ipa_ip_type iptype) +{ + struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_mdfy *rt_rule_entry; + uint32_t tx_index = 0; + + IPACMDBG("\n"); + if (tx_prop == NULL || is_default_gateway == false) + { + IPACMDBG_H("No tx properties or no default route set yet\n"); + return; + } + + const int NUM = tx_prop->num_tx_props; + + for (tx_index = 0; tx_index < tx_prop->num_tx_props; tx_index++) + { + if (tx_prop->tx[tx_index].ip != iptype) + { + IPACMDBG_H("Tx:%d, ip-type: %d ip-type not matching: %d Ignore\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + if (rt_rule == NULL) + { + rt_rule = (struct ipa_ioc_mdfy_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_mdfy_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_mdfy)); + + if (rt_rule == NULL) + { + IPACMERR("Unable to allocate memory for modify rt rule\n"); + return; + } + IPACMDBG("Allocated memory for %d rules successfully\n", NUM); + + rt_rule->commit = 1; + rt_rule->num_rules = 0; + rt_rule->ip = iptype; + } + + rt_rule_entry = &rt_rule->rules[rt_rule->num_rules]; + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + + if (iptype == IPA_IP_v4) + { + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0; + rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v4; + rt_rule_entry->rt_rule_hdl = wan_route_rule_v4_hdl[tx_index]; + } + else + { + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0; + + rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v6; + rt_rule_entry->rt_rule_hdl = wan_route_rule_v6_hdl[tx_index]; + } + IPACMDBG_H("Header handle: 0x%x\n", rt_rule_entry->rule.hdr_hdl); + + if (isSCCMode) + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + else + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + + rt_rule->num_rules++; + } + + if (rt_rule != NULL) + { + + if (rt_rule->num_rules > 0) + { + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; + } + + IPACMDBG("Routing rule modified successfully \n"); + } + + free(rt_rule); + } + + return; +} + +void IPACM_Wan::handle_wan_client_SCC_MCC_switch(bool isSCCMode, ipa_ip_type iptype) +{ + struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_mdfy *rt_rule_entry; + + uint32_t tx_index = 0, clnt_index =0; + int v6_num = 0; + const int NUM_RULES = 1; + + int size = sizeof(struct ipa_ioc_mdfy_rt_rule) + + NUM_RULES * sizeof(struct ipa_rt_rule_mdfy); + + IPACMDBG("\n"); + + if (tx_prop == NULL || is_default_gateway == false) + { + IPACMDBG_H("No tx properties or no default route set yet\n"); + return; + } + + rt_rule = (struct ipa_ioc_mdfy_rt_rule *)calloc(1, size); + if (rt_rule == NULL) + { + IPACMERR("Unable to allocate memory for modify rt rule\n"); + return; + } + + + for (clnt_index = 0; clnt_index < num_wan_client; clnt_index++) + { + if (iptype == IPA_IP_v4) + { + IPACMDBG_H("wan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", + clnt_index, iptype, + get_client_memptr(wan_client, clnt_index)->ipv4_set, + get_client_memptr(wan_client, clnt_index)->route_rule_set_v4); + + if( get_client_memptr(wan_client, clnt_index)->route_rule_set_v4 == false || + get_client_memptr(wan_client, clnt_index)->ipv4_set == false) + { + continue; + } + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if (iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d skip\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + memset(rt_rule, 0, size); + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = iptype; + rt_rule_entry = &rt_rule->rules[0]; + + IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", clnt_index, + get_client_memptr(wan_client, clnt_index)->v4_addr); + + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + clnt_index, + get_client_memptr(wan_client, clnt_index)->hdr_hdl_v4); + + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, clnt_index)->hdr_hdl_v4; + rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, clnt_index)->v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + /* copy ipv4 RT rule hdl */ + IPACMDBG_H("rt rule hdl=%x\n", + get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4); + + rt_rule_entry->rt_rule_hdl = + get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4; + + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; + } + } + } + else + { + IPACMDBG_H("wan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", clnt_index, iptype, + get_client_memptr(wan_client, clnt_index)->ipv6_set, + get_client_memptr(wan_client, clnt_index)->route_rule_set_v6); + + if( get_client_memptr(wan_client, clnt_index)->route_rule_set_v6 == 0) + { + continue; + } + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if (iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d skip\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + memset(rt_rule, 0, size); + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = iptype; + rt_rule_entry = &rt_rule->rules[0]; + + /* Modify only rules in v6 WAN RT TBL*/ + for (v6_num = 0; + v6_num < get_client_memptr(wan_client, clnt_index)->route_rule_set_v6; + v6_num++) + { + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + clnt_index, + get_client_memptr(wan_client, clnt_index)->hdr_hdl_v6); + + /* Downlink traffic from Wan iface, directly through IPA */ + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, clnt_index)->hdr_hdl_v6; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + IPACMDBG_H("rt rule hdl=%x\n", + get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num]); + + rt_rule_entry->rt_rule_hdl = + get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num]; + + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule Modify failed!\n"); + free(rt_rule); + return; + } + } + } /* end of for loop */ + } + + } + + free(rt_rule); + return; +} + /*handle eth client */ int IPACM_Wan::handle_network_stats_update(ipa_get_apn_data_stats_resp_msg_v01 *data) { @@ -5346,3 +6005,138 @@ int IPACM_Wan::handle_network_stats_update(ipa_get_apn_data_stats_resp_msg_v01 * } return IPACM_SUCCESS; } + +int IPACM_Wan::add_dummy_rx_hdr() +{ + +#define IFACE_INDEX_LEN 2 + char index[IFACE_INDEX_LEN]; + struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; + int len = 0; + struct ipa_ioc_copy_hdr sCopyHeader; + struct ipa_hdr_add *ipv6_hdr; + struct ethhdr *eth_ipv6; + struct ipa_ioc_add_hdr_proc_ctx* pHeaderProcTable = NULL; + uint32_t cnt; + + /* get netdev-mac */ + if(tx_prop != NULL) + { + /* copy partial header for v6 */ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v6) + { + IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + PERROR("ioctl copy header failed"); + return IPACM_FAILURE; + } + + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("header oversize\n"); + return IPACM_FAILURE; + } + else + { + /* copy client mac_addr to partial header */ + IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", + sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst); + /* only copy 6 bytes mac-address */ + if(sCopyHeader.is_eth2_ofst_valid == false) + { + memcpy(netdev_mac, &sCopyHeader.hdr[0+IPA_MAC_ADDR_SIZE], + sizeof(netdev_mac)); + } + else + { + memcpy(netdev_mac, &sCopyHeader.hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], + sizeof(netdev_mac)); + } + } + break; + } + } + } + + len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add)); + pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len); + if (pHeaderDescriptor == NULL) + { + IPACMERR("calloc failed to allocate pHeaderDescriptor\n"); + return IPACM_FAILURE; + } + ipv6_hdr = &pHeaderDescriptor->hdr[0]; + /* copy ethernet type to header */ + eth_ipv6 = (struct ethhdr *) (ipv6_hdr->hdr +2); + memcpy(eth_ipv6->h_dest, netdev_mac, ETH_ALEN); + memcpy(eth_ipv6->h_source, ext_router_mac_addr, ETH_ALEN); + eth_ipv6->h_proto = htons(ETH_P_IPV6); + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + + memset(ipv6_hdr->name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + + snprintf(index,sizeof(index), "%d", ipa_if_num); + strlcpy(ipv6_hdr->name, index, sizeof(ipv6_hdr->name)); + ipv6_hdr->name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + + if (strlcat(ipv6_hdr->name, IPA_DUMMY_ETH_HDR_NAME_v6, sizeof(ipv6_hdr->name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(ipv6_hdr->name)); + return IPACM_FAILURE; + } + + ipv6_hdr->hdr_len = ETH_HLEN + 2; + ipv6_hdr->hdr_hdl = -1; + ipv6_hdr->is_partial = 0; + ipv6_hdr->status = -1; + ipv6_hdr->type = IPA_HDR_L2_ETHERNET_II; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + ipv6_hdr->status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", ipv6_hdr->status); + return IPACM_FAILURE; + } + + hdr_hdl_dummy_v6 = ipv6_hdr->hdr_hdl; + IPACMDBG_H("dummy v6 full header name:%s header handle:(0x%x)\n", + ipv6_hdr->name, + hdr_hdl_dummy_v6); + /* add dummy hdr_proc_hdl */ + len = sizeof(struct ipa_ioc_add_hdr_proc_ctx) + sizeof(struct ipa_hdr_proc_ctx_add); + pHeaderProcTable = (ipa_ioc_add_hdr_proc_ctx*)malloc(len); + if(pHeaderProcTable == NULL) + { + IPACMERR("Cannot allocate header processing table.\n"); + return IPACM_FAILURE; + } + + memset(pHeaderProcTable, 0, len); + pHeaderProcTable->commit = 1; + pHeaderProcTable->num_proc_ctxs = 1; + pHeaderProcTable->proc_ctx[0].hdr_hdl = hdr_hdl_dummy_v6; + if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) + { + IPACMERR("Adding dummy hhdr_proc_hdl failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); + return IPACM_FAILURE; + } + else + { + hdr_proc_hdl_dummy_v6 = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; + IPACMDBG_H("dummy hhdr_proc_hdl is added successfully. (0x%x)\n", hdr_proc_hdl_dummy_v6); + } + return IPACM_SUCCESS; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Wlan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wlan.cpp index 3f2d1a26..4923199e 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Wlan.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wlan.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -54,16 +54,8 @@ Skylar Chang /* static member to store the number of total wifi clients within all APs*/ int IPACM_Wlan::total_num_wifi_clients = 0; -uint32_t* IPACM_Wlan::dummy_flt_rule_hdl_v4 = NULL; -uint32_t* IPACM_Wlan::dummy_flt_rule_hdl_v6 = NULL; int IPACM_Wlan::num_wlan_ap_iface = 0; -lan2lan_flt_rule_hdl IPACM_Wlan::self_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; -lan2lan_flt_rule_hdl IPACM_Wlan::self_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; - -lan2lan_flt_rule_hdl IPACM_Wlan::usb_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_USB_CLIENT]; -lan2lan_flt_rule_hdl IPACM_Wlan::usb_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_USB_CLIENT]; - IPACM_Wlan::IPACM_Wlan(int iface_index) : IPACM_Lan(iface_index) { #define WLAN_AMPDU_DEFAULT_FILTER_RULES 3 @@ -91,6 +83,7 @@ IPACM_Wlan::IPACM_Wlan(int iface_index) : IPACM_Lan(iface_index) num_wifi_client = 0; header_name_count = 0; wlan_client = NULL; + wlan_client_len = 0; if(iface_query != NULL) { @@ -110,71 +103,26 @@ IPACM_Wlan::IPACM_Wlan(int iface_index) : IPACM_Lan(iface_index) return; } - IPACM_Wlan::num_wlan_ap_iface++; IPACMDBG_H("Now the number of wlan AP iface is %d\n", IPACM_Wlan::num_wlan_ap_iface); - add_dummy_flt_rule(); - - memset(wlan_guest_ap_flt_rule_hdl_v4, 0, IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(uint32_t)); - wlan_guest_ap_flt_rule_hdl_v6 = 0; - is_guest_ap = false; - num_usb_client = 0; - - memset(eth_bridge_usb_client_flt_info, 0, IPA_LAN_TO_LAN_MAX_USB_CLIENT * sizeof(eth_bridge_client_flt_info)); - num_usb_client = 0; - eth_bridge_wlan_client_rt_from_usb_info_v4 = NULL; - eth_bridge_wlan_client_rt_from_usb_info_v6 = NULL; - eth_bridge_wlan_client_rt_from_wlan_info_v4 = NULL; - eth_bridge_wlan_client_rt_from_wlan_info_v6 = NULL; - if(tx_prop != NULL) - { -#ifdef FEATURE_ETH_BRIDGE_LE - client_rt_info_size_v4 = sizeof(eth_bridge_client_rt_info) + each_client_rt_rule_count_v4 * sizeof(uint32_t); - eth_bridge_wlan_client_rt_from_usb_info_v4 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v4); - eth_bridge_wlan_client_rt_from_wlan_info_v4 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v4); - - client_rt_info_size_v6 = sizeof(eth_bridge_client_rt_info) + each_client_rt_rule_count_v6 * sizeof(uint32_t); - eth_bridge_wlan_client_rt_from_usb_info_v6 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v6); - eth_bridge_wlan_client_rt_from_wlan_info_v6 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v6); -#endif - } - wlan_client_rt_from_usb_info_count_v4 = 0; - wlan_client_rt_from_usb_info_count_v6 = 0; - wlan_client_rt_from_wlan_info_count_v4 = 0; - wlan_client_rt_from_wlan_info_count_v6 = 0; -#ifdef FEATURE_ETH_BRIDGE_LE - if(iface_query != NULL) + + m_is_guest_ap = false; + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == INTERNET) { - if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == WLAN_IF && tx_prop != NULL) - { - if(IPACM_Lan::wlan_hdr_type != IPA_HDR_L2_NONE && tx_prop->tx[0].hdr_l2_type != IPACM_Lan::wlan_hdr_type) - { - IPACMERR("The WLAN header format is not consistent! Now header format is %d.\n", tx_prop->tx[0].hdr_l2_type); - } - else - { - if(wlan_ap_index == 0) - { - if(eth_bridge_get_hdr_template_hdl(&IPACM_Lan::wlan_hdr_template_hdl) == IPACM_FAILURE) - { - IPACMERR("Failed to setup wlan hdr template.\n"); - } - else - { - IPACM_Lan::wlan_hdr_type = tx_prop->tx[0].hdr_l2_type; - add_hdr_proc_ctx(); - } - } - } - } + m_is_guest_ap = true; } -#endif + IPACMDBG_H("%s: guest ap enable: %d \n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, m_is_guest_ap); #ifdef FEATURE_IPA_ANDROID /* set the IPA-client pipe enum */ - if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == WLAN_IF) + if(ipa_if_cate == WLAN_IF) { +#ifdef FEATURE_IPACM_HAL + handle_tethering_client(false, IPACM_CLIENT_MAX); +#else handle_tethering_client(false, IPACM_CLIENT_WLAN); +#endif } #endif return; @@ -214,7 +162,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Received IPA_WLAN_LINK_DOWN_EVENT\n"); handle_down_evt(); /* reset the AP-iface category to unknown */ - IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat=UNKNOWN_IF; + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat = UNKNOWN_IF; IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface IPACM_Wlan::total_num_wifi_clients = (IPACM_Wlan::total_num_wifi_clients) - \ (num_wifi_client); @@ -251,7 +199,6 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) { IPACM_Wlan::num_wlan_ap_iface--; IPACMDBG_H("Now the number of wlan AP iface is %d\n", IPACM_Wlan::num_wlan_ap_iface); - del_dummy_flt_rule(); IPACMDBG_H("Received IPA_LAN_DELETE_SELF event.\n"); IPACMDBG_H("ipa_WLAN (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); @@ -280,7 +227,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) if( ((data->iptype != ip_type) && (ip_type != IPA_IP_MAX)) || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES))) { - IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); + IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); /* Post event to NAT */ if (data->iptype == IPA_IP_v4) { @@ -308,10 +255,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) info->ipv4_addr, info->addr_mask); IPACM_EvtDispatcher::PostEvt(&evt_data); } - if ((num_dft_rt_v6 == 0) && (data->iptype == IPA_IP_v6) && (wlan_ap_index == 0)) - { - install_ipv6_icmp_flt_rule(); - } + if(handle_addr_evt(data) == IPACM_FAILURE) { return; @@ -321,10 +265,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) add_dummy_private_subnet_flt_rule(data->iptype); handle_private_subnet_android(data->iptype); #else - if(wlan_ap_index == 0) - { - handle_private_subnet(data->iptype); - } + handle_private_subnet(data->iptype); #endif if (IPACM_Wan::isWanUP(ipa_if_num)) @@ -334,36 +275,40 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) if(IPACM_Wan::backhaul_is_sta_mode == false) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); - IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4, + IPACM_Wan::getXlat_Mux_Id()); } else { IPACM_Lan::handle_wan_up(IPA_IP_v4); } } + IPACMDBG_H("Finished checking wan_up\n"); + } else { + IPACMDBG_H("Wan_V4 haven't up yet \n"); } if(IPACM_Wan::isWanUP_V6(ipa_if_num)) { if((data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX) && num_dft_rt_v6 == 1) { - if(wlan_ap_index == 0) //install ipv6 prefix rule only once - { - install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); - } + memcpy(ipv6_prefix, IPACM_Wan::backhaul_ipv6_prefix, sizeof(ipv6_prefix)); + install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); + if(IPACM_Wan::backhaul_is_sta_mode == false) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); - IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); } else { IPACM_Lan::handle_wan_up(IPA_IP_v6); } } + IPACMDBG_H("Finished checking wan_up_v6\n"); + } else { + IPACMDBG_H("Wan_V6 haven't up yet \n"); } - - IPACMDBG_H("posting IPA_HANDLE_WLAN_UP:Finished checking wan_up\n"); /* checking if SW-RT_enable */ if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true) { @@ -388,20 +333,41 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); - if (data_wan_tether->if_index_tether == ipa_if_num) +#ifndef FEATURE_IPACM_HAL + if (data_wan_tether->if_index_tether != ipa_if_num) { - if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + IPACMERR("IPA_HANDLE_WAN_UP_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); + return; + } +#endif + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { +#ifdef FEATURE_IPACM_HAL + if(is_upstream_set[IPA_IP_v4] == false) { - if(data_wan_tether->is_sta == false) - { - ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); - IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4); - } - else + IPACMDBG_H("Add upstream for IPv4.\n"); + is_upstream_set[IPA_IP_v4] = true; + if(is_downstream_set[IPA_IP_v4] == true) { - IPACM_Lan::handle_wan_up(IPA_IP_v4); + IPACMDBG_H("Downstream was set before, adding UL rules.\n"); + if(data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + handle_wan_up_ex(ext_prop, IPA_IP_v4, 0); + } else { + handle_wan_up(IPA_IP_v4); + } } } +#else + if(data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + handle_wan_up_ex(ext_prop, IPA_IP_v4, 0); + } else { + handle_wan_up(IPA_IP_v4); + } +#endif } break; @@ -417,24 +383,48 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); - if (data_wan_tether->if_index_tether == ipa_if_num) +#ifndef FEATURE_IPACM_HAL + if (data_wan_tether->if_index_tether != ipa_if_num) { - if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + IPACMERR("IPA_HANDLE_WAN_UP_V6_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); + return; + } +#endif + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { +#ifdef FEATURE_IPACM_HAL + if(is_upstream_set[IPA_IP_v6] == false) { - if(wlan_ap_index == 0) //install ipv6 prefix rule only once + IPACMDBG_H("Add upstream for IPv6.\n"); + is_upstream_set[IPA_IP_v6] = true; + + if(is_downstream_set[IPA_IP_v6] == true) { + IPACMDBG_H("Downstream was set before, adding UL rules.\n"); + memcpy(ipv6_prefix, data_wan_tether->ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(data_wan_tether->ipv6_prefix); + if(data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + handle_wan_up(IPA_IP_v6); + } } - if(data_wan_tether->is_sta == false) - { - ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); - IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6); - } - else - { - IPACM_Lan::handle_wan_up(IPA_IP_v6); - } } +#else + if(data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + handle_wan_up(IPA_IP_v6); + } +#endif } break; @@ -446,23 +436,37 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } + if(rx_prop == NULL) + { + IPACMERR("No rx prop.\n"); + return; + } IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); - if (data_wan_tether->if_index_tether == ipa_if_num) +#ifndef FEATURE_IPACM_HAL + if (data_wan_tether->if_index_tether != ipa_if_num) { - if(data_wan_tether->is_sta == false && wlan_ap_index > 0) - { - IPACMDBG_H("This is not the first AP instance and not STA mode, ignore WAN_DOWN event.\n"); - return; - } - if (rx_prop != NULL) + IPACMERR("IPA_HANDLE_WAN_DOWN_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); + return; + } +#endif + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { +#ifdef FEATURE_IPACM_HAL + if(is_upstream_set[IPA_IP_v4] == true) { - if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + IPACMDBG_H("Del upstream for IPv4.\n"); + is_upstream_set[IPA_IP_v4] = false; + if(is_downstream_set[IPA_IP_v4] == true) { + IPACMDBG_H("Downstream was set before, deleting UL rules.\n"); handle_wan_down(data_wan_tether->is_sta); } } +#else + handle_wan_down(data_wan_tether->is_sta); +#endif } break; @@ -474,33 +478,109 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } + if(rx_prop == NULL) + { + IPACMERR("No rx prop.\n"); + return; + } IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); - if (data_wan_tether->if_index_tether == ipa_if_num) +#ifndef FEATURE_IPACM_HAL + if (data_wan_tether->if_index_tether != ipa_if_num) + { + IPACMERR("IPA_HANDLE_WAN_DOWN_V6_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); + return; + } +#endif + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { - /* clean up v6 RT rules*/ - IPACMDBG_H("Received IPA_WAN_V6_DOWN in WLAN-instance and need clean up client IPv6 address \n"); - /* reset wifi-client ipv6 rt-rules */ +#ifdef FEATURE_IPACM_HAL + if(is_upstream_set[IPA_IP_v6] == true) + { + IPACMDBG_H("Del upstream for IPv6.\n"); + is_upstream_set[IPA_IP_v6] = false; + if(is_downstream_set[IPA_IP_v6] == true) + { + IPACMDBG_H("Downstream was set before, deleting UL rules.\n"); + /* reset usb-client ipv6 rt-rules */ + handle_wlan_client_reset_rt(IPA_IP_v6); + handle_wan_down_v6(data_wan_tether->is_sta); + } + } +#else + /* reset usb-client ipv6 rt-rules */ handle_wlan_client_reset_rt(IPA_IP_v6); + handle_wan_down_v6(data_wan_tether->is_sta); +#endif + } + break; - if(data_wan_tether->is_sta == false && wlan_ap_index > 0) + case IPA_DOWNSTREAM_ADD: + { + ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if(ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_DOWNSTREAM_ADD event.\n"); + if(is_downstream_set[data->prefix.iptype] == false) { - IPACMDBG_H("This is not the first AP instance and not STA mode, ignore WAN_DOWN event.\n"); - return; + IPACMDBG_H("Add downstream for IP iptype %d.\n", data->prefix.iptype); + is_downstream_set[data->prefix.iptype] = true; + memcpy(&prefix[data->prefix.iptype], &data->prefix, + sizeof(prefix[data->prefix.iptype])); + + if(is_upstream_set[data->prefix.iptype] == true) + { + IPACMDBG_H("Upstream was set before, adding modem UL rules.\n"); + if(ip_type == IPA_IP_MAX || ip_type == data->prefix.iptype) + { + if (data->prefix.iptype == IPA_IP_v6) /* ipv6 only */ + install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); + + if (IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */ + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(data->prefix.iptype); + handle_wan_up_ex(ext_prop, data->prefix.iptype, 0); + } else { + handle_wan_up(data->prefix.iptype); /* STA */ + } + } + } } - if (rx_prop != NULL) + } + break; + } + + case IPA_DOWNSTREAM_DEL: + { + ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if(ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_DOWNSTREAM_DEL event.\n"); + if(is_downstream_set[data->prefix.iptype] == true) { - if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + IPACMDBG_H("Del downstream for IP iptype %d.\n", data->prefix.iptype); + is_downstream_set[data->prefix.iptype] = false; + + if(is_upstream_set[data->prefix.iptype] == true) { - handle_wan_down_v6(data_wan_tether->is_sta); + IPACMDBG_H("Upstream was set before, deleting UL rules.\n"); + if (data->prefix.iptype == IPA_IP_v4) + { + handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */ + } else { + handle_wlan_client_reset_rt(IPA_IP_v6); + handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */ + } } } } break; + } #else case IPA_HANDLE_WAN_UP: - { IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); data_wan = (ipacm_event_iface_up*)param; @@ -512,17 +592,16 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { - if(data_wan->is_sta == false) - { + if(data_wan->is_sta == false) + { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); - IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan->xlat_mux_id); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v4); } - else - { - IPACM_Lan::handle_wan_up(IPA_IP_v4); } - } - } break; case IPA_HANDLE_WAN_UP_V6: @@ -537,17 +616,13 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { -#ifdef FEATURE_ETH_BRIDGE_LE - eth_bridge_install_wlan_guest_ap_ipv6_flt_rule(); -#endif - if(wlan_ap_index == 0) //install ipv6 prefix rule only once - { - install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix); - } + memcpy(ipv6_prefix, data_wan->ipv6_prefix, sizeof(ipv6_prefix)); + install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix); + if(data_wan->is_sta == false) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); - IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); } else { @@ -565,11 +640,6 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) return; } IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); - if(data_wan->is_sta == false && wlan_ap_index > 0) - { - IPACMDBG_H("This is not the first AP instance and not STA mode, ignore WAN_DOWN event.\n"); - return; - } if (rx_prop != NULL) { if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) @@ -591,13 +661,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Received IPA_WAN_V6_DOWN in WLAN-instance and need clean up client IPv6 address \n"); /* reset wifi-client ipv6 rt-rules */ handle_wlan_client_reset_rt(IPA_IP_v6); - - IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); - if(data_wan->is_sta == false && wlan_ap_index > 0) - { - IPACMDBG_H("This is not the first AP instance and not STA mode, ignore WAN_DOWN event.\n"); - return; - } + IPACMDBG_H("Backhaul is sta mode ? %d\n", data_wan->is_sta); if (rx_prop != NULL) { if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) @@ -614,36 +678,15 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) ipa_interface_index = iface_ipa_index_query(data->if_index); if (ipa_interface_index == ipa_if_num) { -#ifdef FEATURE_ETH_BRIDGE_LE int i; for(i=0; inum_of_attribs; i++) { if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) { - if(IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid == true) - { - eth_bridge_add_wlan_client_rt_rule(data->attribs[i].u.mac_addr, SRC_WLAN, IPA_IP_v4); - eth_bridge_add_wlan_client_rt_rule(data->attribs[i].u.mac_addr, SRC_WLAN, IPA_IP_v6); - } - if(IPACM_Lan::usb_to_wlan_hdr_proc_ctx.valid == true) - { - eth_bridge_add_wlan_client_rt_rule(data->attribs[i].u.mac_addr, SRC_USB, IPA_IP_v4); - eth_bridge_add_wlan_client_rt_rule(data->attribs[i].u.mac_addr, SRC_USB, IPA_IP_v6); - } - if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) - { - eth_bridge_add_self_client_flt_rule(data->attribs[i].u.mac_addr, IPA_IP_v4); - } - if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) - { - eth_bridge_add_self_client_flt_rule(data->attribs[i].u.mac_addr, IPA_IP_v6); - } - eth_bridge_post_lan_client_event(data->attribs[i].u.mac_addr, IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT); - eth_bridge_add_wlan_client(data->attribs[i].u.mac_addr, ipa_if_num); + eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->attribs[i].u.mac_addr, NULL, NULL); break; } } -#endif IPACMDBG_H("Received IPA_WLAN_CLIENT_ADD_EVENT\n"); handle_wlan_client_init_ex(data); } @@ -657,19 +700,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) if (ipa_interface_index == ipa_if_num) { IPACMDBG_H("Received IPA_WLAN_CLIENT_DEL_EVENT\n"); -#ifdef FEATURE_ETH_BRIDGE_LE - eth_bridge_del_wlan_client_rt_rule(data->mac_addr, SRC_WLAN); - if(IPACM_Lan::usb_to_wlan_hdr_proc_ctx.valid == true) - { - eth_bridge_del_wlan_client_rt_rule(data->mac_addr, SRC_USB); - } - eth_bridge_del_self_client_flt_rule(data->mac_addr); - eth_bridge_post_lan_client_event(data->mac_addr, IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT); - eth_bridge_del_wlan_client(data->mac_addr); -#endif - /* support lan2lan ipa-HW feature*/ - handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v4); - handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v6); + eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr, NULL, NULL); handle_wlan_client_down_evt(data->mac_addr); } } @@ -682,9 +713,6 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) if (ipa_interface_index == ipa_if_num) { IPACMDBG_H("Received IPA_WLAN_CLIENT_POWER_SAVE_EVENT\n"); - /* support lan2lan ipa-HW feature*/ - handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_SAVE, IPA_IP_v4); - handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_SAVE, IPA_IP_v6); handle_wlan_client_pwrsave(data->mac_addr); } } @@ -697,9 +725,6 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) if (ipa_interface_index == ipa_if_num) { IPACMDBG_H("Received IPA_WLAN_CLIENT_RECOVER_EVENT\n"); - /* support lan2lan ipa-HW feature*/ - handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_RECOVER, IPA_IP_v4); - handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_RECOVER, IPA_IP_v6); wlan_index = get_wlan_client_index(data->mac_addr); if ((wlan_index != IPACM_INVALID_INDEX) && @@ -710,25 +735,24 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) get_client_memptr(wlan_client, wlan_index)->power_save_set = false; /* First add route rules and then nat rules */ - if(get_client_memptr(wlan_client, wlan_index)->ipv4_set == true) /* for ipv4 */ - { + if(get_client_memptr(wlan_client, wlan_index)->ipv4_set == true) /* for ipv4 */ + { IPACMDBG_H("recover client index(%d):ipv4 address: 0x%x\n", wlan_index, get_client_memptr(wlan_client, wlan_index)->v4_addr); IPACMDBG_H("Adding Route Rules\n"); - handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v4); - + handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v4); IPACMDBG_H("Adding Nat Rules\n"); Nat_App->ResetPwrSaveIf(get_client_memptr(wlan_client, wlan_index)->v4_addr); - } + } - if(get_client_memptr(wlan_client, wlan_index)->ipv6_set != 0) /* for ipv6 */ - { - handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v6); - } - } - } + if(get_client_memptr(wlan_client, wlan_index)->ipv6_set != 0) /* for ipv6 */ + { + handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v6); + } + } + } } break; @@ -743,15 +767,13 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) { return; } - /* support lan2lan ipa-hw feature */ - handle_lan2lan_client_active(data, IPA_LAN_CLIENT_ACTIVE); handle_wlan_client_route_rule(data->mac_addr, data->iptype); if (data->iptype == IPA_IP_v4) { /* Add NAT rules after ipv4 RT rules are set */ CtList->HandleNeighIpAddrAddEvt(data); -// Nat_App->ResetPwrSaveIf(data->ipv4_addr); + //Nat_App->ResetPwrSaveIf(data->ipv4_addr); } } } @@ -769,104 +791,86 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACM_Iface::handle_software_routing_disable(); break; - case IPA_ETH_BRIDGE_USB_CLIENT_ADD_EVENT: + case IPA_WLAN_SWITCH_TO_SCC: + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_SCC\n"); + if(ip_type == IPA_IP_MAX) { - IPACMDBG_H("Received IPA_ETH_BRIDGE_USB_CLIENT_ADD_EVENT event.\n"); - ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; - if(mac != NULL) - { - if(wlan_ap_index == 0) - { - if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) - { - eth_bridge_add_usb_client_flt_rule(mac->mac_addr, IPA_IP_v4); - } - if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) - { - eth_bridge_add_usb_client_flt_rule(mac->mac_addr, IPA_IP_v6); - } - } - } - else - { - IPACMERR("Event MAC is empty.\n"); - } + handle_SCC_MCC_switch(IPA_IP_v4); + handle_SCC_MCC_switch(IPA_IP_v6); + } + else + { + handle_SCC_MCC_switch(ip_type); } + eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL, NULL, NULL); break; - case IPA_ETH_BRIDGE_USB_CLIENT_DEL_EVENT: + case IPA_WLAN_SWITCH_TO_MCC: + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_MCC\n"); + if(ip_type == IPA_IP_MAX) { - IPACMDBG_H("Received IPA_ETH_BRIDGE_USB_CLIENT_DEL_EVENT event.\n"); - ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; - if(mac != NULL) - { - if(wlan_ap_index == 0) - { - if(eth_bridge_del_usb_client_flt_rule(mac->mac_addr) == IPACM_FAILURE) - { - IPACMDBG_H("Failed to delete usb client MAC based flt rule.\n"); - } - } - } - else - { - IPACMERR("Event MAC is empty.\n"); - } + handle_SCC_MCC_switch(IPA_IP_v4); + handle_SCC_MCC_switch(IPA_IP_v6); + } + else + { + handle_SCC_MCC_switch(ip_type); } + eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL, NULL, NULL); break; - case IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT: + case IPA_CRADLE_WAN_MODE_SWITCH: { - IPACMDBG_H("Received IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT event.\n"); - int i; - ipacm_event_data_fid* fid = (ipacm_event_data_fid*)param; - if(fid == NULL) + IPACMDBG_H("Received IPA_CRADLE_WAN_MODE_SWITCH event.\n"); + ipacm_event_cradle_wan_mode* wan_mode = (ipacm_event_cradle_wan_mode*)param; + if(wan_mode == NULL) { IPACMERR("Event data is empty.\n"); return; } - if(fid->if_index == ipa_if_num) + + if(wan_mode->cradle_wan_mode == BRIDGE) { - IPACMDBG_H("The event was sent by the same interface, ignore.\n"); - return; + handle_cradle_wan_mode_switch(true); } - for(i=0; iiface_table[ipa_if_num].iface_name, + (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == 0) ? "full" : "internet", + (m_is_guest_ap == true) ? "internet" : "full"); + /* Add Natting iface to IPACM_Config if there is Rx/Tx property */ + if (rx_prop != NULL || tx_prop != NULL) { - IPACMERR("Event data is empty.\n"); - return; + IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name); + IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name); } - if(fid->if_index == ipa_if_num) + + if (m_is_guest_ap == true && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == FULL)) { - IPACMDBG_H("The event was sent by the same interface, ignore.\n"); - return; + m_is_guest_ap = false; + IPACMDBG_H("wlan mode is switched to full access mode. \n"); + eth_bridge_handle_wlan_mode_switch(); } - - for(i=0; iiface_table[ipa_if_num].wlan_mode == INTERNET)) { - if(IPACM_Lan::eth_bridge_wlan_client[i].ipa_if_num == ipa_if_num) - { - eth_bridge_del_wlan_client_rt_rule(IPACM_Lan::eth_bridge_wlan_client[i].mac, SRC_USB); - } + m_is_guest_ap = true; + IPACMDBG_H("wlan mode is switched to internet only access mode. \n"); + eth_bridge_handle_wlan_mode_switch(); + } + else + { + IPACMDBG_H("No change in %s access mode. \n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); } } break; - case IPA_TETHERING_STATS_UPDATE_EVENT: { IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_EVENT event.\n"); @@ -885,3888 +889,1315 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) } } break; - default: break; } return; } -/*Configure the initial filter rules */ -int IPACM_Wlan::init_fl_rule(ipa_ip_type iptype) +/* handle wifi client initial,copy all partial headers (tx property) */ +int IPACM_Wlan::handle_wlan_client_init_ex(ipacm_event_data_wlan_ex *data) { - int res = IPACM_SUCCESS, len, offset; - struct ipa_flt_rule_mdfy flt_rule; - struct ipa_ioc_mdfy_flt_rule* pFilteringTable; - /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/ - if (iptype == IPA_IP_v4) - { - if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX)) - { - IPACMDBG_H("Interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); - return res; - } +#define WLAN_IFACE_INDEX_LEN 2 - if (ip_type == IPA_IP_v6) - { - ip_type = IPA_IP_MAX; - } - else - { - ip_type = IPA_IP_v4; - } - IPACMDBG_H("Interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); - } - else - { - if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX)) - { - IPACMDBG_H("Interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); - return res; - } + int res = IPACM_SUCCESS, len = 0, i, evt_size; + char index[WLAN_IFACE_INDEX_LEN]; + struct ipa_ioc_copy_hdr sCopyHeader; + struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; + uint32_t cnt; - if (ip_type == IPA_IP_v4) - { - ip_type = IPA_IP_MAX; - } - else - { - ip_type = IPA_IP_v6; - } + /* start of adding header */ + IPACMDBG_H("Wifi client number for this iface: %d & total number of wlan clients: %d\n", + num_wifi_client,IPACM_Wlan::total_num_wifi_clients); - IPACMDBG_H("Interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); + if ((num_wifi_client >= IPA_MAX_NUM_WIFI_CLIENTS) || + (IPACM_Wlan::total_num_wifi_clients >= IPA_MAX_NUM_WIFI_CLIENTS)) + { + IPACMERR("Reached maximum number of wlan clients\n"); + return IPACM_FAILURE; } - /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */ - if(rx_prop != NULL) + IPACMDBG_H("Wifi client number: %d\n", num_wifi_client); + + /* add header to IPA */ + if(tx_prop != NULL) { - IPACMDBG_H("dev %s add producer dependency\n", dev_name); - IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); - IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false); - IPACMDBG_H("Add producer dependency from %s with registered rx-prop\n", dev_name); - } - else - { - /* Adding the check if no Rx property registered, no filter rules will be added */ - IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); - return IPACM_SUCCESS; - } -#ifdef FEATURE_ETH_BRIDGE_LE - if(wlan_ap_index != 0) - { - IPACMDBG_H("Install frag/multicast/broadcast rules only for the first AP.\n"); - return IPACM_SUCCESS; - } -#endif - - /* construct ipa_ioc_add_flt_rule with default filter rules */ - if (iptype == IPA_IP_v4) - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) - { - IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); - return IPACM_FAILURE; - } -#ifdef FEATURE_ETH_BRIDGE_LE - offset = 0; -#else -#ifndef CT_OPT - offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); -#else - offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) - + NUM_TCP_CTL_FLT_RULE; -#endif -#endif - -#ifdef FEATURE_IPA_ANDROID - offset = offset + wlan_ap_index * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); -#endif - len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_mdfy)); - pFilteringTable = (struct ipa_ioc_mdfy_flt_rule *)calloc(1, len); - if (!pFilteringTable) - { - IPACMERR("Error Locate ipa_ioc_mdfy_flt_rule memory...\n"); - return IPACM_FAILURE; - } - memset(pFilteringTable, 0, len); - - pFilteringTable->commit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES; - - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - - flt_rule.status = -1; - - flt_rule.rule.retain_hdr = 1; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - flt_rule.rule.eq_attrib_type = 0; - - /* Configuring Fragment Filtering Rule */ - IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); -#ifdef FEATURE_ETH_BRIDGE_LE - /* remove meta data mask */ - flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); -#endif - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; - flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset]; - memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - /* Configuring Multicast Filtering Rule */ - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); -#ifdef FEATURE_ETH_BRIDGE_LE - /* remove meta data mask */ - flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); -#endif - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v4.dst_addr_mask = 0xF0000000; - flt_rule.rule.attrib.u.v4.dst_addr = 0xE0000000; - flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+1]; - memcpy(&(pFilteringTable->rules[1]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - /* Configuring Broadcast Filtering Rule */ - flt_rule.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; - flt_rule.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF; - flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+2]; - memcpy(&(pFilteringTable->rules[2]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) - { - IPACMERR("Failed to modify default ipv4 filtering rules.\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - /* copy filter hdls */ - for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++) - { - if (pFilteringTable->rules[i].status == 0) - { - dft_v4fl_rule_hdl[i] = pFilteringTable->rules[i].rule_hdl; - IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]); - } - else - { - IPACMERR("Failed adding default v4 Filtering rule %d\n", i); - } - } - } - } - else - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) - { - IPACMERR("Dummy ipv6 flt rule has not been installed.\n"); - return IPACM_FAILURE; - } -#ifdef FEATURE_ETH_BRIDGE_LE - offset = 1 + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT; -#else -#ifndef CT_OPT - offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR) + MAX_OFFLOAD_PAIR; -#else - offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR) - + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR; -#endif -#endif - - len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_mdfy)); - pFilteringTable = (struct ipa_ioc_mdfy_flt_rule *)calloc(1, len); - if (!pFilteringTable) - { - IPACMERR("Error Locate ipa_ioc_mdfy_flt_rule memory...\n"); - return IPACM_FAILURE; - } - memset(pFilteringTable, 0, len); - - pFilteringTable->commit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES; - - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - - flt_rule.status = -1; - - flt_rule.rule.retain_hdr = 1; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - flt_rule.rule.eq_attrib_type = 0; - - /* Configuring Multicast Filtering Rule */ - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); -#ifdef FEATURE_ETH_BRIDGE_LE - /* remove meta data mask */ - flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); -#endif - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000; - flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr[0] = 0XFF000000; - flt_rule.rule.attrib.u.v6.dst_addr[1] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr[2] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr[3] = 0X00000000; - flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset]; - memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - /* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */ - flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000; - flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr[0] = 0xFE800000; - flt_rule.rule.attrib.u.v6.dst_addr[1] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr[2] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr[3] = 0X00000000; - flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset+1]; - memcpy(&(pFilteringTable->rules[1]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - /* Configuring fec0::/10 Reserved by IETF Filtering Rule */ - flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000; - flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000; - flt_rule.rule.attrib.u.v6.dst_addr[1] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr[2] = 0x00000000; - flt_rule.rule.attrib.u.v6.dst_addr[3] = 0X00000000; - flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset+2]; - memcpy(&(pFilteringTable->rules[2]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - -#ifdef FEATURE_IPA_ANDROID - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - - flt_rule.status = -1; - - flt_rule.rule.retain_hdr = 1; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - flt_rule.rule.eq_attrib_type = 1; - - flt_rule.rule.eq_attrib.rule_eq_bitmap = 0; - - if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA) - { - flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<14); - flt_rule.rule.eq_attrib.metadata_meq32_present = 1; - flt_rule.rule.eq_attrib.metadata_meq32.offset = 0; - flt_rule.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data; - flt_rule.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask; - } - - flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<1); - flt_rule.rule.eq_attrib.protocol_eq_present = 1; - flt_rule.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; - - flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<8); - flt_rule.rule.eq_attrib.num_ihl_offset_meq_32 = 1; - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; - - /* add TCP FIN rule*/ - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[3]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - /* add TCP SYN rule*/ - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[4]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - /* add TCP RST rule*/ - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[5]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); -#endif - - if (m_filtering.ModifyFilteringRule(pFilteringTable) == false) - { - IPACMERR("Failed to modify default ipv6 filtering rules.\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - for (int i = 0; i < IPV6_DEFAULT_FILTERTING_RULES; i++) - { - if (pFilteringTable->rules[i].status == 0) - { - dft_v6fl_rule_hdl[i] = pFilteringTable->rules[i].rule_hdl; - IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]); - } - else - { - IPACMERR("Failing adding v6 default IPV6 rule %d\n", i); - } - } - } - } - -fail: - free(pFilteringTable); - return res; -} - -int IPACM_Wlan::add_dummy_lan2lan_flt_rule(ipa_ip_type iptype) -{ - if(rx_prop == NULL) - { - IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy lan2lan filtering rule.\n", dev_name); - return IPACM_FAILURE; - } - - int offset; - if(iptype == IPA_IP_v4) - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) - { - IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); - return IPACM_FAILURE; - } - -#ifndef CT_OPT - offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) - + IPV4_DEFAULT_FILTERTING_RULES; -#else - offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) - + NUM_TCP_CTL_FLT_RULE + IPV4_DEFAULT_FILTERTING_RULES; -#endif - -#ifdef FEATURE_IPA_ANDROID - offset = offset + wlan_ap_index * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); -#endif - for (int i = 0; i < MAX_OFFLOAD_PAIR; i++) - { - lan2lan_flt_rule_hdl_v4[i].rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+i]; - lan2lan_flt_rule_hdl_v4[i].valid = false; - IPACMDBG_H("Lan2lan v4 flt rule %d hdl:0x%x\n", i, lan2lan_flt_rule_hdl_v4[i].rule_hdl); - } - } - else if(iptype == IPA_IP_v6) - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) - { - IPACMERR("Dummy ipv6 flt rule has not been installed.\n"); - return IPACM_FAILURE; - } - -#ifndef CT_OPT - offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR); -#else - offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR) - + NUM_TCP_CTL_FLT_RULE; -#endif - - for (int i = 0; i < MAX_OFFLOAD_PAIR; i++) - { - lan2lan_flt_rule_hdl_v6[i].rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset+i]; - lan2lan_flt_rule_hdl_v6[i].valid = false; - IPACMDBG_H("Lan2lan v6 flt rule %d hdl:0x%x\n", i, lan2lan_flt_rule_hdl_v6[i].rule_hdl); - } - } - else - { - IPACMERR("IP type is not expected.\n"); - return IPACM_FAILURE; - } - - return IPACM_SUCCESS; -} - -/* configure private subnet filter rules*/ -int IPACM_Wlan::handle_private_subnet(ipa_ip_type iptype) -{ - int i, len, res = IPACM_SUCCESS, offset; - struct ipa_flt_rule_mdfy flt_rule; - struct ipa_ioc_mdfy_flt_rule* pFilteringTable; - - if (rx_prop == NULL) - { - IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); - return IPACM_SUCCESS; - } - - if (iptype == IPA_IP_v4) - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) - { - IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); - return IPACM_FAILURE; - } -#ifdef FEATURE_ETH_BRIDGE_LE - offset = IPV4_DEFAULT_FILTERTING_RULES + IPACM_Iface::ipacmcfg->ipa_num_private_subnet + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT; -#else -#ifndef CT_OPT - offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) - + IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR; -#else - offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) - + IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR; -#endif -#endif - - len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_mdfy); - pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); - if (!pFilteringTable) - { - IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); - return IPACM_FAILURE; - } - memset(pFilteringTable, 0, len); - - pFilteringTable->commit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet; - - /* Make LAN-traffic always go A5, use default IPA-RT table */ - if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4)) - { - IPACMERR("Failed to get routing table handle.\n"); - res = IPACM_FAILURE; - goto fail; - } - - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - flt_rule.status = -1; - - flt_rule.rule.retain_hdr = 1; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_ROUTING; - flt_rule.rule.eq_attrib_type = 0; - flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl; - IPACMDBG_H("Private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name); - - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; -#ifdef FEATURE_ETH_BRIDGE_LE - /* remove meta data mask */ - flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); -#endif - - for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++) - { - flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+i]; - flt_rule.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask; - flt_rule.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr; - memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - } - - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) - { - IPACMERR("Failed to modify private subnet filtering rules.\n"); - res = IPACM_FAILURE; - goto fail; - } - - /* copy filter rule hdls */ - for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++) - { - private_fl_rule_hdl[i] = pFilteringTable->rules[i].rule_hdl; - } - } - else - { - return IPACM_SUCCESS; - } -fail: - free(pFilteringTable); - return res; -} - -/* install UL filter rule from Q6 */ -int IPACM_Wlan::handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptype) -{ - ipa_flt_rule_add flt_rule_entry; - int len = 0, cnt, ret = IPACM_SUCCESS, offset; - ipa_ioc_add_flt_rule *pFilteringTable; - ipa_fltr_installed_notif_req_msg_v01 flt_index; - int fd; - int i; - - IPACMDBG_H("Set extended property rules in LAN\n"); - - if (rx_prop == NULL) - { - IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); - return IPACM_SUCCESS; - } - - if(prop == NULL || prop->num_ext_props <= 0) - { - IPACMDBG_H("No extended property.\n"); - return IPACM_SUCCESS; - } - - if(wlan_ap_index > 0) - { - IPACMDBG_H("This is not the first WLAN AP, do not install modem UL rules.\n"); - return IPACM_SUCCESS; - } - - fd = open(IPA_DEVICE_NAME, O_RDWR); - if (0 == fd) - { - IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); - } - - memset(&flt_index, 0, sizeof(flt_index)); - flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); - flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; - flt_index.filter_index_list_len = prop->num_ext_props; - flt_index.embedded_pipe_index_valid = 1; - flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); - flt_index.retain_header_valid = 1; - flt_index.retain_header = 0; - flt_index.embedded_call_mux_id_valid = 1; - flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); - - IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", flt_index.source_pipe_index, - flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); - - len = sizeof(struct ipa_ioc_add_flt_rule) + prop->num_ext_props * sizeof(struct ipa_flt_rule_add); - pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); - if (pFilteringTable == NULL) - { - IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); - close(fd); - return IPACM_FAILURE; - } - memset(pFilteringTable, 0, len); - - pFilteringTable->commit = 1; - pFilteringTable->ep = rx_prop->rx[0].src_pipe; - pFilteringTable->global = false; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = prop->num_ext_props; - - memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields - flt_rule_entry.at_rear = 1; - flt_rule_entry.flt_rule_hdl = -1; - flt_rule_entry.status = -1; - - flt_rule_entry.rule.retain_hdr = 0; - flt_rule_entry.rule.to_uc = 0; - flt_rule_entry.rule.eq_attrib_type = 1; - if(iptype == IPA_IP_v4) - flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; - else if(iptype == IPA_IP_v6) - flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; - else - { - IPACMERR("IP type is not expected.\n"); - ret = IPACM_FAILURE; - goto fail; - } - - if(iptype == IPA_IP_v4) - { -#ifdef FEATURE_ETH_BRIDGE_LE - offset = IPV4_DEFAULT_FILTERTING_RULES + 2 * IPACM_Iface::ipacmcfg->ipa_num_private_subnet - + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT; -#else -#ifndef CT_OPT - offset = 2*(IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); -#else - offset = 2*(IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); -#endif -#ifdef FEATURE_IPA_ANDROID - offset = offset + 2 * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); -#endif -#endif - } - else - { -#ifdef FEATURE_ETH_BRIDGE_LE - offset = IPV6_DEFAULT_FILTERTING_RULES + 1 + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT + NUM_IPV6_PREFIX_FLT_RULE - + NUM_IPV6_ICMP_FLT_RULE; -#else -#ifndef CT_OPT - offset = 2*(IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR) + NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_ICMP_FLT_RULE; -#else - offset = 2*(IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR) + NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_ICMP_FLT_RULE; -#endif -#endif - } - - for(cnt=0; cntnum_ext_props; cnt++) - { - memcpy(&flt_rule_entry.rule.eq_attrib, - &prop->prop[cnt].eq_attrib, - sizeof(prop->prop[cnt].eq_attrib)); - flt_rule_entry.rule.rt_tbl_idx = prop->prop[cnt].rt_tbl_idx; - memcpy(&pFilteringTable->rules[cnt], &flt_rule_entry, sizeof(flt_rule_entry)); - - flt_index.filter_index_list[cnt].filter_index = offset+cnt; - IPACMDBG_H("Modem UL filtering rule %d has index %d\n", cnt, offset+cnt); - - flt_index.filter_index_list[cnt].filter_handle = prop->prop[cnt].filter_hdl; - } - - if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) - { - IPACMERR("Error sending filtering rule index, aborting...\n"); - ret = IPACM_FAILURE; - goto fail; - } - - if(false == m_filtering.AddFilteringRule(pFilteringTable)) - { - IPACMERR("Error Adding RuleTable to Filtering, aborting...\n"); - ret = IPACM_FAILURE; - goto fail; - } - else - { - if(iptype == IPA_IP_v4) - { - for(i=0; inum_rules; i++) - { - wan_ul_fl_rule_hdl_v4[num_wan_ul_fl_rule_v4] = pFilteringTable->rules[i].flt_rule_hdl; - num_wan_ul_fl_rule_v4++; - } - } - else if(iptype == IPA_IP_v6) - { - for(i=0; inum_rules; i++) - { - wan_ul_fl_rule_hdl_v6[num_wan_ul_fl_rule_v6] = pFilteringTable->rules[i].flt_rule_hdl; - num_wan_ul_fl_rule_v6++; - } - } - else - { - IPACMERR("IP type is not expected.\n"); - goto fail; - } - } - -fail: - free(pFilteringTable); - close(fd); - return ret; -} - -/* handle wifi client initial,copy all partial headers (tx property) */ -int IPACM_Wlan::handle_wlan_client_init_ex(ipacm_event_data_wlan_ex *data) -{ - -#define WLAN_IFACE_INDEX_LEN 2 - - int res = IPACM_SUCCESS, len = 0, i, evt_size; - char index[WLAN_IFACE_INDEX_LEN]; - struct ipa_ioc_copy_hdr sCopyHeader; - struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; - uint32_t cnt; - - /* start of adding header */ - IPACMDBG_H("Wifi client number for this iface: %d & total number of wlan clients: %d\n", - num_wifi_client,IPACM_Wlan::total_num_wifi_clients); - - if ((num_wifi_client >= IPA_MAX_NUM_WIFI_CLIENTS) || - (IPACM_Wlan::total_num_wifi_clients >= IPA_MAX_NUM_WIFI_CLIENTS)) - { - IPACMERR("Reached maximum number of wlan clients\n"); - return IPACM_FAILURE; - } - - IPACMDBG_H("Wifi client number: %d\n", num_wifi_client); - - /* add header to IPA */ - if(tx_prop != NULL) - { - len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add)); - pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len); - if (pHeaderDescriptor == NULL) - { - IPACMERR("calloc failed to allocate pHeaderDescriptor\n"); - return IPACM_FAILURE; - } - - evt_size = sizeof(ipacm_event_data_wlan_ex) + data->num_of_attribs * sizeof(struct ipa_wlan_hdr_attrib_val); - get_client_memptr(wlan_client, num_wifi_client)->p_hdr_info = (ipacm_event_data_wlan_ex*)malloc(evt_size); - memcpy(get_client_memptr(wlan_client, num_wifi_client)->p_hdr_info, data, evt_size); - - /* copy partial header for v4*/ - for (cnt=0; cntnum_tx_props; cnt++) - { - if(tx_prop->tx[cnt].ip==IPA_IP_v4) - { - IPACMDBG_H("Got partial v4-header name from %d tx props\n", cnt); - memset(&sCopyHeader, 0, sizeof(sCopyHeader)); - memcpy(sCopyHeader.name, - tx_prop->tx[cnt].hdr_name, - sizeof(sCopyHeader.name)); - - IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); - if (m_header.CopyHeader(&sCopyHeader) == false) - { - PERROR("ioctl copy header failed"); - res = IPACM_FAILURE; - goto fail; - } - - IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); - if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) - { - IPACMERR("header oversize\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - memcpy(pHeaderDescriptor->hdr[0].hdr, - sCopyHeader.hdr, - sCopyHeader.hdr_len); - } - - for(i = 0; i < data->num_of_attribs; i++) - { - if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) - { - memcpy(get_client_memptr(wlan_client, num_wifi_client)->mac, - data->attribs[i].u.mac_addr, - sizeof(get_client_memptr(wlan_client, num_wifi_client)->mac)); - - /* copy client mac_addr to partial header */ - memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], - get_client_memptr(wlan_client, num_wifi_client)->mac, - IPA_MAC_ADDR_SIZE); - } - else if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID) - { - /* copy client id to header */ - memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], - &data->attribs[i].u.sta_id, sizeof(data->attribs[i].u.sta_id)); - } - else - { - IPACMDBG_H("The attribute type is not expected!\n"); - } - } - - pHeaderDescriptor->commit = true; - pHeaderDescriptor->num_hdrs = 1; - - memset(pHeaderDescriptor->hdr[0].name, 0, - sizeof(pHeaderDescriptor->hdr[0].name)); - - snprintf(index,sizeof(index), "%d", ipa_if_num); - strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); - - if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WLAN_PARTIAL_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) - { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); - res = IPACM_FAILURE; - goto fail; - } - snprintf(index,sizeof(index), "%d", header_name_count); - if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) - { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); - res = IPACM_FAILURE; - goto fail; - } - - - pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; - pHeaderDescriptor->hdr[0].hdr_hdl = -1; - pHeaderDescriptor->hdr[0].is_partial = 0; - pHeaderDescriptor->hdr[0].status = -1; - - if (m_header.AddHeader(pHeaderDescriptor) == false || - pHeaderDescriptor->hdr[0].status != 0) - { - IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); - res = IPACM_FAILURE; - goto fail; - } - - get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; - IPACMDBG_H("client(%d) v4 full header name:%s header handle:(0x%x)\n", - num_wifi_client, - pHeaderDescriptor->hdr[0].name, - get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v4); - get_client_memptr(wlan_client, num_wifi_client)->ipv4_header_set=true; - break; - } - } - - /* copy partial header for v6*/ - for (cnt=0; cntnum_tx_props; cnt++) - { - if(tx_prop->tx[cnt].ip==IPA_IP_v6) - { - IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt); - memset(&sCopyHeader, 0, sizeof(sCopyHeader)); - memcpy(sCopyHeader.name, - tx_prop->tx[cnt].hdr_name, - sizeof(sCopyHeader.name)); - - IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); - if (m_header.CopyHeader(&sCopyHeader) == false) - { - PERROR("ioctl copy header failed"); - res = IPACM_FAILURE; - goto fail; - } - - IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); - if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) - { - IPACMERR("header oversize\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - memcpy(pHeaderDescriptor->hdr[0].hdr, - sCopyHeader.hdr, - sCopyHeader.hdr_len); - } - - for(i = 0; i < data->num_of_attribs; i++) - { - if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) - { - memcpy(get_client_memptr(wlan_client, num_wifi_client)->mac, - data->attribs[i].u.mac_addr, - sizeof(get_client_memptr(wlan_client, num_wifi_client)->mac)); - - /* copy client mac_addr to partial header */ - memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], - get_client_memptr(wlan_client, num_wifi_client)->mac, - IPA_MAC_ADDR_SIZE); - } - else if (data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID) - { - /* copy client id to header */ - memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], - &data->attribs[i].u.sta_id, sizeof(data->attribs[i].u.sta_id)); - } - else - { - IPACMDBG_H("The attribute type is not expected!\n"); - } - } - - pHeaderDescriptor->commit = true; - pHeaderDescriptor->num_hdrs = 1; - - memset(pHeaderDescriptor->hdr[0].name, 0, - sizeof(pHeaderDescriptor->hdr[0].name)); - - snprintf(index,sizeof(index), "%d", ipa_if_num); - strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); - if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WLAN_PARTIAL_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) - { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); - res = IPACM_FAILURE; - goto fail; - } - - snprintf(index,sizeof(index), "%d", header_name_count); - if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) - { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); - res = IPACM_FAILURE; - goto fail; - } - - pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; - pHeaderDescriptor->hdr[0].hdr_hdl = -1; - pHeaderDescriptor->hdr[0].is_partial = 0; - pHeaderDescriptor->hdr[0].status = -1; - - if (m_header.AddHeader(pHeaderDescriptor) == false || - pHeaderDescriptor->hdr[0].status != 0) - { - IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); - res = IPACM_FAILURE; - goto fail; - } - - get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; - IPACMDBG_H("client(%d) v6 full header name:%s header handle:(0x%x)\n", - num_wifi_client, - pHeaderDescriptor->hdr[0].name, - get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v6); - - get_client_memptr(wlan_client, num_wifi_client)->ipv6_header_set=true; - break; - } - } - - /* initialize wifi client*/ - get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v4 = false; - get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v6 = 0; - get_client_memptr(wlan_client, num_wifi_client)->ipv4_set = false; - get_client_memptr(wlan_client, num_wifi_client)->ipv6_set = 0; - get_client_memptr(wlan_client, num_wifi_client)->power_save_set=false; - num_wifi_client++; - header_name_count++; //keep increasing header_name_count - IPACM_Wlan::total_num_wifi_clients++; - res = IPACM_SUCCESS; - IPACMDBG_H("Wifi client number: %d\n", num_wifi_client); - } - else - { - return res; - } - -fail: - free(pHeaderDescriptor); - return res; -} - -/*handle wifi client */ -int IPACM_Wlan::handle_wlan_client_ipaddr(ipacm_event_data_all *data) -{ - int clnt_indx; - int v6_num; - - IPACMDBG_H("number of wifi clients: %d\n", num_wifi_client); - IPACMDBG_H(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - data->mac_addr[0], - data->mac_addr[1], - data->mac_addr[2], - data->mac_addr[3], - data->mac_addr[4], - data->mac_addr[5]); - - clnt_indx = get_wlan_client_index(data->mac_addr); - - if (clnt_indx == IPACM_INVALID_INDEX) - { - IPACMERR("wlan client not found/attached \n"); - return IPACM_FAILURE; - } - - IPACMDBG_H("Ip-type received %d\n", data->iptype); - if (data->iptype == IPA_IP_v4) - { - IPACMDBG_H("ipv4 address: 0x%x\n", data->ipv4_addr); - if (data->ipv4_addr != 0) /* not 0.0.0.0 */ - { - if (get_client_memptr(wlan_client, clnt_indx)->ipv4_set == false) - { - get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr; - get_client_memptr(wlan_client, clnt_indx)->ipv4_set = true; - } - else - { - /* check if client got new IPv4 address*/ - if(data->ipv4_addr == get_client_memptr(wlan_client, clnt_indx)->v4_addr) - { - IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx); - return IPACM_FAILURE; - } - else - { - IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx); - /* delete NAT rules first */ - CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clnt_indx)->v4_addr); - delete_default_qos_rtrules(clnt_indx,IPA_IP_v4); - get_client_memptr(wlan_client, clnt_indx)->route_rule_set_v4 = false; - get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr; - } - } - } - else - { - IPACMDBG_H("Invalid client IPv4 address \n"); - return IPACM_FAILURE; - } - } - else - { - if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) || - (data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) /* check if all 0 not valid ipv6 address */ - { - IPACMDBG_H("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); - if(get_client_memptr(wlan_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR) - { - - for(v6_num=0;v6_num < get_client_memptr(wlan_client, clnt_indx)->ipv6_set;v6_num++) - { - if( data->ipv6_addr[0] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][0] && - data->ipv6_addr[1] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][1] && - data->ipv6_addr[2]== get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][2] && - data->ipv6_addr[3] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][3]) - { - IPACMDBG_H("Already see this ipv6 addr for client:%d\n", clnt_indx); - return IPACM_FAILURE; /* not setup the RT rules*/ - break; - } - } - - /* not see this ipv6 before for wifi client*/ - get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0]; - get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1]; - get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2]; - get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3]; - get_client_memptr(wlan_client, clnt_indx)->ipv6_set++; - } - else - { - IPACMDBG_H("Already got 3 ipv6 addr for client:%d\n", clnt_indx); - return IPACM_FAILURE; /* not setup the RT rules*/ - } - } - } - - return IPACM_SUCCESS; -} - -/*handle wifi client routing rule*/ -int IPACM_Wlan::handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype) -{ - struct ipa_ioc_add_rt_rule *rt_rule; - struct ipa_rt_rule_add *rt_rule_entry; - uint32_t tx_index; - int wlan_index,v6_num; - const int NUM = 1; - - if(tx_prop == NULL) - { - IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); - return IPACM_SUCCESS; - } - - IPACMDBG_H("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - mac_addr[0], mac_addr[1], mac_addr[2], - mac_addr[3], mac_addr[4], mac_addr[5]); - - wlan_index = get_wlan_client_index(mac_addr); - if (wlan_index == IPACM_INVALID_INDEX) - { - IPACMDBG_H("wlan client not found/attached \n"); - return IPACM_SUCCESS; - } - - /* during power_save mode, even receive IP_ADDR_ADD, not setting RT rules*/ - if (get_client_memptr(wlan_client, wlan_index)->power_save_set == true) - { - IPACMDBG_H("wlan client is in power safe mode \n"); - return IPACM_SUCCESS; - } - - if (iptype==IPA_IP_v4) - { - IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", wlan_index, iptype, - get_client_memptr(wlan_client, wlan_index)->ipv4_set, - get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4); - } - else - { - IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wlan_index, iptype, - get_client_memptr(wlan_client, wlan_index)->ipv6_set, - get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6); - } - - - /* Add default Qos routing rules if not set yet */ - if ((iptype == IPA_IP_v4 - && get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4 == false - && get_client_memptr(wlan_client, wlan_index)->ipv4_set == true) - || (iptype == IPA_IP_v6 - && get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 < get_client_memptr(wlan_client, wlan_index)->ipv6_set - )) - { - rt_rule = (struct ipa_ioc_add_rt_rule *) - calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + - NUM * sizeof(struct ipa_rt_rule_add)); - - if (rt_rule == NULL) - { - PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n"); - return IPACM_FAILURE; - } - - rt_rule->commit = 1; - rt_rule->num_rules = (uint8_t)NUM; - rt_rule->ip = iptype; - - - for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) - { - - if(iptype != tx_prop->tx[tx_index].ip) - { - IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", - tx_index, tx_prop->tx[tx_index].ip,iptype); - continue; - } - - rt_rule_entry = &rt_rule->rules[0]; - rt_rule_entry->at_rear = 0; - - if (iptype == IPA_IP_v4) - { - IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wlan_index, - get_client_memptr(wlan_client, wlan_index)->v4_addr); - - IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", - wlan_index, - get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4); - strncpy(rt_rule->rt_tbl_name, - IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, - sizeof(rt_rule->rt_tbl_name)); - - - rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; - memcpy(&rt_rule_entry->rule.attrib, - &tx_prop->tx[tx_index].attrib, - sizeof(rt_rule_entry->rule.attrib)); - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4; - rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wlan_client, wlan_index)->v4_addr; - rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; - - if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - free(rt_rule); - return IPACM_FAILURE; - } - - /* copy ipv4 RT hdl */ - get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4 = - rt_rule->rules[0].rt_rule_hdl; - IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, - get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4, iptype); - } - else - { - for(v6_num = get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6;v6_num < get_client_memptr(wlan_client, wlan_index)->ipv6_set;v6_num++) - { - IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", - wlan_index, - get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6); - - /* v6 LAN_RT_TBL */ - strncpy(rt_rule->rt_tbl_name, - IPACM_Iface::ipacmcfg->rt_tbl_v6.name, - sizeof(rt_rule->rt_tbl_name)); - - /* Support QCMAP LAN traffic feature, send to A5 */ - rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; - memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib)); - rt_rule_entry->rule.hdr_hdl = 0; - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][3]; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; - - if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - free(rt_rule); - return IPACM_FAILURE; - } - - get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl; - IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, - get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[v6_num], iptype); - - /*Copy same rule to v6 WAN RT TBL*/ - strncpy(rt_rule->rt_tbl_name, - IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, - sizeof(rt_rule->rt_tbl_name)); - - /* Downlink traffic from Wan iface, directly through IPA */ - rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; - memcpy(&rt_rule_entry->rule.attrib, - &tx_prop->tx[tx_index].attrib, - sizeof(rt_rule_entry->rule.attrib)); - rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6; - rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][3]; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; - rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; - - if (false == m_routing.AddRoutingRule(rt_rule)) - { - IPACMERR("Routing rule addition failed!\n"); - free(rt_rule); - return IPACM_FAILURE; - } - - get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl; - - IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, - get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num], iptype); - } - } - - } /* end of for loop */ - - free(rt_rule); - - if (iptype == IPA_IP_v4) - { - get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4 = true; - } - else - { - get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 = get_client_memptr(wlan_client, wlan_index)->ipv6_set; - } - } - - return IPACM_SUCCESS; -} - -/*handle wifi client power-save mode*/ -int IPACM_Wlan::handle_wlan_client_pwrsave(uint8_t *mac_addr) -{ - int clt_indx; - IPACMDBG_H("wlan->handle_wlan_client_pwrsave();\n"); - - clt_indx = get_wlan_client_index(mac_addr); - if (clt_indx == IPACM_INVALID_INDEX) - { - IPACMDBG_H("wlan client not attached\n"); - return IPACM_SUCCESS; - } - - if (get_client_memptr(wlan_client, clt_indx)->power_save_set == false) - { - /* First reset nat rules and then route rules */ - if(get_client_memptr(wlan_client, clt_indx)->ipv4_set == true) - { - IPACMDBG_H("Deleting Nat Rules\n"); - Nat_App->UpdatePwrSaveIf(get_client_memptr(wlan_client, clt_indx)->v4_addr); - } - - IPACMDBG_H("Deleting default qos Route Rules\n"); - delete_default_qos_rtrules(clt_indx, IPA_IP_v4); - delete_default_qos_rtrules(clt_indx, IPA_IP_v6); - get_client_memptr(wlan_client, clt_indx)->power_save_set = true; - } - else - { - IPACMDBG_H("wlan client already in power-save mode\n"); - } - return IPACM_SUCCESS; -} - -/*handle wifi client del mode*/ -int IPACM_Wlan::handle_wlan_client_down_evt(uint8_t *mac_addr) -{ - int clt_indx; - uint32_t tx_index; - int num_wifi_client_tmp = num_wifi_client; - int num_v6; - - IPACMDBG_H("total client: %d\n", num_wifi_client_tmp); - - clt_indx = get_wlan_client_index(mac_addr); - if (clt_indx == IPACM_INVALID_INDEX) - { - IPACMDBG_H("wlan client not attached\n"); - return IPACM_SUCCESS; - } - - /* First reset nat rules and then route rules */ - if(get_client_memptr(wlan_client, clt_indx)->ipv4_set == true) - { - IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wlan_client, clt_indx)->v4_addr); - CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clt_indx)->v4_addr); - } - - if (delete_default_qos_rtrules(clt_indx, IPA_IP_v4)) - { - IPACMERR("unbale to delete v4 default qos route rules for index: %d\n", clt_indx); - return IPACM_FAILURE; - } - - if (delete_default_qos_rtrules(clt_indx, IPA_IP_v6)) - { - IPACMERR("unbale to delete v6 default qos route rules for indexn: %d\n", clt_indx); - return IPACM_FAILURE; - } - - /* Delete wlan client header */ - if(get_client_memptr(wlan_client, clt_indx)->ipv4_header_set == true) - { - if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v4) - == false) - { - return IPACM_FAILURE; - } - get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = false; - } - - if(get_client_memptr(wlan_client, clt_indx)->ipv6_header_set == true) - { - if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v6) - == false) - { - return IPACM_FAILURE; - } - get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = false; - } - - /* Reset ip_set to 0*/ - get_client_memptr(wlan_client, clt_indx)->ipv4_set = false; - get_client_memptr(wlan_client, clt_indx)->ipv6_set = 0; - get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = false; - get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = false; - get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = false; - get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = 0; - free(get_client_memptr(wlan_client, clt_indx)->p_hdr_info); - - for (; clt_indx < num_wifi_client_tmp - 1; clt_indx++) - { - get_client_memptr(wlan_client, clt_indx)->p_hdr_info = get_client_memptr(wlan_client, (clt_indx + 1))->p_hdr_info; - - memcpy(get_client_memptr(wlan_client, clt_indx)->mac, - get_client_memptr(wlan_client, (clt_indx + 1))->mac, - sizeof(get_client_memptr(wlan_client, clt_indx)->mac)); - - get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v4 = get_client_memptr(wlan_client, (clt_indx + 1))->hdr_hdl_v4; - get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v6 = get_client_memptr(wlan_client, (clt_indx + 1))->hdr_hdl_v6; - get_client_memptr(wlan_client, clt_indx)->v4_addr = get_client_memptr(wlan_client, (clt_indx + 1))->v4_addr; - - get_client_memptr(wlan_client, clt_indx)->ipv4_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv4_set; - get_client_memptr(wlan_client, clt_indx)->ipv6_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv6_set; - get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv4_header_set; - get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv6_header_set; - - get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = get_client_memptr(wlan_client, (clt_indx + 1))->route_rule_set_v4; - get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = get_client_memptr(wlan_client, (clt_indx + 1))->route_rule_set_v6; - - for(num_v6=0;num_v6< get_client_memptr(wlan_client, clt_indx)->ipv6_set;num_v6++) - { - get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][0] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][0]; - get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][1] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][1]; - get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][2] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][2]; - get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][3] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][3]; - } - - for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) - { - get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4 = - get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4; - - for(num_v6=0;num_v6< get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6;num_v6++) - { - get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6] = - get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6]; - get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6] = - get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6]; - } - } - } - - IPACMDBG_H(" %d wifi client deleted successfully \n", num_wifi_client); - num_wifi_client = num_wifi_client - 1; - IPACM_Wlan::total_num_wifi_clients = IPACM_Wlan::total_num_wifi_clients - 1; - IPACMDBG_H(" Number of wifi client: %d\n", num_wifi_client); - - return IPACM_SUCCESS; -} - -/*handle wlan iface down event*/ -int IPACM_Wlan::handle_down_evt() -{ - int res = IPACM_SUCCESS, i; - - IPACMDBG_H("WLAN ip-type: %d \n", ip_type); - /* no iface address up, directly close iface*/ - if (ip_type == IPACM_IP_NULL) - { - IPACMERR("Invalid iptype: 0x%x\n", ip_type); - goto fail; - } -#ifdef FEATURE_ETH_BRIDGE_LE - if(wlan_ap_index == 0) - { - IPACM_Lan::wlan_hdr_type = IPA_HDR_L2_NONE; - IPACM_Lan::wlan_hdr_template_hdl = 0; - del_hdr_proc_ctx(); - } -#endif - - /* delete wan filter rule */ - if (IPACM_Wan::isWanUP(ipa_if_num) && rx_prop != NULL) - { - IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); - IPACM_Lan::handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); - } - - if (IPACM_Wan::isWanUP_V6(ipa_if_num) && rx_prop != NULL) - { - IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); - IPACM_Lan::handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); - } - IPACMDBG_H("finished deleting wan filtering rules\n "); - - /* Delete v4 filtering rules */ - if (ip_type != IPA_IP_v6 && rx_prop != NULL) - { -#ifdef FEATURE_ETH_BRIDGE_LE - if(wlan_ap_index == 0) - { - /* delete default filter rules */ - for(i=0; iipa_num_private_subnet; i++) - { - if(reset_to_dummy_flt_rule(IPA_IP_v4, wlan_guest_ap_flt_rule_hdl_v4[i]) == IPACM_FAILURE) - { - IPACMERR("Error deleting wlan guest ap IPv4 flt rules.\n"); - res = IPACM_FAILURE; - goto fail; - } - } - } - IPACMDBG_H("Deleted guest ap v4 filter rules successfully.\n"); -#endif - - /* delete icmp filter rules */ - if(wlan_ap_index == 0) - { - if(m_filtering.DeleteFilteringHdls(ipv6_icmp_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE) == false) - { - IPACMERR("Error Deleting ICMPv6 Filtering Rule, aborting...\n"); - res = IPACM_FAILURE; - goto fail; - } - } -#ifndef FEATURE_ETH_BRIDGE_LE -#ifdef CT_OPT - IPACMDBG_H("Delete tcp control flt rules.\n"); - /* Delete tcp control flt rules */ - for(i=0; iipa_num_private_subnet; i++) - { - if(reset_to_dummy_flt_rule(IPA_IP_v4, private_fl_rule_hdl[i]) == IPACM_FAILURE) - { - IPACMERR("Error deleting private subnet IPv4 flt rules.\n"); - res = IPACM_FAILURE; - goto fail; - } - } - } - IPACMDBG_H("Deleted private subnet v4 filter rules successfully.\n"); -#endif - } - - /* Delete v6 filtering rules */ - if (ip_type != IPA_IP_v4 && rx_prop != NULL) - { - IPACMDBG_H("Delete default %d v6 filter rules\n", IPV6_DEFAULT_FILTERTING_RULES); - /* delete default filter rules */ -#ifdef FEATURE_ETH_BRIDGE_LE - if(wlan_ap_index == 0) - { - for(i=0; imac); - eth_bridge_del_self_client_flt_rule(get_client_memptr(wlan_client, i)->mac); - eth_bridge_post_lan_client_event(get_client_memptr(wlan_client, i)->mac, IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT); - eth_bridge_del_wlan_client_rt_rule(get_client_memptr(wlan_client, i)->mac, SRC_WLAN); - eth_bridge_del_wlan_client_rt_rule(get_client_memptr(wlan_client, i)->mac, SRC_USB); -#endif - /* First reset nat rules and then route rules */ - if(get_client_memptr(wlan_client, i)->ipv4_set == true) - { - IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wlan_client, i)->v4_addr); - CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, i)->v4_addr); - } - - if (delete_default_qos_rtrules(i, IPA_IP_v4)) - { - IPACMERR("unbale to delete v4 default qos route rules for index: %d\n", i); - res = IPACM_FAILURE; - goto fail; - } - - if (delete_default_qos_rtrules(i, IPA_IP_v6)) - { - IPACMERR("unbale to delete v6 default qos route rules for index: %d\n", i); - res = IPACM_FAILURE; - goto fail; - } - - IPACMDBG_H("Delete %d client header\n", num_wifi_client); - - handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v4); - handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v6); - - if(get_client_memptr(wlan_client, i)->ipv4_header_set == true) - { - if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, i)->hdr_hdl_v4) - == false) - { - res = IPACM_FAILURE; - goto fail; - } - } - - if(get_client_memptr(wlan_client, i)->ipv6_header_set == true) - { - if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, i)->hdr_hdl_v6) - == false) - { - res = IPACM_FAILURE; - goto fail; - } - } - } /* end of for loop */ - - /* free the wlan clients cache */ - IPACMDBG_H("Free wlan clients cache\n"); - - /* Delete private subnet*/ -#ifdef FEATURE_IPA_ANDROID - if (ip_type != IPA_IP_v6) - { - IPACMDBG_H("current IPACM private subnet_addr number(%d)\n", IPACM_Iface::ipacmcfg->ipa_num_private_subnet); - IPACMDBG_H(" Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); - if(IPACM_Iface::ipacmcfg->DelPrivateSubnet(if_ipv4_subnet, ipa_if_num) == false) - { - IPACMERR(" can't Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); - } - } - /* reset the IPA-client pipe enum */ - handle_tethering_client(true, IPACM_CLIENT_WLAN); -#endif /* defined(FEATURE_IPA_ANDROID)*/ - -fail: - /* Delete corresponding ipa_rm_resource_name of RX-endpoint after delete all IPV4V6 FT-rule */ - if (rx_prop != NULL) - { - IPACMDBG_H("dev %s add producer dependency\n", dev_name); - IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); - IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); - free(rx_prop); - } - - for (i = 0; i < num_wifi_client; i++) - { - if(get_client_memptr(wlan_client, i)->p_hdr_info != NULL) - { - free(get_client_memptr(wlan_client, i)->p_hdr_info); - } - } - if(wlan_client != NULL) - { - free(wlan_client); - } - if (tx_prop != NULL) - { - free(tx_prop); - } - - if (iface_query != NULL) - { - free(iface_query); - } -#ifdef FEATURE_ETH_BRIDGE_LE - if(eth_bridge_usb_client_rt_info_v4 != NULL) - { - free(eth_bridge_usb_client_rt_info_v4); - } - if(eth_bridge_usb_client_rt_info_v6 != NULL) - { - free(eth_bridge_usb_client_rt_info_v6); - } - if(eth_bridge_wlan_client_rt_from_usb_info_v4 != NULL) - { - free(eth_bridge_wlan_client_rt_from_usb_info_v4); - } - if(eth_bridge_wlan_client_rt_from_usb_info_v6 != NULL) - { - free(eth_bridge_wlan_client_rt_from_usb_info_v6); - } - if(eth_bridge_wlan_client_rt_from_wlan_info_v4 != NULL) - { - free(eth_bridge_wlan_client_rt_from_wlan_info_v4); - } - if(eth_bridge_wlan_client_rt_from_wlan_info_v6 != NULL) - { - free(eth_bridge_wlan_client_rt_from_wlan_info_v6); - } -#endif - is_active = false; - post_del_self_evt(); - - return res; -} - -/*handle reset wifi-client rt-rules */ -int IPACM_Wlan::handle_wlan_client_reset_rt(ipa_ip_type iptype) -{ - int i, res = IPACM_SUCCESS; - - /* clean wifi-client routing rules */ - IPACMDBG_H("left %d wifi clients to reset ip-type(%d) rules \n ", num_wifi_client, iptype); - - for (i = 0; i < num_wifi_client; i++) - { - /* Reset RT rules */ - res = delete_default_qos_rtrules(i, iptype); - if (res != IPACM_SUCCESS) - { - IPACMERR("Failed to delete old iptype(%d) rules.\n", iptype); - return res; - } - /* Pass info to LAN2LAN module */ - res = handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT, iptype); - if (res != IPACM_SUCCESS) - { - IPACMERR("Failed to posting delete old iptype(%d) address.\n", iptype); - return res; - } - /* Reset ip-address */ - if(iptype == IPA_IP_v4) - { - get_client_memptr(wlan_client, i)->ipv4_set = false; - } - else - { - get_client_memptr(wlan_client, i)->ipv6_set = 0; - } - } /* end of for loop */ - return res; -} - -/*handle lan2lan internal mesg posting*/ -int IPACM_Wlan::handle_lan2lan_msg_post(uint8_t *mac_addr, ipa_cm_event_id event,ipa_ip_type iptype) -{ - int client_index; - client_index = get_wlan_client_index(mac_addr); - if (client_index == IPACM_INVALID_INDEX) - { - IPACMDBG_H("wlan client not attached\n"); - return IPACM_SUCCESS; - } - - ipacm_event_lan_client* lan_client; - ipacm_cmd_q_data evt_data; - if((get_client_memptr(wlan_client, client_index)->ipv4_set == true) - && (iptype == IPA_IP_v4)) /* handle ipv4 case*/ - { - if(ip_type != IPA_IP_v4 && ip_type != IPA_IP_MAX) - { - IPACMERR("Client has IPv4 addr but iface does not have IPv4 up.\n"); - return IPACM_FAILURE; - } - - lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); - if(lan_client == NULL) - { - IPACMERR("Unable to allocate memory.\n"); - return IPACM_FAILURE; - } - memset(lan_client, 0, sizeof(ipacm_event_lan_client)); - - lan_client->iptype = IPA_IP_v4; - lan_client->ipv4_addr = get_client_memptr(wlan_client, client_index)->v4_addr; - lan_client->p_iface = this; - - memset(&evt_data, 0, sizeof(evt_data)); - evt_data.event = event; - evt_data.evt_data = (void*)lan_client; - - IPACMDBG_H("Posting event: %d\n",event); - IPACM_EvtDispatcher::PostEvt(&evt_data); - } - - if((get_client_memptr(wlan_client, client_index)->ipv6_set > 0) - && (iptype == IPA_IP_v6)) /* handle v6 case: may be multiple v6 addr */ - { - if(ip_type != IPA_IP_v6 && ip_type != IPA_IP_MAX) + len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add)); + pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len); + if (pHeaderDescriptor == NULL) { - IPACMERR("Client has IPv6 addr but iface does not have IPv6 up.\n"); + IPACMERR("calloc failed to allocate pHeaderDescriptor\n"); return IPACM_FAILURE; } - int i; - - for(i=0; iipv6_set; i++) - { - lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); - if(lan_client == NULL) - { - IPACMERR("Unable to allocate memory.\n"); - return IPACM_FAILURE; - } - memset(lan_client, 0, sizeof(ipacm_event_lan_client)); - - lan_client->iptype = IPA_IP_v6; - memcpy(lan_client->ipv6_addr, get_client_memptr(wlan_client, client_index)->v6_addr[i], 4*sizeof(uint32_t)); - lan_client->p_iface = this; - - memset(&evt_data, 0, sizeof(evt_data)); - evt_data.event = event; - evt_data.evt_data = (void*)lan_client; - - IPACMDBG_H("Posting event: %d\n",event); - IPACM_EvtDispatcher::PostEvt(&evt_data); - } - } - return IPACM_SUCCESS; -} - -int IPACM_Wlan::add_lan2lan_hdr(ipa_ip_type iptype, uint8_t* src_mac, uint8_t* dst_mac, uint32_t* hdr_hdl) -{ - if(tx_prop == NULL) - { - IPACMERR("There is no tx_prop, cannot add header.\n"); - return IPACM_FAILURE; - } - if(src_mac == NULL || dst_mac == NULL) - { - IPACMERR("Either src_mac or dst_mac is null, cannot add header.\n"); - return IPACM_FAILURE; - } - if(hdr_hdl == NULL) - { - IPACMERR("Header handle is empty.\n"); - return IPACM_FAILURE; - } - int i, j, k, len; - int res = IPACM_SUCCESS; - char index[4]; - struct ipa_ioc_copy_hdr sCopyHeader; - struct ipa_ioc_add_hdr *pHeader; - - IPACMDBG_H("Get lan2lan header request, src_mac: 0x%02x%02x%02x%02x%02x%02x dst_mac: 0x%02x%02x%02x%02x%02x%02x\n", - src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], dst_mac[0], dst_mac[1], - dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]); - - len = sizeof(struct ipa_ioc_add_hdr) + sizeof(struct ipa_hdr_add); - pHeader = (struct ipa_ioc_add_hdr *)malloc(len); - if (pHeader == NULL) - { - IPACMERR("Failed to allocate header\n"); - return IPACM_FAILURE; - } - memset(pHeader, 0, len); + evt_size = sizeof(ipacm_event_data_wlan_ex) + data->num_of_attribs * sizeof(struct ipa_wlan_hdr_attrib_val); + get_client_memptr(wlan_client, num_wifi_client)->p_hdr_info = (ipacm_event_data_wlan_ex*)malloc(evt_size); + memcpy(get_client_memptr(wlan_client, num_wifi_client)->p_hdr_info, data, evt_size); - if(iptype == IPA_IP_v4) - { /* copy partial header for v4*/ - for(i=0; inum_tx_props; i++) + /* copy partial header for v4*/ + for (cnt=0; cntnum_tx_props; cnt++) { - if(tx_prop->tx[i].ip == IPA_IP_v4) + if(tx_prop->tx[cnt].ip==IPA_IP_v4) { - IPACMDBG_H("Got v4-header name from %d tx props\n", i); + IPACMDBG_H("Got partial v4-header name from %d tx props\n", cnt); memset(&sCopyHeader, 0, sizeof(sCopyHeader)); - memcpy(sCopyHeader.name, tx_prop->tx[i].hdr_name, sizeof(sCopyHeader.name)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); - IPACMDBG_H("Header name: %s\n", sCopyHeader.name); - if(m_header.CopyHeader(&sCopyHeader) == false) + IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) { - IPACMERR("Copy header failed\n"); + PERROR("ioctl copy header failed"); res = IPACM_FAILURE; goto fail; } - IPACMDBG_H("Header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) { - IPACMERR("Header oversize\n"); + IPACMERR("header oversize\n"); res = IPACM_FAILURE; goto fail; } else { - memcpy(pHeader->hdr[0].hdr, sCopyHeader.hdr, sCopyHeader.hdr_len); + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); } - for(j=0; jmac, IPA_MAC_ADDR_SIZE) == 0) - { - break; - } - } - if(j == num_wifi_client) - { - IPACMERR("Not able to find the wifi client from mac addr.\n"); - res = IPACM_FAILURE; - goto fail; - } - else + for(i = 0; i < data->num_of_attribs; i++) { - IPACMDBG_H("Find wifi client at position %d\n", j); - for(k = 0; k < get_client_memptr(wlan_client, j)->p_hdr_info->num_of_attribs; k++) + if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) { - if(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) - { - memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset], - dst_mac, IPA_MAC_ADDR_SIZE); - memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset + IPA_MAC_ADDR_SIZE], - src_mac, IPA_MAC_ADDR_SIZE); - } - else if(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].attrib_type == WLAN_HDR_ATTRIB_STA_ID) - { - memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset], - &get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].u.sta_id, - sizeof(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].u.sta_id)); - } - else + memcpy(get_client_memptr(wlan_client, num_wifi_client)->mac, + data->attribs[i].u.mac_addr, + sizeof(get_client_memptr(wlan_client, num_wifi_client)->mac)); + + /* copy client mac_addr to partial header */ + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], + get_client_memptr(wlan_client, num_wifi_client)->mac, + IPA_MAC_ADDR_SIZE); + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) { - IPACMDBG_H("The attribute type is not expected!\n"); + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); } - } - } - - pHeader->commit = true; - pHeader->num_hdrs = 1; - - memset(pHeader->hdr[0].name, 0, sizeof(pHeader->hdr[0].name)); - strlcpy(pHeader->hdr[0].name, IPA_LAN_TO_LAN_WLAN_HDR_NAME_V4, sizeof(pHeader->hdr[0].name)); - - for(j=0; jhdr[0].name, index, sizeof(pHeader->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) - { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeader->hdr[0].name)); - res = IPACM_FAILURE; - goto fail; - } - - pHeader->hdr[0].hdr_len = sCopyHeader.hdr_len; - pHeader->hdr[0].is_partial = 0; - pHeader->hdr[0].hdr_hdl = -1; - pHeader->hdr[0].status = -1; - - if (m_header.AddHeader(pHeader) == false || pHeader->hdr[0].status != 0) - { - IPACMERR("Ioctl IPA_IOC_ADD_HDR failed with status: %d\n", pHeader->hdr[0].status); - res = IPACM_FAILURE; - goto fail; - } - IPACMDBG_H("Installed v4 full header %s header handle 0x%08x\n", pHeader->hdr[0].name, - pHeader->hdr[0].hdr_hdl); - *hdr_hdl = pHeader->hdr[0].hdr_hdl; - lan2lan_hdr_hdl_v4[j].hdr_hdl = pHeader->hdr[0].hdr_hdl; - break; - } - } - } - else if(iptype == IPA_IP_v6) - { /* copy partial header for v6*/ - for(i=0; inum_tx_props; i++) - { - if(tx_prop->tx[i].ip == IPA_IP_v6) - { - IPACMDBG_H("Got v6-header name from %d tx props\n", i); - memset(&sCopyHeader, 0, sizeof(sCopyHeader)); - memcpy(sCopyHeader.name, tx_prop->tx[i].hdr_name, sizeof(sCopyHeader.name)); - - IPACMDBG_H("Header name: %s\n", sCopyHeader.name); - if(m_header.CopyHeader(&sCopyHeader) == false) - { - IPACMERR("Copy header failed\n"); - res = IPACM_FAILURE; - goto fail; - } - - IPACMDBG_H("Header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); - if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) - { - IPACMERR("Header oversize\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - memcpy(pHeader->hdr[0].hdr, sCopyHeader.hdr, sCopyHeader.hdr_len); - } - for(j=0; jmac, IPA_MAC_ADDR_SIZE) == 0) + } + else if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID) { - break; + /* copy client id to header */ + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], + &data->attribs[i].u.sta_id, sizeof(data->attribs[i].u.sta_id)); } - } - if(j == num_wifi_client) - { - IPACMERR("Not able to find the wifi client from mac addr.\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - IPACMDBG_H("Find wifi client at position %d\n", j); - for(k = 0; k < get_client_memptr(wlan_client, j)->p_hdr_info->num_of_attribs; k++) + else { - if(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) - { - memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset], - dst_mac, IPA_MAC_ADDR_SIZE); - memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset + IPA_MAC_ADDR_SIZE], - src_mac, IPA_MAC_ADDR_SIZE); - } - else if(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].attrib_type == WLAN_HDR_ATTRIB_STA_ID) - { - memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset], - &get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].u.sta_id, - sizeof(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].u.sta_id)); - } - else - { - IPACMDBG_H("The attribute type is not expected!\n"); - } + IPACMDBG_H("The attribute type is not expected!\n"); } } - pHeader->commit = true; - pHeader->num_hdrs = 1; + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; - memset(pHeader->hdr[0].name, 0, sizeof(pHeader->hdr[0].name)); - strlcpy(pHeader->hdr[0].name, IPA_LAN_TO_LAN_WLAN_HDR_NAME_V6, sizeof(pHeader->hdr[0].name)); + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + snprintf(index,sizeof(index), "%d", ipa_if_num); + strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; - for(j=0; jhdr[0].name, IPA_WLAN_PARTIAL_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) { - IPACMERR("Failed to find an available hdr index.\n"); + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); res = IPACM_FAILURE; goto fail; } - lan2lan_hdr_hdl_v6[j].valid = true; - snprintf(index,sizeof(index), "%d", j); - - if (strlcat(pHeader->hdr[0].name, index, sizeof(pHeader->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + snprintf(index,sizeof(index), "%d", header_name_count); + if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) { - IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeader->hdr[0].name)); + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); res = IPACM_FAILURE; goto fail; } - pHeader->hdr[0].hdr_len = sCopyHeader.hdr_len; - pHeader->hdr[0].is_partial = 0; - pHeader->hdr[0].hdr_hdl = -1; - pHeader->hdr[0].status = -1; - if (m_header.AddHeader(pHeader) == false || pHeader->hdr[0].status != 0) + + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) { - IPACMERR("Ioctl IPA_IOC_ADD_HDR failed with status: %d\n", pHeader->hdr[0].status); + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); res = IPACM_FAILURE; goto fail; } - IPACMDBG_H("Installed v6 full header %s header handle 0x%08x\n", pHeader->hdr[0].name, - pHeader->hdr[0].hdr_hdl); - *hdr_hdl = pHeader->hdr[0].hdr_hdl; - lan2lan_hdr_hdl_v6[j].hdr_hdl = pHeader->hdr[0].hdr_hdl; + + get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("client(%d) v4 full header name:%s header handle:(0x%x)\n", + num_wifi_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v4); + get_client_memptr(wlan_client, num_wifi_client)->ipv4_header_set=true; break; } } - } - else - { - IPACMERR("IP type is not expected.\n"); - } - -fail: - free(pHeader); - return res; -} - -/* add dummy filtering rules for WLAN AP-AP mode support */ -void IPACM_Wlan::add_dummy_flt_rule() -{ - int num_v4_dummy_rule, num_v6_dummy_rule; - - if(IPACM_Wlan::num_wlan_ap_iface == 1) - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v4 != NULL || IPACM_Wlan::dummy_flt_rule_hdl_v6 != NULL) - { - IPACMERR("Either v4 or v6 dummy filtering rule handle is not empty.\n"); - return; - } -#ifdef FEATURE_ETH_BRIDGE_LE - num_v4_dummy_rule = IPV4_DEFAULT_FILTERTING_RULES + IPACM_Iface::ipacmcfg->ipa_num_private_subnet + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; - num_v6_dummy_rule = IPV6_DEFAULT_FILTERTING_RULES + 1 + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT; -#else -#ifndef CT_OPT - num_v4_dummy_rule = 2*(IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); - num_v6_dummy_rule = 2*(IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR); -#else - num_v4_dummy_rule = 2*(IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); - num_v6_dummy_rule = 2*(IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR); -#endif -#ifdef FEATURE_IPA_ANDROID - num_v4_dummy_rule = num_v4_dummy_rule - 2* IPACM_Iface::ipacmcfg->ipa_num_private_subnet + 2 * IPA_MAX_PRIVATE_SUBNET_ENTRIES; -#endif -#endif - - IPACM_Wlan::dummy_flt_rule_hdl_v4 = (uint32_t*)malloc(num_v4_dummy_rule * sizeof(uint32_t)); - if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) - { - IPACMERR("Failed to allocate memory.\n"); - return; - } - IPACM_Wlan::dummy_flt_rule_hdl_v6 = (uint32_t*)malloc(num_v6_dummy_rule * sizeof(uint32_t)); - if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) - { - IPACMERR("Failed to allocate memory.\n"); - free(IPACM_Wlan::dummy_flt_rule_hdl_v4); - IPACM_Wlan::dummy_flt_rule_hdl_v4 = NULL; - return; - } - memset(IPACM_Wlan::dummy_flt_rule_hdl_v4, 0, num_v4_dummy_rule * sizeof(uint32_t)); - memset(IPACM_Wlan::dummy_flt_rule_hdl_v6, 0, num_v6_dummy_rule * sizeof(uint32_t)); - - install_dummy_flt_rule(IPA_IP_v4, num_v4_dummy_rule); - install_dummy_flt_rule(IPA_IP_v6, num_v6_dummy_rule); - } - return; -} - -/* install dummy filtering rules for WLAN AP-AP mode support */ -int IPACM_Wlan::install_dummy_flt_rule(ipa_ip_type iptype, int num_rule) -{ - if(rx_prop == NULL) - { - IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy filtering rule.\n", dev_name); - return IPACM_FAILURE; - } - - int i, len, res = IPACM_SUCCESS; - struct ipa_flt_rule_add flt_rule; - ipa_ioc_add_flt_rule* pFilteringTable; - - len = sizeof(struct ipa_ioc_add_flt_rule) + num_rule * sizeof(struct ipa_flt_rule_add); - - pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); - if (pFilteringTable == NULL) - { - IPACMERR("Error allocate flt table memory...\n"); - return IPACM_FAILURE; - } - memset(pFilteringTable, 0, len); - - pFilteringTable->commit = 1; - pFilteringTable->ep = rx_prop->rx[0].src_pipe; - pFilteringTable->global = false; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = num_rule; - - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); - - flt_rule.rule.retain_hdr = 0; - flt_rule.at_rear = true; - flt_rule.flt_rule_hdl = -1; - flt_rule.status = -1; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, - sizeof(flt_rule.rule.attrib)); - - if(iptype == IPA_IP_v4) - { - flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; - flt_rule.rule.attrib.u.v4.src_addr = ~0; - flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; - flt_rule.rule.attrib.u.v4.dst_addr = ~0; - - for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); - } - if (false == m_filtering.AddFilteringRule(pFilteringTable)) - { - IPACMERR("Error adding dummy ipv4 flt rule\n"); - res = IPACM_FAILURE; - goto fail; - } - else + /* copy partial header for v6*/ + for (cnt=0; cntnum_tx_props; cnt++) { - /* copy filter rule hdls */ - for (int i = 0; i < num_rule; i++) + if(tx_prop->tx[cnt].ip==IPA_IP_v6) { - if (pFilteringTable->rules[i].status == 0) - { - IPACM_Wlan::dummy_flt_rule_hdl_v4[i] = pFilteringTable->rules[i].flt_rule_hdl; - IPACMDBG("Dummy v4 flt rule %d hdl:0x%x\n", i, IPACM_Wlan::dummy_flt_rule_hdl_v4[i]); - } - else + IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) { - IPACMERR("Failed adding dummy v4 flt rule %d\n", i); + PERROR("ioctl copy header failed"); res = IPACM_FAILURE; goto fail; } - } - } - } - else if(iptype == IPA_IP_v6) - { - flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; - flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; - flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; - flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; - - for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); - } - if (false == m_filtering.AddFilteringRule(pFilteringTable)) - { - IPACMERR("Error adding dummy ipv6 flt rule\n"); - res = IPACM_FAILURE; - goto fail; - } - else - { - /* copy filter rule hdls */ - for (int i = 0; i < num_rule; i++) - { - if (pFilteringTable->rules[i].status == 0) - { - IPACM_Wlan::dummy_flt_rule_hdl_v6[i] = pFilteringTable->rules[i].flt_rule_hdl; - IPACMDBG("Lan2lan v6 flt rule %d hdl:0x%x\n", i, IPACM_Wlan::dummy_flt_rule_hdl_v6[i]); - } - else + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) { - IPACMERR("Failed adding v6 flt rule %d\n", i); + IPACMERR("header oversize\n"); res = IPACM_FAILURE; goto fail; - } - } - } - } - else - { - IPACMERR("IP type is not expected.\n"); - goto fail; - } - -fail: - free(pFilteringTable); - return res; -} - -/* delete dummy flt rule for WLAN AP-AP mode support*/ -void IPACM_Wlan::del_dummy_flt_rule() -{ - int num_v4_dummy_rule, num_v6_dummy_rule; - - if(IPACM_Wlan::num_wlan_ap_iface == 0) - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL || IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) - { - IPACMERR("Either v4 or v6 dummy flt rule is empty.\n"); - return; - } -#ifndef CT_OPT - num_v4_dummy_rule = 2*(IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); - num_v6_dummy_rule = 2*(IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR); -#else - num_v4_dummy_rule = 2*(IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); - num_v6_dummy_rule = 2*(IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR); -#endif -#ifdef FEATURE_IPA_ANDROID - num_v4_dummy_rule = num_v4_dummy_rule - 2* IPACM_Iface::ipacmcfg->ipa_num_private_subnet + 2 * IPA_MAX_PRIVATE_SUBNET_ENTRIES; -#endif - -#ifdef FEATURE_ETH_BRIDGE_LE - num_v4_dummy_rule = IPV4_DEFAULT_FILTERTING_RULES + IPACM_Iface::ipacmcfg->ipa_num_private_subnet + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; - num_v6_dummy_rule = IPV6_DEFAULT_FILTERTING_RULES + 1 + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT; -#endif - - if(m_filtering.DeleteFilteringHdls(IPACM_Wlan::dummy_flt_rule_hdl_v4, IPA_IP_v4, num_v4_dummy_rule) == false) - { - IPACMERR("Failed to delete ipv4 dummy flt rules.\n"); - return; - } - if(m_filtering.DeleteFilteringHdls(IPACM_Wlan::dummy_flt_rule_hdl_v6, IPA_IP_v6, num_v6_dummy_rule) == false) - { - IPACMERR("Failed to delete ipv6 dummy flt rules.\n"); - return; - } - - free(IPACM_Wlan::dummy_flt_rule_hdl_v4); - IPACM_Wlan::dummy_flt_rule_hdl_v4 = NULL; - free(IPACM_Wlan::dummy_flt_rule_hdl_v6); - IPACM_Wlan::dummy_flt_rule_hdl_v6 = NULL; -#ifdef FEATURE_ETH_BRIDGE_LE - memset(self_client_flt_rule_hdl_v4, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); - memset(self_client_flt_rule_hdl_v6, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); - memset(usb_client_flt_rule_hdl_v4, 0, IPA_LAN_TO_LAN_MAX_USB_CLIENT * sizeof(lan2lan_flt_rule_hdl)); - memset(usb_client_flt_rule_hdl_v6, 0, IPA_LAN_TO_LAN_MAX_USB_CLIENT * sizeof(lan2lan_flt_rule_hdl)); -#endif - } - return; -} - -/* install TCP control filter rules */ -void IPACM_Wlan::install_tcp_ctl_flt_rule(ipa_ip_type iptype) -{ - if (rx_prop == NULL) - { - IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); - return; - } - - int i, len, res = IPACM_SUCCESS, offset; - struct ipa_flt_rule_mdfy flt_rule; - struct ipa_ioc_mdfy_flt_rule* pFilteringTable; - - if (iptype == IPA_IP_v4) - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) - { - IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); - return; - } - offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); -#ifdef FEATURE_IPA_ANDROID - offset = offset + wlan_ap_index * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); -#endif - } - else - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) - { - IPACMERR("Dummy ipv6 flt rule has not been installed.\n"); - return; - } - offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR); - } - - len = sizeof(struct ipa_ioc_mdfy_flt_rule) + NUM_TCP_CTL_FLT_RULE * sizeof(struct ipa_flt_rule_mdfy); - pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); - if (!pFilteringTable) - { - IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); - return; - } - memset(pFilteringTable, 0, len); - - pFilteringTable->commit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = NUM_TCP_CTL_FLT_RULE; - - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - flt_rule.status = -1; - - flt_rule.rule.retain_hdr = 1; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - flt_rule.rule.eq_attrib_type = 1; - - flt_rule.rule.eq_attrib.rule_eq_bitmap = 0; - - flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<14); - flt_rule.rule.eq_attrib.metadata_meq32_present = 1; - flt_rule.rule.eq_attrib.metadata_meq32.offset = 0; - flt_rule.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data; - flt_rule.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask; - - flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<1); - flt_rule.rule.eq_attrib.protocol_eq_present = 1; - flt_rule.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; - - /* add TCP FIN rule*/ - flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<8); - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - /* add TCP SYN rule*/ - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[1]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - /* add TCP RST rule*/ - flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[2]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) - { - IPACMERR("Failed to modify tcp control filtering rules.\n"); - goto fail; - } - else - { - if(iptype == IPA_IP_v4) - { - for(i=0; irules[i].rule_hdl; - } - } - else - { - for(i=0; irules[i].rule_hdl; - } - } - } - -fail: - free(pFilteringTable); - return; -} - -int IPACM_Wlan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype) -{ - if(rx_prop == NULL) - { - IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy lan2lan filtering rule.\n", dev_name); - return IPACM_FAILURE; - } - - int offset; - if(iptype == IPA_IP_v4) - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) - { - IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); - return IPACM_FAILURE; - } + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } -#ifndef CT_OPT - offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) - + IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR; -#else - offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) - + IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + NUM_TCP_CTL_FLT_RULE; -#endif + for(i = 0; i < data->num_of_attribs; i++) + { + if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + memcpy(get_client_memptr(wlan_client, num_wifi_client)->mac, + data->attribs[i].u.mac_addr, + sizeof(get_client_memptr(wlan_client, num_wifi_client)->mac)); -#ifdef FEATURE_IPA_ANDROID - offset = offset + wlan_ap_index * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); -#endif - for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++) - { - private_fl_rule_hdl[i] = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+i]; - IPACMDBG_H("Private subnet v4 flt rule %d hdl:0x%x\n", i, private_fl_rule_hdl[i]); - } - } - return IPACM_SUCCESS; -} + /* copy client mac_addr to partial header */ + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], + get_client_memptr(wlan_client, num_wifi_client)->mac, + IPA_MAC_ADDR_SIZE); -int IPACM_Wlan::eth_bridge_add_wlan_guest_ap_flt_rule(ipa_ip_type iptype) -{ - if(rx_prop == NULL) - { - IPACMDBG_H("There is no rx_prop for iface %s, not able to add wlan guest ap filtering rule.\n", dev_name); - return IPACM_SUCCESS; - } - if(is_guest_ap == false) - { - IPACMDBG_H("This is not WLAN guest AP, do nothing.\n"); - return IPACM_SUCCESS; - } + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } + } + else if (data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID) + { + /* copy client id to header */ + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], + &data->attribs[i].u.sta_id, sizeof(data->attribs[i].u.sta_id)); + } + else + { + IPACMDBG_H("The attribute type is not expected!\n"); + } + } - int len, i, offset, res = IPACM_SUCCESS; - struct ipa_flt_rule_mdfy flt_rule; - struct ipa_ioc_mdfy_flt_rule* pFilteringTable = NULL; - if(iptype == IPA_IP_v4) - { - if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) - { - IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); - return IPACM_FAILURE; - } + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; - offset = IPV4_DEFAULT_FILTERTING_RULES; - len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_mdfy); - pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); - if (!pFilteringTable) - { - IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); - return IPACM_FAILURE; - } - memset(pFilteringTable, 0, len); + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); - pFilteringTable->commit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + snprintf(index,sizeof(index), "%d", ipa_if_num); + strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WLAN_PARTIAL_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - flt_rule.status = -1; + snprintf(index,sizeof(index), "%d", header_name_count); + if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } - flt_rule.rule.retain_hdr = 1; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - flt_rule.rule.eq_attrib_type = 0; + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } - for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++) - { - flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+i]; - flt_rule.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask; - flt_rule.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr; - memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - } + get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("client(%d) v6 full header name:%s header handle:(0x%x)\n", + num_wifi_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v6); - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) - { - IPACMERR("Failed to modify wlan guest AP IPv4 filtering rules.\n"); - res = IPACM_FAILURE; - goto fail; + get_client_memptr(wlan_client, num_wifi_client)->ipv6_header_set=true; + break; + } } - /* copy filter rule hdls */ - for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++) - { - wlan_guest_ap_flt_rule_hdl_v4[i] = pFilteringTable->rules[i].rule_hdl; - } + /* initialize wifi client*/ + get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v4 = false; + get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v6 = 0; + get_client_memptr(wlan_client, num_wifi_client)->ipv4_set = false; + get_client_memptr(wlan_client, num_wifi_client)->ipv6_set = 0; + get_client_memptr(wlan_client, num_wifi_client)->power_save_set=false; + num_wifi_client++; + header_name_count++; //keep increasing header_name_count + IPACM_Wlan::total_num_wifi_clients++; + res = IPACM_SUCCESS; + IPACMDBG_H("Wifi client number: %d\n", num_wifi_client); } else { - if(IPACM_Wan::wan_up_v6 == true) - { - eth_bridge_install_wlan_guest_ap_ipv6_flt_rule(); - } + return res; } + fail: - if(pFilteringTable != NULL) - { - free(pFilteringTable); - } + free(pHeaderDescriptor); return res; } -int IPACM_Wlan::eth_bridge_install_wlan_guest_ap_ipv6_flt_rule() +/*handle wifi client */ +int IPACM_Wlan::handle_wlan_client_ipaddr(ipacm_event_data_all *data) { - if(rx_prop == NULL) - { - IPACMDBG_H("There is no rx_prop for iface %s, not able to add wlan guest ap filtering rule.\n", dev_name); - return IPACM_SUCCESS; - } - if(is_guest_ap == false) - { - IPACMDBG_H("This is not WLAN guest AP, do nothing.\n"); - return IPACM_SUCCESS; - } - - int len, offset, res = IPACM_SUCCESS; - struct ipa_flt_rule_mdfy flt_rule; - struct ipa_ioc_mdfy_flt_rule* pFilteringTable = NULL; - - if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) - { - IPACMERR("Dummy ipv6 flt rule has not been installed.\n"); - return IPACM_FAILURE; - } + int clnt_indx; + int v6_num; + uint32_t ipv6_link_local_prefix = 0xFE800000; + uint32_t ipv6_link_local_prefix_mask = 0xFFC00000; - offset = 0; - len = sizeof(struct ipa_ioc_mdfy_flt_rule) + sizeof(struct ipa_flt_rule_mdfy); - pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); - if (!pFilteringTable) - { - IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); - return IPACM_FAILURE; - } - memset(pFilteringTable, 0, len); - - pFilteringTable->commit = 1; - pFilteringTable->ip = IPA_IP_v6; - pFilteringTable->num_rules = 1; - - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - flt_rule.status = -1; - - flt_rule.rule.retain_hdr = 1; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; - flt_rule.rule.eq_attrib_type = 0; - - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - flt_rule.rule.attrib.u.v6.dst_addr[0] = IPACM_Wan::backhaul_ipv6_prefix[0]; - flt_rule.rule.attrib.u.v6.dst_addr[1] = IPACM_Wan::backhaul_ipv6_prefix[1]; - flt_rule.rule.attrib.u.v6.dst_addr[2] = 0x0; - flt_rule.rule.attrib.u.v6.dst_addr[3] = 0x0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; - flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; - flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0x0; - flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0x0; - - flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset]; - memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) - { - IPACMERR("Failed to modify wlan guest AP IPv6 filtering rules.\n"); - res = IPACM_FAILURE; - goto fail; - } + IPACMDBG_H("number of wifi clients: %d\n", num_wifi_client); + IPACMDBG_H(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + data->mac_addr[0], + data->mac_addr[1], + data->mac_addr[2], + data->mac_addr[3], + data->mac_addr[4], + data->mac_addr[5]); - /* copy filter rule hdls */ - wlan_guest_ap_flt_rule_hdl_v6 = pFilteringTable->rules[0].rule_hdl; + clnt_indx = get_wlan_client_index(data->mac_addr); -fail: - if(pFilteringTable != NULL) - { - free(pFilteringTable); - } - return res; -} + if (clnt_indx == IPACM_INVALID_INDEX) + { + IPACMERR("wlan client not found/attached \n"); + return IPACM_FAILURE; + } -int IPACM_Wlan::eth_bridge_handle_dummy_wlan_client_flt_rule(ipa_ip_type iptype) -{ - int i, offset; - if(wlan_ap_index == 0) + IPACMDBG_H("Ip-type received %d\n", data->iptype); + if (data->iptype == IPA_IP_v4) { - if(iptype == IPA_IP_v4) + IPACMDBG_H("ipv4 address: 0x%x\n", data->ipv4_addr); + if (data->ipv4_addr != 0) /* not 0.0.0.0 */ { - offset = IPV4_DEFAULT_FILTERTING_RULES + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; - for(i=0; iipv4_set == false) { - self_client_flt_rule_hdl_v4[i].rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+i]; - self_client_flt_rule_hdl_v4[i].valid = true; + get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr; + get_client_memptr(wlan_client, clnt_indx)->ipv4_set = true; } - } - else - { - offset = 1; - for(i=0; iipv4_addr == get_client_memptr(wlan_client, clnt_indx)->v4_addr) + { + IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx); + return IPACM_FAILURE; + } + else + { + IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx); + /* delete NAT rules first */ + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clnt_indx)->v4_addr); + delete_default_qos_rtrules(clnt_indx,IPA_IP_v4); + get_client_memptr(wlan_client, clnt_indx)->route_rule_set_v4 = false; + get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr; } } - IPACMDBG_H("Get %d flt rule hdls for wlan clients ip type: %d.\n", IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, iptype); } - return IPACM_SUCCESS; -} - -int IPACM_Wlan::eth_bridge_handle_dummy_usb_client_flt_rule(ipa_ip_type iptype) -{ - int i, offset; - if(wlan_ap_index == 0) + else { - if(iptype == IPA_IP_v4) - { - offset = IPV4_DEFAULT_FILTERTING_RULES + IPACM_Iface::ipacmcfg->ipa_num_private_subnet + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; - for(i=0; iipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) || + (data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) /* check if all 0 not valid ipv6 address */ { - offset = 1 + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; - for(i=0; iipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + if( (data->ipv6_addr[0] & ipv6_link_local_prefix_mask) != (ipv6_link_local_prefix & ipv6_link_local_prefix_mask) && + memcmp(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix)) != 0) { - usb_client_flt_rule_hdl_v6[i].rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset+i]; - usb_client_flt_rule_hdl_v6[i].valid = true; + IPACMDBG_H("This IPv6 address is not global IPv6 address with correct prefix, ignore.\n"); + return IPACM_FAILURE; } + + if(get_client_memptr(wlan_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR) + { + + for(v6_num=0;v6_num < get_client_memptr(wlan_client, clnt_indx)->ipv6_set;v6_num++) + { + if( data->ipv6_addr[0] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][0] && + data->ipv6_addr[1] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][1] && + data->ipv6_addr[2]== get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][2] && + data->ipv6_addr[3] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][3]) + { + IPACMDBG_H("Already see this ipv6 addr for client:%d\n", clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ + break; + } + } + + /* not see this ipv6 before for wifi client*/ + get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0]; + get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1]; + get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2]; + get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3]; + get_client_memptr(wlan_client, clnt_indx)->ipv6_set++; + } + else + { + IPACMDBG_H("Already got %d ipv6 addr for client:%d\n", IPV6_NUM_ADDR, clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ + } } - IPACMDBG_H("Get %d flt rule hdls for usb clients ip type: %d.\n", IPA_LAN_TO_LAN_MAX_USB_CLIENT, iptype); } + return IPACM_SUCCESS; } -int IPACM_Wlan::eth_bridge_add_usb_client_flt_rule(uint8_t* mac, ipa_ip_type iptype) +/*handle wifi client routing rule*/ +int IPACM_Wlan::handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype) { - int i, len, res = IPACM_SUCCESS, client_position; - struct ipa_flt_rule_mdfy flt_rule; - struct ipa_ioc_mdfy_flt_rule* pFilteringTable = NULL; - bool client_is_found = false; + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + uint32_t tx_index; + int wlan_index,v6_num; + const int NUM = 1; - if (rx_prop == NULL) + if(tx_prop == NULL) { IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); - return IPACM_FAILURE; + return IPACM_SUCCESS; + } + + IPACMDBG_H("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + wlan_index = get_wlan_client_index(mac_addr); + if (wlan_index == IPACM_INVALID_INDEX) + { + IPACMDBG_H("wlan client not found/attached \n"); + return IPACM_SUCCESS; + } + + /* during power_save mode, even receive IP_ADDR_ADD, not setting RT rules*/ + if (get_client_memptr(wlan_client, wlan_index)->power_save_set == true) + { + IPACMDBG_H("wlan client is in power safe mode \n"); + return IPACM_SUCCESS; } - if(mac == NULL) + + if (iptype==IPA_IP_v4) { - IPACMERR("MAC address is empty.\n"); - return IPACM_FAILURE; + IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", wlan_index, iptype, + get_client_memptr(wlan_client, wlan_index)->ipv4_set, + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4); } - if(IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == false) + else { - IPACMDBG_H("WLAN to USB hdr proc ctx has not been set, don't add USB client specific flt rule.\n"); - return IPACM_FAILURE; + IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wlan_index, iptype, + get_client_memptr(wlan_client, wlan_index)->ipv6_set, + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6); } - for(i=0; iroute_rule_set_v4 == false + && get_client_memptr(wlan_client, wlan_index)->ipv4_set == true) + || (iptype == IPA_IP_v6 + && get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 < get_client_memptr(wlan_client, wlan_index)->ipv6_set + )) { - if(memcmp(eth_bridge_usb_client_flt_info[i].mac, mac, sizeof(eth_bridge_usb_client_flt_info[i].mac)) == 0) + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_add)); + + if (rt_rule == NULL) + { + PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = (uint8_t)NUM; + rt_rule->ip = iptype; + + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) { - client_is_found = true; - client_position = i; - if( (iptype == IPA_IP_v4 && eth_bridge_usb_client_flt_info[i].flt_rule_set_v4 == true) - || (iptype == IPA_IP_v6 && eth_bridge_usb_client_flt_info[i].flt_rule_set_v6 == true)) + + if(iptype != tx_prop->tx[tx_index].ip) { - IPACMDBG_H("Flt rule for iptype %d has been set.\n", iptype); - return IPACM_SUCCESS; + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", + tx_index, tx_prop->tx[tx_index].ip,iptype); + continue; } - break; - } - } - if(client_is_found == false && num_usb_client == IPA_LAN_TO_LAN_MAX_USB_CLIENT) - { - IPACMDBG_H("The usb client flt table is already full.\n"); - return IPACM_FAILURE; - } + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; - len = sizeof(struct ipa_ioc_mdfy_flt_rule) + sizeof(struct ipa_flt_rule_mdfy); - pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); - if (!pFilteringTable) - { - IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); - return IPACM_FAILURE; - } - memset(pFilteringTable, 0, len); + if (iptype == IPA_IP_v4) + { + IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wlan_index, + get_client_memptr(wlan_client, wlan_index)->v4_addr); + + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + wlan_index, + get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4); + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; - IPACMDBG_H("Receive USB client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + if(IPACM_Iface::ipacmcfg->isMCC_Mode) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4; + rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wlan_client, wlan_index)->v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + /* copy ipv4 RT hdl */ + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4 = + rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4, iptype); + } + else + { + for(v6_num = get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6;v6_num < get_client_memptr(wlan_client, wlan_index)->ipv6_set;v6_num++) + { + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + wlan_index, + get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6); + + /* v6 LAN_RT_TBL */ + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_v6.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Support QCMAP LAN traffic feature, send to A5 */ + rt_rule_entry->rule.dst = iface_query->excp_pipe; + memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = 0; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[v6_num], iptype); + + /*Copy same rule to v6 WAN RT TBL*/ + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Downlink traffic from Wan iface, directly through IPA */ + if(IPACM_Iface::ipacmcfg->isMCC_Mode) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = true; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } - /* add mac based rule on flt table */ - pFilteringTable->commit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = 1; + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl; - /* point to USB-WLAN routing table */ - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - flt_rule.status = -1; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num], iptype); + } + } - flt_rule.rule.retain_hdr = 0; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_ROUTING; - flt_rule.rule.eq_attrib_type = 0; + } /* end of for loop */ - if(iptype == IPA_IP_v4) - { - if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v4)) + free(rt_rule); + + if (iptype == IPA_IP_v4) { - IPACMERR("Failed to get routing table handle.\n"); - res = IPACM_FAILURE; - goto fail; + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4 = true; } - flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v4.hdl; - IPACMDBG_H("WLAN->USB IPv4 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v4.name); - } - else - { - if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v6)) + else { - IPACMERR("Failed to get routing table handle.\n"); - res = IPACM_FAILURE; - goto fail; + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 = get_client_memptr(wlan_client, wlan_index)->ipv6_set; } - flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v6.hdl; - IPACMDBG_H("WLAN->USB IPv6 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v6.name); } - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); - if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) + return IPACM_SUCCESS; +} + +/*handle wifi client power-save mode*/ +int IPACM_Wlan::handle_wlan_client_pwrsave(uint8_t *mac_addr) +{ + int clt_indx; + IPACMDBG_H("wlan->handle_wlan_client_pwrsave();\n"); + + clt_indx = get_wlan_client_index(mac_addr); + if (clt_indx == IPACM_INVALID_INDEX) { - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + IPACMDBG_H("wlan client not attached\n"); + return IPACM_SUCCESS; } - else if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_802_3) + + if (get_client_memptr(wlan_client, clt_indx)->power_save_set == false) { - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + /* First reset nat rules and then route rules */ + if(get_client_memptr(wlan_client, clt_indx)->ipv4_set == true) + { + IPACMDBG_H("Deleting Nat Rules\n"); + Nat_App->UpdatePwrSaveIf(get_client_memptr(wlan_client, clt_indx)->v4_addr); + } + + IPACMDBG_H("Deleting default qos Route Rules\n"); + delete_default_qos_rtrules(clt_indx, IPA_IP_v4); + delete_default_qos_rtrules(clt_indx, IPA_IP_v6); + get_client_memptr(wlan_client, clt_indx)->power_save_set = true; } else { - IPACMERR("WLAN hdr type is not expected.\n"); - res = IPACM_FAILURE; - goto fail; + IPACMDBG_H("wlan client already in power-save mode\n"); } - memcpy(flt_rule.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule.rule.attrib.dst_mac_addr)); - memset(flt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule.rule.attrib.dst_mac_addr_mask)); + return IPACM_SUCCESS; +} + +/*handle wifi client del mode*/ +int IPACM_Wlan::handle_wlan_client_down_evt(uint8_t *mac_addr) +{ + int clt_indx; + uint32_t tx_index; + int num_wifi_client_tmp = num_wifi_client; + int num_v6; + + IPACMDBG_H("total client: %d\n", num_wifi_client_tmp); - if(iptype == IPA_IP_v4) + clt_indx = get_wlan_client_index(mac_addr); + if (clt_indx == IPACM_INVALID_INDEX) { - for(i=0; iipv4_set == true) { - for(i=0; iv4_addr); + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clt_indx)->v4_addr); + } - memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + if (delete_default_qos_rtrules(clt_indx, IPA_IP_v4)) { - IPACMERR("Failed to add wlan client filtering rules.\n"); - res = IPACM_FAILURE; - goto fail; + IPACMERR("unbale to delete v4 default qos route rules for index: %d\n", clt_indx); + return IPACM_FAILURE; } - if(client_is_found == false) + if (delete_default_qos_rtrules(clt_indx, IPA_IP_v6)) { - client_position = num_usb_client; - num_usb_client++; + IPACMERR("unbale to delete v6 default qos route rules for indexn: %d\n", clt_indx); + return IPACM_FAILURE; } - memcpy(eth_bridge_usb_client_flt_info[client_position].mac, mac, sizeof(eth_bridge_usb_client_flt_info[client_position].mac)); - if(iptype == IPA_IP_v4) + /* Delete wlan client header */ + if(get_client_memptr(wlan_client, clt_indx)->ipv4_header_set == true) { - eth_bridge_usb_client_flt_info[client_position].flt_rule_set_v4 = true; - eth_bridge_usb_client_flt_info[client_position].flt_rule_hdl_v4 = usb_client_flt_rule_hdl_v4[i].rule_hdl; - } - else + if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v4) + == false) { - eth_bridge_usb_client_flt_info[client_position].flt_rule_set_v6 = true; - eth_bridge_usb_client_flt_info[client_position].flt_rule_hdl_v6 = usb_client_flt_rule_hdl_v6[i].rule_hdl; + return IPACM_FAILURE; } - -fail: - if(pFilteringTable == NULL) - { - free(pFilteringTable); + get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = false; } - return res; -} -int IPACM_Wlan::eth_bridge_del_usb_client_flt_rule(uint8_t* mac) -{ - if(mac == NULL) + if(get_client_memptr(wlan_client, clt_indx)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v6) + == false) { - IPACMERR("Client MAC address is empty.\n"); return IPACM_FAILURE; } + get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = false; + } - IPACMDBG_H("Receive USB client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + /* Reset ip_set to 0*/ + get_client_memptr(wlan_client, clt_indx)->ipv4_set = false; + get_client_memptr(wlan_client, clt_indx)->ipv6_set = 0; + get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = false; + get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = false; + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = false; + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = 0; + free(get_client_memptr(wlan_client, clt_indx)->p_hdr_info); - int i, j, res = IPACM_SUCCESS; - for(i=0; ip_hdr_info = get_client_memptr(wlan_client, (clt_indx + 1))->p_hdr_info; - if(i == num_usb_client) - { - IPACMERR("Do not find the usb client.\n"); - return IPACM_FAILURE; - } + memcpy(get_client_memptr(wlan_client, clt_indx)->mac, + get_client_memptr(wlan_client, (clt_indx + 1))->mac, + sizeof(get_client_memptr(wlan_client, clt_indx)->mac)); - if(eth_bridge_usb_client_flt_info[i].flt_rule_set_v4 == true) - { - if(reset_to_dummy_flt_rule(IPA_IP_v4, eth_bridge_usb_client_flt_info[i].flt_rule_hdl_v4) == IPACM_SUCCESS) - { - for(j=0; jhdr_hdl_v4 = get_client_memptr(wlan_client, (clt_indx + 1))->hdr_hdl_v4; + get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v6 = get_client_memptr(wlan_client, (clt_indx + 1))->hdr_hdl_v6; + get_client_memptr(wlan_client, clt_indx)->v4_addr = get_client_memptr(wlan_client, (clt_indx + 1))->v4_addr; + + get_client_memptr(wlan_client, clt_indx)->ipv4_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv4_set; + get_client_memptr(wlan_client, clt_indx)->ipv6_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv6_set; + get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv4_header_set; + get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv6_header_set; + + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = get_client_memptr(wlan_client, (clt_indx + 1))->route_rule_set_v4; + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = get_client_memptr(wlan_client, (clt_indx + 1))->route_rule_set_v6; + + for(num_v6=0;num_v6< get_client_memptr(wlan_client, clt_indx)->ipv6_set;num_v6++) + { + get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][0] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][0]; + get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][1] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][1]; + get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][2] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][2]; + get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][3] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][3]; + } + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) { - for(j=0; jwifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4 = + get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4; + + for(num_v6=0;num_v6< get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6;num_v6++) { - IPACMERR("Not finding the rule handle in handle pool.\n"); - return IPACM_FAILURE; - } - } - else - { - IPACMERR("Failed to delete the usb client specific flt rule.\n"); - return IPACM_FAILURE; + get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6] = + get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6]; + get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6] = + get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6]; + } } } - for(j=i+1; jcommit = 1; - pFilteringTable->ip = iptype; - pFilteringTable->num_rules = 1; - - /* point to USB-WLAN routing table */ - memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); - flt_rule.status = -1; - - flt_rule.rule.retain_hdr = 0; - flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_ROUTING; - flt_rule.rule.eq_attrib_type = 0; + IPACMDBG_H("finished deleting wan filtering rules\n "); - if(iptype == IPA_IP_v4) - { - if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4)) - { - IPACMERR("Failed to get routing table handle.\n"); - res = IPACM_FAILURE; - goto fail; - } - flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4.hdl; - IPACMDBG_H("WLAN->WLAN IPv4 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4.name); - } - else + /* Delete v4 filtering rules */ + if (ip_type != IPA_IP_v6 && rx_prop != NULL) { - if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6)) + /* delete IPv4 icmp filter rules */ + if(m_filtering.DeleteFilteringHdls(ipv4_icmp_flt_rule_hdl, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE) == false) { - IPACMERR("Failed to get routing table handle.\n"); + IPACMERR("Error Deleting ICMPv4 Filtering Rule, aborting...\n"); res = IPACM_FAILURE; goto fail; } - flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6.hdl; - IPACMDBG_H("WLAN->WLAN IPv4 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6.name); - } - - memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); - flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); //remove meta data mask - if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) - { - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; - } - else if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_802_3) - { - flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; - } - else - { - IPACMERR("WLAN hdr type is not expected.\n"); - res = IPACM_FAILURE; - goto fail; - } - memcpy(flt_rule.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule.rule.attrib.dst_mac_addr)); - memset(flt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule.rule.attrib.dst_mac_addr_mask)); - - if(iptype == IPA_IP_v4) - { - for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE); + if (dft_v4fl_rule_hdl[0] != 0) { - if(self_client_flt_rule_hdl_v4[i].valid == true) + if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES) == false) { - flt_rule.rule_hdl = self_client_flt_rule_hdl_v4[i].rule_hdl; - self_client_flt_rule_hdl_v4[i].valid = false; - break; + IPACMERR("Error Deleting Filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES); + IPACMDBG_H("Deleted default v4 filter rules successfully.\n"); } - if(i == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT) + /* delete private-ipv4 filter rules */ +#ifdef FEATURE_IPA_ANDROID + if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES) == false) { - IPACMDBG_H("Cannot find a valid flt rule hdl.\n"); + IPACMERR("Error deleting private subnet IPv4 flt rules.\n"); res = IPACM_FAILURE; goto fail; } - } - else - { - for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES); +#else + num_private_subnet_fl_rule = IPACM_Iface::ipacmcfg->ipa_num_private_subnet > IPA_MAX_PRIVATE_SUBNET_ENTRIES? + IPA_MAX_PRIVATE_SUBNET_ENTRIES : IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, num_private_subnet_fl_rule) == false) { - IPACMDBG_H("Cannot find a valid flt rule hdl.\n"); + IPACMERR("Error deleting private subnet flt rules, aborting...\n"); res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, num_private_subnet_fl_rule); +#endif + IPACMDBG_H("Deleted private subnet v4 filter rules successfully.\n"); } - memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); - if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) - { - IPACMERR("Failed to add self client filtering rules.\n"); - res = IPACM_FAILURE; - goto fail; - } - - if(client_is_found == false) - { - client_position = wlan_client_flt_info_count; - wlan_client_flt_info_count++; - } - - memcpy(eth_bridge_wlan_client_flt_info[client_position].mac, mac, sizeof(eth_bridge_wlan_client_flt_info[client_position].mac)); - if(iptype == IPA_IP_v4) - { - eth_bridge_wlan_client_flt_info[client_position].flt_rule_set_v4 = true; - eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v4 = self_client_flt_rule_hdl_v4[i].rule_hdl; - } - else - { - eth_bridge_wlan_client_flt_info[client_position].flt_rule_set_v6 = true; - eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v6 = self_client_flt_rule_hdl_v6[i].rule_hdl; - } - -fail: - if(pFilteringTable == NULL) - { - free(pFilteringTable); - } - return res; -} - -int IPACM_Wlan::eth_bridge_del_self_client_flt_rule(uint8_t* mac) -{ - if(mac == NULL) - { - IPACMERR("Client MAC address is empty.\n"); - return IPACM_FAILURE; - } - - IPACMDBG_H("Receive WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - - int i, j, res = IPACM_SUCCESS; - for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE); - if(eth_bridge_wlan_client_flt_info[i].flt_rule_set_v4 == true) - { - if(reset_to_dummy_flt_rule(IPA_IP_v4, eth_bridge_wlan_client_flt_info[i].flt_rule_hdl_v4) == IPACM_SUCCESS) + if (dft_v6fl_rule_hdl[0] != 0) { - for(j=0; jdecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES); + IPACMDBG_H("Deleted default v6 filter rules successfully.\n"); } - else + } + IPACMDBG_H("finished delete filtering rules\n "); + + /* Delete default v4 RT rule */ + if (ip_type != IPA_IP_v6) + { + IPACMDBG_H("Delete default v4 routing rules\n"); + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) + == false) { - IPACMERR("Failed to delete the wlan client specific flt rule.\n"); - return IPACM_FAILURE; + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; } } - if(eth_bridge_wlan_client_flt_info[i].flt_rule_set_v6 == true) + + /* Delete default v6 RT rule */ + if (ip_type != IPA_IP_v4) { - if(reset_to_dummy_flt_rule(IPA_IP_v6, eth_bridge_wlan_client_flt_info[i].flt_rule_hdl_v6) == IPACM_SUCCESS) + IPACMDBG_H("Delete default v6 routing rules\n"); + /* May have multiple ipv6 iface-RT rules */ + for (i = 0; i < 2*num_dft_rt_v6; i++) { - for(j=0; jipa_num_private_subnet); + IPACMDBG_H(" Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + if(IPACM_Iface::ipacmcfg->DelPrivateSubnet(if_ipv4_subnet, ipa_if_num) == false) + { + IPACMERR(" can't Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + } } - return IPACM_SUCCESS; -} + /* reset the IPA-client pipe enum */ +#ifdef FEATURE_IPACM_HAL + handle_tethering_client(true, IPACM_CLIENT_MAX); +#else + handle_tethering_client(true, IPACM_CLIENT_WLAN); +#endif +#endif /* defined(FEATURE_IPA_ANDROID)*/ -int IPACM_Wlan::eth_bridge_add_wlan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src, ipa_ip_type iptype) -{ - if(tx_prop == NULL) - { - IPACMDBG_H("Tx prop is empty, not adding routing rule.\n"); - return IPACM_SUCCESS; - } - if(mac == NULL) - { - IPACMERR("Client MAC address is empty.\n"); - return IPACM_FAILURE; - } - if(iptype == IPA_IP_v4) +fail: + /* clean wifi-client header, routing rules */ + /* clean wifi client rule*/ + IPACMDBG_H("left %d wifi clients need to be deleted \n ", num_wifi_client); + for (i = 0; i < num_wifi_client; i++) { - if( (src == SRC_WLAN && wlan_client_rt_from_wlan_info_count_v4 == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT) - || (src == SRC_USB && wlan_client_rt_from_usb_info_count_v4 == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT)) + /* First reset nat rules and then route rules */ + if(get_client_memptr(wlan_client, i)->ipv4_set == true) { - IPACMDBG_H("WLAN client number has reached maximum.\n"); - return IPACM_FAILURE; + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wlan_client, i)->v4_addr); + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, i)->v4_addr); } - } - else - { - if( (src == SRC_WLAN && wlan_client_rt_from_wlan_info_count_v6 == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT) - || (src == SRC_USB && wlan_client_rt_from_usb_info_count_v6 == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT)) + + if (delete_default_qos_rtrules(i, IPA_IP_v4)) { - IPACMDBG_H("WLAN client number has reached maximum.\n"); - return IPACM_FAILURE; + IPACMERR("unbale to delete v4 default qos route rules for index: %d\n", i); + res = IPACM_FAILURE; } - } - if( (src == SRC_WLAN && IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid == false) - || (src == SRC_USB && IPACM_Lan::usb_to_wlan_hdr_proc_ctx.valid == false) ) - { - IPACMDBG_H("Hdr proc ctx has not been set for source %d, don't add WLAN client routing rule.\n", src); - return IPACM_FAILURE; - } - IPACMDBG_H("Receive WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + if (delete_default_qos_rtrules(i, IPA_IP_v6)) + { + IPACMERR("unbale to delete v6 default qos route rules for index: %d\n", i); + res = IPACM_FAILURE; + } - int i, len, res = IPACM_SUCCESS; - struct ipa_ioc_add_rt_rule* rt_rule_table = NULL; - struct ipa_rt_rule_add rt_rule; - int position, num_rt_rule; + IPACMDBG_H("Delete %d client header\n", num_wifi_client); - if(src == SRC_WLAN) - { - if(iptype == IPA_IP_v4) + if(get_client_memptr(wlan_client, i)->ipv4_header_set == true) { - for(i=0; ihdr_hdl_v4) + == false) { - if(memcmp(eth_bridge_get_client_rt_info_ptr(i, SRC_WLAN, iptype)->mac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, SRC_WLAN, iptype)->mac)) == 0) - { - IPACMDBG_H("The client's routing rule was added before.\n"); - return IPACM_SUCCESS; - } + res = IPACM_FAILURE; } - memcpy(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v4, src, iptype)->mac, mac, - sizeof(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v4, src, iptype)->mac)); } - else + + if(get_client_memptr(wlan_client, i)->ipv6_header_set == true) { - for(i=0; ihdr_hdl_v6) + == false) { - if(memcmp(eth_bridge_get_client_rt_info_ptr(i, SRC_WLAN, iptype)->mac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, SRC_WLAN, iptype)->mac)) == 0) - { - IPACMDBG_H("The client's routing rule was added before.\n"); - return IPACM_SUCCESS; - } + res = IPACM_FAILURE; } - memcpy(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v6, src, iptype)->mac, mac, - sizeof(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v6, src, iptype)->mac)); } + } /* end of for loop */ + + /* check software routing fl rule hdl */ + if (softwarerouting_act == true && rx_prop != NULL ) + { + IPACMDBG_H("Delete sw routing filtering rules\n"); + IPACM_Iface::handle_software_routing_disable(); } - else + IPACMDBG_H("finished delete software-routing filtering rules\n "); + + /* Delete corresponding ipa_rm_resource_name of RX-endpoint after delete all IPV4V6 FT-rule */ + if (rx_prop != NULL) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); + free(rx_prop); + } + + for (i = 0; i < num_wifi_client; i++) { - if(iptype == IPA_IP_v4) - { - for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, SRC_USB, iptype)->mac)) == 0) - { - IPACMDBG_H("The client's routing rule was added before.\n"); - return IPACM_SUCCESS; - } - } - memcpy(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_usb_info_count_v4, src, iptype)->mac, mac, - sizeof(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_usb_info_count_v4, src, iptype)->mac)); - } - else + if(get_client_memptr(wlan_client, i)->p_hdr_info != NULL) { - for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, SRC_USB, iptype)->mac)) == 0) - { - IPACMDBG_H("The client's routing rule was added before.\n"); - return IPACM_SUCCESS; - } - } - memcpy(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_usb_info_count_v6, src, iptype)->mac, mac, - sizeof(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_usb_info_count_v6, src, iptype)->mac)); + free(get_client_memptr(wlan_client, i)->p_hdr_info); } } - - if(iptype == IPA_IP_v4) + if(wlan_client != NULL) { - num_rt_rule = each_client_rt_rule_count_v4; + free(wlan_client); } - else + if (tx_prop != NULL) { - num_rt_rule = each_client_rt_rule_count_v6; + free(tx_prop); } - len = sizeof(ipa_ioc_add_rt_rule) + num_rt_rule * sizeof(ipa_rt_rule_add); - rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(len); - if(rt_rule_table == NULL) + if (iface_query != NULL) { - IPACMERR("Failed to allocate memory.\n"); - return IPACM_FAILURE; + free(iface_query); } - memset(rt_rule_table, 0, len); - rt_rule_table->commit = 1; - rt_rule_table->ip = iptype; - rt_rule_table->num_rules = num_rt_rule; - if(src == SRC_WLAN) + is_active = false; + post_del_self_evt(); + + return res; +} + +/*handle reset wifi-client rt-rules */ +int IPACM_Wlan::handle_wlan_client_reset_rt(ipa_ip_type iptype) +{ + int i, res = IPACM_SUCCESS; + + /* clean wifi-client routing rules */ + IPACMDBG_H("left %d wifi clients to reset ip-type(%d) rules \n ", num_wifi_client, iptype); + + for (i = 0; i < num_wifi_client; i++) { - if(iptype == IPA_IP_v4) - { - strncpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4.name, sizeof(rt_rule_table->rt_tbl_name)); - } - else + /* Reset RT rules */ + res = delete_default_qos_rtrules(i, iptype); + if (res != IPACM_SUCCESS) { - strncpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6.name, sizeof(rt_rule_table->rt_tbl_name)); + IPACMERR("Failed to delete old iptype(%d) rules.\n", iptype); + return res; } - } - else - { + + /* Reset ip-address */ if(iptype == IPA_IP_v4) { - strncpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v4.name, sizeof(rt_rule_table->rt_tbl_name)); + get_client_memptr(wlan_client, i)->ipv4_set = false; } else { - strncpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_usb_wlan_v6.name, sizeof(rt_rule_table->rt_tbl_name)); + get_client_memptr(wlan_client, i)->ipv6_set = 0; } - } + } /* end of for loop */ + return res; +} - memset(&rt_rule, 0, sizeof(ipa_rt_rule_add)); - rt_rule.at_rear = false; - rt_rule.status = -1; - rt_rule.rt_rule_hdl = -1; +void IPACM_Wlan::handle_SCC_MCC_switch(ipa_ip_type iptype) +{ + struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_mdfy *rt_rule_entry; + uint32_t tx_index; + int wlan_index, v6_num; + const int NUM = 1; + int num_wifi_client_tmp = IPACM_Wlan::num_wifi_client; + bool isAdded = false; - rt_rule.rule.hdr_hdl = 0; - if(src == SRC_WLAN) + if (tx_prop == NULL) { - rt_rule.rule.hdr_proc_ctx_hdl = IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.proc_ctx_hdl; + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return; } - else + + if (rt_rule == NULL) { - rt_rule.rule.hdr_proc_ctx_hdl = IPACM_Lan::usb_to_wlan_hdr_proc_ctx.proc_ctx_hdl; + rt_rule = (struct ipa_ioc_mdfy_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_mdfy_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_mdfy)); + + if (rt_rule == NULL) + { + PERROR("Error Locate ipa_ioc_mdfy_rt_rule memory...\n"); + return; + } + + rt_rule->commit = 0; + rt_rule->num_rules = NUM; + rt_rule->ip = iptype; } - position = 0; - for(i=0; inum_tx_props; i++) + rt_rule_entry = &rt_rule->rules[0]; + + /* modify ipv4 routing rule */ + if (iptype == IPA_IP_v4) { - if(tx_prop->tx[i].ip == iptype) + for (wlan_index = 0; wlan_index < num_wifi_client_tmp; wlan_index++) { - if(position >= num_rt_rule) + IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", + wlan_index, iptype, + get_client_memptr(wlan_client, wlan_index)->ipv4_set, + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4); + + if (get_client_memptr(wlan_client, wlan_index)->power_save_set == true || + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4 == false) { - IPACMERR("Number of routing rules already exceeds limit.\n"); - res = IPACM_FAILURE; - goto fail; + IPACMDBG_H("client %d route rules not set\n", wlan_index); + continue; } - rt_rule.rule.dst = tx_prop->tx[i].dst_pipe; - memcpy(&rt_rule.rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule.rule.attrib)); - if(src == SRC_WLAN) //src is WLAN means packet is from WLAN + IPACMDBG_H("Modify client %d route rule\n", wlan_index); + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) { - if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) + if (iptype != tx_prop->tx[tx_index].ip) { - rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + IPACMDBG_H("Tx:%d, ip-type: %d ip-type not matching: %d ignore\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; } - else + + IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wlan_index, + get_client_memptr(wlan_client, wlan_index)->v4_addr); + + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + wlan_index, + get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4); + + if (IPACM_Iface::ipacmcfg->isMCC_Mode) { - rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; } - } - else //packet is from USB - { - if(IPACM_Lan::usb_hdr_type == IPA_HDR_L2_ETHERNET_II) + else { - rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; } - else + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4; + + rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wlan_client, wlan_index)->v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4, iptype); + + rt_rule_entry->rt_rule_hdl = + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4; + + if (false == m_routing.ModifyRoutingRule(rt_rule)) { - rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; } + isAdded = true; } - memcpy(rt_rule.rule.attrib.dst_mac_addr, mac, sizeof(rt_rule.rule.attrib.dst_mac_addr)); - memset(rt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule.rule.attrib.dst_mac_addr_mask)); - memcpy(&(rt_rule_table->rules[position]), &rt_rule, sizeof(rt_rule_table->rules[position])); - position++; } } - if(false == m_routing.AddRoutingRule(rt_rule_table)) - { - IPACMERR("Routing rule addition failed!\n"); - res = IPACM_FAILURE; - goto fail; - } - else + /* modify ipv6 routing rule */ + if (iptype == IPA_IP_v6) { - if(src == SRC_WLAN) + for (wlan_index = 0; wlan_index < num_wifi_client_tmp; wlan_index++) { - for(i=0; irt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; - } - else - { - eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v6, src, iptype)->rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; - } - } - if(iptype == IPA_IP_v4) - { - wlan_client_rt_from_wlan_info_count_v4++; - IPACMDBG_H("Now the number of IPv4 rt rule on wlan-wlan rt table is %d.\n", wlan_client_rt_from_wlan_info_count_v4); - } - else + + IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wlan_index, iptype, + get_client_memptr(wlan_client, wlan_index)->ipv6_set, + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6); + + if (get_client_memptr(wlan_client, wlan_index)->power_save_set == true || + (get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 < + get_client_memptr(wlan_client, wlan_index)->ipv6_set) ) { - wlan_client_rt_from_wlan_info_count_v6++; - IPACMDBG_H("Now the number of IPv6 rt rule on wlan-wlan rt table is %d.\n", wlan_client_rt_from_wlan_info_count_v6); + IPACMDBG_H("client %d route rules not set\n", wlan_index); + continue; } - } - else - { - for(i=0; inum_tx_props; tx_index++) { - if(iptype == IPA_IP_v4) - { - eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_usb_info_count_v4, src, iptype)->rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; - } - else + if (iptype != tx_prop->tx[tx_index].ip) { - eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_usb_info_count_v6, src, iptype)->rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + IPACMDBG_H("Tx:%d, ip-type: %d ip-type not matching: %d Ignore\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; } - } - if(iptype == IPA_IP_v4) - { - wlan_client_rt_from_usb_info_count_v4++; - IPACMDBG_H("Now the number of IPv4 rt rule on usb-wlan rt table is %d.\n", wlan_client_rt_from_usb_info_count_v4); - } - else - { - wlan_client_rt_from_usb_info_count_v6++; - IPACMDBG_H("Now the number of IPv6 rt rule on usb-wlan rt table is %d.\n", wlan_client_rt_from_usb_info_count_v6); - } - } - } -fail: - if(rt_rule_table != NULL) - { - free(rt_rule_table); - } - return res; -} + for (v6_num = get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6; + v6_num < get_client_memptr(wlan_client, wlan_index)->ipv6_set; + v6_num++) + { -int IPACM_Wlan::eth_bridge_del_wlan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src) -{ - if(tx_prop == NULL) - { - IPACMDBG_H("Tx prop is empty, not deleting routing rule.\n"); - return IPACM_SUCCESS; - } - if(mac == NULL) - { - IPACMERR("Client MAC address is empty.\n"); - return IPACM_FAILURE; - } + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + wlan_index, + get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6); - IPACMDBG_H("Receive WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + if (IPACM_Iface::ipacmcfg->isMCC_Mode) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } - int i, position; + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); - /* first delete the rt rules from IPv4 rt table*/ - if(src == SRC_WLAN) - { - for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v4)->mac)) == 0) - { - position = i; - IPACMDBG_H("The client is found at position %d.\n", position); - break; - } - } - if(i == wlan_client_rt_from_wlan_info_count_v4) - { - IPACMERR("The client is not found.\n"); - return IPACM_FAILURE; - } - } - else - { - for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v4)->mac)) == 0) - { - position = i; - IPACMDBG_H("The client is found at position %d.\n", position); - break; - } - } - if(i == wlan_client_rt_from_usb_info_count_v4) - { - IPACMERR("The client is not found.\n"); - return IPACM_FAILURE; - } - } + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; - for(i=0; irt_rule_hdl[i], IPA_IP_v4) == false) - { - IPACMERR("Failed to delete routing rule %d.\n", i); - return IPACM_FAILURE; - } - } + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; - if(src == SRC_WLAN) - { - for(i=position+1; irt_rule_hdl = + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num]; - /*delete rt rules from IPv6 rt table */ - if(src == SRC_WLAN) - { - for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v6)->mac)) == 0) - { - position = i; - IPACMDBG_H("The client is found at position %d.\n", position); - break; - } - } - if(i == wlan_client_rt_from_wlan_info_count_v6) - { - IPACMERR("The client is not found.\n"); - return IPACM_FAILURE; - } - } - else - { - for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v6)->mac)) == 0) - { - position = i; - IPACMDBG_H("The client is found at position %d.\n", position); - break; + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; + } + isAdded = true; + } } - } - if(i == wlan_client_rt_from_usb_info_count_v6) - { - IPACMERR("The client is not found.\n"); - return IPACM_FAILURE; - } - } - - for(i=0; irt_rule_hdl[i], IPA_IP_v6) == false) - { - IPACMERR("Failed to delete routing rule %d.\n", i); - return IPACM_FAILURE; - } - } - if(src == SRC_WLAN) - { - for(i=position+1; imac, NULL, NULL); } - IPACM_Lan::num_wlan_client--; + return; } + +bool IPACM_Wlan::is_guest_ap() +{ + return m_is_guest_ap; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Xml.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Xml.cpp index f617edc8..b81856a2 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_Xml.cpp +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Xml.cpp @@ -158,7 +158,6 @@ static int ipacm_cfg_xml_parse_tree if (NULL == xml_node) return ret_val; - while ( xml_node != NULL && ret_val == IPACM_SUCCESS) { @@ -166,55 +165,62 @@ static int ipacm_cfg_xml_parse_tree { case XML_ELEMENT_NODE: { - if (IPACM_util_icmp_string((char*)xml_node->name, - system_TAG) == 0 || - IPACM_util_icmp_string((char*)xml_node->name, - ODU_TAG) == 0 || - IPACM_util_icmp_string((char*)xml_node->name, - IPACMCFG_TAG) == 0 || - IPACM_util_icmp_string((char*)xml_node->name, - IPACMIFACECFG_TAG) == 0 || - IPACM_util_icmp_string((char*)xml_node->name, - IFACE_TAG) == 0 || - IPACM_util_icmp_string((char*)xml_node->name, - IPACMPRIVATESUBNETCFG_TAG) == 0 || - IPACM_util_icmp_string((char*)xml_node->name, - SUBNET_TAG) == 0 || - IPACM_util_icmp_string((char*)xml_node->name, - IPACMALG_TAG) == 0 || - IPACM_util_icmp_string((char*)xml_node->name, - ALG_TAG) == 0 || - IPACM_util_icmp_string((char*)xml_node->name, - IPACMNat_TAG) == 0) + if (IPACM_util_icmp_string((char*)xml_node->name, system_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, ODU_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMCFG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMIFACECFG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IFACE_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMPRIVATESUBNETCFG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, SUBNET_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMALG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, ALG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMNat_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IP_PassthroughFlag_TAG) == 0) { - if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IFACE_TAG)) + if (0 == IPACM_util_icmp_string((char*)xml_node->name, IFACE_TAG)) { /* increase iface entry number */ config->iface_config.num_iface_entries++; } - if (0 == IPACM_util_icmp_string((char*)xml_node->name, - SUBNET_TAG)) + if (0 == IPACM_util_icmp_string((char*)xml_node->name, SUBNET_TAG)) { /* increase iface entry number */ config->private_subnet_config.num_subnet_entries++; } - if (0 == IPACM_util_icmp_string((char*)xml_node->name, - ALG_TAG)) + if (0 == IPACM_util_icmp_string((char*)xml_node->name, ALG_TAG)) { /* increase iface entry number */ config->alg_config.num_alg_entries++; } /* go to child */ - ret_val = ipacm_cfg_xml_parse_tree(xml_node->children, - config); + ret_val = ipacm_cfg_xml_parse_tree(xml_node->children, config); } - else if (IPACM_util_icmp_string((char*)xml_node->name, - ODUMODE_TAG) == 0) + else if (IPACM_util_icmp_string((char*)xml_node->name, IP_PassthroughMode_TAG) == 0) { - IPACMDBG("inside ODU-XML\n"); + IPACMDBG_H("inside IP Passthrough\n"); + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (atoi(content_buf)) + { + config->ip_passthrough_mode = true; + IPACMDBG_H("Passthrough enable %d buf(%d)\n", config->ip_passthrough_mode, atoi(content_buf)); + } + else + { + config->ip_passthrough_mode = false; + IPACMDBG_H("Passthrough enable %d buf(%d)\n", config->ip_passthrough_mode, atoi(content_buf)); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, ODUMODE_TAG) == 0) + { + IPACMDBG_H("inside ODU-XML\n"); content = IPACM_read_content_element(xml_node); if (content) { @@ -224,30 +230,49 @@ static int ipacm_cfg_xml_parse_tree if (0 == strncasecmp(content_buf, ODU_ROUTER_TAG, str_size)) { config->router_mode_enable = true; - IPACMDBG("router-mode enable %d\n", config->router_mode_enable); + IPACMDBG_H("router-mode enable %d\n", config->router_mode_enable); } else if (0 == strncasecmp(content_buf, ODU_BRIDGE_TAG, str_size)) { config->router_mode_enable = false; - IPACMDBG("router-mode enable %d\n", config->router_mode_enable); + IPACMDBG_H("router-mode enable %d\n", config->router_mode_enable); } } } - else if (IPACM_util_icmp_string((char*)xml_node->name, - NAME_TAG) == 0) + else if (IPACM_util_icmp_string((char*)xml_node->name, ODUEMBMS_OFFLOAD_TAG) == 0) { + IPACMDBG_H("inside ODU-XML\n"); content = IPACM_read_content_element(xml_node); if (content) { str_size = strlen(content); memset(content_buf, 0, sizeof(content_buf)); memcpy(content_buf, (void *)content, str_size); - strncpy(config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].iface_name, content_buf, str_size); + if (atoi(content_buf)) + { + config->odu_embms_enable = true; + IPACMDBG_H("router-mode enable %d buf(%d)\n", config->odu_embms_enable, atoi(content_buf)); + } + else + { + config->odu_embms_enable = false; + IPACMDBG_H("router-mode enable %d buf(%d)\n", config->odu_embms_enable, atoi(content_buf)); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, NAME_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + strlcpy(content_buf, content, MAX_XML_STR_LEN); + strlcpy(config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].iface_name, content_buf, IPA_IFACE_NAME_LEN); IPACMDBG_H("Name %s\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].iface_name); } } - else if (IPACM_util_icmp_string((char*)xml_node->name, - CATEGORY_TAG) == 0) + else if (IPACM_util_icmp_string((char*)xml_node->name, CATEGORY_TAG) == 0) { content = IPACM_read_content_element(xml_node); if (content) @@ -292,8 +317,52 @@ static int ipacm_cfg_xml_parse_tree } } } - else if (IPACM_util_icmp_string((char*)xml_node->name, - SUBNETADDRESS_TAG) == 0) + else if (IPACM_util_icmp_string((char*)xml_node->name, MODE_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (0 == strncasecmp(content_buf, IFACE_ROUTER_MODE_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode = ROUTER; + IPACMDBG_H("Iface mode %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode); + } + else if (0 == strncasecmp(content_buf, IFACE_BRIDGE_MODE_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode = BRIDGE; + IPACMDBG_H("Iface mode %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, WLAN_MODE_TAG) == 0) + { + IPACMDBG_H("Inside WLAN-XML\n"); + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + + if (0 == strncasecmp(content_buf, WLAN_FULL_MODE_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].wlan_mode = FULL; + IPACMDBG_H("Wlan-mode full(%d)\n", + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].wlan_mode); + } + else if (0 == strncasecmp(content_buf, WLAN_INTERNET_MODE_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].wlan_mode = INTERNET; + config->num_wlan_guest_ap++; + IPACMDBG_H("Wlan-mode internet(%d)\n", + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].wlan_mode); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, SUBNETADDRESS_TAG) == 0) { content = IPACM_read_content_element(xml_node); if (content) @@ -307,8 +376,7 @@ static int ipacm_cfg_xml_parse_tree IPACMDBG_H("subnet_addr: %s \n", content_buf); } } - else if (IPACM_util_icmp_string((char*)xml_node->name, - SUBNETMASK_TAG) == 0) + else if (IPACM_util_icmp_string((char*)xml_node->name, SUBNETMASK_TAG) == 0) { content = IPACM_read_content_element(xml_node); if (content) @@ -322,8 +390,7 @@ static int ipacm_cfg_xml_parse_tree IPACMDBG_H("subnet_mask: %s \n", content_buf); } } - else if (IPACM_util_icmp_string((char*)xml_node->name, - Protocol_TAG) == 0) + else if (IPACM_util_icmp_string((char*)xml_node->name, Protocol_TAG) == 0) { content = IPACM_read_content_element(xml_node); if (content) @@ -336,17 +403,18 @@ static int ipacm_cfg_xml_parse_tree if (0 == strncasecmp(content_buf, TCP_PROTOCOL_TAG, str_size)) { config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol = IPPROTO_TCP; - IPACMDBG_H("Protocol %s: %d\n", content_buf, config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol); + IPACMDBG_H("Protocol %s: %d\n", + content_buf, config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol); } else if (0 == strncasecmp(content_buf, UDP_PROTOCOL_TAG, str_size)) { config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol = IPPROTO_UDP; - IPACMDBG_H("Protocol %s: %d\n", content_buf, config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol); + IPACMDBG_H("Protocol %s: %d\n", + content_buf, config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol); } } } - else if (IPACM_util_icmp_string((char*)xml_node->name, - Port_TAG) == 0) + else if (IPACM_util_icmp_string((char*)xml_node->name, Port_TAG) == 0) { content = IPACM_read_content_element(xml_node); if (content) @@ -359,8 +427,7 @@ static int ipacm_cfg_xml_parse_tree IPACMDBG_H("port %d\n", config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].port); } } - else if (IPACM_util_icmp_string((char*)xml_node->name, - NAT_MaxEntries_TAG) == 0) + else if (IPACM_util_icmp_string((char*)xml_node->name, NAT_MaxEntries_TAG) == 0) { content = IPACM_read_content_element(xml_node); if (content) @@ -395,10 +462,10 @@ int IPACM_read_firewall_xml(char *xml_file, IPACM_firewall_conf_t *config) /* invoke the XML parser and obtain the parse tree */ doc = xmlReadFile(xml_file, "UTF-8", XML_PARSE_NOBLANKS); - if (doc == NULL) { - IPACMDBG_H("IPACM_xml_parse: libxml returned parse error\n"); + if (doc == NULL) { + IPACMDBG_H("IPACM_xml_parse: libxml returned parse error\n"); return IPACM_FAILURE; - } + } /*get the root of the tree*/ root = xmlDocGetRootElement(doc); @@ -411,7 +478,7 @@ int IPACM_read_firewall_xml(char *xml_file, IPACM_firewall_conf_t *config) } /* free the tree */ - xmlFreeDoc(doc); + xmlFreeDoc(doc); return ret_val; } @@ -444,31 +511,19 @@ static int IPACM_firewall_xml_parse_tree case XML_ELEMENT_NODE: { - if (0 == IPACM_util_icmp_string((char*)xml_node->name, - system_TAG) || - 0 == IPACM_util_icmp_string((char*)xml_node->name, - MobileAPFirewallCfg_TAG) || - 0 == IPACM_util_icmp_string((char*)xml_node->name, - Firewall_TAG) || - - 0 == IPACM_util_icmp_string((char*)xml_node->name, - FirewallEnabled_TAG) || - 0 == IPACM_util_icmp_string((char*)xml_node->name, - FirewallPktsAllowed_TAG) - - - ) + if (0 == IPACM_util_icmp_string((char*)xml_node->name, system_TAG) || + 0 == IPACM_util_icmp_string((char*)xml_node->name, MobileAPFirewallCfg_TAG) || + 0 == IPACM_util_icmp_string((char*)xml_node->name, Firewall_TAG) || + 0 == IPACM_util_icmp_string((char*)xml_node->name, FirewallEnabled_TAG) || + 0 == IPACM_util_icmp_string((char*)xml_node->name, FirewallPktsAllowed_TAG)) { - if (0 == IPACM_util_icmp_string((char*)xml_node->name, - Firewall_TAG)) + if (0 == IPACM_util_icmp_string((char*)xml_node->name, Firewall_TAG)) { /* increase firewall entry num */ config->num_extd_firewall_entries++; } - - if (0 == IPACM_util_icmp_string((char*)xml_node->name, - FirewallPktsAllowed_TAG)) + if (0 == IPACM_util_icmp_string((char*)xml_node->name, FirewallPktsAllowed_TAG)) { /* setup action of matched rules */ content = IPACM_read_content_element(xml_node); @@ -479,18 +534,17 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); if (atoi(content_buf)==1) { - config->rule_action_accept = true; + config->rule_action_accept = true; } else { - config->rule_action_accept = false; + config->rule_action_accept = false; } - IPACMDBG_H(" Allow traffic which matches rules ?:%d\n",config->rule_action_accept); + IPACMDBG_H(" Allow traffic which matches rules ?:%d\n",config->rule_action_accept); } } - if (0 == IPACM_util_icmp_string((char*)xml_node->name, - FirewallEnabled_TAG)) + if (0 == IPACM_util_icmp_string((char*)xml_node->name, FirewallEnabled_TAG)) { /* setup if firewall enable or not */ content = IPACM_read_content_element(xml_node); @@ -501,21 +555,19 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); if (atoi(content_buf)==1) { - config->firewall_enable = true; + config->firewall_enable = true; } else { - config->firewall_enable = false; + config->firewall_enable = false; } - IPACMDBG_H(" Firewall Enable?:%d\n", config->firewall_enable); + IPACMDBG_H(" Firewall Enable?:%d\n", config->firewall_enable); } } /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPFamily_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPFamily_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -526,20 +578,16 @@ static int IPACM_firewall_xml_parse_tree config->extd_firewall_entries[config->num_extd_firewall_entries - 1].ip_vsn = (firewall_ip_version_enum)atoi(content_buf); IPACMDBG_H("\n IP family type is %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].ip_vsn); - + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].ip_vsn); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV4SourceAddress_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceAddress_TAG)) { config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_ADDR; /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV4SourceIPAddress_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceIPAddress_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -553,8 +601,7 @@ static int IPACM_firewall_xml_parse_tree IPACMDBG_H("IPv4 source address is: %s \n", content_buf); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV4SourceSubnetMask_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceSubnetMask_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -568,16 +615,13 @@ static int IPACM_firewall_xml_parse_tree IPACMDBG_H("IPv4 source subnet mask is: %s \n", content_buf); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV4DestinationAddress_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationAddress_TAG)) { config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_ADDR; /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV4DestinationIPAddress_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationIPAddress_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -591,8 +635,7 @@ static int IPACM_firewall_xml_parse_tree IPACMDBG_H("IPv4 destination address is: %s \n", content_buf); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV4DestinationSubnetMask_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationSubnetMask_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -602,21 +645,17 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); content_buf[MAX_XML_STR_LEN-1] = '\0'; config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.dst_addr_mask - = ntohl(inet_addr(content_buf)); + = ntohl(inet_addr(content_buf)); IPACMDBG_H("IPv4 destination subnet mask is: %s \n", content_buf); + } } - } - } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV4TypeOfService_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4TypeOfService_TAG)) { config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_TOS; /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TOSValue_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TOSValue_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -626,13 +665,11 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.tos = atoi(content_buf); - IPACMDBG_H("\n IPV4 TOS val is %d \n", config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.tos); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TOSMask_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TOSMask_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -642,13 +679,11 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.tos &= atoi(content_buf); - IPACMDBG_H("\n IPv4 TOS mask is %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.tos); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.tos); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV4NextHeaderProtocol_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4NextHeaderProtocol_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -657,24 +692,19 @@ static int IPACM_firewall_xml_parse_tree memset(content_buf, 0, sizeof(content_buf)); memcpy(content_buf, (void *)content, str_size); config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_PROTOCOL; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.protocol = atoi(content_buf); - IPACMDBG_H("\n IPv4 next header prot is %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.protocol); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.protocol); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV6SourceAddress_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourceAddress_TAG)) { config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_ADDR; /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV6SourceIPAddress_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourceIPAddress_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -691,11 +721,10 @@ static int IPACM_firewall_xml_parse_tree config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[3]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[3]); IPACMDBG_H("\n ipv6 source addr is %d \n ", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[0]); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[0]); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV6SourcePrefix_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourcePrefix_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -717,21 +746,17 @@ static int IPACM_firewall_xml_parse_tree mask_value_v6 = 0; } } - IPACMDBG_H("\n ipv6 source prefix is %d \n", - atoi(content_buf)); + IPACMDBG_H("\n ipv6 source prefix is %d \n", atoi(content_buf)); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV6DestinationAddress_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationAddress_TAG)) { config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_ADDR; /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV6DestinationIPAddress_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationIPAddress_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -747,11 +772,10 @@ static int IPACM_firewall_xml_parse_tree config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[2]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[2]); config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[3]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[3]); IPACMDBG_H("\n ipv6 dest addr is %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[0]); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[0]); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV6DestinationPrefix_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationPrefix_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -773,20 +797,16 @@ static int IPACM_firewall_xml_parse_tree mask_value_v6 = 0; } } - IPACMDBG_H("\n ipv6 dest prefix is %d \n", - atoi(content_buf)); + IPACMDBG_H("\n ipv6 dest prefix is %d \n", atoi(content_buf)); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV6TrafficClass_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6TrafficClass_TAG)) { config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_TC; /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TrfClsValue_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TrfClsValue_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -794,15 +814,13 @@ static int IPACM_firewall_xml_parse_tree str_size = strlen(content); memset(content_buf, 0, sizeof(content_buf)); memcpy(content_buf, (void *)content, str_size); - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.tc = atoi(content_buf); IPACMDBG_H("\n ipv6 trf class val is %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.tc); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.tc); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TrfClsMask_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TrfClsMask_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -812,13 +830,10 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.tc &= atoi(content_buf); - - IPACMDBG_H("\n ipv6 trf class mask is %d \n", - atoi(content_buf)); + IPACMDBG_H("\n ipv6 trf class mask is %d \n", atoi(content_buf)); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - IPV6NextHeaderProtocol_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6NextHeaderProtocol_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -827,22 +842,18 @@ static int IPACM_firewall_xml_parse_tree memset(content_buf, 0, sizeof(content_buf)); memcpy(content_buf, (void *)content, str_size); config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_NEXT_HDR; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.next_hdr = atoi(content_buf); IPACMDBG_H("\n ipv6 next header protocol is %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.next_hdr); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.next_hdr); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCPSource_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSource_TAG)) { /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCPSourcePort_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSourcePort_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -850,13 +861,11 @@ static int IPACM_firewall_xml_parse_tree str_size = strlen(content); memset(content_buf, 0, sizeof(content_buf)); memcpy(content_buf, (void *)content, str_size); - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port = atoi(content_buf); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCPSourceRange_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSourceRange_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -866,34 +875,30 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); if (atoi(content_buf) != 0) { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + atoi(content_buf); - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port - = 0; - IPACMDBG_H("\n tcp source port from %d to %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo, - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port = 0; + IPACMDBG_H("\n tcp source port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi); } else { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT; - IPACMDBG_H("\n tcp source port= %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT; + IPACMDBG_H("\n tcp source port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port); } } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCPDestination_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestination_TAG)) { /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCPDestinationPort_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestinationPort_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -905,8 +910,7 @@ static int IPACM_firewall_xml_parse_tree = atoi(content_buf); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCPDestinationRange_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestinationRange_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -916,34 +920,30 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); if(atoi(content_buf)!=0) { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + atoi(content_buf); - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port - = 0; - IPACMDBG_H("\n tcp dest port from %d to %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo, - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port = 0; + IPACMDBG_H("\n tcp dest port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi); } else { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT; - IPACMDBG_H("\n tcp dest port= %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT; + IPACMDBG_H("\n tcp dest port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port); } } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - UDPSource_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSource_TAG)) { /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - UDPSourcePort_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSourcePort_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -955,8 +955,7 @@ static int IPACM_firewall_xml_parse_tree = atoi(content_buf); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - UDPSourceRange_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSourceRange_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -966,35 +965,30 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); if(atoi(content_buf)!=0) { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + atoi(content_buf); - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port - = 0; - IPACMDBG_H("\n udp source port from %d to %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo, - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port = 0; + IPACMDBG_H("\n udp source port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi); } else { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT; - IPACMDBG_H("\n udp source port= %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port); - + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT; + IPACMDBG_H("\n udp source port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port); } } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - UDPDestination_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestination_TAG)) { /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - UDPDestinationPort_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestinationPort_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -1006,8 +1000,7 @@ static int IPACM_firewall_xml_parse_tree = atoi(content_buf); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - UDPDestinationRange_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestinationRange_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -1017,28 +1010,25 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); if(atoi(content_buf)!=0) { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + atoi(content_buf); - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port - = 0; - IPACMDBG_H("\n UDP dest port from %d to %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo, - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port = 0; + IPACMDBG_H("\n UDP dest port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi); } else { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT; - IPACMDBG_H("\n UDP dest port= %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port); - + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT; + IPACMDBG_H("\n UDP dest port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port); } } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - ICMPType_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ICMPType_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -1049,11 +1039,10 @@ static int IPACM_firewall_xml_parse_tree config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.type = atoi(content_buf); config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_TYPE; IPACMDBG_H("\n icmp type is %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.type); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.type); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - ICMPCode_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ICMPCode_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -1064,11 +1053,10 @@ static int IPACM_firewall_xml_parse_tree config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.code = atoi(content_buf); config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_CODE; IPACMDBG_H("\n icmp code is %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.code); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.code); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - ESPSPI_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ESPSPI_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -1079,18 +1067,15 @@ static int IPACM_firewall_xml_parse_tree config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.spi = atoi(content_buf); config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SPI; IPACMDBG_H("\n esp spi is %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.spi); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.spi); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCP_UDPSource_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSource_TAG)) { /* go to child */ - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCP_UDPSourcePort_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSourcePort_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -1102,8 +1087,7 @@ static int IPACM_firewall_xml_parse_tree = atoi(content_buf); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCP_UDPSourceRange_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSourceRange_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -1113,34 +1097,30 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); if(atoi(content_buf)!=0) { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + atoi(content_buf); - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port - = 0; - IPACMDBG_H("\n tcp_udp source port from %d to %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo, - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port = 0; + IPACMDBG_H("\n tcp_udp source port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi); } else { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT; - IPACMDBG_H("\n tcp_udp source port= %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT; + IPACMDBG_H("\n tcp_udp source port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port); } } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCP_UDPDestination_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestination_TAG)) { - ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, - config); + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCP_UDPDestinationPort_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestinationPort_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -1152,8 +1132,7 @@ static int IPACM_firewall_xml_parse_tree = atoi(content_buf); } } - else if (0 == IPACM_util_icmp_string((char*)xml_node->name, - TCP_UDPDestinationRange_TAG)) + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestinationRange_TAG)) { content = IPACM_read_content_element(xml_node); if (content) @@ -1163,23 +1142,21 @@ static int IPACM_firewall_xml_parse_tree memcpy(content_buf, (void *)content, str_size); if(atoi(content_buf)!=0) { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port; - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi - = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + atoi(content_buf); - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port - = 0; - IPACMDBG_H("\n tcp_udp dest port from %d to %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo, - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port = 0; + IPACMDBG_H("\n tcp_udp dest port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi); } else { - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT; - IPACMDBG_H("\n tcp_udp dest port= %d \n", - config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port); - + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT; + IPACMDBG_H("\n tcp_udp dest port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port); } } } @@ -1194,5 +1171,3 @@ static int IPACM_firewall_xml_parse_tree } /* end while */ return ret_val; } - - diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_cfg.xml b/data-ipa-cfg-mgr/ipacm/src/IPACM_cfg.xml index 95a77966..9bac7a44 100644 --- a/data-ipa-cfg-mgr/ipacm/src/IPACM_cfg.xml +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_cfg.xml @@ -1,7 +1,8 @@ - router + router + 0 @@ -12,10 +13,12 @@ ecm0 LAN + ROUTER rmnet_data0 WAN + ROUTER rmnet_data1 @@ -45,13 +48,30 @@ rmnet_data7 WAN + + softap0 + UNKNOWN + full + wlan0 UNKNOWN + full wlan1 UNKNOWN + full + + + wlan2 + UNKNOWN + full + + + wlan3 + UNKNOWN + full eth0 @@ -62,6 +82,9 @@ VIRTUAL + + 0 + 192.168.225.0 @@ -133,6 +156,11 @@ UDP 137 NETBIOS_NS + + + UDP + 138 + NETBIOS_NS TCP @@ -144,4 +172,4 @@ 500 - \ No newline at end of file + diff --git a/data-ipa-cfg-mgr/ipacm/src/Makefile.am b/data-ipa-cfg-mgr/ipacm/src/Makefile.am index 4ee0a087..92ea9041 100644 --- a/data-ipa-cfg-mgr/ipacm/src/Makefile.am +++ b/data-ipa-cfg-mgr/ipacm/src/Makefile.am @@ -2,7 +2,8 @@ AM_CPPFLAGS = -I./../inc \ -I$(top_srcdir)/ipanat/inc \ ${LIBXML_CFLAGS} AM_CPPFLAGS += -Wall -Wundef -Wno-trigraphs -AM_CPPFLAGS += -DDEBUG -g -DFEATURE_ETH_BRIDGE_LE +AM_CPPFLAGS += -DDEBUG -g -DFEATURE_ETH_BRIDGE_LE -DFEATURE_L2TP +AM_CPPFLAGS += -DFEATURE_IPA_V3 ipacm_SOURCES = IPACM_Main.cpp \ IPACM_Conntrack_NATApp.cpp\ @@ -30,10 +31,19 @@ bin_PROGRAMS = ipacm requiredlibs = ${LIBXML_LIB} -lxml2 -lpthread -lnetfilter_conntrack -lnfnetlink\ ../../ipanat/src/libipanat.la -ipacm_LDADD = $(requiredlibs) - AM_CPPFLAGS += "-std=c++0x" +if USE_GLIB +ipacm_CFLAGS = $(AM_CFLAGS) -DUSE_GLIB @GLIB_CFLAGS@ +ipacm_LDFLAGS = -lpthread @GLIB_LIBS@ +ipacm_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +ipacm_CFLAGS = $(AM_CFLAGS) +ipacm_LDFLAGS = -lpthread +ipacm_CPPFLAGS = $(AM_CPPFLAGS) +endif +ipacm_LDADD = $(requiredlibs) + LOCAL_MODULE := libipanat LOCAL_PRELINK_MODULE := false include $(BUILD_SHARED_LIBRARY) diff --git a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h index 04e3af97..4ef87796 100644 --- a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h +++ b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013 - 2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -38,6 +38,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @target_port: destination port * @private_port: private port * @protocol: protocol of rule (tcp/udp) + * @pdn_index: PDN index in the PDN config table */ typedef struct { uint32_t target_ip; @@ -46,8 +47,21 @@ typedef struct { uint16_t private_port; uint16_t public_port; uint8_t protocol; + uint8_t pdn_index; } ipa_nat_ipv4_rule; +/** +* struct ipa_nat_pdn_entry - holds a PDN entry data +* @public_ip: PDN's public ip address +* @src_metadata: metadata to be used for source NAT metadata replacement +* @dst_metadata: metadata to be used for destination NAT metadata replacement +*/ +typedef struct { + uint32_t public_ip; + uint32_t src_metadata; + uint32_t dst_metadata; +} ipa_nat_pdn_entry; + /** * ipa_nat_add_ipv4_tbl() - create ipv4 nat table * @public_ip_addr: [in] public ipv4 address @@ -114,3 +128,17 @@ int ipa_nat_query_timestamp(uint32_t table_handle, uint32_t rule_handle, uint32_t *time_stamp); + +/** +* ipa_nat_modify_pdn() - modify single PDN entry in the PDN config table +* @table_handle: [in] handle of ipv4 nat table +* @pdn_index : [in] the index of the entry to be modified +* @pdn_info : [in] values for the PDN entry to be changed +* +* Modify a PDN entry +* +* Returns: 0 On Success, negative on failure +*/ +int ipa_nat_modify_pdn(uint32_t tbl_hdl, + uint8_t pdn_index, + ipa_nat_pdn_entry *pdn_info); diff --git a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h index 4c9f5f3f..1896a3e2 100644 --- a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h +++ b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013 - 2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -39,6 +39,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "ipa_nat_logi.h" @@ -214,8 +215,8 @@ typedef struct { | Proto | TimeStamp(3B) | Flags(2B) | IP check sum Diff(2B)| | (1B) | |EN|FIN|Resv | | | ----------------------------------------------------------------------------------- - | TCP/UDP checksum | Reserved(2B) | SW Specific Parameters(4B) | - | diff (2B) | | + | TCP/UDP checksum |PDN info| Reserved| SW Specific Parameters(4B) | + | diff (2B) | (1B) | (1B) | | ----------------------------------------------------------------------------------- Dont change below structure definition. @@ -239,11 +240,23 @@ struct ipa_nat_rule { ------------------------------------ | index table | prev index | | entry | | - ------------------------------------ + ------------------------------------ --------------------------------------------------*/ uint64_t sw_spec_params:32; - uint64_t rsvd2:16; + uint64_t rsvd2:8; + + /*----------------------------------------- + 8 bit PDN info is interpreted as following + ------------------------------------ + | 4 bits | 4 bits | + ------------------------------------ + | PDN index | reserved | + | | | + ------------------------------------ + -------------------------------------------*/ + uint64_t rsvd3:4; + uint64_t pdn_index:4; uint64_t tcp_udp_chksum:16; }; @@ -274,7 +287,18 @@ struct ipa_nat_sw_rule { --------------------------------------------------*/ uint64_t prev_index:16; uint64_t indx_tbl_entry:16; - uint64_t rsvd2:16; + uint64_t rsvd2 :8; + /*----------------------------------------- + 8 bit PDN info is interpreted as following + ------------------------------------ + | 4 bits | 4 bits | + ------------------------------------ + | PDN index | reserved | + | | | + ------------------------------------ + -------------------------------------------*/ + uint64_t rsvd3 :4; + uint64_t pdn_index :4; uint64_t tcp_udp_chksum:16; }; #define IPA_NAT_TABLE_ENTRY_SIZE 32 @@ -316,12 +340,16 @@ struct ipa_nat_ip4_table_cache { #ifdef IPA_ON_R3PC uint32_t mmap_offset; #endif + + uint16_t cur_tbl_cnt; + uint16_t cur_expn_tbl_cnt; }; struct ipa_nat_cache { struct ipa_nat_ip4_table_cache ip4_tbl[IPA_NAT_MAX_IP4_TBLS]; int ipa_fd; uint8_t table_cnt; + enum ipa_hw_type ver; }; struct ipa_nat_indx_tbl_sw_rule { @@ -398,6 +426,8 @@ int ipa_nati_query_timestamp(uint32_t tbl_hdl, uint32_t rule_hdl, uint32_t *time_stamp); +int ipa_nati_modify_pdn(struct ipa_ioc_nat_pdn_entry *entry); + int ipa_nati_add_ipv4_rule(uint32_t tbl_hdl, const ipa_nat_ipv4_rule *clnt_rule, uint32_t *rule_hdl); diff --git a/data-ipa-cfg-mgr/ipanat/src/Android.mk b/data-ipa-cfg-mgr/ipanat/src/Android.mk index ecc64c43..6622e5e1 100644 --- a/data-ipa-cfg-mgr/ipanat/src/Android.mk +++ b/data-ipa-cfg-mgr/ipanat/src/Android.mk @@ -1,3 +1,8 @@ +BOARD_PLATFORM_LIST := test +ifeq ($(call is-board-platform-in-list,$(BOARD_PLATFORM_LIST)),true) +ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM))) +ifneq (, $(filter aarch64 arm arm64, $(TARGET_ARCH))) + LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) @@ -10,9 +15,15 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr LOCAL_SRC_FILES := ipa_nat_drv.c \ ipa_nat_drvi.c + +LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64 LOCAL_CFLAGS := -DDEBUG LOCAL_MODULE := libipanat LOCAL_MODULE_TAGS := optional LOCAL_PRELINK_MODULE := false - +LOCAL_CLANG := true include $(BUILD_SHARED_LIBRARY) + +endif # $(TARGET_ARCH) +endif +endif diff --git a/data-ipa-cfg-mgr/ipanat/src/Makefile.am b/data-ipa-cfg-mgr/ipanat/src/Makefile.am index 8bdb9b8c..8e2d0056 100644 --- a/data-ipa-cfg-mgr/ipanat/src/Makefile.am +++ b/data-ipa-cfg-mgr/ipanat/src/Makefile.am @@ -1,21 +1,38 @@ AM_CFLAGS = -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs +if KERNELMODULES +AM_CFLAGS += -I./../inc $(KERNEL_DIR)/include +else AM_CFLAGS += -I./../inc +endif #AM_CFLAGS += -DDEBUG -g common_CFLAGS = -DUSE_GLIB @GLIB_CFLAGS@ +if !KERNELMODULES common_LDFLAGS = -lrt @GLIB_LIBS@ +endif + +if KERNELMODULES +library_includedir = ../inc $(KERNEL_DIR)/include $(pkgincludedir) +else +library_includedir = $(pkgincludedir) +endif c_sources = ipa_nat_drv.c \ ipa_nat_drvi.c \ ipa_nat_logi.c -library_includedir = $(pkgincludedir) library_include_HEADERS = ./../inc/ipa_nat_drvi.h \ ./../inc/ipa_nat_drv.h \ ./../inc/ipa_nat_logi.h +if KERNELMODULES +noinst_LIBRARIES = libipanat.a +libipanat_a_C = @C@ +libipanat_a_SOURCES = $(c_sources) +else lib_LTLIBRARIES = libipanat.la libipanat_la_C = @C@ libipanat_la_SOURCES = $(c_sources) libipanat_la_CFLAGS = $(AM_CFLAGS) $(common_CFLAGS) libipanat_la_LDFLAGS = -shared $(common_LDFLAGS) -version-info 1:0:0 +endif diff --git a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c index 66504e10..d01a6c96 100644 --- a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c +++ b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013 - 2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -173,3 +173,43 @@ int ipa_nat_query_timestamp(uint32_t tbl_hdl, } +/** +* ipa_nat_modify_pdn() - modify single PDN entry in the PDN config table +* @table_handle: [in] handle of ipv4 nat table +* @pdn_index : [in] the index of the entry to be modified +* @pdn_info : [in] values for the PDN entry to be changed +* +* Modify a PDN entry +* +* Returns: 0 On Success, negative on failure +*/ +int ipa_nat_modify_pdn(uint32_t tbl_hdl, + uint8_t pdn_index, + ipa_nat_pdn_entry *pdn_info) +{ + struct ipa_ioc_nat_pdn_entry pdn_data; + + if (0 == tbl_hdl || tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid parameters passed \n"); + return -EINVAL; + } + + if (!pdn_info) { + IPAERR("pdn_info is NULL \n"); + return -EINVAL; + } + + if (pdn_index > IPA_MAX_PDN_NUM) { + IPAERR("PDN index is out of range %d", pdn_index); + return -EINVAL; + } + + pdn_data.pdn_index = pdn_index; + pdn_data.public_ip = pdn_info->public_ip; + pdn_data.src_metadata = pdn_info->src_metadata; + pdn_data.dst_metadata = pdn_info->dst_metadata; + + return ipa_nati_modify_pdn(&pdn_data); +} + + diff --git a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c index 32114b5b..d309bb34 100644 --- a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c +++ b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013 - 2017, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -33,9 +33,20 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef USE_GLIB #include #define strlcpy g_strlcpy +#else +static size_t strlcpy(char * dst, const char * src, size_t size) { + if (size < 1) + return 0; + strncpy(dst, src, size - 1); + dst[size - 1] = 0; + return strlen(dst); +} #endif struct ipa_nat_cache ipv4_nat_cache; +pthread_mutex_t nat_mutex = PTHREAD_MUTEX_INITIALIZER; + +static ipa_nat_pdn_entry pdns[IPA_MAX_PDN_NUM]; /* ------------------------------------------ UTILITY FUNCTIONS START @@ -152,6 +163,26 @@ uint32_t Read32BitFieldValue(uint32_t param, } } +/** +* GetIPAVer(void) - store IPA HW ver in cache +* +* +* Returns: 0 on success, negative on failure +*/ +int GetIPAVer(void) +{ + int ret; + + ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_GET_HW_VERSION, &ipv4_nat_cache.ver); + if (ret != 0) { + perror("GetIPAVer(): ioctl error value"); + IPAERR("unable to get IPA version. Error ;%d\n", ret); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + return -EINVAL; + } + IPADBG("IPA version is %d\n", ipv4_nat_cache.ver); + return 0; +} /** * CreateNatDevice() - Create nat devices @@ -247,6 +278,7 @@ void GetNearestEven(uint16_t num, uint16_t *ret) /** * dst_hash() - Find the index into ipv4 base table + * @public_ip: [in] public_ip * @trgt_ip: [in] Target IP address * @trgt_port: [in] Target port * @public_port: [in] Public port @@ -260,13 +292,18 @@ void GetNearestEven(uint16_t num, uint16_t *ret) * * Returns: >0 index into ipv4 base table, negative on failure */ -static uint16_t dst_hash(uint32_t trgt_ip, uint16_t trgt_port, - uint16_t public_port, uint8_t proto, - uint16_t size) +static uint16_t dst_hash(uint32_t public_ip, uint32_t trgt_ip, + uint16_t trgt_port, uint16_t public_port, + uint8_t proto, uint16_t size) { uint16_t hash = ((uint16_t)(trgt_ip)) ^ ((uint16_t)(trgt_ip >> 16)) ^ (trgt_port) ^ (public_port) ^ (proto); + if (ipv4_nat_cache.ver >= IPA_HW_v4_0) + hash ^= ((uint16_t)(public_ip)) ^ + ((uint16_t)(public_ip >> 16)); + + IPADBG("public ip 0x%X\n", public_ip); IPADBG("trgt_ip: 0x%x trgt_port: 0x%x\n", trgt_ip, trgt_port); IPADBG("public_port: 0x%x\n", public_port); IPADBG("proto: 0x%x size: 0x%x\n", proto, size); @@ -484,12 +521,18 @@ uint16_t ipa_nati_make_rule_hdl(uint16_t tbl_hdl, tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_hdl-1]; if (tbl_entry >= tbl_ptr->table_entries) { + /* Increase the current expansion table count */ + tbl_ptr->cur_expn_tbl_cnt++; + /* Update the index into table */ rule_hdl = tbl_entry - tbl_ptr->table_entries; rule_hdl = (rule_hdl << IPA_NAT_RULE_HDL_TBL_TYPE_BITS); /* Update the table type mask */ rule_hdl = (rule_hdl | IPA_NAT_RULE_HDL_TBL_TYPE_MASK); } else { + /* Increase the current count */ + tbl_ptr->cur_tbl_cnt++; + rule_hdl = tbl_entry; rule_hdl = (rule_hdl << IPA_NAT_RULE_HDL_TBL_TYPE_BITS); } @@ -675,6 +718,12 @@ int ipa_nati_add_ipv4_tbl(uint32_t public_ip_addr, return -EINVAL; } + /* store the initial public ip address in the cached pdn table + this is backward compatible for pre IPAv4 versions, we will always + use this ip as the single PDN address + */ + pdns[0].public_ip = public_ip_addr; + /* Return table handle */ ipv4_nat_cache.table_cnt++; *tbl_hdl = ipv4_nat_cache.table_cnt; @@ -727,6 +776,11 @@ int ipa_nati_alloc_table(uint16_t number_of_entries, ipv4_nat_cache.ipa_fd = fd; } + if (GetIPAVer()) { + IPAERR("unable to get ipa ver\n"); + return -EIO; + } + ret = CreateNatDevice(mem); return ret; } @@ -817,7 +871,7 @@ int ipa_nati_update_cache(struct ipa_ioc_nat_alloc_mem *mem, prot, flags, fd, offset); #endif - if (NULL == ipv4_rules_addr) { + if (MAP_FAILED == ipv4_rules_addr) { perror("unable to mmap the memory\n"); return -EINVAL; } @@ -898,7 +952,13 @@ int ipa_nati_del_ipv4_table(uint32_t tbl_hdl) if (!ipv4_nat_cache.ip4_tbl[index].valid) { IPAERR("invalid table handle passed\n"); - return -EINVAL; + ret = -EINVAL; + goto fail; + } + + if (pthread_mutex_lock(&nat_mutex) != 0) { + ret = -1; + goto lock_mutex_fail; } /* unmap the device memory from user space */ @@ -912,7 +972,10 @@ int ipa_nati_del_ipv4_table(uint32_t tbl_hdl) /* close the file descriptor of nat device */ if (close(ipv4_nat_cache.ip4_tbl[index].nat_fd)) { IPAERR("unable to close the file descriptor\n"); - return -EINVAL; + ret = -EINVAL; + if (pthread_mutex_unlock(&nat_mutex) != 0) + goto unlock_mutex_fail; + goto fail; } del_cmd.table_index = index; @@ -922,9 +985,12 @@ int ipa_nati_del_ipv4_table(uint32_t tbl_hdl) perror("ipa_nati_del_ipv4_table(): ioctl error value"); IPAERR("unable to post nat del command init Error: %d\n", ret); IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); - return -EINVAL; + ret = -EINVAL; + if (pthread_mutex_unlock(&nat_mutex) != 0) + goto unlock_mutex_fail; + goto fail; } - IPADBG("posted IPA_IOC_V4_DEL_NAT to kernel successfully\n"); + IPAERR("posted IPA_IOC_V4_DEL_NAT to kernel successfully\n"); free(ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta); free(ipv4_nat_cache.ip4_tbl[index].rule_id_array); @@ -936,7 +1002,22 @@ int ipa_nati_del_ipv4_table(uint32_t tbl_hdl) /* Decrease the table count by 1*/ ipv4_nat_cache.table_cnt--; + if (pthread_mutex_unlock(&nat_mutex) != 0) { + ret = -1; + goto unlock_mutex_fail; + } + return 0; + +lock_mutex_fail: + IPAERR("unable to lock the nat mutex\n"); + return ret; + +unlock_mutex_fail: + IPAERR("unable to unlock the nat mutex\n"); + +fail: + return ret; } int ipa_nati_query_timestamp(uint32_t tbl_hdl, @@ -953,6 +1034,11 @@ int ipa_nati_query_timestamp(uint32_t tbl_hdl, return -EINVAL; } + if (pthread_mutex_lock(&nat_mutex) != 0) { + IPAERR("unable to lock the nat mutex\n"); + return -1; + } + ipa_nati_parse_ipv4_rule_hdl(tbl_index, (uint16_t)rule_hdl, &expn_tbl, &tbl_entry); @@ -963,8 +1049,39 @@ int ipa_nati_query_timestamp(uint32_t tbl_hdl, (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_index].ipv4_expn_rules_addr; } - *time_stamp = Read32BitFieldValue(tbl_ptr[tbl_entry].ts_proto, - TIME_STAMP_FIELD); + if (tbl_ptr) + *time_stamp = Read32BitFieldValue(tbl_ptr[tbl_entry].ts_proto, + TIME_STAMP_FIELD); + + if (pthread_mutex_unlock(&nat_mutex) != 0) { + IPAERR("unable to unlock the nat mutex\n"); + return -1; + } + + return 0; +} + +int ipa_nati_modify_pdn(struct ipa_ioc_nat_pdn_entry *entry) +{ + if (entry->public_ip == 0) + IPADBG("PDN %d public ip will be set to 0\n", entry->pdn_index); + + if (ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_NAT_MODIFY_PDN, entry)) { + perror("ipa_nati_modify_pdn(): ioctl error value"); + IPAERR("unable to call modify pdn icotl\n"); + IPAERR("index %d, ip 0x%X, src_metdata 0x%X, dst_metadata 0x%X\n", + entry->pdn_index, entry->public_ip, entry->src_metadata, entry->dst_metadata); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + return -EIO; + } + + pdns[entry->pdn_index].public_ip = entry->public_ip; + pdns[entry->pdn_index].dst_metadata = entry->dst_metadata; + pdns[entry->pdn_index].src_metadata = entry->src_metadata; + + IPADBG("posted IPA_IOC_NAT_MODIFY_PDN to kernel successfully and stored in cache\n index %d, ip 0x%X, src_metdata 0x%X, dst_metadata 0x%X\n", + entry->pdn_index, entry->public_ip, entry->src_metadata, entry->dst_metadata); + return 0; } @@ -977,6 +1094,14 @@ int ipa_nati_add_ipv4_rule(uint32_t tbl_hdl, struct ipa_nat_indx_tbl_sw_rule index_sw_rule; uint16_t new_entry, new_index_tbl_entry; + /* verify that the rule's PDN is valid */ + if (clnt_rule->pdn_index >= IPA_MAX_PDN_NUM || + pdns[clnt_rule->pdn_index].public_ip == 0) { + IPAERR("invalid parameters, pdn index %d, public ip = 0x%X\n", + clnt_rule->pdn_index, pdns[clnt_rule->pdn_index].public_ip); + return -EINVAL; + } + memset(&sw_rule, 0, sizeof(sw_rule)); memset(&index_sw_rule, 0, sizeof(index_sw_rule)); @@ -1068,7 +1193,7 @@ uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule, uint16_t prev = 0, nxt_indx = 0, new_entry; struct ipa_nat_rule *tbl = NULL, *expn_tbl = NULL; - pub_ip_addr = tbl_ptr->public_addr; + pub_ip_addr = pdns[clnt_rule->pdn_index].public_ip; tbl = (struct ipa_nat_rule *)tbl_ptr->ipv4_rules_addr; expn_tbl = (struct ipa_nat_rule *)tbl_ptr->ipv4_expn_rules_addr; @@ -1080,6 +1205,7 @@ uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule, sw_rule->public_port = clnt_rule->public_port; sw_rule->target_ip = clnt_rule->target_ip; sw_rule->target_port = clnt_rule->target_port; + sw_rule->pdn_index = clnt_rule->pdn_index; /* consider only public and private ip fields */ sw_rule->ip_chksum = ipa_nati_calc_ip_cksum(pub_ip_addr, @@ -1106,10 +1232,11 @@ uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule, */ sw_rule->time_stamp = 0; sw_rule->rsvd2 = 0; + sw_rule->rsvd3 = 0; sw_rule->prev_index = 0; sw_rule->indx_tbl_entry = 0; - new_entry = dst_hash(clnt_rule->target_ip, + new_entry = dst_hash(pub_ip_addr, clnt_rule->target_ip, clnt_rule->target_port, clnt_rule->public_port, clnt_rule->protocol, @@ -1152,11 +1279,13 @@ uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule, /* On collision check for the free entry in expansion table */ new_entry = ipa_nati_expn_tbl_free_entry(expn_tbl, - tbl_ptr->expn_table_entries); + tbl_ptr->expn_table_entries); if (IPA_NAT_INVALID_NAT_ENTRY == new_entry) { /* Expansion table is full return*/ - IPAERR("expansion table is full\n"); + IPAERR("Expansion table is full\n"); + IPAERR("Current Table: %d & Expn Entries: %d\n", + tbl_ptr->cur_tbl_cnt, tbl_ptr->cur_expn_tbl_cnt); return IPA_NAT_INVALID_NAT_ENTRY; } new_entry += tbl_ptr->table_entries; @@ -1239,13 +1368,14 @@ uint16_t ipa_nati_generate_index_rule(const ipa_nat_ipv4_rule *clnt_rule, } /* On collision check for the free entry in expansion table */ - new_entry = ipa_nati_index_expn_get_free_entry( - indx_expn_tbl, - tbl_ptr->expn_table_entries); + new_entry = ipa_nati_index_expn_get_free_entry(indx_expn_tbl, + tbl_ptr->expn_table_entries); if (IPA_NAT_INVALID_NAT_ENTRY == new_entry) { /* Expansion table is full return*/ - IPAERR("index expansion table is full\n"); + IPAERR("Index expansion table is full\n"); + IPAERR("Current Table: %d & Expn Entries: %d\n", + tbl_ptr->cur_tbl_cnt, tbl_ptr->cur_expn_tbl_cnt); return IPA_NAT_INVALID_NAT_ENTRY; } new_entry += tbl_ptr->table_entries; @@ -1478,13 +1608,20 @@ int ipa_nati_del_ipv4_rule(uint32_t tbl_hdl, struct ipa_nat_ip4_table_cache *tbl_ptr; del_type rule_pos; uint8_t tbl_indx = (uint8_t)(tbl_hdl - 1); + int ret; /* Parse the rule handle */ ipa_nati_parse_ipv4_rule_hdl(tbl_indx, (uint16_t)rule_hdl, &expn_tbl, &tbl_entry); if (IPA_NAT_INVALID_NAT_ENTRY == tbl_entry) { IPAERR("Invalid Rule Entry\n"); - return -EINVAL; + ret = -EINVAL; + goto fail; + } + + if (pthread_mutex_lock(&nat_mutex) != 0) { + ret = -1; + goto mutex_lock_error; } IPADBG("Delete below rule\n"); @@ -1493,7 +1630,10 @@ int ipa_nati_del_ipv4_rule(uint32_t tbl_hdl, tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_indx]; if (!tbl_ptr->valid) { IPAERR("invalid table handle\n"); - return -EINVAL; + ret = -EINVAL; + if (pthread_mutex_unlock(&nat_mutex) != 0) + goto mutex_unlock_error; + goto fail; } ipa_nati_find_rule_pos(tbl_ptr, expn_tbl, @@ -1502,7 +1642,10 @@ int ipa_nati_del_ipv4_rule(uint32_t tbl_hdl, if (ipa_nati_post_del_dma_cmd(tbl_indx, tbl_entry, expn_tbl, rule_pos)) { - return -EINVAL; + ret = -EINVAL; + if (pthread_mutex_unlock(&nat_mutex) != 0) + goto mutex_unlock_error; + goto fail; } ipa_nati_del_dead_ipv4_head_nodes(tbl_indx); @@ -1516,7 +1659,22 @@ int ipa_nati_del_ipv4_rule(uint32_t tbl_hdl, ipa_nat_dump_ipv4_table(tbl_hdl); #endif + if (pthread_mutex_unlock(&nat_mutex) != 0) { + ret = -1; + goto mutex_unlock_error; + } + return 0; + +mutex_lock_error: + IPAERR("unable to lock the nat mutex\n"); + return ret; + +mutex_unlock_error: + IPAERR("unable to unlock the nat mutex\n"); + +fail: + return ret; } void ReorderCmds(struct ipa_ioc_nat_dma_cmd *cmd, int size) diff --git a/data-ipa-cfg-mgr/ipanat/test/Android.mk b/data-ipa-cfg-mgr/ipanat/test/Android.mk index c5336e4d..b8ae6a4b 100644 --- a/data-ipa-cfg-mgr/ipanat/test/Android.mk +++ b/data-ipa-cfg-mgr/ipanat/test/Android.mk @@ -1,3 +1,5 @@ +BOARD_PLATFORM_LIST := test +ifeq ($(call is-board-platform-in-list,$(BOARD_PLATFORM_LIST)),true) ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM))) ifneq (, $(filter aarch64 arm arm64, $(TARGET_ARCH))) @@ -47,3 +49,4 @@ include $(BUILD_EXECUTABLE) endif # $(TARGET_ARCH) endif +endif