Skip to content

Commit

Permalink
Make Bittorrent LRU cache IPv6 aware.
Browse files Browse the repository at this point in the history
It was the only remaining LRU cache without IPv6 support.
See 81e1ea5

The change in `ndpi_guess_undetected_protocol()` is quite hacky, but
this way we don't need to update `ntopng` code
  • Loading branch information
IvanNardi committed Mar 21, 2023
1 parent 2a3ade3 commit 7860457
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 58 deletions.
2 changes: 0 additions & 2 deletions src/include/ndpi_protocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ void init_armagetron_dissector(struct ndpi_detection_module_struct *ndpi_struct,
void init_amqp_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id);
void init_bgp_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id);
void init_bittorrent_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id);
int ndpi_search_into_bittorrent_cache(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow,
u_int32_t saddr, u_int16_t sport, u_int32_t daddr, u_int16_t dport);
void init_lisp_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id);
void init_teredo_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id);
void init_ciscovpn_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id);
Expand Down
57 changes: 33 additions & 24 deletions src/lib/ndpi_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ _Static_assert(sizeof(ndpi_known_risks) / sizeof(ndpi_risk_info) == NDPI_MAX_RIS
extern void ndpi_unset_risk(struct ndpi_detection_module_struct *ndpi_str,
struct ndpi_flow_struct *flow, ndpi_risk_enum r);
extern u_int32_t make_mining_key(struct ndpi_flow_struct *flow);
extern u_int32_t make_bittorrent_host_key(struct ndpi_flow_struct *flow, int client, int offset);
extern u_int32_t make_bittorrent_peers_key(struct ndpi_flow_struct *flow);
extern int stun_search_into_zoom_cache(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);

/* Forward */
Expand Down Expand Up @@ -5954,42 +5956,37 @@ u_int32_t ndpi_ip_port_hash_funct(u_int32_t ip, u_int16_t port) {
/* #define BITTORRENT_CACHE_DEBUG */

int ndpi_search_into_bittorrent_cache(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
/* Parameters below need to be in network byte order */
u_int32_t saddr, u_int16_t sport, u_int32_t daddr, u_int16_t dport) {
struct ndpi_flow_struct *flow) {

#ifdef BITTORRENT_CACHE_DEBUG
printf("[%s:%u] ndpi_search_into_bittorrent_cache(%08X, %u, %08X, %u) [bt_check_performed=%d]\n",
__FILE__, __LINE__, saddr, sport, daddr, dport,
flow ? flow->bt_check_performed : -1);
printf("[%s:%u] ndpi_search_into_bittorrent_cache(%u, %u) [bt_check_performed=%d]\n",
__FILE__, __LINE__, ntohs(flow->c_port), ntohs(flow->s_port),
flow->bt_check_performed);
#endif

if(flow && flow->bt_check_performed /* Do the check once */)
if(flow->bt_check_performed /* Do the check once */)
return(0);

if(ndpi_struct->bittorrent_cache) {
u_int16_t cached_proto;
u_int8_t found = 0;
u_int32_t key1, key2;
u_int32_t key, key1, key2;

if(flow)
flow->bt_check_performed = 1;
flow->bt_check_performed = 1;

/* Check cached communications */
key1 = ndpi_ip_port_hash_funct(saddr, sport), key2 = ndpi_ip_port_hash_funct(daddr, dport);
key = make_bittorrent_peers_key(flow);
key1 = make_bittorrent_host_key(flow, 1, 0), key2 = make_bittorrent_host_key(flow, 0, 0);

found =
ndpi_lru_find_cache(ndpi_struct->bittorrent_cache, saddr+daddr, &cached_proto, 0 /* Don't remove it as it can be used for other connections */, ndpi_get_current_time(flow))
ndpi_lru_find_cache(ndpi_struct->bittorrent_cache, key, &cached_proto, 0 /* Don't remove it as it can be used for other connections */, ndpi_get_current_time(flow))
|| ndpi_lru_find_cache(ndpi_struct->bittorrent_cache, key1, &cached_proto, 0 /* Don't remove it as it can be used for other connections */, ndpi_get_current_time(flow))
|| ndpi_lru_find_cache(ndpi_struct->bittorrent_cache, key2, &cached_proto, 0 /* Don't remove it as it can be used for other connections */, ndpi_get_current_time(flow));

#ifdef BITTORRENT_CACHE_DEBUG
if(ndpi_struct->packet.udp)
printf("[BitTorrent] *** [UDP] SEARCHING ports %u / %u [%u][%u][found: %u][packet_counter: %u]\n",
ntohs(sport), ntohs(dport), key1, key2, found, flow ? flow->packet_counter : 0);
else
printf("[BitTorrent] *** [TCP] SEARCHING ports %u / %u [%u][%u][found: %u][packet_counter: %u]\n",
ntohs(sport), ntohs(dport), key1, key2, found, flow ? flow->packet_counter : 0);
printf("[BitTorrent] *** [%s] SEARCHING ports %u / %u [%u][%u][%u][found: %u]\n",
flow->l4_proto == IPPROTO_UDP ? "UDP": "TCP",
ntohs(flow->c_port), ntohs(flow->s_port), key, key1, key2, found);
#endif

return(found);
Expand Down Expand Up @@ -6121,9 +6118,7 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st

/* Does it looks like BitTorrent? */
if(ret.app_protocol == NDPI_PROTOCOL_UNKNOWN &&
ndpi_search_into_bittorrent_cache(ndpi_str, flow,
flow->c_address.v4, flow->c_port,
flow->s_address.v4, flow->s_port)) {
ndpi_search_into_bittorrent_cache(ndpi_str, flow)) {
ndpi_set_detected_protocol(ndpi_str, flow, NDPI_PROTOCOL_BITTORRENT, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI_PARTIAL_CACHE);
ret.app_protocol = flow->detected_protocol_stack[0];
}
Expand Down Expand Up @@ -6579,6 +6574,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
}

flow->num_processed_pkts++;
ndpi_str->current_ts = current_time_ms;

/* Init default */

Expand Down Expand Up @@ -7715,6 +7711,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct
struct in_addr addr;
ndpi_protocol ret = NDPI_PROTOCOL_NULL;
u_int8_t user_defined_proto;
struct ndpi_flow_struct fake_flow, *orig_flow;

if(!ndpi_str)
return ret;
Expand Down Expand Up @@ -7768,9 +7765,20 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct
}
}

if(ndpi_search_into_bittorrent_cache(ndpi_str, NULL /* flow */,
htonl(shost), htons(sport),
htonl(dhost), htons(dport))) {
/* Workaround: create a fake flow struct since ndpi_search_into_bittorrent_cache is ipv4/6 agnostic,
while this function is intrinsecally ipv4 only.
This way we don't need to change the (public) ndpi_guess_undetected_protocol() prototype */
fake_flow.is_ipv6 = 0;
fake_flow.c_address.v4 = htonl(shost);
fake_flow.s_address.v4 = htonl(dhost);
fake_flow.c_port = htons(sport);
fake_flow.s_port = htons(dport);
fake_flow.bt_check_performed = 0;
fake_flow.l4_proto = proto;
fake_flow.last_packet_time_ms = ndpi_str->current_ts;
orig_flow = flow;
flow = &fake_flow;
if(ndpi_search_into_bittorrent_cache(ndpi_str, flow /* Real or the fake one */)) {
/* This looks like BitTorrent */
ret.app_protocol = NDPI_PROTOCOL_BITTORRENT;
ret.category = ndpi_get_proto_category(ndpi_str, ret);
Expand All @@ -7781,6 +7789,7 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct

return(ret);
}
flow = orig_flow; /* Restore original value */

check_guessed_skype:
addr.s_addr = htonl(shost);
Expand Down
57 changes: 47 additions & 10 deletions src/lib/protocols/bittorrent.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ struct ndpi_utp_hdr {
u_int16_t sequence_nr, ack_nr;
};

extern int ndpi_search_into_bittorrent_cache(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow);

/* Forward declaration */
static void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow);
Expand Down Expand Up @@ -100,12 +103,45 @@ static void ndpi_search_bittorrent_hash(struct ndpi_detection_module_struct *ndp

/* *********************************************** */

u_int32_t make_bittorrent_host_key(struct ndpi_flow_struct *flow, int client, int offset) {
u_int32_t key;

/* network byte order */
if(flow->is_ipv6) {
if(client)
key = ndpi_ip_port_hash_funct(ndpi_quick_hash(flow->c_address.v6, 16), htons(ntohs(flow->c_port) + offset));
else
key = ndpi_ip_port_hash_funct(ndpi_quick_hash(flow->s_address.v6, 16), flow->s_port);
} else {
if(client)
key = ndpi_ip_port_hash_funct(flow->c_address.v4, htons(ntohs(flow->c_port) + offset));
else
key = ndpi_ip_port_hash_funct(flow->s_address.v4, flow->s_port);
}

return key;
}

/* *********************************************** */

u_int32_t make_bittorrent_peers_key(struct ndpi_flow_struct *flow) {
u_int32_t key;

/* network byte order */
if(flow->is_ipv6)
key = ndpi_quick_hash(flow->c_address.v6, 16) + ndpi_quick_hash(flow->s_address.v6, 16);
else
key = flow->c_address.v4 + flow->s_address.v4;

return key;
}

/* *********************************************** */

static void ndpi_add_connection_as_bittorrent(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
int bt_offset, int check_hash,
ndpi_confidence_t confidence) {
struct ndpi_packet_struct *packet = &ndpi_struct->packet;

if(check_hash)
ndpi_search_bittorrent_hash(ndpi_struct, flow, bt_offset);

Expand All @@ -118,23 +154,24 @@ static void ndpi_add_connection_as_bittorrent(struct ndpi_detection_module_struc
flow->extra_packets_func = search_bittorrent_again;
}

if(ndpi_struct->bittorrent_cache && packet->iph) {
u_int32_t key1, key2, i;
if(ndpi_struct->bittorrent_cache) {
u_int32_t key, key1, key2, i;

key = make_bittorrent_peers_key(flow);
key1 = make_bittorrent_host_key(flow, 1, 0), key2 = make_bittorrent_host_key(flow, 0, 0);

key1 = ndpi_ip_port_hash_funct(flow->c_address.v4, flow->c_port), key2 = ndpi_ip_port_hash_funct(flow->s_address.v4, flow->s_port);

ndpi_lru_add_to_cache(ndpi_struct->bittorrent_cache, key1, NDPI_PROTOCOL_BITTORRENT, ndpi_get_current_time(flow));
ndpi_lru_add_to_cache(ndpi_struct->bittorrent_cache, key2, NDPI_PROTOCOL_BITTORRENT, ndpi_get_current_time(flow));

/* Now add hosts as twins */
ndpi_lru_add_to_cache(ndpi_struct->bittorrent_cache,
flow->c_address.v4 + flow->s_address.v4,
key,
NDPI_PROTOCOL_BITTORRENT,
ndpi_get_current_time(flow));

/* Also add +2 ports of the sender in order to catch additional sockets open by the same client */
for(i=0; i<2; i++) {
key1 = ndpi_ip_port_hash_funct(flow->c_address.v4, htons(ntohs(flow->c_port)+1+i));
key1 = make_bittorrent_host_key(flow, 1, 1 + i);

ndpi_lru_add_to_cache(ndpi_struct->bittorrent_cache, key1, NDPI_PROTOCOL_BITTORRENT, ndpi_get_current_time(flow));
}
Expand Down Expand Up @@ -430,7 +467,7 @@ static u_int8_t is_port(u_int16_t a, u_int16_t b, u_int16_t what) {
static void ndpi_skip_bittorrent(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
struct ndpi_packet_struct *packet) {
if(packet->iph && ndpi_search_into_bittorrent_cache(ndpi_struct, flow, flow->c_address.v4, flow->c_port, flow->s_address.v4, flow->s_port))
if(ndpi_search_into_bittorrent_cache(ndpi_struct, flow))
ndpi_add_connection_as_bittorrent(ndpi_struct, flow, -1, 0, NDPI_CONFIDENCE_DPI_CACHE);
else
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
Expand Down
Loading

0 comments on commit 7860457

Please sign in to comment.