static void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_BITTORRENT) { /* check for tcp retransmission here */ if ((packet->tcp != NULL) && (packet->tcp_retransmission == 0 || packet->num_retried_bytes)) { ndpi_int_search_bittorrent_tcp(ndpi_struct, flow); } else if(packet->udp != NULL) { flow->bittorrent_stage++; if(flow->bittorrent_stage < 10) { if(packet->payload_packet_len > 19 /* min size */) { char *begin; if(ndpi_strnstr(packet->payload, ":target20:", packet->payload_packet_len) || ndpi_strnstr(packet->payload, ":find_node1:", packet->payload_packet_len) || ndpi_strnstr(packet->payload, "d1:ad2:id20:", packet->payload_packet_len)) { bittorrent_found: NDPI_LOG_BITTORRENT(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); ndpi_add_connection_as_bittorrent(ndpi_struct, flow, NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION, NDPI_REAL_PROTOCOL); return; } else if((begin = memchr(packet->payload, 'B', packet->payload_packet_len-19)) != NULL) { long offset = (u_long)begin - (u_long)packet->payload; if((packet->payload_packet_len-19) > offset) { if(memcmp(begin, "BitTorrent protocol", 19) == 0) { goto bittorrent_found; } } } } return; } NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_BITTORRENT); } } }
void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; /* This is broadcast */ if(packet->iph && ((packet->iph->saddr == 0xFFFFFFFF) || (packet->iph->daddr == 0xFFFFFFFF))) return; if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_BITTORRENT) { /* check for tcp retransmission here */ if ((packet->tcp != NULL) && (packet->tcp_retransmission == 0 || packet->num_retried_bytes)) { ndpi_int_search_bittorrent_tcp(ndpi_struct, flow); } else if(packet->udp != NULL) { char *bt_search = "BT-SEARCH * HTTP/1.1\r\n"; if((ntohs(packet->udp->source) < 1024) || (ntohs(packet->udp->dest) < 1024) /* High ports only */) return; /* Check for uTP http://www.bittorrent.org/beps/bep_0029.html wireshark/epan/dissectors/packet-bt-utp.c */ if(packet->payload_packet_len >= 23 /* min header size */) { if(strncmp((const char*)packet->payload, bt_search, strlen(bt_search)) == 0) { ndpi_add_connection_as_bittorrent(ndpi_struct, flow, NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION, NDPI_REAL_PROTOCOL); return; } else { /* Check if this is protocol v0 */ u_int8_t v0_extension = packet->payload[17]; u_int8_t v0_flags = packet->payload[18]; /* Check if this is protocol v1 */ u_int8_t v1_version = packet->payload[0]; u_int8_t v1_extension = packet->payload[1]; u_int32_t v1_window_size = *((u_int32_t*)&packet->payload[12]); if((packet->payload[0]== 0x60) && (packet->payload[1]== 0x0) && (packet->payload[2]== 0x0) && (packet->payload[3]== 0x0) && (packet->payload[4]== 0x0)) { /* Heuristic */ goto bittorrent_found; } else if(((v1_version & 0x0f) == 1) && ((v1_version >> 4) < 5 /* ST_NUM_STATES */) && (v1_extension < 3 /* EXT_NUM_EXT */) && (v1_window_size < 32768 /* 32k */) ) { goto bittorrent_found; } else if((v0_flags < 6 /* ST_NUM_STATES */) && (v0_extension < 3 /* EXT_NUM_EXT */)) { u_int32_t ts = ntohl(*((u_int32_t*)&(packet->payload[4]))); u_int32_t now; #ifndef __KERNEL__ now = (u_int32_t)time(NULL); #else struct timespec t; getnstimeofday(&t); now = t.tv_sec; #endif if((ts < (now+86400)) && (ts > (now-86400))) { goto bittorrent_found; } } } } flow->bittorrent_stage++; if(flow->bittorrent_stage < 10) { if(packet->payload_packet_len > 19 /* min size */) { if(ndpi_strnstr((const char *)packet->payload, ":target20:", packet->payload_packet_len) || ndpi_strnstr((const char *)packet->payload, ":find_node1:", packet->payload_packet_len) || ndpi_strnstr((const char *)packet->payload, "d1:ad2:id20:", packet->payload_packet_len) || ndpi_strnstr((const char *)packet->payload, ":info_hash20:", packet->payload_packet_len) || ndpi_strnstr((const char *)packet->payload, ":filter64", packet->payload_packet_len) || ndpi_strnstr((const char *)packet->payload, "d1:rd2:id20:", packet->payload_packet_len) || ndpi_strnstr((const char *)packet->payload, "BitTorrent protocol", packet->payload_packet_len) ) { bittorrent_found: NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); ndpi_add_connection_as_bittorrent(ndpi_struct, flow, NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION, NDPI_REAL_PROTOCOL); return; } } return; } NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_BITTORRENT); }
void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; /* This is broadcast */ if(packet->iph && ((packet->iph->saddr == 0xFFFFFFFF) || (packet->iph->daddr == 0xFFFFFFFF))) return; if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_BITTORRENT) { /* check for tcp retransmission here */ if ((packet->tcp != NULL) && (packet->tcp_retransmission == 0 || packet->num_retried_bytes)) { ndpi_int_search_bittorrent_tcp(ndpi_struct, flow); } else if(packet->udp != NULL) { /* Check for uTP http://www.bittorrent.org/beps/bep_0029.html wireshark/epan/dissectors/packet-bt-utp.c */ if(packet->payload_packet_len >= 23 /* min header size */) { /* Check if this is protocol v0 */ u_int8_t v0_extension = packet->payload[17]; u_int8_t v0_flags = packet->payload[18]; /* Check if this is protocol v1 */ u_int8_t v1_version = packet->payload[0]; u_int8_t v1_extension = packet->payload[1]; if(((v1_version & 0x0f) == 1) && ((v1_version >> 4) < 6 /* ST_NUM_STATES */) && (v1_extension < 3 /* EXT_NUM_EXT */)) { goto bittorrent_found; } else if((v0_flags < 6 /* ST_NUM_STATES */) && (v0_extension < 3 /* EXT_NUM_EXT */)) { u_int32_t ts, // ts_usec, now = (u_int32_t)time(NULL); ts = ntohl(*((u_int32_t*)&(packet->payload[4]))); // ts_usec = ntohl(*((u_int32_t*)&(packet->payload[8]))); if((ts < (now+86400)) && (ts > (now-86400))) { goto bittorrent_found; } } } flow->bittorrent_stage++; if(flow->bittorrent_stage < 10) { if(packet->payload_packet_len > 19 /* min size */) { char *begin; if(ndpi_strnstr(packet->payload, ":target20:", packet->payload_packet_len) || ndpi_strnstr(packet->payload, ":find_node1:", packet->payload_packet_len) || ndpi_strnstr(packet->payload, "d1:ad2:id20:", packet->payload_packet_len)) { bittorrent_found: NDPI_LOG_BITTORRENT(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n"); ndpi_add_connection_as_bittorrent(ndpi_struct, flow, NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION, NDPI_REAL_PROTOCOL); return; } else if((begin = memchr(packet->payload, 'B', packet->payload_packet_len-19)) != NULL) { long offset = (u_long)begin - (u_long)packet->payload; if((packet->payload_packet_len-19) > offset) { if(memcmp(begin, "BitTorrent protocol", 19) == 0) { goto bittorrent_found; } } } } return; } NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_BITTORRENT); }