Skip to content

Commit

Permalink
Simplify ndpi_internal_guess_undetected_protocol()
Browse files Browse the repository at this point in the history
`ndpi_guess_undetected_protocol()/ndpi_internal_guess_undetected_protocol()`
is a strange function:
* it is exported by the library and it is actively used by `ntopng`
* it is intrinsecally ipv4-only
* it returns basically something like "classification_by_ip"/"classification_by_port"
(these information have already been calculated in `ndpi_do_guess()`...)
* it access the bittorrent LRU caches (similarly to
`ndpi_detection_giveup()` but without all the other caches...)

So:
* make the interface IPv4/6 agnostic
* use the classifications already available

This work will allow to make the Bittorrent caches IPV6-aware (see
81e1ea5).

Handle Dropbox classification "by-port" in the "standard" way.
  • Loading branch information
IvanNardi committed Apr 11, 2023
1 parent 77ea808 commit 7710905
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 106 deletions.
9 changes: 3 additions & 6 deletions fuzz/fuzz_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
ndpi_get_flow_risk_info(&flow, out, sizeof(out), 1);
ndpi_get_flow_ndpi_proto(ndpi_info_mod, &flow, &p2);
ndpi_is_proto(p, NDPI_PROTOCOL_TLS);
/* ndpi_guess_undetected_protocol() is a "strange" function (since is ipv4 only)
but it is exported by the library and it is used by ntopng. Try fuzzing it, here */
/* ndpi_guess_undetected_protocol() is a "strange" function. Try fuzzing it, here */
if(!ndpi_is_protocol_detected(ndpi_info_mod, p)) {
ndpi_guess_undetected_protocol(ndpi_info_mod, bool_value ? &flow : NULL,
flow.l4_proto);
if(!flow.is_ipv6) {
ndpi_guess_undetected_protocol(ndpi_info_mod, bool_value ? &flow : NULL,
flow.l4_proto,
flow.c_address.v4, flow.s_address.v4,
flow.c_port, flow.s_port);
/* Another "strange" function (ipv4 only): fuzz it here, for lack of a better alternative */
ndpi_find_ipv4_category_userdata(ndpi_info_mod, flow.c_address.v4);
}
Expand Down
10 changes: 1 addition & 9 deletions src/include/ndpi_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,20 +427,12 @@ extern "C" {
* @par ndpi_struct = the detection module
* @par flow = the flow we're trying to guess, NULL if not available
* @par proto = the l4 protocol number
* @par shost = source address in host byte order
* @par sport = source port number
* @par dhost = destination address in host byte order
* @par dport = destination port number
* @return the struct ndpi_protocol that match the port base protocol
*
*/
ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int8_t proto,
u_int32_t shost,
u_int16_t sport,
u_int32_t dhost,
u_int16_t dport);
u_int8_t proto);
/**
* Check if the string passed match with a protocol
*
Expand Down
3 changes: 1 addition & 2 deletions src/include/ndpi_protocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ ndpi_port_range* ndpi_build_default_ports(ndpi_port_range *ports,
u_int ndpi_search_tcp_or_udp_raw(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int8_t protocol,
u_int32_t saddr, u_int32_t daddr,
u_int16_t sport, u_int16_t dport);
u_int32_t saddr, u_int32_t daddr);


void init_diameter_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id);
Expand Down
95 changes: 21 additions & 74 deletions src/lib/ndpi_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7841,91 +7841,41 @@ u_int16_t ndpi_get_upper_proto(ndpi_protocol proto) {
/* ****************************************************** */

