mirror of
https://github.com/pavel-odintsov/fastnetmon.git
synced 2024-09-21 10:27:13 +00:00
Added logic to strip 1, 2 or 3 nested vlans
This commit is contained in:
parent
ed7ae8ee98
commit
78bdeae324
@ -130,7 +130,7 @@ class __attribute__((__packed__)) mpls_label_t {
|
||||
public:
|
||||
uint32_t label : 20 = 0, qos : 3 = 0, bottom_of_stack : 1 = 0, ttl : 8 = 0;
|
||||
|
||||
std::string print() {
|
||||
std::string print() const {
|
||||
std::stringstream buffer;
|
||||
|
||||
buffer << "label: " << uint32_t(label) << " "
|
||||
@ -162,7 +162,6 @@ class __attribute__((__packed__)) ethernet_vlan_header_t {
|
||||
|
||||
// We can access data in packet only using special methods which can do all required format conversions
|
||||
public:
|
||||
|
||||
// Returns ethertype in host byte order
|
||||
uint16_t get_ethertype_host_byte_order() const {
|
||||
return fast_ntoh(ethertype);
|
||||
@ -230,7 +229,7 @@ class __attribute__((__packed__)) ethernet_header_t {
|
||||
|
||||
public:
|
||||
// Returns ethertype in host byte order
|
||||
uint16_t get_ethertype_host_byte_order() {
|
||||
uint16_t get_ethertype_host_byte_order() const {
|
||||
return fast_ntoh(ethertype);
|
||||
}
|
||||
|
||||
@ -270,7 +269,6 @@ class __attribute__((__packed__)) arp_header_t {
|
||||
uint32_t target_protocol_address = 0;
|
||||
|
||||
public:
|
||||
|
||||
uint8_t get_hardware_address_length() const {
|
||||
return hardware_address_length;
|
||||
}
|
||||
@ -310,9 +308,11 @@ class __attribute__((__packed__)) arp_header_t {
|
||||
<< "protocol_address_length: " << uint32_t(get_protocol_address_length()) << " "
|
||||
<< "operation: " << get_operation_host_byte_order() << " "
|
||||
<< "sender_hardware_address: " << convert_mac_to_string(sender_hardware_address) << " "
|
||||
<< "sender_protocol_address: " << convert_ip_as_big_endian_to_string(get_sender_protocol_address_network_byte_order()) << " "
|
||||
<< "sender_protocol_address: "
|
||||
<< convert_ip_as_big_endian_to_string(get_sender_protocol_address_network_byte_order()) << " "
|
||||
<< "target_hardware_address: " << convert_mac_to_string(target_hardware_address) << " "
|
||||
<< "target_protocol_address: " << convert_ip_as_big_endian_to_string(get_target_protocol_address_network_byte_order());
|
||||
<< "target_protocol_address: "
|
||||
<< convert_ip_as_big_endian_to_string(get_target_protocol_address_network_byte_order());
|
||||
|
||||
return buffer.str();
|
||||
}
|
||||
@ -401,7 +401,6 @@ class __attribute__((__packed__)) gre_header_t {
|
||||
uint16_t protocol_type = 0;
|
||||
|
||||
public:
|
||||
|
||||
uint16_t get_protocol_type_host_byte_order() const {
|
||||
return fast_ntoh(protocol_type);
|
||||
}
|
||||
@ -472,7 +471,6 @@ class __attribute__((__packed__)) cropped_tcp_header_only_ports_t {
|
||||
uint16_t destination_port = 0;
|
||||
|
||||
public:
|
||||
|
||||
uint16_t get_source_port_host_byte_order() const {
|
||||
return fast_ntoh(source_port);
|
||||
}
|
||||
@ -496,13 +494,11 @@ class __attribute__((__packed__)) tcp_header_t {
|
||||
uint16_t data_offset_and_flags_as_integer = 0;
|
||||
|
||||
private:
|
||||
|
||||
uint16_t window_size = 0;
|
||||
uint16_t checksum = 0;
|
||||
uint16_t urgent = 0;
|
||||
|
||||
public:
|
||||
|
||||
uint16_t get_source_port_host_byte_order() const {
|
||||
return fast_ntoh(source_port);
|
||||
}
|
||||
@ -717,7 +713,6 @@ class __attribute__((__packed__)) ipv6_extension_header_fragment_t {
|
||||
uint32_t identification = 0;
|
||||
|
||||
public:
|
||||
|
||||
uint16_t get_more_fragments() const {
|
||||
uint16_t flags_little_endian = fast_ntoh(fragmentation_and_flags_as_integer);
|
||||
|
||||
@ -876,7 +871,6 @@ static_assert(sizeof(ipv4_header_fragmentation_flags_t) == 2, "Bad size for ipv4
|
||||
class __attribute__((__packed__)) ipv4_header_t {
|
||||
// We must not access these fields directly as they need conversion
|
||||
private:
|
||||
|
||||
uint8_t ihl : 4 = 0, version : 4 = 0;
|
||||
uint8_t ecn : 2 = 0, dscp : 6 = 0;
|
||||
|
||||
@ -896,7 +890,6 @@ class __attribute__((__packed__)) ipv4_header_t {
|
||||
uint32_t destination_ip = 0;
|
||||
|
||||
public:
|
||||
|
||||
ipv4_header_t()
|
||||
: ihl(0), version(0), ecn(0), dscp(0), total_length(0), identification(0), fragmentation_details_as_integer(0),
|
||||
ttl(0), protocol(0), checksum(0), source_ip(0), destination_ip(0) {
|
||||
@ -910,7 +903,7 @@ class __attribute__((__packed__)) ipv4_header_t {
|
||||
return fast_ntoh(total_length);
|
||||
}
|
||||
|
||||
bool is_fragmented() {
|
||||
bool is_fragmented() const {
|
||||
if (this->get_more_fragments_flag()) {
|
||||
return true;
|
||||
}
|
||||
@ -1082,7 +1075,8 @@ enum class parser_code_t {
|
||||
no_ipv6_support,
|
||||
no_ipv6_options_support,
|
||||
unknown_ethertype,
|
||||
arp
|
||||
arp,
|
||||
too_many_nested_vlans,
|
||||
};
|
||||
|
||||
std::string parser_code_to_string(parser_code_t code);
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include "fast_library.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
|
||||
using namespace network_data_stuctures;
|
||||
|
||||
@ -14,6 +14,9 @@ using namespace network_data_stuctures;
|
||||
// TODO: it's not working code yet
|
||||
bool decode_mpls = false;
|
||||
|
||||
// We can strip only 3 nested vlans
|
||||
const uint32_t maximum_vlans_to_strip = 3;
|
||||
|
||||
// Our own native function to convert wire packet into simple_packet_t
|
||||
parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
int length_before_sampling,
|
||||
@ -32,30 +35,44 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
return parser_code_t::memory_violation;
|
||||
}
|
||||
|
||||
ethernet_header_t* ethernet_header = (ethernet_header_t*)local_pointer;
|
||||
const ethernet_header_t* ethernet_header = (const ethernet_header_t*)local_pointer;
|
||||
|
||||
// Copy Ethernet MAC addresses to packet structure using native C++ approach to avoid touching memory with memcpy
|
||||
std::copy(std::begin(ethernet_header->source_mac), std::end(ethernet_header->source_mac), std::begin(packet.source_mac));
|
||||
|
||||
std::copy(std::begin(ethernet_header->destination_mac), std::end(ethernet_header->destination_mac), std::begin(packet.destination_mac));
|
||||
std::copy(std::begin(ethernet_header->destination_mac), std::end(ethernet_header->destination_mac),
|
||||
std::begin(packet.destination_mac));
|
||||
|
||||
local_pointer += sizeof(ethernet_header_t);
|
||||
|
||||
// Copy ethertype as we may need to change it below
|
||||
uint16_t ethertype = ethernet_header->get_ethertype_host_byte_order();
|
||||
|
||||
if (ethertype == IanaEthertypeVLAN) {
|
||||
// Return error if it shorter then vlan header
|
||||
uint32_t number_of_stripped_vlans = 0;
|
||||
|
||||
// This loop will not start if ethertype is not VLAN
|
||||
while (ethertype == IanaEthertypeVLAN) {
|
||||
// Return error if it's shorter than vlan header
|
||||
if (local_pointer + sizeof(ethernet_vlan_header_t) > end_pointer) {
|
||||
return parser_code_t::memory_violation;
|
||||
}
|
||||
|
||||
ethernet_vlan_header_t* ethernet_vlan_header = (ethernet_vlan_header_t*)local_pointer;
|
||||
const ethernet_vlan_header_t* ethernet_vlan_header = (const ethernet_vlan_header_t*)local_pointer;
|
||||
|
||||
// We've agreed that this field keeps only outermost vlan
|
||||
if (number_of_stripped_vlans == 0) {
|
||||
packet.vlan = ethernet_vlan_header->get_vlan_id_host_byte_order();
|
||||
}
|
||||
|
||||
local_pointer += sizeof(ethernet_vlan_header_t);
|
||||
|
||||
number_of_stripped_vlans++;
|
||||
|
||||
// We need to limit it to avoid possibility of attack which uses too many vlans tags to overload our parser
|
||||
if (number_of_stripped_vlans > maximum_vlans_to_strip) {
|
||||
return parser_code_t::too_many_nested_vlans;
|
||||
}
|
||||
|
||||
// Change ethertype to vlan's ethertype
|
||||
ethertype = ethernet_vlan_header->get_ethertype_host_byte_order();
|
||||
}
|
||||
@ -67,7 +84,7 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
return parser_code_t::memory_violation;
|
||||
}
|
||||
|
||||
mpls_label_t* mpls_label_header = (mpls_label_t*)local_pointer;
|
||||
const mpls_label_t* mpls_label_header = (const mpls_label_t*)local_pointer;
|
||||
|
||||
std::cout << "MPLS header: " << mpls_label_header->print() << std::endl;
|
||||
|
||||
@ -90,7 +107,7 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
return parser_code_t::memory_violation;
|
||||
}
|
||||
|
||||
ipv4_header_t* ipv4_header = (ipv4_header_t*)local_pointer;
|
||||
const ipv4_header_t* ipv4_header = (const ipv4_header_t*)local_pointer;
|
||||
|
||||
// Use network representation of addresses
|
||||
packet.src_ip = ipv4_header->get_source_ip_network_byte_order();
|
||||
@ -145,7 +162,7 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
return parser_code_t::memory_violation;
|
||||
}
|
||||
|
||||
ipv6_header_t* ipv6_header = (ipv6_header_t*)local_pointer;
|
||||
const ipv6_header_t* ipv6_header = (const ipv6_header_t*)local_pointer;
|
||||
|
||||
// TODO: we may use std::copy for it to avoid touching memory with memcpy
|
||||
memcpy(&packet.src_ipv6, ipv6_header->source_address, sizeof(packet.src_ipv6));
|
||||
@ -196,7 +213,7 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
|
||||
// We decided to parse only fragmentation header option as only this field may be found in the Wild
|
||||
if (protocol == IpProtocolNumberIPV6_FRAG) {
|
||||
ipv6_extension_header_fragment_t* ipv6_extension_header_fragment = (ipv6_extension_header_fragment_t*)local_pointer;
|
||||
const ipv6_extension_header_fragment_t* ipv6_extension_header_fragment = (const ipv6_extension_header_fragment_t*)local_pointer;
|
||||
|
||||
// If we received this header then we assume that packet was fragmented
|
||||
packet.ip_fragmented = true;
|
||||
@ -224,8 +241,8 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
if (protocol == IpProtocolNumberTCP) {
|
||||
if (local_pointer + sizeof(tcp_header_t) > end_pointer) {
|
||||
// We observed that Huawei routers may send only first 52 bytes of header in sFlow mode
|
||||
// and it's not enough to accommodate whole TCP header which has length of 20 bytes and we can observe only first 14 bytes
|
||||
// and it happened in case of vlan presence
|
||||
// and it's not enough to accommodate whole TCP header which has length of 20 bytes and we can observe only
|
||||
// first 14 bytes and it happened in case of vlan presence
|
||||
|
||||
// To offer better experience we will try retrieving only ports from TCP header as they're located in the beginning of packet
|
||||
if (local_pointer + sizeof(cropped_tcp_header_only_ports_t) > end_pointer) {
|
||||
@ -235,7 +252,7 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
}
|
||||
|
||||
// Use short TCP header which has only access to source and destination ports
|
||||
cropped_tcp_header_only_ports_t* tcp_header = (cropped_tcp_header_only_ports_t*)local_pointer;
|
||||
const cropped_tcp_header_only_ports_t* tcp_header = (const cropped_tcp_header_only_ports_t*)local_pointer;
|
||||
|
||||
packet.source_port = tcp_header->get_source_port_host_byte_order();
|
||||
packet.destination_port = tcp_header->get_destination_port_host_byte_order();
|
||||
@ -243,7 +260,7 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
return parser_code_t::success;
|
||||
}
|
||||
|
||||
tcp_header_t* tcp_header = (tcp_header_t*)local_pointer;
|
||||
const tcp_header_t* tcp_header = (const tcp_header_t*)local_pointer;
|
||||
|
||||
packet.source_port = tcp_header->get_source_port_host_byte_order();
|
||||
packet.destination_port = tcp_header->get_destination_port_host_byte_order();
|
||||
@ -257,7 +274,7 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
return parser_code_t::memory_violation;
|
||||
}
|
||||
|
||||
udp_header_t* udp_header = (udp_header_t*)local_pointer;
|
||||
const udp_header_t* udp_header = (const udp_header_t*)local_pointer;
|
||||
|
||||
packet.source_port = udp_header->get_source_port_host_byte_order();
|
||||
packet.destination_port = udp_header->get_destination_port_host_byte_order();
|
||||
@ -271,7 +288,7 @@ parser_code_t parse_raw_packet_to_simple_packet_full_ng(const uint8_t* pointer,
|
||||
return parser_code_t::memory_violation;
|
||||
}
|
||||
|
||||
gre_header_t* gre_header = (gre_header_t*)local_pointer;
|
||||
const gre_header_t* gre_header = (const gre_header_t*)local_pointer;
|
||||
|
||||
// Current version of parser does not handle these special codes and we just fail parsing process
|
||||
// These flags may extend length of GRE header and current logic is not ready to decode any of them
|
||||
@ -409,4 +426,3 @@ parser_code_t parse_raw_ipv4_packet_to_simple_packet_full_ng(const uint8_t* poin
|
||||
|
||||
return parser_code_t::success;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user