diff options
Diffstat (limited to 'src/dpi.c')
-rw-r--r-- | src/dpi.c | 723 |
1 files changed, 0 insertions, 723 deletions
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: - */ |