summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt9
-rw-r--r--dependencies/nDPIsrvd.h55
-rw-r--r--examples/c-captured/c-captured.c116
-rw-r--r--examples/c-json-stdout/c-json-stdout.c3
-rw-r--r--nDPId-test.c7
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();
}