diff options
-rw-r--r-- | CMakeLists.txt | 173 | ||||
-rw-r--r-- | README.md | 189 | ||||
-rw-r--r-- | cmake/FindVPP.cmake | 209 | ||||
-rw-r--r-- | cmake/Packager.cmake | 151 | ||||
-rw-r--r-- | src/dpi.api | 42 | ||||
-rw-r--r-- | src/dpi.api.h | 179 | ||||
-rw-r--r-- | src/dpi.c | 723 | ||||
-rw-r--r-- | src/dpi.h | 330 | ||||
-rw-r--r-- | src/dpi_api.c | 160 | ||||
-rw-r--r-- | src/dpi_app_match.h | 124 | ||||
-rw-r--r-- | src/dpi_cli.c | 357 | ||||
-rw-r--r-- | src/dpi_node.c | 1035 | ||||
-rw-r--r-- | src/dpi_plugin_doc.md | 107 | ||||
-rw-r--r-- | src/protocols/dpi_ssl.c | 247 |
14 files changed, 10 insertions, 4016 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 95d5cad..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright (c) 2017-2019 Cisco, Intel and/or its affiliates. -# 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. - -cmake_minimum_required(VERSION 3.0 FATAL_ERROR) -project(udpi-plugin) - -include(GNUInstallDirs) - -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} - "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" -) - -set (CMAKE_CXX_STANDARD 11) -set (CMAKE_C_STANDARD 11) - -# Check for memfd_create syscall -include(CheckSymbolExists) -CHECK_SYMBOL_EXISTS ( "__NR_memfd_create" "sys/syscall.h" HAVE_MEMFD_CREATE ) -if ( HAVE_MEMFD_CREATE ) - add_definitions ( -DHAVE_MEMFD_CREATE ) -endif() - -if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - set(UDPI_PLUGIN udpi-plugin) -endif() - -include (Packager) - -# Dependencies - -message(STATUS "Looking for Hyperscan") -find_path(HYPERSCAN_INCLUDE_DIR NAMES hs/hs.h) -find_library(HYPERSCAN_LIB1 NAMES hs) -find_library(HYPERSCAN_LIB2 NAMES hs_runtime) -set (HYPERSCAN_LIB ${HYPERSCAN_LIB1} ${HYPERSCAN_LIB2}) -if(HYPERSCAN_INCLUDE_DIR AND HYPERSCAN_LIB) - include_directories(${HYPERSCAN_INCLUDE_DIR}) - message(STATUS "Found Hyperscan in ${HYPERSCAN_INCLUDE_DIR}") -else() - message(WARNING "-- Hyperscan not found - dpi_plugin disabled") -endif() - -find_package(VPP REQUIRED) - -include_directories(${VPP_INCLUDE_DIR}) - -set(UDPI_PLUGIN_FILES - src/dpi.c - src/dpi_api.c - src/dpi_cli.c - src/dpi_node.c - src/protocols/dpi_ssl.c -) - -set(UDPI_PLUGIN_HEADER_FILES - src/dpi_app_match.h - src/dpi.h - ) - -set(UDPI_API_TEST_SOURCE_FILES - ) - -set(UDPI_API_GENERATED_FILES - ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.h) - -set(UDPI_VAPI_GENERATED_FILES - ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.vapi.h - ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.vapi.hpp) - -if (NOT VPP_HOME) - set(VPP_HOME /usr) -endif() - -if (NOT CMAKE_BUILD_TYPE) - set (CMAKE_BUILD_TYPE "Release") -endif (NOT CMAKE_BUILD_TYPE) - -SET(UDPI_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} CACHE STRING "udpi_install_prefix") - -if (CMAKE_BUILD_TYPE STREQUAL "Release") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wall -march=native -O3 -g") -elseif (CMAKE_BUILD_TYPE STREQUAL "Debug") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -march=native -O0 -g") - add_definitions(-DCLIB_DEBUG -fPIC -fstack-protector-all) -endif() - -execute_process( - COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi - ) -# These files are missing from vpp binary distribution -execute_process( - COMMAND curl https://git.fd.io/vpp/plain/src/vpp-api/vapi/vapi_json_parser.py?h=stable/1908 -o ${CMAKE_BINARY_DIR}/vapi_json_parser.py - COMMAND curl https://git.fd.io/vpp/plain/src/vpp-api/vapi/vapi_c_gen.py?h=stable/1908 -o ${CMAKE_BINARY_DIR}/vapi_c_gen.py - COMMAND curl https://git.fd.io/vpp/plain/src/vpp-api/vapi/vapi_cpp_gen.py?h=stable/1908 -o ${CMAKE_BINARY_DIR}/vapi_cpp_gen.py - ) - -add_custom_command( - COMMAND chmod +x ${CMAKE_BINARY_DIR}/vapi_json_parser.py ${CMAKE_BINARY_DIR}/vapi_c_gen.py ${CMAKE_BINARY_DIR}/vapi_cpp_gen.py - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.h - COMMAND ${VPP_HOME}/bin/vppapigen --input ${CMAKE_CURRENT_SOURCE_DIR}/src/dpi.api --output ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.h - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/dpi.api - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.json - COMMAND ${VPP_HOME}/bin/vppapigen JSON --input ${CMAKE_CURRENT_SOURCE_DIR}/src/dpi.api --output ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.json - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.vapi.h - COMMAND ${CMAKE_BINARY_DIR}/vapi_c_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.json - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.vapi.hpp - COMMAND ${CMAKE_BINARY_DIR}/vapi_cpp_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi/dpi.api.json - ) - -include_directories(SYSTEM) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUDPI_VPP_PLUGIN=1") -add_library(udpi_plugin SHARED - ${UDPI_PLUGIN_FILES} - ${UDPI_API_GENERATED_FILES} - ${UDPI_VAPI_GENERATED_FILES}) -target_link_libraries(udpi_plugin ${HYPERSCAN_LIB}) - -file(COPY ${UDPI_PLUGIN_HEADER_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/udpi) -include_directories(${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins) - -add_library(udpi_api_test_plugin SHARED - ${UDPI_API_TEST_SOURCE_FILES} - ${UDPI_API_GENERATED_FILES}) - -set(VPP_INSTALL_PLUGIN ${UDPI_INSTALL_PREFIX}/vpp_plugins) -set(VPP_INSTALL_API_TEST_PLUGIN ${UDPI_INSTALL_PREFIX}/vpp_api_test_plugins CACHE STRING "vpp_install_api_test_plugin") - -set_target_properties(udpi_plugin - PROPERTIES - LINKER_LANGUAGE C - INSTALL_RPATH ${VPP_INSTALL_PLUGIN} - PREFIX "") -set_target_properties(udpi_api_test_plugin - PROPERTIES - LINKER_LANGUAGE C - PREFIX "") - -install(DIRECTORY - DESTINATION ${VPP_INSTALL_PLUGIN} - COMPONENT ${UDPI_PLUGIN}) -install(TARGETS udpi_plugin - DESTINATION ${VPP_INSTALL_PLUGIN} - COMPONENT ${UDPI_PLUGIN}) - -#install(DIRECTORY -# DESTINATION ${VPP_INSTALL_API_TEST_PLUGIN} -# COMPONENT ${UDPI_PLUGIN}) -#install(TARGETS udpi_api_test_plugin -# DESTINATION ${VPP_INSTALL_API_TEST_PLUGIN} -# COMPONENT ${UDPI_PLUGIN}) - -install(FILES ${UDPI_API_HEADER_FILES} ${UDPI_API_GENERATED_FILES} - DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vpp_plugins/udpi - COMPONENT ${UDPI_PLUGIN}-dev) - -install(FILES ${UDPI_VAPI_GENERATED_FILES} - DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vapi - COMPONENT ${UDPI_PLUGIN}-dev) - -make_packages() @@ -6,192 +6,23 @@ UDPI The UDPI (Universal Deep Packet Inspection) project is a reference framework to build a high performance solution for Deep Packet Inspection, integrated with the general purpose FD.io VPP stack. It leverages industry regex matching library to provide a rich set of features, - which can be used in IPS/IDS, Web Firewall and similar applications. +which can be used in IPS/IDS, Web Firewall and similar applications. - For more information on UDPI and its features please visit the - [UDPI website](https://wiki.fd.io/view/UDPI) +For more information on UDPI and its features please visit the +[UDPI website](https://wiki.fd.io/view/UDPI) ## Changes - Details of the changes leading up to this version of UDPI can be found under - @ref release notes. +Details of the changes leading up to this version of UDPI can be found under +@ref release notes. -## Quick Start ## -``` -From the code tree root -(VPP installed with DEB or RPM pkg) -$ cd udpi-plugin -$ mkdir -p build -$ cd build -$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr #(add "-DCMKAE_INSTALL_LIBDIR=lib" on centos and it's releated) -$ make package +## Getting started -(VPP source code -- build type RELEASE) -$ cd udpi-plugin -$ mkdir -p build -$ cd build -$ cmake .. -DVPP_HOME=<vpp dir>/build-root/install-vpp-native/vpp -DCMAKE_INSTALL_PREFIX=<vpp src>/build-root/install-vpp-native/vpp #(add "-DCMKAE_INSTALL_LIBDIR=lib" on centos and it's releated) -$ make -$ sudo make install +Make sure you have added FD.io repository using https://packagecloud.io/fdio/release/ +installation script. +You should have a sight on the release package, the package name may be different depending on the distribution. +(ex: vpp-plugins.deb for VPP 19.01 and vpp-plugin-core.deb and vpp-plugin-dpdk.deb in 19.04) -(VPP source code -- build type DEBUG) -$ cd udpi-plugin -$ mkdir -p build -$ cd build -$ cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DVPP_HOME=<vpp dir>/build-root/install-vpp_debug-native/vpp -DCMAKE_INSTALL_PREFIX=<vpp src>/build-root/install-vpp_debug-native/vpp #(add "-DCMKAE_INSTALL_LIBDIR=lib" on centos and it's releated) -$ make -$ sudo make install -CMAKE variables: -- CMKAE_INSTALL_LIBDIR -- set the library directory. In CentOS, it is lib or lib64, in debian and it's releated, it is lib/x86_64-linux-gnu -- CMAKE_INSTALL_PREFIX -- set the install directory for the udpi-plugin. This is the common path to the lib folder containing vpp_plugins and vpp_api_test_plugins folders. Default is /usr/local. -- VPP_HOME -- set the directory containing the include and lib directories of vpp. -``` - -## Using udpi plugin ## - -### Platforms ### - -udpi-plugin has been tested in: - -- Ubuntu 16.04 LTS (x86_64) -- Ubuntu 18.04 LTS (x86_64) -- Debian Stable/Testing -- Red Hat Enterprise Linux 7 -- CentOS 7 - - -### Dependencies ### - -Build dependencies: - -- Hyperscan - -- VPP 19.08 - - DEB packages (can be found https://packagecloud.io/fdio/release/install): - - libvppinfra-dev - - vpp-dev - -Running dependencies: - -- VPP 19.08 - - DEB packages (can be found https://packagecloud.io/fdio/release/install): - - vpp - - vpp-plugin-core - - vpp-plugin-dpdk (only to use DPDK compatible nics) - -Hardware support (not mandatory): - -- [DPDK](http://DPDK.org/) compatible nics - -## Getting started ## -In order to start, the udpi plugin requires a running instance of VPP -The steps required to successfully start udpi are: - -- Setup the host to run VPP -- Configure VPP to use DPDK compatible nics -- Start VPP -- Configure VPP interfaces -- Configure and start udpi - -Detailed information for configuring VPP can be found at [https://wiki.fd.io/view/VPP](https://wiki.fd.io/view/VPP). - -### Setup the host for VPP ### - -Hugepages must be enabled in the system - -``` -$ sudo sysctl -w vm.nr_hugepages=1024 -``` - -In order to use a DPDK interface, the `uio` and `uio_pci_generic` or `vfio_pci` modules need to be loaded in the kernel - -``` -$ sudo modprobe uio -$ sudo modprobe uio_pci_generic -$ sudo modprobe vfio_pci -``` - -If the DPDK interface we want to assign to VPP is up, we must bring it down - -``` -$ sudo ifconfig <interface_name> down -``` -or -``` -$ sudo ip link set <interface_name> down -``` - -### Configure VPP ### -The file /etc/VPP/startup.conf contains a set of parameters to setup VPP at startup. -The following example sets up VPP to use a DPDK interfaces: - -``` shell -unix { - nodaemon - log /tmp/vpp.log - full-coredump -} - -api-trace { - on -} - -api-segment { - gid vpp -} - -dpdk { - dev 0000:08:00.0 -} - -plugins { - ## Disable all plugins by default and then selectively enable specific plugins - - ## Enable all plugins by default and then selectively disable specific plugins -} -``` -Where `0000:08:00.0` must be replaced with the actual PCI address of the DPDK interface - -### Start VPP ### - -VPP can be started as a process or a service: - -``` shell -Start VPP as a service in Ubuntu 16.04 -$ sudo systemctl start vpp - -Start VPP as a process in both 16.04 -$ sudo vpp -c /etc/vpp/startup.conf - -``` - -### Configure udpi plugin ### -The udpi plugin can be configured either using the VPP command-line interface (CLI), through a configuration file or through the VPP binary api - -#### udpi plugin CLI #### - -The CLI commands for the udpi plugin start all with the udpi keyword. To see the full list of command available type: -...(to be added) - -## License ## - -This software is distributed under the following license: - -``` -Copyright (c) 2017-2019 Cisco and/or its affiliates. -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. - -``` diff --git a/cmake/FindVPP.cmake b/cmake/FindVPP.cmake deleted file mode 100644 index 56ab482..0000000 --- a/cmake/FindVPP.cmake +++ /dev/null @@ -1,209 +0,0 @@ -# -# Copyright (c) 2018 PANTHEON.tech. -# -# 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. - - -# - Try to find LibVPP -# Once done this will define -# -# VPP_FOUND - system has VPP -# VPP_INCLUDE_DIRS - the VPP include directory -# VPP_LIBRARIES - Link these to use LibSSH - - -if (VPP_LIBRARIES AND VPP_INCLUDE_DIRS) - # in cache already - set(VPP_FOUND TRUE) -else (VPP_LIBRARIES AND VPP_INCLUDE_DIRS) - - set(VPP_INCLUDE_PATH - /usr/include - /usr/local/include - /opt/local/include - /sw/include - ) - - set(VPP_LIBRARY_PATH - /usr/lib - /usr/lib64 - /usr/local/lib - /usr/local/lib64 - /opt/local/lib - /sw/lib - ) - - find_path(VNET_INCLUDE_DIR - NAMES - vnet/vnet.h - PATHS - ${VPP_INCLUDE_PATH} - ${CMAKE_INCLUDE_PATH} - ${CMAKE_INSTALL_PREFIX}/include - - ) - - find_path(VLIB_API_INCLUDE_DIR - NAMES - vlibapi/api.h - PATHS - ${VPP_INCLUDE_PATH} - ${CMAKE_INCLUDE_PATH} - ${CMAKE_INSTALL_PREFIX}/include - ) - - find_path(VLIBMEMORY_INCLUDE_DIR - NAMES - vlibmemory/api.h - PATHS - ${VPP_INCLUDE_PATH} - ${CMAKE_INCLUDE_PATH} - ${CMAKE_INSTALL_PREFIX}/include - ) - - find_path(VPP_MSG_INCLUDE_DIR - NAMES - vpp/api/vpe_msg_enum.h - PATHS - ${VPP_INCLUDE_PATH} - ${CMAKE_INCLUDE_PATH} - ${CMAKE_INSTALL_PREFIX}/include - ) - - find_path(VPP_ALL_INCLUDE_DIR - NAMES - vpp/api/vpe_all_api_h.h - PATHS - ${VPP_INCLUDE_PATH} - ${CMAKE_INCLUDE_PATH} - ${CMAKE_INSTALL_PREFIX}/include - ) - - find_path(VAPI_INCLUDE_DIR - NAMES - vapi/interface.api.vapi.h - PATHS - ${VPP_INCLUDE_PATH} - ${CMAKE_INCLUDE_PATH} - ${CMAKE_INSTALL_PREFIX}/include - ) - - find_path(VOM_INCLUDE_DIR - NAMES - vom/om.hpp - PATHS - ${VPP_INCLUDE_PATH} - ${CMAKE_INCLUDE_PATH} - ${CMAKE_INSTALL_PREFIX}/include - ) - - find_library(VLIBMEMORYCLIENT_LIBRARY - NAMES - vlibmemoryclient - libvlibmemoryclient - PATHS - ${VPP_LIBARY_PATH} - ${CMAKE_LIBRARY_PATH} - ${CMAKE_INSTALL_PREFIX}/lib - ) - - find_library(SVM_LIBRARY - NAMES - svm - libsvm - PATHS - ${VPP_LIBRARY_PATH} - ${CMAKE_LIBRARY_PATH} - ${CMAKE_INSTALL_PREFIX}/lib - ) - - find_library(VPPINFRA_LIBRARY - NAMES - vppinfra - libvppinfra - PATHS - ${VPP_LIBRARY_PATH} - ${CMAKE_LIBRARY_PATH} - ${CMAKE_INSTALL_PREFIX}/lib - ) - - find_library(VLIB_LIBRARY - NAMES - vlib - libvlib - PATHS - ${VPP_LIBRARY_PATH} - ${CMAKE_LIBRARY_PATH} - ${CMAKE_INSTALL_PREFIX}/lib - ) - - find_library(VATPLUGIN_LIBRARY - NAMES - vatplugin - libvatplugin - PATHS - ${VPP_LIBRARY_PATH} - ${CMAKE_LIBRARY_PATH} - ${CMAKE_INSTALL_PREFIX}/lib - ) - - find_library(VAPI_LIBRARY - NAMES - vapiclient - libvapiclient - PATHS - ${VPP_LIBRARY_PATH} - ${CMAKE_LIBRARY_PATH} - ${CMAKE_INSTALL_PREFIX}/lib - ) - - find_library(VOM_LIBRARY - NAMES - vom - libvom - PATHS - ${VPP_LIBRARY_PATH} - ${CMAKE_LIBRARY_PATH} - ${CMAKE_INSTALL_PREFIX}/lib - ) - - if (VPP_INCLUDE_DIR AND VPP_LIBRARY) - set(VPP_FOUND TRUE) - else (VPP_INCLUDE_DIR AND VPP_LIBRARY) - set(VPP_FOUND FALSE) - endif (VPP_INCLUDE_DIR AND VPP_LIBRARY) - - set(VPP_INCLUDE_DIRS - ${VNET_INCLUDE_DIR} - ${VLIB_API_INCLUDE_DIR} - ${VLIB_MEMORY_INCLUDE_DIR} - ${VPP_MSG_INCLUDE_DIR} - ${VPP_ALL_INCLUDE_DIR} - ${VAPI_INCLUDE_DIR} - ${VOM_INCLUDE_DIR} - ) - - set(VPP_LIBRARIES - ${VLIBMEMORYCLIENT_LIBRARY} - ${SVM_LIBRARY} - ${VPPINFRA_LIBRARY} - ${VLIB_LIBRARY} - ${VATPLUGIN_LIBRARY} - ${VAPI_LIBRARY} - ${VOM_LIBRARY} - ) - - # show the VPP_INCLUDE_DIRS and VPP_LIBRARIES variables only in the advanced view - mark_as_advanced(VPP_INCLUDE_DIRS VPP_LIBRARIES) - -endif (VPP_LIBRARIES AND VPP_INCLUDE_DIRS) diff --git a/cmake/Packager.cmake b/cmake/Packager.cmake deleted file mode 100644 index b049819..0000000 --- a/cmake/Packager.cmake +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. -# 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. - -############# -# RPM/DEB/TGZ Packaging utils -# - -set(CONTACT "udpi-dev@lists.fd.io" CACHE STRING "Contact") -set(PACKAGE_MAINTAINER "Udpi Team" CACHE STRING "Maintainer") -set(PACKAGE_VENDOR "fd.io" CACHE STRING "Vendor") - -# macro(set) - -macro(make_packages) - if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") - # parse /etc/os-release - file(READ "/etc/os-release" os_version) - string(REPLACE "\n" ";" os_version ${os_version}) - foreach(_ver ${os_version}) - string(REPLACE "=" ";" _ver ${_ver}) - list(GET _ver 0 _name) - list(GET _ver 1 _value) - set(OS_${_name} ${_value}) - endforeach() - - #extract version from git - execute_process( - COMMAND git describe --long --tags - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - OUTPUT_VARIABLE VER - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - if (NOT VER) - set(VER "v1.0") - endif() - - string(REGEX REPLACE "v(.*)-([0-9]+)-(g[0-9a-f]+)" "\\1;\\2;\\3" VER ${VER}) - list(GET VER 0 tag) - string(REPLACE "-" "~" tag ${tag}) - list(GET VER 1 commit_num) - list(GET VER 2 commit_name) - - message("${tag}") - - if (NOT DEFINED ENV{BUILD_NUMBER}) - set(bld "b1") - else() - set(bld "b$ENV{BUILD_NUMBER}") - endif() - - message("Build number is: ${bld}") - - #define DEB and RPM version numbers - if(${commit_num} EQUAL 0) - set(deb_ver "${tag}") - set(rpm_ver "${tag}") - else() - set(deb_ver "${tag}-${commit_num}-${commit_name}") - set(rpm_ver "${tag}-${commit_num}-${commit_name}") - endif() - - get_cmake_property(components COMPONENTS) - - if(OS_ID_LIKE MATCHES "debian") - set(CPACK_GENERATOR "DEB") - set(type "DEBIAN") - - execute_process( - COMMAND dpkg --print-architecture - OUTPUT_VARIABLE arch - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - set(CPACK_PACKAGE_VERSION "${deb_ver}") - foreach(lc ${components}) - if (${lc} MATCHES ".*Unspecified.*") - continue() - endif() - - string(TOUPPER ${lc} uc) - set(CPACK_${type}_${uc}_FILE_NAME "${lc}_${deb_ver}_${arch}.deb") - - set(DEB_DEPS) - if (NOT ${${lc}_DEB_DEPENDENCIES} STREQUAL "") - string(REPLACE "stable_version" ${tag} DEB_DEPS ${${lc}_DEB_DEPENDENCIES}) - endif() - - set(CPACK_${type}_${uc}_PACKAGE_DEPENDS "${DEB_DEPS}") - set(CPACK_${type}_${uc}_PACKAGE_NAME "${lc}") - set(CPACK_COMPONENT_${uc}_DESCRIPTION "${${lc}_DESCRIPTION}") - endforeach() - elseif(OS_ID_LIKE MATCHES "rhel") - set(CPACK_GENERATOR "RPM") - set(type "RPM") - - execute_process( - COMMAND uname -m - OUTPUT_VARIABLE arch - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - set(CPACK_PACKAGE_VERSION "${rpm_ver}") - foreach(lc ${components}) - if (${lc} MATCHES ".*Unspecified.*") - continue() - endif() - - string(TOUPPER ${lc} uc) - set(CPACK_${type}_${uc}_DESCRIPTION "${${lc}_DESCRIPTION}") - - set(RPM_DEPS) - if (NOT ${${lc}_DEB_DEPENDENCIES} STREQUAL "") - string(REPLACE "stable_version" ${tag} RPM_DEPS ${${lc}_RPM_DEPENDENCIES}) - endif() - - set(CPACK_${type}_${uc}_PACKAGE_REQUIRES "${RPM_DEPS}") - - if(${lc} MATCHES ".*-dev") - set(package_name ${lc}el) - else() - set(package_name ${lc}) - endif() - - set(CPACK_RPM_${uc}_PACKAGE_NAME "${package_name}") - set(CPACK_${type}_${uc}_FILE_NAME "${package_name}-${rpm_ver}.${arch}.rpm") - endforeach() - endif() - - if(CPACK_GENERATOR) - set(CPACK_PACKAGE_NAME ${ARG_NAME}) - set(CPACK_STRIP_FILES OFF) - set(CPACK_PACKAGE_VENDOR "${PACKAGE_VENDOR}") - set(CPACK_COMPONENTS_IGNORE_GROUPS 1) - set(CPACK_${CPACK_GENERATOR}_COMPONENT_INSTALL ON) - set(CPACK_${type}_PACKAGE_MAINTAINER "Udpi Team") - set(CPACK_${type}_PACKAGE_RELEASE 1) - include(CPack) - endif() - endif() -endmacro() diff --git a/src/dpi.api b/src/dpi.api deleted file mode 100644 index b9fa99e..0000000 --- a/src/dpi.api +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018 Intel, Travelping and/or its affiliates. - * 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. - */ - -option version = "1.0.0"; - -define dpi_flow_add_del { - u32 client_index; - u32 context; - u8 is_add; - u8 is_ipv6; - u8 src_ip[16]; - u8 dst_ip[16]; - u16 src_port; - u16 dst_port; - u32 vrf_id; - u8 protocol; -}; - -define dpi_flow_add_del_reply -{ - u32 context; - i32 retval; - u32 flow_id; -}; - -/* - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/dpi.api.h b/src/dpi.api.h deleted file mode 100644 index 3ee50db..0000000 --- a/src/dpi.api.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * VLIB API definitions 2019-09-02 14:52:52 - * Input file: dpi.api - * Automatically generated: please edit the input file NOT this file! - */ - -#include <stdbool.h> -#if defined(vl_msg_id)||defined(vl_union_id) \ - || defined(vl_printfun) ||defined(vl_endianfun) \ - || defined(vl_api_version)||defined(vl_typedefs) \ - || defined(vl_msg_name)||defined(vl_msg_name_crc_list) \ - || defined(vl_api_version_tuple) -/* ok, something was selected */ -#else -#warning no content included from dpi.api -#endif - -#define VL_API_PACKED(x) x __attribute__ ((packed)) - -/****** Message ID / handler enum ******/ - -#ifdef vl_msg_id -vl_msg_id(VL_API_DPI_FLOW_ADD_DEL, vl_api_dpi_flow_add_del_t_handler) -vl_msg_id(VL_API_DPI_FLOW_ADD_DEL_REPLY, vl_api_dpi_flow_add_del_reply_t_handler) -#endif -/****** Message names ******/ - -#ifdef vl_msg_name -vl_msg_name(vl_api_dpi_flow_add_del_t, 1) -vl_msg_name(vl_api_dpi_flow_add_del_reply_t, 1) -#endif -/****** Message name, crc list ******/ - -#ifdef vl_msg_name_crc_list -#define foreach_vl_msg_name_crc_dpi \ -_(VL_API_DPI_FLOW_ADD_DEL, dpi_flow_add_del, 52a12407) \ -_(VL_API_DPI_FLOW_ADD_DEL_REPLY, dpi_flow_add_del_reply, e467dfee) -#endif - -/****** Typedefs ******/ - -#ifdef vl_typedefs -#ifndef included_dpi_api -#define included_dpi_api -#ifndef _vl_api_defined_dpi_flow_add_del -#define _vl_api_defined_dpi_flow_add_del -typedef VL_API_PACKED(struct _vl_api_dpi_flow_add_del { - u16 _vl_msg_id; - u32 client_index; - u32 context; - u8 is_add; - u8 is_ipv6; - u8 src_ip[16]; - u8 dst_ip[16]; - u16 src_port; - u16 dst_port; - u32 vrf_id; - u8 protocol; -}) vl_api_dpi_flow_add_del_t; -#endif - -#ifndef _vl_api_defined_dpi_flow_add_del_reply -#define _vl_api_defined_dpi_flow_add_del_reply -typedef VL_API_PACKED(struct _vl_api_dpi_flow_add_del_reply { - u16 _vl_msg_id; - u32 context; - i32 retval; - u32 flow_id; -}) vl_api_dpi_flow_add_del_reply_t; -#endif - - -#endif -#endif - -/****** Print functions *****/ -#ifdef vl_printfun - -#ifdef LP64 -#define _uword_fmt "%lld" -#define _uword_cast (long long) -#else -#define _uword_fmt "%ld" -#define _uword_cast long -#endif - -#ifndef _vl_api_defined_dpi_flow_add_del_t_print -#define _vl_api_defined_dpi_flow_add_del_t_print -static inline void *vl_api_dpi_flow_add_del_t_print (vl_api_dpi_flow_add_del_t *a,void *handle) -{ - vl_print(handle, "vl_api_dpi_flow_add_del_t:\n"); - vl_print(handle, "_vl_msg_id: %u\n", a->_vl_msg_id); - vl_print(handle, "client_index: %u\n", a->client_index); - vl_print(handle, "context: %u\n", a->context); - vl_print(handle, "is_add: %u\n", a->is_add); - vl_print(handle, "is_ipv6: %u\n", a->is_ipv6); - vl_print(handle, "src_port: %u\n", a->src_port); - vl_print(handle, "dst_port: %u\n", a->dst_port); - vl_print(handle, "vrf_id: %u\n", a->vrf_id); - vl_print(handle, "protocol: %u\n", a->protocol); - return handle; -} - -#endif - -#ifndef _vl_api_defined_dpi_flow_add_del_reply_t_print -#define _vl_api_defined_dpi_flow_add_del_reply_t_print -static inline void *vl_api_dpi_flow_add_del_reply_t_print (vl_api_dpi_flow_add_del_reply_t *a,void *handle) -{ - vl_print(handle, "vl_api_dpi_flow_add_del_reply_t:\n"); - vl_print(handle, "_vl_msg_id: %u\n", a->_vl_msg_id); - vl_print(handle, "context: %u\n", a->context); - vl_print(handle, "retval: %ld\n", a->retval); - vl_print(handle, "flow_id: %u\n", a->flow_id); - return handle; -} - -#endif - - -#endif /* vl_printfun */ - -/****** Endian swap functions *****/ -#ifdef vl_endianfun - -#undef clib_net_to_host_uword -#ifdef LP64 -#define clib_net_to_host_uword clib_net_to_host_u64 -#else -#define clib_net_to_host_uword clib_net_to_host_u32 -#endif - -#ifndef _vl_api_defined_dpi_flow_add_del_t_endian -#define _vl_api_defined_dpi_flow_add_del_t_endian -static inline void vl_api_dpi_flow_add_del_t_endian (vl_api_dpi_flow_add_del_t *a) -{ - a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); - a->client_index = clib_net_to_host_u32(a->client_index); - a->context = clib_net_to_host_u32(a->context); - /* a->is_add = a->is_add (no-op) */ - /* a->is_ipv6 = a->is_ipv6 (no-op) */ - a->src_port = clib_net_to_host_u16(a->src_port); - a->dst_port = clib_net_to_host_u16(a->dst_port); - a->vrf_id = clib_net_to_host_u32(a->vrf_id); - /* a->protocol = a->protocol (no-op) */ -} - -#endif - -#ifndef _vl_api_defined_dpi_flow_add_del_reply_t_endian -#define _vl_api_defined_dpi_flow_add_del_reply_t_endian -static inline void vl_api_dpi_flow_add_del_reply_t_endian (vl_api_dpi_flow_add_del_reply_t *a) -{ - a->_vl_msg_id = clib_net_to_host_u16(a->_vl_msg_id); - a->context = clib_net_to_host_u32(a->context); - a->retval = clib_net_to_host_u32(a->retval); - a->flow_id = clib_net_to_host_u32(a->flow_id); -} - -#endif - - -#endif /* vl_endianfun */ - -/****** Version tuple *****/ - -#ifdef vl_api_version_tuple - -vl_api_version_tuple(dpi.api, 1, 0, 0) - -#endif /* vl_api_version_tuple */ - -/****** API CRC (whole file) *****/ - -#ifdef vl_api_version -vl_api_version(dpi.api, 0x79814222) - -#endif - diff --git a/src/dpi.c b/src/dpi.c deleted file mode 100644 index 6423f3a..0000000 --- a/src/dpi.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 Intel, Travelping and/or its affiliates. - * 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 <stdint.h> -#include <string.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <inttypes.h> - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vnet/ethernet/ethernet.h> -#include <vnet/fib/fib_entry.h> -#include <vnet/fib/fib_table.h> -#include <vnet/mfib/mfib_table.h> -//#include <vnet/adj/adj_mcast.h> -#include <vnet/dpo/dpo.h> -#include <vnet/plugin/plugin.h> -//#include <vpp/app/version.h> -#include <vnet/flow/flow.h> - -#include "dpi.h" - -dpi_main_t dpi_main; -dpi_entry_t *dpi_dbs = NULL; - -#if CLIB_DEBUG > 0 -#define dpi_debug clib_warning -#else -#define dpi_debug(...) \ - do { } while (0) -#endif - -/* Here rules are extracted from below link with BSD License - * https://rules.emergingthreats.net/open-nogpl/snort-2.9.0/emerging-all.rules */ - -dpi_app_match_rule app_match_rules[] = { - {"www.cisco.com", NULL, "Cisco", DPI_APP_CISCO} - , - {"*.google.com", NULL, "Google", DPI_APP_GOOGLE} - , - {"www.bing.com", NULL, "Bing", DPI_APP_BING} - , - {"www.msn.com", NULL, "MSN", DPI_APP_MSN} - , - {"www.yahoo.com", NULL, "", DPI_APP_YAHOO} - , - {"mail.yahoo.com", NULL, "YahooMail", DPI_APP_YAHOOMAIL} - , - {"www.intel.com", NULL, "Intel", DPI_APP_INTEL} - , - {"*.amazon.com", NULL, "Amazon", DPI_APP_AMAZON} - , - {"*.amd.com", NULL, "AMD", DPI_APP_AMD} - , - {"*.baidu.com", NULL, "Baidu", DPI_APP_BAIDU} - , - {"*.apple.com", NULL, "Apple", DPI_APP_APPLE} - , - {"*.facebook.com", NULL, "Facebook", DPI_APP_FACEBOOK} - , - {"*.ebay.com", NULL, "Ebay", DPI_APP_EBAY} - , - {"*.github.com", NULL, "GitHub", DPI_APP_GITHUB} - , - {"*.gmail.com", NULL, "Gmail", DPI_APP_GMAIL} - , - {"*.qq.com", NULL, "QQ", DPI_APP_QQ} - , - {"weixin.qq.com", NULL, "Wechat", DPI_APP_WECHAT} - , - {"*.pinterest.com", NULL, "", DPI_APP_PINTEREST} - , - {"*.lenovo.com", NULL, "Levono", DPI_APP_LENOVO} - , - {"*.linkedin.com", NULL, "LinkedIn", DPI_APP_LINKEDIN} - , - {"*.skype.com", NULL, "Skype", DPI_APP_SKYPE} - , - {"*.microsoft.com", NULL, "Microsoft", DPI_APP_MICROSOFT} - , - {"*.netflix.com", NULL, "Netflix", DPI_APP_NETFLIX} - , - {"*.nokia.com", NULL, "Nokia", DPI_APP_NOKIA} - , - {"*.nvidia.com", NULL, "nVIDIA", DPI_APP_NVIDIA} - , - {"*.office365.com", NULL, "Office", DPI_APP_OFFICE} - , - {"*.oracle.com", NULL, "Oracle", DPI_APP_ORACLE} - , - {"*.Outlook.com", NULL, "Outlook", DPI_APP_OUTLOOK} - , - {"*.pandora.com", NULL, "Pandora", DPI_APP_PANDORA} - , - {"*.paypal.com", NULL, "Paypal", DPI_APP_PAYPAL} - , - {"*.sina.com", NULL, "Sina", DPI_APP_SINA} - , - {"*.sogou.com", NULL, "Sogou", DPI_APP_SOGOU} - , - {"*.symantec.com", NULL, "Symantec", DPI_APP_SYMANTEC} - , - {"*.taobao.com", NULL, "Taobao", DPI_APP_TAOBAO} - , - {"*.twitter.com", NULL, "Twitter", DPI_APP_TWITTER} - , - {"*.ups.com", NULL, "UPS", DPI_APP_UPS} - , - {"*.visa.com", NULL, "VISA", DPI_APP_VISA} - , - {"*.mcafee.com", NULL, "Mcafee", DPI_APP_MCAFEE} - , - {"*.vmware.com", NULL, "VMWare", DPI_APP_VMWARE} - , - {"*.wordpress.com", NULL, "Wordpress", DPI_APP_WORDPRESS} - , - {"www.adobe.com", NULL, "Adobe", DPI_APP_ADOBE} - , - {"www.akamai.com", NULL, "Akamai", DPI_APP_AKAMAI} - , - {"*.alienvault.com", NULL, "Alienvault", DPI_APP_ALIENVAULT} - , - {"www.bitcomet.com", NULL, "Bitcomet", DPI_APP_BITCOMET} - , - {"www.checkpoint.com", NULL, "Checkpoint", DPI_APP_CHECKPOINT} - , - {"*.bloomberg.com", NULL, "Bloomberg", DPI_APP_BLOOMBERG} - , - {"www.dell.com", NULL, "DELL", DPI_APP_DELL} - , - {"www.f5.com", NULL, "F5", DPI_APP_F5} - , - {"www.fireeye.com", NULL, "Fireeye", DPI_APP_FIREEYE} - , - {"*.dropbox.com", NULL, "", DPI_APP_DROPBOX} - , - - {NULL, NULL, NULL, 0} -}; - -int -dpi_event_handler (unsigned int id, unsigned long long from, - unsigned long long to, unsigned int flags, void *ctx) -{ - (void) from; - (void) to; - (void) flags; - - dpi_cb_args_t *args = (dpi_cb_args_t *) ctx; - - args->res = 1; - args->id = id; - - return 0; -} - -int -dpi_search_host_protocol (dpi_flow_info_t * flow, - char *str_to_match, - u32 str_to_match_len, - u16 master_protocol_id, u32 * host_protocol_id) -{ - dpi_main_t *dm = &dpi_main; - dpi_entry_t entry = dm->default_db; - dpi_cb_args_t args = { }; - int ret; - - /* First search default database */ - ret = hs_scan_stream (flow->stream, - (const char *) str_to_match, str_to_match_len, 0, - entry.scratch, dpi_event_handler, (void *) &args); - if ((ret != HS_SUCCESS) && (ret != HS_SCAN_TERMINATED)) - { - return DPI_PROTOCOL_UNKNOWN; - } - else - { - flow->app_id = args.id; - flow->detect_done = 1; - goto done; - } - -done: - if (flow->app_id != ~0) - { - /* Move the protocol to right position */ - flow->detected_protocol[1] = master_protocol_id, - flow->detected_protocol[0] = flow->app_id; - *host_protocol_id = flow->app_id; - - return (flow->detected_protocol[0]); - } - - return DPI_PROTOCOL_UNKNOWN; -} - -char * -host2hex (const char *str) -{ - int len, i; - char *hexbuf, *buf; - - len = strlen (str); - hexbuf = (char *) malloc (len * 4 + 1); - if (!hexbuf) - return (NULL); - - for (i = 0, buf = hexbuf; i < len; i++, buf += 4) - { - snprintf (buf, 5, "\\x%02x", (const char) str[i]); - } - *buf = '\0'; - - return hexbuf; -} - -int -dpi_create_db_entry (dpi_entry_t * entry, u32 num, u32 mode) -{ - hs_compile_error_t *compile_err; - - if (hs_compile_multi - ((const char **) entry->expressions, entry->flags, entry->ids, - num, mode, NULL, &entry->database, &compile_err) != HS_SUCCESS) - { - return -1; - } - - if (hs_alloc_scratch (entry->database, &entry->scratch) != HS_SUCCESS) - { - hs_free_database (entry->database); - entry->database = NULL; - return -1; - } - - return 0; -} - - -int -dpi_flow_add_del (dpi_add_del_flow_args_t * a, u32 * flow_idp) -{ - dpi_main_t *dm = &dpi_main; - vnet_main_t *vnm = dm->vnet_main; - dpi4_flow_key_t key4; - dpi6_flow_key_t key6; - dpi_flow_entry_t *p; - u32 is_ip6 = a->is_ipv6; - u32 flow_id; - dpi_flow_entry_t *flow; - - int not_found; - if (!is_ip6) - { - key4.key[0] = a->src_ip.ip4.as_u32 - | (((u64) a->dst_ip.ip4.as_u32) << 32); - key4.key[1] = (((u64) a->protocol) << 32) - | ((u32) clib_host_to_net_u16 (a->src_port) << 16) - | clib_host_to_net_u16 (a->dst_port); - key4.key[2] = (u64) a->fib_index; - - not_found = - clib_bihash_search_inline_24_8 (&dm->dpi4_flow_by_key, &key4); - p = (void *) &key4.value; - } - else - { - key6.key[0] = a->src_ip.ip6.as_u64[0]; - key6.key[1] = a->src_ip.ip6.as_u64[1]; - key6.key[2] = a->dst_ip.ip6.as_u64[0]; - key6.key[3] = a->dst_ip.ip6.as_u64[1]; - key6.key[4] = (((u64) a->protocol) << 32) - | ((u32) clib_host_to_net_u16 (a->src_port) << 16) - | clib_host_to_net_u16 (a->dst_port); - key6.key[5] = (u64) a->fib_index; - - not_found = - clib_bihash_search_inline_48_8 (&dm->dpi6_flow_by_key, &key6); - p = (void *) &key6.value; - } - - if (not_found) - p = 0; - - if (a->is_add) - { - - /* adding a flow entry: entry must not already exist */ - if (p) - return VNET_API_ERROR_TUNNEL_EXIST; - - pool_get_aligned (dm->dpi_flows, flow, CLIB_CACHE_LINE_BYTES); - clib_memset (flow, 0, sizeof (*flow)); - flow_id = flow - dm->dpi_flows; - - /* copy from arg structure */ -#define _(x) flow->key.x = a->x; - foreach_copy_field; -#undef _ - - flow->next_index = DPI_INPUT_NEXT_IP4_LOOKUP; - flow->flow_index = ~0; - - pool_get_aligned (dm->dpi_infos, flow->info, CLIB_CACHE_LINE_BYTES); - clib_memset (flow->info, 0, sizeof (*flow->info)); - flow->info->app_id = ~0; - - int add_failed; - if (is_ip6) - { - key6.value = (u64) flow_id; - add_failed = clib_bihash_add_del_48_8 (&dm->dpi6_flow_by_key, - &key6, 1 /*add */ ); - } - else - { - key4.value = (u64) flow_id; - add_failed = clib_bihash_add_del_24_8 (&dm->dpi4_flow_by_key, - &key4, 1 /*add */ ); - } - - if (add_failed) - { - pool_put (dm->dpi_infos, flow->info); - pool_put (dm->dpi_flows, flow); - return VNET_API_ERROR_INVALID_REGISTRATION; - } - - /* Open a Hyperscan stream for each flow */ - hs_error_t err = hs_open_stream (dm->default_db.database, 0, - &(flow->info->stream)); - if (err != HS_SUCCESS) - { - pool_put (dm->dpi_infos, flow->info); - pool_put (dm->dpi_flows, flow); - return VNET_API_ERROR_INVALID_REGISTRATION; - } - } - else - { - /* deleting a flow: flow must exist */ - if (!p) - return VNET_API_ERROR_NO_SUCH_ENTRY; - - flow_id = is_ip6 ? key6.value : key4.value; - flow_id = (u32) (flow_id & (u32) (~0)); - flow = pool_elt_at_index (dm->dpi_flows, flow_id); - - if (!is_ip6) - clib_bihash_add_del_24_8 (&dm->dpi4_flow_by_key, &key4, 0 /*del */ ); - else - clib_bihash_add_del_48_8 (&dm->dpi6_flow_by_key, &key6, 0 /*del */ ); - - if (flow->flow_index != ~0) - vnet_flow_del (vnm, flow->flow_index); - - /* Close the Hyperscan stream for each flow */ - hs_error_t err = hs_close_stream (flow->info->stream, NULL, - NULL, NULL); - if (err != HS_SUCCESS) - { - return VNET_API_ERROR_INVALID_REGISTRATION; - } - - pool_put (dm->dpi_infos, flow->info); - pool_put (dm->dpi_flows, flow); - } - - if (flow_idp) - *flow_idp = flow_id; - - return 0; -} - -int -dpi_reverse_flow_add_del (dpi_add_del_flow_args_t * a, u32 flow_id) -{ - dpi_main_t *dm = &dpi_main; - vnet_main_t *vnm = dm->vnet_main; - dpi4_flow_key_t key4; - dpi6_flow_key_t key6; - dpi_flow_entry_t *p; - u32 is_ip6 = a->is_ipv6; - dpi_flow_entry_t *flow; - - int not_found; - if (!is_ip6) - { - key4.key[0] = a->dst_ip.ip4.as_u32 - | (((u64) a->src_ip.ip4.as_u32) << 32); - key4.key[1] = (((u64) a->protocol) << 32) - | ((u32) clib_host_to_net_u16 (a->dst_port) << 16) - | clib_host_to_net_u16 (a->src_port); - key4.key[2] = (u64) a->fib_index; - - not_found = - clib_bihash_search_inline_24_8 (&dm->dpi4_flow_by_key, &key4); - p = (void *) &key4.value; - } - else - { - key6.key[0] = a->dst_ip.ip6.as_u64[0]; - key6.key[1] = a->dst_ip.ip6.as_u64[1]; - key6.key[2] = a->dst_ip.ip6.as_u64[0]; - key6.key[3] = a->dst_ip.ip6.as_u64[1]; - key6.key[4] = (((u64) a->protocol) << 32) - | ((u32) a->dst_port << 16) | (a->src_port); - key6.key[5] = (u64) a->fib_index; - - not_found = - clib_bihash_search_inline_48_8 (&dm->dpi6_flow_by_key, &key6); - p = (void *) &key6.value; - } - - if (not_found) - p = 0; - - if (a->is_add) - { - - /* adding a flow entry: entry must not already exist */ - if (p) - return VNET_API_ERROR_TUNNEL_EXIST; - - int add_failed; - if (is_ip6) - { - key6.value = (u64) flow_id | ((u64) 1 << 63); - add_failed = clib_bihash_add_del_48_8 (&dm->dpi6_flow_by_key, - &key6, 1 /*add */ ); - } - else - { - key4.value = (u64) flow_id | ((u64) 1 << 63); - add_failed = clib_bihash_add_del_24_8 (&dm->dpi4_flow_by_key, - &key4, 1 /*add */ ); - } - - if (add_failed) - { - return VNET_API_ERROR_INVALID_REGISTRATION; - } - } - else - { - /* deleting a flow: flow must exist */ - if (!p) - return VNET_API_ERROR_NO_SUCH_ENTRY; - - flow_id = is_ip6 ? key6.value : key4.value; - flow = pool_elt_at_index (dm->dpi_flows, flow_id); - - if (!is_ip6) - clib_bihash_add_del_24_8 (&dm->dpi4_flow_by_key, &key4, 0 /*del */ ); - else - clib_bihash_add_del_48_8 (&dm->dpi6_flow_by_key, &key6, 0 /*del */ ); - - if (flow->flow_index != ~0) - vnet_flow_del (vnm, flow->flow_index); - - pool_put (dm->dpi_flows, flow); - } - - return 0; -} - -int -dpi_tcp_reass (tcp_reass_args_t * a) -{ - dpi_main_t *dm = &dpi_main; - dpi_flow_entry_t *flow; - - flow = pool_elt_at_index (dm->dpi_flows, a->flow_id); - if (flow == NULL) - return -1; - - flow->reass_en = a->reass_en; - flow->reass_dir = a->reass_dir; - return 0; -} - -int -dpi_add_del_rx_flow (u32 hw_if_index, u32 flow_id, int is_add, u32 is_ipv6) -{ - dpi_main_t *dm = &dpi_main; - vnet_main_t *vnm = dm->vnet_main; - dpi_flow_entry_t *dpi_flow; - vnet_flow_t *vent_flow; - - ip_port_and_mask_t src_port; - ip_port_and_mask_t dst_port; - - - dpi_flow = pool_elt_at_index (dm->dpi_flows, flow_id); - - src_port.port = dpi_flow->key.dst_port; - src_port.mask = ~0; - dst_port.port = dpi_flow->key.dst_port; - dst_port.mask = ~0; - - if (is_add) - { - if (dpi_flow->flow_index == ~0) - { - if (!is_ipv6) - { - ip4_address_and_mask_t src_addr4; - ip4_address_and_mask_t dst_addr4; - src_addr4.addr = dpi_flow->key.src_ip.ip4; - src_addr4.mask.as_u32 = ~0; - dst_addr4.addr = dpi_flow->key.dst_ip.ip4; - dst_addr4.mask.as_u32 = ~0; - - vnet_flow_t flow4 = { - .actions = - VNET_FLOW_ACTION_REDIRECT_TO_NODE | VNET_FLOW_ACTION_MARK, - .mark_flow_id = flow_id + dm->flow_id_start, - .redirect_node_index = 0, - .type = VNET_FLOW_TYPE_IP4_N_TUPLE, - .ip4_n_tuple = { - .src_addr = src_addr4, - .dst_addr = dst_addr4, - .src_port = src_port, - .dst_port = dst_port, - .protocol = dpi_flow->key.protocol, - } - , - }; - vent_flow = &flow4; - } - else - { - ip6_address_and_mask_t src_addr6; - ip6_address_and_mask_t dst_addr6; - src_addr6.addr.as_u64[0] = dpi_flow->key.src_ip.ip6.as_u64[0]; - src_addr6.addr.as_u64[1] = dpi_flow->key.src_ip.ip6.as_u64[1]; - src_addr6.mask.as_u64[0] = ~0; - src_addr6.mask.as_u64[1] = ~0; - dst_addr6.addr.as_u64[0] = dpi_flow->key.dst_ip.ip6.as_u64[0]; - dst_addr6.addr.as_u64[1] = dpi_flow->key.dst_ip.ip6.as_u64[1]; - dst_addr6.mask.as_u64[0] = ~0; - dst_addr6.mask.as_u64[1] = ~0; - - vnet_flow_t flow6 = { - .actions = - VNET_FLOW_ACTION_REDIRECT_TO_NODE | VNET_FLOW_ACTION_MARK, - .mark_flow_id = flow_id + dm->flow_id_start, - .redirect_node_index = 0, - .type = VNET_FLOW_TYPE_IP6_N_TUPLE, - .ip6_n_tuple = { - .src_addr = src_addr6, - .dst_addr = dst_addr6, - .src_port = src_port, - .dst_port = dst_port, - .protocol = dpi_flow->key.protocol, - } - , - }; - vent_flow = &flow6; - } - vnet_flow_add (vnm, vent_flow, &(dpi_flow->flow_index)); - } - return vnet_flow_enable (vnm, dpi_flow->flow_index, hw_if_index); - } - - /* flow index is removed when the flow is deleted */ - return vnet_flow_disable (vnm, dpi_flow->flow_index, hw_if_index); -} - -void -dpi_flow_bypass_mode (u32 sw_if_index, u8 is_ip6, u8 is_enable) -{ - if (is_ip6) - vnet_feature_enable_disable ("ip6-unicast", "dpi6-input", - sw_if_index, is_enable, 0, 0); - else - vnet_feature_enable_disable ("ip4-unicast", "dpi4-input", - sw_if_index, is_enable, 0, 0); -} - -int -dpi_init_hs_database (dpi_entry_t * entry) -{ - u32 i, j; - u32 rule_num = 0; - unsigned char *free_list; - int rv; - - for (i = 0; - (app_match_rules[i].host != NULL - || app_match_rules[i].pattern != NULL); i++) - { - rule_num++; - } - - entry->expressions = (regex_t *) calloc (sizeof (char *), rule_num + 1); - if (entry->expressions == NULL) - return -1; - - entry->ids = (u32 *) calloc (sizeof (u32), rule_num + 1); - if (entry->ids == NULL) - { - free (entry->expressions); - return -1; - } - - entry->flags = (u32 *) calloc (sizeof (u32), rule_num + 1); - if (entry->ids == NULL) - { - free (entry->expressions); - free (entry->ids); - return -1; - } - - free_list = (unsigned char *) calloc (sizeof (unsigned char), rule_num + 1); - if (free_list == NULL) - { - free (entry->expressions); - free (entry->ids); - free (entry->flags); - return -1; - } - - /* first choose pattern, otherwise choose host */ - for (i = 0, j = 0; - (app_match_rules[i].host != NULL - || app_match_rules[i].pattern != NULL); i++) - { - if (app_match_rules[i].pattern) - { - entry->expressions[j] = (regex_t) (app_match_rules[i].pattern); - entry->ids[j] = app_match_rules[i].app_id; - entry->flags[j] = HS_FLAG_SINGLEMATCH; - free_list[j] = 0; - ++j; - } - else - { - /* need to allocate additional buffer for rules */ - entry->expressions[j] = - (regex_t) host2hex (app_match_rules[i].host); - if (entry->expressions[j] != NULL) - { - entry->ids[j] = app_match_rules[i].app_id; - entry->flags[j] = HS_FLAG_SINGLEMATCH; - free_list[j] = 1; - ++j; - } - } - } - - rv = dpi_create_db_entry (entry, j, HS_MODE_STREAM); - - /* Need to free additional buffers */ - for (i = 0; i < j; ++i) - { - if (free_list[i]) - free (entry->expressions[i]); - } - - free (entry->expressions); - free (entry->ids); - free (entry->flags); - free (free_list); - return rv; -} - -#define DPI_HASH_NUM_BUCKETS (2 * 1024) -#define DPI_HASH_MEMORY_SIZE (1 << 20) - -clib_error_t * -dpi_init (vlib_main_t * vm) -{ - dpi_main_t *dm = &dpi_main; - - dm->vnet_main = vnet_get_main (); - dm->vlib_main = vm; - - vnet_flow_get_range (dm->vnet_main, "dpi", 1024 * 1024, &dm->flow_id_start); - - /* initialize the flow hash */ - clib_bihash_init_24_8 (&dm->dpi4_flow_by_key, "dpi4", - DPI_HASH_NUM_BUCKETS, DPI_HASH_MEMORY_SIZE); - clib_bihash_init_48_8 (&dm->dpi6_flow_by_key, "dpi6", - DPI_HASH_NUM_BUCKETS, DPI_HASH_MEMORY_SIZE); - - /* Init default Hyperscan database */ - dpi_init_hs_database (&dm->default_db); - - return 0; -} - -VLIB_INIT_FUNCTION (dpi_init); - -/* *INDENT-OFF* */ -VLIB_PLUGIN_REGISTER () = { -// .version = VPP_BUILD_VER, - .description = "Deep Packet Inspection", -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/dpi.h b/src/dpi.h deleted file mode 100644 index e3d0add..0000000 --- a/src/dpi.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 Intel, Travelping and/or its affiliates. - * 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 included_vnet_dpi_h -#define included_vnet_dpi_h - -#include <vppinfra/lock.h> -#include <vppinfra/error.h> -#include <vppinfra/hash.h> -#include <vnet/vnet.h> -#include <vnet/ip/ip.h> -#include <vnet/ethernet/ethernet.h> -#include <vnet/ip/ip4_packet.h> -#include <vnet/ip/ip6_packet.h> -#include <vnet/udp/udp.h> -#include <vnet/dpo/dpo.h> -#include <vppinfra/bihash_8_8.h> -#include <vppinfra/bihash_24_8.h> -#include <vppinfra/bihash_48_8.h> - -#include <hs/hs.h> -#include <hs/hs_common.h> -#include <hs/hs_compile.h> -#include <hs/hs_runtime.h> -#include "dpi_app_match.h" - -typedef u8 *regex_t; - -typedef struct -{ - u8 *name; - regex_t *expressions; - u32 *flags; - u32 *ids; - hs_database_t *database; - hs_scratch_t *scratch; - u32 ref_cnt; -} dpi_entry_t; - -typedef struct -{ - int res; - u32 id; -} dpi_cb_args_t; - -typedef struct -{ - union - { - struct - { - ip46_address_t src_ip; - ip46_address_t dst_ip; - u16 src_port; - u16 dst_port; - u8 protocol; - u32 fib_index; - }; - u64 key[6]; - }; -} dpi_flow_key_t; - -typedef clib_bihash_kv_24_8_t dpi4_flow_key_t; -typedef clib_bihash_kv_48_8_t dpi6_flow_key_t; - -typedef struct -{ - /* SSL */ - u8 ssl_stage; - u8 ssl_got_server_cert; -} dpi_flow_tcp_t; - -typedef struct -{ - /* TBD */ -} dpi_flow_udp_t; - -typedef struct segment_ -{ - u32 send_sn; - u8 *data; - u32 len; - u32 bi; /* vlib buffer index */ - struct segment_ *next; -} segment; - -typedef struct tcp_stream_ -{ - u32 send_sn; /* expected segment sn */ - u32 ack_sn; /* acked segment sn */ - segment *seg_queue; /* store out-of-order segments */ -} tcp_stream_t; - -typedef struct dpi_flow_info -{ - /* Required for pool_get_aligned */ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - - u16 detected_protocol[2]; - u16 protocol_stack_info; - u16 pkt_num; - u16 pkt_direct_counter[2]; - - hs_stream_t *stream; - u8 detect_begin; - u8 detect_done; - u32 app_id; /* L7 APP ID */ - - u16 guessed_protocol_id; - u16 guessed_host_protocol_id; - - u8 max_more_pkts_to_check; - - int (*more_pkts_func) (u8 * payload, u32 payload_len, - struct dpi_flow_info * flow); - - u16 dst_port; - u8 l4_protocol; - union - { - dpi_flow_tcp_t tcp; - dpi_flow_udp_t udp; - } l4; - - u8 ssl_cert_detected:4; - u8 ssl_cert_num_checks:4; - - union - { - struct - { - char server_cert[64]; - } ssl; - /* TBD: Add more protocols */ - } protos; -} dpi_flow_info_t; - -typedef enum -{ - TCP_STATE_SYN = 1, - TCP_STATE_SYN_ACK = 2, - TCP_STATE_ACK = 3, - TCP_STATE_ESTABLISH = 4, - TCP_STATE_FIN1 = 5, - TCP_STATE_CLOSE = 6, -} tcp_state_t; - -/* tcp packet direction */ -#define DIR_C2S 0 -#define DIR_S2C 1 - -/* tcp reassembly side */ -#define REASS_C2S 0 -#define REASS_S2C 1 -#define REASS_BOTH 2 - -/* Macros to handle sequence numbers */ -#define SN_LT(a,b) ((int)((a) - (b)) < 0) -#define SN_GT(a,b) ((int)((a) - (b)) > 0) -#define SN_EQ(a,b) ((int)((a) - (b)) == 0) - -typedef struct -{ - /* Required for pool_get_aligned */ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - - u32 flow_index; /* infra flow index */ - u32 next_index; - - u8 check_more_pkts:1; - u8 pkt_dir:1; - u8 forward_is_c2s:1; - u8 consumed:1; - u8 reass_en:1; - u8 reass_dir:2; - - dpi_flow_key_t key; - dpi_flow_info_t *info; - - /* TCP stream reassembly */ - tcp_state_t tcp_state; - tcp_stream_t c2s; - tcp_stream_t s2c; - segment *first_seg; - -} dpi_flow_entry_t; - -typedef struct -{ - u32 flow_id; - u8 reass_en; - u8 reass_dir; -} tcp_reass_args_t; - -typedef struct -{ - u8 is_add; - u8 is_ipv6; - ip46_address_t src_ip; - ip46_address_t dst_ip; - u16 src_port; - u16 dst_port; - u8 protocol; - u32 fib_index; -} dpi_add_del_flow_args_t; - -typedef struct -{ - u32 app_id; - u32 db_id; -} dpi_adr_t; - -typedef struct -{ - /* lookup tunnel by key */ - clib_bihash_24_8_t dpi4_flow_by_key; - clib_bihash_48_8_t dpi6_flow_by_key; - - /* vector of dpi flow instances */ - dpi_flow_entry_t *dpi_flows; - u32 flow_id_start; - dpi_flow_info_t *dpi_infos; - segment *seg_pool; - - /* Default hyperscan database */ - dpi_entry_t default_db; - - /* graph node state */ - uword *bm_ip4_bypass_enabled_by_sw_if; - uword *bm_ip6_bypass_enabled_by_sw_if; - - /* API message ID base */ - u16 msg_id_base; - - /* convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; -} dpi_main_t; - -extern dpi_main_t dpi_main; - -#define foreach_copy_field \ -_(src_ip) \ -_(dst_ip) \ -_(src_port) \ -_(dst_port) \ -_(protocol) \ -_(fib_index) - - -#define dpi_enqueue_tcp_segments(seg,vm,node,next_index,to_next,n_left_to_next,bi0,next0) \ -while(seg) \ - { \ - bi0 = seg->bi; \ - to_next[0] = bi0; \ - to_next++; \ - n_left_to_next--; \ - next0 = flow0->next_index; \ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, \ - to_next, n_left_to_next, \ - bi0, next0); \ - prev_seg = seg; \ - seg=seg->next; \ - pool_put(dm->seg_pool, prev_seg); \ - } - - -#define get_u16_t(X,O) (*(u16 *)(((u8 *)X) + O)) -#define DPI_MAX_SSL_REQUEST_SIZE 10000 - -int dpi_flow_add_del (dpi_add_del_flow_args_t * a, u32 * flow_idp); -int dpi_reverse_flow_add_del (dpi_add_del_flow_args_t * a, u32 flow_id); -int dpi_add_del_rx_flow (u32 hw_if_index, u32 flow_id, int is_add, - u32 is_ipv6); -int dpi_tcp_reass (tcp_reass_args_t * a); -void dpi_flow_bypass_mode (u32 sw_if_index, u8 is_ip6, u8 is_enable); -int dpi_search_host_protocol (dpi_flow_info_t * flow, - char *str_to_match, - u32 str_to_match_len, - u16 master_protocol_id, u32 * host_protocol_id); -void dpi_search_tcp_ssl (u8 * payload, u32 payload_len, - dpi_flow_info_t * flow); - -void dpi_detect_application (u8 * payload, u32 payload_len, - dpi_flow_info_t * flow); - -typedef enum -{ - DPI_PROTOCOL_UNKNOWN = 0, - DPI_PROTOCOL_SSL = 1, - DPI_PROTOCOL_SSL_NO_CERT = 2, - DPI_N_PROTOCOL -} dpi_protocol_id_t; - -#define foreach_dpi_input_next \ -_(DROP, "error-drop") \ -_(IP4_LOOKUP, "ip4-lookup") - -typedef enum -{ -#define _(s,n) DPI_INPUT_NEXT_##s, - foreach_dpi_input_next -#undef _ - DPI_INPUT_N_NEXT, -} dpi_input_next_t; - -#endif /* included_vnet_dpi_h */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/dpi_api.c b/src/dpi_api.c deleted file mode 100644 index d8fa690..0000000 --- a/src/dpi_api.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 Intel, Travelping and/or its affiliates. - * 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 <vnet/interface.h> -#include <vnet/api_errno.h> -#include <vnet/feature/feature.h> -#include <vnet/fib/fib_table.h> - -#include <vppinfra/byte_order.h> -#include <vlibmemory/api.h> - -#include "dpi.h" - - -#define vl_msg_id(n,h) n, -typedef enum -{ -#include "dpi.api.h" - /* We'll want to know how many messages IDs we need... */ - VL_MSG_FIRST_AVAILABLE, -} vl_msg_id_t; -#undef vl_msg_id - -/* define message structures */ -#define vl_typedefs -#include "dpi.api.h" -#undef vl_typedefs - -/* define generated endian-swappers */ -#define vl_endianfun -#include "dpi.api.h" -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include "dpi.api.h" -#undef vl_printfun - -/* Get the API version number */ -#define vl_api_version(n,v) static u32 api_version=(v); -#include "dpi.api.h" -#undef vl_api_version - -#define vl_msg_name_crc_list -#include "dpi.api.h" -#undef vl_msg_name_crc_list - -#define REPLY_MSG_ID_BASE dm->msg_id_base -#include <vlibapi/api_helper_macros.h> - -static void -setup_message_id_table (dpi_main_t * dm, api_main_t * am) -{ -#define _(id,n,crc) \ - vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + dm->msg_id_base); - foreach_vl_msg_name_crc_dpi; -#undef _ -} - -#define foreach_dpi_plugin_api_msg \ -_(DPI_FLOW_ADD_DEL, dpi_flow_add_del) - - -/* API message handler */ -static void -vl_api_dpi_flow_add_del_t_handler (vl_api_dpi_flow_add_del_t * mp) -{ - vl_api_dpi_flow_add_del_reply_t *rmp = NULL; - dpi_main_t *dm = &dpi_main; - int rv = 0; - u32 fib_index; - u32 flow_id = ~0; - - fib_index = fib_table_find (fib_ip_proto (mp->is_ipv6), ntohl (mp->vrf_id)); - if (fib_index == ~0) - { - rv = VNET_API_ERROR_NO_SUCH_FIB; - goto out; - } - - dpi_add_del_flow_args_t a = { - .is_add = mp->is_add, - .is_ipv6 = mp->is_ipv6, - .src_ip = to_ip46 (mp->is_ipv6, mp->src_ip), - .dst_ip = to_ip46 (mp->is_ipv6, mp->dst_ip), - .src_port = ntohs (mp->src_port), - .dst_port = ntohs (mp->dst_port), - .protocol = mp->protocol, - .fib_index = fib_index, - }; - - /* Check src ip and dst ip are different */ - if (ip46_address_cmp (&a.dst_ip, &a.src_ip) == 0) - { - rv = VNET_API_ERROR_SAME_SRC_DST; - goto out; - } - - rv = dpi_flow_add_del (&a, &flow_id); - -out: - /* *INDENT-OFF* */ - REPLY_MACRO2(VL_API_DPI_FLOW_ADD_DEL_REPLY, - ({ - rmp->flow_id = htonl (flow_id); - })); - /* *INDENT-ON* */ -} - -static clib_error_t * -dpi_api_hookup (vlib_main_t * vm) -{ - dpi_main_t *dm = &dpi_main; - - u8 *name = format (0, "dpi_%08x%c", api_version, 0); - dm->msg_id_base = vl_msg_api_get_msg_ids - ((char *) name, VL_MSG_FIRST_AVAILABLE); - -#define _(N,n) \ - vl_msg_api_set_handlers((VL_API_##N + dm->msg_id_base), \ - #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_dpi_plugin_api_msg; -#undef _ - - /* Add our API messages to the global name_crc hash table */ - setup_message_id_table (dm, &api_main); - - return 0; -} - -VLIB_API_INIT_FUNCTION (dpi_api_hookup); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/dpi_app_match.h b/src/dpi_app_match.h deleted file mode 100644 index dde4857..0000000 --- a/src/dpi_app_match.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2019 Intel, Travelping and/or its affiliates. - * 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. - *------------------------------------------------------------------ - */ - -/* -#************************************************************* -# Copyright (c) 2003-2017, Emerging Threats -# 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 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 AND FITNESS FOR A PARTICULAR PURPOSE 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 dpi_app_match_h -#define dpi_app_match_h - -typedef enum -{ - DPI_APP_CISCO = 1, - DPI_APP_GOOGLE = 2, - DPI_APP_BING = 3, - DPI_APP_MSN = 4, - DPI_APP_YAHOO = 5, - DPI_APP_YAHOOMAIL = 6, - DPI_APP_INTEL = 7, - DPI_APP_AMAZON = 8, - DPI_APP_AMD = 9, - DPI_APP_BAIDU = 10, - DPI_APP_APPLE = 11, - DPI_APP_FACEBOOK = 12, - DPI_APP_EBAY = 13, - DPI_APP_GITHUB = 14, - DPI_APP_GMAIL = 15, - DPI_APP_QQ = 16, - DPI_APP_WECHAT = 17, - DPI_APP_PINTEREST = 18, - DPI_APP_LENOVO = 19, - DPI_APP_LINKEDIN = 20, - DPI_APP_SKYPE = 21, - DPI_APP_MICROSOFT = 22, - DPI_APP_NETFLIX = 23, - DPI_APP_NOKIA = 24, - DPI_APP_NVIDIA = 25, - DPI_APP_OFFICE = 26, - DPI_APP_ORACLE = 27, - DPI_APP_OUTLOOK = 28, - DPI_APP_PANDORA = 29, - DPI_APP_PAYPAL = 30, - DPI_APP_SINA = 31, - DPI_APP_SOGOU = 32, - DPI_APP_SYMANTEC = 33, - DPI_APP_TAOBAO = 34, - DPI_APP_TWITTER = 35, - DPI_APP_UPS = 36, - DPI_APP_VISA = 37, - DPI_APP_MCAFEE = 38, - DPI_APP_VMWARE = 39, - DPI_APP_WORDPRESS = 40, - DPI_APP_ADOBE = 41, - DPI_APP_AKAMAI = 42, - DPI_APP_ALIENVAULT = 43, - DPI_APP_BITCOMET = 44, - DPI_APP_CHECKPOINT = 45, - DPI_APP_BLOOMBERG = 46, - DPI_APP_DELL = 47, - DPI_APP_F5 = 48, - DPI_APP_FIREEYE = 49, - DPI_APP_DROPBOX = 50, - - /* last app ID */ - DPI_N_APPLICATIONS = 51, -} dpi_application_id_t; - -typedef struct dpi_app_match_rule_ -{ - char *host; - char *pattern; - char *app_name; - u32 app_id; -} dpi_app_match_rule; - -#define DPI_MAX_APP_NUM DPI_N_APPLICATIONS -extern dpi_app_match_rule app_match_rules[]; - - -#endif /* dpi_app_match_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/dpi_cli.c b/src/dpi_cli.c deleted file mode 100644 index 4fbc760..0000000 --- a/src/dpi_cli.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2018 Intel, Travelping and/or its affiliates. - * 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 <stdint.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <inttypes.h> - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> -#include <vnet/ethernet/ethernet.h> -#include <vnet/plugin/plugin.h> -#include <vnet/fib/fib_entry.h> -#include <vnet/fib/fib_table.h> -//#include <vpp/app/version.h> -#include "dpi.h" - - -extern dpi_main_t dpi_main; -extern dpi_entry_t *dpi_dbs; - -static clib_error_t * -dpi_flow_add_del_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd_arg) -{ - unformat_input_t _line_input, *line_input = &_line_input; - ip46_address_t src_ip = ip46_address_initializer; - ip46_address_t dst_ip = ip46_address_initializer; - u16 src_port = 0, dst_port = 0; - u8 is_add = 0; - u8 ipv4_set = 0; - u8 ipv6_set = 0; - u32 tmp; - int rv; - u8 protocol = 0; - u32 table_id; - u32 fib_index = 0; - u32 dpi_flow_id; - - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "add")) - is_add = 1; - else if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "src-ip %U", unformat_ip46_address, - &src_ip, IP46_TYPE_ANY)) - { - ip46_address_is_ip4 (&src_ip) ? (ipv4_set = 1) : (ipv6_set = 1); - } - else if (unformat (line_input, "dst-ip %U", unformat_ip46_address, - &dst_ip, IP46_TYPE_ANY)) - { - ip46_address_is_ip4 (&dst_ip) ? (ipv4_set = 1) : (ipv6_set = 1); - } - else if (unformat (line_input, "src-port %d", &tmp)) - src_port = (u16) tmp; - else if (unformat (line_input, "dst-port %d", &tmp)) - dst_port = (u16) tmp; - else - if (unformat (line_input, "protocol %U", unformat_ip_protocol, &tmp)) - protocol = (u8) tmp; - else if (unformat (line_input, "protocol %u", &tmp)) - protocol = (u8) tmp; - else if (unformat (line_input, "vrf-id %d", &table_id)) - { - fib_index = fib_table_find (fib_ip_proto (ipv6_set), table_id); - } - else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - } - - unformat_free (line_input); - - if (ipv4_set && ipv6_set) - return clib_error_return (0, "both IPv4 and IPv6 addresses specified"); - - dpi_add_del_flow_args_t a = {.is_add = is_add, - .is_ipv6 = ipv6_set, -#define _(x) .x = x, - foreach_copy_field -#undef _ - }; - - /* Add normal flow */ - rv = dpi_flow_add_del (&a, &dpi_flow_id); - if (rv < 0) - return clib_error_return (0, "flow error: %d", rv); - - /* Add reverse flow */ - rv = dpi_reverse_flow_add_del (&a, dpi_flow_id); - if (rv < 0) - return clib_error_return (0, "reverse flow error: %d", rv); - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dpi_flow_add_del_command, static) = { - .path = "dpi flow", - .short_help = "dpi flow [add | del] " - "[src-ip <ip-addr>] [dst-ip <ip-addr>] " - "[src-port <port>] [dst-port <port>] " - "[protocol <protocol>] [vrf-id <nn>]", - .function = dpi_flow_add_del_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dpi_tcp_reass_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd_arg) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u32 flow_id = ~0; - u8 reass_en = 0; - u8 reass_dir = 0; - int rv; - - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "flow_id %d", &flow_id)) - ; - else if (unformat (line_input, "enable")) - { - reass_en = 1; - } - else if (unformat (line_input, "disable")) - { - reass_en = 0; - } - else if (unformat (line_input, "client")) - { - reass_dir = REASS_C2S; - } - else if (unformat (line_input, "server")) - { - reass_dir = REASS_S2C; - } - else if (unformat (line_input, "both")) - { - reass_dir = REASS_BOTH; - } - else - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - } - - unformat_free (line_input); - - tcp_reass_args_t a = {.flow_id = flow_id, - .reass_en = reass_en, - .reass_dir = reass_dir, - }; - - rv = dpi_tcp_reass (&a); - if (rv < 0) - return clib_error_return (0, "flow error: %d", rv); - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dpi_tcp_reass_command, static) = { - .path = "dpi tcp reass", - .short_help = "dpi tcp reass flow_id <nn> <enable|disable> " - "[ <client | server | both> ]", - .function = dpi_tcp_reass_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dpi_flow_offload_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - dpi_main_t *dm = &dpi_main; - vnet_main_t *vnm = dm->vnet_main; - u32 rx_flow_id = ~0; - u32 hw_if_index = ~0; - int is_add = 1; - u32 is_ipv6 = 0; - dpi_flow_entry_t *flow; - vnet_hw_interface_t *hw_if; - u32 rx_fib_index = ~0; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "hw %U", unformat_vnet_hw_interface, vnm, - &hw_if_index)) - continue; - if (unformat (line_input, "rx %d", &rx_flow_id)) - continue; - if (unformat (line_input, "del")) - { - is_add = 0; - continue; - } - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, line_input); - } - - if (rx_flow_id == ~0) - return clib_error_return (0, "missing rx flow"); - if (hw_if_index == ~0) - return clib_error_return (0, "missing hw interface"); - - flow = pool_elt_at_index (dm->dpi_flows, rx_flow_id); - - hw_if = vnet_get_hw_interface (vnm, hw_if_index); - - is_ipv6 = ip46_address_is_ip4 (&(flow->key.src_ip)) ? 0 : 1; - - if (is_ipv6) - { - ip6_main_t *im6 = &ip6_main; - rx_fib_index = - vec_elt (im6->fib_index_by_sw_if_index, hw_if->sw_if_index); - } - else - { - ip4_main_t *im4 = &ip4_main; - rx_fib_index = - vec_elt (im4->fib_index_by_sw_if_index, hw_if->sw_if_index); - } - - if (flow->key.fib_index != rx_fib_index) - return clib_error_return (0, "interface/flow fib mismatch"); - - if (dpi_add_del_rx_flow (hw_if_index, rx_flow_id, is_add, is_ipv6)) - return clib_error_return (0, "error %s flow", - is_add ? "enabling" : "disabling"); - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dpi_flow_offload_command, static) = { - .path = "dpi set flow-offload", - .short_help = - "dpi set flow-offload hw <interface-name> rx <flow-id> [del]", - .function = dpi_flow_offload_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dpi_set_flow_bypass (u32 is_ip6, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - vnet_main_t *vnm = vnet_get_main (); - clib_error_t *error = 0; - u32 sw_if_index, is_enable; - - sw_if_index = ~0; - is_enable = 1; - - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat_user (line_input, unformat_vnet_sw_interface, vnm, - &sw_if_index)) - ; - else if (unformat (line_input, "del")) - is_enable = 0; - else - { - error = unformat_parse_error (line_input); - goto done; - } - } - - if (~0 == sw_if_index) - { - error = clib_error_return (0, "unknown interface `%U'", - format_unformat_error, line_input); - goto done; - } - - dpi_flow_bypass_mode (sw_if_index, is_ip6, is_enable); - -done: - unformat_free (line_input); - - return error; -} - -static clib_error_t * -dpi_set_ip4_flow_bypass_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - return dpi_set_flow_bypass (0, input, cmd); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dpi_set_ip4_flow_bypass_command, static) = -{ - .path = "dpi set ip4 flow-bypass", - .short_help = "dpi set ip4 flow-bypass <interface> [del]", - .function = dpi_set_ip4_flow_bypass_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -dpi_set_ip6_flow_bypass_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - return dpi_set_flow_bypass (0, input, cmd); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dpi_set_ip6_flow_bypass_command, static) = -{ - .path = "dpi set ip6 flow-bypass", - .short_help = "dpi set ip6 flow-bypass <interface> [del]", - .function = dpi_set_ip6_flow_bypass_command_fn, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/dpi_node.c b/src/dpi_node.c deleted file mode 100644 index 6b5f9c1..0000000 --- a/src/dpi_node.c +++ /dev/null @@ -1,1035 +0,0 @@ -/* - * Copyright (c) 2019 Intel and/or its affiliates. - * 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 <vlib/vlib.h> -#include <vnet/pg/pg.h> -#include <vnet/vnet.h> -#include <vnet/ip/ip.h> -#include <vppinfra/bihash_48_8.h> -#include <vppinfra/dlist.h> -#include <vppinfra/pool.h> -#include <vppinfra/vec.h> -#include <vnet/plugin/plugin.h> -//#include <vpp/app/version.h> -#include <vnet/flow/flow.h> -#include <vnet/tcp/tcp_packet.h> - -#include "dpi.h" - -vlib_node_registration_t dpi4_input_node; -vlib_node_registration_t dpi6_input_node; -vlib_node_registration_t dpi4_flow_input_node; -vlib_node_registration_t dpi6_flow_input_node; - - -#define foreach_dpi_input_error \ - _(NONE, "no error") \ - _(NO_SUCH_FLOW, "flow not existed") - -typedef enum -{ -#define _(sym,str) DPI_INPUT_ERROR_##sym, - foreach_dpi_input_error -#undef _ - DPI_INPUT_N_ERROR, -} dpi_input_error_t; - -static char *dpi_input_error_strings[] = { -#define _(sym,string) string, - foreach_dpi_input_error -#undef _ -}; - -typedef struct -{ - u32 next_index; - u32 flow_id; - u32 app_id; - u32 error; -} dpi_rx_trace_t; - -/* *INDENT-OFF* */ -VNET_FEATURE_INIT (dpi4_input, static) = -{ - .arc_name = "ip4-unicast", - .node_name = "dpi4-input", - .runs_before = VNET_FEATURES ("ip4-lookup"), -}; - -VNET_FEATURE_INIT (dpi6_input, static) = -{ - .arc_name = "ip6-unicast", - .node_name = "dpi6-input", - .runs_before = VNET_FEATURES ("ip6-lookup"), -}; -/* *INDENT-on* */ - -static u8 * -format_dpi_rx_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - dpi_rx_trace_t *t = va_arg (*args, dpi_rx_trace_t *); - - if (t->flow_id == ~0) - return format (s, "DPI error - flow %d does not exist", - t->flow_id); - - return format (s, "DPI from flow %d app_id %d next %d error %d", - t->flow_id, t->app_id, t->next_index, t->error); -} - - - -static inline int -parse_ip4_packet_and_lookup (ip4_header_t * ip4, u32 fib_index, - dpi4_flow_key_t * key4, - int * not_found, u64 * flow_id) -{ - dpi_main_t *dm = &dpi_main; - u8 protocol = ip4_is_fragment (ip4) ? 0xfe : ip4->protocol; - u16 src_port = 0; - u16 dst_port = 0; - dpi_flow_entry_t *flow; - - key4->key[0] = ip4->src_address.as_u32 - | (((u64) ip4->dst_address.as_u32) << 32); - - if (protocol == IP_PROTOCOL_UDP || protocol == IP_PROTOCOL_TCP) - { - /* tcp and udp ports have the same offset */ - udp_header_t * udp = ip4_next_header (ip4); - src_port = udp->src_port; - dst_port = udp->dst_port; - } - - key4->key[1] = (((u64) protocol) << 32) | ((u32) src_port << 16) | dst_port; - key4->key[2] = (u64) fib_index; - - key4->value = ~0; - *not_found = clib_bihash_search_inline_24_8 (&dm->dpi4_flow_by_key, key4); - *flow_id = key4->value; - - /* not found, then create new SW flow dynamically */ - if (*not_found) - { - int add_failed; - pool_get_aligned(dm->dpi_flows, flow, CLIB_CACHE_LINE_BYTES); - clib_memset(flow, 0, sizeof(*flow)); - *flow_id = flow - dm->dpi_flows; - - flow->next_index = DPI_INPUT_NEXT_IP4_LOOKUP; - flow->flow_index = ~0; - - pool_get_aligned(dm->dpi_infos, flow->info, CLIB_CACHE_LINE_BYTES); - clib_memset(flow->info, 0, sizeof(*flow->info)); - flow->info->app_id = ~0; - - /* Add forwarding flow entry */ - key4->value = *flow_id; - add_failed = clib_bihash_add_del_24_8 (&dm->dpi4_flow_by_key, key4, - 1 /*add */); - - if (add_failed) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - - /* Add reverse flow entry*/ - key4->key[0] = ip4->dst_address.as_u32 - | (((u64) ip4->src_address.as_u32) << 32); - key4->key[1] = (((u64) protocol) << 32) | ((u32) dst_port << 16) - | src_port; - key4->key[2] = (u64) fib_index; - key4->value = (u64) flow_id | ((u64) 1 << 63); - add_failed = clib_bihash_add_del_24_8 (&dm->dpi4_flow_by_key, key4, - 1 /*add */); - - if (add_failed) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - - /* Open a Hyperscan stream for each flow */ - hs_error_t err = hs_open_stream (dm->default_db.database, 0, - &(flow->info->stream)); - - if (err != HS_SUCCESS) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - } - - return 0; -} - -static inline int -parse_ip6_packet_and_lookup (ip6_header_t * ip6, u32 fib_index, - dpi6_flow_key_t * key6, - int * not_found, u64 * flow_id) -{ - dpi_main_t *dm = &dpi_main; - u8 protocol = ip6->protocol; - u16 src_port = 0; - u16 dst_port = 0; - dpi_flow_entry_t *flow; - - key6->key[0] = ip6->src_address.as_u64[0]; - key6->key[1] = ip6->src_address.as_u64[1]; - key6->key[2] = ip6->dst_address.as_u64[0]; - key6->key[3] = ip6->dst_address.as_u64[1]; - - if (protocol == IP_PROTOCOL_UDP || protocol == IP_PROTOCOL_TCP) - { - /* tcp and udp ports have the same offset */ - udp_header_t * udp = ip6_next_header(ip6); - src_port = udp->src_port; - dst_port = udp->dst_port; - } - - key6->key[4] = (((u64) protocol) << 32) - | ((u32) src_port << 16) - | dst_port; - key6->key[5] = (u64) fib_index; - - key6->value = ~0; - *not_found = clib_bihash_search_inline_48_8 (&dm->dpi6_flow_by_key, key6); - *flow_id = key6->value; - - /* not found, then create new SW flow dynamically */ - if (*not_found) - { - int add_failed; - pool_get_aligned(dm->dpi_flows, flow, CLIB_CACHE_LINE_BYTES); - clib_memset(flow, 0, sizeof(*flow)); - *flow_id = flow - dm->dpi_flows; - - flow->next_index = DPI_INPUT_NEXT_IP4_LOOKUP; - flow->flow_index = ~0; - - pool_get_aligned(dm->dpi_infos, flow->info, CLIB_CACHE_LINE_BYTES); - clib_memset(flow->info, 0, sizeof(*flow->info)); - flow->info->app_id = ~0; - - /* Add forwarding flow entry */ - key6->value = (u64) flow_id; - add_failed = clib_bihash_add_del_48_8 (&dm->dpi6_flow_by_key, - key6, 1 /*add */ ); - if (add_failed) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - - /* Add reverse flow entry*/ - key6->key[0] = ip6->dst_address.as_u64[0]; - key6->key[1] = ip6->dst_address.as_u64[1]; - key6->key[2] = ip6->src_address.as_u64[0]; - key6->key[3] = ip6->src_address.as_u64[1]; - key6->key[4] = (((u64) protocol) << 32) - | ((u32) dst_port << 16) - | src_port; - key6->key[5] = (u64) fib_index; - key6->value = (u64) flow_id | ((u64) 1 << 63); - add_failed = clib_bihash_add_del_48_8 (&dm->dpi6_flow_by_key, - key6, 1 /*add */ ); - - if (add_failed) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - - /* Open a Hyperscan stream for each flow */ - hs_error_t err = hs_open_stream (dm->default_db.database, 0, - &(flow->info->stream)); - - if (err != HS_SUCCESS) - { - pool_put(dm->dpi_infos, flow->info); - pool_put(dm->dpi_flows, flow); - return -1; - } - } - - return 0; -} - -static inline void -dpi_trim_overlap(u32 left_sn, segment *seg) -{ - int overlap_len; - - overlap_len = left_sn - seg->send_sn; - /* trim leading overlap bytes */ - seg->data += overlap_len; - seg->len -= overlap_len; - seg->send_sn += overlap_len; - - /* trim the right overlap bytes */ - if( seg->next - && (seg->send_sn+seg->len) > (seg->next->send_sn) ) - { - overlap_len = (seg->send_sn+seg->len) - (seg->next->send_sn); - if(seg->len > overlap_len) - { - seg->len -= overlap_len; - } - } -} - -/* - * re-order out-of-order segments, and handle overlap segments. - * */ -static inline void -dpi_handle_tcp_segments (dpi_flow_entry_t *flow, tcp_stream_t *stream, - u32 bi, u8 *pkt, u32 payload_len) -{ - dpi_main_t *dm = &dpi_main; - u32 send_sn; - u32 ack_sn; - u32 next_sn; - u32 left_sn; - segment *first_seg = 0; - segment *seg = 0; - segment *new_seg = 0; - tcp_header_t *tcp = (tcp_header_t *)pkt; - u8 *payload = pkt + tcp_doff(tcp) * 4; - - if((tcp->flags & TCP_FLAG_ACK) == TCP_FLAG_ACK) - { - ack_sn = clib_net_to_host_u32(tcp->ack_number); - if(ack_sn != stream->ack_sn) - { - stream->ack_sn = ack_sn; - } - } - - send_sn = clib_net_to_host_u32(tcp->seq_number); - next_sn = send_sn + payload_len; - - /* Handle fully overlapping segments */ - if(SN_GT(stream->send_sn, next_sn)) - { - flow->consumed = 1; - return; - } - - if(SN_LT(stream->send_sn, send_sn)) - { - /* Store out-of-order segments to segment queue */ - for(seg=stream->seg_queue; seg; seg=seg->next) - { - if (send_sn < seg->send_sn ) - break; - } - - pool_get_aligned (dm->seg_pool, new_seg, CLIB_CACHE_LINE_BYTES); - new_seg->bi = bi; - new_seg->send_sn = send_sn; - new_seg->data = payload; - new_seg->len = payload_len; - - /* Insert new segment to right position of segment queue */ - if(seg == stream->seg_queue) - { - new_seg->next = stream->seg_queue; - stream->seg_queue = new_seg; - stream->send_sn = seg->send_sn; - left_sn = stream->send_sn; - } - else - { - new_seg->next = seg->next; - seg->next = new_seg; - left_sn = seg->send_sn; - } - - /* trim overlapped packet */ - dpi_trim_overlap(left_sn, new_seg); - - flow->consumed = 1; - } - else - { - pool_get_aligned(dm->seg_pool, first_seg, CLIB_CACHE_LINE_BYTES); - first_seg->bi = bi; - first_seg->send_sn = send_sn; - first_seg->data = payload; - first_seg->len = payload_len; - first_seg->next = stream->seg_queue; - - /* trim overlapped packet */ - dpi_trim_overlap (stream->send_sn, first_seg); - - /* reassemble continuous segments and move forward to scan */ - for (seg = first_seg; seg->next; seg = seg->next) - { - if (seg->send_sn + seg->len != seg->next->send_sn) - break; - } - - /* left non-continuous segments */ - stream->seg_queue = seg->next; - stream->send_sn = seg->send_sn + seg->len; - - flow->first_seg = first_seg; - seg->next = 0; - - /* scan ordered segments */ - for (seg = first_seg; seg; seg = seg->next) - { - /* detect layer 7 application for single segment */ - dpi_detect_application (seg->data, seg->len, flow->info); - if(flow->info->detect_done) - break; - } - } -} - -static inline int -dpi_handle_tcp_stream (dpi_flow_entry_t *flow, u32 bi, - u8 *pkt, u32 payload_len, u8 is_reverse) -{ - tcp_header_t *tcp; - tcp_stream_t *stream; - - tcp = (tcp_header_t *)pkt; - if((tcp->flags & (TCP_FLAG_SYN|TCP_FLAG_ACK)) == TCP_FLAG_SYN) - { - flow->c2s.send_sn = clib_net_to_host_u32(tcp->seq_number) + 1; - flow->pkt_dir = DIR_C2S; - flow->forward_is_c2s = !is_reverse; - flow->tcp_state = TCP_STATE_SYN; - } - else - { - /* - forward_is_c2s | is_reverse - 0 1 - 0 s2c(1) c2s(0) - 1 c2s(0) s2c(1) - */ - flow->pkt_dir = (flow->forward_is_c2s == is_reverse); - } - - switch(flow->tcp_state) - { - case TCP_STATE_SYN: - { - if(flow->pkt_dir != DIR_S2C) - break; - - if((tcp->flags & (TCP_FLAG_SYN|TCP_FLAG_ACK)) - != (TCP_FLAG_SYN|TCP_FLAG_ACK)) - break; - - flow->s2c.send_sn = clib_net_to_host_u32(tcp->seq_number) + 1; - flow->s2c.ack_sn = clib_net_to_host_u32(tcp->ack_number) + 1; - flow->tcp_state = TCP_STATE_SYN_ACK; - break; - } - - case TCP_STATE_SYN_ACK: - { - if(flow->pkt_dir != DIR_C2S) - break; - - flow->c2s.ack_sn = clib_net_to_host_u32(tcp->ack_number) + 1; - flow->tcp_state = TCP_STATE_ESTABLISH; - break; - } - - case TCP_STATE_ACK: - case TCP_STATE_ESTABLISH: - case TCP_STATE_FIN1: - { - stream = (flow->pkt_dir == DIR_C2S)? &(flow->c2s) : &(flow->s2c); - if( (flow->reass_dir == REASS_BOTH) - || ((flow->pkt_dir==DIR_C2S) && (flow->reass_dir==REASS_C2S)) - || ((flow->pkt_dir==DIR_S2C) && (flow->reass_dir==REASS_S2C)) ) - { - dpi_handle_tcp_segments(flow, stream, bi, pkt, payload_len); - } - - break; - } - - case TCP_STATE_CLOSE: - { - /* Free all segments in the queue */ - break; - } - } - - return 0; -} - -void -dpi_detect_application (u8 *payload, u32 payload_len, - dpi_flow_info_t *flow) -{ - - /* detect if payload is SSL's payload for default port */ - dpi_search_tcp_ssl(payload, payload_len, flow); - - /* TBD: add detect if is SSL's payload with non default port*/ - -} - -always_inline uword -dpi_input_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, u32 is_ip4) -{ - dpi_main_t *dm = &dpi_main; - u32 *from, *to_next, n_left_from, n_left_to_next, next_index; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0, next0 = 0; - vlib_buffer_t *b0; - ip4_header_t *ip40; - ip6_header_t *ip60; - tcp_header_t *tcp0; - udp_header_t *udp0; - dpi4_flow_key_t key40; - dpi6_flow_key_t key60; - u32 fib_index0 = ~0; - u64 flow_id0 = ~0; - u32 flow_index0 = ~0; - int not_found0 = 0; - u8 is_reverse0 = 0; - dpi_flow_entry_t *flow0 = 0; - u32 ip_len0, l4_len0, payload_len0; - u8 protocol0; - u8 *l4_pkt0, *payload0; - u16 dst_port = 0; - segment *seg = 0; - segment *prev_seg = 0; - - bi0 = to_next[0] = from[0]; - b0 = vlib_get_buffer (vm, bi0); - ip_len0 = vlib_buffer_length_in_chain (vm, b0); - - if (is_ip4) - { - ip40 = vlib_buffer_get_current (b0); - ip4_main_t *im4 = &ip4_main; - fib_index0 = vec_elt (im4->fib_index_by_sw_if_index, - vnet_buffer(b0)->sw_if_index[VLIB_RX]); - parse_ip4_packet_and_lookup(ip40, fib_index0, &key40, - ¬_found0, &flow_id0); - } - else - { - ip60 = vlib_buffer_get_current (b0); - ip6_main_t *im6 = &ip6_main; - fib_index0 = vec_elt (im6->fib_index_by_sw_if_index, - vnet_buffer(b0)->sw_if_index[VLIB_RX]); - parse_ip6_packet_and_lookup(ip60, fib_index0, &key60, - ¬_found0, &flow_id0); - } - - is_reverse0 = (u8)((flow_id0 >> 63) & 0x1); - flow_index0 = (u32)(flow_id0 & (u32)(~0)); - flow0 = pool_elt_at_index (dm->dpi_flows, flow_index0); - /* have detected successfully, directly return */ - if(flow0->info->detect_done) - goto enqueue0; - - /* check layer4 */ - if (is_ip4) - { - l4_pkt0 = (u8 *)(ip40 + 1); - l4_len0 = ip_len0 - sizeof(ip4_header_t); - protocol0 = ip40->protocol; - } - else - { - l4_pkt0 = (u8 *)(ip60 + 1); - l4_len0 = ip_len0 - sizeof(ip6_header_t); - protocol0 = ip60->protocol; - } - - if((protocol0 == IP_PROTOCOL_TCP) && (l4_len0 >= 20)) - { - tcp0 = (tcp_header_t *)l4_pkt0; - payload_len0 = l4_len0 - tcp_doff(tcp0) * 4; - payload0 = l4_pkt0 + tcp_doff(tcp0) * 4; - dst_port = tcp0->dst_port; - } - else if ((protocol0 == IP_PROTOCOL_UDP) && (l4_len0 >= 8)) - { - udp0 = (udp_header_t *)l4_pkt0; - payload_len0 = l4_len0 - sizeof(udp_header_t); - payload0 = l4_pkt0 + sizeof(udp_header_t); - dst_port = udp0->dst_port; - } - else - { - payload_len0 = l4_len0; - payload0 = l4_pkt0; - } - - flow0->info->l4_protocol = protocol0; - flow0->info->dst_port = dst_port; - - /* TCP stream reassembly and detect a protocol pdu */ - if((protocol0 == IP_PROTOCOL_TCP) && (flow0->reass_en)) - { - dpi_handle_tcp_stream(flow0, bi0, l4_pkt0, payload_len0, is_reverse0); - - /* This packet has been consumed, retrieve next packet */ - if(flow0->consumed) - goto trace0; - - /* send out continuous scanned segments */ - seg=flow0->first_seg; - dpi_enqueue_tcp_segments(seg,vm,node,next_index,to_next,n_left_to_next,bi0,next0); - flow0->first_seg = 0; - - /* Here detected successfully, send out remaining segments in seg_queue */ - if(flow0->info->detect_done) - { - seg=flow0->c2s.seg_queue; - dpi_enqueue_tcp_segments(seg,vm,node,next_index,to_next,n_left_to_next,bi0,next0); - flow0->c2s.seg_queue = 0; - - seg=flow0->s2c.seg_queue; - dpi_enqueue_tcp_segments(seg,vm,node,next_index,to_next,n_left_to_next,bi0,next0); - flow0->s2c.seg_queue = 0; - } - goto trace0; - } - else - { - /* detect layer 7 application for single packet */ - dpi_detect_application (payload0, payload_len0, flow0->info); - } - -enqueue0: - to_next[0] = bi0; - to_next++; - n_left_to_next--; - next0 = flow0->next_index; - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - -trace0: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dpi_rx_trace_t *tr - = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->app_id = flow0->info->app_id; - tr->next_index = next0; - tr->error = b0->error; - tr->flow_id = flow_index0; - } - - from += 1; - n_left_from -= 1; - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -VLIB_NODE_FN (dpi4_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dpi_input_inline (vm, node, frame, /* is_ip4 */ 1); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dpi4_input_node) = -{ - .name = "dpi4-input", - .vector_size = sizeof (u32), - .n_errors = DPI_INPUT_N_ERROR, - .error_strings = dpi_input_error_strings, - .n_next_nodes = DPI_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [DPI_INPUT_NEXT_##s] = n, - foreach_dpi_input_next -#undef _ - }, - .format_trace = format_dpi_rx_trace, -}; - -/* *INDENT-ON* */ - -/* Dummy init function to get us linked in. */ -static clib_error_t * -dpi4_input_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (dpi4_input_init); - - -VLIB_NODE_FN (dpi6_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dpi_input_inline (vm, node, frame, /* is_ip4 */ 0); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dpi6_input_node) = -{ - .name = "dpi6-input", - .vector_size = sizeof (u32), - .n_errors = DPI_INPUT_N_ERROR, - .error_strings = dpi_input_error_strings, - .n_next_nodes = DPI_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [DPI_INPUT_NEXT_##s] = n, - foreach_dpi_input_next -#undef _ - }, - .format_trace = format_dpi_rx_trace, -}; -/* *INDENT-ON* */ - -/* Dummy init function to get us linked in. */ -static clib_error_t * -dpi6_input_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (dpi6_input_init); - - - -#define foreach_dpi_flow_input_next \ -_(DROP, "error-drop") \ -_(IP4_LOOKUP, "ip4-lookup") - -typedef enum -{ -#define _(s,n) DPI_FLOW_NEXT_##s, - foreach_dpi_flow_input_next -#undef _ - DPI_FLOW_N_NEXT, -} dpi_flow_input_next_t; - -#define foreach_dpi_flow_error \ - _(NONE, "no error") \ - _(IP_CHECKSUM_ERROR, "Rx ip checksum errors") \ - _(IP_HEADER_ERROR, "Rx ip header errors") \ - _(UDP_CHECKSUM_ERROR, "Rx udp checksum errors") \ - _(UDP_LENGTH_ERROR, "Rx udp length errors") - -typedef enum -{ -#define _(f,s) DPI_FLOW_ERROR_##f, - foreach_dpi_flow_error -#undef _ - DPI_FLOW_N_ERROR, -} dpi_flow_error_t; - -static char *dpi_flow_error_strings[] = { -#define _(n,s) s, - foreach_dpi_flow_error -#undef _ -}; - -static_always_inline u8 -dpi_check_ip4 (ip4_header_t * ip4, u16 payload_len) -{ - u16 ip_len = clib_net_to_host_u16 (ip4->length); - return ip_len > payload_len || ip4->ttl == 0 - || ip4->ip_version_and_header_length != 0x45; -} - -static_always_inline u8 -dpi_check_ip6 (ip6_header_t * ip6, u16 payload_len) -{ - u16 ip_len = clib_net_to_host_u16 (ip6->payload_length); - return ip_len > (payload_len - sizeof (ip6_header_t)) - || ip6->hop_limit == 0 - || (ip6->ip_version_traffic_class_and_flow_label >> 28) != 0x6; -} - -always_inline uword -dpi_flow_input_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, u32 is_ip4) -{ - dpi_main_t *dm = &dpi_main; - u32 *from, *to_next, n_left_from, n_left_to_next, next_index; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0, next0 = DPI_FLOW_NEXT_IP4_LOOKUP; - vlib_buffer_t *b0; - ip4_header_t *ip40; - ip6_header_t *ip60; - tcp_header_t *tcp0; - udp_header_t *udp0; - u32 flow_id0 = ~0; - u32 flow_index0 = ~0; - u32 is_reverse0 = 0; - dpi_flow_entry_t *flow0; - u32 ip_len0, l4_len0, payload_len0; - u8 protocol0; - u8 *l4_pkt0, *payload0; - u16 dst_port = 0; - segment *seg = 0; - segment *prev_seg = 0; - - bi0 = to_next[0] = from[0]; - b0 = vlib_get_buffer (vm, bi0); - ip_len0 = vlib_buffer_length_in_chain (vm, b0); - - if (is_ip4) - { - ip40 = vlib_buffer_get_current (b0); - dpi_check_ip4 (ip40, ip_len0); - } - else - { - ip60 = vlib_buffer_get_current (b0); - dpi_check_ip6 (ip60, ip_len0); - } - - ASSERT (b0->flow_id != 0); - flow_id0 = b0->flow_id - dm->flow_id_start; - - is_reverse0 = (u32) ((flow_id0 >> 31) & 0x1); - flow_index0 = (u32) (flow_id0 & (u32) (~(1 << 31))); - flow0 = pool_elt_at_index (dm->dpi_flows, flow_index0); - - /* have detected successfully, directly return */ - if (flow0->info->detect_done) - goto enqueue0; - - /* check layer4 */ - if (is_ip4) - { - l4_pkt0 = (u8 *) (ip40 + 1); - l4_len0 = ip_len0 - sizeof (ip4_header_t); - protocol0 = ip40->protocol; - } - else - { - l4_pkt0 = (u8 *) (ip60 + 1); - l4_len0 = ip_len0 - sizeof (ip6_header_t); - protocol0 = ip60->protocol; - } - - if ((protocol0 == IP_PROTOCOL_TCP) && (l4_len0 >= 20)) - { - tcp0 = (tcp_header_t *) l4_pkt0; - payload_len0 = l4_len0 - tcp_doff (tcp0) * 4; - payload0 = l4_pkt0 + tcp_doff (tcp0) * 4; - dst_port = tcp0->dst_port; - } - else if ((protocol0 == IP_PROTOCOL_UDP) && (l4_len0 >= 8)) - { - udp0 = (udp_header_t *) l4_pkt0; - payload_len0 = l4_len0 - sizeof (udp_header_t); - payload0 = l4_pkt0 + sizeof (udp_header_t); - dst_port = udp0->dst_port; - } - else - { - payload_len0 = l4_len0; - payload0 = l4_pkt0; - } - - flow0->info->l4_protocol = protocol0; - flow0->info->dst_port = dst_port; - - /* TCP stream reassembly and detect a protocol pdu */ - if ((protocol0 == IP_PROTOCOL_TCP) && (flow0->reass_en)) - { - dpi_handle_tcp_stream (flow0, bi0, l4_pkt0, payload_len0, - is_reverse0); - - /* This packet has been consumed, retrieve next packet */ - if (flow0->consumed) - goto trace0; - - /* send out continuous scanned segments */ - seg = flow0->first_seg; - dpi_enqueue_tcp_segments (seg, vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - flow0->first_seg = 0; - - /* Here detected successfully, send out remaining segments in seg_queue */ - if (flow0->info->detect_done) - { - seg = flow0->c2s.seg_queue; - dpi_enqueue_tcp_segments (seg, vm, node, next_index, - to_next, n_left_to_next, bi0, - next0); - flow0->c2s.seg_queue = 0; - - seg = flow0->s2c.seg_queue; - dpi_enqueue_tcp_segments (seg, vm, node, next_index, - to_next, n_left_to_next, bi0, - next0); - flow0->s2c.seg_queue = 0; - } - goto trace0; - } - else - { - /* detect layer 7 application for single packet */ - dpi_detect_application (payload0, payload_len0, flow0->info); - } - -enqueue0: - to_next[0] = bi0; - to_next++; - n_left_to_next--; - next0 = flow0->next_index; - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - -trace0: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - dpi_rx_trace_t *tr - = vlib_add_trace (vm, node, b0, sizeof (*tr)); - tr->app_id = flow0->info->app_id; - tr->next_index = next0; - tr->error = b0->error; - tr->flow_id = flow_index0; - } - - from += 1; - n_left_from -= 1; - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - - -VLIB_NODE_FN (dpi4_flow_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dpi_flow_input_inline (vm, node, frame, /* is_ip4 */ 1); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dpi4_flow_input_node) = { - .name = "dpi4-flow-input", - .type = VLIB_NODE_TYPE_INTERNAL, - .vector_size = sizeof (u32), - - .format_trace = format_dpi_rx_trace, - - .n_errors = DPI_FLOW_N_ERROR, - .error_strings = dpi_flow_error_strings, - - .n_next_nodes = DPI_FLOW_N_NEXT, - .next_nodes = { -#define _(s,n) [DPI_FLOW_NEXT_##s] = n, - foreach_dpi_flow_input_next -#undef _ - }, -}; -/* *INDENT-ON* */ - -/* Dummy init function to get us linked in. */ -static clib_error_t * -dpi4_flow_input_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (dpi4_flow_input_init); - -VLIB_NODE_FN (dpi6_flow_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dpi_flow_input_inline (vm, node, frame, /* is_ip4 */ 0); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (dpi6_flow_input_node) = { - .name = "dpi6-flow-input", - .type = VLIB_NODE_TYPE_INTERNAL, - .vector_size = sizeof (u32), - - .format_trace = format_dpi_rx_trace, - - .n_errors = DPI_FLOW_N_ERROR, - .error_strings = dpi_flow_error_strings, - - .n_next_nodes = DPI_FLOW_N_NEXT, - .next_nodes = { -#define _(s,n) [DPI_FLOW_NEXT_##s] = n, - foreach_dpi_flow_input_next -#undef _ - }, -}; -/* *INDENT-ON* */ - -/* Dummy init function to get us linked in. */ -static clib_error_t * -dpi6_flow_input_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (dpi6_flow_input_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/dpi_plugin_doc.md b/src/dpi_plugin_doc.md deleted file mode 100644 index fc069c0..0000000 --- a/src/dpi_plugin_doc.md +++ /dev/null @@ -1,107 +0,0 @@ -# DPI plugin for VPP {#dpi_plugin_doc} - -## Overview - -DPI plugin can identify and analyze the traffic running on networks in real time. -It can be used on many use cases, such as Web Application Firewall, -Policy based routing, Intrusion Detection System, Intrusion Prevention System, etc. - -The main use case for current approach would be identification of cooperating traffic -for an established TCP connection (i.e. traffic that is not intentionally disguised) -to support application-based QoS. - - -## Design - -The DPI plugin leverage Hyperscan to perform regex matching. - -Hyperscan is a high-performance multiple regex matching library. -Please refer to below for details: -http://intel.github.io/dpi/dev-reference/ - -Below is the brief design: - -1. Provides a default APPID database for detection. - -2. Support TCP connection state tracking. - -3. Support TCP segments reassembly on the fly, which handles out-of-order tcp segments and overlapping segments. - It means that we do not need to reassembly segments first, then dedect applicaion, - and then fragment segments again, which helps to improve performance. - -4. Support Hyperscan Stream mode, which can detect one rule straddling into some tcp segments. - It means that if there is a rule "abcde", then "abc" can be in packet 1, - and "de" can be in packet 2. - -5. Configure static dpi flows with 5-tuple and VRF-aware, and supports both ipv4 and ipv6 flows. - These flows will first try to HW offload to NIC based on DPDK rte_flow mechanism - and vpp/vnet/flow infrastructure. - If failed, then will create static SW flow mappings. - Each flow configuration will create two HW or SW flow mappings, i.e. for forward and reverse traffic. - And both flow mappings will be mapped to the same dpi flow. - Dynamically create new SW mapping and aging out mechanism will be added later. - - "dpi flow [add | del] " - "[src-ip <ip-addr>] [dst-ip <ip-addr>] " - "[src-port <port>] [dst-port <port>] " - "[protocol <protocol>] [vrf-id <nn>]", - - "dpi tcp reass flow_id <nn> <enable|disable> " - "[ <client | server | both> ]", - - "dpi set flow-offload hw <interface-name> rx <flow-id> [del]", - - "dpi set ip4 flow-bypass <interface> [del]", - -6. When HW flow offload matched, packets will be redirected to DPI plugin with dpi flow_id in packet descriptor. - If not, packets will be bypassed to DPI plugin from ip-input, and then lookup SW flow mapping table. - -7. Then will detect layer 7 applications. - This first patch only detect sub protocls within SSL/TLS. - 1). Identify SSL/TLS certificate message and subsequent segments. - 2). Scan SSL/TLS certificate message through hyperscan, and get application id if matched. - 3). If maximum packets for this flow are checked and not found matched application, the detection will end up. - - -## Hyperscan Installation - -Hyperscan can be installed from packages directly on below OS: - Ubuntu 16.04.03 - Ubuntu 18.04 and later version - Fedora 27 and later version - openSUSE rolling-release Tumbleweed and later version - -If you cannot install Hyperscan from packages directly, -you can build and install it from the source code. - -Below are steps to build and install Hyperscan on Ubuntu 16.04: -1).Install binary prerequisites -apt-get install cmake ragel -apt-get install libboost-dev -apt-get install python-dev libbz2-dev - -2).Download Hyperscan sources -wget https://github.com/intel/hyperscan/archive/v5.0.0.tar.gz -tar -xf v5.0.0.tar.gz - -3).Download boost headers -wget https://dl.bintray.com/boostorg/release/1.68.0/source/boost_1_68_0.tar.gz -tar -xf boost_1_68_0.tar.gz -cp -r boost_1_68_0/boost hyperscan-5.0.0/include - -4).Build and install Hyperscan shared library. - Just follow the instruction from here. Compilation can take a long time. -cd hyperscan-5.0.0 -mkdir build -cd build -cmake -DBUILD_SHARED_LIBS=true .. -make -make install - -## Multi-Thread Support -Since generated bytecode database is read only, you can run multiple cores -to utilize the byte database to scale. - - - - diff --git a/src/protocols/dpi_ssl.c b/src/protocols/dpi_ssl.c deleted file mode 100644 index f15a19c..0000000 --- a/src/protocols/dpi_ssl.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2019 Intel and/or its affiliates. - * 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 <stdint.h> -#include <string.h> -#include <net/if.h> -#include <sys/ioctl.h> -#include <inttypes.h> - -#include <vlib/vlib.h> -#include <vlib/unix/unix.h> - -#include "../dpi.h" - -typedef enum -{ - State_Initial = 0, - State_Client_Hello = 1, - State_Server_Hello = 2, - State_Certificate = 3, -} ssl_state; - -enum -{ - MAJOR_TLS = 0x3, -}; - -enum -{ - MINOR_SSL30 = 0, - MINOR_TLS10 = 0x1, - MINOR_TLS11 = 0x2, - MINOR_TLS12 = 0x3, -}; - -typedef enum -{ - change_cipher_spec = 20, - alert = 21, - handshake = 22, - application_data = 23, -} ContentType; - -typedef struct -{ - u8 major; - u8 minor; -} ProtocolVersion; - -typedef struct -{ - u8 type; - ProtocolVersion version; - u16 length; -} __attribute__ ((packed)) ssl_header; - -typedef enum -{ - hello_request = 0, - client_hello = 1, - server_hello = 2, - certificate = 11, - server_key_exchange = 12, - certificate_request = 13, - server_hello_done = 14, - certificate_verify = 15, - client_key_exchange = 16, - finished = 20, -} HandshakeType; - -typedef struct -{ - u8 msg_type; /* handshake type */ - u8 length[3]; /* bytes in message */ -} Handshake_header; - -int dpi_ssl_detect_protocol_from_cert (u8 * payload, u32 payload_len, - dpi_flow_info_t * flow); - -#define dpi_isprint(ch) ((ch) >= 0x20 && (ch) <= 0x7e) -#define dpi_isalpha(ch) (((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z')) -#define dpi_isdigit(ch) ((ch) >= '0' && (ch) <= '9') -#define dpi_isspace(ch) (((ch) >= '\t' && (ch) <= '\r') || ((ch) == ' ')) -#define dpi_min(a,b) ((a < b) ? a : b) - -static void -dpi_set_detected_protocol (dpi_flow_info_t * flow, - u32 upper_protocol, u32 lower_protocol) -{ - - if ((upper_protocol == DPI_PROTOCOL_UNKNOWN) - && (lower_protocol != DPI_PROTOCOL_UNKNOWN)) - upper_protocol = lower_protocol; - - if (upper_protocol == lower_protocol) - lower_protocol = DPI_PROTOCOL_UNKNOWN; - - if ((upper_protocol != DPI_PROTOCOL_UNKNOWN) - && (lower_protocol == DPI_PROTOCOL_UNKNOWN)) - { - if ((flow->guessed_host_protocol_id != DPI_PROTOCOL_UNKNOWN) - && (upper_protocol != flow->guessed_host_protocol_id)) - { - lower_protocol = upper_protocol; - upper_protocol = flow->guessed_host_protocol_id; - } - } - - flow->detected_protocol[0] = upper_protocol; - flow->detected_protocol[1] = lower_protocol; -} - -static u32 -dpi_ssl_refine_master_protocol (dpi_flow_info_t * flow, u32 protocol) -{ - - if (flow->l4.tcp.ssl_got_server_cert == 1) - protocol = DPI_PROTOCOL_SSL; - else - protocol = DPI_PROTOCOL_SSL_NO_CERT; - - return protocol; -} - -int -dpi_ssl_detect_protocol_from_cert (u8 * payload, u32 payload_len, - dpi_flow_info_t * flow) -{ - u32 host_protocol = DPI_PROTOCOL_UNKNOWN; - int rv = 0; - - /* Only check SSL handshake packets. - * Check first segment and subsequent segments. */ - if (((payload_len > (sizeof (ssl_header) + sizeof (Handshake_header))) - && (payload[0] == handshake)) || (flow->detect_begin)) - { - if ((flow->detected_protocol[0] == DPI_PROTOCOL_UNKNOWN) - || (flow->detected_protocol[0] == DPI_PROTOCOL_SSL)) - { - rv = dpi_search_host_protocol (flow, (char *) payload, payload_len, - DPI_PROTOCOL_SSL, &host_protocol); - - if (host_protocol != DPI_PROTOCOL_UNKNOWN) - { - dpi_set_detected_protocol (flow, host_protocol, - dpi_ssl_refine_master_protocol (flow, - DPI_PROTOCOL_SSL)); - return rv; - } - } - } - return 0; -} - - -void -dpi_search_tcp_ssl (u8 * payload, u32 payload_len, dpi_flow_info_t * flow) -{ - u32 cur_len = payload_len; - u32 cur_len2; - u8 handshake_type; - - /* Check first segment of SSL Certificate message */ - if ((payload_len > (sizeof (ssl_header) + sizeof (Handshake_header))) - && (payload[0] == handshake)) - { - handshake_type = payload[5]; - - if (handshake_type == client_hello) - { - flow->l4.tcp.ssl_stage = State_Client_Hello; - return; - } - else if (handshake_type == server_hello) - { - cur_len = ntohs (get_u16_t (payload, 3)) + sizeof (ssl_header); - - /* This packet only contains Server Hello message */ - if (cur_len == payload_len) - { - flow->l4.tcp.ssl_stage = State_Server_Hello; - return; - } - - /* This packet contains Server Hello, Certificate and more messages */ - if (payload_len >= cur_len + sizeof (ssl_header) - && payload[cur_len] == handshake - && payload[cur_len + 1] == MAJOR_TLS) - { - cur_len2 = ntohs (get_u16_t (payload, cur_len + 3)) - + sizeof (ssl_header); - if (payload[cur_len + 5] == certificate) - { - flow->l4.tcp.ssl_stage = State_Certificate; - flow->detect_begin = 1; - /* Scan segments of certificate message */ - if (dpi_ssl_detect_protocol_from_cert (&payload[cur_len], - cur_len2, flow) > 0) - return; - } - } - } - else if (handshake_type == certificate) - { - cur_len = ntohs (get_u16_t (payload, 3)) + sizeof (ssl_header); - - /* This packet contains first segment of certificate message */ - if (cur_len == payload_len) - { - flow->l4.tcp.ssl_stage = State_Certificate; - flow->detect_begin = 1; - /* Scan segments of certificate message */ - if (dpi_ssl_detect_protocol_from_cert (payload, cur_len, flow) > - 0) - return; - } - } - else if (flow->detect_begin) - { - /* Check subsequent segments of SSL Certificate message */ - if (dpi_ssl_detect_protocol_from_cert (payload, cur_len, flow) > 0) - return; - } - } - - return; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |