Skip to content

Commit 25dcaa3

Browse files
committed
Provide an explicit state for the flow classification process
Application should keep calling nDPI until flow state became `NDPI_STATE_CLASSIFIED`. The main loop in the application is simplified to something like: ``` res = ndpi_detection_process_packet(...); if(res->state == NDPI_STATE_CLASSIFIED) { /* Done: you can get finale classification and all metadata. nDPI doesn't need more packets for this flow */ } else { /* nDPI needs more packets for this flow. The provided classification is not final and more metadata might be extracted */ } ``` You can take a look at `ndpiReader` for a slightly more complex example. API changes: * remove the third parameter from `ndpi_detection_giveup()`. If you need to know if the classification flow has been guessed, you can access `flow->protocol_was_guessed` * remove `ndpi_extra_dissection_possible()` * change some prototypes from accepting `ndpi_protocol foo` to `ndpi_master_app_protocol bar`. The update is trivial: from `foo` to `foo.proto`
1 parent f293851 commit 25dcaa3

File tree

124 files changed

+517
-547
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+517
-547
lines changed

example/ndpiReader.c

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ void ndpiCheckHostStringMatch(char *testChar) {
460460
detected_protocol.proto.master_protocol = 0;
461461
detected_protocol.category = match.protocol_category;
462462

463-
ndpi_protocol2name(ndpi_str, detected_protocol, appBufStr,
463+
ndpi_protocol2name(ndpi_str, detected_protocol.proto, appBufStr,
464464
sizeof(appBufStr));
465465

466466
printf("Match Found for string [%s] -> P(%d) B(%d) C(%d) => %s %s %s\n",
@@ -544,7 +544,7 @@ static void ndpiCheckIPMatch(char *testChar) {
544544
memset(&detected_protocol, 0, sizeof(ndpi_protocol));
545545
detected_protocol.proto.app_protocol = ndpi_map_ndpi_id_to_user_proto_id(ndpi_str, ret);
546546

547-
ndpi_protocol2name(ndpi_str, detected_protocol, appBufStr,
547+
ndpi_protocol2name(ndpi_str, detected_protocol.proto, appBufStr,
548548
sizeof(appBufStr));
549549

550550
printf("Match Found for IP %s, port %d -> %s (%d)\n",
@@ -1761,11 +1761,11 @@ static void printFlow(u_int32_t id, struct ndpi_flow_info *flow, u_int16_t threa
17611761
);
17621762

17631763
fprintf(csv_fp, "%s|",
1764-
ndpi_protocol2id(flow->detected_protocol, buf, sizeof(buf)));
1764+
ndpi_protocol2id(flow->detected_protocol.proto, buf, sizeof(buf)));
17651765

17661766
fprintf(csv_fp, "%s|%s|%s|%s|",
17671767
ndpi_protocol2name(ndpi_thread_info[thread_id].workflow->ndpi_struct,
1768-
flow->detected_protocol, buf, sizeof(buf)),
1768+
flow->detected_protocol.proto, buf, sizeof(buf)),
17691769
ndpi_stack2str(ndpi_thread_info[thread_id].workflow->ndpi_struct,
17701770
&flow->detected_protocol.protocol_stack, buf2, sizeof(buf2)),
17711771
ndpi_get_proto_name(ndpi_thread_info[thread_id].workflow->ndpi_struct,
@@ -1904,7 +1904,7 @@ static void printFlow(u_int32_t id, struct ndpi_flow_info *flow, u_int16_t threa
19041904
flow->detected_protocol.proto.master_protocol,
19051905
flow->detected_protocol.proto.app_protocol,
19061906
ndpi_protocol2name(ndpi_thread_info[thread_id].workflow->ndpi_struct,
1907-
flow->detected_protocol, buf1, sizeof(buf1))
1907+
flow->detected_protocol.proto, buf1, sizeof(buf1))
19081908
);
19091909
}
19101910
}
@@ -1946,14 +1946,14 @@ static void printFlow(u_int32_t id, struct ndpi_flow_info *flow, u_int16_t threa
19461946

19471947
#ifdef NDPI_EXTENDED_SANITY_CHECKS
19481948
/* Be sure new stack logic is compatible with legacy code */
1949-
assert(ndpi_stack_get_upper_proto(&flow->detected_protocol.protocol_stack) == ndpi_get_upper_proto(flow->detected_protocol));
1950-
assert(ndpi_stack_get_lower_proto(&flow->detected_protocol.protocol_stack) == ndpi_get_lower_proto(flow->detected_protocol));
1949+
assert(ndpi_stack_get_upper_proto(&flow->detected_protocol.protocol_stack) == ndpi_get_upper_proto(flow->detected_protocol.proto));
1950+
assert(ndpi_stack_get_lower_proto(&flow->detected_protocol.protocol_stack) == ndpi_get_lower_proto(flow->detected_protocol.proto));
19511951
#endif
19521952

19531953
fprintf(out, "%s/%s][Stack: %s][IP: %u/%s]",
1954-
ndpi_protocol2id(flow->detected_protocol, buf, sizeof(buf)),
1954+
ndpi_protocol2id(flow->detected_protocol.proto, buf, sizeof(buf)),
19551955
ndpi_protocol2name(ndpi_thread_info[thread_id].workflow->ndpi_struct,
1956-
flow->detected_protocol, buf1, sizeof(buf1)),
1956+
flow->detected_protocol.proto, buf1, sizeof(buf1)),
19571957
ndpi_stack2str(ndpi_thread_info[thread_id].workflow->ndpi_struct,
19581958
&flow->detected_protocol.protocol_stack, buf2, sizeof(buf2)),
19591959
flow->detected_protocol.protocol_by_ip,
@@ -1987,7 +1987,7 @@ static void printFlow(u_int32_t id, struct ndpi_flow_info *flow, u_int16_t threa
19871987

19881988
fprintf(out, "[%s]",
19891989
ndpi_is_encrypted_proto(ndpi_thread_info[thread_id].workflow->ndpi_struct,
1990-
flow->detected_protocol) ? "Encrypted" : "ClearText");
1990+
flow->detected_protocol.proto) ? "Encrypted" : "ClearText");
19911991

19921992
fprintf(out, "[Confidence: %s]", ndpi_confidence_get_name(flow->confidence));
19931993

@@ -2026,7 +2026,7 @@ static void printFlow(u_int32_t id, struct ndpi_flow_info *flow, u_int16_t threa
20262026
(unsigned int)flow->detected_protocol.category);
20272027

20282028
breed = ndpi_get_proto_breed(ndpi_thread_info[thread_id].workflow->ndpi_struct,
2029-
ndpi_get_upper_proto(flow->detected_protocol));
2029+
ndpi_get_upper_proto(flow->detected_protocol.proto));
20302030
fprintf(out, "[Breed: %s]", ndpi_get_proto_breed_name(breed));
20312031

20322032
fprintf(out, "[%u pkts/%llu bytes ", flow->src2dst_packets, (long long unsigned int) flow->src2dst_bytes);
@@ -2552,14 +2552,13 @@ static void node_proto_guess_walker(const void *node, ndpi_VISIT which, int dept
25522552

25532553
if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */
25542554
if((!flow->detection_completed) && flow->ndpi_flow) {
2555-
u_int8_t proto_guessed;
25562555

25572556
malloc_size_stats = 1;
25582557
flow->detected_protocol = ndpi_detection_giveup(ndpi_thread_info[thread_id].workflow->ndpi_struct,
2559-
flow->ndpi_flow, &proto_guessed);
2558+
flow->ndpi_flow);
25602559
malloc_size_stats = 0;
25612560

2562-
if(proto_guessed) ndpi_thread_info[thread_id].workflow->stats.guessed_flow_protocols++;
2561+
if(flow->ndpi_flow->protocol_was_guessed) ndpi_thread_info[thread_id].workflow->stats.guessed_flow_protocols++;
25632562
}
25642563

25652564
process_ndpi_collected_info(ndpi_thread_info[thread_id].workflow, flow);
@@ -2957,7 +2956,7 @@ static void port_stats_walker(const void *node, ndpi_VISIT which, int depth, voi
29572956
/* get app level protocol */
29582957
if(flow->detected_protocol.proto.master_protocol) {
29592958
ndpi_protocol2name(ndpi_thread_info[thread_id].workflow->ndpi_struct,
2960-
flow->detected_protocol, proto, sizeof(proto));
2959+
flow->detected_protocol.proto, proto, sizeof(proto));
29612960
} else {
29622961
strncpy(proto, ndpi_get_proto_name(ndpi_thread_info[thread_id].workflow->ndpi_struct,
29632962
flow->detected_protocol.proto.app_protocol),sizeof(proto) - 1);
@@ -3065,7 +3064,7 @@ static void dump_realtime_protocol(struct ndpi_workflow * workflow, struct ndpi_
30653064
snprintf(dstip, sizeof(dstip), "[%s]", flow->dst_name ? flow->dst_name : "");
30663065
}
30673066

3068-
ndpi_protocol2name(workflow->ndpi_struct, flow->detected_protocol, app_name, sizeof(app_name));
3067+
ndpi_protocol2name(workflow->ndpi_struct, flow->detected_protocol.proto, app_name, sizeof(app_name));
30693068

30703069
if (ret == 1) {
30713070
fprintf(out, "Detected Realtime protocol %s --> [%s] %s:%d <--> %s:%d app=%s <%s>\n",
@@ -3975,7 +3974,7 @@ static void printFlowsStats() {
39753974
fprintf(out, "\t%u\t%-10s\t%s:%u <-> %s:%u\t[",
39763975
i,
39773976
ndpi_protocol2name(ndpi_thread_info[0].workflow->ndpi_struct,
3978-
all_flows[i].flow->detected_protocol, buf, sizeof(buf)),
3977+
all_flows[i].flow->detected_protocol.proto, buf, sizeof(buf)),
39793978
all_flows[i].flow->src_name ? all_flows[i].flow->src_name : "",
39803979
ntohs(all_flows[i].flow->src_port),
39813980
all_flows[i].flow->dst_name ? all_flows[i].flow->dst_name : "",
@@ -4921,7 +4920,7 @@ static void ndpi_process_packet(u_char *args,
49214920
}
49224921
trailer->flow_risk_info[sizeof(trailer->flow_risk_info) - 1] = '\0';
49234922
trailer->proto.master_protocol = htons(p.proto.master_protocol), trailer->proto.app_protocol = htons(p.proto.app_protocol);
4924-
ndpi_protocol2name(ndpi_thread_info[thread_id].workflow->ndpi_struct, p, trailer->name, sizeof(trailer->name));
4923+
ndpi_protocol2name(ndpi_thread_info[thread_id].workflow->ndpi_struct, p.proto, trailer->name, sizeof(trailer->name));
49254924

49264925
/* Metadata */
49274926
/* Metadata are (all) available in `flow` only after nDPI completed its work!

example/ndpiSimpleIntegration.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -876,12 +876,10 @@ static void ndpi_process_packet(uint8_t * const args,
876876
return;
877877
} else if (flow_to_process->ndpi_flow->num_processed_pkts == 0xFE) {
878878
/* last chance to guess something, better then nothing */
879-
uint8_t protocol_was_guessed = 0;
880879
flow_to_process->guessed_protocol =
881880
ndpi_detection_giveup(workflow->ndpi_struct,
882-
flow_to_process->ndpi_flow,
883-
&protocol_was_guessed);
884-
if (protocol_was_guessed != 0) {
881+
flow_to_process->ndpi_flow);
882+
if (flow_to_process->ndpi_flow->protocol_was_guessed != 0) {
885883
printf("[%8llu, %d, %4d][GUESSED] protocol: %s | app protocol: %s | category: %s\n",
886884
workflow->packets_captured,
887885
reader_thread->array_index,

example/reader_util.c

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,7 @@ static void dump_flow_fingerprint(struct ndpi_workflow * workflow,
11451145
ndpi_serialize_string_uint32(&serializer, "srv_port", ntohs(flow->dst_port));
11461146
ndpi_serialize_string_string(&serializer, "proto",
11471147
ndpi_protocol2name(workflow->ndpi_struct,
1148-
flow->detected_protocol,
1148+
flow->detected_protocol.proto,
11491149
buf, sizeof(buf)));
11501150

11511151
if(flow->server_hostname)
@@ -1192,7 +1192,7 @@ static void process_ndpi_monitoring_info(struct ndpi_flow_info *flow) {
11921192
return;
11931193

11941194
if(flow->monitoring_state == 0 &&
1195-
flow->ndpi_flow->monitoring) {
1195+
flow->ndpi_flow->state == NDPI_STATE_MONITORING) {
11961196
/* We just moved to monitoring state */
11971197
flow->monitoring_state = 1;
11981198
flow->num_packets_before_monitoring = flow->ndpi_flow->packet_direction_complete_counter[0] + flow->ndpi_flow->packet_direction_complete_counter[1];
@@ -1704,7 +1704,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl
17041704
ndpi_serialize_string_uint32(&flow->ndpi_flow_serializer, "detection_completed", flow->detection_completed);
17051705
ndpi_serialize_string_uint32(&flow->ndpi_flow_serializer, "check_extra_packets", flow->check_extra_packets);
17061706

1707-
if(flow->ndpi_flow->monitoring) {
1707+
if(flow->ndpi_flow->state == NDPI_STATE_MONITORING) {
17081708
serialize_monitoring_metadata(flow);
17091709
}
17101710

@@ -2018,26 +2018,19 @@ static struct ndpi_proto packet_processing(struct ndpi_workflow * workflow,
20182018
ipsize, time_ms, &input_info);
20192019
if(monitoring_enabled)
20202020
process_ndpi_monitoring_info(flow);
2021-
enough_packets |= ndpi_flow->fail_with_unknown;
2022-
if(enough_packets || (flow->detected_protocol.proto.app_protocol != NDPI_PROTOCOL_UNKNOWN)) {
2023-
if((!enough_packets)
2024-
&& ndpi_extra_dissection_possible(workflow->ndpi_struct, ndpi_flow))
2025-
; /* Wait for further metadata */
2026-
else {
2027-
/* New protocol detected or give up */
2028-
flow->detection_completed = 1;
2029-
2030-
if(flow->detected_protocol.proto.app_protocol == NDPI_PROTOCOL_UNKNOWN) {
2031-
u_int8_t proto_guessed;
2032-
2033-
flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct, flow->ndpi_flow,
2034-
&proto_guessed);
2035-
if(proto_guessed) workflow->stats.guessed_flow_protocols++;
2036-
}
2021+
if(flow->detected_protocol.state == NDPI_STATE_CLASSIFIED ||
2022+
enough_packets) {
2023+
2024+
flow->detection_completed = 1;
20372025

2038-
process_ndpi_collected_info(workflow, flow);
2026+
if(flow->detected_protocol.state != NDPI_STATE_CLASSIFIED) {
2027+
flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct, flow->ndpi_flow);
20392028
}
2029+
2030+
if(flow->ndpi_flow->protocol_was_guessed) workflow->stats.guessed_flow_protocols++;
2031+
process_ndpi_collected_info(workflow, flow);
20402032
}
2033+
20412034
/* Let's try to save client-server direction */
20422035
flow->current_pkt_from_client_to_server = input_info.in_pkt_dir;
20432036

fuzz/fuzz_config.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
1212
FuzzedDataProvider fuzzed_data(data, size);
1313
struct ndpi_detection_module_struct *ndpi_info_mod;
1414
struct ndpi_flow_struct flow;
15-
u_int8_t protocol_was_guessed, unused;
15+
u_int8_t unused;
1616
u_int32_t i, ret;
1717
u_int16_t bool_value;
1818
struct ndpi_lru_cache_stats lru_stats;
@@ -811,15 +811,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
811811
ndpi_detection_get_l4(pkt.data(), pkt.size(), &l4_return, &l4_len_return, &l4_protocol_return, NDPI_DETECTION_ONLY_IPV4);
812812

813813
ndpi_detection_process_packet(ndpi_info_mod, &flow, pkt.data(), pkt.size(), 0, &input_info);
814-
p = ndpi_detection_giveup(ndpi_info_mod, &flow, &protocol_was_guessed);
814+
p = ndpi_detection_giveup(ndpi_info_mod, &flow);
815815

816816
assert(p.proto.master_protocol == ndpi_get_flow_masterprotocol(&flow));
817817
assert(p.proto.app_protocol == ndpi_get_flow_appprotocol(&flow));
818818
assert(p.category == ndpi_get_flow_category(&flow));
819819
ndpi_is_master_only_protocol(ndpi_info_mod, p.proto.app_protocol);
820820
ndpi_normalize_protocol(ndpi_info_mod, &p.proto);
821-
assert(ndpi_stack_get_upper_proto(&p.protocol_stack) == ndpi_get_upper_proto(p));
822-
assert(ndpi_stack_get_lower_proto(&p.protocol_stack) == ndpi_get_lower_proto(p));
821+
assert(ndpi_stack_get_upper_proto(&p.protocol_stack) == ndpi_get_upper_proto(p.proto));
822+
assert(ndpi_stack_get_lower_proto(&p.protocol_stack) == ndpi_get_lower_proto(p.proto));
823823
ndpi_get_flow_error_code(&flow);
824824
ndpi_get_flow_risk_info(&flow, out, sizeof(out), 1);
825825
ndpi_get_flow_ndpi_proto(&flow, &p2);

fuzz/fuzz_ndpi_reader.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,10 @@ static void node_cleanup_walker(const void *node, ndpi_VISIT which, int depth, v
4646
(void)depth;
4747
(void)user_data;
4848

49-
if(flow == NULL) return;
50-
5149
if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */
5250
if((!flow->detection_completed) && flow->ndpi_flow) {
53-
u_int8_t proto_guessed;
54-
5551
flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct,
56-
flow->ndpi_flow, &proto_guessed);
52+
flow->ndpi_flow);
5753
}
5854

5955
process_ndpi_collected_info(workflow, flow);

fuzz/fuzz_process_packet.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ static ndpi_serializer json_serializer = {};
1010
static ndpi_serializer csv_serializer = {};
1111

1212
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
13-
uint8_t protocol_was_guessed;
14-
1513
if (ndpi_info_mod == NULL) {
1614
fuzz_init_detection_module(&ndpi_info_mod, NULL);
1715

@@ -22,19 +20,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
2220
memset(&ndpi_flow, 0, SIZEOF_FLOW_STRUCT);
2321
ndpi_protocol detected_protocol =
2422
ndpi_detection_process_packet(ndpi_info_mod, &ndpi_flow, Data, Size, 0, NULL);
25-
ndpi_protocol guessed_protocol =
26-
ndpi_detection_giveup(ndpi_info_mod, &ndpi_flow, &protocol_was_guessed);
23+
detected_protocol = ndpi_detection_giveup(ndpi_info_mod, &ndpi_flow);
2724

2825
ndpi_reset_serializer(&json_serializer);
2926
ndpi_reset_serializer(&csv_serializer);
30-
if (protocol_was_guessed == 0)
31-
{
32-
ndpi_dpi2json(ndpi_info_mod, &ndpi_flow, detected_protocol, &json_serializer);
33-
ndpi_dpi2json(ndpi_info_mod, &ndpi_flow, detected_protocol, &csv_serializer);
34-
} else {
35-
ndpi_dpi2json(ndpi_info_mod, &ndpi_flow, guessed_protocol, &json_serializer);
36-
ndpi_dpi2json(ndpi_info_mod, &ndpi_flow, guessed_protocol, &csv_serializer);
37-
}
27+
ndpi_dpi2json(ndpi_info_mod, &ndpi_flow, detected_protocol, &json_serializer);
28+
ndpi_dpi2json(ndpi_info_mod, &ndpi_flow, detected_protocol, &csv_serializer);
3829
ndpi_free_flow_data(&ndpi_flow);
3930

4031
return 0;

python/ndpi/ndpi.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ def process_packet(self, flow, packet, packet_time_ms, input_info):
5959

6060
def giveup(self, flow):
6161
p = lib.ndpi_detection_giveup(self._detection_module,
62-
flow.C,
63-
ffi.new("uint8_t*", 0))
62+
flow.C)
6463
return ndpi_protocol(C=p,
6564
master_protocol=p.proto.master_protocol,
6665
app_protocol=p.proto.app_protocol,

python/ndpi/ndpi_build.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@
5656
const u_int64_t packet_time_ms,
5757
struct ndpi_flow_input_info *input_info);
5858
ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_struct,
59-
struct ndpi_flow_struct *flow,
60-
u_int8_t *protocol_was_guessed);
59+
struct ndpi_flow_struct *flow);
6160
void ndpi_py_setup_detection_module(struct ndpi_detection_module_struct *mod);
6261
struct ndpi_flow_struct * ndpi_py_initialize_flow(void);
6362
char* ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol proto, char *buf, u_int buf_len);

0 commit comments

Comments
 (0)