diff --git a/src/fast_library.cpp b/src/fast_library.cpp index 3b9d158..0d19f14 100644 --- a/src/fast_library.cpp +++ b/src/fast_library.cpp @@ -1284,3 +1284,12 @@ bool store_data_to_stats_server(unsigned short int graphite_port, std::string gr return false; } } + +bool convert_hex_as_string_to_uint(std::string hex, uint32_t& value) { + std::stringstream ss; + + ss << std::hex << hex; + ss >> value; + + return ss.fail(); +} diff --git a/src/fast_library.h b/src/fast_library.h index f0cf02c..d8a19ac 100644 --- a/src/fast_library.h +++ b/src/fast_library.h @@ -53,6 +53,7 @@ std::string convert_int_to_string(int value); std::string print_ipv6_address(struct in6_addr& ipv6_address); std::string print_simple_packet(simple_packet packet); std::string convert_timeval_to_date(struct timeval tv); +bool convert_hex_as_string_to_uint(std::string hex, uint32_t& value); int extract_bit_value(uint8_t num, int bit); int extract_bit_value(uint16_t num, int bit); diff --git a/src/fastnetmon.conf b/src/fastnetmon.conf index e553639..97dea69 100644 --- a/src/fastnetmon.conf +++ b/src/fastnetmon.conf @@ -165,6 +165,12 @@ sflow_host = 0.0.0.0 # This option is not default and you need build it additionally # sflow_lua_hooks_path = /usr/src/fastnetmon/src/sflow_hooks.lua +# sFlow processing QinQ +sflow_qinq_process = off + +# sFlow ethertype of outer tag in QinQ +sflow_qinq_ethertype = 0x8100 + ### ### Actions when attack detected ### diff --git a/src/sflow_hooks.lua b/src/sflow_hooks.lua index a0cf21b..d5f96b4 100644 --- a/src/sflow_hooks.lua +++ b/src/sflow_hooks.lua @@ -123,6 +123,7 @@ typedef struct _SFSample { uint8_t eth_dst[8]; /* vlan */ + uint32_t in_outer_vlan; uint32_t in_vlan; uint32_t in_priority; uint32_t internalPriority; diff --git a/src/sflow_plugin/sflow_collector.cpp b/src/sflow_plugin/sflow_collector.cpp index f0dbc58..e7cb64b 100644 --- a/src/sflow_plugin/sflow_collector.cpp +++ b/src/sflow_plugin/sflow_collector.cpp @@ -41,6 +41,12 @@ bool sflow_lua_hooks_enabled = false; std::string sflow_lua_hooks_path = "/usr/src/fastnetmon/src/sflow_hooks.lua"; #endif +// Ethertype of outer tag in QinQ +uint32_t sflow_qinq_ethertype = 0x8100; + +// Disable QinQ processing by default +bool sflow_qinq_process = false; + // sFLOW v4 specification: http://www.sflow.org/rfc3176.txt std::string plugin_name = "sflow"; @@ -86,6 +92,24 @@ void start_sflow_collection(process_packet_pointer func_ptr) { interface_for_binding = configuration_map["sflow_host"]; } + if (configuration_map.count("sflow_qinq_process") != 0) { + if (configuration_map["sflow_qinq_process"] == "on") { + + sflow_qinq_process = true; + logger << log4cpp::Priority::INFO << plugin_log_prefix << "qinq processing enabled"; + + if (configuration_map.count("sflow_qinq_ethertype") != 0) { + if (convert_hex_as_string_to_uint(configuration_map["sflow_qinq_ethertype"], sflow_qinq_ethertype)) { + logger << log4cpp::Priority::WARN << plugin_log_prefix + << "can't parse value in sflow_qinq_ethertype variable"; + logger << log4cpp::Priority::INFO << plugin_log_prefix + << "disable qinq processing"; + sflow_qinq_process = false; + } + } + } + } + #ifdef ENABLE_LUA_HOOKS if (configuration_map.count("sflow_lua_hooks_path") != 0) { sflow_lua_hooks_path = configuration_map["sflow_lua_hooks_path"]; @@ -535,8 +559,21 @@ void decode_link_layer(SFSample* sample) { type_len = (ptr[0] << 8) + ptr[1]; ptr += 2; + if (sflow_qinq_process && type_len == sflow_qinq_ethertype && ((ptr[2] << 8) + ptr[3]) == 0x8100) { + /* Outer VLAN tag - next two bytes */ + uint32_t vlanData = (ptr[0] << 8) + ptr[1]; + uint32_t vlan = vlanData & 0x0fff; + uint32_t priority = vlanData >> 13; + ptr += 2; + + sample->in_outer_vlan = vlan; + /* now get the type_len again (next two bytes) */ + type_len = (ptr[0] << 8) + ptr[1]; + ptr += 2; + } + if (type_len == 0x8100) { - /* VLAN - next two bytes */ + /* Inner VLAN tag - next two bytes */ uint32_t vlanData = (ptr[0] << 8) + ptr[1]; uint32_t vlan = vlanData & 0x0fff; uint32_t priority = vlanData >> 13; diff --git a/src/sflow_plugin/sflow_data.h b/src/sflow_plugin/sflow_data.h index 441daa5..c2058b0 100644 --- a/src/sflow_plugin/sflow_data.h +++ b/src/sflow_plugin/sflow_data.h @@ -151,6 +151,7 @@ typedef struct _SFSample { uint8_t eth_dst[8]; /* vlan */ + uint32_t in_outer_vlan; uint32_t in_vlan; uint32_t in_priority; uint32_t internalPriority;