static ndpi_protocol ndpi_internal_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_str,
struct ndpi_flow_struct *flow, u_int8_t proto,
u_int32_t shost /* host byte order */, u_int16_t sport,
u_int32_t dhost /* host byte order */, u_int16_t dport) {
u_int32_t rc;
struct in_addr addr;
struct ndpi_flow_struct *flow, u_int8_t proto) {
ndpi_protocol ret = NDPI_PROTOCOL_NULL;
u_int8_t user_defined_proto;

if(!ndpi_str)
return(ret);

#ifdef BITTORRENT_CACHE_DEBUG
printf("[%s:%u] ndpi_guess_undetected_protocol(%08X, %u, %08X, %u) [flow: %p]\n",
__FILE__, __LINE__, shost, sport, dhost, dport, flow);
printf("[%s:%u] [flow: %p] proto %u\n", __FILE__, __LINE__, flow, proto);
#endif

if((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) {
rc = ndpi_search_tcp_or_udp_raw(ndpi_str, flow, proto, shost, dhost, sport, dport);
if(flow && ((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP))) {

if(rc != NDPI_PROTOCOL_UNKNOWN) {
if(flow && (proto == IPPROTO_UDP) &&
NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, rc) && is_udp_not_guessable_protocol(rc))
;
else {
ret.app_protocol = rc,
ret.master_protocol = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto);

if(ret.app_protocol == ret.master_protocol)
ret.master_protocol = NDPI_PROTOCOL_UNKNOWN;

#ifdef BITTORRENT_CACHE_DEBUG
printf("[%s:%u] Guessed %u.%u\n", __FILE__, __LINE__, ret.master_protocol, ret.app_protocol);
#endif

ret.category = ndpi_get_proto_category(ndpi_str, ret);
return(ret);
}
}

rc = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto);
if(rc != NDPI_PROTOCOL_UNKNOWN) {
if(flow && (proto == IPPROTO_UDP) &&
NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, rc) && is_udp_not_guessable_protocol(rc))
;
else {
ret.app_protocol = rc;

if(rc == NDPI_PROTOCOL_TLS)
goto check_guessed_skype;
else {
#ifdef BITTORRENT_CACHE_DEBUG
printf("[%s:%u] Guessed %u.%u\n", __FILE__, __LINE__, ret.master_protocol, ret.app_protocol);
#endif

ret.category = ndpi_get_proto_category(ndpi_str, ret);
return(ret);
}
if(flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) {
if(flow->guessed_protocol_id_by_ip != NDPI_PROTOCOL_UNKNOWN) {
ret.master_protocol = flow->guessed_protocol_id;
ret.app_protocol = flow->guessed_protocol_id_by_ip;
} else {
ret.app_protocol = flow->guessed_protocol_id;
}
} else {
ret.app_protocol = flow->guessed_protocol_id_by_ip;
}

if(ndpi_search_into_bittorrent_cache(ndpi_str, NULL /* flow */,
htonl(shost), htons(sport),
htonl(dhost), htons(dport))) {
if(ret.app_protocol == NDPI_PROTOCOL_UNKNOWN &&
!flow->is_ipv6 && /* TODO */
ndpi_search_into_bittorrent_cache(ndpi_str, flow,
flow->c_address.v4, flow->c_port,
flow->s_address.v4, flow->s_port)) {
/* This looks like BitTorrent */
ret.app_protocol = NDPI_PROTOCOL_BITTORRENT;
ret.category = ndpi_get_proto_category(ndpi_str, ret);

#ifdef BITTORRENT_CACHE_DEBUG
printf("[%s:%u] Guessed %u.%u\n", __FILE__, __LINE__, ret.master_protocol, ret.app_protocol);
#endif

return(ret);
}

check_guessed_skype:
addr.s_addr = htonl(shost);
if(ndpi_network_ptree_match(ndpi_str, &addr) == NDPI_PROTOCOL_SKYPE_TEAMS) {
ret.app_protocol = NDPI_PROTOCOL_SKYPE_TEAMS;
} else {
addr.s_addr = htonl(dhost);
if(ndpi_network_ptree_match(ndpi_str, &addr) == NDPI_PROTOCOL_SKYPE_TEAMS)
ret.app_protocol = NDPI_PROTOCOL_SKYPE_TEAMS;
}
} else
ret.app_protocol = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto);
} else {
ret.app_protocol = ndpi_guess_protocol_id(ndpi_str, flow, proto, 0, 0, &user_defined_proto);
}

ret.category = ndpi_get_proto_category(ndpi_str, ret);

Expand All @@ -7939,11 +7889,8 @@ static ndpi_protocol ndpi_internal_guess_undetected_protocol(struct ndpi_detecti
/* ****************************************************** */

ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_str,
struct ndpi_flow_struct *flow, u_int8_t proto,
u_int32_t shost /* host byte order */, u_int16_t sport,
u_int32_t dhost /* host byte order */, u_int16_t dport) {
ndpi_protocol p = ndpi_internal_guess_undetected_protocol(ndpi_str, flow, proto,
shost, sport, dhost, dport);
struct ndpi_flow_struct *flow, u_int8_t proto) {
ndpi_protocol p = ndpi_internal_guess_undetected_protocol(ndpi_str, flow, proto);

p.master_protocol = ndpi_map_ndpi_id_to_user_proto_id(ndpi_str, p.master_protocol),
p.app_protocol = ndpi_map_ndpi_id_to_user_proto_id(ndpi_str, p.app_protocol);
Expand Down
17 changes: 2 additions & 15 deletions src/lib/protocols/tcp_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,11 @@
u_int ndpi_search_tcp_or_udp_raw(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int8_t protocol,
u_int32_t saddr, u_int32_t daddr, /* host endianess */
u_int16_t sport, u_int16_t dport) /* host endianess */
u_int32_t saddr, u_int32_t daddr) /* host endianess */
{
u_int16_t rc;
struct in_addr host;

if(protocol == IPPROTO_UDP) {
if((sport == dport) && (sport == 17500)) {
return(NDPI_PROTOCOL_DROPBOX);
}
}

if(flow)
return(flow->guessed_protocol_id_by_ip);
else {
Expand All @@ -51,27 +44,21 @@ u_int ndpi_search_tcp_or_udp_raw(struct ndpi_detection_module_struct *ndpi_struc

void ndpi_search_tcp_or_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
{
u_int16_t sport, dport;
u_int proto;
struct ndpi_packet_struct *packet;

if(!ndpi_struct || !flow || flow->host_server_name[0] != '\0')
return;

packet = &ndpi_struct->packet;

if(packet->udp) sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
else if(packet->tcp) sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
else sport = dport = 0;

if(packet->iph /* IPv4 Only: we need to support packet->iphv6 at some point */) {
proto = ndpi_search_tcp_or_udp_raw(ndpi_struct,
flow,
packet->iph ? packet->iph->protocol :
packet->iphv6->ip6_hdr.ip6_un1_nxt,
ntohl(packet->iph->saddr),
ntohl(packet->iph->daddr),
sport, dport);
ntohl(packet->iph->daddr));

if(proto != NDPI_PROTOCOL_UNKNOWN)
ndpi_set_detected_protocol(ndpi_struct, flow, proto, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_MATCH_BY_PORT);
Expand Down

0 comments on commit 7710905

Please sign in to comment.