Skip to content

Commit

Permalink
[IMP] Reorganizing the code.
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniele De Sensi committed Oct 11, 2018
1 parent 5ec3672 commit cd965d1
Show file tree
Hide file tree
Showing 63 changed files with 2,112 additions and 1,730 deletions.
14 changes: 10 additions & 4 deletions CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.5.1)
project(peafowl)
project(peafowl VERSION 1.0.0)
set (CMAKE_BUILD_TYPE Release)
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_C_STANDARD 11)
Expand All @@ -18,6 +18,8 @@ option (ENABLE_DOCS "Enables documentation generation" OFF)

add_compile_options(-Wall -finline-functions -O3)

find_package(PCAP)

# This must be the first thing done, since COVERAGE_COMPILER_FLAGS must be used by all the targets
###########
# codecov #
Expand Down Expand Up @@ -48,8 +50,12 @@ endif (ENABLE_CPPCHECK)
# Testing #
###########
if (ENABLE_TESTS)
enable_testing()
add_subdirectory(test)
if (NOT PCAP_FOUND)
message(FATAL_ERROR "libpcap needs to be installed to run tests")
else()
enable_testing()
add_subdirectory(test)
endif (NOT PCAP_FOUND)
endif (ENABLE_TESTS)

###########
Expand Down Expand Up @@ -93,4 +99,4 @@ if (ENABLE_DOCS)
else (DOXYGEN_FOUND)
message(WARNING "Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
endif (ENABLE_DOCS)
endif (ENABLE_DOCS)
54 changes: 14 additions & 40 deletions README.md
Expand Up @@ -31,16 +31,7 @@ To correctly identify the protocol also when its data is split among multiple IP
and to avoid the possibility of evasion attacks, if required, the framework can perform IP defragmentation and
TCP stream reassembly.

Peafowl also provide the possibility to exploit the parallelism of current multicore machines, splitting the
processing load among the available cores. This feature is particularly useful when some complex processing
is required on the content of the packets (e.g. complex pattern matching, audio/video processing, etc...).
This possibility have been implemented by using [FastFlow](http://calvados.di.unipi.it/dokuwiki/doku.php?id=ffnamespace:about),
a parallel programming framework for multicore platforms based upon non-blocking lock-free/fence-free
synchronization mechanisms.


**If you use Peafowl for scientific purposes, please cite our paper:**

*"Deep Packet Inspection on Commodity Hardware using FastFlow"*, M. Danelutto, L. Deri, D. De Sensi, M. Torquati


Expand Down Expand Up @@ -165,10 +156,7 @@ linking lib/libdpi.a.

The API is based on 3 main calls:

+ ```pfwl_init_stateful(SIZE_IPv4_FLOW_TABLE, SIZE_IPv6_FLOW_TABLE, MAX_IPv4_ACTIVE_FLOWS, MAX_IPv6_ACTIVE_FLOWS)```:
used to initialize the state of the framework. It requires the size of the tables that the framework will use
and the maximum number of flows that the framework should manage. When this number of flows is reached, the
framework will add no other flows to the table. This call returns an handle to the framework, which will
+ ```pfwl_init()```: used to initialize the state of the framework. This call returns an handle to the framework, which will
be required as parameter for most of the framework calls;

+ ```pfwl_get_protocol(state, packet, length, timestamp)```:
Expand All @@ -184,10 +172,8 @@ defragmentation please refer to the documentation in ["src/peafowl.h"](src/peafo

Multicore version
------------------------------------------------------------------------------------------------------------------
You can take advantage of the multicore version by including the ["src/peafowl_mc.h"](src/peafowl_mc.h) header and by
linking lib/libmcdpi.a. Since the user manual for the multicore version of Peafowl is not yet available,
you can look at [this](demo/protocol_identification_mc/protocol_identification.cpp) simple demo file.
If you need more informations about how to use it, contact me at d.desensi.software@gmail.com or read the [Thesis](Thesis.pdf).
A multicore version of Peafowl was available on pre 1.0.0 version of Peafowl. It is not available at the moment
but will be back in Peafowl v1.1.0

Demo application
---------------------------------------------------------------------------------------------------------------------
Expand All @@ -201,8 +187,7 @@ This application can be easily modified to read packet from the network instead
*
* Given a .pcap file, it identifies the protocol of all the packets contained in it.
*
* Created on: 12/11/2012
* Author: Daniele De Sensi
* Author: Daniele De Sensi (d.desensi.software@gmail.com)
*/

#include <peafowl.h>
Expand All @@ -226,8 +211,7 @@ int main(int argc, char** argv){
}
char* pcap_filename=argv[1];
char errbuf[PCAP_ERRBUF_SIZE];

pfwl_library_state_t* state = pfwl_init();

pcap_t *handle = pcap_open_offline(pcap_filename, errbuf);

if(handle==NULL){
Expand All @@ -243,11 +227,11 @@ int main(int argc, char** argv){
memset(protocols, 0, sizeof(protocols));
u_int32_t unknown=0;

pfwl_library_state_t* state = pfwl_init();
while((packet=pcap_next(handle, &header))!=NULL){
r = pfwl_dissect_from_L2(state, packet, header.caplen, time(NULL), pcap_datalink(handle));

if(r.protocol.l4prot == IPPROTO_TCP ||
r.protocol.l4prot == IPPROTO_UDP){
if(r.protocol.l4prot == IPPROTO_TCP || r.protocol.l4prot == IPPROTO_UDP){
if(r.protocol.l7prot < PFWL_NUM_PROTOCOLS){
++protocols[r.protocol.l7prot];
}else{
Expand All @@ -258,7 +242,6 @@ int main(int argc, char** argv){
}

}

pfwl_terminate(state);

if (unknown > 0) printf("Unknown packets: %"PRIu32"\n", unknown);
Expand Down Expand Up @@ -311,14 +294,12 @@ enum protocols{
2) Create a new inspector, by implementing a C function with the following signature and semantic:

```C
uint8_t check_telnet(pfwl_library_state_t* state, // The state of the library
pfwl_pkt_infos_t* pkt, // The parsed information about the current packet
const unsigned char* app_data, // A pointer to the beginning of the
// application (layer 7) data
uint32_t data_length, // The lenght of the application data
pfwl_tracking_informations_t* t // Information about the current state of the
// connection to which the packet belongs to
);
uint8_t check_telnet(pfwl_state_t* state, ///< The state of the library.
const unsigned char* app_data, ///< A pointer to the beginning of the
///< application (layer 7) data.
uint32_t data_length, ///< The lenght of the application data.
pfwl_dissection_info_t* dissection_info, ///< Dissection data collected up to L4.
pfwl_tracking_informations_t* tracking_info); ///< Information about the flow of the packet.
```
The function declaration must be put in ```include/peafowl/inspectors/inspectors.h```, while its definition can be put
in a new source file in inspectors folder (e.g. ```src/inspectors/telnet.c```).
Expand Down Expand Up @@ -541,20 +522,13 @@ their own flow informations also the informations needed by the framework to ide

A more detailed description can be found in the thesis which lead to the development of this framework: [Thesis.pdf](Thesis.pdf)

Advanced usage
================================================================================================================
Details on how to add new protocols and on different configuration parameters can be found in [README_ADVANCED.md](README_ADVANCED.md)

Export to Prometheus DB
================================================================================================================
Dependencies:
- libcurl: e.g. apt-get install libcurl4-openssl-dev

Configuration
================================================================================================================
Default parameters are suited for many cases. Different configuration parameters can be modified in "config.h"
file. The most important are the following:

+ PFWL_HTTP_MAX_HEADERS: The maximum number of headers that can be extracted for a single HTTP packet [default = 256].
+ PFWL_DEFAULT_FLOW_TABLE_AVG_BUCKET_SIZE: Default value for the average bucket size of the flow table.
+ PFWL_DEFAULT_EXPECTED_FLOWS: Default value for the expected flows
+ PFWL_CACHE_LINE_SIZE: Size of L1 cache line
Expand Down
2 changes: 1 addition & 1 deletion cmake/clang_format.cmake
@@ -1,7 +1,7 @@
## get all project files
find_package(ClangFormat)

if(!CLANG_FORMAT_FOUND)
if(NOT CLANG_FORMAT_FOUND)
message("clang-format not found. Please install it to run 'make clangformat'")
endif()

Expand Down
74 changes: 74 additions & 0 deletions cmake/modules/FindPCAP.cmake
@@ -0,0 +1,74 @@
# - Try to find libpcap include dirs and libraries
#
# Usage of this module as follows:
#
# find_package(PCAP)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# PCAP_ROOT_DIR Set this variable to the root installation of
# libpcap if the module has problems finding the
# proper installation path.
#
# Variables defined by this module:
#
# PCAP_FOUND System has libpcap, include and library dirs found
# PCAP_INCLUDE_DIR The libpcap include directories.
# PCAP_LIBRARY The libpcap library (possibly includes a thread
# library e.g. required by pf_ring's libpcap)
# HAVE_PF_RING If a found version of libpcap supports PF_RING

find_path(PCAP_ROOT_DIR
NAMES include/pcap.h
)

find_path(PCAP_INCLUDE_DIR
NAMES pcap.h
HINTS ${PCAP_ROOT_DIR}/include
)

find_library(PCAP_LIBRARY
NAMES pcap
HINTS ${PCAP_ROOT_DIR}/lib
)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PCAP DEFAULT_MSG
PCAP_LIBRARY
PCAP_INCLUDE_DIR
)

include(CheckCSourceCompiles)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
check_c_source_compiles("int main() { return 0; }" PCAP_LINKS_SOLO)
set(CMAKE_REQUIRED_LIBRARIES)

# check if linking against libpcap also needs to link against a thread library
if (NOT PCAP_LINKS_SOLO)
find_package(Threads)
if (THREADS_FOUND)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
check_c_source_compiles("int main() { return 0; }" PCAP_NEEDS_THREADS)
set(CMAKE_REQUIRED_LIBRARIES)
endif ()
if (THREADS_FOUND AND PCAP_NEEDS_THREADS)
set(_tmp ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
list(REMOVE_DUPLICATES _tmp)
set(PCAP_LIBRARY ${_tmp}
CACHE STRING "Libraries needed to link against libpcap" FORCE)
else ()
message(FATAL_ERROR "Couldn't determine how to link against libpcap")
endif ()
endif ()

include(CheckFunctionExists)
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
check_function_exists(pcap_get_pfring_id HAVE_PF_RING)
set(CMAKE_REQUIRED_LIBRARIES)

mark_as_advanced(
PCAP_ROOT_DIR
PCAP_INCLUDE_DIR
PCAP_LIBRARY
)
16 changes: 10 additions & 6 deletions demo/CMakeLists.txt
@@ -1,10 +1,14 @@
include_directories(${CMAKE_SOURCE_DIR}/include)
#add_definitions(-g -O0)
add_subdirectory(protocol_identification)
add_subdirectory(dump_jpeg)
add_subdirectory(sip_extraction)
add_subdirectory(dns_extraction)
add_subdirectory(http_pattern_matching)
if (PCAP_FOUND)
link_directories(${PCAP_LIBRARY})
include_directories($PCAP_INCLUDE_DIR)
add_subdirectory(protocol_identification)
add_subdirectory(dump_jpeg)
add_subdirectory(sip_extraction)
add_subdirectory(dns_extraction)
add_subdirectory(http_pattern_matching)
endif(PCAP_FOUND)

if (ENABLE_PARALLEL)
add_subdirectory(protocol_identification_mc)
endif (ENABLE_PARALLEL)
Expand Down
29 changes: 12 additions & 17 deletions demo/dns_extraction/dns_extraction.c
Expand Up @@ -70,27 +70,22 @@ int main(int argc, char** argv){
/* pfwl_protocol_field_add(state, PFWL_FIELDS_DNS_NS_IP_1); */
// Authoritative Server Name field
/* pfwl_protocol_field_add(state, PFWL_FIELDS_DNS_AUTH_SRV); */
pfwl_protocol_l2_t dlt = pfwl_convert_pcap_dlt(pcap_datalink(handle));

while((packet = pcap_next(handle, &header)) != NULL){
pfwl_dissection_info_t r = pfwl_dissect_from_L2(state, packet, header.caplen, time(NULL), pcap_datalink(handle));

if(r.protocol_l7 == PFWL_PROTOCOL_DNS &&
r.protocol_fields[PFWL_FIELDS_DNS_NAME_SRV].str.len){
const char* field_value = r.protocol_fields[PFWL_FIELDS_DNS_NAME_SRV].str.s;
size_t field_len = r.protocol_fields[PFWL_FIELDS_SIP_REQUEST_URI].str.len;
printf("Name Server detected: %.*s\n", (int) field_len, field_value);
pfwl_dissection_info_t r = pfwl_dissect_from_L2(state, packet, header.caplen, time(NULL), dlt);
pfwl_string_t field;
if(r.l7.protocol == PFWL_PROTOCOL_DNS &&
!pfwl_field_string_get(r.l7.protocol_fields, PFWL_FIELDS_DNS_NAME_SRV, &field)){
printf("Name Server detected: %.*s\n", (int) field.length, field.value);
}
if(r.protocol_l7 == PFWL_PROTOCOL_DNS &&
r.protocol_fields[PFWL_FIELDS_DNS_NS_IP_1].str.len){
const char* field_value = r.protocol_fields[PFWL_FIELDS_DNS_NS_IP_1].str.s;
size_t field_len = r.protocol_fields[PFWL_FIELDS_DNS_NS_IP_1].str.len;
printf("IP address of Name Server: %.*s\n", (int) field_len, field_value);
if(r.l7.protocol == PFWL_PROTOCOL_DNS &&
!pfwl_field_string_get(r.l7.protocol_fields, PFWL_FIELDS_DNS_NS_IP_1, &field)){
printf("IP address of Name Server: %.*s\n", (int) field.length, field.value);
}
if(r.protocol_l7 == PFWL_PROTOCOL_DNS &&
r.protocol_fields[PFWL_FIELDS_DNS_AUTH_SRV].str.len){
const char* field_value = r.protocol_fields[PFWL_FIELDS_DNS_AUTH_SRV].str.s;
size_t field_len = r.protocol_fields[PFWL_FIELDS_DNS_AUTH_SRV].str.len;
printf("Authoritative Server detected: %.*s\n", (int) field_len, field_value);
if(r.l7.protocol == PFWL_PROTOCOL_DNS &&
!pfwl_field_string_get(r.l7.protocol_fields, PFWL_FIELDS_DNS_AUTH_SRV, &field)){
printf("Authoritative Server detected: %.*s\n", (int) field.length, field.value);
}
}
return 0;
Expand Down

0 comments on commit cd965d1

Please sign in to comment.