Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Bittorrent LRU cache IPv6 aware. #1909

Merged
merged 1 commit into from
Apr 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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