From 161bd1acaebbf584674573840535b601f688c412 Mon Sep 17 00:00:00 2001 From: Jaroslav Pesek Date: Tue, 5 Nov 2024 18:30:07 +0100 Subject: [PATCH] ndp input plugin - add parser that works with metadata --- input/ndp.cpp | 31 ++++---------- input/ndp.hpp | 25 +---------- input/parser.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++++++ input/parser.hpp | 4 ++ 4 files changed, 120 insertions(+), 47 deletions(-) diff --git a/input/ndp.cpp b/input/ndp.cpp index 74cfeddf..aad9dd8f 100644 --- a/input/ndp.cpp +++ b/input/ndp.cpp @@ -122,9 +122,9 @@ void NdpPacketReader::parse_ctt_metadata(const ndp_packet *ndp_packet, Metadata_ ctt.vlan_tci = extract(metadata, 64, 16); ctt.vlan_vld = extract(metadata, 80, 1); ctt.vlan_stripped = extract(metadata, 81, 1); - ctt.ip_csum_status = extract(metadata, 82, 2); - ctt.l4_csum_status = extract(metadata, 84, 2); - ctt.parser_status = extract(metadata, 86, 2); + ctt.ip_csum_status = static_cast(extract(metadata, 82, 2)); + ctt.l4_csum_status = static_cast(extract(metadata, 84, 2)); + ctt.parser_status = static_cast(extract(metadata, 86, 2)); ctt.ifc = extract(metadata, 88, 8); ctt.filter_bitmap = extract(metadata, 96, 16); ctt.ctt_export_trig = extract(metadata, 112, 1); @@ -135,9 +135,9 @@ void NdpPacketReader::parse_ctt_metadata(const ndp_packet *ndp_packet, Metadata_ ctt.l2_len = extract(metadata, 192, 7); ctt.l3_len = extract(metadata, 199, 9); ctt.l4_len = extract(metadata, 208, 8); - ctt.l2_ptype = extract(metadata, 216, 4); - ctt.l3_ptype = extract(metadata, 220, 4); - ctt.l4_ptype = extract(metadata, 224, 4); + ctt.l2_ptype = static_cast(extract(metadata, 216, 4)); + ctt.l3_ptype = static_cast(extract(metadata, 220, 4)); + ctt.l4_ptype = static_cast(extract(metadata, 224, 4)); return; } @@ -166,24 +166,7 @@ InputPlugin::Result NdpPacketReader::get(PacketBlock &packets) if (m_ctt_metadata) { Metadata_CTT ctt; parse_ctt_metadata(ndp_packet, ctt); - parse_packet(&opt, m_parser_stats, timestamp, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length); - - Packet *pkt = &opt.pblock->pkts[opt.pblock->cnt - 1]; - - // verify metadata with original parser - if(ctt.l2_len + ctt.l3_len + ctt.l4_len != pkt->packet_len - pkt->payload_len) { - printf("Error: ctt.l2_len (%d) + ctt.l3_len (%d) + ctt.l4_len (%d) != pkt->packet_len (%d) - pkt->payload_len (%d)\n", ctt.l2_len, ctt.l3_len, ctt.l4_len, pkt->packet_len, pkt->payload_len); - } - if(pkt->ip_proto == IPPROTO_TCP) { - if(ctt.l4_ptype != 0x1) { - printf("Error: ctt.l4_ptype (%d) != 0x1 but protocol is TCP (%d)\n", ctt.l4_ptype, pkt->ip_proto); - } - } - if(pkt->ip_proto == IPPROTO_UDP) { - if(ctt.l4_ptype != 0x2) { - printf("Error: ctt.l4_ptype (%d) != 0x2 but protocol is UDP (%d)\n", ctt.l4_ptype, pkt->ip_proto); - } - } + parse_packet_ctt_metadata(&opt, m_parser_stats, ctt, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length); } else { parse_packet(&opt, m_parser_stats, timestamp, ndp_packet->data, ndp_packet->data_length, ndp_packet->data_length); } diff --git a/input/ndp.hpp b/input/ndp.hpp index 0b78b859..b751d3d3 100644 --- a/input/ndp.hpp +++ b/input/ndp.hpp @@ -38,30 +38,9 @@ #include #include -namespace ipxp { +#include "ctt.hpp" -struct Metadata_CTT { - timeval ts; - uint16_t vlan_tci; - bool vlan_vld : 1; - bool vlan_stripped : 1; - uint8_t ip_csum_status : 2; - uint8_t l4_csum_status : 2; - uint8_t parser_status : 2; - uint8_t ifc; - uint16_t filter_bitmap; - uint8_t ctt_export_trig : 1; - uint8_t ctt_rec_matched : 1; - uint8_t ctt_rec_created : 1; - uint8_t ctt_rec_deleted : 1; - uint64_t flow_hash; - uint8_t l2_len : 7; - uint16_t l3_len : 9; - uint8_t l4_len : 8; - uint8_t l2_ptype : 4; - uint8_t l3_ptype : 4; - uint8_t l4_ptype : 4; -}; +namespace ipxp { class NdpOptParser : public OptionsParser { diff --git a/input/parser.cpp b/input/parser.cpp index 61b696cb..5df7cbec 100644 --- a/input/parser.cpp +++ b/input/parser.cpp @@ -27,6 +27,7 @@ */ #include +#include #include #include #include @@ -35,6 +36,7 @@ #include "parser.hpp" #include "headers.hpp" +#include "ctt.hpp" #include namespace ipxp { @@ -776,4 +778,109 @@ void parse_packet(parser_opt_t *opt, ParserStats& stats, struct timeval ts, cons opt->pblock->bytes += len; } +void parse_packet_ctt_metadata(parser_opt_t *opt, ParserStats& stats, const Metadata_CTT& metadata, const uint8_t *data, uint16_t len, uint16_t caplen) +{ + if (opt->pblock->cnt >= opt->pblock->size) { + return; + } + Packet *pkt = &opt->pblock->pkts[opt->pblock->cnt]; + + pkt->packet_len_wire = len; + pkt->ts = metadata.ts; + pkt->src_port = 0; + pkt->dst_port = 0; + pkt->ip_proto = 0; + pkt->ip_ttl = 0; + pkt->ip_flags = 0; + pkt->ip_version = 0; + pkt->ip_payload_len = 0; + pkt->tcp_flags = 0; + pkt->tcp_window = 0; + pkt->tcp_options = 0; + pkt->tcp_mss = 0; + pkt->mplsTop = 0; + + stats.seen_packets++; + + uint16_t data_offset; + uint32_t l3_hdr_offset = metadata.l2_len; + uint32_t l4_hdr_offset = metadata.l2_len + metadata.l3_len; + + try { + // L2 + data_offset = parse_eth_hdr(data, caplen, pkt); + if (pkt->ethertype == ETH_P_TRILL) { + data_offset += parse_trill(data + metadata.l2_len, metadata.l2_len, pkt); + stats.trill_packets++; + data_offset += parse_eth_hdr(data + metadata.l2_len, metadata.l2_len, pkt); + } + + // L3 + if (metadata.l2_ptype == L2_ETHER_IP) { + if (metadata.l3_ptype == L3_IPV4 || metadata.l3_ptype == L3_IPV4_EXT) { + data_offset += parse_ipv4_hdr(data + metadata.l2_len, metadata.l3_len, pkt); + stats.ipv4_packets++; + } else if (metadata.l3_ptype == L3_IPV6 || metadata.l3_ptype == L3_IPV4_EXT) { + data_offset += parse_ipv6_hdr(data + metadata.l2_len, metadata.l3_len, pkt); + stats.ipv6_packets++; + } + } else if (metadata.l2_ptype == L2_ETHER_MPLS) { + data_offset += process_mpls(data + data_offset, caplen - data_offset, pkt); + stats.mpls_packets++; + } else if (metadata.l2_ptype == L2_ETHER_PPPOE) { + data_offset += process_pppoe(data + data_offset, caplen - data_offset, pkt); + stats.pppoe_packets++; + } else { // if not previous, we try delegate to original parser + parse_packet(opt, stats, metadata.ts, data, len, caplen); + return; + } + + // L4 + if (metadata.l4_ptype == L4_TCP) { + data_offset += parse_tcp_hdr(data + l4_hdr_offset, metadata.l4_len, pkt); + stats.tcp_packets++; + } else if (metadata.l4_ptype == L4_UDP) { + data_offset += parse_udp_hdr(data + l4_hdr_offset, metadata.l4_len, pkt); + stats.udp_packets++; + } else { // if not previous, we try delegate to original parser + parse_packet(opt, stats, metadata.ts, data, len, caplen); + return; + } + } catch (const char *err) { + DEBUG_MSG("%s\n", err); + return; + } + + if (pkt->vlan_id) { + stats.vlan_packets++; + } + + uint16_t pkt_len = caplen; + pkt->packet = data; + pkt->packet_len = caplen; + + if (l4_hdr_offset != l3_hdr_offset) { + if (l4_hdr_offset + pkt->ip_payload_len < 64) { + // Packet contains 0x00 padding bytes, do not include them in payload + pkt_len = l4_hdr_offset + pkt->ip_payload_len; + } + pkt->payload_len_wire = pkt->ip_payload_len - (data_offset - l4_hdr_offset); + } else { + pkt->payload_len_wire = pkt_len - data_offset; + } + + pkt->payload_len = pkt->payload_len_wire; + if (pkt->payload_len + data_offset > pkt_len) { + // Set correct size when payload length is bigger than captured payload length + pkt->payload_len = pkt_len - data_offset; + } + pkt->payload = pkt->packet + data_offset; + + DEBUG_MSG("Payload length:\t%u\n", pkt->payload_len); + DEBUG_MSG("Packet parser exits: packet parsed\n"); + opt->packet_valid = true; + opt->pblock->cnt++; + opt->pblock->bytes += len; +} + } diff --git a/input/parser.hpp b/input/parser.hpp index 09950850..5a12631e 100644 --- a/input/parser.hpp +++ b/input/parser.hpp @@ -32,6 +32,8 @@ #include #include +#include "ctt.hpp" + #ifdef WITH_PCAP #include #include @@ -85,5 +87,7 @@ typedef struct parser_opt_s { */ void parse_packet(parser_opt_t *opt, ParserStats& stats, struct timeval ts, const uint8_t *data, uint16_t len, uint16_t caplen); +void parse_packet_ctt_metadata(parser_opt_t *opt, ParserStats& stats, const Metadata_CTT& metadata, const uint8_t *data, uint16_t len, uint16_t caplen); + } #endif /* IPXP_INPUT_PARSER_HPP */