diff options
-rw-r--r-- | CMakeLists.txt | 9 | ||||
-rw-r--r-- | dependencies/nDPIsrvd.h | 55 | ||||
-rw-r--r-- | examples/c-captured/c-captured.c | 116 | ||||
-rw-r--r-- | examples/c-json-stdout/c-json-stdout.c | 3 | ||||
-rw-r--r-- | nDPId-test.c | 7 |
5 files changed, 172 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 457e81b15..ff0088c6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ if(GIT_VERSION STREQUAL "" OR NOT IS_DIRECTORY "${CMAKE_SOURCE_DIR}/.git") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra") -set(NDPID_DEFS -DJSMN_STATIC=1 -DJSMN_STRICT=1) +set(NDPID_DEFS -DJSMN_STATIC=1 -DJSMN_STRICT=1 -DJSMN_PARENT_LINKS=1) if(ENABLE_MEMORY_PROFILING) add_definitions("-DENABLE_MEMORY_PROFILING=1" "-Duthash_malloc=nDPIsrvd_uthash_malloc" @@ -138,6 +138,7 @@ if(NOT STATIC_LIBNDPI_INSTALLDIR STREQUAL "" OR BUILD_NDPI OR NDPI_NO_PKGCONFIG) endif() if(NOT STATIC_LIBNDPI_INSTALLDIR STREQUAL "" OR BUILD_NDPI) + add_definitions("-DLIBNDPI_STATIC=1") set(STATIC_LIBNDPI_INC "${STATIC_LIBNDPI_INSTALLDIR}/include/ndpi") set(STATIC_LIBNDPI_LIB "${STATIC_LIBNDPI_INSTALLDIR}/lib/libndpi.a") else() @@ -197,13 +198,17 @@ if(BUILD_EXAMPLES) add_executable(nDPIsrvd-captured examples/c-captured/c-captured.c utils.c) target_compile_definitions(nDPIsrvd-captured PRIVATE ${NDPID_DEFS}) target_include_directories(nDPIsrvd-captured PRIVATE + "${STATIC_LIBNDPI_INC}" "${NDPI_INCLUDEDIR}" "${NDPI_INCLUDEDIR}/ndpi" "${CMAKE_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}/dependencies" "${CMAKE_SOURCE_DIR}/dependencies/jsmn" "${CMAKE_SOURCE_DIR}/dependencies/uthash/src") - target_link_libraries(nDPIsrvd-captured "${PCAP_LIBRARY}") + target_link_libraries(nDPIsrvd-captured "${pkgcfg_lib_NDPI_ndpi}" + "${pkgcfg_lib_PCRE_pcre}" "${pkgcfg_lib_MAXMINDDB_maxminddb}" + "${GCRYPT_LIBRARY}" "${GCRYPT_ERROR_LIBRARY}" "${PCAP_LIBRARY}") add_executable(nDPIsrvd-json-dump examples/c-json-stdout/c-json-stdout.c) + target_compile_definitions(nDPIsrvd-json-dump PRIVATE ${NDPID_DEFS}) target_include_directories(nDPIsrvd-json-dump PRIVATE "${CMAKE_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}/dependencies/jsmn") diff --git a/dependencies/nDPIsrvd.h b/dependencies/nDPIsrvd.h index 764dd204a..51dc4750f 100644 --- a/dependencies/nDPIsrvd.h +++ b/dependencies/nDPIsrvd.h @@ -28,6 +28,7 @@ token_get_value(sock, (char const *)key, nDPIsrvd_STRLEN_SZ(key), value_length) #define TOKEN_VALUE_EQUALS_SZ(token, string_to_check) \ token_value_equals(token, string_to_check, nDPIsrvd_STRLEN_SZ(string_to_check)) +#define TOKEN_KEY_TO_ULL(token, key) token_key_to_ull(token, key) #define TOKEN_VALUE_TO_ULL(token, value) token_value_to_ull(token, value) #define FIRST_ENUM_VALUE 1 @@ -105,10 +106,11 @@ struct nDPIsrvd_flow struct nDPIsrvd_json_token { char key[nDPIsrvd_JSON_KEY_STRLEN]; - int key_length; UT_hash_handle hh; char const * value; + int key_length; int value_length; + int token_index; }; struct nDPIsrvd_socket; @@ -554,6 +556,38 @@ static inline struct nDPIsrvd_json_token const * token_get(struct nDPIsrvd_socke return NULL; } +static inline struct nDPIsrvd_json_token const * +token_get_next_child(struct nDPIsrvd_socket const * const sock, + struct nDPIsrvd_json_token const * const start, + int * next_index) +{ + struct nDPIsrvd_json_token const * result = NULL; + + if (start == NULL || *next_index >= sock->jsmn.tokens_found) + { + return NULL; + } + if (*next_index < 0) + { + *next_index = start->token_index; + } + + for (int i = *next_index + 2; i < sock->jsmn.tokens_found; i += 2) + { + if (sock->jsmn.tokens[i].parent != start->token_index + 1 || + sock->jsmn.tokens[i].type != JSMN_STRING) + { + continue; + } + + result = token_get(sock, jsmn_token_get(sock, i), jsmn_token_size(sock, i)); + *next_index = i; + break; + } + + return result; +} + static inline char const * token_get_value(struct nDPIsrvd_socket const * const sock, char const * const key, size_t key_length, @@ -588,6 +622,7 @@ static inline enum nDPIsrvd_conversion_return str_value_to_ull(char const * cons nDPIsrvd_ull_ptr const value) { char * endptr = NULL; + errno = 0; *value = strtoull(value_as_string, &endptr, 10); if (value_as_string == endptr) @@ -598,10 +633,25 @@ static inline enum nDPIsrvd_conversion_return str_value_to_ull(char const * cons { return CONVERSION_RANGE_EXCEEDED; } + if (errno == EINVAL) + { + return CONVERSION_NOT_A_NUMBER; + } return CONVERSION_OK; } +static inline enum nDPIsrvd_conversion_return token_key_to_ull(struct nDPIsrvd_json_token const * const token, + nDPIsrvd_ull_ptr const key) +{ + if (token == NULL) + { + return CONVERISON_KEY_NOT_FOUND; + } + + return str_value_to_ull(token->key, key); +} + static inline enum nDPIsrvd_conversion_return token_value_to_ull(struct nDPIsrvd_json_token const * const token, nDPIsrvd_ull_ptr const value) { @@ -795,7 +845,8 @@ static inline enum nDPIsrvd_parse_return nDPIsrvd_parse_all(struct nDPIsrvd_sock { struct nDPIsrvd_json_token jt = {.value = jsmn_token_get(sock, current_token), .value_length = jsmn_token_size(sock, current_token), - .hh = {}}; + .hh = {}, + .token_index = current_token - 1}; if (key == NULL || key_length > nDPIsrvd_JSON_KEY_STRLEN || utarray_len(sock->json.tokens) == nDPIsrvd_MAX_JSON_TOKENS) diff --git a/examples/c-captured/c-captured.c b/examples/c-captured/c-captured.c index 76de75c3d..42da0677d 100644 --- a/examples/c-captured/c-captured.c +++ b/examples/c-captured/c-captured.c @@ -1,6 +1,8 @@ #include <arpa/inet.h> #include <errno.h> #include <linux/limits.h> +#include <ndpi_api.h> +#include <ndpi_typedefs.h> #include <netinet/ip_icmp.h> #include <netinet/tcp.h> #include <netinet/udp.h> @@ -62,7 +64,7 @@ static char * group = NULL; static char * datadir = NULL; static uint8_t process_guessed = 0; static uint8_t process_undetected = 0; -static uint8_t process_risky = 0; +static ndpi_risk process_risky = NDPI_NO_RISK; static uint8_t process_midstream = 0; static uint8_t ignore_empty_flows = 0; @@ -95,6 +97,35 @@ static void packet_data_dtor(void * elt) static const UT_icd packet_data_icd = {sizeof(struct packet_data), NULL, packet_data_copy, packet_data_dtor}; +static void set_ndpi_risk(ndpi_risk * const risk, nDPIsrvd_ull risk_to_add) +{ + if (risk_to_add == 0) + { + *risk = (ndpi_risk)-1; + } + else + { + *risk |= 1ull << --risk_to_add; + } +} + +static void unset_ndpi_risk(ndpi_risk * const risk, nDPIsrvd_ull risk_to_del) +{ + if (risk_to_del == 0) + { + *risk = 0; + } + else + { + *risk &= ~(1ull << --risk_to_del); + } +} + +static int has_ndpi_risk(ndpi_risk * const risk, nDPIsrvd_ull risk_to_check) +{ + return (*risk & (1ull << --risk_to_check)) != 0; +} + static char * generate_pcap_filename(struct nDPIsrvd_flow const * const flow, struct flow_user_data const * const flow_user, char * const dest, @@ -348,7 +379,8 @@ static enum nDPIsrvd_callback_return captured_json_callback(struct nDPIsrvd_sock if (flow_event_name != NULL) { - perror_ull(TOKEN_VALUE_TO_ULL(TOKEN_GET_SZ(sock, "flow_tot_l4_payload_len"), &flow_user->flow_tot_l4_payload_len), + perror_ull(TOKEN_VALUE_TO_ULL(TOKEN_GET_SZ(sock, "flow_tot_l4_payload_len"), + &flow_user->flow_tot_l4_payload_len), "flow_tot_l4_payload_len"); } @@ -378,11 +410,26 @@ static enum nDPIsrvd_callback_return captured_json_callback(struct nDPIsrvd_sock } else if (TOKEN_VALUE_EQUALS_SZ(flow_event_name, "detected") != 0) { + struct nDPIsrvd_json_token const * const flow_risk = TOKEN_GET_SZ(sock, "flow_risk"); + struct nDPIsrvd_json_token const * current = NULL; + int next_child_index = -1; + flow_user->detected = 1; flow_user->detection_finished = 1; - if (TOKEN_GET_SZ(sock, "flow_risk") != NULL) + + if (flow_risk != NULL) { - flow_user->risky = 1; + while ((current = token_get_next_child(sock, flow_risk, &next_child_index)) != NULL) + { + nDPIsrvd_ull numeric_risk_value = 0ull; + + if (TOKEN_KEY_TO_ULL(current, &numeric_risk_value) == CONVERSION_OK && + numeric_risk_value < NDPI_MAX_RISK && + has_ndpi_risk(&process_risky, numeric_risk_value) != 0) + { + flow_user->risky = 1; + } + } } } @@ -453,13 +500,12 @@ static void captured_flow_end_callback(struct nDPIsrvd_socket * const sock, stru } } -static int parse_options(int argc, char ** argv) +static void print_usage(char const * const arg0) { - int opt; - static char const usage[] = "Usage: %s " - "[-d] [-p pidfile] [-s host] [-r rotate-every-n-seconds] [-u user] [-g group] [-D dir] [-G] [-U] [-R] [-M]\n\n" + "[-d] [-p pidfile] [-s host] [-r rotate-every-n-seconds]\n" + "\t \t[-u user] [-g group] [-D dir] [-G] [-U] [-R risk] [-M]\n\n" "\t-d\tForking into background after initialization.\n" "\t-p\tWrite the daemon PID to the given file path.\n" "\t-s\tDestination where nDPIsrvd is listening on.\n" @@ -470,11 +516,33 @@ static int parse_options(int argc, char ** argv) "\t-D\tDatadir - Where to store PCAP files.\n" "\t-G\tGuessed - Dump guessed flows to a PCAP file.\n" "\t-U\tUndetected - Dump undetected flows to a PCAP file.\n" - "\t-R\tRisky - Dump risky flows to a PCAP file.\n" + "\t-R\tRisky - Dump risky flows to a PCAP file. See additional help below.\n" "\t-M\tMidstream - Dump midstream flows to a PCAP file.\n" - "\t-E\tEmpty - Ignore flows w/o any layer 4 payload\n"; + "\t-E\tEmpty - Ignore flows w/o any layer 4 payload\n\n" + "\tPossible options for `-R' (can be specified multiple times, processed from left to right, ~ disables a risk):\n" + "\t \tExample: -R0 -R~15 would enable all risks except risk with id 15\n"; + + fprintf(stderr, usage, arg0); +#ifndef LIBNDPI_STATIC + fprintf(stderr, "\t\t%d - %s\n", 0, "Capture all risks"); +#else + fprintf(stderr, "\t\t%d - %s\n\t\t", 0, "Capture all risks"); +#endif + for (int risk = NDPI_NO_RISK + 1; risk < NDPI_MAX_RISK; ++risk) + { +#ifndef LIBNDPI_STATIC + fprintf(stderr, "\t\t%d - %s%s", risk, ndpi_risk2str(risk), (risk == NDPI_MAX_RISK - 1 ? "\n\n" : "\n")); +#else + fprintf(stderr, "%d%s", risk, (risk == NDPI_MAX_RISK - 1 ? "\n" : ",")); +#endif + } +} + +static int parse_options(int argc, char ** argv) +{ + int opt; - while ((opt = getopt(argc, argv, "hdp:s:r:u:g:D:GURME")) != -1) + while ((opt = getopt(argc, argv, "hdp:s:r:u:g:D:GUR:ME")) != -1) { switch (opt) { @@ -493,6 +561,7 @@ static int parse_options(int argc, char ** argv) if (perror_ull(str_value_to_ull(optarg, &pcap_filename_rotation), "pcap_filename_rotation") != CONVERSION_OK) { + fprintf(stderr, "%s: Argument for `-r' is not a number: %s\n", argv[0], optarg); return 1; } break; @@ -515,8 +584,27 @@ static int parse_options(int argc, char ** argv) process_undetected = 1; break; case 'R': - process_risky = 1; + { + char * value = (optarg[0] == '~' ? optarg + 1 : optarg); + nDPIsrvd_ull risk; + if (perror_ull(str_value_to_ull(value, &risk), "process_risky") != CONVERSION_OK) + { + fprintf(stderr, "%s: Argument for `-R' is not a number: %s\n", argv[0], optarg); + return 1; + } + if (risk >= NDPI_MAX_RISK) + { + fprintf(stderr, "%s: Invalid risk set: %s\n", argv[0], optarg); + return 1; + } + if (optarg[0] == '~') + { + unset_ndpi_risk(&process_risky, risk); + } else { + set_ndpi_risk(&process_risky, risk); + } break; + } case 'M': process_midstream = 1; break; @@ -524,7 +612,7 @@ static int parse_options(int argc, char ** argv) ignore_empty_flows = 1; break; default: - fprintf(stderr, usage, argv[0]); + print_usage(argv[0]); return 1; } } @@ -554,7 +642,7 @@ static int parse_options(int argc, char ** argv) if (optind < argc) { fprintf(stderr, "Unexpected argument after options\n\n"); - fprintf(stderr, usage, argv[0]); + print_usage(argv[0]); return 1; } diff --git a/examples/c-json-stdout/c-json-stdout.c b/examples/c-json-stdout/c-json-stdout.c index 51df70bfa..508e45588 100644 --- a/examples/c-json-stdout/c-json-stdout.c +++ b/examples/c-json-stdout/c-json-stdout.c @@ -115,6 +115,9 @@ int main(void) { if (i % 2 == 1) { +#ifdef JSMN_PARENT_LINKS + printf("[%d][%d]", i, tokens[i].parent); +#endif printf("[%.*s : ", tokens[i].end - tokens[i].start, (char *)(buf + json_start) + tokens[i].start); } else diff --git a/nDPId-test.c b/nDPId-test.c index 13d28cf77..d8fb80d02 100644 --- a/nDPId-test.c +++ b/nDPId-test.c @@ -450,5 +450,12 @@ int main(int argc, char ** argv) ndpi_memory_free_count); } + if (ndpi_memory_alloc_bytes != ndpi_memory_free_bytes || ndpi_memory_alloc_count != ndpi_memory_free_count || + nDPId_return.total_active_flows != nDPId_return.total_idle_flows) + { + fprintf(stderr, "%s: %s\n", argv[0], "Memory / Flow leak detected."); + return 1; + } + return THREADS_RETURNED_ERROR(); } |