1
0
Fork 0
mirror of https://github.com/pavel-odintsov/fastnetmon synced 2024-05-26 16:16:09 +02:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Roberto Berto 2015-07-22 13:06:52 -03:00
commit 82c4704a98
9 changed files with 439 additions and 98 deletions

View File

@ -1,4 +1,5 @@
Thanks file! For all peoples which helped this project :)
- Luke Gorrie for SnabbSwitch and help with lightning speed packet processing :)
- Andrei Ziltsov / FastVPS Eesti OU for testing and patience :)
- Luca Deri for PF_RING toolkit!
- Alfredo Cardigliano for helping me with PF_RING libraries :)

View File

@ -87,6 +87,8 @@ endif()
# Our LPM library
add_library(patricia STATIC libpatricia/patricia.c)
add_library(fastnetmon_pcap_format STATIC fastnetmon_pcap_format.cpp)
# Our tools library
add_library(fast_library STATIC fast_library.cpp)
@ -159,6 +161,7 @@ if(Boost_FOUND)
endif()
target_link_libraries(fast_library patricia)
target_link_libraries(fast_library fastnetmon_pcap_format)
# Try to find ncurses librreary
find_package(Curses REQUIRED)
@ -215,6 +218,7 @@ endif()
# Our libs
target_link_libraries(fastnetmon patricia)
target_link_libraries(fastnetmon fastnetmon_pcap_format)
target_link_libraries(fastnetmon ipfix_rfc)
@ -233,6 +237,7 @@ if (BUILD_PLUGIN_RUNNER)
target_link_libraries(fastnetmon_plugin_runner ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(fastnetmon_plugin_runner patricia)
target_link_libraries(fastnetmon_plugin_runner fastnetmon_pcap_format)
target_link_libraries(fastnetmon_plugin_runner ${LOG4CPP_LIBRARY_PATH})
target_link_libraries(fastnetmon_plugin_runner fast_library)
@ -251,6 +256,9 @@ if (BUILD_PCAP_READER)
target_link_libraries(fastnetmon_pcap_reader fastnetmon_packet_parser)
target_link_libraries(fastnetmon_pcap_reader patricia)
target_link_libraries(fastnetmon_pcap_reader fastnetmon_pcap_format)
target_link_libraries(fastnetmon_pcap_reader fast_library)
target_link_libraries(fastnetmon_pcap_reader ${LOG4CPP_LIBRARY_PATH})
target_link_libraries(fastnetmon_pcap_reader netflow_plugin)

View File

@ -3063,7 +3063,7 @@ void call_attack_details_handlers(uint32_t client_ip, attack_details& current_at
std::string redis_key_name = client_ip_as_string + "_packets_dump";
logger << log4cpp::Priority::INFO << "Start data save in redis for key: " << redis_key_name;
boost::thread redis_store_thread(store_data_in_redis, redis_key_name, attack_details.str());
boost::thread redis_store_thread(store_data_in_redis, redis_key_name, attack_fingerprint);
redis_store_thread.detach();
logger << log4cpp::Priority::INFO << "Finish data save in redis for key: " << redis_key_name;
}

View File

@ -0,0 +1,66 @@
#include "fastnetmon_pcap_format.h"
int pcap_reader(const char* pcap_file_path, pcap_packet_parser_callback pcap_parse_packet_function_ptr) {
int filedesc = open(pcap_file_path, O_RDONLY);
if (filedesc <= 0) {
printf("Can't open dump file");
return -1;
}
struct fastnetmon_pcap_file_header pcap_header;
ssize_t file_header_readed_bytes = read(filedesc, &pcap_header, sizeof(struct fastnetmon_pcap_file_header));
if (file_header_readed_bytes != sizeof(struct fastnetmon_pcap_file_header)) {
printf("Can't read pcap file header");
}
// http://www.tcpdump.org/manpages/pcap-savefile.5.html
if (pcap_header.magic == 0xa1b2c3d4 or pcap_header.magic == 0xd4c3b2a1) {
// printf("Magic readed correctly\n");
} else {
printf("Magic in file header broken\n");
return -2;
}
// Buffer for packets
char packet_buffer[pcap_header.snaplen];
unsigned int read_packets = 0;
while (1) {
// printf("Start packet %d processing\n", read_packets);
struct fastnetmon_pcap_pkthdr pcap_packet_header;
ssize_t packet_header_readed_bytes =
read(filedesc, &pcap_packet_header, sizeof(struct fastnetmon_pcap_pkthdr));
if (packet_header_readed_bytes != sizeof(struct fastnetmon_pcap_pkthdr)) {
// We haven't any packets
break;
}
if (pcap_packet_header.incl_len > pcap_header.snaplen) {
printf("Please enlarge packet buffer! We got packet with size: %d but our buffer is %d "
"bytes\n",
pcap_packet_header.incl_len, pcap_header.snaplen);
return -4;
}
ssize_t packet_payload_readed_bytes = read(filedesc, packet_buffer, pcap_packet_header.incl_len);
if (pcap_packet_header.incl_len != packet_payload_readed_bytes) {
printf("I read packet header but can't read packet payload\n");
return -3;
}
// printf("packet payload read\n");
pcap_parse_packet_function_ptr(packet_buffer, pcap_packet_header.incl_len);
// printf("Process packet %d\n", read_packets);
read_packets++;
}
printf("I correctly read %d packets from this dump\n", read_packets);
return 0;
}

View File

@ -1,6 +1,15 @@
#ifndef FASTNETMON_PCAP_FORMAT_H
#define FASTNETMON_PCAP_FORMAT_H
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*
pcap dump format:
global header: struct pcap_file_header
@ -37,4 +46,8 @@ struct fastnetmon_pcap_pkthdr {
uint32_t orig_len; /* actual length of packet */
};
typedef void (*pcap_packet_parser_callback)(char* buffer, uint32_t len);
int pcap_reader(const char* pcap_file_path, pcap_packet_parser_callback pcap_parse_packet_function_ptr);
#endif

View File

@ -389,17 +389,17 @@ int nf9_rec_to_flow(u_int record_type, u_int record_length, u_int8_t* data, simp
memcpy(&packet.dst_ip, data, record_length);
break;
case NF9_INPUT_SNMP: {
// TODO: port number could be 4 byte (Juniper MX) and we should rewrite BE_COPY for correct handling
uint16_t input_port = 0;
if (record_length > sizeof(input_port)) {
logger << log4cpp::Priority::ERROR << "Received very big packet for NF9_INPUT_SNMP!";
return 0;
//logger << log4cpp::Priority::ERROR << "Received very big packet for NF9_INPUT_SNMP!";
//return 0;
} else {
BE_COPY(input_port);
input_port = fast_ntoh(input_port);
// logger << log4cpp::Priority::INFO << "NF9_INPUT_SNMP is: " << input_port;
}
BE_COPY(input_port);
input_port = fast_ntoh(input_port);
// logger << log4cpp::Priority::INFO << "NF9_INPUT_SNMP is: " << input_port;
}
break;
@ -407,14 +407,13 @@ int nf9_rec_to_flow(u_int record_type, u_int record_length, u_int8_t* data, simp
uint16_t output_port = 0;
if (record_length > sizeof(output_port)) {
logger << log4cpp::Priority::ERROR << "Received very big packet for NF9_OUTPUT_SNMP!";
return 0;
}
BE_COPY(output_port);
output_port = fast_ntoh(output_port);
// logger << log4cpp::Priority::INFO << "NF9_OUTPUT_SNMP is: " << output_port;
//logger << log4cpp::Priority::ERROR << "Received very big packet for NF9_OUTPUT_SNMP!";
//return 0;
} else {
BE_COPY(output_port);
output_port = fast_ntoh(output_port);
// logger << log4cpp::Priority::INFO << "NF9_OUTPUT_SNMP is: " << output_port;
}
}
break;

View File

@ -45,8 +45,6 @@ log4cpp::Category& logger = log4cpp::Category::getRoot();
/* It's prototype for moc testing of FastNetMon, it's very useful for netflow or direct packet
* parsers debug */
void pcap_parse_packet(const char* flow_type, char* buffer, uint32_t len);
void init_logging() {
log4cpp::PatternLayout* layout = new log4cpp::PatternLayout();
layout->setConversionPattern("%d [%p] %m%n");
@ -59,69 +57,7 @@ void init_logging() {
logger.info("Logger initialized!");
}
int pcap_reader(const char* flow_type, const char* pcap_file_path) {
int filedesc = open(pcap_file_path, O_RDONLY);
if (filedesc <= 0) {
printf("Can't open dump file");
return -1;
}
struct fastnetmon_pcap_file_header pcap_header;
ssize_t file_header_readed_bytes = read(filedesc, &pcap_header, sizeof(struct fastnetmon_pcap_file_header));
if (file_header_readed_bytes != sizeof(struct fastnetmon_pcap_file_header)) {
printf("Can't read pcap file header");
}
// http://www.tcpdump.org/manpages/pcap-savefile.5.html
if (pcap_header.magic == 0xa1b2c3d4 or pcap_header.magic == 0xd4c3b2a1) {
// printf("Magic readed correctly\n");
} else {
printf("Magic in file header broken\n");
return -2;
}
// Buffer for packets
char packet_buffer[pcap_header.snaplen];
unsigned int read_packets = 0;
while (1) {
// printf("Start packet %d processing\n", read_packets);
struct fastnetmon_pcap_pkthdr pcap_packet_header;
ssize_t packet_header_readed_bytes =
read(filedesc, &pcap_packet_header, sizeof(struct fastnetmon_pcap_pkthdr));
if (packet_header_readed_bytes != sizeof(struct fastnetmon_pcap_pkthdr)) {
// We haven't any packets
break;
}
if (pcap_packet_header.incl_len > pcap_header.snaplen) {
printf("Please enlarge packet buffer! We got packet with size: %d but our buffer is %d "
"bytes\n",
pcap_packet_header.incl_len, pcap_header.snaplen);
return -4;
}
ssize_t packet_payload_readed_bytes = read(filedesc, packet_buffer, pcap_packet_header.incl_len);
if (pcap_packet_header.incl_len != packet_payload_readed_bytes) {
printf("I read packet header but can't read packet payload\n");
return -3;
}
// printf("packet payload read\n");
pcap_parse_packet(flow_type, packet_buffer, pcap_packet_header.incl_len);
// printf("Process packet %d\n", read_packets);
read_packets++;
}
printf("I correctly read %d packets from this dump\n", read_packets);
return 0;
}
void pcap_parse_packet(const char* flow_type, char* buffer, uint32_t len);
void my_fastnetmon_packet_handler(simple_packet& current_packet) {
std::cout << print_simple_packet(current_packet);
@ -130,7 +66,9 @@ void my_fastnetmon_packet_handler(simple_packet& current_packet) {
extern process_packet_pointer netflow_process_func_ptr;
extern process_packet_pointer sflow_process_func_ptr;
void pcap_parse_packet(const char* flow_type, char* buffer, uint32_t len) {
char* flow_type = NULL;
void pcap_parse_packet(char* buffer, uint32_t len) {
struct pfring_pkthdr packet_header;
memset(&packet_header, 0, sizeof(packet_header));
packet_header.len = len;
@ -167,6 +105,19 @@ void pcap_parse_packet(const char* flow_type, char* buffer, uint32_t len) {
sample.sourceIP.type = SFLADDRESSTYPE_IP_V4;
read_sflow_datagram(&sample);
} else if (strcmp(flow_type, "raw") == 0) {
// We do not need parsed data here
struct pfring_pkthdr packet_header;
memset(&packet_header, 0, sizeof(packet_header));
packet_header.len = payload_length;
packet_header.caplen = payload_length;
fastnetmon_parse_pkt((u_char*)buffer, &packet_header, 4, 1, 0);
char print_buffer[512];
fastnetmon_print_parsed_pkt(print_buffer, 512, (u_char*)buffer, &packet_header);
printf("%s", print_buffer);
} else {
printf("We do not support this flow type: %s\n", flow_type);
}
@ -176,10 +127,11 @@ int main(int argc, char** argv) {
init_logging();
if (argc != 3) {
printf("Please provide flow type: sflow or netflow and path to pcap dump\n");
printf("Please provide flow type: sflow, netflow or raw and path to pcap dump\n");
exit(1);
}
flow_type = argv[1];
printf("We will process file: %s as %s dump\n", argv[2], argv[1]);
pcap_reader(argv[1], argv[2]);
pcap_reader(argv[2], pcap_parse_packet);
}

View File

@ -0,0 +1,171 @@
#include <vector>
#include <iostream>
#include <algorithm>
#include <map>
#include <stdio.h>
#include <stdlib.h>
#include "../fastnetmon_types.h"
// It's very raw API implementation for connection tracking code. Due to HUGE amount of collisions it's very slow: ~1Mpps
// For performance it's very close to std::map but much times more buggy :)
// https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash2.cpp
// 64-bit hash for 64-bit platforms
#define BIG_CONSTANT(x) (x##LLU)
uint64_t MurmurHash64A(const void* key, int len, uint64_t seed) {
const uint64_t m = BIG_CONSTANT(0xc6a4a7935bd1e995);
const int r = 47;
uint64_t h = seed ^ (len * m);
const uint64_t* data = (const uint64_t*)key;
const uint64_t* end = data + (len / 8);
while (data != end) {
uint64_t k = *data++;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
}
const unsigned char* data2 = (const unsigned char*)data;
switch (len & 7) {
case 7:
h ^= uint64_t(data2[6]) << 48;
case 6:
h ^= uint64_t(data2[5]) << 40;
case 5:
h ^= uint64_t(data2[4]) << 32;
case 4:
h ^= uint64_t(data2[3]) << 24;
case 3:
h ^= uint64_t(data2[2]) << 16;
case 2:
h ^= uint64_t(data2[1]) << 8;
case 1:
h ^= uint64_t(data2[0]);
h *= m;
};
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}
class conntrack_hash_struct_for_simple_packet_t {
public:
uint32_t src_ip;
uint32_t dst_ip;
uint16_t source_port;
uint16_t destination_port;
unsigned int protocol;
bool operator==(const conntrack_hash_struct_for_simple_packet_t& rhs) {
// TODO: not so smart, we should fix this!
return memcmp(this, &rhs, sizeof(conntrack_hash_struct_for_simple_packet_t)) == 0;
}
};
// Extract only important for us fields from main simple_packet structure
bool convert_simple_packet_toconntrack_hash_struct(simple_packet& packet, conntrack_hash_struct_for_simple_packet_t& conntrack_struct) {
conntrack_struct.src_ip = packet.src_ip;
conntrack_struct.dst_ip = packet.dst_ip;
conntrack_struct.protocol = packet.protocol;
conntrack_struct.source_port = packet.source_port;
conntrack_struct.destination_port = packet.destination_port;
}
// Class prototype for connection tracking
typedef std::vector< conntrack_hash_struct_for_simple_packet_t > vector_of_connetrack_structs_t;
class connection_tracking_fast_storage_t {
public:
connection_tracking_fast_storage_t(unsigned int structure_size) {
murmur_seed = 13;
max_vector_size = 0;
number_of_buckets = structure_size;
buckets_storage.reserve(structure_size);
}
uint64_t get_bucket_number(conntrack_hash_struct_for_simple_packet_t& element) {
uint64_t conntrack_hash = MurmurHash64A(&element, sizeof(conntrack_hash_struct_for_simple_packet_t), murmur_seed);
return conntrack_hash % number_of_buckets;
}
bool lookup(conntrack_hash_struct_for_simple_packet_t* element) {
uint64_t bucket_number = get_bucket_number(*element);
vector_of_connetrack_structs_t* vector_pointer = &buckets_storage[bucket_number];
unsigned int vector_size = vector_pointer->size();
if (vector_size > max_vector_size) {
max_vector_size = vector_size;
if (max_vector_size > 100) {
printf("We got %u collisions for key %llu\n", max_vector_size, bucket_number);
}
}
if (vector_size == 0) {
return false;
}
vector_of_connetrack_structs_t::iterator itr = std::find(vector_pointer->begin(), vector_pointer->end(), *element);
if (itr == vector_pointer->end()) {
return false;
}
return true;
}
bool insert(conntrack_hash_struct_for_simple_packet_t element) {
uint64_t bucket_number = get_bucket_number(element);
buckets_storage[bucket_number].push_back(element);
}
public:
unsigned int number_of_buckets;
std::vector<vector_of_connetrack_structs_t> buckets_storage;
unsigned int murmur_seed;
// conntrack_hash_struct_for_simple_packet_t conntrack_structure;
unsigned int max_vector_size;
};
connection_tracking_fast_storage_t my_conntrack_storage(32000);
int main() {
// fake data
char data[1500];
simple_packet current_packet;
// parse_raw_packet_to_simple_packet((u_char*)data, length, current_packet);
conntrack_hash_struct_for_simple_packet_t conntrack_structure;
convert_simple_packet_toconntrack_hash_struct(current_packet, conntrack_structure);
if (my_conntrack_storage.lookup(&conntrack_structure)) {
//printf("Already exists\n");
// found it
} else {
//printf("New\n");
my_conntrack_storage.insert(conntrack_structure);
}
}

View File

@ -6,16 +6,30 @@
#include <string.h>
#include <unistd.h>
#include <map>
#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <string>
#include "../../fastnetmon_pcap_format.h"
#include "../../fastnetmon_types.h"
#include "../../fastnetmon_packet_parser.h"
#define DEBUG 1
#include "libndpi/ndpi_api.h"
// For correct compilation with g++
extern "C" {
#ifdef __cplusplus
// extern "C" {
#endif
u_int32_t size_flow_struct = 0;
u_int32_t size_id_struct = 0;
void pcap_parse_packet(const char* flow_type, char* buffer, uint32_t len);
void debug_printf(u_int32_t protocol, void *id_struct, ndpi_log_level_t log_level, const char *format, ...) {
va_list va_ap;
@ -67,8 +81,8 @@ bool init_ndpi() {
ndpi_set_protocol_detection_bitmask2(my_ndpi_struct, &all);
// allocate memory for id and flow tracking
uint32_t size_id_struct = ndpi_detection_get_sizeof_ndpi_id_struct();
uint32_t size_flow_struct = ndpi_detection_get_sizeof_ndpi_flow_struct();
size_id_struct = ndpi_detection_get_sizeof_ndpi_id_struct();
size_flow_struct = ndpi_detection_get_sizeof_ndpi_flow_struct();
// Load custom protocols
// ndpi_load_protocols_file(ndpi_thread_info[thread_id].ndpi_struct, _protoFilePath);
@ -208,11 +222,14 @@ class conntrack_hash_struct_for_simple_packet_t {
uint16_t destination_port;
unsigned int protocol;
bool operator==(const conntrack_hash_struct_for_simple_packet_t& rhs) const {
return memcmp(this, &rhs, sizeof(conntrack_hash_struct_for_simple_packet_t)) == 0;
}
};
// Copy and paste from netmap module
bool parse_raw_packet_to_simple_packet(u_char* buffer, int len, simple_packet& packet) {
inline bool parse_raw_packet_to_simple_packet(u_char* buffer, int len, simple_packet& packet) {
struct pfring_pkthdr packet_header;
memset(&packet_header, 0, sizeof(packet_header));
@ -281,7 +298,17 @@ bool convert_simple_packet_toconntrack_hash_struct(simple_packet& packet, conntr
conntrack_struct.destination_port = packet.destination_port;
}
typedef std::map<uint64_t, unsigned int> my_connection_tracking_storage_t;
namespace std {
template<>
struct hash<conntrack_hash_struct_for_simple_packet_t> {
size_t operator()(const conntrack_hash_struct_for_simple_packet_t& x) const {
return std::hash<unsigned int>()(x.src_ip);
}
};
}
typedef std::unordered_map<conntrack_hash_struct_for_simple_packet_t, unsigned int> my_connection_tracking_storage_t;
my_connection_tracking_storage_t my_connection_tracking_storage;
void firehose_packet(const char *pciaddr, char *data, int length) {
@ -293,18 +320,18 @@ void firehose_packet(const char *pciaddr, char *data, int length) {
conntrack_hash_struct_for_simple_packet_t conntrack_structure;
convert_simple_packet_toconntrack_hash_struct(current_packet, conntrack_structure);
unsigned int seed = 13;
uint64_t conntrack_hash = MurmurHash64A(&conntrack_structure, sizeof(conntrack_structure), seed);
//unsigned int seed = 13;
//uint64_t conntrack_hash = MurmurHash64A(&conntrack_structure, sizeof(conntrack_structure), seed);
// printf("Hash: %llu", conntrack_hash);
my_connection_tracking_storage_t::iterator itr = my_connection_tracking_storage.find(conntrack_hash);
my_connection_tracking_storage_t::iterator itr = my_connection_tracking_storage.find(conntrack_structure);
if (itr == my_connection_tracking_storage.end()) {
my_connection_tracking_storage[ conntrack_hash ] = 123;
printf("Initiate new connection\n");
my_connection_tracking_storage[ conntrack_structure ] = 123;
//printf("Initiate new connection\n");
} else {
printf("Found this connection\n");
//printf("Found this connection\n");
}
/*
@ -336,4 +363,108 @@ void firehose_packet(const char *pciaddr, char *data, int length) {
//printf("Got packet with %d bytes.\n", length);
}
#ifdef __cplusplus
// }
#endif
struct ndpi_id_struct *src = NULL;
struct ndpi_id_struct *dst = NULL;
struct ndpi_flow_struct *flow = NULL;
void pcap_parse_packet(char* buffer, uint32_t len) {
struct pfring_pkthdr packet_header;
memset(&packet_header, 0, sizeof(packet_header));
packet_header.len = len;
packet_header.caplen = len;
// We do not calculate timestamps because timestamping is very CPU intensive operation:
// https://github.com/ntop/PF_RING/issues/9
u_int8_t timestamp = 0;
u_int8_t add_hash = 0;
fastnetmon_parse_pkt((u_char*)buffer, &packet_header, 4, timestamp, add_hash);
// So, we will init nDPI flow here
if (flow == NULL) {
printf ("Allocate buffers\n");
src = (struct ndpi_id_struct*)malloc(size_id_struct);
memset(src, 0, size_id_struct);
dst = (struct ndpi_id_struct*)malloc(size_id_struct);
memset(dst, 0, size_id_struct);
flow = (struct ndpi_flow_struct *)malloc(size_flow_struct);
memset(flow, 0, size_flow_struct);
/*
struct ndpi_flow *newflow = (struct ndpi_flow*)malloc(sizeof(struct ndpi_flow));
memset(newflow, 0, sizeof(struct ndpi_flow));
newflow->protocol = packet_header.extended_hdr.parsed_pkt.l3_proto;
newflow->vlan_id = packet_header.extended_hdr.parsed_pkt.vlan_id;
uint32_t ip_src = packet_header.extended_hdr.parsed_pkt.ip_src.v4;
uint32_t ip_dst = packet_header.extended_hdr.parsed_pkt.ip_dst.v4;
uint16_t src_port = packet_header.extended_hdr.parsed_pkt.l4_src_port;
uint16_t dst_port = packet_header.extended_hdr.parsed_pkt.l4_dst_port;
if (ip_src < ip_dst) {
newflow->lower_ip = ip_src
newflow->upper_ip = ip_dst;
newflow->lower_port = src_port;
newflow->upper_port = dst_port;
} else {
newflow->lower_ip = ip_dst;
newflow->upper_ip = ip_src;
newflow->lower_port = dst_port;
newflow->upper_port = src_port;
}
newflow->src_id = malloc(size_id_struct);
memset(newflow->src_id, 0, size_id_struct);
newflow->dst_id = malloc(size_id_struct);
memset(newflow->dst_id, 0, size_id_struct);
*src = newflow->src_id, *dst = newflow->dst_id;
flow = newflow;
*/
} else {
printf("We process only single packet\n");
exit(0);
return;
}
uint32_t current_tickt = 0 ;
uint8_t* iph = (uint8_t*)(&buffer[packet_header.extended_hdr.parsed_pkt.offset.l3_offset]);
struct ndpi_iphdr* ndpi_ip_header = (struct ndpi_iphdr*)iph;
printf("Protocol: %d\n", ndpi_ip_header->protocol);
unsigned int ipsize = packet_header.len;
ndpi_protocol detected_protocol = ndpi_detection_process_packet(my_ndpi_struct, flow, iph, ipsize, current_tickt, src, dst);
if (detected_protocol.protocol != NDPI_PROTOCOL_UNKNOWN) {
printf("Can't detect protocol\n");
return;
} else {
printf("Protocol detected %d\n", detected_protocol.protocol);
}
}
int main() {
init_ndpi();
const char* path = "/root/ssdp_udp_attack_to_5.101.117.174.pcap";
pcap_reader(path, pcap_parse_packet);
}