diff --git a/Android.mk b/Android.mk index bd04c3a..4c67c26 100644 --- a/Android.mk +++ b/Android.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2016 The Android Open-Source Project +# Copyright (C) 2016 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. @@ -12,12 +12,80 @@ # 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. -# -ifneq ($(filter potter, $(TARGET_DEVICE)),) +ifneq ($(filter potter,$(TARGET_DEVICE)),) LOCAL_PATH := $(call my-dir) +FIRMWARE_ADSP_IMAGES := \ + adsp.b00 adsp.b01 adsp.b02 adsp.b03 adsp.b04 adsp.b05 adsp.b06 \ + adsp.b07 adsp.b08 adsp.b09 adsp.b10 adsp.b11 adsp.b12 adsp.b13 \ + adsp.mdt + +FIRMWARE_ADSP_SYMLINKS := $(addprefix $(TARGET_OUT_ETC)/firmware/,$(notdir $(FIRMWARE_MODEM_IMAGES))) +$(FIRMWARE_ADSP_SYMLINKS): $(LOCAL_INSTALLED_MODULE) + @echo "ADSP Firmware link: $@" + @mkdir -p $(dir $@) + @rm -rf $@ + $(hide) ln -sf /firmware/image/$(notdir $@) $@ + +ALL_DEFAULT_INSTALLED_MODULES += $(FIRMWARE_ADSP_SYMLINKS) + +FIRMWARE_FINGERPRINT_IMAGES := \ + fpctzappfingerprint.b00 fpctzappfingerprint.b01 fpctzappfingerprint.b02 \ + fpctzappfingerprint.b03 fpctzappfingerprint.b04 fpctzappfingerprint.b05 \ + fpctzappfingerprint.b06 fpctzappfingerprint.mdt + +FIRMWARE_FINGERPRINT_SYMLINKS := $(addprefix $(TARGET_OUT_ETC)/firmware/,$(notdir $(FIRMWARE_FINGERPRINT_IMAGES))) +$(FIRMWARE_FINGERPRINT_SYMLINKS): $(LOCAL_INSTALLED_MODULE) + @echo "Fingerprint Firmware link: $@" + @mkdir -p $(dir $@) + @rm -rf $@ + $(hide) ln -sf /firmware/image/$(notdir $@) $@ + +ALL_DEFAULT_INSTALLED_MODULES += $(FIRMWARE_FINGERPRINT_SYMLINKS) + +FIRMWARE_MODEM_IMAGES := \ + modem.b00 modem.b01 modem.b02 modem.b04 modem.b05 modem.b06 \ + modem.b07 modem.b08 modem.b09 modem.b10 modem.b11 modem.b12 \ + modem.b13 modem.b16 modem.b17 modem.b18 modem.b19 modem.b20 \ + modem.mdt + +FIRMWARE_MODEM_SYMLINKS := $(addprefix $(TARGET_OUT_ETC)/firmware/,$(notdir $(FIRMWARE_MODEM_IMAGES))) +$(FIRMWARE_MODEM_SYMLINKS): $(LOCAL_INSTALLED_MODULE) + @echo "Modem Firmware link: $@" + @mkdir -p $(dir $@) + @rm -rf $@ + $(hide) ln -sf /firmware/image/$(notdir $@) $@ + +ALL_DEFAULT_INSTALLED_MODULES += $(FIRMWARE_MODEM_SYMLINKS) + +FIRMWARE_WCNSS_IMAGES := \ + wcnss.b00 wcnss.b01 wcnss.b02 wcnss.b04 wcnss.b06 \ + wcnss.b09 wcnss.b10 wcnss.b11 wcnss.b12 wcnss.mdt + +FIRMWARE_WCNSS_SYMLINKS := $(addprefix $(TARGET_OUT_ETC)/firmware/,$(notdir $(FIRMWARE_WCNSS_IMAGES))) +$(FIRMWARE_WCNSS_SYMLINKS): $(LOCAL_INSTALLED_MODULE) + @echo "WCNSS Firmware link: $@" + @mkdir -p $(dir $@) + @rm -rf $@ + $(hide) ln -sf /firmware/image/$(notdir $@) $@ + +ALL_DEFAULT_INSTALLED_MODULES += $(FIRMWARE_WCNSS_SYMLINKS) + +FIRMWARE_WIDEVINE_IMAGES := \ + widevine.b00 widevine.b01 widevine.b02 widevine.b03 \ + widevine.b04 widevine.b05 widevine.b06 widevine.mdt + +FIRMWARE_WIDEVINE_SYMLINKS := $(addprefix $(TARGET_OUT_ETC)/firmware/,$(notdir $(FIRMWARE_WIDEVINE_IMAGES))) +$(FIRMWARE_WIDEVINE_SYMLINKS): $(LOCAL_INSTALLED_MODULE) + @echo "Widevine Firmware link: $@" + @mkdir -p $(dir $@) + @rm -rf $@ + $(hide) ln -sf /firmware/image/$(notdir $@) $@ + +ALL_DEFAULT_INSTALLED_MODULES += $(FIRMWARE_WIDEVINE_SYMLINKS) + include $(call all-makefiles-under,$(LOCAL_PATH)) endif \ No newline at end of file diff --git a/BoardConfig.mk b/BoardConfig.mk index 679f16b..f02aad7 100644 --- a/BoardConfig.mk +++ b/BoardConfig.mk @@ -1,5 +1,6 @@ # -# Copyright (C) 2015-2016 The Android Open-Source Project +# Copyright (C) 2016 The CyanogenMod Project +# Copyright (C) 2017 The LineageOS Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,66 +13,138 @@ # 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. -# + +-include vendor/motorola/potter/BoardConfigVendor.mk DEVICE_PATH := device/motorola/potter -TARGET_RECOVERY_DEVICE_DIRS := $(DEVICE_PATH) +BOARD_VENDOR := motorola-qcom -TARGET_ARCH := arm -TARGET_CPU_ABI := armeabi-v7a -TARGET_CPU_ABI2 := armeabi -TARGET_CPU_VARIANT := cortex-a53 -TARGET_ARCH_VARIANT := armv7-a-neon -TARGET_CPU_SMP := true -ARCH_ARM_HAVE_TLS_REGISTER := true - -TARGET_GLOBAL_CFLAGS += -mfpu=neon -mfloat-abi=softfp -TARGET_GLOBAL_CPPFLAGS += -mfpu=neon -mfloat-abi=softfp +TARGET_SPECIFIC_HEADER_PATH := $(VENDOR_PATH)/include +# Platform TARGET_BOARD_PLATFORM := msm8953 +TARGET_BOARD_PLATFORM_GPU := qcom-adreno506 +# Bootloader TARGET_BOOTLOADER_BOARD_NAME := MSM8953 TARGET_NO_BOOTLOADER := true -#TARGET_PREBUILT_KERNEL := $(DEVICE_PATH)/boot.img-zImage -#TARGET_PREBUILT_DTB := $(DEVICE_PATH)/boot.img-dt +# Architecture +TARGET_ARCH := arm +TARGET_ARCH_VARIANT := armv7-a-neon +TARGET_CPU_ABI := armeabi-v7a +TARGET_CPU_ABI2 := armeabi +TARGET_CPU_VARIANT := cortex-a53 -BOARD_KERNEL_CMDLINE := androidboot.hardware=qcom ehci-hcd.park=3 androidboot.bootdevice=7824900.sdhci vmalloc=350M androidboot.selinux=permissive +# Asserts +TARGET_OTA_ASSERT_DEVICE := potter,potter_retail + +# Init +TARGET_INIT_VENDOR_LIB := libinit_potter +TARGET_RECOVERY_DEVICE_MODULES := libinit_potter + +# Kernel +BOARD_KERNEL_CMDLINE := console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 androidboot.hardware=qcom user_debug=30 msm_rtb.filter=0x237 +BOARD_KERNEL_CMDLINE += ehci-hcd.park=3 androidboot.bootdevice=7824900.sdhci lpm_levels.sleep_disabled=1 vmalloc=350M BOARD_KERNEL_BASE := 0x80000000 -BOARD_KERNEL_SEPARATED_DT := true -BOARD_RAMDISK_OFFSET := 0x01000000 +BOARD_KERNEL_LZ4C_DT := true BOARD_KERNEL_PAGESIZE := 2048 -BOARD_MKBOOTIMG_ARGS := --ramdisk_offset 0x01000000 -BOARD_CUSTOM_BOOTIMG_MK := $(DEVICE_PATH)/mkbootimg.mk -KERNEL_TOOLCHAIN_PREFIX := arm-linux-androidkernel- +BOARD_KERNEL_SEPARATED_DT := true +BOARD_MKBOOTIMG_ARGS := --ramdisk_offset 0x01000000 --tags_offset 0x00000100 +TARGET_KERNEL_ARCH := arm TARGET_KERNEL_CONFIG := addison_potter TARGET_KERNEL_SOURCE := kernel/motorola/msm8953 -BOARD_USES_QCOM_HARDWARE := true +# Audio +AUDIO_FEATURE_ENABLED_COMPRESS_VOIP := true +AUDIO_FEATURE_ENABLED_EXTN_FORMATS := true +AUDIO_FEATURE_ENABLED_FLAC_OFFLOAD := true +AUDIO_FEATURE_ENABLED_FLUENCE := true +AUDIO_FEATURE_ENABLED_HFP := true +AUDIO_FEATURE_ENABLED_KPI_OPTIMIZE := true +AUDIO_FEATURE_ENABLED_MULTI_VOICE_SESSIONS := true +AUDIO_FEATURE_ENABLED_PCM_OFFLOAD := true +AUDIO_FEATURE_ENABLED_PCM_OFFLOAD_24 := true +BOARD_USES_ALSA_AUDIO := true +USE_CUSTOM_AUDIO_POLICY := 1 +USE_XML_AUDIO_POLICY_CONF := 1 + +# Bluetooth +BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := $(DEVICE_PATH)/bluetooth +BOARD_HAVE_BLUETOOTH := true +BOARD_HAVE_BLUETOOTH_QCOM := true +BLUETOOTH_HCI_USE_MCT := true + +# Camera +TARGET_CAMERASERVICE_CLOSES_NATIVE_HANDLES := true +USE_DEVICE_SPECIFIC_CAMERA := true + +# Charger +BACKLIGHT_PATH := /sys/class/leds/lcd-backlight/brightness +BOARD_CHARGER_ENABLE_SUSPEND := true +BOARD_NO_CHARGER_LED := true + +# CMHW +BOARD_USES_CYANOGEN_HARDWARE := true +BOARD_HARDWARE_CLASS += hardware/cyanogen/cmhw + +# Crypto +TARGET_HW_DISK_ENCRYPTION := true + +# Display +BOARD_USES_ADRENO := true +NUM_FRAMEBUFFER_SURFACE_BUFFERS := 3 +OVERRIDE_RS_DRIVER := libRSDriver_adreno.so +TARGET_USES_C2D_COMPOSITION := true +TARGET_USES_ION := true +USE_OPENGL_RENDERER := true + +# Keymaster +TARGET_PROVIDES_KEYMASTER := true + +# Lights +TARGET_PROVIDES_LIBLIGHT := true + +# Media +TARGET_USES_MEDIA_EXTENSIONS := true # Partitions BOARD_FLASH_BLOCK_SIZE := 131072 +BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4 BOARD_BOOTIMAGE_PARTITION_SIZE := 16777216 # 16384 * 1024 mmcblk0p37 +BOARD_CACHEIMAGE_PARTITION_SIZE := 268435456 # 262144 * 1024 mmcblk0p52 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 16879616 # 16484 * 1024 mmcblk0p38 BOARD_SYSTEMIMAGE_PARTITION_SIZE := 4294967296 # 4194304 * 1024 mmcblk0p53 BOARD_USERDATAIMAGE_PARTITION_SIZE := 25614597120 # 25014255 * 1024 mmcblk0p54 -# don't take forever to wipe -BOARD_SUPPRESS_SECURE_ERASE := true -#COMMON_GLOBAL_CFLAGS += -DNO_SECURE_DISCARD +# Power +TARGET_POWERHAL_VARIANT := qcom -# Crypto -TARGET_HW_DISK_ENCRYPTION := true -TW_INCLUDE_CRYPTO := true +# Qualcomm support +BOARD_USES_QCOM_HARDWARE := true -# TWRP -RECOVERY_SDCARD_ON_DATA := true -TARGET_RECOVERY_FSTAB := device/motorola/potter/twrp.fstab -TARGET_RECOVERY_PIXEL_FORMAT := RGB_565 -TARGET_RECOVERY_QCOM_RTC_FIX := true +# Radio +BOARD_PROVIDES_LIBRIL := true +BOARD_PROVIDES_RILD := true + +# Recovery +BOARD_HAS_NO_SELECT_BUTTON := true +TARGET_RECOVERY_FSTAB := $(DEVICE_PATH)/rootdir/etc/fstab.qcom TARGET_USERIMAGES_USE_EXT4 := true TARGET_USERIMAGES_USE_F2FS := true -TW_NEW_ION_HEAP := true -TW_THEME := portrait_hdpi -TW_SCREEN_BLANK_ON_BOOT := true \ No newline at end of file + +# SELinux +include device/qcom/sepolicy/sepolicy.mk +BOARD_SEPOLICY_DIRS += $(DEVICE_PATH)/sepolicy + +# Wifi +BOARD_HAS_QCOM_WLAN := true +BOARD_WLAN_DEVICE := qcwcn +BOARD_HOSTAPD_DRIVER := NL80211 +BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_qcwcn +BOARD_WPA_SUPPLICANT_DRIVER := NL80211 +BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_qcwcn +WIFI_DRIVER_MODULE_PATH := "/system/lib/modules/wlan.ko" +WIFI_DRIVER_MODULE_NAME := "wlan" +WPA_SUPPLICANT_VERSION := VER_0_8_X \ No newline at end of file diff --git a/android_filesystem_config.h b/android_filesystem_config.h new file mode 100644 index 0000000..bcaea38 --- /dev/null +++ b/android_filesystem_config.h @@ -0,0 +1,37 @@ +/* +# Copyright (c) 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 +# 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 + +#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS + const struct fs_path_config android_device_files[] = { + // { 00755, AID_UID, AID_GID, (1ULL << CAPABILITY), "PATH_TO_BINARY" }, + { 00755, AID_SYSTEM, AID_SYSTEM, (1ULL << CAP_NET_BIND_SERVICE), "system/bin/imsdatadaemon" }, + { 00755, AID_SYSTEM, AID_RADIO, (1ULL << CAP_NET_BIND_SERVICE), "system/bin/ims_rtp_daemon" }, +}; \ No newline at end of file diff --git a/audio/audio_effects.conf b/audio/audio_effects.conf new file mode 100644 index 0000000..612e4f2 --- /dev/null +++ b/audio/audio_effects.conf @@ -0,0 +1,286 @@ +# List of effect libraries to load. Each library element must contain a "path" element +# giving the full path of the library .so file. +# libraries { +# { +# path +# } +# } +libraries { + bundle { + path /system/lib/soundfx/libbundlewrapper.so + } + reverb { + path /system/lib/soundfx/libreverbwrapper.so + } + visualizer_sw { + path /system/lib/soundfx/libvisualizer.so + } + visualizer_hw { + path /system/lib/soundfx/libqcomvisualizer.so + } + downmix { + path /system/lib/soundfx/libdownmix.so + } + loudness_enhancer { + path /system/lib/soundfx/libldnhncr.so + } + proxy { + path /system/lib/soundfx/libeffectproxy.so + } + offload_bundle { + path /system/lib/soundfx/libqcompostprocbundle.so + } + audio_pre_processing { + path /system/lib/soundfx/libqcomvoiceprocessing.so + } +} + +# Default pre-processing library. Add to audio_effect.conf "libraries" section if +# audio HAL implements support for default software audio pre-processing effects +# +# pre_processing { +# path /system/lib/soundfx/libaudiopreprocessing.so +# } + +# list of effects to load. Each effect element must contain a "library" and a "uuid" element. +# The value of the "library" element must correspond to the name of one library element in the +# "libraries" element. +# The name of the effect element is indicative, only the value of the "uuid" element +# designates the effect. +# The uuid is the implementation specific UUID as specified by the effect vendor. This is not the +# generic effect type UUID. +# effects { +# { +# library +# uuid +# } +# ... +# } + +effects { + +# additions for the proxy implementation +# Proxy implementation + #effectname { + #library proxy + #uuid xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + # SW implemetation of the effect. Added as a node under the proxy to + # indicate this as a sub effect. + #libsw { + #library libSW + #uuid yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy + #} End of SW effect + + # HW implementation of the effect. Added as a node under the proxy to + # indicate this as a sub effect. + #libhw { + #library libHW + #uuid zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz + #}End of HW effect + #} End of effect proxy + + bassboost { + library proxy + uuid 14804144-a5ee-4d24-aa88-0002a5d5c51b + + libsw { + library bundle + uuid 8631f300-72e2-11df-b57e-0002a5d5c51b + } + + libhw { + library offload_bundle + uuid 2c4a8c24-1581-487f-94f6-0002a5d5c51b + } + } + virtualizer { + library proxy + uuid d3467faa-acc7-4d34-acaf-0002a5d5c51b + + libsw { + library bundle + uuid 1d4033c0-8557-11df-9f2d-0002a5d5c51b + } + + libhw { + library offload_bundle + uuid 509a4498-561a-4bea-b3b1-0002a5d5c51b + } + } + equalizer { + library proxy + uuid c8e70ecd-48ca-456e-8a4f-0002a5d5c51b + + libsw { + library bundle + uuid ce772f20-847d-11df-bb17-0002a5d5c51b + } + + libhw { + library offload_bundle + uuid a0dac280-401c-11e3-9379-0002a5d5c51b + } + } + volume { + library bundle + uuid 119341a0-8469-11df-81f9-0002a5d5c51b + } + reverb_env_aux { + library proxy + uuid 48404ac9-d202-4ccc-bf84-0002a5d5c51b + + libsw { + library reverb + uuid 4a387fc0-8ab3-11df-8bad-0002a5d5c51b + } + + libhw { + library offload_bundle + uuid 79a18026-18fd-4185-8233-0002a5d5c51b + } + } + reverb_env_ins { + library proxy + uuid b707403a-a1c1-4291-9573-0002a5d5c51b + + libsw { + library reverb + uuid c7a511a0-a3bb-11df-860e-0002a5d5c51b + } + + libhw { + library offload_bundle + uuid eb64ea04-973b-43d2-8f5e-0002a5d5c51b + } + } + reverb_pre_aux { + library proxy + uuid 1b78f587-6d1c-422e-8b84-0002a5d5c51b + + libsw { + library reverb + uuid f29a1400-a3bb-11df-8ddc-0002a5d5c51b + } + + libhw { + library offload_bundle + uuid 6987be09-b142-4b41-9056-0002a5d5c51b + } + } + reverb_pre_ins { + library proxy + uuid f3e178d2-ebcb-408e-8357-0002a5d5c51b + + libsw { + library reverb + uuid 172cdf00-a3bc-11df-a72f-0002a5d5c51b + } + + libhw { + library offload_bundle + uuid aa2bebf6-47cf-4613-9bca-0002a5d5c51b + } + } + visualizer { + library proxy + uuid 1d0a1a53-7d5d-48f2-8e71-27fbd10d842c + + libsw { + library visualizer_sw + uuid d069d9e0-8329-11df-9168-0002a5d5c51b + } + + libhw { + library visualizer_hw + uuid 7a8044a0-1a71-11e3-a184-0002a5d5c51b + } + } + downmix { + library downmix + uuid 93f04452-e4fe-41cc-91f9-e475b6d1d69f + } + hw_acc { + library offload_bundle + uuid 7d1580bd-297f-4683-9239-e475b6d1d69f + } + loudness_enhancer { + library loudness_enhancer + uuid fa415329-2034-4bea-b5dc-5b381c8d1e2c + } + aec { + library audio_pre_processing + uuid 0f8d0d2a-59e5-45fe-b6e4-248c8a799109 + } + ns { + library audio_pre_processing + uuid 1d97bb0b-9e2f-4403-9ae3-58c2554306f8 + } +} + +# Default pre-processing effects. Add to audio_effect.conf "effects" section if +# audio HAL implements support for them. +# +# agc { +# library pre_processing +# uuid aa8130e0-66fc-11e0-bad0-0002a5d5c51b +# } +# aec { +# library pre_processing +# uuid bb392ec0-8d4d-11e0-a896-0002a5d5c51b +# } +# ns { +# library pre_processing +# uuid c06c8400-8e06-11e0-9cb6-0002a5d5c51b +# } + +# Audio preprocessor configurations. +# The pre processor configuration consists in a list of elements each describing +# pre processor settings for a given input source. Valid input source names are: +# "mic", "camcorder", "voice_recognition", "voice_communication" +# Each input source element contains a list of effects elements. The name of the effect +# element must be the name of one of the effects in the "effects" list of the file. +# Each effect element may optionally contain a list of parameters and their +# default value to apply when the pre processor effect is created. +# A parameter is defined by a "param" element and a "value" element. Each of these elements +# consists in one or more elements specifying a type followed by a value. +# The types defined are: "int", "short", "float", "bool" and "string" +# When both "param" and "value" are a single int, a simple form is allowed where just +# the param and value pair is present in the parameter description +# pre_processing { +# { +# { +# { +# param { +# int|short|float|bool|string +# [ int|short|float|bool|string ] +# ... +# } +# value { +# int|short|float|bool|string +# [ int|short|float|bool|string ] +# ... +# } +# } +# { } +# ... +# } +# ... +# } +# ... +# } + +# Added aec, ns effects for voice_commuincation, which are supported by the board + +pre_processing { + voice_communication { + aec { + } + ns { + } + } +} + +# +# TODO: add default audio pre processor configurations after debug and tuning phase +# diff --git a/audio/audio_output_policy.conf b/audio/audio_output_policy.conf new file mode 100644 index 0000000..313d36c --- /dev/null +++ b/audio/audio_output_policy.conf @@ -0,0 +1,56 @@ +# List of profiles for the output device session where stream is routed. +# A stream opened with the inputs attributes which match the "flags" and +# "formats" as specified in the profile is routed to a device at +# sample rate specified under "sampling_rates" and bit width under +# "bit_width" and the topology extracted from the acdb data against +# the "app_type". +# +# the flags and formats are specified using the strings corresponding to +# enums in audio.h and audio_policy.h. They are concatenated with "|" +# without space or "\n". +# the flags and formats should match the ones in "audio_policy.conf" + +outputs { + default { + flags AUDIO_OUTPUT_FLAG_PRIMARY + formats AUDIO_FORMAT_PCM_16_BIT + sampling_rates 48000 + bit_width 16 + app_type 69937 + } + deep_buffer { + flags AUDIO_OUTPUT_FLAG_DEEP_BUFFER + formats AUDIO_FORMAT_PCM_16_BIT + sampling_rates 48000 + bit_width 16 + app_type 69936 + } + direct { + flags AUDIO_OUTPUT_FLAG_DIRECT + formats AUDIO_FORMAT_PCM_16_BIT + sampling_rates 48000 + bit_width 16 + app_type 69936 + } + direct_pcm { + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM + formats AUDIO_FORMAT_PCM_16_BIT + sampling_rates 44100|48000|96000|192000 + bit_width 16 + app_type 69936 + } + compress_offload_16 { + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING + formats AUDIO_FORMAT_MP3|AUDIO_FORMAT_AC3|AUDIO_FORMAT_E_AC3|AUDIO_FORMAT_PCM_16_BIT_OFFLOAD|AUDIO_FORMAT_PCM_24_BIT_OFFLOAD|AUDIO_FORMAT_FLAC|AUDIO_FORMAT_ALAC|AUDIO_FORMAT_APE|AUDIO_FORMAT_AAC_LC|AUDIO_FORMAT_AAC_HE_V1|AUDIO_FORMAT_AAC_HE_V2|AUDIO_FORMAT_WMA|AUDIO_FORMAT_WMA_PRO|AUDIO_FORMAT_VORBIS|AUDIO_FORMAT_AAC_ADTS_LC|AUDIO_FORMAT_AAC_ADTS_HE_V1|AUDIO_FORMAT_AAC_ADTS_HE_V2 + sampling_rates 44100|48000 + bit_width 16 + app_type 69936 + } + compress_offload_24 { + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING + formats AUDIO_FORMAT_PCM_24_BIT_OFFLOAD|AUDIO_FORMAT_FLAC|AUDIO_FORMAT_ALAC|AUDIO_FORMAT_APE|AUDIO_FORMAT_VORBIS + sampling_rates 44100|48000|96000|192000 + bit_width 24 + app_type 69940 + } +} diff --git a/audio/audio_platform_info_extcodec.xml b/audio/audio_platform_info_extcodec.xml new file mode 100644 index 0000000..117e86e --- /dev/null +++ b/audio/audio_platform_info_extcodec.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/audio_policy_configuration.xml b/audio/audio_policy_configuration.xml new file mode 100644 index 0000000..ab5894c --- /dev/null +++ b/audio/audio_policy_configuration.xml @@ -0,0 +1,191 @@ + + + + + + + + + + Speaker + Earpiece + Telephony Tx + Built-In Mic + Built-In Back Mic + Telephony Rx + + Speaker + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/mixer_paths_wcd9306.xml b/audio/mixer_paths_wcd9306.xml new file mode 100644 index 0000000..9011616 --- /dev/null +++ b/audio/mixer_paths_wcd9306.xml @@ -0,0 +1,1198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bluetooth/bdroid_buildcfg.h b/bluetooth/bdroid_buildcfg.h new file mode 100644 index 0000000..bd266be --- /dev/null +++ b/bluetooth/bdroid_buildcfg.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef _BDROID_BUILDCFG_H +#define _BDROID_BUILDCFG_H + +#include +#include + +#define BTM_DEF_LOCAL_NAME "Moto Z Play" +#define BTA_DISABLE_DELAY 1000 /* in milliseconds */ +#define BLUETOOTH_QTI_SW TRUE +#define BLE_VND_INCLUDED TRUE +#endif diff --git a/camera/Android.mk b/camera/Android.mk new file mode 100644 index 0000000..1721477 --- /dev/null +++ b/camera/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES := system/media/camera/include + +LOCAL_SRC_FILES := \ + CameraWrapper.cpp + +LOCAL_SHARED_LIBRARIES := \ + libhardware liblog libcamera_client libutils libcutils + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_MODULE := camera.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/camera/CameraWrapper.cpp b/camera/CameraWrapper.cpp new file mode 100644 index 0000000..53467be --- /dev/null +++ b/camera/CameraWrapper.cpp @@ -0,0 +1,609 @@ +/* + * Copyright (C) 2017 The LineageOS 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. + */ + +/** +* @file CameraWrapper.cpp +* +* This file wraps a vendor camera module. +* +*/ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "CameraWrapper" +#include +#include + +#include +#include +#include +#include +#include +#include + +#define BACK_CAMERA 0 +#define FRONT_CAMERA 1 + +#define OPEN_RETRIES 10 +#define OPEN_RETRY_MSEC 40 + +using namespace android; + +static Mutex gCameraWrapperLock; +static camera_module_t *gVendorModule = 0; + +static char **fixed_set_params = NULL; + +static int camera_device_open(const hw_module_t *module, const char *name, + hw_device_t **device); +static int camera_get_number_of_cameras(void); +static int camera_get_camera_info(int camera_id, struct camera_info *info); + +static struct hw_module_methods_t camera_module_methods = { + .open = camera_device_open +}; + +camera_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = CAMERA_HARDWARE_MODULE_ID, + .name = "Moto Z Play Camera Wrapper", + .author = "The LineageOS Project", + .methods = &camera_module_methods, + .dso = NULL, /* remove compilation warnings */ + .reserved = {0}, /* remove compilation warnings */ + }, + .get_number_of_cameras = camera_get_number_of_cameras, + .get_camera_info = camera_get_camera_info, + .set_callbacks = NULL, /* remove compilation warnings */ + .get_vendor_tag_ops = NULL, /* remove compilation warnings */ + .open_legacy = NULL, /* remove compilation warnings */ + .set_torch_mode = NULL, /* remove compilation warnings */ + .init = NULL, /* remove compilation warnings */ + .reserved = {0}, /* remove compilation warnings */ +}; + + +typedef struct wrapper_camera_device { + camera_device_t base; + int id; + camera_device_t *vendor; +} wrapper_camera_device_t; + +#define VENDOR_CALL(device, func, ...) ({ \ + wrapper_camera_device_t *__wrapper_dev = (wrapper_camera_device_t*) device; \ + __wrapper_dev->vendor->ops->func(__wrapper_dev->vendor, ##__VA_ARGS__); \ +}) + +#define CAMERA_ID(device) (((wrapper_camera_device_t *)(device))->id) + +static int check_vendor_module() +{ + int rv = 0; + ALOGV("%s", __FUNCTION__); + + if (gVendorModule) + return 0; + + rv = hw_get_module_by_class("camera", "vendor", + (const hw_module_t**)&gVendorModule); + if (rv) + ALOGE("failed to open vendor camera module"); + return rv; +} + +static char *camera_fixup_getparams(int id, const char *settings) +{ + CameraParameters params; + params.unflatten(String8(settings)); + +#if !LOG_NDEBUG + ALOGV("%s: original parameters:", __FUNCTION__); + params.dump(); +#endif + + params.set("longshot-supported", "false"); + params.set("video-stabilization-supported", "false"); + +#if !LOG_NDEBUG + ALOGV("%s: fixed parameters:", __FUNCTION__); + params.dump(); +#endif + + String8 strParams = params.flatten(); + char *ret = strdup(strParams.string()); + + return ret; +} + +static char *camera_fixup_setparams(int id, const char *settings) +{ + CameraParameters params; + params.unflatten(String8(settings)); + +#if !LOG_NDEBUG + ALOGV("%s: original parameters:", __FUNCTION__); + params.dump(); +#endif + +#if !LOG_NDEBUG + ALOGV("%s: fixed parameters:", __FUNCTION__); + params.dump(); +#endif + + String8 strParams = params.flatten(); + if (fixed_set_params[id]) + free(fixed_set_params[id]); + fixed_set_params[id] = strdup(strParams.string()); + char *ret = fixed_set_params[id]; + + return ret; +} + +/******************************************************************* + * implementation of camera_device_ops functions + *******************************************************************/ + +static int camera_set_preview_window(struct camera_device *device, + struct preview_stream_ops *window) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, set_preview_window, window); +} + +static void camera_set_callbacks(struct camera_device *device, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user) +{ + if (!device) + return; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + VENDOR_CALL(device, set_callbacks, notify_cb, data_cb, data_cb_timestamp, + get_memory, user); +} + +static void camera_enable_msg_type(struct camera_device *device, + int32_t msg_type) +{ + if (!device) + return; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + VENDOR_CALL(device, enable_msg_type, msg_type); +} + +static void camera_disable_msg_type(struct camera_device *device, + int32_t msg_type) +{ + if (!device) + return; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + VENDOR_CALL(device, disable_msg_type, msg_type); +} + +static int camera_msg_type_enabled(struct camera_device *device, + int32_t msg_type) +{ + if (!device) + return 0; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, msg_type_enabled, msg_type); +} + +static int camera_start_preview(struct camera_device *device) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, start_preview); +} + +static void camera_stop_preview(struct camera_device *device) +{ + if (!device) + return; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + VENDOR_CALL(device, stop_preview); +} + +static int camera_preview_enabled(struct camera_device *device) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, preview_enabled); +} + +static int camera_store_meta_data_in_buffers(struct camera_device *device, + int enable) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, store_meta_data_in_buffers, enable); +} + +static int camera_start_recording(struct camera_device *device) +{ + if (!device) + return EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, start_recording); +} + +static void camera_stop_recording(struct camera_device *device) +{ + if (!device) + return; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + VENDOR_CALL(device, stop_recording); +} + +static int camera_recording_enabled(struct camera_device *device) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, recording_enabled); +} + +static void camera_release_recording_frame(struct camera_device *device, + const void *opaque) +{ + if (!device) + return; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + VENDOR_CALL(device, release_recording_frame, opaque); +} + +static int camera_auto_focus(struct camera_device *device) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, auto_focus); +} + +static int camera_cancel_auto_focus(struct camera_device *device) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, cancel_auto_focus); +} + +static int camera_take_picture(struct camera_device *device) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, take_picture); +} + +static int camera_cancel_picture(struct camera_device *device) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, cancel_picture); +} + +static int camera_set_parameters(struct camera_device *device, + const char *params) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + char *tmp = NULL; + tmp = camera_fixup_setparams(CAMERA_ID(device), params); + + int ret = VENDOR_CALL(device, set_parameters, tmp); + return ret; +} + +static char *camera_get_parameters(struct camera_device *device) +{ + if (!device) + return NULL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + char *params = VENDOR_CALL(device, get_parameters); + + char *tmp = camera_fixup_getparams(CAMERA_ID(device), params); + VENDOR_CALL(device, put_parameters, params); + params = tmp; + return params; +} + +static void camera_put_parameters(struct camera_device *device, char *params) +{ + if (params) + free(params); +} + +static int camera_send_command(struct camera_device *device, + int32_t cmd, int32_t arg1, int32_t arg2) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, send_command, cmd, arg1, arg2); +} + +static void camera_release(struct camera_device *device) +{ + if (!device) + return; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + VENDOR_CALL(device, release); +} + +static int camera_dump(struct camera_device *device, int fd) +{ + if (!device) + return -EINVAL; + + ALOGV("%s->%08X->%08X", __FUNCTION__, (uintptr_t)device, + (uintptr_t)(((wrapper_camera_device_t*)device)->vendor)); + + return VENDOR_CALL(device, dump, fd); +} + +extern "C" void heaptracker_free_leaked_memory(void); + +static int camera_device_close(hw_device_t *device) +{ + int ret = 0; + wrapper_camera_device_t *wrapper_dev = NULL; + + ALOGV("%s", __FUNCTION__); + + Mutex::Autolock lock(gCameraWrapperLock); + + if (!device) { + ret = -EINVAL; + goto done; + } + + for (int i = 0; i < camera_get_number_of_cameras(); i++) { + if (fixed_set_params[i]) + free(fixed_set_params[i]); + } + + wrapper_dev = (wrapper_camera_device_t*) device; + + wrapper_dev->vendor->common.close((hw_device_t*)wrapper_dev->vendor); + if (wrapper_dev->base.ops) + free(wrapper_dev->base.ops); + free(wrapper_dev); +done: +#ifdef HEAPTRACKER + heaptracker_free_leaked_memory(); +#endif + return ret; +} + +/******************************************************************* + * implementation of camera_module functions + *******************************************************************/ + +/* open device handle to one of the cameras + * + * assume camera service will keep singleton of each camera + * so this function will always only be called once per camera instance + */ + +static int camera_device_open(const hw_module_t *module, const char *name, + hw_device_t **device) +{ + int rv = 0; + int num_cameras = 0; + int cameraid; + wrapper_camera_device_t *camera_device = NULL; + camera_device_ops_t *camera_ops = NULL; + + Mutex::Autolock lock(gCameraWrapperLock); + + ALOGV("%s", __FUNCTION__); + + if (name != NULL) { + if (check_vendor_module()) + return -EINVAL; + + cameraid = atoi(name); + num_cameras = gVendorModule->get_number_of_cameras(); + + fixed_set_params = (char **) malloc(sizeof(char *) * num_cameras); + if (!fixed_set_params) { + ALOGE("parameter memory allocation fail"); + rv = -ENOMEM; + goto fail; + } + memset(fixed_set_params, 0, sizeof(char *) * num_cameras); + + if (cameraid > num_cameras) { + ALOGE("camera service provided cameraid out of bounds, " + "cameraid = %d, num supported = %d", + cameraid, num_cameras); + rv = -EINVAL; + goto fail; + } + + camera_device = (wrapper_camera_device_t*)malloc(sizeof(*camera_device)); + if (!camera_device) { + ALOGE("camera_device allocation fail"); + rv = -ENOMEM; + goto fail; + } + memset(camera_device, 0, sizeof(*camera_device)); + camera_device->id = cameraid; + + int retries = OPEN_RETRIES; + bool retry; + do { + rv = gVendorModule->common.methods->open( + (const hw_module_t*)gVendorModule, name, + (hw_device_t**)&(camera_device->vendor)); + retry = --retries > 0 && rv; + if (retry) + usleep(OPEN_RETRY_MSEC * 1000); + } while (retry); + if (rv) { + ALOGE("vendor camera open fail"); + goto fail; + } + ALOGV("%s: got vendor camera device 0x%08X", + __FUNCTION__, (uintptr_t)(camera_device->vendor)); + + camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops)); + if (!camera_ops) { + ALOGE("camera_ops allocation fail"); + rv = -ENOMEM; + goto fail; + } + + memset(camera_ops, 0, sizeof(*camera_ops)); + + camera_device->base.common.tag = HARDWARE_DEVICE_TAG; + camera_device->base.common.version = CAMERA_MODULE_API_VERSION_1_0; + camera_device->base.common.module = (hw_module_t *)(module); + camera_device->base.common.close = camera_device_close; + camera_device->base.ops = camera_ops; + + camera_ops->set_preview_window = camera_set_preview_window; + camera_ops->set_callbacks = camera_set_callbacks; + camera_ops->enable_msg_type = camera_enable_msg_type; + camera_ops->disable_msg_type = camera_disable_msg_type; + camera_ops->msg_type_enabled = camera_msg_type_enabled; + camera_ops->start_preview = camera_start_preview; + camera_ops->stop_preview = camera_stop_preview; + camera_ops->preview_enabled = camera_preview_enabled; + camera_ops->store_meta_data_in_buffers = camera_store_meta_data_in_buffers; + camera_ops->start_recording = camera_start_recording; + camera_ops->stop_recording = camera_stop_recording; + camera_ops->recording_enabled = camera_recording_enabled; + camera_ops->release_recording_frame = camera_release_recording_frame; + camera_ops->auto_focus = camera_auto_focus; + camera_ops->cancel_auto_focus = camera_cancel_auto_focus; + camera_ops->take_picture = camera_take_picture; + camera_ops->cancel_picture = camera_cancel_picture; + camera_ops->set_parameters = camera_set_parameters; + camera_ops->get_parameters = camera_get_parameters; + camera_ops->put_parameters = camera_put_parameters; + camera_ops->send_command = camera_send_command; + camera_ops->release = camera_release; + camera_ops->dump = camera_dump; + + *device = &camera_device->base.common; + } + + return rv; + +fail: + if (camera_device) { + free(camera_device); + camera_device = NULL; + } + if (camera_ops) { + free(camera_ops); + camera_ops = NULL; + } + *device = NULL; + return rv; +} + +static int camera_get_number_of_cameras(void) +{ + ALOGV("%s", __FUNCTION__); + if (check_vendor_module()) + return 0; + return gVendorModule->get_number_of_cameras(); +} + +static int camera_get_camera_info(int camera_id, struct camera_info *info) +{ + ALOGV("%s", __FUNCTION__); + if (check_vendor_module()) + return 0; + return gVendorModule->get_camera_info(camera_id, info); +} diff --git a/cmactions/Android.mk b/cmactions/Android.mk new file mode 100644 index 0000000..00cb9da --- /dev/null +++ b/cmactions/Android.mk @@ -0,0 +1,41 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := CMActions +LOCAL_CERTIFICATE := platform +LOCAL_PRIVILEGED_MODULE := true + +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-v14-preference \ + android-support-v7-appcompat \ + android-support-v7-preference \ + android-support-v7-recyclerview \ + org.cyanogenmod.platform.internal + +LOCAL_PROGUARD_FLAG_FILES := proguard.flags + +LOCAL_RESOURCE_DIR := \ + $(LOCAL_PATH)/res \ + $(LOCAL_PATH)/../../../../packages/resources/devicesettings/res \ + frameworks/support/v14/preference/res \ + frameworks/support/v7/appcompat/res \ + frameworks/support/v7/preference/res \ + frameworks/support/v7/recyclerview/res + +LOCAL_AAPT_FLAGS := --auto-add-overlay \ + --extra-packages android.support.v14.preference:android.support.v7.appcompat:android.support.v7.preference:android.support.v7.recyclerview + +ifneq ($(INCREMENTAL_BUILDS),) + LOCAL_PROGUARD_ENABLED := disabled + LOCAL_JACK_ENABLED := incremental +endif + +include frameworks/base/packages/SettingsLib/common.mk + +include $(BUILD_PACKAGE) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/cmactions/AndroidManifest.xml b/cmactions/AndroidManifest.xml new file mode 100644 index 0000000..2452838 --- /dev/null +++ b/cmactions/AndroidManifest.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmactions/proguard.flags b/cmactions/proguard.flags new file mode 100644 index 0000000..32daf9b --- /dev/null +++ b/cmactions/proguard.flags @@ -0,0 +1,9 @@ +-keep class org.cyanogenmod.CMActions.* { + *; +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keep class ** extends android.support.v14.preference.PreferenceFragment diff --git a/cmactions/res/drawable/ic_settings_gestures.xml b/cmactions/res/drawable/ic_settings_gestures.xml new file mode 100644 index 0000000..95cdede --- /dev/null +++ b/cmactions/res/drawable/ic_settings_gestures.xml @@ -0,0 +1,32 @@ + + + + + + diff --git a/cmactions/res/values/styles.xml b/cmactions/res/values/styles.xml new file mode 100644 index 0000000..c497d8e --- /dev/null +++ b/cmactions/res/values/styles.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/cmactions/res/xml/doze_panel.xml b/cmactions/res/xml/doze_panel.xml new file mode 100644 index 0000000..c260b94 --- /dev/null +++ b/cmactions/res/xml/doze_panel.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + diff --git a/cmactions/res/xml/gesture_panel.xml b/cmactions/res/xml/gesture_panel.xml new file mode 100644 index 0000000..c34cfb7 --- /dev/null +++ b/cmactions/res/xml/gesture_panel.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmactions/src/com/cyanogenmod/settings/device/BootCompletedReceiver.java b/cmactions/src/com/cyanogenmod/settings/device/BootCompletedReceiver.java new file mode 100644 index 0000000..5099111 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/BootCompletedReceiver.java @@ -0,0 +1,66 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.util.Log; + +import com.cyanogenmod.settings.device.ServiceWrapper.LocalBinder; + +import org.cyanogenmod.internal.util.FileUtils; + +public class BootCompletedReceiver extends BroadcastReceiver { + static final String TAG = "CMActions"; + private ServiceWrapper mServiceWrapper; + + @Override + public void onReceive(final Context context, Intent intent) { + Log.i(TAG, "Booting"); + + // Restore nodes to saved preference values + for (String pref : Constants.sButtonPrefKeys) { + String value = Constants.isPreferenceEnabled(context, pref) ? "1" : "0"; + String node = Constants.sBooleanNodePreferenceMap.get(pref); + + if (!FileUtils.writeLine(node, value)) { + Log.w(TAG, "Write to node " + node + + " failed while restoring saved preference values"); + } + } + + context.startService(new Intent(context, ServiceWrapper.class)); + } + + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + LocalBinder binder = (LocalBinder) service; + mServiceWrapper = binder.getService(); + mServiceWrapper.start(); + } + + @Override + public void onServiceDisconnected(ComponentName className) { + mServiceWrapper = null; + } + }; +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/CMActionsService.java b/cmactions/src/com/cyanogenmod/settings/device/CMActionsService.java new file mode 100644 index 0000000..0311cff --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/CMActionsService.java @@ -0,0 +1,109 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import android.app.IntentService; +import android.content.Context; +import android.content.Intent; +import android.os.PowerManager; +import android.provider.Settings; +import android.util.Log; + +import java.util.List; +import java.util.LinkedList; + +public class CMActionsService extends IntentService implements ScreenStateNotifier, + UpdatedStateNotifier { + private static final String TAG = "CMActions"; + + private final Context mContext; + + private final DozePulseAction mDozePulseAction; + private final PowerManager mPowerManager; + private final PowerManager.WakeLock mWakeLock; + private final ScreenReceiver mScreenReceiver; + private final SensorHelper mSensorHelper; + + private final List mScreenStateNotifiers = new LinkedList(); + private final List mUpdatedStateNotifiers = + new LinkedList(); + + public CMActionsService(Context context) { + super("CMActionService"); + mContext = context; + + Log.d(TAG, "Starting"); + + CMActionsSettings cmActionsSettings = new CMActionsSettings(context, this); + mSensorHelper = new SensorHelper(context); + mScreenReceiver = new ScreenReceiver(context, this); + + mDozePulseAction = new DozePulseAction(context); + mScreenStateNotifiers.add(mDozePulseAction); + + // Actionable sensors get screen on/off notifications + mScreenStateNotifiers.add(new GlanceSensor(cmActionsSettings, mSensorHelper, mDozePulseAction)); + mScreenStateNotifiers.add(new ProximitySensor(cmActionsSettings, mSensorHelper, mDozePulseAction)); + mScreenStateNotifiers.add(new StowSensor(cmActionsSettings, mSensorHelper, mDozePulseAction)); + + // Other actions that are always enabled + mUpdatedStateNotifiers.add(new CameraActivationSensor(cmActionsSettings, mSensorHelper)); + mUpdatedStateNotifiers.add(new ChopChopSensor(cmActionsSettings, mSensorHelper)); + mUpdatedStateNotifiers.add(new ProximitySilencer(cmActionsSettings, context, mSensorHelper)); + mUpdatedStateNotifiers.add(new FlipToMute(cmActionsSettings, context, mSensorHelper)); + mUpdatedStateNotifiers.add(new LiftToSilence(cmActionsSettings, context, mSensorHelper)); + + mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CMActionsWakeLock"); + updateState(); + } + + @Override + protected void onHandleIntent(Intent intent) { + } + + @Override + public void screenTurnedOn() { + if (!mWakeLock.isHeld()) { + mWakeLock.acquire(); + } + for (ScreenStateNotifier screenStateNotifier : mScreenStateNotifiers) { + screenStateNotifier.screenTurnedOn(); + } + } + + @Override + public void screenTurnedOff() { + if (mWakeLock.isHeld()) { + mWakeLock.release(); + } + for (ScreenStateNotifier screenStateNotifier : mScreenStateNotifiers) { + screenStateNotifier.screenTurnedOff(); + } + } + + public void updateState() { + if (mPowerManager.isInteractive()) { + screenTurnedOn(); + } else { + screenTurnedOff(); + } + for (UpdatedStateNotifier notifier : mUpdatedStateNotifiers) { + notifier.updateState(); + } + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/CMActionsSettings.java b/cmactions/src/com/cyanogenmod/settings/device/CMActionsSettings.java new file mode 100644 index 0000000..d458822 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/CMActionsSettings.java @@ -0,0 +1,140 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.provider.Settings; + +import android.util.Log; + +public class CMActionsSettings { + private static final String TAG = "CMActions"; + + private static final String GESTURE_CAMERA_ACTION_KEY = "gesture_camera_action"; + private static final String GESTURE_CHOP_CHOP_KEY = "gesture_chop_chop"; + private static final String GESTURE_PICK_UP_KEY = "gesture_pick_up"; + private static final String GESTURE_IR_WAKEUP_KEY = "gesture_hand_wave"; + private static final String GESTURE_IR_SILENCER_KEY = "gesture_ir_silencer"; + private static final String GESTURE_FLIP_TO_MUTE_KEY = "gesture_flip_to_mute"; + private static final String GESTURE_LIFT_TO_SILENCE_KEY = "gesture_lift_to_silence"; + + private final Context mContext; + private final UpdatedStateNotifier mUpdatedStateNotifier; + + private boolean mCameraGestureEnabled; + private boolean mChopChopEnabled; + private boolean mPickUpGestureEnabled; + private boolean mIrWakeUpEnabled; + private boolean mIrSilencerEnabled; + private boolean mFlipToMuteEnabled; + private boolean mLiftToSilenceEnabled; + + public CMActionsSettings(Context context, UpdatedStateNotifier updatedStateNotifier) { + SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); + loadPreferences(sharedPrefs); + sharedPrefs.registerOnSharedPreferenceChangeListener(mPrefListener); + mContext = context; + mUpdatedStateNotifier = updatedStateNotifier; + } + + public boolean isCameraGestureEnabled() { + return mCameraGestureEnabled; + } + + public boolean isChopChopGestureEnabled() { + return mChopChopEnabled; + } + + public static boolean isDozeEnabled(ContentResolver contentResolver) { + return (Settings.Secure.getInt(contentResolver, Settings.Secure.DOZE_ENABLED, 1) != 0); + } + + public boolean isDozeEnabled() { + return isDozeEnabled(mContext.getContentResolver()); + } + + public boolean isIrWakeupEnabled() { + return isDozeEnabled() && mIrWakeUpEnabled; + } + + public boolean isPickUpEnabled() { + return isDozeEnabled() && mPickUpGestureEnabled; + } + + public boolean isIrSilencerEnabled() { + return mIrSilencerEnabled; + } + + public boolean isFlipToMuteEnabled() { + return mFlipToMuteEnabled; + } + + public boolean isLiftToSilenceEnabled() { + return mLiftToSilenceEnabled; + } + + public void cameraAction() { + new CameraActivationAction(mContext).action(); + } + + public void chopChopAction() { + new TorchAction(mContext).action(); + } + + private void loadPreferences(SharedPreferences sharedPreferences) { + mCameraGestureEnabled = sharedPreferences.getBoolean(GESTURE_CAMERA_ACTION_KEY, true); + mChopChopEnabled = sharedPreferences.getBoolean(GESTURE_CHOP_CHOP_KEY, true); + mIrWakeUpEnabled = sharedPreferences.getBoolean(GESTURE_IR_WAKEUP_KEY, true); + mPickUpGestureEnabled = sharedPreferences.getBoolean(GESTURE_PICK_UP_KEY, true); + mIrSilencerEnabled = sharedPreferences.getBoolean(GESTURE_IR_SILENCER_KEY, false); + mFlipToMuteEnabled = sharedPreferences.getBoolean(GESTURE_FLIP_TO_MUTE_KEY, false); + mLiftToSilenceEnabled = sharedPreferences.getBoolean(GESTURE_LIFT_TO_SILENCE_KEY, false); + } + + private SharedPreferences.OnSharedPreferenceChangeListener mPrefListener = + new SharedPreferences.OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + boolean updated = true; + + if (GESTURE_CAMERA_ACTION_KEY.equals(key)) { + mCameraGestureEnabled = sharedPreferences.getBoolean(GESTURE_CAMERA_ACTION_KEY, true); + } else if (GESTURE_CHOP_CHOP_KEY.equals(key)) { + mChopChopEnabled = sharedPreferences.getBoolean(GESTURE_CHOP_CHOP_KEY, true); + } else if (GESTURE_IR_WAKEUP_KEY.equals(key)) { + mIrWakeUpEnabled = sharedPreferences.getBoolean(GESTURE_IR_WAKEUP_KEY, true); + } else if (GESTURE_PICK_UP_KEY.equals(key)) { + mPickUpGestureEnabled = sharedPreferences.getBoolean(GESTURE_PICK_UP_KEY, true); + } else if (GESTURE_IR_SILENCER_KEY.equals(key)) { + mIrSilencerEnabled = sharedPreferences.getBoolean(GESTURE_IR_SILENCER_KEY, false); + } else if (GESTURE_FLIP_TO_MUTE_KEY.equals(key)) { + mFlipToMuteEnabled = sharedPreferences.getBoolean(GESTURE_FLIP_TO_MUTE_KEY, false); + } else if (GESTURE_LIFT_TO_SILENCE_KEY.equals(key)) { + mLiftToSilenceEnabled = sharedPreferences.getBoolean(GESTURE_LIFT_TO_SILENCE_KEY, false); + } else { + updated = false; + } + + if (updated) { + mUpdatedStateNotifier.updateState(); + } + } + }; +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/CameraActivationAction.java b/cmactions/src/com/cyanogenmod/settings/device/CameraActivationAction.java new file mode 100644 index 0000000..45992e9 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/CameraActivationAction.java @@ -0,0 +1,132 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import java.util.List; + +import android.app.KeyguardManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; +import android.os.Vibrator; +import android.provider.MediaStore; +import android.util.Log; + +public class CameraActivationAction implements SensorAction { + private static final String TAG = "CMActions"; + + private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500; + + private final Context mContext; + private final KeyguardManager mKeyguardManager; + private final PackageManager mPackageManager; + private final PowerManager mPowerManager; + + public CameraActivationAction(Context context) { + mContext = context; + mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); + mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + mPackageManager = context.getPackageManager(); + } + + @Override + public void action() { + vibrate(); + turnScreenOn(); + if (mKeyguardManager.inKeyguardRestrictedInputMode()) { + launchSecureCamera(); + } else { + launchCamera(); + } + } + + private void vibrate() { + Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); + v.vibrate(500); + } + + private void turnScreenOn() { + PowerManager.WakeLock wl = mPowerManager.newWakeLock( + PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG); + wl.acquire(TURN_SCREEN_ON_WAKE_LOCK_MS); + } + + private void launchCamera() { + Intent intent = createIntent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + if (getBestActivityInfo(intent) != null) { + // Only launch if we can succeed, but let the user pick the action + mContext.startActivity(intent); + } + } + + private void launchSecureCamera() { + // Keyguard won't allow a picker, try to pick the secure intent in the package + // that would be the one used for a default action of launching the camera + Intent normalIntent = createIntent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + Intent secureIntent = createIntent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); + ActivityInfo normalActivity = getBestActivityInfo(normalIntent); + ActivityInfo secureActivity = getBestActivityInfo(secureIntent, normalActivity); + if (secureActivity != null) { + secureIntent.setComponent(componentName(secureActivity)); + mContext.startActivity(secureIntent); + } + } + + private Intent createIntent(String intentName) { + Intent intent = new Intent(intentName); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_FROM_BACKGROUND); + return intent; + } + + private ActivityInfo getBestActivityInfo(Intent intent) { + ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0); + if (resolveInfo != null) { + return resolveInfo.activityInfo; + } else { + // If the resolving failed, just find our own best match + return getBestActivityInfo(intent, null); + } + } + + private ActivityInfo getBestActivityInfo(Intent intent, ActivityInfo match) { + List activities = mPackageManager.queryIntentActivities(intent, 0); + ActivityInfo best = null; + if (activities.size() > 0) { + best = activities.get(0).activityInfo; + if (match != null) { + String packageName = match.applicationInfo.packageName; + for (int i = activities.size()-1; i >= 0; i--) { + ActivityInfo activityInfo = activities.get(i).activityInfo; + if (packageName.equals(activityInfo.applicationInfo.packageName)) { + best = activityInfo; + } + } + } + } + return best; + } + + private ComponentName componentName(ActivityInfo activity) { + return new ComponentName(activity.applicationInfo.packageName, activity.name); + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/CameraActivationSensor.java b/cmactions/src/com/cyanogenmod/settings/device/CameraActivationSensor.java new file mode 100644 index 0000000..0128ec4 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/CameraActivationSensor.java @@ -0,0 +1,66 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import java.util.List; + +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.util.Log; + +public class CameraActivationSensor implements SensorEventListener, UpdatedStateNotifier { + private static final String TAG = "CMActions-CameraSensor"; + + private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500; + + private final CMActionsSettings mCMActionsSettings; + private final SensorHelper mSensorHelper; + + private final Sensor mSensor; + + private boolean mIsEnabled; + + public CameraActivationSensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper) { + mCMActionsSettings = cmActionsSettings; + mSensorHelper = sensorHelper; + mSensor = sensorHelper.getCameraActivationSensor(); + mSensorHelper.registerListener(mSensor, this); + } + + @Override + public synchronized void updateState() { + if (mCMActionsSettings.isCameraGestureEnabled() && !mIsEnabled) { + Log.d(TAG, "Enabling"); + mIsEnabled = true; + } else if (! mCMActionsSettings.isCameraGestureEnabled() && mIsEnabled) { + Log.d(TAG, "Disabling"); + mIsEnabled = false; + } + } + + @Override + public void onSensorChanged(SensorEvent event) { + Log.d(TAG, "activate camera"); + if (mIsEnabled) mCMActionsSettings.cameraAction(); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/ChopChopSensor.java b/cmactions/src/com/cyanogenmod/settings/device/ChopChopSensor.java new file mode 100644 index 0000000..ac9ace3 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/ChopChopSensor.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015-2016 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. + */ + +package com.cyanogenmod.settings.device; + +import java.util.List; + +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.util.Log; + +public class ChopChopSensor implements SensorEventListener, UpdatedStateNotifier { + private static final String TAG = "CMActions-ChopChopSensor"; + + private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500; + + private final CMActionsSettings mCMActionsSettings; + private final SensorHelper mSensorHelper; + private final Sensor mSensor; + private final Sensor mProx; + + private boolean mIsEnabled; + private boolean mProxIsCovered; + + public ChopChopSensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper) { + mCMActionsSettings = cmActionsSettings; + mSensorHelper = sensorHelper; + mSensor = sensorHelper.getChopChopSensor(); + mProx = sensorHelper.getProximitySensor(); + } + + @Override + public synchronized void updateState() { + if (mCMActionsSettings.isChopChopGestureEnabled() && !mIsEnabled) { + Log.d(TAG, "Enabling"); + mSensorHelper.registerListener(mSensor, this); + mSensorHelper.registerListener(mProx, mProxListener); + mIsEnabled = true; + } else if (! mCMActionsSettings.isChopChopGestureEnabled() && mIsEnabled) { + Log.d(TAG, "Disabling"); + mSensorHelper.unregisterListener(this); + mSensorHelper.unregisterListener(mProxListener); + mIsEnabled = false; + } + } + + @Override + public void onSensorChanged(SensorEvent event) { + Log.d(TAG, "chop chop triggered"); + if (mProxIsCovered) { + Log.d(TAG, "proximity sensor covered, ignoring chop-chop"); + return; + } + mCMActionsSettings.chopChopAction(); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + + private SensorEventListener mProxListener = new SensorEventListener() { + @Override + public synchronized void onSensorChanged(SensorEvent event) { + mProxIsCovered = event.values[0] < mProx.getMaximumRange(); + } + + @Override + public void onAccuracyChanged(Sensor mSensor, int accuracy) { + } + }; + +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/Constants.java b/cmactions/src/com/cyanogenmod/settings/device/Constants.java new file mode 100644 index 0000000..85587a2 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/Constants.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.cyanogenmod.settings.device; + +import java.util.HashMap; +import java.util.Map; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +public class Constants { + + // Swap keys + public static final String FP_HOME_KEY = "fp_home"; + + // Swap nodes + public static final String FP_HOME_NODE = "/sys/homebutton/enable"; + + // Holds -> mapping + public static final Map sBooleanNodePreferenceMap = new HashMap<>(); + + // Holds -> mapping + public static final Map sNodeDefaultMap = new HashMap<>(); + + public static final String[] sButtonPrefKeys = { + FP_HOME_KEY, + }; + + static { + sBooleanNodePreferenceMap.put(FP_HOME_KEY, FP_HOME_NODE); + sNodeDefaultMap.put(FP_HOME_KEY, false); + } + + public static boolean isPreferenceEnabled(Context context, String key) { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + return preferences.getBoolean(key, (Boolean) sNodeDefaultMap.get(key)); + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/DozePreferenceActivity.java b/cmactions/src/com/cyanogenmod/settings/device/DozePreferenceActivity.java new file mode 100644 index 0000000..118c658 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/DozePreferenceActivity.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017 The LineageOS 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. + */ + +package com.cyanogenmod.settings.device; + +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.provider.Settings; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceCategory; +import android.support.v14.preference.PreferenceFragment; +import android.support.v14.preference.SwitchPreference; +import android.view.MenuItem; + +public class DozePreferenceActivity extends PreferenceActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getActionBar().setDisplayHomeAsUpEnabled(true); + getFragmentManager().beginTransaction() + .replace(android.R.id.content, new DozePreferenceFragment()).commit(); + } + + public class DozePreferenceFragment extends PreferenceFragment { + private static final String KEY_AMBIENT_DISPLAY_ENABLE = "doze_enabled"; + + private SwitchPreference mAmbientDisplayPreference; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.doze_panel); + boolean dozeEnabled = CMActionsSettings.isDozeEnabled(getActivity().getContentResolver()); + mAmbientDisplayPreference = (SwitchPreference) findPreference(KEY_AMBIENT_DISPLAY_ENABLE); + // Read from DOZE_ENABLED secure setting + mAmbientDisplayPreference.setChecked(dozeEnabled); + mAmbientDisplayPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean enable = (boolean) newValue; + return enableDoze(enable); + } + }); + } + + private boolean enableDoze(boolean enable) { + return Settings.Secure.putInt(getContext().getContentResolver(), + Settings.Secure.DOZE_ENABLED, enable ? 1 : 0); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/DozePulseAction.java b/cmactions/src/com/cyanogenmod/settings/device/DozePulseAction.java new file mode 100644 index 0000000..75ef9c3 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/DozePulseAction.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +public class DozePulseAction implements SensorAction, ScreenStateNotifier { + private static final String TAG = "CMActions"; + + private static final int DELAY_BETWEEN_DOZES_IN_MS = 1500; + + private final Context mContext; + + private long mLastDoze; + + public DozePulseAction(Context context) { + mContext = context; + } + + @Override + public void screenTurnedOn() { + } + + @Override + public void screenTurnedOff() { + mLastDoze = System.currentTimeMillis(); + } + + public void action() { + if (mayDoze()) { + Log.d(TAG, "Sending doze.pulse intent"); + mContext.sendBroadcast(new Intent("com.android.systemui.doze.pulse")); + } + } + + public synchronized boolean mayDoze() { + long now = System.currentTimeMillis(); + if (now - mLastDoze > DELAY_BETWEEN_DOZES_IN_MS) { + Log.d(TAG, "Allowing doze"); + mLastDoze = now; + return true; + } else { + Log.d(TAG, "Denying doze"); + return false; + } + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/FlipToMute.java b/cmactions/src/com/cyanogenmod/settings/device/FlipToMute.java new file mode 100644 index 0000000..d5d5bf9 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/FlipToMute.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016 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. + */ + +package com.cyanogenmod.settings.device; + +import android.app.NotificationManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.util.Log; + +public class FlipToMute implements UpdatedStateNotifier { + private static final String TAG = "CMActions-FlipToMute"; + + private final NotificationManager mNotificationManager; + private final CMActionsSettings mCMActionsSettings; + private final SensorHelper mSensorHelper; + private final Sensor mFlatDown; + private final Sensor mStow; + + private boolean mIsEnabled; + private boolean mIsFlatDown; + private boolean mIsStowed; + private int mFilter; + private Context mContext; + private Receiver mReceiver; + + public FlipToMute(CMActionsSettings cmActionsSettings, Context context, + SensorHelper sensorHelper) { + mCMActionsSettings = cmActionsSettings; + mContext = context; + mSensorHelper = sensorHelper; + mFlatDown = sensorHelper.getFlatDownSensor(); + mStow = sensorHelper.getStowSensor(); + mNotificationManager = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + mFilter = mNotificationManager.getCurrentInterruptionFilter(); + mReceiver = new Receiver(); + } + + @Override + public void updateState() { + if (mCMActionsSettings.isFlipToMuteEnabled() && !mIsEnabled) { + Log.d(TAG, "Enabling"); + mSensorHelper.registerListener(mFlatDown, mFlatDownListener); + mSensorHelper.registerListener(mStow, mStowListener); + mContext.registerReceiver(mReceiver, + new IntentFilter(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED)); + mIsEnabled = true; + } else if (!mCMActionsSettings.isFlipToMuteEnabled() && mIsEnabled) { + Log.d(TAG, "Disabling"); + mSensorHelper.unregisterListener(mFlatDownListener); + mSensorHelper.unregisterListener(mStowListener); + mContext.unregisterReceiver(mReceiver); + mIsEnabled = false; + } + } + + private SensorEventListener mFlatDownListener = new SensorEventListener() { + @Override + public synchronized void onSensorChanged(SensorEvent event) { + mIsFlatDown = (event.values[0] != 0); + sensorChange(); + } + + @Override + public void onAccuracyChanged(Sensor mSensor, int accuracy) { + } + }; + + private SensorEventListener mStowListener = new SensorEventListener() { + @Override + public synchronized void onSensorChanged(SensorEvent event) { + mIsStowed = (event.values[0] != 0); + sensorChange(); + } + + @Override + public void onAccuracyChanged(Sensor mSensor, int accuracy) { + } + }; + + private void sensorChange() { + + Log.d(TAG, "event: " + mIsFlatDown + " mIsStowed=" + mIsStowed); + + if (mIsFlatDown && mIsStowed) { + mNotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY); + Log.d(TAG, "Interrupt filter: Allow priority"); + } else if (!mIsFlatDown) { + mNotificationManager.setInterruptionFilter(mFilter); + Log.d(TAG, "Interrupt filter: Restore"); + } + } + + public class Receiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if (!mIsFlatDown && !mIsStowed) { + mFilter = mNotificationManager.getCurrentInterruptionFilter(); + Log.d(TAG, "Interrupt filter: Backup"); + } + } + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/GlanceSensor.java b/cmactions/src/com/cyanogenmod/settings/device/GlanceSensor.java new file mode 100644 index 0000000..4d83c81 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/GlanceSensor.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017 The LineageOS 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. + */ + +package com.cyanogenmod.settings.device; + +import android.hardware.Sensor; +import android.hardware.TriggerEvent; +import android.hardware.TriggerEventListener; +import android.util.Log; + +public class GlanceSensor implements ScreenStateNotifier { + private static final String TAG = "CMActions-GlanceSensor"; + + private final CMActionsSettings mCMActionsSettings; + private final SensorHelper mSensorHelper; + private final SensorAction mSensorAction; + private final Sensor mSensor; + + private boolean mEnabled; + + public GlanceSensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper, + SensorAction action) { + mCMActionsSettings = cmActionsSettings; + mSensorHelper = sensorHelper; + mSensorAction = action; + + mSensor = sensorHelper.getGlanceSensor(); + } + + @Override + public void screenTurnedOn() { + if (mEnabled) { + Log.d(TAG, "Disabling"); + mSensorHelper.cancelTriggerSensor(mSensor, mGlanceListener); + mEnabled = false; + } + } + + @Override + public void screenTurnedOff() { + if (mCMActionsSettings.isPickUpEnabled() && !mEnabled) { + Log.d(TAG, "Enabling"); + mSensorHelper.requestTriggerSensor(mSensor, mGlanceListener); + mEnabled = true; + } + } + + private TriggerEventListener mGlanceListener = new TriggerEventListener() { + @Override + public void onTrigger(TriggerEvent event) { + Log.d(TAG, "triggered"); + mSensorAction.action(); + mSensorHelper.requestTriggerSensor(mSensor, mGlanceListener); + } + }; +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/LiftToSilence.java b/cmactions/src/com/cyanogenmod/settings/device/LiftToSilence.java new file mode 100644 index 0000000..a5286c3 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/LiftToSilence.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016 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. + */ + +package com.cyanogenmod.settings.device; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.telephony.PhoneStateListener; +import android.telecom.TelecomManager; +import android.telephony.TelephonyManager; +import android.util.Log; + +public class LiftToSilence extends PhoneStateListener implements SensorEventListener, UpdatedStateNotifier { + private static final String TAG = "CMActions-LiftToSilence"; + + private final CMActionsSettings mCMActionsSettings; + private final SensorHelper mSensorHelper; + private final Sensor mFlatUpSensor; + private final Sensor mStowSensor; + + private final TelecomManager mTelecomManager; + private final TelephonyManager mTelephonyManager; + + private boolean mIsRinging; + private boolean mIsStowed; + private boolean mLastFlatUp; + + public LiftToSilence(CMActionsSettings cmActionsSettings, Context context, + SensorHelper sensorHelper) { + mCMActionsSettings = cmActionsSettings; + mSensorHelper = sensorHelper; + mFlatUpSensor = sensorHelper.getFlatUpSensor(); + mStowSensor = sensorHelper.getStowSensor(); + mTelecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); + mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + } + + @Override + public void updateState() { + if (mCMActionsSettings.isLiftToSilenceEnabled()) { + mTelephonyManager.listen(this, LISTEN_CALL_STATE); + } else { + mTelephonyManager.listen(this, 0); + } + } + + @Override + public synchronized void onCallStateChanged(int state, String incomingNumber) { + if (state == TelephonyManager.CALL_STATE_RINGING && !mIsRinging) { + Log.d(TAG, "Ringing started"); + mSensorHelper.registerListener(mFlatUpSensor, this); + mSensorHelper.registerListener(mStowSensor, mStowListener); + mIsRinging = true; + } else if (state != TelephonyManager.CALL_STATE_RINGING && mIsRinging) { + Log.d(TAG, "Ringing stopped"); + mSensorHelper.unregisterListener(this); + mSensorHelper.unregisterListener(mStowListener); + mIsRinging = false; + } + } + + + @Override + public synchronized void onSensorChanged(SensorEvent event) { + boolean thisFlatUp = (event.values[0] != 0); + + Log.d(TAG, "event: " + thisFlatUp + " mLastFlatUp=" + mLastFlatUp + " mIsStowed=" + + mIsStowed); + + if (mLastFlatUp && !thisFlatUp && !mIsStowed) { + mTelecomManager.silenceRinger(); + } + mLastFlatUp = thisFlatUp; + } + + @Override + public void onAccuracyChanged(Sensor mSensor, int accuracy) { + } + + private SensorEventListener mStowListener = new SensorEventListener() { + @Override + public synchronized void onSensorChanged(SensorEvent event) { + mIsStowed = (event.values[0] != 0); + } + + @Override + public void onAccuracyChanged(Sensor mSensor, int accuracy) { + } + }; +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/ProximitySensor.java b/cmactions/src/com/cyanogenmod/settings/device/ProximitySensor.java new file mode 100644 index 0000000..7c4af6c --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/ProximitySensor.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.util.Log; + +public class ProximitySensor implements ScreenStateNotifier, SensorEventListener { + private static final String TAG = "CMActions-ProximitySensor"; + + private final CMActionsSettings mCMActionsSettings; + private final SensorHelper mSensorHelper; + private final SensorAction mSensorAction; + private final Sensor mSensor; + + private boolean mEnabled; + + private boolean mSawNear = false; + + public ProximitySensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper, + SensorAction action) { + mCMActionsSettings = cmActionsSettings; + mSensorHelper = sensorHelper; + mSensorAction = action; + + mSensor = sensorHelper.getProximitySensor(); + } + + @Override + public void screenTurnedOn() { + if (mEnabled) { + Log.d(TAG, "Disabling"); + mSensorHelper.unregisterListener(this); + mEnabled = false; + } + } + + @Override + public void screenTurnedOff() { + if (mCMActionsSettings.isIrWakeupEnabled() && !mEnabled) { + Log.d(TAG, "Enabling"); + mSensorHelper.registerListener(mSensor, this); + mEnabled = true; + } + } + + @Override + public void onSensorChanged(SensorEvent event) { + boolean isNear = event.values[0] < mSensor.getMaximumRange(); + if (mSawNear && !isNear) { + Log.d(TAG, "wave triggered"); + mSensorAction.action(); + } + mSawNear = isNear; + } + + @Override + public void onAccuracyChanged(Sensor mSensor, int accuracy) { + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/ProximitySilencer.java b/cmactions/src/com/cyanogenmod/settings/device/ProximitySilencer.java new file mode 100644 index 0000000..3975776 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/ProximitySilencer.java @@ -0,0 +1,110 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.telephony.PhoneStateListener; +import android.telecom.TelecomManager; +import android.telephony.TelephonyManager; +import android.util.Log; + +import static android.telephony.TelephonyManager.*; + +public class ProximitySilencer extends PhoneStateListener implements SensorEventListener, UpdatedStateNotifier { + private static final String TAG = "CMActions-ProximitySilencer"; + + private static final int SILENCE_DELAY_MS = 500; + + private final TelecomManager mTelecomManager; + private final TelephonyManager mTelephonyManager; + private final CMActionsSettings mCMActionsSettings; + private final SensorHelper mSensorHelper; + private final Sensor mSensor; + private boolean mIsRinging; + private long mRingStartedMs; + private boolean mCoveredRinging; + + public ProximitySilencer(CMActionsSettings cmActionsSettings, Context context, + SensorHelper sensorHelper) { + mTelecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); + mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + + mCMActionsSettings = cmActionsSettings; + mSensorHelper = sensorHelper; + mSensor = sensorHelper.getProximitySensor(); + mCoveredRinging = false; + mIsRinging = false; + } + + @Override + public void updateState() { + if (mCMActionsSettings.isIrSilencerEnabled()) { + mTelephonyManager.listen(this, LISTEN_CALL_STATE); + } else { + mTelephonyManager.listen(this, 0); + } + } + + @Override + public synchronized void onSensorChanged(SensorEvent event) { + boolean isNear = event.values[0] < mSensor.getMaximumRange(); + long now = System.currentTimeMillis(); + + if (isNear){ + if (mIsRinging && (now - mRingStartedMs >= SILENCE_DELAY_MS)){ + mCoveredRinging = true; + } else { + mCoveredRinging = false; + } + return; + } + + if (!isNear && mIsRinging) { + Log.d(TAG, "event: [" + event.values.length + "]: " + event.values[0] + ", " + + event.values[1] + ", " + event.values[2] + " covered " + Boolean.toString(mCoveredRinging)); + if (mCoveredRinging) { + Log.d(TAG, "Silencing ringer"); + mTelecomManager.silenceRinger(); + } else { + Log.d(TAG, "Ignoring silence gesture: " + now + " is too close to " + + mRingStartedMs + ", delay=" + SILENCE_DELAY_MS + " or covered " + Boolean.toString(mCoveredRinging)); + } + mCoveredRinging = false; + } + } + + @Override + public synchronized void onCallStateChanged(int state, String incomingNumber) { + if (state == CALL_STATE_RINGING && !mIsRinging) { + Log.d(TAG, "Ringing started"); + mSensorHelper.registerListener(mSensor, this); + mIsRinging = true; + mRingStartedMs = System.currentTimeMillis(); + } else if (state != CALL_STATE_RINGING && mIsRinging) { + Log.d(TAG, "Ringing stopped"); + mSensorHelper.unregisterListener(this); + mIsRinging = false; + } + } + + @Override + public void onAccuracyChanged(Sensor mSensor, int accuracy) { + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/ScreenReceiver.java b/cmactions/src/com/cyanogenmod/settings/device/ScreenReceiver.java new file mode 100644 index 0000000..09fe768 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/ScreenReceiver.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import java.util.List; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +public class ScreenReceiver extends BroadcastReceiver { + private final ScreenStateNotifier mNotifier; + + public ScreenReceiver(Context context, ScreenStateNotifier notifier) { + mNotifier = notifier; + + IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_SCREEN_OFF); + context.registerReceiver(this, filter); + } + + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { + mNotifier.screenTurnedOff(); + } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { + mNotifier.screenTurnedOn(); + } + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/ScreenStateNotifier.java b/cmactions/src/com/cyanogenmod/settings/device/ScreenStateNotifier.java new file mode 100644 index 0000000..1ffd844 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/ScreenStateNotifier.java @@ -0,0 +1,22 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +interface ScreenStateNotifier { + public void screenTurnedOn(); + public void screenTurnedOff(); +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/SensorAction.java b/cmactions/src/com/cyanogenmod/settings/device/SensorAction.java new file mode 100644 index 0000000..ed590b2 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/SensorAction.java @@ -0,0 +1,21 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +interface SensorAction { + public void action(); +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/SensorHelper.java b/cmactions/src/com/cyanogenmod/settings/device/SensorHelper.java new file mode 100644 index 0000000..c27fa1d --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/SensorHelper.java @@ -0,0 +1,116 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import java.util.List; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.hardware.TriggerEventListener; +import android.util.Log; + +public class SensorHelper { + private static final String TAG = "CMActions"; + + private static final int SENSOR_TYPE_MMI_CAMERA_ACTIVATION = 65540; + private static final int SENSOR_TYPE_MMI_CHOP_CHOP = 65546; + private static final int SENSOR_TYPE_MMI_FLAT_UP = 65537; + private static final int SENSOR_TYPE_MMI_FLAT_DOWN = 65538; + private static final int SENSOR_TYPE_MMI_STOW = 65539; + + private static final int BATCH_LATENCY_IN_MS = 100; + + private final Context mContext; + private final SensorManager mSensorManager; + + public SensorHelper(Context context) { + mContext = context; + mSensorManager = (SensorManager) mContext .getSystemService(Context.SENSOR_SERVICE); + dumpSensorsList(); + } + + private void dumpSensorsList() { + try { + FileOutputStream out = mContext.openFileOutput("sensors.txt", Context.MODE_PRIVATE); + OutputStreamWriter writer = new OutputStreamWriter(out); + + List sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL); + for (Sensor sensor : sensorList) { + writer.write("sensor " + sensor.getType() + " = " + sensor.getName() + + " max batch: " + sensor.getFifoMaxEventCount() + " isWakeUp: " + sensor.isWakeUpSensor() + "\n"); + } + writer.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public Sensor getCameraActivationSensor() { + return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_CAMERA_ACTIVATION, true); + } + + public Sensor getChopChopSensor() { + return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_CHOP_CHOP, true); + } + + public Sensor getFlatUpSensor() { + return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_FLAT_UP, true); + } + + public Sensor getFlatDownSensor() { + return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_FLAT_DOWN, true); + } + + public Sensor getGlanceSensor() { + return mSensorManager.getDefaultSensor(Sensor.TYPE_GLANCE_GESTURE, true); + } + + public Sensor getProximitySensor() { + return mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY, true); + } + + public Sensor getStowSensor() { + return mSensorManager.getDefaultSensor(SENSOR_TYPE_MMI_STOW, true); + } + + public void registerListener(Sensor sensor, SensorEventListener listener) { + if (!mSensorManager.registerListener(listener, sensor, + SensorManager.SENSOR_DELAY_NORMAL, BATCH_LATENCY_IN_MS * 1000)) { + throw new RuntimeException("Failed to registerListener for sensor " + sensor); + } + } + + public void unregisterListener(SensorEventListener listener) { + mSensorManager.unregisterListener(listener); + } + + /* TriggerSensor */ + public void requestTriggerSensor(Sensor sensor, TriggerEventListener listener) { + if (!mSensorManager.requestTriggerSensor(listener, sensor)) { + throw new RuntimeException("Failed to requestTriggerSensor for sensor " + sensor); + } + } + + public void cancelTriggerSensor(Sensor sensor, TriggerEventListener listener) { + mSensorManager.cancelTriggerSensor(listener, sensor); + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/ServiceWrapper.java b/cmactions/src/com/cyanogenmod/settings/device/ServiceWrapper.java new file mode 100644 index 0000000..0a4b21c --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/ServiceWrapper.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import android.content.Intent; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.util.Log; + +public class ServiceWrapper extends android.app.Service { + static final String TAG = "CMActions-ServiceWrapper"; + + private final IBinder mBinder = new LocalBinder(); + private CMActionsService mCmActionsService; + + public interface ServiceCallback { + void sendResults(int resultCode, Bundle b); + } + + public class LocalBinder extends Binder { + ServiceWrapper getService() { + // Return this instance of the service so clients can call public + // methods + return ServiceWrapper.this; + } + } + + @Override + public void onCreate() { + Log.i(TAG, "onCreate"); + super.onCreate(); + mCmActionsService = new CMActionsService(this); + } + + @Override + public IBinder onBind(Intent intent) { + Log.i(TAG, "onBind"); + return null; + } + + public void setCallback(ServiceCallback callback) { + } + + public void start() { + Log.i(TAG, "start"); + } + + public void stop() { + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/StowSensor.java b/cmactions/src/com/cyanogenmod/settings/device/StowSensor.java new file mode 100644 index 0000000..84f0f08 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/StowSensor.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.util.Log; + +import java.lang.System; + +public class StowSensor implements ScreenStateNotifier, SensorEventListener { + private static final String TAG = "CMActions-StowSensor"; + private static final int IN_POCKET_MIN_TIME = 5000; + + private final CMActionsSettings mCMActionsSettings; + private final SensorHelper mSensorHelper; + private final SensorAction mSensorAction; + private final Sensor mSensor; + + private boolean mEnabled; + private boolean mLastStowed; + private long isStowedTime; + + public StowSensor(CMActionsSettings cmActionsSettings, SensorHelper sensorHelper, + SensorAction action) { + mCMActionsSettings = cmActionsSettings; + mSensorHelper = sensorHelper; + mSensorAction = action; + + mSensor = sensorHelper.getStowSensor(); + } + + @Override + public void screenTurnedOn() { + if (mEnabled) { + Log.d(TAG, "Disabling"); + mSensorHelper.unregisterListener(this); + mEnabled = false; + } + } + + @Override + public void screenTurnedOff() { + if (!mCMActionsSettings.isIrWakeupEnabled() && + mCMActionsSettings.isPickUpEnabled() && !mEnabled) { + Log.d(TAG, "Enabling"); + mSensorHelper.registerListener(mSensor, this); + mEnabled = true; + } + } + + @Override + public void onSensorChanged(SensorEvent event) { + boolean thisStowed = (event.values[0] != 0); + if(thisStowed){ + isStowedTime = System.currentTimeMillis(); + } else if (mLastStowed && !thisStowed) { + long inPocketTime = System.currentTimeMillis() - isStowedTime; + if(inPocketTime >= IN_POCKET_MIN_TIME){ + Log.d(TAG, "Triggered after " + inPocketTime / 1000 + " seconds"); + mSensorAction.action(); + } + } + mLastStowed = thisStowed; + Log.d(TAG, "event: " + thisStowed); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/TorchAction.java b/cmactions/src/com/cyanogenmod/settings/device/TorchAction.java new file mode 100644 index 0000000..f66ae59 --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/TorchAction.java @@ -0,0 +1,81 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +import android.content.Context; +import android.hardware.camera2.CameraManager; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraAccessException; +import android.os.Vibrator; +import android.util.Log; + +public class TorchAction implements SensorAction { + private static final String TAG = "CMActions"; + + private static final int TURN_SCREEN_ON_WAKE_LOCK_MS = 500; + + private CameraManager mCameraManager; + private final Vibrator mVibrator; + private String mRearCameraId; + private static boolean mTorchEnabled; + + public TorchAction(Context mContext) { + mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE); + mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); + try { + for (final String cameraId : mCameraManager.getCameraIdList()) { + CameraCharacteristics characteristics = + mCameraManager.getCameraCharacteristics(cameraId); + int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING); + if (cOrientation == CameraCharacteristics.LENS_FACING_BACK) { + mRearCameraId = cameraId; + break; + } + } + } catch (CameraAccessException e) { + } + } + + @Override + public void action() { + mVibrator.vibrate(250); + if (mRearCameraId != null) { + try { + mCameraManager.setTorchMode(mRearCameraId, !mTorchEnabled); + mTorchEnabled = !mTorchEnabled; + } catch (CameraAccessException e) { + } + } + } + + private class MyTorchCallback extends CameraManager.TorchCallback { + + @Override + public void onTorchModeChanged(String cameraId, boolean enabled) { + if (!cameraId.equals(mRearCameraId)) + return; + mTorchEnabled = enabled; + } + + @Override + public void onTorchModeUnavailable(String cameraId) { + if (!cameraId.equals(mRearCameraId)) + return; + mTorchEnabled = false; + } + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/TouchscreenGesturePreferenceActivity.java b/cmactions/src/com/cyanogenmod/settings/device/TouchscreenGesturePreferenceActivity.java new file mode 100644 index 0000000..41f43af --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/TouchscreenGesturePreferenceActivity.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 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. + */ + +package com.cyanogenmod.settings.device; + +import android.os.Bundle; + +import com.android.settingslib.drawer.SettingsDrawerActivity; + +public class TouchscreenGesturePreferenceActivity extends SettingsDrawerActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getFragmentManager().beginTransaction() + .replace(R.id.content_frame, new TouchscreenGesturePreferenceFragment()).commit(); + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/TouchscreenGesturePreferenceFragment.java b/cmactions/src/com/cyanogenmod/settings/device/TouchscreenGesturePreferenceFragment.java new file mode 100644 index 0000000..cd2628c --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/TouchscreenGesturePreferenceFragment.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2015-2016 The CyanogenMod Project + * Copyright (C) 2017 The LineageOS 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. + */ + +package com.cyanogenmod.settings.device; + +import android.app.AlertDialog; +import android.app.NotificationManager; +import android.os.Bundle; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceCategory; +import android.support.v14.preference.PreferenceFragment; +import android.support.v14.preference.SwitchPreference; +import android.text.TextUtils; + +import java.io.File; + +import org.cyanogenmod.internal.util.FileUtils; +import org.cyanogenmod.internal.util.ScreenType; + +public class TouchscreenGesturePreferenceFragment extends PreferenceFragment { + private SwitchPreference mFlipPref; + private NotificationManager mNotificationManager; + private boolean mFlipClick = false; + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.gesture_panel); + mNotificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE); + mFlipPref = (SwitchPreference) findPreference("gesture_flip_to_mute"); + mFlipPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + public boolean onPreferenceClick(Preference preference) { + if (!mNotificationManager.isNotificationPolicyAccessGranted()) { + mFlipPref.setChecked(false); + new AlertDialog.Builder(getContext()) + .setTitle(getString(R.string.flip_to_mute_title)) + .setMessage(getString(R.string.dnd_access)) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + mFlipClick = true; + startActivity(new Intent( + android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)); + } + }).show(); + } + return true; + } + }); + + //Users may deny DND access after giving it + if (!mNotificationManager.isNotificationPolicyAccessGranted()) { + mFlipPref.setChecked(false); + } + } + + @Override + public void addPreferencesFromResource(int preferencesResId) { + super.addPreferencesFromResource(preferencesResId); + // Initialize node preferences + for (String pref : Constants.sBooleanNodePreferenceMap.keySet()) { + SwitchPreference b = (SwitchPreference) findPreference(pref); + if (b == null) continue; + b.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + public boolean onPreferenceChange(Preference preference, Object newValue) { + String node = Constants.sBooleanNodePreferenceMap.get(preference.getKey()); + if (!TextUtils.isEmpty(node)) { + Boolean value = (Boolean) newValue; + FileUtils.writeLine(node, value ? "1" : "0"); + return true; + } + return false; + } + }); + String node = Constants.sBooleanNodePreferenceMap.get(pref); + if (new File(node).exists()) { + String curNodeValue = FileUtils.readOneLine(node); + b.setChecked(curNodeValue.equals("1")); + } else { + b.setEnabled(false); + } + } + } + + @Override + public void onResume() { + super.onResume(); + + if (mNotificationManager.isNotificationPolicyAccessGranted() && mFlipClick) { + mFlipPref.setChecked(true); + } + } +} diff --git a/cmactions/src/com/cyanogenmod/settings/device/UpdatedStateNotifier.java b/cmactions/src/com/cyanogenmod/settings/device/UpdatedStateNotifier.java new file mode 100644 index 0000000..268b4bd --- /dev/null +++ b/cmactions/src/com/cyanogenmod/settings/device/UpdatedStateNotifier.java @@ -0,0 +1,21 @@ +/* + * 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. + */ + +package com.cyanogenmod.settings.device; + +interface UpdatedStateNotifier { + public void updateState(); +} diff --git a/configs/camera/msm8953_mot_camera.xml b/configs/camera/msm8953_mot_camera.xml new file mode 100644 index 0000000..15461fa --- /dev/null +++ b/configs/camera/msm8953_mot_camera.xml @@ -0,0 +1,135 @@ + + + + + + 1 + mot_imx362 + imx362 + mot_ak7371 + pmic + mot_imx362_chromatix + 1 + BACK + 90 + + 0 + 0x1F + 0x4320 + 0 + + + 4.28 + 1.7 + 0.187 + 65.0 + 51.0 + 0.1 + + + + 2 + mot_ov5695 + ov5695 + mot_ov5695_chromatix + 1 + FRONT + 270 + + 2 + 0x07 + 0x4320 + 0 + + + 2.44 + 2.2 + 1.26 + 72.95 + 57.60 + 0.1 + + + diff --git a/configs/camera/ov16860_chromatix.xml b/configs/camera/ov16860_chromatix.xml new file mode 100644 index 0000000..a2ef38d --- /dev/null +++ b/configs/camera/ov16860_chromatix.xml @@ -0,0 +1,124 @@ + + + + + + + + ov16860_common + ov16860_postproc + ov16860_cpp_snapshot + ov16860_cpp_snapshot + + + ov16860_video_4k + ov16860_cpp_video_4k + ov16860_cpp_liveshot_4k + ov16860_4k_video_3a + + + ov16860_default_ihdr_video + ov16860_cpp_liveshot_ihdr + ov16860_ihdr_video_3a + + + ov16860_ihdr_video_4k + ov16860_cpp_liveshot_4k_ihdr + ov16860_4k_ihdr_video_3a + + + + + ov16860_snapshot + ov16860_snapshot + ov16860_default_video + ov16860_cpp_video + ov16860_cpp_liveshot + ov16860_zsl_preview_3a + ov16860_zsl_video_3a + + + ov16860_hfr_120 + ov16860_hfr_120 + ov16860_hfr_120 + ov16860_cpp_liveshot + ov16860_cpp_hfr_120 + ov16860_hfr_120_3a + ov16860_hfr_120_3a + + + diff --git a/configs/camera/ov5693_chromatix.xml b/configs/camera/ov5693_chromatix.xml new file mode 100644 index 0000000..6fd1f9d --- /dev/null +++ b/configs/camera/ov5693_chromatix.xml @@ -0,0 +1,110 @@ + + + + + + + + ov5693_common + ov5693_postproc + ov5693_cpp_snapshot + ov5693_cpp_snapshot + ov5693_cpp_liveshot + + + + + ov5693_snapshot + ov5693_snapshot + ov5693_default_video + ov5693_snapshot + ov5693_cpp_video + ov5693_snapshot_3a + ov5693_default_video_3a + + + ov5693_hfr_120 + ov5693_hfr_120 + ov5693_hfr_120 + ov5693_hfr_120 + ov5693_cpp_hfr_120 + ov5693_hfr_120_3a + ov5693_hfr_120_3a + + + + diff --git a/configs/com.motorola.cameraone.xml b/configs/com.motorola.cameraone.xml new file mode 100644 index 0000000..01d2732 --- /dev/null +++ b/configs/com.motorola.cameraone.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/configs/libnfc-brcm.conf b/configs/libnfc-brcm.conf new file mode 100644 index 0000000..7c7f4a7 --- /dev/null +++ b/configs/libnfc-brcm.conf @@ -0,0 +1,403 @@ +###################### Start of libnfc-common.conf ####################### + +############################################################################### +# Application options +APPL_TRACE_LEVEL=0xFF +PROTOCOL_TRACE_LEVEL=0xFFFFFFFF + +############################################################################### +# performance measurement +# Change this setting to control how often USERIAL log the performance (throughput) +# data on read/write/poll +# defailt is to log performance dara for every 100 read or write +#REPORT_PERFORMANCE_MEASURE=100 + +############################################################################### +# File used for NFA storage +NFA_STORAGE="/data/nfc" + +############################################################################### +# Snooze Mode Settings +# +# By default snooze mode is enabled. Set SNOOZE_MODE_CFG byte[0] to 0 +# to disable. +# +# If SNOOZE_MODE_CFG is not provided, the default settings are used: +# They are as follows: +# 8 Sleep Mode (0=Disabled 1=UART 8=SPI/I2C) +# 0 Idle Threshold Host +# 0 Idle Threshold HC +# 0 NFC Wake active mode (0=ActiveLow 1=ActiveHigh) +# 1 Host Wake active mode (0=ActiveLow 1=ActiveHigh) +# +#SNOOZE_MODE_CFG={08:00:00:00:01} + +############################################################################### +# Insert a delay in milliseconds after NFC_WAKE and before write to NFCC +#NFC_WAKE_DELAY=20 + +############################################################################### +# Various Delay settings (in ms) used in USERIAL +# POWER_ON_DELAY +# Delay after turning on chip, before writing to transport (default 300) +# PRE_POWER_OFF_DELAY +# Delay after deasserting NFC-Wake before turn off chip (default 0) +# POST_POWER_OFF_DELAY +# Delay after turning off chip, before USERIAL_close returns (default 0) +# +#POWER_ON_DELAY=300 +#PRE_POWER_OFF_DELAY=0 +#POST_POWER_OFF_DELAY=0 + +############################################################################### +# Maximum time (ms) to wait for RESET NTF after setting REG_PU to high +# The default is 1000. +#NFCC_ENABLE_TIMEOUT=0 + +############################################################################### +# LPTD mode configuration +# byte[0] is the length of the remaining bytes in this value +# if set to 0, LPTD params will NOT be sent to NFCC (i.e. disabled). +# byte[1] is the param id it should be set to B9. +# byte[2] is the length of the LPTD parameters +# byte[3] indicates if LPTD is enabled +# if set to 0, LPTD will be disabled (parameters will still be sent). +# byte[4-n] are the LPTD parameters. +# By default, LPTD is enabled and default settings are used. +# See nfc_hal_dm_cfg.c for defaults +#LPTD_CFG={23:B9:21:01:02:FF:FF:04:A0:0F:40:00:80:02:02:10:00:00:00:31:0C:30:00:00:00:00:00:00:00:00:00:00:00:00:00:00} + +############################################################################### +# Startup Configuration (100 bytes maximum) +# +# For the 0xCA parameter, byte[9] (marked by 'AA') is for UICC0, and byte[10] (marked by BB) is +# for UICC1. The values are defined as: +# 0 : UICCx only supports ISO_DEP in low power mode. +# 2 : UICCx only supports Mifare in low power mode. +# 3 : UICCx supports both ISO_DEP and Mifare in low power mode. +# +# AA BB +#NFA_DM_START_UP_CFG={1F:CB:01:01:A5:01:01:CA:14:00:00:00:00:06:E8:03:00:00:00:00:00:00:00:00:00:00:00:00:00:80:01:01} + +############################################################################### +# Startup Vendor Specific Configuration (100 bytes maximum); +# byte[0] TLV total len = 0x5 +# byte[1] NCI_MTS_CMD|NCI_GID_PROP = 0x2f +# byte[2] NCI_MSG_FRAME_LOG = 0x9 +# byte[3] 2 +# byte[4] 0=turn off RF frame logging; 1=turn on +# byte[5] 0=turn off SWP frame logging; 1=turn on +# NFA_DM_START_UP_VSC_CFG={05:2F:09:02:01:01} + +############################################################################### +# Antenna Configuration - This data is used when setting 0xC8 config item +# at startup (before discovery is started). If not used, no value is sent. +# +# The settings for this value are documented here: +# http://wcgbu.broadcom.com/wpan/PM/Project%20Document%20Library/bcm20791B0/ +# Design/Doc/PHY%20register%20settings/BCM20791-B2-1027-02_PHY_Recommended_Reg_Settings.xlsx +# This document is maintained by Paul Forshaw. +# +# The values marked as ?? should be tweaked per antenna or customer/app: +# {20:C8:1E:06:??:00:??:??:??:00:??:24:00:1C:00:75:00:77:00:76:00:1C:00:03:00:0A:00:??:01:00:00:40:04} +# array[0] = 0x20 is length of the payload from array[1] to the end +# array[1] = 0xC8 is PREINIT_DSP_CFG +#PREINIT_DSP_CFG={20:C8:1E:06:1F:00:0F:03:3C:00:04:24:00:1C:00:75:00:77:00:76:00:1C:00:03:00:0A:00:48:01:00:00:40:04} + +############################################################################### +# Configure crystal frequency when internal LPO can't detect the frequency. +#XTAL_FREQUENCY=0 +############################################################################### +# Configure the default Destination Gate used by HCI (the default is 4, which +# is the ETSI loopback gate. +NFA_HCI_DEFAULT_DEST_GATE=0xF0 + +############################################################################### +# Configure the single default SE to use. The default is to use the first +# SE that is detected by the stack. This value might be used when the phone +# supports multiple SE (e.g. 0xF3 and 0xF4) but you want to force it to use +# one of them (e.g. 0xF4). +#ACTIVE_SE=0xF3 + +############################################################################### +# Configure the default NfcA/IsoDep techology and protocol route. Can be +# either a secure element (e.g. 0xF4) or the host (0x00) +#DEFAULT_ISODEP_ROUTE=0x00 + +############################################################################### +# Configure the NFC Extras to open and use a static pipe. If the value is +# not set or set to 0, then the default is use a dynamic pipe based on a +# destination gate (see NFA_HCI_DEFAULT_DEST_GATE). Note there is a value +# for each UICC (where F3="UICC0" and F4="UICC1") +#NFA_HCI_STATIC_PIPE_ID_F3=0x70 +#NFA_HCI_STATIC_PIPE_ID_01=0x19 +NFA_HCI_STATIC_PIPE_ID_C0=0x19 +############################################################################### +# When disconnecting from Oberthur secure element, perform a warm-reset of +# the secure element to deselect the applet. +# The default hex value of the command is 0x3. If this variable is undefined, +# then this feature is not used. +#OBERTHUR_WARM_RESET_COMMAND=0x03 + +############################################################################### +# Force UICC to only listen to the following technology(s). +# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h. +# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B | NFA_TECHNOLOGY_MASK_F +UICC_LISTEN_TECH_MASK=0x07 + +# Forcing HOST to listen for a selected technology +# 0x00 : Disable Host Listen +# 0x01 : Enable Host Listen for Tech A +# 0x02 : Enable Host Listen for Tech B +# 0x03 : Enable Host Listen for Tech AB +HOST_LISTEN_TECH_MASK=0x03 + +############################################################################### +# Enabling/Disabling Forward functionality +# Disable 0x00 +# Enable 0x01 +NXP_FWD_FUNCTIONALITY_ENABLE=0x01 + +############################################################################### +# Allow UICC to be powered off if there is no traffic. +# Timeout is in ms. If set to 0, then UICC will not be powered off. +#UICC_IDLE_TIMEOUT=30000 +UICC_IDLE_TIMEOUT=0 + +############################################################################### +# AID for Empty Select command +# If specified, this AID will be substituted when an Empty SELECT command is +# detected. The first byte is the length of the AID. Maximum length is 16. +AID_FOR_EMPTY_SELECT={08:A0:00:00:01:51:00:00:00} +############################################################################### +# Maximum Number of Credits to be allowed by the NFCC +# This value overrides what the NFCC specifices allowing the host to have +# the control to work-around transport limitations. If this value does +# not exist or is set to 0, the NFCC will provide the number of credits. +MAX_RF_DATA_CREDITS=1 + +############################################################################### +# This setting allows you to disable registering the T4t Virtual SE that causes +# the NFCC to send PPSE requests to the DH. +# The default setting is enabled (i.e. T4t Virtual SE is registered). +#REGISTER_VIRTUAL_SE=1 + +############################################################################### +# When screen is turned off, specify the desired power state of the controller. +# 0: power-off-sleep state; DEFAULT +# 1: full-power state +# 2: screen-off card-emulation (CE4/CE3/CE1 modes are used) +SCREEN_OFF_POWER_STATE=1 + +############################################################################### +# Firmware patch file +# If the value is not set then patch download is disabled. +#FW_PATCH="/vendor/firmware/bcm2079x_firmware.ncd" + +############################################################################### +# Firmware pre-patch file (sent before the above patch file) +# If the value is not set then pre-patch is not used. +#FW_PRE_PATCH="/vendor/firmware/bcm2079x_pre_firmware.ncd" + +############################################################################### +# Firmware patch format +# 1 = HCD +# 2 = NCD (default) +#NFA_CONFIG_FORMAT=2 + +############################################################################### +# SPD Debug mode +# If set to 1, any failure of downloading a patch will trigger a hard-stop +#SPD_DEBUG=0 + +############################################################################### +# SPD Max Retry Count +# The number of attempts to download a patch before giving up (defualt is 3). +# Note, this resets after a power-cycle. +#SPD_MAX_RETRY_COUNT=3 + +############################################################################### +# transport driver +# +# TRANSPORT_DRIVER= +# +# where can be, for example: +# "/dev/ttyS" (UART) +# "/dev/bcmi2cnfc" (I2C) +# "hwtun" (HW Tunnel) +# "/dev/bcmspinfc" (SPI) +# "/dev/btusb0" (BT USB) +#TRANSPORT_DRIVER="/dev/bcm2079x-i2c" + +############################################################################### +# power control driver +# Specify a kernel driver that support ioctl commands to control NFC_EN and +# NFC_WAKE gpio signals. +# +# POWER_CONTRL_DRIVER= +# where can be, for example: +# "/dev/nfcpower" +# "/dev/bcmi2cnfc" (I2C) +# "/dev/bcmspinfc" (SPI) +# i2c and spi driver may be used to control NFC_EN and NFC_WAKE signal +#POWER_CONTROL_DRIVER="/dev/bcm2079x-i2c" + +############################################################################### +# I2C transport driver options +# Mako does not support 10-bit I2C addresses +# Revert to 7-bit address +#BCMI2CNFC_ADDRESS=0x77 + +############################################################################### +# I2C transport driver try to read multiple packets in read() if data is available +# remove the comment below to enable this feature +#READ_MULTIPLE_PACKETS=1 + +############################################################################### +# SPI transport driver options +#SPI_NEGOTIATION={0A:F0:00:01:00:00:00:FF:FF:00:00} + +############################################################################### +# UART transport driver options +# +# PORT=1,2,3,... +# BAUD=115200, 19200, 9600, 4800, +# DATABITS=8, 7, 6, 5 +# PARITY="even" | "odd" | "none" +# STOPBITS="0" | "1" | "1.5" | "2" + +#UART_PORT=2 +#UART_BAUD=115200 +#UART_DATABITS=8 +#UART_PARITY="none" +#UART_STOPBITS="1" + +############################################################################### +# Insert a delay in microseconds per byte after a write to NFCC. +# after writing a block of data to the NFCC, delay this an amopunt of time before +# writing next block of data. the delay is calculated as below +# NFC_WRITE_DELAY * (number of byte written) / 1000 milliseconds +# e.g. after 259 bytes is written, delay (259 * 20 / 1000) 5 ms before next write +#NFC_WRITE_DELAY=20 + +############################################################################### +# Maximum Number of Credits to be allowed by the NFCC +# This value overrides what the NFCC specifices allowing the host to have +# the control to work-around transport limitations. If this value does +# not exist or is set to 0, the NFCC will provide the number of credits. +MAX_RF_DATA_CREDITS=1 + +############################################################################### +# Default poll duration (in ms) +# The defualt is 500ms if not set (see nfc_target.h) +#NFA_DM_DISC_DURATION_POLL=333 +############################################################################### +# Antenna Configuration - This data is used when setting 0xC8 config item +# at startup (before discovery is started). If not used, no value is sent. +# +# The settings for this value are documented here: +# http://wcgbu.broadcom.com/wpan/PM/Project%20Document%20Library/bcm20791B0/ +# Design/Doc/PHY%20register%20settings/BCM20791-B2-1027-02_PHY_Recommended_Reg_Settings.xlsx +# This document is maintained by Paul Forshaw. +# +# The values marked as ?? should be tweaked per antenna or customer/app: +# {20:C8:1E:06:??:00:??:??:??:00:??:24:00:1C:00:75:00:77:00:76:00:1C:00:03:00:0A:00:??:01:00:00:40:04} +# array[0] = 0x20 is length of the payload from array[1] to the end +# array[1] = 0xC8 is PREINIT_DSP_CFG +#PREINIT_DSP_CFG={20:C8:1E:06:1F:00:0F:03:3C:00:04:24:00:1C:00:75:00:77:00:76:00:1C:00:03:00:0A:00:48:01:00:00:40:04} + + +############################################################################### +# Choose the presence-check algorithm for type-4 tag. If not defined, the default value is 1. +# 0 NFA_RW_PRES_CHK_DEFAULT; Let stack selects an algorithm +# 1 NFA_RW_PRES_CHK_I_BLOCK; ISO-DEP protocol's empty I-block +# 2 NFA_RW_PRES_CHK_RESET; Deactivate to Sleep, then re-activate +# 3 NFA_RW_PRES_CHK_RB_CH0; Type-4 tag protocol's ReadBinary command on channel 0 +# 4 NFA_RW_PRES_CHK_RB_CH3; Type-4 tag protocol's ReadBinary command on channel 3 +PRESENCE_CHECK_ALGORITHM=1 + +############################################################################### +# Force tag polling for the following technology(s). +# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h. +# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B | +# NFA_TECHNOLOGY_MASK_F | NFA_TECHNOLOGY_MASK_ISO15693 | +# NFA_TECHNOLOGY_MASK_B_PRIME | NFA_TECHNOLOGY_MASK_KOVIO | +# NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE. +# +# Notable bits: +# NFA_TECHNOLOGY_MASK_A 0x01 /* NFC Technology A */ +# NFA_TECHNOLOGY_MASK_B 0x02 /* NFC Technology B */ +# NFA_TECHNOLOGY_MASK_F 0x04 /* NFC Technology F */ +# NFA_TECHNOLOGY_MASK_ISO15693 0x08 /* Proprietary Technology */ +# NFA_TECHNOLOGY_MASK_KOVIO 0x20 /* Proprietary Technology */ +# NFA_TECHNOLOGY_MASK_A_ACTIVE 0x40 /* NFC Technology A active mode */ +# NFA_TECHNOLOGY_MASK_F_ACTIVE 0x80 /* NFC Technology F active mode */ +POLLING_TECH_MASK=0xEF + +############################################################################### +# Force P2P to only listen for the following technology(s). +# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h. +# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F | +# NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE +# +# Notable bits: +# NFA_TECHNOLOGY_MASK_A 0x01 /* NFC Technology A */ +# NFA_TECHNOLOGY_MASK_F 0x04 /* NFC Technology F */ +# NFA_TECHNOLOGY_MASK_A_ACTIVE 0x40 /* NFC Technology A active mode */ +# NFA_TECHNOLOGY_MASK_F_ACTIVE 0x80 /* NFC Technology F active mode */ +P2P_LISTEN_TECH_MASK=0xC5 + +PRESERVE_STORAGE=0x01 + +############################################################################### +# Override the stack default for NFA_EE_MAX_EE_SUPPORTED set in nfc_target.h. +# The value is set to 3 by default as it assumes we will discover 0xF2, +# 0xF3, and 0xF4. If a platform will exclude and SE, this value can be reduced +# so that the stack will not wait any longer than necessary. + +# Maximum EE supported number +# NXP PN547C2 0x02 +# NXP PN65T 0x03 +# NXP PN548C2 0x02 +# NXP PN66T 0x03 +NFA_MAX_EE_SUPPORTED=0x02 + +############################################################################### +# NCI Hal Module name +NCI_HAL_MODULE="nfc_nci.pn54x" + +############################################################################## +# Deactivate notification wait time out in seconds used in ETSI Reader mode +# 0 - Infinite wait +NFA_DM_DISC_NTF_TIMEOUT=100 + +############################################################################### +# AID_MATCHING constants +# AID_MATCHING_EXACT_ONLY 0x00 +# AID_MATCHING_EXACT_OR_PREFIX 0x01 +# AID_MATCHING_PREFIX_ONLY 0x02 +AID_MATCHING_MODE=0x01 + +############################################################################### +# Default Secure Element route id +DEFAULT_OFFHOST_ROUTE=0x02 + +############################################################################### +# Vendor Specific Proprietary Protocol & Discovery Configuration +# Set to 0xFF if unsupported +# byte[0] NCI_PROTOCOL_18092_ACTIVE +# byte[1] NCI_PROTOCOL_B_PRIME +# byte[2] NCI_PROTOCOL_DUAL +# byte[3] NCI_PROTOCOL_15693 +# byte[4] NCI_PROTOCOL_KOVIO +# byte[5] NCI_PROTOCOL_MIFARE +# byte[6] NCI_DISCOVERY_TYPE_POLL_KOVIO +# byte[7] NCI_DISCOVERY_TYPE_POLL_B_PRIME +# byte[8] NCI_DISCOVERY_TYPE_LISTEN_B_PRIME +NFA_PROPRIETARY_CFG={05:FF:FF:06:81:80:70:FF:FF} + +################################################################################# +# Bail out mode +# If set to 1, NFCC is using bail out mode for either Type A or Type B poll. +NFA_POLL_BAIL_OUT_MODE=0x01 +################################################################################# diff --git a/configs/libnfc-nxp.conf b/configs/libnfc-nxp.conf new file mode 100644 index 0000000..b522c2d --- /dev/null +++ b/configs/libnfc-nxp.conf @@ -0,0 +1,361 @@ +############################################################################### +## Modified by Motorola Mobility LLC +## Version : 3.5.2 (2016/06/21) +## added RF Blk 4 (21 to 22) and rf blk 5 (from 47 to 77) and rf blk 6 (from 10 to 00) +## This file is used by NFC NXP NCI HAL(external/libnfc-nci/halimpl/pn547) +## and NFC Service Java Native Interface Extensions (packages/apps/Nfc/nci/jni/extns/pn547) +## CLIF_ANA_TX_AMPLITUDE_REG_TYPE_B_TERMINAL_M +## CLIF_ANA_TX_AMPLITUDE_REG_TYPE_B_TERMINAL_M change 90 to 00 + +############################################################################### +# Application options +# Logging Levels +# NXPLOG_DEFAULT_LOGLEVEL 0x01 +# ANDROID_LOG_DEBUG 0x03 +# ANDROID_LOG_WARN 0x02 +# ANDROID_LOG_ERROR 0x01 +# ANDROID_LOG_SILENT 0x00 +# +NXPLOG_EXTNS_LOGLEVEL=0x03 +NXPLOG_NCIHAL_LOGLEVEL=0x03 +NXPLOG_NCIX_LOGLEVEL=0x03 +NXPLOG_NCIR_LOGLEVEL=0x03 +NXPLOG_FWDNLD_LOGLEVEL=0x03 +NXPLOG_TML_LOGLEVEL=0x03 + +############################################################################### +# Nfc Device Node name +NXP_NFC_DEV_NODE="/dev/pn544" + +############################################################################### +# Extension for Mifare reader enable +MIFARE_READER_ENABLE=0x01 + +############################################################################### +# Vzw Feature enable +VZW_FEATURE_ENABLE=0x01 + +############################################################################### +# File name for Firmware +NXP_FW_NAME="libpn548ad_fw.so" + +############################################################################### +# System clock source selection configuration +#define CLK_SRC_XTAL 1 +#define CLK_SRC_PLL 2 + +NXP_SYS_CLK_SRC_SEL=0x01 + +############################################################################### +# System clock frequency selection configuration +#define CLK_FREQ_13MHZ 1 +#define CLK_FREQ_19_2MHZ 2 +#define CLK_FREQ_24MHZ 3 +#define CLK_FREQ_26MHZ 4 +#define CLK_FREQ_38_4MHZ 5 +#define CLK_FREQ_52MHZ 6 + +NXP_SYS_CLK_FREQ_SEL=0x04 + +############################################################################### +# The timeout value to be used for clock request acknowledgment +# min value = 0x01 to max = 0x06 + +NXP_SYS_CLOCK_TO_CFG=0x01 + +############################################################################### +# NXP proprietary settings +NXP_ACT_PROP_EXTN={2F, 02, 00} + +############################################################################### +# NFC forum profile settings +NXP_NFC_PROFILE_EXTN={20, 02, 05, 01, A0, 44, 01, 00} + +############################################################################### +# NFCC Configuration Control +# Allow NFCC to manage RF Config 0x01 +# Don't allow NFCC to manage RF Config 0x00 +NXP_NFC_MERGE_RF_PARAMS={20, 02, 04, 01, 85, 01, 01} + +############################################################################### +# Standby enable settings +NXP_CORE_STANDBY={2F, 00, 01, 01} + +############################################################################### +# NXP TVDD configurations settings +# Allow NFCC to configure External TVDD, There are currently three +#configurations (1, 2 and 3) are supported, out of them only one can be +#supported. + +NXP_EXT_TVDD_CFG=0x02 + +#config1:SLALM, 3.3V for both RM and CM +NXP_EXT_TVDD_CFG_1={20, 02, 0B, 02, A0, 66, 01, 00, A0, 0E, 03, 02, 09, 00} + +#config2: use DCDC in CE, use Tx_Pwr_Req, set CFG2 mode, SLALM, +#monitoring 5V from DCDC, 4.7V for both RM and CM, DCDCWaitTime=4.2ms +NXP_EXT_TVDD_CFG_2={20, 02, 0B, 02, A0, 66, 01, 00, A0, 0E, 03, 56, 64, 0A} + +#config3: use DCDC in CE, use Tx_Pwr_Req, SLALM, monitoring 5V from DCDC, +#DCDCWaitTime=4.2ms +NXP_EXT_TVDD_CFG_3={20, 02, 0B, 02, A0, 66, 01, 01, A0, 0E, 03, 52, 64, 0A} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +NXP_RF_CONF_BLK_1={ + 20, 02, 1E, 2, + A0, 1D, 11, 54, 33, 14, 17, 00, AA, 85, 00, 80, 55, 2A, 04, 00, 63, 00, 00, 00, + A0, 0D, 06, 06, 03, 00, 6F, 00, 20 +} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +NXP_RF_CONF_BLK_2={ + 20, 02, 13, 02, + A0, 0D, 06, 06, 30, B0, 00, 10, 00, + A0, 0D, 06, 7C, 30, B0, 00, 10, 00 +} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +NXP_RF_CONF_BLK_3={ + 20, 02, 07, 01, + A0, 0D, 03, 00, 40, 03 +} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +# RF_CLIF_CFG_BR_106_I_RXA_P CLIF_ANA_RX_REG change from 21 to 22 +NXP_RF_CONF_BLK_4={ + 20, 02, 1D, 04, + A0, 0D, 04, 34, 44, 22, 00, + A0, 0D, 04, 46, 44, 22, 00, + A0, 0D, 04, 56, 44, 22, 00, + A0, 0D, 04, 5C, 44, 26, 00 +} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform, Min_level +# RF_CLIF_CFG_BR_106_I_RXA_P CLIF_SIGPRO_RM_CONFIG1_REG change from 47 to 77 +NXP_RF_CONF_BLK_5={ + 20, 02, 0A, 01, + A0, 0D, 06, 34, 2D, 24, 77, 0C, 00 +} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +# RF_CLIF_CFG_BR_106_I_TXA CLIF_ANA_TX_AMPLITUDE_REG change from 10 to 00 +# RF_CLIF_CFG_BR_106_T_TXB +NXP_RF_CONF_BLK_6={ + 20, 02, 2E, 05, + A0, 0D, 06, 32, 42, F8, 00, FF, FF, + A0, 0D, 06, 44, 42, 88, 00, FF, FF, + A0, 0D, 06, 54, 42, 88, 00, FF, FF, + A0, 0D, 06, 5A, 42, 90, 00, FF, FF, + A0, 0D, 06, 98, 42, 00, 00, FF, FF +} + +############################################################################### +## Set configuration optimization decision setting +## Enable = 0x01 +## Disable = 0x00 +NXP_SET_CONFIG_ALWAYS=0x01 + +############################################################################### +# Core configuration extensions +# It includes +# Wired mode settings A0ED, A0EE +# Tag Detector A040, A041, A043 +# Low Power mode A007 +# Clock settings A002, A003 +# PbF settings A008 +NXP_CORE_CONF_EXTN={20, 02, 1D, 07, + A0, EC, 01, 01, + A0, ED, 01, 00, + A0, 5E, 01, 01, + A0, 40, 01, 01, + A0, DD, 01, 2D, + A0, 41, 01, 02, + A0, 96, 01, 01 + } +# A0, 41, 01, 02, +# A0, 43, 01, 04, +# A0, 02, 01, 01, +# A0, 03, 01, 11, +# A0, 07, 01, 03, +# A0, 08, 01, 01 +# } + +############################################################################### +# Core configuration rf field filter settings to enable set to 01 to disable set to 00 last bit +NXP_CORE_RF_FIELD={ 20, 02, 05, 01, A0, 62, 01, 01 + } +############################################################################### +# To enable i2c fragmentation set i2c fragmentation enable 0x01 to disable set to 0x00 +NXP_I2C_FRAGMENTATION_ENABLED=0x00 + +############################################################################### +# Core configuration settings +NXP_CORE_CONF={ 20, 02, 31, 0F, + 28, 01, 00, + 21, 01, 00, + 30, 01, 08, + 31, 01, 03, + 33, 04, 01, 02, 03, 04, + 54, 01, 06, + 50, 01, 02, + 5B, 01, 00, + 60, 01, 0E, + 80, 01, 01, + 81, 01, 01, + 82, 01, 0E, + 18, 01, 01, + 32, 01, 60, + 38, 01, 01 + } + +############################################################################### +# Mifare Classic Key settings +#NXP_CORE_MFCKEY_SETTING={20, 02, 25,04, A0, 51, 06, A0, A1, A2, A3, A4, A5, +# A0, 52, 06, D3, F7, D3, F7, D3, F7, +# A0, 53, 06, FF, FF, FF, FF, FF, FF, +# A0, 54, 06, 00, 00, 00, 00, 00, 00} + +############################################################################### +# Default SE Options +# No secure element 0x00 +# eSE 0x01 +# UICC 0x02 + +NXP_DEFAULT_SE=0x02 + +############################################################################### +#Enable SWP full power mode when phone is power off +NXP_SWP_FULL_PWR_ON=0x00 + +############################################################################### +#### Select the CHIP #### +#PN547C2 0x01 +#PN65T 0x02 +#PN548AD 0x03 +#PN66T 0x04 + +NXP_NFC_CHIP=0x03 + +############################################################################### +# CE when Screen state is locked +# Disable 0x00 +# Enable 0x01 +NXP_CE_ROUTE_STRICT_DISABLE=0x01 + +#Timeout in secs to get NFCEE Discover notification +NXP_DEFAULT_NFCEE_DISC_TIMEOUT=20 + +NXP_DEFAULT_NFCEE_TIMEOUT=0x06 + +#Timeout in secs +NXP_SWP_RD_START_TIMEOUT=0x0A + +#Timeout in secs +NXP_SWP_RD_TAG_OP_TIMEOUT=0x01 + +############################################################################### +#Set the default AID route Location : +#This settings will be used when application does not set this parameter +# host 0x00 +# eSE 0x01 +# UICC 0x02 +DEFAULT_AID_ROUTE=0x02 + +############################################################################### +#Set the Mifare Desfire route Location : +#This settings will be used when application does not set this parameter +# host 0x00 +# eSE 0x01 +# UICC 0x02 +DEFAULT_DESFIRE_ROUTE=0x02 + +############################################################################### +#Set the Mifare CLT route Location : +#This settings will be used when application does not set this parameter +# host 0x00 +# eSE 0x01 +# UICC 0x02 +DEFAULT_MIFARE_CLT_ROUTE=0x02 + +############################################################################### +#Set the default AID Power state : +#This settings will be used when application does not set this parameter +# bit pos 0 = Switch On +# bit pos 1 = Switch Off +# bit pos 2 = Battery Off +# bit pos 3 = Screen Lock +# bit pos 4 = Screen Off +DEFAULT_AID_PWR_STATE=0x9 + +############################################################################### +#Set the Mifare Desfire Power state : +#This settings will be used when application does not set this parameter +# bit pos 0 = Switch On +# bit pos 1 = Switch Off +# bit pos 2 = Battery Off +# bit pos 3 = Screen Lock +# bit pos 4 = Screen Off +DEFAULT_DESFIRE_PWR_STATE=0x1B + +############################################################################### +#Set the Mifare CLT Power state : +#This settings will be used when application does not set this parameter +# bit pos 0 = Switch On +# bit pos 1 = Switch Off +# bit pos 2 = Battery Off +# bit pos 3 = Screen Lock +# bit pos 4 = Screen Off +DEFAULT_MIFARE_CLT_PWR_STATE=0x1B + +############################################################################### +# AID Matching platform options +# AID_MATCHING_L 0x01 +# AID_MATCHING_K 0x02 +AID_MATCHING_PLATFORM=0x01 +############################################################################### +#CHINA_TIANJIN_RF_SETTING +#Enable 0x01 +#Disable 0x00 +NXP_CHINA_TIANJIN_RF_ENABLED=0x01 +############################################################################### +#SWP_SWITCH_TIMEOUT_SETTING +# Allowed range of swp timeout setting is 0x00 to 0x3C [0 - 60]. +# Timeout in milliseconds, for example +# No Timeout 0x00 +# 10 millisecond timeout 0x0A +NXP_SWP_SWITCH_TIMEOUT=0x0A +############################################################################### +#Dynamic RSSI feature enable +# Disable 0x00 +# Enable 0x01 +NXP_AGC_DEBUG_ENABLE=0x00 + +############################################################################### +#Config to allow adding aids +#NFC on/off is required after this config +#1 = enabling adding aid to NFCC routing table. +#0 = disabling adding aid to NFCC routing table. +NXP_ENABLE_ADD_AID=0x01 +################################################################################ +# Enable/Disable checking default proto SE Id +# Disable 0x00 +# Enable 0x01 +NXP_CHECK_DEFAULT_PROTO_SE_ID=0x01 + +############################################################################### +# UICC mode supported +# Disable 0x00 +# Enable 0x01 +NXP_DUAL_UICC_ENABLE=0x00 diff --git a/configs/libnfc-nxp_ds.conf b/configs/libnfc-nxp_ds.conf new file mode 100644 index 0000000..4c6c305 --- /dev/null +++ b/configs/libnfc-nxp_ds.conf @@ -0,0 +1,346 @@ +############################################################################### +## Modified by Motorola Mobility LLC +## Version : 3.5.2 (2016/05/26) +## Dual SIM with switcher HW + +## This file is used by NFC NXP NCI HAL(external/libnfc-nci/halimpl/pn547) +## and NFC Service Java Native Interface Extensions (packages/apps/Nfc/nci/jni/extns/pn547) + +############################################################################### +# Application options +# Logging Levels +# NXPLOG_DEFAULT_LOGLEVEL 0x01 +# ANDROID_LOG_DEBUG 0x03 +# ANDROID_LOG_WARN 0x02 +# ANDROID_LOG_ERROR 0x01 +# ANDROID_LOG_SILENT 0x00 +# +NXPLOG_EXTNS_LOGLEVEL=0x03 +NXPLOG_NCIHAL_LOGLEVEL=0x03 +NXPLOG_NCIX_LOGLEVEL=0x03 +NXPLOG_NCIR_LOGLEVEL=0x03 +NXPLOG_FWDNLD_LOGLEVEL=0x03 +NXPLOG_TML_LOGLEVEL=0x03 + +############################################################################### +# Nfc Device Node name +NXP_NFC_DEV_NODE="/dev/pn544" + +############################################################################### +# Extension for Mifare reader enable +MIFARE_READER_ENABLE=0x01 + +############################################################################### +# Vzw Feature enable +VZW_FEATURE_ENABLE=0x01 + +############################################################################### +# File name for Firmware +NXP_FW_NAME="libpn548ad_fw.so" + +############################################################################### +# System clock source selection configuration +#define CLK_SRC_XTAL 1 +#define CLK_SRC_PLL 2 + +NXP_SYS_CLK_SRC_SEL=0x01 + +############################################################################### +# System clock frequency selection configuration +#define CLK_FREQ_13MHZ 1 +#define CLK_FREQ_19_2MHZ 2 +#define CLK_FREQ_24MHZ 3 +#define CLK_FREQ_26MHZ 4 +#define CLK_FREQ_38_4MHZ 5 +#define CLK_FREQ_52MHZ 6 + +NXP_SYS_CLK_FREQ_SEL=0x04 + +############################################################################### +# The timeout value to be used for clock request acknowledgment +# min value = 0x01 to max = 0x06 + +NXP_SYS_CLOCK_TO_CFG=0x01 + +############################################################################### +# NXP proprietary settings +NXP_ACT_PROP_EXTN={2F, 02, 00} + +############################################################################### +# NFC forum profile settings +NXP_NFC_PROFILE_EXTN={20, 02, 05, 01, A0, 44, 01, 00} + +############################################################################### +# NFCC Configuration Control +# Allow NFCC to manage RF Config 0x01 +# Don't allow NFCC to manage RF Config 0x00 +NXP_NFC_MERGE_RF_PARAMS={20, 02, 04, 01, 85, 01, 01} + +############################################################################### +# Standby enable settings +NXP_CORE_STANDBY={2F, 00, 01, 01} + +############################################################################### +# NXP TVDD configurations settings +# Allow NFCC to configure External TVDD, There are currently three +#configurations (1, 2 and 3) are supported, out of them only one can be +#supported. + +NXP_EXT_TVDD_CFG=0x02 + +#config1:SLALM, 3.3V for both RM and CM +NXP_EXT_TVDD_CFG_1={20, 02, 0B, 02, A0, 66, 01, 00, A0, 0E, 03, 02, 09, 00} + +#config2: use DCDC in CE, use Tx_Pwr_Req, set CFG2 mode, SLALM, +#monitoring 5V from DCDC, 4.7V for both RM and CM, DCDCWaitTime=4.2ms +# No Dual SIM +#NXP_EXT_TVDD_CFG_2={20, 02, 0B, 02, A0, 66, 01, 00, A0, 0E, 03, 56, 64, 0A} +# Dual SIM - bit 7 of the second value should be set to 1 +NXP_EXT_TVDD_CFG_2={20, 02, 0B, 02, A0, 66, 01, 00, A0, 0E, 03, 56, E4, 0A} + +#config3: use DCDC in CE, use Tx_Pwr_Req, SLALM, monitoring 5V from DCDC, +#DCDCWaitTime=4.2ms +NXP_EXT_TVDD_CFG_3={20, 02, 0B, 02, A0, 66, 01, 01, A0, 0E, 03, 52, 64, 0A} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +NXP_RF_CONF_BLK_1={ + 20, 02, 1E, 2, + A0, 1D, 11, 54, 33, 14, 17, 00, AA, 85, 00, 80, 55, 2A, 04, 00, 63, 00, 00, 00, + A0, 0D, 06, 06, 03, 00, 73, 00, 20 +} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +NXP_RF_CONF_BLK_2={ + 20, 02, 13, 02, + A0, 0D, 06, 06, 30, B0, 00, 10, 00, + A0, 0D, 06, 7C, 30, B0, 00, 10, 00 +} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +NXP_RF_CONF_BLK_3={ + 20, 02, 07, 01, + A0, 0D, 03, 00, 40, 03 +} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +#NXP_RF_CONF_BLK_4={ +#} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform, Min_level +#NXP_RF_CONF_BLK_5={ +#} + +############################################################################### +# NXP RF configuration ALM/PLM settings +# This section needs to be updated with the correct values based on the platform +#NXP_RF_CONF_BLK_6={ +#} + +############################################################################### +## Set configuration optimization decision setting +## Enable = 0x01 +## Disable = 0x00 +NXP_SET_CONFIG_ALWAYS=0x01 + +############################################################################### +# Core configuration extensions +# It includes +# Wired mode settings A0ED, A0EE +# Tag Detector A040, A041, A043 +# Low Power mode A007 +# Clock settings A002, A003 +# PbF settings A008 +NXP_CORE_CONF_EXTN={20, 02, 1D, 07, + A0, EC, 01, 11, + A0, ED, 01, 00, + A0, 5E, 01, 01, + A0, 40, 01, 01, + A0, DD, 01, 2D, + A0, 41, 01, 02, + A0, 96, 01, 01 + } +# A0, 41, 01, 02, +# A0, 43, 01, 04, +# A0, 02, 01, 01, +# A0, 03, 01, 11, +# A0, 07, 01, 03, +# A0, 08, 01, 01 +# } + +############################################################################### +# Core configuration rf field filter settings to enable set to 01 to disable set to 00 last bit +NXP_CORE_RF_FIELD={ 20, 02, 05, 01, A0, 62, 01, 01 + } +############################################################################### +# To enable i2c fragmentation set i2c fragmentation enable 0x01 to disable set to 0x00 +NXP_I2C_FRAGMENTATION_ENABLED=0x00 + +############################################################################### +# Core configuration settings +NXP_CORE_CONF={ 20, 02, 31, 0F, + 28, 01, 00, + 21, 01, 00, + 30, 01, 08, + 31, 01, 03, + 33, 04, 01, 02, 03, 04, + 54, 01, 06, + 50, 01, 02, + 5B, 01, 00, + 60, 01, 0E, + 80, 01, 01, + 81, 01, 01, + 82, 01, 0E, + 18, 01, 01, + 32, 01, 60, + 38, 01, 01 + } + +############################################################################### +# Mifare Classic Key settings +#NXP_CORE_MFCKEY_SETTING={20, 02, 25,04, A0, 51, 06, A0, A1, A2, A3, A4, A5, +# A0, 52, 06, D3, F7, D3, F7, D3, F7, +# A0, 53, 06, FF, FF, FF, FF, FF, FF, +# A0, 54, 06, 00, 00, 00, 00, 00, 00} + +############################################################################### +# Default SE Options +# No secure element 0x00 +# eSE 0x01 +# UICC 0x02 + +NXP_DEFAULT_SE=0x02 + +############################################################################### +#Enable SWP full power mode when phone is power off +NXP_SWP_FULL_PWR_ON=0x00 + +############################################################################### +#### Select the CHIP #### +#PN547C2 0x01 +#PN65T 0x02 +#PN548AD 0x03 +#PN66T 0x04 + +NXP_NFC_CHIP=0x03 + +############################################################################### +# CE when Screen state is locked +# Disable 0x00 +# Enable 0x01 +NXP_CE_ROUTE_STRICT_DISABLE=0x01 + +#Timeout in secs to get NFCEE Discover notification +NXP_DEFAULT_NFCEE_DISC_TIMEOUT=20 + +NXP_DEFAULT_NFCEE_TIMEOUT=0x06 + +#Timeout in secs +NXP_SWP_RD_START_TIMEOUT=0x0A + +#Timeout in secs +NXP_SWP_RD_TAG_OP_TIMEOUT=0x01 + +############################################################################### +#Set the default AID route Location : +#This settings will be used when application does not set this parameter +# host 0x00 +# eSE 0x01 +# UICC 0x02 +DEFAULT_AID_ROUTE=0x00 + +############################################################################### +#Set the Mifare Desfire route Location : +#This settings will be used when application does not set this parameter +# host 0x00 +# eSE 0x01 +# UICC 0x02 +DEFAULT_DESFIRE_ROUTE=0x02 + +############################################################################### +#Set the Mifare CLT route Location : +#This settings will be used when application does not set this parameter +# host 0x00 +# eSE 0x01 +# UICC 0x02 +DEFAULT_MIFARE_CLT_ROUTE=0x02 + +############################################################################### +#Set the default AID Power state : +#This settings will be used when application does not set this parameter +# bit pos 0 = Switch On +# bit pos 1 = Switch Off +# bit pos 2 = Battery Off +# bit pos 3 = Screen Lock +# bit pos 4 = Screen Off +DEFAULT_AID_PWR_STATE=0x9 + +############################################################################### +#Set the Mifare Desfire Power state : +#This settings will be used when application does not set this parameter +# bit pos 0 = Switch On +# bit pos 1 = Switch Off +# bit pos 2 = Battery Off +# bit pos 3 = Screen Lock +# bit pos 4 = Screen Off +DEFAULT_DESFIRE_PWR_STATE=0x1B + +############################################################################### +#Set the Mifare CLT Power state : +#This settings will be used when application does not set this parameter +# bit pos 0 = Switch On +# bit pos 1 = Switch Off +# bit pos 2 = Battery Off +# bit pos 3 = Screen Lock +# bit pos 4 = Screen Off +DEFAULT_MIFARE_CLT_PWR_STATE=0x1B + +############################################################################### +# AID Matching platform options +# AID_MATCHING_L 0x01 +# AID_MATCHING_K 0x02 +AID_MATCHING_PLATFORM=0x01 +############################################################################### +#CHINA_TIANJIN_RF_SETTING +#Enable 0x01 +#Disable 0x00 +NXP_CHINA_TIANJIN_RF_ENABLED=0x01 +############################################################################### +#SWP_SWITCH_TIMEOUT_SETTING +# Allowed range of swp timeout setting is 0x00 to 0x3C [0 - 60]. +# Timeout in milliseconds, for example +# No Timeout 0x00 +# 10 millisecond timeout 0x0A +NXP_SWP_SWITCH_TIMEOUT=0x0A +############################################################################### +#Dynamic RSSI feature enable +# Disable 0x00 +# Enable 0x01 +NXP_AGC_DEBUG_ENABLE=0x00 + +############################################################################### +#Config to allow adding aids +#NFC on/off is required after this config +#1 = enabling adding aid to NFCC routing table. +#0 = disabling adding aid to NFCC routing table. +NXP_ENABLE_ADD_AID=0x01 +################################################################################ +# Enable/Disable checking default proto SE Id +# Disable 0x00 +# Enable 0x01 +NXP_CHECK_DEFAULT_PROTO_SE_ID=0x01 + +############################################################################### +# UICC mode supported +# Disable 0x00 +# Enable 0x01 +NXP_DUAL_UICC_ENABLE=0x01 diff --git a/configs/media_codecs.xml b/configs/media_codecs.xml new file mode 100644 index 0000000..d555f16 --- /dev/null +++ b/configs/media_codecs.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/media_codecs_performance.xml b/configs/media_codecs_performance.xml new file mode 100644 index 0000000..6622f87 --- /dev/null +++ b/configs/media_codecs_performance.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/media_profiles.xml b/configs/media_profiles.xml new file mode 100644 index 0000000..59466c8 --- /dev/null +++ b/configs/media_profiles.xml @@ -0,0 +1,515 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/qdcm_calib_data_mipi_mot_cmd_smd_1080p_549.xml b/configs/qdcm_calib_data_mipi_mot_cmd_smd_1080p_549.xml new file mode 100644 index 0000000..f698e72 --- /dev/null +++ b/configs/qdcm_calib_data_mipi_mot_cmd_smd_1080p_549.xml @@ -0,0 +1,34 @@ + + + + + + 000000000000000000000000000000005E2BA1BB244EE73F669FC728CFBCCE3F861C5BCF108E993F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000412C9B3924B5803F73BC02D193B2EF3F016C4084B872863F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810A47904AB1933F57B5A4A31CCCAE3FE2C80391451AEB3F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000031130000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000200000000000000000000000200000000000000000000000300000000000000000000000300000000000000000000000400000000000000000000000400000000000000000000000500000000000000000000000500000000000000000000000600000000000000000000000600000000000000000000000700000000000000000000000700000000000000000000000800000000000000000000000800000000000000000000000900000000000000000000000900000000000000000000000A00000000000000000000000A00000000000000000000000B00000000000000000000000B00000000000000000000000C00000000000000000000000C00000000000000000000000D00000000000000000000000D00000000000000000000000E00000000000000000000000E00000000000000000000000F00000000000000000000000F00000000000000000000001000000000000000000000001000000000000000000000000000000001000000000000000000000001000000000000000100000001000000000000000100000001000000000000000200000001000000000000000200000001000000000000000300000001000000000000000300000001000000000000000400000001000000000000000400000001000000000000000500000001000000000000000500000001000000000000000600000001000000000000000600000001000000000000000700000001000000000000000700000001000000000000000800000001000000000000000800000001000000000000000900000001000000000000000900000001000000000000000A00000001000000000000000A00000001000000000000000B00000001000000000000000B00000001000000000000000C00000001000000000000000C00000001000000000000000D00000001000000000000000D00000001000000000000000E00000001000000000000000E00000001000000000000000F00000001000000000000000F00000001000000000000001000000001000000000000001000000001000000000000000000000002000000000000000000000002000000000000000100000002000000000000000100000002000000000000000200000002000000000000000200000002000000000000000300000002000000000000000300000002000000000000000400000002000000000000000400000002000000000000000500000002000000000000000500000002000000000000000600000002000000000000000600000002000000000000000700000002000000000000000700000002000000000000000800000002000000000000000800000002000000000000000900000002000000000000000900000002000000000000000A00000002000000000000000A00000002000000000000000B00000002000000000000000B00000002000000000000000C00000002000000000000000C00000002000000000000000D00000002000000000000000D00000002000000000000000E00000002000000000000000E00000002000000000000000F00000002000000000000000F00000002000000000000001000000002000000000000001000000002000000000000000000000003000000000000000000000003000000000000000100000003000000000000000100000003000000000000000200000003000000000000000200000003000000000000000300000003000000000000000300000003000000000000000400000003000000000000000400000003000000000000000500000003000000000000000500000003000000000000000600000003000000000000000600000003000000000000000700000003000000000000000700000003000000000000000800000003000000000000000800000003000000000000000900000003000000000000000900000003000000000000000A00000003000000000000000A00000003000000000000000B00000003000000000000000B00000003000000000000000C00000003000000000000000C00000003000000000000000D00000003000000000000000D00000003000000000000000E00000003000000000000000E00000003000000000000000F00000003000000000000000F00000003000000000000001000000003000000000000001000000003000000000000000000000004000000000000000000000004000000000000000100000004000000000000000100000004000000000000000200000004000000000000000200000004000000000000000300000004000000000000000300000004000000000000000400000004000000000000000400000004000000000000000500000004000000000000000500000004000000000000000600000004000000000000000600000004000000000000000700000004000000000000000700000004000000000000000800000004000000000000000800000004000000000000000900000004000000000000000900000004000000000000000A00000004000000000000000A00000004000000000000000B00000004000000000000000B00000004000000000000000C00000004000000000000000C00000004000000000000000D00000004000000000000000D00000004000000000000000E00000004000000000000000E00000004000000000000000F00000004000000000000000F00000004000000000000001000000004000000000000001000000004000000000000000000000005000000000000000000000005000000000000000100000005000000000000000100000005000000000000000200000005000000000000000200000005000000000000000300000005000000000000000300000005000000000000000400000005000000000000000400000005000000000000000500000005000000000000000500000005000000000000000600000005000000000000000600000005000000000000000700000005000000000000000700000005000000000000000800000005000000000000000800000005000000000000000900000005000000000000000900000005000000000000000A00000005000000000000000A00000005000000000000000B00000005000000000000000B00000005000000000000000C00000005000000000000000C00000005000000000000000D00000005000000000000000D00000005000000000000000E00000005000000000000000E00000005000000000000000F00000005000000000000000F00000005000000000000001000000005000000000000001000000005000000000000000000000006000000000000000000000006000000000000000100000006000000000000000100000006000000000000000200000006000000000000000200000006000000000000000300000006000000000000000300000006000000000000000400000006000000000000000400000006000000000000000500000006000000000000000500000006000000000000000600000006000000000000000600000006000000000000000700000006000000000000000700000006000000000000000800000006000000000000000800000006000000000000000900000006000000000000000900000006000000000000000A00000006000000000000000A00000006000000000000000B00000006000000000000000B00000006000000000000000C00000006000000000000000C00000006000000000000000D00000006000000000000000D00000006000000000000000E00000006000000000000000E00000006000000000000000F00000006000000000000000F00000006000000000000001000000006000000000000001000000006000000000000000000000007000000000000000000000007000000000000000100000007000000000000000100000007000000000000000200000007000000000000000200000007000000000000000300000007000000000000000300000007000000000000000400000007000000000000000400000007000000000000000500000007000000000000000500000007000000000000000600000007000000000000000600000007000000000000000700000007000000000000000700000007000000000000000800000007000000000000000800000007000000000000000900000007000000000000000900000007000000000000000A00000007000000000000000A00000007000000000000000B00000007000000000000000B00000007000000000000000C00000007000000000000000C00000007000000000000000D00000007000000000000000D00000007000000000000000E00000007000000000000000E00000007000000000000000F00000007000000000000000F00000007000000000000001000000007000000000000001000000007000000000000000000000008000000000000000000000008000000000000000100000008000000000000000100000008000000000000000200000008000000000000000200000008000000000000000300000008000000000000000300000008000000000000000400000008000000000000000400000008000000000000000500000008000000000000000500000008000000000000000600000008000000000000000600000008000000000000000700000008000000000000000700000008000000000000000800000008000000000000000800000008000000000000000900000008000000000000000900000008000000000000000A00000008000000000000000A00000008000000000000000B00000008000000000000000B00000008000000000000000C00000008000000000000000C00000008000000000000000D00000008000000000000000D00000008000000000000000E00000008000000000000000E00000008000000000000000F00000008000000000000000F00000008000000000000001000000008000000000000001000000008000000000000000000000009000000000000000000000009000000000000000100000009000000000000000100000009000000000000000200000009000000000000000200000009000000000000000300000009000000000000000300000009000000000000000400000009000000000000000400000009000000000000000500000009000000000000000500000009000000000000000600000009000000000000000600000009000000000000000700000009000000000000000700000009000000000000000800000009000000000000000800000009000000000000000900000009000000000000000900000009000000000000000A00000009000000000000000A00000009000000000000000B00000009000000000000000B00000009000000000000000C00000009000000000000000C00000009000000000000000D00000009000000000000000D00000009000000000000000E00000009000000000000000E00000009000000000000000F00000009000000000000000F0000000900000000000000100000000900000000000000100000000900000000000000000000000A00000000000000000000000A00000000000000010000000A00000000000000010000000A00000000000000020000000A00000000000000020000000A00000000000000030000000A00000000000000030000000A00000000000000040000000A00000000000000040000000A00000000000000050000000A00000000000000050000000A00000000000000060000000A00000000000000060000000A00000000000000070000000A00000000000000070000000A00000000000000080000000A00000000000000080000000A00000000000000090000000A00000000000000090000000A000000000000000A0000000A000000000000000A0000000A000000000000000B0000000A000000000000000B0000000A000000000000000C0000000A000000000000000C0000000A000000000000000D0000000A000000000000000D0000000A000000000000000E0000000A000000000000000E0000000A000000000000000F0000000A000000000000000F0000000A00000000000000100000000A00000000000000100000000A00000000000000000000000B00000000000000000000000B00000000000000010000000B00000000000000010000000B00000000000000020000000B00000000000000020000000B00000000000000030000000B00000000000000030000000B00000000000000040000000B00000000000000040000000B00000000000000050000000B00000000000000050000000B00000000000000060000000B00000000000000060000000B00000000000000070000000B00000000000000070000000B00000000000000080000000B00000000000000080000000B00000000000000090000000B00000000000000090000000B000000000000000A0000000B000000000000000A0000000B000000000000000B0000000B000000000000000B0000000B000000000000000C0000000B000000000000000C0000000B000000000000000D0000000B000000000000000D0000000B000000000000000E0000000B000000000000000E0000000B000000000000000F0000000B000000000000000F0000000B00000000000000100000000B00000000000000100000000B00000000000000000000000C00000000000000000000000C00000000000000010000000C00000000000000010000000C00000000000000020000000C00000000000000020000000C00000000000000030000000C00000000000000030000000C00000000000000040000000C00000000000000040000000C00000000000000050000000C00000000000000050000000C00000000000000060000000C00000000000000060000000C00000000000000070000000C00000000000000070000000C00000000000000080000000C00000000000000080000000C00000000000000090000000C00000000000000090000000C000000000000000A0000000C000000000000000A0000000C000000000000000B0000000C000000000000000B0000000C000000000000000C0000000C000000000000000C0000000C000000000000000D0000000C000000000000000D0000000C000000000000000E0000000C000000000000000E0000000C000000000000000F0000000C000000000000000F0000000C00000000000000100000000C00000000000000100000000C00000000000000000000000D00000000000000000000000D00000000000000010000000D00000000000000010000000D00000000000000020000000D00000000000000020000000D00000000000000030000000D00000000000000030000000D00000000000000040000000D00000000000000040000000D00000000000000050000000D00000000000000050000000D00000000000000060000000D00000000000000060000000D00000000000000070000000D00000000000000070000000D00000000000000080000000D00000000000000080000000D00000000000000090000000D00000000000000090000000D000000000000000A0000000D000000000000000A0000000D000000000000000B0000000D000000000000000B0000000D000000000000000C0000000D000000000000000C0000000D000000000000000D0000000D000000000000000D0000000D000000000000000E0000000D000000000000000E0000000D000000000000000F0000000D000000000000000F0000000D00000000000000100000000D00000000000000100000000D00000000000000000000000E00000000000000000000000E00000000000000010000000E00000000000000010000000E00000000000000020000000E00000000000000020000000E00000000000000030000000E00000000000000030000000E00000000000000040000000E00000000000000040000000E00000000000000050000000E00000000000000050000000E00000000000000060000000E00000000000000060000000E00000000000000070000000E00000000000000070000000E00000000000000080000000E00000000000000080000000E00000000000000090000000E00000000000000090000000E000000000000000A0000000E000000000000000A0000000E000000000000000B0000000E000000000000000B0000000E000000000000000C0000000E000000000000000C0000000E000000000000000D0000000E000000000000000D0000000E000000000000000E0000000E000000000000000E0000000E000000000000000F0000000E000000000000000F0000000E00000000000000100000000E00000000000000100000000E00000000000000000000000F00000000000000000000000F00000000000000010000000F00000000000000010000000F00000000000000020000000F00000000000000020000000F00000000000000030000000F00000000000000030000000F00000000000000040000000F00000000000000040000000F00000000000000050000000F00000000000000050000000F00000000000000060000000F00000000000000060000000F00000000000000070000000F00000000000000070000000F00000000000000080000000F00000000000000080000000F00000000000000090000000F00000000000000090000000F000000000000000A0000000F000000000000000A0000000F000000000000000B0000000F000000000000000B0000000F000000000000000C0000000F000000000000000C0000000F000000000000000D0000000F000000000000000D0000000F000000000000000E0000000F000000000000000E0000000F000000000000000F0000000F000000000000000F0000000F00000000000000100000000F00000000000000100000000F000000000000000000000010000000000000000000000010000000000000000100000010000000000000000100000010000000000000000200000010000000000000000200000010000000000000000300000010000000000000000300000010000000000000000400000010000000000000000400000010000000000000000500000010000000000000000500000010000000000000000600000010000000000000000600000010000000000000000700000010000000000000000700000010000000000000000800000010000000000000000800000010000000000000000900000010000000000000000900000010000000000000000A00000010000000000000000A00000010000000000000000B00000010000000000000000B00000010000000000000000C00000010000000000000000C00000010000000000000000D00000010000000000000000D00000010000000000000000E00000010000000000000000E00000010000000000000000F00000010000000000000000F00000010000000000000001000000010000000000000001000000010000000000000000000000000000000010000000000000000000000010000000100000000000000010000000100000000000000010000000200000000000000010000000200000000000000010000000300000000000000010000000300000000000000010000000400000000000000010000000400000000000000010000000500000000000000010000000500000000000000010000000600000000000000010000000600000000000000010000000700000000000000010000000700000000000000010000000800000000000000010000000800000000000000010000000900000000000000010000000900000000000000010000000A00000000000000010000000A00000000000000010000000B00000000000000010000000B00000000000000010000000C00000000000000010000000C00000000000000010000000D00000000000000010000000D00000000000000010000000E00000000000000010000000E00000000000000010000000F00000000000000010000000F00000000000000010000001000000000000000010000001000000000000000010000000000000001000000010000000000000001000000010000000100000001000000010000000100000001000000010000000200000001000000010000000200000001000000010000000300000001000000010000000300000001000000010000000400000001000000010000000400000001000000010000000500000001000000010000000500000001000000010000000600000001000000010000000600000001000000010000000700000001000000010000000700000001000000010000000800000001000000010000000800000001000000010000000900000001000000010000000900000001000000010000000A00000001000000010000000A00000001000000010000000B00000001000000010000000B00000001000000010000000C00000001000000010000000C00000001000000010000000D00000001000000010000000D00000001000000010000000E00000001000000010000000E00000001000000010000000F00000001000000010000000F00000001000000010000001000000001000000010000001000000001000000010000000000000002000000010000000000000002000000010000000100000002000000010000000100000002000000010000000200000002000000010000000200000002000000010000000300000002000000010000000300000002000000010000000400000002000000010000000400000002000000010000000500000002000000010000000500000002000000010000000600000002000000010000000600000002000000010000000700000002000000010000000700000002000000010000000800000002000000010000000800000002000000010000000900000002000000010000000900000002000000010000000A00000002000000010000000A00000002000000010000000B00000002000000010000000B00000002000000010000000C00000002000000010000000C00000002000000010000000D00000002000000010000000D00000002000000010000000E00000002000000010000000E00000002000000010000000F00000002000000010000000F00000002000000010000001000000002000000010000001000000002000000010000000000000003000000010000000000000003000000010000000100000003000000010000000100000003000000010000000200000003000000010000000200000003000000010000000300000003000000010000000300000003000000010000000400000003000000010000000400000003000000010000000500000003000000010000000500000003000000010000000600000003000000010000000600000003000000010000000700000003000000010000000700000003000000010000000800000003000000010000000800000003000000010000000900000003000000010000000900000003000000010000000A00000003000000010000000A00000003000000010000000B00000003000000010000000B00000003000000010000000C00000003000000010000000C00000003000000010000000D00000003000000010000000D00000003000000010000000E00000003000000010000000E00000003000000010000000F00000003000000010000000F00000003000000010000001000000003000000010000001000000003000000010000000000000004000000010000000000000004000000010000000100000004000000010000000100000004000000010000000200000004000000010000000200000004000000010000000300000004000000010000000300000004000000010000000400000004000000010000000400000004000000010000000500000004000000010000000500000004000000010000000600000004000000010000000600000004000000010000000700000004000000010000000700000004000000010000000800000004000000010000000800000004000000010000000900000004000000010000000900000004000000010000000A00000004000000010000000A00000004000000010000000B00000004000000010000000B00000004000000010000000C00000004000000010000000C00000004000000010000000D00000004000000010000000D00000004000000010000000E00000004000000010000000E00000004000000010000000F00000004000000010000000F00000004000000010000001000000004000000010000001000000004000000010000000000000005000000010000000000000005000000010000000100000005000000010000000100000005000000010000000200000005000000010000000200000005000000010000000300000005000000010000000300000005000000010000000400000005000000010000000400000005000000010000000500000005000000010000000500000005000000010000000600000005000000010000000600000005000000010000000700000005000000010000000700000005000000010000000800000005000000010000000800000005000000010000000900000005000000010000000900000005000000010000000A00000005000000010000000A00000005000000010000000B00000005000000010000000B00000005000000010000000C00000005000000010000000C00000005000000010000000D00000005000000010000000D00000005000000010000000E00000005000000010000000E00000005000000010000000F00000005000000010000000F00000005000000010000001000000005000000010000001000000005000000010000000000000006000000010000000000000006000000010000000100000006000000010000000100000006000000010000000200000006000000010000000200000006000000010000000300000006000000010000000300000006000000010000000400000006000000010000000400000006000000010000000500000006000000010000000500000006000000010000000600000006000000010000000600000006000000010000000700000006000000010000000700000006000000010000000800000006000000010000000800000006000000010000000900000006000000010000000900000006000000010000000A00000006000000010000000A00000006000000010000000B00000006000000010000000B00000006000000010000000C00000006000000010000000C00000006000000010000000D00000006000000010000000D00000006000000010000000E00000006000000010000000E00000006000000010000000F00000006000000010000000F00000006000000010000001000000006000000010000001000000006000000010000000000000007000000010000000000000007000000010000000100000007000000010000000100000007000000010000000200000007000000010000000200000007000000010000000300000007000000010000000300000007000000010000000400000007000000010000000400000007000000010000000500000007000000010000000500000007000000010000000600000007000000010000000600000007000000010000000700000007000000010000000700000007000000010000000800000007000000010000000800000007000000010000000900000007000000010000000900000007000000010000000A00000007000000010000000A00000007000000010000000B00000007000000010000000B00000007000000010000000C00000007000000010000000C00000007000000010000000D00000007000000010000000D00000007000000010000000E00000007000000010000000E00000007000000010000000F00000007000000010000000F00000007000000010000001000000007000000010000001000000007000000010000000000000008000000010000000000000008000000010000000100000008000000010000000100000008000000010000000200000008000000010000000200000008000000010000000300000008000000010000000300000008000000010000000400000008000000010000000400000008000000010000000500000008000000010000000500000008000000010000000600000008000000010000000600000008000000010000000700000008000000010000000700000008000000010000000800000008000000010000000800000008000000010000000900000008000000010000000900000008000000010000000A00000008000000010000000A00000008000000010000000B00000008000000010000000B00000008000000010000000C00000008000000010000000C00000008000000010000000D00000008000000010000000D00000008000000010000000E00000008000000010000000E00000008000000010000000F00000008000000010000000F00000008000000010000001000000008000000010000001000000008000000010000000000000009000000010000000000000009000000010000000100000009000000010000000100000009000000010000000200000009000000010000000200000009000000010000000300000009000000010000000300000009000000010000000400000009000000010000000400000009000000010000000500000009000000010000000500000009000000010000000600000009000000010000000600000009000000010000000700000009000000010000000700000009000000010000000800000009000000010000000800000009000000010000000900000009000000010000000900000009000000010000000A00000009000000010000000A00000009000000010000000B00000009000000010000000B00000009000000010000000C00000009000000010000000C00000009000000010000000D00000009000000010000000D00000009000000010000000E00000009000000010000000E00000009000000010000000F00000009000000010000000F0000000900000001000000100000000900000001000000100000000900000001000000000000000A00000001000000000000000A00000001000000010000000A00000001000000010000000A00000001000000020000000A00000001000000020000000A00000001000000030000000A00000001000000030000000A00000001000000040000000A00000001000000040000000A00000001000000050000000A00000001000000050000000A00000001000000060000000A00000001000000060000000A00000001000000070000000A00000001000000070000000A00000001000000080000000A00000001000000080000000A00000001000000090000000A00000001000000090000000A000000010000000A0000000A000000010000000A0000000A000000010000000B0000000A000000010000000B0000000A000000010000000C0000000A000000010000000C0000000A000000010000000D0000000A000000010000000D0000000A000000010000000E0000000A000000010000000E0000000A000000010000000F0000000A000000010000000F0000000A00000001000000100000000A00000001000000100000000A00000001000000000000000B00000001000000000000000B00000001000000010000000B00000001000000010000000B00000001000000020000000B00000001000000020000000B00000001000000030000000B00000001000000030000000B00000001000000040000000B00000001000000040000000B00000001000000050000000B00000001000000050000000B00000001000000060000000B00000001000000060000000B00000001000000070000000B00000001000000070000000B00000001000000080000000B00000001000000080000000B00000001000000090000000B00000001000000090000000B000000010000000A0000000B000000010000000A0000000B000000010000000B0000000B000000010000000B0000000B000000010000000C0000000B000000010000000C0000000B000000010000000D0000000B000000010000000D0000000B000000010000000E0000000B000000010000000E0000000B000000010000000F0000000B000000010000000F0000000B00000001000000100000000B00000001000000100000000B00000001000000000000000C00000001000000000000000C00000001000000010000000C00000001000000010000000C00000001000000020000000C00000001000000020000000C00000001000000030000000C00000001000000030000000C00000001000000040000000C00000001000000040000000C00000001000000050000000C00000001000000050000000C00000001000000060000000C00000001000000060000000C00000001000000070000000C00000001000000070000000C00000001000000080000000C00000001000000080000000C00000001000000090000000C00000001000000090000000C000000010000000A0000000C000000010000000A0000000C000000010000000B0000000C000000010000000B0000000C000000010000000C0000000C000000010000000C0000000C000000010000000D0000000C000000010000000D0000000C000000010000000E0000000C000000010000000E0000000C000000010000000F0000000C000000010000000F0000000C00000001000000100000000C00000001000000100000000C00000001000000000000000D00000001000000000000000D00000001000000010000000D00000001000000010000000D00000001000000020000000D00000001000000020000000D00000001000000030000000D00000001000000030000000D00000001000000040000000D00000001000000040000000D00000001000000050000000D00000001000000050000000D00000001000000060000000D00000001000000060000000D00000001000000070000000D00000001000000070000000D00000001000000080000000D00000001000000080000000D00000001000000090000000D00000001000000090000000D000000010000000A0000000D000000010000000A0000000D000000010000000B0000000D000000010000000B0000000D000000010000000C0000000D000000010000000C0000000D000000010000000D0000000D000000010000000D0000000D000000010000000E0000000D000000010000000E0000000D000000010000000F0000000D000000010000000F0000000D00000001000000100000000D00000001000000100000000D00000001000000000000000E00000001000000000000000E00000001000000010000000E00000001000000010000000E00000001000000020000000E00000001000000020000000E00000001000000030000000E00000001000000030000000E00000001000000040000000E00000001000000040000000E00000001000000050000000E00000001000000050000000E00000001000000060000000E00000001000000060000000E00000001000000070000000E00000001000000070000000E00000001000000080000000E00000001000000080000000E00000001000000090000000E00000001000000090000000E000000010000000A0000000E000000010000000A0000000E000000010000000B0000000E000000010000000B0000000E000000010000000C0000000E000000010000000C0000000E000000010000000D0000000E000000010000000D0000000E000000010000000E0000000E000000010000000E0000000E000000010000000F0000000E000000010000000F0000000E00000001000000100000000E00000001000000100000000E00000001000000000000000F00000001000000000000000F00000001000000010000000F00000001000000010000000F00000001000000020000000F00000001000000020000000F00000001000000030000000F00000001000000030000000F00000001000000040000000F00000001000000040000000F00000001000000050000000F00000001000000050000000F00000001000000060000000F00000001000000060000000F00000001000000070000000F00000001000000070000000F00000001000000080000000F00000001000000080000000F00000001000000090000000F00000001000000090000000F000000010000000A0000000F000000010000000A0000000F000000010000000B0000000F000000010000000B0000000F000000010000000C0000000F000000010000000C0000000F000000010000000D0000000F000000010000000D0000000F000000010000000E0000000F000000010000000E0000000F000000010000000F0000000F000000010000000F0000000F00000001000000100000000F00000001000000100000000F000000010000000000000010000000010000000000000010000000010000000100000010000000010000000100000010000000010000000200000010000000010000000200000010000000010000000300000010000000010000000300000010000000010000000400000010000000010000000400000010000000010000000500000010000000010000000500000010000000010000000600000010000000010000000600000010000000010000000700000010000000010000000700000010000000010000000800000010000000010000000800000010000000010000000900000010000000010000000900000010000000010000000A00000010000000010000000A00000010000000010000000B00000010000000010000000B00000010000000010000000C00000010000000010000000C00000010000000010000000D00000010000000010000000D00000010000000010000000E00000010000000010000000E00000010000000010000000F00000010000000010000000F00000010000000010000001000000010000000010000001000000010000000010000000000000000000000020000000000000000000000020000000100000000000000020000000100000000000000020000000200000000000000020000000200000000000000020000000300000000000000020000000300000000000000020000000400000000000000020000000400000000000000020000000500000000000000020000000500000000000000020000000600000000000000020000000600000000000000020000000700000000000000020000000700000000000000020000000800000000000000020000000800000000000000020000000900000000000000020000000900000000000000020000000A00000000000000020000000A00000000000000020000000B00000000000000020000000B00000000000000020000000C00000000000000020000000C00000000000000020000000D00000000000000020000000D00000000000000020000000E00000000000000020000000E00000000000000020000000F00000000000000020000000F00000000000000020000001000000000000000020000001000000000000000020000000000000001000000020000000000000001000000020000000100000001000000020000000100000001000000020000000200000001000000020000000200000001000000020000000300000001000000020000000300000001000000020000000400000001000000020000000400000001000000020000000500000001000000020000000500000001000000020000000600000001000000020000000600000001000000020000000700000001000000020000000700000001000000020000000800000001000000020000000800000001000000020000000900000001000000020000000900000001000000020000000A00000001000000020000000A00000001000000020000000B00000001000000020000000B00000001000000020000000C00000001000000020000000C00000001000000020000000D00000001000000020000000D00000001000000020000000E00000001000000020000000E00000001000000020000000F00000001000000020000000F00000001000000020000001000000001000000020000001000000001000000020000000000000002000000020000000000000002000000020000000100000002000000020000000100000002000000020000000200000002000000020000000200000002000000020000000300000002000000020000000300000002000000020000000400000002000000020000000400000002000000020000000500000002000000020000000500000002000000020000000600000002000000020000000600000002000000020000000700000002000000020000000700000002000000020000000800000002000000020000000800000002000000020000000900000002000000020000000900000002000000020000000A00000002000000020000000A00000002000000020000000B00000002000000020000000B00000002000000020000000C00000002000000020000000C00000002000000020000000D00000002000000020000000D00000002000000020000000E00000002000000020000000E00000002000000020000000F00000002000000020000000F00000002000000020000001000000002000000020000001000000002000000020000000000000003000000020000000000000003000000020000000100000003000000020000000100000003000000020000000200000003000000020000000200000003000000020000000300000003000000020000000300000003000000020000000400000003000000020000000400000003000000020000000500000003000000020000000500000003000000020000000600000003000000020000000600000003000000020000000700000003000000020000000700000003000000020000000800000003000000020000000800000003000000020000000900000003000000020000000900000003000000020000000A00000003000000020000000A00000003000000020000000B00000003000000020000000B00000003000000020000000C00000003000000020000000C00000003000000020000000D00000003000000020000000D00000003000000020000000E00000003000000020000000E00000003000000020000000F00000003000000020000000F00000003000000020000001000000003000000020000001000000003000000020000000000000004000000020000000000000004000000020000000100000004000000020000000100000004000000020000000200000004000000020000000200000004000000020000000300000004000000020000000300000004000000020000000400000004000000020000000400000004000000020000000500000004000000020000000500000004000000020000000600000004000000020000000600000004000000020000000700000004000000020000000700000004000000020000000800000004000000020000000800000004000000020000000900000004000000020000000900000004000000020000000A00000004000000020000000A00000004000000020000000B00000004000000020000000B00000004000000020000000C00000004000000020000000C00000004000000020000000D00000004000000020000000D00000004000000020000000E00000004000000020000000E00000004000000020000000F00000004000000020000000F00000004000000020000001000000004000000020000001000000004000000020000000000000005000000020000000000000005000000020000000100000005000000020000000100000005000000020000000200000005000000020000000200000005000000020000000300000005000000020000000300000005000000020000000400000005000000020000000400000005000000020000000500000005000000020000000500000005000000020000000600000005000000020000000600000005000000020000000700000005000000020000000700000005000000020000000800000005000000020000000800000005000000020000000900000005000000020000000900000005000000020000000A00000005000000020000000A00000005000000020000000B00000005000000020000000B00000005000000020000000C00000005000000020000000C00000005000000020000000D00000005000000020000000D00000005000000020000000E00000005000000020000000E00000005000000020000000F00000005000000020000000F00000005000000020000001000000005000000020000001000000005000000020000000000000006000000020000000000000006000000020000000100000006000000020000000100000006000000020000000200000006000000020000000200000006000000020000000300000006000000020000000300000006000000020000000400000006000000020000000400000006000000020000000500000006000000020000000500000006000000020000000600000006000000020000000600000006000000020000000700000006000000020000000700000006000000020000000800000006000000020000000800000006000000020000000900000006000000020000000900000006000000020000000A00000006000000020000000A00000006000000020000000B00000006000000020000000B00000006000000020000000C00000006000000020000000C00000006000000020000000D00000006000000020000000D00000006000000020000000E00000006000000020000000E00000006000000020000000F00000006000000020000000F00000006000000020000001000000006000000020000001000000006000000020000000000000007000000020000000000000007000000020000000100000007000000020000000100000007000000020000000200000007000000020000000200000007000000020000000300000007000000020000000300000007000000020000000400000007000000020000000400000007000000020000000500000007000000020000000500000007000000020000000600000007000000020000000600000007000000020000000700000007000000020000000700000007000000020000000800000007000000020000000800000007000000020000000900000007000000020000000900000007000000020000000A00000007000000020000000A00000007000000020000000B00000007000000020000000B00000007000000020000000C00000007000000020000000C00000007000000020000000D00000007000000020000000D00000007000000020000000E00000007000000020000000E00000007000000020000000F00000007000000020000000F00000007000000020000001000000007000000020000001000000007000000020000000000000008000000020000000000000008000000020000000100000008000000020000000100000008000000020000000200000008000000020000000200000008000000020000000300000008000000020000000300000008000000020000000400000008000000020000000400000008000000020000000500000008000000020000000500000008000000020000000600000008000000020000000600000008000000020000000700000008000000020000000700000008000000020000000800000008000000020000000800000008000000020000000900000008000000020000000900000008000000020000000A00000008000000020000000A00000008000000020000000B00000008000000020000000B00000008000000020000000C00000008000000020000000C00000008000000020000000D00000008000000020000000D00000008000000020000000E00000008000000020000000E00000008000000020000000F00000008000000020000000F00000008000000020000001000000008000000020000001000000008000000020000000000000009000000020000000000000009000000020000000100000009000000020000000100000009000000020000000200000009000000020000000200000009000000020000000300000009000000020000000300000009000000020000000400000009000000020000000400000009000000020000000500000009000000020000000500000009000000020000000600000009000000020000000600000009000000020000000700000009000000020000000700000009000000020000000800000009000000020000000800000009000000020000000900000009000000020000000900000009000000020000000A00000009000000020000000A00000009000000020000000B00000009000000020000000B00000009000000020000000C00000009000000020000000C00000009000000020000000D00000009000000020000000D00000009000000020000000E00000009000000020000000E00000009000000020000000F00000009000000020000000F0000000900000002000000100000000900000002000000100000000900000002000000000000000A00000002000000000000000A00000002000000010000000A00000002000000010000000A00000002000000020000000A00000002000000020000000A00000002000000030000000A00000002000000030000000A00000002000000040000000A00000002000000040000000A00000002000000050000000A00000002000000050000000A00000002000000060000000A00000002000000060000000A00000002000000070000000A00000002000000070000000A00000002000000080000000A00000002000000080000000A00000002000000090000000A00000002000000090000000A000000020000000A0000000A000000020000000A0000000A000000020000000B0000000A000000020000000B0000000A000000020000000C0000000A000000020000000C0000000A000000020000000D0000000A000000020000000D0000000A000000020000000E0000000A000000020000000E0000000A000000020000000F0000000A000000020000000F0000000A00000002000000100000000A00000002000000100000000A00000002000000000000000B00000002000000000000000B00000002000000010000000B00000002000000010000000B00000002000000020000000B00000002000000020000000B00000002000000030000000B00000002000000030000000B00000002000000040000000B00000002000000040000000B00000002000000050000000B00000002000000050000000B00000002000000060000000B00000002000000060000000B00000002000000070000000B00000002000000070000000B00000002000000080000000B00000002000000080000000B00000002000000090000000B00000002000000090000000B000000020000000A0000000B000000020000000A0000000B000000020000000B0000000B000000020000000B0000000B000000020000000C0000000B000000020000000C0000000B000000020000000D0000000B000000020000000D0000000B000000020000000E0000000B000000020000000E0000000B000000020000000F0000000B000000020000000F0000000B00000002000000100000000B00000002000000100000000B00000002000000000000000C00000002000000000000000C00000002000000010000000C00000002000000010000000C00000002000000020000000C00000002000000020000000C00000002000000030000000C00000002000000030000000C00000002000000040000000C00000002000000040000000C00000002000000050000000C00000002000000050000000C00000002000000060000000C00000002000000060000000C00000002000000070000000C00000002000000070000000C00000002000000080000000C00000002000000080000000C00000002000000090000000C00000002000000090000000C000000020000000A0000000C000000020000000A0000000C000000020000000B0000000C000000020000000B0000000C000000020000000C0000000C000000020000000C0000000C000000020000000D0000000C000000020000000D0000000C000000020000000E0000000C000000020000000E0000000C000000020000000F0000000C000000020000000F0000000C00000002000000100000000C00000002000000100000000C00000002000000000000000D00000002000000000000000D00000002000000010000000D00000002000000010000000D00000002000000020000000D00000002000000020000000D00000002000000030000000D00000002000000030000000D00000002000000040000000D00000002000000040000000D00000002000000050000000D00000002000000050000000D00000002000000060000000D00000002000000060000000D00000002000000070000000D00000002000000070000000D00000002000000080000000D00000002000000080000000D00000002000000090000000D00000002000000090000000D000000020000000A0000000D000000020000000A0000000D000000020000000B0000000D000000020000000B0000000D000000020000000C0000000D000000020000000C0000000D000000020000000D0000000D000000020000000D0000000D000000020000000E0000000D000000020000000E0000000D000000020000000F0000000D000000020000000F0000000D00000002000000100000000D00000002000000100000000D00000002000000000000000E00000002000000000000000E00000002000000010000000E00000002000000010000000E00000002000000020000000E00000002000000020000000E00000002000000030000000E00000002000000030000000E00000002000000040000000E00000002000000040000000E00000002000000050000000E00000002000000050000000E00000002000000060000000E00000002000000060000000E00000002000000070000000E00000002000000070000000E00000002000000080000000E00000002000000080000000E00000002000000090000000E00000002000000090000000E000000020000000A0000000E000000020000000A0000000E000000020000000B0000000E000000020000000B0000000E000000020000000C0000000E000000020000000C0000000E000000020000000D0000000E000000020000000D0000000E000000020000000E0000000E000000020000000E0000000E000000020000000F0000000E000000020000000F0000000E00000002000000100000000E00000002000000100000000E00000002000000000000000F00000002000000000000000F00000002000000010000000F00000002000000010000000F00000002000000020000000F00000002000000020000000F00000002000000030000000F00000002000000030000000F00000002000000040000000F00000002000000040000000F00000002000000050000000F00000002000000050000000F00000002000000060000000F00000002000000060000000F00000002000000070000000F00000002000000070000000F00000002000000080000000F00000002000000080000000F00000002000000090000000F00000002000000090000000F000000020000000A0000000F000000020000000A0000000F000000020000000B0000000F000000020000000B0000000F000000020000000C0000000F000000020000000C0000000F000000020000000D0000000F000000020000000D0000000F000000020000000E0000000F000000020000000E0000000F000000020000000F0000000F000000020000000F0000000F00000002000000100000000F00000002000000100000000F000000020000000000000010000000020000000000000010000000020000000100000010000000020000000100000010000000020000000200000010000000020000000200000010000000020000000300000010000000020000000300000010000000020000000400000010000000020000000400000010000000020000000500000010000000020000000500000010000000020000000600000010000000020000000600000010000000020000000700000010000000020000000700000010000000020000000800000010000000020000000800000010000000020000000900000010000000020000000900000010000000020000000A00000010000000020000000A00000010000000020000000B00000010000000020000000B00000010000000020000000C00000010000000020000000C00000010000000020000000D00000010000000020000000D00000010000000020000000E00000010000000020000000E00000010000000020000000F00000010000000020000000F00000010000000020000001000000010000000020000001000000010000000020000000000000000000000030000000000000000000000030000000100000000000000030000000100000000000000030000000200000000000000030000000200000000000000030000000300000000000000030000000300000000000000030000000400000000000000030000000400000000000000030000000500000000000000030000000500000000000000030000000600000000000000030000000600000000000000030000000700000000000000030000000700000000000000030000000800000000000000030000000800000000000000030000000900000000000000030000000900000000000000030000000A00000000000000030000000A00000000000000030000000B00000000000000030000000B00000000000000030000000C00000000000000030000000C00000000000000030000000D00000000000000030000000D00000000000000030000000E00000000000000030000000E00000000000000030000000F00000000000000030000000F00000000000000030000001000000000000000030000001000000000000000030000000000000001000000030000000000000001000000030000000100000001000000030000000100000001000000030000000200000001000000030000000200000001000000030000000300000001000000030000000300000001000000030000000400000001000000030000000400000001000000030000000500000001000000030000000500000001000000030000000600000001000000030000000600000001000000030000000700000001000000030000000700000001000000030000000800000001000000030000000800000001000000030000000900000001000000030000000900000001000000030000000A00000001000000030000000A00000001000000030000000B00000001000000030000000B00000001000000030000000C00000001000000030000000C00000001000000030000000D00000001000000030000000D00000001000000030000000E00000001000000030000000E00000001000000030000000F00000001000000030000000F00000001000000030000001000000001000000030000001000000001000000030000000000000002000000030000000000000002000000030000000100000002000000030000000100000002000000030000000200000002000000030000000200000002000000030000000300000002000000030000000300000002000000030000000400000002000000030000000400000002000000030000000500000002000000030000000500000002000000030000000600000002000000030000000600000002000000030000000700000002000000030000000700000002000000030000000800000002000000030000000800000002000000030000000900000002000000030000000900000002000000030000000A00000002000000030000000A00000002000000030000000B00000002000000030000000B00000002000000030000000C00000002000000030000000C00000002000000030000000D00000002000000030000000D00000002000000030000000E00000002000000030000000E00000002000000030000000F00000002000000030000000F00000002000000030000001000000002000000030000001000000002000000030000000000000003000000030000000000000003000000030000000100000003000000030000000100000003000000030000000200000003000000030000000200000003000000030000000300000003000000030000000300000003000000030000000400000003000000030000000400000003000000030000000500000003000000030000000500000003000000030000000600000003000000030000000600000003000000030000000700000003000000030000000700000003000000030000000800000003000000030000000800000003000000030000000900000003000000030000000900000003000000030000000A00000003000000030000000A00000003000000030000000B00000003000000030000000B00000003000000030000000C00000003000000030000000C00000003000000030000000D00000003000000030000000D00000003000000030000000E00000003000000030000000E00000003000000030000000F00000003000000030000000F00000003000000030000001000000003000000030000001000000003000000030000000000000004000000030000000000000004000000030000000100000004000000030000000100000004000000030000000200000004000000030000000200000004000000030000000300000004000000030000000300000004000000030000000400000004000000030000000400000004000000030000000500000004000000030000000500000004000000030000000600000004000000030000000600000004000000030000000700000004000000030000000700000004000000030000000800000004000000030000000800000004000000030000000900000004000000030000000900000004000000030000000A00000004000000030000000A00000004000000030000000B00000004000000030000000B00000004000000030000000C00000004000000030000000C00000004000000030000000D00000004000000030000000D00000004000000030000000E00000004000000030000000E00000004000000030000000F00000004000000030000000F00000004000000030000001000000004000000030000001000000004000000030000000000000005000000030000000000000005000000030000000100000005000000030000000100000005000000030000000200000005000000030000000200000005000000030000000300000005000000030000000300000005000000030000000400000005000000030000000400000005000000030000000500000005000000030000000500000005000000030000000600000005000000030000000600000005000000030000000700000005000000030000000700000005000000030000000800000005000000030000000800000005000000030000000900000005000000030000000900000005000000030000000A00000005000000030000000A00000005000000030000000B00000005000000030000000B00000005000000030000000C00000005000000030000000C00000005000000030000000D00000005000000030000000D00000005000000030000000E00000005000000030000000E00000005000000030000000F00000005000000030000000F00000005000000030000001000000005000000030000001000000005000000030000000000000006000000030000000000000006000000030000000100000006000000030000000100000006000000030000000200000006000000030000000200000006000000030000000300000006000000030000000300000006000000030000000400000006000000030000000400000006000000030000000500000006000000030000000500000006000000030000000600000006000000030000000600000006000000030000000700000006000000030000000700000006000000030000000800000006000000030000000800000006000000030000000900000006000000030000000900000006000000030000000A00000006000000030000000A00000006000000030000000B00000006000000030000000B00000006000000030000000C00000006000000030000000C00000006000000030000000D00000006000000030000000D00000006000000030000000E00000006000000030000000E00000006000000030000000F00000006000000030000000F00000006000000030000001000000006000000030000001000000006000000030000000000000007000000030000000000000007000000030000000100000007000000030000000100000007000000030000000200000007000000030000000200000007000000030000000300000007000000030000000300000007000000030000000400000007000000030000000400000007000000030000000500000007000000030000000500000007000000030000000600000007000000030000000600000007000000030000000700000007000000030000000700000007000000030000000800000007000000030000000800000007000000030000000900000007000000030000000900000007000000030000000A00000007000000030000000A00000007000000030000000B00000007000000030000000B00000007000000030000000C00000007000000030000000C00000007000000030000000D00000007000000030000000D00000007000000030000000E00000007000000030000000E00000007000000030000000F00000007000000030000000F00000007000000030000001000000007000000030000001000000007000000030000000000000008000000030000000000000008000000030000000100000008000000030000000100000008000000030000000200000008000000030000000200000008000000030000000300000008000000030000000300000008000000030000000400000008000000030000000400000008000000030000000500000008000000030000000500000008000000030000000600000008000000030000000600000008000000030000000700000008000000030000000700000008000000030000000800000008000000030000000800000008000000030000000900000008000000030000000900000008000000030000000A00000008000000030000000A00000008000000030000000B00000008000000030000000B00000008000000030000000C00000008000000030000000C00000008000000030000000D00000008000000030000000D00000008000000030000000E00000008000000030000000E00000008000000030000000F00000008000000030000000F00000008000000030000001000000008000000030000001000000008000000030000000000000009000000030000000000000009000000030000000100000009000000030000000100000009000000030000000200000009000000030000000200000009000000030000000300000009000000030000000300000009000000030000000400000009000000030000000400000009000000030000000500000009000000030000000500000009000000030000000600000009000000030000000600000009000000030000000700000009000000030000000700000009000000030000000800000009000000030000000800000009000000030000000900000009000000030000000900000009000000030000000A00000009000000030000000A00000009000000030000000B00000009000000030000000B00000009000000030000000C00000009000000030000000C00000009000000030000000D00000009000000030000000D00000009000000030000000E00000009000000030000000E00000009000000030000000F00000009000000030000000F0000000900000003000000100000000900000003000000100000000900000003000000000000000A00000003000000000000000A00000003000000010000000A00000003000000010000000A00000003000000020000000A00000003000000020000000A00000003000000030000000A00000003000000030000000A00000003000000040000000A00000003000000040000000A00000003000000050000000A00000003000000050000000A00000003000000060000000A00000003000000060000000A00000003000000070000000A00000003000000070000000A00000003000000080000000A00000003000000080000000A00000003000000090000000A00000003000000090000000A000000030000000A0000000A000000030000000A0000000A000000030000000B0000000A000000030000000B0000000A000000030000000C0000000A000000030000000C0000000A000000030000000D0000000A000000030000000D0000000A000000030000000E0000000A000000030000000E0000000A000000030000000F0000000A000000030000000F0000000A00000003000000100000000A00000003000000100000000A00000003000000000000000B00000003000000000000000B00000003000000010000000B00000003000000010000000B00000003000000020000000B00000003000000020000000B00000003000000030000000B00000003000000030000000B00000003000000040000000B00000003000000040000000B00000003000000050000000B00000003000000050000000B00000003000000060000000B00000003000000060000000B00000003000000070000000B00000003000000070000000B00000003000000080000000B00000003000000080000000B00000003000000090000000B00000003000000090000000B000000030000000A0000000B000000030000000A0000000B000000030000000B0000000B000000030000000B0000000B000000030000000C0000000B000000030000000C0000000B000000030000000D0000000B000000030000000D0000000B000000030000000E0000000B000000030000000E0000000B000000030000000F0000000B000000030000000F0000000B00000003000000100000000B00000003000000100000000B00000003000000000000000C00000003000000000000000C00000003000000010000000C00000003000000010000000C00000003000000020000000C00000003000000020000000C00000003000000030000000C00000003000000030000000C00000003000000040000000C00000003000000040000000C00000003000000050000000C00000003000000050000000C00000003000000060000000C00000003000000060000000C00000003000000070000000C00000003000000070000000C00000003000000080000000C00000003000000080000000C00000003000000090000000C00000003000000090000000C000000030000000A0000000C000000030000000A0000000C000000030000000B0000000C000000030000000B0000000C000000030000000C0000000C000000030000000C0000000C000000030000000D0000000C000000030000000D0000000C000000030000000E0000000C000000030000000E0000000C000000030000000F0000000C000000030000000F0000000C00000003000000100000000C00000003000000100000000C00000003000000000000000D00000003000000000000000D00000003000000010000000D00000003000000010000000D00000003000000020000000D00000003000000020000000D00000003000000030000000D00000003000000030000000D00000003000000040000000D00000003000000040000000D00000003000000050000000D00000003000000050000000D00000003000000060000000D00000003000000060000000D00000003000000070000000D00000003000000070000000D00000003000000080000000D00000003000000080000000D00000003000000090000000D00000003000000090000000D000000030000000A0000000D000000030000000A0000000D000000030000000B0000000D000000030000000B0000000D000000030000000C0000000D000000030000000C0000000D000000030000000D0000000D000000030000000D0000000D000000030000000E0000000D000000030000000E0000000D000000030000000F0000000D000000030000000F0000000D00000003000000100000000D00000003000000100000000D00000003000000000000000E00000003000000000000000E00000003000000010000000E00000003000000010000000E00000003000000020000000E00000003000000020000000E00000003000000030000000E00000003000000030000000E00000003000000040000000E00000003000000040000000E00000003000000050000000E00000003000000050000000E00000003000000060000000E00000003000000060000000E00000003000000070000000E00000003000000070000000E00000003000000080000000E00000003000000080000000E00000003000000090000000E00000003000000090000000E000000030000000A0000000E000000030000000A0000000E000000030000000B0000000E000000030000000B0000000E000000030000000C0000000E000000030000000C0000000E000000030000000D0000000E000000030000000D0000000E000000030000000E0000000E000000030000000E0000000E000000030000000F0000000E000000030000000F0000000E00000003000000100000000E00000003000000100000000E00000003000000000000000F00000003000000000000000F00000003000000010000000F00000003000000010000000F00000003000000020000000F00000003000000020000000F00000003000000030000000F00000003000000030000000F00000003000000040000000F00000003000000040000000F00000003000000050000000F00000003000000050000000F00000003000000060000000F00000003000000060000000F00000003000000070000000F00000003000000070000000F00000003000000080000000F00000003000000080000000F00000003000000090000000F00000003000000090000000F000000030000000A0000000F000000030000000A0000000F000000030000000B0000000F000000030000000B0000000F000000030000000C0000000F000000030000000C0000000F000000030000000D0000000F000000030000000D0000000F000000030000000E0000000F000000030000000E0000000F000000030000000F0000000F000000030000000F0000000F00000003000000100000000F00000003000000100000000F000000030000000000000010000000030000000000000010000000030000000100000010000000030000000100000010000000030000000200000010000000030000000200000010000000030000000300000010000000030000000300000010000000030000000400000010000000030000000400000010000000030000000500000010000000030000000500000010000000030000000600000010000000030000000600000010000000030000000700000010000000030000000700000010000000030000000800000010000000030000000800000010000000030000000900000010000000030000000900000010000000030000000A00000010000000030000000A00000010000000030000000B00000010000000030000000B00000010000000030000000C00000010000000030000000C00000010000000030000000D00000010000000030000000D00000010000000030000000E00000010000000030000000E00000010000000030000000F00000010000000030000000F00000010000000030000001000000010000000030000001000000010000000030000000000000000000000040000000000000000000000040000000100000000000000040000000100000000000000040000000200000000000000040000000200000000000000040000000300000000000000040000000300000000000000040000000400000000000000040000000400000000000000040000000500000000000000040000000500000000000000040000000600000000000000040000000600000000000000040000000700000000000000040000000700000000000000040000000800000000000000040000000800000000000000040000000900000000000000040000000900000000000000040000000A00000000000000040000000A00000000000000040000000B00000000000000040000000B00000000000000040000000C00000000000000040000000C00000000000000040000000D00000000000000040000000D00000000000000040000000E00000000000000040000000E00000000000000040000000F00000000000000040000000F00000000000000040000001000000000000000040000001000000000000000040000000000000001000000040000000000000001000000040000000100000001000000040000000100000001000000040000000200000001000000040000000200000001000000040000000300000001000000040000000300000001000000040000000400000001000000040000000400000001000000040000000500000001000000040000000500000001000000040000000600000001000000040000000600000001000000040000000700000001000000040000000700000001000000040000000800000001000000040000000800000001000000040000000900000001000000040000000900000001000000040000000A00000001000000040000000A00000001000000040000000B00000001000000040000000B00000001000000040000000C00000001000000040000000C00000001000000040000000D00000001000000040000000D00000001000000040000000E00000001000000040000000E00000001000000040000000F00000001000000040000000F00000001000000040000001000000001000000040000001000000001000000040000000000000002000000040000000000000002000000040000000100000002000000040000000100000002000000040000000200000002000000040000000200000002000000040000000300000002000000040000000300000002000000040000000400000002000000040000000400000002000000040000000500000002000000040000000500000002000000040000000600000002000000040000000600000002000000040000000700000002000000040000000700000002000000040000000800000002000000040000000800000002000000040000000900000002000000040000000900000002000000040000000A00000002000000040000000A00000002000000040000000B00000002000000040000000B00000002000000040000000C00000002000000040000000C00000002000000040000000D00000002000000040000000D00000002000000040000000E00000002000000040000000E00000002000000040000000F00000002000000040000000F00000002000000040000001000000002000000040000001000000002000000040000000000000003000000040000000000000003000000040000000100000003000000040000000100000003000000040000000200000003000000040000000200000003000000040000000300000003000000040000000300000003000000040000000400000003000000040000000400000003000000040000000500000003000000040000000500000003000000040000000600000003000000040000000600000003000000040000000700000003000000040000000700000003000000040000000800000003000000040000000800000003000000040000000900000003000000040000000900000003000000040000000A00000003000000040000000A00000003000000040000000B00000003000000040000000B00000003000000040000000C00000003000000040000000C00000003000000040000000D00000003000000040000000D00000003000000040000000E00000003000000040000000E00000003000000040000000F00000003000000040000000F00000003000000040000001000000003000000040000001000000003000000040000000000000004000000040000000000000004000000040000000100000004000000040000000100000004000000040000000200000004000000040000000200000004000000040000000300000004000000040000000300000004000000040000000400000004000000040000000400000004000000040000000500000004000000040000000500000004000000040000000600000004000000040000000600000004000000040000000700000004000000040000000700000004000000040000000800000004000000040000000800000004000000040000000900000004000000040000000900000004000000040000000A00000004000000040000000A00000004000000040000000B00000004000000040000000B00000004000000040000000C00000004000000040000000C00000004000000040000000D00000004000000040000000D00000004000000040000000E00000004000000040000000E00000004000000040000000F00000004000000040000000F00000004000000040000001000000004000000040000001000000004000000040000000000000005000000040000000000000005000000040000000100000005000000040000000100000005000000040000000200000005000000040000000200000005000000040000000300000005000000040000000300000005000000040000000400000005000000040000000400000005000000040000000500000005000000040000000500000005000000040000000600000005000000040000000600000005000000040000000700000005000000040000000700000005000000040000000800000005000000040000000800000005000000040000000900000005000000040000000900000005000000040000000A00000005000000040000000A00000005000000040000000B00000005000000040000000B00000005000000040000000C00000005000000040000000C00000005000000040000000D00000005000000040000000D00000005000000040000000E00000005000000040000000E00000005000000040000000F00000005000000040000000F00000005000000040000001000000005000000040000001000000005000000040000000000000006000000040000000000000006000000040000000100000006000000040000000100000006000000040000000200000006000000040000000200000006000000040000000300000006000000040000000300000006000000040000000400000006000000040000000400000006000000040000000500000006000000040000000500000006000000040000000600000006000000040000000600000006000000040000000700000006000000040000000700000006000000040000000800000006000000040000000800000006000000040000000900000006000000040000000900000006000000040000000A00000006000000040000000A00000006000000040000000B00000006000000040000000B00000006000000040000000C00000006000000040000000C00000006000000040000000D00000006000000040000000D00000006000000040000000E00000006000000040000000E00000006000000040000000F00000006000000040000000F00000006000000040000001000000006000000040000001000000006000000040000000000000007000000040000000000000007000000040000000100000007000000040000000100000007000000040000000200000007000000040000000200000007000000040000000300000007000000040000000300000007000000040000000400000007000000040000000400000007000000040000000500000007000000040000000500000007000000040000000600000007000000040000000600000007000000040000000700000007000000040000000700000007000000040000000800000007000000040000000800000007000000040000000900000007000000040000000900000007000000040000000A00000007000000040000000A00000007000000040000000B00000007000000040000000B00000007000000040000000C00000007000000040000000C00000007000000040000000D00000007000000040000000D00000007000000040000000E00000007000000040000000E00000007000000040000000F00000007000000040000000F00000007000000040000001000000007000000040000001000000007000000040000000000000008000000040000000000000008000000040000000100000008000000040000000100000008000000040000000200000008000000040000000200000008000000040000000300000008000000040000000300000008000000040000000400000008000000040000000400000008000000040000000500000008000000040000000500000008000000040000000600000008000000040000000600000008000000040000000700000008000000040000000700000008000000040000000800000008000000040000000800000008000000040000000900000008000000040000000900000008000000040000000A00000008000000040000000A00000008000000040000000B00000008000000040000000B00000008000000040000000C00000008000000040000000C00000008000000040000000D00000008000000040000000D00000008000000040000000E00000008000000040000000E00000008000000040000000F00000008000000040000000F00000008000000040000001000000008000000040000001000000008000000040000000000000009000000040000000000000009000000040000000100000009000000040000000100000009000000040000000200000009000000040000000200000009000000040000000300000009000000040000000300000009000000040000000400000009000000040000000400000009000000040000000500000009000000040000000500000009000000040000000600000009000000040000000600000009000000040000000700000009000000040000000700000009000000040000000800000009000000040000000800000009000000040000000900000009000000040000000900000009000000040000000A00000009000000040000000A00000009000000040000000B00000009000000040000000B00000009000000040000000C00000009000000040000000C00000009000000040000000D00000009000000040000000D00000009000000040000000E00000009000000040000000E00000009000000040000000F00000009000000040000000F0000000900000004000000100000000900000004000000100000000900000004000000000000000A00000004000000000000000A00000004000000010000000A00000004000000010000000A00000004000000020000000A00000004000000020000000A00000004000000030000000A00000004000000030000000A00000004000000040000000A00000004000000040000000A00000004000000050000000A00000004000000050000000A00000004000000060000000A00000004000000060000000A00000004000000070000000A00000004000000070000000A00000004000000080000000A00000004000000080000000A00000004000000090000000A00000004000000090000000A000000040000000A0000000A000000040000000A0000000A000000040000000B0000000A000000040000000B0000000A000000040000000C0000000A000000040000000C0000000A000000040000000D0000000A000000040000000D0000000A000000040000000E0000000A000000040000000E0000000A000000040000000F0000000A000000040000000F0000000A00000004000000100000000A00000004000000100000000A00000004000000000000000B00000004000000000000000B00000004000000010000000B00000004000000010000000B00000004000000020000000B00000004000000020000000B00000004000000030000000B00000004000000030000000B00000004000000040000000B00000004000000040000000B00000004000000050000000B00000004000000050000000B00000004000000060000000B00000004000000060000000B00000004000000070000000B00000004000000070000000B00000004000000080000000B00000004000000080000000B00000004000000090000000B00000004000000090000000B000000040000000A0000000B000000040000000A0000000B000000040000000B0000000B000000040000000B0000000B000000040000000C0000000B000000040000000C0000000B000000040000000D0000000B000000040000000D0000000B000000040000000E0000000B000000040000000E0000000B000000040000000F0000000B000000040000000F0000000B00000004000000100000000B00000004000000100000000B00000004000000000000000C00000004000000000000000C00000004000000010000000C00000004000000010000000C00000004000000020000000C00000004000000020000000C00000004000000030000000C00000004000000030000000C00000004000000040000000C00000004000000040000000C00000004000000050000000C00000004000000050000000C00000004000000060000000C00000004000000060000000C00000004000000070000000C00000004000000070000000C00000004000000080000000C00000004000000080000000C00000004000000090000000C00000004000000090000000C000000040000000A0000000C000000040000000A0000000C000000040000000B0000000C000000040000000B0000000C000000040000000C0000000C000000040000000C0000000C000000040000000D0000000C000000040000000D0000000C000000040000000E0000000C000000040000000E0000000C000000040000000F0000000C000000040000000F0000000C00000004000000100000000C00000004000000100000000C00000004000000000000000D00000004000000000000000D00000004000000010000000D00000004000000010000000D00000004000000020000000D00000004000000020000000D00000004000000030000000D00000004000000030000000D00000004000000040000000D00000004000000040000000D00000004000000050000000D00000004000000050000000D00000004000000060000000D00000004000000060000000D00000004000000070000000D00000004000000070000000D00000004000000080000000D00000004000000080000000D00000004000000090000000D00000004000000090000000D000000040000000A0000000D000000040000000A0000000D000000040000000B0000000D000000040000000B0000000D000000040000000C0000000D000000040000000C0000000D000000040000000D0000000D000000040000000D0000000D000000040000000E0000000D000000040000000E0000000D000000040000000F0000000D000000040000000F0000000D00000004000000100000000D00000004000000100000000D00000004000000000000000E00000004000000000000000E00000004000000010000000E00000004000000010000000E00000004000000020000000E00000004000000020000000E00000004000000030000000E00000004000000030000000E00000004000000040000000E00000004000000040000000E00000004000000050000000E00000004000000050000000E00000004000000060000000E00000004000000060000000E00000004000000070000000E00000004000000070000000E00000004000000080000000E00000004000000080000000E00000004000000090000000E00000004000000090000000E000000040000000A0000000E000000040000000A0000000E000000040000000B0000000E000000040000000B0000000E000000040000000C0000000E000000040000000C0000000E000000040000000D0000000E000000040000000D0000000E000000040000000E0000000E000000040000000E0000000E000000040000000F0000000E000000040000000F0000000E00000004000000100000000E00000004000000100000000E00000004000000000000000F00000004000000000000000F00000004000000010000000F00000004000000010000000F00000004000000020000000F00000004000000020000000F00000004000000030000000F00000004000000030000000F00000004000000040000000F00000004000000040000000F00000004000000050000000F00000004000000050000000F00000004000000060000000F00000004000000060000000F00000004000000070000000F00000004000000070000000F00000004000000080000000F00000004000000080000000F00000004000000090000000F00000004000000090000000F000000040000000A0000000F000000040000000A0000000F000000040000000B0000000F000000040000000B0000000F000000040000000C0000000F000000040000000C0000000F000000040000000D0000000F000000040000000D0000000F000000040000000E0000000F000000040000000E0000000F000000040000000F0000000F000000040000000F0000000F00000004000000100000000F00000004000000100000000F000000040000000000000010000000040000000000000010000000040000000100000010000000040000000100000010000000040000000200000010000000040000000200000010000000040000000300000010000000040000000300000010000000040000000400000010000000040000000400000010000000040000000500000010000000040000000500000010000000040000000600000010000000040000000600000010000000040000000700000010000000040000000700000010000000040000000800000010000000040000000800000010000000040000000900000010000000040000000900000010000000040000000A00000010000000040000000A00000010000000040000000B00000010000000040000000B00000010000000040000000C00000010000000040000000C00000010000000040000000D00000010000000040000000D00000010000000040000000E00000010000000040000000E00000010000000040000000F00000010000000040000000F00000010000000040000001000000010000000040000001000000010000000040000000000000000000000050000000000000000000000050000000100000000000000050000000100000000000000050000000200000000000000050000000200000000000000050000000300000000000000050000000300000000000000050000000400000000000000050000000400000000000000050000000500000000000000050000000500000000000000050000000600000000000000050000000600000000000000050000000700000000000000050000000700000000000000050000000800000000000000050000000800000000000000050000000900000000000000050000000900000000000000050000000A00000000000000050000000A00000000000000050000000B00000000000000050000000B00000000000000050000000C00000000000000050000000C00000000000000050000000D00000000000000050000000D00000000000000050000000E00000000000000050000000E00000000000000050000000F00000000000000050000000F00000000000000050000001000000000000000050000001000000000000000050000000000000001000000050000000000000001000000050000000100000001000000050000000100000001000000050000000200000001000000050000000200000001000000050000000300000001000000050000000300000001000000050000000400000001000000050000000400000001000000050000000500000001000000050000000500000001000000050000000600000001000000050000000600000001000000050000000700000001000000050000000700000001000000050000000800000001000000050000000800000001000000050000000900000001000000050000000900000001000000050000000A00000001000000050000000A00000001000000050000000B00000001000000050000000B00000001000000050000000C00000001000000050000000C00000001000000050000000D00000001000000050000000D00000001000000050000000E00000001000000050000000E00000001000000050000000F00000001000000050000000F00000001000000050000001000000001000000050000001000000001000000050000000000000002000000050000000000000002000000050000000100000002000000050000000100000002000000050000000200000002000000050000000200000002000000050000000300000002000000050000000300000002000000050000000400000002000000050000000400000002000000050000000500000002000000050000000500000002000000050000000600000002000000050000000600000002000000050000000700000002000000050000000700000002000000050000000800000002000000050000000800000002000000050000000900000002000000050000000900000002000000050000000A00000002000000050000000A00000002000000050000000B00000002000000050000000B00000002000000050000000C00000002000000050000000C00000002000000050000000D00000002000000050000000D00000002000000050000000E00000002000000050000000E00000002000000050000000F00000002000000050000000F00000002000000050000001000000002000000050000001000000002000000050000000000000003000000050000000000000003000000050000000100000003000000050000000100000003000000050000000200000003000000050000000200000003000000050000000300000003000000050000000300000003000000050000000400000003000000050000000400000003000000050000000500000003000000050000000500000003000000050000000600000003000000050000000600000003000000050000000700000003000000050000000700000003000000050000000800000003000000050000000800000003000000050000000900000003000000050000000900000003000000050000000A00000003000000050000000A00000003000000050000000B00000003000000050000000B00000003000000050000000C00000003000000050000000C00000003000000050000000D00000003000000050000000D00000003000000050000000E00000003000000050000000E00000003000000050000000F00000003000000050000000F00000003000000050000001000000003000000050000001000000003000000050000000000000004000000050000000000000004000000050000000100000004000000050000000100000004000000050000000200000004000000050000000200000004000000050000000300000004000000050000000300000004000000050000000400000004000000050000000400000004000000050000000500000004000000050000000500000004000000050000000600000004000000050000000600000004000000050000000700000004000000050000000700000004000000050000000800000004000000050000000800000004000000050000000900000004000000050000000900000004000000050000000A00000004000000050000000A00000004000000050000000B00000004000000050000000B00000004000000050000000C00000004000000050000000C00000004000000050000000D00000004000000050000000D00000004000000050000000E00000004000000050000000E00000004000000050000000F00000004000000050000000F00000004000000050000001000000004000000050000001000000004000000050000000000000005000000050000000000000005000000050000000100000005000000050000000100000005000000050000000200000005000000050000000200000005000000050000000300000005000000050000000300000005000000050000000400000005000000050000000400000005000000050000000500000005000000050000000500000005000000050000000600000005000000050000000600000005000000050000000700000005000000050000000700000005000000050000000800000005000000050000000800000005000000050000000900000005000000050000000900000005000000050000000A00000005000000050000000A00000005000000050000000B00000005000000050000000B00000005000000050000000C00000005000000050000000C00000005000000050000000D00000005000000050000000D00000005000000050000000E00000005000000050000000E00000005000000050000000F00000005000000050000000F00000005000000050000001000000005000000050000001000000005000000050000000000000006000000050000000000000006000000050000000100000006000000050000000100000006000000050000000200000006000000050000000200000006000000050000000300000006000000050000000300000006000000050000000400000006000000050000000400000006000000050000000500000006000000050000000500000006000000050000000600000006000000050000000600000006000000050000000700000006000000050000000700000006000000050000000800000006000000050000000800000006000000050000000900000006000000050000000900000006000000050000000A00000006000000050000000A00000006000000050000000B00000006000000050000000B00000006000000050000000C00000006000000050000000C00000006000000050000000D00000006000000050000000D00000006000000050000000E00000006000000050000000E00000006000000050000000F00000006000000050000000F00000006000000050000001000000006000000050000001000000006000000050000000000000007000000050000000000000007000000050000000100000007000000050000000100000007000000050000000200000007000000050000000200000007000000050000000300000007000000050000000300000007000000050000000400000007000000050000000400000007000000050000000500000007000000050000000500000007000000050000000600000007000000050000000600000007000000050000000700000007000000050000000700000007000000050000000800000007000000050000000800000007000000050000000900000007000000050000000900000007000000050000000A00000007000000050000000A00000007000000050000000B00000007000000050000000B00000007000000050000000C00000007000000050000000C00000007000000050000000D00000007000000050000000D00000007000000050000000E00000007000000050000000E00000007000000050000000F00000007000000050000000F00000007000000050000001000000007000000050000001000000007000000050000000000000008000000050000000000000008000000050000000100000008000000050000000100000008000000050000000200000008000000050000000200000008000000050000000300000008000000050000000300000008000000050000000400000008000000050000000400000008000000050000000500000008000000050000000500000008000000050000000600000008000000050000000600000008000000050000000700000008000000050000000700000008000000050000000800000008000000050000000800000008000000050000000900000008000000050000000900000008000000050000000A00000008000000050000000A00000008000000050000000B00000008000000050000000B00000008000000050000000C00000008000000050000000C00000008000000050000000D00000008000000050000000D00000008000000050000000E00000008000000050000000E00000008000000050000000F00000008000000050000000F00000008000000050000001000000008000000050000001000000008000000050000000000000009000000050000000000000009000000050000000100000009000000050000000100000009000000050000000200000009000000050000000200000009000000050000000300000009000000050000000300000009000000050000000400000009000000050000000400000009000000050000000500000009000000050000000500000009000000050000000600000009000000050000000600000009000000050000000700000009000000050000000700000009000000050000000800000009000000050000000800000009000000050000000900000009000000050000000900000009000000050000000A00000009000000050000000A00000009000000050000000B00000009000000050000000B00000009000000050000000C00000009000000050000000C00000009000000050000000D00000009000000050000000D00000009000000050000000E00000009000000050000000E00000009000000050000000F00000009000000050000000F0000000900000005000000100000000900000005000000100000000900000005000000000000000A00000005000000000000000A00000005000000010000000A00000005000000010000000A00000005000000020000000A00000005000000020000000A00000005000000030000000A00000005000000030000000A00000005000000040000000A00000005000000040000000A00000005000000050000000A00000005000000050000000A00000005000000060000000A00000005000000060000000A00000005000000070000000A00000005000000070000000A00000005000000080000000A00000005000000080000000A00000005000000090000000A00000005000000090000000A000000050000000A0000000A000000050000000A0000000A000000050000000B0000000A000000050000000B0000000A000000050000000C0000000A000000050000000C0000000A000000050000000D0000000A000000050000000D0000000A000000050000000E0000000A000000050000000E0000000A000000050000000F0000000A000000050000000F0000000A00000005000000100000000A00000005000000100000000A00000005000000000000000B00000005000000000000000B00000005000000010000000B00000005000000010000000B00000005000000020000000B00000005000000020000000B00000005000000030000000B00000005000000030000000B00000005000000040000000B00000005000000040000000B00000005000000050000000B00000005000000050000000B00000005000000060000000B00000005000000060000000B00000005000000070000000B00000005000000070000000B00000005000000080000000B00000005000000080000000B00000005000000090000000B00000005000000090000000B000000050000000A0000000B000000050000000A0000000B000000050000000B0000000B000000050000000B0000000B000000050000000C0000000B000000050000000C0000000B000000050000000D0000000B000000050000000D0000000B000000050000000E0000000B000000050000000E0000000B000000050000000F0000000B000000050000000F0000000B00000005000000100000000B00000005000000100000000B00000005000000000000000C00000005000000000000000C00000005000000010000000C00000005000000010000000C00000005000000020000000C00000005000000020000000C00000005000000030000000C00000005000000030000000C00000005000000040000000C00000005000000040000000C00000005000000050000000C00000005000000050000000C00000005000000060000000C00000005000000060000000C00000005000000070000000C00000005000000070000000C00000005000000080000000C00000005000000080000000C00000005000000090000000C00000005000000090000000C000000050000000A0000000C000000050000000A0000000C000000050000000B0000000C000000050000000B0000000C000000050000000C0000000C000000050000000C0000000C000000050000000D0000000C000000050000000D0000000C000000050000000E0000000C000000050000000E0000000C000000050000000F0000000C000000050000000F0000000C00000005000000100000000C00000005000000100000000C00000005000000000000000D00000005000000000000000D00000005000000010000000D00000005000000010000000D00000005000000020000000D00000005000000020000000D00000005000000030000000D00000005000000030000000D00000005000000040000000D00000005000000040000000D00000005000000050000000D00000005000000050000000D00000005000000060000000D00000005000000060000000D00000005000000070000000D00000005000000070000000D00000005000000080000000D00000005000000080000000D00000005000000090000000D00000005000000090000000D000000050000000A0000000D000000050000000A0000000D000000050000000B0000000D000000050000000B0000000D000000050000000C0000000D000000050000000C0000000D000000050000000D0000000D000000050000000D0000000D000000050000000E0000000D000000050000000E0000000D000000050000000F0000000D000000050000000F0000000D00000005000000100000000D00000005000000100000000D00000005000000000000000E00000005000000000000000E00000005000000010000000E00000005000000010000000E00000005000000020000000E00000005000000020000000E00000005000000030000000E00000005000000030000000E00000005000000040000000E00000005000000040000000E00000005000000050000000E00000005000000050000000E00000005000000060000000E00000005000000060000000E00000005000000070000000E00000005000000070000000E00000005000000080000000E00000005000000080000000E00000005000000090000000E00000005000000090000000E000000050000000A0000000E000000050000000A0000000E000000050000000B0000000E000000050000000B0000000E000000050000000C0000000E000000050000000C0000000E000000050000000D0000000E000000050000000D0000000E000000050000000E0000000E000000050000000E0000000E000000050000000F0000000E000000050000000F0000000E00000005000000100000000E00000005000000100000000E00000005000000000000000F00000005000000000000000F00000005000000010000000F00000005000000010000000F00000005000000020000000F00000005000000020000000F00000005000000030000000F00000005000000030000000F00000005000000040000000F00000005000000040000000F00000005000000050000000F00000005000000050000000F00000005000000060000000F00000005000000060000000F00000005000000070000000F00000005000000070000000F00000005000000080000000F00000005000000080000000F00000005000000090000000F00000005000000090000000F000000050000000A0000000F000000050000000A0000000F000000050000000B0000000F000000050000000B0000000F000000050000000C0000000F000000050000000C0000000F000000050000000D0000000F000000050000000D0000000F000000050000000E0000000F000000050000000E0000000F000000050000000F0000000F000000050000000F0000000F00000005000000100000000F00000005000000100000000F000000050000000000000010000000050000000000000010000000050000000100000010000000050000000100000010000000050000000200000010000000050000000200000010000000050000000300000010000000050000000300000010000000050000000400000010000000050000000400000010000000050000000500000010000000050000000500000010000000050000000600000010000000050000000600000010000000050000000700000010000000050000000700000010000000050000000800000010000000050000000800000010000000050000000900000010000000050000000900000010000000050000000A00000010000000050000000A00000010000000050000000B00000010000000050000000B00000010000000050000000C00000010000000050000000C00000010000000050000000D00000010000000050000000D00000010000000050000000E00000010000000050000000E00000010000000050000000F00000010000000050000000F00000010000000050000001000000010000000050000001000000010000000050000000000000000000000060000000000000000000000060000000100000000000000060000000100000000000000060000000200000000000000060000000200000000000000060000000300000000000000060000000300000000000000060000000400000000000000060000000400000000000000060000000500000000000000060000000500000000000000060000000600000000000000060000000600000000000000060000000700000000000000060000000700000000000000060000000800000000000000060000000800000000000000060000000900000000000000060000000900000000000000060000000A00000000000000060000000A00000000000000060000000B00000000000000060000000B00000000000000060000000C00000000000000060000000C00000000000000060000000D00000000000000060000000D00000000000000060000000E00000000000000060000000E00000000000000060000000F00000000000000060000000F00000000000000060000001000000000000000060000001000000000000000060000000000000001000000060000000000000001000000060000000100000001000000060000000100000001000000060000000200000001000000060000000200000001000000060000000300000001000000060000000300000001000000060000000400000001000000060000000400000001000000060000000500000001000000060000000500000001000000060000000600000001000000060000000600000001000000060000000700000001000000060000000700000001000000060000000800000001000000060000000800000001000000060000000900000001000000060000000900000001000000060000000A00000001000000060000000A00000001000000060000000B00000001000000060000000B00000001000000060000000C00000001000000060000000C00000001000000060000000D00000001000000060000000D00000001000000060000000E00000001000000060000000E00000001000000060000000F00000001000000060000000F00000001000000060000001000000001000000060000001000000001000000060000000000000002000000060000000000000002000000060000000100000002000000060000000100000002000000060000000200000002000000060000000200000002000000060000000300000002000000060000000300000002000000060000000400000002000000060000000400000002000000060000000500000002000000060000000500000002000000060000000600000002000000060000000600000002000000060000000700000002000000060000000700000002000000060000000800000002000000060000000800000002000000060000000900000002000000060000000900000002000000060000000A00000002000000060000000A00000002000000060000000B00000002000000060000000B00000002000000060000000C00000002000000060000000C00000002000000060000000D00000002000000060000000D00000002000000060000000E00000002000000060000000E00000002000000060000000F00000002000000060000000F00000002000000060000001000000002000000060000001000000002000000060000000000000003000000060000000000000003000000060000000100000003000000060000000100000003000000060000000200000003000000060000000200000003000000060000000300000003000000060000000300000003000000060000000400000003000000060000000400000003000000060000000500000003000000060000000500000003000000060000000600000003000000060000000600000003000000060000000700000003000000060000000700000003000000060000000800000003000000060000000800000003000000060000000900000003000000060000000900000003000000060000000A00000003000000060000000A00000003000000060000000B00000003000000060000000B00000003000000060000000C00000003000000060000000C00000003000000060000000D00000003000000060000000D00000003000000060000000E00000003000000060000000E00000003000000060000000F00000003000000060000000F00000003000000060000001000000003000000060000001000000003000000060000000000000004000000060000000000000004000000060000000100000004000000060000000100000004000000060000000200000004000000060000000200000004000000060000000300000004000000060000000300000004000000060000000400000004000000060000000400000004000000060000000500000004000000060000000500000004000000060000000600000004000000060000000600000004000000060000000700000004000000060000000700000004000000060000000800000004000000060000000800000004000000060000000900000004000000060000000900000004000000060000000A00000004000000060000000A00000004000000060000000B00000004000000060000000B00000004000000060000000C00000004000000060000000C00000004000000060000000D00000004000000060000000D00000004000000060000000E00000004000000060000000E00000004000000060000000F00000004000000060000000F00000004000000060000001000000004000000060000001000000004000000060000000000000005000000060000000000000005000000060000000100000005000000060000000100000005000000060000000200000005000000060000000200000005000000060000000300000005000000060000000300000005000000060000000400000005000000060000000400000005000000060000000500000005000000060000000500000005000000060000000600000005000000060000000600000005000000060000000700000005000000060000000700000005000000060000000800000005000000060000000800000005000000060000000900000005000000060000000900000005000000060000000A00000005000000060000000A00000005000000060000000B00000005000000060000000B00000005000000060000000C00000005000000060000000C00000005000000060000000D00000005000000060000000D00000005000000060000000E00000005000000060000000E00000005000000060000000F00000005000000060000000F00000005000000060000001000000005000000060000001000000005000000060000000000000006000000060000000000000006000000060000000100000006000000060000000100000006000000060000000200000006000000060000000200000006000000060000000300000006000000060000000300000006000000060000000400000006000000060000000400000006000000060000000500000006000000060000000500000006000000060000000600000006000000060000000600000006000000060000000700000006000000060000000700000006000000060000000800000006000000060000000800000006000000060000000900000006000000060000000900000006000000060000000A00000006000000060000000A00000006000000060000000B00000006000000060000000B00000006000000060000000C00000006000000060000000C00000006000000060000000D00000006000000060000000D00000006000000060000000E00000006000000060000000E00000006000000060000000F00000006000000060000000F00000006000000060000001000000006000000060000001000000006000000060000000000000007000000060000000000000007000000060000000100000007000000060000000100000007000000060000000200000007000000060000000200000007000000060000000300000007000000060000000300000007000000060000000400000007000000060000000400000007000000060000000500000007000000060000000500000007000000060000000600000007000000060000000600000007000000060000000700000007000000060000000700000007000000060000000800000007000000060000000800000007000000060000000900000007000000060000000900000007000000060000000A00000007000000060000000A00000007000000060000000B00000007000000060000000B00000007000000060000000C00000007000000060000000C00000007000000060000000D00000007000000060000000D00000007000000060000000E00000007000000060000000E00000007000000060000000F00000007000000060000000F00000007000000060000001000000007000000060000001000000007000000060000000000000008000000060000000000000008000000060000000100000008000000060000000100000008000000060000000200000008000000060000000200000008000000060000000300000008000000060000000300000008000000060000000400000008000000060000000400000008000000060000000500000008000000060000000500000008000000060000000600000008000000060000000600000008000000060000000700000008000000060000000700000008000000060000000800000008000000060000000800000008000000060000000900000008000000060000000900000008000000060000000A00000008000000060000000A00000008000000060000000B00000008000000060000000B00000008000000060000000C00000008000000060000000C00000008000000060000000D00000008000000060000000D00000008000000060000000E00000008000000060000000E00000008000000060000000F00000008000000060000000F00000008000000060000001000000008000000060000001000000008000000060000000000000009000000060000000000000009000000060000000100000009000000060000000100000009000000060000000200000009000000060000000200000009000000060000000300000009000000060000000300000009000000060000000400000009000000060000000400000009000000060000000500000009000000060000000500000009000000060000000600000009000000060000000600000009000000060000000700000009000000060000000700000009000000060000000800000009000000060000000800000009000000060000000900000009000000060000000900000009000000060000000A00000009000000060000000A00000009000000060000000B00000009000000060000000B00000009000000060000000C00000009000000060000000C00000009000000060000000D00000009000000060000000D00000009000000060000000E00000009000000060000000E00000009000000060000000F00000009000000060000000F0000000900000006000000100000000900000006000000100000000900000006000000000000000A00000006000000000000000A00000006000000010000000A00000006000000010000000A00000006000000020000000A00000006000000020000000A00000006000000030000000A00000006000000030000000A00000006000000040000000A00000006000000040000000A00000006000000050000000A00000006000000050000000A00000006000000060000000A00000006000000060000000A00000006000000070000000A00000006000000070000000A00000006000000080000000A00000006000000080000000A00000006000000090000000A00000006000000090000000A000000060000000A0000000A000000060000000A0000000A000000060000000B0000000A000000060000000B0000000A000000060000000C0000000A000000060000000C0000000A000000060000000D0000000A000000060000000D0000000A000000060000000E0000000A000000060000000E0000000A000000060000000F0000000A000000060000000F0000000A00000006000000100000000A00000006000000100000000A00000006000000000000000B00000006000000000000000B00000006000000010000000B00000006000000010000000B00000006000000020000000B00000006000000020000000B00000006000000030000000B00000006000000030000000B00000006000000040000000B00000006000000040000000B00000006000000050000000B00000006000000050000000B00000006000000060000000B00000006000000060000000B00000006000000070000000B00000006000000070000000B00000006000000080000000B00000006000000080000000B00000006000000090000000B00000006000000090000000B000000060000000A0000000B000000060000000A0000000B000000060000000B0000000B000000060000000B0000000B000000060000000C0000000B000000060000000C0000000B000000060000000D0000000B000000060000000D0000000B000000060000000E0000000B000000060000000E0000000B000000060000000F0000000B000000060000000F0000000B00000006000000100000000B00000006000000100000000B00000006000000000000000C00000006000000000000000C00000006000000010000000C00000006000000010000000C00000006000000020000000C00000006000000020000000C00000006000000030000000C00000006000000030000000C00000006000000040000000C00000006000000040000000C00000006000000050000000C00000006000000050000000C00000006000000060000000C00000006000000060000000C00000006000000070000000C00000006000000070000000C00000006000000080000000C00000006000000080000000C00000006000000090000000C00000006000000090000000C000000060000000A0000000C000000060000000A0000000C000000060000000B0000000C000000060000000B0000000C000000060000000C0000000C000000060000000C0000000C000000060000000D0000000C000000060000000D0000000C000000060000000E0000000C000000060000000E0000000C000000060000000F0000000C000000060000000F0000000C00000006000000100000000C00000006000000100000000C00000006000000000000000D00000006000000000000000D00000006000000010000000D00000006000000010000000D00000006000000020000000D00000006000000020000000D00000006000000030000000D00000006000000030000000D00000006000000040000000D00000006000000040000000D00000006000000050000000D00000006000000050000000D00000006000000060000000D00000006000000060000000D00000006000000070000000D00000006000000070000000D00000006000000080000000D00000006000000080000000D00000006000000090000000D00000006000000090000000D000000060000000A0000000D000000060000000A0000000D000000060000000B0000000D000000060000000B0000000D000000060000000C0000000D000000060000000C0000000D000000060000000D0000000D000000060000000D0000000D000000060000000E0000000D000000060000000E0000000D000000060000000F0000000D000000060000000F0000000D00000006000000100000000D00000006000000100000000D00000006000000000000000E00000006000000000000000E00000006000000010000000E00000006000000010000000E00000006000000020000000E00000006000000020000000E00000006000000030000000E00000006000000030000000E00000006000000040000000E00000006000000040000000E00000006000000050000000E00000006000000050000000E00000006000000060000000E00000006000000060000000E00000006000000070000000E00000006000000070000000E00000006000000080000000E00000006000000080000000E00000006000000090000000E00000006000000090000000E000000060000000A0000000E000000060000000A0000000E000000060000000B0000000E000000060000000B0000000E000000060000000C0000000E000000060000000C0000000E000000060000000D0000000E000000060000000D0000000E000000060000000E0000000E000000060000000E0000000E000000060000000F0000000E000000060000000F0000000E00000006000000100000000E00000006000000100000000E00000006000000000000000F00000006000000000000000F00000006000000010000000F00000006000000010000000F00000006000000020000000F00000006000000020000000F00000006000000030000000F00000006000000030000000F00000006000000040000000F00000006000000040000000F00000006000000050000000F00000006000000050000000F00000006000000060000000F00000006000000060000000F00000006000000070000000F00000006000000070000000F00000006000000080000000F00000006000000080000000F00000006000000090000000F00000006000000090000000F000000060000000A0000000F000000060000000A0000000F000000060000000B0000000F000000060000000B0000000F000000060000000C0000000F000000060000000C0000000F000000060000000D0000000F000000060000000D0000000F000000060000000E0000000F000000060000000E0000000F000000060000000F0000000F000000060000000F0000000F00000006000000100000000F00000006000000100000000F000000060000000000000010000000060000000000000010000000060000000100000010000000060000000100000010000000060000000200000010000000060000000200000010000000060000000300000010000000060000000300000010000000060000000400000010000000060000000400000010000000060000000500000010000000060000000500000010000000060000000600000010000000060000000600000010000000060000000700000010000000060000000700000010000000060000000800000010000000060000000800000010000000060000000900000010000000060000000900000010000000060000000A00000010000000060000000A00000010000000060000000B00000010000000060000000B00000010000000060000000C00000010000000060000000C00000010000000060000000D00000010000000060000000D00000010000000060000000E00000010000000060000000E00000010000000060000000F00000010000000060000000F00000010000000060000001000000010000000060000001000000010000000060000000000000000000000070000000000000000000000070000000100000000000000070000000100000000000000070000000200000000000000070000000200000000000000070000000300000000000000070000000300000000000000070000000400000000000000070000000400000000000000070000000500000000000000070000000500000000000000070000000600000000000000070000000600000000000000070000000700000000000000070000000700000000000000070000000800000000000000070000000800000000000000070000000900000000000000070000000900000000000000070000000A00000000000000070000000A00000000000000070000000B00000000000000070000000B00000000000000070000000C00000000000000070000000C00000000000000070000000D00000000000000070000000D00000000000000070000000E00000000000000070000000E00000000000000070000000F00000000000000070000000F00000000000000070000001000000000000000070000001000000000000000070000000000000001000000070000000000000001000000070000000100000001000000070000000100000001000000070000000200000001000000070000000200000001000000070000000300000001000000070000000300000001000000070000000400000001000000070000000400000001000000070000000500000001000000070000000500000001000000070000000600000001000000070000000600000001000000070000000700000001000000070000000700000001000000070000000800000001000000070000000800000001000000070000000900000001000000070000000900000001000000070000000A00000001000000070000000A00000001000000070000000B00000001000000070000000B00000001000000070000000C00000001000000070000000C00000001000000070000000D00000001000000070000000D00000001000000070000000E00000001000000070000000E00000001000000070000000F00000001000000070000000F00000001000000070000001000000001000000070000001000000001000000070000000000000002000000070000000000000002000000070000000100000002000000070000000100000002000000070000000200000002000000070000000200000002000000070000000300000002000000070000000300000002000000070000000400000002000000070000000400000002000000070000000500000002000000070000000500000002000000070000000600000002000000070000000600000002000000070000000700000002000000070000000700000002000000070000000800000002000000070000000800000002000000070000000900000002000000070000000900000002000000070000000A00000002000000070000000A00000002000000070000000B00000002000000070000000B00000002000000070000000C00000002000000070000000C00000002000000070000000D00000002000000070000000D00000002000000070000000E00000002000000070000000E00000002000000070000000F00000002000000070000000F00000002000000070000001000000002000000070000001000000002000000070000000000000003000000070000000000000003000000070000000100000003000000070000000100000003000000070000000200000003000000070000000200000003000000070000000300000003000000070000000300000003000000070000000400000003000000070000000400000003000000070000000500000003000000070000000500000003000000070000000600000003000000070000000600000003000000070000000700000003000000070000000700000003000000070000000800000003000000070000000800000003000000070000000900000003000000070000000900000003000000070000000A00000003000000070000000A00000003000000070000000B00000003000000070000000B00000003000000070000000C00000003000000070000000C00000003000000070000000D00000003000000070000000D00000003000000070000000E00000003000000070000000E00000003000000070000000F00000003000000070000000F00000003000000070000001000000003000000070000001000000003000000070000000000000004000000070000000000000004000000070000000100000004000000070000000100000004000000070000000200000004000000070000000200000004000000070000000300000004000000070000000300000004000000070000000400000004000000070000000400000004000000070000000500000004000000070000000500000004000000070000000600000004000000070000000600000004000000070000000700000004000000070000000700000004000000070000000800000004000000070000000800000004000000070000000900000004000000070000000900000004000000070000000A00000004000000070000000A00000004000000070000000B00000004000000070000000B00000004000000070000000C00000004000000070000000C00000004000000070000000D00000004000000070000000D00000004000000070000000E00000004000000070000000E00000004000000070000000F00000004000000070000000F00000004000000070000001000000004000000070000001000000004000000070000000000000005000000070000000000000005000000070000000100000005000000070000000100000005000000070000000200000005000000070000000200000005000000070000000300000005000000070000000300000005000000070000000400000005000000070000000400000005000000070000000500000005000000070000000500000005000000070000000600000005000000070000000600000005000000070000000700000005000000070000000700000005000000070000000800000005000000070000000800000005000000070000000900000005000000070000000900000005000000070000000A00000005000000070000000A00000005000000070000000B00000005000000070000000B00000005000000070000000C00000005000000070000000C00000005000000070000000D00000005000000070000000D00000005000000070000000E00000005000000070000000E00000005000000070000000F00000005000000070000000F00000005000000070000001000000005000000070000001000000005000000070000000000000006000000070000000000000006000000070000000100000006000000070000000100000006000000070000000200000006000000070000000200000006000000070000000300000006000000070000000300000006000000070000000400000006000000070000000400000006000000070000000500000006000000070000000500000006000000070000000600000006000000070000000600000006000000070000000700000006000000070000000700000006000000070000000800000006000000070000000800000006000000070000000900000006000000070000000900000006000000070000000A00000006000000070000000A00000006000000070000000B00000006000000070000000B00000006000000070000000C00000006000000070000000C00000006000000070000000D00000006000000070000000D00000006000000070000000E00000006000000070000000E00000006000000070000000F00000006000000070000000F00000006000000070000001000000006000000070000001000000006000000070000000000000007000000070000000000000007000000070000000100000007000000070000000100000007000000070000000200000007000000070000000200000007000000070000000300000007000000070000000300000007000000070000000400000007000000070000000400000007000000070000000500000007000000070000000500000007000000070000000600000007000000070000000600000007000000070000000700000007000000070000000700000007000000070000000800000007000000070000000800000007000000070000000900000007000000070000000900000007000000070000000A00000007000000070000000A00000007000000070000000B00000007000000070000000B00000007000000070000000C00000007000000070000000C00000007000000070000000D00000007000000070000000D00000007000000070000000E00000007000000070000000E00000007000000070000000F00000007000000070000000F00000007000000070000001000000007000000070000001000000007000000070000000000000008000000070000000000000008000000070000000100000008000000070000000100000008000000070000000200000008000000070000000200000008000000070000000300000008000000070000000300000008000000070000000400000008000000070000000400000008000000070000000500000008000000070000000500000008000000070000000600000008000000070000000600000008000000070000000700000008000000070000000700000008000000070000000800000008000000070000000800000008000000070000000900000008000000070000000900000008000000070000000A00000008000000070000000A00000008000000070000000B00000008000000070000000B00000008000000070000000C00000008000000070000000C00000008000000070000000D00000008000000070000000D00000008000000070000000E00000008000000070000000E00000008000000070000000F00000008000000070000000F00000008000000070000001000000008000000070000001000000008000000070000000000000009000000070000000000000009000000070000000100000009000000070000000100000009000000070000000200000009000000070000000200000009000000070000000300000009000000070000000300000009000000070000000400000009000000070000000400000009000000070000000500000009000000070000000500000009000000070000000600000009000000070000000600000009000000070000000700000009000000070000000700000009000000070000000800000009000000070000000800000009000000070000000900000009000000070000000900000009000000070000000A00000009000000070000000A00000009000000070000000B00000009000000070000000B00000009000000070000000C00000009000000070000000C00000009000000070000000D00000009000000070000000D00000009000000070000000E00000009000000070000000E00000009000000070000000F00000009000000070000000F0000000900000007000000100000000900000007000000100000000900000007000000000000000A00000007000000000000000A00000007000000010000000A00000007000000010000000A00000007000000020000000A00000007000000020000000A00000007000000030000000A00000007000000030000000A00000007000000040000000A00000007000000040000000A00000007000000050000000A00000007000000050000000A00000007000000060000000A00000007000000060000000A00000007000000070000000A00000007000000070000000A00000007000000080000000A00000007000000080000000A00000007000000090000000A00000007000000090000000A000000070000000A0000000A000000070000000A0000000A000000070000000B0000000A000000070000000B0000000A000000070000000C0000000A000000070000000C0000000A000000070000000D0000000A000000070000000D0000000A000000070000000E0000000A000000070000000E0000000A000000070000000F0000000A000000070000000F0000000A00000007000000100000000A00000007000000100000000A00000007000000000000000B00000007000000000000000B00000007000000010000000B00000007000000010000000B00000007000000020000000B00000007000000020000000B00000007000000030000000B00000007000000030000000B00000007000000040000000B00000007000000040000000B00000007000000050000000B00000007000000050000000B00000007000000060000000B00000007000000060000000B00000007000000070000000B00000007000000070000000B00000007000000080000000B00000007000000080000000B00000007000000090000000B00000007000000090000000B000000070000000A0000000B000000070000000A0000000B000000070000000B0000000B000000070000000B0000000B000000070000000C0000000B000000070000000C0000000B000000070000000D0000000B000000070000000D0000000B000000070000000E0000000B000000070000000E0000000B000000070000000F0000000B000000070000000F0000000B00000007000000100000000B00000007000000100000000B00000007000000000000000C00000007000000000000000C00000007000000010000000C00000007000000010000000C00000007000000020000000C00000007000000020000000C00000007000000030000000C00000007000000030000000C00000007000000040000000C00000007000000040000000C00000007000000050000000C00000007000000050000000C00000007000000060000000C00000007000000060000000C00000007000000070000000C00000007000000070000000C00000007000000080000000C00000007000000080000000C00000007000000090000000C00000007000000090000000C000000070000000A0000000C000000070000000A0000000C000000070000000B0000000C000000070000000B0000000C000000070000000C0000000C000000070000000C0000000C000000070000000D0000000C000000070000000D0000000C000000070000000E0000000C000000070000000E0000000C000000070000000F0000000C000000070000000F0000000C00000007000000100000000C00000007000000100000000C00000007000000000000000D00000007000000000000000D00000007000000010000000D00000007000000010000000D00000007000000020000000D00000007000000020000000D00000007000000030000000D00000007000000030000000D00000007000000040000000D00000007000000040000000D00000007000000050000000D00000007000000050000000D00000007000000060000000D00000007000000060000000D00000007000000070000000D00000007000000070000000D00000007000000080000000D00000007000000080000000D00000007000000090000000D00000007000000090000000D000000070000000A0000000D000000070000000A0000000D000000070000000B0000000D000000070000000B0000000D000000070000000C0000000D000000070000000C0000000D000000070000000D0000000D000000070000000D0000000D000000070000000E0000000D000000070000000E0000000D000000070000000F0000000D000000070000000F0000000D00000007000000100000000D00000007000000100000000D00000007000000000000000E00000007000000000000000E00000007000000010000000E00000007000000010000000E00000007000000020000000E00000007000000020000000E00000007000000030000000E00000007000000030000000E00000007000000040000000E00000007000000040000000E00000007000000050000000E00000007000000050000000E00000007000000060000000E00000007000000060000000E00000007000000070000000E00000007000000070000000E00000007000000080000000E00000007000000080000000E00000007000000090000000E00000007000000090000000E000000070000000A0000000E000000070000000A0000000E000000070000000B0000000E000000070000000B0000000E000000070000000C0000000E000000070000000C0000000E000000070000000D0000000E000000070000000D0000000E000000070000000E0000000E000000070000000E0000000E000000070000000F0000000E000000070000000F0000000E00000007000000100000000E00000007000000100000000E00000007000000000000000F00000007000000000000000F00000007000000010000000F00000007000000010000000F00000007000000020000000F00000007000000020000000F00000007000000030000000F00000007000000030000000F00000007000000040000000F00000007000000040000000F00000007000000050000000F00000007000000050000000F00000007000000060000000F00000007000000060000000F00000007000000070000000F00000007000000070000000F00000007000000080000000F00000007000000080000000F00000007000000090000000F00000007000000090000000F000000070000000A0000000F000000070000000A0000000F000000070000000B0000000F000000070000000B0000000F000000070000000C0000000F000000070000000C0000000F000000070000000D0000000F000000070000000D0000000F000000070000000E0000000F000000070000000E0000000F000000070000000F0000000F000000070000000F0000000F00000007000000100000000F00000007000000100000000F000000070000000000000010000000070000000000000010000000070000000100000010000000070000000100000010000000070000000200000010000000070000000200000010000000070000000300000010000000070000000300000010000000070000000400000010000000070000000400000010000000070000000500000010000000070000000500000010000000070000000600000010000000070000000600000010000000070000000700000010000000070000000700000010000000070000000800000010000000070000000800000010000000070000000900000010000000070000000900000010000000070000000A00000010000000070000000A00000010000000070000000B00000010000000070000000B00000010000000070000000C00000010000000070000000C00000010000000070000000D00000010000000070000000D00000010000000070000000E00000010000000070000000E00000010000000070000000F00000010000000070000000F00000010000000070000001000000010000000070000001000000010000000070000000000000000000000080000000000000000000000080000000100000000000000080000000100000000000000080000000200000000000000080000000200000000000000080000000300000000000000080000000300000000000000080000000400000000000000080000000400000000000000080000000500000000000000080000000500000000000000080000000600000000000000080000000600000000000000080000000700000000000000080000000700000000000000080000000800000000000000080000000800000000000000080000000900000000000000080000000900000000000000080000000A00000000000000080000000A00000000000000080000000B00000000000000080000000B00000000000000080000000C00000000000000080000000C00000000000000080000000D00000000000000080000000D00000000000000080000000E00000000000000080000000E00000000000000080000000F00000000000000080000000F00000000000000080000001000000000000000080000001000000000000000080000000000000001000000080000000000000001000000080000000100000001000000080000000100000001000000080000000200000001000000080000000200000001000000080000000300000001000000080000000300000001000000080000000400000001000000080000000400000001000000080000000500000001000000080000000500000001000000080000000600000001000000080000000600000001000000080000000700000001000000080000000700000001000000080000000800000001000000080000000800000001000000080000000900000001000000080000000900000001000000080000000A00000001000000080000000A00000001000000080000000B00000001000000080000000B00000001000000080000000C00000001000000080000000C00000001000000080000000D00000001000000080000000D00000001000000080000000E00000001000000080000000E00000001000000080000000F00000001000000080000000F00000001000000080000001000000001000000080000001000000001000000080000000000000002000000080000000000000002000000080000000100000002000000080000000100000002000000080000000200000002000000080000000200000002000000080000000300000002000000080000000300000002000000080000000400000002000000080000000400000002000000080000000500000002000000080000000500000002000000080000000600000002000000080000000600000002000000080000000700000002000000080000000700000002000000080000000800000002000000080000000800000002000000080000000900000002000000080000000900000002000000080000000A00000002000000080000000A00000002000000080000000B00000002000000080000000B00000002000000080000000C00000002000000080000000C00000002000000080000000D00000002000000080000000D00000002000000080000000E00000002000000080000000E00000002000000080000000F00000002000000080000000F00000002000000080000001000000002000000080000001000000002000000080000000000000003000000080000000000000003000000080000000100000003000000080000000100000003000000080000000200000003000000080000000200000003000000080000000300000003000000080000000300000003000000080000000400000003000000080000000400000003000000080000000500000003000000080000000500000003000000080000000600000003000000080000000600000003000000080000000700000003000000080000000700000003000000080000000800000003000000080000000800000003000000080000000900000003000000080000000900000003000000080000000A00000003000000080000000A00000003000000080000000B00000003000000080000000B00000003000000080000000C00000003000000080000000C00000003000000080000000D00000003000000080000000D00000003000000080000000E00000003000000080000000E00000003000000080000000F00000003000000080000000F00000003000000080000001000000003000000080000001000000003000000080000000000000004000000080000000000000004000000080000000100000004000000080000000100000004000000080000000200000004000000080000000200000004000000080000000300000004000000080000000300000004000000080000000400000004000000080000000400000004000000080000000500000004000000080000000500000004000000080000000600000004000000080000000600000004000000080000000700000004000000080000000700000004000000080000000800000004000000080000000800000004000000080000000900000004000000080000000900000004000000080000000A00000004000000080000000A00000004000000080000000B00000004000000080000000B00000004000000080000000C00000004000000080000000C00000004000000080000000D00000004000000080000000D00000004000000080000000E00000004000000080000000E00000004000000080000000F00000004000000080000000F00000004000000080000001000000004000000080000001000000004000000080000000000000005000000080000000000000005000000080000000100000005000000080000000100000005000000080000000200000005000000080000000200000005000000080000000300000005000000080000000300000005000000080000000400000005000000080000000400000005000000080000000500000005000000080000000500000005000000080000000600000005000000080000000600000005000000080000000700000005000000080000000700000005000000080000000800000005000000080000000800000005000000080000000900000005000000080000000900000005000000080000000A00000005000000080000000A00000005000000080000000B00000005000000080000000B00000005000000080000000C00000005000000080000000C00000005000000080000000D00000005000000080000000D00000005000000080000000E00000005000000080000000E00000005000000080000000F00000005000000080000000F00000005000000080000001000000005000000080000001000000005000000080000000000000006000000080000000000000006000000080000000100000006000000080000000100000006000000080000000200000006000000080000000200000006000000080000000300000006000000080000000300000006000000080000000400000006000000080000000400000006000000080000000500000006000000080000000500000006000000080000000600000006000000080000000600000006000000080000000700000006000000080000000700000006000000080000000800000006000000080000000800000006000000080000000900000006000000080000000900000006000000080000000A00000006000000080000000A00000006000000080000000B00000006000000080000000B00000006000000080000000C00000006000000080000000C00000006000000080000000D00000006000000080000000D00000006000000080000000E00000006000000080000000E00000006000000080000000F00000006000000080000000F00000006000000080000001000000006000000080000001000000006000000080000000000000007000000080000000000000007000000080000000100000007000000080000000100000007000000080000000200000007000000080000000200000007000000080000000300000007000000080000000300000007000000080000000400000007000000080000000400000007000000080000000500000007000000080000000500000007000000080000000600000007000000080000000600000007000000080000000700000007000000080000000700000007000000080000000800000007000000080000000800000007000000080000000900000007000000080000000900000007000000080000000A00000007000000080000000A00000007000000080000000B00000007000000080000000B00000007000000080000000C00000007000000080000000C00000007000000080000000D00000007000000080000000D00000007000000080000000E00000007000000080000000E00000007000000080000000F00000007000000080000000F00000007000000080000001000000007000000080000001000000007000000080000000000000008000000080000000000000008000000080000000100000008000000080000000100000008000000080000000200000008000000080000000200000008000000080000000300000008000000080000000300000008000000080000000400000008000000080000000400000008000000080000000500000008000000080000000500000008000000080000000600000008000000080000000600000008000000080000000700000008000000080000000700000008000000080000000800000008000000080000000800000008000000080000000900000008000000080000000900000008000000080000000A00000008000000080000000A00000008000000080000000B00000008000000080000000B00000008000000080000000C00000008000000080000000C00000008000000080000000D00000008000000080000000D00000008000000080000000E00000008000000080000000E00000008000000080000000F00000008000000080000000F00000008000000080000001000000008000000080000001000000008000000080000000000000009000000080000000000000009000000080000000100000009000000080000000100000009000000080000000200000009000000080000000200000009000000080000000300000009000000080000000300000009000000080000000400000009000000080000000400000009000000080000000500000009000000080000000500000009000000080000000600000009000000080000000600000009000000080000000700000009000000080000000700000009000000080000000800000009000000080000000800000009000000080000000900000009000000080000000900000009000000080000000A00000009000000080000000A00000009000000080000000B00000009000000080000000B00000009000000080000000C00000009000000080000000C00000009000000080000000D00000009000000080000000D00000009000000080000000E00000009000000080000000E00000009000000080000000F00000009000000080000000F0000000900000008000000100000000900000008000000100000000900000008000000000000000A00000008000000000000000A00000008000000010000000A00000008000000010000000A00000008000000020000000A00000008000000020000000A00000008000000030000000A00000008000000030000000A00000008000000040000000A00000008000000040000000A00000008000000050000000A00000008000000050000000A00000008000000060000000A00000008000000060000000A00000008000000070000000A00000008000000070000000A00000008000000080000000A00000008000000080000000A00000008000000090000000A00000008000000090000000A000000080000000A0000000A000000080000000A0000000A000000080000000B0000000A000000080000000B0000000A000000080000000C0000000A000000080000000C0000000A000000080000000D0000000A000000080000000D0000000A000000080000000E0000000A000000080000000E0000000A000000080000000F0000000A000000080000000F0000000A00000008000000100000000A00000008000000100000000A00000008000000000000000B00000008000000000000000B00000008000000010000000B00000008000000010000000B00000008000000020000000B00000008000000020000000B00000008000000030000000B00000008000000030000000B00000008000000040000000B00000008000000040000000B00000008000000050000000B00000008000000050000000B00000008000000060000000B00000008000000060000000B00000008000000070000000B00000008000000070000000B00000008000000080000000B00000008000000080000000B00000008000000090000000B00000008000000090000000B000000080000000A0000000B000000080000000A0000000B000000080000000B0000000B000000080000000B0000000B000000080000000C0000000B000000080000000C0000000B000000080000000D0000000B000000080000000D0000000B000000080000000E0000000B000000080000000E0000000B000000080000000F0000000B000000080000000F0000000B00000008000000100000000B00000008000000100000000B00000008000000000000000C00000008000000000000000C00000008000000010000000C00000008000000010000000C00000008000000020000000C00000008000000020000000C00000008000000030000000C00000008000000030000000C00000008000000040000000C00000008000000040000000C00000008000000050000000C00000008000000050000000C00000008000000060000000C00000008000000060000000C00000008000000070000000C00000008000000070000000C00000008000000080000000C00000008000000080000000C00000008000000090000000C00000008000000090000000C000000080000000A0000000C000000080000000A0000000C000000080000000B0000000C000000080000000B0000000C000000080000000C0000000C000000080000000C0000000C000000080000000D0000000C000000080000000D0000000C000000080000000E0000000C000000080000000E0000000C000000080000000F0000000C000000080000000F0000000C00000008000000100000000C00000008000000100000000C00000008000000000000000D00000008000000000000000D00000008000000010000000D00000008000000010000000D00000008000000020000000D00000008000000020000000D00000008000000030000000D00000008000000030000000D00000008000000040000000D00000008000000040000000D00000008000000050000000D00000008000000050000000D00000008000000060000000D00000008000000060000000D00000008000000070000000D00000008000000070000000D00000008000000080000000D00000008000000080000000D00000008000000090000000D00000008000000090000000D000000080000000A0000000D000000080000000A0000000D000000080000000B0000000D000000080000000B0000000D000000080000000C0000000D000000080000000C0000000D000000080000000D0000000D000000080000000D0000000D000000080000000E0000000D000000080000000E0000000D000000080000000F0000000D000000080000000F0000000D00000008000000100000000D00000008000000100000000D00000008000000000000000E00000008000000000000000E00000008000000010000000E00000008000000010000000E00000008000000020000000E00000008000000020000000E00000008000000030000000E00000008000000030000000E00000008000000040000000E00000008000000040000000E00000008000000050000000E00000008000000050000000E00000008000000060000000E00000008000000060000000E00000008000000070000000E00000008000000070000000E00000008000000080000000E00000008000000080000000E00000008000000090000000E00000008000000090000000E000000080000000A0000000E000000080000000A0000000E000000080000000B0000000E000000080000000B0000000E000000080000000C0000000E000000080000000C0000000E000000080000000D0000000E000000080000000D0000000E000000080000000E0000000E000000080000000E0000000E000000080000000F0000000E000000080000000F0000000E00000008000000100000000E00000008000000100000000E00000008000000000000000F00000008000000000000000F00000008000000010000000F00000008000000010000000F00000008000000020000000F00000008000000020000000F00000008000000030000000F00000008000000030000000F00000008000000040000000F00000008000000040000000F00000008000000050000000F00000008000000050000000F00000008000000060000000F00000008000000060000000F00000008000000070000000F00000008000000070000000F00000008000000080000000F00000008000000080000000F00000008000000090000000F00000008000000090000000F000000080000000A0000000F000000080000000A0000000F000000080000000B0000000F000000080000000B0000000F000000080000000C0000000F000000080000000C0000000F000000080000000D0000000F000000080000000D0000000F000000080000000E0000000F000000080000000E0000000F000000080000000F0000000F000000080000000F0000000F00000008000000100000000F00000008000000100000000F000000080000000000000010000000080000000000000010000000080000000100000010000000080000000100000010000000080000000200000010000000080000000200000010000000080000000300000010000000080000000300000010000000080000000400000010000000080000000400000010000000080000000500000010000000080000000500000010000000080000000600000010000000080000000600000010000000080000000700000010000000080000000700000010000000080000000800000010000000080000000800000010000000080000000900000010000000080000000900000010000000080000000A00000010000000080000000A00000010000000080000000B00000010000000080000000B00000010000000080000000C00000010000000080000000C00000010000000080000000D00000010000000080000000D00000010000000080000000E00000010000000080000000E00000010000000080000000F00000010000000080000000F00000010000000080000001000000010000000080000001000000010000000080000000000000000000000090000000000000000000000090000000100000000000000090000000100000000000000090000000200000000000000090000000200000000000000090000000300000000000000090000000300000000000000090000000400000000000000090000000400000000000000090000000500000000000000090000000500000000000000090000000600000000000000090000000600000000000000090000000700000000000000090000000700000000000000090000000800000000000000090000000800000000000000090000000900000000000000090000000900000000000000090000000A00000000000000090000000A00000000000000090000000B00000000000000090000000B00000000000000090000000C00000000000000090000000C00000000000000090000000D00000000000000090000000D00000000000000090000000E00000000000000090000000E00000000000000090000000F00000000000000090000000F00000000000000090000001000000000000000090000001000000000000000090000000000000001000000090000000000000001000000090000000100000001000000090000000100000001000000090000000200000001000000090000000200000001000000090000000300000001000000090000000300000001000000090000000400000001000000090000000400000001000000090000000500000001000000090000000500000001000000090000000600000001000000090000000600000001000000090000000700000001000000090000000700000001000000090000000800000001000000090000000800000001000000090000000900000001000000090000000900000001000000090000000A00000001000000090000000A00000001000000090000000B00000001000000090000000B00000001000000090000000C00000001000000090000000C00000001000000090000000D00000001000000090000000D00000001000000090000000E00000001000000090000000E00000001000000090000000F00000001000000090000000F00000001000000090000001000000001000000090000001000000001000000090000000000000002000000090000000000000002000000090000000100000002000000090000000100000002000000090000000200000002000000090000000200000002000000090000000300000002000000090000000300000002000000090000000400000002000000090000000400000002000000090000000500000002000000090000000500000002000000090000000600000002000000090000000600000002000000090000000700000002000000090000000700000002000000090000000800000002000000090000000800000002000000090000000900000002000000090000000900000002000000090000000A00000002000000090000000A00000002000000090000000B00000002000000090000000B00000002000000090000000C00000002000000090000000C00000002000000090000000D00000002000000090000000D00000002000000090000000E00000002000000090000000E00000002000000090000000F00000002000000090000000F00000002000000090000001000000002000000090000001000000002000000090000000000000003000000090000000000000003000000090000000100000003000000090000000100000003000000090000000200000003000000090000000200000003000000090000000300000003000000090000000300000003000000090000000400000003000000090000000400000003000000090000000500000003000000090000000500000003000000090000000600000003000000090000000600000003000000090000000700000003000000090000000700000003000000090000000800000003000000090000000800000003000000090000000900000003000000090000000900000003000000090000000A00000003000000090000000A00000003000000090000000B00000003000000090000000B00000003000000090000000C00000003000000090000000C00000003000000090000000D00000003000000090000000D00000003000000090000000E00000003000000090000000E00000003000000090000000F00000003000000090000000F00000003000000090000001000000003000000090000001000000003000000090000000000000004000000090000000000000004000000090000000100000004000000090000000100000004000000090000000200000004000000090000000200000004000000090000000300000004000000090000000300000004000000090000000400000004000000090000000400000004000000090000000500000004000000090000000500000004000000090000000600000004000000090000000600000004000000090000000700000004000000090000000700000004000000090000000800000004000000090000000800000004000000090000000900000004000000090000000900000004000000090000000A00000004000000090000000A00000004000000090000000B00000004000000090000000B00000004000000090000000C00000004000000090000000C00000004000000090000000D00000004000000090000000D00000004000000090000000E00000004000000090000000E00000004000000090000000F00000004000000090000000F00000004000000090000001000000004000000090000001000000004000000090000000000000005000000090000000000000005000000090000000100000005000000090000000100000005000000090000000200000005000000090000000200000005000000090000000300000005000000090000000300000005000000090000000400000005000000090000000400000005000000090000000500000005000000090000000500000005000000090000000600000005000000090000000600000005000000090000000700000005000000090000000700000005000000090000000800000005000000090000000800000005000000090000000900000005000000090000000900000005000000090000000A00000005000000090000000A00000005000000090000000B00000005000000090000000B00000005000000090000000C00000005000000090000000C00000005000000090000000D00000005000000090000000D00000005000000090000000E00000005000000090000000E00000005000000090000000F00000005000000090000000F00000005000000090000001000000005000000090000001000000005000000090000000000000006000000090000000000000006000000090000000100000006000000090000000100000006000000090000000200000006000000090000000200000006000000090000000300000006000000090000000300000006000000090000000400000006000000090000000400000006000000090000000500000006000000090000000500000006000000090000000600000006000000090000000600000006000000090000000700000006000000090000000700000006000000090000000800000006000000090000000800000006000000090000000900000006000000090000000900000006000000090000000A00000006000000090000000A00000006000000090000000B00000006000000090000000B00000006000000090000000C00000006000000090000000C00000006000000090000000D00000006000000090000000D00000006000000090000000E00000006000000090000000E00000006000000090000000F00000006000000090000000F00000006000000090000001000000006000000090000001000000006000000090000000000000007000000090000000000000007000000090000000100000007000000090000000100000007000000090000000200000007000000090000000200000007000000090000000300000007000000090000000300000007000000090000000400000007000000090000000400000007000000090000000500000007000000090000000500000007000000090000000600000007000000090000000600000007000000090000000700000007000000090000000700000007000000090000000800000007000000090000000800000007000000090000000900000007000000090000000900000007000000090000000A00000007000000090000000A00000007000000090000000B00000007000000090000000B00000007000000090000000C00000007000000090000000C00000007000000090000000D00000007000000090000000D00000007000000090000000E00000007000000090000000E00000007000000090000000F00000007000000090000000F00000007000000090000001000000007000000090000001000000007000000090000000000000008000000090000000000000008000000090000000100000008000000090000000100000008000000090000000200000008000000090000000200000008000000090000000300000008000000090000000300000008000000090000000400000008000000090000000400000008000000090000000500000008000000090000000500000008000000090000000600000008000000090000000600000008000000090000000700000008000000090000000700000008000000090000000800000008000000090000000800000008000000090000000900000008000000090000000900000008000000090000000A00000008000000090000000A00000008000000090000000B00000008000000090000000B00000008000000090000000C00000008000000090000000C00000008000000090000000D00000008000000090000000D00000008000000090000000E00000008000000090000000E00000008000000090000000F00000008000000090000000F00000008000000090000001000000008000000090000001000000008000000090000000000000009000000090000000000000009000000090000000100000009000000090000000100000009000000090000000200000009000000090000000200000009000000090000000300000009000000090000000300000009000000090000000400000009000000090000000400000009000000090000000500000009000000090000000500000009000000090000000600000009000000090000000600000009000000090000000700000009000000090000000700000009000000090000000800000009000000090000000800000009000000090000000900000009000000090000000900000009000000090000000A00000009000000090000000A00000009000000090000000B00000009000000090000000B00000009000000090000000C00000009000000090000000C00000009000000090000000D00000009000000090000000D00000009000000090000000E00000009000000090000000E00000009000000090000000F00000009000000090000000F0000000900000009000000100000000900000009000000100000000900000009000000000000000A00000009000000000000000A00000009000000010000000A00000009000000010000000A00000009000000020000000A00000009000000020000000A00000009000000030000000A00000009000000030000000A00000009000000040000000A00000009000000040000000A00000009000000050000000A00000009000000050000000A00000009000000060000000A00000009000000060000000A00000009000000070000000A00000009000000070000000A00000009000000080000000A00000009000000080000000A00000009000000090000000A00000009000000090000000A000000090000000A0000000A000000090000000A0000000A000000090000000B0000000A000000090000000B0000000A000000090000000C0000000A000000090000000C0000000A000000090000000D0000000A000000090000000D0000000A000000090000000E0000000A000000090000000E0000000A000000090000000F0000000A000000090000000F0000000A00000009000000100000000A00000009000000100000000A00000009000000000000000B00000009000000000000000B00000009000000010000000B00000009000000010000000B00000009000000020000000B00000009000000020000000B00000009000000030000000B00000009000000030000000B00000009000000040000000B00000009000000040000000B00000009000000050000000B00000009000000050000000B00000009000000060000000B00000009000000060000000B00000009000000070000000B00000009000000070000000B00000009000000080000000B00000009000000080000000B00000009000000090000000B00000009000000090000000B000000090000000A0000000B000000090000000A0000000B000000090000000B0000000B000000090000000B0000000B000000090000000C0000000B000000090000000C0000000B000000090000000D0000000B000000090000000D0000000B000000090000000E0000000B000000090000000E0000000B000000090000000F0000000B000000090000000F0000000B00000009000000100000000B00000009000000100000000B00000009000000000000000C00000009000000000000000C00000009000000010000000C00000009000000010000000C00000009000000020000000C00000009000000020000000C00000009000000030000000C00000009000000030000000C00000009000000040000000C00000009000000040000000C00000009000000050000000C00000009000000050000000C00000009000000060000000C00000009000000060000000C00000009000000070000000C00000009000000070000000C00000009000000080000000C00000009000000080000000C00000009000000090000000C00000009000000090000000C000000090000000A0000000C000000090000000A0000000C000000090000000B0000000C000000090000000B0000000C000000090000000C0000000C000000090000000C0000000C000000090000000D0000000C000000090000000D0000000C000000090000000E0000000C000000090000000E0000000C000000090000000F0000000C000000090000000F0000000C00000009000000100000000C00000009000000100000000C00000009000000000000000D00000009000000000000000D00000009000000010000000D00000009000000010000000D00000009000000020000000D00000009000000020000000D00000009000000030000000D00000009000000030000000D00000009000000040000000D00000009000000040000000D00000009000000050000000D00000009000000050000000D00000009000000060000000D00000009000000060000000D00000009000000070000000D00000009000000070000000D00000009000000080000000D00000009000000080000000D00000009000000090000000D00000009000000090000000D000000090000000A0000000D000000090000000A0000000D000000090000000B0000000D000000090000000B0000000D000000090000000C0000000D000000090000000C0000000D000000090000000D0000000D000000090000000D0000000D000000090000000E0000000D000000090000000E0000000D000000090000000F0000000D000000090000000F0000000D00000009000000100000000D00000009000000100000000D00000009000000000000000E00000009000000000000000E00000009000000010000000E00000009000000010000000E00000009000000020000000E00000009000000020000000E00000009000000030000000E00000009000000030000000E00000009000000040000000E00000009000000040000000E00000009000000050000000E00000009000000050000000E00000009000000060000000E00000009000000060000000E00000009000000070000000E00000009000000070000000E00000009000000080000000E00000009000000080000000E00000009000000090000000E00000009000000090000000E000000090000000A0000000E000000090000000A0000000E000000090000000B0000000E000000090000000B0000000E000000090000000C0000000E000000090000000C0000000E000000090000000D0000000E000000090000000D0000000E000000090000000E0000000E000000090000000E0000000E000000090000000F0000000E000000090000000F0000000E00000009000000100000000E00000009000000100000000E00000009000000000000000F00000009000000000000000F00000009000000010000000F00000009000000010000000F00000009000000020000000F00000009000000020000000F00000009000000030000000F00000009000000030000000F00000009000000040000000F00000009000000040000000F00000009000000050000000F00000009000000050000000F00000009000000060000000F00000009000000060000000F00000009000000070000000F00000009000000070000000F00000009000000080000000F00000009000000080000000F00000009000000090000000F00000009000000090000000F000000090000000A0000000F000000090000000A0000000F000000090000000B0000000F000000090000000B0000000F000000090000000C0000000F000000090000000C0000000F000000090000000D0000000F000000090000000D0000000F000000090000000E0000000F000000090000000E0000000F000000090000000F0000000F000000090000000F0000000F00000009000000100000000F00000009000000100000000F000000090000000000000010000000090000000000000010000000090000000100000010000000090000000100000010000000090000000200000010000000090000000200000010000000090000000300000010000000090000000300000010000000090000000400000010000000090000000400000010000000090000000500000010000000090000000500000010000000090000000600000010000000090000000600000010000000090000000700000010000000090000000700000010000000090000000800000010000000090000000800000010000000090000000900000010000000090000000900000010000000090000000A00000010000000090000000A00000010000000090000000B00000010000000090000000B00000010000000090000000C00000010000000090000000C00000010000000090000000D00000010000000090000000D00000010000000090000000E00000010000000090000000E00000010000000090000000F00000010000000090000000F000000100000000900000010000000100000000900000010000000100000000900000000000000000000000A00000000000000000000000A00000001000000000000000A00000001000000000000000A00000002000000000000000A00000002000000000000000A00000003000000000000000A00000003000000000000000A00000004000000000000000A00000004000000000000000A00000005000000000000000A00000005000000000000000A00000006000000000000000A00000006000000000000000A00000007000000000000000A00000007000000000000000A00000008000000000000000A00000008000000000000000A00000009000000000000000A00000009000000000000000A0000000A000000000000000A0000000A000000000000000A0000000B000000000000000A0000000B000000000000000A0000000C000000000000000A0000000C000000000000000A0000000D000000000000000A0000000D000000000000000A0000000E000000000000000A0000000E000000000000000A0000000F000000000000000A0000000F000000000000000A00000010000000000000000A00000010000000000000000A00000000000000010000000A00000000000000010000000A00000001000000010000000A00000001000000010000000A00000002000000010000000A00000002000000010000000A00000003000000010000000A00000003000000010000000A00000004000000010000000A00000004000000010000000A00000005000000010000000A00000005000000010000000A00000006000000010000000A00000006000000010000000A00000007000000010000000A00000007000000010000000A00000008000000010000000A00000008000000010000000A00000009000000010000000A00000009000000010000000A0000000A000000010000000A0000000A000000010000000A0000000B000000010000000A0000000B000000010000000A0000000C000000010000000A0000000C000000010000000A0000000D000000010000000A0000000D000000010000000A0000000E000000010000000A0000000E000000010000000A0000000F000000010000000A0000000F000000010000000A00000010000000010000000A00000010000000010000000A00000000000000020000000A00000000000000020000000A00000001000000020000000A00000001000000020000000A00000002000000020000000A00000002000000020000000A00000003000000020000000A00000003000000020000000A00000004000000020000000A00000004000000020000000A00000005000000020000000A00000005000000020000000A00000006000000020000000A00000006000000020000000A00000007000000020000000A00000007000000020000000A00000008000000020000000A00000008000000020000000A00000009000000020000000A00000009000000020000000A0000000A000000020000000A0000000A000000020000000A0000000B000000020000000A0000000B000000020000000A0000000C000000020000000A0000000C000000020000000A0000000D000000020000000A0000000D000000020000000A0000000E000000020000000A0000000E000000020000000A0000000F000000020000000A0000000F000000020000000A00000010000000020000000A00000010000000020000000A00000000000000030000000A00000000000000030000000A00000001000000030000000A00000001000000030000000A00000002000000030000000A00000002000000030000000A00000003000000030000000A00000003000000030000000A00000004000000030000000A00000004000000030000000A00000005000000030000000A00000005000000030000000A00000006000000030000000A00000006000000030000000A00000007000000030000000A00000007000000030000000A00000008000000030000000A00000008000000030000000A00000009000000030000000A00000009000000030000000A0000000A000000030000000A0000000A000000030000000A0000000B000000030000000A0000000B000000030000000A0000000C000000030000000A0000000C000000030000000A0000000D000000030000000A0000000D000000030000000A0000000E000000030000000A0000000E000000030000000A0000000F000000030000000A0000000F000000030000000A00000010000000030000000A00000010000000030000000A00000000000000040000000A00000000000000040000000A00000001000000040000000A00000001000000040000000A00000002000000040000000A00000002000000040000000A00000003000000040000000A00000003000000040000000A00000004000000040000000A00000004000000040000000A00000005000000040000000A00000005000000040000000A00000006000000040000000A00000006000000040000000A00000007000000040000000A00000007000000040000000A00000008000000040000000A00000008000000040000000A00000009000000040000000A00000009000000040000000A0000000A000000040000000A0000000A000000040000000A0000000B000000040000000A0000000B000000040000000A0000000C000000040000000A0000000C000000040000000A0000000D000000040000000A0000000D000000040000000A0000000E000000040000000A0000000E000000040000000A0000000F000000040000000A0000000F000000040000000A00000010000000040000000A00000010000000040000000A00000000000000050000000A00000000000000050000000A00000001000000050000000A00000001000000050000000A00000002000000050000000A00000002000000050000000A00000003000000050000000A00000003000000050000000A00000004000000050000000A00000004000000050000000A00000005000000050000000A00000005000000050000000A00000006000000050000000A00000006000000050000000A00000007000000050000000A00000007000000050000000A00000008000000050000000A00000008000000050000000A00000009000000050000000A00000009000000050000000A0000000A000000050000000A0000000A000000050000000A0000000B000000050000000A0000000B000000050000000A0000000C000000050000000A0000000C000000050000000A0000000D000000050000000A0000000D000000050000000A0000000E000000050000000A0000000E000000050000000A0000000F000000050000000A0000000F000000050000000A00000010000000050000000A00000010000000050000000A00000000000000060000000A00000000000000060000000A00000001000000060000000A00000001000000060000000A00000002000000060000000A00000002000000060000000A00000003000000060000000A00000003000000060000000A00000004000000060000000A00000004000000060000000A00000005000000060000000A00000005000000060000000A00000006000000060000000A00000006000000060000000A00000007000000060000000A00000007000000060000000A00000008000000060000000A00000008000000060000000A00000009000000060000000A00000009000000060000000A0000000A000000060000000A0000000A000000060000000A0000000B000000060000000A0000000B000000060000000A0000000C000000060000000A0000000C000000060000000A0000000D000000060000000A0000000D000000060000000A0000000E000000060000000A0000000E000000060000000A0000000F000000060000000A0000000F000000060000000A00000010000000060000000A00000010000000060000000A00000000000000070000000A00000000000000070000000A00000001000000070000000A00000001000000070000000A00000002000000070000000A00000002000000070000000A00000003000000070000000A00000003000000070000000A00000004000000070000000A00000004000000070000000A00000005000000070000000A00000005000000070000000A00000006000000070000000A00000006000000070000000A00000007000000070000000A00000007000000070000000A00000008000000070000000A00000008000000070000000A00000009000000070000000A00000009000000070000000A0000000A000000070000000A0000000A000000070000000A0000000B000000070000000A0000000B000000070000000A0000000C000000070000000A0000000C000000070000000A0000000D000000070000000A0000000D000000070000000A0000000E000000070000000A0000000E000000070000000A0000000F000000070000000A0000000F000000070000000A00000010000000070000000A00000010000000070000000A00000000000000080000000A00000000000000080000000A00000001000000080000000A00000001000000080000000A00000002000000080000000A00000002000000080000000A00000003000000080000000A00000003000000080000000A00000004000000080000000A00000004000000080000000A00000005000000080000000A00000005000000080000000A00000006000000080000000A00000006000000080000000A00000007000000080000000A00000007000000080000000A00000008000000080000000A00000008000000080000000A00000009000000080000000A00000009000000080000000A0000000A000000080000000A0000000A000000080000000A0000000B000000080000000A0000000B000000080000000A0000000C000000080000000A0000000C000000080000000A0000000D000000080000000A0000000D000000080000000A0000000E000000080000000A0000000E000000080000000A0000000F000000080000000A0000000F000000080000000A00000010000000080000000A00000010000000080000000A00000000000000090000000A00000000000000090000000A00000001000000090000000A00000001000000090000000A00000002000000090000000A00000002000000090000000A00000003000000090000000A00000003000000090000000A00000004000000090000000A00000004000000090000000A00000005000000090000000A00000005000000090000000A00000006000000090000000A00000006000000090000000A00000007000000090000000A00000007000000090000000A00000008000000090000000A00000008000000090000000A00000009000000090000000A00000009000000090000000A0000000A000000090000000A0000000A000000090000000A0000000B000000090000000A0000000B000000090000000A0000000C000000090000000A0000000C000000090000000A0000000D000000090000000A0000000D000000090000000A0000000E000000090000000A0000000E000000090000000A0000000F000000090000000A0000000F000000090000000A00000010000000090000000A00000010000000090000000A000000000000000A0000000A000000000000000A0000000A000000010000000A0000000A000000010000000A0000000A000000020000000A0000000A000000020000000A0000000A000000030000000A0000000A000000030000000A0000000A000000040000000A0000000A000000040000000A0000000A000000050000000A0000000A000000050000000A0000000A000000060000000A0000000A000000060000000A0000000A000000070000000A0000000A000000070000000A0000000A000000080000000A0000000A000000080000000A0000000A000000090000000A0000000A000000090000000A0000000A0000000A0000000A0000000A0000000A0000000A0000000A0000000B0000000A0000000A0000000B0000000A0000000A0000000C0000000A0000000A0000000C0000000A0000000A0000000D0000000A0000000A0000000D0000000A0000000A0000000E0000000A0000000A0000000E0000000A0000000A0000000F0000000A0000000A0000000F0000000A0000000A000000100000000A0000000A000000100000000A0000000A000000000000000B0000000A000000000000000B0000000A000000010000000B0000000A000000010000000B0000000A000000020000000B0000000A000000020000000B0000000A000000030000000B0000000A000000030000000B0000000A000000040000000B0000000A000000040000000B0000000A000000050000000B0000000A000000050000000B0000000A000000060000000B0000000A000000060000000B0000000A000000070000000B0000000A000000070000000B0000000A000000080000000B0000000A000000080000000B0000000A000000090000000B0000000A000000090000000B0000000A0000000A0000000B0000000A0000000A0000000B0000000A0000000B0000000B0000000A0000000B0000000B0000000A0000000C0000000B0000000A0000000C0000000B0000000A0000000D0000000B0000000A0000000D0000000B0000000A0000000E0000000B0000000A0000000E0000000B0000000A0000000F0000000B0000000A0000000F0000000B0000000A000000100000000B0000000A000000100000000B0000000A000000000000000C0000000A000000000000000C0000000A000000010000000C0000000A000000010000000C0000000A000000020000000C0000000A000000020000000C0000000A000000030000000C0000000A000000030000000C0000000A000000040000000C0000000A000000040000000C0000000A000000050000000C0000000A000000050000000C0000000A000000060000000C0000000A000000060000000C0000000A000000070000000C0000000A000000070000000C0000000A000000080000000C0000000A000000080000000C0000000A000000090000000C0000000A000000090000000C0000000A0000000A0000000C0000000A0000000A0000000C0000000A0000000B0000000C0000000A0000000B0000000C0000000A0000000C0000000C0000000A0000000C0000000C0000000A0000000D0000000C0000000A0000000D0000000C0000000A0000000E0000000C0000000A0000000E0000000C0000000A0000000F0000000C0000000A0000000F0000000C0000000A000000100000000C0000000A000000100000000C0000000A000000000000000D0000000A000000000000000D0000000A000000010000000D0000000A000000010000000D0000000A000000020000000D0000000A000000020000000D0000000A000000030000000D0000000A000000030000000D0000000A000000040000000D0000000A000000040000000D0000000A000000050000000D0000000A000000050000000D0000000A000000060000000D0000000A000000060000000D0000000A000000070000000D0000000A000000070000000D0000000A000000080000000D0000000A000000080000000D0000000A000000090000000D0000000A000000090000000D0000000A0000000A0000000D0000000A0000000A0000000D0000000A0000000B0000000D0000000A0000000B0000000D0000000A0000000C0000000D0000000A0000000C0000000D0000000A0000000D0000000D0000000A0000000D0000000D0000000A0000000E0000000D0000000A0000000E0000000D0000000A0000000F0000000D0000000A0000000F0000000D0000000A000000100000000D0000000A000000100000000D0000000A000000000000000E0000000A000000000000000E0000000A000000010000000E0000000A000000010000000E0000000A000000020000000E0000000A000000020000000E0000000A000000030000000E0000000A000000030000000E0000000A000000040000000E0000000A000000040000000E0000000A000000050000000E0000000A000000050000000E0000000A000000060000000E0000000A000000060000000E0000000A000000070000000E0000000A000000070000000E0000000A000000080000000E0000000A000000080000000E0000000A000000090000000E0000000A000000090000000E0000000A0000000A0000000E0000000A0000000A0000000E0000000A0000000B0000000E0000000A0000000B0000000E0000000A0000000C0000000E0000000A0000000C0000000E0000000A0000000D0000000E0000000A0000000D0000000E0000000A0000000E0000000E0000000A0000000E0000000E0000000A0000000F0000000E0000000A0000000F0000000E0000000A000000100000000E0000000A000000100000000E0000000A000000000000000F0000000A000000000000000F0000000A000000010000000F0000000A000000010000000F0000000A000000020000000F0000000A000000020000000F0000000A000000030000000F0000000A000000030000000F0000000A000000040000000F0000000A000000040000000F0000000A000000050000000F0000000A000000050000000F0000000A000000060000000F0000000A000000060000000F0000000A000000070000000F0000000A000000070000000F0000000A000000080000000F0000000A000000080000000F0000000A000000090000000F0000000A000000090000000F0000000A0000000A0000000F0000000A0000000A0000000F0000000A0000000B0000000F0000000A0000000B0000000F0000000A0000000C0000000F0000000A0000000C0000000F0000000A0000000D0000000F0000000A0000000D0000000F0000000A0000000E0000000F0000000A0000000E0000000F0000000A0000000F0000000F0000000A0000000F0000000F0000000A000000100000000F0000000A000000100000000F0000000A00000000000000100000000A00000000000000100000000A00000001000000100000000A00000001000000100000000A00000002000000100000000A00000002000000100000000A00000003000000100000000A00000003000000100000000A00000004000000100000000A00000004000000100000000A00000005000000100000000A00000005000000100000000A00000006000000100000000A00000006000000100000000A00000007000000100000000A00000007000000100000000A00000008000000100000000A00000008000000100000000A00000009000000100000000A00000009000000100000000A0000000A000000100000000A0000000A000000100000000A0000000B000000100000000A0000000B000000100000000A0000000C000000100000000A0000000C000000100000000A0000000D000000100000000A0000000D000000100000000A0000000E000000100000000A0000000E000000100000000A0000000F000000100000000A0000000F000000100000000A00000010000000100000000A00000010000000100000000A00000000000000000000000B00000000000000000000000B00000001000000000000000B00000001000000000000000B00000002000000000000000B00000002000000000000000B00000003000000000000000B00000003000000000000000B00000004000000000000000B00000004000000000000000B00000005000000000000000B00000005000000000000000B00000006000000000000000B00000006000000000000000B00000007000000000000000B00000007000000000000000B00000008000000000000000B00000008000000000000000B00000009000000000000000B00000009000000000000000B0000000A000000000000000B0000000A000000000000000B0000000B000000000000000B0000000B000000000000000B0000000C000000000000000B0000000C000000000000000B0000000D000000000000000B0000000D000000000000000B0000000E000000000000000B0000000E000000000000000B0000000F000000000000000B0000000F000000000000000B00000010000000000000000B00000010000000000000000B00000000000000010000000B00000000000000010000000B00000001000000010000000B00000001000000010000000B00000002000000010000000B00000002000000010000000B00000003000000010000000B00000003000000010000000B00000004000000010000000B00000004000000010000000B00000005000000010000000B00000005000000010000000B00000006000000010000000B00000006000000010000000B00000007000000010000000B00000007000000010000000B00000008000000010000000B00000008000000010000000B00000009000000010000000B00000009000000010000000B0000000A000000010000000B0000000A000000010000000B0000000B000000010000000B0000000B000000010000000B0000000C000000010000000B0000000C000000010000000B0000000D000000010000000B0000000D000000010000000B0000000E000000010000000B0000000E000000010000000B0000000F000000010000000B0000000F000000010000000B00000010000000010000000B00000010000000010000000B00000000000000020000000B00000000000000020000000B00000001000000020000000B00000001000000020000000B00000002000000020000000B00000002000000020000000B00000003000000020000000B00000003000000020000000B00000004000000020000000B00000004000000020000000B00000005000000020000000B00000005000000020000000B00000006000000020000000B00000006000000020000000B00000007000000020000000B00000007000000020000000B00000008000000020000000B00000008000000020000000B00000009000000020000000B00000009000000020000000B0000000A000000020000000B0000000A000000020000000B0000000B000000020000000B0000000B000000020000000B0000000C000000020000000B0000000C000000020000000B0000000D000000020000000B0000000D000000020000000B0000000E000000020000000B0000000E000000020000000B0000000F000000020000000B0000000F000000020000000B00000010000000020000000B00000010000000020000000B00000000000000030000000B00000000000000030000000B00000001000000030000000B00000001000000030000000B00000002000000030000000B00000002000000030000000B00000003000000030000000B00000003000000030000000B00000004000000030000000B00000004000000030000000B00000005000000030000000B00000005000000030000000B00000006000000030000000B00000006000000030000000B00000007000000030000000B00000007000000030000000B00000008000000030000000B00000008000000030000000B00000009000000030000000B00000009000000030000000B0000000A000000030000000B0000000A000000030000000B0000000B000000030000000B0000000B000000030000000B0000000C000000030000000B0000000C000000030000000B0000000D000000030000000B0000000D000000030000000B0000000E000000030000000B0000000E000000030000000B0000000F000000030000000B0000000F000000030000000B00000010000000030000000B00000010000000030000000B00000000000000040000000B00000000000000040000000B00000001000000040000000B00000001000000040000000B00000002000000040000000B00000002000000040000000B00000003000000040000000B00000003000000040000000B00000004000000040000000B00000004000000040000000B00000005000000040000000B00000005000000040000000B00000006000000040000000B00000006000000040000000B00000007000000040000000B00000007000000040000000B00000008000000040000000B00000008000000040000000B00000009000000040000000B00000009000000040000000B0000000A000000040000000B0000000A000000040000000B0000000B000000040000000B0000000B000000040000000B0000000C000000040000000B0000000C000000040000000B0000000D000000040000000B0000000D000000040000000B0000000E000000040000000B0000000E000000040000000B0000000F000000040000000B0000000F000000040000000B00000010000000040000000B00000010000000040000000B00000000000000050000000B00000000000000050000000B00000001000000050000000B00000001000000050000000B00000002000000050000000B00000002000000050000000B00000003000000050000000B00000003000000050000000B00000004000000050000000B00000004000000050000000B00000005000000050000000B00000005000000050000000B00000006000000050000000B00000006000000050000000B00000007000000050000000B00000007000000050000000B00000008000000050000000B00000008000000050000000B00000009000000050000000B00000009000000050000000B0000000A000000050000000B0000000A000000050000000B0000000B000000050000000B0000000B000000050000000B0000000C000000050000000B0000000C000000050000000B0000000D000000050000000B0000000D000000050000000B0000000E000000050000000B0000000E000000050000000B0000000F000000050000000B0000000F000000050000000B00000010000000050000000B00000010000000050000000B00000000000000060000000B00000000000000060000000B00000001000000060000000B00000001000000060000000B00000002000000060000000B00000002000000060000000B00000003000000060000000B00000003000000060000000B00000004000000060000000B00000004000000060000000B00000005000000060000000B00000005000000060000000B00000006000000060000000B00000006000000060000000B00000007000000060000000B00000007000000060000000B00000008000000060000000B00000008000000060000000B00000009000000060000000B00000009000000060000000B0000000A000000060000000B0000000A000000060000000B0000000B000000060000000B0000000B000000060000000B0000000C000000060000000B0000000C000000060000000B0000000D000000060000000B0000000D000000060000000B0000000E000000060000000B0000000E000000060000000B0000000F000000060000000B0000000F000000060000000B00000010000000060000000B00000010000000060000000B00000000000000070000000B00000000000000070000000B00000001000000070000000B00000001000000070000000B00000002000000070000000B00000002000000070000000B00000003000000070000000B00000003000000070000000B00000004000000070000000B00000004000000070000000B00000005000000070000000B00000005000000070000000B00000006000000070000000B00000006000000070000000B00000007000000070000000B00000007000000070000000B00000008000000070000000B00000008000000070000000B00000009000000070000000B00000009000000070000000B0000000A000000070000000B0000000A000000070000000B0000000B000000070000000B0000000B000000070000000B0000000C000000070000000B0000000C000000070000000B0000000D000000070000000B0000000D000000070000000B0000000E000000070000000B0000000E000000070000000B0000000F000000070000000B0000000F000000070000000B00000010000000070000000B00000010000000070000000B00000000000000080000000B00000000000000080000000B00000001000000080000000B00000001000000080000000B00000002000000080000000B00000002000000080000000B00000003000000080000000B00000003000000080000000B00000004000000080000000B00000004000000080000000B00000005000000080000000B00000005000000080000000B00000006000000080000000B00000006000000080000000B00000007000000080000000B00000007000000080000000B00000008000000080000000B00000008000000080000000B00000009000000080000000B00000009000000080000000B0000000A000000080000000B0000000A000000080000000B0000000B000000080000000B0000000B000000080000000B0000000C000000080000000B0000000C000000080000000B0000000D000000080000000B0000000D000000080000000B0000000E000000080000000B0000000E000000080000000B0000000F000000080000000B0000000F000000080000000B00000010000000080000000B00000010000000080000000B00000000000000090000000B00000000000000090000000B00000001000000090000000B00000001000000090000000B00000002000000090000000B00000002000000090000000B00000003000000090000000B00000003000000090000000B00000004000000090000000B00000004000000090000000B00000005000000090000000B00000005000000090000000B00000006000000090000000B00000006000000090000000B00000007000000090000000B00000007000000090000000B00000008000000090000000B00000008000000090000000B00000009000000090000000B00000009000000090000000B0000000A000000090000000B0000000A000000090000000B0000000B000000090000000B0000000B000000090000000B0000000C000000090000000B0000000C000000090000000B0000000D000000090000000B0000000D000000090000000B0000000E000000090000000B0000000E000000090000000B0000000F000000090000000B0000000F000000090000000B00000010000000090000000B00000010000000090000000B000000000000000A0000000B000000000000000A0000000B000000010000000A0000000B000000010000000A0000000B000000020000000A0000000B000000020000000A0000000B000000030000000A0000000B000000030000000A0000000B000000040000000A0000000B000000040000000A0000000B000000050000000A0000000B000000050000000A0000000B000000060000000A0000000B000000060000000A0000000B000000070000000A0000000B000000070000000A0000000B000000080000000A0000000B000000080000000A0000000B000000090000000A0000000B000000090000000A0000000B0000000A0000000A0000000B0000000A0000000A0000000B0000000B0000000A0000000B0000000B0000000A0000000B0000000C0000000A0000000B0000000C0000000A0000000B0000000D0000000A0000000B0000000D0000000A0000000B0000000E0000000A0000000B0000000E0000000A0000000B0000000F0000000A0000000B0000000F0000000A0000000B000000100000000A0000000B000000100000000A0000000B000000000000000B0000000B000000000000000B0000000B000000010000000B0000000B000000010000000B0000000B000000020000000B0000000B000000020000000B0000000B000000030000000B0000000B000000030000000B0000000B000000040000000B0000000B000000040000000B0000000B000000050000000B0000000B000000050000000B0000000B000000060000000B0000000B000000060000000B0000000B000000070000000B0000000B000000070000000B0000000B000000080000000B0000000B000000080000000B0000000B000000090000000B0000000B000000090000000B0000000B0000000A0000000B0000000B0000000A0000000B0000000B0000000B0000000B0000000B0000000B0000000B0000000B0000000C0000000B0000000B0000000C0000000B0000000B0000000D0000000B0000000B0000000D0000000B0000000B0000000E0000000B0000000B0000000E0000000B0000000B0000000F0000000B0000000B0000000F0000000B0000000B000000100000000B0000000B000000100000000B0000000B000000000000000C0000000B000000000000000C0000000B000000010000000C0000000B000000010000000C0000000B000000020000000C0000000B000000020000000C0000000B000000030000000C0000000B000000030000000C0000000B000000040000000C0000000B000000040000000C0000000B000000050000000C0000000B000000050000000C0000000B000000060000000C0000000B000000060000000C0000000B000000070000000C0000000B000000070000000C0000000B000000080000000C0000000B000000080000000C0000000B000000090000000C0000000B000000090000000C0000000B0000000A0000000C0000000B0000000A0000000C0000000B0000000B0000000C0000000B0000000B0000000C0000000B0000000C0000000C0000000B0000000C0000000C0000000B0000000D0000000C0000000B0000000D0000000C0000000B0000000E0000000C0000000B0000000E0000000C0000000B0000000F0000000C0000000B0000000F0000000C0000000B000000100000000C0000000B000000100000000C0000000B000000000000000D0000000B000000000000000D0000000B000000010000000D0000000B000000010000000D0000000B000000020000000D0000000B000000020000000D0000000B000000030000000D0000000B000000030000000D0000000B000000040000000D0000000B000000040000000D0000000B000000050000000D0000000B000000050000000D0000000B000000060000000D0000000B000000060000000D0000000B000000070000000D0000000B000000070000000D0000000B000000080000000D0000000B000000080000000D0000000B000000090000000D0000000B000000090000000D0000000B0000000A0000000D0000000B0000000A0000000D0000000B0000000B0000000D0000000B0000000B0000000D0000000B0000000C0000000D0000000B0000000C0000000D0000000B0000000D0000000D0000000B0000000D0000000D0000000B0000000E0000000D0000000B0000000E0000000D0000000B0000000F0000000D0000000B0000000F0000000D0000000B000000100000000D0000000B000000100000000D0000000B000000000000000E0000000B000000000000000E0000000B000000010000000E0000000B000000010000000E0000000B000000020000000E0000000B000000020000000E0000000B000000030000000E0000000B000000030000000E0000000B000000040000000E0000000B000000040000000E0000000B000000050000000E0000000B000000050000000E0000000B000000060000000E0000000B000000060000000E0000000B000000070000000E0000000B000000070000000E0000000B000000080000000E0000000B000000080000000E0000000B000000090000000E0000000B000000090000000E0000000B0000000A0000000E0000000B0000000A0000000E0000000B0000000B0000000E0000000B0000000B0000000E0000000B0000000C0000000E0000000B0000000C0000000E0000000B0000000D0000000E0000000B0000000D0000000E0000000B0000000E0000000E0000000B0000000E0000000E0000000B0000000F0000000E0000000B0000000F0000000E0000000B000000100000000E0000000B000000100000000E0000000B000000000000000F0000000B000000000000000F0000000B000000010000000F0000000B000000010000000F0000000B000000020000000F0000000B000000020000000F0000000B000000030000000F0000000B000000030000000F0000000B000000040000000F0000000B000000040000000F0000000B000000050000000F0000000B000000050000000F0000000B000000060000000F0000000B000000060000000F0000000B000000070000000F0000000B000000070000000F0000000B000000080000000F0000000B000000080000000F0000000B000000090000000F0000000B000000090000000F0000000B0000000A0000000F0000000B0000000A0000000F0000000B0000000B0000000F0000000B0000000B0000000F0000000B0000000C0000000F0000000B0000000C0000000F0000000B0000000D0000000F0000000B0000000D0000000F0000000B0000000E0000000F0000000B0000000E0000000F0000000B0000000F0000000F0000000B0000000F0000000F0000000B000000100000000F0000000B000000100000000F0000000B00000000000000100000000B00000000000000100000000B00000001000000100000000B00000001000000100000000B00000002000000100000000B00000002000000100000000B00000003000000100000000B00000003000000100000000B00000004000000100000000B00000004000000100000000B00000005000000100000000B00000005000000100000000B00000006000000100000000B00000006000000100000000B00000007000000100000000B00000007000000100000000B00000008000000100000000B00000008000000100000000B00000009000000100000000B00000009000000100000000B0000000A000000100000000B0000000A000000100000000B0000000B000000100000000B0000000B000000100000000B0000000C000000100000000B0000000C000000100000000B0000000D000000100000000B0000000D000000100000000B0000000E000000100000000B0000000E000000100000000B0000000F000000100000000B0000000F000000100000000B00000010000000100000000B00000010000000100000000B00000000000000000000000C00000000000000000000000C00000001000000000000000C00000001000000000000000C00000002000000000000000C00000002000000000000000C00000003000000000000000C00000003000000000000000C00000004000000000000000C00000004000000000000000C00000005000000000000000C00000005000000000000000C00000006000000000000000C00000006000000000000000C00000007000000000000000C00000007000000000000000C00000008000000000000000C00000008000000000000000C00000009000000000000000C00000009000000000000000C0000000A000000000000000C0000000A000000000000000C0000000B000000000000000C0000000B000000000000000C0000000C000000000000000C0000000C000000000000000C0000000D000000000000000C0000000D000000000000000C0000000E000000000000000C0000000E000000000000000C0000000F000000000000000C0000000F000000000000000C00000010000000000000000C00000010000000000000000C00000000000000010000000C00000000000000010000000C00000001000000010000000C00000001000000010000000C00000002000000010000000C00000002000000010000000C00000003000000010000000C00000003000000010000000C00000004000000010000000C00000004000000010000000C00000005000000010000000C00000005000000010000000C00000006000000010000000C00000006000000010000000C00000007000000010000000C00000007000000010000000C00000008000000010000000C00000008000000010000000C00000009000000010000000C00000009000000010000000C0000000A000000010000000C0000000A000000010000000C0000000B000000010000000C0000000B000000010000000C0000000C000000010000000C0000000C000000010000000C0000000D000000010000000C0000000D000000010000000C0000000E000000010000000C0000000E000000010000000C0000000F000000010000000C0000000F000000010000000C00000010000000010000000C00000010000000010000000C00000000000000020000000C00000000000000020000000C00000001000000020000000C00000001000000020000000C00000002000000020000000C00000002000000020000000C00000003000000020000000C00000003000000020000000C00000004000000020000000C00000004000000020000000C00000005000000020000000C00000005000000020000000C00000006000000020000000C00000006000000020000000C00000007000000020000000C00000007000000020000000C00000008000000020000000C00000008000000020000000C00000009000000020000000C00000009000000020000000C0000000A000000020000000C0000000A000000020000000C0000000B000000020000000C0000000B000000020000000C0000000C000000020000000C0000000C000000020000000C0000000D000000020000000C0000000D000000020000000C0000000E000000020000000C0000000E000000020000000C0000000F000000020000000C0000000F000000020000000C00000010000000020000000C00000010000000020000000C00000000000000030000000C00000000000000030000000C00000001000000030000000C00000001000000030000000C00000002000000030000000C00000002000000030000000C00000003000000030000000C00000003000000030000000C00000004000000030000000C00000004000000030000000C00000005000000030000000C00000005000000030000000C00000006000000030000000C00000006000000030000000C00000007000000030000000C00000007000000030000000C00000008000000030000000C00000008000000030000000C00000009000000030000000C00000009000000030000000C0000000A000000030000000C0000000A000000030000000C0000000B000000030000000C0000000B000000030000000C0000000C000000030000000C0000000C000000030000000C0000000D000000030000000C0000000D000000030000000C0000000E000000030000000C0000000E000000030000000C0000000F000000030000000C0000000F000000030000000C00000010000000030000000C00000010000000030000000C00000000000000040000000C00000000000000040000000C00000001000000040000000C00000001000000040000000C00000002000000040000000C00000002000000040000000C00000003000000040000000C00000003000000040000000C00000004000000040000000C00000004000000040000000C00000005000000040000000C00000005000000040000000C00000006000000040000000C00000006000000040000000C00000007000000040000000C00000007000000040000000C00000008000000040000000C00000008000000040000000C00000009000000040000000C00000009000000040000000C0000000A000000040000000C0000000A000000040000000C0000000B000000040000000C0000000B000000040000000C0000000C000000040000000C0000000C000000040000000C0000000D000000040000000C0000000D000000040000000C0000000E000000040000000C0000000E000000040000000C0000000F000000040000000C0000000F000000040000000C00000010000000040000000C00000010000000040000000C00000000000000050000000C00000000000000050000000C00000001000000050000000C00000001000000050000000C00000002000000050000000C00000002000000050000000C00000003000000050000000C00000003000000050000000C00000004000000050000000C00000004000000050000000C00000005000000050000000C00000005000000050000000C00000006000000050000000C00000006000000050000000C00000007000000050000000C00000007000000050000000C00000008000000050000000C00000008000000050000000C00000009000000050000000C00000009000000050000000C0000000A000000050000000C0000000A000000050000000C0000000B000000050000000C0000000B000000050000000C0000000C000000050000000C0000000C000000050000000C0000000D000000050000000C0000000D000000050000000C0000000E000000050000000C0000000E000000050000000C0000000F000000050000000C0000000F000000050000000C00000010000000050000000C00000010000000050000000C00000000000000060000000C00000000000000060000000C00000001000000060000000C00000001000000060000000C00000002000000060000000C00000002000000060000000C00000003000000060000000C00000003000000060000000C00000004000000060000000C00000004000000060000000C00000005000000060000000C00000005000000060000000C00000006000000060000000C00000006000000060000000C00000007000000060000000C00000007000000060000000C00000008000000060000000C00000008000000060000000C00000009000000060000000C00000009000000060000000C0000000A000000060000000C0000000A000000060000000C0000000B000000060000000C0000000B000000060000000C0000000C000000060000000C0000000C000000060000000C0000000D000000060000000C0000000D000000060000000C0000000E000000060000000C0000000E000000060000000C0000000F000000060000000C0000000F000000060000000C00000010000000060000000C00000010000000060000000C00000000000000070000000C00000000000000070000000C00000001000000070000000C00000001000000070000000C00000002000000070000000C00000002000000070000000C00000003000000070000000C00000003000000070000000C00000004000000070000000C00000004000000070000000C00000005000000070000000C00000005000000070000000C00000006000000070000000C00000006000000070000000C00000007000000070000000C00000007000000070000000C00000008000000070000000C00000008000000070000000C00000009000000070000000C00000009000000070000000C0000000A000000070000000C0000000A000000070000000C0000000B000000070000000C0000000B000000070000000C0000000C000000070000000C0000000C000000070000000C0000000D000000070000000C0000000D000000070000000C0000000E000000070000000C0000000E000000070000000C0000000F000000070000000C0000000F000000070000000C00000010000000070000000C00000010000000070000000C00000000000000080000000C00000000000000080000000C00000001000000080000000C00000001000000080000000C00000002000000080000000C00000002000000080000000C00000003000000080000000C00000003000000080000000C00000004000000080000000C00000004000000080000000C00000005000000080000000C00000005000000080000000C00000006000000080000000C00000006000000080000000C00000007000000080000000C00000007000000080000000C00000008000000080000000C00000008000000080000000C00000009000000080000000C00000009000000080000000C0000000A000000080000000C0000000A000000080000000C0000000B000000080000000C0000000B000000080000000C0000000C000000080000000C0000000C000000080000000C0000000D000000080000000C0000000D000000080000000C0000000E000000080000000C0000000E000000080000000C0000000F000000080000000C0000000F000000080000000C00000010000000080000000C00000010000000080000000C00000000000000090000000C00000000000000090000000C00000001000000090000000C00000001000000090000000C00000002000000090000000C00000002000000090000000C00000003000000090000000C00000003000000090000000C00000004000000090000000C00000004000000090000000C00000005000000090000000C00000005000000090000000C00000006000000090000000C00000006000000090000000C00000007000000090000000C00000007000000090000000C00000008000000090000000C00000008000000090000000C00000009000000090000000C00000009000000090000000C0000000A000000090000000C0000000A000000090000000C0000000B000000090000000C0000000B000000090000000C0000000C000000090000000C0000000C000000090000000C0000000D000000090000000C0000000D000000090000000C0000000E000000090000000C0000000E000000090000000C0000000F000000090000000C0000000F000000090000000C00000010000000090000000C00000010000000090000000C000000000000000A0000000C000000000000000A0000000C000000010000000A0000000C000000010000000A0000000C000000020000000A0000000C000000020000000A0000000C000000030000000A0000000C000000030000000A0000000C000000040000000A0000000C000000040000000A0000000C000000050000000A0000000C000000050000000A0000000C000000060000000A0000000C000000060000000A0000000C000000070000000A0000000C000000070000000A0000000C000000080000000A0000000C000000080000000A0000000C000000090000000A0000000C000000090000000A0000000C0000000A0000000A0000000C0000000A0000000A0000000C0000000B0000000A0000000C0000000B0000000A0000000C0000000C0000000A0000000C0000000C0000000A0000000C0000000D0000000A0000000C0000000D0000000A0000000C0000000E0000000A0000000C0000000E0000000A0000000C0000000F0000000A0000000C0000000F0000000A0000000C000000100000000A0000000C000000100000000A0000000C000000000000000B0000000C000000000000000B0000000C000000010000000B0000000C000000010000000B0000000C000000020000000B0000000C000000020000000B0000000C000000030000000B0000000C000000030000000B0000000C000000040000000B0000000C000000040000000B0000000C000000050000000B0000000C000000050000000B0000000C000000060000000B0000000C000000060000000B0000000C000000070000000B0000000C000000070000000B0000000C000000080000000B0000000C000000080000000B0000000C000000090000000B0000000C000000090000000B0000000C0000000A0000000B0000000C0000000A0000000B0000000C0000000B0000000B0000000C0000000B0000000B0000000C0000000C0000000B0000000C0000000C0000000B0000000C0000000D0000000B0000000C0000000D0000000B0000000C0000000E0000000B0000000C0000000E0000000B0000000C0000000F0000000B0000000C0000000F0000000B0000000C000000100000000B0000000C000000100000000B0000000C000000000000000C0000000C000000000000000C0000000C000000010000000C0000000C000000010000000C0000000C000000020000000C0000000C000000020000000C0000000C000000030000000C0000000C000000030000000C0000000C000000040000000C0000000C000000040000000C0000000C000000050000000C0000000C000000050000000C0000000C000000060000000C0000000C000000060000000C0000000C000000070000000C0000000C000000070000000C0000000C000000080000000C0000000C000000080000000C0000000C000000090000000C0000000C000000090000000C0000000C0000000A0000000C0000000C0000000A0000000C0000000C0000000B0000000C0000000C0000000B0000000C0000000C0000000C0000000C0000000C0000000C0000000C0000000C0000000D0000000C0000000C0000000D0000000C0000000C0000000E0000000C0000000C0000000E0000000C0000000C0000000F0000000C0000000C0000000F0000000C0000000C000000100000000C0000000C000000100000000C0000000C000000000000000D0000000C000000000000000D0000000C000000010000000D0000000C000000010000000D0000000C000000020000000D0000000C000000020000000D0000000C000000030000000D0000000C000000030000000D0000000C000000040000000D0000000C000000040000000D0000000C000000050000000D0000000C000000050000000D0000000C000000060000000D0000000C000000060000000D0000000C000000070000000D0000000C000000070000000D0000000C000000080000000D0000000C000000080000000D0000000C000000090000000D0000000C000000090000000D0000000C0000000A0000000D0000000C0000000A0000000D0000000C0000000B0000000D0000000C0000000B0000000D0000000C0000000C0000000D0000000C0000000C0000000D0000000C0000000D0000000D0000000C0000000D0000000D0000000C0000000E0000000D0000000C0000000E0000000D0000000C0000000F0000000D0000000C0000000F0000000D0000000C000000100000000D0000000C000000100000000D0000000C000000000000000E0000000C000000000000000E0000000C000000010000000E0000000C000000010000000E0000000C000000020000000E0000000C000000020000000E0000000C000000030000000E0000000C000000030000000E0000000C000000040000000E0000000C000000040000000E0000000C000000050000000E0000000C000000050000000E0000000C000000060000000E0000000C000000060000000E0000000C000000070000000E0000000C000000070000000E0000000C000000080000000E0000000C000000080000000E0000000C000000090000000E0000000C000000090000000E0000000C0000000A0000000E0000000C0000000A0000000E0000000C0000000B0000000E0000000C0000000B0000000E0000000C0000000C0000000E0000000C0000000C0000000E0000000C0000000D0000000E0000000C0000000D0000000E0000000C0000000E0000000E0000000C0000000E0000000E0000000C0000000F0000000E0000000C0000000F0000000E0000000C000000100000000E0000000C000000100000000E0000000C000000000000000F0000000C000000000000000F0000000C000000010000000F0000000C000000010000000F0000000C000000020000000F0000000C000000020000000F0000000C000000030000000F0000000C000000030000000F0000000C000000040000000F0000000C000000040000000F0000000C000000050000000F0000000C000000050000000F0000000C000000060000000F0000000C000000060000000F0000000C000000070000000F0000000C000000070000000F0000000C000000080000000F0000000C000000080000000F0000000C000000090000000F0000000C000000090000000F0000000C0000000A0000000F0000000C0000000A0000000F0000000C0000000B0000000F0000000C0000000B0000000F0000000C0000000C0000000F0000000C0000000C0000000F0000000C0000000D0000000F0000000C0000000D0000000F0000000C0000000E0000000F0000000C0000000E0000000F0000000C0000000F0000000F0000000C0000000F0000000F0000000C000000100000000F0000000C000000100000000F0000000C00000000000000100000000C00000000000000100000000C00000001000000100000000C00000001000000100000000C00000002000000100000000C00000002000000100000000C00000003000000100000000C00000003000000100000000C00000004000000100000000C00000004000000100000000C00000005000000100000000C00000005000000100000000C00000006000000100000000C00000006000000100000000C00000007000000100000000C00000007000000100000000C00000008000000100000000C00000008000000100000000C00000009000000100000000C00000009000000100000000C0000000A000000100000000C0000000A000000100000000C0000000B000000100000000C0000000B000000100000000C0000000C000000100000000C0000000C000000100000000C0000000D000000100000000C0000000D000000100000000C0000000E000000100000000C0000000E000000100000000C0000000F000000100000000C0000000F000000100000000C00000010000000100000000C00000010000000100000000C00000000000000000000000D00000000000000000000000D00000001000000000000000D00000001000000000000000D00000002000000000000000D00000002000000000000000D00000003000000000000000D00000003000000000000000D00000004000000000000000D00000004000000000000000D00000005000000000000000D00000005000000000000000D00000006000000000000000D00000006000000000000000D00000007000000000000000D00000007000000000000000D00000008000000000000000D00000008000000000000000D00000009000000000000000D00000009000000000000000D0000000A000000000000000D0000000A000000000000000D0000000B000000000000000D0000000B000000000000000D0000000C000000000000000D0000000C000000000000000D0000000D000000000000000D0000000D000000000000000D0000000E000000000000000D0000000E000000000000000D0000000F000000000000000D0000000F000000000000000D00000010000000000000000D00000010000000000000000D00000000000000010000000D00000000000000010000000D00000001000000010000000D00000001000000010000000D00000002000000010000000D00000002000000010000000D00000003000000010000000D00000003000000010000000D00000004000000010000000D00000004000000010000000D00000005000000010000000D00000005000000010000000D00000006000000010000000D00000006000000010000000D00000007000000010000000D00000007000000010000000D00000008000000010000000D00000008000000010000000D00000009000000010000000D00000009000000010000000D0000000A000000010000000D0000000A000000010000000D0000000B000000010000000D0000000B000000010000000D0000000C000000010000000D0000000C000000010000000D0000000D000000010000000D0000000D000000010000000D0000000E000000010000000D0000000E000000010000000D0000000F000000010000000D0000000F000000010000000D00000010000000010000000D00000010000000010000000D00000000000000020000000D00000000000000020000000D00000001000000020000000D00000001000000020000000D00000002000000020000000D00000002000000020000000D00000003000000020000000D00000003000000020000000D00000004000000020000000D00000004000000020000000D00000005000000020000000D00000005000000020000000D00000006000000020000000D00000006000000020000000D00000007000000020000000D00000007000000020000000D00000008000000020000000D00000008000000020000000D00000009000000020000000D00000009000000020000000D0000000A000000020000000D0000000A000000020000000D0000000B000000020000000D0000000B000000020000000D0000000C000000020000000D0000000C000000020000000D0000000D000000020000000D0000000D000000020000000D0000000E000000020000000D0000000E000000020000000D0000000F000000020000000D0000000F000000020000000D00000010000000020000000D00000010000000020000000D00000000000000030000000D00000000000000030000000D00000001000000030000000D00000001000000030000000D00000002000000030000000D00000002000000030000000D00000003000000030000000D00000003000000030000000D00000004000000030000000D00000004000000030000000D00000005000000030000000D00000005000000030000000D00000006000000030000000D00000006000000030000000D00000007000000030000000D00000007000000030000000D00000008000000030000000D00000008000000030000000D00000009000000030000000D00000009000000030000000D0000000A000000030000000D0000000A000000030000000D0000000B000000030000000D0000000B000000030000000D0000000C000000030000000D0000000C000000030000000D0000000D000000030000000D0000000D000000030000000D0000000E000000030000000D0000000E000000030000000D0000000F000000030000000D0000000F000000030000000D00000010000000030000000D00000010000000030000000D00000000000000040000000D00000000000000040000000D00000001000000040000000D00000001000000040000000D00000002000000040000000D00000002000000040000000D00000003000000040000000D00000003000000040000000D00000004000000040000000D00000004000000040000000D00000005000000040000000D00000005000000040000000D00000006000000040000000D00000006000000040000000D00000007000000040000000D00000007000000040000000D00000008000000040000000D00000008000000040000000D00000009000000040000000D00000009000000040000000D0000000A000000040000000D0000000A000000040000000D0000000B000000040000000D0000000B000000040000000D0000000C000000040000000D0000000C000000040000000D0000000D000000040000000D0000000D000000040000000D0000000E000000040000000D0000000E000000040000000D0000000F000000040000000D0000000F000000040000000D00000010000000040000000D00000010000000040000000D00000000000000050000000D00000000000000050000000D00000001000000050000000D00000001000000050000000D00000002000000050000000D00000002000000050000000D00000003000000050000000D00000003000000050000000D00000004000000050000000D00000004000000050000000D00000005000000050000000D00000005000000050000000D00000006000000050000000D00000006000000050000000D00000007000000050000000D00000007000000050000000D00000008000000050000000D00000008000000050000000D00000009000000050000000D00000009000000050000000D0000000A000000050000000D0000000A000000050000000D0000000B000000050000000D0000000B000000050000000D0000000C000000050000000D0000000C000000050000000D0000000D000000050000000D0000000D000000050000000D0000000E000000050000000D0000000E000000050000000D0000000F000000050000000D0000000F000000050000000D00000010000000050000000D00000010000000050000000D00000000000000060000000D00000000000000060000000D00000001000000060000000D00000001000000060000000D00000002000000060000000D00000002000000060000000D00000003000000060000000D00000003000000060000000D00000004000000060000000D00000004000000060000000D00000005000000060000000D00000005000000060000000D00000006000000060000000D00000006000000060000000D00000007000000060000000D00000007000000060000000D00000008000000060000000D00000008000000060000000D00000009000000060000000D00000009000000060000000D0000000A000000060000000D0000000A000000060000000D0000000B000000060000000D0000000B000000060000000D0000000C000000060000000D0000000C000000060000000D0000000D000000060000000D0000000D000000060000000D0000000E000000060000000D0000000E000000060000000D0000000F000000060000000D0000000F000000060000000D00000010000000060000000D00000010000000060000000D00000000000000070000000D00000000000000070000000D00000001000000070000000D00000001000000070000000D00000002000000070000000D00000002000000070000000D00000003000000070000000D00000003000000070000000D00000004000000070000000D00000004000000070000000D00000005000000070000000D00000005000000070000000D00000006000000070000000D00000006000000070000000D00000007000000070000000D00000007000000070000000D00000008000000070000000D00000008000000070000000D00000009000000070000000D00000009000000070000000D0000000A000000070000000D0000000A000000070000000D0000000B000000070000000D0000000B000000070000000D0000000C000000070000000D0000000C000000070000000D0000000D000000070000000D0000000D000000070000000D0000000E000000070000000D0000000E000000070000000D0000000F000000070000000D0000000F000000070000000D00000010000000070000000D00000010000000070000000D00000000000000080000000D00000000000000080000000D00000001000000080000000D00000001000000080000000D00000002000000080000000D00000002000000080000000D00000003000000080000000D00000003000000080000000D00000004000000080000000D00000004000000080000000D00000005000000080000000D00000005000000080000000D00000006000000080000000D00000006000000080000000D00000007000000080000000D00000007000000080000000D00000008000000080000000D00000008000000080000000D00000009000000080000000D00000009000000080000000D0000000A000000080000000D0000000A000000080000000D0000000B000000080000000D0000000B000000080000000D0000000C000000080000000D0000000C000000080000000D0000000D000000080000000D0000000D000000080000000D0000000E000000080000000D0000000E000000080000000D0000000F000000080000000D0000000F000000080000000D00000010000000080000000D00000010000000080000000D00000000000000090000000D00000000000000090000000D00000001000000090000000D00000001000000090000000D00000002000000090000000D00000002000000090000000D00000003000000090000000D00000003000000090000000D00000004000000090000000D00000004000000090000000D00000005000000090000000D00000005000000090000000D00000006000000090000000D00000006000000090000000D00000007000000090000000D00000007000000090000000D00000008000000090000000D00000008000000090000000D00000009000000090000000D00000009000000090000000D0000000A000000090000000D0000000A000000090000000D0000000B000000090000000D0000000B000000090000000D0000000C000000090000000D0000000C000000090000000D0000000D000000090000000D0000000D000000090000000D0000000E000000090000000D0000000E000000090000000D0000000F000000090000000D0000000F000000090000000D00000010000000090000000D00000010000000090000000D000000000000000A0000000D000000000000000A0000000D000000010000000A0000000D000000010000000A0000000D000000020000000A0000000D000000020000000A0000000D000000030000000A0000000D000000030000000A0000000D000000040000000A0000000D000000040000000A0000000D000000050000000A0000000D000000050000000A0000000D000000060000000A0000000D000000060000000A0000000D000000070000000A0000000D000000070000000A0000000D000000080000000A0000000D000000080000000A0000000D000000090000000A0000000D000000090000000A0000000D0000000A0000000A0000000D0000000A0000000A0000000D0000000B0000000A0000000D0000000B0000000A0000000D0000000C0000000A0000000D0000000C0000000A0000000D0000000D0000000A0000000D0000000D0000000A0000000D0000000E0000000A0000000D0000000E0000000A0000000D0000000F0000000A0000000D0000000F0000000A0000000D000000100000000A0000000D000000100000000A0000000D000000000000000B0000000D000000000000000B0000000D000000010000000B0000000D000000010000000B0000000D000000020000000B0000000D000000020000000B0000000D000000030000000B0000000D000000030000000B0000000D000000040000000B0000000D000000040000000B0000000D000000050000000B0000000D000000050000000B0000000D000000060000000B0000000D000000060000000B0000000D000000070000000B0000000D000000070000000B0000000D000000080000000B0000000D000000080000000B0000000D000000090000000B0000000D000000090000000B0000000D0000000A0000000B0000000D0000000A0000000B0000000D0000000B0000000B0000000D0000000B0000000B0000000D0000000C0000000B0000000D0000000C0000000B0000000D0000000D0000000B0000000D0000000D0000000B0000000D0000000E0000000B0000000D0000000E0000000B0000000D0000000F0000000B0000000D0000000F0000000B0000000D000000100000000B0000000D000000100000000B0000000D000000000000000C0000000D000000000000000C0000000D000000010000000C0000000D000000010000000C0000000D000000020000000C0000000D000000020000000C0000000D000000030000000C0000000D000000030000000C0000000D000000040000000C0000000D000000040000000C0000000D000000050000000C0000000D000000050000000C0000000D000000060000000C0000000D000000060000000C0000000D000000070000000C0000000D000000070000000C0000000D000000080000000C0000000D000000080000000C0000000D000000090000000C0000000D000000090000000C0000000D0000000A0000000C0000000D0000000A0000000C0000000D0000000B0000000C0000000D0000000B0000000C0000000D0000000C0000000C0000000D0000000C0000000C0000000D0000000D0000000C0000000D0000000D0000000C0000000D0000000E0000000C0000000D0000000E0000000C0000000D0000000F0000000C0000000D0000000F0000000C0000000D000000100000000C0000000D000000100000000C0000000D000000000000000D0000000D000000000000000D0000000D000000010000000D0000000D000000010000000D0000000D000000020000000D0000000D000000020000000D0000000D000000030000000D0000000D000000030000000D0000000D000000040000000D0000000D000000040000000D0000000D000000050000000D0000000D000000050000000D0000000D000000060000000D0000000D000000060000000D0000000D000000070000000D0000000D000000070000000D0000000D000000080000000D0000000D000000080000000D0000000D000000090000000D0000000D000000090000000D0000000D0000000A0000000D0000000D0000000A0000000D0000000D0000000B0000000D0000000D0000000B0000000D0000000D0000000C0000000D0000000D0000000C0000000D0000000D0000000D0000000D0000000D0000000D0000000D0000000D0000000E0000000D0000000D0000000E0000000D0000000D0000000F0000000D0000000D0000000F0000000D0000000D000000100000000D0000000D000000100000000D0000000D000000000000000E0000000D000000000000000E0000000D000000010000000E0000000D000000010000000E0000000D000000020000000E0000000D000000020000000E0000000D000000030000000E0000000D000000030000000E0000000D000000040000000E0000000D000000040000000E0000000D000000050000000E0000000D000000050000000E0000000D000000060000000E0000000D000000060000000E0000000D000000070000000E0000000D000000070000000E0000000D000000080000000E0000000D000000080000000E0000000D000000090000000E0000000D000000090000000E0000000D0000000A0000000E0000000D0000000A0000000E0000000D0000000B0000000E0000000D0000000B0000000E0000000D0000000C0000000E0000000D0000000C0000000E0000000D0000000D0000000E0000000D0000000D0000000E0000000D0000000E0000000E0000000D0000000E0000000E0000000D0000000F0000000E0000000D0000000F0000000E0000000D000000100000000E0000000D000000100000000E0000000D000000000000000F0000000D000000000000000F0000000D000000010000000F0000000D000000010000000F0000000D000000020000000F0000000D000000020000000F0000000D000000030000000F0000000D000000030000000F0000000D000000040000000F0000000D000000040000000F0000000D000000050000000F0000000D000000050000000F0000000D000000060000000F0000000D000000060000000F0000000D000000070000000F0000000D000000070000000F0000000D000000080000000F0000000D000000080000000F0000000D000000090000000F0000000D000000090000000F0000000D0000000A0000000F0000000D0000000A0000000F0000000D0000000B0000000F0000000D0000000B0000000F0000000D0000000C0000000F0000000D0000000C0000000F0000000D0000000D0000000F0000000D0000000D0000000F0000000D0000000E0000000F0000000D0000000E0000000F0000000D0000000F0000000F0000000D0000000F0000000F0000000D000000100000000F0000000D000000100000000F0000000D00000000000000100000000D00000000000000100000000D00000001000000100000000D00000001000000100000000D00000002000000100000000D00000002000000100000000D00000003000000100000000D00000003000000100000000D00000004000000100000000D00000004000000100000000D00000005000000100000000D00000005000000100000000D00000006000000100000000D00000006000000100000000D00000007000000100000000D00000007000000100000000D00000008000000100000000D00000008000000100000000D00000009000000100000000D00000009000000100000000D0000000A000000100000000D0000000A000000100000000D0000000B000000100000000D0000000B000000100000000D0000000C000000100000000D0000000C000000100000000D0000000D000000100000000D0000000D000000100000000D0000000E000000100000000D0000000E000000100000000D0000000F000000100000000D0000000F000000100000000D00000010000000100000000D00000010000000100000000D00000000000000000000000E00000000000000000000000E00000001000000000000000E00000001000000000000000E00000002000000000000000E00000002000000000000000E00000003000000000000000E00000003000000000000000E00000004000000000000000E00000004000000000000000E00000005000000000000000E00000005000000000000000E00000006000000000000000E00000006000000000000000E00000007000000000000000E00000007000000000000000E00000008000000000000000E00000008000000000000000E00000009000000000000000E00000009000000000000000E0000000A000000000000000E0000000A000000000000000E0000000B000000000000000E0000000B000000000000000E0000000C000000000000000E0000000C000000000000000E0000000D000000000000000E0000000D000000000000000E0000000E000000000000000E0000000E000000000000000E0000000F000000000000000E0000000F000000000000000E00000010000000000000000E00000010000000000000000E00000000000000010000000E00000000000000010000000E00000001000000010000000E00000001000000010000000E00000002000000010000000E00000002000000010000000E00000003000000010000000E00000003000000010000000E00000004000000010000000E00000004000000010000000E00000005000000010000000E00000005000000010000000E00000006000000010000000E00000006000000010000000E00000007000000010000000E00000007000000010000000E00000008000000010000000E00000008000000010000000E00000009000000010000000E00000009000000010000000E0000000A000000010000000E0000000A000000010000000E0000000B000000010000000E0000000B000000010000000E0000000C000000010000000E0000000C000000010000000E0000000D000000010000000E0000000D000000010000000E0000000E000000010000000E0000000E000000010000000E0000000F000000010000000E0000000F000000010000000E00000010000000010000000E00000010000000010000000E00000000000000020000000E00000000000000020000000E00000001000000020000000E00000001000000020000000E00000002000000020000000E00000002000000020000000E00000003000000020000000E00000003000000020000000E00000004000000020000000E00000004000000020000000E00000005000000020000000E00000005000000020000000E00000006000000020000000E00000006000000020000000E00000007000000020000000E00000007000000020000000E00000008000000020000000E00000008000000020000000E00000009000000020000000E00000009000000020000000E0000000A000000020000000E0000000A000000020000000E0000000B000000020000000E0000000B000000020000000E0000000C000000020000000E0000000C000000020000000E0000000D000000020000000E0000000D000000020000000E0000000E000000020000000E0000000E000000020000000E0000000F000000020000000E0000000F000000020000000E00000010000000020000000E00000010000000020000000E00000000000000030000000E00000000000000030000000E00000001000000030000000E00000001000000030000000E00000002000000030000000E00000002000000030000000E00000003000000030000000E00000003000000030000000E00000004000000030000000E00000004000000030000000E00000005000000030000000E00000005000000030000000E00000006000000030000000E00000006000000030000000E00000007000000030000000E00000007000000030000000E00000008000000030000000E00000008000000030000000E00000009000000030000000E00000009000000030000000E0000000A000000030000000E0000000A000000030000000E0000000B000000030000000E0000000B000000030000000E0000000C000000030000000E0000000C000000030000000E0000000D000000030000000E0000000D000000030000000E0000000E000000030000000E0000000E000000030000000E0000000F000000030000000E0000000F000000030000000E00000010000000030000000E00000010000000030000000E00000000000000040000000E00000000000000040000000E00000001000000040000000E00000001000000040000000E00000002000000040000000E00000002000000040000000E00000003000000040000000E00000003000000040000000E00000004000000040000000E00000004000000040000000E00000005000000040000000E00000005000000040000000E00000006000000040000000E00000006000000040000000E00000007000000040000000E00000007000000040000000E00000008000000040000000E00000008000000040000000E00000009000000040000000E00000009000000040000000E0000000A000000040000000E0000000A000000040000000E0000000B000000040000000E0000000B000000040000000E0000000C000000040000000E0000000C000000040000000E0000000D000000040000000E0000000D000000040000000E0000000E000000040000000E0000000E000000040000000E0000000F000000040000000E0000000F000000040000000E00000010000000040000000E00000010000000040000000E00000000000000050000000E00000000000000050000000E00000001000000050000000E00000001000000050000000E00000002000000050000000E00000002000000050000000E00000003000000050000000E00000003000000050000000E00000004000000050000000E00000004000000050000000E00000005000000050000000E00000005000000050000000E00000006000000050000000E00000006000000050000000E00000007000000050000000E00000007000000050000000E00000008000000050000000E00000008000000050000000E00000009000000050000000E00000009000000050000000E0000000A000000050000000E0000000A000000050000000E0000000B000000050000000E0000000B000000050000000E0000000C000000050000000E0000000C000000050000000E0000000D000000050000000E0000000D000000050000000E0000000E000000050000000E0000000E000000050000000E0000000F000000050000000E0000000F000000050000000E00000010000000050000000E00000010000000050000000E00000000000000060000000E00000000000000060000000E00000001000000060000000E00000001000000060000000E00000002000000060000000E00000002000000060000000E00000003000000060000000E00000003000000060000000E00000004000000060000000E00000004000000060000000E00000005000000060000000E00000005000000060000000E00000006000000060000000E00000006000000060000000E00000007000000060000000E00000007000000060000000E00000008000000060000000E00000008000000060000000E00000009000000060000000E00000009000000060000000E0000000A000000060000000E0000000A000000060000000E0000000B000000060000000E0000000B000000060000000E0000000C000000060000000E0000000C000000060000000E0000000D000000060000000E0000000D000000060000000E0000000E000000060000000E0000000E000000060000000E0000000F000000060000000E0000000F000000060000000E00000010000000060000000E00000010000000060000000E00000000000000070000000E00000000000000070000000E00000001000000070000000E00000001000000070000000E00000002000000070000000E00000002000000070000000E00000003000000070000000E00000003000000070000000E00000004000000070000000E00000004000000070000000E00000005000000070000000E00000005000000070000000E00000006000000070000000E00000006000000070000000E00000007000000070000000E00000007000000070000000E00000008000000070000000E00000008000000070000000E00000009000000070000000E00000009000000070000000E0000000A000000070000000E0000000A000000070000000E0000000B000000070000000E0000000B000000070000000E0000000C000000070000000E0000000C000000070000000E0000000D000000070000000E0000000D000000070000000E0000000E000000070000000E0000000E000000070000000E0000000F000000070000000E0000000F000000070000000E00000010000000070000000E00000010000000070000000E00000000000000080000000E00000000000000080000000E00000001000000080000000E00000001000000080000000E00000002000000080000000E00000002000000080000000E00000003000000080000000E00000003000000080000000E00000004000000080000000E00000004000000080000000E00000005000000080000000E00000005000000080000000E00000006000000080000000E00000006000000080000000E00000007000000080000000E00000007000000080000000E00000008000000080000000E00000008000000080000000E00000009000000080000000E00000009000000080000000E0000000A000000080000000E0000000A000000080000000E0000000B000000080000000E0000000B000000080000000E0000000C000000080000000E0000000C000000080000000E0000000D000000080000000E0000000D000000080000000E0000000E000000080000000E0000000E000000080000000E0000000F000000080000000E0000000F000000080000000E00000010000000080000000E00000010000000080000000E00000000000000090000000E00000000000000090000000E00000001000000090000000E00000001000000090000000E00000002000000090000000E00000002000000090000000E00000003000000090000000E00000003000000090000000E00000004000000090000000E00000004000000090000000E00000005000000090000000E00000005000000090000000E00000006000000090000000E00000006000000090000000E00000007000000090000000E00000007000000090000000E00000008000000090000000E00000008000000090000000E00000009000000090000000E00000009000000090000000E0000000A000000090000000E0000000A000000090000000E0000000B000000090000000E0000000B000000090000000E0000000C000000090000000E0000000C000000090000000E0000000D000000090000000E0000000D000000090000000E0000000E000000090000000E0000000E000000090000000E0000000F000000090000000E0000000F000000090000000E00000010000000090000000E00000010000000090000000E000000000000000A0000000E000000000000000A0000000E000000010000000A0000000E000000010000000A0000000E000000020000000A0000000E000000020000000A0000000E000000030000000A0000000E000000030000000A0000000E000000040000000A0000000E000000040000000A0000000E000000050000000A0000000E000000050000000A0000000E000000060000000A0000000E000000060000000A0000000E000000070000000A0000000E000000070000000A0000000E000000080000000A0000000E000000080000000A0000000E000000090000000A0000000E000000090000000A0000000E0000000A0000000A0000000E0000000A0000000A0000000E0000000B0000000A0000000E0000000B0000000A0000000E0000000C0000000A0000000E0000000C0000000A0000000E0000000D0000000A0000000E0000000D0000000A0000000E0000000E0000000A0000000E0000000E0000000A0000000E0000000F0000000A0000000E0000000F0000000A0000000E000000100000000A0000000E000000100000000A0000000E000000000000000B0000000E000000000000000B0000000E000000010000000B0000000E000000010000000B0000000E000000020000000B0000000E000000020000000B0000000E000000030000000B0000000E000000030000000B0000000E000000040000000B0000000E000000040000000B0000000E000000050000000B0000000E000000050000000B0000000E000000060000000B0000000E000000060000000B0000000E000000070000000B0000000E000000070000000B0000000E000000080000000B0000000E000000080000000B0000000E000000090000000B0000000E000000090000000B0000000E0000000A0000000B0000000E0000000A0000000B0000000E0000000B0000000B0000000E0000000B0000000B0000000E0000000C0000000B0000000E0000000C0000000B0000000E0000000D0000000B0000000E0000000D0000000B0000000E0000000E0000000B0000000E0000000E0000000B0000000E0000000F0000000B0000000E0000000F0000000B0000000E000000100000000B0000000E000000100000000B0000000E000000000000000C0000000E000000000000000C0000000E000000010000000C0000000E000000010000000C0000000E000000020000000C0000000E000000020000000C0000000E000000030000000C0000000E000000030000000C0000000E000000040000000C0000000E000000040000000C0000000E000000050000000C0000000E000000050000000C0000000E000000060000000C0000000E000000060000000C0000000E000000070000000C0000000E000000070000000C0000000E000000080000000C0000000E000000080000000C0000000E000000090000000C0000000E000000090000000C0000000E0000000A0000000C0000000E0000000A0000000C0000000E0000000B0000000C0000000E0000000B0000000C0000000E0000000C0000000C0000000E0000000C0000000C0000000E0000000D0000000C0000000E0000000D0000000C0000000E0000000E0000000C0000000E0000000E0000000C0000000E0000000F0000000C0000000E0000000F0000000C0000000E000000100000000C0000000E000000100000000C0000000E000000000000000D0000000E000000000000000D0000000E000000010000000D0000000E000000010000000D0000000E000000020000000D0000000E000000020000000D0000000E000000030000000D0000000E000000030000000D0000000E000000040000000D0000000E000000040000000D0000000E000000050000000D0000000E000000050000000D0000000E000000060000000D0000000E000000060000000D0000000E000000070000000D0000000E000000070000000D0000000E000000080000000D0000000E000000080000000D0000000E000000090000000D0000000E000000090000000D0000000E0000000A0000000D0000000E0000000A0000000D0000000E0000000B0000000D0000000E0000000B0000000D0000000E0000000C0000000D0000000E0000000C0000000D0000000E0000000D0000000D0000000E0000000D0000000D0000000E0000000E0000000D0000000E0000000E0000000D0000000E0000000F0000000D0000000E0000000F0000000D0000000E000000100000000D0000000E000000100000000D0000000E000000000000000E0000000E000000000000000E0000000E000000010000000E0000000E000000010000000E0000000E000000020000000E0000000E000000020000000E0000000E000000030000000E0000000E000000030000000E0000000E000000040000000E0000000E000000040000000E0000000E000000050000000E0000000E000000050000000E0000000E000000060000000E0000000E000000060000000E0000000E000000070000000E0000000E000000070000000E0000000E000000080000000E0000000E000000080000000E0000000E000000090000000E0000000E000000090000000E0000000E0000000A0000000E0000000E0000000A0000000E0000000E0000000B0000000E0000000E0000000B0000000E0000000E0000000C0000000E0000000E0000000C0000000E0000000E0000000D0000000E0000000E0000000D0000000E0000000E0000000E0000000E0000000E0000000E0000000E0000000E0000000F0000000E0000000E0000000F0000000E0000000E000000100000000E0000000E000000100000000E0000000E000000000000000F0000000E000000000000000F0000000E000000010000000F0000000E000000010000000F0000000E000000020000000F0000000E000000020000000F0000000E000000030000000F0000000E000000030000000F0000000E000000040000000F0000000E000000040000000F0000000E000000050000000F0000000E000000050000000F0000000E000000060000000F0000000E000000060000000F0000000E000000070000000F0000000E000000070000000F0000000E000000080000000F0000000E000000080000000F0000000E000000090000000F0000000E000000090000000F0000000E0000000A0000000F0000000E0000000A0000000F0000000E0000000B0000000F0000000E0000000B0000000F0000000E0000000C0000000F0000000E0000000C0000000F0000000E0000000D0000000F0000000E0000000D0000000F0000000E0000000E0000000F0000000E0000000E0000000F0000000E0000000F0000000F0000000E0000000F0000000F0000000E000000100000000F0000000E000000100000000F0000000E00000000000000100000000E00000000000000100000000E00000001000000100000000E00000001000000100000000E00000002000000100000000E00000002000000100000000E00000003000000100000000E00000003000000100000000E00000004000000100000000E00000004000000100000000E00000005000000100000000E00000005000000100000000E00000006000000100000000E00000006000000100000000E00000007000000100000000E00000007000000100000000E00000008000000100000000E00000008000000100000000E00000009000000100000000E00000009000000100000000E0000000A000000100000000E0000000A000000100000000E0000000B000000100000000E0000000B000000100000000E0000000C000000100000000E0000000C000000100000000E0000000D000000100000000E0000000D000000100000000E0000000E000000100000000E0000000E000000100000000E0000000F000000100000000E0000000F000000100000000E00000010000000100000000E00000010000000100000000E00000000000000000000000F00000000000000000000000F00000001000000000000000F00000001000000000000000F00000002000000000000000F00000002000000000000000F00000003000000000000000F00000003000000000000000F00000004000000000000000F00000004000000000000000F00000005000000000000000F00000005000000000000000F00000006000000000000000F00000006000000000000000F00000007000000000000000F00000007000000000000000F00000008000000000000000F00000008000000000000000F00000009000000000000000F00000009000000000000000F0000000A000000000000000F0000000A000000000000000F0000000B000000000000000F0000000B000000000000000F0000000C000000000000000F0000000C000000000000000F0000000D000000000000000F0000000D000000000000000F0000000E000000000000000F0000000E000000000000000F0000000F000000000000000F0000000F000000000000000F00000010000000000000000F00000010000000000000000F00000000000000010000000F00000000000000010000000F00000001000000010000000F00000001000000010000000F00000002000000010000000F00000002000000010000000F00000003000000010000000F00000003000000010000000F00000004000000010000000F00000004000000010000000F00000005000000010000000F00000005000000010000000F00000006000000010000000F00000006000000010000000F00000007000000010000000F00000007000000010000000F00000008000000010000000F00000008000000010000000F00000009000000010000000F00000009000000010000000F0000000A000000010000000F0000000A000000010000000F0000000B000000010000000F0000000B000000010000000F0000000C000000010000000F0000000C000000010000000F0000000D000000010000000F0000000D000000010000000F0000000E000000010000000F0000000E000000010000000F0000000F000000010000000F0000000F000000010000000F00000010000000010000000F00000010000000010000000F00000000000000020000000F00000000000000020000000F00000001000000020000000F00000001000000020000000F00000002000000020000000F00000002000000020000000F00000003000000020000000F00000003000000020000000F00000004000000020000000F00000004000000020000000F00000005000000020000000F00000005000000020000000F00000006000000020000000F00000006000000020000000F00000007000000020000000F00000007000000020000000F00000008000000020000000F00000008000000020000000F00000009000000020000000F00000009000000020000000F0000000A000000020000000F0000000A000000020000000F0000000B000000020000000F0000000B000000020000000F0000000C000000020000000F0000000C000000020000000F0000000D000000020000000F0000000D000000020000000F0000000E000000020000000F0000000E000000020000000F0000000F000000020000000F0000000F000000020000000F00000010000000020000000F00000010000000020000000F00000000000000030000000F00000000000000030000000F00000001000000030000000F00000001000000030000000F00000002000000030000000F00000002000000030000000F00000003000000030000000F00000003000000030000000F00000004000000030000000F00000004000000030000000F00000005000000030000000F00000005000000030000000F00000006000000030000000F00000006000000030000000F00000007000000030000000F00000007000000030000000F00000008000000030000000F00000008000000030000000F00000009000000030000000F00000009000000030000000F0000000A000000030000000F0000000A000000030000000F0000000B000000030000000F0000000B000000030000000F0000000C000000030000000F0000000C000000030000000F0000000D000000030000000F0000000D000000030000000F0000000E000000030000000F0000000E000000030000000F0000000F000000030000000F0000000F000000030000000F00000010000000030000000F00000010000000030000000F00000000000000040000000F00000000000000040000000F00000001000000040000000F00000001000000040000000F00000002000000040000000F00000002000000040000000F00000003000000040000000F00000003000000040000000F00000004000000040000000F00000004000000040000000F00000005000000040000000F00000005000000040000000F00000006000000040000000F00000006000000040000000F00000007000000040000000F00000007000000040000000F00000008000000040000000F00000008000000040000000F00000009000000040000000F00000009000000040000000F0000000A000000040000000F0000000A000000040000000F0000000B000000040000000F0000000B000000040000000F0000000C000000040000000F0000000C000000040000000F0000000D000000040000000F0000000D000000040000000F0000000E000000040000000F0000000E000000040000000F0000000F000000040000000F0000000F000000040000000F00000010000000040000000F00000010000000040000000F00000000000000050000000F00000000000000050000000F00000001000000050000000F00000001000000050000000F00000002000000050000000F00000002000000050000000F00000003000000050000000F00000003000000050000000F00000004000000050000000F00000004000000050000000F00000005000000050000000F00000005000000050000000F00000006000000050000000F00000006000000050000000F00000007000000050000000F00000007000000050000000F00000008000000050000000F00000008000000050000000F00000009000000050000000F00000009000000050000000F0000000A000000050000000F0000000A000000050000000F0000000B000000050000000F0000000B000000050000000F0000000C000000050000000F0000000C000000050000000F0000000D000000050000000F0000000D000000050000000F0000000E000000050000000F0000000E000000050000000F0000000F000000050000000F0000000F000000050000000F00000010000000050000000F00000010000000050000000F00000000000000060000000F00000000000000060000000F00000001000000060000000F00000001000000060000000F00000002000000060000000F00000002000000060000000F00000003000000060000000F00000003000000060000000F00000004000000060000000F00000004000000060000000F00000005000000060000000F00000005000000060000000F00000006000000060000000F00000006000000060000000F00000007000000060000000F00000007000000060000000F00000008000000060000000F00000008000000060000000F00000009000000060000000F00000009000000060000000F0000000A000000060000000F0000000A000000060000000F0000000B000000060000000F0000000B000000060000000F0000000C000000060000000F0000000C000000060000000F0000000D000000060000000F0000000D000000060000000F0000000E000000060000000F0000000E000000060000000F0000000F000000060000000F0000000F000000060000000F00000010000000060000000F00000010000000060000000F00000000000000070000000F00000000000000070000000F00000001000000070000000F00000001000000070000000F00000002000000070000000F00000002000000070000000F00000003000000070000000F00000003000000070000000F00000004000000070000000F00000004000000070000000F00000005000000070000000F00000005000000070000000F00000006000000070000000F00000006000000070000000F00000007000000070000000F00000007000000070000000F00000008000000070000000F00000008000000070000000F00000009000000070000000F00000009000000070000000F0000000A000000070000000F0000000A000000070000000F0000000B000000070000000F0000000B000000070000000F0000000C000000070000000F0000000C000000070000000F0000000D000000070000000F0000000D000000070000000F0000000E000000070000000F0000000E000000070000000F0000000F000000070000000F0000000F000000070000000F00000010000000070000000F00000010000000070000000F00000000000000080000000F00000000000000080000000F00000001000000080000000F00000001000000080000000F00000002000000080000000F00000002000000080000000F00000003000000080000000F00000003000000080000000F00000004000000080000000F00000004000000080000000F00000005000000080000000F00000005000000080000000F00000006000000080000000F00000006000000080000000F00000007000000080000000F00000007000000080000000F00000008000000080000000F00000008000000080000000F00000009000000080000000F00000009000000080000000F0000000A000000080000000F0000000A000000080000000F0000000B000000080000000F0000000B000000080000000F0000000C000000080000000F0000000C000000080000000F0000000D000000080000000F0000000D000000080000000F0000000E000000080000000F0000000E000000080000000F0000000F000000080000000F0000000F000000080000000F00000010000000080000000F00000010000000080000000F00000000000000090000000F00000000000000090000000F00000001000000090000000F00000001000000090000000F00000002000000090000000F00000002000000090000000F00000003000000090000000F00000003000000090000000F00000004000000090000000F00000004000000090000000F00000005000000090000000F00000005000000090000000F00000006000000090000000F00000006000000090000000F00000007000000090000000F00000007000000090000000F00000008000000090000000F00000008000000090000000F00000009000000090000000F00000009000000090000000F0000000A000000090000000F0000000A000000090000000F0000000B000000090000000F0000000B000000090000000F0000000C000000090000000F0000000C000000090000000F0000000D000000090000000F0000000D000000090000000F0000000E000000090000000F0000000E000000090000000F0000000F000000090000000F0000000F000000090000000F00000010000000090000000F00000010000000090000000F000000000000000A0000000F000000000000000A0000000F000000010000000A0000000F000000010000000A0000000F000000020000000A0000000F000000020000000A0000000F000000030000000A0000000F000000030000000A0000000F000000040000000A0000000F000000040000000A0000000F000000050000000A0000000F000000050000000A0000000F000000060000000A0000000F000000060000000A0000000F000000070000000A0000000F000000070000000A0000000F000000080000000A0000000F000000080000000A0000000F000000090000000A0000000F000000090000000A0000000F0000000A0000000A0000000F0000000A0000000A0000000F0000000B0000000A0000000F0000000B0000000A0000000F0000000C0000000A0000000F0000000C0000000A0000000F0000000D0000000A0000000F0000000D0000000A0000000F0000000E0000000A0000000F0000000E0000000A0000000F0000000F0000000A0000000F0000000F0000000A0000000F000000100000000A0000000F000000100000000A0000000F000000000000000B0000000F000000000000000B0000000F000000010000000B0000000F000000010000000B0000000F000000020000000B0000000F000000020000000B0000000F000000030000000B0000000F000000030000000B0000000F000000040000000B0000000F000000040000000B0000000F000000050000000B0000000F000000050000000B0000000F000000060000000B0000000F000000060000000B0000000F000000070000000B0000000F000000070000000B0000000F000000080000000B0000000F000000080000000B0000000F000000090000000B0000000F000000090000000B0000000F0000000A0000000B0000000F0000000A0000000B0000000F0000000B0000000B0000000F0000000B0000000B0000000F0000000C0000000B0000000F0000000C0000000B0000000F0000000D0000000B0000000F0000000D0000000B0000000F0000000E0000000B0000000F0000000E0000000B0000000F0000000F0000000B0000000F0000000F0000000B0000000F000000100000000B0000000F000000100000000B0000000F000000000000000C0000000F000000000000000C0000000F000000010000000C0000000F000000010000000C0000000F000000020000000C0000000F000000020000000C0000000F000000030000000C0000000F000000030000000C0000000F000000040000000C0000000F000000040000000C0000000F000000050000000C0000000F000000050000000C0000000F000000060000000C0000000F000000060000000C0000000F000000070000000C0000000F000000070000000C0000000F000000080000000C0000000F000000080000000C0000000F000000090000000C0000000F000000090000000C0000000F0000000A0000000C0000000F0000000A0000000C0000000F0000000B0000000C0000000F0000000B0000000C0000000F0000000C0000000C0000000F0000000C0000000C0000000F0000000D0000000C0000000F0000000D0000000C0000000F0000000E0000000C0000000F0000000E0000000C0000000F0000000F0000000C0000000F0000000F0000000C0000000F000000100000000C0000000F000000100000000C0000000F000000000000000D0000000F000000000000000D0000000F000000010000000D0000000F000000010000000D0000000F000000020000000D0000000F000000020000000D0000000F000000030000000D0000000F000000030000000D0000000F000000040000000D0000000F000000040000000D0000000F000000050000000D0000000F000000050000000D0000000F000000060000000D0000000F000000060000000D0000000F000000070000000D0000000F000000070000000D0000000F000000080000000D0000000F000000080000000D0000000F000000090000000D0000000F000000090000000D0000000F0000000A0000000D0000000F0000000A0000000D0000000F0000000B0000000D0000000F0000000B0000000D0000000F0000000C0000000D0000000F0000000C0000000D0000000F0000000D0000000D0000000F0000000D0000000D0000000F0000000E0000000D0000000F0000000E0000000D0000000F0000000F0000000D0000000F0000000F0000000D0000000F000000100000000D0000000F000000100000000D0000000F000000000000000E0000000F000000000000000E0000000F000000010000000E0000000F000000010000000E0000000F000000020000000E0000000F000000020000000E0000000F000000030000000E0000000F000000030000000E0000000F000000040000000E0000000F000000040000000E0000000F000000050000000E0000000F000000050000000E0000000F000000060000000E0000000F000000060000000E0000000F000000070000000E0000000F000000070000000E0000000F000000080000000E0000000F000000080000000E0000000F000000090000000E0000000F000000090000000E0000000F0000000A0000000E0000000F0000000A0000000E0000000F0000000B0000000E0000000F0000000B0000000E0000000F0000000C0000000E0000000F0000000C0000000E0000000F0000000D0000000E0000000F0000000D0000000E0000000F0000000E0000000E0000000F0000000E0000000E0000000F0000000F0000000E0000000F0000000F0000000E0000000F000000100000000E0000000F000000100000000E0000000F000000000000000F0000000F000000000000000F0000000F000000010000000F0000000F000000010000000F0000000F000000020000000F0000000F000000020000000F0000000F000000030000000F0000000F000000030000000F0000000F000000040000000F0000000F000000040000000F0000000F000000050000000F0000000F000000050000000F0000000F000000060000000F0000000F000000060000000F0000000F000000070000000F0000000F000000070000000F0000000F000000080000000F0000000F000000080000000F0000000F000000090000000F0000000F000000090000000F0000000F0000000A0000000F0000000F0000000A0000000F0000000F0000000B0000000F0000000F0000000B0000000F0000000F0000000C0000000F0000000F0000000C0000000F0000000F0000000D0000000F0000000F0000000D0000000F0000000F0000000E0000000F0000000F0000000E0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000F000000100000000F0000000F000000100000000F0000000F00000000000000100000000F00000000000000100000000F00000001000000100000000F00000001000000100000000F00000002000000100000000F00000002000000100000000F00000003000000100000000F00000003000000100000000F00000004000000100000000F00000004000000100000000F00000005000000100000000F00000005000000100000000F00000006000000100000000F00000006000000100000000F00000007000000100000000F00000007000000100000000F00000008000000100000000F00000008000000100000000F00000009000000100000000F00000009000000100000000F0000000A000000100000000F0000000A000000100000000F0000000B000000100000000F0000000B000000100000000F0000000C000000100000000F0000000C000000100000000F0000000D000000100000000F0000000D000000100000000F0000000E000000100000000F0000000E000000100000000F0000000F000000100000000F0000000F000000100000000F00000010000000100000000F00000010000000100000000F0000000000000000000000100000000000000000000000100000000100000000000000100000000100000000000000100000000200000000000000100000000200000000000000100000000300000000000000100000000300000000000000100000000400000000000000100000000400000000000000100000000500000000000000100000000500000000000000100000000600000000000000100000000600000000000000100000000700000000000000100000000700000000000000100000000800000000000000100000000800000000000000100000000900000000000000100000000900000000000000100000000A00000000000000100000000A00000000000000100000000B00000000000000100000000B00000000000000100000000C00000000000000100000000C00000000000000100000000D00000000000000100000000D00000000000000100000000E00000000000000100000000E00000000000000100000000F00000000000000100000000F00000000000000100000001000000000000000100000001000000000000000100000000000000001000000100000000000000001000000100000000100000001000000100000000100000001000000100000000200000001000000100000000200000001000000100000000300000001000000100000000300000001000000100000000400000001000000100000000400000001000000100000000500000001000000100000000500000001000000100000000600000001000000100000000600000001000000100000000700000001000000100000000700000001000000100000000800000001000000100000000800000001000000100000000900000001000000100000000900000001000000100000000A00000001000000100000000A00000001000000100000000B00000001000000100000000B00000001000000100000000C00000001000000100000000C00000001000000100000000D00000001000000100000000D00000001000000100000000E00000001000000100000000E00000001000000100000000F00000001000000100000000F00000001000000100000001000000001000000100000001000000001000000100000000000000002000000100000000000000002000000100000000100000002000000100000000100000002000000100000000200000002000000100000000200000002000000100000000300000002000000100000000300000002000000100000000400000002000000100000000400000002000000100000000500000002000000100000000500000002000000100000000600000002000000100000000600000002000000100000000700000002000000100000000700000002000000100000000800000002000000100000000800000002000000100000000900000002000000100000000900000002000000100000000A00000002000000100000000A00000002000000100000000B00000002000000100000000B00000002000000100000000C00000002000000100000000C00000002000000100000000D00000002000000100000000D00000002000000100000000E00000002000000100000000E00000002000000100000000F00000002000000100000000F00000002000000100000001000000002000000100000001000000002000000100000000000000003000000100000000000000003000000100000000100000003000000100000000100000003000000100000000200000003000000100000000200000003000000100000000300000003000000100000000300000003000000100000000400000003000000100000000400000003000000100000000500000003000000100000000500000003000000100000000600000003000000100000000600000003000000100000000700000003000000100000000700000003000000100000000800000003000000100000000800000003000000100000000900000003000000100000000900000003000000100000000A00000003000000100000000A00000003000000100000000B00000003000000100000000B00000003000000100000000C00000003000000100000000C00000003000000100000000D00000003000000100000000D00000003000000100000000E00000003000000100000000E00000003000000100000000F00000003000000100000000F00000003000000100000001000000003000000100000001000000003000000100000000000000004000000100000000000000004000000100000000100000004000000100000000100000004000000100000000200000004000000100000000200000004000000100000000300000004000000100000000300000004000000100000000400000004000000100000000400000004000000100000000500000004000000100000000500000004000000100000000600000004000000100000000600000004000000100000000700000004000000100000000700000004000000100000000800000004000000100000000800000004000000100000000900000004000000100000000900000004000000100000000A00000004000000100000000A00000004000000100000000B00000004000000100000000B00000004000000100000000C00000004000000100000000C00000004000000100000000D00000004000000100000000D00000004000000100000000E00000004000000100000000E00000004000000100000000F00000004000000100000000F00000004000000100000001000000004000000100000001000000004000000100000000000000005000000100000000000000005000000100000000100000005000000100000000100000005000000100000000200000005000000100000000200000005000000100000000300000005000000100000000300000005000000100000000400000005000000100000000400000005000000100000000500000005000000100000000500000005000000100000000600000005000000100000000600000005000000100000000700000005000000100000000700000005000000100000000800000005000000100000000800000005000000100000000900000005000000100000000900000005000000100000000A00000005000000100000000A00000005000000100000000B00000005000000100000000B00000005000000100000000C00000005000000100000000C00000005000000100000000D00000005000000100000000D00000005000000100000000E00000005000000100000000E00000005000000100000000F00000005000000100000000F00000005000000100000001000000005000000100000001000000005000000100000000000000006000000100000000000000006000000100000000100000006000000100000000100000006000000100000000200000006000000100000000200000006000000100000000300000006000000100000000300000006000000100000000400000006000000100000000400000006000000100000000500000006000000100000000500000006000000100000000600000006000000100000000600000006000000100000000700000006000000100000000700000006000000100000000800000006000000100000000800000006000000100000000900000006000000100000000900000006000000100000000A00000006000000100000000A00000006000000100000000B00000006000000100000000B00000006000000100000000C00000006000000100000000C00000006000000100000000D00000006000000100000000D00000006000000100000000E00000006000000100000000E00000006000000100000000F00000006000000100000000F00000006000000100000001000000006000000100000001000000006000000100000000000000007000000100000000000000007000000100000000100000007000000100000000100000007000000100000000200000007000000100000000200000007000000100000000300000007000000100000000300000007000000100000000400000007000000100000000400000007000000100000000500000007000000100000000500000007000000100000000600000007000000100000000600000007000000100000000700000007000000100000000700000007000000100000000800000007000000100000000800000007000000100000000900000007000000100000000900000007000000100000000A00000007000000100000000A00000007000000100000000B00000007000000100000000B00000007000000100000000C00000007000000100000000C00000007000000100000000D00000007000000100000000D00000007000000100000000E00000007000000100000000E00000007000000100000000F00000007000000100000000F00000007000000100000001000000007000000100000001000000007000000100000000000000008000000100000000000000008000000100000000100000008000000100000000100000008000000100000000200000008000000100000000200000008000000100000000300000008000000100000000300000008000000100000000400000008000000100000000400000008000000100000000500000008000000100000000500000008000000100000000600000008000000100000000600000008000000100000000700000008000000100000000700000008000000100000000800000008000000100000000800000008000000100000000900000008000000100000000900000008000000100000000A00000008000000100000000A00000008000000100000000B00000008000000100000000B00000008000000100000000C00000008000000100000000C00000008000000100000000D00000008000000100000000D00000008000000100000000E00000008000000100000000E00000008000000100000000F00000008000000100000000F00000008000000100000001000000008000000100000001000000008000000100000000000000009000000100000000000000009000000100000000100000009000000100000000100000009000000100000000200000009000000100000000200000009000000100000000300000009000000100000000300000009000000100000000400000009000000100000000400000009000000100000000500000009000000100000000500000009000000100000000600000009000000100000000600000009000000100000000700000009000000100000000700000009000000100000000800000009000000100000000800000009000000100000000900000009000000100000000900000009000000100000000A00000009000000100000000A00000009000000100000000B00000009000000100000000B00000009000000100000000C00000009000000100000000C00000009000000100000000D00000009000000100000000D00000009000000100000000E00000009000000100000000E00000009000000100000000F00000009000000100000000F0000000900000010000000100000000900000010000000100000000900000010000000000000000A00000010000000000000000A00000010000000010000000A00000010000000010000000A00000010000000020000000A00000010000000020000000A00000010000000030000000A00000010000000030000000A00000010000000040000000A00000010000000040000000A00000010000000050000000A00000010000000050000000A00000010000000060000000A00000010000000060000000A00000010000000070000000A00000010000000070000000A00000010000000080000000A00000010000000080000000A00000010000000090000000A00000010000000090000000A000000100000000A0000000A000000100000000A0000000A000000100000000B0000000A000000100000000B0000000A000000100000000C0000000A000000100000000C0000000A000000100000000D0000000A000000100000000D0000000A000000100000000E0000000A000000100000000E0000000A000000100000000F0000000A000000100000000F0000000A00000010000000100000000A00000010000000100000000A00000010000000000000000B00000010000000000000000B00000010000000010000000B00000010000000010000000B00000010000000020000000B00000010000000020000000B00000010000000030000000B00000010000000030000000B00000010000000040000000B00000010000000040000000B00000010000000050000000B00000010000000050000000B00000010000000060000000B00000010000000060000000B00000010000000070000000B00000010000000070000000B00000010000000080000000B00000010000000080000000B00000010000000090000000B00000010000000090000000B000000100000000A0000000B000000100000000A0000000B000000100000000B0000000B000000100000000B0000000B000000100000000C0000000B000000100000000C0000000B000000100000000D0000000B000000100000000D0000000B000000100000000E0000000B000000100000000E0000000B000000100000000F0000000B000000100000000F0000000B00000010000000100000000B00000010000000100000000B00000010000000000000000C00000010000000000000000C00000010000000010000000C00000010000000010000000C00000010000000020000000C00000010000000020000000C00000010000000030000000C00000010000000030000000C00000010000000040000000C00000010000000040000000C00000010000000050000000C00000010000000050000000C00000010000000060000000C00000010000000060000000C00000010000000070000000C00000010000000070000000C00000010000000080000000C00000010000000080000000C00000010000000090000000C00000010000000090000000C000000100000000A0000000C000000100000000A0000000C000000100000000B0000000C000000100000000B0000000C000000100000000C0000000C000000100000000C0000000C000000100000000D0000000C000000100000000D0000000C000000100000000E0000000C000000100000000E0000000C000000100000000F0000000C000000100000000F0000000C00000010000000100000000C00000010000000100000000C00000010000000000000000D00000010000000000000000D00000010000000010000000D00000010000000010000000D00000010000000020000000D00000010000000020000000D00000010000000030000000D00000010000000030000000D00000010000000040000000D00000010000000040000000D00000010000000050000000D00000010000000050000000D00000010000000060000000D00000010000000060000000D00000010000000070000000D00000010000000070000000D00000010000000080000000D00000010000000080000000D00000010000000090000000D00000010000000090000000D000000100000000A0000000D000000100000000A0000000D000000100000000B0000000D000000100000000B0000000D000000100000000C0000000D000000100000000C0000000D000000100000000D0000000D000000100000000D0000000D000000100000000E0000000D000000100000000E0000000D000000100000000F0000000D000000100000000F0000000D00000010000000100000000D00000010000000100000000D00000010000000000000000E00000010000000000000000E00000010000000010000000E00000010000000010000000E00000010000000020000000E00000010000000020000000E00000010000000030000000E00000010000000030000000E00000010000000040000000E00000010000000040000000E00000010000000050000000E00000010000000050000000E00000010000000060000000E00000010000000060000000E00000010000000070000000E00000010000000070000000E00000010000000080000000E00000010000000080000000E00000010000000090000000E00000010000000090000000E000000100000000A0000000E000000100000000A0000000E000000100000000B0000000E000000100000000B0000000E000000100000000C0000000E000000100000000C0000000E000000100000000D0000000E000000100000000D0000000E000000100000000E0000000E000000100000000E0000000E000000100000000F0000000E000000100000000F0000000E00000010000000100000000E00000010000000100000000E00000010000000000000000F00000010000000000000000F00000010000000010000000F00000010000000010000000F00000010000000020000000F00000010000000020000000F00000010000000030000000F00000010000000030000000F00000010000000040000000F00000010000000040000000F00000010000000050000000F00000010000000050000000F00000010000000060000000F00000010000000060000000F00000010000000070000000F00000010000000070000000F00000010000000080000000F00000010000000080000000F00000010000000090000000F00000010000000090000000F000000100000000A0000000F000000100000000A0000000F000000100000000B0000000F000000100000000B0000000F000000100000000C0000000F000000100000000C0000000F000000100000000D0000000F000000100000000D0000000F000000100000000E0000000F000000100000000E0000000F000000100000000F0000000F000000100000000F0000000F00000010000000100000000F00000010000000100000000F000000100000000000000010000000100000000000000010000000100000000100000010000000100000000100000010000000100000000200000010000000100000000200000010000000100000000300000010000000100000000300000010000000100000000400000010000000100000000400000010000000100000000500000010000000100000000500000010000000100000000600000010000000100000000600000010000000100000000700000010000000100000000700000010000000100000000800000010000000100000000800000010000000100000000900000010000000100000000900000010000000100000000A00000010000000100000000A00000010000000100000000B00000010000000100000000B00000010000000100000000C00000010000000100000000C00000010000000100000000D00000010000000100000000D00000010000000100000000E00000010000000100000000E00000010000000100000000F00000010000000100000000F00000010000000100000001000000010000000100000001000000010000000100000 + 00000000000100000600000000000000010000000200000004000000050000000600000007000000090000000A0000000B0000000C0000000E0000000F0000001000000012000000140000001500000017000000190000001B0000001D0000001F000000210000002300000025000000280000002A0000002D000000300000003200000035000000380000003B0000003E0000004200000045000000480000004C0000004F00000053000000570000005B0000005F00000063000000670000006B0000007000000074000000790000007E00000083000000880000008D00000092000000970000009C000000A2000000A8000000AD000000B3000000B9000000BF000000C5000000CC000000D2000000D8000000DF000000E6000000ED000000F4000000FB00000002010000090100001101000018010000200100002801000030010000380100004001000049010000510100005A010000620100006B010000740100007D010000860100009001000099010000A3010000AC010000B6010000C0010000CA010000D5010000DF010000EA010000F4010000FF0100000A02000015020000200200002B02000037020000420200004E0200005A02000066020000720200007F0200008B02000098020000A4020000B1020000BE020000CB020000D8020000E6020000F3020000010300000F0300001D0300002B03000039030000480300005603000065030000740300008303000092030000A1030000B1030000C0030000D0030000E0030000F003000000040000110400002104000032040000430400005404000065040000760400008704000099040000AB040000BD040000CF040000E1040000F304000006050000180500002B0500003E0500005105000065050000780500008C050000A0050000B3050000C8050000DC050000F0050000050600001A0600002E06000043060000590600006E0600008406000099060000AF060000C5060000DB060000F2060000080700001F070000360700004D070000640700007C07000093070000AB070000C3070000DB070000F30700000B080000240800003D080000550800006F08000088080000A1080000BB080000D4080000EE08000008090000230900003D09000058090000730900008E090000A9090000C4090000DF090000FB090000170A0000330A00004F0A00006C0A0000880A0000A50A0000C20A0000DF0A0000FC0A0000190B0000370B0000550B0000730B0000910B0000AF0B0000CE0B0000EC0B00000B0C00002A0C00004A0C0000690C0000890C0000A80C0000C80C0000E80C0000090D0000290D00004A0D00006B0D00008C0D0000AD0D0000CF0D0000F00D0000120E0000340E0000560E0000790E00009B0E0000BE0E0000E10E0000040F0000270F00004B0F00006E0F0000920F0000B60F0000DB0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000004000000050000000600000007000000090000000A0000000B0000000C0000000E0000000F0000001000000012000000140000001500000017000000190000001B0000001D0000001F000000210000002300000025000000280000002A0000002D000000300000003200000035000000380000003B0000003E0000004200000045000000480000004C0000004F00000053000000570000005B0000005F00000063000000670000006B0000007000000074000000790000007E00000083000000880000008D00000092000000970000009C000000A2000000A8000000AD000000B3000000B9000000BF000000C5000000CC000000D2000000D8000000DF000000E6000000ED000000F4000000FB00000002010000090100001101000018010000200100002801000030010000380100004001000049010000510100005A010000620100006B010000740100007D010000860100009001000099010000A3010000AC010000B6010000C0010000CA010000D5010000DF010000EA010000F4010000FF0100000A02000015020000200200002B02000037020000420200004E0200005A02000066020000720200007F0200008B02000098020000A4020000B1020000BE020000CB020000D8020000E6020000F3020000010300000F0300001D0300002B03000039030000480300005603000065030000740300008303000092030000A1030000B1030000C0030000D0030000E0030000F003000000040000110400002104000032040000430400005404000065040000760400008704000099040000AB040000BD040000CF040000E1040000F304000006050000180500002B0500003E0500005105000065050000780500008C050000A0050000B3050000C8050000DC050000F0050000050600001A0600002E06000043060000590600006E0600008406000099060000AF060000C5060000DB060000F2060000080700001F070000360700004D070000640700007C07000093070000AB070000C3070000DB070000F30700000B080000240800003D080000550800006F08000088080000A1080000BB080000D4080000EE08000008090000230900003D09000058090000730900008E090000A9090000C4090000DF090000FB090000170A0000330A00004F0A00006C0A0000880A0000A50A0000C20A0000DF0A0000FC0A0000190B0000370B0000550B0000730B0000910B0000AF0B0000CE0B0000EC0B00000B0C00002A0C00004A0C0000690C0000890C0000A80C0000C80C0000E80C0000090D0000290D00004A0D00006B0D00008C0D0000AD0D0000CF0D0000F00D0000120E0000340E0000560E0000790E00009B0E0000BE0E0000E10E0000040F0000270F00004B0F00006E0F0000920F0000B60F0000DB0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000004000000050000000600000007000000090000000A0000000B0000000C0000000E0000000F0000001000000012000000140000001500000017000000190000001B0000001D0000001F000000210000002300000025000000280000002A0000002D000000300000003200000035000000380000003B0000003E0000004200000045000000480000004C0000004F00000053000000570000005B0000005F00000063000000670000006B0000007000000074000000790000007E00000083000000880000008D00000092000000970000009C000000A2000000A8000000AD000000B3000000B9000000BF000000C5000000CC000000D2000000D8000000DF000000E6000000ED000000F4000000FB00000002010000090100001101000018010000200100002801000030010000380100004001000049010000510100005A010000620100006B010000740100007D010000860100009001000099010000A3010000AC010000B6010000C0010000CA010000D5010000DF010000EA010000F4010000FF0100000A02000015020000200200002B02000037020000420200004E0200005A02000066020000720200007F0200008B02000098020000A4020000B1020000BE020000CB020000D8020000E6020000F3020000010300000F0300001D0300002B03000039030000480300005603000065030000740300008303000092030000A1030000B1030000C0030000D0030000E0030000F003000000040000110400002104000032040000430400005404000065040000760400008704000099040000AB040000BD040000CF040000E1040000F304000006050000180500002B0500003E0500005105000065050000780500008C050000A0050000B3050000C8050000DC050000F0050000050600001A0600002E06000043060000590600006E0600008406000099060000AF060000C5060000DB060000F2060000080700001F070000360700004D070000640700007C07000093070000AB070000C3070000DB070000F30700000B080000240800003D080000550800006F08000088080000A1080000BB080000D4080000EE08000008090000230900003D09000058090000730900008E090000A9090000C4090000DF090000FB090000170A0000330A00004F0A00006C0A0000880A0000A50A0000C20A0000DF0A0000FC0A0000190B0000370B0000550B0000730B0000910B0000AF0B0000CE0B0000EC0B00000B0C00002A0C00004A0C0000690C0000890C0000A80C0000C80C0000E80C0000090D0000290D00004A0D00006B0D00008C0D0000AD0D0000CF0D0000F00D0000120E0000340E0000560E0000790E00009B0E0000BE0E0000E10E0000040F0000270F00004B0F00006E0F0000920F0000B60F0000DB0F0000FF0F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 00000000000400000600000000000000280000003B00000048000000530000005B000000630000006B00000073000000790000007F000000850000008A0000008F00000094000000990000009E000000A3000000A6000000AA000000AD000000B0000000B4000000B7000000BB000000BE000000C1000000C5000000C8000000CB000000CF000000D2000000D6000000D9000000DD000000E1000000E4000000E7000000EA000000ED000000F1000000F4000000F7000000F9000000FC000000FF0000000201000005010000070100000A0100000C0100000F010000110100001401000016010000180100001A0100001D0100001F010000210100002301000026010000280100002A0100002C0100002E0100003001000032010000340100003601000038010000390100003B0100003D0100003F0100004101000043010000440100004601000048010000490100004B0100004D0100004E0100005001000052010000530100005501000057010000590100005A0100005C0100005E0100006001000061010000630100006501000067010000680100006A0100006C0100006E0100007001000072010000740100007601000077010000790100007B0100007D0100007E0100008001000082010000840100008501000087010000890100008A0100008C0100008E0100008F0100009101000093010000940100009601000097010000990100009A0100009C0100009D0100009F010000A0010000A2010000A3010000A5010000A7010000A8010000A9010000AB010000AC010000AE010000AF010000B1010000B2010000B3010000B5010000B6010000B8010000B9010000BA010000BC010000BD010000BE010000C0010000C1010000C2010000C4010000C5010000C6010000C8010000C9010000CA010000CB010000CD010000CE010000CF010000D0010000D2010000D3010000D4010000D5010000D7010000D8010000D9010000DA010000DB010000DC010000DE010000DF010000E0010000E1010000E2010000E4010000E5010000E6010000E7010000E8010000E9010000EB010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F5010000F6010000F7010000F8010000F9010000F9010000FA010000FB010000FC010000FD010000FE010000FE010000FF01000000020000010200000202000003020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000D0200000E0200000F020000100200001102000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F02000020020000210200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002B0200002C0200002D0200002E0200002F0200003002000031020000320200003202000033020000340200003502000036020000370200003802000039020000390200003A0200003B0200003C0200003D0200003E0200003E0200003F0200004002000041020000420200004302000043020000440200004502000046020000470200004802000048020000490200004A0200004B0200004C0200004C0200004D0200004E0200004F0200005002000051020000510200005202000053020000540200005502000055020000560200005702000058020000590200005A0200005A0200005B0200005C0200005D0200005E0200005F0200005F02000060020000610200006202000063020000640200006502000065020000660200006702000068020000690200006A0200006A0200006B0200006C0200006D0200006E0200006F0200007002000070020000710200007202000073020000740200007502000075020000760200007702000078020000790200007A0200007B0200007B0200007C0200007D0200007E0200007F0200007F0200008002000081020000820200008302000084020000840200008502000086020000870200008802000088020000890200008A0200008B0200008C0200008C0200008D0200008E0200008F020000900200009002000091020000920200009302000093020000940200009502000096020000970200009702000098020000990200009A0200009A0200009B0200009C0200009D0200009E0200009E0200009F020000A0020000A1020000A1020000A2020000A3020000A4020000A4020000A5020000A6020000A7020000A7020000A8020000A9020000AA020000AA020000AB020000AC020000AD020000AD020000AE020000AF020000B0020000B0020000B1020000B2020000B3020000B3020000B4020000B5020000B6020000B6020000B7020000B8020000B9020000B9020000BA020000BB020000BB020000BC020000BD020000BD020000BE020000BF020000BF020000C0020000C1020000C1020000C2020000C3020000C4020000C4020000C5020000C6020000C6020000C7020000C8020000C8020000C9020000CA020000CA020000CB020000CC020000CC020000CD020000CE020000CF020000CF020000D0020000D1020000D2020000D2020000D3020000D4020000D4020000D5020000D6020000D7020000D7020000D8020000D9020000D9020000DA020000DB020000DC020000DC020000DD020000DD020000DE020000DF020000DF020000E0020000E1020000E1020000E2020000E3020000E3020000E4020000E4020000E5020000E6020000E6020000E7020000E8020000E8020000E9020000EA020000EA020000EB020000EB020000EC020000ED020000ED020000EE020000EF020000EF020000F0020000F1020000F1020000F2020000F2020000F3020000F4020000F4020000F5020000F6020000F6020000F7020000F8020000F8020000F9020000F9020000FA020000FB020000FB020000FC020000FD020000FD020000FE020000FE020000FF02000000030000000300000103000001030000020300000303000003030000040300000403000005030000060300000603000007030000070300000803000009030000090300000A0300000A0300000B0300000C0300000C0300000D0300000D0300000E0300000E0300000F03000010030000100300001103000011030000120300001303000013030000140300001403000015030000160300001603000017030000170300001803000018030000190300001A0300001A0300001B0300001B0300001C0300001D0300001D0300001E0300001E0300001F0300001F03000020030000210300002103000022030000220300002303000024030000240300002503000025030000260300002603000027030000280300002803000029030000290300002A0300002A0300002B0300002C0300002C0300002D0300002D0300002E0300002E0300002F0300003003000030030000310300003103000032030000320300003303000034030000340300003503000035030000360300003703000037030000380300003803000039030000390300003A0300003B0300003B0300003C0300003C0300003D0300003D0300003E0300003F0300003F0300004003000040030000410300004103000042030000430300004303000044030000440300004503000045030000460300004603000047030000480300004803000049030000490300004A0300004A0300004B0300004C0300004C0300004D0300004D0300004E0300004E0300004E0300004F0300004F030000500300005003000051030000510300005203000052030000520300005303000053030000540300005403000055030000550300005603000056030000560300005703000057030000580300005803000059030000590300005A0300005A0300005A0300005B0300005B0300005C0300005C0300005D0300005D0300005E0300005E0300005F0300005F0300006003000061030000610300006203000062030000630300006303000064030000640300006503000065030000660300006703000067030000680300006803000069030000690300006A0300006A0300006B0300006C0300006C0300006D0300006D0300006E0300006E0300006F0300006F030000700300007003000071030000710300007203000072030000730300007303000074030000740300007503000075030000760300007703000077030000780300007803000079030000790300007A0300007A0300007B0300007B0300007C0300007C0300007D0300007D0300007E0300007E0300007F0300007F03000080030000800300008103000081030000820300008203000083030000830300008403000084030000850300008503000086030000860300008703000087030000880300008803000089030000890300008A0300008A0300008B0300008B0300008C0300008C0300008D0300008D0300008E0300008E0300008F0300008F03000090030000900300009103000091030000920300009203000093030000930300009403000094030000950300009503000096030000960300009703000097030000980300009803000099030000990300009A0300009A0300009B0300009B0300009C0300009C0300009D0300009D0300009E0300009E0300009F0300009F030000A0030000A0030000A1030000A1030000A1030000A2030000A2030000A3030000A3030000A4030000A4030000A5030000A5030000A6030000A6030000A7030000A7030000A8030000A8030000A9030000A9030000AA030000AA030000AA030000AB030000AB030000AC030000AC030000AD030000AD030000AE030000AE030000AF030000AF030000B0030000B0030000B1030000B1030000B2030000B2030000B3030000B3030000B4030000B4030000B4030000B5030000B5030000B6030000B6030000B7030000B7030000B8030000B8030000B9030000B9030000BA030000BA030000BB030000BB030000BC030000BC030000BD030000BD030000BE030000BE030000BE030000BF030000BF030000C0030000C0030000C1030000C1030000C2030000C2030000C3030000C3030000C3030000C4030000C4030000C5030000C5030000C6030000C6030000C7030000C7030000C8030000C8030000C8030000C9030000C9030000CA030000CA030000CB030000CB030000CC030000CC030000CD030000CD030000CD030000CE030000CE030000CF030000CF030000D0030000D0030000D1030000D1030000D1030000D2030000D2030000D3030000D3030000D4030000D4030000D5030000D5030000D6030000D6030000D6030000D7030000D7030000D8030000D8030000D9030000D9030000DA030000DA030000DA030000DB030000DB030000DC030000DC030000DD030000DD030000DE030000DE030000DE030000DF030000DF030000E0030000E0030000E1030000E1030000E2030000E2030000E2030000E3030000E3030000E4030000E4030000E5030000E5030000E5030000E6030000E6030000E7030000E7030000E8030000E8030000E9030000E9030000E9030000EA030000EA030000EB030000EB030000EC030000EC030000ED030000ED030000ED030000EE030000EE030000EF030000EF030000F0030000F0030000F0030000F1030000F1030000F2030000F2030000F3030000F3030000F4030000F4030000FF03000000000000280000003B00000048000000530000005B000000630000006B00000073000000790000007F000000850000008A0000008F00000094000000990000009E000000A3000000A6000000AA000000AD000000B0000000B4000000B7000000BB000000BE000000C1000000C5000000C8000000CB000000CF000000D2000000D6000000D9000000DD000000E1000000E4000000E7000000EA000000ED000000F1000000F4000000F7000000F9000000FC000000FF0000000201000005010000070100000A0100000C0100000F010000110100001401000016010000180100001A0100001D0100001F010000210100002301000026010000280100002A0100002C0100002E0100003001000032010000340100003601000038010000390100003B0100003D0100003F0100004101000043010000440100004601000048010000490100004B0100004D0100004E0100005001000052010000530100005501000057010000590100005A0100005C0100005E0100006001000061010000630100006501000067010000680100006A0100006C0100006E0100007001000072010000740100007601000077010000790100007B0100007D0100007E0100008001000082010000840100008501000087010000890100008A0100008C0100008E0100008F0100009101000093010000940100009601000097010000990100009A0100009C0100009D0100009F010000A0010000A2010000A3010000A5010000A7010000A8010000A9010000AB010000AC010000AE010000AF010000B1010000B2010000B3010000B5010000B6010000B8010000B9010000BA010000BC010000BD010000BE010000C0010000C1010000C2010000C4010000C5010000C6010000C8010000C9010000CA010000CB010000CD010000CE010000CF010000D0010000D2010000D3010000D4010000D5010000D7010000D8010000D9010000DA010000DB010000DC010000DE010000DF010000E0010000E1010000E2010000E4010000E5010000E6010000E7010000E8010000E9010000EB010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F5010000F6010000F7010000F8010000F9010000F9010000FA010000FB010000FC010000FD010000FE010000FE010000FF01000000020000010200000202000003020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000D0200000E0200000F020000100200001102000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F02000020020000210200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002B0200002C0200002D0200002E0200002F0200003002000031020000320200003202000033020000340200003502000036020000370200003802000039020000390200003A0200003B0200003C0200003D0200003E0200003E0200003F0200004002000041020000420200004302000043020000440200004502000046020000470200004802000048020000490200004A0200004B0200004C0200004C0200004D0200004E0200004F0200005002000051020000510200005202000053020000540200005502000055020000560200005702000058020000590200005A0200005A0200005B0200005C0200005D0200005E0200005F0200005F02000060020000610200006202000063020000640200006502000065020000660200006702000068020000690200006A0200006A0200006B0200006C0200006D0200006E0200006F0200007002000070020000710200007202000073020000740200007502000075020000760200007702000078020000790200007A0200007B0200007B0200007C0200007D0200007E0200007F0200007F0200008002000081020000820200008302000084020000840200008502000086020000870200008802000088020000890200008A0200008B0200008C0200008C0200008D0200008E0200008F020000900200009002000091020000920200009302000093020000940200009502000096020000970200009702000098020000990200009A0200009A0200009B0200009C0200009D0200009E0200009E0200009F020000A0020000A1020000A1020000A2020000A3020000A4020000A4020000A5020000A6020000A7020000A7020000A8020000A9020000AA020000AA020000AB020000AC020000AD020000AD020000AE020000AF020000B0020000B0020000B1020000B2020000B3020000B3020000B4020000B5020000B6020000B6020000B7020000B8020000B9020000B9020000BA020000BB020000BB020000BC020000BD020000BD020000BE020000BF020000BF020000C0020000C1020000C1020000C2020000C3020000C4020000C4020000C5020000C6020000C6020000C7020000C8020000C8020000C9020000CA020000CA020000CB020000CC020000CC020000CD020000CE020000CF020000CF020000D0020000D1020000D2020000D2020000D3020000D4020000D4020000D5020000D6020000D7020000D7020000D8020000D9020000D9020000DA020000DB020000DC020000DC020000DD020000DD020000DE020000DF020000DF020000E0020000E1020000E1020000E2020000E3020000E3020000E4020000E4020000E5020000E6020000E6020000E7020000E8020000E8020000E9020000EA020000EA020000EB020000EB020000EC020000ED020000ED020000EE020000EF020000EF020000F0020000F1020000F1020000F2020000F2020000F3020000F4020000F4020000F5020000F6020000F6020000F7020000F8020000F8020000F9020000F9020000FA020000FB020000FB020000FC020000FD020000FD020000FE020000FE020000FF02000000030000000300000103000001030000020300000303000003030000040300000403000005030000060300000603000007030000070300000803000009030000090300000A0300000A0300000B0300000C0300000C0300000D0300000D0300000E0300000E0300000F03000010030000100300001103000011030000120300001303000013030000140300001403000015030000160300001603000017030000170300001803000018030000190300001A0300001A0300001B0300001B0300001C0300001D0300001D0300001E0300001E0300001F0300001F03000020030000210300002103000022030000220300002303000024030000240300002503000025030000260300002603000027030000280300002803000029030000290300002A0300002A0300002B0300002C0300002C0300002D0300002D0300002E0300002E0300002F0300003003000030030000310300003103000032030000320300003303000034030000340300003503000035030000360300003703000037030000380300003803000039030000390300003A0300003B0300003B0300003C0300003C0300003D0300003D0300003E0300003F0300003F0300004003000040030000410300004103000042030000430300004303000044030000440300004503000045030000460300004603000047030000480300004803000049030000490300004A0300004A0300004B0300004C0300004C0300004D0300004D0300004E0300004E0300004E0300004F0300004F030000500300005003000051030000510300005203000052030000520300005303000053030000540300005403000055030000550300005603000056030000560300005703000057030000580300005803000059030000590300005A0300005A0300005A0300005B0300005B0300005C0300005C0300005D0300005D0300005E0300005E0300005F0300005F0300006003000061030000610300006203000062030000630300006303000064030000640300006503000065030000660300006703000067030000680300006803000069030000690300006A0300006A0300006B0300006C0300006C0300006D0300006D0300006E0300006E0300006F0300006F030000700300007003000071030000710300007203000072030000730300007303000074030000740300007503000075030000760300007703000077030000780300007803000079030000790300007A0300007A0300007B0300007B0300007C0300007C0300007D0300007D0300007E0300007E0300007F0300007F03000080030000800300008103000081030000820300008203000083030000830300008403000084030000850300008503000086030000860300008703000087030000880300008803000089030000890300008A0300008A0300008B0300008B0300008C0300008C0300008D0300008D0300008E0300008E0300008F0300008F03000090030000900300009103000091030000920300009203000093030000930300009403000094030000950300009503000096030000960300009703000097030000980300009803000099030000990300009A0300009A0300009B0300009B0300009C0300009C0300009D0300009D0300009E0300009E0300009F0300009F030000A0030000A0030000A1030000A1030000A1030000A2030000A2030000A3030000A3030000A4030000A4030000A5030000A5030000A6030000A6030000A7030000A7030000A8030000A8030000A9030000A9030000AA030000AA030000AA030000AB030000AB030000AC030000AC030000AD030000AD030000AE030000AE030000AF030000AF030000B0030000B0030000B1030000B1030000B2030000B2030000B3030000B3030000B4030000B4030000B4030000B5030000B5030000B6030000B6030000B7030000B7030000B8030000B8030000B9030000B9030000BA030000BA030000BB030000BB030000BC030000BC030000BD030000BD030000BE030000BE030000BE030000BF030000BF030000C0030000C0030000C1030000C1030000C2030000C2030000C3030000C3030000C3030000C4030000C4030000C5030000C5030000C6030000C6030000C7030000C7030000C8030000C8030000C8030000C9030000C9030000CA030000CA030000CB030000CB030000CC030000CC030000CD030000CD030000CD030000CE030000CE030000CF030000CF030000D0030000D0030000D1030000D1030000D1030000D2030000D2030000D3030000D3030000D4030000D4030000D5030000D5030000D6030000D6030000D6030000D7030000D7030000D8030000D8030000D9030000D9030000DA030000DA030000DA030000DB030000DB030000DC030000DC030000DD030000DD030000DE030000DE030000DE030000DF030000DF030000E0030000E0030000E1030000E1030000E2030000E2030000E2030000E3030000E3030000E4030000E4030000E5030000E5030000E5030000E6030000E6030000E7030000E7030000E8030000E8030000E9030000E9030000E9030000EA030000EA030000EB030000EB030000EC030000EC030000ED030000ED030000ED030000EE030000EE030000EF030000EF030000F0030000F0030000F0030000F1030000F1030000F2030000F2030000F3030000F3030000F4030000F4030000FF03000000000000280000003B00000048000000530000005B000000630000006B00000073000000790000007F000000850000008A0000008F00000094000000990000009E000000A3000000A6000000AA000000AD000000B0000000B4000000B7000000BB000000BE000000C1000000C5000000C8000000CB000000CF000000D2000000D6000000D9000000DD000000E1000000E4000000E7000000EA000000ED000000F1000000F4000000F7000000F9000000FC000000FF0000000201000005010000070100000A0100000C0100000F010000110100001401000016010000180100001A0100001D0100001F010000210100002301000026010000280100002A0100002C0100002E0100003001000032010000340100003601000038010000390100003B0100003D0100003F0100004101000043010000440100004601000048010000490100004B0100004D0100004E0100005001000052010000530100005501000057010000590100005A0100005C0100005E0100006001000061010000630100006501000067010000680100006A0100006C0100006E0100007001000072010000740100007601000077010000790100007B0100007D0100007E0100008001000082010000840100008501000087010000890100008A0100008C0100008E0100008F0100009101000093010000940100009601000097010000990100009A0100009C0100009D0100009F010000A0010000A2010000A3010000A5010000A7010000A8010000A9010000AB010000AC010000AE010000AF010000B1010000B2010000B3010000B5010000B6010000B8010000B9010000BA010000BC010000BD010000BE010000C0010000C1010000C2010000C4010000C5010000C6010000C8010000C9010000CA010000CB010000CD010000CE010000CF010000D0010000D2010000D3010000D4010000D5010000D7010000D8010000D9010000DA010000DB010000DC010000DE010000DF010000E0010000E1010000E2010000E4010000E5010000E6010000E7010000E8010000E9010000EB010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F5010000F6010000F7010000F8010000F9010000F9010000FA010000FB010000FC010000FD010000FE010000FE010000FF01000000020000010200000202000003020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000D0200000E0200000F020000100200001102000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F02000020020000210200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002B0200002C0200002D0200002E0200002F0200003002000031020000320200003202000033020000340200003502000036020000370200003802000039020000390200003A0200003B0200003C0200003D0200003E0200003E0200003F0200004002000041020000420200004302000043020000440200004502000046020000470200004802000048020000490200004A0200004B0200004C0200004C0200004D0200004E0200004F0200005002000051020000510200005202000053020000540200005502000055020000560200005702000058020000590200005A0200005A0200005B0200005C0200005D0200005E0200005F0200005F02000060020000610200006202000063020000640200006502000065020000660200006702000068020000690200006A0200006A0200006B0200006C0200006D0200006E0200006F0200007002000070020000710200007202000073020000740200007502000075020000760200007702000078020000790200007A0200007B0200007B0200007C0200007D0200007E0200007F0200007F0200008002000081020000820200008302000084020000840200008502000086020000870200008802000088020000890200008A0200008B0200008C0200008C0200008D0200008E0200008F020000900200009002000091020000920200009302000093020000940200009502000096020000970200009702000098020000990200009A0200009A0200009B0200009C0200009D0200009E0200009E0200009F020000A0020000A1020000A1020000A2020000A3020000A4020000A4020000A5020000A6020000A7020000A7020000A8020000A9020000AA020000AA020000AB020000AC020000AD020000AD020000AE020000AF020000B0020000B0020000B1020000B2020000B3020000B3020000B4020000B5020000B6020000B6020000B7020000B8020000B9020000B9020000BA020000BB020000BB020000BC020000BD020000BD020000BE020000BF020000BF020000C0020000C1020000C1020000C2020000C3020000C4020000C4020000C5020000C6020000C6020000C7020000C8020000C8020000C9020000CA020000CA020000CB020000CC020000CC020000CD020000CE020000CF020000CF020000D0020000D1020000D2020000D2020000D3020000D4020000D4020000D5020000D6020000D7020000D7020000D8020000D9020000D9020000DA020000DB020000DC020000DC020000DD020000DD020000DE020000DF020000DF020000E0020000E1020000E1020000E2020000E3020000E3020000E4020000E4020000E5020000E6020000E6020000E7020000E8020000E8020000E9020000EA020000EA020000EB020000EB020000EC020000ED020000ED020000EE020000EF020000EF020000F0020000F1020000F1020000F2020000F2020000F3020000F4020000F4020000F5020000F6020000F6020000F7020000F8020000F8020000F9020000F9020000FA020000FB020000FB020000FC020000FD020000FD020000FE020000FE020000FF02000000030000000300000103000001030000020300000303000003030000040300000403000005030000060300000603000007030000070300000803000009030000090300000A0300000A0300000B0300000C0300000C0300000D0300000D0300000E0300000E0300000F03000010030000100300001103000011030000120300001303000013030000140300001403000015030000160300001603000017030000170300001803000018030000190300001A0300001A0300001B0300001B0300001C0300001D0300001D0300001E0300001E0300001F0300001F03000020030000210300002103000022030000220300002303000024030000240300002503000025030000260300002603000027030000280300002803000029030000290300002A0300002A0300002B0300002C0300002C0300002D0300002D0300002E0300002E0300002F0300003003000030030000310300003103000032030000320300003303000034030000340300003503000035030000360300003703000037030000380300003803000039030000390300003A0300003B0300003B0300003C0300003C0300003D0300003D0300003E0300003F0300003F0300004003000040030000410300004103000042030000430300004303000044030000440300004503000045030000460300004603000047030000480300004803000049030000490300004A0300004A0300004B0300004C0300004C0300004D0300004D0300004E0300004E0300004E0300004F0300004F030000500300005003000051030000510300005203000052030000520300005303000053030000540300005403000055030000550300005603000056030000560300005703000057030000580300005803000059030000590300005A0300005A0300005A0300005B0300005B0300005C0300005C0300005D0300005D0300005E0300005E0300005F0300005F0300006003000061030000610300006203000062030000630300006303000064030000640300006503000065030000660300006703000067030000680300006803000069030000690300006A0300006A0300006B0300006C0300006C0300006D0300006D0300006E0300006E0300006F0300006F030000700300007003000071030000710300007203000072030000730300007303000074030000740300007503000075030000760300007703000077030000780300007803000079030000790300007A0300007A0300007B0300007B0300007C0300007C0300007D0300007D0300007E0300007E0300007F0300007F03000080030000800300008103000081030000820300008203000083030000830300008403000084030000850300008503000086030000860300008703000087030000880300008803000089030000890300008A0300008A0300008B0300008B0300008C0300008C0300008D0300008D0300008E0300008E0300008F0300008F03000090030000900300009103000091030000920300009203000093030000930300009403000094030000950300009503000096030000960300009703000097030000980300009803000099030000990300009A0300009A0300009B0300009B0300009C0300009C0300009D0300009D0300009E0300009E0300009F0300009F030000A0030000A0030000A1030000A1030000A1030000A2030000A2030000A3030000A3030000A4030000A4030000A5030000A5030000A6030000A6030000A7030000A7030000A8030000A8030000A9030000A9030000AA030000AA030000AA030000AB030000AB030000AC030000AC030000AD030000AD030000AE030000AE030000AF030000AF030000B0030000B0030000B1030000B1030000B2030000B2030000B3030000B3030000B4030000B4030000B4030000B5030000B5030000B6030000B6030000B7030000B7030000B8030000B8030000B9030000B9030000BA030000BA030000BB030000BB030000BC030000BC030000BD030000BD030000BE030000BE030000BE030000BF030000BF030000C0030000C0030000C1030000C1030000C2030000C2030000C3030000C3030000C3030000C4030000C4030000C5030000C5030000C6030000C6030000C7030000C7030000C8030000C8030000C8030000C9030000C9030000CA030000CA030000CB030000CB030000CC030000CC030000CD030000CD030000CD030000CE030000CE030000CF030000CF030000D0030000D0030000D1030000D1030000D1030000D2030000D2030000D3030000D3030000D4030000D4030000D5030000D5030000D6030000D6030000D6030000D7030000D7030000D8030000D8030000D9030000D9030000DA030000DA030000DA030000DB030000DB030000DC030000DC030000DD030000DD030000DE030000DE030000DE030000DF030000DF030000E0030000E0030000E1030000E1030000E2030000E2030000E2030000E3030000E3030000E4030000E4030000E5030000E5030000E5030000E6030000E6030000E7030000E7030000E8030000E8030000E9030000E9030000E9030000EA030000EA030000EB030000EB030000EC030000EC030000ED030000ED030000ED030000EE030000EE030000EF030000EF030000F0030000F0030000F0030000F1030000F1030000F2030000F2030000F3030000F3030000F4030000F4030000FF030000 + 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F00000021000000210000000300000003000000000000002D00000000000000010000000000C842000000000000803F0000C842000000000000803F0100000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000FF000000C3000000010000000000C842000000000000803F0000C842000000000000803F0200000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000870000004B000000010000000000C842000000000000803F0000C842000000000000803F0000000000000000640000000A0000000100000064000000000000000100000021000000210000000300000003000000000000000000000080010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 0000C842 + + + 00000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 00000000000100000600000000000000010000000200000004000000050000000600000007000000090000000A0000000B0000000C0000000E0000000F0000001000000012000000140000001500000017000000190000001B0000001D0000001F000000210000002300000025000000280000002A0000002D000000300000003200000035000000380000003B0000003E0000004200000045000000480000004C0000004F00000053000000570000005B0000005F00000063000000670000006B0000007000000074000000790000007E00000083000000880000008D00000092000000970000009C000000A2000000A8000000AD000000B3000000B9000000BF000000C5000000CC000000D2000000D8000000DF000000E6000000ED000000F4000000FB00000002010000090100001101000018010000200100002801000030010000380100004001000049010000510100005A010000620100006B010000740100007D010000860100009001000099010000A3010000AC010000B6010000C0010000CA010000D5010000DF010000EA010000F4010000FF0100000A02000015020000200200002B02000037020000420200004E0200005A02000066020000720200007F0200008B02000098020000A4020000B1020000BE020000CB020000D8020000E6020000F3020000010300000F0300001D0300002B03000039030000480300005603000065030000740300008303000092030000A1030000B1030000C0030000D0030000E0030000F003000000040000110400002104000032040000430400005404000065040000760400008704000099040000AB040000BD040000CF040000E1040000F304000006050000180500002B0500003E0500005105000065050000780500008C050000A0050000B3050000C8050000DC050000F0050000050600001A0600002E06000043060000590600006E0600008406000099060000AF060000C5060000DB060000F2060000080700001F070000360700004D070000640700007C07000093070000AB070000C3070000DB070000F30700000B080000240800003D080000550800006F08000088080000A1080000BB080000D4080000EE08000008090000230900003D09000058090000730900008E090000A9090000C4090000DF090000FB090000170A0000330A00004F0A00006C0A0000880A0000A50A0000C20A0000DF0A0000FC0A0000190B0000370B0000550B0000730B0000910B0000AF0B0000CE0B0000EC0B00000B0C00002A0C00004A0C0000690C0000890C0000A80C0000C80C0000E80C0000090D0000290D00004A0D00006B0D00008C0D0000AD0D0000CF0D0000F00D0000120E0000340E0000560E0000790E00009B0E0000BE0E0000E10E0000040F0000270F00004B0F00006E0F0000920F0000B60F0000DB0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000004000000050000000600000007000000090000000A0000000B0000000C0000000E0000000F0000001000000012000000140000001500000017000000190000001B0000001D0000001F000000210000002300000025000000280000002A0000002D000000300000003200000035000000380000003B0000003E0000004200000045000000480000004C0000004F00000053000000570000005B0000005F00000063000000670000006B0000007000000074000000790000007E00000083000000880000008D00000092000000970000009C000000A2000000A8000000AD000000B3000000B9000000BF000000C5000000CC000000D2000000D8000000DF000000E6000000ED000000F4000000FB00000002010000090100001101000018010000200100002801000030010000380100004001000049010000510100005A010000620100006B010000740100007D010000860100009001000099010000A3010000AC010000B6010000C0010000CA010000D5010000DF010000EA010000F4010000FF0100000A02000015020000200200002B02000037020000420200004E0200005A02000066020000720200007F0200008B02000098020000A4020000B1020000BE020000CB020000D8020000E6020000F3020000010300000F0300001D0300002B03000039030000480300005603000065030000740300008303000092030000A1030000B1030000C0030000D0030000E0030000F003000000040000110400002104000032040000430400005404000065040000760400008704000099040000AB040000BD040000CF040000E1040000F304000006050000180500002B0500003E0500005105000065050000780500008C050000A0050000B3050000C8050000DC050000F0050000050600001A0600002E06000043060000590600006E0600008406000099060000AF060000C5060000DB060000F2060000080700001F070000360700004D070000640700007C07000093070000AB070000C3070000DB070000F30700000B080000240800003D080000550800006F08000088080000A1080000BB080000D4080000EE08000008090000230900003D09000058090000730900008E090000A9090000C4090000DF090000FB090000170A0000330A00004F0A00006C0A0000880A0000A50A0000C20A0000DF0A0000FC0A0000190B0000370B0000550B0000730B0000910B0000AF0B0000CE0B0000EC0B00000B0C00002A0C00004A0C0000690C0000890C0000A80C0000C80C0000E80C0000090D0000290D00004A0D00006B0D00008C0D0000AD0D0000CF0D0000F00D0000120E0000340E0000560E0000790E00009B0E0000BE0E0000E10E0000040F0000270F00004B0F00006E0F0000920F0000B60F0000DB0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000004000000050000000600000007000000090000000A0000000B0000000C0000000E0000000F0000001000000012000000140000001500000017000000190000001B0000001D0000001F000000210000002300000025000000280000002A0000002D000000300000003200000035000000380000003B0000003E0000004200000045000000480000004C0000004F00000053000000570000005B0000005F00000063000000670000006B0000007000000074000000790000007E00000083000000880000008D00000092000000970000009C000000A2000000A8000000AD000000B3000000B9000000BF000000C5000000CC000000D2000000D8000000DF000000E6000000ED000000F4000000FB00000002010000090100001101000018010000200100002801000030010000380100004001000049010000510100005A010000620100006B010000740100007D010000860100009001000099010000A3010000AC010000B6010000C0010000CA010000D5010000DF010000EA010000F4010000FF0100000A02000015020000200200002B02000037020000420200004E0200005A02000066020000720200007F0200008B02000098020000A4020000B1020000BE020000CB020000D8020000E6020000F3020000010300000F0300001D0300002B03000039030000480300005603000065030000740300008303000092030000A1030000B1030000C0030000D0030000E0030000F003000000040000110400002104000032040000430400005404000065040000760400008704000099040000AB040000BD040000CF040000E1040000F304000006050000180500002B0500003E0500005105000065050000780500008C050000A0050000B3050000C8050000DC050000F0050000050600001A0600002E06000043060000590600006E0600008406000099060000AF060000C5060000DB060000F2060000080700001F070000360700004D070000640700007C07000093070000AB070000C3070000DB070000F30700000B080000240800003D080000550800006F08000088080000A1080000BB080000D4080000EE08000008090000230900003D09000058090000730900008E090000A9090000C4090000DF090000FB090000170A0000330A00004F0A00006C0A0000880A0000A50A0000C20A0000DF0A0000FC0A0000190B0000370B0000550B0000730B0000910B0000AF0B0000CE0B0000EC0B00000B0C00002A0C00004A0C0000690C0000890C0000A80C0000C80C0000E80C0000090D0000290D00004A0D00006B0D00008C0D0000AD0D0000CF0D0000F00D0000120E0000340E0000560E0000790E00009B0E0000BE0E0000E10E0000040F0000270F00004B0F00006E0F0000920F0000B60F0000DB0F0000FF0F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 010000000004000006000000000000000D0000001A00000027000000330000003D000000470000004F000000570000005E000000650000006B00000071000000770000007C00000082000000870000008B0000009000000095000000990000009E000000A2000000A6000000AA000000AE000000B1000000B5000000B9000000BC000000C0000000C3000000C7000000CA000000CD000000D0000000D3000000D6000000D9000000DC000000DF000000E2000000E5000000E8000000EB000000ED000000F0000000F3000000F5000000F8000000FB000000FD00000000010000020100000501000007010000090100000C0100000E010000100100001301000015010000170100001A0100001C0100001E01000020010000220100002501000027010000290100002B0100002D0100002F01000031010000330100003501000037010000390100003B0100003D0100003F01000041010000430100004501000047010000480100004A0100004C0100004E0100005001000052010000530100005501000057010000590100005A0100005C0100005E0100006001000061010000630100006501000066010000680100006A0100006B0100006D0100006F0100007001000072010000740100007501000077010000780100007A0100007B0100007D0100007F010000800100008201000083010000850100008601000088010000890100008B0100008C0100008E0100008F010000910100009201000094010000950100009601000098010000990100009B0100009C0100009E0100009F010000A0010000A2010000A3010000A5010000A6010000A7010000A9010000AA010000AB010000AD010000AE010000AF010000B1010000B2010000B3010000B5010000B6010000B7010000B9010000BA010000BB010000BD010000BE010000BF010000C0010000C2010000C3010000C4010000C5010000C7010000C8010000C9010000CA010000CC010000CD010000CE010000CF010000D1010000D2010000D3010000D4010000D5010000D7010000D8010000D9010000DA010000DB010000DD010000DE010000DF010000E0010000E1010000E2010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F0200001002000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F02000040020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004B0200004C0200004D0200004E0200004F02000050020000510200005202000053020000540200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005C0200005D0200005E0200005F0200006002000061020000620200006202000063020000640200006502000066020000670200006802000068020000690200006A0200006B0200006C0200006D0200006E0200006E0200006F0200007002000071020000720200007302000073020000740200007502000076020000770200007802000078020000790200007A0200007B0200007C0200007D0200007D0200007E0200007F020000800200008102000081020000820200008302000084020000850200008502000086020000870200008802000089020000890200008A0200008B0200008C0200008D0200008D0200008E0200008F020000900200009102000091020000920200009302000094020000940200009502000096020000970200009802000098020000990200009A0200009B0200009B0200009C0200009D0200009E0200009E0200009F020000A0020000A1020000A2020000A2020000A3020000A4020000A5020000A5020000A6020000A7020000A8020000A8020000A9020000AA020000AB020000AB020000AC020000AD020000AE020000AE020000AF020000B0020000B1020000B1020000B2020000B3020000B3020000B4020000B5020000B6020000B6020000B7020000B8020000B9020000B9020000BA020000BB020000BB020000BC020000BD020000BE020000BE020000BF020000C0020000C1020000C1020000C2020000C3020000C3020000C4020000C5020000C6020000C6020000C7020000C8020000C8020000C9020000CA020000CA020000CB020000CC020000CD020000CD020000CE020000CF020000CF020000D0020000D1020000D1020000D2020000D3020000D4020000D4020000D5020000D6020000D6020000D7020000D8020000D8020000D9020000DA020000DA020000DB020000DC020000DD020000DD020000DE020000DF020000DF020000E0020000E1020000E1020000E2020000E3020000E3020000E4020000E5020000E5020000E6020000E7020000E7020000E8020000E9020000E9020000EA020000EB020000EB020000EC020000ED020000ED020000EE020000EF020000EF020000F0020000F1020000F1020000F2020000F3020000F3020000F4020000F5020000F5020000F6020000F6020000F7020000F8020000F8020000F9020000FA020000FA020000FB020000FC020000FC020000FD020000FE020000FE020000FF020000000300000003000001030000010300000203000003030000030300000403000005030000050300000603000007030000070300000803000008030000090300000A0300000A0300000B0300000C0300000C0300000D0300000D0300000E0300000F0300000F030000100300001103000011030000120300001203000013030000140300001403000015030000160300001603000017030000170300001803000019030000190300001A0300001B0300001B0300001C0300001C0300001D0300001E0300001E0300001F0300001F030000200300002103000021030000220300002203000023030000240300002403000025030000250300002603000027030000270300002803000028030000290300002A0300002A0300002B0300002B0300002C0300002D0300002D0300002E0300002E0300002F03000030030000300300003103000031030000320300003303000033030000340300003403000035030000360300003603000037030000370300003803000038030000390300003A0300003A0300003B0300003B0300003C0300003D0300003D0300003E0300003E0300003F0300003F03000040030000410300004103000042030000420300004303000043030000440300004503000045030000460300004603000047030000470300004803000049030000490300004A0300004A0300004B0300004B0300004C0300004D0300004D0300004E0300004E0300004F0300004F0300005003000051030000510300005203000052030000530300005303000054030000540300005503000056030000560300005703000057030000580300005803000059030000590300005A0300005B0300005B0300005C0300005C0300005D0300005D0300005E0300005E0300005F030000600300006003000061030000610300006203000062030000630300006303000064030000640300006503000066030000660300006703000067030000680300006803000069030000690300006A0300006A0300006B0300006C0300006C0300006D0300006D0300006E0300006E0300006F0300006F030000700300007003000071030000710300007203000073030000730300007403000074030000750300007503000076030000760300007703000077030000780300007803000079030000790300007A0300007A0300007B0300007C0300007C0300007D0300007D0300007E0300007E0300007F0300007F030000800300008003000081030000810300008203000082030000830300008303000084030000840300008503000085030000860300008703000087030000880300008803000089030000890300008A0300008A0300008B0300008B0300008C0300008C0300008D0300008D0300008E0300008E0300008F0300008F03000090030000900300009103000091030000920300009203000093030000930300009403000094030000950300009503000096030000960300009703000097030000980300009803000099030000990300009A0300009A0300009B0300009B0300009C0300009C0300009D0300009D0300009E0300009E0300009F0300009F030000A0030000A0030000A1030000A1030000A2030000A2030000A3030000A3030000A4030000A4030000A5030000A5030000A6030000A6030000A7030000A7030000A8030000A8030000A9030000A9030000AA030000AA030000AB030000AB030000AC030000AC030000AD030000AD030000AE030000AE030000AF030000AF030000B0030000B0030000B1030000B1030000B2030000B2030000B3030000B3030000B4030000B4030000B5030000B5030000B6030000B6030000B7030000B7030000B8030000B8030000B9030000B9030000BA030000BA030000BA030000BB030000BB030000BC030000BC030000BD030000BD030000BE030000BE030000BF030000BF030000C0030000C0030000C1030000C1030000C2030000C2030000C3030000C3030000C4030000C4030000C5030000C5030000C5030000C6030000C6030000C7030000C7030000C8030000C8030000C9030000C9030000CA030000CA030000CB030000CB030000CC030000CC030000CD030000CD030000CE030000CE030000CE030000CF030000CF030000D0030000D0030000D1030000D1030000D2030000D2030000D3030000D3030000D4030000D4030000D5030000D5030000D5030000D6030000D6030000D7030000D7030000D8030000D8030000D9030000D9030000DA030000DA030000DB030000DB030000DB030000DC030000DC030000DD030000DD030000DE030000DE030000DF030000DF030000E0030000E0030000E1030000E1030000E1030000E2030000E2030000E3030000E3030000E4030000E4030000E5030000E5030000E6030000E6030000E6030000E7030000E7030000E8030000E8030000E9030000E9030000EA030000EA030000EB030000EB030000EB030000EC030000EC030000ED030000ED030000EE030000EE030000EF030000EF030000EF030000F0030000F0030000F1030000F1030000F2030000F2030000F3030000F3030000F3030000F4030000F4030000F5030000F5030000F6030000F6030000F7030000F7030000F7030000F8030000F8030000F9030000F9030000FA030000FA030000FB030000FB030000FB030000FC030000FC030000FD030000FD030000FE030000FE030000FF030000FF030000000000000D0000001A00000027000000330000003D000000470000004F000000570000005E000000650000006B00000071000000770000007C00000082000000870000008B0000009000000095000000990000009E000000A2000000A6000000AA000000AE000000B1000000B5000000B9000000BC000000C0000000C3000000C7000000CA000000CD000000D0000000D3000000D6000000D9000000DC000000DF000000E2000000E5000000E8000000EB000000ED000000F0000000F3000000F5000000F8000000FB000000FD00000000010000020100000501000007010000090100000C0100000E010000100100001301000015010000170100001A0100001C0100001E01000020010000220100002501000027010000290100002B0100002D0100002F01000031010000330100003501000037010000390100003B0100003D0100003F01000041010000430100004501000047010000480100004A0100004C0100004E0100005001000052010000530100005501000057010000590100005A0100005C0100005E0100006001000061010000630100006501000066010000680100006A0100006B0100006D0100006F0100007001000072010000740100007501000077010000780100007A0100007B0100007D0100007F010000800100008201000083010000850100008601000088010000890100008B0100008C0100008E0100008F010000910100009201000094010000950100009601000098010000990100009B0100009C0100009E0100009F010000A0010000A2010000A3010000A5010000A6010000A7010000A9010000AA010000AB010000AD010000AE010000AF010000B1010000B2010000B3010000B5010000B6010000B7010000B9010000BA010000BB010000BD010000BE010000BF010000C0010000C2010000C3010000C4010000C5010000C7010000C8010000C9010000CA010000CC010000CD010000CE010000CF010000D1010000D2010000D3010000D4010000D5010000D7010000D8010000D9010000DA010000DB010000DD010000DE010000DF010000E0010000E1010000E2010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F0200001002000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F02000040020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004B0200004C0200004D0200004E0200004F02000050020000510200005202000053020000540200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005C0200005D0200005E0200005F0200006002000061020000620200006202000063020000640200006502000066020000670200006802000068020000690200006A0200006B0200006C0200006D0200006E0200006E0200006F0200007002000071020000720200007302000073020000740200007502000076020000770200007802000078020000790200007A0200007B0200007C0200007D0200007D0200007E0200007F020000800200008102000081020000820200008302000084020000850200008502000086020000870200008802000089020000890200008A0200008B0200008C0200008D0200008D0200008E0200008F020000900200009102000091020000920200009302000094020000940200009502000096020000970200009802000098020000990200009A0200009B0200009B0200009C0200009D0200009E0200009E0200009F020000A0020000A1020000A2020000A2020000A3020000A4020000A5020000A5020000A6020000A7020000A8020000A8020000A9020000AA020000AB020000AB020000AC020000AD020000AE020000AE020000AF020000B0020000B1020000B1020000B2020000B3020000B3020000B4020000B5020000B6020000B6020000B7020000B8020000B9020000B9020000BA020000BB020000BB020000BC020000BD020000BE020000BE020000BF020000C0020000C1020000C1020000C2020000C3020000C3020000C4020000C5020000C6020000C6020000C7020000C8020000C8020000C9020000CA020000CA020000CB020000CC020000CD020000CD020000CE020000CF020000CF020000D0020000D1020000D1020000D2020000D3020000D4020000D4020000D5020000D6020000D6020000D7020000D8020000D8020000D9020000DA020000DA020000DB020000DC020000DD020000DD020000DE020000DF020000DF020000E0020000E1020000E1020000E2020000E3020000E3020000E4020000E5020000E5020000E6020000E7020000E7020000E8020000E9020000E9020000EA020000EB020000EB020000EC020000ED020000ED020000EE020000EF020000EF020000F0020000F1020000F1020000F2020000F3020000F3020000F4020000F5020000F5020000F6020000F6020000F7020000F8020000F8020000F9020000FA020000FA020000FB020000FC020000FC020000FD020000FE020000FE020000FF020000000300000003000001030000010300000203000003030000030300000403000005030000050300000603000007030000070300000803000008030000090300000A0300000A0300000B0300000C0300000C0300000D0300000D0300000E0300000F0300000F030000100300001103000011030000120300001203000013030000140300001403000015030000160300001603000017030000170300001803000019030000190300001A0300001B0300001B0300001C0300001C0300001D0300001E0300001E0300001F0300001F030000200300002103000021030000220300002203000023030000240300002403000025030000250300002603000027030000270300002803000028030000290300002A0300002A0300002B0300002B0300002C0300002D0300002D0300002E0300002E0300002F03000030030000300300003103000031030000320300003303000033030000340300003403000035030000360300003603000037030000370300003803000038030000390300003A0300003A0300003B0300003B0300003C0300003D0300003D0300003E0300003E0300003F0300003F03000040030000410300004103000042030000420300004303000043030000440300004503000045030000460300004603000047030000470300004803000049030000490300004A0300004A0300004B0300004B0300004C0300004D0300004D0300004E0300004E0300004F0300004F0300005003000051030000510300005203000052030000530300005303000054030000540300005503000056030000560300005703000057030000580300005803000059030000590300005A0300005B0300005B0300005C0300005C0300005D0300005D0300005E0300005E0300005F030000600300006003000061030000610300006203000062030000630300006303000064030000640300006503000066030000660300006703000067030000680300006803000069030000690300006A0300006A0300006B0300006C0300006C0300006D0300006D0300006E0300006E0300006F0300006F030000700300007003000071030000710300007203000073030000730300007403000074030000750300007503000076030000760300007703000077030000780300007803000079030000790300007A0300007A0300007B0300007C0300007C0300007D0300007D0300007E0300007E0300007F0300007F030000800300008003000081030000810300008203000082030000830300008303000084030000840300008503000085030000860300008703000087030000880300008803000089030000890300008A0300008A0300008B0300008B0300008C0300008C0300008D0300008D0300008E0300008E0300008F0300008F03000090030000900300009103000091030000920300009203000093030000930300009403000094030000950300009503000096030000960300009703000097030000980300009803000099030000990300009A0300009A0300009B0300009B0300009C0300009C0300009D0300009D0300009E0300009E0300009F0300009F030000A0030000A0030000A1030000A1030000A2030000A2030000A3030000A3030000A4030000A4030000A5030000A5030000A6030000A6030000A7030000A7030000A8030000A8030000A9030000A9030000AA030000AA030000AB030000AB030000AC030000AC030000AD030000AD030000AE030000AE030000AF030000AF030000B0030000B0030000B1030000B1030000B2030000B2030000B3030000B3030000B4030000B4030000B5030000B5030000B6030000B6030000B7030000B7030000B8030000B8030000B9030000B9030000BA030000BA030000BA030000BB030000BB030000BC030000BC030000BD030000BD030000BE030000BE030000BF030000BF030000C0030000C0030000C1030000C1030000C2030000C2030000C3030000C3030000C4030000C4030000C5030000C5030000C5030000C6030000C6030000C7030000C7030000C8030000C8030000C9030000C9030000CA030000CA030000CB030000CB030000CC030000CC030000CD030000CD030000CE030000CE030000CE030000CF030000CF030000D0030000D0030000D1030000D1030000D2030000D2030000D3030000D3030000D4030000D4030000D5030000D5030000D5030000D6030000D6030000D7030000D7030000D8030000D8030000D9030000D9030000DA030000DA030000DB030000DB030000DB030000DC030000DC030000DD030000DD030000DE030000DE030000DF030000DF030000E0030000E0030000E1030000E1030000E1030000E2030000E2030000E3030000E3030000E4030000E4030000E5030000E5030000E6030000E6030000E6030000E7030000E7030000E8030000E8030000E9030000E9030000EA030000EA030000EB030000EB030000EB030000EC030000EC030000ED030000ED030000EE030000EE030000EF030000EF030000EF030000F0030000F0030000F1030000F1030000F2030000F2030000F3030000F3030000F3030000F4030000F4030000F5030000F5030000F6030000F6030000F7030000F7030000F7030000F8030000F8030000F9030000F9030000FA030000FA030000FB030000FB030000FB030000FC030000FC030000FD030000FD030000FE030000FE030000FF030000FF030000000000000D0000001A00000027000000330000003D000000470000004F000000570000005E000000650000006B00000071000000770000007C00000082000000870000008B0000009000000095000000990000009E000000A2000000A6000000AA000000AE000000B1000000B5000000B9000000BC000000C0000000C3000000C7000000CA000000CD000000D0000000D3000000D6000000D9000000DC000000DF000000E2000000E5000000E8000000EB000000ED000000F0000000F3000000F5000000F8000000FB000000FD00000000010000020100000501000007010000090100000C0100000E010000100100001301000015010000170100001A0100001C0100001E01000020010000220100002501000027010000290100002B0100002D0100002F01000031010000330100003501000037010000390100003B0100003D0100003F01000041010000430100004501000047010000480100004A0100004C0100004E0100005001000052010000530100005501000057010000590100005A0100005C0100005E0100006001000061010000630100006501000066010000680100006A0100006B0100006D0100006F0100007001000072010000740100007501000077010000780100007A0100007B0100007D0100007F010000800100008201000083010000850100008601000088010000890100008B0100008C0100008E0100008F010000910100009201000094010000950100009601000098010000990100009B0100009C0100009E0100009F010000A0010000A2010000A3010000A5010000A6010000A7010000A9010000AA010000AB010000AD010000AE010000AF010000B1010000B2010000B3010000B5010000B6010000B7010000B9010000BA010000BB010000BD010000BE010000BF010000C0010000C2010000C3010000C4010000C5010000C7010000C8010000C9010000CA010000CC010000CD010000CE010000CF010000D1010000D2010000D3010000D4010000D5010000D7010000D8010000D9010000DA010000DB010000DD010000DE010000DF010000E0010000E1010000E2010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F0200001002000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F02000040020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004B0200004C0200004D0200004E0200004F02000050020000510200005202000053020000540200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005C0200005D0200005E0200005F0200006002000061020000620200006202000063020000640200006502000066020000670200006802000068020000690200006A0200006B0200006C0200006D0200006E0200006E0200006F0200007002000071020000720200007302000073020000740200007502000076020000770200007802000078020000790200007A0200007B0200007C0200007D0200007D0200007E0200007F020000800200008102000081020000820200008302000084020000850200008502000086020000870200008802000089020000890200008A0200008B0200008C0200008D0200008D0200008E0200008F020000900200009102000091020000920200009302000094020000940200009502000096020000970200009802000098020000990200009A0200009B0200009B0200009C0200009D0200009E0200009E0200009F020000A0020000A1020000A2020000A2020000A3020000A4020000A5020000A5020000A6020000A7020000A8020000A8020000A9020000AA020000AB020000AB020000AC020000AD020000AE020000AE020000AF020000B0020000B1020000B1020000B2020000B3020000B3020000B4020000B5020000B6020000B6020000B7020000B8020000B9020000B9020000BA020000BB020000BB020000BC020000BD020000BE020000BE020000BF020000C0020000C1020000C1020000C2020000C3020000C3020000C4020000C5020000C6020000C6020000C7020000C8020000C8020000C9020000CA020000CA020000CB020000CC020000CD020000CD020000CE020000CF020000CF020000D0020000D1020000D1020000D2020000D3020000D4020000D4020000D5020000D6020000D6020000D7020000D8020000D8020000D9020000DA020000DA020000DB020000DC020000DD020000DD020000DE020000DF020000DF020000E0020000E1020000E1020000E2020000E3020000E3020000E4020000E5020000E5020000E6020000E7020000E7020000E8020000E9020000E9020000EA020000EB020000EB020000EC020000ED020000ED020000EE020000EF020000EF020000F0020000F1020000F1020000F2020000F3020000F3020000F4020000F5020000F5020000F6020000F6020000F7020000F8020000F8020000F9020000FA020000FA020000FB020000FC020000FC020000FD020000FE020000FE020000FF020000000300000003000001030000010300000203000003030000030300000403000005030000050300000603000007030000070300000803000008030000090300000A0300000A0300000B0300000C0300000C0300000D0300000D0300000E0300000F0300000F030000100300001103000011030000120300001203000013030000140300001403000015030000160300001603000017030000170300001803000019030000190300001A0300001B0300001B0300001C0300001C0300001D0300001E0300001E0300001F0300001F030000200300002103000021030000220300002203000023030000240300002403000025030000250300002603000027030000270300002803000028030000290300002A0300002A0300002B0300002B0300002C0300002D0300002D0300002E0300002E0300002F03000030030000300300003103000031030000320300003303000033030000340300003403000035030000360300003603000037030000370300003803000038030000390300003A0300003A0300003B0300003B0300003C0300003D0300003D0300003E0300003E0300003F0300003F03000040030000410300004103000042030000420300004303000043030000440300004503000045030000460300004603000047030000470300004803000049030000490300004A0300004A0300004B0300004B0300004C0300004D0300004D0300004E0300004E0300004F0300004F0300005003000051030000510300005203000052030000530300005303000054030000540300005503000056030000560300005703000057030000580300005803000059030000590300005A0300005B0300005B0300005C0300005C0300005D0300005D0300005E0300005E0300005F030000600300006003000061030000610300006203000062030000630300006303000064030000640300006503000066030000660300006703000067030000680300006803000069030000690300006A0300006A0300006B0300006C0300006C0300006D0300006D0300006E0300006E0300006F0300006F030000700300007003000071030000710300007203000073030000730300007403000074030000750300007503000076030000760300007703000077030000780300007803000079030000790300007A0300007A0300007B0300007C0300007C0300007D0300007D0300007E0300007E0300007F0300007F030000800300008003000081030000810300008203000082030000830300008303000084030000840300008503000085030000860300008703000087030000880300008803000089030000890300008A0300008A0300008B0300008B0300008C0300008C0300008D0300008D0300008E0300008E0300008F0300008F03000090030000900300009103000091030000920300009203000093030000930300009403000094030000950300009503000096030000960300009703000097030000980300009803000099030000990300009A0300009A0300009B0300009B0300009C0300009C0300009D0300009D0300009E0300009E0300009F0300009F030000A0030000A0030000A1030000A1030000A2030000A2030000A3030000A3030000A4030000A4030000A5030000A5030000A6030000A6030000A7030000A7030000A8030000A8030000A9030000A9030000AA030000AA030000AB030000AB030000AC030000AC030000AD030000AD030000AE030000AE030000AF030000AF030000B0030000B0030000B1030000B1030000B2030000B2030000B3030000B3030000B4030000B4030000B5030000B5030000B6030000B6030000B7030000B7030000B8030000B8030000B9030000B9030000BA030000BA030000BA030000BB030000BB030000BC030000BC030000BD030000BD030000BE030000BE030000BF030000BF030000C0030000C0030000C1030000C1030000C2030000C2030000C3030000C3030000C4030000C4030000C5030000C5030000C5030000C6030000C6030000C7030000C7030000C8030000C8030000C9030000C9030000CA030000CA030000CB030000CB030000CC030000CC030000CD030000CD030000CE030000CE030000CE030000CF030000CF030000D0030000D0030000D1030000D1030000D2030000D2030000D3030000D3030000D4030000D4030000D5030000D5030000D5030000D6030000D6030000D7030000D7030000D8030000D8030000D9030000D9030000DA030000DA030000DB030000DB030000DB030000DC030000DC030000DD030000DD030000DE030000DE030000DF030000DF030000E0030000E0030000E1030000E1030000E1030000E2030000E2030000E3030000E3030000E4030000E4030000E5030000E5030000E6030000E6030000E6030000E7030000E7030000E8030000E8030000E9030000E9030000EA030000EA030000EB030000EB030000EB030000EC030000EC030000ED030000ED030000EE030000EE030000EF030000EF030000EF030000F0030000F0030000F1030000F1030000F2030000F2030000F3030000F3030000F3030000F4030000F4030000F5030000F5030000F6030000F6030000F7030000F7030000F7030000F8030000F8030000F9030000F9030000FA030000FA030000FB030000FB030000FB030000FC030000FC030000FD030000FD030000FE030000FE030000FF030000FF030000 + 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F00000021000000210000000300000003000000000000002D00000000000000000000000000C84200000000000000000000C84200000000000000000100000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000B5FFFFFF5BFFFFFF000000000000C84200000000000000000000C84200000000000000000200000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000A50000004B000000000000000000C84200000000000000000000C84200000000000000000000000000000000640000000A0000000100000064000000000000000100000021000000210000000300000003000000000000000000000080010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 0000C842 + 00000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + 00000000000000000000000000000000000000000000F03F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006D6FB724076CE83F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CBBF9657AEB7DB3F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 00000000000100000600000000000000010000000200000004000000050000000600000007000000090000000A0000000B0000000C0000000E0000000F0000001000000012000000140000001500000017000000190000001B0000001D0000001F000000210000002300000025000000280000002A0000002D000000300000003200000035000000380000003B0000003E0000004200000045000000480000004C0000004F00000053000000570000005B0000005F00000063000000670000006B0000007000000074000000790000007E00000083000000880000008D00000092000000970000009C000000A2000000A8000000AD000000B3000000B9000000BF000000C5000000CC000000D2000000D8000000DF000000E6000000ED000000F4000000FB00000002010000090100001101000018010000200100002801000030010000380100004001000049010000510100005A010000620100006B010000740100007D010000860100009001000099010000A3010000AC010000B6010000C0010000CA010000D5010000DF010000EA010000F4010000FF0100000A02000015020000200200002B02000037020000420200004E0200005A02000066020000720200007F0200008B02000098020000A4020000B1020000BE020000CB020000D8020000E6020000F3020000010300000F0300001D0300002B03000039030000480300005603000065030000740300008303000092030000A1030000B1030000C0030000D0030000E0030000F003000000040000110400002104000032040000430400005404000065040000760400008704000099040000AB040000BD040000CF040000E1040000F304000006050000180500002B0500003E0500005105000065050000780500008C050000A0050000B3050000C8050000DC050000F0050000050600001A0600002E06000043060000590600006E0600008406000099060000AF060000C5060000DB060000F2060000080700001F070000360700004D070000640700007C07000093070000AB070000C3070000DB070000F30700000B080000240800003D080000550800006F08000088080000A1080000BB080000D4080000EE08000008090000230900003D09000058090000730900008E090000A9090000C4090000DF090000FB090000170A0000330A00004F0A00006C0A0000880A0000A50A0000C20A0000DF0A0000FC0A0000190B0000370B0000550B0000730B0000910B0000AF0B0000CE0B0000EC0B00000B0C00002A0C00004A0C0000690C0000890C0000A80C0000C80C0000E80C0000090D0000290D00004A0D00006B0D00008C0D0000AD0D0000CF0D0000F00D0000120E0000340E0000560E0000790E00009B0E0000BE0E0000E10E0000040F0000270F00004B0F00006E0F0000920F0000B60F0000DB0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000004000000050000000600000007000000090000000A0000000B0000000C0000000E0000000F0000001000000012000000140000001500000017000000190000001B0000001D0000001F000000210000002300000025000000280000002A0000002D000000300000003200000035000000380000003B0000003E0000004200000045000000480000004C0000004F00000053000000570000005B0000005F00000063000000670000006B0000007000000074000000790000007E00000083000000880000008D00000092000000970000009C000000A2000000A8000000AD000000B3000000B9000000BF000000C5000000CC000000D2000000D8000000DF000000E6000000ED000000F4000000FB00000002010000090100001101000018010000200100002801000030010000380100004001000049010000510100005A010000620100006B010000740100007D010000860100009001000099010000A3010000AC010000B6010000C0010000CA010000D5010000DF010000EA010000F4010000FF0100000A02000015020000200200002B02000037020000420200004E0200005A02000066020000720200007F0200008B02000098020000A4020000B1020000BE020000CB020000D8020000E6020000F3020000010300000F0300001D0300002B03000039030000480300005603000065030000740300008303000092030000A1030000B1030000C0030000D0030000E0030000F003000000040000110400002104000032040000430400005404000065040000760400008704000099040000AB040000BD040000CF040000E1040000F304000006050000180500002B0500003E0500005105000065050000780500008C050000A0050000B3050000C8050000DC050000F0050000050600001A0600002E06000043060000590600006E0600008406000099060000AF060000C5060000DB060000F2060000080700001F070000360700004D070000640700007C07000093070000AB070000C3070000DB070000F30700000B080000240800003D080000550800006F08000088080000A1080000BB080000D4080000EE08000008090000230900003D09000058090000730900008E090000A9090000C4090000DF090000FB090000170A0000330A00004F0A00006C0A0000880A0000A50A0000C20A0000DF0A0000FC0A0000190B0000370B0000550B0000730B0000910B0000AF0B0000CE0B0000EC0B00000B0C00002A0C00004A0C0000690C0000890C0000A80C0000C80C0000E80C0000090D0000290D00004A0D00006B0D00008C0D0000AD0D0000CF0D0000F00D0000120E0000340E0000560E0000790E00009B0E0000BE0E0000E10E0000040F0000270F00004B0F00006E0F0000920F0000B60F0000DB0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000004000000050000000600000007000000090000000A0000000B0000000C0000000E0000000F0000001000000012000000140000001500000017000000190000001B0000001D0000001F000000210000002300000025000000280000002A0000002D000000300000003200000035000000380000003B0000003E0000004200000045000000480000004C0000004F00000053000000570000005B0000005F00000063000000670000006B0000007000000074000000790000007E00000083000000880000008D00000092000000970000009C000000A2000000A8000000AD000000B3000000B9000000BF000000C5000000CC000000D2000000D8000000DF000000E6000000ED000000F4000000FB00000002010000090100001101000018010000200100002801000030010000380100004001000049010000510100005A010000620100006B010000740100007D010000860100009001000099010000A3010000AC010000B6010000C0010000CA010000D5010000DF010000EA010000F4010000FF0100000A02000015020000200200002B02000037020000420200004E0200005A02000066020000720200007F0200008B02000098020000A4020000B1020000BE020000CB020000D8020000E6020000F3020000010300000F0300001D0300002B03000039030000480300005603000065030000740300008303000092030000A1030000B1030000C0030000D0030000E0030000F003000000040000110400002104000032040000430400005404000065040000760400008704000099040000AB040000BD040000CF040000E1040000F304000006050000180500002B0500003E0500005105000065050000780500008C050000A0050000B3050000C8050000DC050000F0050000050600001A0600002E06000043060000590600006E0600008406000099060000AF060000C5060000DB060000F2060000080700001F070000360700004D070000640700007C07000093070000AB070000C3070000DB070000F30700000B080000240800003D080000550800006F08000088080000A1080000BB080000D4080000EE08000008090000230900003D09000058090000730900008E090000A9090000C4090000DF090000FB090000170A0000330A00004F0A00006C0A0000880A0000A50A0000C20A0000DF0A0000FC0A0000190B0000370B0000550B0000730B0000910B0000AF0B0000CE0B0000EC0B00000B0C00002A0C00004A0C0000690C0000890C0000A80C0000C80C0000E80C0000090D0000290D00004A0D00006B0D00008C0D0000AD0D0000CF0D0000F00D0000120E0000340E0000560E0000790E00009B0E0000BE0E0000E10E0000040F0000270F00004B0F00006E0F0000920F0000B60F0000DB0F0000FF0F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 010000000004000006000000000000000D0000001A00000027000000330000003D000000470000004F000000570000005E000000650000006B00000071000000770000007C00000082000000870000008B0000009000000095000000990000009E000000A2000000A6000000AA000000AE000000B1000000B5000000B9000000BC000000C0000000C3000000C7000000CA000000CD000000D0000000D3000000D6000000D9000000DC000000DF000000E2000000E5000000E8000000EB000000ED000000F0000000F3000000F5000000F8000000FB000000FD00000000010000020100000501000007010000090100000C0100000E010000100100001301000015010000170100001A0100001C0100001E01000020010000220100002501000027010000290100002B0100002D0100002F01000031010000330100003501000037010000390100003B0100003D0100003F01000041010000430100004501000047010000480100004A0100004C0100004E0100005001000052010000530100005501000057010000590100005A0100005C0100005E0100006001000061010000630100006501000066010000680100006A0100006B0100006D0100006F0100007001000072010000740100007501000077010000780100007A0100007B0100007D0100007F010000800100008201000083010000850100008601000088010000890100008B0100008C0100008E0100008F010000910100009201000094010000950100009601000098010000990100009B0100009C0100009E0100009F010000A0010000A2010000A3010000A5010000A6010000A7010000A9010000AA010000AB010000AD010000AE010000AF010000B1010000B2010000B3010000B5010000B6010000B7010000B9010000BA010000BB010000BD010000BE010000BF010000C0010000C2010000C3010000C4010000C5010000C7010000C8010000C9010000CA010000CC010000CD010000CE010000CF010000D1010000D2010000D3010000D4010000D5010000D7010000D8010000D9010000DA010000DB010000DD010000DE010000DF010000E0010000E1010000E2010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F0200001002000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F02000040020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004B0200004C0200004D0200004E0200004F02000050020000510200005202000053020000540200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005C0200005D0200005E0200005F0200006002000061020000620200006202000063020000640200006502000066020000670200006802000068020000690200006A0200006B0200006C0200006D0200006E0200006E0200006F0200007002000071020000720200007302000073020000740200007502000076020000770200007802000078020000790200007A0200007B0200007C0200007D0200007D0200007E0200007F020000800200008102000081020000820200008302000084020000850200008502000086020000870200008802000089020000890200008A0200008B0200008C0200008D0200008D0200008E0200008F020000900200009102000091020000920200009302000094020000940200009502000096020000970200009802000098020000990200009A0200009B0200009B0200009C0200009D0200009E0200009E0200009F020000A0020000A1020000A2020000A2020000A3020000A4020000A5020000A5020000A6020000A7020000A8020000A8020000A9020000AA020000AB020000AB020000AC020000AD020000AE020000AE020000AF020000B0020000B1020000B1020000B2020000B3020000B3020000B4020000B5020000B6020000B6020000B7020000B8020000B9020000B9020000BA020000BB020000BB020000BC020000BD020000BE020000BE020000BF020000C0020000C1020000C1020000C2020000C3020000C3020000C4020000C5020000C6020000C6020000C7020000C8020000C8020000C9020000CA020000CA020000CB020000CC020000CD020000CD020000CE020000CF020000CF020000D0020000D1020000D1020000D2020000D3020000D4020000D4020000D5020000D6020000D6020000D7020000D8020000D8020000D9020000DA020000DA020000DB020000DC020000DD020000DD020000DE020000DF020000DF020000E0020000E1020000E1020000E2020000E3020000E3020000E4020000E5020000E5020000E6020000E7020000E7020000E8020000E9020000E9020000EA020000EB020000EB020000EC020000ED020000ED020000EE020000EF020000EF020000F0020000F1020000F1020000F2020000F3020000F3020000F4020000F5020000F5020000F6020000F6020000F7020000F8020000F8020000F9020000FA020000FA020000FB020000FC020000FC020000FD020000FE020000FE020000FF020000000300000003000001030000010300000203000003030000030300000403000005030000050300000603000007030000070300000803000008030000090300000A0300000A0300000B0300000C0300000C0300000D0300000D0300000E0300000F0300000F030000100300001103000011030000120300001203000013030000140300001403000015030000160300001603000017030000170300001803000019030000190300001A0300001B0300001B0300001C0300001C0300001D0300001E0300001E0300001F0300001F030000200300002103000021030000220300002203000023030000240300002403000025030000250300002603000027030000270300002803000028030000290300002A0300002A0300002B0300002B0300002C0300002D0300002D0300002E0300002E0300002F03000030030000300300003103000031030000320300003303000033030000340300003403000035030000360300003603000037030000370300003803000038030000390300003A0300003A0300003B0300003B0300003C0300003D0300003D0300003E0300003E0300003F0300003F03000040030000410300004103000042030000420300004303000043030000440300004503000045030000460300004603000047030000470300004803000049030000490300004A0300004A0300004B0300004B0300004C0300004D0300004D0300004E0300004E0300004F0300004F0300005003000051030000510300005203000052030000530300005303000054030000540300005503000056030000560300005703000057030000580300005803000059030000590300005A0300005B0300005B0300005C0300005C0300005D0300005D0300005E0300005E0300005F030000600300006003000061030000610300006203000062030000630300006303000064030000640300006503000066030000660300006703000067030000680300006803000069030000690300006A0300006A0300006B0300006C0300006C0300006D0300006D0300006E0300006E0300006F0300006F030000700300007003000071030000710300007203000073030000730300007403000074030000750300007503000076030000760300007703000077030000780300007803000079030000790300007A0300007A0300007B0300007C0300007C0300007D0300007D0300007E0300007E0300007F0300007F030000800300008003000081030000810300008203000082030000830300008303000084030000840300008503000085030000860300008703000087030000880300008803000089030000890300008A0300008A0300008B0300008B0300008C0300008C0300008D0300008D0300008E0300008E0300008F0300008F03000090030000900300009103000091030000920300009203000093030000930300009403000094030000950300009503000096030000960300009703000097030000980300009803000099030000990300009A0300009A0300009B0300009B0300009C0300009C0300009D0300009D0300009E0300009E0300009F0300009F030000A0030000A0030000A1030000A1030000A2030000A2030000A3030000A3030000A4030000A4030000A5030000A5030000A6030000A6030000A7030000A7030000A8030000A8030000A9030000A9030000AA030000AA030000AB030000AB030000AC030000AC030000AD030000AD030000AE030000AE030000AF030000AF030000B0030000B0030000B1030000B1030000B2030000B2030000B3030000B3030000B4030000B4030000B5030000B5030000B6030000B6030000B7030000B7030000B8030000B8030000B9030000B9030000BA030000BA030000BA030000BB030000BB030000BC030000BC030000BD030000BD030000BE030000BE030000BF030000BF030000C0030000C0030000C1030000C1030000C2030000C2030000C3030000C3030000C4030000C4030000C5030000C5030000C5030000C6030000C6030000C7030000C7030000C8030000C8030000C9030000C9030000CA030000CA030000CB030000CB030000CC030000CC030000CD030000CD030000CE030000CE030000CE030000CF030000CF030000D0030000D0030000D1030000D1030000D2030000D2030000D3030000D3030000D4030000D4030000D5030000D5030000D5030000D6030000D6030000D7030000D7030000D8030000D8030000D9030000D9030000DA030000DA030000DB030000DB030000DB030000DC030000DC030000DD030000DD030000DE030000DE030000DF030000DF030000E0030000E0030000E1030000E1030000E1030000E2030000E2030000E3030000E3030000E4030000E4030000E5030000E5030000E6030000E6030000E6030000E7030000E7030000E8030000E8030000E9030000E9030000EA030000EA030000EB030000EB030000EB030000EC030000EC030000ED030000ED030000EE030000EE030000EF030000EF030000EF030000F0030000F0030000F1030000F1030000F2030000F2030000F3030000F3030000F3030000F4030000F4030000F5030000F5030000F6030000F6030000F7030000F7030000F7030000F8030000F8030000F9030000F9030000FA030000FA030000FB030000FB030000FB030000FC030000FC030000FD030000FD030000FE030000FE030000FF030000FF030000000000000D0000001A00000027000000330000003D000000470000004F000000570000005E000000650000006B00000071000000770000007C00000082000000870000008B0000009000000095000000990000009E000000A2000000A6000000AA000000AE000000B1000000B5000000B9000000BC000000C0000000C3000000C7000000CA000000CD000000D0000000D3000000D6000000D9000000DC000000DF000000E2000000E5000000E8000000EB000000ED000000F0000000F3000000F5000000F8000000FB000000FD00000000010000020100000501000007010000090100000C0100000E010000100100001301000015010000170100001A0100001C0100001E01000020010000220100002501000027010000290100002B0100002D0100002F01000031010000330100003501000037010000390100003B0100003D0100003F01000041010000430100004501000047010000480100004A0100004C0100004E0100005001000052010000530100005501000057010000590100005A0100005C0100005E0100006001000061010000630100006501000066010000680100006A0100006B0100006D0100006F0100007001000072010000740100007501000077010000780100007A0100007B0100007D0100007F010000800100008201000083010000850100008601000088010000890100008B0100008C0100008E0100008F010000910100009201000094010000950100009601000098010000990100009B0100009C0100009E0100009F010000A0010000A2010000A3010000A5010000A6010000A7010000A9010000AA010000AB010000AD010000AE010000AF010000B1010000B2010000B3010000B5010000B6010000B7010000B9010000BA010000BB010000BD010000BE010000BF010000C0010000C2010000C3010000C4010000C5010000C7010000C8010000C9010000CA010000CC010000CD010000CE010000CF010000D1010000D2010000D3010000D4010000D5010000D7010000D8010000D9010000DA010000DB010000DD010000DE010000DF010000E0010000E1010000E2010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F0200001002000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F02000040020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004B0200004C0200004D0200004E0200004F02000050020000510200005202000053020000540200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005C0200005D0200005E0200005F0200006002000061020000620200006202000063020000640200006502000066020000670200006802000068020000690200006A0200006B0200006C0200006D0200006E0200006E0200006F0200007002000071020000720200007302000073020000740200007502000076020000770200007802000078020000790200007A0200007B0200007C0200007D0200007D0200007E0200007F020000800200008102000081020000820200008302000084020000850200008502000086020000870200008802000089020000890200008A0200008B0200008C0200008D0200008D0200008E0200008F020000900200009102000091020000920200009302000094020000940200009502000096020000970200009802000098020000990200009A0200009B0200009B0200009C0200009D0200009E0200009E0200009F020000A0020000A1020000A2020000A2020000A3020000A4020000A5020000A5020000A6020000A7020000A8020000A8020000A9020000AA020000AB020000AB020000AC020000AD020000AE020000AE020000AF020000B0020000B1020000B1020000B2020000B3020000B3020000B4020000B5020000B6020000B6020000B7020000B8020000B9020000B9020000BA020000BB020000BB020000BC020000BD020000BE020000BE020000BF020000C0020000C1020000C1020000C2020000C3020000C3020000C4020000C5020000C6020000C6020000C7020000C8020000C8020000C9020000CA020000CA020000CB020000CC020000CD020000CD020000CE020000CF020000CF020000D0020000D1020000D1020000D2020000D3020000D4020000D4020000D5020000D6020000D6020000D7020000D8020000D8020000D9020000DA020000DA020000DB020000DC020000DD020000DD020000DE020000DF020000DF020000E0020000E1020000E1020000E2020000E3020000E3020000E4020000E5020000E5020000E6020000E7020000E7020000E8020000E9020000E9020000EA020000EB020000EB020000EC020000ED020000ED020000EE020000EF020000EF020000F0020000F1020000F1020000F2020000F3020000F3020000F4020000F5020000F5020000F6020000F6020000F7020000F8020000F8020000F9020000FA020000FA020000FB020000FC020000FC020000FD020000FE020000FE020000FF020000000300000003000001030000010300000203000003030000030300000403000005030000050300000603000007030000070300000803000008030000090300000A0300000A0300000B0300000C0300000C0300000D0300000D0300000E0300000F0300000F030000100300001103000011030000120300001203000013030000140300001403000015030000160300001603000017030000170300001803000019030000190300001A0300001B0300001B0300001C0300001C0300001D0300001E0300001E0300001F0300001F030000200300002103000021030000220300002203000023030000240300002403000025030000250300002603000027030000270300002803000028030000290300002A0300002A0300002B0300002B0300002C0300002D0300002D0300002E0300002E0300002F03000030030000300300003103000031030000320300003303000033030000340300003403000035030000360300003603000037030000370300003803000038030000390300003A0300003A0300003B0300003B0300003C0300003D0300003D0300003E0300003E0300003F0300003F03000040030000410300004103000042030000420300004303000043030000440300004503000045030000460300004603000047030000470300004803000049030000490300004A0300004A0300004B0300004B0300004C0300004D0300004D0300004E0300004E0300004F0300004F0300005003000051030000510300005203000052030000530300005303000054030000540300005503000056030000560300005703000057030000580300005803000059030000590300005A0300005B0300005B0300005C0300005C0300005D0300005D0300005E0300005E0300005F030000600300006003000061030000610300006203000062030000630300006303000064030000640300006503000066030000660300006703000067030000680300006803000069030000690300006A0300006A0300006B0300006C0300006C0300006D0300006D0300006E0300006E0300006F0300006F030000700300007003000071030000710300007203000073030000730300007403000074030000750300007503000076030000760300007703000077030000780300007803000079030000790300007A0300007A0300007B0300007C0300007C0300007D0300007D0300007E0300007E0300007F0300007F030000800300008003000081030000810300008203000082030000830300008303000084030000840300008503000085030000860300008703000087030000880300008803000089030000890300008A0300008A0300008B0300008B0300008C0300008C0300008D0300008D0300008E0300008E0300008F0300008F03000090030000900300009103000091030000920300009203000093030000930300009403000094030000950300009503000096030000960300009703000097030000980300009803000099030000990300009A0300009A0300009B0300009B0300009C0300009C0300009D0300009D0300009E0300009E0300009F0300009F030000A0030000A0030000A1030000A1030000A2030000A2030000A3030000A3030000A4030000A4030000A5030000A5030000A6030000A6030000A7030000A7030000A8030000A8030000A9030000A9030000AA030000AA030000AB030000AB030000AC030000AC030000AD030000AD030000AE030000AE030000AF030000AF030000B0030000B0030000B1030000B1030000B2030000B2030000B3030000B3030000B4030000B4030000B5030000B5030000B6030000B6030000B7030000B7030000B8030000B8030000B9030000B9030000BA030000BA030000BA030000BB030000BB030000BC030000BC030000BD030000BD030000BE030000BE030000BF030000BF030000C0030000C0030000C1030000C1030000C2030000C2030000C3030000C3030000C4030000C4030000C5030000C5030000C5030000C6030000C6030000C7030000C7030000C8030000C8030000C9030000C9030000CA030000CA030000CB030000CB030000CC030000CC030000CD030000CD030000CE030000CE030000CE030000CF030000CF030000D0030000D0030000D1030000D1030000D2030000D2030000D3030000D3030000D4030000D4030000D5030000D5030000D5030000D6030000D6030000D7030000D7030000D8030000D8030000D9030000D9030000DA030000DA030000DB030000DB030000DB030000DC030000DC030000DD030000DD030000DE030000DE030000DF030000DF030000E0030000E0030000E1030000E1030000E1030000E2030000E2030000E3030000E3030000E4030000E4030000E5030000E5030000E6030000E6030000E6030000E7030000E7030000E8030000E8030000E9030000E9030000EA030000EA030000EB030000EB030000EB030000EC030000EC030000ED030000ED030000EE030000EE030000EF030000EF030000EF030000F0030000F0030000F1030000F1030000F2030000F2030000F3030000F3030000F3030000F4030000F4030000F5030000F5030000F6030000F6030000F7030000F7030000F7030000F8030000F8030000F9030000F9030000FA030000FA030000FB030000FB030000FB030000FC030000FC030000FD030000FD030000FE030000FE030000FF030000FF030000000000000D0000001A00000027000000330000003D000000470000004F000000570000005E000000650000006B00000071000000770000007C00000082000000870000008B0000009000000095000000990000009E000000A2000000A6000000AA000000AE000000B1000000B5000000B9000000BC000000C0000000C3000000C7000000CA000000CD000000D0000000D3000000D6000000D9000000DC000000DF000000E2000000E5000000E8000000EB000000ED000000F0000000F3000000F5000000F8000000FB000000FD00000000010000020100000501000007010000090100000C0100000E010000100100001301000015010000170100001A0100001C0100001E01000020010000220100002501000027010000290100002B0100002D0100002F01000031010000330100003501000037010000390100003B0100003D0100003F01000041010000430100004501000047010000480100004A0100004C0100004E0100005001000052010000530100005501000057010000590100005A0100005C0100005E0100006001000061010000630100006501000066010000680100006A0100006B0100006D0100006F0100007001000072010000740100007501000077010000780100007A0100007B0100007D0100007F010000800100008201000083010000850100008601000088010000890100008B0100008C0100008E0100008F010000910100009201000094010000950100009601000098010000990100009B0100009C0100009E0100009F010000A0010000A2010000A3010000A5010000A6010000A7010000A9010000AA010000AB010000AD010000AE010000AF010000B1010000B2010000B3010000B5010000B6010000B7010000B9010000BA010000BB010000BD010000BE010000BF010000C0010000C2010000C3010000C4010000C5010000C7010000C8010000C9010000CA010000CC010000CD010000CE010000CF010000D1010000D2010000D3010000D4010000D5010000D7010000D8010000D9010000DA010000DB010000DD010000DE010000DF010000E0010000E1010000E2010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F0200001002000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F02000040020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004B0200004C0200004D0200004E0200004F02000050020000510200005202000053020000540200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005C0200005D0200005E0200005F0200006002000061020000620200006202000063020000640200006502000066020000670200006802000068020000690200006A0200006B0200006C0200006D0200006E0200006E0200006F0200007002000071020000720200007302000073020000740200007502000076020000770200007802000078020000790200007A0200007B0200007C0200007D0200007D0200007E0200007F020000800200008102000081020000820200008302000084020000850200008502000086020000870200008802000089020000890200008A0200008B0200008C0200008D0200008D0200008E0200008F020000900200009102000091020000920200009302000094020000940200009502000096020000970200009802000098020000990200009A0200009B0200009B0200009C0200009D0200009E0200009E0200009F020000A0020000A1020000A2020000A2020000A3020000A4020000A5020000A5020000A6020000A7020000A8020000A8020000A9020000AA020000AB020000AB020000AC020000AD020000AE020000AE020000AF020000B0020000B1020000B1020000B2020000B3020000B3020000B4020000B5020000B6020000B6020000B7020000B8020000B9020000B9020000BA020000BB020000BB020000BC020000BD020000BE020000BE020000BF020000C0020000C1020000C1020000C2020000C3020000C3020000C4020000C5020000C6020000C6020000C7020000C8020000C8020000C9020000CA020000CA020000CB020000CC020000CD020000CD020000CE020000CF020000CF020000D0020000D1020000D1020000D2020000D3020000D4020000D4020000D5020000D6020000D6020000D7020000D8020000D8020000D9020000DA020000DA020000DB020000DC020000DD020000DD020000DE020000DF020000DF020000E0020000E1020000E1020000E2020000E3020000E3020000E4020000E5020000E5020000E6020000E7020000E7020000E8020000E9020000E9020000EA020000EB020000EB020000EC020000ED020000ED020000EE020000EF020000EF020000F0020000F1020000F1020000F2020000F3020000F3020000F4020000F5020000F5020000F6020000F6020000F7020000F8020000F8020000F9020000FA020000FA020000FB020000FC020000FC020000FD020000FE020000FE020000FF020000000300000003000001030000010300000203000003030000030300000403000005030000050300000603000007030000070300000803000008030000090300000A0300000A0300000B0300000C0300000C0300000D0300000D0300000E0300000F0300000F030000100300001103000011030000120300001203000013030000140300001403000015030000160300001603000017030000170300001803000019030000190300001A0300001B0300001B0300001C0300001C0300001D0300001E0300001E0300001F0300001F030000200300002103000021030000220300002203000023030000240300002403000025030000250300002603000027030000270300002803000028030000290300002A0300002A0300002B0300002B0300002C0300002D0300002D0300002E0300002E0300002F03000030030000300300003103000031030000320300003303000033030000340300003403000035030000360300003603000037030000370300003803000038030000390300003A0300003A0300003B0300003B0300003C0300003D0300003D0300003E0300003E0300003F0300003F03000040030000410300004103000042030000420300004303000043030000440300004503000045030000460300004603000047030000470300004803000049030000490300004A0300004A0300004B0300004B0300004C0300004D0300004D0300004E0300004E0300004F0300004F0300005003000051030000510300005203000052030000530300005303000054030000540300005503000056030000560300005703000057030000580300005803000059030000590300005A0300005B0300005B0300005C0300005C0300005D0300005D0300005E0300005E0300005F030000600300006003000061030000610300006203000062030000630300006303000064030000640300006503000066030000660300006703000067030000680300006803000069030000690300006A0300006A0300006B0300006C0300006C0300006D0300006D0300006E0300006E0300006F0300006F030000700300007003000071030000710300007203000073030000730300007403000074030000750300007503000076030000760300007703000077030000780300007803000079030000790300007A0300007A0300007B0300007C0300007C0300007D0300007D0300007E0300007E0300007F0300007F030000800300008003000081030000810300008203000082030000830300008303000084030000840300008503000085030000860300008703000087030000880300008803000089030000890300008A0300008A0300008B0300008B0300008C0300008C0300008D0300008D0300008E0300008E0300008F0300008F03000090030000900300009103000091030000920300009203000093030000930300009403000094030000950300009503000096030000960300009703000097030000980300009803000099030000990300009A0300009A0300009B0300009B0300009C0300009C0300009D0300009D0300009E0300009E0300009F0300009F030000A0030000A0030000A1030000A1030000A2030000A2030000A3030000A3030000A4030000A4030000A5030000A5030000A6030000A6030000A7030000A7030000A8030000A8030000A9030000A9030000AA030000AA030000AB030000AB030000AC030000AC030000AD030000AD030000AE030000AE030000AF030000AF030000B0030000B0030000B1030000B1030000B2030000B2030000B3030000B3030000B4030000B4030000B5030000B5030000B6030000B6030000B7030000B7030000B8030000B8030000B9030000B9030000BA030000BA030000BA030000BB030000BB030000BC030000BC030000BD030000BD030000BE030000BE030000BF030000BF030000C0030000C0030000C1030000C1030000C2030000C2030000C3030000C3030000C4030000C4030000C5030000C5030000C5030000C6030000C6030000C7030000C7030000C8030000C8030000C9030000C9030000CA030000CA030000CB030000CB030000CC030000CC030000CD030000CD030000CE030000CE030000CE030000CF030000CF030000D0030000D0030000D1030000D1030000D2030000D2030000D3030000D3030000D4030000D4030000D5030000D5030000D5030000D6030000D6030000D7030000D7030000D8030000D8030000D9030000D9030000DA030000DA030000DB030000DB030000DB030000DC030000DC030000DD030000DD030000DE030000DE030000DF030000DF030000E0030000E0030000E1030000E1030000E1030000E2030000E2030000E3030000E3030000E4030000E4030000E5030000E5030000E6030000E6030000E6030000E7030000E7030000E8030000E8030000E9030000E9030000EA030000EA030000EB030000EB030000EB030000EC030000EC030000ED030000ED030000EE030000EE030000EF030000EF030000EF030000F0030000F0030000F1030000F1030000F2030000F2030000F3030000F3030000F3030000F4030000F4030000F5030000F5030000F6030000F6030000F7030000F7030000F7030000F8030000F8030000F9030000F9030000FA030000FA030000FB030000FB030000FB030000FC030000FC030000FD030000FD030000FE030000FE030000FF030000FF030000 + 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F00000021000000210000000300000003000000000000002D00000000000000000000000000C84200000000000000000000C84200000000000000000100000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000B5FFFFFF5BFFFFFF000000000000C84200000000000000000000C84200000000000000000200000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000A50000004B000000000000000000C84200000000000000000000C84200000000000000000000000000000000640000000A0000000100000064000000000000000100000021000000210000000300000003000000000000000000000080010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + 0000C842 + 00000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + + ECFFFFFF0000803F936F163FDA1AB13DEDFFFFFF0000803F87501D3FB9530A3EEEFFFFFF0000803FAAEE213FD1912C3EEFFFFFFF0000803F8CBC283F8C82603EF0FFFFFF0000803F473C2D3FD1E9813EF1FFFFFF0000803F5C02343FFE0E9D3EF2FFFFFF0000803F6E6E383FE04DAF3EF3FFFFFF0000803F31093F3F3C16CB3EF4FFFFFF0000803F3960433F73BDDD3EF5FFFFFF0000803F91D5493F6519FA3EF6FFFFFF0000803F840E4E3F957E063FF7FFFFFF0000803F1B62543FCEDF143FF8FFFFFF0000803F828C583F90871E3FF9FFFFFF0000803FF2B65E3F1A182D3FFAFFFFFF0000803FE7C4623FABCE363FFBFFFFFF0000803FD7BE683F8E5A453FFCFFFFFF0000803F41B66C3FD6194F3FFDFFFFFF0000803F1E8A723F8AAC5D3FFEFFFFFF0000803F516B763F6475673FFFFFFFFF0000803F8A227C3FB41E763F000000000000803F0000803F0000803F01000000836B723F6189773F0000803F02000000BF0C6A3F484E723F0000803F03000000CD945E3F191E6B3F0000803F04000000B988573FEFAB663F0000803F0500000084D44D3F5E81603F0000803F0600000045D9473FEBAA5C3F0000803F07000000CA883F3F2651573F0000803F080000005C593A3FADFB533F0000803F09000000802D333F05514F3F0000803F0A00000083C02E3FC3624C3F0000803F0B0000005986283FE04C483F0000803F0C0000008C9D243F18B3453F0000803F0D000000431C1F3F8909423F0000803F0E000000ABB21B3FE4C03F3F0000803F0F0000003DD4163FC07A3C3F0000803F1000000009C0133FE4683A3F0000803F110000008A740F3FF27B373F0000803F1200000039B80C3FCB9D353F0000803F130000005DDE083FBAF9323F0000803F140000009467063F3448313F0000803F + + diff --git a/configs/sec_config b/configs/sec_config new file mode 100644 index 0000000..b0db281 --- /dev/null +++ b/configs/sec_config @@ -0,0 +1,321 @@ +/* IPC Security Config */ +/* :: */ +16:4294967295:1000:1021 +/* :: */ +56:4294967295:1021 +/* Allow SS CTL service to be used by system and net_raw processes */ +43:4294967295:1000:3004 +/* :: */ +71:4294967295:1001 +/* :: */ +50:4294967295:1001 +/* QMI-SLIM service permitted to gps and net_raw */ +55:4294967295:1021 +/* Allow Sensor services to be used by sensor process */ +256:4294967295:1000:1006:1013:1021:1047:3011 +257:4294967295:1000:1006:1013:1021:1047:3011 +258:4294967295:1000:1006:1013:1021:1047:3011 +259:4294967295:1000:1006:1013:1021:1047:3011 +260:4294967295:1000:1006:1013:1021:1047:3011 +261:4294967295:1000:1006:1013:1021:1047:3011 +262:4294967295:1000:1006:1013:1021:1047:3011 +263:4294967295:1000:1006:1013:1021:1047:3011 +264:4294967295:1000:1006:1013:1021:1047:3011 +265:4294967295:1000:1006:1013:1021:1047:3011 +266:4294967295:1000:1006:1013:1021:1047:3011 +267:4294967295:1000:1006:1013:1021:1047:3011 +268:4294967295:1000:1006:1013:1021:1047:3011 +269:4294967295:1000:1006:1013:1021:1047:3011 +270:4294967295:1000:1006:1013:1021:1047:3011 +271:4294967295:1000:1006:1013:1021:1047:3011 +272:4294967295:1000:1006:1013:1021:1047:3011 +273:4294967295:1000:1006:1013:1021:1047:3011 +274:4294967295:1000:1006:1013:1021:1047:3011 +275:4294967295:1000:1006:1013:1021:1047:3011 +276:4294967295:1000:1006:1013:1021:1047:3011 +277:4294967295:1000:1006:1013:1021:1047:3011 +278:4294967295:1000:1006:1013:1021:1047:3011 +279:4294967295:1000:1006:1013:1021:1047:3011 +280:4294967295:1000:1006:1013:1021:1047:3011 +281:4294967295:1000:1006:1013:1021:1047:3011 +282:4294967295:1000:1006:1013:1021:1047:3011 +283:4294967295:1000:1006:1013:1021:1047:3011 +284:4294967295:1000:1006:1013:1021:1047:3011 +285:4294967295:1000:1006:1013:1021:1047:3011 +286:4294967295:1000:1006:1013:1021:1047:3011 +287:4294967295:1000:1006:1013:1021:1047:3011 +288:4294967295:1000:1006:1013:1021:1047:3011 +289:4294967295:1000:1006:1013:1021:1047:3011 +290:4294967295:1000:1006:1013:1021:1047:3011 +291:4294967295:1000:1006:1013:1021:1047:3011 +292:4294967295:1000:1006:1013:1021:1047:3011 +293:4294967295:1000:1006:1013:1021:1047:3011 +294:4294967295:1000:1006:1013:1021:1047:3011 +295:4294967295:1000:1006:1013:1021:1047:3011 +296:4294967295:1000:1006:1013:1021:1047:3011 +297:4294967295:1000:1006:1013:1021:1047:3011 +298:4294967295:1000:1006:1013:1021:1047:3011 +299:4294967295:1000:1006:1013:1021:1047:3011 +300:4294967295:1000:1006:1013:1021:1047:3011 +301:4294967295:1000:1006:1013:1021:1047:3011 +302:4294967295:1000:1006:1013:1021:1047:3011 +303:4294967295:1000:1006:1013:1021:1047:3011 +304:4294967295:1000:1006:1013:1021:1047:3011 +305:4294967295:1000:1006:1013:1021:1047:3011 +306:4294967295:1000:1006:1013:1021:1047:3011 +307:4294967295:1000:1006:1013:1021:1047:3011 +308:4294967295:1000:1006:1013:1021:1047:3011 +309:4294967295:1000:1006:1013:1021:1047:3011 +310:4294967295:1000:1006:1013:1021:1047:3011 +311:4294967295:1000:1006:1013:1021:1047:3011 +312:4294967295:1000:1006:1013:1021:1047:3011 +313:4294967295:1000:1006:1013:1021:1047:3011 +314:4294967295:1000:1006:1013:1021:1047:3011 +315:4294967295:1000:1006:1013:1021:1047:3011 +316:4294967295:1000:1006:1013:1021:1047:3011 +317:4294967295:1000:1006:1013:1021:1047:3011 +318:4294967295:1000:1006:1013:1021:1047:3011 +319:4294967295:1000:1006:1013:1021:1047:3011 +320:4294967295:1000:1006:1013:1021:1047:3011 +321:4294967295:1000:1006:1013:1021:1047:3011 +322:4294967295:1000:1006:1013:1021:1047:3011 +323:4294967295:1000:1006:1013:1021:1047:3011 +324:4294967295:1000:1006:1013:1021:1047:3011 +325:4294967295:1000:1006:1013:1021:1047:3011 +326:4294967295:1000:1006:1013:1021:1047:3011 +327:4294967295:1000:1006:1013:1021:1047:3011 +328:4294967295:1000:1006:1013:1021:1047:3011 +329:4294967295:1000:1006:1013:1021:1047:3011 +330:4294967295:1000:1006:1013:1021:1047:3011 +331:4294967295:1000:1006:1013:1021:1047:3011 +332:4294967295:1000:1006:1013:1021:1047:3011 +333:4294967295:1000:1006:1013:1021:1047:3011 +334:4294967295:1000:1006:1013:1021:1047:3011 +335:4294967295:1000:1006:1013:1021:1047:3011 +336:4294967295:1000:1006:1013:1021:1047:3011 +337:4294967295:1000:1006:1013:1021:1047:3011 +338:4294967295:1000:1006:1013:1021:1047:3011 +339:4294967295:1000:1006:1013:1021:1047:3011 +340:4294967295:1000:1006:1013:1021:1047:3011 +341:4294967295:1000:1006:1013:1021:1047:3011 +342:4294967295:1000:1006:1013:1021:1047:3011 +343:4294967295:1000:1006:1013:1021:1047:3011 +344:4294967295:1000:1006:1013:1021:1047:3011 +345:4294967295:1000:1006:1013:1021:1047:3011 +346:4294967295:1000:1006:1013:1021:1047:3011 +347:4294967295:1000:1006:1013:1021:1047:3011 +348:4294967295:1000:1006:1013:1021:1047:3011 +349:4294967295:1000:1006:1013:1021:1047:3011 +350:4294967295:1000:1006:1013:1021:1047:3011 +351:4294967295:1000:1006:1013:1021:1047:3011 +352:4294967295:1000:1006:1013:1021:1047:3011 +353:4294967295:1000:1006:1013:1021:1047:3011 +354:4294967295:1000:1006:1013:1021:1047:3011 +355:4294967295:1000:1006:1013:1021:1047:3011 +356:4294967295:1000:1006:1013:1021:1047:3011 +357:4294967295:1000:1006:1013:1021:1047:3011 +358:4294967295:1000:1006:1013:1021:1047:3011 +359:4294967295:1000:1006:1013:1021:1047:3011 +360:4294967295:1000:1006:1013:1021:1047:3011 +361:4294967295:1000:1006:1013:1021:1047:3011 +362:4294967295:1000:1006:1013:1021:1047:3011 +363:4294967295:1000:1006:1013:1021:1047:3011 +364:4294967295:1000:1006:1013:1021:1047:3011 +365:4294967295:1000:1006:1013:1021:1047:3011 +366:4294967295:1000:1006:1013:1021:1047:3011 +367:4294967295:1000:1006:1013:1021:1047:3011 +368:4294967295:1000:1006:1013:1021:1047:3011 +369:4294967295:1000:1006:1013:1021:1047:3011 +370:4294967295:1000:1006:1013:1021:1047:3011 +371:4294967295:1000:1006:1013:1021:1047:3011 +372:4294967295:1000:1006:1013:1021:1047:3011 +373:4294967295:1000:1006:1013:1021:1047:3011 +374:4294967295:1000:1006:1013:1021:1047:3011 +375:4294967295:1000:1006:1013:1021:1047:3011 +376:4294967295:1000:1006:1013:1021:1047:3011 +377:4294967295:1000:1006:1013:1021:1047:3011 +378:4294967295:1000:1006:1013:1021:1047:3011 +379:4294967295:1000:1006:1013:1021:1047:3011 +380:4294967295:1000:1006:1013:1021:1047:3011 +381:4294967295:1000:1006:1013:1021:1047:3011 +382:4294967295:1000:1006:1013:1021:1047:3011 +383:4294967295:1000:1006:1013:1021:1047:3011 +384:4294967295:1000:1006:1013:1021:1047:3011 +385:4294967295:1000:1006:1013:1021:1047:3011 +386:4294967295:1000:1006:1013:1021:1047:3011 +387:4294967295:1000:1006:1013:1021:1047:3011 +388:4294967295:1000:1006:1013:1021:1047:3011 +389:4294967295:1000:1006:1013:1021:1047:3011 +390:4294967295:1000:1006:1013:1021:1047:3011 +391:4294967295:1000:1006:1013:1021:1047:3011 +392:4294967295:1000:1006:1013:1021:1047:3011 +393:4294967295:1000:1006:1013:1021:1047:3011 +394:4294967295:1000:1006:1013:1021:1047:3011 +395:4294967295:1000:1006:1013:1021:1047:3011 +396:4294967295:1000:1006:1013:1021:1047:3011 +397:4294967295:1000:1006:1013:1021:1047:3011 +398:4294967295:1000:1006:1013:1021:1047:3011 +399:4294967295:1000:1006:1013:1021:1047:3011 +400:4294967295:1000:1006:1013:1021:1047:3011 +401:4294967295:1000:1006:1013:1021:1047:3011 +402:4294967295:1000:1006:1013:1021:1047:3011 +403:4294967295:1000:1006:1013:1021:1047:3011 +404:4294967295:1000:1006:1013:1021:1047:3011 +405:4294967295:1000:1006:1013:1021:1047:3011 +406:4294967295:1000:1006:1013:1021:1047:3011 +407:4294967295:1000:1006:1013:1021:1047:3011 +408:4294967295:1000:1006:1013:1021:1047:3011 +409:4294967295:1000:1006:1013:1021:1047:3011 +410:4294967295:1000:1006:1013:1021:1047:3011 +411:4294967295:1000:1006:1013:1021:1047:3011 +412:4294967295:1000:1006:1013:1021:1047:3011 +413:4294967295:1000:1006:1013:1021:1047:3011 +414:4294967295:1000:1006:1013:1021:1047:3011 +415:4294967295:1000:1006:1013:1021:1047:3011 +416:4294967295:1000:1006:1013:1021:1047:3011 +417:4294967295:1000:1006:1013:1021:1047:3011 +418:4294967295:1000:1006:1013:1021:1047:3011 +419:4294967295:1000:1006:1013:1021:1047:3011 +420:4294967295:1000:1006:1013:1021:1047:3011 +421:4294967295:1000:1006:1013:1021:1047:3011 +422:4294967295:1000:1006:1013:1021:1047:3011 +423:4294967295:1000:1006:1013:1021:1047:3011 +424:4294967295:1000:1006:1013:1021:1047:3011 +425:4294967295:1000:1006:1013:1021:1047:3011 +426:4294967295:1000:1006:1013:1021:1047:3011 +427:4294967295:1000:1006:1013:1021:1047:3011 +428:4294967295:1000:1006:1013:1021:1047:3011 +429:4294967295:1000:1006:1013:1021:1047:3011 +430:4294967295:1000:1006:1013:1021:1047:3011 +431:4294967295:1000:1006:1013:1021:1047:3011 +432:4294967295:1000:1006:1013:1021:1047:3011 +433:4294967295:1000:1006:1013:1021:1047:3011 +434:4294967295:1000:1006:1013:1021:1047:3011 +435:4294967295:1000:1006:1013:1021:1047:3011 +436:4294967295:1000:1006:1013:1021:1047:3011 +437:4294967295:1000:1006:1013:1021:1047:3011 +438:4294967295:1000:1006:1013:1021:1047:3011 +439:4294967295:1000:1006:1013:1021:1047:3011 +440:4294967295:1000:1006:1013:1021:1047:3011 +441:4294967295:1000:1006:1013:1021:1047:3011 +442:4294967295:1000:1006:1013:1021:1047:3011 +443:4294967295:1000:1006:1013:1021:1047:3011 +444:4294967295:1000:1006:1013:1021:1047:3011 +445:4294967295:1000:1006:1013:1021:1047:3011 +446:4294967295:1000:1006:1013:1021:1047:3011 +447:4294967295:1000:1006:1013:1021:1047:3011 +448:4294967295:1000:1006:1013:1021:1047:3011 +449:4294967295:1000:1006:1013:1021:1047:3011 +450:4294967295:1000:1006:1013:1021:1047:3011 +451:4294967295:1000:1006:1013:1021:1047:3011 +452:4294967295:1000:1006:1013:1021:1047:3011 +453:4294967295:1000:1006:1013:1021:1047:3011 +454:4294967295:1000:1006:1013:1021:1047:3011 +455:4294967295:1000:1006:1013:1021:1047:3011 +456:4294967295:1000:1006:1013:1021:1047:3011 +457:4294967295:1000:1006:1013:1021:1047:3011 +458:4294967295:1000:1006:1013:1021:1047:3011 +459:4294967295:1000:1006:1013:1021:1047:3011 +460:4294967295:1000:1006:1013:1021:1047:3011 +461:4294967295:1000:1006:1013:1021:1047:3011 +462:4294967295:1000:1006:1013:1021:1047:3011 +463:4294967295:1000:1006:1013:1021:1047:3011 +464:4294967295:1000:1006:1013:1021:1047:3011 +465:4294967295:1000:1006:1013:1021:1047:3011 +466:4294967295:1000:1006:1013:1021:1047:3011 +467:4294967295:1000:1006:1013:1021:1047:3011 +468:4294967295:1000:1006:1013:1021:1047:3011 +469:4294967295:1000:1006:1013:1021:1047:3011 +470:4294967295:1000:1006:1013:1021:1047:3011 +471:4294967295:1000:1006:1013:1021:1047:3011 +472:4294967295:1000:1006:1013:1021:1047:3011 +473:4294967295:1000:1006:1013:1021:1047:3011 +474:4294967295:1000:1006:1013:1021:1047:3011 +475:4294967295:1000:1006:1013:1021:1047:3011 +476:4294967295:1000:1006:1013:1021:1047:3011 +477:4294967295:1000:1006:1013:1021:1047:3011 +478:4294967295:1000:1006:1013:1021:1047:3011 +479:4294967295:1000:1006:1013:1021:1047:3011 +480:4294967295:1000:1006:1013:1021:1047:3011 +481:4294967295:1000:1006:1013:1021:1047:3011 +482:4294967295:1000:1006:1013:1021:1047:3011 +483:4294967295:1000:1006:1013:1021:1047:3011 +484:4294967295:1000:1006:1013:1021:1047:3011 +485:4294967295:1000:1006:1013:1021:1047:3011 +486:4294967295:1000:1006:1013:1021:1047:3011 +487:4294967295:1000:1006:1013:1021:1047:3011 +488:4294967295:1000:1006:1013:1021:1047:3011 +489:4294967295:1000:1006:1013:1021:1047:3011 +490:4294967295:1000:1006:1013:1021:1047:3011 +491:4294967295:1000:1006:1013:1021:1047:3011 +492:4294967295:1000:1006:1013:1021:1047:3011 +493:4294967295:1000:1006:1013:1021:1047:3011 +494:4294967295:1000:1006:1013:1021:1047:3011 +495:4294967295:1000:1006:1013:1021:1047:3011 +496:4294967295:1000:1006:1013:1021:1047:3011 +497:4294967295:1000:1006:1013:1021:1047:3011 +498:4294967295:1000:1006:1013:1021:1047:3011 +499:4294967295:1000:1006:1013:1021:1047:3011 +500:4294967295:1000:1006:1013:1021:1047:3011 +501:4294967295:1000:1006:1013:1021:1047:3011 +502:4294967295:1000:1006:1013:1021:1047:3011 +503:4294967295:1000:1006:1013:1021:1047:3011 +504:4294967295:1000:1006:1013:1021:1047:3011 +505:4294967295:1000:1006:1013:1021:1047:3011 +506:4294967295:1000:1006:1013:1021:1047:3011 +507:4294967295:1000:1006:1013:1021:1047:3011 +508:4294967295:1000:1006:1013:1021:1047:3011 +509:4294967295:1000:1006:1013:1021:1047:3011 +510:4294967295:1000:1006:1013:1021:1047:3011 +511:4294967295:1000:1006:1013:1021:1047:3011 +/* Allow RCS service to aquire net_raw permission */ +18:4294967295:1001:3004 +/* Allow QMID service to aquire net_raw permission */ +3:4294967295:1001:3004 +2:4294967295:1001:3004 +42:4294967295:1001:3004 +18:4294967295:1001:3004 +9:4294967295:1001:3004 +1:4294967295:1001:3004:1000 +4:4294967295:1001:3004 +7:4294967295:1001:3004 +8:4294967295:1001:3004:1000 +68:4294967295:1001:3004 +/* DPM */ +47:4294967295:1001:3004 +/* Allow communication to some QMI services with radio privilages */ +/* Format is :: */ +/* PBM */ +12:4294967295:1001 +/* WMS */ +5:4294967295:1001 +/* IMS VT */ +32:4294967295:1001 +/* IMSP */ +31:4294967295:1001 +/* PDC */ +36:4294967295:1001 +/* SAR */ +17:4294967295:1001 +/* RFRPE */ +41:4294967295:1001 +/*UIM*/ +11:4294967295:1001 +/*CAT*/ +10:4294967295:1001 +/*IMSA*/ +33:4294967295:1001 +/* CSVT */ +29:4294967295:1001 +/*LTE*/ +70:4294967295:1001 +/* Allow Data dpmd to access QMI DFS */ +48:4294967295:1000:3004 +/* DIAG */ +4097:4294967295:2002:2950:3009 +/* :: */ +69:4294967295:1000 +/* :: */ +57:4294967295:1000 +/* MOTEXT */ +228:4294967295:1001:3004 diff --git a/configs/thermal-engine-potter.conf b/configs/thermal-engine-potter.conf new file mode 100644 index 0000000..e4b42a1 --- /dev/null +++ b/configs/thermal-engine-potter.conf @@ -0,0 +1,110 @@ +[FRONT_TEMP] +algo_type virtual +trip_sensor msm_therm +set_point -18000 +set_point_clr -20000 +sensors msm_therm pa_therm0 chg_therm batt_temp +weights 110 100 85 110 +offsets -2000 -2000 -2000 -2000 +sampling 10000 +math 0 +sys_temp + +[REPORT-FRONT-TEMP] +algo_type monitor +sampling 300000 +sensor FRONT_TEMP +thresholds 45000 +thresholds_clr 43000 +actions report +action_info 1 + +[BACK_TEMP] +algo_type virtual +trip_sensor msm_therm +set_point -18000 +set_point_clr -20000 +sensors msm_therm pa_therm0 chg_therm batt_temp +weights 110 100 85 110 +offsets -1000 -1000 -1000 -1000 +sampling 10000 +math 0 +sys_temp + +[REPORT-BACK-TEMP] +algo_type monitor +sampling 300000 +sensor BACK_TEMP +thresholds 45000 +thresholds_clr 43000 +actions report +action_info 1 + +[SS-BATT-BATT] +algo_type ss +sampling 5000 +sensor batt_therm +device battery +set_point 44000 +set_point_clr 42000 + +[SS-CHG-BATT] +algo_type ss +sampling 5000 +sensor chg_therm +device battery +set_point 43000 +set_point_clr 41000 + +[SS-MSM-CLUSTER0] +algo_type ss +sampling 1000 +sensor msm_therm +device cluster0 +set_point 49000 +set_point_clr 44000 +device_max_limit 1401600 + +[VIRTUAL-CPUS] +algo_type virtual +trip_sensor tsens_tz_sensor9 +set_point 75000 +set_point_clr 65000 +sensors tsens_tz_sensor9 tsens_tz_sensor10 tsens_tz_sensor11 tsens_tz_sensor12 tsens_tz_sensor13 tsens_tz_sensor4 tsens_tz_sensor5 tsens_tz_sensor6 tsens_tz_sensor7 tsens_tz_sensor8 +sampling 50 +math 2 + +[SS-GPU] +algo_type ss +sampling 250 +sensor gpu +device gpu +set_point 95000 +set_point_clr 65000 + +[SS-POPMEM] +algo_type ss +disable +sampling 250 +sensor pop_mem +device cluster0 +set_point 70000 +set_point_clr 55000 +time_constant 2 + +[SS-CPUS-ALL] +algo_type ss +sampling 50 +sensor VIRTUAL-CPUS +device cluster0 +set_point 95000 +set_point_clr 55000 + +[MONITOR-CAMERA-MSM] +algo_type monitor +sampling 1000 +sensor msm_therm +thresholds 52000 56000 +thresholds_clr 47000 53000 +actions camera camera +action_info 1 2 diff --git a/data-ipa-cfg-mgr/Android.mk b/data-ipa-cfg-mgr/Android.mk new file mode 100644 index 0000000..f013b86 --- /dev/null +++ b/data-ipa-cfg-mgr/Android.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2016 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/Makefile.am b/data-ipa-cfg-mgr/Makefile.am new file mode 100644 index 0000000..fab2aff --- /dev/null +++ b/data-ipa-cfg-mgr/Makefile.am @@ -0,0 +1,3 @@ +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = foreign +SUBDIRS = ipanat/src ipacm/src/ diff --git a/data-ipa-cfg-mgr/configure.ac b/data-ipa-cfg-mgr/configure.ac new file mode 100644 index 0000000..33164c0 --- /dev/null +++ b/data-ipa-cfg-mgr/configure.ac @@ -0,0 +1,57 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.65]) +AC_INIT(data-ipa, 1.0.0) +AM_INIT_AUTOMAKE(data-ipa, 1.0.0) +AC_OUTPUT(Makefile ipanat/src/Makefile ipacm/src/Makefile) +AC_CONFIG_SRCDIR([ipanat/src/ipa_nat_drv.c]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_CC +AC_PROG_LIBTOOL +AC_PROG_CXX + +PKG_CHECK_MODULES([LIBXML], [libxml-2.0]) +AC_SUBST([LIBXML_CFLAGS]) +AC_SUBST([LIBXML_LIBS]) + +# Checks for libraries. + +AC_ARG_WITH(sanitized-headers, + AS_HELP_STRING([--with-sanitized-headers=DIR], + [Specify the location of the sanitized Linux headers]), + [CPPFLAGS="$CPPFLAGS -idirafter $withval"]) + +AC_ARG_WITH([glib], + AC_HELP_STRING([--with-glib], + [enable glib, building HLOS systems which use glib])) + +if (test "x${with_glib}" = "xyes"); then + AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib]) + PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GThread >= 2.16 is required)) + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GLib >= 2.16 is required)) + GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" + GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) +fi + +AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") + +# Checks for header files. +AC_CHECK_HEADERS([fcntl.h netinet/in.h sys/ioctl.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_OFF_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_FUNC_MMAP +AC_CHECK_FUNCS([memset munmap]) + +AC_OUTPUT diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h new file mode 100644 index 0000000..27d7c8b --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h @@ -0,0 +1,109 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_CmdQueue.h + + @brief + This file implements the IPAM Comment Queue definitions + + @Author + +*/ +#ifndef IPA_CONNTRACK_MESSAGE_H +#define IPA_CONNTRACK_MESSAGE_H + +#include +#include "IPACM_Defs.h" + + + +/*--------------------------------------------------------------------------- + Event data required by IPA_CM +---------------------------------------------------------------------------*/ + + +typedef struct _ipacm_cmd_q_data { + ipa_cm_event_id event; + void *evt_data; +}ipacm_cmd_q_data; + +typedef struct cmd_s +{ + void (*callback_ptr)(ipacm_cmd_q_data *); + ipacm_cmd_q_data data; +}cmd_t; + +class Message +{ +private: + Message *m_next; + +public: + cmd_t evt; + + Message() + { + m_next = NULL; + evt.callback_ptr = NULL; + } + ~Message() { } + void setnext(Message *item) { m_next = item; } + Message* getnext() { return m_next; } +}; + +class MessageQueue +{ + +private: + Message *Head; + Message *Tail; + Message* dequeue(void); + static MessageQueue *inst_internal; + static MessageQueue *inst_external; + + MessageQueue() + { + Head = NULL; + Tail = NULL; + } + +public: + + ~MessageQueue() { } + void enqueue(Message *item); + + static void* Process(void *); + static MessageQueue* getInstanceInternal(); + static MessageQueue* getInstanceExternal(); + +}; + +#endif /* IPA_CONNTRACK_MESSAGE_H */ + diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h new file mode 100644 index 0000000..5bcb4eb --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h @@ -0,0 +1,357 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_Config.h + + @brief + This file implements the IPACM Configuration from XML file + + @Author + Skylar Chang + +*/ +#ifndef IPACM_CONFIG_H +#define IPACM_CONFIG_H + +#include "IPACM_Defs.h" +#include "IPACM_Xml.h" +#include "IPACM_EvtDispatcher.h" + +typedef struct +{ + char iface_name[IPA_IFACE_NAME_LEN]; +}NatIfaces; + +/* for IPACM rm dependency use*/ +typedef struct _ipa_rm_client +{ + ipa_rm_resource_name producer_rm1; + ipa_rm_resource_name consumer_rm1; + ipa_rm_resource_name producer_rm2; + ipa_rm_resource_name consumer_rm2; + bool producer1_up; /* only monitor producer_rm1, not monitor producer_rm2 */ + bool consumer1_up; /* only monitor consumer_rm1, not monitor consumer_rm2 */ + bool rm_set; /* once producer1_up and consumer1_up, will add bi-directional dependency */ + bool rx_bypass_ipa; /* support WLAN may not register RX-property, should not add dependency */ +}ipa_rm_client; + +#define MAX_NUM_EXT_PROPS 25 + +/* used to hold extended properties */ +typedef struct +{ + uint8_t num_ext_props; + ipa_ioc_ext_intf_prop prop[MAX_NUM_EXT_PROPS]; +} ipacm_ext_prop; + +/* iface */ +class IPACM_Config +{ +public: + + /* IPACM ipa_client map to rm_resource*/ + ipa_rm_resource_name ipa_client_rm_map_tbl[IPA_CLIENT_MAX]; + + /* IPACM monitored rm_depency table */ + ipa_rm_client ipa_rm_tbl[IPA_MAX_RM_ENTRY]; + + /* IPACM rm_depency a2 endpoint check*/ + int ipa_rm_a2_check; + + /* Store interested interface and their configuration from XML file */ + ipa_ifi_dev_name_t *iface_table; + + /* Store interested ALG port from XML file */ + ipacm_alg *alg_table; + + /* Store private subnet configuration from XML file */ + ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES]; + + /* Store the non nat iface names */ + NatIfaces *pNatIfaces; + + /* Store the bridge iface names */ + char ipa_virtual_iface_name[IPA_IFACE_NAME_LEN]; + + /* Store the number of interface IPACM read from XML file */ + int ipa_num_ipa_interfaces; + + int ipa_num_private_subnet; + + int ipa_num_alg_ports; + + int ipa_nat_max_entries; + + bool ipacm_odu_router_mode; + + 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_CONS - IPA_CLIENT_PROD]; + int flt_rule_count_v6[IPA_CLIENT_CONS - IPA_CLIENT_PROD]; + + /* 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_odu_v4, rt_tbl_odu_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_CONS - IPA_CLIENT_PROD) || (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_CONS - IPA_CLIENT_PROD) || (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_CONS - IPA_CLIENT_PROD) || (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; + } + + int GetAlgPorts(int nPorts, ipacm_alg *pAlgPorts); + + inline int GetNatMaxEntries(void) + { + return ipa_nat_max_entries; + } + + inline int GetNatIfacesCnt() + { + return ipa_nat_iface_entries; + } + int GetNatIfaces(int nPorts, NatIfaces *ifaces); + + /* for IPACM resource manager dependency usage */ + void AddRmDepend(ipa_rm_resource_name rm1,bool rx_bypass_ipa); + + void DelRmDepend(ipa_rm_resource_name rm1); + + int AddNatIfaces(char *dev_name); + + int DelNatIfaces(char *dev_name); + + inline void SetQmapId(uint8_t id) + { + qmap_id = id; + } + + inline uint8_t GetQmapId() + { + return qmap_id; + } + + int SetExtProp(ipa_ioc_query_intf_ext_props *prop); + + ipacm_ext_prop* GetExtProp(ipa_ip_type ip_type); + + int DelExtProp(ipa_ip_type ip_type); + + int Init(void); + + inline bool isPrivateSubnet(uint32_t ip_addr) + { + for(int cnt=0; cnt> 8) << 8; + ipa_num_private_subnet++; + + /* IPACM private subnet set changes */ + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + data_fid->if_index = ipa_if_index; // already ipa index, not fid index + evt_data.event = IPA_PRIVATE_SUBNET_CHANGE_EVENT; + evt_data.evt_data = data_fid; + + /* Insert IPA_PRIVATE_SUBNET_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + return true; + } + IPACMERR("IPACM private subnet_addr overflow, total entry(%d)\n", ipa_num_private_subnet); + return false; + } + + inline bool DelPrivateSubnet(uint32_t ip_addr, int ipa_if_index) + { + ipacm_cmd_q_data evt_data; + ipacm_event_data_fid *data_fid; + for(int cnt=0; cntif_index = ipa_if_index; // already ipa index, not fid index + evt_data.event = IPA_PRIVATE_SUBNET_CHANGE_EVENT; + evt_data.evt_data = data_fid; + + /* Insert IPA_PRIVATE_SUBNET_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + return true; + } + } + IPACMDBG("can't find private subnet_addr as: 0x%x \n", ip_addr); + return false; + } +#endif /* defined(FEATURE_IPA_ANDROID)*/ + + static const char *DEVICE_NAME_ODU; + +private: + static IPACM_Config *pInstance; + static const char *DEVICE_NAME; + IPACM_Config(void); + int m_fd; /* File descriptor of the IPA device node /dev/ipa */ + uint8_t qmap_id; + ipacm_ext_prop ext_prop_v4; + ipacm_ext_prop ext_prop_v6; +}; + +#endif /* IPACM_CONFIG */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h new file mode 100644 index 0000000..a6076cf --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h @@ -0,0 +1,104 @@ +/* +Copyright (c) 2013, 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_CONNTRACK_FILTER_H +#define IPACM_CONNTRACK_FILTER_H + +#include +#include +#include +#include +#include +#include + +#include "IPACM_ConntrackClient.h" +#include "IPACM_CmdQueue.h" +#include "IPACM_Conntrack_NATApp.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Defs.h" + +#ifndef IPACM_DEBUG +#define IPACM_DEBUG +#endif + +extern "C" +{ +#include +#include +#include +} + +using namespace std; + +#define UDP_TIMEOUT_UPDATE 20 +#define BROADCAST_IPV4_ADDR 0xFFFFFFFF + +class IPACM_ConntrackClient +{ + +private: + static IPACM_ConntrackClient *pInstance; + + struct nfct_handle *tcp_hdl; + struct nfct_handle *udp_hdl; + struct nfct_filter *tcp_filter; + struct nfct_filter *udp_filter; + static int IPA_Conntrack_Filters_Ignore_Local_Addrs(struct nfct_filter *filter); + static int IPA_Conntrack_Filters_Ignore_Bridge_Addrs(struct nfct_filter *filter); + static int IPA_Conntrack_Filters_Ignore_Local_Iface(struct nfct_filter *, ipacm_event_iface_up *); + IPACM_ConntrackClient(); + +public: + static int IPAConntrackEventCB(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data); + + static int IPA_Conntrack_UDP_Filter_Init(void); + static int IPA_Conntrack_TCP_Filter_Init(void); + static void* TCPRegisterWithConnTrack(void *); + static void* UDPRegisterWithConnTrack(void *); + static void* UDPConnTimeoutUpdate(void *); + + static void UpdateUDPFilters(void *, bool); + static void UpdateTCPFilters(void *, bool); + static void Read_TcpUdp_Timeout(char *in, int len); + + static IPACM_ConntrackClient* GetInstance(); + +#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 new file mode 100644 index 0000000..cdf3ef5 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackListener.h @@ -0,0 +1,123 @@ +/* +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 +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_CONNTRACK_LISTENER +#define IPACM_CONNTRACK_LISTENER + +#include +#include +#include +#include + +#include +#include +#include + +#include "IPACM_CmdQueue.h" +#include "IPACM_Conntrack_NATApp.h" +#include "IPACM_Listener.h" +#ifdef CT_OPT +#include "IPACM_LanToLan.h" +#endif + +#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 +{ + +private: + bool isCTReg; + bool isNatThreadStart; + bool WanUp; + NatApp *nat_inst; + + int NatIfaceCnt; + int StaClntCnt; + NatIfaces *pNatIfaces; + 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 + IPACM_LanToLan *p_lan2lan; +#endif + + void ProcessCTMessage(void *); + void ProcessTCPorUDPMsg(struct nf_conntrack *, + enum nf_conntrack_msg_type, u_int8_t); + 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: + char wan_ifname[IPA_IFACE_NAME_LEN]; + uint32_t wan_ipaddr; + bool isStaMode; + IPACM_ConntrackListener(); + void event_callback(ipa_cm_event_id, void *data); + inline bool isWanUp() + { + return WanUp; + } + + void HandleNeighIpAddrAddEvt(ipacm_event_data_all *); + void HandleNeighIpAddrDelEvt(uint32_t); + void HandleSTAClientAddEvt(uint32_t); + void HandleSTAClientDelEvt(uint32_t); +}; + +extern IPACM_ConntrackListener *CtList; + +#endif /* IPACM_CONNTRACK_LISTENER */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h new file mode 100644 index 0000000..e50b316 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h @@ -0,0 +1,133 @@ +/* +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 +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_CONNTRACK_NATAPP_H +#define IPACM_CONNTRACK_NATAPP_H + +#include /* for stderror */ +#include +#include /* for perror */ + +#include "IPACM_Config.h" +#include "IPACM_Xml.h" + +extern "C" +{ +#include +#include +} + +#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; + uint16_t private_port; + + uint32_t target_ip; + uint16_t target_port; + + uint32_t public_ip; + uint16_t public_port; + + u_int8_t protocol; + uint32_t timestamp; + + bool dst_nat; + bool enabled; + uint32_t rule_hdl; + +}nat_table_entry; + +#define CHK_TBL_HDL() if(nat_table_hdl == 0){ return -1; } + +class NatApp +{ +private: + + static NatApp *pInstance; + + nat_table_entry *cache; + nat_table_entry temp[MAX_TEMP_ENTRIES]; + uint32_t pub_ip_addr; + uint32_t pub_ip_addr_pre; + uint32_t nat_table_hdl; + + int curCnt, max_entries; + + ipacm_alg *pALGPorts; + uint16_t nALGPort; + + uint32_t tcp_timeout; + uint32_t udp_timeout; + + uint32_t PwrSaveIfs[IPA_MAX_NUM_WIFI_CLIENTS]; + + struct nf_conntrack *ct; + struct nfct_handle *ct_hdl; + + NatApp(); + int Init(); + + void UpdateCTUdpTs(nat_table_entry *, uint32_t); + bool ChkForDup(const nat_table_entry *); + bool isAlgPort(uint8_t, uint16_t); + void Reset(); + bool isPwrSaveIf(uint32_t); + +public: + static NatApp* GetInstance(); + + int AddTable(uint32_t); + uint32_t GetTableHdl(uint32_t); + int DeleteTable(uint32_t); + + int AddEntry(const nat_table_entry *); + int DeleteEntry(const nat_table_entry *); + + void UpdateUDPTimeStamp(); + + int UpdatePwrSaveIf(uint32_t); + int ResetPwrSaveIf(uint32_t); + int DelEntriesOnClntDiscon(uint32_t); + int DelEntriesOnSTAClntDiscon(uint32_t); + + 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, bool isDummy = false); +}; + + + +#endif /* IPACM_CONNTRACK_NATAPP_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h new file mode 100644 index 0000000..d2cc362 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h @@ -0,0 +1,354 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_Defs.h + + @brief + This file implements the common definitions amon all ifaces. + + @Author + Skylar Chang + +*/ +#ifndef IPA_CM_DEFS_H +#define IPA_CM_DEFS_H + +#include +#include +#include +#include "IPACM_Log.h" + +#ifdef USE_GLIB +#include +#define strlcpy g_strlcpy +#define strlcat g_strlcat +#endif + +extern "C" +{ +#include +#include +} + +#define IF_NAME_LEN 16 +#define IPA_MAX_FILE_LEN 64 +#define IPA_IFACE_NAME_LEN 16 +#define IPA_ALG_PROTOCOL_NAME_LEN 10 + +#define IPA_WLAN_PARTIAL_HDR_OFFSET 0 // 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" +#define IPA_ETH_HDR_NAME_v6 "IPACM_ETH_v6" +#define IPA_ODU_HDR_NAME_v4 "IPACM_ODU_v4" +#define IPA_ODU_HDR_NAME_v6 "IPACM_ODU_v6" + + +#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_ODU_ROUTE_TABLE_NAME "ODURTBLv4" +#define V6_ODU_ROUTE_TABLE_NAME "ODURTBLv6" + +#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 TCP_FIN_SHIFT 16 +#define TCP_SYN_SHIFT 17 +#define TCP_RST_SHIFT 18 +#define NUM_IPV6_PREFIX_FLT_RULE 1 + +/*--------------------------------------------------------------------------- + Return values indicating error status +---------------------------------------------------------------------------*/ + +#define IPACM_SUCCESS 0 /* Successful operation */ +#define IPACM_FAILURE -1 /* Unsuccessful operation */ + +#define IPACM_IP_NULL (ipa_ip_type)0xFF +#define IPACM_INVALID_INDEX (ipa_ip_type)0xFF + +#define IPA_MAX_NUM_WIFI_CLIENTS 32 +#define IPA_MAX_NUM_WAN_CLIENTS 10 +#define IPA_MAX_NUM_ETH_CLIENTS 15 +#define IPA_MAX_NUM_AMPDU_RULE 15 +#define IPA_MAC_ADDR_SIZE 6 + +/*=========================================================================== + GLOBAL DEFINITIONS AND DECLARATIONS +===========================================================================*/ +typedef enum +{ + 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 */ + IPACM_EVENT_MAX +} ipa_cm_event_id; + +typedef struct +{ + uint8_t num_rule; + uint32_t rule_hdl[MAX_NUM_PROP]; +} lan_to_lan_rt_rule_hdl; + +typedef enum +{ + LAN_IF = 0, + WLAN_IF, + WAN_IF, + VIRTUAL_IF, + ETH_IF, + EMBMS_IF, + ODU_IF, + 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; + enum nf_conntrack_msg_type type; +}ipacm_ct_evt_data; + +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; + +typedef struct +{ + uint32_t subnet_addr; + uint32_t subnet_mask; +} ipa_private_subnet; + + +typedef struct _ipacm_event_data_all +{ + enum ipa_ip_type iptype; + int if_index; + uint32_t ipv4_addr; + uint32_t ipv6_addr[4]; + uint8_t mac_addr[IPA_MAC_ADDR_SIZE]; +} ipacm_event_data_all; + +class IPACM_Lan; + +typedef struct +{ + 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_event_eth_bridge; + +typedef struct +{ + enum ipa_ip_type iptype; + uint32_t src_ipv4_addr; + uint32_t dst_ipv4_addr; + uint32_t src_ipv6_addr[4]; + uint32_t dst_ipv6_addr[4]; +} ipacm_event_connection; + +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; + 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; + +typedef struct +{ + int if_index; + uint8_t num_of_attribs; + struct ipa_wlan_hdr_attrib_val attribs[0]; +} ipacm_event_data_wlan_ex; + +typedef struct _ipacm_event_iface_up +{ + char ifname[IPA_IFACE_NAME_LEN]; + uint32_t ipv4_addr; + 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 +{ + uint32_t if_index_tether; + uint32_t ipv6_prefix[2]; + bool is_sta; +}ipacm_event_iface_up_tehter; + +typedef enum +{ + Q6_WAN = 0, + WLAN_WAN, + ECM_WAN +} ipacm_wan_iface_type; + +typedef struct _ipacm_ifacemgr_data +{ + int if_index; + ipacm_wan_iface_type if_type; + uint8_t mac_addr[IPA_MAC_ADDR_SIZE]; +}ipacm_ifacemgr_data; + +#endif /* IPA_CM_DEFS_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_EvtDispatcher.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_EvtDispatcher.h new file mode 100644 index 0000000..550f4d4 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_EvtDispatcher.h @@ -0,0 +1,76 @@ +/* +Copyright (c) 2013, 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. +*/ + +/*! + @file + IPACM_EvtDispatcher.h + + @brief + This file implements the IPAM event dispatcher definitions + + @Author + +*/ +#ifndef IPACM_EvtDispatcher_H +#define IPACM_EvtDispatcher_H + +#include +#include +#include "IPACM_Defs.h" +#include "IPACM_Listener.h" + +/* queue */ +typedef struct _cmd_evts +{ + ipa_cm_event_id event; + IPACM_Listener *obj; + //int ipa_interface_index; + _cmd_evts *next; +} cmd_evts; + + + +class IPACM_EvtDispatcher +{ +public: + + /* api for all iface instances to register events */ + static int registr(ipa_cm_event_id event, IPACM_Listener *obj); + + /* api for all iface instances to de-register events */ + static int deregistr(IPACM_Listener *obj); + + static int PostEvt(ipacm_cmd_q_data *); + static void ProcessEvt(ipacm_cmd_q_data *); + +private: + static cmd_evts *head; +}; + +#endif /* IPACM_EvtDispatcher_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h new file mode 100644 index 0000000..9bb8247 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h @@ -0,0 +1,76 @@ +/* +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 +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. +*/ + +/*! + @file + IPACM_Filtering.h + + @brief + This file implements the IPACM filtering definitions + + @Author + Skylar Chang + +*/ + +#ifndef IPACM_FILTERING_H +#define IPACM_FILTERING_H + +#include +#include +#include +#include + +class IPACM_Filtering +{ +public: + 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); + bool DeviceNodeIsOpened(); + bool DeleteFilteringHdls(uint32_t *flt_rule_hdls, + ipa_ip_type ip, + uint8_t num_rules); + + bool AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *rule_table_v4, struct ipa_ioc_add_flt_rule const * rule_table_v6, uint8_t mux_id); + bool SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01* table); + bool ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule* ruleTable); + ipa_filter_action_enum_v01 GetQmiFilterAction(ipa_flt_action action); + +private: + static const char *DEVICE_NAME; + int fd; /* File descriptor of the IPA device node /dev/ipa */ +}; + +#endif //IPACM_FILTERING_H + diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Header.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Header.h new file mode 100644 index 0000000..027c8ff --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Header.h @@ -0,0 +1,70 @@ +/* +Copyright (c) 2013, 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. +*/ + +/* + * IPACM_Header.h + * + * Created on: Jun 20, 2012 + * Author: tatias + */ + +////////////////////////////////////////////////////////////////////////////////// + +#ifndef IPACM_HEADER_H +#define IPACM_HEADER_H + +#include +#include "linux/msm_ipa.h" + +////////////////////////////////////////////////////////////////////////////////// + +class IPACM_Header +{ +private: + int m_fd; +public: + bool AddHeader(struct ipa_ioc_add_hdr *pHeaderTable); + bool DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTable); + bool GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct); + bool CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct); + bool Commit(); + bool Reset(); + bool DeleteHeaderHdl(uint32_t hdr_hdl); + bool AddHeaderProcCtx(struct ipa_ioc_add_hdr_proc_ctx* pHeader); + bool DeleteHeaderProcCtx(uint32_t hdl); + + IPACM_Header(); + ~IPACM_Header(); + bool DeviceNodeIsOpened(); +}; + + +#endif + + diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h new file mode 100644 index 0000000..43b0da6 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h @@ -0,0 +1,153 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_iface.h + + @brief + This file implements the basis Iface definitions. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_IFACE_H +#define IPACM_IFACE_H + +#include +#include +#include +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Header.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Xml.h" +#include "IPACM_Log.h" +#include "IPACM_Config.h" +#include "IPACM_Defs.h" +#include + +/* current support 2 ipv6-address*/ +#define MAX_DEFAULT_v4_ROUTE_RULES 1 +#define MAX_DEFAULT_v6_ROUTE_RULES 2 +#define IPV4_DEFAULT_FILTERTING_RULES 3 + +#ifdef FEATURE_IPA_ANDROID +#define IPV6_DEFAULT_FILTERTING_RULES 6 +#else +#define IPV6_DEFAULT_FILTERTING_RULES 3 +#endif + +#define IPV6_DEFAULT_LAN_FILTERTING_RULES 1 +#define IPV6_NUM_ADDR 3 +#define MAX_SOFTWAREROUTING_FILTERTING_RULES 2 +#define INVALID_IFACE -1 + +/* iface */ +class IPACM_Iface :public IPACM_Listener +{ +public: + + /* Static class for reading IPACM configuration from XML file*/ + static IPACM_Config *ipacmcfg; + + /* IPACM interface id */ + int ipa_if_num; + + /* IPACM interface category */ + ipacm_iface_type ipa_if_cate; + + /* IPACM interface name */ + char dev_name[IF_NAME_LEN]; + + /* IPACM interface iptype v4, v6 or both */ + ipa_ip_type ip_type; + + /* IPACM interface v6 ip-address*/ + uint32_t ipv6_addr[MAX_DEFAULT_v6_ROUTE_RULES][4]; + + uint32_t software_routing_fl_rule_hdl[MAX_SOFTWAREROUTING_FILTERTING_RULES]; + + bool softwarerouting_act; + + /* IPACM number of default route rules for ipv6*/ + int num_dft_rt_v6; + + uint32_t dft_v4fl_rule_hdl[IPV4_DEFAULT_FILTERTING_RULES]; + uint32_t dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES + IPV6_DEFAULT_LAN_FILTERTING_RULES]; + /* create additional set of v6 RT-rules in Wanv6RT table*/ + uint32_t dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+2*MAX_DEFAULT_v6_ROUTE_RULES]; + + ipa_ioc_query_intf *iface_query; + ipa_ioc_query_intf_tx_props *tx_prop; + ipa_ioc_query_intf_rx_props *rx_prop; + + virtual int handle_down_evt() = 0; + + virtual int handle_addr_evt(ipacm_event_data_addr *data) = 0; + + IPACM_Iface(int iface_index); + + virtual void event_callback(ipa_cm_event_id event, + void *data) = 0; + + /* Query ipa_interface_index by given linux interface_index */ + static int iface_ipa_index_query(int interface_index); + + /* Query ipa_interface ipv4_addr by given linux interface_index */ + static void iface_addr_query(int interface_index); + + /*Query the IPA endpoint property */ + int query_iface_property(void); + + /*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); + + static IPACM_Routing m_routing; + static IPACM_Filtering m_filtering; + static IPACM_Header m_header; + + /* software routing enable */ + virtual int handle_software_routing_enable(void); + + /* software routing disable */ + virtual int handle_software_routing_disable(void); + +private: + + static const char *DEVICE_NAME; +}; + +#endif /* IPACM_IFACE_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h new file mode 100644 index 0000000..c7184f2 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h @@ -0,0 +1,90 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_IfaceManager.h + + @brief + This file implements the IPAM iface_manager definitions + + @Author + Skylar Chang + +*/ +#ifndef IPACM_IFACEMANAGER_H +#define IPACM_IFACEMANAGER_H + +#include +#include + +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Listener.h" +#include "IPACM_Iface.h" + +#define IPA_INSTANCE_NOT_FOUND 0 +#define IPA_INSTANCE_FOUND 1 + +/* queue */ +typedef struct _iface_instances +{ + /* Linux interface id */ + int ipa_if_index; + IPACM_Listener *obj; + _iface_instances *next; +} iface_instances; + + +class IPACM_IfaceManager : public IPACM_Listener +{ + +public: + + IPACM_IfaceManager(); + + void event_callback(ipa_cm_event_id event, + void *data); + + /* api for all iface instances to de-register instances */ + static int deregistr(IPACM_Listener *param); + + +private: + int create_iface_instance(ipacm_ifacemgr_data *); + + /* api to register instances */ + int registr(int ipa_if_index, IPACM_Listener *obj); + + int SearchInstance(int ipa_if_index); + + static iface_instances *head; + +}; + +#endif /* IPACM_IFACEMANAGER_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h new file mode 100644 index 0000000..6c54f5e --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h @@ -0,0 +1,390 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_Lan.h + + @brief + This file implements the LAN iface definitions + + @Author + Skylar Chang + +*/ +#ifndef IPACM_LAN_H +#define IPACM_LAN_H + +#include +#include + +#include "IPACM_CmdQueue.h" +#include "IPACM_Iface.h" +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Config.h" +#include "IPACM_Conntrack_NATApp.h" + +#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 MAX_NUM_EXT_PROPS +#define NUM_IPV4_ICMP_FLT_RULE 1 +#define NUM_IPV6_ICMP_FLT_RULE 1 + +/* ndc bandwidth ipatetherstats */ +/* out_bytes> out_pkts> in_bytes> in_pkts */ + +#define PIPE_STATS "%s %s %lu %lu %lu %lu" +#define IPA_PIPE_STATS_FILE_NAME "/data/misc/ipa/tether_stats" + +/* store each lan-iface unicast routing rule and its handler*/ +struct ipa_lan_rt_rule +{ + ipa_ip_type ip; + uint32_t v4_addr; + uint32_t v4_addr_mask; + uint32_t v6_addr[4]; + uint32_t rt_rule_hdl[0]; +}; + +/* Support multiple eth client */ +typedef struct _eth_client_rt_hdl +{ + uint32_t eth_rt_rule_hdl_v4; + uint32_t eth_rt_rule_hdl_v6[IPV6_NUM_ADDR]; + uint32_t eth_rt_rule_hdl_v6_wan[IPV6_NUM_ADDR]; +}eth_client_rt_hdl; + +typedef struct _ipa_eth_client +{ + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint32_t v4_addr; + uint32_t v6_addr[IPV6_NUM_ADDR][4]; + uint32_t hdr_hdl_v4; + uint32_t hdr_hdl_v6; + bool route_rule_set_v4; + int route_rule_set_v6; + bool ipv4_set; + int ipv6_set; + bool ipv4_header_set; + bool ipv6_header_set; + eth_client_rt_hdl eth_rt_hdl[0]; /* depends on number of tx properties */ +}ipa_eth_client; + + +/* lan iface */ +class IPACM_Lan : public IPACM_Iface +{ +public: + + IPACM_Lan(int iface_index); + ~IPACM_Lan(); + + /* store lan's wan-up filter rule handlers */ + uint32_t lan_wan_fl_rule_hdl[IPA_WAN_DEFAULT_FILTER_RULE_HANDLES]; + + /* store private-subnet filter rule handlers */ + 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); + + 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, uint8_t xlat_mux_id); + + /* delete filter rule for wan_down event*/ + virtual int handle_wan_down(bool is_sta_mode); + + /* delete filter rule for wan_down event*/ + virtual int handle_wan_down_v6(bool is_sta_mode); + + /* configure private subnet filter rules*/ + virtual int handle_private_subnet(ipa_ip_type iptype); + + /* handle new_address event*/ + int handle_addr_evt(ipacm_event_data_addr *data); + + 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, uint8_t xlat_mux_id); + + int handle_cradle_wan_mode_switch(bool is_wan_bridge_mode); + + int install_ipv4_icmp_flt_rule(); + + + /* 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); + + /* 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); + + /* delete filtering rule */ + int eth_bridge_del_flt_rule(uint32_t flt_rule_hdl, ipa_ip_type iptype); + + /* delete routing rule */ + int eth_bridge_del_rt_rule(uint32_t rt_rule_hdl, ipa_ip_type iptype); + + /* delete header processing context */ + int eth_bridge_del_hdr_proc_ctx(uint32_t hdr_proc_ctx_hdl); + + + +protected: + + int each_client_rt_rule_count[IPA_IP_MAX]; + + uint32_t eth_bridge_flt_rule_offset[IPA_IP_MAX]; + + /* 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); + + + + virtual int add_dummy_private_subnet_flt_rule(ipa_ip_type iptype); + + int handle_private_subnet_android(ipa_ip_type iptype); + + int reset_to_dummy_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl); + + virtual int install_ipv6_prefix_flt_rule(uint32_t* prefix); + + virtual void delete_ipv6_prefix_flt_rule(); + + int install_ipv6_icmp_flt_rule(); + + void post_del_self_evt(); + + /* handle tethering stats */ + int handle_tethering_stats_event(ipa_get_data_stats_resp_msg_v01 *data); + + /* handle tethering client */ + int handle_tethering_client(bool reset, ipacm_client_enum ipa_client); + + /* 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]; + + 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]; + + int num_wan_ul_fl_rule_v4; + int num_wan_ul_fl_rule_v6; + + bool is_active; + bool modem_ul_v4_set; + bool modem_ul_v6_set; + + uint32_t if_ipv4_subnet; + + uint32_t ipv6_prefix[2]; + +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 */ + + int eth_client_len; + + ipa_eth_client *eth_client; + + int header_name_count; + + int num_eth_client; + + NatApp *Nat_App; + + int ipv6_set; + + uint32_t ODU_hdr_hdl_v4, ODU_hdr_hdl_v6; + + uint32_t *odu_route_rule_v4_hdl; + + uint32_t *odu_route_rule_v6_hdl; + + bool ipv4_header_set; + + bool ipv6_header_set; + + inline ipa_eth_client* get_client_memptr(ipa_eth_client *param, int cnt) + { + char *ret = ((char *)param) + (eth_client_len * cnt); + return (ipa_eth_client *)ret; + } + + inline int get_eth_client_index(uint8_t *mac_addr) + { + int cnt; + int num_eth_client_tmp = num_eth_client; + + IPACMDBG_H("Passed 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]); + + for(cnt = 0; cnt < num_eth_client_tmp; cnt++) + { + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(eth_client, cnt)->mac[0], + get_client_memptr(eth_client, cnt)->mac[1], + get_client_memptr(eth_client, cnt)->mac[2], + get_client_memptr(eth_client, cnt)->mac[3], + get_client_memptr(eth_client, cnt)->mac[4], + get_client_memptr(eth_client, cnt)->mac[5]); + + if(memcmp(get_client_memptr(eth_client, cnt)->mac, + mac_addr, + sizeof(get_client_memptr(eth_client, cnt)->mac)) == 0) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + return cnt; + } + } + + return IPACM_INVALID_INDEX; + } + + inline int delete_eth_rtrules(int clt_indx, ipa_ip_type iptype) + { + uint32_t tx_index; + uint32_t rt_hdl; + int num_v6; + + if(iptype == IPA_IP_v4) + { + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if((tx_prop->tx[tx_index].ip == IPA_IP_v4) && (get_client_memptr(eth_client, clt_indx)->route_rule_set_v4==true)) /* for ipv4 */ + { + IPACMDBG_H("Delete client index %d ipv4 RT-rules for tx:%d\n",clt_indx,tx_index); + rt_hdl = get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4; + + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v4) == false) + { + return IPACM_FAILURE; + } + } + } /* end of for loop */ + + /* clean the ipv4 RT rules for eth-client:clt_indx */ + if(get_client_memptr(eth_client, clt_indx)->route_rule_set_v4==true) /* for ipv4 */ + { + get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = false; + } + } + + if(iptype == IPA_IP_v6) + { + 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, clt_indx)->route_rule_set_v6 != 0)) /* for ipv6 */ + { + for(num_v6 =0;num_v6 < get_client_memptr(eth_client, clt_indx)->route_rule_set_v6;num_v6++) + { + IPACMDBG_H("Delete client index %d ipv6 RT-rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index); + rt_hdl = get_client_memptr(eth_client, clt_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, clt_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; + } + } + } + } /* end of for loop */ + + /* clean the ipv6 RT rules for eth-client:clt_indx */ + if(get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 != 0) /* for ipv6 */ + { + get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = 0; + } + } + + return IPACM_SUCCESS; + } + + /* handle eth client initial, construct full headers (tx property) */ + int handle_eth_hdr_init(uint8_t *mac_addr); + + /* handle eth client ip-address */ + int handle_eth_client_ipaddr(ipacm_event_data_all *data); + + /* handle eth client routing rule*/ + int handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype); + + /*handle eth client del mode*/ + int handle_eth_client_down_evt(uint8_t *mac_addr); + + /* handle odu client initial, construct full headers (tx property) */ + int handle_odu_hdr_init(uint8_t *mac_addr); + + /* handle odu default route rule configuration */ + int handle_odu_route_add(); + + /* handle odu default route rule deletion */ + int handle_odu_route_del(); + + /*handle lan iface down event*/ + int handle_down_evt(); + + /*handle reset usb-client rt-rules */ + int handle_lan_client_reset_rt(ipa_ip_type iptype); +}; + +#endif /* IPACM_LAN_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h new file mode 100644 index 0000000..a28631e --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h @@ -0,0 +1,202 @@ +/* +Copyright (c) 2014, 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. +*/ + +/* + * IPACM_LanToLan.h + * + * Created on: Mar 4th, 2014 + * Author: Shihuan Liu + */ + +#ifndef IPACM_LANTOLAN_H +#define IPACM_LANTOLAN_H + +#include +#include "linux/msm_ipa.h" +#include "IPACM_Iface.h" +#include "IPACM_Defs.h" +#include "IPACM_Lan.h" + +#ifdef FEATURE_IPA_ANDROID +#include +#else/* defined(FEATURE_IPA_ANDROID) */ +#include +#endif /* ndefined(FEATURE_IPA_ANDROID)*/ + +#define MAX_NUM_CACHED_CLIENT_ADD_EVENT 10 +#define MAX_NUM_IFACE 10 +#define MAX_NUM_CLIENT 16 + +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 client_info +{ + uint8_t mac_addr[6]; + 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 */ +}; + +struct flt_rule_info +{ + client_info *p_client; + uint32_t flt_rule_hdl[IPA_IP_MAX]; +}; + +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); + + 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(); + + void increment_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type); + + void decrement_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type); + +private: + + 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; + + 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; + + 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); + + void clear_all_flt_rule_for_one_peer_iface(peer_iface_info *peer); + + void clear_all_rt_rule_for_one_peer_iface(peer_iface_info *peer); + + 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: + + IPACM_LanToLan(); + +private: + + ~IPACM_LanToLan(); + + list m_iface; + + list m_cached_client_add_event; + + void handle_iface_up(ipacm_event_eth_bridge *data); + + void handle_iface_down(ipacm_event_eth_bridge *data); + + void handle_client_add(ipacm_event_eth_bridge *data); + + void handle_client_del(ipacm_event_eth_bridge *data); + + void handle_wlan_scc_mcc_switch(ipacm_event_eth_bridge *data); + + void handle_new_iface_up(IPACM_LanToLan_Iface *new_iface, IPACM_LanToLan_Iface *exist_iface); + + void event_callback(ipa_cm_event_id event, void* param); + + void handle_cached_client_add_event(IPACM_Lan *p_iface); + + void clear_cached_client_add_event(IPACM_Lan *p_iface); + + void print_data_structure_info(); + +}; + +#endif diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Listener.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Listener.h new file mode 100644 index 0000000..9d774fe --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Listener.h @@ -0,0 +1,54 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Listener.h + + @brief + This file implements the abstract class notifier. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_LISTENER_H +#define IPACM_LISTENER_H + +#include "IPACM_Defs.h" +#include "IPACM_CmdQueue.h" + +/* abstract class notifier */ +class IPACM_Listener +{ +public: + virtual void event_callback(ipa_cm_event_id event, void *data) = 0; + virtual ~IPACM_Listener(void) {}; +}; + +#endif /* IPACM_LISTENER_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h new file mode 100644 index 0000000..dab0280 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h @@ -0,0 +1,102 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_log.h + + @brief + This file implements the IPAM log functionality. + + @Author + Skylar Chang + +*/ + +#ifndef IPACM_LOG_H +#define IPACM_LOG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include + +#define MAX_BUF_LEN 256 + +#ifdef FEATURE_IPA_ANDROID +#define IPACMLOG_FILE "/dev/socket/ipacm_log_file" +#else/* defined(FEATURE_IPA_ANDROID) */ +#define IPACMLOG_FILE "/etc/ipacm_log_file" +#endif /* defined(NOT FEATURE_IPA_ANDROID)*/ + +typedef struct ipacm_log_buffer_s { + char user_data[MAX_BUF_LEN]; +} ipacm_log_buffer_t; + +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,"ERROR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ + ipacm_log_send (buffer_send);\ + 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__); + +#ifdef __cplusplus +} +#endif + +#endif /* IPACM_LOG_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h new file mode 100644 index 0000000..14e86e5 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h @@ -0,0 +1,81 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Neighbor.h + + @brief + This file implements the functionality of handling IPACM Neighbor events. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_NEIGHBOR_H +#define IPACM_NEIGHBOR_H + +#include +#include +#include +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Listener.h" +#include "IPACM_Iface.h" + +#define IPA_MAX_NUM_NEIGHBOR_CLIENTS 100 + +struct ipa_neighbor_client +{ + uint8_t mac_addr[6]; + int iface_index; + uint32_t v4_addr; + int ipa_if_num; +}; + +class IPACM_Neighbor : public IPACM_Listener +{ + +public: + + IPACM_Neighbor(); + + void event_callback(ipa_cm_event_id event, + void *data); + +private: + + int num_neighbor_client; + + int circular_index; + + ipa_neighbor_client neighbor_client[IPA_MAX_NUM_NEIGHBOR_CLIENTS]; + +}; + +#endif /* IPACM_NEIGHBOR_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Netlink.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Netlink.h new file mode 100644 index 0000000..b0bdeb8 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Netlink.h @@ -0,0 +1,223 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPA_Netlink.h + + @brief + IPACM Netlink Messaging Implementation File + + @Author + Skylar Chang + +*/ +#ifndef IPACM_NETLINK_H +#define IPACM_NETLINK_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "IPACM_Defs.h" + +#define MAX_NUM_OF_FD 10 +#define IPA_NL_MSG_MAX_LEN (2048) + +/*--------------------------------------------------------------------------- + Type representing enumeration of NetLink event indication messages +---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Types representing parsed NetLink message +---------------------------------------------------------------------------*/ +#define IPA_NLA_PARAM_NONE (0x0000) +#define IPA_NLA_PARAM_PREFIXADDR (0x0001) +#define IPA_NLA_PARAM_LOCALADDR (0x0002) +#define IPA_NLA_PARAM_LABELNAME (0x0004) +#define IPA_NLA_PARAM_BCASTADDR (0x0008) +#define IPA_NLA_PARAM_ACASTADDR (0x0010) +#define IPA_NLA_PARAM_MCASTADDR (0x0020) +#define IPA_NLA_PARAM_CACHEINFO (0x0080) +#define IPA_NLA_PARAM_PROTOINFO (0x0100) +#define IPA_NLA_PARAM_FLAGS (0x0200) + +#define IPA_RTA_PARAM_NONE (0x0000) +#define IPA_RTA_PARAM_DST (0x0001) +#define IPA_RTA_PARAM_SRC (0x0002) +#define IPA_RTA_PARAM_GATEWAY (0x0004) +#define IPA_RTA_PARAM_IIF (0x0008) +#define IPA_RTA_PARAM_OIF (0x0010) +#define IPA_RTA_PARAM_CACHEINFO (0x0020) +#define IPA_RTA_PARAM_PRIORITY (0x0080) +#define IPA_RTA_PARAM_METRICS (0x0100) + + +/*--------------------------------------------------------------------------- + Type representing function callback registered with a socket listener + thread for reading from a socket on receipt of an incoming message +---------------------------------------------------------------------------*/ +typedef int (*ipa_sock_thrd_fd_read_f)(int fd); + +typedef enum +{ + IPA_INIT = 0, + IPA_LINK_UP_WAIT, + IPA_LINK_UP, + IPA_LINK_DOWN_WAIT, + IPA_LINK_DOWN +} ipa_nl_state_e; + +typedef struct +{ + int sk_fd; + ipa_sock_thrd_fd_read_f read_func; +} ipa_nl_sk_fd_map_info_t; + +typedef struct +{ + ipa_nl_sk_fd_map_info_t sk_fds[MAX_NUM_OF_FD]; + fd_set fdset; + int num_fd; + int max_fd; +} ipa_nl_sk_fd_set_info_t; + +typedef struct +{ + int sk_fd; /* socket descriptor */ + struct sockaddr_nl sk_addr_loc; /* local address of socket */ +} ipa_nl_sk_info_t; + +typedef struct ipa_nl_addr_s { + struct sockaddr_storage ip_addr; + unsigned int mask; +} ipa_nl_addr_t; + +typedef struct ipa_nl_proto_info_s { + unsigned int param_mask; + unsigned int flags; + struct ifla_cacheinfo cache_info; +} ipa_nl_proto_info_t; + +typedef struct +{ + struct ifinfomsg metainfo; /* from header */ +} ipa_nl_link_info_t; + + + +typedef struct ipa_nl_addr_info_s { + struct ifaddrmsg metainfo; /* from header */ + struct /* attributes */ + { + unsigned int param_mask; + unsigned char label_name[IF_NAME_LEN]; + struct sockaddr_storage prefix_addr; + struct sockaddr_storage local_addr; + struct sockaddr_storage bcast_addr; + struct sockaddr_storage acast_addr; + struct sockaddr_storage mcast_addr; + } attr_info; +} ipa_nl_addr_info_t; + + +typedef struct ipa_nl_neigh_info_s { + struct ndmsg metainfo; /* from header */ + struct /* attributes */ + { + unsigned int param_mask; + struct sockaddr_storage local_addr; + struct sockaddr lladdr_hwaddr; + } attr_info; +} ipa_nl_neigh_info_t; + + + +typedef struct ipa_nl_route_info_s { + struct rtmsg metainfo; /* from header */ + struct /* attributes */ + { + unsigned int param_mask; + struct sockaddr_storage dst_addr; + struct sockaddr_storage src_addr; + struct sockaddr_storage gateway_addr; + struct sockaddr_storage mark_addr; + struct rta_cacheinfo cache_info; + __u32 iif_index; /* Link index */ + __u32 oif_index; /* Link index */ + __u32 priority; + __u32 metrics; + ipa_nl_proto_info_t proto_info; + } attr_info; +} ipa_nl_route_info_t; + +#define IPA_FLOW_TYPE_INVALID (-1) + +typedef struct +{ + unsigned int type; + bool link_event; + /* Optional parameters */ + ipa_nl_link_info_t nl_link_info; + ipa_nl_addr_info_t nl_addr_info; + ipa_nl_neigh_info_t nl_neigh_info; + ipa_nl_route_info_t nl_route_info; +} ipa_nl_msg_t; + +/* Initialization routine for listener on NetLink sockets interface */ +int ipa_nl_listener_init +( + unsigned int nl_type, + unsigned int nl_groups, + ipa_nl_sk_fd_set_info_t *sk_fdset, + ipa_sock_thrd_fd_read_f read_f + ); + +/* Virtual function registered to receive incoming messages over the NETLINK routing socket*/ +int ipa_nl_recv_msg(int fd); + +/* map mask value for ipv6 */ +int mask_v6(int index, uint32_t *mask); + +#ifdef __cplusplus +} +#endif + +#endif /* IPACM_NETLINK_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h new file mode 100644 index 0000000..b5ffabc --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h @@ -0,0 +1,78 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Routing.cpp + + @brief + This file implements the IPACM routing functionality. + + @Author + Skylar Chang + +*/ + + +#ifndef IPACM_ROUTING_H +#define IPACM_ROUTING_H + +#include +#include +#include + +using namespace std; + +class IPACM_Routing +{ +public: + IPACM_Routing(); + ~IPACM_Routing(); + + bool AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable); + bool DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable); + + bool Commit(enum ipa_ip_type ip); + bool Reset(enum ipa_ip_type ip); + + bool GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable); + + 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 new file mode 100644 index 0000000..fe6d35e --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wan.h @@ -0,0 +1,499 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Wan.cpp + + @brief + This file implements the WAN iface functionality. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_WAN_H +#define IPACM_WAN_H + +#include +#include +#include +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include +#include +#include + +#define IPA_NUM_DEFAULT_WAN_FILTER_RULES 3 /*1 for v4, 2 for v6*/ +#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4 2 + +#ifdef FEATURE_IPA_ANDROID +#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 6 +#else +#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 3 +#endif + +#define NETWORK_STATS "%s %lu %lu %lu %lu" +#define IPA_NETWORK_STATS_FILE_NAME "/data/misc/ipa/network_stats" + +typedef struct _wan_client_rt_hdl +{ + uint32_t wan_rt_rule_hdl_v4; + uint32_t wan_rt_rule_hdl_v6[IPV6_NUM_ADDR]; + uint32_t wan_rt_rule_hdl_v6_wan[IPV6_NUM_ADDR]; +}wan_client_rt_hdl; + +typedef struct _ipa_wan_client +{ + ipacm_event_data_wlan_ex* p_hdr_info; + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint32_t v4_addr; + uint32_t v6_addr[IPV6_NUM_ADDR][4]; + uint32_t hdr_hdl_v4; + uint32_t hdr_hdl_v6; + bool route_rule_set_v4; + int route_rule_set_v6; + bool ipv4_set; + int ipv6_set; + bool ipv4_header_set; + bool ipv6_header_set; + bool power_save_set; + wan_client_rt_hdl wan_rt_hdl[0]; /* depends on number of tx properties */ +}ipa_wan_client; + +/* wan iface */ +class IPACM_Wan : public IPACM_Iface +{ + +public: + + 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 + int i; + for (i=0; i < ipa_if_num_tether_v4_total;i++) + { + if (ipa_if_num_tether_v4[i] == ipa_if_num_tether) + { + IPACMDBG_H("support ipv4 tether_iface(%s)\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); + return wan_up; + break; + } + } + return false; +#else + return wan_up; +#endif + } + + static bool isWanUP_V6(int ipa_if_num_tether) + { +#ifdef FEATURE_IPA_ANDROID + int i; + for (i=0; i < ipa_if_num_tether_v6_total;i++) + { + if (ipa_if_num_tether_v6[i] == ipa_if_num_tether) + { + IPACMDBG_H("support ipv6 tether_iface(%s)\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); + return wan_up_v6; + break; + } + } + return false; +#else + return wan_up_v6; +#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); + + static struct ipa_flt_rule_add flt_rule_v4[IPA_MAX_FLT_RULE]; + static struct ipa_flt_rule_add flt_rule_v6[IPA_MAX_FLT_RULE]; + + static int num_v4_flt_rule; + static int num_v6_flt_rule; + + ipacm_wan_iface_type m_is_sta_mode; + static bool backhaul_is_sta_mode; + static bool is_ext_prop_set; + 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; + static int ipa_if_num_tether_v4[IPA_MAX_IFACE_ENTRIES]; + static int ipa_if_num_tether_v6_total; + static int ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES]; +#endif + +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; + uint32_t *wan_route_rule_v6_hdl_a5; + uint32_t hdr_hdl_sta_v4; + uint32_t hdr_hdl_sta_v6; + uint32_t firewall_hdl_v4[IPACM_MAX_FIREWALL_ENTRIES]; + uint32_t firewall_hdl_v6[IPACM_MAX_FIREWALL_ENTRIES]; + uint32_t dft_wan_fl_hdl[IPA_NUM_DEFAULT_WAN_FILTER_RULES]; + uint32_t ipv6_dest_flt_rule_hdl[MAX_DEFAULT_v6_ROUTE_RULES]; + int num_ipv6_dest_flt_rule; + 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; + bool header_set_v6; + bool header_partial_default_wan_v4; + bool header_partial_default_wan_v6; + uint8_t ext_router_mac_addr[IPA_MAC_ADDR_SIZE]; + uint8_t netdev_mac[IPA_MAC_ADDR_SIZE]; + + static int num_ipv4_modem_pdn; + + static int num_ipv6_modem_pdn; + + int modem_ipv4_pdn_index; + + int modem_ipv6_pdn_index; + + bool is_default_gateway; + + uint32_t ipv6_prefix[2]; + + /* IPACM firewall Configuration file*/ + IPACM_firewall_conf_t firewall_config; + + /* STA mode wan-client*/ + int wan_client_len; + ipa_wan_client *wan_client; + 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) + { + char *ret = ((char *)param) + (wan_client_len * cnt); + return (ipa_wan_client *)ret; + } + + inline int get_wan_client_index(uint8_t *mac_addr) + { + int cnt; + int num_wan_client_tmp = num_wan_client; + + IPACMDBG_H("Passed 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]); + + for(cnt = 0; cnt < num_wan_client_tmp; cnt++) + { + IPACMDBG_H("stored MAC %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]); + + if(memcmp(get_client_memptr(wan_client, cnt)->mac, + mac_addr, + sizeof(get_client_memptr(wan_client, cnt)->mac)) == 0) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + return cnt; + } + } + + 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; + uint32_t rt_hdl; + int num_v6; + + if(iptype == IPA_IP_v4) + { + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if((tx_prop->tx[tx_index].ip == IPA_IP_v4) && (get_client_memptr(wan_client, clt_indx)->route_rule_set_v4==true)) /* for ipv4 */ + { + IPACMDBG_H("Delete client index %d ipv4 Qos rules for tx:%d \n",clt_indx,tx_index); + rt_hdl = get_client_memptr(wan_client, clt_indx)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4; + + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v4) == false) + { + return IPACM_FAILURE; + } + } + } /* end of for loop */ + + /* clean the 4 Qos ipv4 RT rules for client:clt_indx */ + if(get_client_memptr(wan_client, clt_indx)->route_rule_set_v4==true) /* for ipv4 */ + { + get_client_memptr(wan_client, clt_indx)->route_rule_set_v4 = false; + } + } + + if(iptype == IPA_IP_v6) + { + 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(wan_client, clt_indx)->route_rule_set_v6 != 0)) /* for ipv6 */ + { + for(num_v6 =0;num_v6 < get_client_memptr(wan_client, clt_indx)->route_rule_set_v6;num_v6++) + { + IPACMDBG_H("Delete client index %d ipv6 Qos rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index); + rt_hdl = get_client_memptr(wan_client, clt_indx)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + + rt_hdl = get_client_memptr(wan_client, clt_indx)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + } + + } + } /* end of for loop */ + + /* clean the 4 Qos ipv6 RT rules for client:clt_indx */ + if(get_client_memptr(wan_client, clt_indx)->route_rule_set_v6 != 0) /* for ipv6 */ + { + get_client_memptr(wan_client, clt_indx)->route_rule_set_v6 = 0; + } + } + + return IPACM_SUCCESS; + } + + int handle_wan_hdr_init(uint8_t *mac_addr); + int handle_wan_client_ipaddr(ipacm_event_data_all *data); + int handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype); + + /* handle new_address event */ + int handle_addr_evt(ipacm_event_data_addr *data); + + /* wan default route/filter rule configuration */ + int handle_route_add_evt(ipa_ip_type iptype); + + /* 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 */ + int config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, ipa_ioc_add_flt_rule *pFilteringTable_v6); + + int handle_route_del_evt(ipa_ip_type iptype); + + int del_dft_firewall_rules(ipa_ip_type iptype); + + int handle_down_evt(); + + /*handle wan-iface down event */ + int handle_down_evt_ex(); + + /* wan default route/filter rule delete */ + int handle_route_del_evt_ex(ipa_ip_type iptype); + + /* configure the initial firewall filter rules */ + int config_dft_firewall_rules_ex(struct ipa_flt_rule_add* rules, int rule_offset, + ipa_ip_type iptype); + + /* init filtering rule in wan dl filtering table */ + int init_fl_rule_ex(ipa_ip_type iptype); + + /* add ICMP and ALG rules in wan dl filtering table */ + int add_icmp_alg_rules(struct ipa_flt_rule_add* rules, int rule_offset, ipa_ip_type iptype); + + /* query extended property */ + int query_ext_prop(); + + ipa_ioc_query_intf_ext_props *ext_prop; + + int config_wan_firewall_rule(ipa_ip_type iptype); + + int del_wan_firewall_rule(ipa_ip_type iptype); + + int add_dft_filtering_rule(struct ipa_flt_rule_add* rules, int rule_offset, ipa_ip_type iptype); + + int install_wan_filtering_rule(bool is_sw_routing); + + void change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib); + + 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 new file mode 100644 index 0000000..eb911ac --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wlan.h @@ -0,0 +1,240 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_Wlan.h + + @brief + This file implements the WLAN iface functionality. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_WLAN_H +#define IPACM_WLAN_H + +#include +#include +#include +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Lan.h" +#include "IPACM_Iface.h" +#include "IPACM_Conntrack_NATApp.h" + +typedef struct _wlan_client_rt_hdl +{ + uint32_t wifi_rt_rule_hdl_v4; + uint32_t wifi_rt_rule_hdl_v6[IPV6_NUM_ADDR]; + uint32_t wifi_rt_rule_hdl_v6_wan[IPV6_NUM_ADDR]; +}wlan_client_rt_hdl; + +typedef struct _ipa_wlan_client +{ + ipacm_event_data_wlan_ex* p_hdr_info; + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint32_t v4_addr; + uint32_t v6_addr[IPV6_NUM_ADDR][4]; + uint32_t hdr_hdl_v4; + uint32_t hdr_hdl_v6; + bool route_rule_set_v4; + int route_rule_set_v6; + bool ipv4_set; + int ipv6_set; + bool ipv4_header_set; + bool ipv6_header_set; + bool power_save_set; + wlan_client_rt_hdl wifi_rt_hdl[0]; /* depends on number of tx properties */ +}ipa_wlan_client; + +/* wlan iface */ +class IPACM_Wlan : public IPACM_Lan +{ + +public: + + IPACM_Wlan(int iface_index); + virtual ~IPACM_Wlan(void); + + static int total_num_wifi_clients; + + void event_callback(ipa_cm_event_id event, void *data); + + bool is_guest_ap(); + +private: + + bool m_is_guest_ap; + + /* handle wlan access mode switch in ethernet bridging*/ + void eth_bridge_handle_wlan_mode_switch(); + + + int wlan_client_len; + ipa_wlan_client *wlan_client; + + int header_name_count; + int num_wifi_client; + + int wlan_ap_index; + + static int num_wlan_ap_iface; + + NatApp *Nat_App; + + inline ipa_wlan_client* get_client_memptr(ipa_wlan_client *param, int cnt) + { + char *ret = ((char *)param) + (wlan_client_len * cnt); + return (ipa_wlan_client *)ret; + } + + inline int get_wlan_client_index(uint8_t *mac_addr) + { + int cnt; + int num_wifi_client_tmp = num_wifi_client; + + IPACMDBG_H("Passed 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]); + + for(cnt = 0; cnt < num_wifi_client_tmp; cnt++) + { + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wlan_client, cnt)->mac[0], + get_client_memptr(wlan_client, cnt)->mac[1], + get_client_memptr(wlan_client, cnt)->mac[2], + get_client_memptr(wlan_client, cnt)->mac[3], + get_client_memptr(wlan_client, cnt)->mac[4], + get_client_memptr(wlan_client, cnt)->mac[5]); + + if(memcmp(get_client_memptr(wlan_client, cnt)->mac, + mac_addr, + sizeof(get_client_memptr(wlan_client, cnt)->mac)) == 0) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + return cnt; + } + } + + return IPACM_INVALID_INDEX; + } + + inline int delete_default_qos_rtrules(int clt_indx, ipa_ip_type iptype) + { + uint32_t tx_index; + uint32_t rt_hdl; + int num_v6; + + if(iptype == IPA_IP_v4) + { + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if((tx_prop->tx[tx_index].ip == IPA_IP_v4) && (get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4==true)) /* for ipv4 */ + { + IPACMDBG_H("Delete client index %d ipv4 Qos rules for tx:%d \n",clt_indx,tx_index); + rt_hdl = get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4; + + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v4) == false) + { + return IPACM_FAILURE; + } + } + } /* end of for loop */ + + /* clean the 4 Qos ipv4 RT rules for client:clt_indx */ + if(get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4==true) /* for ipv4 */ + { + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = false; + } + } + + if(iptype == IPA_IP_v6) + { + 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(wlan_client, clt_indx)->route_rule_set_v6 != 0)) /* for ipv6 */ + { + for(num_v6 =0;num_v6 < get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6;num_v6++) + { + IPACMDBG_H("Delete client index %d ipv6 Qos rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index); + rt_hdl = get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + + rt_hdl = get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + } + + } + } /* end of for loop */ + + /* clean the 4 Qos ipv6 RT rules for client:clt_indx */ + if(get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 != 0) /* for ipv6 */ + { + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = 0; + } + } + + return IPACM_SUCCESS; + } + + /* for handle wifi client initial,copy all partial headers (tx property) */ + int handle_wlan_client_init_ex(ipacm_event_data_wlan_ex *data); + + /*handle wifi client */ + int handle_wlan_client_ipaddr(ipacm_event_data_all *data); + + /*handle wifi client routing rule*/ + int handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype); + + /*handle wifi client power-save mode*/ + int handle_wlan_client_pwrsave(uint8_t *mac_addr); + + /*handle wifi client del mode*/ + int handle_wlan_client_down_evt(uint8_t *mac_addr); + + /*handle wlan iface down event*/ + int handle_down_evt(); + + /*handle reset wifi-client rt-rules */ + int handle_wlan_client_reset_rt(ipa_ip_type iptype); + + void handle_SCC_MCC_switch(ipa_ip_type); + +}; + + +#endif /* IPACM_WLAN_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h new file mode 100644 index 0000000..64c00ed --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h @@ -0,0 +1,303 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Xml.h + + @brief + This file implements the XML specific parsing functionality. + + @Author + Skylar Chang/Shihuan Liu + +*/ +#ifndef IPACM_XML_H +#define IPACM_XML_H + +#include +#include "IPACM_Defs.h" +#include +#include +#include +#include +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + + +#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) */ +#define IPACM_XML_MAX_FILESIZE (2 << 20) +#define IPACM_MAX_FIREWALL_ENTRIES 50 +#define IPACM_IPV6_ADDR_LEN 16 + +/* Defines for clipping space or space & quotes (single, double) */ +#define IPACM_XML_CLIP_SPACE " " +#define IPACM_XML_CLIP_SPACE_QUOTES " '\"" + +#define MAX_XML_STR_LEN 120 + +/* IPA Config Entries */ +#define system_TAG "system" +#define ODU_TAG "ODUCFG" +#define ODUMODE_TAG "OduMode" +#define ODUEMBMS_OFFLOAD_TAG "eMBMS_offload" +#define ODU_ROUTER_TAG "router" +#define ODU_BRIDGE_TAG "bridge" +#define IPACMCFG_TAG "IPACM" +#define IPACMIFACECFG_TAG "IPACMIface" +#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" +#define SUBNETMASK_TAG "SubnetMask" +#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" +#define Port_TAG "Port" +#define TCP_PROTOCOL_TAG "TCP" +#define UDP_PROTOCOL_TAG "UDP" + +/* FIREWALL Config Entries */ +#define Firewall_TAG "Firewall" +#define MobileAPFirewallCfg_TAG "MobileAPFirewallCfg" +#define FirewallEnabled_TAG "FirewallEnabled" +#define FirewallPktsAllowed_TAG "FirewallPktsAllowed" + +#define IPFamily_TAG "IPFamily" +#define IPV4SourceAddress_TAG "IPV4SourceAddress" +#define IPV4SourceIPAddress_TAG "IPV4SourceIPAddress" +#define IPV4SourceSubnetMask_TAG "IPV4SourceSubnetMask" + +#define IPV4DestinationAddress_TAG "IPV4DestinationAddress" +#define IPV4DestinationIPAddress_TAG "IPV4DestinationIPAddress" +#define IPV4DestinationSubnetMask_TAG "IPV4DestinationSubnetMask" + +#define IPV4TypeOfService_TAG "IPV4TypeOfService" +#define TOSValue_TAG "TOSValue" +#define TOSMask_TAG "TOSMask" + +#define IPV4NextHeaderProtocol_TAG "IPV4NextHeaderProtocol" + +#define IPV6SourceAddress_TAG "IPV6SourceAddress" +#define IPV6SourceIPAddress_TAG "IPV6SourceIPAddress" +#define IPV6SourcePrefix_TAG "IPV6SourcePrefix" + +#define IPV6DestinationAddress_TAG "IPV6DestinationAddress" +#define IPV6DestinationIPAddress_TAG "IPV6DestinationIPAddress" +#define IPV6DestinationPrefix_TAG "IPV6DestinationPrefix" + +#define IPV6TrafficClass_TAG "IPV6TrafficClass" +#define TrfClsValue_TAG "TrfClsValue" +#define TrfClsMask_TAG "TrfClsMask" + +#define IPV6NextHeaderProtocol_TAG "IPV6NextHeaderProtocol" + +#define TCPSource_TAG "TCPSource" +#define TCPSourcePort_TAG "TCPSourcePort" +#define TCPSourceRange_TAG "TCPSourceRange" + +#define TCPDestination_TAG "TCPDestination" +#define TCPDestinationPort_TAG "TCPDestinationPort" +#define TCPDestinationRange_TAG "TCPDestinationRange" + +#define UDPSource_TAG "UDPSource" +#define UDPSourcePort_TAG "UDPSourcePort" +#define UDPSourceRange_TAG "UDPSourceRange" + +#define UDPDestination_TAG "UDPDestination" +#define UDPDestinationPort_TAG "UDPDestinationPort" +#define UDPDestinationRange_TAG "UDPDestinationRange" + +#define ICMPType_TAG "ICMPType" +#define ICMPCode_TAG "ICMPCode" + +#define ESP_TAG "ESP" +#define ESPSPI_TAG "ESPSPI" + +#define TCP_UDPSource_TAG "TCP_UDPSource" +#define TCP_UDPSourcePort_TAG "TCP_UDPSourcePort" +#define TCP_UDPSourceRange_TAG "TCP_UDPSourceRange" + +#define TCP_UDPDestination_TAG "TCP_UDPDestination" +#define TCP_UDPDestinationPort_TAG "TCP_UDPDestinationPort" +#define TCP_UDPDestinationRange_TAG "TCP_UDPDestinationRange" + +#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_ip_protocol_enum_type; + +/* define as mobileap firewall rule format*/ +typedef enum +{ + IP_V4 = 4, + IP_V6 = 6 +} firewall_ip_version_enum; + +/*--------------------------------------------------------------------------- + Extended FireWall Entry Configuration. +---------------------------------------------------------------------------*/ +typedef struct +{ + struct ipa_rule_attrib attrib; + firewall_ip_version_enum ip_vsn; +} IPACM_extd_firewall_entry_conf_t; + + +/*--------------------------------------------------------------------------- + Extended FireWall configuration. +---------------------------------------------------------------------------*/ +typedef union +{ + 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; +} IPACM_firewall_conf_t; + + + +typedef struct +{ + 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]; +} ipacm_private_subnet_conf_t; + +typedef struct +{ + uint8_t protocol; + uint16_t port; +} ipacm_alg; + +typedef struct +{ + 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; + int nat_max_entries; + 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 */ +); + +/* 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 */ +); + +#ifdef __cplusplus +} +#endif + +#endif //IPACM_XML diff --git a/data-ipa-cfg-mgr/ipacm/src/Android.mk b/data-ipa-cfg-mgr/ipacm/src/Android.mk new file mode 100644 index 0000000..101df25 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/Android.mk @@ -0,0 +1,98 @@ +BOARD_PLATFORM_LIST := msm8916 +BOARD_PLATFORM_LIST += msm8909 +ifneq ($(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) + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../inc +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../ipanat/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/libxml2/include +LOCAL_C_INCLUDES += external/libnetfilter_conntrack/include +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 +ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT))) +LOCAL_CFLAGS += -DDEBUG +endif + +ifeq ($(TARGET_BOARD_PLATFORM),msmcobalt) +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 \ + IPACM_CmdQueue.cpp \ + IPACM_Filtering.cpp \ + IPACM_Routing.cpp \ + IPACM_Header.cpp \ + IPACM_Lan.cpp \ + IPACM_Iface.cpp \ + IPACM_Wlan.cpp \ + IPACM_Wan.cpp \ + IPACM_IfaceManager.cpp \ + IPACM_Neighbor.cpp \ + IPACM_Netlink.cpp \ + IPACM_Xml.cpp \ + IPACM_Conntrack_NATApp.cpp\ + IPACM_ConntrackClient.cpp \ + IPACM_ConntrackListener.cpp \ + IPACM_Log.cpp + +LOCAL_MODULE := ipacm +LOCAL_CLANG := false +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := libipanat +LOCAL_SHARED_LIBRARIES += libxml2 +LOCAL_SHARED_LIBRARIES += libnfnetlink +LOCAL_SHARED_LIBRARIES += libnetfilter_conntrack +LOCAL_CLANG := true +include $(BUILD_EXECUTABLE) + +################################################################################ + +define ADD_TEST + +include $(CLEAR_VARS) +LOCAL_MODULE := $1 +LOCAL_SRC_FILES := $1 +LOCAL_MODULE_CLASS := ipacm +LOCAL_MODULE_TAGS := debug +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC) +include $(BUILD_PREBUILT) + +endef + +include $(CLEAR_VARS) +LOCAL_MODULE := IPACM_cfg.xml +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC) +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 new file mode 100644 index 0000000..a17fb08 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_CmdQueue.cpp @@ -0,0 +1,205 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_CmdQueue.cpp + + @brief + This file implements the IPAM Comment Queue functionality + + @Author + Sunil + +*/ +#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_internal = NULL; +MessageQueue* MessageQueue::inst_external = NULL; + +MessageQueue* MessageQueue::getInstanceInternal() +{ + if(inst_internal == NULL) + { + inst_internal = new MessageQueue(); + if(inst_internal == NULL) + { + IPACMERR("unable to create internal Message Queue instance\n"); + return NULL; + } + } + + 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) +{ + if(!Head) + { + Tail = item; + Head = item; + } + else + { + if(Tail == NULL) + { + IPACMDBG("Tail is null\n"); + Head->setnext(item); + } + else + { + Tail->setnext(item); + } + Tail = item; + } +} + + +Message* MessageQueue::dequeue(void) +{ + if(Head == NULL) + { + return NULL; + } + else + { + Message *tmp = Head; + Head = Head->getnext(); + + return tmp; + } +} + + +void* MessageQueue::Process(void *param) +{ + MessageQueue *MsgQueueInternal = NULL; + MessageQueue *MsgQueueExternal = NULL; + Message *item = NULL; + IPACMDBG("MessageQueue::Process()\n"); + + 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 external cmd queue process\n"); + return NULL; + } + + while(1) + { + if(pthread_mutex_lock(&mutex) != 0) + { + IPACMERR("unable to lock the mutex\n"); + return NULL; + } + + 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) + { + IPACMDBG("Waiting for Message\n"); + + if(pthread_cond_wait(&cond_var, &mutex) != 0) + { + IPACMERR("unable to lock the mutex\n"); + + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return NULL; + } + + return NULL; + } + + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return NULL; + } + + } + else + { + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return NULL; + } + + IPACMDBG("Processing item %p event ID: %d\n",item,item->evt.data.event); + item->evt.callback_ptr(&item->evt.data); + delete item; + item = NULL; + } + + } /* Go forever until a termination indication is received */ + +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp new file mode 100644 index 0000000..d8c4227 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp @@ -0,0 +1,824 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_Config.cpp + + @brief + This file implements the IPACM Configuration from XML file + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include + +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(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; + 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; + ipa_num_alg_ports = 0; + 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)); + memset(&rt_tbl_wan_v4, 0, sizeof(rt_tbl_wan_v4)); + memset(&rt_tbl_v6, 0, sizeof(rt_tbl_v6)); + memset(&rt_tbl_wan_v6, 0, sizeof(rt_tbl_wan_v6)); + memset(&rt_tbl_wan_dl, 0, sizeof(rt_tbl_wan_dl)); + memset(&rt_tbl_odu_v4, 0, sizeof(rt_tbl_odu_v4)); + memset(&rt_tbl_odu_v6, 0, sizeof(rt_tbl_odu_v6)); + + memset(&ext_prop_v4, 0, sizeof(ext_prop_v4)); + memset(&ext_prop_v6, 0, sizeof(ext_prop_v6)); + + qmap_id = ~0; + + memset(flt_rule_count_v4, 0, (IPA_CLIENT_CONS - IPA_CLIENT_PROD)*sizeof(int)); + memset(flt_rule_count_v6, 0, (IPA_CLIENT_CONS - IPA_CLIENT_PROD)*sizeof(int)); + memset(bridge_mac, 0, IPA_MAC_ADDR_SIZE*sizeof(uint8_t)); + + IPACMDBG_H(" create IPACM_Config constructor\n"); + return; +} + +int IPACM_Config::Init(void) +{ + /* Read IPACM Config file */ + char IPACM_config_file[IPA_MAX_FILE_LEN]; + IPACM_conf_t *cfg; + cfg = (IPACM_conf_t *)malloc(sizeof(IPACM_conf_t)); + if(cfg == NULL) + { + IPACMERR("Unable to allocate cfg memory.\n"); + return IPACM_FAILURE; + } + uint32_t subnet_addr; + uint32_t subnet_mask; + int i, ret = IPACM_SUCCESS; + struct in_addr in_addr_print; + + m_fd = open(DEVICE_NAME, O_RDWR); + if (0 > m_fd) + { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + } + strncpy(IPACM_config_file, "/etc/IPACM_cfg.xml", sizeof(IPACM_config_file)); + + IPACMDBG_H("\n IPACM XML file is %s \n", IPACM_config_file); + if (IPACM_SUCCESS == ipacm_read_cfg_xml(IPACM_config_file, cfg)) + { + IPACMDBG_H("\n IPACM XML read OK \n"); + } + else + { + IPACMERR("\n IPACM XML read failed \n"); + ret = IPACM_FAILURE; + goto fail; + } + + /* Check wlan AP-AP access mode configuration */ + if (cfg->num_wlan_guest_ap == 2) + { + IPACMDBG_H("IPACM_Config::Both wlan APs can not be configured in guest ap mode. \n"); + IPACMDBG_H("IPACM_Config::configure both APs in full access mode or at least one in guest ap mode. \n"); + ret = IPACM_FAILURE; + goto fail; + } + /* Construct IPACM Iface table */ + ipa_num_ipa_interfaces = cfg->iface_config.num_iface_entries; + if (iface_table != NULL) + { + free(iface_table); + iface_table = NULL; + IPACMDBG_H("RESET IPACM_Config::iface_table\n"); + } + iface_table = (ipa_ifi_dev_name_t *)calloc(ipa_num_ipa_interfaces, + sizeof(ipa_ifi_dev_name_t)); + if(iface_table == NULL) + { + IPACMERR("Unable to allocate iface_table memory.\n"); + ret = IPACM_FAILURE; + goto fail; + } + + for (i = 0; i < cfg->iface_config.num_iface_entries; i++) + { + 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; + 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) + { + 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); + } + } + + /* Construct IPACM Private_Subnet table */ + memset(&private_subnet_table, 0, sizeof(private_subnet_table)); + ipa_num_private_subnet = cfg->private_subnet_config.num_subnet_entries; + + for (i = 0; i < cfg->private_subnet_config.num_subnet_entries; i++) + { + memcpy(&private_subnet_table[i].subnet_addr, + &cfg->private_subnet_config.private_subnet_entries[i].subnet_addr, + sizeof(cfg->private_subnet_config.private_subnet_entries[i].subnet_addr)); + + memcpy(&private_subnet_table[i].subnet_mask, + &cfg->private_subnet_config.private_subnet_entries[i].subnet_mask, + sizeof(cfg->private_subnet_config.private_subnet_entries[i].subnet_mask)); + + subnet_addr = htonl(private_subnet_table[i].subnet_addr); + memcpy(&in_addr_print,&subnet_addr,sizeof(in_addr_print)); + IPACMDBG_H("%dst::private_subnet_table= %s \n ", i, + inet_ntoa(in_addr_print)); + + subnet_mask = htonl(private_subnet_table[i].subnet_mask); + memcpy(&in_addr_print,&subnet_mask,sizeof(in_addr_print)); + IPACMDBG_H("%dst::private_subnet_table= %s \n ", i, + inet_ntoa(in_addr_print)); + } + + /* Construct IPACM ALG table */ + ipa_num_alg_ports = cfg->alg_config.num_alg_entries; + if (alg_table != NULL) + { + free(alg_table); + alg_table = NULL; + IPACMDBG_H("RESET IPACM_Config::alg_table \n"); + } + alg_table = (ipacm_alg *)calloc(ipa_num_alg_ports, + sizeof(ipacm_alg)); + if(alg_table == NULL) + { + IPACMERR("Unable to allocate alg_table memory.\n"); + ret = IPACM_FAILURE; + free(iface_table); + goto fail;; + } + for (i = 0; i < cfg->alg_config.num_alg_entries; i++) + { + alg_table[i].protocol = cfg->alg_config.alg_entries[i].protocol; + alg_table[i].port = cfg->alg_config.alg_entries[i].port; + IPACMDBG_H("IPACM_Config::ipacm_alg[%d] = %d, port=%d\n", i, alg_table[i].protocol, alg_table[i].port); + } + + ipa_nat_max_entries = cfg->nat_max_entries; + IPACMDBG_H("Nat Maximum Entries %d\n", ipa_nat_max_entries); + + /* 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) + { + free(pNatIfaces); + 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) + { + IPACMERR("unable to allocate nat ifaces\n"); + ret = IPACM_FAILURE; + free(iface_table); + free(alg_table); + goto fail; + } + + /* Construct the routing table ictol name in iface static member*/ + rt_tbl_default_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_default_v4.name, V4_DEFAULT_ROUTE_TABLE_NAME, sizeof(rt_tbl_default_v4.name)); + + rt_tbl_lan_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_lan_v4.name, V4_LAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_lan_v4.name)); + + rt_tbl_wan_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_wan_v4.name, V4_WAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_wan_v4.name)); + + rt_tbl_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_v6.name, V6_COMMON_ROUTE_TABLE_NAME, sizeof(rt_tbl_v6.name)); + + rt_tbl_wan_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_wan_v6.name, V6_WAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_wan_v6.name)); + + rt_tbl_odu_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_odu_v4.name, V4_ODU_ROUTE_TABLE_NAME, sizeof(rt_tbl_odu_v4.name)); + + rt_tbl_odu_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_odu_v6.name, V6_ODU_ROUTE_TABLE_NAME, sizeof(rt_tbl_odu_v6.name)); + + 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)); + + /* 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; + ipa_client_rm_map_tbl[IPA_CLIENT_A5_WLAN_AMPDU_PROD]= IPA_RM_RESOURCE_HSIC_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_A2_EMBEDDED_PROD]= IPA_RM_RESOURCE_Q6_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_A2_TETHERED_PROD]= IPA_RM_RESOURCE_Q6_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_APPS_LAN_WAN_PROD]= IPA_RM_RESOURCE_Q6_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_WLAN1_CONS]= IPA_RM_RESOURCE_WLAN_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_WLAN2_CONS]= IPA_RM_RESOURCE_WLAN_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_WLAN3_CONS]= IPA_RM_RESOURCE_WLAN_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_WLAN4_CONS]= IPA_RM_RESOURCE_WLAN_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_USB_CONS]= IPA_RM_RESOURCE_USB_CONS; + 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; + ipa_rm_tbl[0].consumer_rm1 = IPA_RM_RESOURCE_Q6_CONS; + ipa_rm_tbl[0].producer_rm2 = IPA_RM_RESOURCE_Q6_PROD; + ipa_rm_tbl[0].consumer_rm2 = IPA_RM_RESOURCE_WLAN_CONS; + + ipa_rm_tbl[1].producer_rm1 = IPA_RM_RESOURCE_USB_PROD; + ipa_rm_tbl[1].consumer_rm1 = IPA_RM_RESOURCE_Q6_CONS; + ipa_rm_tbl[1].producer_rm2 = IPA_RM_RESOURCE_Q6_PROD; + ipa_rm_tbl[1].consumer_rm2 = IPA_RM_RESOURCE_USB_CONS; + + ipa_rm_tbl[2].producer_rm1 = IPA_RM_RESOURCE_WLAN_PROD; + ipa_rm_tbl[2].consumer_rm1 = IPA_RM_RESOURCE_USB_CONS; + 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) + { + free(cfg); + cfg = NULL; + } + + return ret; +} + +IPACM_Config* IPACM_Config::GetInstance() +{ + int res = IPACM_SUCCESS; + + if (pInstance == NULL) + { + pInstance = new IPACM_Config(); + + res = pInstance->Init(); + if (res != IPACM_SUCCESS) + { + delete pInstance; + IPACMERR("unable to initialize config instance\n"); + return NULL; + } + } + + return pInstance; +} + +int IPACM_Config::GetAlgPorts(int nPorts, ipacm_alg *pAlgPorts) +{ + if (nPorts <= 0 || pAlgPorts == NULL) + { + IPACMERR("Invalid input\n"); + return -1; + } + + for (int cnt = 0; cnt < nPorts; cnt++) + { + pAlgPorts[cnt].protocol = alg_table[cnt].protocol; + pAlgPorts[cnt].port = alg_table[cnt].port; + } + + return 0; +} + +int IPACM_Config::GetNatIfaces(int nIfaces, NatIfaces *pIfaces) +{ + if (nIfaces <= 0 || pIfaces == NULL) + { + IPACMERR("Invalid input\n"); + return -1; + } + + for (int cnt=0; cntnum_ext_props <= 0) + { + IPACMERR("There is no extended property!\n"); + return IPACM_FAILURE; + } + + num = prop->num_ext_props; + for(i=0; iext[i].ip == IPA_IP_v4) + { + if(ext_prop_v4.num_ext_props >= MAX_NUM_EXT_PROPS) + { + 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)); + ext_prop_v4.num_ext_props++; + } + else if(prop->ext[i].ip == IPA_IP_v6) + { + if(ext_prop_v6.num_ext_props >= MAX_NUM_EXT_PROPS) + { + 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)); + ext_prop_v6.num_ext_props++; + } + else + { + IPACMERR("The IP type is not expected!\n"); + return IPACM_FAILURE; + } + } + + IPACMDBG_H("Set extended property succeeded.\n"); + + return IPACM_SUCCESS; +} + +ipacm_ext_prop* IPACM_Config::GetExtProp(ipa_ip_type ip_type) +{ + if(ip_type == IPA_IP_v4) + return &ext_prop_v4; + else if(ip_type == IPA_IP_v6) + return &ext_prop_v6; + else + { + IPACMERR("Failed to get extended property: the IP version is neither IPv4 nor IPv6!\n"); + return NULL; + } +} + +int IPACM_Config::DelExtProp(ipa_ip_type ip_type) +{ + if(ip_type != IPA_IP_v6) + { + memset(&ext_prop_v4, 0, sizeof(ext_prop_v4)); + } + + if(ip_type != IPA_IP_v4) + { + memset(&ext_prop_v6, 0, sizeof(ext_prop_v6)); + } + + 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 new file mode 100644 index 0000000..146cedb --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackClient.cpp @@ -0,0 +1,652 @@ +/* +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 +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 +#include +#include +#include +#include +#include +#include "IPACM_Iface.h" +#include "IPACM_ConntrackListener.h" +#include "IPACM_ConntrackClient.h" +#include "IPACM_Log.h" + +#define LO_NAME "lo" + +extern IPACM_EvtDispatcher cm_dis; +extern void ParseCTMessage(struct nf_conntrack *ct); + +IPACM_ConntrackClient *IPACM_ConntrackClient::pInstance = NULL; +IPACM_ConntrackListener *CtList = NULL; + +/* ================================ + Local Function Definitions + ================================= +*/ +IPACM_ConntrackClient::IPACM_ConntrackClient() +{ + IPACMDBG("\n"); + + tcp_hdl = NULL; + udp_hdl = NULL; + tcp_filter = NULL; + udp_filter = NULL; +} + +IPACM_ConntrackClient* IPACM_ConntrackClient::GetInstance() +{ + if(pInstance == NULL) + { + pInstance = new IPACM_ConntrackClient(); + + pInstance->udp_filter = nfct_filter_create(); + if(pInstance->udp_filter == NULL) + { + IPACMERR("unable to create UDP filter\n"); + delete pInstance; + return NULL; + } + IPACMDBG("Created UDP filter\n"); + + pInstance->tcp_filter = nfct_filter_create(); + if(pInstance->tcp_filter == NULL) + { + IPACMERR("unable to create TCP filter\n"); + delete pInstance; + return NULL; + } + IPACMDBG("Created TCP filter\n"); + } + + return pInstance; +} + +int IPACM_ConntrackClient::IPAConntrackEventCB +( + enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data + ) +{ + ipacm_cmd_q_data evt_data; + ipacm_ct_evt_data *ct_data; + uint8_t ip_type = 0; + + IPACMDBG("Event callback called with msgtype: %d\n",type); + + /* Retrieve ip type */ + ip_type = nfct_get_attr_u8(ct, ATTR_REPL_L3PROTO); + +#ifndef CT_OPT + if(AF_INET6 == ip_type) + { + IPACMDBG("Ignoring ipv6(%d) connections\n", ip_type); + goto IGNORE; + } + +#endif + + ct_data = (ipacm_ct_evt_data *)malloc(sizeof(ipacm_ct_evt_data)); + if(ct_data == NULL) + { + IPACMERR("unable to allocate memory \n"); + goto IGNORE; + } + + ct_data->ct = ct; + ct_data->type = type; + + evt_data.event = IPA_PROCESS_CT_MESSAGE; + evt_data.evt_data = (void *)ct_data; + +#ifdef CT_OPT + if(AF_INET6 == ip_type) + { + evt_data.event = IPA_PROCESS_CT_MESSAGE_V6; + } +#endif + + if(0 != IPACM_EvtDispatcher::PostEvt(&evt_data)) + { + IPACMERR("Error sending Conntrack message to processing thread!\n"); + free(ct_data); + goto IGNORE; + } + +/* NFCT_CB_STOLEN means that the conntrack object is not released after the + callback That must be manually done later when the object is no longer needed. */ + return NFCT_CB_STOLEN; + +IGNORE: + nfct_destroy(ct); + return NFCT_CB_STOLEN; + +} + +int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Bridge_Addrs +( + struct nfct_filter *filter +) +{ + int fd; + fd = socket(AF_INET, SOCK_DGRAM, 0); + if(fd < 0) + { + PERROR("unable to open socket"); + return -1; + } + + int ret; + uint32_t ipv4_addr; + struct ifreq ifr; + + /* 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)); + IPACMDBG("bridge interface name (%s)\n", ifr.ifr_name); + + ret = ioctl(fd, SIOCGIFADDR, &ifr); + if (ret < 0) + { + IPACMERR("unable to retrieve (%s) interface address\n",ifr.ifr_name); + close(fd); + return -1; + } + IPACMDBG("Interface (%s) address %s\n", ifr.ifr_name, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); + ipv4_addr = ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr); + close(fd); + + /* ignore whatever is destined to or originates from broadcast ip address */ + struct nfct_filter_ipv4 filter_ipv4; + + filter_ipv4.addr = ipv4_addr; + filter_ipv4.mask = 0xffffffff; + + nfct_filter_set_logic(filter, + NFCT_FILTER_DST_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4); + + nfct_filter_set_logic(filter, + NFCT_FILTER_SRC_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4); + + return 0; +} + +int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Local_Iface +( + struct nfct_filter *filter, + ipacm_event_iface_up *param +) +{ + struct nfct_filter_ipv4 filter_ipv4; + + filter_ipv4.addr = param->ipv4_addr; + filter_ipv4.mask = 0xffffffff; + + /* ignore whatever is destined to local interfaces */ + IPACMDBG("Ignore connections destinated to interface %s", param->ifname); + iptodot("with ipv4 address", param->ipv4_addr); + nfct_filter_set_logic(filter, + NFCT_FILTER_DST_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4); + + IPACMDBG("Ignore connections orignated from interface %s", param->ifname); + iptodot("with ipv4 address", filter_ipv4.addr); + nfct_filter_set_logic(filter, + NFCT_FILTER_SRC_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4); + + /* Retrieve broadcast address */ + /* Intialize with 255.255.255.255 */ + uint32_t bc_ip_addr = 0xFFFFFFFF; + + /* calculate broadcast address from addr and addr_mask */ + bc_ip_addr = (bc_ip_addr & (~param->addr_mask)); + bc_ip_addr = (bc_ip_addr | (param->ipv4_addr & param->addr_mask)); + + /* netfitler expecting in host-byte order */ + filter_ipv4.addr = bc_ip_addr; + filter_ipv4.mask = 0xffffffff; + + iptodot("with broadcast address", filter_ipv4.addr); + nfct_filter_set_logic(filter, + NFCT_FILTER_DST_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4); + + return 0; +} + +/* Function which sets up filters to ignore + connections to and from local interfaces */ +int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Local_Addrs +( + struct nfct_filter *filter +) +{ + struct nfct_filter_ipv4 filter_ipv4; + + /* ignore whatever is destined to or originates from broadcast ip address */ + filter_ipv4.addr = 0xffffffff; + filter_ipv4.mask = 0xffffffff; + + nfct_filter_set_logic(filter, + NFCT_FILTER_DST_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4); + + nfct_filter_set_logic(filter, + NFCT_FILTER_SRC_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4); + + return 0; +} /* IPA_Conntrack_Filters_Ignore_Local_Addrs() */ + +/* Initialize TCP Filter */ +int IPACM_ConntrackClient::IPA_Conntrack_TCP_Filter_Init(void) +{ + int ret = 0; + IPACM_ConntrackClient *pClient; + + IPACMDBG("\n"); + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to get conntrack client instance\n"); + return -1; + } + + ret = nfct_filter_set_logic(pClient->tcp_filter, + NFCT_FILTER_L4PROTO, + NFCT_FILTER_LOGIC_POSITIVE); + if(ret == -1) + { + IPACMERR("Unable to set filter logic\n"); + return -1; + } + + /* set protocol filters as tcp and udp */ + nfct_filter_add_attr_u32(pClient->tcp_filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP); + + + struct nfct_filter_proto tcp_proto_state; + tcp_proto_state.proto = IPPROTO_TCP; + tcp_proto_state.state = TCP_CONNTRACK_ESTABLISHED; + + ret = nfct_filter_set_logic(pClient->tcp_filter, + NFCT_FILTER_L4PROTO_STATE, + NFCT_FILTER_LOGIC_POSITIVE); + if(ret == -1) + { + IPACMERR("unable to set filter logic\n"); + return -1; + } + nfct_filter_add_attr(pClient->tcp_filter, + NFCT_FILTER_L4PROTO_STATE, + &tcp_proto_state); + + + tcp_proto_state.proto = IPPROTO_TCP; + tcp_proto_state.state = TCP_CONNTRACK_FIN_WAIT; + ret = nfct_filter_set_logic(pClient->tcp_filter, + NFCT_FILTER_L4PROTO_STATE, + NFCT_FILTER_LOGIC_POSITIVE); + if(ret == -1) + { + IPACMERR("unable to set filter logic\n"); + return -1; + } + + nfct_filter_add_attr(pClient->tcp_filter, + NFCT_FILTER_L4PROTO_STATE, + &tcp_proto_state); + return 0; +} + + +/* Initialize UDP Filter */ +int IPACM_ConntrackClient::IPA_Conntrack_UDP_Filter_Init(void) +{ + int ret = 0; + IPACM_ConntrackClient *pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to get conntrack client instance\n"); + return -1; + } + + ret = nfct_filter_set_logic(pClient->udp_filter, + NFCT_FILTER_L4PROTO, + NFCT_FILTER_LOGIC_POSITIVE); + if(ret == -1) + { + IPACMERR("unable to set filter logic\n"); + } + /* set protocol filters as tcp and udp */ + nfct_filter_add_attr_u32(pClient->udp_filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP); + + return 0; +} + +void* IPACM_ConntrackClient::UDPConnTimeoutUpdate(void *ptr) +{ + + NatApp *nat_inst = NULL; +#ifdef IPACM_DEBUG + IPACMDBG("\n"); +#endif + + nat_inst = NatApp::GetInstance(); + if(nat_inst == NULL) + { + IPACMERR("unable to create nat instance\n"); + return NULL; + } + + while(1) + { + nat_inst->UpdateUDPTimeStamp(); + sleep(UDP_TIMEOUT_UPDATE); + } /* end of while(1) loop */ + +#ifdef IPACM_DEBUG + IPACMDBG("Returning from %s() %d\n", __FUNCTION__, __LINE__); +#endif + + return NULL; +} + +/* Thread to initialize TCP Conntrack Filters*/ +void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *) +{ + int ret; + IPACM_ConntrackClient *pClient; + unsigned subscrips = 0; + + IPACMDBG("\n"); + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to get conntrack client instance\n"); + return NULL; + } + + subscrips = (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); +#ifdef CT_OPT + subscrips |= NF_NETLINK_CONNTRACK_NEW; +#endif + + pClient->tcp_hdl = nfct_open(CONNTRACK, subscrips); + if(pClient->tcp_hdl == NULL) + { + PERROR("nfct_open\n"); + return NULL; + } + + /* Initialize the filter */ + ret = IPA_Conntrack_TCP_Filter_Init(); + if(ret == -1) + { + IPACMERR("Unable to initliaze TCP Filter\n"); + return NULL; + } + + /* Attach the filter to net filter handler */ + ret = nfct_filter_attach(nfct_fd(pClient->tcp_hdl), pClient->tcp_filter); + if(ret == -1) + { + IPACMDBG("unable to attach TCP filter\n"); + return NULL; + } + + /* Register callback with netfilter handler */ + 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), + IPAConntrackEventCB, NULL); +#else + nfct_callback_register(pClient->tcp_hdl, (nf_conntrack_msg_type) NFCT_T_ALL, IPAConntrackEventCB, NULL); +#endif + + /* Block to catch events from net filter connection track */ + /* nfct_catch() receives conntrack events from kernel-space, by default it + blocks waiting for events. */ + IPACMDBG("Waiting for events\n"); + + ret = nfct_catch(pClient->tcp_hdl); + if(ret == -1) + { + IPACMERR("(%d)(%s)\n", ret, strerror(errno)); + return NULL; + } + + IPACMDBG("Exit from tcp thread\n"); + + /* destroy the filter.. this will not detach the filter */ + nfct_filter_destroy(pClient->tcp_filter); + pClient->tcp_filter = NULL; + + /* de-register the callback */ + nfct_callback_unregister(pClient->tcp_hdl); + /* close the handle */ + nfct_close(pClient->tcp_hdl); + pClient->tcp_hdl = NULL; + + pthread_exit(NULL); + return NULL; +} + +/* Thread to initialize UDP Conntrack Filters*/ +void* IPACM_ConntrackClient::UDPRegisterWithConnTrack(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 NULL; + } + + pClient->udp_hdl = nfct_open(CONNTRACK, + (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY)); + if(pClient->udp_hdl == NULL) + { + PERROR("nfct_open\n"); + return NULL; + } + + /* Initialize Filter */ + ret = IPA_Conntrack_UDP_Filter_Init(); + if(-1 == ret) + { + IPACMDBG("Unable to initalize udp filters\n"); + return NULL; + } + + /* Attach the filter to net filter handler */ + ret = nfct_filter_attach(nfct_fd(pClient->udp_hdl), pClient->udp_filter); + if(ret == -1) + { + IPACMDBG("unable to attach the filter\n"); + return NULL; + } + + /* Register callback with netfilter handler */ + 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); + + /* Block to catch events from net filter connection track */ +ctcatch: + ret = nfct_catch(pClient->udp_hdl); + if(ret == -1) + { + IPACMDBG("(%d)(%s)\n", ret, strerror(errno)); + return NULL; + } + else + { + IPACMDBG("ctcatch ret:%d\n", ret); + goto ctcatch; + } + + IPACMDBG("Exit from udp thread with ret: %d\n", ret); + + /* destroy the filter.. this will not detach the filter */ + nfct_filter_destroy(pClient->udp_filter); + pClient->udp_filter = NULL; + + /* de-register the callback */ + nfct_callback_unregister(pClient->udp_hdl); + /* close the handle */ + nfct_close(pClient->udp_hdl); + pClient->udp_hdl = NULL; + + pthread_exit(NULL); + return NULL; +} + +void IPACM_ConntrackClient::UpdateUDPFilters(void *param, bool isWan) +{ + static bool isIgnore = false; + int ret = 0; + IPACM_ConntrackClient *pClient = NULL; + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to retrieve conntrack client instance\n"); + return; + } + + if(pClient->udp_filter == NULL) + { + return; + } + + if(!isWan) + { + IPA_Conntrack_Filters_Ignore_Local_Iface(pClient->udp_filter, + (ipacm_event_iface_up *)param); + + if(!isIgnore) + { + IPA_Conntrack_Filters_Ignore_Bridge_Addrs(pClient->udp_filter); + IPA_Conntrack_Filters_Ignore_Local_Addrs(pClient->udp_filter); + isIgnore = true; + } + } + + /* Attach the filter to udp handle */ + if(pClient->udp_hdl != NULL) + { + IPACMDBG("attaching the filter to udp handle\n"); + ret = nfct_filter_attach(nfct_fd(pClient->udp_hdl), pClient->udp_filter); + if(ret == -1) + { + PERROR("unable to attach the filter to udp handle\n"); + IPACMERR("udp handle:%p, fd:%d Error: %d\n",pClient->udp_hdl, nfct_fd(pClient->udp_hdl), ret); + return; + } + } + + return; +} + +void IPACM_ConntrackClient::UpdateTCPFilters(void *param, bool isWan) +{ + static bool isIgnore = false; + int ret = 0; + IPACM_ConntrackClient *pClient = NULL; + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to retrieve conntrack client instance\n"); + return; + } + + if(pClient->tcp_filter == NULL) + return; + + if(!isWan) + { + IPA_Conntrack_Filters_Ignore_Local_Iface(pClient->tcp_filter, + (ipacm_event_iface_up *)param); + + if(!isIgnore) + { + IPA_Conntrack_Filters_Ignore_Bridge_Addrs(pClient->udp_filter); + IPA_Conntrack_Filters_Ignore_Local_Addrs(pClient->udp_filter); + isIgnore = true; + } + } + + /* Attach the filter to tcp handle */ + if(pClient->tcp_hdl != NULL) + { + IPACMDBG("attaching the filter to tcp handle\n"); + ret = nfct_filter_attach(nfct_fd(pClient->tcp_hdl), pClient->tcp_filter); + if(ret == -1) + { + PERROR("unable to attach the filter to tcp handle\n"); + IPACMERR("tcp handle:%p, fd:%d Error: %d\n",pClient->tcp_hdl, nfct_fd(pClient->tcp_hdl), ret); + return; + } + } + + return; +} + diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp new file mode 100644 index 0000000..38ab7da --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp @@ -0,0 +1,1200 @@ +/* +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 +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 "IPACM_ConntrackListener.h" +#include "IPACM_ConntrackClient.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Iface.h" +#include "IPACM_Wan.h" + +IPACM_ConntrackListener::IPACM_ConntrackListener() +{ + IPACMDBG("\n"); + + isNatThreadStart = false; + isCTReg = false; + WanUp = false; + nat_inst = NatApp::GetInstance(); + + NatIfaceCnt = 0; + StaClntCnt = 0; + pNatIfaces = 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)); + memset(sta_clnt_ipv4_addr, 0, sizeof(sta_clnt_ipv4_addr)); + + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, this); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, this); + IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE, this); + 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(); +#endif +} + +void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt, + void *data) +{ + ipacm_event_iface_up *wan_down = NULL; + + if(data == NULL) + { + IPACMERR("Invalid Data\n"); + return; + } + + switch(evt) + { + case IPA_PROCESS_CT_MESSAGE: + IPACMDBG("Received IPA_PROCESS_CT_MESSAGE event\n"); + ProcessCTMessage(data); + break; + +#ifdef CT_OPT + case IPA_PROCESS_CT_MESSAGE_V6: + IPACMDBG("Received IPA_PROCESS_CT_MESSAGE_V6 event\n"); + ProcessCTV6Message(data); + break; +#endif + + case IPA_HANDLE_WAN_UP: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); + CreateConnTrackThreads(); + if(!isWanUp()) + { + TriggerWANUp(data); + } + break; + + case IPA_HANDLE_WAN_DOWN: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n"); + wan_down = (ipacm_event_iface_up *)data; + if(isWanUp()) + { + TriggerWANDown(wan_down->ipv4_addr); + } + break; + + /* if wlan or lan comes up after wan interface, modify + tcp/udp filters to ignore local wlan or lan connections */ + case IPA_HANDLE_WLAN_UP: + case IPA_HANDLE_LAN_UP: + 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); + 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; + } +} + +int IPACM_ConntrackListener::CheckNatIface( + ipacm_event_data_all *data, bool *NatIface) +{ + int fd = 0, len = 0, cnt, i, j; + struct ifreq ifr; + *NatIface = false; + + if (data->ipv4_addr == 0 || data->iptype != IPA_IP_v4) + { + IPACMDBG("Ignoring\n"); + return IPACM_FAILURE; + } + + IPACMDBG("Received interface index %d with ip type: %d", data->if_index, data->iptype); + iptodot(" and ipv4 address", data->ipv4_addr); + + if (pConfig == NULL) + { + pConfig = IPACM_Config::GetInstance(); + if (pConfig == NULL) + { + IPACMERR("Unable to get Config instance\n"); + return IPACM_FAILURE; + } + } + + cnt = pConfig->GetNatIfacesCnt(); + NatIfaceCnt = cnt; + IPACMDBG("Total Nat ifaces: %d\n", NatIfaceCnt); + 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 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) + { + PERROR("get interface name socket create failed"); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + ifr.ifr_ifindex = data->if_index; + if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) + { + PERROR("call_ioctl_on_dev: ioctl failed:"); + close(fd); + return IPACM_FAILURE; + } + close(fd); + + for (i = 0; i < NatIfaceCnt; i++) + { + if (strncmp(ifr.ifr_name, + pNatIfaces[i].iface_name, + sizeof(pNatIfaces[i].iface_name)) == 0) + { + IPACMDBG_H("Nat iface (%s), entry (%d), dont cache", + pNatIfaces[i].iface_name, j); + iptodot("with ipv4 address: ", nat_iface_ipv4_addr[j]); + *NatIface = true; + return IPACM_SUCCESS; + } + } + + 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) + { + 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; + } + } + } + } + else + { + /* for delete operation */ + for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++) + { + if (nonnat_iface_ipv4_addr[cnt] == data->ipv4_addr) + { + 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; + } + } + + } + + 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 (j = 0; j < MAX_IFACE_ADDRESS; j++) + { + /* 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) + { + 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) +{ + int cnt; + + if(ipv4_addr == 0) + { + IPACMDBG("Ignoring\n"); + return; + } + + iptodot("HandleNeighIpAddrDelEvt(): Received ip addr", ipv4_addr); + for(cnt = 0; cntFlushTempEntries(ipv4_addr, false); + nat_inst->DelEntriesOnClntDiscon(ipv4_addr); + } + } + + return; +} + +void IPACM_ConntrackListener::TriggerWANUp(void *in_param) +{ + ipacm_event_iface_up *wanup_data = (ipacm_event_iface_up *)in_param; + + 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) + { + IPACMERR("Invalid ipv4 address,ignoring IPA_HANDLE_WAN_UP event\n"); + return; + } + + WanUp = true; + isStaMode = wanup_data->is_sta; + IPACMDBG("isStaMode: %d\n", isStaMode); + + wan_ipaddr = wanup_data->ipv4_addr; + memcpy(wan_ifname, wanup_data->ifname, sizeof(wan_ifname)); + + if(nat_inst != NULL) + { + nat_inst->AddTable(wanup_data->ipv4_addr); + } + + IPACMDBG("creating nat threads\n"); + CreateNatThreads(); +} + +int IPACM_ConntrackListener::CreateConnTrackThreads(void) +{ + int ret; + pthread_t tcp_thread = 0, udp_thread = 0; + + 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; + } + + IPACMDBG("created TCP conntrack event listner thread\n"); + if(pthread_setname_np(tcp_thread, "tcp ct listener") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + if(!udp_thread) + { + 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"); + if(pthread_setname_np(udp_thread, "udp ct listener") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + isCTReg = true; + } + + return 0; + +error: + return -1; +} +int IPACM_ConntrackListener::CreateNatThreads(void) +{ + int ret; + pthread_t udpcto_thread = 0; + + if(isNatThreadStart == false) + { + if(!udpcto_thread) + { + 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"); + if(pthread_setname_np(udpcto_thread, "udp conn timeout") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + isNatThreadStart = true; + } + return 0; + +error: + return -1; +} + +void IPACM_ConntrackListener::TriggerWANDown(uint32_t wan_addr) +{ + 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)); + + WanUp = false; + + if(nat_inst != NULL) + { + nat_inst->DeleteTable(wan_addr); + } +} + + +void ParseCTMessage(struct nf_conntrack *ct) +{ + uint32_t status, timeout; + IPACMDBG("Printing conntrack parameters\n"); + + iptodot("ATTR_IPV4_SRC = ATTR_ORIG_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC)); + iptodot("ATTR_IPV4_DST = ATTR_ORIG_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST)); + IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); + IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); + + iptodot("ATTR_REPL_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC)); + iptodot("ATTR_REPL_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST)); + IPACMDBG("ATTR_REPL_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC)); + IPACMDBG("ATTR_REPL_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)); + + iptodot("ATTR_SNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_SNAT_IPV4)); + iptodot("ATTR_DNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_DNAT_IPV4)); + IPACMDBG("ATTR_SNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_SNAT_PORT)); + IPACMDBG("ATTR_DNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_DNAT_PORT)); + + IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK)); + IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE)); + IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID)); + + status = nfct_get_attr_u32(ct, ATTR_STATUS); + IPACMDBG("ATTR_STATUS: 0x%x\n", status); + + timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT); + IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout); + + if(IPS_SRC_NAT & status) + { + IPACMDBG("IPS_SRC_NAT set\n"); + } + + if(IPS_DST_NAT & status) + { + IPACMDBG("IPS_DST_NAT set\n"); + } + + if(IPS_SRC_NAT_DONE & status) + { + IPACMDBG("IPS_SRC_NAT_DONE set\n"); + } + + if(IPS_DST_NAT_DONE & status) + { + IPACMDBG(" IPS_DST_NAT_DONE set\n"); + } + + IPACMDBG("\n"); + return; +} + +void ParseCTV6Message(struct nf_conntrack *ct) +{ + uint32_t status, timeout; + struct nfct_attr_grp_ipv6 orig_params; + uint8_t l4proto, tcp_flags, tcp_state; + + IPACMDBG("Printing conntrack parameters\n"); + + nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params); + IPACMDBG("Orig src_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.src[0], orig_params.src[1], + orig_params.src[2], orig_params.src[3]); + IPACMDBG("Orig dst_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.dst[0], orig_params.dst[1], + orig_params.dst[2], orig_params.dst[3]); + + IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); + IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); + + IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK)); + IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE)); + IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID)); + + timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT); + IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout); + + status = nfct_get_attr_u32(ct, ATTR_STATUS); + IPACMDBG("ATTR_STATUS: 0x%x\n", status); + + l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); + IPACMDBG("ATTR_ORIG_L4PROTO: 0x%x\n", l4proto); + if(l4proto == IPPROTO_TCP) + { + tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); + IPACMDBG("ATTR_TCP_STATE: 0x%x\n", tcp_state); + + tcp_flags = nfct_get_attr_u8(ct, ATTR_TCP_FLAGS_ORIG); + IPACMDBG("ATTR_TCP_FLAGS_ORIG: 0x%x\n", tcp_flags); + } + + IPACMDBG("\n"); + return; +} + +#ifdef CT_OPT +void IPACM_ConntrackListener::ProcessCTV6Message(void *param) +{ + ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param; + u_int8_t l4proto = 0; + uint32_t status = 0; + struct nf_conntrack *ct = evt_data->ct; + +#ifdef IPACM_DEBUG + char buf[1024]; + + /* Process message and generate ioctl call to kernel thread */ + nfct_snprintf(buf, sizeof(buf), evt_data->ct, + evt_data->type, NFCT_O_PLAIN, NFCT_OF_TIME); + IPACMDBG("%s\n", buf); + IPACMDBG("\n"); + ParseCTV6Message(ct); +#endif + + if(p_lan2lan == NULL) + { + IPACMERR("Lan2Lan Instance is null\n"); + goto IGNORE; + } + + status = nfct_get_attr_u32(ct, ATTR_STATUS); + if((IPS_DST_NAT & status) || (IPS_SRC_NAT & status)) + { + IPACMDBG("Either Destination or Source nat flag Set\n"); + goto IGNORE; + } + + l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); + if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto) + { + IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto); + goto IGNORE; + } + + IPACMDBG("Neither Destination nor Source nat flag Set\n"); + struct nfct_attr_grp_ipv6 orig_params; + nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params); + + ipacm_event_connection lan2lan_conn; + lan2lan_conn.iptype = IPA_IP_v6; + memcpy(lan2lan_conn.src_ipv6_addr, orig_params.src, + sizeof(lan2lan_conn.src_ipv6_addr)); + IPACMDBG("Before convert, src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1], + lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]); + for(int cnt=0; cnt<4; cnt++) + { + lan2lan_conn.src_ipv6_addr[cnt] = ntohl(lan2lan_conn.src_ipv6_addr[cnt]); + } + IPACMDBG("After convert src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1], + lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]); + + memcpy(lan2lan_conn.dst_ipv6_addr, orig_params.dst, + sizeof(lan2lan_conn.dst_ipv6_addr)); + IPACMDBG("Before convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1], + lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]); + for(int cnt=0; cnt<4; cnt++) + { + lan2lan_conn.dst_ipv6_addr[cnt] = ntohl(lan2lan_conn.dst_ipv6_addr[cnt]); + } + IPACMDBG("After convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1], + lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]); + + if(((IPPROTO_UDP == l4proto) && (NFCT_T_NEW == evt_data->type)) || + ((IPPROTO_TCP == l4proto) && + (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED)) + ) + { + p_lan2lan->handle_new_connection(&lan2lan_conn); + } + else if((IPPROTO_UDP == l4proto && NFCT_T_DESTROY == evt_data->type) || + (IPPROTO_TCP == l4proto && + nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT)) + { + p_lan2lan->handle_del_connection(&lan2lan_conn); + } + +IGNORE: + /* Cleanup item that was allocated during the original CT callback */ + nfct_destroy(ct); + return; +} +#endif + +void IPACM_ConntrackListener::ProcessCTMessage(void *param) +{ + ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param; + u_int8_t l4proto = 0; + +#ifdef IPACM_DEBUG + char buf[1024]; + unsigned int out_flags; + + /* Process message and generate ioctl call to kernel thread */ + 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_H("%s\n", buf); + + ParseCTMessage(evt_data->ct); +#endif + + l4proto = nfct_get_attr_u8(evt_data->ct, ATTR_ORIG_L4PROTO); + if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto) + { + IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto); + } + else + { + ProcessTCPorUDPMsg(evt_data->ct, evt_data->type, l4proto); + } + + /* Cleanup item that was allocated during the original CT callback */ + nfct_destroy(evt_data->ct); + 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( + struct nf_conntrack *ct, + enum nf_conntrack_msg_type type, + u_int8_t l4proto) +{ + nat_table_entry rule; + uint32_t status = 0; + uint32_t orig_src_ip, orig_dst_ip; + bool isAdd = false; + + 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); + + /* Retrieve Protocol */ + rule.protocol = nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO); + + if(IPS_DST_NAT & status) + { + status = IPS_DST_NAT; + } + else if(IPS_SRC_NAT & status) + { + status = IPS_SRC_NAT; + } + else + { + IPACMDBG("Neither Destination nor Source nat flag Set\n"); + orig_src_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); + orig_src_ip = ntohl(orig_src_ip); + if(orig_src_ip == 0) + { + IPACMERR("unable to retrieve orig src ip address\n"); + return; + } + + orig_dst_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST); + orig_dst_ip = ntohl(orig_dst_ip); + if(orig_dst_ip == 0) + { + IPACMERR("unable to retrieve orig dst ip address\n"); + 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; + } + 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); + +#ifdef CT_OPT + HandleLan2Lan(ct, type, &rule); +#endif + return; + } + } + + if(IPS_DST_NAT == status || IPS_SRC_NAT == status) + { + PopulateTCPorUDPEntry(ct, status, &rule); + rule.public_ip = wan_ipaddr; + } + else + { + IPACMDBG("Neither source Nor destination nat\n"); + goto IGNORE; + } + + if (rule.private_ip != wan_ipaddr) + { + isAdd = AddIface(&rule, &nat_entry.isTempEntry); + if (!isAdd) + { + goto IGNORE; + } + } + else + { + 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; + } + + CheckSTAClient(&rule, &nat_entry.isTempEntry); + nat_entry.rule = &rule; + AddORDeleteNatEntry(&nat_entry); + return; + +IGNORE: + 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("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_H("Received STA client 0x%x\n", clnt_ip_addr); + + if(StaClntCnt >= MAX_STA_CLNT_IFACES) + { + IPACMDBG("Max STA client reached, ignore 0x%x\n", clnt_ip_addr); + return; + } + + for(cnt=0; cntFlushTempEntries(clnt_ip_addr, true); + return; +} + +void IPACM_ConntrackListener::HandleSTAClientDelEvt(uint32_t clnt_ip_addr) +{ + int cnt; + IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr); + + for(cnt=0; cntDelEntriesOnSTAClntDiscon(clnt_ip_addr); + StaClntCnt--; + IPACMDBG("STA client cnt %d\n", StaClntCnt); + break; + } + } + + nat_inst->FlushTempEntries(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 new file mode 100644 index 0000000..f0bdd99 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp @@ -0,0 +1,969 @@ +/* +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 +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 "IPACM_Conntrack_NATApp.h" +#include "IPACM_ConntrackClient.h" + +#define INVALID_IP_ADDR 0x0 + +/* NatApp class Implementation */ +NatApp *NatApp::pInstance = NULL; +NatApp::NatApp() +{ + max_entries = 0; + cache = NULL; + + nat_table_hdl = 0; + pub_ip_addr = 0; + + curCnt = 0; + + pALGPorts = NULL; + nALGPort = 0; + + ct = NULL; + ct_hdl = NULL; + + memset(temp, 0, sizeof(temp)); +} + +int NatApp::Init(void) +{ + IPACM_Config *pConfig; + int size = 0; + + pConfig = IPACM_Config::GetInstance(); + if(pConfig == NULL) + { + IPACMERR("Unable to get Config instance\n"); + return -1; + } + + max_entries = pConfig->GetNatMaxEntries(); + + size = (sizeof(nat_table_entry) * max_entries); + cache = (nat_table_entry *)malloc(size); + if(cache == NULL) + { + IPACMERR("Unable to allocate memory for cache\n"); + goto fail; + } + IPACMDBG("Allocated %d bytes for config manager nat cache\n", size); + memset(cache, 0, size); + + nALGPort = pConfig->GetAlgPortCnt(); + if(nALGPort > 0) + { + 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; + } + + IPACMDBG("Printing %d alg ports information\n", nALGPort); + for(int cnt=0; cntInit()) + { + delete pInstance; + return NULL; + } + } + + return pInstance; +} + +/* NAT APP related object function definitions */ + +int NatApp::AddTable(uint32_t pub_ip) +{ + int ret; + int cnt = 0; + ipa_nat_ipv4_rule nat_rule; + IPACMDBG_H("%s() %d\n", __FUNCTION__, __LINE__); + + /* Not reset the cache wait it timeout by destroy event */ +#if 0 + if (pub_ip != pub_ip_addr_pre) + { + IPACMDBG("Reset the cache because NAT-ipv4 different\n"); + memset(cache, 0, sizeof(nat_table_entry) * max_entries); + curCnt = 0; + } +#endif + ret = ipa_nat_add_ipv4_tbl(pub_ip, max_entries, &nat_table_hdl); + if(ret) + { + IPACMERR("unable to create nat table Error:%d\n", ret); + return ret; + } + + /* Add back the cached NAT-entry */ + if (pub_ip == pub_ip_addr_pre) + { + IPACMDBG("Restore the cache to ipa NAT-table\n"); + for(cnt = 0; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip !=0) + { + memset(&nat_rule, 0 , sizeof(nat_rule)); + nat_rule.private_ip = cache[cnt].private_ip; + nat_rule.target_ip = cache[cnt].target_ip; + nat_rule.target_port = cache[cnt].target_port; + nat_rule.private_port = cache[cnt].private_port; + nat_rule.public_port = cache[cnt].public_port; + nat_rule.protocol = cache[cnt].protocol; + + if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to add the rule delete from cache\n"); + memset(&cache[cnt], 0, sizeof(cache[cnt])); + curCnt--; + continue; + } + cache[cnt].enabled = true; + + IPACMDBG("On wan-iface reset added below rule successfully\n"); + iptodot("Private IP", nat_rule.private_ip); + iptodot("Target IP", nat_rule.target_ip); + IPACMDBG("Private Port:%d \t Target Port: %d\t", nat_rule.private_port, nat_rule.target_port); + IPACMDBG("Public Port:%d\n", nat_rule.public_port); + IPACMDBG("protocol: %d\n", nat_rule.protocol); + } + } + } + + pub_ip_addr = pub_ip; + return 0; +} + +void NatApp::Reset() +{ + int cnt = 0; + + nat_table_hdl = 0; + pub_ip_addr = 0; + /* NAT tbl deleted, reset enabled bit */ + for(cnt = 0; cnt < max_entries; cnt++) + { + cache[cnt].enabled = false; + } +} + +int NatApp::DeleteTable(uint32_t pub_ip) +{ + int ret; + IPACMDBG_H("%s() %d\n", __FUNCTION__, __LINE__); + + CHK_TBL_HDL(); + + if(pub_ip_addr != pub_ip) + { + IPACMDBG("Public ip address is not matching\n"); + IPACMERR("unable to delete the nat table\n"); + return -1; + } + + ret = ipa_nat_del_ipv4_tbl(nat_table_hdl); + if(ret) + { + IPACMERR("unable to delete nat table Error: %d\n", ret);; + return ret; + } + + pub_ip_addr_pre = pub_ip_addr; + Reset(); + return 0; +} + +/* Check for duplicate entries */ +bool NatApp::ChkForDup(const nat_table_entry *rule) +{ + int cnt = 0; + IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); + + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == rule->private_ip && + cache[cnt].target_ip == rule->target_ip && + cache[cnt].private_port == rule->private_port && + cache[cnt].target_port == rule->target_port && + cache[cnt].protocol == rule->protocol) + { + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"Duplicate Rule\n"); + return true; + } + } + + return false; +} + +/* Delete the entry from Nat table on connection close */ +int NatApp::DeleteEntry(const nat_table_entry *rule) +{ + int cnt = 0; + IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); + + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"for deletion\n"); + + + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == rule->private_ip && + cache[cnt].target_ip == rule->target_ip && + cache[cnt].private_port == rule->private_port && + cache[cnt].target_port == rule->target_port && + cache[cnt].protocol == rule->protocol) + { + + if(cache[cnt].enabled == true) + { + if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0) + { + IPACMERR("%s() %d deletion failed\n", __FUNCTION__, __LINE__); + } + + IPACMDBG_H("Deleted Nat entry(%d) Successfully\n", cnt); + } + else + { + IPACMDBG_H("Deleted Nat entry(%d) only from cache\n", cnt); + } + + memset(&cache[cnt], 0, sizeof(cache[cnt])); + curCnt--; + break; + } + } + + return 0; +} + +/* 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(); + 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, ignore\n"); + return -1; + } + + if(rule->private_ip == 0 || + rule->target_ip == 0 || + rule->private_port == 0 || + rule->target_port == 0 || + rule->protocol == 0) + { + IPACMERR("Invalid Connection, ignoring it\n"); + return 0; + } + + if(!ChkForDup(rule)) + { + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == 0 && + cache[cnt].target_ip == 0 && + cache[cnt].private_port == 0 && + cache[cnt].target_port == 0 && + cache[cnt].protocol == 0) + { + break; + } + } + + if(max_entries == cnt) + { + IPACMERR("Error: Unable to add, reached maximum rules\n"); + return -1; + } + else + { + nat_rule.private_ip = rule->private_ip; + nat_rule.target_ip = rule->target_ip; + nat_rule.target_port = rule->target_port; + nat_rule.private_port = rule->private_port; + nat_rule.public_port = rule->public_port; + nat_rule.protocol = rule->protocol; + + if(isPwrSaveIf(rule->private_ip) || + isPwrSaveIf(rule->target_ip)) + { + IPACMDBG("Device is Power Save mode: Dont insert into nat table but cache\n"); + cache[cnt].enabled = false; + cache[cnt].rule_hdl = 0; + } + else + { + + if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to add the rule\n"); + return -1; + } + + cache[cnt].enabled = true; + } + + cache[cnt].private_ip = rule->private_ip; + cache[cnt].target_ip = rule->target_ip; + cache[cnt].target_port = rule->target_port; + cache[cnt].private_port = rule->private_port; + cache[cnt].protocol = rule->protocol; + cache[cnt].timestamp = 0; + cache[cnt].public_port = rule->public_port; + cache[cnt].dst_nat = rule->dst_nat; + curCnt++; + } + + } + else + { + IPACMERR("Duplicate rule. Ignore it\n"); + return -1; + } + + if(cache[cnt].enabled == true) + { + IPACMDBG_H("Added rule(%d) successfully\n", cnt); + } + else + { + IPACMDBG_H("Cached rule(%d) successfully\n", cnt); + } + + return 0; +} + +void NatApp::UpdateCTUdpTs(nat_table_entry *rule, uint32_t new_ts) +{ + int ret; + + 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); + + if(!ct_hdl) + { + ct_hdl = nfct_open(CONNTRACK, 0); + if(!ct_hdl) + { + PERROR("nfct_open"); + return; + } + } + + if(!ct) + { + ct = nfct_new(); + if(!ct) + { + PERROR("nfct_new"); + return; + } + } + + nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); + if(rule->protocol == IPPROTO_UDP) + { + nfct_set_attr_u8(ct, ATTR_L4PROTO, rule->protocol); + nfct_set_attr_u32(ct, ATTR_TIMEOUT, udp_timeout); + } + else + { + nfct_set_attr_u8(ct, ATTR_L4PROTO, rule->protocol); + nfct_set_attr_u32(ct, ATTR_TIMEOUT, tcp_timeout); + } + + if(rule->dst_nat == false) + { + nfct_set_attr_u32(ct, ATTR_IPV4_SRC, htonl(rule->private_ip)); + nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(rule->private_port)); + + nfct_set_attr_u32(ct, ATTR_IPV4_DST, htonl(rule->target_ip)); + nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(rule->target_port)); + + IPACMDBG("dst nat is not set\n"); + } + else + { + nfct_set_attr_u32(ct, ATTR_IPV4_SRC, htonl(rule->target_ip)); + nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(rule->target_port)); + + nfct_set_attr_u32(ct, ATTR_IPV4_DST, htonl(pub_ip_addr)); + nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(rule->public_port)); + + IPACMDBG("dst nat is set\n"); + } + + iptodot("Source IP:", nfct_get_attr_u32(ct, ATTR_IPV4_SRC)); + iptodot("Destination IP:", nfct_get_attr_u32(ct, ATTR_IPV4_DST)); + IPACMDBG("Source Port: %d, Destination Port: %d\n", + nfct_get_attr_u16(ct, ATTR_PORT_SRC), nfct_get_attr_u16(ct, ATTR_PORT_DST)); + + IPACMDBG("updating %d connection with time: %d\n", + rule->protocol, nfct_get_attr_u32(ct, ATTR_TIMEOUT)); + + ret = nfct_query(ct_hdl, NFCT_Q_UPDATE, ct); + if(ret == -1) + { + IPACMERR("unable to update time stamp"); + DeleteEntry(rule); + } + else + { + rule->timestamp = new_ts; + IPACMDBG("Updated time stamp successfully\n"); + } + + return; +} + +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 && + (cache[cnt].private_ip != cache[cnt].public_ip)) + { + IPACMDBG("\n"); + if(ipa_nat_query_timestamp(nat_table_hdl, cache[cnt].rule_hdl, &ts) < 0) + { + IPACMERR("unable to retrieve timeout for rule hanle: %d\n", cache[cnt].rule_hdl); + continue; + } + + if(cache[cnt].timestamp == ts) + { + IPACMDBG("No Change in Time Stamp: cahce:%d, ipahw:%d\n", + cache[cnt].timestamp, ts); + continue; + } + + if (read_to == false) { + read_to = true; + Read_TcpUdp_Timeout(); + } + + UpdateCTUdpTs(&cache[cnt], ts); + } /* end of outer if */ + + } /* end of for loop */ + +} + +bool NatApp::isAlgPort(uint8_t proto, uint16_t port) +{ + int cnt; + for(cnt = 0; cnt < nALGPort; cnt++) + { + if(proto == pALGPorts[cnt].protocol && + port == pALGPorts[cnt].port) + { + return true; + } + } + + return false; +} + +bool NatApp::isPwrSaveIf(uint32_t ip_addr) +{ + int cnt; + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(0 != PwrSaveIfs[cnt] && + ip_addr == PwrSaveIfs[cnt]) + { + return true; + } + } + + return false; +} + +int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip) +{ + int cnt; + IPACMDBG_H("Received IP address: 0x%x\n", client_lan_ip); + + if(client_lan_ip == INVALID_IP_ADDR) + { + IPACMERR("Invalid ip address received\n"); + return -1; + } + + /* check for duplicate events */ + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == client_lan_ip) + { + IPACMDBG("The client 0x%x is already in power save\n", client_lan_ip); + return 0; + } + } + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == 0) + { + PwrSaveIfs[cnt] = client_lan_ip; + break; + } + } + + for(cnt = 0; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == client_lan_ip && + cache[cnt].enabled == true) + { + if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to delete the rule\n"); + continue; + } + + cache[cnt].enabled = false; + cache[cnt].rule_hdl = 0; + } + } + + return 0; +} + +int NatApp::ResetPwrSaveIf(uint32_t client_lan_ip) +{ + int cnt; + ipa_nat_ipv4_rule nat_rule; + + IPACMDBG_H("Received ip address: 0x%x\n", client_lan_ip); + + if(client_lan_ip == INVALID_IP_ADDR) + { + IPACMERR("Invalid ip address received\n"); + return -1; + } + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == client_lan_ip) + { + PwrSaveIfs[cnt] = 0; + break; + } + } + + for(cnt = 0; cnt < max_entries; cnt++) + { + IPACMDBG("cache (%d): enable %d, ip 0x%x\n", cnt, cache[cnt].enabled, cache[cnt].private_ip); + + if(cache[cnt].private_ip == client_lan_ip && + cache[cnt].enabled == false) + { + memset(&nat_rule, 0 , sizeof(nat_rule)); + nat_rule.private_ip = cache[cnt].private_ip; + nat_rule.target_ip = cache[cnt].target_ip; + nat_rule.target_port = cache[cnt].target_port; + nat_rule.private_port = cache[cnt].private_port; + nat_rule.public_port = cache[cnt].public_port; + nat_rule.protocol = cache[cnt].protocol; + + if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to add the rule delete from cache\n"); + memset(&cache[cnt], 0, sizeof(cache[cnt])); + curCnt--; + continue; + } + cache[cnt].enabled = true; + + IPACMDBG("On power reset added below rule successfully\n"); + iptodot("Private IP", nat_rule.private_ip); + iptodot("Target IP", nat_rule.target_ip); + IPACMDBG("Private Port:%d \t Target Port: %d\t", nat_rule.private_port, nat_rule.target_port); + IPACMDBG("Public Port:%d\n", nat_rule.public_port); + IPACMDBG("protocol: %d\n", nat_rule.protocol); + + } + } + + return -1; +} + +uint32_t NatApp::GetTableHdl(uint32_t in_ip_addr) +{ + if(in_ip_addr == pub_ip_addr) + { + return nat_table_hdl; + } + + return -1; +} + +void NatApp::AddTempEntry(const nat_table_entry *new_entry) +{ + int cnt; + + 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\n", entry->private_port, entry->target_port); + IPACMDBG("protocol: %d\n", entry->protocol); + + for(cnt=0; cntprivate_ip && + temp[cnt].target_ip == entry->target_ip && + temp[cnt].private_port == entry->private_port && + temp[cnt].target_port == entry->target_port && + temp[cnt].protocol == entry->protocol) + { + memset(&temp[cnt], 0, sizeof(nat_table_entry)); + IPACMDBG("Delete Temp Entry\n"); + return; + } + } + + IPACMDBG("No Such Temp Entry exists\n"); + return; +} + +void NatApp::FlushTempEntries(uint32_t ip_addr, bool isAdd, + bool isDummy) +{ + int cnt; + int ret; + + IPACMDBG_H("Received below with isAdd:%d ", isAdd); + iptodot("IP Address: ", ip_addr); + + for(cnt=0; cntprivate_ip == 0 || + rule->target_ip == 0 || + rule->private_port == 0 || + rule->target_port == 0 || + rule->protocol == 0) + { + IPACMERR("Invalid Connection, ignoring it\n"); + return; + } + + if(!ChkForDup(rule)) + { + for(cnt=0; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == 0 && + cache[cnt].target_ip == 0 && + cache[cnt].private_port == 0 && + cache[cnt].target_port == 0 && + cache[cnt].protocol == 0) + { + break; + } + } + + if(max_entries == cnt) + { + IPACMERR("Error: Unable to add, reached maximum rules\n"); + return; + } + else + { + cache[cnt].enabled = false; + cache[cnt].rule_hdl = 0; + cache[cnt].private_ip = rule->private_ip; + cache[cnt].target_ip = rule->target_ip; + cache[cnt].target_port = rule->target_port; + cache[cnt].private_port = rule->private_port; + 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++; + } + + } + else + { + IPACMERR("Duplicate rule. Ignore it\n"); + return; + } + + 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 new file mode 100644 index 0000000..edb5901 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_EvtDispatcher.cpp @@ -0,0 +1,214 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_EvtDispatcher.cpp + + @brief + This file implements the IPAM event dispatcher functionality + + @Author + +*/ +#include +#include +#include +#include +#include "IPACM_CmdQueue.h" +#include "IPACM_Defs.h" + + +extern pthread_mutex_t mutex; +extern pthread_cond_t cond_var; + +cmd_evts *IPACM_EvtDispatcher::head = NULL; +extern uint32_t ipacm_event_stats[IPACM_EVENT_MAX]; + +int IPACM_EvtDispatcher::PostEvt +( + ipacm_cmd_q_data *data +) +{ + Message *item = NULL; + MessageQueue *MsgQueue = NULL; + + 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"); + return IPACM_FAILURE; + } + + item = new Message(); + if(item == NULL) + { + IPACMERR("unable to create new message item\n"); + return IPACM_FAILURE; + } + + item->evt.callback_ptr = IPACM_EvtDispatcher::ProcessEvt; + memcpy(&item->evt.data, data, sizeof(ipacm_cmd_q_data)); + + if(pthread_mutex_lock(&mutex) != 0) + { + IPACMERR("unable to lock the mutex\n"); + return IPACM_FAILURE; + } + + IPACMDBG("Enqueing item\n"); + MsgQueue->enqueue(item); + IPACMDBG("Enqueued item %p\n", item); + + if(pthread_cond_signal(&cond_var) != 0) + { + IPACMDBG("unable to lock the mutex\n"); + /* Release the mutex before you return failure */ + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return IPACM_FAILURE; + } + return IPACM_FAILURE; + } + + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return IPACM_FAILURE; + } + + return IPACM_SUCCESS; +} + +void IPACM_EvtDispatcher::ProcessEvt(ipacm_cmd_q_data *data) +{ + + cmd_evts *tmp = head, tmp1; + + if(head == NULL) + { + IPACMDBG("Queue is empty\n"); + } + + while(tmp != NULL) + { + memcpy(&tmp1, tmp, sizeof(tmp1)); + if(data->event == tmp1.event) + { + ipacm_event_stats[data->event]++; + tmp1.obj->event_callback(data->event, data->evt_data); + IPACMDBG(" Find matched registered events\n"); + } + tmp = tmp1.next; + } + + IPACMDBG(" Finished process events\n"); + + if(data->evt_data != NULL) + { + IPACMDBG("free the event:%d data: %p\n", data->event, data->evt_data); + free(data->evt_data); + } + return; +} + +int IPACM_EvtDispatcher::registr(ipa_cm_event_id event, IPACM_Listener *obj) +{ + cmd_evts *tmp = head,*nw; + + nw = (cmd_evts *)malloc(sizeof(cmd_evts)); + if(nw != NULL) + { + nw->event = event; + nw->obj = obj; + nw->next = NULL; + } + else + { + return IPACM_FAILURE; + } + + if(head == NULL) + { + head = nw; + } + else + { + while(tmp->next) + { + tmp = tmp->next; + } + tmp->next = nw; + } + return IPACM_SUCCESS; +} + + +int IPACM_EvtDispatcher::deregistr(IPACM_Listener *param) +{ + cmd_evts *tmp = head,*tmp1,*prev = head; + + while(tmp != NULL) + { + if(tmp->obj == param) + { + tmp1 = tmp; + if(tmp == head) + { + head = head->next; + } + else if(tmp->next == NULL) + { + prev->next = NULL; + } + else + { + prev->next = tmp->next; + } + + tmp = tmp->next; + free(tmp1); + } + else + { + prev = tmp; + tmp = tmp->next; + } + } + return IPACM_SUCCESS; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp new file mode 100644 index 0000000..22eb19c --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp @@ -0,0 +1,536 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_Filtering.cpp + + @brief + This file implements the IPACM filtering functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include + +#include "IPACM_Filtering.h" +#include +#include "IPACM_Defs.h" + + +const char *IPACM_Filtering::DEVICE_NAME = "/dev/ipa"; + +IPACM_Filtering::IPACM_Filtering() +{ + fd = open(DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + } +} + +IPACM_Filtering::~IPACM_Filtering() +{ + close(fd); +} + +bool IPACM_Filtering::DeviceNodeIsOpened() +{ + return fd; +} + +bool IPACM_Filtering::AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTable) +{ + 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 and global value: %d\n", ruleTable->ep, ruleTable->global); + 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); + } + + retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE, ruleTable); + if (retval != 0) + { + IPACMERR("Failed adding Filtering rule %p\n", ruleTable); + PERROR("unable to add filter rule:"); + + for (int cnt = 0; cnt < ruleTable->num_rules; cnt++) + { + if (ruleTable->rules[cnt].status != 0) + { + IPACMERR("Adding Filter rule:%d failed with status:%d\n", + cnt, ruleTable->rules[cnt].status); + } + } + return false; + } + + 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); + } + } + + IPACMDBG("Added Filtering rule %p\n", ruleTable); + 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; + + retval = ioctl(fd, IPA_IOC_DEL_FLT_RULE, ruleTable); + if (retval != 0) + { + IPACMERR("Failed deleting Filtering rule %p\n", ruleTable); + return false; + } + + IPACMDBG("Deleted Filtering rule %p\n", ruleTable); + return true; +} + +bool IPACM_Filtering::Commit(enum ipa_ip_type ip) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_COMMIT_FLT, ip); + if (retval != 0) + { + IPACMERR("failed committing Filtering rules.\n"); + return false; + } + + IPACMDBG("Committed Filtering rules to IPA HW.\n"); + return true; +} + +bool IPACM_Filtering::Reset(enum ipa_ip_type ip) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_RESET_FLT, ip); + retval |= ioctl(fd, IPA_IOC_COMMIT_FLT, ip); + if (retval) + { + IPACMERR("failed resetting Filtering block.\n"); + return false; + } + + IPACMDBG("Reset command issued to IPA Filtering block.\n"); + return true; +} + +bool IPACM_Filtering::DeleteFilteringHdls +( + uint32_t *flt_rule_hdls, + ipa_ip_type ip, + uint8_t num_rules +) +{ + struct ipa_ioc_del_flt_rule *flt_rule; + bool res = true; + int len = 0, cnt = 0; + const uint8_t UNIT_RULES = 1; + + len = (sizeof(struct ipa_ioc_del_flt_rule)) + (UNIT_RULES * sizeof(struct ipa_flt_rule_del)); + flt_rule = (struct ipa_ioc_del_flt_rule *)malloc(len); + if (flt_rule == NULL) + { + IPACMERR("unable to allocate memory for del filter rule\n"); + return false; + } + + for (cnt = 0; cnt < num_rules; cnt++) + { + memset(flt_rule, 0, len); + flt_rule->commit = 1; + flt_rule->num_hdls = UNIT_RULES; + flt_rule->ip = ip; + + if (flt_rule_hdls[cnt] == 0) + { + IPACMERR("invalid filter handle passed, ignoring it: %d\n", cnt) + } + else + { + + flt_rule->hdl[0].status = -1; + flt_rule->hdl[0].hdl = flt_rule_hdls[cnt]; + IPACMDBG("Deleting filter hdl:(0x%x) with ip type: %d\n", flt_rule_hdls[cnt], ip); + + if (DeleteFilteringRule(flt_rule) == false) + { + PERROR("Filter rule deletion failed!\n"); + res = false; + goto fail; + } + else + { + + if (flt_rule->hdl[0].status != 0) + { + IPACMERR("Filter rule hdl 0x%x deletion failed with error:%d\n", + flt_rule->hdl[0].hdl, flt_rule->hdl[0].status); + res = false; + goto fail; + } + } + } + } + +fail: + free(flt_rule); + + return res; +} + +bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *rule_table_v4, struct ipa_ioc_add_flt_rule const * rule_table_v6, uint8_t mux_id) +{ + 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) + { + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + return false; + } + + if(rule_table_v4 != NULL) + { + num_rules += rule_table_v4->num_rules; + IPACMDBG_H("Get %d WAN DL IPv4 filtering rules.\n", rule_table_v4->num_rules); + } + if(rule_table_v6 != NULL) + { + num_rules += rule_table_v6->num_rules; + 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"); + close(fd_wwan_ioctl); + return false; + } + else + { + memset(&qmi_rule_msg, 0, sizeof(qmi_rule_msg)); + + if (num_rules > 0) + { + qmi_rule_msg.filter_spec_list_valid = true; + } + else + { + 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++; + } + else + { + IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos); + } + } + } + + if(rule_table_v6 != NULL) + { + for(cnt = rule_table_v6->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_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); + } + } + } + + ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE, &qmi_rule_msg); + if (ret != 0) + { + IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_msg, ret); + close(fd_wwan_ioctl); + return false; + } + } + /* 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; +} + +bool IPACM_Filtering::SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01* table) +{ + int ret = 0; + int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); + if(fd_wwan_ioctl < 0) + { + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + return false; + } + + ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_INDEX, table); + if (ret != 0) + { + IPACMERR("Failed adding filtering rule index %p with ret %d\n", table, ret); + close(fd_wwan_ioctl); + return false; + } + + IPACMDBG("Added Filtering rule index %p\n", table); + close(fd_wwan_ioctl); + return true; +} + +ipa_filter_action_enum_v01 IPACM_Filtering::GetQmiFilterAction(ipa_flt_action action) +{ + switch(action) + { + case IPA_PASS_TO_ROUTING: + return QMI_IPA_FILTER_ACTION_ROUTING_V01; + + case IPA_PASS_TO_SRC_NAT: + return QMI_IPA_FILTER_ACTION_SRC_NAT_V01; + + case IPA_PASS_TO_DST_NAT: + return QMI_IPA_FILTER_ACTION_DST_NAT_V01; + + case IPA_PASS_TO_EXCEPTION: + return QMI_IPA_FILTER_ACTION_EXCEPTION_V01; + + default: + return IPA_FILTER_ACTION_ENUM_MAX_ENUM_VAL_V01; + } +} + +bool IPACM_Filtering::ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule* ruleTable) +{ + int i, ret = 0; + + IPACMDBG("Printing filtering add attributes\n"); + IPACMDBG("IP type: %d Number of rules: %d commit value: %d\n", ruleTable->ip, ruleTable->num_rules, ruleTable->commit); + + for (i=0; inum_rules; i++) + { + IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", i, ruleTable->rules[i].rule.attrib.attrib_mask); + } + + ret = ioctl(fd, IPA_IOC_MDFY_FLT_RULE, ruleTable); + if (ret != 0) + { + IPACMERR("Failed modifying filtering rule %p\n", ruleTable); + + for (i = 0; i < ruleTable->num_rules; i++) + { + if (ruleTable->rules[i].status != 0) + { + IPACMERR("Modifying filter rule %d failed\n", i); + } + } + return false; + } + + IPACMDBG("Modified filtering rule %p\n", ruleTable); + return true; +} + diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp new file mode 100644 index 0000000..c77c69c --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp @@ -0,0 +1,236 @@ +/* +Copyright (c) 2013, 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 +#include +#include + +#include "IPACM_Header.h" +#include "IPACM_Log.h" + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//All interaction through the driver are made through this inode. +static const char *DEVICE_NAME = "/dev/ipa"; + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +IPACM_Header::IPACM_Header() +{ + m_fd = open(DEVICE_NAME, O_RDWR); + if (-1 == m_fd) + { + IPACMERR("Failed to open %s in IPACM_Header test application constructor.\n", DEVICE_NAME); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +IPACM_Header::~IPACM_Header() +{ + if (-1 != m_fd) + { + close(m_fd); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::DeviceNodeIsOpened() +{ + return (-1 != m_fd); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::AddHeader(struct ipa_ioc_add_hdr *pHeaderTableToAdd) +{ + int nRetVal = 0; + //call the Driver ioctl in order to add header + nRetVal = ioctl(m_fd, IPA_IOC_ADD_HDR, pHeaderTableToAdd); + IPACMDBG("return value: %d\n", nRetVal); + return (-1 != nRetVal); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTableToDelete) +{ + int nRetVal = 0; + //call the Driver ioctl in order to remove header + nRetVal = ioctl(m_fd, IPA_IOC_DEL_HDR, pHeaderTableToDelete); + IPACMDBG("return value: %d\n", nRetVal); + return (-1 != nRetVal); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::Commit() +{ + int nRetVal = 0; + nRetVal = ioctl(m_fd, IPA_IOC_COMMIT_HDR); + IPACMDBG("return value: %d\n", nRetVal); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::Reset() +{ + int nRetVal = 0; + + nRetVal = ioctl(m_fd, IPA_IOC_RESET_HDR); + nRetVal |= ioctl(m_fd, IPA_IOC_COMMIT_HDR); + IPACMDBG("return value: %d\n", nRetVal); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_GET_HDR, pHeaderStruct); + if (retval) + { + IPACMERR("IPA_IOC_GET_HDR ioctl failed, routingTable =0x%p, retval=0x%x.\n", pHeaderStruct, retval); + return false; + } + + IPACMDBG("IPA_IOC_GET_HDR ioctl issued to IPA header insertion block.\n"); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_COPY_HDR, pCopyHeaderStruct); + if (retval) + { + IPACMERR("IPA_IOC_COPY_HDR ioctl failed, retval=0x%x.\n", retval); + return false; + } + + IPACMDBG("IPA_IOC_COPY_HDR ioctl issued to IPA header insertion block.\n"); + return true; +} + +bool IPACM_Header::DeleteHeaderHdl(uint32_t hdr_hdl) +{ + const uint8_t NUM_HDLS = 1; + struct ipa_ioc_del_hdr *pHeaderDescriptor = NULL; + struct ipa_hdr_del *hd_rule_entry; + int len = 0; + bool res = true; + + if (hdr_hdl == 0) + { + IPACMERR("Invalid header handle passed. Ignoring it\n"); + return false; + } + + len = (sizeof(struct ipa_ioc_del_hdr)) + (NUM_HDLS * sizeof(struct ipa_hdr_del)); + pHeaderDescriptor = (struct ipa_ioc_del_hdr *)malloc(len); + if (pHeaderDescriptor == NULL) + { + IPACMERR("Unable to allocate memory for del header\n"); + return false; + } + + memset(pHeaderDescriptor, 0, len); + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdls = NUM_HDLS; + hd_rule_entry = &pHeaderDescriptor->hdl[0]; + + hd_rule_entry->hdl = hdr_hdl; + hd_rule_entry->status = -1; + + IPACMDBG("Deleting Header hdl:(%x)\n", hd_rule_entry->hdl); + if ((false == DeleteHeader(pHeaderDescriptor)) || + (hd_rule_entry->status)) + { + IPACMERR("Header hdl:(%x) deletion failed! status: %d\n", hd_rule_entry->hdl,hd_rule_entry->status); + res = false; + goto fail; + } + + IPACMDBG_H("Deleted Header hdl:(%x) successfully\n", hd_rule_entry->hdl); + +fail: + free(pHeaderDescriptor); + + return res; + +} + +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 == 0); +} + +bool IPACM_Header::DeleteHeaderProcCtx(uint32_t hdl) +{ + int len, ret; + struct ipa_ioc_del_hdr_proc_ctx* pHeaderTable = NULL; + + len = sizeof(struct ipa_ioc_del_hdr_proc_ctx) + sizeof(struct ipa_hdr_proc_ctx_del); + pHeaderTable = (struct ipa_ioc_del_hdr_proc_ctx*)malloc(len); + if(pHeaderTable == NULL) + { + IPACMERR("Failed to allocate buffer.\n"); + return false; + } + memset(pHeaderTable, 0, len); + + pHeaderTable->commit = 1; + pHeaderTable->num_hdls = 1; + 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 == 0); +} + diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp new file mode 100644 index 0000000..84132c9 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp @@ -0,0 +1,995 @@ +/* +Copyright (c) 2013, 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_Iface.cpp + + @brief + This file implements the basis Iface functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ +#include +} + + +const char *IPACM_Iface::DEVICE_NAME = "/dev/ipa"; +IPACM_Routing IPACM_Iface::m_routing; +IPACM_Filtering IPACM_Iface::m_filtering; +IPACM_Header IPACM_Iface::m_header; + +IPACM_Config *IPACM_Iface::ipacmcfg = IPACM_Config::GetInstance(); + +IPACM_Iface::IPACM_Iface(int iface_index) +{ + ip_type = IPACM_IP_NULL; /* initially set invalid */ + num_dft_rt_v6 = 0; + softwarerouting_act = false; + ipa_if_num = iface_index; + ipa_if_cate = IPACM_Iface::ipacmcfg->iface_table[iface_index].if_cat; + + iface_query = NULL; + tx_prop = NULL; + rx_prop = NULL; + + memcpy(dev_name, + IPACM_Iface::ipacmcfg->iface_table[iface_index].iface_name, + sizeof(IPACM_Iface::ipacmcfg->iface_table[iface_index].iface_name)); + + memset(dft_v4fl_rule_hdl, 0, sizeof(dft_v4fl_rule_hdl)); + memset(dft_v6fl_rule_hdl, 0, sizeof(dft_v6fl_rule_hdl)); + + memset(dft_rt_rule_hdl, 0, sizeof(dft_rt_rule_hdl)); + memset(software_routing_fl_rule_hdl, 0, sizeof(software_routing_fl_rule_hdl)); + memset(ipv6_addr, 0, sizeof(ipv6_addr)); + + query_iface_property(); + IPACMDBG_H(" create iface-index(%d) constructor\n", ipa_if_num); + return; +} + +/* software routing enable */ +int IPACM_Iface::handle_software_routing_enable(void) +{ + + int res = IPACM_SUCCESS; + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_add_flt_rule *m_pFilteringTable; + + IPACMDBG("\n"); + if (softwarerouting_act == true) + { + IPACMDBG("already setup software_routing rule for (%s)iface ip-family %d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type); + return IPACM_SUCCESS; + } + + if(rx_prop == NULL) + { + IPACMDBG("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_flt_rule) + + 1 * sizeof(struct ipa_flt_rule_add) + ); + if (!m_pFilteringTable) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->num_rules = (uint8_t)1; + + + /* Configuring Software-Routing Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = false; + 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)); + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* check iface is v4 or v6 or both*/ +// if (ip_type == IPA_IP_MAX) +// { + /* handle v4 */ + m_pFilteringTable->ip = IPA_IP_v4; + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (m_pFilteringTable->rules[0].status) + { + IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status); + res = IPACM_FAILURE; + 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; + + + /* handle v6*/ + m_pFilteringTable->ip = IPA_IP_v6; + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (m_pFilteringTable->rules[0].status) + { + IPACMDBG("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status); + res = IPACM_FAILURE; + 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; + softwarerouting_act = true; +#if 0 + } + else + { + if (ip_type == IPA_IP_v4) + { + m_pFilteringTable->ip = IPA_IP_v4; + } + else + { + m_pFilteringTable->ip = IPA_IP_v6; + } + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (m_pFilteringTable->rules[0].status) + { + IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status); + res = IPACM_FAILURE; + 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) + { + software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + else + { + software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + softwarerouting_act = true; + } +#endif + +fail: + free(m_pFilteringTable); + + return res; +} + +/* software routing disable */ +int IPACM_Iface::handle_software_routing_disable(void) +{ + int res = IPACM_SUCCESS; + ipa_ip_type ip; + uint32_t flt_hdl; + + if (rx_prop == NULL) + { + IPACMDBG("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if (softwarerouting_act == false) + { + IPACMDBG("already delete software_routing rule for (%s)iface ip-family %d\n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type); + return IPACM_SUCCESS; + } + +// if (ip_type == IPA_IP_MAX) +// { + /* ipv4 case */ + if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[0], + IPA_IP_v4, 1) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + 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], + IPA_IP_v6, 1) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + softwarerouting_act = false; +#if 0 + } + else + { + if (ip_type == IPA_IP_v4) + { + ip = IPA_IP_v4; + } + else + { + ip = IPA_IP_v6; + } + + + if (ip_type == IPA_IP_v4) + { + flt_hdl = software_routing_fl_rule_hdl[0]; + } + else + { + flt_hdl = software_routing_fl_rule_hdl[1]; + } + + if (m_filtering.DeleteFilteringHdls(&flt_hdl, ip, 1) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, ip, 1); + softwarerouting_act = false; + } +#endif + +fail: + return res; +} + +/* Query ipa_interface_index by given linux interface_index */ +int IPACM_Iface::iface_ipa_index_query +( + int interface_index +) +{ + int fd; + int link = INVALID_IFACE; + int i = 0; + struct ifreq ifr; + + + if(IPACM_Iface::ipacmcfg->iface_table == NULL) + { + IPACMERR("Iface table in IPACM_Config is not available.\n"); + return link; + } + + /* Search known linux interface-index and map to IPA interface-index*/ + for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++) + { + if (interface_index == IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index) + { + link = i; + IPACMDBG("Interface (%s) found: linux(%d) ipa(%d) \n", + IPACM_Iface::ipacmcfg->iface_table[i].iface_name, + IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index, + link); + return link; + break; + } + } + + /* Search/Configure linux interface-index and map it to IPA interface-index */ + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + PERROR("get interface name socket create failed"); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + + ifr.ifr_ifindex = interface_index; + IPACMDBG_H("Interface index %d\n", interface_index); + + if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) + { + PERROR("call_ioctl_on_dev: ioctl failed:"); + close(fd); + return IPACM_FAILURE; + } + close(fd); + + IPACMDBG_H("Received interface name %s\n", ifr.ifr_name); + for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++) + { + if (strncmp(ifr.ifr_name, + IPACM_Iface::ipacmcfg->iface_table[i].iface_name, + sizeof(IPACM_Iface::ipacmcfg->iface_table[i].iface_name)) == 0) + { + IPACMDBG_H("Interface (%s) linux(%d) mapped to ipa(%d) \n", ifr.ifr_name, + IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index, i); + + link = i; + IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index = interface_index; + break; + } + } + + return link; +} + +/* Query ipa_interface ipv4_addr by given linux interface_index */ +void IPACM_Iface::iface_addr_query +( + int interface_index +) +{ + int fd; + struct ifreq ifr; + struct ifaddrs *myaddrs, *ifa; + ipacm_cmd_q_data evt_data; + ipacm_event_data_addr *data_addr; + struct in_addr iface_ipv4; + + /* use linux interface-index to find interface name */ + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + PERROR("get interface name socket create failed"); + return ; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + + ifr.ifr_ifindex = interface_index; + IPACMDBG_H("Interface index %d\n", interface_index); + + if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) + { + PERROR("call_ioctl_on_dev: ioctl failed:"); + close(fd); + return ; + } + IPACMDBG_H("Interface index %d name: %s\n", interface_index,ifr.ifr_name); + close(fd); + + /* query ipv4/v6 address */ + if(getifaddrs(&myaddrs) != 0) + { + IPACMERR("getifaddrs"); + return ; + } + + for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == NULL) + continue; + if (!(ifa->ifa_flags & IFF_UP)) + continue; + + if(strcmp(ifr.ifr_name,ifa->ifa_name) == 0) // find current iface + { + IPACMDBG_H("Internal post new_addr event for iface %s\n", ifa->ifa_name); + switch (ifa->ifa_addr->sa_family) + { + case AF_INET: + { + struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr; + IPACMDBG_H("ipv4 address %s\n",inet_ntoa(s4->sin_addr)); + iface_ipv4 = s4->sin_addr; + /* post new_addr event to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + freeifaddrs(myaddrs); + return ; + } + 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", + data_addr->if_index, + data_addr->ipv4_addr); + + evt_data.event = IPA_ADDR_ADD_EVENT; + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + break; + } + + case AF_INET6: + { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr; + /* post new_addr event to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + freeifaddrs(myaddrs); + return ; + } + data_addr->iptype = IPA_IP_v6; + data_addr->if_index = interface_index; + memcpy(data_addr->ipv6_addr, + &s6->sin6_addr, + sizeof(data_addr->ipv6_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]); + IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n", + data_addr->if_index, + 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; + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + break; + } + + default: + continue; + } + } + } + freeifaddrs(myaddrs); + return ; +} + +/*Query the IPA endpoint property */ +int IPACM_Iface::query_iface_property(void) +{ + int res = IPACM_SUCCESS, fd = 0; + uint32_t cnt=0; + + fd = open(DEVICE_NAME, O_RDWR); + IPACMDBG("iface query-property \n"); + if (0 == fd) + { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + return IPACM_FAILURE; + } + + iface_query = (struct ipa_ioc_query_intf *) + calloc(1, sizeof(struct ipa_ioc_query_intf)); + if(iface_query == NULL) + { + IPACMERR("Unable to allocate iface_query memory.\n"); + close(fd); + return IPACM_FAILURE; + } + IPACMDBG_H("iface name %s\n", dev_name); + memcpy(iface_query->name, dev_name, sizeof(dev_name)); + + if (ioctl(fd, IPA_IOC_QUERY_INTF, iface_query) < 0) + { + PERROR("ioctl IPA_IOC_QUERY_INTF failed\n"); + /* iface_query memory will free when iface-down*/ + res = IPACM_FAILURE; + } + + if(iface_query->num_tx_props > 0) + { + tx_prop = (struct ipa_ioc_query_intf_tx_props *) + calloc(1, sizeof(struct ipa_ioc_query_intf_tx_props) + + iface_query->num_tx_props * sizeof(struct ipa_ioc_tx_intf_prop)); + if(tx_prop == NULL) + { + IPACMERR("Unable to allocate tx_prop memory.\n"); + 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; + + 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, 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) + { + rx_prop = (struct ipa_ioc_query_intf_rx_props *) + calloc(1, sizeof(struct ipa_ioc_query_intf_rx_props) + + iface_query->num_rx_props * sizeof(struct ipa_ioc_rx_intf_prop)); + if(rx_prop == NULL) + { + IPACMERR("Unable to allocate rx_prop memory.\n"); + close(fd); + return IPACM_FAILURE; + } + memcpy(rx_prop->name, dev_name, + sizeof(rx_prop->name)); + 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 (res != IPACM_FAILURE) + { + for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++) + { + IPACMDBG_H("Rx(%d):attrib-mask:0x%x, ip-type: %d, src_pipe: %d\n", + cnt, rx_prop->rx[cnt].attrib.attrib_mask, rx_prop->rx[cnt].ip, rx_prop->rx[cnt].src_pipe); + } + } + } + + /* 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); + } + + close(fd); + return res; +} + +/*Configure the initial filter rules */ +int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) +{ + + int res = IPACM_SUCCESS, len = 0; + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_add_flt_rule *m_pFilteringTable; + + /* Adding this hack because WLAN may not registered for Rx-endpoint, other ifaces will always have*/ + const char *dev_wlan0="wlan0"; + const char *dev_wlan1="wlan1"; + const char *dev_ecm0="ecm0"; + + /* 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)) + { + IPACMDBG_H(" NOT add producer dependency on dev %s with registered rx-prop cat:%d \n", dev_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat); + } + else + { + 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->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false); + } + else + { + /* only wlan may take software-path, not register Rx-property*/ + if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_HSIC_PROD); + IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true); + } + if(strcmp(dev_name,dev_ecm0) == 0) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_USB_PROD); + IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true); + } + } + } + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + /* construct ipa_ioc_add_flt_rule with default filter rules */ + if (iptype == IPA_IP_v4) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + + (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add)); + + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!m_pFilteringTable) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = iptype; + m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES; + + /* Configuring Fragment Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.rule.retain_hdr = 1; + 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.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, + sizeof(flt_rule_entry.rule.attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring Multicast Filtering Rule */ + 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; + 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)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + 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++) + { + if (m_pFilteringTable->rules[i].status == 0) + { + dft_v4fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_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 + { + len = sizeof(struct ipa_ioc_add_flt_rule) + + (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add)); + + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!m_pFilteringTable) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = iptype; + m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.rule.retain_hdr = 1; + 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; + /* Configuring Multicast Filtering Rule */ + 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; + 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] = 0XFF000000; + 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 */ + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000; + 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] = 0xFE800000; + 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 */ + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000; + 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] = 0xFEC00000; + 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)); + +#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)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + 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) + { + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14); + 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; + } + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1); + flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1; + flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8); + flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1; + flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; + + /* 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)); + + /* 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)); + + /* 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)); +#endif + if (m_filtering.AddFilteringRule(m_pFilteringTable) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + 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; + i++) + { + if (m_pFilteringTable->rules[i].status == 0) + { + dft_v6fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_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(m_pFilteringTable); + + return res; +} + +/* get ipa interface name */ +int IPACM_Iface::ipa_get_if_index +( + 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; + } + + 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; +} + +void IPACM_Iface::config_ip_type(ipa_ip_type iptype) +{ + /* 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; + } + + 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; + } + + 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; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp new file mode 100644 index 0000000..a142553 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp @@ -0,0 +1,565 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_IfaceManager.cpp + + @brief + This file implements the IPAM iface_manager functionality. + + @Author + Skylar Chang + +*/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +iface_instances *IPACM_IfaceManager::head = NULL; + +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 + 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 USB-iface + IPACM_EvtDispatcher::registr(IPA_WAN_EMBMS_LINK_UP_EVENT, this); // register for wan eMBMS-iface + return; +} + +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) + { + case IPA_CFG_CHANGE_EVENT: + 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("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) + { + IPACMDBG("WAN-EMBMS (%s) link already up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); + } + else if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) + { + IPACMDBG_H("WAN-LTE (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); + ifmgr_data.if_index = evt_data->if_index; + ifmgr_data.if_type = Q6_WAN; + create_iface_instance(&ifmgr_data); + } + 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) + { + /* usb-backhaul using sta_mode ECM_WAN*/ + IPACMDBG_H("WAN-usb (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, evt_data->if_index); + ifmgr_data.if_index = evt_data->if_index; + ifmgr_data.if_type = ECM_WAN; + create_iface_instance(&ifmgr_data); + } + else + { + ifmgr_data.if_index = evt_data->if_index; + ifmgr_data.if_type = Q6_WAN; + create_iface_instance(&ifmgr_data); + } + break; + + 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) + { + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = WLAN_IF; + IPACMDBG_H("WLAN AP (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); + ifmgr_data.if_index = evt_data->if_index; + ifmgr_data.if_type = Q6_WAN; + create_iface_instance(&ifmgr_data); + } + else + { + IPACMDBG_H("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; + + 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) + { + /* wlan-backhaul using sta_mode WLAN_WAN */ + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = WAN_IF; + IPACMDBG_H("WLAN STA (%s) link up, iface: %d: \n", + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, StaData->if_index); + + ifmgr_data.if_index = StaData->if_index; + ifmgr_data.if_type = WLAN_WAN; + memcpy(ifmgr_data.mac_addr, StaData->mac_addr, sizeof(ifmgr_data.mac_addr)); + create_iface_instance(&ifmgr_data); + } + else + { + IPACMDBG_H("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; + + /* 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) && (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); + } + } + break; + + default: + break; + } + return; +} + +int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) +{ + int if_index = param->if_index; + ipacm_wan_iface_type is_sta_mode = param->if_type; + + int ipa_interface_index; + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(if_index); + + if(ipa_interface_index == INVALID_IFACE) + { + IPACMDBG_H("Unhandled interface received, fid: %d\n",if_index); + return IPACM_SUCCESS; + } + + /* check if duplicate instance*/ + if(SearchInstance(ipa_interface_index) == IPA_INSTANCE_NOT_FOUND) + { + /* IPA_INSTANCE_NOT_FOUND */ + switch(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat) + { + + case LAN_IF: + { + IPACMDBG_H("Creating Lan interface\n"); + IPACM_Lan *lan = new IPACM_Lan(ipa_interface_index); + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, lan); + //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_SW_ROUTING_ENABLE, lan); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, lan); +#ifdef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_TETHER, lan); + 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); +#else + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, lan); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, lan); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, lan); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, lan); +#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_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); + /* solve the new_addr comes earlier issue */ + IPACM_Iface::iface_addr_query(if_index); + } + break; + + 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_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; + + case ODU_IF: + { + if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true) + { + 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_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_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_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); + } + } + break; + + case WLAN_IF: + { + IPACMDBG_H("Creating WLan interface\n"); + IPACM_Wlan *wl = new IPACM_Wlan(ipa_interface_index); + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_ADD_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_ADD_EVENT_EX, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_DEL_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_POWER_SAVE_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_RECOVER_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, wl); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, wl); +#ifdef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_TETHER, wl); + 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); +#else + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, wl); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, wl); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, wl); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, wl); +#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_CFG_CHANGE_EVENT, wl); +#endif + IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, wl); +#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); + } + break; + + case WAN_IF: + { + if((IPACM_Iface::ipacmcfg->ipacm_odu_enable == false) || (IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true)) + { + IPACMDBG_H("Creating Wan interface\n"); + IPACM_Wan *w; + if(is_sta_mode == WLAN_WAN) + { + w = new IPACM_Wan(ipa_interface_index, is_sta_mode, param->mac_addr); + } + else + { + w = new IPACM_Wan(ipa_interface_index, is_sta_mode, NULL); + } + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, w); +#ifdef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, w); + IPACM_EvtDispatcher::registr(IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, w); + if(is_sta_mode == Q6_WAN) + { + IPACM_EvtDispatcher::registr(IPA_NETWORK_STATS_UPDATE_EVENT, w); + }; +#else/* defined(FEATURE_IPA_ANDROID) */ + IPACM_EvtDispatcher::registr(IPA_ROUTE_ADD_EVENT, w); + IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, w); +#endif /* not defined(FEATURE_IPA_ANDROID)*/ + IPACM_EvtDispatcher::registr(IPA_FIREWALL_CHANGE_EVENT, w); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, w); + 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); + } + } + break; + + /* WAN-eMBMS instance */ + case EMBMS_IF: + { + IPACMDBG("Creating Wan-eMBSM interface\n"); + IPACM_Wan *embms = new IPACM_Wan(ipa_interface_index, is_sta_mode, NULL); + IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, embms); + IPACMDBG("ipa_WAN (%s):ipa_index (%d) instance open/registr ok\n", embms->dev_name, embms->ipa_if_num); + registr(ipa_interface_index, embms); + } + break; + + default: + IPACMDBG_H("Unhandled interface category received iface name: %s, category: %d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); + return IPACM_SUCCESS; + } + } + return IPACM_SUCCESS; +} + + +int IPACM_IfaceManager::registr(int ipa_if_index, IPACM_Listener *obj) +{ + iface_instances *tmp = head,*nw; + + nw = (iface_instances *)malloc(sizeof(iface_instances)); + if(nw != NULL) + { + nw->ipa_if_index = ipa_if_index; + nw->obj = obj; + nw->next = NULL; + } + else + { + return IPACM_FAILURE; + } + + if(head == NULL) + { + head = nw; + } + else + { + while(tmp->next) + { + tmp = tmp->next; + } + tmp->next = nw; + } + return IPACM_SUCCESS; +} + +int IPACM_IfaceManager::deregistr(IPACM_Listener *param) +{ + iface_instances *tmp = head,*tmp1,*prev = head; + + while(tmp != NULL) + { + if(tmp->obj == param) + { + tmp1 = tmp; + if(tmp == head) + { + head = head->next; + } + else if(tmp->next == NULL) + { + prev->next = NULL; + } + else + { + prev->next = tmp->next; + } + + tmp = tmp->next; + free(tmp1); + } + else + { + prev = tmp; + tmp = tmp->next; + } + } + return IPACM_SUCCESS; +} + + +int IPACM_IfaceManager::SearchInstance(int ipa_if_index) +{ + + iface_instances *tmp = head; + + while(tmp != NULL) + { + if(ipa_if_index == tmp->ipa_if_index) + { + IPACMDBG_H("Find existed iface-instance name: %s\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_index].iface_name); + return IPA_INSTANCE_FOUND; + } + tmp = tmp->next; + } + + IPACMDBG_H("No existed iface-instance name: %s,\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_index].iface_name); + + return IPA_INSTANCE_NOT_FOUND; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp new file mode 100644 index 0000000..a119746 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp @@ -0,0 +1,4229 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_Lan.cpp + + @brief + This file implements the LAN iface functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include "IPACM_Netlink.h" +#include "IPACM_Lan.h" +#include "IPACM_Wan.h" +#include "IPACM_IfaceManager.h" +#include "linux/rmnet_ipa_fd_ioctl.h" +#include "linux/ipa_qmi_service_v01.h" +#include "linux/msm_ipa.h" +#include "IPACM_ConntrackListener.h" +#include +#include + +bool IPACM_Lan::odu_up = false; + +IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) +{ + num_eth_client = 0; + header_name_count = 0; + ipv6_set = 0; + ipv4_header_set = false; + ipv6_header_set = false; + odu_route_rule_v4_hdl = NULL; + odu_route_rule_v6_hdl = NULL; + eth_client = NULL; + int i, m_fd_odu, ret = IPACM_SUCCESS; + + Nat_App = NatApp::GetInstance(); + if (Nat_App == NULL) + { + IPACMERR("unable to get Nat App instance \n"); + return; + } + + /* support eth multiple clients */ + if(iface_query != NULL) + { + if(ipa_if_cate != 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); + + /* ODU routing table initilization */ + 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)); + if ((odu_route_rule_v4_hdl == NULL) || (odu_route_rule_v6_hdl == NULL)) + { + IPACMERR("unable to allocate memory\n"); + return; + } + } + } + + 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)); + + is_active = true; + memset(ipv4_icmp_flt_rule_hdl, 0, NUM_IPV4_ICMP_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(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) + { + m_fd_odu = open(IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU, O_RDWR); + if (0 == m_fd_odu) + { + IPACMERR("Failed opening %s.\n", IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU); + return ; + } + + if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true) + { + ret = ioctl(m_fd_odu, ODU_BRIDGE_IOC_SET_MODE, ODU_BRIDGE_MODE_ROUTER); + IPACM_Iface::ipacmcfg->ipacm_odu_enable = true; + } + else + { + ret = ioctl(m_fd_odu, ODU_BRIDGE_IOC_SET_MODE, ODU_BRIDGE_MODE_BRIDGE); + IPACM_Iface::ipacmcfg->ipacm_odu_enable = true; + } + + if (ret) + { + 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; + } + } + + each_client_rt_rule_count[IPA_IP_v4] = 0; + each_client_rt_rule_count[IPA_IP_v6] = 0; + if(iface_query != NULL && tx_prop != NULL) + { + for(i=0; inum_tx_props; i++) + each_client_rt_rule_count[tx_prop->tx[i].ip]++; + } + 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(ipa_if_cate == LAN_IF) + { + handle_tethering_client(false, IPACM_CLIENT_USB); + } +#endif + return; +} + +IPACM_Lan::~IPACM_Lan() +{ + IPACM_EvtDispatcher::deregistr(this); + IPACM_IfaceManager::deregistr(this); + return; +} + + +/* LAN-iface's callback function */ +void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) +{ + if(is_active == false && event != IPA_LAN_DELETE_SELF) + { + IPACMDBG_H("The interface is no longer active, return.\n"); + return; + } + + int ipa_interface_index; + ipacm_ext_prop* ext_prop; + ipacm_event_iface_up* data_wan; + ipacm_event_iface_up_tehter* data_wan_tether; + + switch (event) + { + case IPA_LINK_DOWN_EVENT: + { + 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) + { + IPACMDBG_H("Received IPA_LINK_DOWN_EVENT\n"); + handle_down_evt(); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + return; + } + } + break; + + case IPA_CFG_CHANGE_EVENT: + { + if ( IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) + { + IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category changed\n"); + /* delete previous instance */ + handle_down_evt(); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + 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; + + case IPA_PRIVATE_SUBNET_CHANGE_EVENT: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + /* internel event: data->if_index is ipa_if_index */ + if (data->if_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from itself posting, ignore\n"); + return; + } + else + { + IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from other LAN iface \n"); +#ifdef FEATURE_IPA_ANDROID + handle_private_subnet_android(IPA_IP_v4); +#endif + IPACMDBG_H(" delete old private subnet rules, use new sets \n"); + return; + } + } + break; + + case IPA_LAN_DELETE_SELF: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + if(data->if_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_LAN_DELETE_SELF event.\n"); + IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); + /* posting link-up event for cradle use-case */ + if(is_mode_switch) + { + IPACMDBG_H("Posting IPA_USB_LINK_UP_EVENT event for (%s)\n", dev_name); + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(evt_data)); + + ipacm_event_data_fid *data_fid = NULL; + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for IPA_USB_LINK_UP_EVENT data_fid\n"); + return; + } + if(IPACM_Iface::ipa_get_if_index(dev_name, &(data_fid->if_index))) + { + IPACMERR("Error while getting interface index for %s device", dev_name); + } + evt_data.event = IPA_USB_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + //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; + } + + case IPA_ADDR_ADD_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) || + (data->iptype == IPA_IP_v6 && + data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 && + data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) ) + { + IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n"); + return; + } + + + 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 + && ipa_if_cate == ODU_IF) + { + if((data->iptype == IPA_IP_v6) && (num_dft_rt_v6 == 0)) + { + handle_addr_evt_odu_bridge(data); + } +#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 + } + else + { + + /* check v4 not setup before, v6 can have 2 iface ip */ + 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); + 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)) + { + if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX) + { + 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, + IPACM_Wan::getXlat_Mux_Id()); + } + else + { + handle_wan_up(IPA_IP_v4); + } + } + } + + 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, 0); + } + else + { + handle_wan_up(IPA_IP_v6); + } + } + } + + /* Post event to NAT */ + if (data->iptype == IPA_IP_v4) + { + ipacm_cmd_q_data evt_data; + ipacm_event_iface_up *info; + + info = (ipacm_event_iface_up *) + malloc(sizeof(ipacm_event_iface_up)); + if (info == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + + memcpy(info->ifname, dev_name, IF_NAME_LEN); + info->ipv4_addr = data->ipv4_addr; + info->addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[0].subnet_mask; + + evt_data.event = IPA_HANDLE_LAN_UP; + evt_data.evt_data = (void *)info; + + /* Insert IPA_HANDLE_LAN_UP to command queue */ + IPACMDBG_H("posting IPA_HANDLE_LAN_UP for IPv4 with below information\n"); + IPACMDBG_H("IPv4 address:0x%x, IPv4 address mask:0x%x\n", + info->ipv4_addr, info->addr_mask); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + IPACMDBG_H("Finish handling IPA_ADDR_ADD_EVENT for ip-family(%d)\n", data->iptype); + } + + IPACMDBG_H("Finish handling IPA_ADDR_ADD_EVENT for ip-family(%d)\n", data->iptype); + /* checking if SW-RT_enable */ + if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true) + { + /* handle software routing enable event*/ + IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + handle_software_routing_enable(); + } + + } + } + } + break; +#ifdef FEATURE_IPA_ANDROID + case IPA_HANDLE_WAN_UP_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_TETHER event\n"); + + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\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) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + 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); + } + } + } + break; + + case IPA_HANDLE_WAN_UP_V6_TETHER: + 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) + { + IPACMERR("No event data is found.\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) + { + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + 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); + } + } + } + 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) + { + IPACMERR("No event data is found.\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) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + handle_wan_down(data_wan_tether->is_sta); + } + } + break; + + case IPA_HANDLE_WAN_DOWN_V6_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6_TETHER event\n"); + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\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) + { + /* 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"); + /* reset usb-client ipv6 rt-rules */ + handle_lan_client_reset_rt(IPA_IP_v6); + + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + handle_wan_down_v6(data_wan_tether->is_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) + { + 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(data_wan->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan->xlat_mux_id); + } + else + { + handle_wan_up(IPA_IP_v4); + } + } + break; + + case IPA_HANDLE_WAN_UP_V6: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6 event\n"); + + data_wan = (ipacm_event_iface_up*)param; + 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) + { + 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); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + 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) + { + 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) + { + handle_wan_down(data_wan->is_sta); + } + break; + + 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) + { + IPACMERR("No event data is found.\n"); + return; + } + /* clean up v6 RT rules*/ + IPACMDBG_H("Received IPA_WAN_V6_DOWN in LAN-instance and need clean up client IPv6 address \n"); + /* reset usb-client ipv6 rt-rules */ + 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) + { + handle_wan_down_v6(data_wan->is_sta); + } + break; +#endif + + case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT: + { + ipacm_event_data_all *data = (ipacm_event_data_all *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + 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 && ipa_if_cate == ODU_IF) + { + 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); + 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) + { + IPACMDBG_H("ODU is in bridge mode, no action \n"); + return; + } + } + + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("ETH iface got client \n"); + /* 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); + return; + } + } + break; + + case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT: + { + ipacm_event_data_all *data = (ipacm_event_data_all *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + 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) + { + if (data->iptype == IPA_IP_v6) + { + handle_del_ipv6_addr(data); + return; + } + + eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr); + + IPACMDBG_H("LAN iface delete client \n"); + handle_eth_client_down_evt(data->mac_addr); + return; + } + } + break; + + case IPA_SW_ROUTING_ENABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n"); + /* handle software routing enable event*/ + handle_software_routing_enable(); + break; + + case IPA_SW_ROUTING_DISABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n"); + /* handle software routing disable event*/ + handle_software_routing_disable(); + break; + + case IPA_CRADLE_WAN_MODE_SWITCH: + { + 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(wan_mode->cradle_wan_mode == BRIDGE) + { + handle_cradle_wan_mode_switch(true); + } + else + { + handle_cradle_wan_mode_switch(false); + } + } + break; + + case IPA_TETHERING_STATS_UPDATE_EVENT: + { + IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_EVENT event.\n"); + if (IPACM_Wan::isWanUP(ipa_if_num) || IPACM_Wan::isWanUP_V6(ipa_if_num)) + { + if(IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */ + { + ipa_get_data_stats_resp_msg_v01 *data = (ipa_get_data_stats_resp_msg_v01 *)param; + IPACMDBG("Received IPA_TETHERING_STATS_UPDATE_STATS ipa_stats_type: %d\n",data->ipa_stats_type); + IPACMDBG("Received %d UL, %d DL pipe stats\n",data->ul_src_pipe_stats_list_len, + data->dl_dst_pipe_stats_list_len); + if (data->ipa_stats_type != QMI_IPA_STATS_TYPE_PIPE_V01) + { + IPACMERR("not valid pipe stats enum(%d)\n", data->ipa_stats_type); + return; + } + handle_tethering_stats_event(data); + } + } + } + break; + + default: + break; + } + + return; +} + + +int IPACM_Lan::handle_del_ipv6_addr(ipacm_event_data_all *data) +{ + uint32_t tx_index; + uint32_t rt_hdl; + int num_v6 =0, clnt_indx; + + clnt_indx = get_eth_client_index(data->mac_addr); + if (clnt_indx == IPACM_INVALID_INDEX) + { + IPACMERR("eth client not found/attached \n"); + return IPACM_FAILURE; + } + + 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) + { + IPACMERR("number of wan_ul_fl_rule_v4 (%d) > MAX_WAN_UL_FILTER_RULES (%d), aborting...\n", num_wan_ul_fl_rule_v4, MAX_WAN_UL_FILTER_RULES); + close(fd); + return IPACM_FAILURE; + } + if (m_filtering.DeleteFilteringHdls(wan_ul_fl_rule_hdl_v4, + IPA_IP_v4, num_wan_ul_fl_rule_v4) == false) + { + IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n"); + 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; + modem_ul_v4_set = false; + + 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; + flt_index.retain_header = 0; + flt_index.embedded_call_mux_id_valid = 1; + flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); + + if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) + { + IPACMERR("Error sending filtering rule index, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + } + else + { + if (m_filtering.DeleteFilteringHdls(&lan_wan_fl_rule_hdl[0], IPA_IP_v4, 1) == false) + { + IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + } + + close(fd); + return IPACM_SUCCESS; +} + +/* handle new_address event*/ +int IPACM_Lan::handle_addr_evt(ipacm_event_data_addr *data) +{ + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 1; + int num_ipv6_addr; + int res = IPACM_SUCCESS; + + IPACMDBG_H("set route/filter rule ip-type: %d \n", data->iptype); + +/* 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) + { + 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 *) + 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; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = data->iptype; + 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; + 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 = 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]); + /* initial multicast/broadcast/fragment filter rule */ + + init_fl_rule(data->iptype); + 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); + } + else + { + /* check if see that v6-addr already or not*/ + 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])) + { + return IPACM_FAILURE; + 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; + } + + 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)); + + 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]; + 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 = 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[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl; + + /* 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); + + if (num_dft_rt_v6 == 0) + { + 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); + + init_fl_rule(data->iptype); + } + num_dft_rt_v6++; + IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6); + } + + IPACMDBG_H("finish route/filter rule ip-type: %d, res(%d)\n", data->iptype, res); + +fail: + free(rt_rule); + return res; +} + +/* configure private subnet filter rules*/ +int IPACM_Lan::handle_private_subnet(ipa_ip_type iptype) +{ + struct ipa_flt_rule_add flt_rule_entry; + int i; + + ipa_ioc_add_flt_rule *m_pFilteringTable; + + IPACMDBG_H("lan->handle_private_subnet(); set route/filter rule \n"); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if (iptype == IPA_IP_v4) + { + + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_flt_rule) + + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_add) + ); + if (!m_pFilteringTable) + { + PERROR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v4; + m_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("LAN m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_default_v4); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.retain_hdr = 1; + 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 + /* 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); + + 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; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask; + flt_rule_entry.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr; + memcpy(&(m_pFilteringTable->rules[i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Loop %d 5\n", i); + } + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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++) + { + private_fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl; + } + free(m_pFilteringTable); + } + else + { + IPACMDBG_H("No private subnet rules for ipv6 iface %s\n", dev_name); + } + return IPACM_SUCCESS; +} + + +/* for STA mode wan up: configure filter rule for wan_up event*/ +int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) +{ + struct ipa_flt_rule_add flt_rule_entry; + int len = 0; + ipa_ioc_add_flt_rule *m_pFilteringTable; + + IPACMDBG_H("set WAN interface as default filter rule\n"); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(ip_type == IPA_IP_v4) + { + 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) + { + PERROR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)1; + + 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 hanle for table: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl); + + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + 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, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + + 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; + + memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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); + } + + + /* 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) + { + /* add default v6 filter rule */ + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_flt_rule) + + 1 * sizeof(struct ipa_flt_rule_add)); + + if (!m_pFilteringTable) + { + PERROR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v6; + m_pFilteringTable->num_rules = (uint8_t)1; + + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_v6)) + { + IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_v6=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_v6); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + 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_ROUTING; +#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, + sizeof(flt_rule_entry.rule.attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; + 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] = 0X00000000; + 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; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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 */ + dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES] = m_pFilteringTable->rules[0].flt_rule_hdl; + free(m_pFilteringTable); + } + + return IPACM_SUCCESS; +} + +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; + struct ipa_ioc_write_qmapid mux; + + if(rx_prop != NULL) + { + /* give mud ID to IPA-driver for WLAN/LAN pkts */ + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (0 == fd) + { + IPACMDBG_H("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + mux.qmap_id = ipacm_config->GetQmapId(); + for(cnt=0; cntnum_rx_props; cnt++) + { + mux.client = rx_prop->rx[cnt].src_pipe; + ret = ioctl(fd, IPA_IOC_WRITE_QMAPID, &mux); + if (ret) + { + IPACMERR("Failed to write mux id %d\n", mux.qmap_id); + close(fd); + return IPACM_FAILURE; + } + } + close(fd); + } + + /* 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 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 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); + } + return ret; +} + +/* handle ETH client initial, construct full headers (tx property) */ +int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr) +{ + +#define ETH_IFACE_INDEX_LEN 2 + + int res = IPACM_SUCCESS, len = 0; + char index[ETH_IFACE_INDEX_LEN]; + struct ipa_ioc_copy_hdr sCopyHeader; + struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; + uint32_t cnt; + int clnt_indx; + + clnt_indx = get_eth_client_index(mac_addr); + + if (clnt_indx != IPACM_INVALID_INDEX) + { + IPACMERR("eth client is found/attached already with index %d \n", clnt_indx); + return IPACM_FAILURE; + } + + /* add header to IPA */ + if (num_eth_client >= IPA_MAX_NUM_ETH_CLIENTS) + { + IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_ETH_CLIENTS); + return IPACM_FAILURE; + } + + IPACMDBG_H("ETH client number: %d\n", num_eth_client); + + memcpy(get_client_memptr(eth_client, num_eth_client)->mac, + mac_addr, + sizeof(get_client_memptr(eth_client, num_eth_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]); + + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(eth_client, num_eth_client)->mac[0], + get_client_memptr(eth_client, num_eth_client)->mac[1], + get_client_memptr(eth_client, num_eth_client)->mac[2], + get_client_memptr(eth_client, num_eth_client)->mac[3], + get_client_memptr(eth_client, num_eth_client)->mac[4], + get_client_memptr(eth_client, num_eth_client)->mac[5]); + + /* 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; + } + + /* 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); + 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"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + /* copy client mac_addr to partial header */ + if (sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + 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)); + + 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)); + 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(eth_client, num_eth_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n", + num_eth_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v4); + get_client_memptr(eth_client, num_eth_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); + 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"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + /* copy client mac_addr to partial header */ + if (sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + 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)); + + 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)); + 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(eth_client, num_eth_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n", + num_eth_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v6); + + get_client_memptr(eth_client, num_eth_client)->ipv6_header_set=true; + + break; + + } + } + /* initialize wifi client*/ + get_client_memptr(eth_client, num_eth_client)->route_rule_set_v4 = false; + get_client_memptr(eth_client, num_eth_client)->route_rule_set_v6 = 0; + get_client_memptr(eth_client, num_eth_client)->ipv4_set = false; + get_client_memptr(eth_client, num_eth_client)->ipv6_set = 0; + num_eth_client++; + header_name_count++; //keep increasing header_name_count + res = IPACM_SUCCESS; + IPACMDBG_H("eth client number: %d\n", num_eth_client); + } + else + { + return res; + } +fail: + free(pHeaderDescriptor); + return res; +} + +/*handle eth client */ +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", + 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_eth_client_index(data->mac_addr); + + if (clnt_indx == IPACM_INVALID_INDEX) + { + IPACMERR("eth 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(eth_client, clnt_indx)->ipv4_set == false) + { + get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr; + get_client_memptr(eth_client, clnt_indx)->ipv4_set = true; + } + else + { + /* 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); + 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(eth_client, clnt_indx)->v4_addr); + delete_eth_rtrules(clnt_indx,IPA_IP_v4); + 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 + { + 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( (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] && + 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 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]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3]; + get_client_memptr(eth_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*/ + } + } + } + + return IPACM_SUCCESS; +} + +/*handle eth client routing rule*/ +int IPACM_Lan::handle_eth_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 eth_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]); + + eth_index = get_eth_client_index(mac_addr); + if (eth_index == IPACM_INVALID_INDEX) + { + IPACMDBG_H("eth client not found/attached \n"); + return IPACM_SUCCESS; + } + + if (iptype==IPA_IP_v4) { + IPACMDBG_H("eth client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", eth_index, iptype, + get_client_memptr(eth_client, eth_index)->ipv4_set, + get_client_memptr(eth_client, eth_index)->route_rule_set_v4); + } else { + IPACMDBG_H("eth client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", eth_index, iptype, + 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 + && get_client_memptr(eth_client, eth_index)->ipv4_set == true) + || (iptype == IPA_IP_v6 + && get_client_memptr(eth_client, eth_index)->route_rule_set_v6 < get_client_memptr(eth_client, eth_index)->ipv6_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); + if (tx_prop != NULL) + { + 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)); + + 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", eth_index, + get_client_memptr(eth_client, eth_index)->v4_addr); + + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + eth_index, + get_client_memptr(eth_client, eth_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'; + 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(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; +#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 */ + get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_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(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4, iptype); + + } else { + + for(v6_num = get_client_memptr(eth_client, eth_index)->route_rule_set_v6;v6_num < get_client_memptr(eth_client, eth_index)->ipv6_set;v6_num++) + { + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + eth_index, + get_client_memptr(eth_client, eth_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 = 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(eth_client, eth_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(eth_client, eth_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(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_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(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*/ + 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, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = get_client_memptr(eth_client, eth_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(eth_client, eth_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(eth_client, eth_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(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_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(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[v6_num], iptype); + } + } + + } /* end of for loop */ + + free(rt_rule); + + if (iptype == IPA_IP_v4) + { + get_client_memptr(eth_client, eth_index)->route_rule_set_v4 = true; + } + else + { + get_client_memptr(eth_client, eth_index)->route_rule_set_v6 = get_client_memptr(eth_client, eth_index)->ipv6_set; + } + } + return IPACM_SUCCESS; +} + +/* handle odu client initial, construct full headers (tx property) */ +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; + + IPACMDBG("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]); + + /* 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; + } + + /* copy partial header for v4*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v4) + { + IPACMDBG("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("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("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 */ + if (sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + 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)); + 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; + 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; + } + + ODU_hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + ipv4_header_set = true ; + IPACMDBG(" ODU v4 full header name:%s header handle:(0x%x)\n", + pHeaderDescriptor->hdr[0].name, + ODU_hdr_hdl_v4); + break; + } + } + + + /* copy partial header for v6*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v6) + { + + IPACMDBG("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("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("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 */ + if (sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + 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)); + + 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; + 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; + } + + ODU_hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + ipv6_header_set = true ; + IPACMDBG(" ODU v4 full header name:%s header handle:(0x%x)\n", + pHeaderDescriptor->hdr[0].name, + ODU_hdr_hdl_v6); + break; + } + } + } +fail: + free(pHeaderDescriptor); + return res; +} + + +/* handle odu default route rule configuration */ +int IPACM_Lan::handle_odu_route_add() +{ + /* add default WAN route */ + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + uint32_t tx_index; + const int NUM = 1; + + if(tx_prop == NULL) + { + IPACMDBG_H("No tx properties, ignore default route setting\n"); + return IPACM_SUCCESS; + } + + 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) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = (uint8_t)NUM; + + + 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) + { + 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 + { + 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, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + if (IPA_IP_v4 == tx_prop->tx[tx_index].ip) + { + 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; + } + odu_route_rule_v4_hdl[tx_index] = rt_rule_entry->rt_rule_hdl; + 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); + } + 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; +#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; + } + odu_route_rule_v6_hdl[tx_index] = rt_rule_entry->rt_rule_hdl; + 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; +} + +/* handle odu default route rule deletion */ +int IPACM_Lan::handle_odu_route_del() +{ + uint32_t tx_index; + + if(tx_prop == NULL) + { + 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++) + { + if (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) + { + 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) + { + 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; +} + +/*handle eth client del mode*/ +int IPACM_Lan::handle_eth_client_down_evt(uint8_t *mac_addr) +{ + int clt_indx; + uint32_t tx_index; + int num_eth_client_tmp = num_eth_client; + int num_v6; + + IPACMDBG_H("total client: %d\n", num_eth_client_tmp); + + clt_indx = get_eth_client_index(mac_addr); + if (clt_indx == IPACM_INVALID_INDEX) + { + IPACMDBG_H("eth client not attached\n"); + return IPACM_SUCCESS; + } + + /* First reset nat rules and then route rules */ + if(get_client_memptr(eth_client, clt_indx)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(eth_client, clt_indx)->v4_addr); + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, clt_indx)->v4_addr); + } + + if (delete_eth_rtrules(clt_indx, IPA_IP_v4)) + { + IPACMERR("unbale to delete ecm-client v4 route rules for index: %d\n", clt_indx); + return IPACM_FAILURE; + } + + if (delete_eth_rtrules(clt_indx, IPA_IP_v6)) + { + IPACMERR("unbale to delete ecm-client v6 route rules for index: %d\n", clt_indx); + return IPACM_FAILURE; + } + + /* Delete eth client header */ + if(get_client_memptr(eth_client, clt_indx)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, clt_indx)->hdr_hdl_v4) + == false) + { + return IPACM_FAILURE; + } + get_client_memptr(eth_client, clt_indx)->ipv4_header_set = false; + } + + if(get_client_memptr(eth_client, clt_indx)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, clt_indx)->hdr_hdl_v6) + == false) + { + return IPACM_FAILURE; + } + get_client_memptr(eth_client, clt_indx)->ipv6_header_set = false; + } + + /* Reset ip_set to 0*/ + get_client_memptr(eth_client, clt_indx)->ipv4_set = false; + get_client_memptr(eth_client, clt_indx)->ipv6_set = 0; + get_client_memptr(eth_client, clt_indx)->ipv4_header_set = false; + get_client_memptr(eth_client, clt_indx)->ipv6_header_set = false; + get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = false; + get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = 0; + + for (; clt_indx < num_eth_client_tmp - 1; clt_indx++) + { + memcpy(get_client_memptr(eth_client, clt_indx)->mac, + get_client_memptr(eth_client, (clt_indx + 1))->mac, + sizeof(get_client_memptr(eth_client, clt_indx)->mac)); + + get_client_memptr(eth_client, clt_indx)->hdr_hdl_v4 = get_client_memptr(eth_client, (clt_indx + 1))->hdr_hdl_v4; + get_client_memptr(eth_client, clt_indx)->hdr_hdl_v6 = get_client_memptr(eth_client, (clt_indx + 1))->hdr_hdl_v6; + get_client_memptr(eth_client, clt_indx)->v4_addr = get_client_memptr(eth_client, (clt_indx + 1))->v4_addr; + + get_client_memptr(eth_client, clt_indx)->ipv4_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv4_set; + get_client_memptr(eth_client, clt_indx)->ipv6_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv6_set; + get_client_memptr(eth_client, clt_indx)->ipv4_header_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv4_header_set; + get_client_memptr(eth_client, clt_indx)->ipv6_header_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv6_header_set; + + get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = get_client_memptr(eth_client, (clt_indx + 1))->route_rule_set_v4; + get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = get_client_memptr(eth_client, (clt_indx + 1))->route_rule_set_v6; + + for (num_v6=0;num_v6< get_client_memptr(eth_client, clt_indx)->ipv6_set;num_v6++) + { + get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][0] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][0]; + get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][1] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][1]; + get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][2] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][2]; + get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][3] = get_client_memptr(eth_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(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4 = + get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4; + + for(num_v6=0;num_v6< get_client_memptr(eth_client, clt_indx)->route_rule_set_v6;num_v6++) + { + get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6] = + get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6]; + get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6] = + get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6]; + } + } + } + + IPACMDBG_H(" %d eth client deleted successfully \n", num_eth_client); + num_eth_client = num_eth_client - 1; + IPACMDBG_H(" Number of eth client: %d\n", num_eth_client); + + /* Del RM dependency */ + if(num_eth_client == 0) + { + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule*/ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + if (tx_prop != NULL) + { + 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]); + } + } + + return IPACM_SUCCESS; +} + +/*handle LAN iface down event*/ +int IPACM_Lan::handle_down_evt() +{ + int i; + int res = IPACM_SUCCESS; + + IPACMDBG_H("lan handle_down_evt\n "); + if (ipa_if_cate == ODU_IF) + { + /* delete ODU default RT rules */ + 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) + { + if (m_header.DeleteHeaderHdl(ODU_hdr_hdl_v4) + == false) + { + IPACMERR("ODU ipv4 header delete fail\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("ODU ipv4 header delete success\n"); + } + + if (ipv6_header_set) + { + if (m_header.DeleteHeaderHdl(ODU_hdr_hdl_v6) + == false) + { + IPACMERR("ODU ipv6 header delete fail\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMERR("ODU ipv6 header delete success\n"); + } + } + + /* no iface address up, directly close iface*/ + if (ip_type == IPACM_IP_NULL) + { + goto fail; + } + + /* 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); + } + + 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); + } + + /* delete default filter rules */ + if (ip_type != IPA_IP_v6 && rx_prop != NULL) + { + if(m_filtering.DeleteFilteringHdls(ipv4_icmp_flt_rule_hdl, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE) == false) + { + IPACMERR("Error Deleting ICMPv4 Filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE); + + 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); + + /* free private-subnet ipv4 filter rules */ + if (IPACM_Iface::ipacmcfg->ipa_num_private_subnet > IPA_PRIV_SUBNET_FILTER_RULE_HANDLES) + { + IPACMERR(" the number of rules are bigger than array, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + +#ifdef FEATURE_IPA_ANDROID + if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES) == false) + { + 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, 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 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 "); + + if (ip_type != IPA_IP_v4 && rx_prop != NULL) + { + 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; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE); + + if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES) == false) + { + 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("Finished delete default iface ipv6 filtering rules \n "); + + if (ip_type != IPA_IP_v6) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) + == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + IPACMDBG_H("Finished delete default iface ipv4 rules \n "); + + /* delete default v6 routing rule */ + if (ip_type != IPA_IP_v4) + { + /* may have multiple ipv6 iface-RT rules*/ + for (i = 0; i < 2*num_dft_rt_v6; i++) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + i], IPA_IP_v6) + == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + + IPACMDBG_H("Finished delete default iface ipv6 rules \n "); + + /* free the edm clients cache */ + IPACMDBG_H("Free ecm clients cache\n"); + + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule */ + IPACMDBG_H("dev %s delete producer dependency\n", dev_name); + if (tx_prop != NULL) + { + 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]); + } + + eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL); + +/* 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 */ + if(ipa_if_cate != WAN_IF) + { + handle_tethering_client(true, IPACM_CLIENT_USB); + } +#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); + } + if (odu_route_rule_v6_hdl != NULL) + { + free(odu_route_rule_v6_hdl); + } + /* 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]); + IPACMDBG_H("Finished delete dependency \n "); + free(rx_prop); + } + + if (eth_client != NULL) + { + free(eth_client); + } + + if (tx_prop != NULL) + { + free(tx_prop); + } + if (iface_query != NULL) + { + free(iface_query); + } + + is_active = false; + post_del_self_evt(); + + return res; +} + +/* install UL filter rule from Q6 */ +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, index; + uint32_t value = 0; + + IPACMDBG_H("Set modem UL flt rules\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; + } + + fd = open(IPA_DEVICE_NAME, O_RDWR); + 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(); +#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) + { + 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; +#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; + + 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) + { + 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 + { + IPACMERR("IP type is not expected.\n"); + ret = IPACM_FAILURE; + 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; + + /* 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_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 + { + 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)) + { + 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++; + } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules); + } + 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++; + } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules); + } + else + { + IPACMERR("IP type is not expected.\n"); + goto fail; + } + } + +fail: + free(pFilteringTable); + close(fd); + return ret; +} + +int IPACM_Lan::handle_wan_down_v6(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; + } + + delete_ipv6_prefix_flt_rule(); + + memset(ipv6_prefix, 0, sizeof(ipv6_prefix)); + + if(is_sta_mode == false) + { + if (num_wan_ul_fl_rule_v6 > MAX_WAN_UL_FILTER_RULES) + { + IPACMERR(" the number of rules (%d) are bigger than array (%d), aborting...\n", num_wan_ul_fl_rule_v6, MAX_WAN_UL_FILTER_RULES); + 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) + { + IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n"); + 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; + + 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; + flt_index.retain_header = 0; + flt_index.embedded_call_mux_id_valid = 1; + flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); + if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) + { + IPACMERR("Error sending filtering rule index, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + } + else + { + if (m_filtering.DeleteFilteringHdls(&dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES], + IPA_IP_v6, 1) == false) + { + IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + } + close(fd); + return IPACM_SUCCESS; +} + +int IPACM_Lan::reset_to_dummy_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl) +{ + 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 flt rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 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; +} + +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; + + /* 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 */ + + /* 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; +} + +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; + + if(rx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + + 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; + + 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 = 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 Adding Filtering rule, aborting...\n"); + free(flt_rule); + return IPACM_FAILURE; + } + else + { + 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); + } + } + 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) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + + 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_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; +#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)); + + 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 + { + 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 < 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; + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(iptype == IPA_IP_v6) + { + IPACMDBG_H("There is no ipv6 dummy filter rules needed for iface %s\n", dev_name); + return 0; + } + else + { + for(i=0; iipa_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; + + for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++) + { + flt_rule.rule_hdl = private_fl_rule_hdl[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)); + IPACMDBG_H(" IPACM private subnet_addr as: 0x%x entry(%d)\n", flt_rule.rule.attrib.u.v4.dst_addr, i); + } + + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to modify private subnet filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + } +fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix) +{ + if(prefix == NULL) + { + IPACMERR("IPv6 prefix is empty.\n"); + return IPACM_FAILURE; + } + IPACMDBG_H("Receive IPv6 prefix: 0x%08x%08x.\n", prefix[0], prefix[1]); + + int len; + struct ipa_ioc_add_flt_rule* flt_rule; + struct ipa_flt_rule_add flt_rule_entry; + + if(rx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + + 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 = 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; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = prefix[0]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = prefix[1]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x0; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x0; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x0; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x0; + 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_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]); + free(flt_rule); + } + } + return IPACM_SUCCESS; +} + +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 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) + { + IPACMERR("Failed to get interface IP address.\n"); + return IPACM_FAILURE; + } + + if(data->iptype == IPA_IP_v6) + { + 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; + } + + memcpy(&ipv6_addr, data->ipv6_addr, sizeof(struct in6_addr)); + + 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); + } + + return res; +} + +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(t1 == IPA_HDR_L2_802_3) + { + 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; + } + } + + 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_cradle_wan_mode_switch(bool is_wan_bridge_mode) +{ + 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) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + 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) + { + PERROR("Error Locate ipa_ioc_mdfy_flt_rule memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)1; + + 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); + + + 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) + { + 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; + + 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; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0; + + memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry)); + if (false == m_filtering.ModifyFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Modifying RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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; +} + +/*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; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + + 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 (data->dl_dst_pipe_stats_list_valid) + { + 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; + } + } + } + } + } + + if (data->ul_src_pipe_stats_list_valid) + { + 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; + } + } + } + } + } + close(fd); + + 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; + } + + 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; +} + +/*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; + + if(fd_wwan_ioctl < 0) + { + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + return IPACM_FAILURE; + } + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + close(fd_wwan_ioctl); + return IPACM_FAILURE; + } + + memset(&tether_client, 0, sizeof(tether_client)); + tether_client.reset_client = reset; + tether_client.ipa_client = ipa_client; + + if(tx_prop != NULL) + { + 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); + } + } + + if(rx_prop != NULL) + { + tether_client.ul_src_pipe_len = rx_prop->num_rx_props; + for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++) + { + 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); + } + } + + ret = ioctl(fd_wwan_ioctl, WAN_IOC_SET_TETHER_CLIENT_PIPE, &tether_client); + if (ret != 0) + { + IPACMERR("Failed set tether-client-pipe %p with ret %d\n ", &tether_client, ret); + } + IPACMDBG("Set tether-client-pipe %p\n", &tether_client); + close(fd); + close(fd_wwan_ioctl); + return ret; +} + +/* 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) +{ + ipacm_cmd_q_data eth_bridge_evt; + ipacm_event_eth_bridge *evt_data; + + evt_data = (ipacm_event_eth_bridge*)malloc(sizeof(ipacm_event_eth_bridge)); + if(evt_data == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return; + } + memset(evt_data, 0, sizeof(ipacm_event_eth_bridge)); + + evt_data->p_iface = this; + evt_data->iptype = iptype; + if(mac) + { + IPACMDBG_H("Client mac: 0x%02x%02x%02x%02x%02x%02x \n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + memcpy(evt_data->mac_addr, mac, sizeof(evt_data->mac_addr)); + } + + memset(ð_bridge_evt, 0, sizeof(ipacm_cmd_q_data)); + eth_bridge_evt.evt_data = (void*)evt_data; + eth_bridge_evt.event = evt; + + 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) + { + IPACMERR("No tx prop.\n"); + return IPACM_FAILURE; + } + + 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 context table.\n"); + return IPACM_FAILURE; + } + + 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("Adding hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); + res = IPACM_FAILURE; + goto end; + } + + *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) + { + IPACMERR("Failed to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(rt_rule_table, 0, len); + + rt_rule_table->commit = 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++) + { + if(tx_prop->tx[i].ip == iptype) + { + if(position >= num_rt_rule || position >= MAX_NUM_PROP) + { + IPACMERR("Number of routing rules already exceeds limit.\n"); + res = IPACM_FAILURE; + goto end; + } + + 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; + } + + 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(&(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 end; + } + else + { + *rt_rule_count = position; + for(i=0; irules[i].rt_rule_hdl; + } + +end: + free(rt_rule_table); + return res; +} + +/* 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) +{ + 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) + { + IPACMDBG_H("No tx properties \n"); + return IPACM_FAILURE; + } + + if(ipa_if_cate != WLAN_IF) + { + IPACMDBG_H("This is not WLAN IF, no need to modify rt rule.\n"); + return IPACM_SUCCESS; + } + + 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]); + + len = sizeof(struct ipa_ioc_mdfy_rt_rule) + rt_rule_count * sizeof(struct ipa_rt_rule_mdfy); + rt_rule = (struct ipa_ioc_mdfy_rt_rule *)malloc(len); + if(rt_rule == NULL) + { + IPACMERR("Unable to allocate memory for modify rt rule\n"); + return IPACM_FAILURE; + } + memset(rt_rule, 0, len); + + rt_rule->commit = 1; + rt_rule->num_rules = 0; + rt_rule->ip = iptype; + + for (index = 0; index < tx_prop->num_tx_props; index++) + { + if (tx_prop->tx[index].ip == iptype) + { + if (rt_rule->num_rules >= rt_rule_count || + rt_rule->num_rules >= MAX_NUM_PROP) + { + IPACMERR("Number of routing rules exceeds limit.\n"); + res = IPACM_FAILURE; + goto end; + } + + rt_rule_entry = &rt_rule->rules[rt_rule->num_rules]; + + if (IPACM_Iface::ipacmcfg->isMCC_Mode) + { + 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; + } + else + { + 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; + } + + 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++; + } + } + + if(m_routing.ModifyRoutingRule(rt_rule) == false) + { + IPACMERR("Failed to modify routing rules.\n"); + res = IPACM_FAILURE; + goto end; + } + if(m_routing.Commit(iptype) == false) + { + IPACMERR("Failed to commit routing rules.\n"); + res = IPACM_FAILURE; + goto end; + } + IPACMDBG("Modified routing rules successfully.\n"); + +end: + free(rt_rule); + return res; +} + +int IPACM_Lan::eth_bridge_add_flt_rule(uint8_t *mac, uint32_t rt_tbl_hdl, ipa_ip_type iptype, uint32_t *flt_rule_hdl) +{ + int len, res = IPACM_SUCCESS; + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL; + +#ifdef FEATURE_IPA_V3 + if (rx_prop == NULL || tx_prop == NULL) + { + IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name); + return IPACM_FAILURE; + } + + 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]); + + 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); + + /* 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]; + + 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 + { + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + + 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; +} + +int IPACM_Lan::eth_bridge_del_flt_rule(uint32_t flt_rule_hdl, ipa_ip_type iptype) +{ + if(m_filtering.DeleteFilteringHdls(&flt_rule_hdl, iptype, 1) == false) + { + IPACMERR("Failed to delete the client specific flt rule.\n"); + return IPACM_FAILURE; + } + return IPACM_SUCCESS; +} + +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) + { + IPACMERR("Failed to delete routing rule.\n"); + return IPACM_FAILURE; + } + return IPACM_SUCCESS; +} + +/* 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; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp new file mode 100644 index 0000000..d77f389 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp @@ -0,0 +1,1262 @@ +/* +Copyright (c) 2014, 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. +*/ +/*! + @file + IPACM_LanToLan.cpp + + @brief + This file implements the functionality of offloading LAN to LAN traffic. + + @Author + Shihuan Liu + +*/ + +#include +#include "IPACM_LanToLan.h" +#include "IPACM_Wlan.h" + +#define __stringify(x...) #x + +const char *ipa_l2_hdr_type[] = { + __stringify(NONE), + __stringify(ETH_II), + __stringify(802_3), + __stringify(L2_MAX) +}; + +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; + 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; + + 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() +{ + 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); + + return; +} + +IPACM_LanToLan::~IPACM_LanToLan() +{ + IPACMDBG_DMESG("WARNING: UNEXPECTEDLY KILL LAN2LAN CONTROLLER!\n"); + return; +} + +void IPACM_LanToLan::event_callback(ipa_cm_event_id event, void* param) +{ + ipacm_event_eth_bridge *data = (ipacm_event_eth_bridge*)param; + IPACMDBG_H("Get %s event.\n", IPACM_Iface::ipacmcfg->getEventName(event)); + + switch(event) + { + case IPA_ETH_BRIDGE_IFACE_UP: + { + handle_iface_up(data); + break; + } + + case IPA_ETH_BRIDGE_IFACE_DOWN: + { + handle_iface_down(data); + break; + } + + case IPA_ETH_BRIDGE_CLIENT_ADD: + { + handle_client_add(data); + break; + } + + case IPA_ETH_BRIDGE_CLIENT_DEL: + { + handle_client_del(data); + break; + } + + case IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH: + { + handle_wlan_scc_mcc_switch(data); + break; + } + default: + break; + } + + print_data_structure_info(); + return; +} + +void IPACM_LanToLan::handle_iface_up(ipacm_event_eth_bridge *data) +{ + list::iterator it; + + 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++) + { + 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); + + /* install intra-BSS rules */ + if(it->get_m_support_intra_iface_offload()) + it->add_all_intra_interface_client_flt_rule(data->iptype); + } + break; + } + } + + if(it == m_iface.end()) //If the interface has not been created before + { + if(m_iface.size() == MAX_NUM_IFACE) + { + IPACMERR("The number of interfaces has reached maximum %d.\n", MAX_NUM_IFACE); + return; + } + + if(!data->p_iface->tx_prop || !data->p_iface->rx_prop) + { + IPACMERR("The interface %s does not have tx_prop or rx_prop.\n", data->p_iface->dev_name); + return; + } + + 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) + { + 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(); + + /* install inter-interface rules */ + if(front_iface.get_m_support_inter_iface_offload()) + { + for(it = ++m_iface.begin(); it != m_iface.end(); it++) + { + /* 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(); + } + } + + /* 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()); + } + return; +} + +void IPACM_LanToLan::handle_iface_down(ipacm_event_eth_bridge *data) +{ + list::iterator it_target_iface; + + 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++) + { + if(it_target_iface->get_iface_pointer() == data->p_iface) + { + IPACMDBG_H("Found the interface.\n"); + break; + } + } + + 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; + } + + it_target_iface->handle_down_event(); + m_iface.erase(it_target_iface); + + return; +} + +void IPACM_LanToLan::handle_new_iface_up(IPACM_LanToLan_Iface *new_iface, IPACM_LanToLan_Iface *exist_iface) +{ + 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]; + + 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); + + /* 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]); + + 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]); + + 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); + + 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; + + 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++) + { + 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); + break; + } + } + + /* if the iface was not found, cache the client add event */ + if(it_iface == m_iface.end()) + { + 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"); + } + } + return; +} + +void IPACM_LanToLan::handle_client_del(ipacm_event_eth_bridge *data) +{ + 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++) + { + 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(it_iface == m_iface.end()) + { + IPACMDBG_H("The interface is not found.\n"); + } + + return; +} + +void IPACM_LanToLan::handle_wlan_scc_mcc_switch(ipacm_event_eth_bridge *data) +{ + list::iterator it_iface; + + 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(it_iface->get_iface_pointer() == data->p_iface) + { + it_iface->handle_wlan_scc_mcc_switch(); + break; + } + } + return; +} + +void IPACM_LanToLan::handle_cached_client_add_event(IPACM_Lan *p_iface) +{ + list::iterator it; + + it = m_cached_client_add_event.begin(); + while(it != m_cached_client_add_event.end()) + { + 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; +} + +void IPACM_LanToLan::clear_cached_client_add_event(IPACM_Lan *p_iface) +{ + list::iterator it; + + it = m_cached_client_add_event.begin(); + while(it != m_cached_client_add_event.end()) + { + 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]); + it = m_cached_client_add_event.erase(it); + } + else + { + it++; + } + } + return; +} + +void IPACM_LanToLan::print_data_structure_info() +{ + list::iterator it; + list::iterator it_event; + int i; + + IPACMDBG_H("There are %d interfaces in total.\n", m_iface.size()); + + for(it = m_iface.begin(); it != m_iface.end(); it++) + { + it->print_data_structure_info(); + } + + IPACMDBG_H("There are %d cached client add events in total.\n", m_cached_client_add_event.size()); + + i = 1; + for(it_event = m_cached_client_add_event.begin(); it_event != m_cached_client_add_event.end(); it_event++) + { + 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++; + } + + 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) + { + for(it = m_client_info.begin(); it != m_client_info.end(); it++) + { + add_client_rt_rule(&peer, &(*it)); + } + } + + return; +} + +void IPACM_LanToLan_Iface::add_client_rt_rule(peer_iface_info *peer_info, client_info *client) +{ + int i, num_rt_rule; + uint32_t rt_rule_hdl[MAX_NUM_PROP]; + ipa_hdr_l2_type peer_l2_hdr_type; + + peer_l2_hdr_type = peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type; + + /* if the peer info is not for intra interface communication */ + if(peer_info->peer != this) + { + 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]; + } + + 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]; + } + } + else + { + 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); + + 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; iintra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][i] = rt_rule_hdl[i]; + } + + 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; iintra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][i] = rt_rule_hdl[i]; + } + } + + 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++) + { + add_client_flt_rule(&(*it_iface), &(*it_client), iptype); + } + } + return; +} + +void IPACM_LanToLan_Iface::add_all_intra_interface_client_flt_rule(ipa_ip_type iptype) +{ + 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++) + { + add_client_flt_rule(&m_intra_interface_info, &(*it_client), iptype); + } + + return; +} + +void IPACM_LanToLan_Iface::add_one_client_flt_rule(IPACM_LanToLan_Iface *peer_iface, client_info *client) +{ + list::iterator it; + + for(it = m_peer_iface_info.begin(); it != m_peer_iface_info.end(); it++) + { + if(it->peer == peer_iface) + { + 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; + } + } + 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; + flt_rule_info new_flt_info; + ipa_ioc_get_rt_tbl rt_tbl; + + 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); + + for(it_flt = peer->flt_rule.begin(); it_flt != peer->flt_rule.end(); it_flt++) + { + if(it_flt->p_client == client) //the client is already in the flt info list + { + IPACMDBG_H("The client is found in flt info list.\n"); + it_flt->flt_rule_hdl[iptype] = flt_rule_hdl; + break; + } + } + + if(it_flt == peer->flt_rule.end()) //the client is not in the flt info list + { + 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; + + peer->flt_rule.push_front(new_flt_info); + } + + return; +} + +void IPACM_LanToLan_Iface::del_one_client_flt_rule(IPACM_LanToLan_Iface *peer_iface, client_info *client) +{ + list::iterator it; + + for(it = m_peer_iface_info.begin(); it != m_peer_iface_info.end(); it++) + { + if(it->peer == peer_iface) + { + IPACMDBG_H("Found the peer iface info.\n"); + del_client_flt_rule(&(*it), client); + break; + } + } + 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++) + { + if(it_flt->p_client == client) //found the client in flt info list + { + IPACMDBG_H("Found the client in flt info list.\n"); + if(m_is_ip_addr_assigned[IPA_IP_v4]) + { + m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4); + IPACMDBG_H("IPv4 flt rule %d is deleted.\n", it_flt->flt_rule_hdl[IPA_IP_v4]); + } + if(m_is_ip_addr_assigned[IPA_IP_v6]) + { + m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6); + IPACMDBG_H("IPv6 flt rule %d is deleted.\n", it_flt->flt_rule_hdl[IPA_IP_v6]); + } + + peer->flt_rule.erase(it_flt); + break; + } + } + return; +} + +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; + + 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("Delete routing rules for inter interface communication.\n"); + + 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; + } + else + { + 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++) + { + 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]); + } + 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++) + { + 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); + } + + /* 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++) + { + if(m_is_ip_addr_assigned[IPA_IP_v4]) + { + m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4); + IPACMDBG_H("IPv4 flt rule %d is deleted.\n", it->flt_rule_hdl[IPA_IP_v4]); + } + if(m_is_ip_addr_assigned[IPA_IP_v6]) + { + m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6); + IPACMDBG_H("IPv6 flt rule %d is deleted.\n", it->flt_rule_hdl[IPA_IP_v6]); + } + } + peer->flt_rule.clear(); + return; +} + +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) + { + for(it = m_client_info.begin(); it != m_client_info.end(); it++) + { + del_client_rt_rule(peer, &(*it)); + } + } + + return; +} + +void IPACM_LanToLan_Iface::handle_wlan_scc_mcc_switch() +{ + 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; + + /* modify inter-interface routing rules */ + if(m_support_inter_iface_offload) + { + 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++) + { + 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) + { + 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]); + } + } + } + } + } + + /* modify routing rules for intra-interface communication */ + IPACMDBG_H("Modify rt rules for intra-interface communication.\n"); + if(m_support_intra_iface_offload) + { + 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_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("%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]); + } + } + } + + return; +} + +void IPACM_LanToLan_Iface::handle_intra_interface_info() +{ + uint32_t hdr_proc_ctx_hdl; + + if(m_p_iface->tx_prop == NULL) + { + IPACMERR("No tx prop.\n"); + return; + } + + 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) +{ + list::iterator it_client; + list::iterator it_peer_info; + client_info new_client; + bool flag[IPA_HDR_L2_MAX]; + + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) + { + if(memcmp(it_client->mac_addr, mac, sizeof(it_client->mac_addr)) == 0) + { + IPACMDBG_H("This client has been added before.\n"); + return; + } + } + + if(m_client_info.size() == MAX_NUM_CLIENT) + { + IPACMDBG_H("The number of clients has reached maximum %d.\n", MAX_NUM_CLIENT); + return; + } + + memcpy(new_client.mac_addr, mac, sizeof(new_client.mac_addr)); + 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) + { + 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++) + { + /* 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 */ + add_client_rt_rule(&(*it_peer_info), &front_client); + 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); + } + } + + /* install intra-interface rules */ + if(m_support_intra_iface_offload) + { + /* 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]) + { + add_client_flt_rule(&m_intra_interface_info, &front_client, IPA_IP_v4); + } + if(m_is_ip_addr_assigned[IPA_IP_v6]) + { + add_client_flt_rule(&m_intra_interface_info, &front_client, IPA_IP_v6); + } + } + + return; +} + +void IPACM_LanToLan_Iface::handle_client_del(uint8_t *mac) +{ + list::iterator it_client; + list::iterator it_peer_info; + bool flag[IPA_HDR_L2_MAX]; + + for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++) + { + if(memcmp(it_client->mac_addr, mac, sizeof(it_client->mac_addr)) == 0) //found the client + { + IPACMDBG_H("Found the client.\n"); + break; + } + } + + if(it_client != m_client_info.end()) //if we found the client + { + /* uninstall inter-interface rules */ + if(m_support_inter_iface_offload) + { + 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("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) + { + IPACMDBG_H("Delete client routing rule for peer interface.\n"); + del_client_rt_rule(&(*it_peer_info), &(*it_client)); + flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] = true; + } + } + } + + /* 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 + { + IPACMDBG_H("The client is not found.\n"); + } + + return; +} + +void IPACM_LanToLan_Iface::add_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_type) +{ + uint32_t hdr_proc_ctx_hdl; + + if(ref_cnt_peer_l2_hdr_type[peer_l2_type] == 1) + { + 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; +} + +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) + { + 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]); + } + return; +} + +void IPACM_LanToLan_Iface::print_data_structure_info() +{ + list::iterator it_peer; + list::iterator it_client; + int i, j, k; + + 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); + + if(m_support_inter_iface_offload) + { + for(i = 0; i < IPA_HDR_L2_MAX; i++) + { + 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) + { + 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(m_support_intra_iface_offload) + { + IPACMDBG_H("Hdr proc ctx for intra-interface: %d\n", hdr_proc_ctx_for_intra_interface); + } + + 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++) + { + 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)); + + if(m_support_inter_iface_offload) + { + for(j = 0; j < IPA_HDR_L2_MAX; j++) + { + if(ref_cnt_peer_l2_hdr_type[j] > 0) + { + 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(m_support_intra_iface_offload) + { + 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]); + } + + 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("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++) + { + print_peer_info(&(*it_peer)); + } + + if(m_support_intra_iface_offload) + { + IPACMDBG_H("This interface supports intra-interface communication, printing info:\n"); + print_peer_info(&m_intra_interface_info); + } + + return; +} + +void IPACM_LanToLan_Iface::print_peer_info(peer_iface_info *peer_info) +{ + list::iterator it_flt; + list::iterator it_rt; + + IPACMDBG_H("Printing peer info for iface %s:\n", peer_info->peer->m_p_iface->dev_name); + + 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++) + { + 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]); + } + if(m_is_ip_addr_assigned[IPA_IP_v6]) + { + IPACMDBG_H("IPv6 %d\n", it_flt->flt_rule_hdl[IPA_IP_v6]); + } + } + + return; +} + +IPACM_Lan* IPACM_LanToLan_Iface::get_iface_pointer() +{ + return m_p_iface; +} + +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]; +} + +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; +} + +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; +} + +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; +} + +void IPACM_LanToLan_Iface::increment_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type) +{ + 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; +} + +void IPACM_LanToLan_Iface::decrement_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type) +{ + 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; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Log.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Log.cpp new file mode 100644 index 0000000..20dd26c --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Log.cpp @@ -0,0 +1,107 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_log.cpp + + @brief + This file implements the IPAM log functionality. + + @Author + Skylar Chang + +*/ +#include "IPACM_Log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void logmessage(int log_level) +{ + return; +} + +/* start IPACMDIAG socket*/ +int create_socket(unsigned int *sockfd) +{ + + if ((*sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) == IPACM_FAILURE) + { + perror("Error creating ipacm_log socket\n"); + return IPACM_FAILURE; + } + + if(fcntl(*sockfd, F_SETFD, FD_CLOEXEC) < 0) + { + perror("Couldn't set ipacm_log Close on Exec\n"); + } + + return IPACM_SUCCESS; +} + +void ipacm_log_send( void * user_data) +{ + ipacm_log_buffer_t ipacm_log_buffer; + int numBytes=0, len; + struct sockaddr_un ipacmlog_socket; + static unsigned int ipacm_log_sockfd = 0; + + if(ipacm_log_sockfd == 0) + { + /* start ipacm_log socket */ + if(create_socket(&ipacm_log_sockfd) < 0) + { + printf("unable to create ipacm_log socket\n"); + return; + } + printf("create ipacm_log socket successfully\n"); + } + ipacmlog_socket.sun_family = AF_UNIX; + strcpy(ipacmlog_socket.sun_path, IPACMLOG_FILE); + len = strlen(ipacmlog_socket.sun_path) + sizeof(ipacmlog_socket.sun_family); + + memcpy(ipacm_log_buffer.user_data, user_data, MAX_BUF_LEN); + + //printf("send : %s\n", ipacm_log_buffer.user_data); + if ((numBytes = sendto(ipacm_log_sockfd, (void *)&ipacm_log_buffer, sizeof(ipacm_log_buffer.user_data), 0, + (struct sockaddr *)&ipacmlog_socket, len)) == -1) + { + printf("Send Failed(%d) %s \n",errno,strerror(errno)); + return; + } + return; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp new file mode 100644 index 0000000..c6ab9ee --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp @@ -0,0 +1,939 @@ +/* +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 +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. +*/ +/*! + @file + IPACM_Main.cpp + + @brief + This file implements the IPAM functionality. + + @Author + Skylar Chang + +*/ +/****************************************************************************** + + IPCM_MAIN.C + +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "linux/ipa_qmi_service_v01.h" + +#include "IPACM_CmdQueue.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Defs.h" +#include "IPACM_Neighbor.h" +#include "IPACM_IfaceManager.h" +#include "IPACM_Log.h" + +#include "IPACM_ConntrackListener.h" +#include "IPACM_ConntrackClient.h" +#include "IPACM_Netlink.h" + +/* not defined(FEATURE_IPA_ANDROID)*/ +#ifndef FEATURE_IPA_ANDROID +#include "IPACM_LanToLan.h" +#endif + +#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_DIR_NAME "/data" +#else/* defined(FEATURE_IPA_ANDROID) */ +#define IPACM_PID_FILE "/etc/ipacm.pid" +#define IPACM_DIR_NAME "/etc" +#endif /* defined(NOT FEATURE_IPA_ANDROID)*/ +#define IPACM_NAME "ipacm" + +#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) +#define INOTIFY_BUF_LEN (INOTIFY_EVENT_SIZE + 2*sizeof(IPACM_FIREWALL_FILE_NAME)) + +#define IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS 3 +#define IPA_DRIVER_WLAN_EVENT_SIZE (sizeof(struct ipa_wlan_msg_ex)+ IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS*sizeof(ipa_wlan_hdr_attrib_val)) +#define IPA_DRIVER_PIPE_STATS_EVENT_SIZE (sizeof(struct ipa_get_data_stats_resp_msg_v01)) +#define IPA_DRIVER_WLAN_META_MSG (sizeof(struct ipa_msg_meta)) +#define IPA_DRIVER_WLAN_BUF_LEN (IPA_DRIVER_PIPE_STATS_EVENT_SIZE + IPA_DRIVER_WLAN_META_MSG) + +uint32_t ipacm_event_stats[IPACM_EVENT_MAX]; +bool ipacm_logging = true; + +void ipa_is_ipacm_running(void); +int ipa_get_if_index(char *if_name, int *if_index); + +/* start netlink socket monitor*/ +void* netlink_start(void *param) +{ + ipa_nl_sk_fd_set_info_t sk_fdset; + int ret_val = 0; + memset(&sk_fdset, 0, sizeof(ipa_nl_sk_fd_set_info_t)); + IPACMDBG_H("netlink starter memset sk_fdset succeeds\n"); + ret_val = ipa_nl_listener_init(NETLINK_ROUTE, (RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK | + RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NEIGH | + RTNLGRP_IPV6_PREFIX), + &sk_fdset, ipa_nl_recv_msg); + + if (ret_val != IPACM_SUCCESS) + { + IPACMERR("Failed to initialize IPA netlink event listener\n"); + return NULL; + } + + return NULL; +} + +/* start firewall-rule monitor*/ +void* firewall_monitor(void *param) +{ + int length; + int wd; + char buffer[INOTIFY_BUF_LEN]; + int inotify_fd; + ipacm_cmd_q_data evt_data; + uint32_t mask = IN_MODIFY | IN_MOVE; + + inotify_fd = inotify_init(); + if (inotify_fd < 0) + { + PERROR("inotify_init"); + } + + IPACMDBG_H("Waiting for nofications in dir %s with mask: 0x%x\n", IPACM_DIR_NAME, mask); + + wd = inotify_add_watch(inotify_fd, + IPACM_DIR_NAME, + mask); + + while (1) + { + length = read(inotify_fd, buffer, INOTIFY_BUF_LEN); + if (length < 0) + { + IPACMERR("inotify read() error return length: %d and mask: 0x%x\n", length, mask); + continue; + } + + struct inotify_event* event; + event = (struct inotify_event*)malloc(length); + if(event == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memset(event, 0, length); + memcpy(event, buffer, length); + + if (event->len > 0) + { + if ( (event->mask & IN_MODIFY) || (event->mask & IN_MOVE)) + { + if (event->mask & IN_ISDIR) + { + IPACMDBG_H("The directory %s was 0x%x\n", event->name, event->mask); + } + else if (!strncmp(event->name, IPACM_FIREWALL_FILE_NAME, event->len)) // firewall_rule change + { + IPACMDBG_H("File \"%s\" was 0x%x\n", event->name, event->mask); + IPACMDBG_H("The interested file %s .\n", IPACM_FIREWALL_FILE_NAME); + + evt_data.event = IPA_FIREWALL_CHANGE_EVENT; + evt_data.evt_data = NULL; + + /* Insert IPA_FIREWALL_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + else if (!strncmp(event->name, IPACM_CFG_FILE_NAME, event->len)) // IPACM_configuration change + { + IPACMDBG_H("File \"%s\" was 0x%x\n", event->name, event->mask); + IPACMDBG_H("The interested file %s .\n", IPACM_CFG_FILE_NAME); + + evt_data.event = IPA_CFG_CHANGE_EVENT; + evt_data.evt_data = NULL; + + /* Insert IPA_FIREWALL_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + } + IPACMDBG_H("Received monitoring event %s.\n", event->name); + } + free(event); + } + + (void)inotify_rm_watch(inotify_fd, wd); + (void)close(inotify_fd); + return NULL; +} + + +/* start IPACM wan-driver notifier */ +void* ipa_driver_msg_notifier(void *param) +{ + int length, fd, cnt; + char buffer[IPA_DRIVER_WLAN_BUF_LEN]; + struct ipa_msg_meta event_hdr; + struct ipa_ecm_msg event_ecm; + struct ipa_wan_msg event_wan; + struct ipa_wlan_msg_ex event_ex_o; + struct ipa_wlan_msg *event_wlan=NULL; + 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_cmd_q_data evt_data; + ipacm_event_data_mac *data = 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; + + ipacm_cmd_q_data new_neigh_evt; + ipacm_event_data_all* new_neigh_data; + + fd = open(IPA_DRIVER, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DRIVER); + return NULL; + } + + while (1) + { + 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; + data_network_stats = NULL; + + length = read(fd, buffer, IPA_DRIVER_WLAN_BUF_LEN); + if (length < 0) + { + PERROR("didn't read IPA_driver correctly"); + continue; + } + + memcpy(&event_hdr, buffer,sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Message type: %d\n", event_hdr.msg_type); + IPACMDBG_H("Event header length received: %d\n",event_hdr.msg_len); + + /* Insert WLAN_DRIVER_EVENT to command queue */ + switch (event_hdr.msg_type) + { + + case SW_ROUTING_ENABLE: + IPACMDBG_H("Received SW_ROUTING_ENABLE\n"); + evt_data.event = IPA_SW_ROUTING_ENABLE; + IPACMDBG_H("Not supported anymore\n"); + continue; + + case SW_ROUTING_DISABLE: + IPACMDBG_H("Received SW_ROUTING_DISABLE\n"); + evt_data.event = IPA_SW_ROUTING_DISABLE; + IPACMDBG_H("Not supported anymore\n"); + continue; + + case WLAN_AP_CONNECT: + event_wlan = (struct ipa_wlan_msg *) (buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_AP_CONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("AP Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wlan->name, &(data_fid->if_index)); + evt_data.event = IPA_WLAN_AP_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + break; + + case WLAN_AP_DISCONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_AP_DISCONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("AP Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wlan->name, &(data_fid->if_index)); + evt_data.event = IPA_WLAN_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + break; + case WLAN_STA_CONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_STA_CONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("STA Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if(data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_STA_LINK_UP_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_STA_DISCONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_STA_DISCONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("STA Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wlan->name, &(data_fid->if_index)); + evt_data.event = IPA_WLAN_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + break; + + case WLAN_CLIENT_CONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_CLIENT_CONNECT\n"); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_CLIENT_ADD_EVENT; + evt_data.evt_data = data; + break; + + 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) + { + IPACMERR("buffer size overflow\n"); + return NULL; + } + length = sizeof(ipa_wlan_msg_ex)+ event_ex_o.num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val); + IPACMDBG_H("num_of_attribs %d, length %d\n", event_ex_o.num_of_attribs, length); + event_ex = (ipa_wlan_msg_ex *)malloc(length); + if(event_ex == NULL ) + { + IPACMERR("Unable to allocate memory\n"); + return NULL; + } + memcpy(event_ex, buffer + sizeof(struct ipa_msg_meta), length); + data_ex = (ipacm_event_data_wlan_ex *)malloc(sizeof(ipacm_event_data_wlan_ex) + event_ex_o.num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val)); + if (data_ex == NULL) + { + IPACMERR("unable to allocate memory for event data\n"); + return NULL; + } + data_ex->num_of_attribs = event_ex->num_of_attribs; + + 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]); + } + else if(event_ex->attribs[cnt].attrib_type == WLAN_HDR_ATTRIB_STA_ID) + { + IPACMDBG_H("Wlan client id %d\n",event_ex->attribs[cnt].u.sta_id); + } + else + { + IPACMDBG_H("Wlan message has unexpected type!\n"); + } + } + 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; + + case WLAN_CLIENT_DISCONNECT: + IPACMDBG_H("Received WLAN_CLIENT_DISCONNECT\n"); + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_CLIENT_DEL_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_CLIENT_POWER_SAVE_MODE: + IPACMDBG_H("Received WLAN_CLIENT_POWER_SAVE_MODE\n"); + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_CLIENT_POWER_SAVE_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_CLIENT_NORMAL_MODE: + IPACMDBG_H("Received WLAN_CLIENT_NORMAL_MODE\n"); + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.evt_data = data; + evt_data.event = IPA_WLAN_CLIENT_RECOVER_EVENT; + break; + + 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)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_fid\n"); + return NULL; + } + data_fid->if_index = event_ecm.ifindex; + evt_data.event = IPA_USB_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + break; + + case ECM_DISCONNECT: + memcpy(&event_ecm, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_ecm_msg)); + IPACMDBG_H("Received ECM_DISCONNECT name: %s\n",event_ecm.name); + 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"); + return NULL; + } + data_fid->if_index = event_ecm.ifindex; + evt_data.event = IPA_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + break; + /* Add for 8994 Android case */ + 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)); + if(data_iptype == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_iptype\n"); + return NULL; + } + 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; + evt_data.evt_data = data_iptype; + break; + 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)); + if(data_iptype == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_iptype\n"); + return NULL; + } + 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; + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_DEL: fid(%d) ip-type(%d)\n", data_iptype->if_index, data_iptype->iptype); + evt_data.event = IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT; + evt_data.evt_data = data_iptype; + break; + /* End of adding for 8994 Android case */ + + /* Add for embms case */ + case WAN_EMBMS_CONNECT: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg)); + IPACMDBG("Received WAN_EMBMS_CONNECT name: %s\n",event_wan.upstream_ifname); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_fid->if_index)); + evt_data.event = IPA_WAN_EMBMS_LINK_UP_EVENT; + 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)); + if(data_tethering_stats == NULL) + { + IPACMERR("unable to allocate memory for event data_tethering_stats\n"); + return NULL; + } + memcpy(data_tethering_stats, + &event_data_stats, + sizeof(struct ipa_get_data_stats_resp_msg_v01)); + IPACMDBG("Received IPA_TETHERING_STATS_UPDATE_STATS ipa_stats_type: %d\n",data_tethering_stats->ipa_stats_type); + IPACMDBG("Received %d UL, %d DL pipe stats\n",data_tethering_stats->ul_src_pipe_stats_list_len, data_tethering_stats->dl_dst_pipe_stats_list_len); + evt_data.event = IPA_TETHERING_STATS_UPDATE_EVENT; + evt_data.evt_data = data_tethering_stats; + break; + + case IPA_TETHERING_STATS_UPDATE_NETWORK_STATS: + memcpy(&event_network_stats, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_get_apn_data_stats_resp_msg_v01)); + data_network_stats = (ipa_get_apn_data_stats_resp_msg_v01 *)malloc(sizeof(ipa_get_apn_data_stats_resp_msg_v01)); + if(data_network_stats == NULL) + { + IPACMERR("unable to allocate memory for event data_network_stats\n"); + return NULL; + } + memcpy(data_network_stats, + &event_network_stats, + sizeof(struct ipa_get_apn_data_stats_resp_msg_v01)); + IPACMDBG("Received %d apn network stats \n", data_network_stats->apn_data_stats_list_len); + evt_data.event = IPA_NETWORK_STATS_UPDATE_EVENT; + evt_data.evt_data = data_network_stats; + break; + + default: + IPACMDBG_H("Unhandled message type: %d\n", event_hdr.msg_type); + continue; + + } + /* 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); + return NULL; +} + +void IPACM_Sig_Handler(int sig) +{ + int cnt; + ipacm_cmd_q_data evt_data; + + printf("Received Signal: %d\n", sig); + memset(&evt_data, 0, sizeof(evt_data)); + + switch(sig) + { + case SIGUSR1: + IPACMDBG_H("Received SW_ROUTING_ENABLE request \n"); + evt_data.event = IPA_SW_ROUTING_ENABLE; + IPACM_Iface::ipacmcfg->ipa_sw_rt_enable = true; + break; + + case SIGUSR2: + IPACMDBG_H("Received SW_ROUTING_DISABLE request \n"); + evt_data.event = IPA_SW_ROUTING_DISABLE; + IPACM_Iface::ipacmcfg->ipa_sw_rt_enable = false; + break; + } + /* finish command queue */ + IPACMDBG_H("Posting event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + return; +} + +void RegisterForSignals(void) +{ + + signal(SIGUSR1, IPACM_Sig_Handler); + signal(SIGUSR2, IPACM_Sig_Handler); +} + + +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; + + /* check if ipacm is already running or not */ + ipa_is_ipacm_running(); + + IPACMDBG_H("In main()\n"); + IPACM_Neighbor *neigh = new IPACM_Neighbor(); + IPACM_IfaceManager *ifacemgr = new IPACM_IfaceManager(); + +#ifdef FEATURE_ETH_BRIDGE_LE + IPACM_LanToLan* lan2lan = new IPACM_LanToLan(); +#endif + + IPACM_ConntrackClient *cc = IPACM_ConntrackClient::GetInstance(); + CtList = new IPACM_ConntrackListener(); + + IPACMDBG_H("Staring IPA main\n"); + IPACMDBG_H("ipa_cmdq_successful\n"); + + + RegisterForSignals(); + + if (IPACM_SUCCESS == cmd_queue_thread) + { + ret = pthread_create(&cmd_queue_thread, NULL, MessageQueue::Process, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to command queue thread\n"); + 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) + { + ret = pthread_create(&netlink_thread, NULL, netlink_start, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to create netlink thread\n"); + 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); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to create monitor thread\n"); + 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_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); + pthread_join(netlink_thread, NULL); + pthread_join(monitor_thread, NULL); + pthread_join(ipa_driver_thread, NULL); + return IPACM_SUCCESS; +} + +/*=========================================================================== + FUNCTION ipa_is_ipacm_running +===========================================================================*/ +/*! +@brief + Determine whether there's already an IPACM process running, if so, terminate + the current one + +@return + None + +@note + +- Dependencies + - None + +- Side Effects + - None +*/ +/*=========================================================================*/ + +void ipa_is_ipacm_running(void) { + + int fd; + struct flock lock; + int retval; + + fd = open(IPACM_PID_FILE, O_RDWR | O_CREAT, 0600); + if ( fd <= 0 ) + { + IPACMERR("Failed to open %s, error is %d - %s\n", + IPACM_PID_FILE, errno, strerror(errno)); + exit(0); + } + + /* + * Getting an exclusive Write lock on the file, if it fails, + * it means that another instance of IPACM is running and it + * got the lock before us. + */ + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + retval = fcntl(fd, F_SETLK, &lock); + + if (retval != 0) + { + retval = fcntl(fd, F_GETLK, &lock); + if (retval == 0) + { + IPACMERR("Unable to get lock on file %s (my PID %d), PID %d already has it\n", + IPACM_PID_FILE, getpid(), lock.l_pid); + close(fd); + exit(0); + } + } + else + { + IPACMERR("PID %d is IPACM main process\n", getpid()); + } + + return; +} + +/*=========================================================================== + FUNCTION ipa_get_if_index +===========================================================================*/ +/*! +@brief + get ipa interface index by given the interface name + +@return + IPACM_SUCCESS or IPA_FALUIRE + +@note + +- Dependencies + - None + +- Side Effects + - None +*/ +/*=========================================================================*/ +int ipa_get_if_index +( + char *if_name, + int *if_index + ) +{ + int fd; + struct ifreq ifr; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + PERROR("get interface index socket create failed"); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + + (void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); + + if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) + { + IPACMERR("call_ioctl_on_dev: ioctl failed: can't find device %s",if_name); + *if_index = -1; + close(fd); + return IPACM_FAILURE; + } + + *if_index = ifr.ifr_ifindex; + close(fd); + return IPACM_SUCCESS; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp new file mode 100644 index 0000000..5a72c4c --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp @@ -0,0 +1,570 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Neighbor.cpp + + @brief + This file implements the functionality of handling IPACM Neighbor events. + + @Author + Skylar Chang + +*/ + +#include +#include +#include +#include "IPACM_Defs.h" +#include "IPACM_Log.h" + + +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); + return; +} + +void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) +{ + ipacm_event_data_all *data_all = NULL; + int i, ipa_interface_index; + ipacm_cmd_q_data evt_data; + int num_neighbor_client_temp = num_neighbor_client; + + IPACMDBG("Recieved event %d\n", event); + + switch (event) + { + case IPA_WLAN_CLIENT_ADD_EVENT_EX: + { + ipacm_event_data_wlan_ex *data = (ipacm_event_data_wlan_ex *)param; + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index); + /* 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]; + + IPACMDBG_H("Received IPA_WLAN_CLIENT_ADD_EVENT\n"); + for(i = 0; i < data->num_of_attribs; i++) + { + if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + memcpy(client_mac_addr, + data->attribs[i].u.mac_addr, + sizeof(client_mac_addr)); + IPACMDBG_H("AP Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + client_mac_addr[0], client_mac_addr[1], client_mac_addr[2], + client_mac_addr[3], client_mac_addr[4], client_mac_addr[5]); + } + else + { + IPACMDBG_H("The attribute type is not expected!\n"); + } + } + + for (i = 0; i < num_neighbor_client_temp; i++) + { + /* find the client */ + if (memcmp(neighbor_client[i].mac_addr, client_mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + { + /* 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) + { + /* use previous ipv4 first */ + if(data->if_index != neighbor_client[i].iface_index) + { + IPACMERR("update new kernel iface index \n"); + neighbor_client[i].iface_index = data->if_index; + } + + /* 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; + } + + if (neighbor_client[i].v4_addr != 0) /* not 0.0.0.0 */ + { + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if (data_all == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + 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)); + 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); + /* 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, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + } + } + } + break; + } + } + } + break; + + 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); + /* check for failure return */ + if (IPACM_FAILURE == ipa_interface_index) { + IPACMERR("not supported iface id: %d\n", data->if_index); + break; + } + if (data->iptype == IPA_IP_v4) + { + if (data->ipv4_addr != 0) /* not 0.0.0.0 */ + { + 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) + { + /* searh if seen this client or not*/ + for (i = 0; i < num_neighbor_client_temp; i++) + { + 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; + 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) + { + 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); + + /* ask for replaced iface name*/ + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); + /* 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, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].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; + /* 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) + { + /* 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; + } + } + /* not find client */ + if (i == num_neighbor_client_temp) + { + 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; + 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], + neighbor_client[num_neighbor_client_temp].mac_addr[3], + neighbor_client[num_neighbor_client_temp].mac_addr[4], + neighbor_client[num_neighbor_client_temp].mac_addr[5], + num_neighbor_client); + } + 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; + 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++; + } + } + } + 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++) + { + /* 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; + 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; + } + 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, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + } + } + } + else + { //ipv6 starts + + 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"); + /* 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) + { + /* searh if seen this client or not*/ + for (i = 0; i < num_neighbor_client_temp; i++) + { + 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; + /* 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); + /* ask for replaced iface name*/ + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); + /* 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, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].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 ipv6\n", + evt_data.event, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + } + } + else + { + 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) + { + /* use previous ipv4 first */ + if(data->if_index != neighbor_client[i].iface_index) + { + IPACMDBG_H("update new kernel iface index \n"); + neighbor_client[i].iface_index = data->if_index; + } + + /* check if client associated with previous network interface */ + if(ipa_interface_index != neighbor_client[i].ipa_if_num) + { + IPACMDBG_H("client associate to different AP \n"); + } + + if (neighbor_client[i].v4_addr != 0) /* not 0.0.0.0 */ + { + /* 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; + } + 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)); + 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); + /* 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, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].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; + 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; + } + 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) && (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 (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 = 0; + 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], + neighbor_client[num_neighbor_client_temp].mac_addr[3], + neighbor_client[num_neighbor_client_temp].mac_addr[4], + neighbor_client[num_neighbor_client_temp].mac_addr[5], + 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; + 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++; + return; + } + } + } + } + } //ipv6 ends + } + break; + } + return; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp new file mode 100644 index 0000000..30295b1 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp @@ -0,0 +1,1773 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Netlink.cpp + + @brief + This file implements the IPAM Netlink Socket Parer functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include "IPACM_CmdQueue.h" +#include "IPACM_Defs.h" +#include "IPACM_Netlink.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Log.h" + +int ipa_get_if_name(char *if_name, int if_index); +int find_mask(int ip_v4_last, int *mask_value); + +#ifdef FEATURE_IPA_ANDROID + +#define IPACM_NL_COPY_ADDR( event_info, element ) \ + memcpy( &event_info->attr_info.element.__data, \ + RTA_DATA(rtah), \ + sizeof(event_info->attr_info.element.__data) ); + +#define IPACM_EVENT_COPY_ADDR_v6( event_data, element) \ + memcpy( event_data, element.__data, sizeof(event_data)); + +#define IPACM_EVENT_COPY_ADDR_v4( event_data, element) \ + memcpy( &event_data, element.__data, sizeof(event_data)); + +#define IPACM_NL_REPORT_ADDR( prefix, addr ) \ + if( AF_INET6 == (addr).ss_family ) { \ + IPACM_LOG_IPV6_ADDR( prefix, addr.__data); \ + } else { \ + IPACM_LOG_IPV4_ADDR( prefix, (*(unsigned int*)&(addr).__data) ); \ + } + +#else/* defined(FEATURE_IPA_ANDROID) */ + +#define IPACM_NL_COPY_ADDR( event_info, element ) \ + memcpy( &event_info->attr_info.element.__ss_padding, \ + RTA_DATA(rtah), \ + sizeof(event_info->attr_info.element.__ss_padding) ); + +#define IPACM_EVENT_COPY_ADDR_v6( event_data, element) \ + memcpy( event_data, element.__ss_padding, sizeof(event_data)); + +#define IPACM_EVENT_COPY_ADDR_v4( event_data, element) \ + memcpy( &event_data, element.__ss_padding, sizeof(event_data)); + +#define IPACM_NL_REPORT_ADDR( prefix, addr ) \ + if( AF_INET6 == (addr).ss_family ) { \ + IPACM_LOG_IPV6_ADDR( prefix, addr.__ss_padding); \ + } else { \ + IPACM_LOG_IPV4_ADDR( prefix, (*(unsigned int*)&(addr).__ss_padding) ); \ + } +#endif /* defined(FEATURE_IPA_ANDROID)*/ + +#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#define IPACM_LOG_IPV6_ADDR(prefix, ip_addr) \ + IPACMDBG_H(prefix); \ + IPACMDBG_H(" IPV6 Address %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", \ + (int)ip_addr[0], (int)ip_addr[1], \ + (int)ip_addr[2], (int)ip_addr[3], \ + (int)ip_addr[4], (int)ip_addr[5], \ + (int)ip_addr[6], (int)ip_addr[7], \ + (int)ip_addr[8], (int)ip_addr[9], \ + (int)ip_addr[10], (int)ip_addr[11], \ + (int)ip_addr[12], (int)ip_addr[13], \ + (int)ip_addr[14], (int)ip_addr[15]); + +#define IPACM_LOG_IPV4_ADDR(prefix, ip_addr) \ + IPACMDBG_H(prefix); \ + IPACMDBG_H(" IPV4 Address %d.%d.%d.%d\n", \ + (unsigned char)(ip_addr), \ + (unsigned char)(ip_addr >> 8), \ + (unsigned char)(ip_addr >> 16) , \ + (unsigned char)(ip_addr >> 24)); + +/* Opens a netlink socket*/ +static int ipa_nl_open_socket +( + ipa_nl_sk_info_t *sk_info, + int protocol, + unsigned int grps + ) +{ + int *p_sk_fd; + int buf_size = 6669999, sendbuff=0, res; + struct sockaddr_nl *p_sk_addr_loc; + socklen_t optlen; + + p_sk_fd = &(sk_info->sk_fd); + p_sk_addr_loc = &(sk_info->sk_addr_loc); + + /* Open netlink socket for specified protocol */ + if((*p_sk_fd = socket(AF_NETLINK, SOCK_RAW, protocol)) < 0) + { + IPACMERR("cannot open netlink socket\n"); + return IPACM_FAILURE; + } + + optlen = sizeof(sendbuff); + res = getsockopt(*p_sk_fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen); + + if(res == -1) { + IPACMDBG("Error getsockopt one"); + } else { + IPACMDBG("orignal send buffer size = %d\n", sendbuff); + } + IPACMDBG("sets the send buffer to %d\n", buf_size); + if (setsockopt(*p_sk_fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(int)) == -1) { + IPACMERR("Error setting socket opts\n"); + } + + /* Initialize socket addresses to null */ + memset(p_sk_addr_loc, 0, sizeof(struct sockaddr_nl)); + + /* Populate local socket address using specified groups */ + p_sk_addr_loc->nl_family = AF_NETLINK; + p_sk_addr_loc->nl_pid = getpid(); + p_sk_addr_loc->nl_groups = grps; + + /* Bind socket to the local address, i.e. specified groups. This ensures + that multicast messages for these groups are delivered over this + socket. */ + + if(bind(*p_sk_fd, + (struct sockaddr *)p_sk_addr_loc, + sizeof(struct sockaddr_nl)) < 0) + { + IPACMERR("Socket bind failed\n"); + return IPACM_FAILURE; + } + + return IPACM_SUCCESS; +} + +/* Add fd to fdmap array and store read handler function ptr (up to MAX_NUM_OF_FD).*/ +static int ipa_nl_addfd_map +( + ipa_nl_sk_fd_set_info_t *info, + int fd, + ipa_sock_thrd_fd_read_f read_f + ) +{ + if(info->num_fd < MAX_NUM_OF_FD) + { + FD_SET(fd, &info->fdset); + + /* Add fd to fdmap array and store read handler function ptr */ + info->sk_fds[info->num_fd].sk_fd = fd; + info->sk_fds[info->num_fd].read_func = read_f; + + /* Increment number of fds stored in fdmap */ + info->num_fd++; + if(info->max_fd < fd) + info->max_fd = fd; + } + else + { + return IPACM_FAILURE; + } + + return IPACM_SUCCESS; +} + +/* start socket listener */ +static int ipa_nl_sock_listener_start +( + ipa_nl_sk_fd_set_info_t *sk_fd_set + ) +{ + int i, ret; + + while(true) + { + for(i = 0; i < sk_fd_set->num_fd; i++ ) + { + FD_SET(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset)); + } + + if((ret = select(sk_fd_set->max_fd + 1, &(sk_fd_set->fdset), NULL, NULL, NULL)) < 0) + { + IPACMERR("ipa_nl select failed\n"); + } + else + { + for(i = 0; i < sk_fd_set->num_fd; i++) + { + + if(FD_ISSET(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset))) + { + + if(sk_fd_set->sk_fds[i].read_func) + { + if(IPACM_SUCCESS != ((sk_fd_set->sk_fds[i].read_func)(sk_fd_set->sk_fds[i].sk_fd))) + { + IPACMERR("Error on read callback[%d] fd=%d\n", + i, + sk_fd_set->sk_fds[i].sk_fd); + } + FD_CLR(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset)); + } + else + { + IPACMERR("No read function\n"); + } + } + + } /* end of for loop*/ + } /* end of else */ + } /* end of while */ + + return IPACM_SUCCESS; +} + +/* allocate memory for ipa_nl__msg */ +static struct msghdr* ipa_nl_alloc_msg +( + uint32_t msglen + ) +{ + unsigned char *buf = NULL; + struct sockaddr_nl *nladdr = NULL; + struct iovec *iov = NULL; + struct msghdr *msgh = NULL; + + if(IPA_NL_MSG_MAX_LEN < msglen) + { + IPACMERR("Netlink message exceeds maximum length\n"); + return NULL; + } + + msgh = (struct msghdr *)malloc(sizeof(struct msghdr)); + if(msgh == NULL) + { + IPACMERR("Failed malloc for msghdr\n"); + return NULL; + } + + nladdr = (struct sockaddr_nl *)malloc(sizeof(struct sockaddr_nl)); + if(nladdr == NULL) + { + IPACMERR("Failed malloc for sockaddr\n"); + free(msgh); + return NULL; + } + + iov = (struct iovec *)malloc(sizeof(struct iovec)); + if(iov == NULL) + { + PERROR("Failed malloc for iovec"); + free(nladdr); + free(msgh); + return NULL; + } + + buf = (unsigned char *)malloc(msglen); + if(buf == NULL) + { + IPACMERR("Failed malloc for mglen\n"); + free(iov); + free(nladdr); + free(msgh); + return NULL; + } + + memset(nladdr, 0, sizeof(struct sockaddr_nl)); + nladdr->nl_family = AF_NETLINK; + + memset(msgh, 0x0, sizeof(struct msghdr)); + msgh->msg_name = nladdr; + msgh->msg_namelen = sizeof(struct sockaddr_nl); + msgh->msg_iov = iov; + msgh->msg_iovlen = 1; + + memset(iov, 0x0, sizeof(struct iovec)); + iov->iov_base = buf; + iov->iov_len = msglen; + + return msgh; +} + +/* release IPA message */ +static void ipa_nl_release_msg +( + struct msghdr *msgh + ) +{ + unsigned char *buf = NULL; + struct sockaddr_nl *nladdr = NULL; + struct iovec *iov = NULL; + + if(NULL == msgh) + { + return; + } + + nladdr = (struct sockaddr_nl *)msgh->msg_name; + iov = msgh->msg_iov; + if(msgh->msg_iov) + { + buf = (unsigned char *)msgh->msg_iov->iov_base; + } + + if(buf) + { + free(buf); + } + if(iov) + { + free(iov); + } + if(nladdr) + { + free(nladdr); + } + if(msgh) + { + free(msgh); + } + return; +} + +/* receive and process nl message */ +static int ipa_nl_recv +( + int fd, + struct msghdr **msg_pptr, + unsigned int *msglen_ptr + ) +{ + struct msghdr *msgh = NULL; + int rmsgl; + + msgh = ipa_nl_alloc_msg(IPA_NL_MSG_MAX_LEN); + if(NULL == msgh) + { + IPACMERR("Failed to allocate NL message\n"); + goto error; + } + + + /* Receive message over the socket */ + rmsgl = recvmsg(fd, msgh, 0); + + /* Verify that something was read */ + if(rmsgl <= 0) + { + PERROR("NL recv error"); + goto error; + } + + /* Verify that NL address length in the received message is expected value */ + if(sizeof(struct sockaddr_nl) != msgh->msg_namelen) + { + IPACMERR("rcvd msg with namelen != sizeof sockaddr_nl\n"); + goto error; + } + + /* Verify that message was not truncated. This should not occur */ + if(msgh->msg_flags & MSG_TRUNC) + { + IPACMERR("Rcvd msg truncated!\n"); + goto error; + } + + *msg_pptr = msgh; + *msglen_ptr = rmsgl; + + return IPACM_SUCCESS; + +/* An error occurred while receiving the message. Free all memory before + returning. */ +error: + ipa_nl_release_msg(msgh); + *msg_pptr = NULL; + *msglen_ptr = 0; + + return IPACM_FAILURE; +} + +/* decode the rtm netlink message */ +static int ipa_nl_decode_rtm_link +( + const char *buffer, + unsigned int buflen, + ipa_nl_link_info_t *link_info +) +{ + struct rtattr; + /* NL message header */ + struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; + + /* Extract the header data */ + link_info->metainfo = *(struct ifinfomsg *)NLMSG_DATA(nlh); + buflen -= sizeof(struct nlmsghdr); + + return IPACM_SUCCESS; +} + +/* Decode kernel address message parameters from Netlink attribute TLVs. */ +static int ipa_nl_decode_rtm_addr +( + const char *buffer, + unsigned int buflen, + ipa_nl_addr_info_t *addr_info + ) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; /* NL message header */ + struct rtattr *rtah = NULL; + + /* Extract the header data */ + addr_info->metainfo = *((struct ifaddrmsg *)NLMSG_DATA(nlh)); + buflen -= sizeof(struct nlmsghdr); + + /* Extract the available attributes */ + addr_info->attr_info.param_mask = IPA_NLA_PARAM_NONE; + + rtah = IFA_RTA(NLMSG_DATA(nlh)); + + while(RTA_OK(rtah, buflen)) + { + switch(rtah->rta_type) + { + + case IFA_ADDRESS: + addr_info->attr_info.prefix_addr.ss_family = addr_info->metainfo.ifa_family; + IPACM_NL_COPY_ADDR( addr_info, prefix_addr ); + addr_info->attr_info.param_mask |= IPA_NLA_PARAM_PREFIXADDR; + break; + default: + break; + + } + /* Advance to next attribute */ + rtah = RTA_NEXT(rtah, buflen); + } + + return IPACM_SUCCESS; +} + +/* Decode kernel neighbor message parameters from Netlink attribute TLVs. */ +static int ipa_nl_decode_rtm_neigh +( + const char *buffer, + unsigned int buflen, + ipa_nl_neigh_info_t *neigh_info + ) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; /* NL message header */ + struct rtattr *rtah = NULL; + + /* Extract the header data */ + neigh_info->metainfo = *((struct ndmsg *)NLMSG_DATA(nlh)); + buflen -= sizeof(struct nlmsghdr); + + /* Extract the available attributes */ + neigh_info->attr_info.param_mask = IPA_NLA_PARAM_NONE; + + rtah = NDA_RTA(NLMSG_DATA(nlh)); + + while(RTA_OK(rtah, buflen)) + { + switch(rtah->rta_type) + { + + case NDA_DST: + neigh_info->attr_info.local_addr.ss_family = neigh_info->metainfo.ndm_family; + IPACM_NL_COPY_ADDR( neigh_info, local_addr ); + break; + + case NDA_LLADDR: + memcpy(neigh_info->attr_info.lladdr_hwaddr.sa_data, + RTA_DATA(rtah), + sizeof(neigh_info->attr_info.lladdr_hwaddr.sa_data)); + break; + + default: + break; + + } + + /* Advance to next attribute */ + rtah = RTA_NEXT(rtah, buflen); + } + + return IPACM_SUCCESS; +} + +/* Decode kernel route message parameters from Netlink attribute TLVs. */ +static int ipa_nl_decode_rtm_route +( + const char *buffer, + unsigned int buflen, + ipa_nl_route_info_t *route_info + ) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; /* NL message header */ + struct rtattr *rtah = NULL; + + /* Extract the header data */ + route_info->metainfo = *((struct rtmsg *)NLMSG_DATA(nlh)); + buflen -= sizeof(struct nlmsghdr); + + route_info->attr_info.param_mask = IPA_RTA_PARAM_NONE; + rtah = RTM_RTA(NLMSG_DATA(nlh)); + + while(RTA_OK(rtah, buflen)) + { + switch(rtah->rta_type) + { + + case RTA_DST: + route_info->attr_info.dst_addr.ss_family = route_info->metainfo.rtm_family; + IPACM_NL_COPY_ADDR( route_info, dst_addr ); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_DST; + break; + + case RTA_SRC: + route_info->attr_info.src_addr.ss_family = route_info->metainfo.rtm_family; + IPACM_NL_COPY_ADDR( route_info, src_addr ); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_SRC; + break; + + case RTA_GATEWAY: + route_info->attr_info.gateway_addr.ss_family = route_info->metainfo.rtm_family; + IPACM_NL_COPY_ADDR( route_info, gateway_addr ); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_GATEWAY; + break; + + case RTA_IIF: + memcpy(&route_info->attr_info.iif_index, + RTA_DATA(rtah), + sizeof(route_info->attr_info.iif_index)); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_IIF; + break; + + case RTA_OIF: + memcpy(&route_info->attr_info.oif_index, + RTA_DATA(rtah), + sizeof(route_info->attr_info.oif_index)); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_OIF; + break; + + case RTA_PRIORITY: + memcpy(&route_info->attr_info.priority, + RTA_DATA(rtah), + sizeof(route_info->attr_info.priority)); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_PRIORITY; + break; + + default: + break; + + } + + /* Advance to next attribute */ + rtah = RTA_NEXT(rtah, buflen); + } + + return IPACM_SUCCESS; +} + +/* decode the ipa nl-message */ +static int ipa_nl_decode_nlmsg +( + const char *buffer, + unsigned int buflen, + ipa_nl_msg_t *msg_ptr + ) +{ + char dev_name[IF_NAME_LEN]={0}; + 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, if_ipv4_addr_gw =0; + + ipacm_cmd_q_data evt_data; + ipacm_event_data_all *data_all; + ipacm_event_data_fid *data_fid; + ipacm_event_data_addr *data_addr; + + + while(NLMSG_OK(nlh, buflen)) + { + memset(dev_name,0,IF_NAME_LEN); + IPACMDBG("Received msg:%d from netlink\n", nlh->nlmsg_type) + switch(nlh->nlmsg_type) + { + case RTM_NEWLINK: + msg_ptr->type = nlh->nlmsg_type; + msg_ptr->link_event = true; + if(IPACM_SUCCESS != ipa_nl_decode_rtm_link(buffer, buflen, &(msg_ptr->nl_link_info))) + { + IPACMERR("Failed to decode rtm link message\n"); + return IPACM_FAILURE; + } + else + { + IPACMDBG("Got RTM_NEWLINK with below values\n"); + IPACMDBG("RTM_NEWLINK, ifi_change:%d\n", msg_ptr->nl_link_info.metainfo.ifi_change); + 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"); + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; + + if(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_UP) + { + IPACMDBG_H("Interface %s bring up with IP-family: %d \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_family); + /* post link up to command queue */ + evt_data.event = IPA_LINK_UP_EVENT; + IPACMDBG_H("Posting IPA_LINK_UP_EVENT with if index: %d\n", + msg_ptr->nl_link_info.metainfo.ifi_index); + } + else + { + IPACMDBG_H("Interface %s bring down with IP-family: %d \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_family); + /* post link down to command queue */ + evt_data.event = IPA_LINK_DOWN_EVENT; + IPACMDBG_H("Posting IPA_LINK_DOWN_EVENT with if index: %d\n", + data_fid->if_index); + } + evt_data.evt_data = data_fid; + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + + /* 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)) + { + + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; + + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); + if(ret_val != IPACM_SUCCESS) + { + 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); + + /*-------------------------------------------------------------------------- + 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_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)) + { + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; + + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + 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; + 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); + } + } + break; + + case RTM_DELLINK: + IPACMDBG("\n GOT dellink event\n"); + msg_ptr->type = nlh->nlmsg_type; + msg_ptr->link_event = true; + IPACMDBG("entering rtm decode\n"); + if(IPACM_SUCCESS != ipa_nl_decode_rtm_link(buffer, buflen, &(msg_ptr->nl_link_info))) + { + IPACMERR("Failed to decode rtm link message\n"); + return IPACM_FAILURE; + } + else + { + IPACMDBG("Got RTM_DELLINK with below values\n"); + IPACMDBG("RTM_DELLINK, ifi_change:%d\n", msg_ptr->nl_link_info.metainfo.ifi_change); + 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) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + IPACMDBG("Interface %s bring down \n", dev_name); + + /* post link down to command queue */ + evt_data.event = IPA_LINK_DOWN_EVENT; + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + + data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; + + IPACMDBG_H("posting IPA_LINK_DOWN_EVENT with if idnex:%d\n", + data_fid->if_index); + evt_data.evt_data = data_fid; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + break; + + case RTM_NEWADDR: + IPACMDBG("\n GOT RTM_NEWADDR event\n"); + if(IPACM_SUCCESS != ipa_nl_decode_rtm_addr(buffer, buflen, &(msg_ptr->nl_addr_info))) + { + IPACMERR("Failed to decode rtm addr message\n"); + return IPACM_FAILURE; + } + else + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_addr_info.metainfo.ifa_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + } + IPACMDBG("Interface %s \n", dev_name); + + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family) + { + data_addr->iptype = IPA_IP_v6; + IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr ); + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_addr_info.attr_info.prefix_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]); + } + else + { + data_addr->iptype = IPA_IP_v4; + IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr ); + IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr, msg_ptr->nl_addr_info.attr_info.prefix_addr); + data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr); + + } + + evt_data.event = IPA_ADDR_ADD_EVENT; + data_addr->if_index = msg_ptr->nl_addr_info.metainfo.ifa_index; + 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", + data_addr->if_index, + data_addr->ipv6_addr[0], + data_addr->ipv6_addr[1], + data_addr->ipv6_addr[2], + data_addr->ipv6_addr[3]); + } + else + { + IPACMDBG("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv4 addr:0x%x\n", + data_addr->if_index, + data_addr->ipv4_addr); + } + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + break; + + case RTM_NEWROUTE: + + if(IPACM_SUCCESS != ipa_nl_decode_rtm_route(buffer, buflen, &(msg_ptr->nl_route_info))) + { + IPACMERR("Failed to decode rtm route message\n"); + return IPACM_FAILURE; + } + + IPACMDBG("In case RTM_NEWROUTE\n"); + 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); + IPACMDBG("rtm_family: %d\n", msg_ptr->nl_route_info.metainfo.rtm_family); + IPACMDBG("param_mask: 0x%x\n", msg_ptr->nl_route_info.attr_info.param_mask); + + /* 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_RA)) && + (msg_ptr->nl_route_info.metainfo.rtm_scope == RT_SCOPE_UNIVERSE) && + (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) + { + IPACMDBG("\n GOT RTM_NEWROUTE event\n"); + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + IPACM_NL_REPORT_ADDR( "route add -host", msg_ptr->nl_route_info.attr_info.dst_addr ); + IPACM_NL_REPORT_ADDR( "gw", msg_ptr->nl_route_info.attr_info.gateway_addr ); + IPACMDBG("dev %s\n",dev_name ); + /* insert to command queue */ + IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + temp = (-1); + + evt_data.event = IPA_ROUTE_ADD_EVENT; + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + 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_mask = ntohl(if_ipipv4_addr_mask); + + IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv4 address 0x%x, mask:0x%x\n", + data_addr->if_index, + data_addr->ipv4_addr, + data_addr->ipv4_addr_mask); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + + } + else + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + if(AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) + { + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_PRIORITY) + { + IPACMDBG_H("ip -6 route add default dev %s metric %d\n", + dev_name, + msg_ptr->nl_route_info.attr_info.priority); + } + else + { + IPACMDBG_H("ip -6 route add default dev %s\n", dev_name); + } + + 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); + + 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; + + IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 address\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + + } + else + { + IPACM_NL_REPORT_ADDR( "route add default gw \n", msg_ptr->nl_route_info.attr_info.gateway_addr ); + IPACMDBG_H("dev %s \n", dev_name); + IPACM_NL_REPORT_ADDR( "dstIP:", msg_ptr->nl_route_info.attr_info.dst_addr ); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + 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, 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_gw); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + } + } + + /* ipv6 routing table */ + if((AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) && + (msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && + (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_KERNEL) && + (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) + { + IPACMDBG("\n GOT valid v6-RTM_NEWROUTE event\n"); + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) + { + IPACM_NL_REPORT_ADDR( "Route ADD DST:", msg_ptr->nl_route_info.attr_info.dst_addr ); + IPACMDBG("%d, metric %d, dev %s\n", + msg_ptr->nl_route_info.metainfo.rtm_dst_len, + msg_ptr->nl_route_info.attr_info.priority, + dev_name); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + 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]); + + mask_value_v6 = msg_ptr->nl_route_info.metainfo.rtm_dst_len; + for(mask_index = 0; mask_index < 4; mask_index++) + { + if(mask_value_v6 >= 32) + { + mask_v6(32, &data_addr->ipv6_addr_mask[mask_index]); + mask_value_v6 -= 32; + } + else + { + mask_v6(mask_value_v6, &data_addr->ipv6_addr_mask[mask_index]); + mask_value_v6 = 0; + } + } + + IPACMDBG("ADD IPV6 MASK %d: %08x:%08x:%08x:%08x \n", + msg_ptr->nl_route_info.metainfo.rtm_dst_len, + data_addr->ipv6_addr_mask[0], + data_addr->ipv6_addr_mask[1], + data_addr->ipv6_addr_mask[2], + data_addr->ipv6_addr_mask[3]); + + 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]); + + 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; + + IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 addr\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_GATEWAY) + { + IPACM_NL_REPORT_ADDR( "Route ADD ::/0 Next Hop:", msg_ptr->nl_route_info.attr_info.gateway_addr ); + IPACMDBG(" metric %d, dev %s\n", + msg_ptr->nl_route_info.attr_info.priority, + dev_name); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + 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]); + + 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; + + IPACMDBG("posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 address\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + } + break; + + case RTM_DELROUTE: + if(IPACM_SUCCESS != ipa_nl_decode_rtm_route(buffer, buflen, &(msg_ptr->nl_route_info))) + { + IPACMERR("Failed to decode rtm route message\n"); + return IPACM_FAILURE; + } + /* 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_RA)) && + (msg_ptr->nl_route_info.metainfo.rtm_scope == 0) && + (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) + { + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + IPACM_NL_REPORT_ADDR( "route del -host ", msg_ptr->nl_route_info.attr_info.dst_addr); + IPACM_NL_REPORT_ADDR( " gw ", msg_ptr->nl_route_info.attr_info.gateway_addr); + IPACMDBG("dev %s\n", dev_name); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + temp = (-1); + if_ipipv4_addr_mask = ntohl(temp); + + evt_data.event = IPA_ROUTE_DEL_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_mask = ntohl(if_ipipv4_addr_mask); + + IPACMDBG_H("Posting event IPA_ROUTE_DEL_EVENT with if index:%d, ipv4 address 0x%x, mask:0x%x\n", + data_addr->if_index, + data_addr->ipv4_addr, + data_addr->ipv4_addr_mask); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + else + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + if(AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) + { + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_PRIORITY) + { + IPACMDBG("ip -6 route del default dev %s metric %d\n", + dev_name, + msg_ptr->nl_route_info.attr_info.priority); + } + else + { + 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); + 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 + { + IPACM_NL_REPORT_ADDR( "route del default gw", msg_ptr->nl_route_info.attr_info.gateway_addr); + IPACMDBG("dev %s\n", dev_name); + + IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr); + + IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); + data_addr->ipv4_addr_mask = ntohl(data_addr->ipv4_addr_mask); + + data_addr->iptype = IPA_IP_v4; + } + + evt_data.event = IPA_ROUTE_DEL_EVENT; + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + + IPACMDBG_H("Posting IPA_ROUTE_DEL_EVENT with if index:%d\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + } + + /* ipv6 routing table */ + if((AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) && + (msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && + (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_KERNEL) && + (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) + { + IPACMDBG("\n GOT valid v6-RTM_DELROUTE event\n"); + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name"); + return IPACM_FAILURE; + } + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) + { + IPACM_NL_REPORT_ADDR( "DEL", msg_ptr->nl_route_info.attr_info.dst_addr); + IPACMDBG("/%d, metric %d, dev %s\n", + msg_ptr->nl_route_info.metainfo.rtm_dst_len, + msg_ptr->nl_route_info.attr_info.priority, + dev_name); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + 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]); + + mask_value_v6 = msg_ptr->nl_route_info.metainfo.rtm_dst_len; + for(mask_index = 0; mask_index < 4; mask_index++) + { + IPACMDBG("%dst %d \n", + mask_index, + mask_value_v6); + if(mask_value_v6 >= 32) + { + mask_v6(32, &data_addr->ipv6_addr_mask[mask_index]); + mask_value_v6 -= 32; + IPACMDBG("%dst: %08x \n", + mask_index, + data_addr->ipv6_addr_mask[mask_index]); + } + else + { + mask_v6(mask_value_v6, data_addr->ipv6_addr_mask); + mask_value_v6 = 0; + IPACMDBG("%dst: %08x \n", + mask_index, + data_addr->ipv6_addr_mask[mask_index]); + } + } + + IPACMDBG("DEL IPV6 MASK 0st: %08x ", + data_addr->ipv6_addr_mask[0]); + IPACMDBG("1st: %08x ", + data_addr->ipv6_addr_mask[1]); + IPACMDBG("2st: %08x ", + data_addr->ipv6_addr_mask[2]); + IPACMDBG("3st: %08x \n", + data_addr->ipv6_addr_mask[3]); + + 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]); + + evt_data.event = IPA_ROUTE_DEL_EVENT; + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + data_addr->iptype = IPA_IP_v6; + + IPACMDBG_H("posting event IPA_ROUTE_DEL_EVENT with if index:%d, ipv4 address\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + } + break; + + case RTM_NEWNEIGH: + if(IPACM_SUCCESS != ipa_nl_decode_rtm_neigh(buffer, buflen, &(msg_ptr->nl_neigh_info))) + { + IPACMERR("Failed to decode rtm neighbor message\n"); + return IPACM_FAILURE; + } + + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_neigh_info.metainfo.ndm_ifindex); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface index\n"); + return IPACM_FAILURE; + } + else + { + 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 */ + 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) + { + 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; + } + else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET) + { + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); + IPACM_EVENT_COPY_ADDR_v4( data_all->ipv4_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); + data_all->ipv4_addr = ntohl(data_all->ipv4_addr); + data_all->iptype = IPA_IP_v4; + } + else + { + data_all->iptype = IPA_IP_v6; + } + + IPACMDBG("NDA_LLADDR:MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[0], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[1], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[2], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[3], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[4], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[5]); + + + memcpy(data_all->mac_addr, + msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data, + sizeof(data_all->mac_addr)); + data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex; + /* 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 */ + break; + + case RTM_DELNEIGH: + if(IPACM_SUCCESS != ipa_nl_decode_rtm_neigh(buffer, buflen, &(msg_ptr->nl_neigh_info))) + { + IPACMERR("Failed to decode rtm neighbor message\n"); + return IPACM_FAILURE; + } + + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_neigh_info.metainfo.ndm_ifindex); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface index\n"); + return IPACM_FAILURE; + } + else + { + IPACMDBG("\n GOT RTM_DELNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); + } + + /* 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) + { + 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; + } + else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET) + { + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); + IPACM_EVENT_COPY_ADDR_v4( data_all->ipv4_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); + data_all->ipv4_addr = ntohl(data_all->ipv4_addr); + data_all->iptype = IPA_IP_v4; + } + else + { + data_all->iptype = IPA_IP_v6; + } + + IPACMDBG("NDA_LLADDR:MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[0], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[1], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[2], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[3], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[4], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[5]); + + 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_DEL_NEIGH_EVENT; + data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex; + + IPACMDBG_H("posting IPA_DEL_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 */ + break; + + default: + IPACMDBG(" ignore NL event %d!!!\n ", nlh->nlmsg_type); + break; + + } + nlh = NLMSG_NEXT(nlh, buflen); + } + + return IPACM_SUCCESS; +} + + +/* Virtual function registered to receive incoming messages over the NETLINK routing socket*/ +int ipa_nl_recv_msg(int fd) +{ + struct msghdr *msghdr = NULL; + struct iovec *iov = NULL; + unsigned int msglen = 0; + ipa_nl_msg_t *nlmsg = NULL; + + nlmsg = (ipa_nl_msg_t *)malloc(sizeof(ipa_nl_msg_t)); + if(NULL == nlmsg) + { + IPACMERR("Failed alloc of nlmsg \n"); + goto error; + } + else + { + if(IPACM_SUCCESS != ipa_nl_recv(fd, &msghdr, &msglen)) + { + IPACMERR("Failed to receive nl message \n"); + goto error; + } + + if(msghdr== NULL) + { + IPACMERR(" failed to get msghdr\n"); + goto error; + } + + iov = msghdr->msg_iov; + + memset(nlmsg, 0, sizeof(ipa_nl_msg_t)); + if(IPACM_SUCCESS != ipa_nl_decode_nlmsg((char *)iov->iov_base, msglen, nlmsg)) + { + IPACMERR("Failed to decode nl message \n"); + goto error; + } + /* Release NetLink message buffer */ + if(msghdr) + { + ipa_nl_release_msg(msghdr); + } + if(nlmsg) + { + free(nlmsg); + } + } + + return IPACM_SUCCESS; + +error: + if(msghdr) + { + ipa_nl_release_msg(msghdr); + } + if(nlmsg) + { + free(nlmsg); + } + + return IPACM_FAILURE; +} + +/* get ipa interface name */ +int ipa_get_if_name +( + char *if_name, + int if_index + ) +{ + int fd; + struct ifreq ifr; + + if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + IPACMERR("get interface name socket create failed \n"); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + ifr.ifr_ifindex = if_index; + IPACMDBG("Interface index %d\n", if_index); + + if(ioctl(fd, SIOCGIFNAME, &ifr) < 0) + { + IPACMERR("call_ioctl_on_dev: ioctl failed:\n"); + close(fd); + return IPACM_FAILURE; + } + + (void)strncpy(if_name, ifr.ifr_name, sizeof(ifr.ifr_name)); + IPACMDBG("interface name %s\n", ifr.ifr_name); + close(fd); + + return IPACM_SUCCESS; +} + +/* Initialization routine for listener on NetLink sockets interface */ +int ipa_nl_listener_init +( + unsigned int nl_type, + unsigned int nl_groups, + ipa_nl_sk_fd_set_info_t *sk_fdset, + ipa_sock_thrd_fd_read_f read_f + ) +{ + ipa_nl_sk_info_t sk_info; + int ret_val; + + memset(&sk_info, 0, sizeof(ipa_nl_sk_info_t)); + IPACMDBG_H("Entering IPA NL listener init\n"); + + if(ipa_nl_open_socket(&sk_info, nl_type, nl_groups) == IPACM_SUCCESS) + { + IPACMDBG_H("IPA Open netlink socket succeeds\n"); + } + else + { + IPACMERR("Netlink socket open failed\n"); + return IPACM_FAILURE; + } + + /* Add NETLINK socket to the list of sockets that the listener + thread should listen on. */ + + if(ipa_nl_addfd_map(sk_fdset, sk_info.sk_fd, read_f) != IPACM_SUCCESS) + { + IPACMERR("cannot add nl routing sock for reading\n"); + close(sk_info.sk_fd); + return IPACM_FAILURE; + } + + /* Start the socket listener thread */ + ret_val = ipa_nl_sock_listener_start(sk_fdset); + + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Failed to start NL listener\n"); + } + + return IPACM_SUCCESS; +} + +/* find the newroute subnet mask */ +int find_mask(int ip_v4_last, int *mask_value) +{ + + switch(ip_v4_last) + { + + case 3: + *mask_value = 252; + return IPACM_SUCCESS; + break; + + case 7: + *mask_value = 248; + return IPACM_SUCCESS; + break; + + case 15: + *mask_value = 240; + return IPACM_SUCCESS; + break; + + case 31: + *mask_value = 224; + return IPACM_SUCCESS; + break; + + case 63: + *mask_value = 192; + return IPACM_SUCCESS; + break; + + case 127: + *mask_value = 128; + return IPACM_SUCCESS; + break; + + case 255: + *mask_value = 0; + return IPACM_SUCCESS; + break; + + default: + return IPACM_FAILURE; + break; + + } +} + +/* map mask value for ipv6 */ +int mask_v6(int index, uint32_t *mask) +{ + switch(index) + { + + case 0: + *mask = 0x00000000; + return IPACM_SUCCESS; + break; + case 4: + *mask = 0xf0000000; + return IPACM_SUCCESS; + break; + case 8: + *mask = 0xff000000; + return IPACM_SUCCESS; + break; + case 12: + *mask = 0xfff00000; + return IPACM_SUCCESS; + break; + case 16: + *mask = 0xffff0000; + return IPACM_SUCCESS; + break; + case 20: + *mask = 0xfffff000; + return IPACM_SUCCESS; + break; + case 24: + *mask = 0xffffff00; + return IPACM_SUCCESS; + break; + case 28: + *mask = 0xfffffff0; + return IPACM_SUCCESS; + break; + case 32: + *mask = 0xffffffff; + return IPACM_SUCCESS; + break; + default: + return IPACM_FAILURE; + break; + + } +} + + diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp new file mode 100644 index 0000000..2a2555a --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp @@ -0,0 +1,276 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Routing.cpp + + @brief + This file implements the IPACM routing functionality. + + @Author + +*/ + +#include +#include +#include +#include +#include + +#include "IPACM_Routing.h" +#include + +const char *IPACM_Routing::DEVICE_NAME = "/dev/ipa"; + +IPACM_Routing::IPACM_Routing() +{ + m_fd = open(DEVICE_NAME, O_RDWR); + if (0 == m_fd) + { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + } +} + +IPACM_Routing::~IPACM_Routing() +{ + close(m_fd); +} + +bool IPACM_Routing::DeviceNodeIsOpened() +{ + int res = fcntl(m_fd, F_GETFL); + + if (m_fd > 0 && res >= 0) return true; + else return false; + +} + +bool IPACM_Routing::AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable) +{ + int retval = 0, cnt=0; + bool isInvalid = false; + + if (!DeviceNodeIsOpened()) + { + IPACMERR("Device is not opened\n"); + 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) + { + IPACMERR("Failed adding routing rule %p\n", 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; +} + +bool IPACM_Routing::DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_DEL_RT_RULE, ruleTable); + if (retval) + { + IPACMERR("Failed deleting routing rule table %p\n", ruleTable); + return false; + } + + IPACMDBG_H("Deleted routing rule %p\n", ruleTable); + return true; +} + +bool IPACM_Routing::Commit(enum ipa_ip_type ip) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_COMMIT_RT, ip); + if (retval) + { + IPACMERR("Failed commiting routing rules.\n"); + return false; + } + + IPACMDBG_H("Commited routing rules to IPA HW.\n"); + return true; +} + +bool IPACM_Routing::Reset(enum ipa_ip_type ip) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_RESET_RT, ip); + retval |= ioctl(m_fd, IPA_IOC_COMMIT_RT, ip); + if (retval) + { + IPACMERR("Failed resetting routing block.\n"); + return false; + } + + IPACMDBG_H("Reset command issued to IPA routing block.\n"); + return true; +} + +bool IPACM_Routing::GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_GET_RT_TBL, routingTable); + if (retval) + { + 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; +} + +bool IPACM_Routing::PutRoutingTable(uint32_t routingTableHandle) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_PUT_RT_TBL, routingTableHandle); + if (retval) + { + IPACMERR("IPA_IOCTL_PUT_RT_TBL ioctl failed.\n"); + return false; + } + + IPACMDBG_H("IPA_IOCTL_PUT_RT_TBL ioctl issued to IPA routing block.\n"); + return true; +} + +bool IPACM_Routing::DeleteRoutingHdl(uint32_t rt_rule_hdl, ipa_ip_type ip) +{ + const uint8_t NUM_RULES = 1; + struct ipa_ioc_del_rt_rule *rt_rule; + struct ipa_rt_rule_del *rt_rule_entry; + bool res = true; + int len = 0; + + if (rt_rule_hdl == 0) + { + IPACMERR(" No route handle passed. Ignoring it\n"); + return res; + } + + len = (sizeof(struct ipa_ioc_del_rt_rule)) + (NUM_RULES * sizeof(struct ipa_rt_rule_del)); + rt_rule = (struct ipa_ioc_del_rt_rule *)malloc(len); + if (rt_rule == NULL) + { + IPACMERR("unable to allocate memory for del route rule\n"); + return false; + } + + memset(rt_rule, 0, len); + rt_rule->commit = 1; + rt_rule->num_hdls = NUM_RULES; + rt_rule->ip = ip; + + rt_rule_entry = &rt_rule->hdl[0]; + rt_rule_entry->status = -1; + rt_rule_entry->hdl = rt_rule_hdl; + + IPACMDBG_H("Deleting Route hdl:(0x%x) with ip type: %d\n", rt_rule_entry->hdl, ip); + if ((false == DeleteRoutingRule(rt_rule)) || + (rt_rule_entry->status)) + { + PERROR("Routing rule deletion failed!\n"); + goto fail; + res = false; + } + +fail: + free(rt_rule); + + 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 new file mode 100644 index 0000000..4ee6c10 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wan.cpp @@ -0,0 +1,6139 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Wan.cpp + + @brief + This file implements the WAN iface functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include +#include +#include "IPACM_EvtDispatcher.h" +#include +#include "linux/rmnet_ipa_fd_ioctl.h" +#include "IPACM_Config.h" +#include "IPACM_Defs.h" +#include +#include "linux/ipa_qmi_service_v01.h" + +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; + +struct ipa_flt_rule_add IPACM_Wan::flt_rule_v4[IPA_MAX_FLT_RULE]; +struct ipa_flt_rule_add IPACM_Wan::flt_rule_v6[IPA_MAX_FLT_RULE]; + +char IPACM_Wan::wan_up_dev_name[IF_NAME_LEN]; + +bool IPACM_Wan::backhaul_is_sta_mode = false; +bool IPACM_Wan::is_ext_prop_set = false; + +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]; + +#ifdef FEATURE_IPA_ANDROID +int IPACM_Wan::ipa_if_num_tether_v4_total = 0; +int IPACM_Wan::ipa_if_num_tether_v6_total = 0; + +int IPACM_Wan::ipa_if_num_tether_v4[IPA_MAX_IFACE_ENTRIES]; +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) +{ + num_firewall_v4 = 0; + num_firewall_v6 = 0; + wan_route_rule_v4_hdl = NULL; + wan_route_rule_v6_hdl = NULL; + wan_route_rule_v6_hdl_a5 = NULL; + wan_client = NULL; + + if(iface_query != NULL) + { + wan_route_rule_v4_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); + wan_route_rule_v6_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); + wan_route_rule_v6_hdl_a5 = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); + IPACMDBG_H("IPACM->IPACM_Wan(%d) constructor: Tx:%d\n", ipa_if_num, iface_query->num_tx_props); + } + 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; + header_set_v6 = false; + header_partial_default_wan_v4 = false; + header_partial_default_wan_v6 = false; + hdr_hdl_sta_v4 = 0; + hdr_hdl_sta_v6 = 0; + 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; + + if(iface_query != NULL) + { + wan_client_len = (sizeof(ipa_wan_client)) + (iface_query->num_tx_props * sizeof(wan_client_rt_hdl)); + wan_client = (ipa_wan_client *)calloc(IPA_MAX_NUM_WAN_CLIENTS, wan_client_len); + if (wan_client == NULL) + { + IPACMERR("unable to allocate memory\n"); + return; + } + IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props); + } + + + if(m_is_sta_mode == Q6_WAN) + { + IPACMDBG_H("The new WAN interface is modem.\n"); + is_default_gateway = false; + query_ext_prop(); + } + else + { + IPACMDBG_H("The new WAN interface is WLAN STA.\n"); + } + + m_fd_ipa = open(IPA_DEVICE_NAME, O_RDWR); + if(0 == m_fd_ipa) + { + IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME); + } + + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == EMBMS_IF) + { + IPACMDBG(" IPACM->IPACM_Wan_eMBMS(%d)\n", ipa_if_num); + embms_is_on = true; + install_wan_filtering_rule(false); + /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */ + if(tx_prop != NULL) + { + 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); + } + } + else + { + IPACMDBG(" IPACM->IPACM_Wan(%d)\n", ipa_if_num); + } + return; +} + +IPACM_Wan::~IPACM_Wan() +{ + IPACM_EvtDispatcher::deregistr(this); + IPACM_IfaceManager::deregistr(this); + return; +} + +/* handle new_address event */ +int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) +{ + struct ipa_ioc_add_rt_rule *rt_rule; + 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)); + + 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; + 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]; + 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; + + /* 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; + num_ipv6_modem_pdn++; + IPACMDBG_H("Now the number of modem ipv6 pdn is %d.\n", num_ipv6_modem_pdn); + init_fl_rule_ex(data->iptype); + } + else + { + 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) + { + if(rx_prop != NULL && is_global_ipv6_addr(data->ipv6_addr) + && num_ipv6_dest_flt_rule < MAX_DEFAULT_v6_ROUTE_RULES) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + + 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 = 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; + memcpy(flt_rule_entry.rule.attrib.u.v6.dst_addr, data->ipv6_addr, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr)); + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + 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); + res = IPACM_FAILURE; + goto fail; + } + 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++; + free(flt_rule); + } + } + } + /* store ipv6 prefix if the ipv6 address is not link local */ + if(is_global_ipv6_addr(data->ipv6_addr)) + { + memcpy(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix)); + } + num_dft_rt_v6++; + } + 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"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + 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.attrib.attrib_mask = IPA_FLT_DST_ADDR; + /* still need setup v4 default routing rule to A5*/ + 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"); + 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 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]); + /* initial multicast/broadcast/fragment filter rule */ + + /* only do one time */ + if(!wan_v4_addr_set) + { + /* 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; + 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); + +fail: + free(rt_rule); + + return res; +} + +void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) +{ + int ipa_interface_index; + + switch (event) + { + case IPA_WLAN_LINK_DOWN_EVENT: + { + if(m_is_sta_mode == WLAN_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) + { + IPACMDBG_H("Received IPA_WLAN_LINK_DOWN_EVENT\n"); + handle_down_evt(); + /* reset the STA-iface category to unknown */ + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat = UNKNOWN_IF; + IPACMDBG_H("IPA_WAN_STA (%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; + + 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) && + (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); + /* posting link-up event for cradle use-case */ + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(evt_data)); + + ipacm_event_data_fid *data_fid = NULL; + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for IPA_USB_LINK_UP_EVENT data_fid\n"); + return; + } + if(IPACM_Iface::ipa_get_if_index(dev_name, &(data_fid->if_index))) + { + IPACMERR("Error while getting interface index for %s device", dev_name); + } + evt_data.event = IPA_USB_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + IPACMDBG_H("Posting event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + + /* delete previous instance */ + handle_down_evt(); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + delete this; + return; + } + } + break; + + case IPA_LINK_DOWN_EVENT: + { + 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); + 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; + + case IPA_ADDR_ADD_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) || + (data->iptype == IPA_IP_v6 && + data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 && + data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) ) + { + IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n"); + return; + } + + if (ipa_interface_index == ipa_if_num) + { + 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 == 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); + handle_addr_evt(data); + /* checking if SW-RT_enable */ + if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true && + m_is_sta_mode != Q6_WAN) + { + /* handle software routing enable event*/ + IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + handle_software_routing_enable(); + } + + } + } + } + break; + + + case IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT: + { + ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT (Android) for ip-type (%d)\n", data->iptype); + /* The special below condition is to handle default gateway */ + if ((data->iptype == IPA_IP_v4) && (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)) + { + 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); +#endif + handle_route_add_evt(data->iptype); + } +#ifdef FEATURE_IPA_ANDROID + /* using ipa_if_index, not netdev_index */ + post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); +#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 + /* using ipa_if_index, not netdev_index */ + post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); +#endif + } + } + else /* double check if current default iface is not itself */ + { + if ((data->iptype == IPA_IP_v4) && (active_v4 == true)) + { + 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); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v4); + } + else + { + del_dft_firewall_rules(IPA_IP_v4); + handle_route_del_evt(IPA_IP_v4); + } + } + else if ((data->iptype == IPA_IP_v6) && (active_v6 == true)) + { + IPACMDBG_H("Received v6 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 v6 route for old iface (%s)\n", dev_name); + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } + else + { + del_dft_firewall_rules(IPA_IP_v6); + handle_route_del_evt(IPA_IP_v6); + } + } + } + } + break; + + case IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT: + { + ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + 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; +#ifdef FEATURE_IPA_ANDROID + /* 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*/ + if(IPACM_Wan::ipa_if_num_tether_v4_total != 0) + { + IPACMDBG_H("still have tether ipv4 client on upsteam iface\n"); + return; + } +#endif + 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); + } + else + { + del_dft_firewall_rules(IPA_IP_v4); + handle_route_del_evt(IPA_IP_v4); + } + } + else if ((data->iptype == IPA_IP_v6) && (active_v6 == true)) + { +#ifdef FEATURE_IPA_ANDROID + /* 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*/ + if(IPACM_Wan::ipa_if_num_tether_v6_total != 0) + { + IPACMDBG_H("still have tether ipv6 client on upsteam iface\n"); + return; + } +#endif + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } + else + { + del_dft_firewall_rules(IPA_IP_v6); + handle_route_del_evt(IPA_IP_v6); + } + } + } + } + break; + case IPA_NETWORK_STATS_UPDATE_EVENT: + { + ipa_get_apn_data_stats_resp_msg_v01 *data = (ipa_get_apn_data_stats_resp_msg_v01 *)param; + if (!data->apn_data_stats_list_valid) + { + IPACMERR("not valid APN\n"); + return; + } + else + { + handle_network_stats_update(data); + } + } + break; + case IPA_ROUTE_ADD_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_ROUTE_ADD_EVENT\n"); + IPACMDBG_H("ipv4 addr 0x%x\n", data->ipv4_addr); + IPACMDBG_H("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask); + + /* The special below condition is to handle default gateway */ + 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)) + { + 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)) + { + 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 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 */ + { + if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true)) + { + IPACMDBG_H("Received v4 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + 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); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v4); + } + else + { + del_dft_firewall_rules(IPA_IP_v4); + handle_route_del_evt(IPA_IP_v4); + } + } + 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("Received v6 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + IPACMDBG_H("need clean default v6 route for old iface (%s)\n", dev_name); + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } + else + { + del_dft_firewall_rules(IPA_IP_v6); + handle_route_del_evt(IPA_IP_v6); + } + } + } + } + break; + + case IPA_ROUTE_DEL_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_ROUTE_DEL_EVENT\n"); + 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 + { + del_dft_firewall_rules(IPA_IP_v4); + handle_route_del_evt(IPA_IP_v4); + } + } + 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"); + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } + else + { + del_dft_firewall_rules(IPA_IP_v6); + handle_route_del_evt(IPA_IP_v6); + } + } + } + } + break; + + case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT: + { + ipacm_event_data_all *data = (ipacm_event_data_all *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n"); + + if (m_is_sta_mode == WLAN_WAN) + { + 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"); + IPACMDBG_H("for its own ipv4 address\n"); + return; + } + else if (data->iptype == IPA_IP_v6) + { + for (int num_ipv6_addr = 0; num_ipv6_addr < num_dft_rt_v6; num_ipv6_addr++) + { + if ((ipv6_addr[num_ipv6_addr][0] == data->ipv6_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("Ignore IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n"); + IPACMDBG_H("for its own ipv6 address\n"); + return; + } + } + } + } + + IPACMDBG_H("wan-iface got client \n"); + /* first construc WAN-client full header */ + if(memcmp(data->mac_addr, + invalid_mac, + sizeof(data->mac_addr)) == 0) + { + IPACMDBG_H("Received invalid Client 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]); + return; + } + + handle_wan_hdr_init(data->mac_addr); + 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; + + case IPA_SW_ROUTING_ENABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n"); + /* handle software routing enable event */ + if(m_is_sta_mode == Q6_WAN) + { + install_wan_filtering_rule(true); + } + else + { + handle_software_routing_enable(); + } + break; + + case IPA_SW_ROUTING_DISABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n"); + /* handle software routing disable event */ + if(m_is_sta_mode == Q6_WAN) + { + /* send current DL rules to modem */ + install_wan_filtering_rule(false); + softwarerouting_act = false; + } + else + { + handle_software_routing_disable(); + } + break; + + case IPA_FIREWALL_CHANGE_EVENT: + IPACMDBG_H("Received IPA_FIREWALL_CHANGE_EVENT\n"); + + if(m_is_sta_mode == Q6_WAN) + { + if(is_default_gateway == false) + { + IPACMDBG_H("Interface %s is not default gw, return.\n", dev_name); + return; + } + + if(ip_type == IPA_IP_v4) + { + del_wan_firewall_rule(IPA_IP_v4); + config_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + } + else if(ip_type == IPA_IP_v6) + { + del_wan_firewall_rule(IPA_IP_v6); + config_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + } + else if(ip_type == IPA_IP_MAX) + { + del_wan_firewall_rule(IPA_IP_v4); + config_wan_firewall_rule(IPA_IP_v4); + + del_wan_firewall_rule(IPA_IP_v6); + config_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + } + else + { + IPACMERR("IP type is not expected.\n"); + } + } + else + { + 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); + } + } + 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; + } + + return; +} + +/* wan default route/filter rule configuration */ +int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) +{ + + /* add default WAN route */ + 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); + + /* copy header from tx-property, see if partial or not */ + /* assume all tx-property uses the same header name for v4 or v6*/ + + if(tx_prop == NULL) + { + IPACMDBG_H("No tx properties, ignore default route setting\n"); + return IPACM_SUCCESS; + } + + is_default_gateway = true; + IPACMDBG_H("Default route is added to iface %s.\n", dev_name); + + 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) + { + IPACM_Wan::backhaul_is_sta_mode = true; + if((iptype==IPA_IP_v4) && (header_set_v4 != true)) + { + header_partial_default_wan_v4 = true; + IPACMDBG_H("STA ipv4-header haven't constructed \n"); + return IPACM_SUCCESS; + } + else if((iptype==IPA_IP_v6) && (header_set_v6 != true)) + { + header_partial_default_wan_v6 = true; + IPACMDBG_H("STA ipv6-header haven't constructed \n"); + return IPACM_SUCCESS; + } + } + else + { + IPACM_Wan::backhaul_is_sta_mode = false; + IPACMDBG_H("reset backhaul to LTE \n"); + + if (iface_query != NULL && iface_query->num_ext_props > 0) + { + if(ext_prop == NULL) + { + IPACMERR("Extended property is empty.\n"); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->SetQmapId(ext_prop->ext[0].mux_id); + IPACMDBG_H("Setting up QMAP ID %d.\n", ext_prop->ext[0].mux_id); + } + } + else + { + IPACMERR("iface_query is empty.\n"); + 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) + { + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + 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) + { + IPACMERR("ioctl copy header failed"); + return IPACM_FAILURE; + } + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if(sCopyHeader.is_partial) + { + IPACMDBG_H("Not setup default WAN routing rules cuz the header is not complete\n"); + if(iptype==IPA_IP_v4) + { + header_partial_default_wan_v4 = true; + } + else + { + header_partial_default_wan_v6 = true; + } + return IPACM_SUCCESS; + } + else + { + if(iptype==IPA_IP_v4) + { + header_partial_default_wan_v4 = false; + } + else + { + header_partial_default_wan_v6 = false; + } + } + } +#endif + + 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) + { + IPACMERR("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; + + + 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; + + if(m_is_sta_mode != Q6_WAN) + { + IPACMDBG_H(" WAN instance is in STA mode \n"); + 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; + } + + /* use the STA-header handler */ + if (iptype == IPA_IP_v4) + { + 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 + { + 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(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; + 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; +#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_v4_hdl[tx_index] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("Got ipv4 wan-route rule hdl:0x%x,tx:%d,ip-type: %d \n", + wan_route_rule_v4_hdl[tx_index], + tx_index, + iptype); + } + 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; +#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[tx_index] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("Set ipv6 wan-route rule hdl for v6_lan_table:0x%x,tx:%d,ip-type: %d \n", + wan_route_rule_v6_hdl[tx_index], + tx_index, + iptype); + } + } + } + + /* add a catch-all rule in wan dl routing table */ + + if (iptype == IPA_IP_v6) + { + 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; + active_v4 = true; + memcpy(IPACM_Wan::wan_up_dev_name, + dev_name, + sizeof(IPACM_Wan::wan_up_dev_name)); + + if(m_is_sta_mode == Q6_WAN) + { + config_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + } + else + { + config_dft_firewall_rules(IPA_IP_v4); + } + + memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname)); + wanup_data->ipv4_addr = wan_v4_addr; + if (m_is_sta_mode!=Q6_WAN) + { + wanup_data->is_sta = true; + } + else + { + wanup_data->is_sta = false; + } + 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); + 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, + dev_name, + sizeof(IPACM_Wan::wan_up_dev_name)); + + if(m_is_sta_mode == Q6_WAN) + { + config_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + } + else + { + config_dft_firewall_rules(IPA_IP_v6); + } + + memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname)); + if (m_is_sta_mode!=Q6_WAN) + { + wanup_data->is_sta = true; + } + else + { + wanup_data->is_sta = false; + } + memcpy(wanup_data->ipv6_prefix, ipv6_prefix, sizeof(wanup_data->ipv6_prefix)); + IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_V6 with below information:\n"); + IPACMDBG_H("if_name:%s, is sta mode: %d\n", wanup_data->ifname, wanup_data->is_sta); + IPACMDBG_H("ipv6 prefix: 0x%08x%08x.\n", ipv6_prefix[0], ipv6_prefix[1]); + memset(&evt_data, 0, sizeof(evt_data)); + evt_data.event = IPA_HANDLE_WAN_UP_V6; + evt_data.evt_data = (void *)wanup_data; + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + + /* 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); + + 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) +{ + ipacm_cmd_q_data evt_data; + ipacm_event_iface_up_tehter *wanup_data; + + wanup_data = (ipacm_event_iface_up_tehter *)malloc(sizeof(ipacm_event_iface_up_tehter)); + if (wanup_data == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return IPACM_FAILURE; + } + memset(wanup_data, 0, sizeof(ipacm_event_iface_up_tehter)); + + wanup_data->if_index_tether = ipa_if_num_tether; + if (m_is_sta_mode!=Q6_WAN) + { + wanup_data->is_sta = true; + } + else + { + wanup_data->is_sta = false; + } + IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_TETHER with below information:\n"); + IPACMDBG_H("tether_if_name:%s, is sta mode:%d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wanup_data->is_sta); + memset(&evt_data, 0, sizeof(evt_data)); + + if (iptype == IPA_IP_v4) + { + evt_data.event = IPA_HANDLE_WAN_UP_TETHER; + /* Add support tether ifaces to its array*/ + IPACM_Wan::ipa_if_num_tether_v4[IPACM_Wan::ipa_if_num_tether_v4_total] = ipa_if_num_tether; + IPACMDBG_H("adding tether iface(%s) ipa_if_num_tether_v4_total(%d) on wan_iface(%s)\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, + IPACM_Wan::ipa_if_num_tether_v4_total, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + IPACM_Wan::ipa_if_num_tether_v4_total++; + } + else + { + evt_data.event = IPA_HANDLE_WAN_UP_V6_TETHER; + memcpy(wanup_data->ipv6_prefix, ipv6_prefix, sizeof(wanup_data->ipv6_prefix)); + /* Add support tether ifaces to its array*/ + IPACM_Wan::ipa_if_num_tether_v6[IPACM_Wan::ipa_if_num_tether_v6_total] = ipa_if_num_tether; + IPACMDBG_H("adding tether iface(%s) ipa_if_num_tether_v6_total(%d) on wan_iface(%s)\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, + IPACM_Wan::ipa_if_num_tether_v6_total, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + IPACM_Wan::ipa_if_num_tether_v6_total++; + } + evt_data.evt_data = (void *)wanup_data; + IPACM_EvtDispatcher::PostEvt(&evt_data); + + 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) + { + IPACMERR("Unable to allocate memory\n"); + return IPACM_FAILURE; + } + memset(wandown_data, 0, sizeof(ipacm_event_iface_up_tehter)); + + wandown_data->if_index_tether = ipa_if_num_tether; + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + IPACMDBG_H("Posting IPA_HANDLE_WAN_DOWN_TETHER with below information:\n"); + IPACMDBG_H("tether_if_name:%s, is sta mode:%d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wandown_data->is_sta); + memset(&evt_data, 0, sizeof(evt_data)); + + 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) + { + IPACMDBG_H("Not finding the tether client.\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); + } + 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) + { + IPACMDBG_H("Not finding the tether client.\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.evt_data = (void *)wandown_data; + IPACM_EvtDispatcher::PostEvt(&evt_data); + return IPACM_SUCCESS; +} +#endif + +/* construct complete ethernet header */ +int IPACM_Wan::handle_sta_header_add_evt() +{ + 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; + } + + /* checking if the ipv4 same as default route */ + if(wan_v4_addr_gw_set) + { + 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(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; + } + + 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; + } + } + + /* checking if the ipv4 same as default route */ + if(wan_v6_addr_gw_set) + { + 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]); + + 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); + /* 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(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); + } + else + { + 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) + { + handle_route_add_evt(IPA_IP_v4); + } + + if(header_partial_default_wan_v6 == true) + { + handle_route_add_evt(IPA_IP_v6); + } + return res; +} + +/* 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; + + 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 */ +int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) +{ + struct ipa_flt_rule_add flt_rule_entry; + int i, rule_v4 = 0, rule_v6 = 0, len; + + IPACMDBG_H("ip-family: %d; \n", iptype); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + /* default firewall is disable and the rule action is drop */ + memset(&firewall_config, 0, sizeof(firewall_config)); + strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(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++) + { + 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 + { + 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; + 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) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + 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; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v6; + m_pFilteringTable->num_rules = (uint8_t)1; + + 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_FRAGMENT; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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); + } + } + + if (iptype == IPA_IP_v4) + { + if (rule_v4 == 0) + { + memset(m_pFilteringTable, 0, len); + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)1; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4)) + { + IPACMERR("m_routing.GetRoutingTable(rt_tbl_lan_v4) Failed.\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == 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 + { + 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; + 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, + 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; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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); + } + + /* copy filter hdls */ + dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + else + { + memset(m_pFilteringTable, 0, len); + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)1; + + IPACMDBG_H("Retreiving Routing handle for routing table name:%s\n", + IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name); + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4)) + { + IPACMERR("m_routing.GetRoutingTable(&rt_tbl_lan_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_lan_v4); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + IPACMDBG_H("Routing handle for wan routing table:0x%x\n", IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl); + + if(firewall_config.firewall_enable == true) + { + rule_v4 = 0; + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + { + if (firewall_config.extd_firewall_entries[i].ip_vsn == 4) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + 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) + { + 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)); + + IPACMDBG_H("rx property attrib mask: 0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + 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; + + /* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */ + if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol + == IPACM_FIREWALL_IPPROTO_TCP_UDP) + { + /* insert TCP rule*/ + flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", + m_pFilteringTable->rules[0].rule.attrib.attrib_mask); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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, + m_pFilteringTable->rules[rule_v4].status); + firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl; + num_firewall_v4++; + rule_v4++; + } + + /* insert UDP rule*/ + flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", + m_pFilteringTable->rules[0].rule.attrib.attrib_mask); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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, + m_pFilteringTable->rules[rule_v4].status); + firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl; + num_firewall_v4++; + rule_v4++; + } + } + else + { + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", + m_pFilteringTable->rules[0].rule.attrib.attrib_mask); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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, + m_pFilteringTable->rules[rule_v4].status); + firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl; + num_firewall_v4++; + rule_v4++; + } + } + } + } /* end of firewall ipv4 filter rule add for loop*/ + } + /* configure default filter rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == 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 + { + 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; + 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; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", + m_pFilteringTable->rules[0].rule.attrib.attrib_mask); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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); + } + + /* copy filter hdls */ + dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + + } + else + { + if (rule_v6 == 0) + { + memset(m_pFilteringTable, 0, len); + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v6; + m_pFilteringTable->num_rules = (uint8_t)1; + + /* Construct ICMP rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + 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)); + 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(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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 */ + dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl; + + /* End of construct ICMP rule */ + + /* v6 default route */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6)) //rt_tbl_wan_v6 rt_tbl_v6 + { + IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == true) + { + flt_rule_entry.at_rear = true; + + /* default action for v6 is PASS_TO_ROUTE 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_ROUTING; + } + } + else + { + 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)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; + 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] = 0X00000000; + 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; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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 */ + dft_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + else + { + memset(m_pFilteringTable, 0, len); + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v6; + m_pFilteringTable->num_rules = (uint8_t)1; + + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6)) + { + IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + if(firewall_config.firewall_enable == true) + { + rule_v6 = 0; + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + { + if (firewall_config.extd_firewall_entries[i].ip_vsn == 6) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + /* matched rules for v6 go PASS_TO_ROUTE */ + if(firewall_config.rule_action_accept == true) + { + 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 + 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, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + 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; + + /* check if the rule is define as TCP/UDP */ + if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP) + { + /* insert TCP rule*/ + flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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; + num_firewall_v6++; + rule_v6++; + } + + /* insert UDP rule*/ + flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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; + num_firewall_v6++; + rule_v6++; + } + } + else + { + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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; + num_firewall_v6++; + rule_v6++; + } + } + } + } /* end of firewall ipv6 filter rule add for loop*/ + } + + /* Construct ICMP rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + 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)); + 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(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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 */ + dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl; + /* End of construct ICMP rule */ + + /* setup default wan filter rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == true) + { + flt_rule_entry.at_rear = true; + + /* default action for v6 is PASS_TO_ROUTE 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_ROUTING; + } + } + else + { + 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)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; + 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] = 0X00000000; + 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; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + 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*/ + dft_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + } + + if(m_pFilteringTable != NULL) + { + free(m_pFilteringTable); + } + return IPACM_SUCCESS; +} + +/* configure the initial firewall filter rules */ +int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype) +{ + struct ipa_flt_rule_add flt_rule_entry; + int i; + int num_rules = 0, original_num_rules = 0; + ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + ipa_ioc_generate_flt_eq flt_eq; + int pos = rule_offset; + + IPACMDBG_H("ip-family: %d; \n", iptype); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(rules == NULL || rule_offset < 0) + { + IPACMERR("No filtering table is available.\n"); + return IPACM_FAILURE; + } + + /* default firewall is disable and the rule action is drop */ + memset(&firewall_config, 0, sizeof(firewall_config)); + strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(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"); + } + else + { + IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n"); + } + + /* add IPv6 frag rule when firewall is enabled*/ + 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; + + flt_rule_entry.rule.retain_hdr = 1; + 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; + 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"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + IPACMDBG_H("IPv6 frag flt rule uses routing table index %d\n", rt_tbl_idx.idx); + + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + 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_FRAGMENT; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v6; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + IPACM_Wan::num_v6_flt_rule++; + } + + if (iptype == IPA_IP_v4) + { + original_num_rules = IPACM_Wan::num_v4_flt_rule; + if(firewall_config.firewall_enable == true) + { + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + { + if (firewall_config.extd_firewall_entries[i].ip_vsn == 4) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + + /* 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_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) + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + } + else /*pass to dst nat*/ + { + 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"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memcpy(&flt_rule_entry.rule.attrib, + &firewall_config.extd_firewall_entries[i].attrib, + sizeof(struct ipa_rule_attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + 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; + + change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib); + + /* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */ + if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol == IPACM_FIREWALL_IPPROTO_TCP_UDP) + { + /* insert TCP rule*/ + flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask); + pos++; + num_firewall_v4++; + IPACM_Wan::num_v4_flt_rule++; + + /* insert UDP rule*/ + flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask); + pos++; + num_firewall_v4++; + IPACM_Wan::num_v4_flt_rule++; + } + else + { + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask); + pos++; + num_firewall_v4++; + IPACM_Wan::num_v4_flt_rule++; + } + } + } /* end of firewall ipv4 filter rule add for loop*/ + } + /* configure default filter rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == 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_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + } + else + { + 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) + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + } + else /*pass to dst nat*/ + { + 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"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + 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; + + change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask); + pos++; + num_firewall_v4++; + IPACM_Wan::num_v4_flt_rule++; + + num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules - 1; + } + else + { + original_num_rules = IPACM_Wan::num_v6_flt_rule; + + if(firewall_config.firewall_enable == true) + { + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + { + if (firewall_config.extd_firewall_entries[i].ip_vsn == 6) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + 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) + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); + } + else + { + 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"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memcpy(&flt_rule_entry.rule.attrib, + &firewall_config.extd_firewall_entries[i].attrib, + sizeof(struct ipa_rule_attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + 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; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + /* check if the rule is define as TCP/UDP */ + if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP) + { + /* insert TCP rule*/ + flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + num_firewall_v6++; + IPACM_Wan::num_v6_flt_rule++; + + /* insert UDP rule*/ + flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + num_firewall_v6++; + IPACM_Wan::num_v6_flt_rule++; + } + else + { + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + num_firewall_v6++; + IPACM_Wan::num_v6_flt_rule++; + } + } + } /* end of firewall ipv6 filter rule add for loop*/ + } + + /* setup default wan filter rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + 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 */ + if(firewall_config.firewall_enable == true) + { + /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/ + if(firewall_config.rule_action_accept == true) + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + } + else + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); + } + } + else + { + 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"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[1].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; + 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] = 0X00000000; + 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; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + num_firewall_v6++; + IPACM_Wan::num_v6_flt_rule++; + + num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules - 1; + } + IPACMDBG_H("Constructed %d firewall rules for ip type %d\n", num_rules, iptype); + return IPACM_SUCCESS; +} + +int IPACM_Wan::init_fl_rule_ex(ipa_ip_type iptype) +{ + int res = IPACM_SUCCESS; + + char *dev_wlan0="wlan0"; + char *dev_wlan1="wlan1"; + char *dev_ecm0="ecm0"; + + /* 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 */ + { + /* reset the num_v4_flt_rule*/ + IPACM_Wan::num_v4_flt_rule = 0; + add_dft_filtering_rule(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4); + } + } + else if(iptype == IPA_IP_v6) + { + 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; + add_dft_filtering_rule(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6); + } + } + else + { + IPACMERR("IP type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + install_wan_filtering_rule(false); + +fail: + return res; +} + +int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype) +{ + int res = IPACM_SUCCESS, i, original_num_rules = 0, num_rules = 0; + struct ipa_flt_rule_add flt_rule_entry; + IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg; + ipa_ioc_generate_flt_eq flt_eq; + ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + + if(rules == NULL || rule_offset < 0) + { + IPACMERR("No filtering table is available.\n"); + return IPACM_FAILURE; + } + + if(iptype == IPA_IP_v4) + { + original_num_rules = IPACM_Wan::num_v4_flt_rule; + + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + 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)) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + 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)); + /* 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; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACM_Wan::num_v4_flt_rule++; + + /* Configure ALG filtering rules */ + 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++) + { + flt_rule_entry.rule.attrib.src_port = ipacm_config->alg_table[i].port; + flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[rule_offset + 1 + i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACM_Wan::num_v4_flt_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); + 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++) + { + flt_rule_entry.rule.attrib.dst_port = ipacm_config->alg_table[i].port; + flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset + ipacm_config->ipa_num_alg_ports + 1 + i]), + &flt_rule_entry, + sizeof(struct ipa_flt_rule_add)); + IPACM_Wan::num_v4_flt_rule++; + } + num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules; + } + else /* IPv6 case */ + { + original_num_rules = IPACM_Wan::num_v6_flt_rule; + + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + 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)) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + 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)); + /* 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; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACM_Wan::num_v6_flt_rule++; + + num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules; + } + +fail: + IPACMDBG_H("Constructed %d ICMP/ALG rules for ip type %d\n", num_rules, iptype); + return res; +} + +int IPACM_Wan::query_ext_prop() +{ + int fd, ret = IPACM_SUCCESS, cnt; + + if (iface_query->num_ext_props > 0) + { + fd = open(IPA_DEVICE_NAME, O_RDWR); + IPACMDBG_H("iface query-property \n"); + if (0 == fd) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + ext_prop = (struct ipa_ioc_query_intf_ext_props *) + calloc(1, sizeof(struct ipa_ioc_query_intf_ext_props) + + iface_query->num_ext_props * sizeof(struct ipa_ioc_ext_intf_prop)); + if(ext_prop == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memcpy(ext_prop->name, dev_name, + sizeof(dev_name)); + ext_prop->num_ext_props = iface_query->num_ext_props; + + IPACMDBG_H("Query extended property for iface %s\n", ext_prop->name); + + ret = ioctl(fd, IPA_IOC_QUERY_INTF_EXT_PROPS, ext_prop); + if (ret < 0) + { + IPACMERR("ioctl IPA_IOC_QUERY_INTF_EXT_PROPS failed\n"); + /* ext_prop memory will free when iface-down*/ + free(ext_prop); + close(fd); + 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); + + for (cnt = 0; cnt < ext_prop->num_ext_props; cnt++) + { +#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) + { + IPACM_Iface::ipacmcfg->SetExtProp(ext_prop); + IPACM_Wan::is_ext_prop_set = true; + } + close(fd); + } + return IPACM_SUCCESS; +} + +int IPACM_Wan::config_wan_firewall_rule(ipa_ip_type iptype) +{ + int res = IPACM_SUCCESS; + + IPACMDBG_H("Configure WAN DL firewall rules.\n"); + + if(iptype == IPA_IP_v4) + { + IPACM_Wan::num_v4_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4; + if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4)) + { + IPACMERR("Failed to add ICMP and ALG port filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype); + + if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4)) + { + IPACMERR("Failed to add firewall filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Succeded in constructing firewall rules for ip type %d\n", iptype); + } + else if(iptype == IPA_IP_v6) + { + IPACM_Wan::num_v6_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6; + if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6)) + { + IPACMERR("Failed to add ICMP and ALG port filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype); + + if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6)) + { + IPACMERR("Failed to add firewall filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Succeded in constructing firewall rules for ip type %d\n", iptype); + } + else + { + IPACMERR("IP type is not expected.\n"); + return IPACM_FAILURE; + } + +fail: + return res; +} + +int IPACM_Wan::add_dft_filtering_rule(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype) +{ + struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_generate_flt_eq flt_eq; + int res = IPACM_SUCCESS; + + if(rules == NULL) + { + IPACMERR("No filtering table available.\n"); + return IPACM_FAILURE; + } + if(rx_prop == NULL) + { + IPACMERR("No tx property.\n"); + return IPACM_FAILURE; + } + + if (iptype == IPA_IP_v4) + { + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + 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)) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + 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); + + /* Configuring Multicast Filtering Rule */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* remove meta data mask since we only install default flt rules once for all modem PDN*/ + 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.v4.dst_addr_mask = 0xF0000000; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000; + + change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[rule_offset]), &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; + + change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACM_Wan::num_v4_flt_rule += IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4; + IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4, iptype); + } + else /*insert rules for ipv6*/ + { + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + 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)) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + 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 */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* remove meta data mask since we only install default flt rules once for all modem PDN*/ + 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_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] = 0xFF000000; + 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; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */ + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000; + 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] = 0xFE800000; + 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; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring fec0::/10 Reserved by IETF Filtering Rule */ + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000; + 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] = 0xFEC00000; + 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; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset + 2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + +#ifdef FEATURE_IPA_ANDROID + IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6); + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + flt_rule_entry.rule.eq_attrib_type = 1; + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0; + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1); + flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1; + flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8); + flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1; + flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; + + /* add TCP FIN rule*/ + flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)< IPACM_MAX_FIREWALL_ENTRIES) + { + IPACMERR("the number of v4 firewall entries overflow, aborting...\n"); + return IPACM_FAILURE; + } + if (num_firewall_v4 != 0) + { + if (m_filtering.DeleteFilteringHdls(firewall_hdl_v4, + IPA_IP_v4, num_firewall_v4) == false) + { + 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 + { + IPACMDBG_H("No ipv4 firewall rules, no need deleted\n"); + } + + if (m_filtering.DeleteFilteringHdls(dft_wan_fl_hdl, + IPA_IP_v4, 1) == false) + { + 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; + } + + /* free v6 firewall filter rule */ + if ((iptype == IPA_IP_v6) && (active_v6 == true)) + { + if (num_firewall_v6 > IPACM_MAX_FIREWALL_ENTRIES) + { + IPACMERR("the number of v6 firewall entries overflow, aborting...\n"); + return IPACM_FAILURE; + } + if (num_firewall_v6 != 0) + { + if (m_filtering.DeleteFilteringHdls(firewall_hdl_v6, + IPA_IP_v6, num_firewall_v6) == false) + { + 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 + { + IPACMDBG_H("No ipv6 firewall rules, no need deleted\n"); + } + + if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[1], + IPA_IP_v6, 1) == false) + { + 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; + } + 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)) + { + 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; + } + + return IPACM_SUCCESS; +} + +/* for STA mode: wan default route/filter rule delete */ +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 for STA-mode with ip-family:%d \n", iptype); + + if(tx_prop == NULL) + { + IPACMDBG_H("No tx properties, ignore delete default route setting\n"); + return IPACM_SUCCESS; + } + + is_default_gateway = false; + IPACMDBG_H("Default route is deleted to iface %s.\n", dev_name); + + if (((iptype == IPA_IP_v4) && (active_v4 == true)) || + ((iptype == IPA_IP_v6) && (active_v6 == true))) + { + + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ + 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->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + + 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 deleted\n", + tx_index, tx_prop->tx[tx_index].ip,iptype); + continue; + } + + if (iptype == 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,iptype); + + if (m_routing.DeleteRoutingHdl(wan_route_rule_v4_hdl[tx_index], IPA_IP_v4) == false) + { + IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v4, wan_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,iptype); + + if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl[tx_index], IPA_IP_v6) == false) + { + IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v6, wan_route_rule_v6_hdl[tx_index], tx_index); + return IPACM_FAILURE; + } + } + } + + /* Delete the default wan route*/ + if (iptype == IPA_IP_v6) + { + IPACMDBG_H("ip-type %d: default v6 wan RT-rule deleted\n",iptype); + if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false) + { + IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]); + return IPACM_FAILURE; + } + } + ipacm_event_iface_up *wandown_data; + wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up)); + if (wandown_data == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return IPACM_FAILURE; + } + memset(wandown_data, 0, sizeof(ipacm_event_iface_up)); + + if (iptype == IPA_IP_v4) + { + wandown_data->ipv4_addr = wan_v4_addr; + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + evt_data.event = IPA_HANDLE_WAN_DOWN; + evt_data.evt_data = (void *)wandown_data; + /* Insert IPA_HANDLE_WAN_DOWN to command queue */ + IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv4 (%d.%d.%d.%d) \n", + (unsigned char)(wandown_data->ipv4_addr), + (unsigned char)(wandown_data->ipv4_addr >> 8), + (unsigned char)(wandown_data->ipv4_addr >> 16), + (unsigned char)(wandown_data->ipv4_addr >> 24)); + + IPACM_EvtDispatcher::PostEvt(&evt_data); + IPACMDBG_H("setup wan_up/active_v4= false \n"); + IPACM_Wan::wan_up = false; + active_v4 = false; + if(IPACM_Wan::wan_up_v6) + { + IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + else + { + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + memcpy(wandown_data->ipv6_prefix, ipv6_prefix, sizeof(wandown_data->ipv6_prefix)); + evt_data.event = IPA_HANDLE_WAN_DOWN_V6; + evt_data.evt_data = (void *)wandown_data; + /* Insert IPA_HANDLE_WAN_DOWN to command queue */ + IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv6 with prefix 0x%08x%08x\n", ipv6_prefix[0], ipv6_prefix[1]); + IPACM_EvtDispatcher::PostEvt(&evt_data); + IPACMDBG_H("setup wan_up_v6/active_v6= false \n"); + IPACM_Wan::wan_up_v6 = false; + active_v6 = false; + if(IPACM_Wan::wan_up) + { + IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + } + else + { + IPACMDBG_H(" The default WAN routing rules are deleted already \n"); + } + + return IPACM_SUCCESS; +} + +int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype) +{ + ipacm_cmd_q_data evt_data; + + IPACMDBG_H("got handle_route_del_evt_ex with ip-family:%d \n", iptype); + + if(tx_prop == NULL) + { + IPACMDBG_H("No tx properties, ignore delete default route setting\n"); + return IPACM_SUCCESS; + } + + is_default_gateway = false; + IPACMDBG_H("Default route is deleted to iface %s.\n", dev_name); + + if (((iptype == IPA_IP_v4) && (active_v4 == true)) || + ((iptype == IPA_IP_v6) && (active_v6 == true))) + { + + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ + 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->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + + /* Delete the default route*/ + if (iptype == IPA_IP_v6) + { + IPACMDBG_H("ip-type %d: default v6 wan RT-rule deleted\n",iptype); + if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false) + { + IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]); + return IPACM_FAILURE; + } + } + + ipacm_event_iface_up *wandown_data; + wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up)); + if (wandown_data == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return IPACM_FAILURE; + } + memset(wandown_data, 0, sizeof(ipacm_event_iface_up)); + + if (iptype == IPA_IP_v4) + { + wandown_data->ipv4_addr = wan_v4_addr; + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + evt_data.event = IPA_HANDLE_WAN_DOWN; + evt_data.evt_data = (void *)wandown_data; + /* Insert IPA_HANDLE_WAN_DOWN to command queue */ + IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv4 with address: 0x%x\n", wan_v4_addr); + IPACM_EvtDispatcher::PostEvt(&evt_data); + + IPACMDBG_H("setup wan_up/active_v4= false \n"); + IPACM_Wan::wan_up = false; + active_v4 = false; + if(IPACM_Wan::wan_up_v6) + { + IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + else + { + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + memcpy(wandown_data->ipv6_prefix, ipv6_prefix, sizeof(wandown_data->ipv6_prefix)); + evt_data.event = IPA_HANDLE_WAN_DOWN_V6; + evt_data.evt_data = (void *)wandown_data; + IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN_V6 for IPv6 with prefix 0x%08x%08x\n", ipv6_prefix[0], ipv6_prefix[1]); + IPACM_EvtDispatcher::PostEvt(&evt_data); + + IPACMDBG_H("setup wan_up_v6/active_v6= false \n"); + IPACM_Wan::wan_up_v6 = false; + active_v6 = false; + if(IPACM_Wan::wan_up) + { + IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + } + else + { + IPACMDBG_H(" The default WAN routing rules are deleted already \n"); + } + + return IPACM_SUCCESS; +} + +/* configure the initial embms filter rules */ +int IPACM_Wan::config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, ipa_ioc_add_flt_rule *pFilteringTable_v6) +{ + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + struct ipa_ioc_generate_flt_eq flt_eq; + + if (rx_prop == NULL) + { + IPACMDBG("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(pFilteringTable_v4 == NULL || pFilteringTable_v6 == NULL) + { + IPACMERR("Either v4 or v6 filtering table is empty.\n"); + return IPACM_FAILURE; + } + + /* set up ipv4 odu rule*/ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + /* get eMBMS ODU tbl index*/ + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + 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)) + { + IPACMERR("Failed to get routing table index from name\n"); + return IPACM_FAILURE; + } + IPACMDBG_H("Odu routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.at_rear = false; + + flt_rule_entry.rule.retain_hdr = 0; + 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, + &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; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v4; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(pFilteringTable_v4->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* construc v6 rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + /* get eMBMS ODU tbl*/ + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + 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)) + { + IPACMERR("Failed to get routing table index from name\n"); + return IPACM_FAILURE; + } + IPACMDBG_H("Odu routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.at_rear = false; + + flt_rule_entry.rule.retain_hdr = 0; + 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, + &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.v6.dst_addr_mask[0] = 0x00000000; + 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] = 0X00000000; + 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; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v6; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(pFilteringTable_v6->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + return IPACM_SUCCESS; +} + + +/*for STA mode: handle wan-iface down event */ +int IPACM_Wan::handle_down_evt() +{ + int res = IPACM_SUCCESS; + int i; + + IPACMDBG_H(" wan handle_down_evt \n"); + + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + if (tx_prop != NULL) + { + 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]); + } + + /* no iface address up, directly close iface*/ + if (ip_type == IPACM_IP_NULL) + { + goto fail; + } + + /* make sure default routing rules and firewall rules are deleted*/ + if (active_v4) + { + if (rx_prop != NULL) + { + del_dft_firewall_rules(IPA_IP_v4); + } + handle_route_del_evt(IPA_IP_v4); + IPACMDBG_H("Delete default v4 routing rules\n"); + } + + if (active_v6) + { + if (rx_prop != NULL) + { + del_dft_firewall_rules(IPA_IP_v6); + } + handle_route_del_evt(IPA_IP_v6); + IPACMDBG_H("Delete default v6 routing 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("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + + /* delete default v6 RT rule */ + if (ip_type != IPA_IP_v4) + { + IPACMDBG_H("Delete default v6 routing rules\n"); + /* May have multiple ipv6 iface-routing rules*/ + for (i = 0; i < 2*num_dft_rt_v6; i++) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + + IPACMDBG_H("finished delete default v6 RT rules\n "); + } + + + /* clean wan-client header, routing rules */ + IPACMDBG_H("left %d wan clients need to be deleted \n ", num_wan_client); + for (i = 0; i < num_wan_client; i++) + { + /* Del NAT rules before ipv4 RT rules are delete */ + if(get_client_memptr(wan_client, i)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wan_client, i)->v4_addr); + CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, i)->v4_addr); + } + + if (delete_wan_rtrules(i, IPA_IP_v4)) + { + IPACMERR("unbale to delete wan-client v4 route rules for index %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + + if (delete_wan_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_wan_client); + + + if(get_client_memptr(wan_client, i)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v4) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + + if(get_client_memptr(wan_client, i)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v6) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + } /* end of for loop */ + + /* free the edm clients cache */ + IPACMDBG_H("Free wan clients cache\n"); + + /* check software routing fl rule hdl */ + if (softwarerouting_act == true) + { + handle_software_routing_disable(); + } + + /* free filter rule handlers */ + 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) + { + 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 "); + } + + + 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) + { + 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) + { + if(m_filtering.DeleteFilteringHdls(ipv6_dest_flt_rule_hdl, IPA_IP_v6, num_ipv6_dest_flt_rule) == false) + { + IPACMERR("Failed to delete ipv6 dest flt rules.\n"); + 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 "); + } + if(hdr_proc_hdl_dummy_v6) + { + if(m_header.DeleteHeaderProcCtx(hdr_proc_hdl_dummy_v6) == false) + { + IPACMERR("Failed to delete hdr_proc_hdl_dummy_v6\n"); + res = IPACM_FAILURE; + goto fail; + } + } + if(hdr_hdl_dummy_v6) + { + if (m_header.DeleteHeaderHdl(hdr_hdl_dummy_v6) == false) + { + IPACMERR("Failed to delete hdr_hdl_dummy_v6\n"); + res = IPACM_FAILURE; + goto fail; + } + } +fail: + if (tx_prop != NULL) + { + free(tx_prop); + } + if (rx_prop != NULL) + { + free(rx_prop); + } + if (iface_query != NULL) + { + free(iface_query); + } + if (wan_route_rule_v4_hdl != NULL) + { + free(wan_route_rule_v4_hdl); + } + if (wan_route_rule_v6_hdl != NULL) + { + free(wan_route_rule_v6_hdl); + } + if (wan_route_rule_v6_hdl_a5 != NULL) + { + free(wan_route_rule_v6_hdl_a5); + } + if (wan_client != NULL) + { + free(wan_client); + } + close(m_fd_ipa); + return res; +} + +int IPACM_Wan::handle_down_evt_ex() +{ + int res = IPACM_SUCCESS; + int i, tether_total; + int ipa_if_num_tether_tmp[IPA_MAX_IFACE_ENTRIES]; + + IPACMDBG_H(" wan handle_down_evt \n"); + + /* free ODU filter rule handlers */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == EMBMS_IF) + { + embms_is_on = false; + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + if (tx_prop != NULL) + { + 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]); + } + + if (rx_prop != NULL) + { + install_wan_filtering_rule(false); + IPACMDBG("finished delete embms filtering rule\n "); + } + 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--; + IPACMDBG_H("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn); + /* only when default gw goes down we post WAN_DOWN event*/ + if(is_default_gateway == true) + { + IPACM_Wan::wan_up = false; + del_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v4); +#ifdef FEATURE_IPA_ANDROID + /* posting wan_down_tether for all lan clients */ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++) + { + ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i]; + } + tether_total = IPACM_Wan::ipa_if_num_tether_v4_total; + for (i=0; i < tether_total; i++) + { + post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]); + IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n", + i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name); + } +#endif + if(IPACM_Wan::wan_up_v6) + { + IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + + /* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/ + if(num_ipv4_modem_pdn == 0) + { + IPACMDBG_H("Now the number of modem ipv4 interface is 0, delete default flt rules.\n"); + IPACM_Wan::num_v4_flt_rule = 0; + memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add)); + install_wan_filtering_rule(false); + } + + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + else if(ip_type == IPA_IP_v6) + { + if (num_dft_rt_v6 > 1) + num_ipv6_modem_pdn--; + IPACMDBG_H("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn); + /* only when default gw goes down we post WAN_DOWN event*/ + if(is_default_gateway == true) + { + IPACM_Wan::wan_up_v6 = false; + 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 + /* posting wan_down_tether for all lan clients */ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++) + { + ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i]; + } + tether_total = IPACM_Wan::ipa_if_num_tether_v6_total; + for (i=0; i < tether_total; i++) + { + post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]); + IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n", + i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name); + } +#endif + if(IPACM_Wan::wan_up) + { + IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + + /* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/ + if(num_ipv6_modem_pdn == 0) + { + IPACMDBG_H("Now the number of modem ipv6 interface is 0, delete default flt rules.\n"); + IPACM_Wan::num_v6_flt_rule = 0; + memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add)); + install_wan_filtering_rule(false); + } + + for (i = 0; i < 2*num_dft_rt_v6; i++) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + else + { + num_ipv4_modem_pdn--; + IPACMDBG_H("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn); + if (num_dft_rt_v6 > 1) + num_ipv6_modem_pdn--; + IPACMDBG_H("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn); + /* only when default gw goes down we post WAN_DOWN event*/ + if(is_default_gateway == true) + { + IPACM_Wan::wan_up = false; + del_wan_firewall_rule(IPA_IP_v4); + handle_route_del_evt_ex(IPA_IP_v4); +#ifdef FEATURE_IPA_ANDROID + /* posting wan_down_tether for all lan clients */ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++) + { + ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i]; + } + tether_total = IPACM_Wan::ipa_if_num_tether_v4_total; + for (i=0; i < tether_total; i++) + { + post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]); + IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n", + i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name); + } +#endif + IPACM_Wan::wan_up_v6 = false; + del_wan_firewall_rule(IPA_IP_v6); + handle_route_del_evt_ex(IPA_IP_v6); +#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++) + { + ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i]; + } + tether_total = IPACM_Wan::ipa_if_num_tether_v6_total; + for (i=0; i < tether_total; i++) + { + post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]); + IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n", + i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name); + } +#endif + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + + install_wan_filtering_rule(false); + } + + /* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/ + if(num_ipv4_modem_pdn == 0) + { + IPACMDBG_H("Now the number of modem ipv4 interface is 0, delete default flt rules.\n"); + IPACM_Wan::num_v4_flt_rule = 0; + memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add)); + install_wan_filtering_rule(false); + } + /* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/ + if(num_ipv6_modem_pdn == 0) + { + IPACMDBG_H("Now the number of modem ipv6 interface is 0, delete default flt rules.\n"); + IPACM_Wan::num_v6_flt_rule = 0; + memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add)); + install_wan_filtering_rule(false); + } + + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + + for (i = 0; i < 2*num_dft_rt_v6; i++) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + + /* check software routing fl rule hdl */ + if (softwarerouting_act == true) + { + handle_software_routing_disable(); + } + +fail: + if (tx_prop != NULL) + { + free(tx_prop); + } + if (rx_prop != NULL) + { + free(rx_prop); + } + if (ext_prop != NULL) + { + free(ext_prop); + } + if (iface_query != NULL) + { + free(iface_query); + } + if (wan_route_rule_v4_hdl != NULL) + { + free(wan_route_rule_v4_hdl); + } + if (wan_route_rule_v6_hdl != NULL) + { + free(wan_route_rule_v6_hdl); + } + if (wan_route_rule_v6_hdl_a5 != NULL) + { + free(wan_route_rule_v6_hdl_a5); + } + if (wan_client != NULL) + { + free(wan_client); + } + close(m_fd_ipa); + return res; +} + +int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) +{ + int len, res = IPACM_SUCCESS; + uint8_t mux_id; + ipa_ioc_add_flt_rule *pFilteringTable_v4 = NULL; + ipa_ioc_add_flt_rule *pFilteringTable_v6 = NULL; + + mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); + if(rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + if (is_sw_routing == true || + IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true) + { + /* contruct SW-RT rules to Q6*/ + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + ipa_ioc_generate_flt_eq flt_eq; + + IPACMDBG("\n"); + if (softwarerouting_act == true) + { + IPACMDBG("already setup software_routing rule for (%s)iface ip-family %d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type); + return IPACM_SUCCESS; + } + + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable_v4 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable_v4, 0, len); + IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is 1\n"); + + pFilteringTable_v4->commit = 1; + pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe; + pFilteringTable_v4->global = false; + pFilteringTable_v4->ip = IPA_IP_v4; + pFilteringTable_v4->num_rules = (uint8_t)1; + + /* 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)); + 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) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + flt_rule_entry.at_rear = false; + 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, + sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v4; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(pFilteringTable_v4->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable_v6 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + free(pFilteringTable_v4); + return IPACM_FAILURE; + } + memset(pFilteringTable_v6, 0, len); + IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is 1\n"); + + pFilteringTable_v6->commit = 1; + pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe; + pFilteringTable_v6->global = false; + pFilteringTable_v6->ip = IPA_IP_v6; + pFilteringTable_v6->num_rules = (uint8_t)1; + + /* 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)); + 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"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + flt_rule_entry.at_rear = false; + 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, + sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v6; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(pFilteringTable_v6->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + softwarerouting_act = true; + /* end of contruct SW-RT rules to Q6*/ + } + else + { + if(embms_is_on == false) + { + if(IPACM_Wan::num_v4_flt_rule > 0) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v4_flt_rule * sizeof(struct ipa_flt_rule_add); + pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len); + + IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is %d\n", IPACM_Wan::num_v4_flt_rule); + + if (pFilteringTable_v4 == NULL) + { + 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; + pFilteringTable_v4->ip = IPA_IP_v4; + pFilteringTable_v4->num_rules = (uint8_t)IPACM_Wan::num_v4_flt_rule; + + memcpy(pFilteringTable_v4->rules, IPACM_Wan::flt_rule_v4, IPACM_Wan::num_v4_flt_rule * sizeof(ipa_flt_rule_add)); + } + + if(IPACM_Wan::num_v6_flt_rule > 0) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v6_flt_rule * sizeof(struct ipa_flt_rule_add); + pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len); + + IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is %d\n", IPACM_Wan::num_v6_flt_rule); + + if (pFilteringTable_v6 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + 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; + pFilteringTable_v6->ip = IPA_IP_v6; + pFilteringTable_v6->num_rules = (uint8_t)IPACM_Wan::num_v6_flt_rule; + + memcpy(pFilteringTable_v6->rules, IPACM_Wan::flt_rule_v6, IPACM_Wan::num_v6_flt_rule * sizeof(ipa_flt_rule_add)); + } + } + else //embms is on, always add 1 embms rule on top of WAN DL flt table + { + /* allocate ipv4 filtering table */ + len = sizeof(struct ipa_ioc_add_flt_rule) + (1 + IPACM_Wan::num_v4_flt_rule) * sizeof(struct ipa_flt_rule_add); + pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len); + IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is %d\n", IPACM_Wan::num_v4_flt_rule + 1); + if (pFilteringTable_v4 == NULL) + { + 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; + pFilteringTable_v4->ip = IPA_IP_v4; + pFilteringTable_v4->num_rules = (uint8_t)IPACM_Wan::num_v4_flt_rule + 1; + + /* allocate ipv6 filtering table */ + len = sizeof(struct ipa_ioc_add_flt_rule) + (1 + IPACM_Wan::num_v6_flt_rule) * sizeof(struct ipa_flt_rule_add); + pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len); + IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is %d\n", IPACM_Wan::num_v6_flt_rule + 1); + if (pFilteringTable_v6 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + 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; + pFilteringTable_v6->ip = IPA_IP_v6; + pFilteringTable_v6->num_rules = (uint8_t)IPACM_Wan::num_v6_flt_rule + 1; + + config_dft_embms_rules(pFilteringTable_v4, pFilteringTable_v6); + if(IPACM_Wan::num_v4_flt_rule > 0) + { + memcpy(&(pFilteringTable_v4->rules[1]), IPACM_Wan::flt_rule_v4, IPACM_Wan::num_v4_flt_rule * sizeof(ipa_flt_rule_add)); + } + + if(IPACM_Wan::num_v6_flt_rule > 0) + { + memcpy(&(pFilteringTable_v6->rules[1]), IPACM_Wan::flt_rule_v6, IPACM_Wan::num_v6_flt_rule * sizeof(ipa_flt_rule_add)); + } + } + } + + if(false == m_filtering.AddWanDLFilteringRule(pFilteringTable_v4, pFilteringTable_v6, mux_id)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + +fail: + if(pFilteringTable_v4 != NULL) + { + free(pFilteringTable_v4); + } + if(pFilteringTable_v6 != NULL) + { + free(pFilteringTable_v6); + } + return res; +} + +void IPACM_Wan::change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib) +{ + if(attrib == NULL) + { + IPACMERR("Attribute pointer is NULL.\n"); + return; + } + + if(iptype == IPA_IP_v6) + { + int i; + for(i=0; i<4; i++) + { + attrib->u.v6.src_addr[i] = htonl(attrib->u.v6.src_addr[i]); + attrib->u.v6.src_addr_mask[i] = htonl(attrib->u.v6.src_addr_mask[i]); + attrib->u.v6.dst_addr[i] = htonl(attrib->u.v6.dst_addr[i]); + attrib->u.v6.dst_addr_mask[i] = htonl(attrib->u.v6.dst_addr_mask[i]); + } + } + else + { + IPACMDBG_H("IP type is not IPv6, do nothing: %d\n", iptype); + } + + return; +} + +bool IPACM_Wan::is_global_ipv6_addr(uint32_t* ipv6_addr) +{ + if(ipv6_addr == NULL) + { + IPACMERR("IPv6 address is empty.\n"); + return false; + } + IPACMDBG_H("Get ipv6 address with first word 0x%08x.\n", ipv6_addr[0]); + + uint32_t ipv6_link_local_prefix, ipv6_link_local_prefix_mask; + ipv6_link_local_prefix = 0xFE800000; + ipv6_link_local_prefix_mask = 0xFFC00000; + if((ipv6_addr[0] & ipv6_link_local_prefix_mask) == (ipv6_link_local_prefix & ipv6_link_local_prefix_mask)) + { + IPACMDBG_H("This IPv6 address is link local.\n"); + return false; + } + else + { + IPACMDBG_H("This IPv6 address is not link local.\n"); + return true; + } +} + +/* handle STA WAN-client */ +/* handle WAN client initial, construct full headers (tx property) */ +int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) +{ + +#define WAN_IFACE_INDEX_LEN 2 + + 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; + uint32_t cnt; + int clnt_indx; + + clnt_indx = get_wan_client_index(mac_addr); + + if (clnt_indx != IPACM_INVALID_INDEX) + { + IPACMERR("eth client is found/attached already with index %d \n", clnt_indx); + return IPACM_FAILURE; + } + + /* add header to IPA */ + if (num_wan_client >= IPA_MAX_NUM_WAN_CLIENTS) + { + IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_WAN_CLIENTS); + return IPACM_FAILURE; + } + + IPACMDBG_H("WAN client number: %d\n", num_wan_client); + + memcpy(get_client_memptr(wan_client, num_wan_client)->mac, + 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]); + + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, num_wan_client)->mac[0], + get_client_memptr(wan_client, num_wan_client)->mac[1], + get_client_memptr(wan_client, num_wan_client)->mac[2], + get_client_memptr(wan_client, num_wan_client)->mac[3], + get_client_memptr(wan_client, num_wan_client)->mac[4], + get_client_memptr(wan_client, num_wan_client)->mac[5]); + + /* 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; + } + + /* 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); + 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"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + /* 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(&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; + + 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'; + 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)); + 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(wan_client, num_wan_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n", + num_wan_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4); + get_client_memptr(wan_client, num_wan_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); + 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"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + /* copy client mac_addr to partial header */ + 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; + + 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'; + 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; + } + 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(wan_client, num_wan_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n", + num_wan_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6); + + get_client_memptr(wan_client, num_wan_client)->ipv6_header_set=true; + + break; + + } + } + /* initialize wifi client*/ + get_client_memptr(wan_client, num_wan_client)->route_rule_set_v4 = false; + get_client_memptr(wan_client, num_wan_client)->route_rule_set_v6 = 0; + get_client_memptr(wan_client, num_wan_client)->ipv4_set = false; + get_client_memptr(wan_client, num_wan_client)->ipv6_set = 0; + num_wan_client++; + header_name_count++; //keep increasing header_name_count + res = IPACM_SUCCESS; + IPACMDBG_H("eth client number: %d\n", num_wan_client); + } + else + { + return res; + } +fail: + free(pHeaderDescriptor); + + return res; +} + +/*handle eth client */ +int IPACM_Wan::handle_wan_client_ipaddr(ipacm_event_data_all *data) +{ + int clnt_indx; + int v6_num; + + IPACMDBG_H("number of wan clients: %d\n", num_wan_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_wan_client_index(data->mac_addr); + + if (clnt_indx == IPACM_INVALID_INDEX) + { + IPACMERR("wan 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(wan_client, clnt_indx)->ipv4_set == false) + { + get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr; + get_client_memptr(wan_client, clnt_indx)->ipv4_set = true; + /* Add NAT rules after ipv4 RT rules are set */ + CtList->HandleSTAClientAddEvt(data->ipv4_addr); + } + else + { + /* check if client got new IPv4 address*/ + if(data->ipv4_addr == get_client_memptr(wan_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); + /* Del NAT rules before ipv4 RT rules are delete */ + CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, clnt_indx)->v4_addr); + delete_wan_rtrules(clnt_indx,IPA_IP_v4); + get_client_memptr(wan_client, clnt_indx)->route_rule_set_v4 = false; + get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr; + /* Add NAT rules after ipv4 RT rules are set */ + CtList->HandleSTAClientAddEvt(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(wan_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR) + { + + for(v6_num=0;v6_num < get_client_memptr(wan_client, clnt_indx)->ipv6_set;v6_num++) + { + if( data->ipv6_addr[0] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][0] && + data->ipv6_addr[1] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][1] && + data->ipv6_addr[2]== get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][2] && + data->ipv6_addr[3] == get_client_memptr(wan_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*/ + } + } + + /* not see this ipv6 before for wifi client*/ + get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0]; + get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1]; + get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2]; + get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3]; + get_client_memptr(wan_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 wan client routing rule*/ +int IPACM_Wan::handle_wan_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 wan_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]); + + wan_index = get_wan_client_index(mac_addr); + if (wan_index == IPACM_INVALID_INDEX) + { + IPACMDBG_H("wan client not found/attached \n"); + return IPACM_SUCCESS; + } + + 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); + } 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); + } + + /* 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) + || (iptype == IPA_IP_v6 + && 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 */ + 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)); + + 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", 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); + 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; +#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 */ + 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 */ + 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; + } + + 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; + } + + 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); + } + } + + } /* end of for loop */ + + free(rt_rule); + + if (iptype == IPA_IP_v4) + { + get_client_memptr(wan_client, wan_index)->route_rule_set_v4 = true; + } + else + { + get_client_memptr(wan_client, wan_index)->route_rule_set_v6 = get_client_memptr(wan_client, wan_index)->ipv6_set; + } + } + + 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) +{ + FILE *fp = NULL; + + for (int apn_index =0; apn_index < data->apn_data_stats_list_len; apn_index++) + { + if(data->apn_data_stats_list[apn_index].mux_id == ext_prop->ext[0].mux_id) + { + IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_NETWORK_STATS, MUX ID %d TX (P%lu/B%lu) RX (P%lu/B%lu)\n", + data->apn_data_stats_list[apn_index].mux_id, + data->apn_data_stats_list[apn_index].num_ul_packets, + data->apn_data_stats_list[apn_index].num_ul_bytes, + data->apn_data_stats_list[apn_index].num_dl_packets, + data->apn_data_stats_list[apn_index].num_dl_bytes); + fp = fopen(IPA_NETWORK_STATS_FILE_NAME, "w"); + if ( fp == NULL ) + { + IPACMERR("Failed to write pipe stats to %s, error is %d - %s\n", + IPA_NETWORK_STATS_FILE_NAME, errno, strerror(errno)); + return IPACM_FAILURE; + } + + fprintf(fp, NETWORK_STATS, + dev_name, + data->apn_data_stats_list[apn_index].num_ul_packets, + data->apn_data_stats_list[apn_index].num_ul_bytes, + data->apn_data_stats_list[apn_index].num_dl_packets, + data->apn_data_stats_list[apn_index].num_dl_bytes); + fclose(fp); + break; + }; + } + 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 new file mode 100644 index 0000000..c067550 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wlan.cpp @@ -0,0 +1,2036 @@ +/* +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 +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. +*/ +/*! +@file +IPACM_Wlan.cpp + +@brief +This file implements the WLAN iface functionality. + +@Author +Skylar Chang + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* static member to store the number of total wifi clients within all APs*/ +int IPACM_Wlan::total_num_wifi_clients = 0; + +int IPACM_Wlan::num_wlan_ap_iface = 0; + +IPACM_Wlan::IPACM_Wlan(int iface_index) : IPACM_Lan(iface_index) +{ +#define WLAN_AMPDU_DEFAULT_FILTER_RULES 3 + + wlan_ap_index = IPACM_Wlan::num_wlan_ap_iface; + if(wlan_ap_index < 0 || wlan_ap_index > 1) + { + IPACMERR("Wlan_ap_index is not correct: %d, not creating instance.\n", wlan_ap_index); + if (tx_prop != NULL) + { + free(tx_prop); + } + if (rx_prop != NULL) + { + free(rx_prop); + } + if (iface_query != NULL) + { + free(iface_query); + } + delete this; + return; + } + + num_wifi_client = 0; + header_name_count = 0; + wlan_client = NULL; + + if(iface_query != NULL) + { + wlan_client_len = (sizeof(ipa_wlan_client)) + (iface_query->num_tx_props * sizeof(wlan_client_rt_hdl)); + wlan_client = (ipa_wlan_client *)calloc(IPA_MAX_NUM_WIFI_CLIENTS, wlan_client_len); + if (wlan_client == NULL) + { + IPACMERR("unable to allocate memory\n"); + return; + } + IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props); + } + Nat_App = NatApp::GetInstance(); + if (Nat_App == NULL) + { + IPACMERR("unable to get Nat App instance \n"); + 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); + + m_is_guest_ap = false; + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == INTERNET) + { + m_is_guest_ap = true; + } + 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(ipa_if_cate == WLAN_IF) + { + handle_tethering_client(false, IPACM_CLIENT_WLAN); + } +#endif + return; +} + + +IPACM_Wlan::~IPACM_Wlan() +{ + IPACM_EvtDispatcher::deregistr(this); + IPACM_IfaceManager::deregistr(this); + return; +} + +void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) +{ + if(is_active == false && event != IPA_LAN_DELETE_SELF) + { + IPACMDBG_H("The interface is no longer active, return.\n"); + return; + } + + int ipa_interface_index; + int wlan_index; + ipacm_ext_prop* ext_prop; + ipacm_event_iface_up* data_wan; + ipacm_event_iface_up_tehter* data_wan_tether; + + switch (event) + { + + case IPA_WLAN_LINK_DOWN_EVENT: + { + 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) + { + 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->DelNatIfaces(dev_name); // delete NAT-iface + IPACM_Wlan::total_num_wifi_clients = (IPACM_Wlan::total_num_wifi_clients) - \ + (num_wifi_client); + return; + } + } + break; + + case IPA_PRIVATE_SUBNET_CHANGE_EVENT: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + /* internel event: data->if_index is ipa_if_index */ + if (data->if_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from itself posting, ignore\n"); + return; + } + else + { + IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from other LAN iface \n"); +#ifdef FEATURE_IPA_ANDROID + handle_private_subnet_android(IPA_IP_v4); +#endif + IPACMDBG_H(" delete old private subnet rules, use new sets \n"); + return; + } + } + break; + + case IPA_LAN_DELETE_SELF: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + if(data->if_index == ipa_if_num) + { + IPACM_Wlan::num_wlan_ap_iface--; + IPACMDBG_H("Now the number of wlan AP iface is %d\n", IPACM_Wlan::num_wlan_ap_iface); + + 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); + delete this; + } + break; + } + + case IPA_ADDR_ADD_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) || + (data->iptype == IPA_IP_v6 && + data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 && + data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) ) + { + IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n"); + return; + } + + if (ipa_interface_index == ipa_if_num) + { + /* check v4 not setup before, v6 can have 2 iface ip */ + 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); + /* Post event to NAT */ + if (data->iptype == IPA_IP_v4) + { + ipacm_cmd_q_data evt_data; + ipacm_event_iface_up *info; + + info = (ipacm_event_iface_up *) + malloc(sizeof(ipacm_event_iface_up)); + if (info == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + + memcpy(info->ifname, dev_name, IF_NAME_LEN); + info->ipv4_addr = data->ipv4_addr; + info->addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[0].subnet_mask; + + evt_data.event = IPA_HANDLE_WLAN_UP; + evt_data.evt_data = (void *)info; + + /* Insert IPA_HANDLE_WLAN_UP to command queue */ + IPACMDBG_H("posting IPA_HANDLE_WLAN_UP for IPv4 with below information\n"); + IPACMDBG_H("IPv4 address:0x%x, IPv4 address mask:0x%x\n", + info->ipv4_addr, info->addr_mask); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + + 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)) + { + if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX) + { + 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_Wan::getXlat_Mux_Id()); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v4); + } + } + } + + 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); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v6); + } + } + } + + 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) + { + /* handle software routing enable event*/ + IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + handle_software_routing_enable(); + } + } + } + } + break; +#ifdef FEATURE_IPA_ANDROID + case IPA_HANDLE_WAN_UP_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_TETHER event\n"); + + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\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) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + 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, 0); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v4); + } + } + } + break; + + case IPA_HANDLE_WAN_UP_V6_TETHER: + 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) + { + IPACMERR("No event data is found.\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) + { + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + 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); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v6); + } + } + } + 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) + { + IPACMERR("No event data is found.\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) + { + 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) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + handle_wan_down(data_wan_tether->is_sta); + } + } + } + break; + + case IPA_HANDLE_WAN_DOWN_V6_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6_TETHER event\n"); + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\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) + { + /* 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 */ + handle_wlan_client_reset_rt(IPA_IP_v6); + + if (rx_prop != NULL) + { + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + handle_wan_down_v6(data_wan_tether->is_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) + { + 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(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, data_wan->xlat_mux_id); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v4); + } + } + break; + + case IPA_HANDLE_WAN_UP_V6: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6 event\n"); + + data_wan = (ipacm_event_iface_up*)param; + 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) + { + 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, 0); + } + else + { + IPACM_Lan::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) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + if (rx_prop != NULL) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + handle_wan_down(data_wan->is_sta); + } + } + break; + + 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) + { + IPACMERR("No event data is found.\n"); + return; + } + /* 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 */ + handle_wlan_client_reset_rt(IPA_IP_v6); + 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) + { + handle_wan_down_v6(data_wan->is_sta); + } + } + break; +#endif + + case IPA_WLAN_CLIENT_ADD_EVENT_EX: + { + ipacm_event_data_wlan_ex *data = (ipacm_event_data_wlan_ex *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + int i; + for(i=0; inum_of_attribs; i++) + { + if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->attribs[i].u.mac_addr); + break; + } + } + IPACMDBG_H("Received IPA_WLAN_CLIENT_ADD_EVENT\n"); + handle_wlan_client_init_ex(data); + } + } + break; + + case IPA_WLAN_CLIENT_DEL_EVENT: + { + ipacm_event_data_mac *data = (ipacm_event_data_mac *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WLAN_CLIENT_DEL_EVENT\n"); + eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr); + handle_wlan_client_down_evt(data->mac_addr); + } + } + break; + + case IPA_WLAN_CLIENT_POWER_SAVE_EVENT: + { + ipacm_event_data_mac *data = (ipacm_event_data_mac *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WLAN_CLIENT_POWER_SAVE_EVENT\n"); + handle_wlan_client_pwrsave(data->mac_addr); + } + } + break; + + case IPA_WLAN_CLIENT_RECOVER_EVENT: + { + ipacm_event_data_mac *data = (ipacm_event_data_mac *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WLAN_CLIENT_RECOVER_EVENT\n"); + + wlan_index = get_wlan_client_index(data->mac_addr); + if ((wlan_index != IPACM_INVALID_INDEX) && + (get_client_memptr(wlan_client, wlan_index)->power_save_set == true)) + { + + IPACMDBG_H("change wlan client out of power safe mode \n"); + 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 */ + { + 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); + 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); + } + } + } + } + break; + + case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT: + { + ipacm_event_data_all *data = (ipacm_event_data_all *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT\n"); + if (handle_wlan_client_ipaddr(data) == IPACM_FAILURE) + { + return; + } + + 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); + } + } + } + break; + + /* handle software routing enable event, iface will update softwarerouting_act to true*/ + case IPA_SW_ROUTING_ENABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n"); + IPACM_Iface::handle_software_routing_enable(); + break; + + /* handle software routing disable event, iface will update softwarerouting_act to false*/ + case IPA_SW_ROUTING_DISABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n"); + IPACM_Iface::handle_software_routing_disable(); + break; + + case IPA_WLAN_SWITCH_TO_SCC: + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_SCC\n"); + if(ip_type == IPA_IP_MAX) + { + 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); + break; + + case IPA_WLAN_SWITCH_TO_MCC: + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_MCC\n"); + if(ip_type == IPA_IP_MAX) + { + 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); + break; + + case IPA_CRADLE_WAN_MODE_SWITCH: + { + 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(wan_mode->cradle_wan_mode == BRIDGE) + { + handle_cradle_wan_mode_switch(true); + } + else + { + handle_cradle_wan_mode_switch(false); + } + } + break; + case IPA_CFG_CHANGE_EVENT: + { + IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT event for %s with new wlan-mode: %s old wlan-mode: %s\n", + IPACM_Iface::ipacmcfg->iface_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) + { + IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name); + IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name); + } + + if (m_is_guest_ap == true && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == FULL)) + { + m_is_guest_ap = false; + IPACMDBG_H("wlan mode is switched to full access mode. \n"); + eth_bridge_handle_wlan_mode_switch(); + } + else if (m_is_guest_ap == false && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == INTERNET)) + { + 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"); + if (IPACM_Wan::isWanUP(ipa_if_num) || IPACM_Wan::isWanUP_V6(ipa_if_num)) + { + if(IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */ + { + ipa_get_data_stats_resp_msg_v01 *data = (ipa_get_data_stats_resp_msg_v01 *)param; + if (data->ipa_stats_type != QMI_IPA_STATS_TYPE_PIPE_V01) + { + IPACMERR("not valid pipe stats\n"); + return; + } + handle_tethering_stats_event(data); + }; + } + } + break; + default: + break; + } + return; +} + +/* 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); + /* 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"); + } + } + + 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)); + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + + 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); + + /* 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"); + } + } + + 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)); + 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; + } + + 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; + uint32_t ipv6_link_local_prefix = 0xFE800000; + uint32_t ipv6_link_local_prefix_mask = 0xFFC00000; + + 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( (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(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*/ + } + } + } + + 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); + 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'; + + 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 = 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 */ + 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; + } + + 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, num_private_subnet_fl_rule; + + 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; + } + + /* 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); + 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) + { + /* delete IPv4 icmp filter rules */ + if(m_filtering.DeleteFilteringHdls(ipv4_icmp_flt_rule_hdl, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE) == false) + { + IPACMERR("Error Deleting ICMPv4 Filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE); + + 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 default v4 filter rules successfully.\n"); + + /* 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) + { + 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, 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) + { + 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"); + } + + /* Delete v6 filtering rules */ + if (ip_type != IPA_IP_v4 && rx_prop != NULL) + { + /* delete icmp filter rules */ + 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; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE); + + if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES) == false) + { + 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 default v6 filter rules successfully.\n"); + } + 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("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + + /* Delete default v6 RT rule */ + if (ip_type != IPA_IP_v4) + { + 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++) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) + == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + IPACMDBG_H("finished deleting default RT rules\n "); + + eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL); + + /* 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: + /* 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++) + { + /* 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; + } + + 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; + } + + IPACMDBG_H("Delete %d client header\n", num_wifi_client); + + 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; + } + } + + 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; + } + } + } /* 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(); + } + 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(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); + } + + 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; + } + + /* 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; +} + +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; + + if (tx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return; + } + + 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) + { + PERROR("Error Locate ipa_ioc_mdfy_rt_rule memory...\n"); + return; + } + + rt_rule->commit = 0; + rt_rule->num_rules = NUM; + rt_rule->ip = iptype; + } + rt_rule_entry = &rt_rule->rules[0]; + + /* modify ipv4 routing rule */ + if (iptype == IPA_IP_v4) + { + for (wlan_index = 0; wlan_index < num_wifi_client_tmp; wlan_index++) + { + 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) + { + IPACMDBG_H("client %d route rules not set\n", wlan_index); + continue; + } + + IPACMDBG_H("Modify client %d route rule\n", wlan_index); + 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 ip-type not matching: %d ignore\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + 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) + { + 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; + + 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)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; + } + isAdded = true; + } + + } + } + + /* modify ipv6 routing rule */ + if (iptype == IPA_IP_v6) + { + for (wlan_index = 0; wlan_index < num_wifi_client_tmp; wlan_index++) + { + + 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) ) + { + IPACMDBG_H("client %d route rules not set\n", wlan_index); + continue; + } + + IPACMDBG_H("Modify client %d route rule\n", wlan_index); + 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 ip-type not matching: %d Ignore\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + 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); + + 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; + + rt_rule_entry->rt_rule_hdl = + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num]; + + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; + } + isAdded = true; + } + } + + } + } + + + if (isAdded) + { + if (false == m_routing.Commit(iptype)) + { + IPACMERR("Routing rule modify commit failed!\n"); + free(rt_rule); + return; + } + + IPACMDBG("Routing rule modified successfully \n"); + } + + if(rt_rule) + { + free(rt_rule); + } + return; +} + +void IPACM_Wlan::eth_bridge_handle_wlan_mode_switch() +{ + int i; + + /* ====== post events to mimic WLAN interface goes down/up when AP mode is changing ====== */ + + /* first post IFACE_DOWN event */ + eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL); + + /* then post IFACE_UP event */ + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL); + } + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL); + } + + /* at last post CLIENT_ADD event */ + for(i = 0; i < num_wifi_client; i++) + { + eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, + get_client_memptr(wlan_client, i)->mac); + } + + 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 new file mode 100644 index 0000000..073dc98 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Xml.cpp @@ -0,0 +1,1176 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_Xml.cpp + + @brief + This file implements the XML specific parsing functionality. + + @Author + Skylar Chang/Shihuan Liu +*/ + +#include +#include +#include + +#include "IPACM_Xml.h" +#include "IPACM_Log.h" +#include "IPACM_Netlink.h" + +static char* IPACM_read_content_element +( + xmlNode* element +); + +static int32_t IPACM_util_icmp_string +( + const char* xml_str, + const char* str +); + +static int ipacm_cfg_xml_parse_tree +( + xmlNode* xml_node, + IPACM_conf_t *config +); + +static int IPACM_firewall_xml_parse_tree +( + xmlNode* xml_node, + IPACM_firewall_conf_t *config +); + +/*Reads content (stored as child) of the element */ +static char* IPACM_read_content_element +( + xmlNode* element +) +{ + xmlNode* child_ptr; + + for (child_ptr = element->children; + child_ptr != NULL; + child_ptr = child_ptr->next) + { + if (child_ptr->type == XML_TEXT_NODE) + { + return (char*)child_ptr->content; + } + } + return NULL; +} + +/* insensitive comparison of a libxml's string (xml_str) and a regular string (str)*/ +static int32_t IPACM_util_icmp_string +( + const char* xml_str, + const char* str +) +{ + int32_t ret = -1; + + if (NULL != xml_str && NULL != str) + { + uint32_t len1 = strlen(str); + uint32_t len2 = strlen(xml_str); + /* If the lengths match, do the string comparison */ + if (len1 == len2) + { + ret = strncasecmp(xml_str, str, len1); + } + } + + return ret; +} + +/* This function read IPACM XML and populate the IPA CM Cfg */ +int ipacm_read_cfg_xml(char *xml_file, IPACM_conf_t *config) +{ + xmlDocPtr doc = NULL; + xmlNode* root = NULL; + int ret_val = IPACM_SUCCESS; + + /* 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"); + return IPACM_FAILURE; + } + + /*Get the root of the tree*/ + root = xmlDocGetRootElement(doc); + + memset(config, 0, sizeof(IPACM_conf_t)); + + /* parse the xml tree returned by libxml */ + ret_val = ipacm_cfg_xml_parse_tree(root, config); + + if (ret_val != IPACM_SUCCESS) + { + IPACMDBG_H("IPACM_xml_parse: ipacm_cfg_xml_parse_tree returned parse error!\n"); + } + + /* Free up the libxml's parse tree */ + xmlFreeDoc(doc); + + return ret_val; +} + +/* This function traverses the xml tree*/ +static int ipacm_cfg_xml_parse_tree +( + xmlNode* xml_node, + IPACM_conf_t *config +) +{ + int32_t ret_val = IPACM_SUCCESS; + int str_size; + char* content; + char content_buf[MAX_XML_STR_LEN]; + + if (NULL == xml_node) + return ret_val; + while ( xml_node != NULL && + ret_val == IPACM_SUCCESS) + { + switch (xml_node->type) + { + 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 || + IPACM_util_icmp_string((char*)xml_node->name, IP_PassthroughFlag_TAG) == 0) + { + 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)) + { + /* increase iface entry number */ + config->private_subnet_config.num_subnet_entries++; + } + + 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); + } + else if (IPACM_util_icmp_string((char*)xml_node->name, IP_PassthroughMode_TAG) == 0) + { + 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) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (0 == strncasecmp(content_buf, ODU_ROUTER_TAG, str_size)) + { + config->router_mode_enable = true; + 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_H("router-mode enable %d\n", config->router_mode_enable); + } + } + } + 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); + 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)); + memcpy(content_buf, (void *)content, str_size); + strlcpy(config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].iface_name, content_buf, str_size+1); + 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) + { + 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, WANIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = WAN_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, LANIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = LAN_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, WLANIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = WLAN_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, VIRTUALIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = VIRTUAL_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, UNKNOWNIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = UNKNOWN_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, ETHIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = ETH_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, ODUIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = ODU_IF; + IPACMDBG("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + } + } + 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) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->private_subnet_config.private_subnet_entries[config->private_subnet_config.num_subnet_entries - 1].subnet_addr + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("subnet_addr: %s \n", content_buf); + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, SUBNETMASK_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); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->private_subnet_config.private_subnet_entries[config->private_subnet_config.num_subnet_entries - 1].subnet_mask + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("subnet_mask: %s \n", content_buf); + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, Protocol_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); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + + 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); + } + 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); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, Port_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); + config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].port + = atoi(content_buf); + 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) + { + 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); + config->nat_max_entries = atoi(content_buf); + IPACMDBG_H("Nat Table Max Entries %d\n", config->nat_max_entries); + } + } + } + break; + default: + break; + } + /* go to sibling */ + xml_node = xml_node->next; + } /* end while */ + return ret_val; +} + +/* This function read QCMAP CM Firewall XML and populate the QCMAP CM Cfg */ +int IPACM_read_firewall_xml(char *xml_file, IPACM_firewall_conf_t *config) +{ + xmlDocPtr doc = NULL; + xmlNode* root = NULL; + int ret_val; + + IPACM_ASSERT(xml_file != NULL); + IPACM_ASSERT(config != NULL); + + /* 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"); + return IPACM_FAILURE; + } + /*get the root of the tree*/ + root = xmlDocGetRootElement(doc); + + /* parse the xml tree returned by libxml*/ + ret_val = IPACM_firewall_xml_parse_tree(root, config); + + if (ret_val != IPACM_SUCCESS) + { + IPACMDBG_H("IPACM_xml_parse: ipacm_firewall_xml_parse_tree returned parse error!\n"); + } + + /* free the tree */ + xmlFreeDoc(doc); + + return ret_val; +} + + +/* This function traverses the firewall xml tree */ +static int IPACM_firewall_xml_parse_tree +( + xmlNode* xml_node, + IPACM_firewall_conf_t *config +) +{ + int mask_value_v6, mask_index; + int32_t ret_val = IPACM_SUCCESS; + char *content; + int str_size; + char content_buf[MAX_XML_STR_LEN]; + struct in6_addr ip6_addr; + + IPACM_ASSERT(config != NULL); + + if (NULL == xml_node) + return ret_val; + + while ( xml_node != NULL && + ret_val == IPACM_SUCCESS) + { + switch (xml_node->type) + { + + 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, Firewall_TAG)) + { + /* increase firewall entry num */ + config->num_extd_firewall_entries++; + } + + if (0 == IPACM_util_icmp_string((char*)xml_node->name, FirewallPktsAllowed_TAG)) + { + /* setup action of matched rules */ + 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)==1) + { + config->rule_action_accept = true; + } + else + { + config->rule_action_accept = false; + } + 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)) + { + /* setup if firewall enable or not */ + 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)==1) + { + config->firewall_enable = true; + } + else + { + config->firewall_enable = false; + } + IPACMDBG_H(" Firewall Enable?:%d\n", config->firewall_enable); + } + } + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPFamily_TAG)) + { + 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); + 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); + } + } + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceIPAddress_TAG)) + { + 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); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.src_addr + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("IPv4 source address is: %s \n", content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceSubnetMask_TAG)) + { + 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); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.src_addr_mask + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("IPv4 source subnet mask is: %s \n", content_buf); + } + } + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationIPAddress_TAG)) + { + 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); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.dst_addr + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("IPv4 destination address is: %s \n", content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationSubnetMask_TAG)) + { + 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); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + if (content_buf > 0) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.dst_addr_mask + = 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)) + { + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TOSValue_TAG)) + { + 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); + 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)) + { + 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); + 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); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4NextHeaderProtocol_TAG)) + { + 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); + 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); + } + } + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourceIPAddress_TAG)) + { + 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); + inet_pton(AF_INET6, content_buf, &ip6_addr); + memcpy(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr, + ip6_addr.s6_addr, IPACM_IPV6_ADDR_LEN * sizeof(uint8_t)); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[0]=ntohl(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[1]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[1]); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[2]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[2]); + 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]); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourcePrefix_TAG)) + { + 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); + mask_value_v6 = atoi(content_buf); + for (mask_index = 0; mask_index < 4; mask_index++) + { + if (mask_value_v6 >= 32) + { + mask_v6(32, &(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr_mask[mask_index])); + mask_value_v6 -= 32; + } + else + { + mask_v6(mask_value_v6, &(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr_mask[mask_index])); + mask_value_v6 = 0; + } + } + 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)) + { + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationIPAddress_TAG)) + { + 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); + inet_pton(AF_INET6, content_buf, &ip6_addr); + memcpy(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr, + ip6_addr.s6_addr, IPACM_IPV6_ADDR_LEN * sizeof(uint8_t)); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[0]=ntohl(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[1]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[1]); + 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]); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationPrefix_TAG)) + { + 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); + mask_value_v6 = atoi(content_buf); + for (mask_index = 0; mask_index < 4; mask_index++) + { + if (mask_value_v6 >= 32) + { + mask_v6(32, &(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr_mask[mask_index])); + mask_value_v6 -= 32; + } + else + { + mask_v6(mask_value_v6, &(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr_mask[mask_index])); + mask_value_v6 = 0; + } + } + 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)) + { + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TrfClsValue_TAG)) + { + 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); + 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); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TrfClsMask_TAG)) + { + 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); + 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)); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6NextHeaderProtocol_TAG)) + { + 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); + 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); + } + } + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSourcePort_TAG)) + { + 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); + 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)) + { + 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) != 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); + } + 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); + } + } + } + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestinationPort_TAG)) + { + 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); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + = atoi(content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestinationRange_TAG)) + { + 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)!=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); + } + 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); + } + } + } + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSourcePort_TAG)) + { + 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); + 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, UDPSourceRange_TAG)) + { + 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)!=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); + } + 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); + } + } + } + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestinationPort_TAG)) + { + 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); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + = atoi(content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestinationRange_TAG)) + { + 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)!=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); + } + 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); + } + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ICMPType_TAG)) + { + 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); + 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); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ICMPCode_TAG)) + { + 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); + 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); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ESPSPI_TAG)) + { + 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); + 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); + } + } + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSourcePort_TAG)) + { + 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); + 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, TCP_UDPSourceRange_TAG)) + { + 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)!=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); + } + 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); + + } + } + } + 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); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestinationPort_TAG)) + { + 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); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + = atoi(content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestinationRange_TAG)) + { + 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)!=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); + } + 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); + } + } + } + } + break; + + default: + break; + } + /* go to sibling */ + xml_node = xml_node->next; + } /* 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 new file mode 100644 index 0000000..9bac7a4 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_cfg.xml @@ -0,0 +1,175 @@ + + + + router + 0 + + + + + rndis0 + LAN + + + ecm0 + LAN + ROUTER + + + rmnet_data0 + WAN + ROUTER + + + rmnet_data1 + WAN + + + rmnet_data2 + WAN + + + rmnet_data3 + WAN + + + rmnet_data4 + WAN + + + rmnet_data5 + WAN + + + rmnet_data6 + WAN + + + rmnet_data7 + WAN + + + softap0 + UNKNOWN + full + + + wlan0 + UNKNOWN + full + + + wlan1 + UNKNOWN + full + + + wlan2 + UNKNOWN + full + + + wlan3 + UNKNOWN + full + + + eth0 + ODU + + + bridge0 + VIRTUAL + + + + 0 + + + + 192.168.225.0 + 255.255.255.0 + + + + + TCP + 21 + FTP + + + TCP + 554 + RTSP + + + TCP + 5060 + SIP + + + UDP + 5060 + SIP + + + TCP + 1723 + PPTP + + + UDP + 69 + TFTP + + + UDP + 53 + DNS + + + TCP + 53 + DNS + + + UDP + 10080 + AMANDA + + + UDP + 1719 + H323 + + + TCP + 1720 + H323 + + + TCP + 6667 + IRC + + + UDP + 137 + NETBIOS_NS + + + UDP + 138 + NETBIOS_NS + + + TCP + 6566 + SANE + + + + 500 + + + diff --git a/data-ipa-cfg-mgr/ipacm/src/Makefile.am b/data-ipa-cfg-mgr/ipacm/src/Makefile.am new file mode 100644 index 0000000..7a62a75 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/Makefile.am @@ -0,0 +1,55 @@ +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 += -DFEATURE_IPA_V3 + +ipacm_SOURCES = IPACM_Main.cpp \ + IPACM_Conntrack_NATApp.cpp\ + IPACM_ConntrackClient.cpp \ + IPACM_ConntrackListener.cpp \ + IPACM_EvtDispatcher.cpp \ + IPACM_Config.cpp \ + IPACM_CmdQueue.cpp \ + IPACM_Log.cpp \ + IPACM_Filtering.cpp \ + IPACM_Routing.cpp \ + IPACM_Header.cpp \ + IPACM_Lan.cpp \ + IPACM_Iface.cpp \ + IPACM_Wlan.cpp \ + IPACM_Wan.cpp \ + IPACM_IfaceManager.cpp \ + IPACM_Neighbor.cpp \ + IPACM_Netlink.cpp \ + IPACM_Xml.cpp \ + IPACM_LanToLan.cpp + +bin_PROGRAMS = ipacm + +requiredlibs = ${LIBXML_LIB} -lxml2 -lpthread -lnetfilter_conntrack -lnfnetlink\ + ../../ipanat/src/libipanat.la + +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) + +etcdir = ${sysconfdir} +etc_SCRIPTS = IPACM_cfg.xml + +init_ddir = ${sysconfdir}/init.d +init_d_SCRIPTS = start_ipacm_le diff --git a/data-ipa-cfg-mgr/ipacm/src/mobileap_firewall.xml b/data-ipa-cfg-mgr/ipacm/src/mobileap_firewall.xml new file mode 100644 index 0000000..84da527 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/mobileap_firewall.xml @@ -0,0 +1,7 @@ + + + + 1 + 0 + + diff --git a/data-ipa-cfg-mgr/ipacm/src/start_ipacm_le b/data-ipa-cfg-mgr/ipacm/src/start_ipacm_le new file mode 100644 index 0000000..3541a0b --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/start_ipacm_le @@ -0,0 +1,57 @@ +#! /bin/sh +# +################################ +# Copyright (c) 2013, 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. +################################ + +# ipacm init.d script to start the data-ipa Software's ipacm daemon + +set -e + +case "$1" in + start) + echo -n "Starting ipacm: " + start-stop-daemon -S -b -a ipacm + echo "done" + ;; + stop) + echo -n "Stopping ipacm: " + start-stop-daemon -K -n ipacm + echo "done" + ;; + restart) + $0 stop + $0 start + ;; + *) + echo "Usage ipacm { start | stop | restart}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h new file mode 100644 index 0000000..04e3af9 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h @@ -0,0 +1,116 @@ +/* +Copyright (c) 2013, 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 "string.h" /* memset */ +#include "stdlib.h" /* free, malloc */ +#include "stdint.h" /* uint32_t */ + +/** + * struct ipa_nat_ipv4_rule - To hold ipv4 nat rule + * @target_ip: destination ip address + * @private_ip: private ip address + * @target_port: destination port + * @private_port: private port + * @protocol: protocol of rule (tcp/udp) + */ +typedef struct { + uint32_t target_ip; + uint32_t private_ip; + uint16_t target_port; + uint16_t private_port; + uint16_t public_port; + uint8_t protocol; +} ipa_nat_ipv4_rule; + +/** + * ipa_nat_add_ipv4_tbl() - create ipv4 nat table + * @public_ip_addr: [in] public ipv4 address + * @number_of_entries: [in] number of nat entries + * @table_handle: [out] Handle of new ipv4 nat table + * + * To create new ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_add_ipv4_tbl(uint32_t public_ip_addr, + uint16_t number_of_entries, + uint32_t *table_handle); + +/** + * ipa_nat_del_ipv4_tbl() - delete ipv4 table + * @table_handle: [in] Handle of ipv4 nat table + * + * To delete given ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_del_ipv4_tbl(uint32_t table_handle); + +/** + * ipa_nat_add_ipv4_rule() - to insert new ipv4 rule + * @table_handle: [in] handle of ipv4 nat table + * @rule: [in] Pointer to new rule + * @rule_handle: [out] Return the handle to rule + * + * To insert new ipv4 nat rule into ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_add_ipv4_rule(uint32_t table_handle, + const ipa_nat_ipv4_rule * rule, + uint32_t *rule_handle); + +/** + * ipa_nat_del_ipv4_rule() - to delete ipv4 nat rule + * @table_handle: [in] handle of ipv4 nat table + * @rule_handle: [in] ipv4 nat rule handle + * + * To insert new ipv4 nat rule into ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_del_ipv4_rule(uint32_t table_handle, + uint32_t rule_handle); + + +/** + * ipa_nat_query_timestamp() - to query timestamp + * @table_handle: [in] handle of ipv4 nat table + * @rule_handle: [in] ipv4 nat rule handle + * @time_stamp: [out] time stamp of rule + * + * To retrieve the timestamp that lastly the + * nat rule was accessed + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_query_timestamp(uint32_t table_handle, + uint32_t rule_handle, + uint32_t *time_stamp); + diff --git a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h new file mode 100644 index 0000000..6f9b1bd --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h @@ -0,0 +1,482 @@ +/* +Copyright (c) 2013, 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_NAT_DRVI_H +#define IPA_NAT_DRVI_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipa_nat_logi.h" + +#define NAT_DUMP + +/*======= IMPLEMENTATION related data structures and functions ======= */ +#ifdef IPA_ON_R3PC +#define NAT_MMAP_MEM_SIZE (2 * 1024UL * 1024UL - 1) +#endif + +#define IPA_DEV_NAME "/dev/ipa" +#define NAT_DEV_DIR "/dev" +#define NAT_DEV_NAME "ipaNatTable" +#define NAT_DEV_FULL_NAME "/dev/ipaNatTable" + +#define IPA_NAT_TABLE_VALID 1 +#define IPA_NAT_MAX_IP4_TBLS 1 +#define IPA_NAT_BASE_TABLE_PERCENTAGE .8 +#define IPA_NAT_EXPANSION_TABLE_PERCENTAGE .2 + +#define IPA_NAT_NUM_OF_BASE_TABLES 2 +#define IPA_NAT_UNUSED_BASE_ENTRIES 2 + +#define IPA_NAT_RULE_FLAG_FIELD_OFFSET 18 +#define IPA_NAT_RULE_NEXT_FIELD_OFFSET 8 +#define IPA_NAT_RULE_PROTO_FIELD_OFFSET 22 + +#define IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET 2 +#define IPA_NAT_INDEX_RULE_NAT_INDEX_FIELD_OFFSET 0 + +#define IPA_NAT_RULE_FLAG_FIELD_SIZE 2 +#define IPA_NAT_RULE_NEXTFIELD_FIELD_SIZE 2 + +#define IPA_NAT_FLAG_ENABLE_BIT_MASK 0x8000 +#define IPA_NAT_FLAG_DISABLE_BIT_MASK 0x0000 + +#define IPA_NAT_FLAG_ENABLE_BIT 1 +#define IPA_NAT_FLAG_DISABLE_BIT 0 + +#define IPA_NAT_INVALID_PROTO_FIELD_VALUE 0xFF00 +#define IPA_NAT_INVALID_PROTO_FIELD_CMP 0xFF + +#define IPA_NAT_INVALID_INDEX 0xFF +#define IPA_NAT_INVALID_NAT_ENTRY 0x0 + +#define INDX_TBL_ENTRY_SIZE_IN_BITS 16 + +/* ----------- Rule id ----------------------- + + ------------------------------------------------ + | 3bits | 12 bits | 1 bit | + ------------------------------------------------ + | reserved | index into table | 0 - base | + | | | 1 - expansion | + ------------------------------------------------ + +*/ +#define IPA_NAT_RULE_HDL_TBL_TYPE_BITS 0x1 +#define IPA_NAT_RULE_HDL_TBL_TYPE_MASK 0x1 + +/* ----------- sw specif parameter ----- + ------------------------------------ + | 16 bits | 16 bits | + ------------------------------------ + | index table | prev index | + | entry | | + ------------------------------------ +-----------------------------------------*/ +#define IPA_NAT_SW_PARAM_PREV_INDX_BYTE 0 +#define IPA_NAT_SW_PARAM_INDX_TBL_ENTRY_BYTE 1 + +typedef enum { + IPA_NAT_BASE_TBL = 0, + IPA_NAT_EXPN_TBL = 1, + IPA_NAT_INDX_TBL = 2, + IPA_NAT_INDEX_EXPN_TBL = 3, +} nat_table_type; + +typedef enum { + NEXT_INDEX_FIELD, + PUBLIC_PORT_FILED, + PRIVATE_PORT_FIELD, + TARGET_PORT_FIELD, + IP_CHKSUM_FIELD, + ENABLE_FIELD, + TIME_STAMP_FIELD, + PROTOCOL_FIELD, + TCP_UDP_CHKSUM_FIELD, + SW_SPEC_PARAM_PREV_INDEX_FIELD, + SW_SPEC_PARAM_INDX_TBL_ENTRY_FIELD, + INDX_TBL_TBL_ENTRY_FIELD, + INDX_TBL_NEXT_INDEX_FILED +} ipa_nat_rule_field_type; + +/* + --------------------------------------------- + | 3 | 2 | 1 | 0 | + --------------------------------------------- + | Public Port(2B) | Next Index(2B) | + --------------------------------------------- +*/ +typedef struct { + uint32_t next_index:16; + uint32_t public_port:16; +} next_index_pub_port; + + +/* + --------------------------------------------- + | 3 | 2 | 1 | 0 | + --------------------------------------------- + | Flags(2B) | IP check sum Diff(2B)| + |EN|FIN|Resv | | | + --------------------------------------------- +*/ +typedef struct { + uint32_t ip_chksum:16; + uint32_t rsvd1:14; + uint32_t redirect:1; + uint32_t enable:1; +} ipcksum_enbl; + + +/* + --------------------------------------- + | 7 | 6 | 5 | 4 | + --------------------------------------- + | Proto | TimeStamp(3B) | + | (1B) | | + --------------------------------------- +*/ +typedef struct { + uint32_t time_stamp:24; + uint32_t protocol:8; +} time_stamp_proto; + + +/* + --------------------------------------------- + | 3 | 2 | 1 | 0 | + --------------------------------------------- + | next_index | Table entry | + ---------------------------------------------- +*/ +typedef struct { + uint16_t tbl_entry; + uint16_t next_index; +} tbl_ent_nxt_indx; + +/*-------------------------------------------------- + 32 bit sw_spec_params is interpreted as follows + ------------------------------------ + | 16 bits | 16 bits | + ------------------------------------ + | index table | prev index | + | entry | | + ------------------------------------ +--------------------------------------------------*/ +typedef struct { + uint16_t prev_index; + uint16_t index_table_entry; +} sw_spec_params; + +/*------------------------ NAT Table Entry --------------------------------------- + + ----------------------------------------------------------------------------------- + | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + ----------------------------------------------------------------------------------- + | Target IP(4B) | Private IP(4B) | + ----------------------------------------------------------------------------------- + |Target Port(2B) | Private Port(2B) | Public Port(2B) | Next Index(2B) | + ----------------------------------------------------------------------------------- + | 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) | | + ----------------------------------------------------------------------------------- + + Dont change below structure definition. + It should be same as above(little endian order) + -------------------------------------------------------------------------------*/ +struct ipa_nat_rule { + uint64_t private_ip:32; + uint64_t target_ip:32; + + uint64_t nxt_indx_pub_port:32; + uint64_t private_port:16; + uint64_t target_port:16; + + uint64_t ip_cksm_enbl:32; + uint64_t ts_proto:32; + + /*-------------------------------------------------- + 32 bit sw_spec_params is interpreted as follows + ------------------------------------ + | 16 bits | 16 bits | + ------------------------------------ + | index table | prev index | + | entry | | + ------------------------------------ + --------------------------------------------------*/ + uint64_t sw_spec_params:32; + + uint64_t rsvd2:16; + uint64_t tcp_udp_chksum:16; +}; + +struct ipa_nat_sw_rule { + uint64_t private_ip:32; + uint64_t target_ip:32; + + uint64_t next_index:16; + uint64_t public_port:16; + uint64_t private_port:16; + uint64_t target_port:16; + + uint64_t ip_chksum:16; + uint64_t rsvd1:14; + uint64_t redirect:1; + uint64_t enable:1; + uint64_t time_stamp:24; + uint64_t protocol:8; + + /*-------------------------------------------------- + 32 bit sw_spec_params is interpreted as follows + ------------------------------------ + | 16 bits | 16 bits | + ------------------------------------ + | index table | prev index | + | entry | | + ------------------------------------ + --------------------------------------------------*/ + uint64_t prev_index:16; + uint64_t indx_tbl_entry:16; + uint64_t rsvd2:16; + uint64_t tcp_udp_chksum:16; +}; +#define IPA_NAT_TABLE_ENTRY_SIZE 32 +#define IPA_NAT_INDEX_TABLE_ENTRY_SIZE 4 + +struct ipa_nat_indx_tbl_rule { + uint32_t tbl_entry_nxt_indx; +}; + +struct ipa_nat_sw_indx_tbl_rule { + uint16_t tbl_entry; + uint16_t next_index; +}; + +struct ipa_nat_indx_tbl_meta_info { + uint16_t prev_index; +}; + +struct ipa_nat_ip4_table_cache { + uint8_t valid; + uint32_t public_addr; + + int nat_fd; + int size; + uint32_t tbl_addr_offset; + char table_name[IPA_RESOURCE_NAME_MAX]; + + char *ipv4_rules_addr; + char *index_table_addr; + uint16_t table_entries; + + char *ipv4_expn_rules_addr; + char *index_table_expn_addr; + uint16_t expn_table_entries; + + struct ipa_nat_indx_tbl_meta_info *index_expn_table_meta; + + uint16_t *rule_id_array; +#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; +}; + +struct ipa_nat_indx_tbl_sw_rule { + uint16_t tbl_entry; + uint16_t next_index; + uint16_t prev_index; +}; + +typedef enum { + IPA_NAT_DEL_TYPE_ONLY_ONE, + IPA_NAT_DEL_TYPE_HEAD, + IPA_NAT_DEL_TYPE_MIDDLE, + IPA_NAT_DEL_TYPE_LAST, +} del_type; + +/** + * ipa_nati_parse_ipv4_rule_hdl() - prase rule handle + * @tbl_hdl: [in] nat table rule + * @rule_hdl: [in] nat rule handle + * @expn_tbl: [out] expansion table or not + * @tbl_entry: [out] index into table + * + * Parse the rule handle to retrieve the nat table + * type and entry of nat table + * + * Returns: None + */ +void ipa_nati_parse_ipv4_rule_hdl(uint8_t tbl_hdl, + uint16_t rule_hdl, + uint8_t *expn_tbl, + uint16_t *tbl_entry); + +/** + * ipa_nati_make_rule_hdl() - makes nat rule handle + * @tbl_hdl: [in] nat table handle + * @tbl_entry: [in] nat table entry + * + * Calculate the nat rule handle which from + * nat entry which will be returned to client of + * nat driver + * + * Returns: >0 nat rule handle + */ +uint16_t ipa_nati_make_rule_hdl(uint16_t tbl_hdl, + uint16_t tbl_entry); + +uint32_t ipa_nati_get_index_entry_offset( + struct ipa_nat_ip4_table_cache*, + nat_table_type tbl_type, + uint16_t indx_tbl_entry); +uint32_t ipa_nati_get_entry_offset( + struct ipa_nat_ip4_table_cache*, + nat_table_type tbl_type, + uint16_t tbl_entry); + +int ipa_nati_add_ipv4_tbl(uint32_t public_ip_addr, + uint16_t number_of_entries, + uint32_t *table_hanle); + +int ipa_nati_alloc_table(uint16_t number_of_entries, + struct ipa_ioc_nat_alloc_mem *mem, + uint16_t*, uint16_t*); + +int ipa_nati_update_cache(struct ipa_ioc_nat_alloc_mem *, + uint32_t public_ip_addr, + uint16_t tbl_entries, + uint16_t expn_tbl_entries); + +int ipa_nati_del_ipv4_table(uint32_t tbl_hdl); +int ipa_nati_reset_ipv4_table(uint32_t tbl_hdl); +int ipa_nati_post_ipv4_init_cmd(uint8_t tbl_index); + +int ipa_nati_query_timestamp(uint32_t tbl_hdl, + uint32_t rule_hdl, + uint32_t *time_stamp); + +int ipa_nati_add_ipv4_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + uint32_t *rule_hdl); + +int ipa_nati_generate_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_sw_rule *rule, + struct ipa_nat_indx_tbl_sw_rule *index_sw_rule, + uint16_t *tbl_entry, + uint16_t *indx_tbl_entry); + +uint16_t ipa_nati_expn_tbl_free_entry(struct ipa_nat_rule *expn_tbl, + uint16_t size); + +uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_sw_rule *sw_rule, + struct ipa_nat_ip4_table_cache *tbl_ptr); + +uint16_t ipa_nati_generate_index_rule(const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_indx_tbl_sw_rule *sw_rule, + struct ipa_nat_ip4_table_cache *tbl_ptr); + +uint16_t ipa_nati_index_expn_get_free_entry(struct ipa_nat_indx_tbl_rule *tbl, + uint16_t size); + +void ipa_nati_copy_ipv4_rule_to_hw( + struct ipa_nat_ip4_table_cache *ipv4_cache, + struct ipa_nat_sw_rule *rule, + uint16_t entry, uint8_t tbl_index); + +void ipa_nati_copy_ipv4_index_rule_to_hw( + struct ipa_nat_ip4_table_cache *ipv4_cache, + struct ipa_nat_indx_tbl_sw_rule *indx_sw_rule, + uint16_t entry, uint8_t tbl_index); + +void ipa_nati_write_next_index(uint8_t tbl_indx, + nat_table_type tbl_type, + uint16_t value, + uint32_t offset); + +int ipa_nati_post_ipv4_dma_cmd(uint8_t tbl_indx, + uint16_t entry); + +int ipa_nati_del_ipv4_rule(uint32_t tbl_hdl, + uint32_t rule_hdl); + +int ipa_nati_post_del_dma_cmd(uint8_t tbl_indx, + uint16_t tbl_entry, + uint8_t expn_tbl, + del_type rule_pos); + +void ipa_nati_find_index_rule_pos( + struct ipa_nat_ip4_table_cache *cache_ptr, + uint16_t tbl_entry, + del_type *rule_pos); + +void ipa_nati_del_dead_ipv4_head_nodes(uint8_t tbl_indx); +void ipa_nati_find_rule_pos(struct ipa_nat_ip4_table_cache *cache_ptr, + uint8_t expn_tbl, + uint16_t tbl_entry, + del_type *rule_pos); +void ipa_nati_del_dead_ipv4_head_nodes(uint8_t tbl_indx); + +uint16_t Read16BitFieldValue(uint32_t param, + ipa_nat_rule_field_type fld_type); + +/* ======================================================== + Debug functions + ========================================================*/ +#ifdef NAT_DUMP +void ipa_nati_print_rule(struct ipa_nat_rule*, uint32_t); +void ipa_nat_dump_ipv4_table(uint32_t); +void ipa_nati_print_index_rule(struct ipa_nat_indx_tbl_rule*, + uint32_t, uint16_t); +int ipa_nati_query_nat_rules(uint32_t, nat_table_type); +#endif + +#endif /* #ifndef IPA_NAT_DRVI_H */ diff --git a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_logi.h b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_logi.h new file mode 100644 index 0000000..5f79cc6 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_logi.h @@ -0,0 +1,73 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + ipa_nat_logi.h + + @brief + This file implements the IPAM log functionality. + + @Author + + +*/ + +#ifndef IPA_NAT_LOGI_H +#define IPA_NAT_LOGI_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include + +#define PERROR(fmt) printf("%s:%d %s()", __FILE__, __LINE__, __FUNCTION__);\ + perror(fmt); + +#define IPAERR(fmt, ...) printf("ERR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); + +#ifdef DEBUG +#define IPADBG(fmt, ...) printf("%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); + +#define IPADUMP(fmt, ...) printf(fmt, ##__VA_ARGS__); + +#else +#define IPADBG(fmt, ...) +#define IPADUMP(fmt, ...) +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* IPA_NAT_LOGI_H */ diff --git a/data-ipa-cfg-mgr/ipanat/src/Android.mk b/data-ipa-cfg-mgr/ipanat/src/Android.mk new file mode 100644 index 0000000..a54a57a --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/Android.mk @@ -0,0 +1,28 @@ +BOARD_PLATFORM_LIST := msm8916 +BOARD_PLATFORM_LIST += msm8909 +ifneq ($(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) + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc +LOCAL_C_INCLUDES += $(LOCAL_PATH) +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +LOCAL_SRC_FILES := ipa_nat_drv.c \ + ipa_nat_drvi.c + +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 \ No newline at end of file diff --git a/data-ipa-cfg-mgr/ipanat/src/Makefile.am b/data-ipa-cfg-mgr/ipanat/src/Makefile.am new file mode 100644 index 0000000..8bdb9b8 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/Makefile.am @@ -0,0 +1,21 @@ +AM_CFLAGS = -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs +AM_CFLAGS += -I./../inc +#AM_CFLAGS += -DDEBUG -g + +common_CFLAGS = -DUSE_GLIB @GLIB_CFLAGS@ +common_LDFLAGS = -lrt @GLIB_LIBS@ + +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 + +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 diff --git a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c new file mode 100644 index 0000000..66504e1 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c @@ -0,0 +1,175 @@ +/* +Copyright (c) 2013, 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 "ipa_nat_drv.h" +#include "ipa_nat_drvi.h" + +/** + * ipa_nat_add_ipv4_tbl() - create ipv4 nat table + * @public_ip_addr: [in] public ipv4 address + * @number_of_entries: [in] number of nat entries + * @table_handle: [out] Handle of new ipv4 nat table + * + * To create new ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_add_ipv4_tbl(uint32_t public_ip_addr, + uint16_t number_of_entries, + uint32_t *tbl_hdl) +{ + int ret; + + if (NULL == tbl_hdl || 0 == number_of_entries) { + IPAERR("Invalid parameters \n"); + return -EINVAL; + } + + ret = ipa_nati_add_ipv4_tbl(public_ip_addr, + number_of_entries, + tbl_hdl); + if (ret != 0) { + IPAERR("unable to add table \n"); + return -EINVAL; + } + IPADBG("Returning table handle 0x%x\n", *tbl_hdl); + + return ret; +} /* __ipa_nat_add_ipv4_tbl() */ + +/** + * ipa_nat_del_ipv4_tbl() - delete ipv4 table + * @table_handle: [in] Handle of ipv4 nat table + * + * To delete given ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_del_ipv4_tbl(uint32_t tbl_hdl) +{ + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed \n"); + return -EINVAL; + } + IPADBG("Passed Table Handle: 0x%x\n", tbl_hdl); + + return ipa_nati_del_ipv4_table(tbl_hdl); +} + +/** + * ipa_nat_add_ipv4_rule() - to insert new ipv4 rule + * @table_handle: [in] handle of ipv4 nat table + * @rule: [in] Pointer to new rule + * @rule_handle: [out] Return the handle to rule + * + * To insert new ipv4 nat rule into ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_add_ipv4_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + uint32_t *rule_hdl) +{ + int result = -EINVAL; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS || NULL == rule_hdl || + NULL == clnt_rule) { + IPAERR("invalide table handle passed \n"); + return result; + } + IPADBG("Passed Table handle: 0x%x\n", tbl_hdl); + + if (ipa_nati_add_ipv4_rule(tbl_hdl, clnt_rule, rule_hdl) != 0) { + return result; + } + + IPADBG("returning rule handle 0x%x\n", *rule_hdl); + return 0; +} + + +/** + * ipa_nat_del_ipv4_rule() - to delete ipv4 nat rule + * @table_handle: [in] handle of ipv4 nat table + * @rule_handle: [in] ipv4 nat rule handle + * + * To insert new ipv4 nat rule into ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_del_ipv4_rule(uint32_t tbl_hdl, + uint32_t rule_hdl) +{ + int result = -EINVAL; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + IPA_NAT_INVALID_NAT_ENTRY == rule_hdl) { + IPAERR("invalide parameters\n"); + return result; + } + IPADBG("Passed Table: 0x%x and rule handle 0x%x\n", tbl_hdl, rule_hdl); + + result = ipa_nati_del_ipv4_rule(tbl_hdl, rule_hdl); + if (result) { + IPAERR("unable to delete rule from hw \n"); + return result; + } + + return 0; +} + +/** + * ipa_nat_query_timestamp() - to query timestamp + * @table_handle: [in] handle of ipv4 nat table + * @rule_handle: [in] ipv4 nat rule handle + * @time_stamp: [out] time stamp of rule + * + * To retrieve the timestamp that lastly the + * nat rule was accessed + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_query_timestamp(uint32_t tbl_hdl, + uint32_t rule_hdl, + uint32_t *time_stamp) +{ + + if (0 == tbl_hdl || tbl_hdl > IPA_NAT_MAX_IP4_TBLS || + NULL == time_stamp) { + IPAERR("invalid parameters passed \n"); + return -EINVAL; + } + IPADBG("Passed Table: 0x%x and rule handle 0x%x\n", tbl_hdl, rule_hdl); + + return ipa_nati_query_timestamp(tbl_hdl, rule_hdl, time_stamp); +} + + diff --git a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c new file mode 100644 index 0000000..faa8c8c --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c @@ -0,0 +1,2340 @@ +/* +Copyright (c) 2013, 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 "ipa_nat_drv.h" +#include "ipa_nat_drvi.h" + +#ifdef USE_GLIB +#include +#define strlcpy g_strlcpy +#endif + +struct ipa_nat_cache ipv4_nat_cache; +pthread_mutex_t nat_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* ------------------------------------------ + UTILITY FUNCTIONS START + --------------------------------------------*/ + +/** + * UpdateSwSpecParams() - updates sw specific params + * @rule: [in/out] nat table rule + * @param_type: [in] which param need to update + * @value: [in] value of param + * + * Update SW specific params in the passed rule. + * + * Returns: None + */ +void UpdateSwSpecParams(struct ipa_nat_rule *rule, + uint8_t param_type, + uint32_t value) +{ + uint32_t temp = rule->sw_spec_params; + + if (IPA_NAT_SW_PARAM_INDX_TBL_ENTRY_BYTE == param_type) { + value = (value << INDX_TBL_ENTRY_SIZE_IN_BITS); + temp &= 0x0000FFFF; + } else { + temp &= 0xFFFF0000; + } + + temp = (temp | value); + rule->sw_spec_params = temp; + return; +} + +/** + * Read8BitFieldValue() + * @rule: [in/out] + * @param_type: [in] + * @value: [in] + * + * + * + * Returns: None + */ + +uint8_t Read8BitFieldValue(uint32_t param, + ipa_nat_rule_field_type fld_type) +{ + void *temp = (void *)¶m; + + switch (fld_type) { + + case PROTOCOL_FIELD: + return ((time_stamp_proto *)temp)->protocol; + + default: + IPAERR("Invalid Field type passed\n"); + return 0; + } +} + +uint16_t Read16BitFieldValue(uint32_t param, + ipa_nat_rule_field_type fld_type) +{ + void *temp = (void *)¶m; + + switch (fld_type) { + + case NEXT_INDEX_FIELD: + return ((next_index_pub_port *)temp)->next_index; + + case PUBLIC_PORT_FILED: + return ((next_index_pub_port *)temp)->public_port; + + case ENABLE_FIELD: + return ((ipcksum_enbl *)temp)->enable; + + case SW_SPEC_PARAM_PREV_INDEX_FIELD: + return ((sw_spec_params *)temp)->prev_index; + + case SW_SPEC_PARAM_INDX_TBL_ENTRY_FIELD: + return ((sw_spec_params *)temp)->index_table_entry; + + case INDX_TBL_TBL_ENTRY_FIELD: + return ((tbl_ent_nxt_indx *)temp)->tbl_entry; + + case INDX_TBL_NEXT_INDEX_FILED: + return ((tbl_ent_nxt_indx *)temp)->next_index; + +#ifdef NAT_DUMP + case IP_CHKSUM_FIELD: + return ((ipcksum_enbl *)temp)->ip_chksum; +#endif + + default: + IPAERR("Invalid Field type passed\n"); + return 0; + } +} + +uint32_t Read32BitFieldValue(uint32_t param, + ipa_nat_rule_field_type fld_type) +{ + + void *temp = (void *)¶m; + + switch (fld_type) { + + case TIME_STAMP_FIELD: + return ((time_stamp_proto *)temp)->time_stamp; + + default: + IPAERR("Invalid Field type passed\n"); + return 0; + } +} + + +/** + * CreateNatDevice() - Create nat devices + * @mem: [in] name of device that need to create + * + * Create Nat device and Register for file create + * notification in given directory and wait till + * receive notification + * + * Returns: 0 on success, negative on failure + */ +int CreateNatDevice(struct ipa_ioc_nat_alloc_mem *mem) +{ + int ret; + + ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_ALLOC_NAT_MEM, mem); + if (ret != 0) { + perror("CreateNatDevice(): ioctl error value"); + IPAERR("unable to post nat mem init. Error ;%d\n", ret); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + return -EINVAL; + } + IPADBG("posted IPA_IOC_ALLOC_NAT_MEM to kernel successfully\n"); + return 0; +} + +/** + * GetNearest2Power() - Returns the nearest power of 2 + * @num: [in] given number + * @ret: [out] nearest power of 2 + * + * Returns the nearest power of 2 for a + * given number + * + * Returns: 0 on success, negative on failure + */ +int GetNearest2Power(uint16_t num, uint16_t *ret) +{ + uint16_t number = num; + uint16_t tmp = 1; + *ret = 0; + + if (0 == num) { + return -EINVAL; + } + + if (1 == num) { + *ret = 2; + return 0; + } + + for (;;) { + if (1 == num) { + if (number != tmp) { + tmp *= 2; + } + + *ret = tmp; + return 0; + } + + num >>= 1; + tmp *= 2; + } + + return -EINVAL; +} + +/** + * GetNearestEven() - Returns the nearest even number + * @num: [in] given number + * @ret: [out] nearest even number + * + * Returns the nearest even number for a given number + * + * Returns: 0 on success, negative on failure + */ +void GetNearestEven(uint16_t num, uint16_t *ret) +{ + + if (num < 2) { + *ret = 2; + return; + } + + while ((num % 2) != 0) { + num = num + 1; + } + + *ret = num; + return; +} + +/** + * dst_hash() - Find the index into ipv4 base table + * @trgt_ip: [in] Target IP address + * @trgt_port: [in] Target port + * @public_port: [in] Public port + * @proto: [in] Protocol (TCP/IP) + * @size: [in] size of the ipv4 base Table + * + * This hash method is used to find the hash index of new nat + * entry into ipv4 base table. In case of zero index, the + * new entry will be stored into N-1 index where N is size of + * ipv4 base table + * + * 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) +{ + uint16_t hash = ((uint16_t)(trgt_ip)) ^ ((uint16_t)(trgt_ip >> 16)) ^ + (trgt_port) ^ (public_port) ^ (proto); + + 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); + + hash = (hash & size); + + /* If the hash resulted to zero then set it to maximum value + as zero is unused entry in nat tables */ + if (0 == hash) { + return size; + } + + IPADBG("dst_hash returning value: %d\n", hash); + return hash; +} + +/** + * src_hash() - Find the index into ipv4 index base table + * @priv_ip: [in] Private IP address + * @priv_port: [in] Private port + * @trgt_ip: [in] Target IP address + * @trgt_port: [in] Target Port + * @proto: [in] Protocol (TCP/IP) + * @size: [in] size of the ipv4 index base Table + * + * This hash method is used to find the hash index of new nat + * entry into ipv4 index base table. In case of zero index, the + * new entry will be stored into N-1 index where N is size of + * ipv4 index base table + * + * Returns: >0 index into ipv4 index base table, negative on failure + */ +static uint16_t src_hash(uint32_t priv_ip, uint16_t priv_port, + uint32_t trgt_ip, uint16_t trgt_port, + uint8_t proto, uint16_t size) +{ + uint16_t hash = ((uint16_t)(priv_ip)) ^ ((uint16_t)(priv_ip >> 16)) ^ + (priv_port) ^ + ((uint16_t)(trgt_ip)) ^ ((uint16_t)(trgt_ip >> 16)) ^ + (trgt_port) ^ (proto); + + IPADBG("priv_ip: 0x%x priv_port: 0x%x\n", priv_ip, priv_port); + IPADBG("trgt_ip: 0x%x trgt_port: 0x%x\n", trgt_ip, trgt_port); + IPADBG("proto: 0x%x size: 0x%x\n", proto, size); + + hash = (hash & size); + + /* If the hash resulted to zero then set it to maximum value + as zero is unused entry in nat tables */ + if (0 == hash) { + return size; + } + + IPADBG("src_hash returning value: %d\n", hash); + return hash; +} + +/** + * ipa_nati_calc_ip_cksum() - Calculate the source nat + * IP checksum diff + * @pub_ip_addr: [in] public ip address + * @priv_ip_addr: [in] Private ip address + * + * source nat ip checksum different is calculated as + * public_ip_addr - private_ip_addr + * Here we are using 1's complement to represent -ve number. + * So take 1's complement of private ip addr and add it + * to public ip addr. + * + * Returns: >0 ip checksum diff + */ +static uint16_t ipa_nati_calc_ip_cksum(uint32_t pub_ip_addr, + uint32_t priv_ip_addr) +{ + uint16_t ret; + uint32_t cksum = 0; + + /* Add LSB(2 bytes) of public ip address to cksum */ + cksum += (pub_ip_addr & 0xFFFF); + + /* Add MSB(2 bytes) of public ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (pub_ip_addr>>16); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Calculate the 1's complement of private ip address */ + priv_ip_addr = (~priv_ip_addr); + + /* Add LSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (priv_ip_addr & 0xFFFF); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Add MSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (priv_ip_addr>>16); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Return the LSB(2 bytes) of checksum */ + ret = (uint16_t)cksum; + return ret; +} + +/** + * ipa_nati_calc_tcp_udp_cksum() - Calculate the source nat + * TCP/UDP checksum diff + * @pub_ip_addr: [in] public ip address + * @pub_port: [in] public tcp/udp port + * @priv_ip_addr: [in] Private ip address + * @priv_port: [in] Private tcp/udp prot + * + * source nat tcp/udp checksum is calculated as + * (pub_ip_addr + pub_port) - (priv_ip_addr + priv_port) + * Here we are using 1's complement to represent -ve number. + * So take 1's complement of prviate ip addr &private port + * and add it public ip addr & public port. + * + * Returns: >0 tcp/udp checksum diff + */ +static uint16_t ipa_nati_calc_tcp_udp_cksum(uint32_t pub_ip_addr, + uint16_t pub_port, + uint32_t priv_ip_addr, + uint16_t priv_port) +{ + uint16_t ret = 0; + uint32_t cksum = 0; + + /* Add LSB(2 bytes) of public ip address to cksum */ + cksum += (pub_ip_addr & 0xFFFF); + + /* Add MSB(2 bytes) of public ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (pub_ip_addr>>16); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Add public port to cksum and + check for carry forward(CF), if any add it */ + cksum += pub_port; + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Calculate the 1's complement of private ip address */ + priv_ip_addr = (~priv_ip_addr); + + /* Add LSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (priv_ip_addr & 0xFFFF); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Add MSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add + */ + cksum += (priv_ip_addr>>16); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Calculate the 1's complement of private port */ + priv_port = (~priv_port); + + /* Add public port to cksum and + check for carry forward(CF), if any add it */ + cksum += priv_port; + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* return the LSB(2 bytes) of checksum */ + ret = (uint16_t)cksum; + return ret; +} + +/** + * ipa_nati_make_rule_hdl() - makes nat rule handle + * @tbl_hdl: [in] nat table handle + * @tbl_entry: [in] nat table entry + * + * Calculate the nat rule handle which from + * nat entry which will be returned to client of + * nat driver + * + * Returns: >0 nat rule handle + */ +uint16_t ipa_nati_make_rule_hdl(uint16_t tbl_hdl, + uint16_t tbl_entry) +{ + struct ipa_nat_ip4_table_cache *tbl_ptr; + uint16_t rule_hdl = 0; + uint16_t cnt = 0; + + 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); + } + + for (; cnt < (tbl_ptr->table_entries + tbl_ptr->expn_table_entries); cnt++) { + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_ptr->rule_id_array[cnt]) { + tbl_ptr->rule_id_array[cnt] = rule_hdl; + return cnt + 1; + } + } + + return 0; +} + +/** + * ipa_nati_parse_ipv4_rule_hdl() - prase rule handle + * @tbl_hdl: [in] nat table rule + * @rule_hdl: [in] nat rule handle + * @expn_tbl: [out] expansion table or not + * @tbl_entry: [out] index into table + * + * Parse the rule handle to retrieve the nat table + * type and entry of nat table + * + * Returns: None + */ +void ipa_nati_parse_ipv4_rule_hdl(uint8_t tbl_index, + uint16_t rule_hdl, uint8_t *expn_tbl, + uint16_t *tbl_entry) +{ + struct ipa_nat_ip4_table_cache *tbl_ptr; + uint16_t rule_id; + + *expn_tbl = 0; + *tbl_entry = IPA_NAT_INVALID_NAT_ENTRY; + tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_index]; + + if (rule_hdl >= (tbl_ptr->table_entries + tbl_ptr->expn_table_entries)) { + IPAERR("invalid rule handle\n"); + return; + } + + rule_id = tbl_ptr->rule_id_array[rule_hdl-1]; + + /* Retrieve the table type */ + *expn_tbl = 0; + if (rule_id & IPA_NAT_RULE_HDL_TBL_TYPE_MASK) { + *expn_tbl = 1; + } + + /* Retrieve the table entry */ + *tbl_entry = (rule_id >> IPA_NAT_RULE_HDL_TBL_TYPE_BITS); + return; +} + +uint32_t ipa_nati_get_entry_offset(struct ipa_nat_ip4_table_cache *cache_ptr, + nat_table_type tbl_type, + uint16_t tbl_entry) +{ + struct ipa_nat_rule *tbl_ptr; + uint32_t ret = 0; + + if (IPA_NAT_EXPN_TBL == tbl_type) { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + } else { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_rules_addr; + } + + ret = (char *)&tbl_ptr[tbl_entry] - (char *)tbl_ptr; + ret += cache_ptr->tbl_addr_offset; + return ret; +} + +uint32_t ipa_nati_get_index_entry_offset(struct ipa_nat_ip4_table_cache *cache_ptr, + nat_table_type tbl_type, + uint16_t indx_tbl_entry) +{ + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + uint32_t ret = 0; + + if (IPA_NAT_INDEX_EXPN_TBL == tbl_type) { + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_expn_addr; + } else { + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_addr; + } + + ret = (char *)&indx_tbl_ptr[indx_tbl_entry] - (char *)indx_tbl_ptr; + ret += cache_ptr->tbl_addr_offset; + return ret; +} + +/* ------------------------------------------ + UTILITY FUNCTIONS END +--------------------------------------------*/ + +/* ------------------------------------------ + Main Functions +--------------------------------------------**/ +void ipa_nati_reset_tbl(uint8_t tbl_indx) +{ + uint16_t table_entries = ipv4_nat_cache.ip4_tbl[tbl_indx].table_entries; + uint16_t expn_table_entries = ipv4_nat_cache.ip4_tbl[tbl_indx].expn_table_entries; + + /* Base table */ + IPADBG("memset() base table to 0, %p\n", + ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_rules_addr); + + memset(ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_rules_addr, + 0, + IPA_NAT_TABLE_ENTRY_SIZE * table_entries); + + /* Base expansino table */ + IPADBG("memset() expn base table to 0, %p\n", + ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_expn_rules_addr); + + memset(ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_expn_rules_addr, + 0, + IPA_NAT_TABLE_ENTRY_SIZE * expn_table_entries); + + /* Index table */ + IPADBG("memset() index table to 0, %p\n", + ipv4_nat_cache.ip4_tbl[tbl_indx].index_table_addr); + + memset(ipv4_nat_cache.ip4_tbl[tbl_indx].index_table_addr, + 0, + IPA_NAT_INDEX_TABLE_ENTRY_SIZE * table_entries); + + /* Index expansion table */ + IPADBG("memset() index expn table to 0, %p\n", + ipv4_nat_cache.ip4_tbl[tbl_indx].index_table_expn_addr); + + memset(ipv4_nat_cache.ip4_tbl[tbl_indx].index_table_expn_addr, + 0, + IPA_NAT_INDEX_TABLE_ENTRY_SIZE * expn_table_entries); + + IPADBG("returning from ipa_nati_reset_tbl()\n"); + return; +} + +int ipa_nati_add_ipv4_tbl(uint32_t public_ip_addr, + uint16_t number_of_entries, + uint32_t *tbl_hdl) +{ + struct ipa_ioc_nat_alloc_mem mem; + uint8_t tbl_indx = ipv4_nat_cache.table_cnt; + uint16_t table_entries, expn_table_entries; + int ret; + + *tbl_hdl = 0; + /* Allocate table */ + memset(&mem, 0, sizeof(mem)); + ret = ipa_nati_alloc_table(number_of_entries, + &mem, + &table_entries, + &expn_table_entries); + if (0 != ret) { + IPAERR("unable to allocate nat table\n"); + return -ENOMEM; + } + + /* Update the cache + The (IPA_NAT_UNUSED_BASE_ENTRIES/2) indicates zero entry entries + for both base and expansion table + */ + ret = ipa_nati_update_cache(&mem, + public_ip_addr, + table_entries, + expn_table_entries); + if (0 != ret) { + IPAERR("unable to update cache Error: %d\n", ret); + return -EINVAL; + } + + /* Reset the nat table before posting init cmd */ + ipa_nati_reset_tbl(tbl_indx); + + /* Initialize the ipa hw with nat table dimensions */ + ret = ipa_nati_post_ipv4_init_cmd(tbl_indx); + if (0 != ret) { + IPAERR("unable to post nat_init command Error %d\n", ret); + return -EINVAL; + } + + /* Return table handle */ + ipv4_nat_cache.table_cnt++; + *tbl_hdl = ipv4_nat_cache.table_cnt; + +#ifdef NAT_DUMP + ipa_nat_dump_ipv4_table(*tbl_hdl); +#endif + return 0; +} + +int ipa_nati_alloc_table(uint16_t number_of_entries, + struct ipa_ioc_nat_alloc_mem *mem, + uint16_t *table_entries, + uint16_t *expn_table_entries) +{ + int fd = 0, ret; + uint16_t total_entries; + + /* Copy the table name */ + strlcpy(mem->dev_name, NAT_DEV_NAME, IPA_RESOURCE_NAME_MAX); + + /* Calculate the size for base table and expansion table */ + *table_entries = (uint16_t)(number_of_entries * IPA_NAT_BASE_TABLE_PERCENTAGE); + if (*table_entries == 0) { + *table_entries = 1; + } + if (GetNearest2Power(*table_entries, table_entries)) { + IPAERR("unable to calculate power of 2\n"); + return -EINVAL; + } + + *expn_table_entries = (uint16_t)(number_of_entries * IPA_NAT_EXPANSION_TABLE_PERCENTAGE); + GetNearestEven(*expn_table_entries, expn_table_entries); + + total_entries = (*table_entries)+(*expn_table_entries); + + /* Calclate the memory size for both table and index table entries */ + mem->size = (IPA_NAT_TABLE_ENTRY_SIZE * total_entries); + IPADBG("Nat Table size: %d\n", mem->size); + mem->size += (IPA_NAT_INDEX_TABLE_ENTRY_SIZE * total_entries); + IPADBG("Nat Base and Index Table size: %d\n", mem->size); + + if (!ipv4_nat_cache.ipa_fd) { + fd = open(IPA_DEV_NAME, O_RDONLY); + if (fd < 0) { + perror("ipa_nati_alloc_table(): open error value:"); + IPAERR("unable to open ipa device\n"); + return -EIO; + } + ipv4_nat_cache.ipa_fd = fd; + } + + ret = CreateNatDevice(mem); + return ret; +} + + +int ipa_nati_update_cache(struct ipa_ioc_nat_alloc_mem *mem, + uint32_t public_addr, + uint16_t tbl_entries, + uint16_t expn_tbl_entries) +{ + uint32_t index = ipv4_nat_cache.table_cnt; + char *ipv4_rules_addr = NULL; + + int fd = 0; + int flags = MAP_SHARED; + int prot = PROT_READ | PROT_WRITE; + off_t offset = 0; +#ifdef IPA_ON_R3PC + int ret = 0; + uint32_t nat_mem_offset = 0; +#endif + + ipv4_nat_cache.ip4_tbl[index].valid = IPA_NAT_TABLE_VALID; + ipv4_nat_cache.ip4_tbl[index].public_addr = public_addr; + ipv4_nat_cache.ip4_tbl[index].size = mem->size; + ipv4_nat_cache.ip4_tbl[index].tbl_addr_offset = mem->offset; + + ipv4_nat_cache.ip4_tbl[index].table_entries = tbl_entries; + ipv4_nat_cache.ip4_tbl[index].expn_table_entries = expn_tbl_entries; + + IPADBG("num of ipv4 rules:%d\n", tbl_entries); + IPADBG("num of ipv4 expn rules:%d\n", expn_tbl_entries); + + /* allocate memory for nat index expansion table */ + if (NULL == ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta) { + ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta = + malloc(sizeof(struct ipa_nat_indx_tbl_meta_info) * expn_tbl_entries); + + if (NULL == ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta) { + IPAERR("Fail to allocate ipv4 index expansion table meta\n"); + return 0; + } + + memset(ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta, + 0, + sizeof(struct ipa_nat_indx_tbl_meta_info) * expn_tbl_entries); + } + + /* Allocate memory for rule_id_array */ + if (NULL == ipv4_nat_cache.ip4_tbl[index].rule_id_array) { + ipv4_nat_cache.ip4_tbl[index].rule_id_array = + malloc(sizeof(uint16_t) * (tbl_entries + expn_tbl_entries)); + + if (NULL == ipv4_nat_cache.ip4_tbl[index].rule_id_array) { + IPAERR("Fail to allocate rule id array\n"); + return 0; + } + + memset(ipv4_nat_cache.ip4_tbl[index].rule_id_array, + 0, + sizeof(uint16_t) * (tbl_entries + expn_tbl_entries)); + } + + + /* open the nat table */ + strlcpy(mem->dev_name, NAT_DEV_FULL_NAME, IPA_RESOURCE_NAME_MAX); + fd = open(mem->dev_name, O_RDWR); + if (fd < 0) { + perror("ipa_nati_update_cache(): open error value:"); + IPAERR("unable to open nat device. Error:%d\n", fd); + return -EIO; + } + + /* copy the nat table name */ + strlcpy(ipv4_nat_cache.ip4_tbl[index].table_name, + mem->dev_name, + IPA_RESOURCE_NAME_MAX); + ipv4_nat_cache.ip4_tbl[index].nat_fd = fd; + + /* open the nat device Table */ +#ifndef IPA_ON_R3PC + ipv4_rules_addr = (void *)mmap(NULL, mem->size, + prot, flags, + fd, offset); +#else + IPADBG("user space r3pc\n"); + ipv4_rules_addr = (void *)mmap((caddr_t)0, NAT_MMAP_MEM_SIZE, + prot, flags, + fd, offset); +#endif + if (MAP_FAILED == ipv4_rules_addr) { + perror("unable to mmap the memory\n"); + return -EINVAL; + } + +#ifdef IPA_ON_R3PC + ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_GET_NAT_OFFSET, &nat_mem_offset); + if (ret != 0) { + perror("ipa_nati_post_ipv4_init_cmd(): ioctl error value"); + IPAERR("unable to post ant offset cmd Error: %d\n", ret); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + return -EIO; + } + ipv4_rules_addr += nat_mem_offset; + ipv4_nat_cache.ip4_tbl[index].mmap_offset = nat_mem_offset; +#endif + + IPADBG("mmap return value 0x%lx\n", (long unsigned int)ipv4_rules_addr); + + ipv4_nat_cache.ip4_tbl[index].ipv4_rules_addr = ipv4_rules_addr; + + ipv4_nat_cache.ip4_tbl[index].ipv4_expn_rules_addr = + ipv4_rules_addr + (IPA_NAT_TABLE_ENTRY_SIZE * tbl_entries); + + ipv4_nat_cache.ip4_tbl[index].index_table_addr = + ipv4_rules_addr + (IPA_NAT_TABLE_ENTRY_SIZE * (tbl_entries + expn_tbl_entries)); + + ipv4_nat_cache.ip4_tbl[index].index_table_expn_addr = + ipv4_rules_addr + + (IPA_NAT_TABLE_ENTRY_SIZE * (tbl_entries + expn_tbl_entries))+ + (IPA_NAT_INDEX_TABLE_ENTRY_SIZE * tbl_entries); + + return 0; +} + +/* comment: check the implementation once + offset should be in terms of byes */ +int ipa_nati_post_ipv4_init_cmd(uint8_t tbl_index) +{ + struct ipa_ioc_v4_nat_init cmd; + uint32_t offset = ipv4_nat_cache.ip4_tbl[tbl_index].tbl_addr_offset; + int ret; + + cmd.tbl_index = tbl_index; + + cmd.ipv4_rules_offset = offset; + cmd.expn_rules_offset = cmd.ipv4_rules_offset + + (ipv4_nat_cache.ip4_tbl[tbl_index].table_entries * IPA_NAT_TABLE_ENTRY_SIZE); + + cmd.index_offset = cmd.expn_rules_offset + + (ipv4_nat_cache.ip4_tbl[tbl_index].expn_table_entries * IPA_NAT_TABLE_ENTRY_SIZE); + + cmd.index_expn_offset = cmd.index_offset + + (ipv4_nat_cache.ip4_tbl[tbl_index].table_entries * IPA_NAT_INDEX_TABLE_ENTRY_SIZE); + + cmd.table_entries = ipv4_nat_cache.ip4_tbl[tbl_index].table_entries - 1; + cmd.expn_table_entries = ipv4_nat_cache.ip4_tbl[tbl_index].expn_table_entries; + + cmd.ip_addr = ipv4_nat_cache.ip4_tbl[tbl_index].public_addr; + + ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_V4_INIT_NAT, &cmd); + if (ret != 0) { + perror("ipa_nati_post_ipv4_init_cmd(): ioctl error value"); + IPAERR("unable to post init cmd Error: %d\n", ret); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + return -EINVAL; + } + IPADBG("Posted IPA_IOC_V4_INIT_NAT to kernel successfully\n"); + + return 0; +} + +int ipa_nati_del_ipv4_table(uint32_t tbl_hdl) +{ + uint8_t index = (uint8_t)(tbl_hdl - 1); + void *addr = (void *)ipv4_nat_cache.ip4_tbl[index].ipv4_rules_addr; + struct ipa_ioc_v4_nat_del del_cmd; + int ret; + + if (!ipv4_nat_cache.ip4_tbl[index].valid) { + IPAERR("invalid table handle passed\n"); + ret = -EINVAL; + goto fail; + } + + if (pthread_mutex_lock(&nat_mutex) != 0) { + ret = -1; + goto lock_mutex_fail; + } + + /* unmap the device memory from user space */ +#ifndef IPA_ON_R3PC + munmap(addr, ipv4_nat_cache.ip4_tbl[index].size); +#else + addr = (char *)addr - ipv4_nat_cache.ip4_tbl[index].mmap_offset; + munmap(addr, NAT_MMAP_MEM_SIZE); +#endif + + /* 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"); + ret = -EINVAL; + if (pthread_mutex_unlock(&nat_mutex) != 0) + goto unlock_mutex_fail; + goto fail; + } + + del_cmd.table_index = index; + del_cmd.public_ip_addr = ipv4_nat_cache.ip4_tbl[index].public_addr; + ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_V4_DEL_NAT, &del_cmd); + if (ret != 0) { + 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); + ret = -EINVAL; + if (pthread_mutex_unlock(&nat_mutex) != 0) + goto unlock_mutex_fail; + goto fail; + } + 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); + + memset(&ipv4_nat_cache.ip4_tbl[index], + 0, + sizeof(ipv4_nat_cache.ip4_tbl[index])); + + /* 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, + uint32_t rule_hdl, + uint32_t *time_stamp) +{ + uint8_t tbl_index = (uint8_t)(tbl_hdl - 1); + uint8_t expn_tbl = 0; + uint16_t tbl_entry = 0; + struct ipa_nat_rule *tbl_ptr = NULL; + + if (!ipv4_nat_cache.ip4_tbl[tbl_index].valid) { + IPAERR("invalid table handle\n"); + 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); + + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_index].ipv4_rules_addr; + if (expn_tbl) { + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_index].ipv4_expn_rules_addr; + } + + 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_add_ipv4_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + uint32_t *rule_hdl) +{ + struct ipa_nat_ip4_table_cache *tbl_ptr; + struct ipa_nat_sw_rule sw_rule; + struct ipa_nat_indx_tbl_sw_rule index_sw_rule; + uint16_t new_entry, new_index_tbl_entry; + + memset(&sw_rule, 0, sizeof(sw_rule)); + memset(&index_sw_rule, 0, sizeof(index_sw_rule)); + + /* Generate rule from client input */ + if (ipa_nati_generate_rule(tbl_hdl, clnt_rule, + &sw_rule, &index_sw_rule, + &new_entry, &new_index_tbl_entry)) { + IPAERR("unable to generate rule\n"); + return -EINVAL; + } + + tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_hdl-1]; + ipa_nati_copy_ipv4_rule_to_hw(tbl_ptr, &sw_rule, new_entry, (uint8_t)(tbl_hdl-1)); + ipa_nati_copy_ipv4_index_rule_to_hw(tbl_ptr, + &index_sw_rule, + new_index_tbl_entry, + (uint8_t)(tbl_hdl-1)); + + IPADBG("new entry:%d, new index entry: %d\n", new_entry, new_index_tbl_entry); + if (ipa_nati_post_ipv4_dma_cmd((uint8_t)(tbl_hdl - 1), new_entry)) { + IPAERR("unable to post dma command\n"); + return -EIO; + } + + /* Generate rule handle */ + *rule_hdl = ipa_nati_make_rule_hdl((uint16_t)tbl_hdl, new_entry); + if (!(*rule_hdl)) { + IPAERR("unable to generate rule handle\n"); + return -EINVAL; + } + +#ifdef NAT_DUMP + ipa_nat_dump_ipv4_table(tbl_hdl); +#endif + + return 0; +} + +int ipa_nati_generate_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_sw_rule *rule, + struct ipa_nat_indx_tbl_sw_rule *index_sw_rule, + uint16_t *tbl_entry, + uint16_t *indx_tbl_entry) +{ + struct ipa_nat_ip4_table_cache *tbl_ptr; + uint16_t tmp; + + if (NULL == clnt_rule || NULL == index_sw_rule || + NULL == rule || NULL == tbl_entry || + NULL == indx_tbl_entry) { + IPAERR("invalid parameters\n"); + return -EINVAL; + } + + tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_hdl-1]; + + *tbl_entry = ipa_nati_generate_tbl_rule(clnt_rule, + rule, + tbl_ptr); + if (IPA_NAT_INVALID_NAT_ENTRY == *tbl_entry) { + IPAERR("unable to generate table entry\n"); + return -EINVAL; + } + + index_sw_rule->tbl_entry = *tbl_entry; + *indx_tbl_entry = ipa_nati_generate_index_rule(clnt_rule, + index_sw_rule, + tbl_ptr); + if (IPA_NAT_INVALID_NAT_ENTRY == *indx_tbl_entry) { + IPAERR("unable to generate index table entry\n"); + return -EINVAL; + } + + rule->indx_tbl_entry = *indx_tbl_entry; + if (*indx_tbl_entry >= tbl_ptr->table_entries) { + tmp = *indx_tbl_entry - tbl_ptr->table_entries; + tbl_ptr->index_expn_table_meta[tmp].prev_index = index_sw_rule->prev_index; + } + + return 0; +} + +uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_sw_rule *sw_rule, + struct ipa_nat_ip4_table_cache *tbl_ptr) +{ + uint32_t pub_ip_addr; + 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; + + tbl = (struct ipa_nat_rule *)tbl_ptr->ipv4_rules_addr; + expn_tbl = (struct ipa_nat_rule *)tbl_ptr->ipv4_expn_rules_addr; + + /* copy the values from client rule to sw rule */ + sw_rule->private_ip = clnt_rule->private_ip; + sw_rule->private_port = clnt_rule->private_port; + sw_rule->protocol = clnt_rule->protocol; + sw_rule->public_port = clnt_rule->public_port; + sw_rule->target_ip = clnt_rule->target_ip; + sw_rule->target_port = clnt_rule->target_port; + + /* consider only public and private ip fields */ + sw_rule->ip_chksum = ipa_nati_calc_ip_cksum(pub_ip_addr, + clnt_rule->private_ip); + + if (IPPROTO_TCP == sw_rule->protocol || + IPPROTO_UDP == sw_rule->protocol) { + /* consider public and private ip & port fields */ + sw_rule->tcp_udp_chksum = ipa_nati_calc_tcp_udp_cksum( + pub_ip_addr, + clnt_rule->public_port, + clnt_rule->private_ip, + clnt_rule->private_port); + } + + sw_rule->rsvd1 = 0; + sw_rule->enable = IPA_NAT_FLAG_DISABLE_BIT; + sw_rule->next_index = 0; + + /* + SW sets this timer to 0. + The assumption is that 0 is an invalid clock value and no clock + wraparounds are expected + */ + sw_rule->time_stamp = 0; + sw_rule->rsvd2 = 0; + sw_rule->prev_index = 0; + sw_rule->indx_tbl_entry = 0; + + new_entry = dst_hash(clnt_rule->target_ip, + clnt_rule->target_port, + clnt_rule->public_port, + clnt_rule->protocol, + tbl_ptr->table_entries-1); + + /* check whether there is any collision + if no collision return */ + if (!Read16BitFieldValue(tbl[new_entry].ip_cksm_enbl, + ENABLE_FIELD)) { + sw_rule->prev_index = 0; + IPADBG("Destination Nat New Entry Index %d\n", new_entry); + return new_entry; + } + + /* First collision */ + if (Read16BitFieldValue(tbl[new_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == IPA_NAT_INVALID_NAT_ENTRY) { + sw_rule->prev_index = new_entry; + } else { /* check for more than one collision */ + /* Find the IPA_NAT_DEL_TYPE_LAST entry in list */ + nxt_indx = Read16BitFieldValue(tbl[new_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + + while (nxt_indx != IPA_NAT_INVALID_NAT_ENTRY) { + prev = nxt_indx; + + nxt_indx -= tbl_ptr->table_entries; + nxt_indx = Read16BitFieldValue(expn_tbl[nxt_indx].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + + /* Handling error case */ + if (prev == nxt_indx) { + IPAERR("Error: Prev index:%d and next:%d index should not be same\n", prev, nxt_indx); + return IPA_NAT_INVALID_NAT_ENTRY; + } + } + + sw_rule->prev_index = prev; + } + + /* 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); + + if (IPA_NAT_INVALID_NAT_ENTRY == new_entry) { + /* Expansion table is full return*/ + 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; + + IPADBG("new entry index %d\n", new_entry); + return new_entry; +} + +/* returns expn table entry index */ +uint16_t ipa_nati_expn_tbl_free_entry(struct ipa_nat_rule *expn_tbl, + uint16_t size) +{ + int cnt; + + for (cnt = 1; cnt < size; cnt++) { + if (!Read16BitFieldValue(expn_tbl[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + IPADBG("new expansion table entry index %d\n", cnt); + return cnt; + } + } + + IPAERR("nat expansion table is full\n"); + return 0; +} + +uint16_t ipa_nati_generate_index_rule(const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_indx_tbl_sw_rule *sw_rule, + struct ipa_nat_ip4_table_cache *tbl_ptr) +{ + struct ipa_nat_indx_tbl_rule *indx_tbl, *indx_expn_tbl; + uint16_t prev = 0, nxt_indx = 0, new_entry; + + indx_tbl = + (struct ipa_nat_indx_tbl_rule *)tbl_ptr->index_table_addr; + indx_expn_tbl = + (struct ipa_nat_indx_tbl_rule *)tbl_ptr->index_table_expn_addr; + + new_entry = src_hash(clnt_rule->private_ip, + clnt_rule->private_port, + clnt_rule->target_ip, + clnt_rule->target_port, + clnt_rule->protocol, + tbl_ptr->table_entries-1); + + /* check whether there is any collision + if no collision return */ + if (!Read16BitFieldValue(indx_tbl[new_entry].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + sw_rule->prev_index = 0; + IPADBG("Source Nat Index Table Entry %d\n", new_entry); + return new_entry; + } + + /* check for more than one collision */ + if (Read16BitFieldValue(indx_tbl[new_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == IPA_NAT_INVALID_NAT_ENTRY) { + sw_rule->prev_index = new_entry; + IPADBG("First collosion. Entry %d\n", new_entry); + } else { + /* Find the IPA_NAT_DEL_TYPE_LAST entry in list */ + nxt_indx = Read16BitFieldValue(indx_tbl[new_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + while (nxt_indx != IPA_NAT_INVALID_NAT_ENTRY) { + prev = nxt_indx; + + nxt_indx -= tbl_ptr->table_entries; + nxt_indx = Read16BitFieldValue(indx_expn_tbl[nxt_indx].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + /* Handling error case */ + if (prev == nxt_indx) { + IPAERR("Error: Prev:%d and next:%d index should not be same\n", prev, nxt_indx); + return IPA_NAT_INVALID_NAT_ENTRY; + } + } + + sw_rule->prev_index = prev; + } + + /* 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); + + if (IPA_NAT_INVALID_NAT_ENTRY == new_entry) { + /* Expansion table is full return*/ + 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; + + + if (sw_rule->prev_index == new_entry) { + IPAERR("Error: prev_entry:%d ", sw_rule->prev_index); + IPAERR("and new_entry:%d should not be same ", new_entry); + IPAERR("infinite loop detected\n"); + return IPA_NAT_INVALID_NAT_ENTRY; + } + + IPADBG("index table entry %d\n", new_entry); + return new_entry; +} + +/* returns index expn table entry index */ +uint16_t ipa_nati_index_expn_get_free_entry( + struct ipa_nat_indx_tbl_rule *indx_tbl, + uint16_t size) +{ + int cnt; + for (cnt = 1; cnt < size; cnt++) { + if (!Read16BitFieldValue(indx_tbl[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + return cnt; + } + } + + IPAERR("nat index expansion table is full\n"); + return 0; +} + +void ipa_nati_write_next_index(uint8_t tbl_indx, + nat_table_type tbl_type, + uint16_t value, + uint32_t offset) +{ + struct ipa_ioc_nat_dma_cmd *cmd; + + IPADBG("Updating next index field of table %d on collosion using dma\n", tbl_type); + IPADBG("table index: %d, value: %d offset;%d\n", tbl_indx, value, offset); + + cmd = (struct ipa_ioc_nat_dma_cmd *) + malloc(sizeof(struct ipa_ioc_nat_dma_cmd)+ + sizeof(struct ipa_ioc_nat_dma_one)); + if (NULL == cmd) { + IPAERR("unable to allocate memory\n"); + return; + } + + cmd->dma[0].table_index = tbl_indx; + cmd->dma[0].base_addr = tbl_type; + cmd->dma[0].data = value; + cmd->dma[0].offset = offset; + + cmd->entries = 1; + if (ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_NAT_DMA, cmd)) { + perror("ipa_nati_post_ipv4_dma_cmd(): ioctl error value"); + IPAERR("unable to call dma icotl to update next index\n"); + IPAERR("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + goto fail; + } + +fail: + free(cmd); + + return; +} + +void ipa_nati_copy_ipv4_rule_to_hw( + struct ipa_nat_ip4_table_cache *ipv4_cache, + struct ipa_nat_sw_rule *rule, + uint16_t entry, uint8_t tbl_index) +{ + struct ipa_nat_rule *tbl_ptr; + uint16_t prev_entry = rule->prev_index; + nat_table_type tbl_type; + uint32_t offset = 0; + + if (entry < ipv4_cache->table_entries) { + tbl_ptr = (struct ipa_nat_rule *)ipv4_cache->ipv4_rules_addr; + + memcpy(&tbl_ptr[entry], + rule, + sizeof(struct ipa_nat_rule)); + } else { + tbl_ptr = (struct ipa_nat_rule *)ipv4_cache->ipv4_expn_rules_addr; + memcpy(&tbl_ptr[entry - ipv4_cache->table_entries], + rule, + sizeof(struct ipa_nat_rule)); + } + + /* Update the previos entry next_index */ + if (IPA_NAT_INVALID_NAT_ENTRY != prev_entry) { + + if (prev_entry < ipv4_cache->table_entries) { + tbl_type = IPA_NAT_BASE_TBL; + tbl_ptr = (struct ipa_nat_rule *)ipv4_cache->ipv4_rules_addr; + } else { + tbl_type = IPA_NAT_EXPN_TBL; + /* tbp_ptr is already pointing to expansion table + no need to initialize it */ + prev_entry = prev_entry - ipv4_cache->table_entries; + } + + offset = ipa_nati_get_entry_offset(ipv4_cache, tbl_type, prev_entry); + offset += IPA_NAT_RULE_NEXT_FIELD_OFFSET; + + ipa_nati_write_next_index(tbl_index, tbl_type, entry, offset); + } + + return; +} + +void ipa_nati_copy_ipv4_index_rule_to_hw( + struct ipa_nat_ip4_table_cache *ipv4_cache, + struct ipa_nat_indx_tbl_sw_rule *indx_sw_rule, + uint16_t entry, + uint8_t tbl_index) +{ + struct ipa_nat_indx_tbl_rule *tbl_ptr; + struct ipa_nat_sw_indx_tbl_rule sw_rule; + uint16_t prev_entry = indx_sw_rule->prev_index; + nat_table_type tbl_type; + uint16_t offset = 0; + + sw_rule.next_index = indx_sw_rule->next_index; + sw_rule.tbl_entry = indx_sw_rule->tbl_entry; + + if (entry < ipv4_cache->table_entries) { + tbl_ptr = (struct ipa_nat_indx_tbl_rule *)ipv4_cache->index_table_addr; + + memcpy(&tbl_ptr[entry], + &sw_rule, + sizeof(struct ipa_nat_indx_tbl_rule)); + } else { + tbl_ptr = (struct ipa_nat_indx_tbl_rule *)ipv4_cache->index_table_expn_addr; + + memcpy(&tbl_ptr[entry - ipv4_cache->table_entries], + &sw_rule, + sizeof(struct ipa_nat_indx_tbl_rule)); + } + + /* Update the next field of previous entry on collosion */ + if (IPA_NAT_INVALID_NAT_ENTRY != prev_entry) { + if (prev_entry < ipv4_cache->table_entries) { + tbl_type = IPA_NAT_INDX_TBL; + tbl_ptr = (struct ipa_nat_indx_tbl_rule *)ipv4_cache->index_table_addr; + } else { + tbl_type = IPA_NAT_INDEX_EXPN_TBL; + /* tbp_ptr is already pointing to expansion table + no need to initialize it */ + prev_entry = prev_entry - ipv4_cache->table_entries; + } + + offset = ipa_nati_get_index_entry_offset(ipv4_cache, tbl_type, prev_entry); + offset += IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET; + + IPADBG("Updating next index field of index table on collosion using dma()\n"); + ipa_nati_write_next_index(tbl_index, tbl_type, entry, offset); + } + + return; +} + +int ipa_nati_post_ipv4_dma_cmd(uint8_t tbl_indx, + uint16_t entry) +{ + struct ipa_ioc_nat_dma_cmd *cmd; + struct ipa_nat_rule *tbl_ptr; + uint32_t offset = ipv4_nat_cache.ip4_tbl[tbl_indx].tbl_addr_offset; + int ret = 0; + + cmd = (struct ipa_ioc_nat_dma_cmd *) + malloc(sizeof(struct ipa_ioc_nat_dma_cmd)+ + sizeof(struct ipa_ioc_nat_dma_one)); + if (NULL == cmd) { + IPAERR("unable to allocate memory\n"); + return -ENOMEM; + } + + if (entry < ipv4_nat_cache.ip4_tbl[tbl_indx].table_entries) { + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_rules_addr; + + cmd->dma[0].table_index = tbl_indx; + cmd->dma[0].base_addr = IPA_NAT_BASE_TBL; + cmd->dma[0].data = IPA_NAT_FLAG_ENABLE_BIT_MASK; + + cmd->dma[0].offset = (char *)&tbl_ptr[entry] - (char *)tbl_ptr; + cmd->dma[0].offset += IPA_NAT_RULE_FLAG_FIELD_OFFSET; + } else { + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_expn_rules_addr; + entry = entry - ipv4_nat_cache.ip4_tbl[tbl_indx].table_entries; + + cmd->dma[0].table_index = tbl_indx; + cmd->dma[0].base_addr = IPA_NAT_EXPN_TBL; + cmd->dma[0].data = IPA_NAT_FLAG_ENABLE_BIT_MASK; + + cmd->dma[0].offset = (char *)&tbl_ptr[entry] - (char *)tbl_ptr; + cmd->dma[0].offset += IPA_NAT_RULE_FLAG_FIELD_OFFSET; + cmd->dma[0].offset += offset; + } + + cmd->entries = 1; + if (ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_NAT_DMA, cmd)) { + perror("ipa_nati_post_ipv4_dma_cmd(): ioctl error value"); + IPAERR("unable to call dma icotl\n"); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + ret = -EIO; + goto fail; + } + IPADBG("posted IPA_IOC_NAT_DMA to kernel successfully during add operation\n"); + + +fail: + free(cmd); + + return ret; +} + + +int ipa_nati_del_ipv4_rule(uint32_t tbl_hdl, + uint32_t rule_hdl) +{ + uint8_t expn_tbl; + uint16_t tbl_entry; + struct ipa_nat_ip4_table_cache *tbl_ptr; + del_type rule_pos; + uint8_t tbl_indx = (uint8_t)(tbl_hdl - 1); + + /* 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; + } + + IPADBG("Delete below rule\n"); + IPADBG("tbl_entry:%d expn_tbl:%d\n", tbl_entry, expn_tbl); + + tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_indx]; + if (!tbl_ptr->valid) { + IPAERR("invalid table handle\n"); + return -EINVAL; + } + + ipa_nati_find_rule_pos(tbl_ptr, expn_tbl, + tbl_entry, &rule_pos); + IPADBG("rule_pos:%d\n", rule_pos); + + if (ipa_nati_post_del_dma_cmd(tbl_indx, tbl_entry, + expn_tbl, rule_pos)) { + return -EINVAL; + } + + ipa_nati_del_dead_ipv4_head_nodes(tbl_indx); + + /* Reset rule_id_array entry */ + ipv4_nat_cache.ip4_tbl[tbl_indx].rule_id_array[rule_hdl-1] = + IPA_NAT_INVALID_NAT_ENTRY; + +#ifdef NAT_DUMP + IPADBG("Dumping Table after deleting rule\n"); + ipa_nat_dump_ipv4_table(tbl_hdl); +#endif + + return 0; +} + +void ReorderCmds(struct ipa_ioc_nat_dma_cmd *cmd, int size) +{ + int indx_tbl_start = 0, cnt, cnt1; + struct ipa_ioc_nat_dma_cmd *tmp; + + IPADBG("called ReorderCmds() with entries :%d\n", cmd->entries); + + for (cnt = 0; cnt < cmd->entries; cnt++) { + if (cmd->dma[cnt].base_addr == IPA_NAT_INDX_TBL || + cmd->dma[cnt].base_addr == IPA_NAT_INDEX_EXPN_TBL) { + indx_tbl_start = cnt; + break; + } + } + + if (indx_tbl_start == 0) { + IPADBG("Reorder not needed\n"); + return; + } + + tmp = (struct ipa_ioc_nat_dma_cmd *)malloc(size); + if (tmp == NULL) { + IPAERR("unable to allocate memory\n"); + return; + } + + cnt1 = 0; + tmp->entries = cmd->entries; + for (cnt = indx_tbl_start; cnt < cmd->entries; cnt++) { + tmp->dma[cnt1] = cmd->dma[cnt]; + cnt1++; + } + + for (cnt = 0; cnt < indx_tbl_start; cnt++) { + tmp->dma[cnt1] = cmd->dma[cnt]; + cnt1++; + } + + memset(cmd, 0, size); + memcpy(cmd, tmp, size); + free(tmp); + + return; +} + +int ipa_nati_post_del_dma_cmd(uint8_t tbl_indx, + uint16_t cur_tbl_entry, + uint8_t expn_tbl, + del_type rule_pos) +{ + +#define MAX_DMA_ENTRIES_FOR_DEL 3 + + struct ipa_nat_ip4_table_cache *cache_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + struct ipa_nat_rule *tbl_ptr; + int ret = 0, size = 0; + + uint16_t indx_tbl_entry = IPA_NAT_INVALID_NAT_ENTRY; + del_type indx_rule_pos; + + struct ipa_ioc_nat_dma_cmd *cmd; + uint8_t no_of_cmds = 0; + + uint16_t prev_entry = IPA_NAT_INVALID_NAT_ENTRY; + uint16_t next_entry = IPA_NAT_INVALID_NAT_ENTRY; + uint16_t indx_next_entry = IPA_NAT_INVALID_NAT_ENTRY; + uint16_t indx_next_next_entry = IPA_NAT_INVALID_NAT_ENTRY; + uint16_t table_entry; + + size = sizeof(struct ipa_ioc_nat_dma_cmd)+ + (MAX_DMA_ENTRIES_FOR_DEL * sizeof(struct ipa_ioc_nat_dma_one)); + + cmd = (struct ipa_ioc_nat_dma_cmd *)malloc(size); + if (NULL == cmd) { + IPAERR("unable to allocate memory\n"); + return -ENOMEM; + } + + cache_ptr = &ipv4_nat_cache.ip4_tbl[tbl_indx]; + if (!expn_tbl) { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_rules_addr; + } else { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + } + + + if (!Read16BitFieldValue(tbl_ptr[cur_tbl_entry].ip_cksm_enbl, + ENABLE_FIELD)) { + IPAERR("Deleting invalid(not enabled) rule\n"); + ret = -EINVAL; + goto fail; + } + + indx_tbl_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].sw_spec_params, + SW_SPEC_PARAM_INDX_TBL_ENTRY_FIELD); + + /* ================================================ + Base Table rule Deletion + ================================================*/ + /* Just delete the current rule by disabling the flag field */ + if (IPA_NAT_DEL_TYPE_ONLY_ONE == rule_pos) { + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_BASE_TBL; + cmd->dma[no_of_cmds].data = IPA_NAT_FLAG_DISABLE_BIT_MASK; + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, + cur_tbl_entry); + cmd->dma[no_of_cmds].offset += IPA_NAT_RULE_FLAG_FIELD_OFFSET; + } + + /* Just update the protocol field to invalid */ + else if (IPA_NAT_DEL_TYPE_HEAD == rule_pos) { + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_BASE_TBL; + cmd->dma[no_of_cmds].data = IPA_NAT_INVALID_PROTO_FIELD_VALUE; + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, + cur_tbl_entry); + cmd->dma[no_of_cmds].offset += IPA_NAT_RULE_PROTO_FIELD_OFFSET; + + IPADBG("writing invalid proto: 0x%x\n", cmd->dma[no_of_cmds].data); + } + + /* + Update the previous entry of next_index field value + with current entry next_index field value + */ + else if (IPA_NAT_DEL_TYPE_MIDDLE == rule_pos) { + prev_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].sw_spec_params, + SW_SPEC_PARAM_PREV_INDEX_FIELD); + + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + + cmd->dma[no_of_cmds].base_addr = IPA_NAT_BASE_TBL; + if (prev_entry >= cache_ptr->table_entries) { + cmd->dma[no_of_cmds].base_addr = IPA_NAT_EXPN_TBL; + prev_entry -= cache_ptr->table_entries; + } + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, prev_entry); + + cmd->dma[no_of_cmds].offset += IPA_NAT_RULE_NEXT_FIELD_OFFSET; + } + + /* + Reset the previous entry of next_index field with 0 + */ + else if (IPA_NAT_DEL_TYPE_LAST == rule_pos) { + prev_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].sw_spec_params, + SW_SPEC_PARAM_PREV_INDEX_FIELD); + + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = IPA_NAT_INVALID_NAT_ENTRY; + + cmd->dma[no_of_cmds].base_addr = IPA_NAT_BASE_TBL; + if (prev_entry >= cache_ptr->table_entries) { + cmd->dma[no_of_cmds].base_addr = IPA_NAT_EXPN_TBL; + prev_entry -= cache_ptr->table_entries; + } + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, prev_entry); + + cmd->dma[no_of_cmds].offset += IPA_NAT_RULE_NEXT_FIELD_OFFSET; + } + + /* ================================================ + Base Table rule Deletion End + ================================================*/ + + /* ================================================ + Index Table rule Deletion + ================================================*/ + ipa_nati_find_index_rule_pos(cache_ptr, + indx_tbl_entry, + &indx_rule_pos); + IPADBG("Index table entry: 0x%x\n", indx_tbl_entry); + IPADBG("and position: %d\n", indx_rule_pos); + if (indx_tbl_entry >= cache_ptr->table_entries) { + indx_tbl_entry -= cache_ptr->table_entries; + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_expn_addr; + } else { + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_addr; + } + + /* Just delete the current rule by resetting nat_table_index field to 0 */ + if (IPA_NAT_DEL_TYPE_ONLY_ONE == indx_rule_pos) { + no_of_cmds++; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = IPA_NAT_INVALID_NAT_ENTRY; + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, + indx_tbl_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NAT_INDEX_FIELD_OFFSET; + } + + /* copy the next entry values to current entry */ + else if (IPA_NAT_DEL_TYPE_HEAD == indx_rule_pos) { + next_entry = + Read16BitFieldValue(indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + next_entry -= cache_ptr->table_entries; + + no_of_cmds++; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + cmd->dma[no_of_cmds].table_index = tbl_indx; + + /* Copy the nat_table_index field value of next entry */ + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_expn_addr; + cmd->dma[no_of_cmds].data = + Read16BitFieldValue(indx_tbl_ptr[next_entry].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD); + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, + indx_tbl_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NAT_INDEX_FIELD_OFFSET; + + /* Copy the next_index field value of next entry */ + no_of_cmds++; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = + Read16BitFieldValue(indx_tbl_ptr[next_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, indx_tbl_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET; + indx_next_entry = next_entry; + } + + /* + Update the previous entry of next_index field value + with current entry next_index field value + */ + else if (IPA_NAT_DEL_TYPE_MIDDLE == indx_rule_pos) { + prev_entry = cache_ptr->index_expn_table_meta[indx_tbl_entry].prev_index; + + no_of_cmds++; + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = + Read16BitFieldValue(indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + if (prev_entry >= cache_ptr->table_entries) { + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDEX_EXPN_TBL; + prev_entry -= cache_ptr->table_entries; + } + + IPADBG("prev_entry: %d update with cur next_index: %d\n", + prev_entry, cmd->dma[no_of_cmds].data); + IPADBG("prev_entry: %d exist in table_type:%d\n", + prev_entry, cmd->dma[no_of_cmds].base_addr); + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, prev_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET; + } + + /* Reset the previous entry next_index field with 0 */ + else if (IPA_NAT_DEL_TYPE_LAST == indx_rule_pos) { + prev_entry = cache_ptr->index_expn_table_meta[indx_tbl_entry].prev_index; + + no_of_cmds++; + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = IPA_NAT_INVALID_NAT_ENTRY; + + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + if (prev_entry >= cache_ptr->table_entries) { + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDEX_EXPN_TBL; + prev_entry -= cache_ptr->table_entries; + } + + IPADBG("Reseting prev_entry: %d next_index\n", prev_entry); + IPADBG("prev_entry: %d exist in table_type:%d\n", + prev_entry, cmd->dma[no_of_cmds].base_addr); + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, prev_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET; + } + + /* ================================================ + Index Table rule Deletion End + ================================================*/ + cmd->entries = no_of_cmds + 1; + + if (cmd->entries > 1) { + ReorderCmds(cmd, size); + } + if (ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_NAT_DMA, cmd)) { + perror("ipa_nati_post_del_dma_cmd(): ioctl error value"); + IPAERR("unable to post cmd\n"); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + ret = -EIO; + goto fail; + } + + /* if entry exist in IPA_NAT_DEL_TYPE_MIDDLE of list + Update the previous entry in sw specific parameters + */ + if (IPA_NAT_DEL_TYPE_MIDDLE == rule_pos) { + /* Retrieve the current entry prev_entry value */ + prev_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].sw_spec_params, + SW_SPEC_PARAM_PREV_INDEX_FIELD); + + /* Retrieve the next entry */ + next_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + + next_entry -= cache_ptr->table_entries; + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + + /* copy the current entry prev_entry value to next entry*/ + UpdateSwSpecParams(&tbl_ptr[next_entry], + IPA_NAT_SW_PARAM_PREV_INDX_BYTE, + prev_entry); + } + + /* Reset the other field values of current delete entry + In case of IPA_NAT_DEL_TYPE_HEAD, don't reset */ + if (IPA_NAT_DEL_TYPE_HEAD != rule_pos) { + memset(&tbl_ptr[cur_tbl_entry], 0, sizeof(struct ipa_nat_rule)); + } + + if (indx_rule_pos == IPA_NAT_DEL_TYPE_HEAD) { + + /* Update next next entry previous value to current + entry as we moved the next entry values + to current entry */ + indx_next_next_entry = + Read16BitFieldValue(indx_tbl_ptr[indx_next_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + if (indx_next_next_entry != 0 && + indx_next_next_entry >= cache_ptr->table_entries) { + + IPADBG("Next Next entry: %d\n", indx_next_next_entry); + indx_next_next_entry -= cache_ptr->table_entries; + + IPADBG("Updating entry: %d prev index to: %d\n", + indx_next_next_entry, indx_tbl_entry); + cache_ptr->index_expn_table_meta[indx_next_next_entry].prev_index = + indx_tbl_entry; + } + + /* Now reset the next entry as we copied + the next entry to current entry */ + IPADBG("Resetting, index table entry(Proper): %d\n", + (cache_ptr->table_entries + indx_next_entry)); + + /* This resets both table entry and next index values */ + indx_tbl_ptr[indx_next_entry].tbl_entry_nxt_indx = 0; + + /* + In case of IPA_NAT_DEL_TYPE_HEAD, update the sw specific parameters + (index table entry) of base table entry + */ + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_addr; + table_entry = + Read16BitFieldValue(indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD); + + if (table_entry >= cache_ptr->table_entries) { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + table_entry -= cache_ptr->table_entries; + } else { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_rules_addr; + } + + UpdateSwSpecParams(&tbl_ptr[table_entry], + IPA_NAT_SW_PARAM_INDX_TBL_ENTRY_BYTE, + indx_tbl_entry); + } else { + /* Update the prev_entry value (in index_expn_table_meta) + for the next_entry in list with current entry prev_entry value + */ + if (IPA_NAT_DEL_TYPE_MIDDLE == indx_rule_pos) { + next_entry = + Read16BitFieldValue(indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + if (next_entry >= cache_ptr->table_entries) { + next_entry -= cache_ptr->table_entries; + } + + cache_ptr->index_expn_table_meta[next_entry].prev_index = + cache_ptr->index_expn_table_meta[indx_tbl_entry].prev_index; + + cache_ptr->index_expn_table_meta[indx_tbl_entry].prev_index = + IPA_NAT_INVALID_NAT_ENTRY; + } + + IPADBG("At, indx_tbl_entry value: %d\n", indx_tbl_entry); + IPADBG("At, indx_tbl_entry member address: %p\n", + &indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx); + + indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx = 0; + + } + +fail: + free(cmd); + + return ret; +} + +void ipa_nati_find_index_rule_pos( + struct ipa_nat_ip4_table_cache *cache_ptr, + uint16_t tbl_entry, + del_type *rule_pos) +{ + struct ipa_nat_indx_tbl_rule *tbl_ptr; + + if (tbl_entry >= cache_ptr->table_entries) { + tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_expn_addr; + + tbl_entry -= cache_ptr->table_entries; + if (Read16BitFieldValue(tbl_ptr[tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == IPA_NAT_INVALID_NAT_ENTRY) { + *rule_pos = IPA_NAT_DEL_TYPE_LAST; + } else { + *rule_pos = IPA_NAT_DEL_TYPE_MIDDLE; + } + } else { + tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_addr; + + if (Read16BitFieldValue(tbl_ptr[tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == IPA_NAT_INVALID_NAT_ENTRY) { + *rule_pos = IPA_NAT_DEL_TYPE_ONLY_ONE; + } else { + *rule_pos = IPA_NAT_DEL_TYPE_HEAD; + } + } +} + +void ipa_nati_find_rule_pos(struct ipa_nat_ip4_table_cache *cache_ptr, + uint8_t expn_tbl, + uint16_t tbl_entry, + del_type *rule_pos) +{ + struct ipa_nat_rule *tbl_ptr; + + if (expn_tbl) { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + if (Read16BitFieldValue(tbl_ptr[tbl_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == IPA_NAT_INVALID_NAT_ENTRY) { + *rule_pos = IPA_NAT_DEL_TYPE_LAST; + } else { + *rule_pos = IPA_NAT_DEL_TYPE_MIDDLE; + } + } else { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_rules_addr; + if (Read16BitFieldValue(tbl_ptr[tbl_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == IPA_NAT_INVALID_NAT_ENTRY) { + *rule_pos = IPA_NAT_DEL_TYPE_ONLY_ONE; + } else { + *rule_pos = IPA_NAT_DEL_TYPE_HEAD; + } + } +} + +void ipa_nati_del_dead_ipv4_head_nodes(uint8_t tbl_indx) +{ + struct ipa_nat_rule *tbl_ptr; + uint16_t cnt; + + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_rules_addr; + + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_indx].table_entries; + cnt++) { + + if (Read8BitFieldValue(tbl_ptr[cnt].ts_proto, + PROTOCOL_FIELD) == IPA_NAT_INVALID_PROTO_FIELD_CMP + && + Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == IPA_NAT_INVALID_NAT_ENTRY) { + /* Delete the IPA_NAT_DEL_TYPE_HEAD node */ + IPADBG("deleting the dead node 0x%x\n", cnt); + memset(&tbl_ptr[cnt], 0, sizeof(struct ipa_nat_rule)); + } + } /* end of for loop */ + + return; +} + + +/* ======================================================== + Debug functions + ========================================================*/ +#ifdef NAT_DUMP +void ipa_nat_dump_ipv4_table(uint32_t tbl_hdl) +{ + struct ipa_nat_rule *tbl_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + int cnt; + uint8_t atl_one = 0; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed\n"); + return; + } + + /* Print ipv4 rules */ + IPADBG("Dumping ipv4 active rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + atl_one = 1; + ipa_nati_print_rule(&tbl_ptr[cnt], cnt); + } + } + if (!atl_one) { + IPADBG("No active base rules, total: %d\n", + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries); + } + atl_one = 0; + + /* Print ipv4 expansion rules */ + IPADBG("Dumping ipv4 active expansion rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_expn_rules_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + atl_one = 1; + ipa_nati_print_rule(&tbl_ptr[cnt], + (cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries)); + } + } + if (!atl_one) { + IPADBG("No active base expansion rules, total: %d\n", + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries); + } + atl_one = 0; + + /* Print ipv4 index rules */ + IPADBG("Dumping ipv4 index active rules:\n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + atl_one = 1; + ipa_nati_print_index_rule(&indx_tbl_ptr[cnt], cnt, 0); + } + } + if (!atl_one) { + IPADBG("No active index table rules, total:%d\n", + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries); + } + atl_one = 0; + + + /* Print ipv4 index expansion rules */ + IPADBG("Dumping ipv4 index expansion active rules:\n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_expn_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + atl_one = 1; + ipa_nati_print_index_rule(&indx_tbl_ptr[cnt], + (cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries), + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_expn_table_meta[cnt].prev_index); + } + } + if (!atl_one) { + IPADBG("No active index expansion rules, total:%d\n", + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries); + } + atl_one = 0; + +} + +void ipa_nati_print_rule( + struct ipa_nat_rule *param, + uint32_t rule_id) +{ + struct ipa_nat_sw_rule sw_rule; + memcpy(&sw_rule, param, sizeof(sw_rule)); + uint32_t ip_addr; + + IPADUMP("rule-id:%d ", rule_id); + ip_addr = sw_rule.target_ip; + IPADUMP("Trgt-IP:%d.%d.%d.%d ", + ((ip_addr & 0xFF000000) >> 24), ((ip_addr & 0x00FF0000) >> 16), + ((ip_addr & 0x0000FF00) >> 8), ((ip_addr & 0x000000FF))); + + IPADUMP("Trgt-Port:%d Priv-Port:%d ", sw_rule.target_port, sw_rule.private_port); + + ip_addr = sw_rule.private_ip; + IPADUMP("Priv-IP:%d.%d.%d.%d ", + ((ip_addr & 0xFF000000) >> 24), ((ip_addr & 0x00FF0000) >> 16), + ((ip_addr & 0x0000FF00) >> 8), ((ip_addr & 0x000000FF))); + + IPADUMP("Pub-Port:%d Nxt-indx:%d ", sw_rule.public_port, sw_rule.next_index); + IPADUMP("IP-cksm-delta:0x%x En-bit:0x%x ", sw_rule.ip_chksum, sw_rule.enable); + IPADUMP("TS:0x%x Proto:0x%x ", sw_rule.time_stamp, sw_rule.protocol); + IPADUMP("Prv-indx:%d indx_tbl_entry:%d ", sw_rule.prev_index, sw_rule.indx_tbl_entry); + IPADUMP("Tcp-udp-cksum-delta:0x%x", sw_rule.tcp_udp_chksum); + IPADUMP("\n"); + return; +} + +void ipa_nati_print_index_rule( + struct ipa_nat_indx_tbl_rule *param, + uint32_t rule_id, uint16_t prev_indx) +{ + struct ipa_nat_sw_indx_tbl_rule sw_rule; + memcpy(&sw_rule, param, sizeof(sw_rule)); + + IPADUMP("rule-id:%d Table_entry:%d Next_index:%d, prev_indx:%d", + rule_id, sw_rule.tbl_entry, sw_rule.next_index, prev_indx); + IPADUMP("\n"); + return; +} + +int ipa_nati_query_nat_rules( + uint32_t tbl_hdl, + nat_table_type tbl_type) +{ + struct ipa_nat_rule *tbl_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + int cnt = 0, ret = 0; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed\n"); + return ret; + } + + /* Print ipv4 rules */ + if (tbl_type == IPA_NAT_BASE_TBL) { + IPADBG("Counting ipv4 active rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].ipv4_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + ret++; + } + } + if (!ret) { + IPADBG("No active base rules\n"); + } + + IPADBG("Number of active base rules: %d\n", ret); + } + + /* Print ipv4 expansion rules */ + if (tbl_type == IPA_NAT_EXPN_TBL) { + IPADBG("Counting ipv4 active expansion rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].ipv4_expn_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + ret++; + } + } + if (!ret) { + IPADBG("No active base expansion rules\n"); + } + + IPADBG("Number of active base expansion rules: %d\n", ret); + } + + /* Print ipv4 index rules */ + if (tbl_type == IPA_NAT_INDX_TBL) { + IPADBG("Counting ipv4 index active rules:\n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].index_table_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + ret++; + } + } + if (!ret) { + IPADBG("No active index table rules\n"); + } + + IPADBG("Number of active index table rules: %d\n", ret); + } + + /* Print ipv4 index expansion rules */ + if (tbl_type == IPA_NAT_INDEX_EXPN_TBL) { + IPADBG("Counting ipv4 index expansion active rules:\n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].index_table_expn_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + ret++; + } + } + + if (!ret) + IPADBG("No active index expansion rules\n"); + + IPADBG("Number of active index expansion rules: %d\n", ret); + } + + return ret; +} +#endif diff --git a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_logi.c b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_logi.c new file mode 100644 index 0000000..b829b78 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_logi.c @@ -0,0 +1,49 @@ +/* +Copyright (c) 2013, 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. +*/ +/*! + @file + IPACM_log.cpp + + @brief + This file implements the IPAM log functionality. + + @Author + Skylar Chang + +*/ +#include "ipa_nat_logi.h" +#include +#include + +void log_nat_message(char *msg) +{ + return; +} + + diff --git a/data-ipa-cfg-mgr/ipanat/test/Android.mk b/data-ipa-cfg-mgr/ipanat/test/Android.mk new file mode 100644 index 0000000..4c94b56 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/Android.mk @@ -0,0 +1,53 @@ +BOARD_PLATFORM_LIST := msm8916 +BOARD_PLATFORM_LIST += msm8909 +ifneq ($(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) + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../ipanat/inc + +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +LOCAL_MODULE := ipa_nat_test +LOCAL_SRC_FILES := ipa_nat_test000.c \ + ipa_nat_test001.c \ + ipa_nat_test002.c \ + ipa_nat_test003.c \ + ipa_nat_test004.c \ + ipa_nat_test005.c \ + ipa_nat_test006.c \ + ipa_nat_test007.c \ + ipa_nat_test008.c \ + ipa_nat_test009.c \ + ipa_nat_test010.c \ + ipa_nat_test011.c \ + ipa_nat_test012.c \ + ipa_nat_test013.c \ + ipa_nat_test014.c \ + ipa_nat_test015.c \ + ipa_nat_test016.c \ + ipa_nat_test017.c \ + ipa_nat_test018.c \ + ipa_nat_test019.c \ + ipa_nat_test020.c \ + ipa_nat_test021.c \ + ipa_nat_test022.c \ + main.c + + +LOCAL_SHARED_LIBRARIES := libipanat + +LOCAL_MODULE_TAGS := debug +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/kernel-tests/ip_accelerator + +include $(BUILD_EXECUTABLE) + +endif # $(TARGET_ARCH) +endif +endif \ No newline at end of file diff --git a/data-ipa-cfg-mgr/ipanat/test/Makefile.am b/data-ipa-cfg-mgr/ipanat/test/Makefile.am new file mode 100644 index 0000000..3aec070 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/Makefile.am @@ -0,0 +1,42 @@ +AM_CPPFLAGS = -I./../inc \ + -I$(top_srcdir)/ipanat/inc + +AM_CPPFLAGS += -Wall -Wundef -Wno-trigraphs +AM_CPPFLAGS += -g + +ipanattest_SOURCES = ipa_nat_test000.c \ + ipa_nat_test001.c \ + ipa_nat_test002.c \ + ipa_nat_test003.c \ + ipa_nat_test004.c \ + ipa_nat_test005.c \ + ipa_nat_test006.c \ + ipa_nat_test007.c \ + ipa_nat_test008.c \ + ipa_nat_test009.c \ + ipa_nat_test010.c \ + ipa_nat_test011.c \ + ipa_nat_test012.c \ + ipa_nat_test013.c \ + ipa_nat_test014.c \ + ipa_nat_test015.c \ + ipa_nat_test016.c \ + ipa_nat_test017.c \ + ipa_nat_test018.c \ + ipa_nat_test019.c \ + ipa_nat_test020.c \ + ipa_nat_test021.c \ + ipa_nat_test022.c \ + main.c + + +bin_PROGRAMS = ipanattest + +requiredlibs = ../src/libipanat.la + +ipanattest_LDADD = $(requiredlibs) + +LOCAL_MODULE := libipanat +LOCAL_PRELINK_MODULE := false +include $(BUILD_SHARED_LIBRARY) + diff --git a/data-ipa-cfg-mgr/ipanat/test/README.txt b/data-ipa-cfg-mgr/ipanat/test/README.txt new file mode 100644 index 0000000..4e87121 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/README.txt @@ -0,0 +1,18 @@ +1 To run this suite separately(each test case creates table and delete table) use below command + - To execute test suite nt times with n entries, command "ipanatest sep nt n" + + Example: To execute test suite 1 time with 100 entries, command "ipanattest sep 100" + + +2. To run test suite not separately(creates table and delete table only once) use below command + - To execute test suite nt times with n entries, command "ipanatest reg nt n" + + Example: To execute test suite 5 times with 32 entries, command "ipanattest reg 5 32" + + +3. To run inotify regression test use command, "ipanattest inotify nt" + + Example: To execute inotify 5 times, command "ipanattest inotify 5" + + +4. if we just give command "ipanattest", runs test suite 1 time with 100 entries (non separate) diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test.h b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test.h new file mode 100644 index 0000000..d5ac0d5 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014, 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 FILES FOR MODULE + +===========================================================================*/ +#include "stdint.h" /* uint32_t */ +#include "stdio.h" +#include /* for proto definitions */ + +#define u32 uint32_t +#define u16 uint16_t +#define u8 uint8_t + +/*============ Preconditions to run NAT Test cases =========*/ +#define IPA_NAT_TEST_PRE_COND_TE 20 + +#define CHECK_ERR1(x, tbl_hdl) \ + if(ipa_nat_validate_ipv4_table(tbl_hdl)) { \ + if(sep) {\ + ipa_nat_del_ipv4_tbl(tbl_hdl); \ + }\ + return -1;\ + }\ + if(x) { \ + IPAERR("%d\n", ret); \ + if(sep) {\ + ipa_nat_del_ipv4_tbl(tbl_hdl); \ + }\ + return -1; \ + } + +#define CHECK_ERR(x) if(x) { \ + IPAERR("%d\n", ret); \ + return -1;\ + } + +#if 0 +#define CHECK_ERR(x) if(x) { \ + IPAERR("%d\n", ret); \ + if(sep) {\ + ipa_nat_del_ipv4_tbl(tbl_hdl); \ + }\ + return -1;\ + } +#endif + +#define IPADBG(fmt, args...) printf(" %s:%d " fmt, __FUNCTION__, __LINE__, ## args) +#define IPAERR(fmt, args...) printf(" %s:%d " fmt, __FUNCTION__, __LINE__, ## args) + +#define NAT_DUMP +int ipa_nat_validate_ipv4_table(u32); + +int ipa_nat_test000(int, u32, u8); +int ipa_nat_test001(int, u32, u8); +int ipa_nat_test002(int, u32, u8); +int ipa_nat_test003(int, u32, u8); +int ipa_nat_test004(int, u32, u8); +int ipa_nat_test005(int, u32, u8); +int ipa_nat_test006(int, u32, u8); +int ipa_nat_test007(int, u32, u8); +int ipa_nat_test008(int, u32, u8); +int ipa_nat_test009(int, u32, u8); +int ipa_nat_test010(int, u32, u8); +int ipa_nat_test011(int, u32, u8); +int ipa_nat_test012(int, u32, u8); +int ipa_nat_test013(int, u32, u8); +int ipa_nat_test014(int, u32, u8); +int ipa_nat_test015(int, u32, u8); +int ipa_nat_test016(int, u32, u8); +int ipa_nat_test017(int, u32, u8); +int ipa_nat_test018(int, u32, u8); +int ipa_nat_test019(int, u32, u8); +int ipa_nat_test020(int, u32, u8); +int ipa_nat_test021(int, int); +int ipa_nat_test022(int, u32, u8); diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test000.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test000.c new file mode 100644 index 0000000..09914ea --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test000.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test000.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Delete ipv4 table +*/ +/*===========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test000(int total_entries, u32 tbl_hdl, u8 sep) +{ + + int ret; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + if (0 != ret) + { + IPAERR("unable to create ipv4 nat table and returning Error:%d\n", ret); + return -1; + } + IPADBG("create nat ipv4 table successfully() \n"); + + IPADBG("calling ipa_nat_del_ipv4_tbl() \n"); + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + if (0 != ret) + { + IPAERR("Unable to delete ipv4 nat table %d\n", ret); + return -1; + } + IPADBG("deleted ipv4 nat table successfully. Test passed \n"); + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test001.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test001.c new file mode 100644 index 0000000..8daef33 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test001.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test001.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Add ipv4 rule + 3. Delete ipv4 table +*/ +/*===========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test001(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s()\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test002.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test002.c new file mode 100644 index 0000000..e6f5ae3 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test002.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test002.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Add ipv4 rule + 3. delete ipv4 rule + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test002(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s()\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test003.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test003.c new file mode 100644 index 0000000..0634265 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test003.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, 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. + */ + + +/*=========================================================================*/ +/*! + @file + IPA_NAT_ipa_nat_test003.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Add ipv4 rule + 3. Add ipv4 rule + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test003(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test004.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test004.c new file mode 100644 index 0000000..02378ff --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test004.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test004.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Query nat table handle + 3. Delete ipv4 table +*/ +/*===========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test004(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret = 0; + u32 tbl_hdl1 = 0; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl1); + if(ret == 0) + { + IPAERR("able to delete table using invalid table handle\n"); + return -1; + } + } + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test005.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test005.c new file mode 100644 index 0000000..12228d1 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test005.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test005.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Add ipv4 rule + 3. Delete ipv4 rule + 4. Add ipv4 rule + 5. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test005(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret = 0; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + if (sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test006.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test006.c new file mode 100644 index 0000000..36f0171 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test006.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test006.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same ipv rules + 3. delete first followed by second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test006(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret=0; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test007.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test007.c new file mode 100644 index 0000000..4160c02 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test007.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test007.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same ipv rules + 3. delete second followed by first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test007(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test008.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test008.c new file mode 100644 index 0000000..d016055 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test008.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test008.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 2 distinct rules + 3. delete first followed by second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test008(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + ipv4_rule1.target_ip = 0xC1171602; /* 193.23.22.2 */ + ipv4_rule1.target_port = 1234; + ipv4_rule1.private_ip = 0xC2171602; /* 194.23.22.2 */ + ipv4_rule1.private_port = 5678; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test009.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test009.c new file mode 100644 index 0000000..cf3c40f --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test009.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test009.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 2 distinct rules + 3. delete second followed by first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test009(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xC1171602; /* 193.23.22.2 */ + ipv4_rule1.target_port = 1234; + ipv4_rule1.private_ip = 0xC2171602; /* 194.23.22.2 */ + ipv4_rule1.private_port = 5678; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test010.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test010.c new file mode 100644 index 0000000..42d7fee --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test010.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test010.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 3 distinct ipv4 rules + 3. delete first, second followed by last + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test010(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1, rule_hdl2; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1, ipv4_rule2; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule1.target_port = 1235; + ipv4_rule1.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule1.private_port = 5679; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 9051; + + ipv4_rule2.target_ip = 0xC1171602; /* 193.23.22.2 */ + ipv4_rule2.target_port = 1235; + ipv4_rule2.private_ip = 0xC2171602; /* 194.23.22.2 */ + ipv4_rule2.private_port = 5679; + ipv4_rule2.protocol = IPPROTO_TCP; + ipv4_rule2.public_port = 9051; + + IPADBG("%s():\n",__FUNCTION__); + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule2, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test011.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test011.c new file mode 100644 index 0000000..bcce76c --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test011.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test011.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 3 distinct ipv4 rules + 3. delete second, first followed by last + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test011(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1, rule_hdl2; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1, ipv4_rule2; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xF1181601; + ipv4_rule1.target_port = 1555; + ipv4_rule1.private_ip = 0xF2151601; + ipv4_rule1.private_port = 5999; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 9111; + + ipv4_rule2.target_ip = 0xC1166602; + ipv4_rule2.target_port = 1555; + ipv4_rule2.private_ip = 0xC2155602; + ipv4_rule2.private_port = 5777; + ipv4_rule2.protocol = IPPROTO_TCP; + ipv4_rule2.public_port = 9000; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule2, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test012.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test012.c new file mode 100644 index 0000000..9d3c835 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test012.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test012.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 3 distinct ipv4 rules + 3. Delete third, second, first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + + +int ipa_nat_test012(int totoal_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1, rule_hdl2; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1, ipv4_rule2; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xD1171601; + ipv4_rule1.target_port = 3512; + ipv4_rule1.private_ip = 0xD2471601; + ipv4_rule1.private_port = 9997; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 8881; + + ipv4_rule2.target_ip = 0xC1172452; + ipv4_rule2.target_port = 1895; + ipv4_rule2.private_ip = 0xC2172452; + ipv4_rule2.private_port = 6668; + ipv4_rule2.protocol = IPPROTO_TCP; + ipv4_rule2.public_port = 5551; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, totoal_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule2, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test013.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test013.c new file mode 100644 index 0000000..2b9b005 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test013.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test013.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 3 distinct ipv4 rules + 3. Delete third, first and second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test013(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1, rule_hdl2; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1, ipv4_rule2; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xC1171609; /* 193.23.22.9 */ + ipv4_rule1.target_port = 1235; + ipv4_rule1.private_ip = 0xC2171609; /* 194.23.22.9 */ + ipv4_rule1.private_port = 6579; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 8951; + + ipv4_rule2.target_ip = 0xC1171606; /* 193.23.22.6 */ + ipv4_rule2.target_port = 1235; + ipv4_rule2.private_ip = 0xC2171606; /* 194.23.22.6 */ + ipv4_rule2.private_port = 7956; + ipv4_rule2.protocol = IPPROTO_TCP; + ipv4_rule2.public_port = 5109; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule2, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test014.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test014.c new file mode 100644 index 0000000..fd30317 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test014.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, 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. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test014.cpp + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete first, second and third + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test014(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s()\n", __FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test015.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test015.c new file mode 100644 index 0000000..eaef923 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test015.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, 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. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test015.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete first, third and second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + + +int ipa_nat_test015(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test016.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test016.c new file mode 100644 index 0000000..23157e2 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test016.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, 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. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test016.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete second, first and third + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test016(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test017.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test017.c new file mode 100644 index 0000000..d88e611 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test017.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, 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. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test017.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete second, third and first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test017(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test018.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test018.c new file mode 100644 index 0000000..c885d4d --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test018.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, 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. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test018.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete third, second and first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test018(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test019.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test019.c new file mode 100644 index 0000000..3ba3119 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test019.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, 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. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test019.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete third, first and second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test019(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test020.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test020.c new file mode 100644 index 0000000..e6871b5 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test020.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test020.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 4 ipv rules + 3. delete third, second, fourth and first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test020(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3, rule_hdl4; + ipa_nat_ipv4_rule ipv4_rule; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl4); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl4); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test021.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test021.c new file mode 100644 index 0000000..48c4321 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test021.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, 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. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test021.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test021(int total_entries, int reg) +{ + + int ret, i; + u32 tbl_hdl; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + IPADBG("%s():\n",__FUNCTION__); + + for(i=0; i +#include +#include +#include +#include +#include + +#include "ipa_nat_drv.h" +#include "ipa_nat_drvi.h" +#include "ipa_nat_test.h" + +extern struct ipa_nat_cache ipv4_nat_cache; + +int chk_for_loop(u32 tbl_hdl) +{ + struct ipa_nat_rule *tbl_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + int cnt; + uint16_t cur_entry; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed \n"); + return -EINVAL; + } + + IPADBG("checking ipv4 rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl,ENABLE_FIELD)) { + if(Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == cnt) + { + IPAERR("Infinite loop detected, entry\n"); + ipa_nati_print_rule(&tbl_ptr[cnt], cnt); + return -EINVAL; + } + } + } + + /* Print ipv4 expansion rules */ + IPADBG("checking ipv4 active expansion rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_expn_rules_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + cur_entry = + cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + if (Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == cur_entry) + { + IPAERR("Infinite loop detected\n"); + ipa_nati_print_rule(&tbl_ptr[cnt], + (cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries)); + return -EINVAL; + } + } + } + + /* Print ipv4 index rules */ + IPADBG("checking ipv4 index active rules: \n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == cnt) + { + IPAERR("Infinite loop detected\n"); + ipa_nati_print_index_rule(&indx_tbl_ptr[cnt], cnt, 0); + return -EINVAL; + } + } + } + + /* Print ipv4 index expansion rules */ + IPADBG("Checking ipv4 index expansion active rules: \n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_expn_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + cur_entry = + cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == cur_entry) + { + IPAERR("Infinite loop detected\n"); + ipa_nati_print_index_rule(&indx_tbl_ptr[cnt], + (cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries), + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].index_expn_table_meta[cnt].prev_index); + return -EINVAL; + } + } + } + return 0; +} + +uint8_t is_base_entry_valid(u32 tbl_hdl, u16 entry) +{ + struct ipa_nat_rule *tbl_ptr; + + if (entry > + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries) + { + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_expn_rules_addr; + entry -= + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + } + else + { + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_rules_addr; + } + return (Read16BitFieldValue(tbl_ptr[entry].ip_cksm_enbl, + ENABLE_FIELD)); +} + +uint8_t is_index_entry_valid(u32 tbl_hdl, u16 entry) +{ + struct ipa_nat_indx_tbl_rule *tbl_ptr; + + if (entry > + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries) + { + tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_expn_addr; + entry -= + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + } + else + { + tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_addr; + } + if (Read16BitFieldValue(tbl_ptr[entry].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + return 1; + } + else + { + return 0; + } +} + +int chk_for_validity(u32 tbl_hdl) +{ + struct ipa_nat_rule *tbl_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + uint16_t nxt_index, prv_index; + int cnt; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed \n"); + return -EINVAL; + } + + /* Validate base table next_indx and prev_indx values */ + IPADBG("Validating ipv4 active rules: \n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + nxt_index = + Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + if (!is_base_entry_valid(tbl_hdl, nxt_index)) { + IPAERR("Invalid next index found, entry:%d\n", cnt); + } + } + } + + IPADBG("Validating ipv4 expansion active rules: \n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_expn_rules_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + /* Validate next index */ + nxt_index = + Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + if (!is_base_entry_valid(tbl_hdl, nxt_index)) { + IPAERR("Invalid next index found, entry:%d\n", cnt); + } + /* Validate previous index */ + prv_index = + Read16BitFieldValue(tbl_ptr[cnt].sw_spec_params, + SW_SPEC_PARAM_PREV_INDEX_FIELD); + if (!is_base_entry_valid(tbl_hdl, prv_index)) { + IPAERR("Invalid Previous index found, entry:%d\n", cnt); + } + } + } + + IPADBG("Validating ipv4 index active rules: \n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + nxt_index = + Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + if (!is_index_entry_valid(tbl_hdl, nxt_index)) { + IPAERR("Invalid next index found, entry:%d\n", cnt); + } + } + } + + IPADBG("Validating ipv4 index expansion active rules: \n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_expn_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + /* Validate next index*/ + nxt_index = + Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + if (!is_index_entry_valid(tbl_hdl, nxt_index)) { + IPAERR("Invalid next index found, entry:%d\n", cnt); + } + + /* Validate previous index*/ + prv_index = + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_expn_table_meta[cnt].prev_index; + + if (!is_index_entry_valid(tbl_hdl, prv_index)) { + IPAERR("Invalid Previous index found, entry:%d\n", cnt); + } + } + } + + return 0; +} + +int ipa_nat_validate_ipv4_table(u32 tbl_hdl) +{ + int ret = 0; + + ret = chk_for_loop(tbl_hdl); + if (ret) + return ret; + ret = chk_for_validity(tbl_hdl); + + return ret; +} + +int main(int argc, char* argv[]) +{ + int exec = 0, pass = 0, ret; + int cnt, nt=1; + int total_entries = 100; + u8 sep = 0; + u32 tbl_hdl = 0; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + IPADBG("ipa_nat_testing user space nat driver\n"); + + if (argc == 4) + { + if (!strncmp(argv[1], "reg", 3)) + { + nt = atoi(argv[2]); + total_entries = atoi(argv[3]); + IPADBG("Reg: %d, Nat Entries: %d\n", nt, total_entries); + } + else if (!strncmp(argv[1], "sep", 3)) + { + sep = 1; + nt = atoi(argv[2]); + total_entries = atoi(argv[3]); + } + } + else if (argc == 3) + { + if (!strncmp(argv[1], "inotify", 7)) + { + ipa_nat_test021(total_entries, atoi(argv[2])); + return 0; + } + else if (!strncmp(argv[1], "sep", 3)) + { + sep = 1; + total_entries = atoi(argv[2]); + } + } + else if (argc == 2) + { + total_entries = atoi(argv[1]); + IPADBG("Nat Entries: %d\n", total_entries); + } + + + for (cnt=0; cnt= IPA_NAT_TEST_PRE_COND_TE) + { + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test010(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test011(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test012(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test013(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test014(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test015(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test016(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test017(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test018(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test019(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test020(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test022(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + } + + if (!sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + } + /*======= Printing Results ==========*/ + IPADBG("Total ipa_nat Tests Run:%d, Pass:%d, Fail:%d\n",exec, pass, exec-pass); + return 0; +} diff --git a/device.mk b/device.mk new file mode 100644 index 0000000..f858329 --- /dev/null +++ b/device.mk @@ -0,0 +1,278 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# Copyright (C) 2017 The LineageOS 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. + +$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_full.mk) + +# Overlay +DEVICE_PACKAGE_OVERLAYS += $(LOCAL_PATH)/overlay + +# These are the hardware-specific features +PRODUCT_COPY_FILES += \ + frameworks/native/data/etc/android.hardware.bluetooth.xml:system/etc/permissions/android.hardware.bluetooth.xml \ + frameworks/native/data/etc/android.hardware.bluetooth_le.xml:system/etc/permissions/android.hardware.bluetooth_le.xml \ + frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml \ + frameworks/native/data/etc/android.hardware.camera.front.xml:system/etc/permissions/android.hardware.camera.front.xml \ + frameworks/native/data/etc/android.hardware.fingerprint.xml:system/etc/permissions/android.hardware.fingerprint.xml \ + frameworks/native/data/etc/android.hardware.location.gps.xml:system/etc/permissions/android.hardware.location.gps.xml \ + frameworks/native/data/etc/android.hardware.nfc.xml:system/etc/permissions/android.hardware.nfc.xml \ + frameworks/native/data/etc/android.hardware.nfc.hce.xml:system/etc/permissions/android.hardware.nfc.hce.xml \ + frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:system/etc/permissions/android.hardware.sensor.accelerometer.xml \ + frameworks/native/data/etc/android.hardware.sensor.compass.xml:system/etc/permissions/android.hardware.sensor.compass.xml \ + frameworks/native/data/etc/android.hardware.sensor.gyroscope.xml:system/etc/permissions/android.hardware.sensor.gyroscope.xml \ + frameworks/native/data/etc/android.hardware.sensor.light.xml:system/etc/permissions/android.hardware.sensor.light.xml \ + frameworks/native/data/etc/android.hardware.sensor.proximity.xml:system/etc/permissions/android.hardware.sensor.proximity.xml \ + frameworks/native/data/etc/android.hardware.sensor.stepcounter.xml:system/etc/permissions/android.hardware.sensor.stepcounter.xml \ + frameworks/native/data/etc/android.hardware.sensor.stepdetector.xml:system/etc/permissions/android.hardware.sensor.stepdetector.xml \ + frameworks/native/data/etc/android.hardware.telephony.cdma.xml:system/etc/permissions/android.hardware.telephony.cdma.xml \ + frameworks/native/data/etc/android.hardware.telephony.gsm.xml:system/etc/permissions/android.hardware.telephony.gsm.xml \ + frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \ + frameworks/native/data/etc/android.hardware.usb.accessory.xml:system/etc/permissions/android.hardware.usb.accessory.xml \ + frameworks/native/data/etc/android.hardware.usb.host.xml:system/etc/permissions/android.hardware.usb.host.xml \ + frameworks/native/data/etc/android.hardware.vulkan.level-1.xml:system/etc/permissions/android.hardware.vulkan.level.xml \ + frameworks/native/data/etc/android.hardware.vulkan.version-1_0_3.xml:system/etc/permissions/android.hardware.vulkan.version.xml \ + frameworks/native/data/etc/android.hardware.wifi.xml:system/etc/permissions/android.hardware.wifi.xml \ + frameworks/native/data/etc/android.hardware.wifi.direct.xml:system/etc/permissions/android.hardware.wifi.direct.xml \ + frameworks/native/data/etc/android.software.midi.xml:system/etc/permissions/android.software.midi.xml \ + frameworks/native/data/etc/android.software.print.xml:system/etc/permissions/android.software.print.xml \ + frameworks/native/data/etc/android.software.sip.voip.xml:system/etc/permissions/android.software.sip.voip.xml \ + frameworks/native/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml + +# Motorola Camera permissions +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/com.motorola.cameraone.xml:system/etc/permissions/com.motorola.cameraone.xml + +# Screen density +PRODUCT_AAPT_PREF_CONFIG := xxhdpi +PRODUCT_AAPT_CONFIG := normal + +# Dalvik +PRODUCT_PROPERTY_OVERRIDES += \ + dalvik.vm.heapgrowthlimit=192m \ + dalvik.vm.heapsize=384m + +$(call inherit-product, frameworks/native/build/phone-xxhdpi-3072-dalvik-heap.mk) +$(call inherit-product, frameworks/native/build/phone-xxhdpi-3072-hwui-memory.mk) + +# Audio +PRODUCT_PACKAGES += \ + audiod \ + audio.a2dp.default \ + audio.primary.msm8953 \ + audio.r_submix.default \ + audio.usb.default \ + libaudio-resampler \ + libqcomvisualizer \ + libqcomvoiceprocessing \ + libqcompostprocbundle \ + libshim_adsp \ + tinymix + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/audio/audio_effects.conf:system/vendor/etc/audio_effects.conf \ + $(LOCAL_PATH)/audio/audio_output_policy.conf:system/vendor/etc/audio_output_policy.conf \ + $(LOCAL_PATH)/audio/audio_platform_info_extcodec.xml:system/etc/audio_platform_info_extcodec.xml \ + $(LOCAL_PATH)/audio/audio_policy_configuration.xml:system/etc/audio_policy_configuration.xml \ + $(LOCAL_PATH)/audio/mixer_paths_wcd9306.xml:system/etc/mixer_paths_wcd9306.xml + +PRODUCT_COPY_FILES += \ + frameworks/av/services/audiopolicy/config/a2dp_audio_policy_configuration.xml:/system/etc/a2dp_audio_policy_configuration.xml \ + frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:/system/etc/audio_policy_volumes.xml \ + frameworks/av/services/audiopolicy/config/default_volume_tables.xml:/system/etc/default_volume_tables.xml \ + frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:/system/etc/r_submix_audio_policy_configuration.xml \ + frameworks/av/services/audiopolicy/config/usb_audio_policy_configuration.xml:/system/etc/usb_audio_policy_configuration.xml + +# Browser +PRODUCT_PACKAGES += \ + Gello + +# Camera +PRODUCT_PACKAGES += \ + camera.msm8953 \ + libbson \ + libshim_camera \ + Snap + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/camera/msm8953_mot_camera.xml:system/etc/camera/msm8953_mot_camera.xml \ + $(LOCAL_PATH)/configs/camera/ov5693_chromatix.xml:system/etc/camera/ov5693_chromatix.xml \ + $(LOCAL_PATH)/configs/camera/ov16860_chromatix.xml:system/etc/camera/ov16860_chromatix.xml + +# CMActions +PRODUCT_PACKAGES += \ + CMActions + +# Display +PRODUCT_PACKAGES += \ + gralloc.msm8953 \ + copybit.msm8953 \ + hwcomposer.msm8953 \ + memtrack.msm8953 \ + libtinyxml + +# Display Calibration +PRODUCT_PACKAGES += \ + libjni_livedisplay + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/qdcm_calib_data_mipi_mot_cmd_smd_1080p_549.xml:system/etc/qdcm_calib_data_mipi_mot_cmd_smd_1080p_549.xml + +# DRM +PRODUCT_PACKAGES += \ + libprotobuf-cpp-lite + +# Ebtables +PRODUCT_PACKAGES += \ + ebtables \ + ethertypes \ + libebtc + +# Fingerprint +PRODUCT_PACKAGES += \ + fingerprintd + +# For android_filesystem_config.h +PRODUCT_PACKAGES += \ + fs_config_files + +# GPS +#PRODUCT_PACKAGES += \ +# gps.msm8916 + +# IMS +PRODUCT_PACKAGES += \ + libshim_ims + +# IPA Manager +PRODUCT_PACKAGES += \ + ipacm \ + IPACM_cfg.xml + +# IRSC +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/sec_config:system/etc/sec_config + +# Lights +PRODUCT_PACKAGES += \ + lights.msm8953 + +# Media +PRODUCT_PACKAGES += \ + libc2dcolorconvert + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/media_codecs.xml:system/etc/media_codecs.xml \ + $(LOCAL_PATH)/configs/media_codecs_performance.xml:system/etc/media_codecs_performance.xml \ + $(LOCAL_PATH)/configs/media_profiles.xml:system/etc/media_profiles.xml + +PRODUCT_COPY_FILES += \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml + +# NFC +PRODUCT_COPY_FILES += \ + frameworks/base/nfc-extras/com.android.nfc_extras.xml:system/etc/permissions/com.android.nfc_extras.xml + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/libnfc-brcm.conf:system/etc/libnfc-brcm.conf \ + $(LOCAL_PATH)/configs/libnfc-nxp.conf:system/etc/libnfc-nxp.conf \ + $(LOCAL_PATH)/configs/libnfc-nxp_ds.conf:system/etc/libnfc-nxp_ds.conf \ + +PRODUCT_PACKAGES += \ + libnfc \ + libnfc_jni \ + nfc_nci.pn54x.default \ + NfcNci \ + Tag \ + com.android.nfc_extras + +# OMX +PRODUCT_PACKAGES += \ + libOmxAacEnc \ + libOmxAmrEnc \ + libOmxCore \ + libOmxEvrcEnc \ + libOmxQcelp13Enc \ + libOmxVdec \ + libOmxVenc \ + libOmxVidcCommon \ + libstagefrighthw + +# Power +PRODUCT_PACKAGES += \ + power.msm8953 + +# Ramdisk +PRODUCT_PACKAGES += \ + init.mmi.touch.sh \ + init.qcom.bt.sh \ + init.qcom.ril.sh + +PRODUCT_PACKAGES += \ + fstab.qcom \ + init.mmi.boot.sh \ + init.mmi.laser.sh \ + init.mmi.rc \ + init.mmi.usb.rc \ + init.qcom.rc \ + ueventd.qcom.rc + +# RIL +PRODUCT_PACKAGES += \ + librmnetctl \ + libxml2 + +# Thermal +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/thermal-engine-potter.conf:system/etc/thermal-engine-potter.conf + +# Wifi +PRODUCT_PACKAGES += \ + hostapd_default.conf \ + hostapd \ + wpa_supplicant \ + wpa_supplicant.conf + +PRODUCT_PACKAGES += \ + p2p_supplicant_overlay.conf \ + wpa_supplicant_overlay.conf + +PRODUCT_PACKAGES += \ + libcurl \ + libqsap_sdk \ + libQWiFiSoftApCfg \ + tcpdump \ + wcnss_service + +# Wifi Symlinks +PRODUCT_PACKAGES += \ + WCNSS_qcom_cfg.ini \ + WCNSS_qcom_wlan_nv.bin \ + WCNSS_qcom_wlan_nv_Argentina.bin \ + WCNSS_qcom_wlan_nv_Brazil.bin \ + WCNSS_qcom_wlan_nv_India.bin \ + WCNSS_wlan_dictionary.dat + +PRODUCT_COPY_FILES += \ + kernel/motorola/msm8953/drivers/staging/prima/firmware_bin/WCNSS_cfg.dat:system/etc/firmware/wlan/prima/WCNSS_cfg.dat \ + $(LOCAL_PATH)/wifi/WCNSS_qcom_cfg.ini:system/etc/firmware/wlan/prima/WCNSS_qcom_cfg.ini + +PRODUCT_BUILD_PROP_OVERRIDES += BUILD_UTC_DATE=0 + +PRODUCT_GMS_CLIENTID_BASE := android-motorola + +$(call inherit-product, $(SRC_TARGET_DIR)/product/full_base_telephony.mk) +$(call inherit-product, vendor/cm/config/common_full_phone.mk) \ No newline at end of file diff --git a/extract-files.sh b/extract-files.sh new file mode 100644 index 0000000..4002d8d --- /dev/null +++ b/extract-files.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# +# Copyright (C) 2016 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. +# + +set -e + +DEVICE=potter +VENDOR=motorola + +# Load extractutils and do some sanity checks +MY_DIR="${BASH_SOURCE%/*}" +if [[ ! -d "$MY_DIR" ]]; then MY_DIR="$PWD"; fi + +CM_ROOT="$MY_DIR"/../../.. + +HELPER="$CM_ROOT"/vendor/cm/build/tools/extract_utils.sh +if [ ! -f "$HELPER" ]; then + echo "Unable to find helper script at $HELPER" + exit 1 +fi +. "$HELPER" + +if [ $# -eq 0 ]; then + SRC=adb +else + if [ $# -eq 1 ]; then + SRC=$1 + else + echo "$0: bad number of arguments" + echo "" + echo "usage: $0 [PATH_TO_EXPANDED_ROM]" + echo "" + echo "If PATH_TO_EXPANDED_ROM is not specified, blobs will be extracted from" + echo "the device using adb pull." + exit 1 + fi +fi + +# Initialize the helper +setup_vendor "$DEVICE" "$VENDOR" "$CM_ROOT" + +extract "$MY_DIR"/proprietary-files.txt "$SRC" + +"$MY_DIR"/setup-makefiles.sh \ No newline at end of file diff --git a/full_potter.mk b/full_potter.mk index d979b2a..2521968 100644 --- a/full_potter.mk +++ b/full_potter.mk @@ -1,5 +1,5 @@ # -# Copyright (C) 2015 The Android Open-Source Project +# 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. @@ -14,12 +14,11 @@ # limitations under the License. # -# Inherit from those products. Most specific first. -$(call inherit-product, $(SRC_TARGET_DIR)/product/full_base_telephony.mk) +# Inherit from potter device +$(call inherit-product, device/motorola/potter/device.mk) # Device identifier. This must come after all inclusions PRODUCT_DEVICE := potter PRODUCT_NAME := full_potter -PRODUCT_BRAND := motorola -PRODUCT_MODEL := Moto G5 Plus -PRODUCT_MANUFACTURER := motorola \ No newline at end of file + +$(call inherit-product-if-exists, vendor/motorola/potter/potter-vendor.mk) \ No newline at end of file diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h new file mode 100644 index 0000000..7a00c09 --- /dev/null +++ b/include/private/android_filesystem_config.h @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2007 The Android Open Source 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. + */ + +/* This file is used to define the properties of the filesystem +** images generated by build tools (mkbootfs and mkyaffs2image) and +** by the device side of adb. +*/ + +#ifndef _ANDROID_FILESYSTEM_CONFIG_H_ +#define _ANDROID_FILESYSTEM_CONFIG_H_ + +#include +#include +#include + +#if defined(__ANDROID__) +#include +#else +#include +#endif + +#define CAP_MASK_LONG(cap_name) (1ULL << (cap_name)) + +/* This is the master Users and Groups config for the platform. + * DO NOT EVER RENUMBER + */ + +#define AID_ROOT 0 /* traditional unix root user */ + +#define AID_SYSTEM 1000 /* system server */ + +#define AID_RADIO 1001 /* telephony subsystem, RIL */ +#define AID_BLUETOOTH 1002 /* bluetooth subsystem */ +#define AID_GRAPHICS 1003 /* graphics devices */ +#define AID_INPUT 1004 /* input devices */ +#define AID_AUDIO 1005 /* audio devices */ +#define AID_CAMERA 1006 /* camera devices */ +#define AID_LOG 1007 /* log devices */ +#define AID_COMPASS 1008 /* compass device */ +#define AID_MOUNT 1009 /* mountd socket */ +#define AID_WIFI 1010 /* wifi subsystem */ +#define AID_ADB 1011 /* android debug bridge (adbd) */ +#define AID_INSTALL 1012 /* group for installing packages */ +#define AID_MEDIA 1013 /* mediaserver process */ +#define AID_DHCP 1014 /* dhcp client */ +#define AID_SDCARD_RW 1015 /* external storage write access */ +#define AID_VPN 1016 /* vpn system */ +#define AID_KEYSTORE 1017 /* keystore subsystem */ +#define AID_USB 1018 /* USB devices */ +#define AID_DRM 1019 /* DRM server */ +#define AID_MDNSR 1020 /* MulticastDNSResponder (service discovery) */ +#define AID_GPS 1021 /* GPS daemon */ +#define AID_UNUSED1 1022 /* deprecated, DO NOT USE */ +#define AID_MEDIA_RW 1023 /* internal media storage write access */ +#define AID_MTP 1024 /* MTP USB driver access */ +#define AID_UNUSED2 1025 /* deprecated, DO NOT USE */ +#define AID_DRMRPC 1026 /* group for drm rpc */ +#define AID_NFC 1027 /* nfc subsystem */ +#define AID_SDCARD_R 1028 /* external storage read access */ +#define AID_CLAT 1029 /* clat part of nat464 */ +#define AID_LOOP_RADIO 1030 /* loop radio devices */ +#define AID_MEDIA_DRM 1031 /* MediaDrm plugins */ +#define AID_PACKAGE_INFO 1032 /* access to installed package details */ +#define AID_SDCARD_PICS 1033 /* external storage photos access */ +#define AID_SDCARD_AV 1034 /* external storage audio/video access */ +#define AID_SDCARD_ALL 1035 /* access all users external storage */ +#define AID_LOGD 1036 /* log daemon */ +#define AID_SHARED_RELRO 1037 /* creator of shared GNU RELRO files */ +#define AID_DBUS 1038 /* dbus-daemon IPC broker process */ +#define AID_TLSDATE 1039 /* tlsdate unprivileged user */ +#define AID_MEDIA_EX 1040 /* mediaextractor process */ +#define AID_AUDIOSERVER 1041 /* audioserver process */ +#define AID_METRICS_COLL 1042 /* metrics_collector process */ +#define AID_METRICSD 1043 /* metricsd process */ +#define AID_WEBSERV 1044 /* webservd process */ +#define AID_DEBUGGERD 1045 /* debuggerd unprivileged user */ +#define AID_MEDIA_CODEC 1046 /* mediacodec process */ +#define AID_CAMERASERVER 1047 /* cameraserver process */ + +#define AID_SHELL 2000 /* adb and debug shell user */ +#define AID_CACHE 2001 /* cache access */ +#define AID_DIAG 2002 /* access to diagnostic resources */ + +/* The range 2900-2999 is reserved for OEM, and must never be + * used here */ +#define AID_OEM_RESERVED_START 2900 + +#define AID_QCOM_DIAG 2950 /* access to QTI diagnostic resources */ +#define AID_RFS 2951 /* Remote Filesystem for peripheral processors */ +#define AID_RFS_SHARED 2952 /* Shared files for Remote Filesystem for peripheral processors */ + +#define AID_OEM_RESERVED_END 2999 + +/* The 3000 series are intended for use as supplemental group id's only. + * They indicate special Android capabilities that the kernel is aware of. */ +#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */ +#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */ +#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */ +#define AID_NET_RAW 3004 /* can create raw INET sockets */ +#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */ +#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */ +#define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */ +#define AID_NET_BT_STACK 3008 /* bluetooth: access config files */ +#define AID_READPROC 3009 /* Allow /proc read access */ +#define AID_WAKELOCK 3010 /* Allow system wakelock read/write access */ + +#define AID_SENSORS 3011 /* access to /dev/socket/sensor_ctl_socket & QCCI/QCSI */ +#define AID_RFS_OLD 3012 /* DEPRECATED OLD ID FOR RFS, DO NOT USE */ +#define AID_RFS_SHARED_OLD 3013 /* DEPRECATED OLD ID FOR RFS-SHARED */ + +/* The range 5000-5999 is also reserved for OEM, and must never be used here. */ +#define AID_OEM_RESERVED_2_START 5000 +#define AID_OEM_RESERVED_2_END 5999 + +/* Motorola IDs */ +#define AID_MOT_ACCY 9000 /* access to accessory */ +#define AID_MOT_PWRIC 9001 /* power IC */ +#define AID_MOT_USB 9002 /* mot usb */ +#define AID_MOT_DRM 9003 /* can access DRM resource. */ +#define AID_MOT_TCMD 9004 /* mot_tcmd */ +#define AID_MOT_SEC_RTC 9005 /* mot cpcap rtc */ +#define AID_MOT_TOMBSTONE 9006 +#define AID_MOT_TPAPI 9007 /* mot_tpapi */ +#define AID_MOT_SECCLKD 9008 /* mot_secclkd */ +#define AID_MOT_WHISPER 9009 /* Whisper Protocol access */ +#define AID_MOT_CAIF 9010 /* can create CAIF sockets */ +#define AID_MOT_DLNA 9011 /* DLNA native */ +#define AID_MOT_ATVC 9012 /* mot_atvc - This is for use of the ATVC service ONLY */ +#define AID_SPRINT_EXTENSION 9013 /* IKASANTISPRINT-149 sprint extension service */ +#define AID_MOT_DBVC 9014 /* mot_dbvc - This group is used to access DataBlock feature related data */ +#define AID_FINGERP 9015 /* IKFPS-98 Add permission group for fingerprint */ +#define AID_MOT_ESDFS 9016 /* mot_esdfs for ESDFS package list parsing */ +#define AID_POWER 9017 /* power management */ +#define AID_ITSON 9018 /* itson permission */ +#define AID_MOT_DTV 9019 /* dtv */ +#define AID_MOT_MOD 9020 /* can interact with motorola mod HW */ + +#define AID_MOT_SHARED 9323 /* motorola shared uid, IKSWM-342 */ +#define AID_MOT_COMMON 9341 /* motorola common uid, IKSWM-342 */ +/* Motorola IDs */ + +#define AID_EVERYBODY 9997 /* shared between all apps in the same profile */ +#define AID_MISC 9998 /* access to misc storage */ +#define AID_NOBODY 9999 + +#define AID_APP 10000 /* first app user */ + +#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */ +#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */ + +#define AID_USER 100000 /* offset for uid ranges for each user */ + +#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */ +#define AID_SHARED_GID_END 59999 /* start of gids for apps in each user to share */ + +#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES) +/* + * Used in: + * bionic/libc/bionic/stubs.cpp + * external/libselinux/src/android.c + * system/core/logd/LogStatistics.cpp + * system/core/init/ueventd.cpp + * system/core/init/util.cpp + */ +struct android_id_info { + const char *name; + unsigned aid; +}; + +static const struct android_id_info android_ids[] = { + { "root", AID_ROOT, }, + + { "system", AID_SYSTEM, }, + + { "radio", AID_RADIO, }, + { "bluetooth", AID_BLUETOOTH, }, + { "graphics", AID_GRAPHICS, }, + { "input", AID_INPUT, }, + { "audio", AID_AUDIO, }, + { "camera", AID_CAMERA, }, + { "log", AID_LOG, }, + { "compass", AID_COMPASS, }, + { "mount", AID_MOUNT, }, + { "wifi", AID_WIFI, }, + { "adb", AID_ADB, }, + { "install", AID_INSTALL, }, + { "media", AID_MEDIA, }, + { "dhcp", AID_DHCP, }, + { "sdcard_rw", AID_SDCARD_RW, }, + { "vpn", AID_VPN, }, + { "keystore", AID_KEYSTORE, }, + { "usb", AID_USB, }, + { "drm", AID_DRM, }, + { "mdnsr", AID_MDNSR, }, + { "gps", AID_GPS, }, + // AID_UNUSED1 + { "media_rw", AID_MEDIA_RW, }, + { "mtp", AID_MTP, }, + // AID_UNUSED2 + { "drmrpc", AID_DRMRPC, }, + { "nfc", AID_NFC, }, + { "sdcard_r", AID_SDCARD_R, }, + { "clat", AID_CLAT, }, + { "loop_radio", AID_LOOP_RADIO, }, + { "mediadrm", AID_MEDIA_DRM, }, + { "package_info", AID_PACKAGE_INFO, }, + { "sdcard_pics", AID_SDCARD_PICS, }, + { "sdcard_av", AID_SDCARD_AV, }, + { "sdcard_all", AID_SDCARD_ALL, }, + { "logd", AID_LOGD, }, + { "shared_relro", AID_SHARED_RELRO, }, + { "dbus", AID_DBUS, }, + { "tlsdate", AID_TLSDATE, }, + { "mediaex", AID_MEDIA_EX, }, + { "audioserver", AID_AUDIOSERVER, }, + { "metrics_coll", AID_METRICS_COLL }, + { "metricsd", AID_METRICSD }, + { "webserv", AID_WEBSERV }, + { "debuggerd", AID_DEBUGGERD, }, + { "mediacodec", AID_MEDIA_CODEC, }, + { "cameraserver", AID_CAMERASERVER, }, + + { "shell", AID_SHELL, }, + { "cache", AID_CACHE, }, + { "diag", AID_DIAG, }, + + { "qcom_diag", AID_QCOM_DIAG, }, + + { "rfs", AID_RFS, }, + { "rfs_shared", AID_RFS_SHARED, }, + + { "net_bt_admin", AID_NET_BT_ADMIN, }, + { "net_bt", AID_NET_BT, }, + { "inet", AID_INET, }, + { "net_raw", AID_NET_RAW, }, + { "net_admin", AID_NET_ADMIN, }, + { "net_bw_stats", AID_NET_BW_STATS, }, + { "net_bw_acct", AID_NET_BW_ACCT, }, + { "net_bt_stack", AID_NET_BT_STACK, }, + { "readproc", AID_READPROC, }, + { "wakelock", AID_WAKELOCK, }, + { "sensors", AID_SENSORS, }, + + { "rfs_old", AID_RFS_OLD, }, + { "rfs_shared_old", AID_RFS_SHARED_OLD, }, + { "everybody", AID_EVERYBODY, }, + { "misc", AID_MISC, }, + { "nobody", AID_NOBODY, }, + + /* Motorola IDs */ + { "mot_accy", AID_MOT_ACCY, }, + { "mot_pwric", AID_MOT_PWRIC, }, + { "mot_usb", AID_MOT_USB, }, + { "mot_drm", AID_MOT_DRM, }, + { "mot_tcmd", AID_MOT_TCMD, }, + { "mot_sec_rtc", AID_MOT_SEC_RTC, }, + { "mot_tombstone", AID_MOT_TOMBSTONE, }, + { "mot_tpapi", AID_MOT_TPAPI, }, + { "mot_secclkd", AID_MOT_SECCLKD, }, + { "mot_whisper", AID_MOT_WHISPER, }, + { "mot_caif", AID_MOT_CAIF, }, + { "mot_dlna", AID_MOT_DLNA, }, + { "mot_atvc", AID_MOT_ATVC, }, + { "sprint_extension", AID_SPRINT_EXTENSION, }, + { "mot_dbvc", AID_MOT_DBVC, }, + { "fingerp", AID_FINGERP, }, + { "mot_esdfs", AID_MOT_ESDFS, }, + { "power", AID_POWER, }, + { "itson", AID_ITSON, }, + { "mot_dtv", AID_MOT_DTV, }, + { "mot_shared", AID_MOT_SHARED, }, + { "mot_common", AID_MOT_COMMON, }, + { "mot_mod", AID_MOT_MOD, }, + /* Motorola IDs */ +}; + +#define android_id_count \ + (sizeof(android_ids) / sizeof(android_ids[0])) + +struct fs_path_config { + unsigned mode; + unsigned uid; + unsigned gid; + uint64_t capabilities; + const char *prefix; +}; + +/* Rules for directories and files has moved to system/code/libcutils/fs_config.c */ + +__BEGIN_DECLS + +/* + * Used in: + * build/tools/fs_config/fs_config.c + * build/tools/fs_get_stats/fs_get_stats.c + * system/extras/ext4_utils/make_ext4fs_main.c + * external/squashfs-tools/squashfs-tools/android.c + * system/core/cpio/mkbootfs.c + * system/core/adb/file_sync_service.cpp + * system/extras/ext4_utils/canned_fs_config.c + */ +void fs_config(const char *path, int dir, const char *target_out_path, + unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities); + +ssize_t fs_config_generate(char *buffer, size_t length, const struct fs_path_config *pc); + +__END_DECLS + +#endif +#endif diff --git a/init/Android.mk b/init/Android.mk new file mode 100644 index 0000000..45f13d2 --- /dev/null +++ b/init/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := system/core/init +LOCAL_CPPFLAGS := -Wall -DANDROID_TARGET=\"$(TARGET_BOARD_PLATFORM)\" +LOCAL_SRC_FILES := init_potter.cpp +LOCAL_MODULE := libinit_potter + +include $(BUILD_STATIC_LIBRARY) diff --git a/init/init_potter.cpp b/init/init_potter.cpp new file mode 100644 index 0000000..e0f0da1 --- /dev/null +++ b/init/init_potter.cpp @@ -0,0 +1,51 @@ +/* + Copyright (c) 2014, 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 "vendor_init.h" +#include "property_service.h" +#include "log.h" +#include "util.h" + +void vendor_load_properties() +{ + std::string platform = property_get("ro.board.platform"); + if (platform != ANDROID_TARGET) + return; + + std::string sku = property_get("ro.boot.hardware.sku"); + property_set("ro.product.model", sku.c_str()); + + // rmt_storage + std::string device = property_get("ro.boot.device"); + std::string radio = property_get("ro.boot.radio"); + property_set("ro.hw.device", device.c_str()); + property_set("ro.hw.radio", radio.c_str()); +} diff --git a/liblight/Android.mk b/liblight/Android.mk new file mode 100644 index 0000000..10fb4dc --- /dev/null +++ b/liblight/Android.mk @@ -0,0 +1,27 @@ +# +# Copyright (C) 2016 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) +# HAL module implemenation stored in +# hw/..so +include $(CLEAR_VARS) + +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_SRC_FILES := lights.c +LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/liblight/NOTICE b/liblight/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/liblight/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/liblight/lights.c b/liblight/lights.c new file mode 100644 index 0000000..c9ec4de --- /dev/null +++ b/liblight/lights.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2016 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. + * + * Blinking patterns reference: + * https://github.com/MotorolaMobilityLLC/kernel-msm/commit/3b521f965fae990b2a7f13a6fc98fcf0ea50f66b + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +/******************************************************************************/ + + +#define LED_LIGHT_ON 3 +#define LED_LIGHT_OFF 0 + +static pthread_once_t g_init = PTHREAD_ONCE_INIT; +static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; + +char const*const CHARGING_LED_FILE + = "/sys/class/leds/white/brightness"; + +char const*const LCD_FILE + = "/sys/class/leds/lcd-backlight/brightness"; + +/** + * device methods + */ + +void init_globals(void) +{ + // init the mutex + pthread_mutex_init(&g_lock, NULL); +} + +static int +write_int(char const* path, int value) +{ + int fd; + static int already_warned = 0; + + fd = open(path, O_RDWR); + if (fd >= 0) { + char buffer[20]; + int bytes = sprintf(buffer, "%d\n", value); + int amt = write(fd, buffer, bytes); + close(fd); + return amt == -1 ? -errno : 0; + } else { + if (already_warned == 0) { + ALOGE("write_int failed to open %s\n", path); + already_warned = 1; + } + return -errno; + } +} + +static int +is_lit(struct light_state_t const* state) +{ + return state->color & 0x00ffffff; +} + +static int +rgb_to_brightness(struct light_state_t const* state) +{ + int color = state->color & 0x00ffffff; + return ((77*((color>>16)&0x00ff)) + + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; +} + +static int +set_light_backlight(__attribute__((unused)) struct light_device_t* dev, + struct light_state_t const* state) +{ + int err = 0; + int brightness = rgb_to_brightness(state); + pthread_mutex_lock(&g_lock); + err = write_int(LCD_FILE, brightness); + pthread_mutex_unlock(&g_lock); + return err; +} + +static int +set_light_notifications(struct light_device_t* dev, struct light_state_t const* state) +{ + int brightness_level; + int err = 0; + + if (!dev) + return -1; + + pthread_mutex_lock(&g_lock); + + if (is_lit(state)) + brightness_level = LED_LIGHT_ON; + else + brightness_level = LED_LIGHT_OFF; + + err = write_int(CHARGING_LED_FILE, brightness_level); + + pthread_mutex_unlock(&g_lock); + return err; +} + + + +/** Close the lights device */ +static int +close_lights(struct light_device_t *dev) +{ + if (dev) { + free(dev); + } + return 0; +} + + +/******************************************************************************/ + +/** + * module methods + */ + +/** Open a new instance of a lights device using name */ +static int open_lights(const struct hw_module_t* module, char const* name, + struct hw_device_t** device) +{ + int (*set_light)(struct light_device_t* dev, + struct light_state_t const* state); + + if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) + set_light = set_light_backlight; + else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) + set_light = set_light_notifications; + else + return -EINVAL; + + pthread_once(&g_init, init_globals); + + struct light_device_t *dev = malloc(sizeof(struct light_device_t)); + memset(dev, 0, sizeof(*dev)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = (struct hw_module_t*)module; + dev->common.close = (int (*)(struct hw_device_t*))close_lights; + dev->set_light = set_light; + + *device = (struct hw_device_t*)dev; + return 0; +} + +static struct hw_module_methods_t lights_module_methods = { + .open = open_lights, +}; + +/* + * The lights Module + */ +struct hw_module_t HAL_MODULE_INFO_SYM = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = LIGHTS_HARDWARE_MODULE_ID, + .name = "MSM8953 lights Module", + .author = "Google, Inc., Alberto97, dhacker29", + .methods = &lights_module_methods, +}; diff --git a/libshims/Android.mk b/libshims/Android.mk new file mode 100644 index 0000000..0e56d0f --- /dev/null +++ b/libshims/Android.mk @@ -0,0 +1,41 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# Copyright (C) 2017 The LineageOS 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) + +# ADSP +include $(CLEAR_VARS) +LOCAL_C_INCLUDES := external/tinyalsa/include +LOCAL_SRC_FILES := mixer.c +LOCAL_MODULE := libshim_adsp +LOCAL_MODULE_TAGS := optional +include $(BUILD_SHARED_LIBRARY) + +# Camera +include $(CLEAR_VARS) +LOCAL_SRC_FILES := GraphicBuffer.cpp +LOCAL_SHARED_LIBRARIES := libui +LOCAL_MODULE := libshim_camera +LOCAL_MODULE_TAGS := optional +include $(BUILD_SHARED_LIBRARY) + +# IMS +include $(CLEAR_VARS) +LOCAL_SRC_FILES := MediaBuffer.c +LOCAL_SHARED_LIBRARIES := libstagefright_foundation +LOCAL_MODULE := libshim_ims +LOCAL_MODULE_TAGS := optional +include $(BUILD_SHARED_LIBRARY) diff --git a/libshims/GraphicBuffer.cpp b/libshims/GraphicBuffer.cpp new file mode 100644 index 0000000..2ccb650 --- /dev/null +++ b/libshims/GraphicBuffer.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 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. + */ + +#include + +// GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, +// uint32_t inUsage, std::string requestorName = ""); +extern "C" void _ZN7android13GraphicBufferC1EjjijNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE( + uint32_t inWidth, uint32_t inHeight, int inFormat, uint32_t inUsage, + std::string requestorName); + +//libmot_gpu_mapper.so +extern "C" void _ZN7android13GraphicBufferC1Ejjij( + uint32_t inWidth, uint32_t inHeight, int inFormat, uint32_t inUsage) { + std::string requestorName = ""; + _ZN7android13GraphicBufferC1EjjijNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE( + inWidth, inHeight, inFormat, inUsage, requestorName); +} diff --git a/libshims/MediaBuffer.c b/libshims/MediaBuffer.c new file mode 100644 index 0000000..fe76d0a --- /dev/null +++ b/libshims/MediaBuffer.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2016 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. + */ + +/* TODO: Actually provide implementations for these function! */ + +void _ZNK7android11MediaBuffer8refcountEv() {} diff --git a/libshims/mixer.c b/libshims/mixer.c new file mode 100644 index 0000000..58735b9 --- /dev/null +++ b/libshims/mixer.c @@ -0,0 +1,620 @@ +/* mixer.c +** +** Copyright 2011, The Android Open Source Project +** +** 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 Android Open Source Project 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 BY The Android Open Source Project ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project 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 +#include +#include +#include +#include +#include + +#include + +#include +#define __force +#define __bitwise +#define __user +#include + +#include + +struct mixer_ctl { + struct mixer *mixer; + struct snd_ctl_elem_info info; + char **ename; +}; + +struct mixer { + int fd; + struct snd_ctl_card_info card_info; + struct mixer_ctl *ctl; + unsigned int count; +}; + +static void mixer_cleanup_control(struct mixer_ctl *ctl) +{ + unsigned int m; + + if (ctl->ename) { + unsigned int max = ctl->info.value.enumerated.items; + for (m = 0; m < max; m++) + free(ctl->ename[m]); + free(ctl->ename); + } +} + +void mixer_close(struct mixer *mixer) +{ + unsigned int n; + + if (!mixer) + return; + + if (mixer->fd >= 0) + close(mixer->fd); + + if (mixer->ctl) { + for (n = 0; n < mixer->count; n++) + mixer_cleanup_control(&mixer->ctl[n]); + free(mixer->ctl); + } + + free(mixer); + + /* TODO: verify frees */ +} + +static void *mixer_realloc_z(void *ptr, size_t curnum, size_t newnum, size_t size) +{ + int8_t *newp; + + newp = realloc(ptr, size * newnum); + if (!newp) + return NULL; + + memset(newp + (curnum * size), 0, (newnum-curnum) * size); + return newp; +} + +static int add_controls(struct mixer *mixer) +{ + struct snd_ctl_elem_list elist; + struct snd_ctl_elem_info tmp; + struct snd_ctl_elem_id *eid = NULL; + struct snd_ctl_elem_info *info; + struct mixer_ctl *ctl; + int fd = mixer->fd; + const unsigned int old_count = mixer->count; + unsigned int extra_count; + unsigned int n, m; + + memset(&elist, 0, sizeof(elist)); + if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0) + goto fail; + + if (old_count == elist.count) + return 0; /* no new controls return unchanged */ + + ctl = mixer_realloc_z(mixer->ctl, old_count, elist.count, + sizeof(struct mixer_ctl)); + if (!ctl) + goto fail; + mixer->ctl = ctl; + + extra_count = elist.count - old_count; /* controls we haven't seen before */ + eid = calloc(extra_count, sizeof(struct snd_ctl_elem_id)); + if (!eid) + goto fail; + + /* Add all controls we haven't seen before + * ALSA drivers are not allowed to remove or re-order controls that + * have already been created so we know that any new controls must + * be after the ones we have already collected + */ + elist.offset = old_count; /* first control we haven't seen yet */ + elist.space = extra_count; + elist.pids = eid; + if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0) + goto fail; + + for (n = old_count; n < old_count + extra_count; n++) { + struct snd_ctl_elem_info *ei = &mixer->ctl[n].info; + ei->id.numid = eid[n - old_count].numid; + if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0) + goto fail_extend; + ctl[n].mixer = mixer; + if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { + char **enames = calloc(ei->value.enumerated.items, sizeof(char*)); + if (!enames) + goto fail_extend; + ctl[n].ename = enames; + for (m = 0; m < ei->value.enumerated.items; m++) { + memset(&tmp, 0, sizeof(tmp)); + tmp.id.numid = ei->id.numid; + tmp.value.enumerated.item = m; + if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0) + goto fail_extend; + enames[m] = strdup(tmp.value.enumerated.name); + if (!enames[m]) + goto fail_extend; + } + } + } + + mixer->count = old_count + extra_count; + free(eid); + return 0; + +fail_extend: + /* cleanup the control we failed on but leave the ones that were already + * added. Also no advantage to shrinking the resized memory block, we + * might want to extend the controls again later + */ + mixer_cleanup_control(&ctl[n]); + + mixer->count = n; /* keep controls we successfully added */ + /* fall through... */ +fail: + free(eid); + return -1; +} + +struct mixer *mixer_open(unsigned int card) +{ + struct mixer *mixer = NULL; + int fd; + char fn[256]; + + snprintf(fn, sizeof(fn), "/dev/snd/controlC%u", card); + fd = open(fn, O_RDWR); + if (fd < 0) + return 0; + + mixer = calloc(1, sizeof(*mixer)); + if (!mixer) + goto fail; + + if (ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info) < 0) + goto fail; + + mixer->fd = fd; + + if (add_controls(mixer) != 0) + goto fail; + + return mixer; + +fail: + if (mixer) + mixer_close(mixer); + else if (fd >= 0) + close(fd); + return NULL; +} + +int mixer_update_ctls(struct mixer *mixer) +{ + if (!mixer) + return 0; + + return add_controls(mixer); +} + +const char *mixer_get_name(struct mixer *mixer) +{ + return (const char *)mixer->card_info.name; +} + +unsigned int mixer_get_num_ctls(struct mixer *mixer) +{ + if (!mixer) + return 0; + + return mixer->count; +} + +struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id) +{ + if (mixer && (id < mixer->count)) + return mixer->ctl + id; + + return NULL; +} + +struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name) +{ + unsigned int n; + struct mixer_ctl *ctl = mixer->ctl; + + if (!mixer) + return NULL; + + for (n = 0; n < mixer->count; n++) + if (!strcmp(name, (char*) ctl[n].info.id.name)) + return &ctl[n]; + + return NULL; +} + +void mixer_ctl_update(struct mixer_ctl *ctl) +{ + ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info); +} + +const char *mixer_ctl_get_name(struct mixer_ctl *ctl) +{ + if (!ctl) + return NULL; + + return (const char *)ctl->info.id.name; +} + +enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl) +{ + if (!ctl) + return MIXER_CTL_TYPE_UNKNOWN; + + switch (ctl->info.type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return MIXER_CTL_TYPE_BOOL; + case SNDRV_CTL_ELEM_TYPE_INTEGER: return MIXER_CTL_TYPE_INT; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return MIXER_CTL_TYPE_ENUM; + case SNDRV_CTL_ELEM_TYPE_BYTES: return MIXER_CTL_TYPE_BYTE; + case SNDRV_CTL_ELEM_TYPE_IEC958: return MIXER_CTL_TYPE_IEC958; + case SNDRV_CTL_ELEM_TYPE_INTEGER64: return MIXER_CTL_TYPE_INT64; + default: return MIXER_CTL_TYPE_UNKNOWN; + }; +} + +const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl) +{ + if (!ctl) + return ""; + + switch (ctl->info.type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL"; + case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT"; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM"; + case SNDRV_CTL_ELEM_TYPE_BYTES: return "BYTE"; + case SNDRV_CTL_ELEM_TYPE_IEC958: return "IEC958"; + case SNDRV_CTL_ELEM_TYPE_INTEGER64: return "INT64"; + default: return "Unknown"; + }; +} + +unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl) +{ + if (!ctl) + return 0; + + return ctl->info.count; +} + +static int percent_to_int(struct snd_ctl_elem_info *ei, int percent) +{ + int range; + + if (percent > 100) + percent = 100; + else if (percent < 0) + percent = 0; + + range = (ei->value.integer.max - ei->value.integer.min); + + return ei->value.integer.min + (range * percent) / 100; +} + +static int int_to_percent(struct snd_ctl_elem_info *ei, int value) +{ + int range = (ei->value.integer.max - ei->value.integer.min); + + if (range == 0) + return 0; + + return ((value - ei->value.integer.min) / range) * 100; +} + +int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id) +{ + if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER)) + return -EINVAL; + + return int_to_percent(&ctl->info, mixer_ctl_get_value(ctl, id)); +} + +int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent) +{ + if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER)) + return -EINVAL; + + return mixer_ctl_set_value(ctl, id, percent_to_int(&ctl->info, percent)); +} + +int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id) +{ + struct snd_ctl_elem_value ev; + int ret; + + if (!ctl || (id >= ctl->info.count)) + return -EINVAL; + + memset(&ev, 0, sizeof(ev)); + ev.id.numid = ctl->info.id.numid; + ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev); + if (ret < 0) + return ret; + + switch (ctl->info.type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + return !!ev.value.integer.value[id]; + + case SNDRV_CTL_ELEM_TYPE_INTEGER: + return ev.value.integer.value[id]; + + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + return ev.value.enumerated.item[id]; + + case SNDRV_CTL_ELEM_TYPE_BYTES: + return ev.value.bytes.data[id]; + + default: + return -EINVAL; + } + + return 0; +} + +int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count) +{ + struct snd_ctl_elem_value ev; + int ret = 0; + size_t size; + void *source; + + if (!ctl || (count > ctl->info.count) || !count || !array) + return -EINVAL; + + memset(&ev, 0, sizeof(ev)); + ev.id.numid = ctl->info.id.numid; + + switch (ctl->info.type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + case SNDRV_CTL_ELEM_TYPE_INTEGER: + ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev); + if (ret < 0) + return ret; + size = sizeof(ev.value.integer.value[0]); + source = ev.value.integer.value; + break; + + case SNDRV_CTL_ELEM_TYPE_BYTES: + /* check if this is new bytes TLV */ + if (ctl->info.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) { + struct snd_ctl_tlv *tlv; + int ret; + + if (count > SIZE_MAX - sizeof(*tlv)) + return -EINVAL; + tlv = calloc(1, sizeof(*tlv) + count); + if (!tlv) + return -ENOMEM; + tlv->numid = ctl->info.id.numid; + tlv->length = count; + ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_READ, tlv); + + source = tlv->tlv; + memcpy(array, source, count); + + free(tlv); + + return ret; + } else { + ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev); + if (ret < 0) + return ret; + size = sizeof(ev.value.bytes.data[0]); + source = ev.value.bytes.data; + break; + } + + case SNDRV_CTL_ELEM_TYPE_IEC958: + size = sizeof(ev.value.iec958); + source = &ev.value.iec958; + break; + + default: + return -EINVAL; + } + + memcpy(array, source, size * count); + + return 0; +} + +int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value) +{ + struct snd_ctl_elem_value ev; + int ret; + + if (!ctl || (id >= ctl->info.count)) + return -EINVAL; + + memset(&ev, 0, sizeof(ev)); + ev.id.numid = ctl->info.id.numid; + ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev); + if (ret < 0) + return ret; + + switch (ctl->info.type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + ev.value.integer.value[id] = !!value; + break; + + case SNDRV_CTL_ELEM_TYPE_INTEGER: { + int min = mixer_ctl_get_range_min(ctl); + int max = mixer_ctl_get_range_max(ctl); + if (min < max && (value < min || value > max)) + return -EINVAL; + ev.value.integer.value[id] = value; + break; + } + + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + if (value < 0 || (value >= 0 && (unsigned int)value >= mixer_ctl_get_num_enums(ctl))) + return -EINVAL; + ev.value.enumerated.item[id] = value; + break; + + case SNDRV_CTL_ELEM_TYPE_BYTES: + ev.value.bytes.data[id] = value; + break; + + default: + return -EINVAL; + } + + return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev); +} + +int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count) +{ + struct snd_ctl_elem_value ev; + size_t size; + void *dest; + + if (!ctl || (count > ctl->info.count) || !count || !array) + return -EINVAL; + + memset(&ev, 0, sizeof(ev)); + ev.id.numid = ctl->info.id.numid; + + switch (ctl->info.type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + case SNDRV_CTL_ELEM_TYPE_INTEGER: + size = sizeof(ev.value.integer.value[0]); + dest = ev.value.integer.value; + break; + + case SNDRV_CTL_ELEM_TYPE_BYTES: + /* check if this is new bytes TLV */ + if (ctl->info.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) { + struct snd_ctl_tlv *tlv; + int ret = 0; + if (count > SIZE_MAX - sizeof(*tlv)) + return -EINVAL; + tlv = calloc(1, sizeof(*tlv) + count); + if (!tlv) + return -ENOMEM; + tlv->numid = ctl->info.id.numid; + tlv->length = count; + memcpy(tlv->tlv, array, count); + + ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_WRITE, tlv); + free(tlv); + + return ret; + } else { + size = sizeof(ev.value.bytes.data[0]); + dest = ev.value.bytes.data; + } + break; + + case SNDRV_CTL_ELEM_TYPE_IEC958: + size = sizeof(ev.value.iec958); + dest = &ev.value.iec958; + break; + + default: + return -EINVAL; + } + + memcpy(dest, array, size * count); + + return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev); +} + +int mixer_ctl_get_range_min(struct mixer_ctl *ctl) +{ + if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER)) + return -EINVAL; + + return ctl->info.value.integer.min; +} + +int mixer_ctl_get_range_max(struct mixer_ctl *ctl) +{ + if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER)) + return -EINVAL; + + return ctl->info.value.integer.max; +} + +unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl) +{ + if (!ctl) + return 0; + + return ctl->info.value.enumerated.items; +} + +const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl, + unsigned int enum_id) +{ + if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) || + (enum_id >= ctl->info.value.enumerated.items)) + return NULL; + + return (const char *)ctl->ename[enum_id]; +} + +int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string) +{ + unsigned int i, num_enums; + struct snd_ctl_elem_value ev; + int ret; + + if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_ENUMERATED)) + return -EINVAL; + + num_enums = ctl->info.value.enumerated.items; + for (i = 0; i < num_enums; i++) { + if (!strcmp(string, ctl->ename[i])) { + memset(&ev, 0, sizeof(ev)); + ev.value.enumerated.item[0] = i; + ev.id.numid = ctl->info.id.numid; + ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev); + if (ret < 0) + return ret; + return 0; + } + } + + return -EINVAL; +} + diff --git a/lineage.dependencies b/lineage.dependencies new file mode 100644 index 0000000..ead4688 --- /dev/null +++ b/lineage.dependencies @@ -0,0 +1,18 @@ +[ + { + "repository": "android_kernel_motorola_msm8953", + "target_path": "kernel/motorola/msm8953" + }, + { + "repository": "android_external_bson", + "target_path": "external/bson" + }, + { + "repository": "android_device_qcom_common", + "target_path": "device/qcom/common" + }, + { + "repository": "android_packages_resources_devicesettings", + "target_path": "packages/resources/devicesettings" + } +] diff --git a/lineage.mk b/lineage.mk new file mode 100644 index 0000000..6a26d2d --- /dev/null +++ b/lineage.mk @@ -0,0 +1,34 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# Copyright (C) 2017 The LineageOS 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. + +$(call inherit-product, device/motorola/potter/full_potter.mk) + +# Boot animation +TARGET_SCREEN_WIDTH := 1080 +TARGET_SCREEN_HEIGHT := 1920 + +## Device identifier. This must come after all inclusions +PRODUCT_DEVICE := potter +PRODUCT_NAME := lineage_potter +PRODUCT_BRAND := motorola +PRODUCT_MANUFACTURER := motorola + +PRODUCT_SYSTEM_PROPERTY_BLACKLIST := ro.product.model + +PRODUCT_BUILD_PROP_OVERRIDES += \ + BUILD_FINGERPRINT=motorola/potter/potter:7.0/NPN25.137-15/1:user/release-keys \ + PRIVATE_BUILD_DESC="potter-7.0/NPN25.137-15/1:user/release-keys \ + PRODUCT_NAME="Moto G5 Plus" \ No newline at end of file diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml new file mode 100644 index 0000000..0f73e46 --- /dev/null +++ b/overlay/frameworks/base/core/res/res/values/config.xml @@ -0,0 +1,288 @@ + + + + + + + true + + + 88 + + + + 5 + 10 + 40 + 100 + 325 + 1250 + 3500 + 10000 + 20000 + 30000 + + + + + + 6 + 11 + 30 + 59 + 69 + 92 + 118 + 155 + 222 + 255 + + + + + 0 + 30 + 15 + 30 + + + + + 35 + + + + + 25 + + + + + 0 + 15 + 30 + 15 + + + + + "rndis\\d" + + + + + "wlan0" + + + + + "bnep\\d" + "bt-pan" + + + + + + 0 + 1 + 4 + 5 + 7 + + + + + lte:524288,1048576,8388608,262144,524288,4194304 + lte_ca:524288,1048576,8388608,262144,524288,4194304 + umts:131072,262144,1452032,4096,16384,399360 + hspa:131072,262144,1452032,4096,16384,399360 + hsupa:131072,262144,1452032,4096,16384,399360 + hsdpa:131072,262144,1452032,4096,16384,399360 + hspap:131072,262144,1452032,4096,16384,399360 + edge:16384,32768,131072,4096,16384,65536 + gprs:4096,8192,24576,4096,8192,24576 + evdo:131072,262144,1048576,4096,16384,524288 + ehrpd:4094,87380,1048576,4096,16384,262144 + + + + 131072,262144,3145728,4096,221184,3145728 + + + true + + + 3300 + + + + true + + + true + + + true + + + true + + + true + + + true + + + + XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin + XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin + XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin + NTP_SERVER=north-america.pool.ntp.org + SUPL_MODE=0 + SUPL_HOST=NONE + SUPL_PORT=7275 + SUPL_VER=0x20000 + LPP_PROFILE=3 + NMEA_PROVIDER=0 + A_GLONASS_POS_PROTOCOL_SELECT=0 + ERR_ESTIMATE=0 + INTERMEDIATE_POS=0 + SUPL_ES=0 + GPS_LOCK=2 + + + + 4 + + + true + + + true + + + true + + + 64 + + + 64 + + + 17 + + + com.android.systemui/com.android.systemui.doze.DozeService + + + true + + + true + + + GSM | WCDMA | LTE | CDMA | EVDO + + + true + + + true + + diff --git a/overlay/frameworks/base/core/res/res/xml/power_profile.xml b/overlay/frameworks/base/core/res/res/xml/power_profile.xml new file mode 100644 index 0000000..fc3895c --- /dev/null +++ b/overlay/frameworks/base/core/res/res/xml/power_profile.xml @@ -0,0 +1,62 @@ + + + 0 + 103 + 175 + 30 + 1 + 1 + 100 + 24 + 129 + 108 + 70 + 120 + 13 + + 5 + 5 + + + 2 + 2 + + + 652800 + 1036800 + 1401600 + 1689600 + 1843200 + 1958400 + 2016000 + + + 41 + 56 + 67 + 87 + 95 + 106 + 112 + + + 652800 + 1036800 + 1401600 + 1689600 + 1843200 + 1958400 + 2016000 + + + 41 + 56 + 67 + 87 + 95 + 106 + 112 + + 4 + 13 + diff --git a/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml b/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml new file mode 100644 index 0000000..85c9179 --- /dev/null +++ b/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml @@ -0,0 +1,22 @@ + + + + + true + diff --git a/overlay/frameworks/base/packages/SystemUI/res/values/config.xml b/overlay/frameworks/base/packages/SystemUI/res/values/config.xml new file mode 100644 index 0000000..cc3ba22 --- /dev/null +++ b/overlay/frameworks/base/packages/SystemUI/res/values/config.xml @@ -0,0 +1,28 @@ + + + + + + + + true + + + diff --git a/overlay/packages/apps/Dialer/res/values/config.xml b/overlay/packages/apps/Dialer/res/values/config.xml new file mode 100644 index 0000000..493fcbe --- /dev/null +++ b/overlay/packages/apps/Dialer/res/values/config.xml @@ -0,0 +1,20 @@ + + + + true + diff --git a/overlay/packages/apps/Settings/res/values/config.xml b/overlay/packages/apps/Settings/res/values/config.xml new file mode 100644 index 0000000..b70703d --- /dev/null +++ b/overlay/packages/apps/Settings/res/values/config.xml @@ -0,0 +1,30 @@ + + + + + + + true + + + 1 + + diff --git a/overlay/packages/apps/Settings/res/values/dimens.xml b/overlay/packages/apps/Settings/res/values/dimens.xml new file mode 100644 index 0000000..ceb7a97 --- /dev/null +++ b/overlay/packages/apps/Settings/res/values/dimens.xml @@ -0,0 +1,23 @@ + + + + + + + 5dp + 95% + + diff --git a/overlay/packages/apps/Snap/res/values/config.xml b/overlay/packages/apps/Snap/res/values/config.xml new file mode 100644 index 0000000..278ce83 --- /dev/null +++ b/overlay/packages/apps/Snap/res/values/config.xml @@ -0,0 +1,31 @@ + + + + + + false + + + false + + + true + + + true + + diff --git a/overlay/packages/apps/Snap/res/values/qcomstrings.xml b/overlay/packages/apps/Snap/res/values/qcomstrings.xml new file mode 100644 index 0000000..c614376 --- /dev/null +++ b/overlay/packages/apps/Snap/res/values/qcomstrings.xml @@ -0,0 +1,22 @@ + + + + + false + enable + on + diff --git a/overlay/packages/services/Telephony/res/values/config.xml b/overlay/packages/services/Telephony/res/values/config.xml new file mode 100644 index 0000000..3dfeabf --- /dev/null +++ b/overlay/packages/services/Telephony/res/values/config.xml @@ -0,0 +1,26 @@ + + + + + + true + + + true + + diff --git a/overlay/vendor/cmsdk/cm/res/res/values/config.xml b/overlay/vendor/cmsdk/cm/res/res/values/config.xml new file mode 100644 index 0000000..83a217e --- /dev/null +++ b/overlay/vendor/cmsdk/cm/res/res/values/config.xml @@ -0,0 +1,50 @@ + + + + + + + 0 + + + + Standard:standard + Vibrant:dynamic + Comfort:astronomy + + + + true + + diff --git a/proprietary-files.txt b/proprietary-files.txt new file mode 100644 index 0000000..2b1ac3d --- /dev/null +++ b/proprietary-files.txt @@ -0,0 +1,523 @@ +# Proprietary files for potter + +# ADSP +bin/adspd +bin/adsprpcd +lib/libadspd.so +vendor/lib/libadsprpc.so +vendor/lib/libadsp_default_listener.so +vendor/lib/libmdsprpc.so +vendor/lib/rfsa/adsp/libapps_mem_heap.so +vendor/lib/rfsa/adsp/libdspCV_skel.so +vendor/lib/rfsa/adsp/libfastcvadsp.so +vendor/lib/rfsa/adsp/libfastcvadsp_skel.so +vendor/lib/rfsa/adsp/libobjectMattingApp_skel.so +vendor/lib/rfsa/adsp/libscveBlobDescriptor_skel.so +vendor/lib/rfsa/adsp/libscveCleverCapture_skel.so +vendor/lib/rfsa/adsp/libscveObjectSegmentation_skel.so +vendor/lib/rfsa/adsp/libscveT2T_skel.so +vendor/lib/rfsa/adsp/libscveTextReco_skel.so + +# Audio +etc/acdbdata/Bluetooth_cal.acdb +etc/acdbdata/General_cal.acdb +etc/acdbdata/Global_cal.acdb +etc/acdbdata/Handset_cal.acdb +etc/acdbdata/Hdmi_cal.acdb +etc/acdbdata/Headset_cal.acdb +etc/acdbdata/Speaker_cal.acdb +vendor/lib/libacdb-fts.so +vendor/lib/libacdbloader.so +vendor/lib/libacdbmapper.so +vendor/lib/libacdbrtac.so +vendor/lib/libadiertac.so +vendor/lib/libaudcal.so +vendor/lib/libvoice-svc.so + +# Audio firmware +etc/firmware/marley-dsp1-ultrasound.wmfw +etc/firmware/marley-dsp2-aov-frontend.wmfw +etc/firmware/marley-dsp3-aov-control.wmfw + +# Bluetooth +bin/btnvtool +bin/hci_qcomm_init +vendor/lib/libaptX-1.0.0-rel-Android21-ARMv7A.so +vendor/lib/libaptXScheduler.so +vendor/lib/libbtnv.so + +# Camera +bin/mm-qcamera-daemon +lib/hw/camera.msm8953.so:lib/hw/camera.vendor.msm8953.so +lib/hw/camera.rc.so +lib/libadvalgcore.so +lib/libarcsoft_beautyshot.so +lib/libcamerabgprocservice.so +lib/libfamily_photo.so +lib/libjscore.so +lib/libjustshoot.so +lib/libmbs.so +lib/libmmcamera_interface.so +lib/libmmjpeg_interface.so +lib/libmm-qcamera.so +lib/libmodmanager.so +lib/libmorpho_image_stabilizer4.so +lib/libmot_afd.so +lib/libmotimager_utils.so +lib/libmot_lux_standardization.so +lib/libmot-qc-fd-offline.so +lib/lib_motsensorlistener.so +lib/lib_mottof.so +lib/libmpbase.so +lib/libqomx_core.so +vendor/lib/libactuator_mot_lc898212xd.so +vendor/lib/libcamerabgproc-jni.so +vendor/lib/libchromaflash.so +vendor/lib/libfastcvopt.so +vendor/lib/libflash_pmic.so +vendor/lib/libflash_sky81298.so +vendor/lib/libjpegdhw.so +vendor/lib/libjpegehw.so +vendor/lib/libmmcamera2_c2d_module.so +vendor/lib/libmmcamera2_cpp_module.so +vendor/lib/libmmcamera2_dcrf.so +vendor/lib/libmmcamera2_frame_algorithm.so +vendor/lib/libmmcamera2_iface_modules.so +vendor/lib/libmmcamera2_imglib_modules.so +vendor/lib/libmmcamera2_isp_modules.so +vendor/lib/libmmcamera2_is.so +vendor/lib/libmmcamera2_mct.so +vendor/lib/libmmcamera2_pp_buf_mgr.so +vendor/lib/libmmcamera2_pproc_modules.so +vendor/lib/libmmcamera2_q3a_core.so +vendor/lib/libmmcamera2_sensor_modules.so +vendor/lib/libmmcamera2_stats_algorithm.so +vendor/lib/libmmcamera2_stats_modules.so +vendor/lib/libmmcamera_cac3_lib.so +vendor/lib/libmmcamera_chromaflash_lib.so +vendor/lib/libmmcamera_dbg.so +vendor/lib/libmmcamera_dcrf_lib.so +vendor/lib/libmmcamera_dummyalgo.so +vendor/lib/libmmcamera_eebinparse.so +vendor/lib/libmmcamera_eeprom_util.so +vendor/lib/libmmcamera_eztune_module.so +vendor/lib/libmmcamera_facedetection_lib.so +vendor/lib/libmmcamera_faceproc.so +vendor/lib/libmmcamera_hdr_gb_lib.so +vendor/lib/libmmcamera_imglib.so +vendor/lib/libmmcamera_isp_abf40.so +vendor/lib/libmmcamera_isp_bcc40.so +vendor/lib/libmmcamera_isp_be_stats44.so +vendor/lib/libmmcamera_isp_bf_stats47.so +vendor/lib/libmmcamera_isp_bg_stats44.so +vendor/lib/libmmcamera_isp_bhist_stats44.so +vendor/lib/libmmcamera_isp_bpc40.so +vendor/lib/libmmcamera_isp_chroma_enhan40.so +vendor/lib/libmmcamera_isp_chroma_suppress40.so +vendor/lib/libmmcamera_isp_clamp_encoder40.so +vendor/lib/libmmcamera_isp_clamp_video40.so +vendor/lib/libmmcamera_isp_clamp_viewfinder40.so +vendor/lib/libmmcamera_isp_color_correct40.so +vendor/lib/libmmcamera_isp_color_xform_encoder40.so +vendor/lib/libmmcamera_isp_color_xform_viewfinder40.so +vendor/lib/libmmcamera_isp_cs_stats44.so +vendor/lib/libmmcamera_isp_demosaic40.so +vendor/lib/libmmcamera_isp_demux40.so +vendor/lib/libmmcamera_isp_fovcrop_encoder40.so +vendor/lib/libmmcamera_isp_fovcrop_viewfinder40.so +vendor/lib/libmmcamera_isp_gamma40.so +vendor/lib/libmmcamera_isp_ihist_stats44.so +vendor/lib/libmmcamera_isp_linearization40.so +vendor/lib/libmmcamera_isp_ltm44.so +vendor/lib/libmmcamera_isp_luma_adaptation40.so +vendor/lib/libmmcamera_isp_mce40.so +vendor/lib/libmmcamera_isp_mesh_rolloff40.so +vendor/lib/libmmcamera_isp_rs_stats44.so +vendor/lib/libmmcamera_isp_scaler_encoder44.so +vendor/lib/libmmcamera_isp_scaler_viewfinder44.so +vendor/lib/libmmcamera_isp_sce40.so +vendor/lib/libmmcamera_isp_sub_module.so +vendor/lib/libmmcamera_isp_template.so +vendor/lib/libmmcamera_isp_wb40.so +vendor/lib/libmmcamera_llvd.so +vendor/lib/libmmcamera_optizoom_lib.so +vendor/lib/libmmcamera_ov16860_eeprom.so +vendor/lib/libmmcamera_ov16860_pdaf.so +vendor/lib/libmmcamera_ov16860.so +vendor/lib/libmmcamera_ov5693_eeprom.so +vendor/lib/libmmcamera_ov5693.so +vendor/lib/libmmcamera_ovpdaf.so +vendor/lib/libmmcamera_paaf_lib.so +vendor/lib/libmmcamera_pdafcamif.so +vendor/lib/libmmcamera_pdaf.so +vendor/lib/libmmcamera_ppbase_module.so +vendor/lib/libmmcamera_ppeiscore.so +vendor/lib/libmmcamera_stillmore_lib.so +vendor/lib/libmmcamera_sw2d_lib.so +vendor/lib/libmmcamera_thread_services.so +vendor/lib/libmmcamera_tintless_algo.so +vendor/lib/libmmcamera_tintless_bg_pca_algo.so +vendor/lib/libmmcamera_trueportrait_lib.so +vendor/lib/libmmcamera_ubifocus_lib.so +vendor/lib/libmmcamera_vstab_module.so +vendor/lib/libmmjpeg.so +vendor/lib/libmmqjpeg_codec.so +vendor/lib/libmmqjpegdma.so +vendor/lib/libmmsw_detail_enhancement.so +vendor/lib/libmmsw_math.so +vendor/lib/libmmsw_opencl.so +vendor/lib/libmmsw_platform.so +vendor/lib/libmot_gpu_mapper.so +vendor/lib/libmotocalibration.so +vendor/lib/liboptizoom.so +vendor/lib/libqomx_jpegdec.so +vendor/lib/libqomx_jpegenc.so +vendor/lib/libseemore.so +vendor/lib/libtrueportrait.so +vendor/lib/libts_detected_face_hal.so +vendor/lib/libts_face_beautify_hal.so +vendor/lib/libubifocus.so + +# Chromatix +vendor/lib/libchromatix_ov5693_common.so +vendor/lib/libchromatix_ov5693_cpp_hfr_120.so +vendor/lib/libchromatix_ov5693_cpp_liveshot.so +vendor/lib/libchromatix_ov5693_cpp_snapshot.so +vendor/lib/libchromatix_ov5693_cpp_video.so +vendor/lib/libchromatix_ov5693_default_video.so +vendor/lib/libchromatix_ov5693_default_video_3a.so +vendor/lib/libchromatix_ov5693_hfr_120.so +vendor/lib/libchromatix_ov5693_hfr_120_3a.so +vendor/lib/libchromatix_ov5693_postproc.so +vendor/lib/libchromatix_ov5693_snapshot.so +vendor/lib/libchromatix_ov5693_snapshot_3a.so +vendor/lib/libchromatix_ov16860_4k_ihdr_video_3a.so +vendor/lib/libchromatix_ov16860_4k_video_3a.so +vendor/lib/libchromatix_ov16860_common.so +vendor/lib/libchromatix_ov16860_cpp_hfr_120.so +vendor/lib/libchromatix_ov16860_cpp_ihdr_video.so +vendor/lib/libchromatix_ov16860_cpp_ihdr_video_4k.so +vendor/lib/libchromatix_ov16860_cpp_liveshot.so +vendor/lib/libchromatix_ov16860_cpp_liveshot_4k.so +vendor/lib/libchromatix_ov16860_cpp_liveshot_4k_ihdr.so +vendor/lib/libchromatix_ov16860_cpp_liveshot_ihdr.so +vendor/lib/libchromatix_ov16860_cpp_snapshot.so +vendor/lib/libchromatix_ov16860_cpp_video.so +vendor/lib/libchromatix_ov16860_cpp_video_4k.so +vendor/lib/libchromatix_ov16860_default_ihdr_video.so +vendor/lib/libchromatix_ov16860_default_video.so +vendor/lib/libchromatix_ov16860_hfr_120.so +vendor/lib/libchromatix_ov16860_hfr_120_3a.so +vendor/lib/libchromatix_ov16860_ihdr_video_3a.so +vendor/lib/libchromatix_ov16860_ihdr_video_4k.so +vendor/lib/libchromatix_ov16860_postproc.so +vendor/lib/libchromatix_ov16860_snapshot.so +vendor/lib/libchromatix_ov16860_video_4k.so +vendor/lib/libchromatix_ov16860_zsl_preview_3a.so +vendor/lib/libchromatix_ov16860_zsl_video_3a.so + +# Camera firmware +etc/firmware/cpp_firmware_v1_1_1.fw +etc/firmware/cpp_firmware_v1_1_6.fw +etc/firmware/cpp_firmware_v1_2_0.fw +etc/firmware/cpp_firmware_v1_4_0.fw +etc/firmware/cpp_firmware_v1_5_0.fw +etc/firmware/cpp_firmware_v1_5_2.fw +etc/firmware/cpp_firmware_v1_6_0.fw +etc/firmware/cpp_firmware_v1_8_0.fw +etc/firmware/cpp_firmware_v1_10_0.fw + +# Display +-framework/com.qti.snapdragon.sdk.display.jar +-vendor/app/colorservice/colorservice.apk +etc/permissions/com.qti.snapdragon.sdk.display.xml +vendor/bin/mm-pp-dpps +vendor/lib/libdisp-aba.so +vendor/lib/libmm-disp-apis.so +vendor/lib/libmm-qdcm.so +vendor/lib/libscalar.so +vendor/lib/libsdm-color.so +vendor/lib/libsdm-diag.so +vendor/lib/libsdm-disp-apis.so +vendor/lib/libsdmextension.so +vendor/lib/libsd_sdk_display.so + +# DRM +bin/qseecomd +vendor/lib/libcppf.so +vendor/lib/libdrmfs.so +vendor/lib/libdrmtime.so +vendor/lib/libGPreqcancel.so +vendor/lib/libGPreqcancel_svc.so +vendor/lib/libGPTEE.so +vendor/lib/libmm-hdcpmgr.so +vendor/lib/liboemcrypto.so +vendor/lib/libQSEEComAPI.so +vendor/lib/librpmb.so +vendor/lib/libssd.so +vendor/lib/libwvdrm_L1.so +vendor/lib/libWVStreamControlAPI_L1.so +vendor/lib/mediadrm/libwvdrmengine.so + +# Fingerprint +lib/hw/fingerprint.msm8953.so +lib/libcom_fingerprints_service.so +lib/lib_fpc_tac_shared.so +vendor/lib/hw/gatekeeper.msm8953.so + +# GPS +etc/flp.conf +etc/gps.conf +etc/sap.conf +lib/hw/gps.default.so +lib/libgnsspps.so +lib/libgps.utils.so +lib/libloc_api_v02.so +lib/libloc_core.so +lib/libloc_ds_api.so +lib/libloc_eng.so +lib/libloc_pla.so +lib/libloc_stub.so +vendor/lib/hw/flp.default.so +vendor/lib/libflp.so +vendor/lib/libgeofence.so +vendor/lib/libizat_core.so +vendor/lib/liblbs_core.so + +# Graphics +vendor/lib/egl/eglSubDriverAndroid.so|ec4432c13c525a8e7699fc113ed76d12888b9a4a +vendor/lib/egl/libEGL_adreno.so|4caf9805f540f252cbc59a1baeaf68947c4a3629 +vendor/lib/egl/libGLESv1_CM_adreno.so|08562444668386dbef3a91da4afe035c4cf3cca5 +vendor/lib/egl/libGLESv2_adreno.so|8336e1447123d07ce050d38b65f5c626ff5c364a +vendor/lib/egl/libq3dtools_adreno.so|dc98724f776d1adb238a51f526f81c1a7332e7de +vendor/lib/egl/libQTapGLES.so|103398f835687009fc6fc87150127b90947f0170 +vendor/lib/hw/vulkan.msm8953.so|9577e2339bf06adf5a7e3ba319755f4eb66f1084 +vendor/lib/libadreno_utils.so|688253d34b3b4df78cbe549f22138ec85c50cff5 +vendor/lib/libbccQTI.so|19ab8268addaa5b73631551dbc61154581636eca +vendor/lib/libC2D2.so|7d5a26e6150ff9fbd2f0ad635a0d07a4326ff478 +vendor/lib/libc2d30-a5xx.so|6085baf304356bc4a9f49e163ddef5b0eaf225ed +vendor/lib/libc2d30_bltlib.so|c7fa938f42498c3e320088aa41b25982696ed565 +vendor/lib/libCB.so|a0ca4debf1e18bdafce70eb3dfa6482c83f52453 +vendor/lib/libgsl.so|67637a099ccdea51c6a4c47116f400693a99edbc +vendor/lib/libllvm-glnext.so|c80881bc8f0379491b3bc27126d7d7c5ceed1e1b +vendor/lib/libllvm-qcom.so|c41627a71ecf4f25f31261cc11d69fe0d0d227f7 +vendor/lib/libllvm-qgl.so|f4a6fb48bbc96853a5fbd21112cbebe6e2f583f3 +vendor/lib/libmmQSM.so|7edd945bb418d41f95686268ca702497507b51ba +vendor/lib/libOpenCL.so|9979863bcd10e3d47b9490dbfd9ed6e64b6d7f9a +vendor/lib/librs_adreno_sha1.so|d4402f0e5300c7ac6b5593a85caac9c36056465d +vendor/lib/librs_adreno.so|24191762448388fccc115b57ee2774f31a62a4a9 +vendor/lib/libRSDriver_adreno.so|5530b378a031d4c2725a7192a7ca02abc379caf0 + +# Graphics firmware +etc/firmware/a530_gpmu.fw2 +etc/firmware/a530_pfp.fw +etc/firmware/a530_pm4.fw +etc/firmware/a530v1_pfp.fw +etc/firmware/a530v1_pm4.fw +etc/firmware/a530v2_seq.fw2 +etc/firmware/a530v3_gpmu.fw2 +etc/firmware/a530v3_seq.fw2 + +# IMS +-framework/imscmlibrary.jar +-vendor/app/ims/ims.apk|138de3a169d8c4703d9e5645abeb19e427b04909 +-vendor/app/imssettings/imssettings.apk|3020cdd3bc6d3c5bd147f2086fdd62fae108d81b +bin/imscmservice +bin/imsdatadaemon +bin/imsqmidaemon +bin/ims_rtp_daemon +etc/permissions/imscm.xml +etc/permissions/ims.xml +etc/permissions/qti_permissions.xml +vendor/lib/lib-dplmedia.so +vendor/lib/libimscamera_jni.so +vendor/lib/lib-imscamera.so +vendor/lib/lib-imsdpl.so +vendor/lib/libimsmedia_jni.so +vendor/lib/lib-imsqimf.so +vendor/lib/lib-imsrcscmclient.so +vendor/lib/lib-ims-rcscmjni.so +vendor/lib/lib-imsrcscmservice.so +vendor/lib/lib-imsrcscm.so +vendor/lib/lib-imsrcs.so +vendor/lib/lib-imsSDP.so +vendor/lib/lib-imss.so +vendor/lib/lib-imsvt.so +vendor/lib/lib-imsxml.so +vendor/lib/librcc.so +vendor/lib/lib-rcsimssjni.so +vendor/lib/lib-rcsjni.so +vendor/lib/lib-rtpcommon.so +vendor/lib/lib-rtpcore.so +vendor/lib/lib-rtpdaemoninterface.so +vendor/lib/lib-rtpsl.so + +# IPA +bin/ipacm-diag + +# Media +vendor/lib/libAlacSwDec.so +vendor/lib/libApeSwDec.so +vendor/lib/libI420colorconvert.so +vendor/lib/libmm-color-convertor.so +vendor/lib/libmmosal.so +vendor/lib/libOmxAlacDec.so +vendor/lib/libOmxAlacDecSw.so +vendor/lib/libOmxApeDec.so +vendor/lib/libOmxApeDecSw.so +vendor/lib/libOmxWmaDec.so + +# Moto +bin/batt_health +bin/dbvc_atvc_property_set + +# NFC +vendor/firmware/libpn548ad_fw.so + +# Qualcomm framework +bin/irsc_util +vendor/lib/hw/keystore.msm8953.so +vendor/lib/libdiag.so +vendor/lib/libdsi_netctrl.so +vendor/lib/libdsutils.so +vendor/lib/libidl.so +vendor/lib/libqcci_legacy.so +vendor/lib/libqdi.so +vendor/lib/libqdp.so +vendor/lib/libqisl.so +vendor/lib/libqmi_cci.so +vendor/lib/libqmi_client_helper.so +vendor/lib/libqmi_client_qmux.so +vendor/lib/libqmi_common_so.so +vendor/lib/libqmi_csi.so +vendor/lib/libqmi_encdec.so +vendor/lib/libqmiservices.so +vendor/lib/libqmi.so +vendor/lib/libsmemlog.so + +# Radio +-app/datastatusnotification/datastatusnotification.apk +-app/embms/embms.apk +bin/netmgrd +bin/pm-proxy +bin/pm-service +bin/qmi_motext_hook +bin/radish +bin/rild +bin/rmt_storage +bin/tftp_server +etc/data/dsi_config.xml +etc/data/netmgr_config.xml +etc/permissions/embms.xml +etc/permissions/qcrilhook.xml +-framework/embmslibrary.jar +-framework/qcrilhook.jar +lib/libadropbox.so +lib/libmdmcutback.so|e93c51738fa50ca63d0e67f86a02cf22ba8e1985 +lib/libmotext_inf.so +lib/libqmimotext.so +-lib/libril.so +vendor/bin/qti +vendor/lib/libconfigdb.so +vendor/lib/liblqe.so +vendor/lib/libmdmdetect.so +vendor/lib/libnetmgr.so +vendor/lib/libperipheral_client.so +vendor/lib/libqcmaputils.so +vendor/lib/libril-qc-ltedirectdisc.so +vendor/lib/libril-qc-qmi-1.so +vendor/lib/libril-qc-radioconfig.so +vendor/lib/libril-qcril-hook-oem.so +vendor/lib/librilqmiservices.so +vendor/lib/libsettings.so +vendor/lib/libsubsystem_control.so +vendor/lib/libSubSystemShutdown.so +vendor/lib/libsystem_health_mon.so +vendor/lib/libxml.so +vendor/qcril.db + +# CNE +-priv-app/CNEService/CNEService.apk +bin/cnd +etc/cne/andsfCne.xml +etc/cne/SwimConfig.xml +etc/cne/wqeclient/ROW/ROW_profile1.xml +etc/cne/wqeclient/ROW/ROW_profile2.xml +etc/cne/wqeclient/ROW/ROW_profile3.xml +etc/cne/wqeclient/ROW/ROW_profile5.xml +etc/permissions/cneapiclient.xml +vendor/lib/libcneapiclient.so +vendor/lib/libcneqmiutils.so +vendor/lib/libcne.so +vendor/lib/libvendorconn.so +vendor/lib/libwms.so +vendor/lib/libwqe.so + +# SCVE +vendor/lib/libscveBlobDescriptor.so +vendor/lib/libscveBlobDescriptor_stub.so +vendor/lib/libscveCleverCapture.so +vendor/lib/libscveCleverCapture_stub.so +vendor/lib/libscveCommon.so +vendor/lib/libscveCommon_stub.so +vendor/lib/libscveFaceRecognition.so +vendor/lib/libscveImageCloning.so +vendor/lib/libscveImageCorrection.so +vendor/lib/libscveImageRemoval.so +vendor/lib/libscveMotionVector.so +vendor/lib/libscveObjectMatting.so +vendor/lib/libscveObjectMatting_stub.so +vendor/lib/libscveObjectSegmentation.so +vendor/lib/libscveObjectSegmentation_stub.so +vendor/lib/libscveObjectTracker.so +vendor/lib/libscveObjectTracker_stub.so +vendor/lib/libscvePanorama_lite.so +vendor/lib/libscvePanorama.so +vendor/lib/libscveTextRecoPostProcessing.so +vendor/lib/libscveTextReco.so +vendor/lib/libscveTextReco_stub.so + +# Sensors +bin/motosh +etc/firmware/sensorhubfw.bin +lib/hw/sensorhub.msm8953.so +lib/hw/sensors.potter.so +lib/hw/sensors.iio.so +lib/hw/sensors.msm8953.so +lib/libiio.so +lib/libsensorhub.so +vendor/lib/libsensor1.so +vendor/lib/libsensorhubservice_jni.so +vendor/lib/libsensor_reg.so + +# Thermal +vendor/bin/thermal-engine +vendor/lib/libthermalclient.so +vendor/lib/libthermalioctl.so + +# Time services +-app/TimeService/TimeService.apk +bin/time_daemon +vendor/lib/libtime_genoff.so +vendor/lib/libTimeService.so + +# Touchscreen +etc/firmware/synaptics-s3508-16082601-255c40-addison.tdat +etc/firmware/synaptics-s3508sga-16082601-255c40-addison.tdat + +# Vendor extension +vendor/bin/perfd +vendor/lib/libqti-iop.so +vendor/lib/libqti-iop-client.so +vendor/lib/libqti-perfd-client.so +vendor/lib/libqti_performance.so + +# WCNSS +etc/wifi/WCNSS_qcom_wlan_nv.bin:etc/firmware/wlan/prima/WCNSS_qcom_wlan_nv.bin +etc/wifi/WCNSS_qcom_wlan_nv_Argentina.bin:etc/firmware/wlan/prima/WCNSS_qcom_wlan_nv_Argentina.bin +etc/wifi/WCNSS_qcom_wlan_nv_Brazil.bin:etc/firmware/wlan/prima/WCNSS_qcom_wlan_nv_Brazil.bin +etc/wifi/WCNSS_qcom_wlan_nv_India.bin:etc/firmware/wlan/prima/WCNSS_qcom_wlan_nv_India.bin +etc/wifi/WCNSS_wlan_dictionary.dat:etc/firmware/wlan/prima/WCNSS_wlan_dictionary.dat + +# WiFi +bin/ptt_socket_app \ No newline at end of file diff --git a/rootdir/Android.mk b/rootdir/Android.mk new file mode 100644 index 0000000..0673120 --- /dev/null +++ b/rootdir/Android.mk @@ -0,0 +1,83 @@ +LOCAL_PATH:= $(call my-dir) + +# Configuration scripts + +include $(CLEAR_VARS) +LOCAL_MODULE := init.mmi.boot.sh +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.mmi.boot.sh +LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.mmi.laser.sh +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.mmi.laser.sh +LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.mmi.touch.sh +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.mmi.touch.sh +LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.qcom.bt.sh +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.qcom.bt.sh +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.qcom.ril.sh +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.qcom.ril.sh +include $(BUILD_PREBUILT) + +# Init scripts + +include $(CLEAR_VARS) +LOCAL_MODULE := fstab.qcom +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/fstab.qcom +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.mmi.rc +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.mmi.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.mmi.usb.rc +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.mmi.usb.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.qcom.rc +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.qcom.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := ueventd.qcom.rc +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/ueventd.qcom.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) diff --git a/rootdir/etc/fstab.qcom b/rootdir/etc/fstab.qcom new file mode 100644 index 0000000..8d832f0 --- /dev/null +++ b/rootdir/etc/fstab.qcom @@ -0,0 +1,22 @@ +# Android fstab file. +# The filesystem that contains the filesystem checker binary (typically /system) cannot +# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK + +#TODO: Add 'check' as fs_mgr_flags with data partition. +# Currently we dont have e2fsck compiled. So fs check would failed. + +# +/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1,discard wait +/dev/block/bootdevice/by-name/userdata /data f2fs rw,discard,nosuid,nodev,noatime,nodiratime,nobarrier,inline_xattr,inline_data wait,check,formattable,encryptable=/dev/block/bootdevice/by-name/metadata +/dev/block/bootdevice/by-name/cache /cache ext4 rw,noatime,nosuid,nodev,barrier=1,data=ordered wait,check,formattable +/dev/block/bootdevice/by-name/modem /firmware ext4 ro,nosuid,nodev,barrier=0,context=u:object_r:firmware_file:s0 wait +/dev/block/bootdevice/by-name/fsg /fsg ext4 ro,nosuid,nodev,context=u:object_r:fsg_file:s0 wait +/dev/block/bootdevice/by-name/dsp /dsp ext4 ro,nosuid,nodev,barrier=1 wait +/dev/block/bootdevice/by-name/persist /persist ext4 nosuid,nodev,barrier=1,noatime,noauto_da_alloc,context=u:object_r:persist_file:s0 wait +/dev/block/bootdevice/by-name/boot /boot emmc defaults recoveryonly +/dev/block/bootdevice/by-name/recovery /recovery emmc defaults recoveryonly +/dev/block/bootdevice/by-name/misc /misc emmc defaults defaults + +/devices/soc/7864900.sdhci/mmc_host* auto auto nosuid,nodev wait,voldmanaged=sdcard1:auto,encryptable=userdata +/devices/*/xhci-hcd.*.auto/usb* auto auto defaults voldmanaged=usb:auto +/dev/block/zram0 none swap defaults zramsize=536870912 diff --git a/rootdir/etc/init.mmi.boot.sh b/rootdir/etc/init.mmi.boot.sh new file mode 100644 index 0000000..ab7ac6f --- /dev/null +++ b/rootdir/etc/init.mmi.boot.sh @@ -0,0 +1,71 @@ +#!/system/bin/sh + +PATH=/sbin:/system/sbin:/system/bin:/system/xbin +export PATH + +scriptname=${0##*/} + +notice() +{ + echo "$*" + echo "$scriptname: $*" > /dev/kmsg +} + + +start_copying_prebuilt_qcril_db() +{ + if [ -f /system/vendor/qcril.db -a ! -f /data/misc/radio/qcril.db ]; then + cp /system/vendor/qcril.db /data/misc/radio/qcril.db + chown -h radio.radio /data/misc/radio/qcril.db + else + # [MOTO] if qcril.db's owner is not radio (e.g. root), + # reset it for the recovery + qcril_db_owner=`stat -c %U /data/misc/radio/qcril.db` + echo "qcril.db's owner is $qcril_db_owner" + if [ $qcril_db_owner != "radio" ]; then + echo "reset owner to radio for qcril.db" + chown -h radio.radio /data/misc/radio/qcril.db + fi + fi +} + +# We take this from cpuinfo because hex "letters" are lowercase there +set -A cinfo `cat /proc/cpuinfo | /system/bin/grep Revision` +hw=${cinfo[2]#?} + +# Now "cook" the value so it can be matched against devtree names +m2=${hw%?} +minor2=${hw#$m2} +m1=${m2%?} +minor1=${m2#$m1} +if [ "$minor2" == "0" ]; then + minor2="" + if [ "$minor1" == "0" ]; then + minor1="" + fi +fi +setprop ro.hw.revision p${hw%??}$minor1$minor2 +unset hw cinfo m1 m2 minor1 minor2 + +# Let kernel know our image version/variant/crm_version +if [ -f /sys/devices/soc0/select_image ]; then + image_version="10:" + image_version+=`getprop ro.build.id` + image_version+=":" + image_version+=`getprop ro.build.version.incremental` + image_variant=`getprop ro.product.name` + image_variant+="-" + image_variant+=`getprop ro.build.type` + oem_version=`getprop ro.build.version.codename` + echo 10 > /sys/devices/soc0/select_image + echo $image_version > /sys/devices/soc0/image_version + echo $image_variant > /sys/devices/soc0/image_variant + echo $oem_version > /sys/devices/soc0/image_crm_version +fi + +# +# Copy qcril.db if needed for RIL +# +start_copying_prebuilt_qcril_db +echo 1 > /data/misc/radio/db_check_done + diff --git a/rootdir/etc/init.mmi.laser.sh b/rootdir/etc/init.mmi.laser.sh new file mode 100644 index 0000000..7ff849e --- /dev/null +++ b/rootdir/etc/init.mmi.laser.sh @@ -0,0 +1,48 @@ +#!/system/bin/sh +scriptname=${0##*/} +dbg_on=1 +debug() +{ + [ $dbg_on ] && echo "Debug: $*" +} + +notice() +{ + echo "$*" + echo "$scriptname: $*" > /dev/kmsg +} + +error_and_leave() +{ + local err_msg + local err_code=$1 + case $err_code in + 1) err_msg="Error: No response";; + 2) err_msg="Error: in factory mode";; + 3) err_msg="Error: calibration file not exist";; + 4) err_msg="Error: the calibration sys file not show up";; + esac + notice "$err_msg" + exit $err_code +} + +bootmode=`getprop ro.bootmode` +if [ $bootmode == "mot-factory" ] +then + error_and_leave 2 +fi + +laser_offset_path=/sys/kernel/range/offset +laser_offset_string=$(ls $laser_offset_path) +[ -z "$laser_offset_string" ] && error_and_leave 4 + +cal_offset_path=/persist/camera/focus/offset_cal +cal_offset_string=$(ls $cal_offset_path) +[ -z "$cal_offset_string" ] && error_and_leave 3 + +offset_cal=$(cat $cal_offset_path) +debug "offset cal value [$offset_cal]" + +debug "set cal value to kernel" +echo $offset_cal > $laser_offset_path +notice "laser cal data update success" diff --git a/rootdir/etc/init.mmi.rc b/rootdir/etc/init.mmi.rc new file mode 100644 index 0000000..1edb4cd --- /dev/null +++ b/rootdir/etc/init.mmi.rc @@ -0,0 +1,317 @@ +# Moto USB configuration +import init.mmi.usb.rc + +on early-boot + write /sys/module/subsystem_restart/parameters/disable_restart_work 0x0 + write /proc/sys/kernel/poweroff_cmd "/system/bin/reboot -p" + +on init + chown system log /sys/fs/pstore/console-ramoops-0 + chmod 0440 /sys/fs/pstore/console-ramoops-0 + chown system log /sys/fs/pstore/annotate-ramoops-0 + chmod 0640 /sys/fs/pstore/annotate-ramoops-0 + chown system log /sys/fs/pstore/dmesg-ramoops-0 + chmod 0640 /sys/fs/pstore/dmesg-ramoops-0 + + # Setup kernel dropbox permissions so that dropboxd can utilize it + chown root diag /sys/kernel/dropbox/event + chown root diag /sys/kernel/dropbox/data + +on fs + # use /persist as phony PDS partition + symlink /persist /pds + +on post-fs + mkdir /persist/camera 0755 mot_tcmd mot_tcmd + mkdir /persist/camera/focus 0775 camera mot_tcmd + mkdir /persist/camera/ledcal 0775 camera mot_tcmd + mkdir /persist/batt_health 0755 mot_pwric mot_pwric + mkdir /persist/mdm 0770 radio radio + mkdir /persist/factory 0755 mot_tcmd mot_tcmd + mkdir /persist/factory/audio 0755 mot_tcmd system + mkdir /persist/factory/wlan 0755 mot_tcmd mot_tcmd + mkdir /persist/factory/regulatory 0755 mot_tcmd system + mkdir /persist/public 0755 mot_tcmd mot_tcmd + mkdir /persist/public/atvc 0770 mot_atvc shell + mkdir /persist/public/battd 0755 mot_accy mot_tcmd + mkdir /persist/public/hiddenmenu 0755 radio radio + mkdir /persist/public/hiddenmenu/data 0775 system mot_tcmd + mkdir /persist/public/locale 0700 system system + mkdir /persist/public/omadm 0700 radio radio + mkdir /persist/public/svcs 0770 system system + mkdir /persist/wifi 0755 mot_tcmd mot_tcmd + mkdir /persist/bt 0755 mot_tcmd bluetooth + mkdir /persist/wmdrm 0775 mot_drm mot_drm + + chown mot_tcmd mot_tcmd /persist/factory/fti + chmod 0660 /persist/factory/fti + chown mot_tcmd mot_tcmd /persist/factory/byte + chmod 0660 /persist/factory/byte + chmod 0660 /persist/wifi/wlan_mac.bin + chown mot_tcmd mot_tcmd /persist/bt/bt_bdaddr + chmod 0664 /persist/bt/bt_bdaddr + + swapon_all fstab.qcom + write /proc/sys/vm/page-cluster 0 + +on post-fs-data + + # Setup folders for security + mkdir /persist/security 02770 mot_tpapi mot_tpapi + mkdir /data/local/dbvc 0750 mot_tcmd shell + + # Create directory used by power_supply_logger + mkdir /data/power_supply_logger 0750 mot_pwric log + + # Create moodle directory that MOT_MOODLE can write to + mkdir /data/local/moodle 0770 graphics mot_tcmd + + # Permissions for Factory Test of Charging Paths + chown mot_pwric mot_pwric /sys/class/power_supply/battery/device/force_chg_auto_enable + chown mot_pwric mot_pwric /sys/class/power_supply/battery/device/force_chg_ibatt + chown mot_pwric mot_pwric /sys/class/power_supply/battery/device/force_chg_itrick + chown mot_pwric mot_pwric /sys/class/power_supply/battery/device/force_chg_iusb + chown mot_pwric mot_pwric /sys/class/power_supply/battery/device/force_chg_usb_suspend + chown mot_pwric mot_pwric /sys/class/power_supply/battery/device/force_chg_fail_clear + chown mot_pwric mot_pwric /sys/class/power_supply/battery/device/force_chg_usb_otg_ctl + + chown root mot_mod /sys/module/qpnp_smbcharger_mmi/parameters/eb_rechrg_start_soc + chown root mot_mod /sys/module/qpnp_smbcharger_mmi/parameters/eb_rechrg_stop_soc + chown root mot_mod /sys/module/qpnp_smbcharger_mmi/parameters/eb_attach_start_soc + chown root mot_mod /sys/module/qpnp_smbcharger_mmi/parameters/eb_attach_stop_soc + chown root mot_mod /sys/module/qpnp_smbcharger_mmi/parameters/eb_low_start_soc + chown root mot_mod /sys/module/qpnp_smbcharger_mmi/parameters/eb_low_stop_soc + chown root mot_mod /sys/module/qpnp_smbcharger_mmi/parameters/eb_on_sw + + chmod 0664 /sys/module/qpnp_smbcharger_mmi/parameters/eb_rechrg_start_soc + chmod 0664 /sys/module/qpnp_smbcharger_mmi/parameters/eb_rechrg_stop_soc + chmod 0664 /sys/module/qpnp_smbcharger_mmi/parameters/eb_attach_start_soc + chmod 0664 /sys/module/qpnp_smbcharger_mmi/parameters/eb_attach_stop_soc + chmod 0664 /sys/module/qpnp_smbcharger_mmi/parameters/eb_low_start_soc + chmod 0664 /sys/module/qpnp_smbcharger_mmi/parameters/eb_low_stop_soc + chmod 0664 /sys/module/qpnp_smbcharger_mmi/parameters/eb_on_sw + + chown root mot_mod /sys/class/power_supply/usb/usb_priority + chmod 0660 /sys/class/power_supply/usb/usb_priority + + # Sensor Hub calibration data directory + mkdir /data/misc/sensorhub 0770 system compass + + # Setup folder for native to transfer data to NativeDropBoxAgent + mkdir /data/system/dropbox-add 0730 system diag + + # Create directory for cutback + mkdir /data/misc/cutback 0770 radio wifi + + #setup folder for WLAN WAPI + mkdir /data/wapi_certificate 0750 system wifi + chown system wifi /data/wapi_certificate + + # Create greybus firmware folder + mkdir /data/gbfirmware 0770 mot_mod mot_mod + + # Create bug2go folder + mkdir /data/bug2go 0770 log log + + # Permissions for phone power off log + mkdir /data/power_log 0750 root log + chmod 0660 /sys/module/power_supply_log/parameters/log_file + write /sys/module/power_supply_log/parameters/log_file /data/power_log/power_off.log + + # Subsystem RAM-dumps + mkdir /data/ss-ram-dumps 0750 system log + mkdir /data/ss-ram-dumps/bp-dumps 0750 system log + mkdir /data/ss-ram-dumps/riva-dumps 0750 system log + + # folder for Blueooth ramdump + mkdir /data/bt-ram-dumps 0750 bluetooth log + + # SD card encryption metadata + mkdir /data/misc/sds 0750 root root + + # Required by FingerPrint Cards (FPC) via init so we don't need to give qseecomd or fingerprintd permissions to create them + mkdir /data/fpc 0700 system system + mkdir /data/.fps 0770 system input + + #Folder for hardware properties + mkdir /data/hardware_revisions 0755 system system + + #Create directory for adspd + mkdir /data/adspd 0770 audio diag + + # Setup folder for camera dump subsystem + mkdir /data/camera_dump 0750 media media + + # Imager tuning data for camera subsystem + mkdir /data/misc/imager 0770 camera camera + + #setup folder for WLAN WAPI + chmod 0770 /data/wapi_certificate + +on boot + # restore default console_loglevel to KERN_DEBUG + # restore default_message_loglevel to KERN_WARNING + write /proc/sys/kernel/printk "7 4 1 7" + + # Change ownership and permission for backlight + chown system system /sys/class/backlight/lcd-backlight:0/brightness + chmod 0664 /sys/class/backlight/lcd-backlight:0/brightness + chown system system /sys/class/backlight/lcd-backlight:0/max_brightness + chmod 0664 /sys/class/backlight/lcd-backlight:0/max_brightness + chmod 0664 /sys/class/leds/lcd-backlight/brightness + chown system system /sys/class/leds/white/brightness + chmod 0664 /sys/class/leds/white/brightness + + # Change ownership for Dynamic-CABC feature + chown system system /sys/class/graphics/fb0/cabc_mode + # Change ownership for for ACL feature + chown system system /sys/class/graphics/fb0/acl_mode + + # Change ownership and permission for vibrator + chown system system /sys/class/timed_output/vibrator/enable + chmod 0660 /sys/class/timed_output/vibrator/enable + + # Change ownership and permission for laser_sensor + chown system system /sys/kernel/range/enable_sar + chmod 0660 /sys/kernel/range/enable_sar + chown system system /sys/kernel/range/set_delay_ms + chmod 0660 /sys/kernel/range/set_delay_ms + chown system system /sys/kernel/range/near + chmod 0660 /sys/kernel/range/near + + # Change the ownership of display TE files for tcmds + chown root mot_tcmd /sys/class/graphics/fb0/te_enable + chown root mot_tcmd /sys/class/graphics/fb0/frame_counter + + # Change ownership of aov related sysfs entries + wait /sys/kernel/aov/event + chown audio audio /sys/kernel/aov/trigger + chown audio audio /sys/kernel/aov/register + chown audio audio /sys/kernel/aov/event + + # Change permission for type C params + chown root mot_tcmd /sys/devices/soc/78b6000.i2c/i2c-2/2-0022/CC_state + chown root mot_tcmd /sys/devices/soc/78b6000.i2c/i2c-2/2-0022/enable_vconn + # Change ownership and permission for AMPS factory testing + chown root mot_tcmd /sys/class/i2c-adapter/i2c-2/2-002d/enable + chmod 0660 /sys/class/i2c-adapter/i2c-2/2-002d/enable + chown root mot_tcmd /sys/class/i2c-adapter/i2c-2/2-002d/hsic_vdd + chmod 0660 /sys/class/i2c-adapter/i2c-2/2-002d/hsic_vdd + + # Change permission for fingerprint sensor + chown system mot_tcmd /sys/bus/spi/devices/spi8.0/nav + chown system mot_tcmd /sys/bus/spi/devices/spi8.0/clk_enable + chown system mot_tcmd /sys/bus/spi/devices/spi8.0/dev_enable + chown system mot_tcmd /sys/bus/spi/devices/spi8.0/irq + chown system mot_tcmd /sys/bus/spi/devices/spi8.0/irq_cnt + chmod 0440 /sys/bus/spi/devices/spi8.0/irq_cnt + + # STML4 driver parameter permissions + chown root mot_tcmd /sys/module/motosh/parameters/irq_disable + chmod 0660 /sys/module/motosh/parameters/irq_disable + + #STML4 device permissions + chown system compass /dev/motosh + chmod 0660 /dev/motosh + chown compass compass /dev/motosh_as + chmod 0660 /dev/motosh_as + chown compass compass /dev/motosh_ms + chmod 0660 /dev/motosh_ms + chown compass compass /sys/devices/virtual/motosh/motosh_as/timestamp_time_ns + chmod 0440 /sys/devices/virtual/motosh/motosh_as/timestamp_time_ns + chown compass compass /sys/devices/virtual/motosh/motosh_as/rv_6axis_update_rate + chmod 0660 /sys/devices/virtual/motosh/motosh_as/rv_6axis_update_rate + chown compass compass /sys/devices/virtual/motosh/motosh_as/rv_9axis_update_rate + chmod 0660 /sys/devices/virtual/motosh/motosh_as/rv_9axis_update_rate + chown compass compass /sys/devices/virtual/motosh/motosh_as/game_rv_update_rate + chmod 0660 /sys/devices/virtual/motosh/motosh_as/game_rv_update_rate + chown compass compass /sys/devices/virtual/motosh/motosh_as/gravity_update_rate + chmod 0660 /sys/devices/virtual/motosh/motosh_as/gravity_update_rate + chown compass compass /sys/devices/virtual/motosh/motosh_as/linear_accel_update_rate + chmod 0660 /sys/devices/virtual/motosh/motosh_as/linear_accel_update_rate + + # Quiet binder logs + write /sys/module/binder/parameters/debug_mask 0x5 + +on charger + trigger early-fs + trigger fs + trigger post-fs + trigger post-fs-data + trigger moto-charger + class_stop main + class_stop late_start + +on moto-charger + setprop ro.board.platform msm8953 + trigger firmware_mounts_complete + start batt_health + start thermal-com + +on property:ro.boot.dualsim=true + setprop persist.radio.multisim.config dsds + setprop ro.telephony.default_network 10,10 + +on property:ro.boot.dualsim=false + setprop persist.radio.multisim.config "" + setprop ro.telephony.default_network 10 + +service adspd /system/bin/adspd + seclabel u:r:adspd:s0 + class main + socket adspdsock stream 0660 system audio + user audio + group audio input diag + +service batt_health /system/bin/batt_health + class late_start + user mot_pwric + group mot_pwric cache net_admin log + disabled + +on property:sys.boot_completed=1 && property:ro.boot.secure_hardware=0 + start batt_health + +service fingerprintd /system/bin/fingerprintd + class late_start + user system + group input + +service mmi-boot-sh /system/bin/init.mmi.boot.sh + class core + user root + oneshot + +service mmi-laser-sh /system/bin/init.mmi.laser.sh + class core + user root + oneshot + +service mmi-touch-sh /system/bin/init.mmi.touch.sh + class core + user root + oneshot + +# Start Sensor daemon +service motosh /system/bin/motosh boot + class late_start + user compass + group compass misc input + oneshot + seclabel u:r:sensor_hub:s0 + +service thermal-com /system/vendor/bin/thermal-engine --minimode + class main + user root + disabled + +# Set RPS Mask for Wifi Hotspot +on property:sys.wifi.tethering=true + write /sys/class/net/rmnet_data0/queues/rx-0/rps_cpus ${sys.usb.rps_mask} + write /sys/class/net/wlan0/queues/rx-0/rps_cpus ${sys.usb.rps_mask} + write /sys/class/net/wlan0/queues/rx-1/rps_cpus ${sys.usb.rps_mask} + write /sys/class/net/wlan0/queues/rx-2/rps_cpus ${sys.usb.rps_mask} + write /sys/class/net/wlan0/queues/rx-3/rps_cpus ${sys.usb.rps_mask} + +on property:sys.wifi.tethering=false + write /sys/class/net/rmnet_data0/queues/rx-0/rps_cpus ${sys.rmnet_vnd.rps_mask} diff --git a/rootdir/etc/init.mmi.touch.sh b/rootdir/etc/init.mmi.touch.sh new file mode 100644 index 0000000..f5b5d0a --- /dev/null +++ b/rootdir/etc/init.mmi.touch.sh @@ -0,0 +1,349 @@ +#!/system/bin/sh + +PATH=/sbin:/system/sbin:/system/bin:/system/xbin +export PATH + +while getopts ds op; +do + case $op in + d) dbg_on=1;; + s) dump_statistics=1;; + esac +done +shift $(($OPTIND-1)) + +scriptname=${0##*/} +touch_class_path=/sys/class/touchscreen +touch_product_string=$(ls $touch_class_path) +touch_status_prop=hw.touch.status + +debug() +{ + [ $dbg_on ] && echo "Debug: $*" +} + +notice() +{ + echo "$*" + echo "$scriptname: $*" > /dev/kmsg +} + +sanity_check() +{ + read_touch_property flashprog || return 1 + [[ ( -z "$property" ) || ( "$property" == "1" ) ]] && return 1 + read_touch_property productinfo || return 1 + [[ ( -z "$property" ) || ( "$property" == "0" ) ]] && return 1 + read_touch_property buildid || return 1 + config_id=${property#*-} + [[ ( -z "$config_id" ) || ( "$config_id" == "0" ) ]] && return 1 + build_id=${property%-*} + [[ ( -z "$build_id" ) || ( "$build_id" == "0" ) ]] && return 1 + return 0 +} + +error_and_leave() +{ + local err_msg + local err_code=$1 + local touch_status="unknown" + case $err_code in + 1) err_msg="Error: No response from touch IC" + touch_status="dead";; + 2) err_msg="Error: Cannot read property $2";; + 3) err_msg="Error: No matching firmware file found";; + 4) err_msg="Error: Touch IC is in bootloader mode" + touch_status="dead";; + 5) err_msg="Error: Touch provides no reflash interface" + touch_status="dead";; + 6) err_msg="Error: Touch driver is not running" + touch_status="absent";; + 7) err_msg="Warning: Touch firmware is not the latest";; + esac + notice "$err_msg" + + # perform sanity check and declare touch ready if error is not fatal + if [ "$touch_status" == "unknown" ]; then + touch_status="ready" + sanity_check + [ "$?" == "1" ] && touch_status="dead" + fi + + # perform recovery if touch is declared dead + if [ "$touch_status" == "dead" ]; then + notice "Touch needs to go through recovery!!!" + reboot_cnt=$(getprop $touch_status_prop 2>/dev/null) + [ -z "$reboot_cnt" ] && reboot_cnt=0 + debug "current reboot counter [$reboot_cnt]" + fi + + setprop $touch_status_prop $touch_status + notice "property [$touch_status_prop] set to [`getprop $touch_status_prop`]" + + if [ "$touch_status" == "dead" ]; then + if [ $((reboot_cnt)) -lt 2 ]; then + notice "Touch is not working; rebooting..." + debug "sleep 3s to allow touch-dead-sh service to run" + sleep 3 + [ -z "$dbg_on" ] && reboot + else + notice "Although touch is not working, no more reboots" + fi + fi + + exit $err_code +} + +[ -z "$touch_product_string" ] && error_and_leave 6 + +touch_vendor=$(cat $touch_class_path/$touch_product_string/vendor) +debug "touch vendor [$touch_vendor]" +touch_path=/sys$(cat $touch_class_path/$touch_product_string/path) +debug "sysfs touch path: $touch_path" +panel_path=/sys/devices/virtual/graphics/fb0 +debug "sysfs panel path: $panel_path" + +if [ $dump_statistics ]; then + debug "dumping touch statistics" + cat $touch_path/ic_ver + [ -f $touch_path/stats ] && cat $touch_path/stats + return 0 +fi + +[ -f $touch_path/doreflash ] || error_and_leave 5 +[ -f $touch_path/poweron ] || error_and_leave 5 + +selinux=$(getprop ro.boot.selinux 2> /dev/null) + +if [ "$selinux" == "permissive" ]; then + debug "loosen permissions to touch report sysfs entries" + touch_report_files="reporting query stats" + for entry in $touch_report_files; do + chmod 0666 $touch_path/$entry + debug "change permissions of $touch_path/$entry" + done + for entry in $(ls $touch_path/f54/ 2>/dev/null); do + chmod 0666 $touch_path/f54/$entry + debug "change permissions of $touch_path/f54/$entry" + done + unset touch_report_files +fi + +# Set permissions to enable factory touch tests +chown root:mot_tcmd $touch_path/drv_irq +chown root:mot_tcmd $touch_path/hw_irqstat +chown root:mot_tcmd $touch_path/reset +# Set permissions to allow Bug2Go access to touch statistics +chown root:log $touch_path/stats + +debug "wait until driver reports ..." +while true; do + readiness=$(cat $touch_path/poweron) + if [ "$readiness" == "1" ]; then + debug "ready to flash!!!" + break; + fi + sleep 1 + debug "not ready; keep waiting..." +done +unset readiness + +device_property=ro.hw.device +hwrev_property=ro.hw.revision +firmware_path=/system/etc/firmware + +let dec_cfg_id_boot=0; dec_cfg_id_latest=0; + +read_touch_property() +{ + property="" + debug "retrieving property: [$touch_path/$1]" + property=$(cat $touch_path/$1 2> /dev/null) + debug "touch property [$1] is: [$property]" + [ -z "$property" ] && return 1 + return 0 +} + +read_panel_property() +{ + property="" + debug "retrieving panel property: [$panel_path/$1]" + property=$(cat $panel_path/$1 2> /dev/null) + debug "panel property [$1] is: [$property]" + [ -z "$property" ] && return 1 + return 0 +} + +find_latest_config_id() +{ + local fw_mask=$1 + local skip_fields=$2 + local dec max z str_hex i + + str_cfg_id_latest="" + + debug "scanning dir for files matching [$fw_mask]" + let dec=0; max=0; + for file in $(ls $fw_mask 2>/dev/null); + do + z=$file + i=0 + while [ ! $i -eq $skip_fields ]; + do + z=${z#*-} + i=$((i+1)) + done + + str_hex=${z%%-*}; + + let dec=0x$str_hex + if [ $dec -gt $max ]; + then + let max=$dec; dec_cfg_id_latest=$dec; + str_cfg_id_latest=$str_hex + fi + done + + [ -z "$str_cfg_id_latest" ] && return 1 + return 0 +} + +read_touch_property flashprog || error_and_leave 1 +bl_mode=$property +debug "bl mode: $bl_mode" + +read_touch_property productinfo || error_and_leave 1 +touch_product_id=$property +if [ -z "$touch_product_id" ] || [ "$touch_product_id" == "0" ]; +then + debug "touch ic reports invalid product id" + error_and_leave 1 +fi +debug "touch product id: $touch_product_id" + +read_touch_property buildid || error_and_leave 1 +str_cfg_id_boot=${property#*-} +let dec_cfg_id_boot=0x$str_cfg_id_boot +debug "touch config id: $str_cfg_id_boot" + +build_id_boot=${property%-*} +debug "touch build id: $build_id_boot" + +typeset -l product_id +product_id=$(getprop $device_property 2> /dev/null) +[ -z "$product_id" ] && error_and_leave 2 $device_property +product_id=${product_id%-*} +product_id=${product_id%_*} +debug "product id: $product_id" + +hwrev_id=$(getprop $hwrev_property 2> /dev/null) +[ -z "$hwrev_id" ] && notice "hw revision undefined" +debug "hw revision: $hwrev_id" + +read_panel_property "panel_supplier" +supplier=$property +[ -z "$supplier" ] && debug "driver does not report panel supplier" +debug "panel supplier: $supplier" + +cd $firmware_path + +find_best_match() +{ + local hw_mask=$1 + local panel_supplier=$2 + local skip_fields fw_mask + + while [ ! -z "$hw_mask" ]; do + if [ "$hw_mask" == "-" ]; then + hw_mask="" + fi + + if [ ! -z "$panel_supplier" ]; + then + skip_fields=3 + fw_mask="$touch_vendor-$panel_supplier-$touch_product_id-*-$product_id$hw_mask.*" + else + skip_fields=2 + fw_mask="$touch_vendor-$touch_product_id-*-$product_id$hw_mask.*" + fi + + find_latest_config_id "$fw_mask" "$skip_fields" && break + + hw_mask=${hw_mask%?} + done + + [ -z "$str_cfg_id_latest" ] && return 1 + + if [ -z "$panel_supplier" ]; then + firmware_file=$(ls $touch_vendor-$touch_product_id-$str_cfg_id_latest-*-$product_id$hw_mask.*) + else + firmware_file=$(ls $touch_vendor-$panel_supplier-$touch_product_id-$str_cfg_id_latest-*-$product_id$hw_mask.*) + fi + notice "Firmware file for upgrade $firmware_file" + + return 0 +} + +hw_mask="-$hwrev_id" +debug "hw_mask=$hw_mask" + +match_not_found=1 +if [ ! -z "$supplier" ]; +then + debug "search for best hw revision match with supplier" + find_best_match "-$hwrev_id" "$supplier" + match_not_found=$? +fi + +if [ "$match_not_found" -ne "0" ]; +then + debug "search for best hw revision match without supplier" + find_best_match "-$hwrev_id" || error_and_leave 3 +fi + +recovery=0 +if [ "$bl_mode" == "1" ] || [ "$build_id_boot" == "0" ]; +then + recovery=1 + notice "Initiating touch firmware recovery" + notice " bl mode = $bl_mode" + notice " build id = $build_id_boot" +fi + +if [ $dec_cfg_id_boot -ne $dec_cfg_id_latest ] || [ "$recovery" == "1" ]; +then + debug "forcing firmware upgrade" + echo 1 > $touch_path/forcereflash + debug "sending reflash command" + echo $firmware_file > $touch_path/doreflash + read_touch_property flashprog || error_and_leave 1 + bl_mode=$property + [ "$bl_mode" == "1" ] && error_and_leave 4 + read_touch_property buildid || error_and_leave 1 + str_cfg_id_new=${property#*-} + build_id_new=${property%-*} + + notice "Touch firmware config id at boot time $str_cfg_id_boot" + notice "Touch firmware config id in the file $str_cfg_id_latest" + notice "Touch firmware config id currently programmed $str_cfg_id_new" + + [ "$str_cfg_id_latest" != "$str_cfg_id_new" ] && error_and_leave 7 + + if [ -f $touch_path/f54/force_update ]; then + notice "forcing F54 registers update" + echo 1 > $touch_path/f54/force_update + fi +fi + +notice "Touch firmware is up to date" +setprop $touch_status_prop "ready" +notice "property [$touch_status_prop] set to [`getprop $touch_status_prop`]" + +unset device_property hwrev_property supplier +unset str_cfg_id_boot str_cfg_id_latest str_cfg_id_new +unset dec_cfg_id_boot dec_cfg_id_latest match_not_found +unset hwrev_id product_id touch_product_id scriptname +unset synaptics_link firmware_path touch_path +unset bl_mode dbg_on hw_mask firmware_file property + +return 0 diff --git a/rootdir/etc/init.mmi.usb.rc b/rootdir/etc/init.mmi.usb.rc new file mode 100644 index 0000000..0423094 --- /dev/null +++ b/rootdir/etc/init.mmi.usb.rc @@ -0,0 +1,446 @@ +# Copyright (c) 2011, Code Aurora Forum. 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 Code Aurora 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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. +# + +on init + write /sys/class/android_usb/android0/f_rndis/wceis 1 + +on boot + write /sys/class/android_usb/android0/iSerial ${ro.serialno} + write /sys/class/android_usb/android0/iManufacturer ${ro.product.manufacturer} + write /sys/class/android_usb/android0/iProduct ${ro.product.model} + mkdir /dev/bus 0755 root root + mkdir /dev/bus/usb 0755 root root + chown system system /sys/class/android_usb/android0/secure + chmod 0660 /sys/class/android_usb/android0/secure + # Configure BAM2BAM_IPA for RNDIS + write /sys/class/android_usb/android0/f_rndis_qc/rndis_transports BAM2BAM_IPA + # Disable RNDIS UL aggregation + write /sys/class/android_usb/android0/f_rndis_qc/max_pkt_per_xfer 1 + write /sys/module/g_android/parameters/mtp_rx_req_len 524288 + write /sys/module/g_android/parameters/mtp_tx_req_len 524288 + + chown root system /sys/module/uvcvideo/parameters/quirks + chmod 0660 /sys/module/uvcvideo/parameters/quirks + +on charger + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 22B8 + write /sys/class/android_usb/android0/idProduct 2EB7 + write /sys/class/android_usb/android0/functions mass_storage + write /sys/class/android_usb/android0/enable 1 + +on fs + mkdir /dev/usb-ffs 0770 shell shell + mkdir /dev/usb-ffs/adb 0770 shell shell + mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=2000 + write /sys/class/android_usb/android0/f_ffs/aliases adb + +# Disable USB-SS in bp-tools +on property:ro.bootmode=bp-tools + write /sys/module/fusb302/parameters/disable_ss_switch 1 + +# USB compositions +# QC compositions for msm8953 +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_bam,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9025 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_bam,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9026 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# QC compositions for MSM8996 +on property:sys.usb.config=diag,serial_cdev,serial_tty,rmnet_bam,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9025 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_cdev,serial_tty,rmnet_bam,mass_storage + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9026 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# QC compositions for MSM8937 +on property:sys.usb.config=diag,serial_smd,rmnet_qti_bam,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9091 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_qti_bam + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9092 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_ipa,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9091 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_ipa + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9092 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# QDSS - Qualcomm Debug Subsystem +on property:sys.usb.config=diag,qdss,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9060 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/functions diag,qdss,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Motorola Compositions for msm8953 bp-tools mode +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpt_adb} + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Motorola Compositions for msm8937 bp-tools mode +on property:sys.usb.config=diag,serial_smd,rmnet,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpt_adb} + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpt} + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_bam_ipa,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpt_adb} + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_bam_ipa + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpt} + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpt} + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=rndis,diag,serial_smd,serial_tty,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpteth_adb} + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/functions rndis,diag,serial,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=rndis,diag,serial_smd,serial_tty + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpteth} + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/functions rndis,diag,serial + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# Motorola Compositions for MSM8996 bp-tools mode +on property:sys.usb.config=diag,serial_cdev,serial_tty,rmnet,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpt_adb} + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_cdev,serial_tty,rmnet + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpt} + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=rndis,diag,serial_cdev,serial_tty,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpteth_adb} + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty + write /sys/class/android_usb/android0/functions rndis,diag,serial,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=rndis,diag,serial_cdev,serial_tty + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct ${ro.usb.bpteth} + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty + write /sys/class/android_usb/android0/functions rndis,diag,serial + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +#Factory mode Compositions +on property:sys.usb.config=usbnet,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct 2e2d + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/functions usbnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=usbnet + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idProduct 2e2c + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/functions usbnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# Standard AOSP Compositions +on property:sys.usb.config=rndis + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct 2e24 + write /sys/class/android_usb/android0/functions rndis + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=rndis,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct 2e25 + write /sys/class/android_usb/android0/functions rndis,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/bDeviceClass 0 + write /sys/class/android_usb/android0/bDeviceSubClass 0 + write /sys/class/android_usb/android0/bDeviceProtocol 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct ${ro.usb.mtp} + write /sys/class/android_usb/android0/functions mtp + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp,cdrom + stop adbd + write /sys/class/android_usb/android0/f_mass_storage/lun/file "" + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/bDeviceClass 0 + write /sys/class/android_usb/android0/bDeviceSubClass 0 + write /sys/class/android_usb/android0/bDeviceProtocol 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct ${ro.usb.mtp_cdrom} + write /sys/class/android_usb/android0/f_mass_storage/cdrom 1 + write /sys/class/android_usb/android0/functions mtp,mass_storage + write /sys/class/android_usb/android0/enable 1 + write /sys/class/android_usb/android0/f_mass_storage/lun/file "/system/etc/cdrom" + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/bDeviceClass 0 + write /sys/class/android_usb/android0/bDeviceSubClass 0 + write /sys/class/android_usb/android0/bDeviceProtocol 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct ${ro.usb.mtp_adb} + write /sys/class/android_usb/android0/functions mtp,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=ptp + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/bDeviceClass 0 + write /sys/class/android_usb/android0/bDeviceSubClass 0 + write /sys/class/android_usb/android0/bDeviceProtocol 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct ${ro.usb.ptp} + write /sys/class/android_usb/android0/functions ptp + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=ptp,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/bDeviceClass 0 + write /sys/class/android_usb/android0/bDeviceSubClass 0 + write /sys/class/android_usb/android0/bDeviceProtocol 0 + write /sys/class/android_usb/android0/idVendor 22b8 + write /sys/class/android_usb/android0/idProduct ${ro.usb.ptp_adb} + write /sys/class/android_usb/android0/functions ptp,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# USB midi configuration +on property:sys.usb.config=midi + stop adbd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 18D1 + write /sys/class/android_usb/android0/idProduct 4EE8 + write /sys/class/android_usb/android0/functions ${sys.usb.config} + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# USB midi configuration, with adb +on property:sys.usb.config=midi,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 18D1 + write /sys/class/android_usb/android0/idProduct 4EE9 + write /sys/class/android_usb/android0/functions ${sys.usb.config} + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Set RPS Mask for USB tethering +on property:sys.usb.tethering=true + write /sys/class/net/rndis0/queues/rx-0/rps_cpus ${sys.usb.rps_mask} + write /sys/class/net/rmnet_data0/queues/rx-0/rps_cpus ${sys.usb.rps_mask} + +on property:sys.usb.tethering=false + write /sys/class/net/rmnet_data0/queues/rx-0/rps_cpus ${sys.rmnet_vnd.rps_mask} diff --git a/rootdir/etc/init.qcom.bt.sh b/rootdir/etc/init.qcom.bt.sh new file mode 100644 index 0000000..0e1ec31 --- /dev/null +++ b/rootdir/etc/init.qcom.bt.sh @@ -0,0 +1,90 @@ +#!/system/bin/sh +# Copyright (c) 2009-2013, 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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. +# + +LOG_TAG="qcom-bluetooth" +LOG_NAME="${0}:" + +loge () +{ + /system/bin/log -t $LOG_TAG -p e "$LOG_NAME $@" +} + +logi () +{ + /system/bin/log -t $LOG_TAG -p i "$LOG_NAME $@" +} + +failed () +{ + loge "$1: exit code $2" + exit $2 +} + +POWER_CLASS=`getprop qcom.bt.dev_power_class` +LE_POWER_CLASS=`getprop qcom.bt.le_dev_pwr_class` + +setprop bluetooth.status off + +case $POWER_CLASS in + 1) PWR_CLASS="-p 0" ; + logi "Power Class: 1";; + 2) PWR_CLASS="-p 1" ; + logi "Power Class: 2";; + 3) PWR_CLASS="-p 2" ; + logi "Power Class: CUSTOM";; + *) PWR_CLASS=""; + logi "Power Class: Ignored. Default(1) used (1-CLASS1/2-CLASS2/3-CUSTOM)"; + logi "Power Class: To override, Before turning BT ON; setprop qcom.bt.dev_power_class <1 or 2 or 3>";; +esac + +case $LE_POWER_CLASS in + 1) LE_PWR_CLASS="-P 0" ; + logi "LE Power Class: 1";; + 2) LE_PWR_CLASS="-P 1" ; + logi "LE Power Class: 2";; + 3) LE_PWR_CLASS="-P 2" ; + logi "LE Power Class: CUSTOM";; + *) LE_PWR_CLASS="-P 1"; + logi "LE Power Class: Ignored. Default(2) used (1-CLASS1/2-CLASS2/3-CUSTOM)"; + logi "LE Power Class: To override, Before turning BT ON; setprop qcom.bt.le_dev_pwr_class <1 or 2 or 3>";; +esac + +eval $(/system/bin/hci_qcomm_init -e $PWR_CLASS $LE_PWR_CLASS && echo "exit_code_hci_qcomm_init=0" || echo "exit_code_hci_qcomm_init=1") + +case $exit_code_hci_qcomm_init in + 0) logi "Bluetooth QSoC firmware download succeeded, $BTS_DEVICE $BTS_TYPE $BTS_BAUD $BTS_ADDRESS";; + *) failed "Bluetooth QSoC firmware download failed" $exit_code_hci_qcomm_init; + + setprop bluetooth.status off + + exit $exit_code_hci_qcomm_init;; +esac + +setprop bluetooth.status on + +exit 0 diff --git a/rootdir/etc/init.qcom.rc b/rootdir/etc/init.qcom.rc new file mode 100644 index 0000000..c649f61 --- /dev/null +++ b/rootdir/etc/init.qcom.rc @@ -0,0 +1,721 @@ +# Copyright (c) 2009-2012, 2014-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 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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. +# + +import init.mmi.rc + +on early-init + mount debugfs debugfs /sys/kernel/debug + chmod 0755 /sys/kernel/debug + mkdir /firmware 0771 system system + mkdir /system 0777 root root + symlink /data/tombstones /tombstones + mkdir /dsp 0771 media media + +on fs + wait /dev/block/bootdevice + mount_all fstab.qcom + write /proc/sys/vm/swappiness 100 + + # Keeping following partitions outside fstab file. As user may not have + # these partition flashed on the device. Failure to mount any partition in fstab file + # results in failure to launch late-start class. + + wait /dev/block/bootdevice/by-name/persist + mkdir /persist/data 0700 system system + restorecon_recursive /persist + + wait /dev/block/bootdevice/by-name/dsp + restorecon_recursive /dsp + +on init + # Symbols required for motorola blobs + export LD_SHIM_LIBS /system/vendor/lib/libmot_gpu_mapper.so|libshim_camera.so:/system/vendor/lib/lib-imsvt.so|libshim_ims.so:/system/bin/adspd|libshim_adsp.so + + write /sys/module/qpnp_rtc/parameters/poweron_alarm 1 + + # Set permissions for persist partition + mkdir /persist 0771 system system + + # Create cgroup mount point for memory + mkdir /sys/fs/cgroup/memory/bg 0750 root system + write /sys/fs/cgroup/memory/bg/memory.swappiness 140 + write /sys/fs/cgroup/memory/bg/memory.move_charge_at_immigrate 1 + chown root system /sys/fs/cgroup/memory/bg/tasks + chmod 0660 /sys/fs/cgroup/memory/bg/tasks + +on early-boot + # set RLIMIT_MEMLOCK to 64MB + setrlimit 8 67108864 67108864 + # Allow subsystem (modem etc) debugging + write /sys/kernel/boot_adsp/boot 1 + # Motorola uses external sensorhub, do not boot the slpi + # write /sys/kernel/boot_slpi/boot 1 + +on boot + insmod /system/lib/modules/adsprpc.ko + # access permission for secure touch + chmod 0660 /sys/devices/soc/78b7000.i2c/i2c-3/3-0020/input/input0/secure_touch_enable + chmod 0440 /sys/devices/soc/78b7000.i2c/i2c-3/3-0020/input/input0/secure_touch + chown system drmrpc /sys/devices/soc/78b7000.i2c/i2c-3/3-0020/input/input0/secure_touch_enable + chown system drmrpc /sys/devices/soc/78b7000.i2c/i2c-3/3-0020/input/input0/secure_touch + + chown bluetooth bluetooth /sys/module/bluetooth_power/parameters/power + chown bluetooth net_bt /sys/class/rfkill/rfkill0/type + chown bluetooth net_bt /sys/class/rfkill/rfkill0/state + chown bluetooth bluetooth /proc/bluetooth/sleep/proto + chown bluetooth bluetooth /sys/module/hci_uart/parameters/ath_lpm + chown bluetooth bluetooth /sys/module/hci_uart/parameters/ath_btwrite + chown system system /sys/module/sco/parameters/disable_esco + chown bluetooth bluetooth /sys/module/hci_smd/parameters/hcismd_set + chown system system /sys/module/radio_iris_transport/parameters/fmsmd_set + chmod 0660 /sys/module/bluetooth_power/parameters/power + chmod 0660 /sys/module/hci_smd/parameters/hcismd_set + chmod 0660 /sys/module/radio_iris_transport/parameters/fmsmd_set + chmod 0660 /sys/class/rfkill/rfkill0/state + chmod 0660 /proc/bluetooth/sleep/proto + chown bluetooth net_bt /dev/ttyHS0 + chmod 0660 /sys/module/hci_uart/parameters/ath_lpm + chmod 0660 /sys/module/hci_uart/parameters/ath_btwrite + chmod 0660 /dev/ttyHS0 + chown bluetooth bluetooth /sys/devices/platform/msm_serial_hs.0/clock + chmod 0660 /sys/devices/platform/msm_serial_hs.0/clock + + chmod 0660 /dev/ttyHS2 + chown bluetooth bluetooth /dev/ttyHS2 + + chown bluetooth net_bt /sys/class/rfkill/rfkill0/device/extldo + chmod 0660 /sys/class/rfkill/rfkill0/device/extldo + + # Mark the copy complete flag to not completed + write /data/misc/radio/copy_complete 0 + chown radio radio /data/misc/radio/copy_complete + chmod 0660 /data/misc/radio/copy_complete + + # File flags for prebuilt ril db file + write /data/misc/radio/prebuilt_db_support 1 + chown radio radio /data/misc/radio/prebuilt_db_support + chmod 0400 /data/misc/radio/prebuilt_db_support + write /data/misc/radio/db_check_done 0 + chown radio radio /data/misc/radio/db_check_done + chmod 0660 /data/misc/radio/db_check_done + + start rmt_storage + + #Create QMUX deamon socket area + mkdir /dev/socket/qmux_radio 0770 radio radio + chmod 2770 /dev/socket/qmux_radio + mkdir /dev/socket/qmux_audio 0770 media audio + chmod 2770 /dev/socket/qmux_audio + mkdir /dev/socket/qmux_bluetooth 0770 bluetooth bluetooth + chmod 2770 /dev/socket/qmux_bluetooth + mkdir /dev/socket/qmux_gps 0770 gps gps + chmod 2770 /dev/socket/qmux_gps + + mkdir /persist/drm 0770 system system + mkdir /persist/bluetooth 0770 bluetooth bluetooth + mkdir /persist/misc 0770 system system + + #Create NETMGR daemon socket area + mkdir /dev/socket/netmgr 0750 radio radio + + setprop wifi.interface wlan0 + + setprop ro.telephony.call_ring.multiple false + + #enable camera read sensors data + setprop persist.camera.gyro.disable 0 + + chmod 0444 /sys/devices/platform/msm_hsusb/gadget/usb_state + + #For bridgemgr daemon to inform the USB driver of the correct transport + chown radio radio /sys/class/android_usb/f_rmnet_smd_sdio/transport + + setprop net.tcp.2g_init_rwnd 10 + + # Assign TCP buffer thresholds to be ceiling value of technology maximums + # Increased technology maximums should be reflected here. + write /proc/sys/net/core/rmem_max 8388608 + write /proc/sys/net/core/wmem_max 8388608 + + #To allow interfaces to get v6 address when tethering is enabled + write /proc/sys/net/ipv6/conf/rmnet0/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet1/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet2/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet3/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet4/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet5/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet6/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet7/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio0/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio1/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio2/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio3/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio4/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio5/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio6/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio7/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_usb0/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_usb1/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_usb2/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_usb3/accept_ra 2 + + # To prevent out of order acknowledgements from making + # connection tracking to treat them as not belonging to + # the connection they belong to. + # Otherwise, a weird issue happens in which some long + # connections on high-throughput links get dropped when + # an ack packet comes out of order + write /proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal 1 + + # Allow access for CCID command/response timeout configuration + chown system system /sys/module/ccid_bridge/parameters/bulk_msg_timeout + + # bond0 used by FST Manager + chown wifi wifi /sys/class/net/bond0/bonding/queue_id + + # FPC home button permissions + chown system system /sys/homebutton/enable + + # Display + chown system graphics /sys/class/graphics/fb1/hpd + chmod 0664 /sys/class/graphics/fb1/hpd + chown system graphics /sys/class/graphics/fb1/res_info + chmod 0664 /sys/class/graphics/fb1/res_info + chown system graphics /sys/class/graphics/fb1/video_mode + chmod 0664 /sys/class/graphics/fb1/video_mode + chown system graphics /sys/class/graphics/fb1/cec/enable + chmod 0664 /sys/class/graphics/fb1/cec/enable + chown system graphics /sys/class/graphics/fb1/cec/logical_addr + chmod 0664 /sys/class/graphics/fb1/cec/logical_addr + chown system graphics /sys/class/graphics/fb1/cec/rd_msg + chmod 0664 /sys/class/graphics/fb1/cec/rd_msg + chown system graphics /sys/class/graphics/fb1/cec/wr_msg + chmod 0600 /sys/class/graphics/fb1/cec/wr_msg + + chown system graphics /sys/class/graphics/fb0/idle_time + chmod 0664 /sys/class/graphics/fb0/idle_time + chown system graphics /sys/class/graphics/fb0/dyn_pu + chmod 0664 /sys/class/graphics/fb0/dyn_pu + chown system graphics /sys/class/graphics/fb0/modes + chmod 0664 /sys/class/graphics/fb0/modes + chown system graphics /sys/class/graphics/fb0/mode + chmod 0664 /sys/class/graphics/fb0/mode + chown system graphics /sys/class/graphics/fb0/msm_cmd_autorefresh_en + chmod 0664 /sys/class/graphics/fb0/msm_cmd_autorefresh_en + + setprop debug.gralloc.enable_fb_ubwc 1 + setprop debug.gralloc.gfx_ubwc_disable 0 + +# msm specific files that need to be created on /data +on post-fs-data + mkdir /tombstones/modem 0771 system system + mkdir /tombstones/lpass 0771 system system + mkdir /tombstones/wcnss 0771 system system + mkdir /tombstones/dsps 0771 system system + mkdir /persist/data/sfs 0700 system system + mkdir /persist/data/tz 0700 system system + mkdir /data/misc/dts 0770 media audio + mkdir /data/misc/hbtp 0750 system system + + #Create directories for Fingerprint + mkdir /data/misc/stargate 0770 system system + mkdir /data/misc/stargate/bg_estimation 0770 system system + mkdir /data/misc/stargate/calib_test 0770 system system + mkdir /data/misc/stargate/database 0770 system system + + # Create directory for TZ Apps + mkdir /data/misc/qsee 0770 system system + + #Create folder for mm-qcamera-daemon + mkdir /data/misc/camera 0770 camera camera + + mkdir /data/media 0770 media_rw media_rw + chown media_rw media_rw /data/media + + mkdir /data/misc/ipa 0700 net_admin net_admin + + mkdir /data/misc/bluetooth 0770 bluetooth bluetooth + + # Create the directories used by the Wireless subsystem + mkdir /data/misc/wifi 0770 wifi wifi + mkdir /data/misc/wifi/sockets 0770 wifi wifi + mkdir /data/misc/wifi/wpa_supplicant 0770 wifi wifi + mkdir /data/misc/dhcp 0750 dhcp system + + #create port-bridge log dir + mkdir /data/misc/port_bridge 0770 radio radio + chmod 0770 /data/misc/port_bridge + + #create netmgr log dir + mkdir /data/misc/netmgr 0770 radio radio + chmod 0770 /data/misc/netmgr + + # Create the directories used by CnE subsystem + mkdir /data/connectivity 0771 system system + chown system system /data/connectivity + + # Create the directories used by DPM subsystem + mkdir /data/dpm 0771 system system + chown system system /data/dpm + + mkdir /data/dpm/nsrm 0771 system system + chown system system /data/dpm/nsrm + + # Create directory used by audio subsystem + mkdir /data/misc/audio 0770 audio audio + + # Create directory for audio delta files + mkdir /data/misc/audio/acdbdata 0770 media audio + mkdir /data/misc/audio/acdbdata/delta 0770 media audio + + # Create directory used by the DASH client + mkdir /data/misc/dash 0770 media audio + + # Create directory used by display clients + mkdir /data/misc/display 0770 system graphics + + # Mounting of persist is moved to 'on emmc-fs' and 'on fs' sections + # We chown/chmod /persist again so because mount is run as root + defaults + chown system system /persist + chmod 0771 /persist + chown system system /persist/WCNSS_qcom_wlan_nv.bin + chmod 0664 /sys/devices/platform/msm_sdcc.1/polling + chmod 0664 /sys/devices/platform/msm_sdcc.2/polling + chmod 0664 /sys/devices/platform/msm_sdcc.3/polling + chmod 0664 /sys/devices/platform/msm_sdcc.4/polling + + # Chown polling nodes as needed from UI running on system server + chown system system /sys/devices/platform/msm_sdcc.1/polling + chown system system /sys/devices/platform/msm_sdcc.2/polling + chown system system /sys/devices/platform/msm_sdcc.3/polling + chown system system /sys/devices/platform/msm_sdcc.4/polling + + #Create the symlink to qcn wpa_supplicant folder for ar6000 wpa_supplicant + mkdir /data/system 0775 system system + #symlink /data/misc/wifi/wpa_supplicant /data/system/wpa_supplicant + + #Create directories for Location services + mkdir /data/misc/location 0770 gps gps + mkdir /data/misc/location/mq 0770 gps gps + mkdir /data/misc/location/xtwifi 0770 gps gps + mkdir /data/misc/location/gpsone_d 0770 system gps + mkdir /data/misc/location/quipc 0770 gps system + mkdir /data/misc/location/gsiff 0770 gps gps + + #Create directory from IMS services + mkdir /data/shared 0755 + chown system system /data/shared + + #Create directory for FOTA + mkdir /data/fota 0771 + chown system system /data/fota + + #Create directory for hostapd + mkdir /data/hostapd 0770 system wifi + + # Create /data/time folder for time-services + mkdir /data/time/ 0700 system system + + mkdir /data/audio/ 0770 media audio + + # Create a folder for audio delta files + mkdir /data/audio/acdbdata 0770 media audio + mkdir /data/audio/acdbdata/delta 0770 media audio + + #Create a folder for SRS to be able to create a usercfg file + mkdir /data/data/media 0770 media media + + #Create FM dir for patchdownloader + mkdir /data/misc/fm 0770 system system + chmod 0770 /data/misc/fm + + # RIDL data + mkdir /data/misc/SelfHost/ 0710 system shell + mkdir /data/misc/SelfHost/QCLogs/ 2750 system shell + mkdir /data/misc/SelfHost/QCLogs/temp/ 0700 system shell + mkdir /data/misc/SelfHost/storage/ 0700 system shell + mkdir /data/misc/SelfHost/Running/ 2750 system shell + mkdir /data/misc/SelfHost/socket/ 2770 system system + + #Create PERFD deamon related dirs + mkdir /data/system/perfd 0770 root system + chmod 2770 /data/system/perfd + + # NFC local data and nfcee xml storage + mkdir /data/nfc 0770 nfc nfc + mkdir /data/nfc/param 0770 nfc nfc + + #Create IOP deamon related dirs + mkdir /data/misc/iop 0770 root system + + #Create SWAP related dirs + mkdir /data/system/swap 0770 root system + chmod 2770 /data/system/swap + + # Force all SSR systems to 'related' so they attempt + # self-recovery without rebooting the device + write /sys/bus/msm_subsys/devices/subsys0/restart_level related + write /sys/bus/msm_subsys/devices/subsys1/restart_level related + write /sys/bus/msm_subsys/devices/subsys2/restart_level related + write /sys/bus/msm_subsys/devices/subsys3/restart_level related + write /sys/bus/msm_subsys/devices/subsys4/restart_level related + + setprop vold.post_fs_data_done 1 + +service charger /charger + class charger + group log + seclabel u:r:healthd:s0 + +# Allow usb charging to be disabled peristently +on property:persist.usb.chgdisabled=1 + write /sys/class/power_supply/battery/charging_enabled 0 + +on property:persist.usb.chgdisabled=0 + write /sys/class/power_supply/battery/charging_enabled 1 + +service perfd /system/vendor/bin/perfd + class main + user root + group root readproc + disabled + socket perfd seqpacket 0666 root system + writepid /dev/cpuset/system-background/tasks + +service qseecomd /system/bin/qseecomd + class core + user root + group root + +service thermal-engine /system/vendor/bin/thermal-engine + class main + user root + socket thermal-send-client stream 0666 system system + socket thermal-recv-client stream 0660 system system + socket thermal-recv-passive-client stream 0666 system system + group root + +service time_daemon /system/bin/time_daemon + class late_start + user root + group root + +service audiod /system/bin/audiod + class late_start + user system + group system + +on property:vold.decrypt=trigger_restart_framework + start config_bt_addr + +on property:persist.env.fastdorm.enabled=true + setprop persist.radio.data_no_toggle 1 + +#start camera server as daemon +service qcamerasvr /system/bin/mm-qcamera-daemon + class late_start + user camera + group camera system inet input graphics + +service cnd /system/bin/cnd + class main + socket cnd stream 660 root inet + +service wcnss-service /system/bin/wcnss_service + class main + user system + group system wifi radio + oneshot + +service adsprpcd /system/bin/adsprpcd + class main + user media + group media + +service irsc_util /system/bin/irsc_util "/etc/sec_config" + class core + user root + oneshot + +service ims_rtp_daemon /system/bin/ims_rtp_daemon + class main + user system + socket ims_rtpd stream 0660 system radio + group radio diag diag inet log + disabled + +on property:sys.ims.DATA_DAEMON_STATUS=1 + start ims_rtp_daemon + +service imscmservice /system/bin/imscmservice + class main + user system + group radio diag diag log + disabled + +on property:sys.ims.DATA_DAEMON_STATUS=1 + start imscmservice + +service imsdatadaemon /system/bin/imsdatadaemon + class main + user system + socket ims_datad stream 0660 system radio + group system wifi radio inet log diag + disabled + +on property:sys.ims.QMI_DAEMON_STATUS=1 + start imsdatadaemon + +service imsqmidaemon /system/bin/imsqmidaemon + class main + user system + socket ims_qmid stream 0660 system radio + group radio log diag + +service rmt_storage /system/bin/rmt_storage + class core + user root + +service tftp_server /system/bin/tftp_server + class core + user root + +service per_mgr /system/bin/pm-service + class core + user system + group system net_raw + +service per_proxy /system/bin/pm-proxy + class core + user system + group system + disabled + +on property:init.svc.per_mgr=running + start per_proxy + +on property:sys.shutdown.requested=* + stop per_proxy + +service config_bt_addr /system/bin/btnvtool -O + class core + user bluetooth + group bluetooth radio + oneshot + +service netmgrd /system/bin/netmgrd + class main + +service ipacm-diag /system/bin/ipacm-diag + class main + user system + socket ipacm_log_file dgram 660 system net_admin + group net_admin qcom_diag + +service ipacm /system/bin/ipacm + class main + user net_admin + group net_admin inet + +service qti /system/vendor/bin/qti + class main + user radio + group radio net_raw qcom_diag usb net_admin + +on property:ro.use_data_netmgrd=false + # netmgr not supported on specific target + stop netmgrd + +# Adjust socket buffer to enlarge TCP receive window for high bandwidth +# but only if ro.data.large_tcp_window_size property is set. +on property:ro.data.large_tcp_window_size=true + write /proc/sys/net/ipv4/tcp_adv_win_scale 2 + +on property:sys.sysctl.tcp_adv_win_scale=* + write /proc/sys/net/ipv4/tcp_adv_win_scale ${sys.sysctl.tcp_adv_win_scale} + +service p2p_supplicant /system/bin/wpa_supplicant \ + -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \ + -I/system/etc/wifi/p2p_supplicant_overlay.conf -N \ + -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ + -I/system/etc/wifi/wpa_supplicant_overlay.conf \ + -O/data/misc/wifi/sockets -puse_p2p_group_interface=1 -dd \ + -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0 + # we will start as root and wpa_supplicant will switch to user wifi + # after setting up the capabilities required for WEXT + # user wifi + # group wifi inet keystore + class main + socket wpa_wlan0 dgram 660 wifi wifi + disabled + oneshot + +service wpa_supplicant /system/bin/wpa_supplicant \ + -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ + -I/system/etc/wifi/wpa_supplicant_overlay.conf \ + -O/data/misc/wifi/sockets -dd \ + -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0 + # we will start as root and wpa_supplicant will switch to user wifi + # after setting up the capabilities required for WEXT + # user wifi + # group wifi inet keystore + class main + socket wpa_wlan0 dgram 660 wifi wifi + disabled + oneshot + +service hostapd /system/bin/hostapd -dd /data/misc/wifi/hostapd.conf + class late_start + user root + group root + oneshot + disabled + +service ril-daemon /system/bin/rild + class main + socket rild stream 660 root radio + socket sap_uim_socket1 stream 660 bluetooth bluetooth + socket rild-debug stream 660 radio system + socket cutback stream 660 media radio + socket wpa_wlan0 dgram 660 wifi wifi + user root + group radio cache inet misc audio log diag qcom_diag net_raw wifi compass + writepid /dev/cpuset/system-background/tasks + +service ril-daemon2 /system/bin/rild -c 2 + class main + socket rild2 stream 660 root radio + socket rild-debug2 stream 660 radio system + user root + group radio cache inet misc audio sdcard_r sdcard_rw qcom_diag diag log + +service rild2-wrapper /system/bin/sh /system/etc/init.qcom.ril.sh + class late_start + user root + group root + oneshot + +service msm_irqbalance /system/bin/msm_irqbalance -f /system/vendor/etc/msm_irqbalance.conf + class core + user root + group root + +on charger + wait /dev/block/bootdevice/by-name/system + mount ext4 /dev/block/bootdevice/by-name/system /system ro barrier=1 + load_all_props + setprop sys.usb.configfs 0 + setprop persist.sys.usb.config mass_storage + write /sys/class/leds/white/trigger "battery-full" + +on property:sys.boot_completed=1 + write /dev/kmsg "Boot completed " + setprop sys.io.scheduler bfq + + # scheduler settings + write /proc/sys/kernel/sched_window_stats_policy 3 + write /proc/sys/kernel/sched_ravg_hist_size 3 + + # task packing settings + write /sys/devices/system/cpu/cpu0/sched_static_cpu_pwr_cost 0 + write /sys/devices/system/cpu/cpu1/sched_static_cpu_pwr_cost 0 + write /sys/devices/system/cpu/cpu2/sched_static_cpu_pwr_cost 0 + write /sys/devices/system/cpu/cpu3/sched_static_cpu_pwr_cost 0 + write /sys/devices/system/cpu/cpu4/sched_static_cpu_pwr_cost 0 + write /sys/devices/system/cpu/cpu5/sched_static_cpu_pwr_cost 0 + write /sys/devices/system/cpu/cpu6/sched_static_cpu_pwr_cost 0 + write /sys/devices/system/cpu/cpu7/sched_static_cpu_pwr_cost 0 + + # init task load, restrict wakeups to preferred cluster + write /proc/sys/kernel/sched_init_task_load 15 + + # spill load is set to 100% by default in the kernel + write /proc/sys/kernel/sched_spill_nr_run 3 + + # Apply inter-cluster load balancer restrictions + write /proc/sys/kernel/sched_restrict_cluster_spill 1 + + write /sys/class/devfreq/qcom,mincpubw/governor "cpufreq" + + # disable thermal & BCL core_control to update interactive gov settings + write /sys/module/msm_thermal/core_control/enabled 0 + + # governor settings + write /sys/devices/system/cpu/cpu0/online 1 + write /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor "interactive" + write /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay "19000 1401600:39000" + write /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load 85 + write /sys/devices/system/cpu/cpufreq/interactive/timer_rate 20000 + write /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq 1401600 + write /sys/devices/system/cpu/cpufreq/interactive/io_is_busy 0 + write /sys/devices/system/cpu/cpufreq/interactive/target_loads "85 1401600:80" + write /sys/devices/system/cpu/cpufreq/interactive/min_sample_time 39000 + write /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq 652800 + + # re-enable thermal & BCL core_control now + write /sys/module/msm_thermal/core_control/enabled 1 + + # Bring up all cores online + write /sys/devices/system/cpu/cpu1/online 1 + write /sys/devices/system/cpu/cpu2/online 1 + write /sys/devices/system/cpu/cpu3/online 1 + write /sys/devices/system/cpu/cpu4/online 1 + write /sys/devices/system/cpu/cpu5/online 1 + write /sys/devices/system/cpu/cpu6/online 1 + write /sys/devices/system/cpu/cpu7/online 1 + + # Enable low power modes + write /sys/module/lpm_levels/parameters/sleep_disabled 0 + + # SMP scheduler + write /proc/sys/kernel/sched_upmigrate 100 + write /proc/sys/kernel/sched_downmigrate 100 + + # Enable sched guided freq control + write /sys/devices/system/cpu/cpufreq/interactive/use_sched_load 1 + write /sys/devices/system/cpu/cpufreq/interactive/use_migration_notif 1 + write /proc/sys/kernel/sched_freq_inc_notify 200000 + write /proc/sys/kernel/sched_freq_dec_notify 200000 + + # Log kernel wake-up source + write /sys/module/msm_show_resume_irq/parameters/debug_mask 1 + + #Reset read ahead for dm-1 to 128KB + write /sys/block/dm-1/queue/read_ahead_kb 128 + #Reset the "read ahead" setting for system patition + # result: ext4: 32KB, dm_verity:64KB, block layer: 128KB + write /sys/fs/ext4/dm-0/inode_readahead_blks 8 + write /sys/module/dm_verity/parameters/prefetch_cluster 65536 + + write /sys/block/mmcblk0/bdi/read_ahead_kb 128 + write /sys/block/mmcblk0/queue/read_ahead_kb 128 + write /sys/block/dm-0/queue/read_ahead_kb 128 + write /sys/block/dm-1/queue/read_ahead_kb 128 + #WDSP FW boot sysfs node used by STHAL + chown media audio /sys/kernel/wdsp0/boot + rm /data/system/perfd/default_values + start perfd diff --git a/rootdir/etc/init.qcom.ril.sh b/rootdir/etc/init.qcom.ril.sh new file mode 100644 index 0000000..d9637f2 --- /dev/null +++ b/rootdir/etc/init.qcom.ril.sh @@ -0,0 +1,8 @@ +#!/system/bin/sh +export PATH=/system/xbin:$PATH + +multisim=`getprop persist.radio.multisim.config` + +if [ "$multisim" = "dsds" ] || [ "$multisim" = "dsda" ]; then + start ril-daemon2 +fi diff --git a/rootdir/etc/ueventd.qcom.rc b/rootdir/etc/ueventd.qcom.rc new file mode 100644 index 0000000..b780503 --- /dev/null +++ b/rootdir/etc/ueventd.qcom.rc @@ -0,0 +1,359 @@ +# Copyright (c) 2012-2015, 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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. +# + +/dev/null 0666 root root +/dev/zero 0666 root root +/dev/full 0666 root root +/dev/ptmx 0666 root root +/dev/tty 0666 root root +/dev/random 0666 root root +/dev/urandom 0666 root root + +/dev/ashmem 0666 root root +/dev/binder 0666 root root +/dev/tspdrv 0666 root root +/dev/ttyHSL0 0660 radio system +# logger should be world writable (for logging) but not readable +/dev/log/* 0666 root log + +# the DIAG device node is not world writable/readable. +/dev/diag 0660 system qcom_diag +/dev/ttydiag0 0660 system qcom_diag +/dev/ttydiag1 0660 system qcom_diag +/dev/ttydiag2 0660 system qcom_diag + +/dev/genlock 0666 system system +/dev/kgsl 0666 system system +/dev/kgsl-3d0 0666 system system +/dev/kgsl-2d0 0666 root root +/dev/kgsl-2d1 0666 root root +/dev/ion 0664 system system +/dev/rtc0 0660 system system +/dev/smd0 0660 system system +/dev/smd4 0660 system system +/dev/smd_cxm_qmi 0640 radio radio +/dev/smd5 0660 system system +/dev/smd6 0660 system system +/dev/smd7 0660 bluetooth bluetooth +/dev/ccid_bridge 0660 system system +/dev/ipa 0660 system net_admin +/dev/wwan_ioctl 0660 system net_admin +/dev/ipaNatTable 0660 net_admin net_admin +/dev/rmnet_ctrl 0660 usb usb +/dev/dpl_ctrl 0660 usb usb + +#permissions for CSVT +/dev/smd11 0660 radio radio + +/dev/radio0 0640 system system +/dev/rfcomm0 0660 bluetooth bluetooth +/dev/ttyUSB0 0660 bluetooth bluetooth +/dev/smdcntl0 0640 radio radio +/dev/smdcntl1 0640 radio radio +/dev/smdcntl2 0640 radio radio +/dev/smdcntl3 0640 radio radio +/dev/smdcntl4 0640 radio radio +/dev/smdcntl5 0640 radio radio +/dev/smdcntl6 0640 radio radio +/dev/smdcntl7 0640 radio radio +/dev/smdcntl8 0640 radio radio +/dev/smdcnt_rev0 0640 radio radio +/dev/smdcnt_rev1 0640 radio radio +/dev/smdcnt_rev2 0640 radio radio +/dev/smdcnt_rev3 0640 radio radio +/dev/smdcnt_rev4 0640 radio radio +/dev/smdcnt_rev5 0640 radio radio +/dev/smdcnt_rev6 0640 radio radio +/dev/smdcnt_rev7 0640 radio radio +/dev/smdcnt_rev8 0640 radio radio +/dev/smuxctl32 0640 radio radio +/dev/sdioctl0 0640 radio radio +/dev/sdioctl1 0640 radio radio +/dev/sdioctl2 0640 radio radio +/dev/sdioctl3 0640 radio radio +/dev/sdioctl4 0640 radio radio +/dev/sdioctl5 0640 radio radio +/dev/sdioctl6 0640 radio radio +/dev/sdioctl7 0640 radio radio +/dev/sdioctl8 0640 radio radio +/dev/rmnet_mux_ctrl 0640 radio radio +/dev/hsicctl0 0640 radio radio +/dev/hsicctl1 0640 radio radio +/dev/hsicctl2 0640 radio radio +/dev/hsicctl3 0640 radio radio +/dev/hsicctl4 0640 radio radio +/dev/hsicctl5 0640 radio radio +/dev/hsicctl6 0640 radio radio +/dev/hsicctl7 0640 radio radio +/dev/hsicctl8 0640 radio radio +/dev/hsicctl9 0640 radio radio +/dev/hsicctl10 0640 radio radio +/dev/hsicctl11 0640 radio radio +/dev/hsicctl12 0640 radio radio +/dev/hsicctl13 0640 radio radio +/dev/hsicctl14 0640 radio radio +/dev/hsicctl15 0640 radio radio +/dev/hsicctl16 0640 radio radio +/dev/mhi_pipe_14 0640 radio radio +/dev/mhi_pipe_16 0640 radio radio +/dev/mhi_pipe_32 0640 radio radio +/dev/at_usb0 0640 radio radio +/dev/at_mdm0 0640 radio radio +/dev/video* 0660 system camera +/dev/v4l2-hal-ctrl 0660 system camera +/dev/media* 0660 system camera +/dev/v4l-subdev* 0660 system camera +/dev/qseecom 0660 system drmrpc +/dev/qsee_ipc_irq_spss 0660 system drmrpc +/dev/seemplog 0660 system system +/dev/pft 0660 system drmrpc +/dev/spcom 0660 system system +/dev/sp_kernel 0660 system system +/dev/sp_ssr 0660 system system +/dev/sp_keymaster 0660 system system +/dev/cryptoapp 0660 system system +/dev/gemini0 0660 system camera +/dev/jpeg0 0660 system camera +/dev/jpeg1 0660 system camera +/dev/jpeg2 0660 system camera +/dev/jpeg3 0660 system camera +/dev/adsprpc-smd 0664 system system +/dev/system_health_monitor 0644 radio system +/dev/mdss_rotator 0664 system system +# wlan +/dev/wcnss_wlan 0660 system system +/dev/wcnss_ctrl 0660 system system +/sys/devices/soc/a000000.qcom,wcnss-wlan/net/wlan0/queues/rx-* rps_cpus 0660 system system +/sys/devices/soc/a000000.qcom,wcnss-wlan/net/p2p0/queues/rx-* rps_cpus 0660 system system +/dev/msm_camera/* 0660 system camera +/dev/gemini/ 0660 system camera +/dev/mercury0 0660 system camera +/dev/msm_vidc_reg 0660 system audio +/dev/msm_vidc_dec 0660 system audio +/dev/msm_vidc_dec_sec 0660 system audio +/dev/msm_vidc_enc 0660 system audio +/dev/msm_rotator 0660 system system +/dev/hw_random 0600 root root + +#permissions for audio +/dev/wcd-dsp-glink 0660 system audio +/dev/audio_slimslave 0660 system audio +/dev/msm_qcelp 0660 system audio +/dev/msm_evrc 0660 system audio +/dev/msm_wma 0660 system audio +/dev/msm_wmapro 0660 system audio +/dev/msm_alac 0660 system audio +/dev/msm_ape 0660 system audio +/dev/msm_amrnb 0660 system audio +/dev/msm_amrwb 0660 system audio +/dev/msm_amrwbplus 0660 system audio +/dev/msm_aac 0660 system audio +/dev/msm_multi_aac 0660 system audio +/dev/msm_aac_in 0660 system audio +/dev/msm_qcelp_in 0660 system audio +/dev/msm_evrc_in 0660 system audio +/dev/msm_amrnb_in 0640 system audio +/dev/msm_a2dp_in 0660 system audio +/dev/msm_ac3 0660 system audio +/dev/msm_audio_cal 0660 system audio +/dev/msm_hweffects 0660 system audio +/dev/msm_cad 0660 system audio +/dev/msm_fm 0660 system audio +/dev/msm_mvs 0660 system audio +/dev/msm_pcm_lp_dec 0660 system audio +/dev/msm_preproc_ctl 0660 system audio +/dev/msm_rtac 0660 system audio +/dev/msm_voicememo 0660 system audio +/dev/smd3 0660 bluetooth net_bt_stack +/dev/smd2 0660 bluetooth net_bt_stack +/dev/ttyHSL1 0660 system system +/dev/ttyHS1 0660 system system +/dev/mdm 0660 system radio +/sys/devices/virtual/smdpkt/smdcntl* open_timeout 0664 radio radio +/dev/sdio_tty_ciq_00 0660 system system +/dev/tty_sdio_00 0660 system system +/dev/ttyGS0 0660 system system +/dev/i2c-5 0660 media media +/dev/voice_svc 0660 system audio +/dev/avtimer 0660 system audio + +# DVB devices +/dev/dvb/adapter0/demux* 0440 media media +/dev/dvb/adapter0/dvr* 0660 media media +/dev/dvb/adapter0/video* 0660 media media + +# Block devices +/dev/block/bootdevice/by-name/hob 0660 radio radio +/dev/block/bootdevice/by-name/dhob 0660 radio radio +/dev/block/bootdevice/by-name/clogo 0660 root mot_tcmd +/dev/block/bootdevice/by-name/cid 0660 root mot_tcmd +/dev/block/bootdevice/by-name/logs 0640 root log +/dev/block/bootdevice/by-name/utags 0660 mot_tcmd system +/dev/block/bootdevice/by-name/utagsBackup 0660 mot_tcmd system + +# Broadcast devices +/dev/tsc_mux0 0660 media media +/dev/tsc_ci0 0660 media media + +# sensors +/sys/devices/i2c-12/12-* pollrate_ms 0664 system system +/sys/devices/f9925000.i2c/i2c-0/0-* enable 0660 input system +/sys/devices/f9925000.i2c/i2c-0/0-* poll_delay 0660 input system +/sys/devices/soc/78b6000.i2c/i2c-0/0-* enable 0660 input system +/sys/devices/soc/78b6000.i2c/i2c-0/0-* poll_delay 0660 input system +/sys/devices/soc/78b6000.i2c/i2c-0/0-* enable_wakeup 0660 input system +/sys/devices/soc/78b6000.i2c/i2c-0/0-* max_latency 0660 input system +/sys/devices/soc/78b6000.i2c/i2c-0/0-* flush 0660 input system +/sys/devices/soc/78b6000.i2c/i2c-0/0-* calibrate 0660 input system +/sys/devices/soc/78b5000.i2c/i2c-1/1-* enable 0660 input system +/sys/devices/soc/78b5000.i2c/i2c-1/1-* poll_delay 0660 input system +/sys/devices/soc/78b5000.i2c/i2c-1/1-* enable_wakeup 0660 input system +/sys/devices/soc/78b5000.i2c/i2c-1/1-* max_latency 0660 input system +/sys/devices/soc/78b5000.i2c/i2c-1/1-* flush 0660 input system +/sys/devices/soc/78b5000.i2c/i2c-1/1-* calibrate 0660 input system +/sys/devices/virtual/optical_sensors/proximity ps_adc 0660 input system +/sys/devices/virtual/optical_sensors/proximity ps_poll_delay 0660 input system +/sys/devices/virtual/optical_sensors/lightsensor ls_auto 0660 input system +/sys/devices/virtual/optical_sensors/lightsensor ls_poll_delay 0660 input system +/sys/devices/virtual/input/input* poll 0660 input system +/sys/devices/virtual/input/input* pollrate_ms 0660 input system +/sys/devices/soc/78b7000.i2c/i2c-3/3-0020/input/input* secure_touch 0440 system drmrpc +/sys/devices/soc/78b7000.i2c/i2c-3/3-0020/input/input* secure_touch_enable 0660 system drmrpc +/sys/devices/soc/78b7000.i2c/i2c-3/3-0038/input/input* secure_touch 0440 system drmrpc +/sys/devices/soc/78b7000.i2c/i2c-3/3-0038/input/input* secure_touch_enable 0660 system drmrpc +/sys/devices/soc/78b7000.i2c/i2c-3/3-004b/input/input* secure_touch 0440 system drmrpc +/sys/devices/soc/78b7000.i2c/i2c-3/3-004b/input/input* secure_touch_enable 0660 system drmrpc +/sys/devices/soc/c179000.i2c/i2c-5/5-0020/input/input* secure_touch 0440 system drmrpc +/sys/devices/soc/c179000.i2c/i2c-5/5-0020/input/input* secure_touch_enable 0660 system drmrpc + +# laser sensor access +/sys/devices/virtual/input/input* enable_ps_sensor 0660 system system +/sys/devices/virtual/input/input* set_delay_ms 0660 system system + +# vm_bms +/dev/vm_bms 0660 system system +/dev/battery_data 0660 system system + +# wlan +/dev/wcnss_wlan 0660 system system +/dev/wcnss_ctrl 0660 system system +/sys/devices/soc/600000.qcom,pcie/pci0000:00/0000:00:00.0/0000:01:00.0/net/wlan0/queues/rx-* rps_cpus 0660 system system +/sys/devices/soc/600000.qcom,pcie/pci0000:00/0000:00:00.0/0000:01:00.0/net/p2p0/queues/rx-* rps_cpus 0660 system system + +#nfc permissions +/dev/nfc-nci 0660 nfc nfc +/dev/nq-nci 0660 nfc nfc +/dev/assd 0660 nfc nfc +/dev/bcm2079x-i2c 0660 nfc nfc +/dev/pn544 0660 nfc nfc + +# UIO devices +/dev/uio0 0660 system system +/dev/uio1 0660 system system +/dev/uio2 0660 system system + +# SSR devices +/dev/subsys_* 0640 system system + +# Add device block for FRP +/dev/block/platform/soc/7464900.sdhci/by-name/frp 0600 system system +/dev/block/platform/soc/624000.ufshc/by-name/frp 0600 system system +/dev/block/bootdevice/by-name/frp 0600 system system + +# Ultrasound device +/dev/usf1 0660 system system + +# Ramdump devices +/dev/ramdump* 0640 system system + +# Fingerprint device +/dev/qbt1000 0660 system system + +#ImproveTouch device +/dev/hbtp_input 0660 system system +/dev/hbtp_vm 0660 system system + +# Add device block for FRP +/dev/block/bootdevice/by-name/frp 0600 system system + +# I2C +/dev/i2c-* 0660 system system + +#JOT fixture devices for AMPS factory testing +/dev/hidraw0 0660 root mot_tcmd +/dev/hidraw1 0660 root mot_tcmd + +# MOD device +/sys/devices/soc/75b5000.i2c/i2c-7/7-0072 irq_enable 0660 mot_tcmd mot_tcmd +/sys/devices/soc/0.apba_ctrl apba_enable 0660 mot_tcmd mot_mod +/sys/devices/soc/0.apba_ctrl apba_mode 0660 mot_tcmd mot_mod +/sys/devices/soc/0.apba_ctrl flash_partition 0220 mot_tcmd mot_mod +/sys/devices/soc/0.apba_ctrl unipro_mid 0440 root mot_mod +/sys/devices/soc/0.apba_ctrl unipro_pid 0440 root mot_mod +/sys/devices/soc/0.apba_ctrl vid 0440 root mot_mod +/sys/devices/soc/0.apba_ctrl pid 0440 root mot_mod +/sys/devices/soc/0.apba_ctrl fw_version 0440 root mot_mod +/sys/devices/soc/0.apba_ctrl fw_version_str 0440 root mot_mod +/sys/devices/soc/soc:muc_svc@0/mods_interfaces/* hotplug 0660 root mot_mod +/sys/devices/soc/soc:muc_svc@0/mods_interfaces/* uevent 0660 root mot_mod +/sys/devices/soc/soc:muc_svc@0/mods_interfaces/* current_limit 0220 root mot_mod +/sys/devices/soc/soc:muc_svc@0/mods_interfaces/* rtc_sync 0220 root mot_mod +/sys/devices/soc/soc:muc_svc@0 flashmode 0660 root mot_mod +/sys/devices/soc/soc:muc_svc@0 reset 0660 root mot_mod +/sys/devices/soc/0.muc/0.muc:muc_svc@0/mods_interfaces/* hotplug 0660 root mot_mod +/sys/devices/soc/0.muc/0.muc:muc_svc@0/mods_interfaces/* uevent 0660 root mot_mod +/sys/devices/soc/0.muc/0.muc:muc_svc@0 flashmode 0660 root mot_mod +/sys/devices/platform/mods_ap uevent 0660 root mot_mod +/sys/devices/platform/mods_ap/* uevent 0660 root mot_mod +/sys/devices/platform/mods_ap/greybus1 uevent 0664 root mot_mod + +# MOD display device +/sys/devices/platform/mods_ap/greybus1/*/*/display/display* state 0660 root mot_mod +/sys/devices/platform/mods_ap/greybus1/*/*/display/display* config 0444 root mot_mod +/sys/devices/platform/mods_ap/greybus1/*/*/display/display* notification 0660 root mot_mod + +# MOD light device +/sys/devices/platform/mods_ap/greybus1/*/*/leds/mod_light*::backlight brightness 0660 root mot_mod + +# RAW device +/dev/gbraw* 0660 root mot_mod +# Audio device +/sys/devices/platform/mods_codec.0 uevent 0660 root mot_mod +/sys/devices/platform/mods_codec.0/* uevent 0660 root mot_mod + +# MOD camera device +/dev/mot_camera_ext* 0660 system camera +/sys/devices/virtual/video4linux/mot_camera_ext* open_mode 0660 system camera +/sys/devices/virtual/video4linux/mot_camera_ext* uevent 0660 root mot_mod +/sys/devices/virtual/video4linux/video* open_mode 0660 system camera +/sys/devices/virtual/video4linux/video* uevent 0660 root mot_mod + +# Laser device +/dev/laser 0660 system camera + +#DTV +/dev/isdbt 0660 mot_dtv mot_dtv diff --git a/sepolicy/adspd.te b/sepolicy/adspd.te new file mode 100644 index 0000000..e6cee41 --- /dev/null +++ b/sepolicy/adspd.te @@ -0,0 +1,13 @@ +type adspd, domain, domain_deprecated; +type adspd_exec, exec_type, file_type; +init_daemon_domain(adspd) + +allow adspd audio_device:chr_file { ioctl open read write }; +allow adspd audio_device:dir search; +allow adspd input_device:chr_file { ioctl open read }; +allow adspd input_device:dir search; +allow adspd sysfs_adsp:file write; +# The below one is WRONG +allow adspd sysfs:file write; + +set_prop(adspd, adspd_prop) diff --git a/sepolicy/cameraserver.te b/sepolicy/cameraserver.te new file mode 100644 index 0000000..d28a479 --- /dev/null +++ b/sepolicy/cameraserver.te @@ -0,0 +1,2 @@ +# Shouldn't do this here +allow cameraserver self:netlink_kobject_uevent_socket { read bind create setopt }; diff --git a/sepolicy/device.te b/sepolicy/device.te new file mode 100644 index 0000000..cd97148 --- /dev/null +++ b/sepolicy/device.te @@ -0,0 +1 @@ +type laser_device, dev_type; diff --git a/sepolicy/file.te b/sepolicy/file.te new file mode 100644 index 0000000..39dce8c --- /dev/null +++ b/sepolicy/file.te @@ -0,0 +1,12 @@ +# FSG +type fsg_file, fs_type, contextmount_type; + +# RIL +type netmgr_data_file, file_type, data_file_type; + +# sysfs +type sysfs_adsp, fs_type, sysfs_type; +type sysfs_homebutton, fs_type, sysfs_type; +type sysfs_mmi_fp, fs_type, sysfs_type; +type sysfs_mmi_laser, fs_type, sysfs_type; +type sysfs_mmi_touch, fs_type, sysfs_type; diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts new file mode 100644 index 0000000..8cccea9 --- /dev/null +++ b/sepolicy/file_contexts @@ -0,0 +1,39 @@ +# ADSP +/sys/kernel/aov(/.*)? u:object_r:sysfs_adsp:s0 + +# Binaries +/system/bin/adspd u:object_r:adspd_exec:s0 +/system/bin/init\.mmi\.boot\.sh u:object_r:mmi_boot_exec:s0 +/system/bin/init\.mmi\.laser\.sh u:object_r:mmi_laser_exec:s0 +/system/bin/init\.mmi\.touch\.sh u:object_r:mmi_touch_sh_exec:s0 +/system/bin/motosh u:object_r:sensor_hub_exec:s0 + +# Camera +/sys/kernel/range/offset u:object_r:sysfs_mmi_laser:s0 + +# CMActions +/sys/homebutton/enable u:object_r:sysfs_homebutton:s0 + +# Fingerprint +/data/.fps(/.*)? u:object_r:fingerprintd_data_file:s0 +/data/fpc u:object_r:fingerprintd_data_file:s0 +/sys/devices/soc/7af8000\.spi/spi_master/spi8/spi8\.0(/.*)? u:object_r:sysfs_mmi_fp:s0 + +# mmi_touch related /sys files +/sys/devices/soc/78b7000\.i2c/i2c-3/3-0020(/.*)? u:object_r:sysfs_mmi_touch:s0 + +# Partitions +/dev/block/bootdevice/by-name/cache u:object_r:cache_block_device:s0 +/dev/block/bootdevice/by-name/frp u:object_r:frp_block_device:s0 +/dev/block/bootdevice/by-name/metadata u:object_r:metadata_block_device:s0 +/dev/block/bootdevice/by-name/persist u:object_r:persist_block_device:s0 + +# RIL +/data/misc/netmgr(/.*)? u:object_r:netmgr_data_file:s0 + +# Sensors +/dev/laser u:object_r:laser_device:s0 +/dev/mmi_sys_temp u:object_r:thermal_device:s0 +/dev/motosh u:object_r:sensors_device:s0 +/dev/motosh_as u:object_r:sensors_device:s0 +/dev/motosh_ms u:object_r:sensors_device:s0 diff --git a/sepolicy/fingerprintd.te b/sepolicy/fingerprintd.te new file mode 100644 index 0000000..626519a --- /dev/null +++ b/sepolicy/fingerprintd.te @@ -0,0 +1,9 @@ +allow fingerprintd firmware_file:dir search; +allow fingerprintd firmware_file:file { getattr open read }; +allow fingerprintd fingerprintd_data_file:dir { add_name getattr remove_name write }; +allow fingerprintd fingerprintd_data_file:file { append create getattr open setattr unlink }; +allow fingerprintd fingerprintd_data_file:sock_file { create unlink }; +allow fingerprintd sysfs_mmi_fp:dir { open read search }; +allow fingerprintd sysfs_mmi_fp:file rw_file_perms; +allow fingerprintd system_data_file:sock_file unlink; +allow fingerprintd tee_device:chr_file { ioctl open read write }; diff --git a/sepolicy/init.te b/sepolicy/init.te new file mode 100644 index 0000000..5e24563 --- /dev/null +++ b/sepolicy/init.te @@ -0,0 +1,21 @@ +allow init audio_device:chr_file { write ioctl }; +allow init input_device:chr_file ioctl; +allow init sensors_device:chr_file { write ioctl }; +allow init tee_device:chr_file { write ioctl }; + +allow init servicemanager:binder { transfer call }; +allow init system_server:binder call; + +allow init property_socket:sock_file write; +allow init socket_device:sock_file { create setattr unlink }; + +allow init system_data_file:file { rename append }; +allow init firmware_file:dir mounton; + +# ptt_socket_app +allow init dnsproxyd_socket:sock_file write; +allow init netd:unix_stream_socket connectto; +allow init self:netlink_socket { read write getattr connect }; + +allow init debugfs:file write; +allow init persist_file:filesystem { getattr mount relabelfrom relabelto }; diff --git a/sepolicy/mediacodec.te b/sepolicy/mediacodec.te new file mode 100644 index 0000000..799c2ea --- /dev/null +++ b/sepolicy/mediacodec.te @@ -0,0 +1 @@ +allow mediacodec firmware_file:file { open read }; diff --git a/sepolicy/mediadrmserver.te b/sepolicy/mediadrmserver.te new file mode 100644 index 0000000..296f1ee --- /dev/null +++ b/sepolicy/mediadrmserver.te @@ -0,0 +1,2 @@ +allow mediadrmserver firmware_file:dir search; +allow mediadrmserver firmware_file:file r_file_perms; diff --git a/sepolicy/mediaserver.te b/sepolicy/mediaserver.te new file mode 100644 index 0000000..252b0ef --- /dev/null +++ b/sepolicy/mediaserver.te @@ -0,0 +1,2 @@ +allow mediaserver persist_file:dir search; +allow mediaserver persist_file:file { read getattr open }; diff --git a/sepolicy/mm-qcamerad.te b/sepolicy/mm-qcamerad.te new file mode 100644 index 0000000..6e4a8c9 --- /dev/null +++ b/sepolicy/mm-qcamerad.te @@ -0,0 +1,4 @@ +allow mm-qcamerad laser_device:chr_file { read write ioctl open }; +allow mm-qcamerad persist_file:dir search; +allow mm-qcamerad persist_file:file { read getattr open }; +allow mm-qcamerad system_data_file:dir read; diff --git a/sepolicy/mmi_boot.te b/sepolicy/mmi_boot.te new file mode 100644 index 0000000..8a6ea1a --- /dev/null +++ b/sepolicy/mmi_boot.te @@ -0,0 +1,16 @@ +type mmi_boot, domain, domain_deprecated; +type mmi_boot_exec, exec_type, file_type; +init_daemon_domain(mmi_boot) + +# shell scripts need to execute /system/bin/sh +allow mmi_boot shell_exec:file rx_file_perms; +allow mmi_boot toolbox_exec:file rx_file_perms; + +allow mmi_boot radio_data_file:dir { add_name search write }; +allow mmi_boot radio_data_file:file { create setattr }; +allow mmi_boot radio_data_file:file rw_file_perms; +allow mmi_boot self:capability chown; +allow mmi_boot self:capability dac_override; +allow mmi_boot sysfs_socinfo:file write; + +set_prop(mmi_boot, hw_rev_prop); diff --git a/sepolicy/mmi_laser.te b/sepolicy/mmi_laser.te new file mode 100644 index 0000000..efabb70 --- /dev/null +++ b/sepolicy/mmi_laser.te @@ -0,0 +1,15 @@ +type mmi_laser, domain, domain_deprecated; +type mmi_laser_exec, exec_type, file_type; +init_daemon_domain(mmi_laser) + +# shell scripts need to execute /system/bin/sh +allow mmi_laser shell_exec:file rx_file_perms; +allow mmi_laser toolbox_exec:file rx_file_perms; + +# Logs to /dev/kmsg +allow mmi_laser kmsg_device:chr_file w_file_perms; + +allow mmi_laser persist_file:dir search; +allow mmi_laser persist_file:file r_file_perms; +allow mmi_laser self:capability dac_override; +allow mmi_laser sysfs_mmi_laser:file rw_file_perms; diff --git a/sepolicy/mmi_touch_te.te b/sepolicy/mmi_touch_te.te new file mode 100644 index 0000000..225e34c --- /dev/null +++ b/sepolicy/mmi_touch_te.te @@ -0,0 +1,27 @@ +type mmi_touch_sh, domain; +type mmi_touch_sh_exec, exec_type, file_type; +init_daemon_domain(mmi_touch_sh) + +# shell scripts need to execute /system/bin/sh +allow mmi_touch_sh shell_exec:file rx_file_perms; +allow mmi_touch_sh toolbox_exec:file rx_file_perms; + +# Logs to /dev/kmsg +allow mmi_touch_sh kmsg_device:chr_file w_file_perms; + +# Write to /sys/path/to/firmware/forcereflash +# Read from /sys/path/to/firmware/poweron (and others) +allow mmi_touch_sh sysfs_mmi_touch:file rw_file_perms; +allow mmi_touch_sh sysfs_mmi_touch:file setattr; +allow mmi_touch_sh sysfs_mmi_touch:dir search; +allow mmi_touch_sh system_file:dir r_file_perms; +allow mmi_touch_sh self:capability chown; + +# WRONG +allow mmi_touch_sh sysfs:dir r_dir_perms; +allow mmi_touch_sh sysfs:file rw_file_perms; +allow mmi_touch_sh sysfs:file setattr; +allow mmi_touch_sh sysfs:lnk_file getattr; + +set_prop(mmi_touch_sh, touch_prop); +set_prop(mmi_touch_sh, hw_rev_prop); diff --git a/sepolicy/netmgrd.te b/sepolicy/netmgrd.te new file mode 100644 index 0000000..a317d4f --- /dev/null +++ b/sepolicy/netmgrd.te @@ -0,0 +1,4 @@ +allow netmgrd netmgr_data_file:dir { add_name search write }; +allow netmgrd netmgr_data_file:file create; +allow netmgrd netmgr_data_file:file rw_file_perms; +allow netmgrd self:capability dac_override; diff --git a/sepolicy/per_mgr.te b/sepolicy/per_mgr.te new file mode 100644 index 0000000..6d75682 --- /dev/null +++ b/sepolicy/per_mgr.te @@ -0,0 +1 @@ +allow per_mgr self:capability net_raw; diff --git a/sepolicy/persist_file.te b/sepolicy/persist_file.te new file mode 100644 index 0000000..a55225e --- /dev/null +++ b/sepolicy/persist_file.te @@ -0,0 +1 @@ +allow persist_file self:filesystem associate; diff --git a/sepolicy/priv_app.te b/sepolicy/priv_app.te new file mode 100644 index 0000000..ad63ca4 --- /dev/null +++ b/sepolicy/priv_app.te @@ -0,0 +1 @@ +allow priv_app device:dir r_dir_perms; diff --git a/sepolicy/property.te b/sepolicy/property.te new file mode 100644 index 0000000..9d80ab6 --- /dev/null +++ b/sepolicy/property.te @@ -0,0 +1,4 @@ +type adspd_prop, property_type; +type motosh_prop, property_type; +type hw_rev_prop, property_type; +type touch_prop, property_type; diff --git a/sepolicy/property_contexts b/sepolicy/property_contexts new file mode 100644 index 0000000..b3bd9a5 --- /dev/null +++ b/sepolicy/property_contexts @@ -0,0 +1,5 @@ +hw.aov.disable_hotword u:object_r:adspd_prop:s0 +hw.aov.hotword_dsp_path u:object_r:adspd_prop:s0 +hw.motosh.booted u:object_r:motosh_prop:s0 +ro.hw.revision u:object_r:hw_rev_prop:s0 +hw.touch.status u:object_r:touch_prop:s0 diff --git a/sepolicy/rfs_access.te b/sepolicy/rfs_access.te new file mode 100644 index 0000000..f4264c9 --- /dev/null +++ b/sepolicy/rfs_access.te @@ -0,0 +1 @@ +allow rfs_access self:capability net_raw; diff --git a/sepolicy/rild.te b/sepolicy/rild.te new file mode 100644 index 0000000..511ab64 --- /dev/null +++ b/sepolicy/rild.te @@ -0,0 +1,2 @@ +allow rild persist_file:dir search; +allow rild persist_file:file rw_file_perms; diff --git a/sepolicy/rmt_storage.te b/sepolicy/rmt_storage.te new file mode 100644 index 0000000..d4aa68b --- /dev/null +++ b/sepolicy/rmt_storage.te @@ -0,0 +1,3 @@ +allow rmt_storage fsg_file:dir search; +allow rmt_storage fsg_file:file { read open }; +allow rmt_storage self:capability dac_override; diff --git a/sepolicy/sensor_hub.te b/sepolicy/sensor_hub.te new file mode 100644 index 0000000..e0e5ef8 --- /dev/null +++ b/sepolicy/sensor_hub.te @@ -0,0 +1,6 @@ +type sensor_hub, domain, domain_deprecated; +type sensor_hub_exec, exec_type, file_type; +init_daemon_domain(sensor_hub) + +allow sensor_hub sensors_device:chr_file rw_file_perms; +set_prop(sensor_hub, motosh_prop) diff --git a/sepolicy/system_app.te b/sepolicy/system_app.te new file mode 100644 index 0000000..ef05374 --- /dev/null +++ b/sepolicy/system_app.te @@ -0,0 +1 @@ +allow system_app sysfs_homebutton:file rw_file_perms; diff --git a/sepolicy/system_server.te b/sepolicy/system_server.te new file mode 100644 index 0000000..3253d80 --- /dev/null +++ b/sepolicy/system_server.te @@ -0,0 +1,2 @@ +allow system_server persist_file:dir rw_dir_perms; +allow system_server persist_file:file rw_file_perms; diff --git a/sepolicy/time_daemon.te b/sepolicy/time_daemon.te new file mode 100644 index 0000000..7ff6dc3 --- /dev/null +++ b/sepolicy/time_daemon.te @@ -0,0 +1 @@ +allow time_daemon persist_file:file rw_file_perms; diff --git a/sepolicy/ueventd.te b/sepolicy/ueventd.te new file mode 100644 index 0000000..57eb7cb --- /dev/null +++ b/sepolicy/ueventd.te @@ -0,0 +1,4 @@ +allow ueventd device:chr_file { relabelfrom relabelto }; +allow ueventd sysfs_mmi_fp:file w_file_perms; +allow ueventd sysfs_mmi_touch:file w_file_perms; +allow ueventd sysfs_mmi_touch:dir search; diff --git a/sepolicy/wcnss_service.te b/sepolicy/wcnss_service.te new file mode 100644 index 0000000..46c74a3 --- /dev/null +++ b/sepolicy/wcnss_service.te @@ -0,0 +1 @@ +allow wcnss_service self:capability { setgid setuid }; diff --git a/setup-makefiles.sh b/setup-makefiles.sh new file mode 100644 index 0000000..1625a5a --- /dev/null +++ b/setup-makefiles.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# Copyright (C) 2016 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. +# + +set -e + +# Required! +DEVICE=potter +VENDOR=motorola + +# Load extractutils and do some sanity checks +MY_DIR="${BASH_SOURCE%/*}" +if [[ ! -d "$MY_DIR" ]]; then MY_DIR="$PWD"; fi + +CM_ROOT="$MY_DIR"/../../.. + +HELPER="$CM_ROOT"/vendor/cm/build/tools/extract_utils.sh +if [ ! -f "$HELPER" ]; then + echo "Unable to find helper script at $HELPER" + exit 1 +fi +. "$HELPER" + +# Initialize the helper +setup_vendor "$DEVICE" "$VENDOR" "$CM_ROOT" + +# Copyright headers and guards +write_headers + +# The standard blobs +write_makefiles "$MY_DIR"/proprietary-files.txt + +# We are done! +write_footers \ No newline at end of file diff --git a/system.prop b/system.prop new file mode 100644 index 0000000..778ac50 --- /dev/null +++ b/system.prop @@ -0,0 +1,137 @@ +# +# system.prop for potter +# + +# Android Run Time +ro.sys.fw.dex2oat_thread_count=4 + +# Audio +audio.deep_buffer.media=true +audio.offload.buffer.size.kb=64 +audio.offload.gapless.enabled=true +audio.offload.pcm.16bit.enable=true +audio.offload.pcm.24bit.enable=true + +persist.audio.calfile0=/etc/acdbdata/Bluetooth_cal.acdb +persist.audio.calfile1=/etc/acdbdata/General_cal.acdb +persist.audio.calfile2=/etc/acdbdata/Global_cal.acdb +persist.audio.calfile3=/etc/acdbdata/Handset_cal.acdb +persist.audio.calfile4=/etc/acdbdata/Hdmi_cal.acdb +persist.audio.calfile5=/etc/acdbdata/Headset_cal.acdb +persist.audio.calfile6=/etc/acdbdata/Speaker_cal.acdb + +persist.audio.fluence.mode=endfire +persist.audio.fluence.speaker=true +persist.audio.fluence.voicecall=true +ro.qc.sdk.audio.fluencetype=none +ro.qc.sdk.audio.ssr=false + +use.voice.path.for.pcm.voip=false + +# Bluetooth +bluetooth.hfp.client=1 +qcom.bluetooth.soc=smd +qcom.bt.le_dev_pwr_class=1 +ro.bluetooth.dun=true +ro.bluetooth.hfp.ver=1.7 +ro.bluetooth.sap=true +ro.qualcomm.bluetooth.ftp=true +ro.qualcomm.bluetooth.hfp=true +ro.qualcomm.bluetooth.hsp=true +ro.qualcomm.bluetooth.map=true +ro.qualcomm.bluetooth.nap=true +ro.qualcomm.bluetooth.opp=true +ro.qualcomm.bluetooth.pbap=true +ro.qualcomm.bt.hci_transport=smd + +# Camera +camera.disable_zsl_mode=1 +camera.display.umax=1920x1080 +camera.display.lmax=1280x720 +camera.hal1.packagelist=com.skype.raider,com.google.android.talk +vidc.dec.downscalar_width=1920 +vidc.dec.downscalar_height=1088 +vidc.dec.disable.split.cpu=1 +vidc.enc.dcvs.extra-buff-count=2 +vidc.enc.disable_bframes=1 + +# CNE +persist.cne.feature=1 +persist.cne.logging.qxdm=3974 +persist.cne.rat.wlan.chip.oem=WCN +persist.dpm.feature=0 +persist.sys.cnd.iwlan=1 + +# Display +debug.egl.hw=1 +debug.enable.sglscale=1 +debug.gralloc.enable_fb_ubwc=1 +debug.mdpcomp.logs=0 +debug.sf.hw=1 +dev.pm.dyn_samplingrate=1 +persist.demo.hdmirotationlock=false +persist.hwc.mdpcomp.enable=true +ro.opengles.version=196609 +ro.sf.lcd_density=480 + +# FRP +#ro.frp.pst=/dev/block/bootdevice/by-name/frp + +# IMS +persist.radio.jbims=1 +persist.radio.RATE_ADAPT_ENABLE=1 +persist.radio.VT_ENABLE=1 +persist.radio.VT_HYBRID_ENABLE=1 +persist.radio.VT_USE_MDM_TIME=0 + +# Media +media.aac_51_output_enabled=true + +# NFC +persist.nfc.smartcard.config=SIM1,SIM2,eSE1 + +# NITZ +persist.rild.nitz_plmn= +persist.rild.nitz_long_ons_0= +persist.rild.nitz_long_ons_1= +persist.rild.nitz_long_ons_2= +persist.rild.nitz_long_ons_3= +persist.rild.nitz_short_ons_0= +persist.rild.nitz_short_ons_1= +persist.rild.nitz_short_ons_2= +persist.rild.nitz_short_ons_3= + +# Qualcomm +com.qc.hardware=true +debug.qc.hardware=true +persist.timed.enable=true + +# Radio +persist.data.qmi.adb_logmask=0 +persist.radio.apn_delay=5000 +persist.radio.apm_sim_not_pwdn=1 +persist.radio.dfr_mode_set=1 +persist.radio.force_get_pref=1 +persist.radio.msgtunnel.start=true +persist.radio.no_wait_for_card=1 +persist.radio.oem_ind_to_both=0 +persist.radio.relay_oprt_change=1 +rild.libargs=-d /dev/smd0 +rild.libpath=/system/vendor/lib/libril-qc-qmi-1.so + +ro.use_data_netmgrd=true +persist.data.netmgrd.qos.enable=true +persist.data.mode=concurrent + +# USB +ro.usb.mtp=0x2e82 +ro.usb.mtp_adb=0x2e76 +ro.usb.ptp=0x2e83 +ro.usb.ptp_adb=0x2e84 +ro.usb.bpt=0x2ee5 +ro.usb.bpt_adb=0x2ee6 +ro.usb.bpteth=0x2ee7 +ro.usb.bpteth_adb=0x2ee8 + +# Vendor Extension +ro.vendor.extension_library=libqti-perfd-client.so \ No newline at end of file diff --git a/wifi/Android.mk b/wifi/Android.mk new file mode 100644 index 0000000..30e6d5b --- /dev/null +++ b/wifi/Android.mk @@ -0,0 +1,133 @@ +LOCAL_PATH:= $(call my-dir) + +#---------------------------------------------------------------------- +# Copy additional target-specific files +#---------------------------------------------------------------------- + +include $(CLEAR_VARS) +LOCAL_MODULE := hostapd_default.conf +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/hostapd +LOCAL_SRC_FILES := hostapd_default.conf +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := p2p_supplicant_overlay.conf +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/wifi +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := wpa_supplicant_overlay.conf +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/wifi +include $(BUILD_PREBUILT) + +#---------------------------------------------------------------------- +# Symlinks +#---------------------------------------------------------------------- + +include $(CLEAR_VARS) +LOCAL_MODULE := WCNSS_qcom_cfg.ini +LOCAL_MODULE_CLASS := FAKE +LOCAL_MODULE_TAGS := optional +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): TARGET := $(TARGET_OUT)/etc/firmware/wlan/prima/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): SYMLINK := $(TARGET_OUT)/etc/wifi/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): + $(hide) echo "Symlink: $(SYMLINK) -> $(TARGET)" + $(hide) mkdir -p $(dir $@) + $(hide) mkdir -p $(dir $(SYMLINK)) + $(hide) rm -rf $@ + $(hide) rm -rf $(SYMLINK) + $(hide) ln -sf $(TARGET) $(SYMLINK) + $(hide) touch $@ + +include $(CLEAR_VARS) +LOCAL_MODULE := WCNSS_qcom_wlan_nv.bin +LOCAL_MODULE_CLASS := FAKE +LOCAL_MODULE_TAGS := optional +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): TARGET := $(TARGET_OUT)/etc/firmware/wlan/prima/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): SYMLINK := $(TARGET_OUT)/etc/wifi/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): + $(hide) echo "Symlink: $(SYMLINK) -> $(TARGET)" + $(hide) mkdir -p $(dir $@) + $(hide) mkdir -p $(dir $(SYMLINK)) + $(hide) rm -rf $@ + $(hide) rm -rf $(SYMLINK) + $(hide) ln -sf $(TARGET) $(SYMLINK) + $(hide) touch $@ + + +include $(CLEAR_VARS) +LOCAL_MODULE := WCNSS_qcom_wlan_nv_Argentina.bin +LOCAL_MODULE_CLASS := FAKE +LOCAL_MODULE_TAGS := optional +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): TARGET := $(TARGET_OUT)/etc/firmware/wlan/prima/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): SYMLINK := $(TARGET_OUT)/etc/wifi/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): + $(hide) echo "Symlink: $(SYMLINK) -> $(TARGET)" + $(hide) mkdir -p $(dir $@) + $(hide) mkdir -p $(dir $(SYMLINK)) + $(hide) rm -rf $@ + $(hide) rm -rf $(SYMLINK) + $(hide) ln -sf $(TARGET) $(SYMLINK) + $(hide) touch $@ + + +include $(CLEAR_VARS) +LOCAL_MODULE := WCNSS_qcom_wlan_nv_Brazil.bin +LOCAL_MODULE_CLASS := FAKE +LOCAL_MODULE_TAGS := optional +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): TARGET := $(TARGET_OUT)/etc/firmware/wlan/prima/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): SYMLINK := $(TARGET_OUT)/etc/wifi/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): + $(hide) echo "Symlink: $(SYMLINK) -> $(TARGET)" + $(hide) mkdir -p $(dir $@) + $(hide) mkdir -p $(dir $(SYMLINK)) + $(hide) rm -rf $@ + $(hide) rm -rf $(SYMLINK) + $(hide) ln -sf $(TARGET) $(SYMLINK) + $(hide) touch $@ + + +include $(CLEAR_VARS) +LOCAL_MODULE := WCNSS_qcom_wlan_nv_India.bin +LOCAL_MODULE_CLASS := FAKE +LOCAL_MODULE_TAGS := optional +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): TARGET := $(TARGET_OUT)/etc/firmware/wlan/prima/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): SYMLINK := $(TARGET_OUT)/etc/wifi/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): + $(hide) echo "Symlink: $(SYMLINK) -> $(TARGET)" + $(hide) mkdir -p $(dir $@) + $(hide) mkdir -p $(dir $(SYMLINK)) + $(hide) rm -rf $@ + $(hide) rm -rf $(SYMLINK) + $(hide) ln -sf $(TARGET) $(SYMLINK) + $(hide) touch $@ + +include $(CLEAR_VARS) +LOCAL_MODULE := WCNSS_wlan_dictionary.dat +LOCAL_MODULE_CLASS := FAKE +LOCAL_MODULE_TAGS := optional +include $(BUILD_SYSTEM)/base_rules.mk +$(LOCAL_BUILT_MODULE): TARGET := $(TARGET_OUT)/etc/firmware/wlan/prima/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): SYMLINK := $(TARGET_OUT)/etc/wifi/$(LOCAL_MODULE) +$(LOCAL_BUILT_MODULE): + $(hide) echo "Symlink: $(SYMLINK) -> $(TARGET)" + $(hide) mkdir -p $(dir $@) + $(hide) mkdir -p $(dir $(SYMLINK)) + $(hide) rm -rf $@ + $(hide) rm -rf $(SYMLINK) + $(hide) ln -sf $(TARGET) $(SYMLINK) + $(hide) touch $@ + diff --git a/wifi/WCNSS_qcom_cfg.ini b/wifi/WCNSS_qcom_cfg.ini new file mode 100644 index 0000000..d3f5bef --- /dev/null +++ b/wifi/WCNSS_qcom_cfg.ini @@ -0,0 +1,438 @@ +# This file allows user to override the factory + +# defaults for the WLAN Driver + +# Disable QCOM SAR cutback algorithm and its default driver value +SARPowerBackoff=0 + +# ARP rates toggling +gToggleArpBDRates=1 + +# INI parameter used to control SSR test framework +# Set its value to 1 to enable APPS triggered SSR testing +gEnableForceTargetAssert=1 + +# Enable MCC Mode +gEnableMCCMode=1 + +# Enable IMPS or not +gEnableImps=1 + +# Enable/Disable Idle Scan + +gEnableIdleScan=0 + + +# Increase sleep duration (seconds) during IMPS +# 0 implies no periodic wake up from IMPS. Periodic wakeup is +# unnecessary if Idle Scan is disabled. +gImpsModSleepTime=0 + + +# Enable BMPS or not +gEnableBmps=1 + +# Enable suspend or not + +# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter + +gEnableSuspend=3 + + +# Phy Mode (auto, b, g, n, etc) +# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac +gDot11Mode=0 + + +# CSR Roaming Enable(1) Disable(0) + +gRoamingTime=0 + + +# Assigned MAC Addresses - This will be used until NV items are in place + +# Each byte of MAC address is represented in Hex format as XX + +Intf0MacAddress=000AF58989FF +Intf1MacAddress=000AF58989FE +Intf2MacAddress=000AF58989FD + +Intf3MacAddress=000AF58989FC + +# Set/Clear UAPSD mask + +UapsdMask=0 + +# UAPSD service interval for VO,VI, BE, BK traffic + +InfraUapsdVoSrvIntv=20 + +InfraUapsdViSrvIntv=40 + +# Flag to allow STA send AddTspec even when ACM is Off +gAddTSWhenACMIsOff=1 + +# Make 1x1 the default antenna configuration + +gNumRxAnt=1 + + +# Beacon filtering frequency (unit in beacon intervals) + +gNthBeaconFilter=50 + + +# Enable WAPI or not + +# WAPIIsEnabled=0 + + +# Flags to filter Mcast abd Bcast RX packets. + +# Value 0: No filtering, 1: Filter all Multicast. + +# 2: Filter all Broadcast. 3: Filter all Mcast abd Bcast + +McastBcastFilter=0 + + +#Enable NDP offload +hostNSOffload=1 + +#Flag to enable HostARPOffload feature or not + +hostArpOffload=1 + + +#SoftAP Related Parameters + +# AP MAc addr + +gAPMacAddr=000AF589dcab + + +# 802.11n Protection flag + +gEnableApProt=1 + + +#Enable OBSS protection + +gEnableApOBSSProt=1 + + +#Enable/Disable UAPSD for SoftAP + +gEnableApUapsd=1 + + +# Fixed Rate + +gFixedRate=0 + + +# Maximum Tx power + +# gTxPowerCap=30 + + +# Fragmentation Threshold + +# gFragmentationThreshold=2346 + + +# RTS threshold + +RTSThreshold=2347 + + +# Intra-BSS forward + +gDisableIntraBssFwd=0 + + +# WMM Enable/Disable + +WmmIsEnabled=0 + + +# 802.11d support + +g11dSupportEnabled=1 + +# CCX Support and fast transition +EseEnabled=0 +FastTransitionEnabled=1 +ImplicitQosIsEnabled=0 +gNeighborScanTimerPeriod=200 + +# default value of this parameter is zero to enable dynamic threshold allocation +# to set static roming threshold uncomment below parameter and set vaule +#gNeighborLookupThreshold=78 + +gNeighborScanChannelMinTime=20 +gNeighborScanChannelMaxTime=30 + +# Legacy (non-CCX, non-802.11r) Fast Roaming Support +# To enable, set FastRoamEnabled=1 +# To disable, set FastRoamEnabled=0 +FastRoamEnabled=1 + +#Check if the AP to which we are roaming is better than current AP in terms of RSSI. +#Checking is disabled if set to Zero.Otherwise it will use this value as to how better +#the RSSI of the new/roamable AP should be for roaming +RoamRssiDiff=5 + +# SAP Country code + +# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door. + +# Example + +# US Indoor, USI + +# Korea Outdoor, KRO + +# Japan without optional byte, JP + +# France without optional byte, FR + +#gAPCntryCode=USI + + +#Short Guard Interval Enable/disable + +gShortGI20Mhz=1 + +gShortGI40Mhz=1 + + +#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled + +gAPAutoShutOff=0 + + +# SAP auto channel selection configuration + +# 0 = disable auto channel selection + +# 1 = enable auto channel selection, channel provided by supplicant will be ignored + +gApAutoChannelSelection=0 + + +# Listen Energy Detect Mode Configuration + +# Valid values 0-128 + +# 128 means disable Energy Detect feature + +# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. + +# 10-128 are reserved. + +# The EDET threshold mapping is as follows in 3dB step: + +# 0 = -60 dBm + +# 1 = -63 dBm + +# 2 = -66 dBm + +# ... + +# 7 = -81 dBm + +# 8 = -84 dBm + +# 9 = -87 dBm + +# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: + +# + +# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. + +# + +gEnablePhyAgcListenMode=128 + + +#Preferred channel to start BT AMP AP mode (0 means, any channel) + +BtAmpPreferredChannel=0 + + +#Preferred band (both or 2.4 only or 5 only) + +BandCapability=0 + + +#Beacon Early Termination (1 = enable the BET feature, 0 = disable) + +enableBeaconEarlyTermination=1 + +beaconEarlyTerminationWakeInterval=11 + + +#Bluetooth Alternate Mac Phy (1 = enable the BT AMP feature, 0 = disable) + +gEnableBtAmp=0 + + +#SOFTAP Channel Range selection + +gAPChannelSelectStartChannel=1 + +gAPChannelSelectEndChannel=11 + + +#SOFTAP Channel Range selection Operating band + +# 0:2.4GHZ 1: LOW-5GHZ 2:MID-5GHZ 3:HIGH-5GHZ 4: 4.9HZ BAND + +gAPChannelSelectOperatingBand=0 + + +#Channel Bonding +gChannelBondingMode5GHz=1 + +gEnableModulatedDTIM = 3 +gMaxLIModulatedDTIM = 3 +gEnableDatainactivity = 200 + +#Enable Keep alive with non-zero period value + +gStaKeepAlivePeriod=30 + + +#Say gGoKeepAlivePeriod(5 seconds) and gGoLinkMonitorPeriod(10 seconds). +#For every 10 seconds DUT sends Qos Null frame(i.e., Keep Alive frame if link is idle for last 10 seconds.) +#For both active and power save clients. + +#Power save clients: DUT set TIM bit from 10th second onwards and till client honors TIM bit. +#If doesn't honor for 5 seconds then Driver remove client. + +#Active clients: DUT send Qos Null frame for 10th seconds onwards if it is not success still DUT try on +#11th second if not tries on 12th and so on till 15th second. Hence before disconnection DUT will send 5 NULL frames. +#Hence in any case DUT will detect client got removed in (10+5) seconds. i.e., (gGoKeepAlivePeriod +gGoLinkMonitorPeriod).. + +#gGoLinkMonitorPeriod/ gApLinkMonitorPeriod is period where link is idle and it is period +#where we send NULL frame. + +#gApLinkMonitorPeriod = 10 + +#gGoLinkMonitorPeriod = 10 + +#gGoKeepAlivePeriod/gApKeepAlivePeriod is time to spend to check whether frame are succeed to send or not. +#Hence total effective detection time is gGoLinkMonitorPeriod+ gGoKeepAlivePeriod/gApLinkMonitorPeriod+ gApKeepAlivePeriod. +gGoKeepAlivePeriod = 10 + +gApKeepAlivePeriod = 30 +#If set will start with active scan after driver load, otherwise will start with + +#passive scan to find out the domain + +#gEnableBypass11d=1 + + +#If set to 0, will not scan DFS channels + +gEnableDFSChnlScan=1 + +gEnableLogp=1 + + +# Enable Automatic Tx Power control + +gEnableAutomaticTxPowerControl=0 + +# 0 for OLPC 1 for CLPC and SCPC +gEnableCloseLoop=1 + +#Data Inactivity Timeout when in powersave (in ms) +gDataInactivityTimeout=200 + +gEnableLpwrImgTransition=1 + +# Scan Timing Parameters +# gPassiveMaxChannelTime=110 +# gPassiveMinChannelTime=60 +# Enable Tx LDPC +#gTxLdpcEnable = 1 for HT mode, 2 for VHT mode,3 for both HT and VHT +gTxLdpcEnable=3 +# gActiveMaxChannelTime=40 +# gActiveMinChannelTime=20 + +gNumStaChanCombinedConc=1 + +# Valid values are 2048,4096,8192 and so on +# Please don't use values other than the ones mentioned above +gMaxMediumTime=4096 + +# 802.11K support +gRrmEnable=1 +gRrmOperChanMax=8 +gRrmNonOperChanMax=8 +gRrmRandIntvl=100 + +#Scan offload +gEnableDirectedScanOffload=0 + +#FlexConnect Power Factor +#Default is set to 0 (disable) +gFlexConnectPowerFactor=0 + +gVhtChannelWidth=2 + +# VHT Tx/Rx MCS values +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gVhtRxMCS=2 +gVhtTxMCS=2 + +# Enable Tx beamforming +gTxBFEnable=1 + +#Enable/Disable TDLS Feature +gEnableTDLSSupport=1 + +#Enable/Disable TDLS Implicit Trigger +gEnableTDLSImplicitTrigger=1 + +#Enable/Disable TDLS WMM Mode +gEnableTDLSWmmMode=1 + +#Enable/Disable TDLS Buffer Sta +gEnableTDLSBufferSta=1 + +#Enable/Disable Mgmt Frame Logging +gEnableMgmtLogging=1 + +#Enable/Disable MAc Spoofing + +#Set RPS CPU mask +rps_mask=0f + + +gEnableMacAddrSpoof=2 + +gEnableTDLSScan=1 +gTDLSExternalControl=1 +gEnableTDLSSupport=1 +gTDLSTxStatsPeriod=500 +gTDLSTxPacketThreshold=10 +gTDLSDiscoveryPeriod=20000 +gTDLSMaxDiscoveryAttempt=5 +gTDLSIdleTimeout=40000 +gTDLSRssiHysteresis=100 +gTDLSIdlePacketThreshold=5 +gEnableTDLSScanCoexistence=1 +gBtcEnableIndTimerVal=5 + +gIgnorePeerErpInfo=1 + +END + +# Note: Configuration parser would not read anything past the END marker + diff --git a/wifi/hostapd_default.conf b/wifi/hostapd_default.conf new file mode 100644 index 0000000..71503ac --- /dev/null +++ b/wifi/hostapd_default.conf @@ -0,0 +1,1043 @@ +##### hostapd configuration file ############################################## +# Empty lines and lines starting with # are ignored + +# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for +# management frames); ath0 for madwifi +interface=wlan0 + +# In case of madwifi and nl80211 driver interfaces, an additional configuration +# parameter, bridge, must be used to notify hostapd if the interface is +# included in a bridge. This parameter is not used with Host AP driver. +#bridge=br0 + +# Driver interface type (hostap/wired/madwifi/prism54/test/none/nl80211/bsd); +# default: hostap). nl80211 is used with all Linux mac80211 drivers. +# Use driver=none if building hostapd as a standalone RADIUS server that does +# not control any wireless/wired driver. +driver=nl80211 + +# hostapd event logger configuration +# +# Two output method: syslog and stdout (only usable if not forking to +# background). +# +# Module bitfield (ORed bitfield of modules that will be logged; -1 = all +# modules): +# bit 0 (1) = IEEE 802.11 +# bit 1 (2) = IEEE 802.1X +# bit 2 (4) = RADIUS +# bit 3 (8) = WPA +# bit 4 (16) = driver interface +# bit 5 (32) = IAPP +# bit 6 (64) = MLME +# +# Levels (minimum value for logged events): +# 0 = verbose debugging +# 1 = debugging +# 2 = informational messages +# 3 = notification +# 4 = warning +# +logger_syslog=-1 +logger_syslog_level=2 +logger_stdout=-1 +logger_stdout_level=2 + +# Dump file for state information (on SIGUSR1) +dump_file=/tmp/hostapd.dump + +# Interface for separate control program. If this is specified, hostapd +# will create this directory and a UNIX domain socket for listening to requests +# from external programs (CLI/GUI, etc.) for status information and +# configuration. The socket file will be named based on the interface name, so +# multiple hostapd processes/interfaces can be run at the same time if more +# than one interface is used. +# /var/run/hostapd is the recommended directory for sockets and by default, +# hostapd_cli will use it when trying to connect with hostapd. +ctrl_interface=/data/misc/wifi/hostapd + + +# Access control for the control interface can be configured by setting the +# directory to allow only members of a group to use sockets. This way, it is +# possible to run hostapd as root (since it needs to change network +# configuration and open raw sockets) and still allow GUI/CLI components to be +# run as non-root users. However, since the control interface can be used to +# change the network configuration, this access needs to be protected in many +# cases. By default, hostapd is configured to use gid 0 (root). If you +# want to allow non-root users to use the contron interface, add a new group +# and change this value to match with that group. Add users that should have +# control interface access to this group. +# +# This variable can be a group name or gid. +#ctrl_interface_group=wheel +#ctrl_interface_group=0 + + +##### IEEE 802.11 related configuration ####################################### + +# SSID to be used in IEEE 802.11 management frames +ssid=QualcommSoftAP + +# Country code (ISO/IEC 3166-1). Used to set regulatory domain. +# Set as needed to indicate country in which device is operating. +# This can limit available channels and transmit power. +#country_code=US + +# Enable IEEE 802.11d. This advertises the country_code and the set of allowed +# channels and transmit power levels based on the regulatory limits. The +# country_code setting must be configured with the correct country for +# IEEE 802.11d functions. +# (default: 0 = disabled) +ieee80211d=1 + +# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g, +# n = IEEE 802.11n, g_only = IEEE 802.11g_only, n_only = IEEE 802.11n_only, +# Default: IEEE 802.11n +hw_mode=g + +# Channel number (IEEE 802.11) +# (default: 0, i.e., not set) +# Please note that some drivers (e.g., madwifi) do not use this value from +# hostapd and the channel will need to be configuration separately with +# iwconfig. +channel=6 + +# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535) +beacon_int=100 + +# DTIM (delivery trafic information message) period (range 1..255): +# number of beacons between DTIMs (1 = every beacon includes DTIM element) +# (default: 2) +dtim_period=2 + +# Maximum number of stations allowed in station table. New stations will be +# rejected after the station table is full. IEEE 802.11 has a limit of 2007 +# different association IDs, so this number should not be larger than that. +# (default: 2007) +max_num_sta=255 + +# RTS/CTS threshold; 2347 = disabled (default); range 0..2347 +# If this field is not included in hostapd.conf, hostapd will not control +# RTS threshold and 'iwconfig wlan# rts ' can be used to set it. +#rts_threshold=2347 + +# Fragmentation threshold; 2346 = disabled (default); range 256..2346 +# If this field is not included in hostapd.conf, hostapd will not control +# fragmentation threshold and 'iwconfig wlan# frag ' can be used to set +# it. +#fragm_threshold=2346 + +# Rate configuration +# Default is to enable all rates supported by the hardware. This configuration +# item allows this list be filtered so that only the listed rates will be left +# in the list. If the list is empty, all rates are used. This list can have +# entries that are not in the list of rates the hardware supports (such entries +# are ignored). The entries in this list are in 100 kbps, i.e., 11 Mbps = 110. +# If this item is present, at least one rate have to be matching with the rates +# hardware supports. +# default: use the most common supported rate setting for the selected +# hw_mode (i.e., this line can be removed from configuration file in most +# cases) +#supported_rates=10 20 55 110 60 90 120 180 240 360 480 540 + +# Basic rate set configuration +# List of rates (in 100 kbps) that are included in the basic rate set. +# If this item is not included, usually reasonable default set is used. +# This basic rates set is currently used for g-only profile +#basic_rates=60 + +# Short Preamble +# This parameter can be used to enable optional use of short preamble for +# frames sent at 2 Mbps, 5.5 Mbps, and 11 Mbps to improve network performance. +# This applies only to IEEE 802.11b-compatible networks and this should only be +# enabled if the local hardware supports use of short preamble. If any of the +# associated STAs do not support short preamble, use of short preamble will be +# disabled (and enabled when such STAs disassociate) dynamically. +# 0 = do not allow use of short preamble (default) +# 1 = allow use of short preamble +#preamble=1 + +# Station MAC address -based authentication +# Please note that this kind of access control requires a driver that uses +# hostapd to take care of management frame processing and as such, this can be +# used with driver=hostap or driver=nl80211, but not with driver=madwifi. +# 0 = accept unless in deny list +# 1 = deny unless in accept list +# 2 = use external RADIUS server (accept/deny lists are searched first) +macaddr_acl=0 + +# Accept/deny lists are read from separate files (containing list of +# MAC addresses, one per line). Use absolute path name to make sure that the +# files can be read on SIGHUP configuration reloads. +accept_mac_file=/data/misc/wifi/hostapd.accept +deny_mac_file=/data/misc/wifi/hostapd.deny + +# IEEE 802.11 specifies two authentication algorithms. hostapd can be +# configured to allow both of these or only one. Open system authentication +# should be used with IEEE 802.1X. +# Bit fields of allowed authentication algorithms: +# bit 0 = Open System Authentication +# bit 1 = Shared Key Authentication (requires WEP) +auth_algs=3 + +# Send empty SSID in beacons and ignore probe request frames that do not +# specify full SSID, i.e., require stations to know SSID. +# default: disabled (0) +# 1 = send empty (length=0) SSID in beacon and ignore probe request for +# broadcast SSID +# 2 = clear SSID (ASCII 0), but keep the original length (this may be required +# with some clients that do not support empty SSID) and ignore probe +# requests for broadcast SSID +ignore_broadcast_ssid=0 + +# TX queue parameters (EDCF / bursting) +# default for all these fields: not set, use hardware defaults +# tx_queue__ +# queues: data0, data1, data2, data3, after_beacon, beacon +# (data0 is the highest priority queue) +# parameters: +# aifs: AIFS (default 2) +# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023) +# cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); cwMax >= cwMin +# burst: maximum length (in milliseconds with precision of up to 0.1 ms) for +# bursting +# +# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): +# These parameters are used by the access point when transmitting frames +# to the clients. +# +# Low priority / AC_BK = background +#tx_queue_data3_aifs=7 +#tx_queue_data3_cwmin=15 +#tx_queue_data3_cwmax=1023 +#tx_queue_data3_burst=0 +# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0 +# +# Normal priority / AC_BE = best effort +#tx_queue_data2_aifs=3 +#tx_queue_data2_cwmin=15 +#tx_queue_data2_cwmax=63 +#tx_queue_data2_burst=0 +# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0 +# +# High priority / AC_VI = video +#tx_queue_data1_aifs=1 +#tx_queue_data1_cwmin=7 +#tx_queue_data1_cwmax=15 +#tx_queue_data1_burst=3.0 +# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0 +# +# Highest priority / AC_VO = voice +#tx_queue_data0_aifs=1 +#tx_queue_data0_cwmin=3 +#tx_queue_data0_cwmax=7 +#tx_queue_data0_burst=1.5 +# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3 +# +# Special queues; normally not user configurable +# +#tx_queue_after_beacon_aifs=2 +#tx_queue_after_beacon_cwmin=15 +#tx_queue_after_beacon_cwmax=1023 +#tx_queue_after_beacon_burst=0 +# +#tx_queue_beacon_aifs=2 +#tx_queue_beacon_cwmin=3 +#tx_queue_beacon_cwmax=7 +#tx_queue_beacon_burst=1.5 + +# 802.1D Tag (= UP) to AC mappings +# WMM specifies following mapping of data frames to different ACs. This mapping +# can be configured using Linux QoS/tc and sch_pktpri.o module. +# 802.1D Tag 802.1D Designation Access Category WMM Designation +# 1 BK AC_BK Background +# 2 - AC_BK Background +# 0 BE AC_BE Best Effort +# 3 EE AC_BE Best Effort +# 4 CL AC_VI Video +# 5 VI AC_VI Video +# 6 VO AC_VO Voice +# 7 NC AC_VO Voice +# Data frames with no priority information: AC_BE +# Management frames: AC_VO +# PS-Poll frames: AC_BE + +# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): +# for 802.11a or 802.11g networks +# These parameters are sent to WMM clients when they associate. +# The parameters will be used by WMM clients for frames transmitted to the +# access point. +# +# note - txop_limit is in units of 32microseconds +# note - acm is admission control mandatory flag. 0 = admission control not +# required, 1 = mandatory +# note - here cwMin and cmMax are in exponent form. the actual cw value used +# will be (2^n)-1 where n is the value given here +# +wmm_enabled=1 +# +# Low priority / AC_BK = background +wmm_ac_bk_cwmin=4 +wmm_ac_bk_cwmax=10 +wmm_ac_bk_aifs=7 +wmm_ac_bk_txop_limit=0 +wmm_ac_bk_acm=0 +# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10 +# +# Normal priority / AC_BE = best effort +wmm_ac_be_aifs=3 +wmm_ac_be_cwmin=4 +wmm_ac_be_cwmax=10 +wmm_ac_be_txop_limit=0 +wmm_ac_be_acm=0 +# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7 +# +# High priority / AC_VI = video +wmm_ac_vi_aifs=2 +wmm_ac_vi_cwmin=3 +wmm_ac_vi_cwmax=4 +wmm_ac_vi_txop_limit=94 +wmm_ac_vi_acm=0 +# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188 +# +# Highest priority / AC_VO = voice +wmm_ac_vo_aifs=2 +wmm_ac_vo_cwmin=2 +wmm_ac_vo_cwmax=3 +wmm_ac_vo_txop_limit=47 +wmm_ac_vo_acm=0 +# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102 + +# Static WEP key configuration +# +# The key number to use when transmitting. +# It must be between 0 and 3, and the corresponding key must be set. +# default: not set +#wep_default_key=0 +# The WEP keys to use. +# A key may be a quoted string or unquoted hexadecimal digits. +# The key length should be 5, 13, or 16 characters, or 10, 26, or 32 +# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or +# 128-bit (152-bit) WEP is used. +# Only the default key must be supplied; the others are optional. +# default: not set +#wep_key0=1234567890 +#wep_key1=1234567890 +#wep_key2=1234567890 +#wep_key3=1234567890 + +# Station inactivity limit +# +# If a station does not send anything in ap_max_inactivity seconds, an +# empty data frame is sent to it in order to verify whether it is +# still in range. If this frame is not ACKed, the station will be +# disassociated and then deauthenticated. This feature is used to +# clear station table of old entries when the STAs move out of the +# range. +# +# The station can associate again with the AP if it is still in range; +# this inactivity poll is just used as a nicer way of verifying +# inactivity; i.e., client will not report broken connection because +# disassociation frame is not sent immediately without first polling +# the STA with a data frame. +# default: 300 (i.e., 5 minutes) +#ap_max_inactivity=300 + +# Enable/disable internal bridge for packets between associated stations. +# +# When IEEE 802.11 is used in managed mode, packets are usually send through +# the AP even if they are from a wireless station to another wireless station. +# This functionality requires that the AP has a bridge functionality that sends +# frames back to the same interface if their destination is another associated +# station. In addition, broadcast/multicast frames from wireless stations will +# be sent both to the host system net stack (e.g., to eventually wired network) +# and back to the wireless interface. +# +# The internal bridge is implemented within the wireless kernel module and it +# bypasses kernel filtering (netfilter/iptables/ebtables). If direct +# communication between the stations needs to be prevented, the internal +# bridge can be disabled by setting bridge_packets=0. +# +# Note: If this variable is not included in hostapd.conf, hostapd does not +# change the configuration and iwpriv can be used to set the value with +# 'iwpriv wlan# param 10 0' command. If the variable is in hostapd.conf, +# hostapd will override possible iwpriv configuration whenever configuration +# file is reloaded. +# +# default: do not control from hostapd (80211.o defaults to 1=enabled) +#bridge_packets=1 + +# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to +# remain asleep). Default: 65535 (no limit apart from field size) +#max_listen_interval=100 + +# Client isolation can be used to prevent low-level bridging of frames between +# associated stations in the BSS. By default, this bridging is allowed. +#ap_isolate=1 + +##### IEEE 802.11n related configuration ###################################### + +# ieee80211n: Whether IEEE 802.11n (HT) is enabled +# 0 = disabled (default) +# 1 = enabled +# Note: You will also need to enable WMM for full HT functionality. +ieee80211n=1 + +#require_ht=1 + +# ht_capab: HT capabilities (list of flags) +# LDPC coding capability: [LDPC] = supported +# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary +# channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz +# with secondary channel below the primary channel +# (20 MHz only if neither is set) +# Note: There are limits on which channels can be used with HT40- and +# HT40+. Following table shows the channels that may be available for +# HT40- and HT40+ use per IEEE 802.11n Annex J: +# freq HT40- HT40+ +# 2.4 GHz 5-13 1-7 (1-9 in Europe/Japan) +# 5 GHz 40,48,56,64 36,44,52,60 +# (depending on the location, not all of these channels may be available +# for use) +# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC] +# (SMPS disabled if neither is set) +# HT-greenfield: [GF] (disabled if not set) +# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set) +# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set) +# Tx STBC: [TX-STBC] (disabled if not set) +# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial +# streams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC +# disabled if none of these set +# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set) +# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not +# set) +# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set) +# PSMP support: [PSMP] (disabled if not set) +# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set) +# QcHostapd: +# LOWER byte for associated stations +# UPPER byte for overlapping stations +# each byte will have the following info +# bit15 bit14 bit13 bit12 bit11 bit10 bit9 bit8 +# OBSS RIFS LSIG_TXOP NON_GF HT20 FROM_11G FROM_11B FROM_11A +# bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 +# OBSS RIFS LSIG_TXOP NON_GF HT_20 FROM_11G FROM_11B FROM_11A +#ht_capab=[HT40-] [SHORT-GI-20] [SHORT-GI-40] +ht_capab=[SHORT-GI-20] [GF] [DSSS_CCK-40] [LSIG-TXOP-PROT] +#ht_capab=[LDPC] [HT40-] [HT40+] [SMPS-STATIC] [SMPS-DYNAMIC] [GF] [SHORT-GI-20] [SHORT-GI-40] [TX-STBC] [RX-STBC1] [RX-STBC12] [RX-STBC123] [DELAYED-BA] [MAX-AMSDU-7935] [DSSS_CCK-40] [PSMP] [LSIG-TXOP-PROT] + +##### IEEE 802.1X-2004 related configuration ################################## + +# Require IEEE 802.1X authorization +#ieee8021x=1 + +# IEEE 802.1X/EAPOL version +# hostapd is implemented based on IEEE Std 802.1X-2004 which defines EAPOL +# version 2. However, there are many client implementations that do not handle +# the new version number correctly (they seem to drop the frames completely). +# In order to make hostapd interoperate with these clients, the version number +# can be set to the older version (1) with this configuration value. +#eapol_version=2 + +# Optional displayable message sent with EAP Request-Identity. The first \0 +# in this string will be converted to ASCII-0 (nul). This can be used to +# separate network info (comma separated list of attribute=value pairs); see, +# e.g., RFC 4284. +#eap_message=hello +#eap_message=hello\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com + +# WEP rekeying (disabled if key lengths are not set or are set to 0) +# Key lengths for default/broadcast and individual/unicast keys: +# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits) +# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits) +#wep_key_len_broadcast=5 +#wep_key_len_unicast=5 +# Rekeying period in seconds. 0 = do not rekey (i.e., set keys only once) +#wep_rekey_period=300 + +# EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if +# only broadcast keys are used) +eapol_key_index_workaround=0 + +# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable +# reauthentication). +#eap_reauth_period=3600 + +# Use PAE group address (01:80:c2:00:00:03) instead of individual target +# address when sending EAPOL frames with driver=wired. This is the most common +# mechanism used in wired authentication, but it also requires that the port +# is only used by one station. +#use_pae_group_addr=1 + +##### Integrated EAP server ################################################### + +# Optionally, hostapd can be configured to use an integrated EAP server +# to process EAP authentication locally without need for an external RADIUS +# server. This functionality can be used both as a local authentication server +# for IEEE 802.1X/EAPOL and as a RADIUS server for other devices. + +# Use integrated EAP server instead of external RADIUS authentication +# server. This is also needed if hostapd is configured to act as a RADIUS +# authentication server. +eap_server=1 + +# Path for EAP server user database +#eap_user_file=/etc/hostapd.eap_user + +# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS +#ca_cert=/etc/hostapd.ca.pem + +# Server certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS +#server_cert=/etc/hostapd.server.pem + +# Private key matching with the server certificate for EAP-TLS/PEAP/TTLS +# This may point to the same file as server_cert if both certificate and key +# are included in a single file. PKCS#12 (PFX) file (.p12/.pfx) can also be +# used by commenting out server_cert and specifying the PFX file as the +# private_key. +#private_key=/etc/hostapd.server.prv + +# Passphrase for private key +#private_key_passwd=secret passphrase + +# Enable CRL verification. +# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a +# valid CRL signed by the CA is required to be included in the ca_cert file. +# This can be done by using PEM format for CA certificate and CRL and +# concatenating these into one file. Whenever CRL changes, hostapd needs to be +# restarted to take the new CRL into use. +# 0 = do not verify CRLs (default) +# 1 = check the CRL of the user certificate +# 2 = check all CRLs in the certificate path +#check_crl=1 + +# dh_file: File path to DH/DSA parameters file (in PEM format) +# This is an optional configuration file for setting parameters for an +# ephemeral DH key exchange. In most cases, the default RSA authentication does +# not use this configuration. However, it is possible setup RSA to use +# ephemeral DH key exchange. In addition, ciphers with DSA keys always use +# ephemeral DH keys. This can be used to achieve forward secrecy. If the file +# is in DSA parameters format, it will be automatically converted into DH +# params. This parameter is required if anonymous EAP-FAST is used. +# You can generate DH parameters file with OpenSSL, e.g., +# "openssl dhparam -out /etc/hostapd.dh.pem 1024" +#dh_file=/etc/hostapd.dh.pem + +# Configuration data for EAP-SIM database/authentication gateway interface. +# This is a text string in implementation specific format. The example +# implementation in eap_sim_db.c uses this as the UNIX domain socket name for +# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses "unix:" +# prefix. +#eap_sim_db=unix:/tmp/hlr_auc_gw.sock + +# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret, +# random value. It is configured as a 16-octet value in hex format. It can be +# generated, e.g., with the following command: +# od -tx1 -v -N16 /dev/random | colrm 1 8 | tr -d ' ' +#pac_opaque_encr_key=000102030405060708090a0b0c0d0e0f + +# EAP-FAST authority identity (A-ID) +# A-ID indicates the identity of the authority that issues PACs. The A-ID +# should be unique across all issuing servers. In theory, this is a variable +# length field, but due to some existing implementations required A-ID to be +# 16 octets in length, it is strongly recommended to use that length for the +# field to provided interoperability with deployed peer implementation. This +# field is configured in hex format. +#eap_fast_a_id=101112131415161718191a1b1c1d1e1f + +# EAP-FAST authority identifier information (A-ID-Info) +# This is a user-friendly name for the A-ID. For example, the enterprise name +# and server name in a human-readable format. This field is encoded as UTF-8. +#eap_fast_a_id_info=test server + +# Enable/disable different EAP-FAST provisioning modes: +#0 = provisioning disabled +#1 = only anonymous provisioning allowed +#2 = only authenticated provisioning allowed +#3 = both provisioning modes allowed (default) +#eap_fast_prov=3 + +# EAP-FAST PAC-Key lifetime in seconds (hard limit) +#pac_key_lifetime=604800 + +# EAP-FAST PAC-Key refresh time in seconds (soft limit on remaining hard +# limit). The server will generate a new PAC-Key when this number of seconds +# (or fewer) of the lifetime remains. +#pac_key_refresh_time=86400 + +# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND +# (default: 0 = disabled). +#eap_sim_aka_result_ind=1 + +# Trusted Network Connect (TNC) +# If enabled, TNC validation will be required before the peer is allowed to +# connect. Note: This is only used with EAP-TTLS and EAP-FAST. If any other +# EAP method is enabled, the peer will be allowed to connect without TNC. +#tnc=1 + + +##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) ####################### + +# Interface to be used for IAPP broadcast packets +#iapp_interface=eth0 + + +##### RADIUS client configuration ############################################# +# for IEEE 802.1X with external Authentication Server, IEEE 802.11 +# authentication with external ACL for MAC addresses, and accounting + +# The own IP address of the access point (used as NAS-IP-Address) +own_ip_addr=127.0.0.1 + +# Optional NAS-Identifier string for RADIUS messages. When used, this should be +# a unique to the NAS within the scope of the RADIUS server. For example, a +# fully qualified domain name can be used here. +# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and +# 48 octets long. +#nas_identifier=ap.example.com + +# RADIUS authentication server +#auth_server_addr=127.0.0.1 +#auth_server_port=1812 +#auth_server_shared_secret=secret + +# RADIUS accounting server +#acct_server_addr=127.0.0.1 +#acct_server_port=1813 +#acct_server_shared_secret=secret + +# Secondary RADIUS servers; to be used if primary one does not reply to +# RADIUS packets. These are optional and there can be more than one secondary +# server listed. +#auth_server_addr=127.0.0.2 +#auth_server_port=1812 +#auth_server_shared_secret=secret2 +# +#acct_server_addr=127.0.0.2 +#acct_server_port=1813 +#acct_server_shared_secret=secret2 + +# Retry interval for trying to return to the primary RADIUS server (in +# seconds). RADIUS client code will automatically try to use the next server +# when the current server is not replying to requests. If this interval is set, +# primary server will be retried after configured amount of time even if the +# currently used secondary server is still working. +#radius_retry_primary_interval=600 + + +# Interim accounting update interval +# If this is set (larger than 0) and acct_server is configured, hostapd will +# send interim accounting updates every N seconds. Note: if set, this overrides +# possible Acct-Interim-Interval attribute in Access-Accept message. Thus, this +# value should not be configured in hostapd.conf, if RADIUS server is used to +# control the interim interval. +# This value should not be less 600 (10 minutes) and must not be less than +# 60 (1 minute). +#radius_acct_interim_interval=600 + +# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN +# is used for the stations. This information is parsed from following RADIUS +# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN), +# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value +# VLANID as a string). vlan_file option below must be configured if dynamic +# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be +# used to set static client MAC address to VLAN ID mapping. +# 0 = disabled (default) +# 1 = option; use default interface if RADIUS server does not include VLAN ID +# 2 = required; reject authentication if RADIUS server does not include VLAN ID +#dynamic_vlan=0 + +# VLAN interface list for dynamic VLAN mode is read from a separate text file. +# This list is used to map VLAN ID from the RADIUS server to a network +# interface. Each station is bound to one interface in the same way as with +# multiple BSSIDs or SSIDs. Each line in this text file is defining a new +# interface and the line must include VLAN ID and interface name separated by +# white space (space or tab). +#vlan_file=/etc/hostapd.vlan + +# Interface where 802.1q tagged packets should appear when a RADIUS server is +# used to determine which VLAN a station is on. hostapd creates a bridge for +# each VLAN. Then hostapd adds a VLAN interface (associated with the interface +# indicated by 'vlan_tagged_interface') and the appropriate wireless interface +# to the bridge. +#vlan_tagged_interface=eth0 + + +##### RADIUS authentication server configuration ############################## + +# hostapd can be used as a RADIUS authentication server for other hosts. This +# requires that the integrated EAP server is also enabled and both +# authentication services are sharing the same configuration. + +# File name of the RADIUS clients configuration for the RADIUS server. If this +# commented out, RADIUS server is disabled. +#radius_server_clients=/etc/hostapd.radius_clients + +# The UDP port number for the RADIUS authentication server +#radius_server_auth_port=1812 + +# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API) +#radius_server_ipv6=1 + + +##### WPA/IEEE 802.11i configuration ########################################## + +# Enable WPA. Setting this variable configures the AP to require WPA (either +# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either +# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK. +# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys), +# RADIUS authentication server must be configured, and WPA-EAP must be included +# in wpa_key_mgmt. +# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0) +# and/or WPA2 (full IEEE 802.11i/RSN): +# bit0 = WPA +# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled) +#wpa=1 + +# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit +# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase +# (8..63 characters) that will be converted to PSK. This conversion uses SSID +# so the PSK changes when ASCII passphrase is used and the SSID is changed. +# wpa_psk (dot11RSNAConfigPSKValue) +# wpa_passphrase (dot11RSNAConfigPSKPassPhrase) +#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef +#wpa_passphrase=qualcomm + +# Optionally, WPA PSKs can be read from a separate text file (containing list +# of (PSK,MAC address) pairs. This allows more than one PSK to be configured. +# Use absolute path name to make sure that the files can be read on SIGHUP +# configuration reloads. +#wpa_psk_file=/etc/hostapd.wpa_psk + +# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The +# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be +# added to enable SHA256-based stronger algorithms. +# (dot11RSNAConfigAuthenticationSuitesTable) +#wpa_key_mgmt=WPA-PSK +#wpa_key_mgmt=WPA-EAP + +# Set of accepted cipher suites (encryption algorithms) for pairwise keys +# (unicast packets). This is a space separated list of algorithms: +# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] +# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] +# Group cipher suite (encryption algorithm for broadcast and multicast frames) +# is automatically selected based on this configuration. If only CCMP is +# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise, +# TKIP will be used as the group cipher. +# (dot11RSNAConfigPairwiseCiphersTable) +# Pairwise cipher for WPA (v1) (default: TKIP) +#wpa_pairwise=TKIP CCMP +# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value) +#rsn_pairwise=CCMP + +# Time interval for rekeying GTK (broadcast/multicast encryption keys) in +# seconds. (dot11RSNAConfigGroupRekeyTime) +wpa_group_rekey=86400 + +# Rekey GTK when any STA that possesses the current GTK is leaving the BSS. +# (dot11RSNAConfigGroupRekeyStrict) +#wpa_strict_rekey=1 + +# Time interval for rekeying GMK (master key used internally to generate GTKs +# (in seconds). +#wpa_gmk_rekey=86400 + +# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of +# PTK to mitigate some attacks against TKIP deficiencies. +#wpa_ptk_rekey=600 + +# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up +# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN +# authentication and key handshake before actually associating with a new AP. +# (dot11RSNAPreauthenticationEnabled) +#rsn_preauth=1 +# +# Space separated list of interfaces from which pre-authentication frames are +# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all +# interface that are used for connections to other APs. This could include +# wired interfaces and WDS links. The normal wireless data interface towards +# associated stations (e.g., wlan0) should not be added, since +# pre-authentication is only used with APs other than the currently associated +# one. +#rsn_preauth_interfaces=eth0 + +# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e) is +# allowed. This is only used with RSN/WPA2. +# 0 = disabled (default) +# 1 = enabled +#peerkey=1 + +# ieee80211w: Whether management frame protection (MFP) is enabled +# 0 = disabled (default) +# 1 = optional +# 2 = required +#ieee80211w=0 + +# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP) +# (maximum time to wait for a SA Query response) +# dot11AssociationSAQueryMaximumTimeout, 1...4294967295 +#assoc_sa_query_max_timeout=1000 + +# Association SA Query retry timeout (in TU = 1.024 ms; for MFP) +# (time between two subsequent SA Query requests) +# dot11AssociationSAQueryRetryTimeout, 1...4294967295 +#assoc_sa_query_retry_timeout=201 + + +# okc: Opportunistic Key Caching (aka Proactive Key Caching) +# Allow PMK cache to be shared opportunistically among configured interfaces +# and BSSes (i.e., all configurations within a single hostapd process). +# 0 = disabled (default) +# 1 = enabled +#okc=1 + + +##### IEEE 802.11r configuration ############################################## + +# Mobility Domain identifier (dot11FTMobilityDomainID, MDID) +# MDID is used to indicate a group of APs (within an ESS, i.e., sharing the +# same SSID) between which a STA can use Fast BSS Transition. +# 2-octet identifier as a hex string. +#mobility_domain=a1b2 + +# PMK-R0 Key Holder identifier (dot11FTR0KeyHolderID) +# 1 to 48 octet identifier. +# This is configured with nas_identifier (see RADIUS client section above). + +# Default lifetime of the PMK-RO in minutes; range 1..65535 +# (dot11FTR0KeyLifetime) +#r0_key_lifetime=10000 + +# PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID) +# 6-octet identifier as a hex string. +#r1_key_holder=000102030405 + +# Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535) +# (dot11FTReassociationDeadline) +#reassociation_deadline=1000 + +# List of R0KHs in the same Mobility Domain +# format: <128-bit key as hex string> +# This list is used to map R0KH-ID (NAS Identifier) to a destination MAC +# address when requesting PMK-R1 key from the R0KH that the STA used during the +# Initial Mobility Domain Association. +#r0kh=02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f +#r0kh=02:01:02:03:04:06 r0kh-2.example.com 00112233445566778899aabbccddeeff +# And so on.. One line per R0KH. + +# List of R1KHs in the same Mobility Domain +# format: <128-bit key as hex string> +# This list is used to map R1KH-ID to a destination MAC address when sending +# PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD +# that can request PMK-R1 keys. +#r1kh=02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f +#r1kh=02:01:02:03:04:06 02:11:22:33:44:66 00112233445566778899aabbccddeeff +# And so on.. One line per R1KH. + +# Whether PMK-R1 push is enabled at R0KH +# 0 = do not push PMK-R1 to all configured R1KHs (default) +# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived +#pmk_r1_push=1 + +##### Passive scanning ######################################################## +# Scan different channels every N seconds. 0 = disable passive scanning. +#passive_scan_interval=60 + +# Listen N usecs on each channel when doing passive scanning. +# This value plus the time needed for changing channels should be less than +# 32 milliseconds (i.e. 32000 usec) to avoid interruptions to normal +# operations. Time needed for channel changing varies based on the used wlan +# hardware. +# default: disabled (0) +#passive_scan_listen=10000 + +# Passive scanning mode: +# 0 = scan all supported modes (802.11a/b/g/Turbo) (default) +# 1 = scan only the mode that is currently used for normal operations +#passive_scan_mode=1 + +# Maximum number of entries kept in AP table (either for passive scanning or +# for detecting Overlapping Legacy BSS Condition). The oldest entry will be +# removed when adding a new entry that would make the list grow over this +# limit. Note! Wi-Fi certification for IEEE 802.11g requires that OLBC is +# enabled, so this field should not be set to 0 when using IEEE 802.11g. +# default: 255 +#ap_table_max_size=255 + +# Number of seconds of no frames received after which entries may be deleted +# from the AP table. Since passive scanning is not usually performed frequently +# this should not be set to very small value. In addition, there is no +# guarantee that every scan cycle will receive beacon frames from the +# neighboring APs. +# default: 60 +#ap_table_expiration_time=3600 + + +##### Wi-Fi Protected Setup (WPS) ############################################# + +# WPS state +# 0 = WPS disabled (default) +# 1 = WPS enabled, not configured +# 2 = WPS enabled, configured +#wps_state=2 + +# AP can be configured into a locked state where new WPS Registrar are not +# accepted, but previously authorized Registrars (including the internal one) +# can continue to add new Enrollees. +ap_setup_locked=1 + +# Universally Unique IDentifier (UUID; see RFC 4122) of the device +# This value is used as the UUID for the internal WPS Registrar. If the AP +# is also using UPnP, this value should be set to the device's UPnP UUID. +# If not configured, UUID will be generated based on the local MAC address. +#uuid=12345678-9abc-def0-1234-56789abcdef0 + +# Note: If wpa_psk_file is set, WPS is used to generate random, per-device PSKs +# that will be appended to the wpa_psk_file. If wpa_psk_file is not set, the +# default PSK (wpa_psk/wpa_passphrase) will be delivered to Enrollees. Use of +# per-device PSKs is recommended as the more secure option (i.e., make sure to +# set wpa_psk_file when using WPS with WPA-PSK). + +# When an Enrollee requests access to the network with PIN method, the Enrollee +# PIN will need to be entered for the Registrar. PIN request notifications are +# sent to hostapd ctrl_iface monitor. In addition, they can be written to a +# text file that could be used, e.g., to populate the AP administration UI with +# pending PIN requests. If the following variable is set, the PIN requests will +# be written to the configured file. +#wps_pin_requests=/var/run/hostapd_wps_pin_requests + +# Device Name +# User-friendly description of device; up to 32 octets encoded in UTF-8 +#device_name=Wireless AP + +# Manufacturer +# The manufacturer of the device (up to 64 ASCII characters) +#manufacturer=Qualcomm + +# Model Name +# Model of the device (up to 32 ASCII characters) +#model_name=QualcommSoftAP + +# Model Number +# Additional device description (up to 32 ASCII characters) +#model_number=123 + +# Serial Number +# Serial number of the device (up to 32 characters) +#serial_number=12345 + +# Primary Device Type +# Used format: -- +# categ = Category as an integer value +# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for +# default WPS OUI +# subcateg = OUI-specific Sub Category as an integer value +# Examples: +# 1-0050F204-1 (Computer / PC) +# 1-0050F204-2 (Computer / Server) +# 5-0050F204-1 (Storage / NAS) +# 6-0050F204-1 (Network Infrastructure / AP) +#device_type=6-0050F204-1 + +# OS Version +# 4-octet operating system version number (hex string) +#os_version=01020300 + +# Config Methods +# List of the supported configuration methods +config_methods=label display push_button keypad + +# Access point PIN for initial configuration and adding Registrars +# If not set, hostapd will not allow external WPS Registrars to control the +# access point. +#ap_pin=12345670 + +# Skip building of automatic WPS credential +# This can be used to allow the automatically generated Credential attribute to +# be replaced with pre-configured Credential(s). +#skip_cred_build=1 + +# Additional Credential attribute(s) +# This option can be used to add pre-configured Credential attributes into M8 +# message when acting as a Registrar. If skip_cred_build=1, this data will also +# be able to override the Credential attribute that would have otherwise been +# automatically generated based on network configuration. This configuration +# option points to an external file that much contain the WPS Credential +# attribute(s) as binary data. +#extra_cred=hostapd.cred + +# Credential processing +# 0 = process received credentials internally (default) +# 1 = do not process received credentials; just pass them over ctrl_iface to +# external program(s) +# 2 = process received credentials internally and pass them over ctrl_iface +# to external program(s) +# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and +# extra_cred be used to provide the Credential data for Enrollees. +# +# wps_cred_processing=1 will disabled automatic updates of hostapd.conf file +# both for Credential processing and for marking AP Setup Locked based on +# validation failures of AP PIN. An external program is responsible on updating +# the configuration appropriately in this case. +#wps_cred_processing=0 + +# AP Settings Attributes for M7 +# By default, hostapd generates the AP Settings Attributes for M7 based on the +# current configuration. It is possible to override this by providing a file +# with pre-configured attributes. This is similar to extra_cred file format, +# but the AP Settings attributes are not encapsulated in a Credential +# attribute. +#ap_settings=hostapd.ap_settings + +# WPS UPnP interface +# If set, support for external Registrars is enabled. +#upnp_iface=br0 + +# Friendly Name (required for UPnP) +# Short description for end use. Should be less than 64 characters. +#friendly_name=Qualcomm Access Point + +# Manufacturer URL (optional for UPnP) +#manufacturer_url=http://www.qualcomm.com/ + +# Model Description (recommended for UPnP) +# Long description for end user. Should be less than 128 characters. +#model_description=Wireless Access Point + +# Model URL (optional for UPnP) +#model_url=http://www.qualcomm.com/ + +# Universal Product Code (optional for UPnP) +# 12-digit, all-numeric code that identifies the consumer package. +#upc=123456789012 + +##### Multiple BSSID support ################################################## +# +# Above configuration is using the default interface (wlan#, or multi-SSID VLAN +# interfaces). Other BSSIDs can be added by using separator 'bss' with +# default interface name to be allocated for the data packets of the new BSS. +# +# hostapd will generate BSSID mask based on the BSSIDs that are +# configured. hostapd will verify that dev_addr & MASK == dev_addr. If this is +# not the case, the MAC address of the radio must be changed before starting +# hostapd (ifconfig wlan0 hw ether ). +# +# BSSIDs are assigned in order to each BSS, unless an explicit BSSID is +# specified using the 'bssid' parameter. +# If an explicit BSSID is specified, it must be chosen such that it: +# - results in a valid MASK that covers it and the dev_addr +# - is not the same as the MAC address of the radio +# - is not the same as any other explicitly specified BSSID +# +# Please note that hostapd uses some of the values configured for the first BSS +# as the defaults for the following BSSes. However, it is recommended that all +# BSSes include explicit configuration of all relevant configuration items. +# +#bss=wlan0_0 +#ssid=test2 +# most of the above items can be used here (apart from radio interface specific +# items, like channel) + +#bss=wlan0_1 +#bssid=00:13:10:95:fe:0b +# ... diff --git a/wifi/p2p_supplicant_overlay.conf b/wifi/p2p_supplicant_overlay.conf new file mode 100644 index 0000000..acbace2 --- /dev/null +++ b/wifi/p2p_supplicant_overlay.conf @@ -0,0 +1 @@ +disable_scan_offload=1 diff --git a/wifi/wpa_supplicant_overlay.conf b/wifi/wpa_supplicant_overlay.conf new file mode 100644 index 0000000..e1f530d --- /dev/null +++ b/wifi/wpa_supplicant_overlay.conf @@ -0,0 +1,3 @@ +disable_scan_offload=1 +p2p_disabled=1 +tdls_external_control=1