Skip to content

Commit

Permalink
Make Bittorrent LRU cache IPv6 aware. (#1909)
Browse files Browse the repository at this point in the history
It was the only remaining LRU cache without IPv6 support.
See 81e1ea5
  • Loading branch information
IvanNardi authored Apr 29, 2023
1 parent 6b803f4 commit bb370f5
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 59 deletions.
2 changes: 0 additions & 2 deletions src/include/ndpi_protocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,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
43 changes: 18 additions & 25 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);
extern void ookla_add_to_cache(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow);
Expand Down Expand Up @@ -6103,42 +6105,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 @@ -6268,9 +6265,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 @@ -6736,6 +6731,7 @@ static ndpi_protocol ndpi_internal_detection_process_packet(struct ndpi_detectio
}

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

/* Init default */

Expand Down Expand Up @@ -7911,10 +7907,7 @@ static ndpi_protocol ndpi_internal_guess_undetected_protocol(struct ndpi_detecti
}

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)) {
ndpi_search_into_bittorrent_cache(ndpi_str, flow)) {
/* This looks like BitTorrent */
ret.app_protocol = NDPI_PROTOCOL_BITTORRENT;
}
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 bb370f5

Please sign in to comment.