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); } } }
static int matchStringProtocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, char *string_to_match, u_int string_to_match_len) { int i = 0, end = string_to_match_len-1, num_found = 0; struct ndpi_packet_struct *packet = &flow->packet; #ifdef AHOCORASICK AC_TEXT_t ac_input_text; #endif while(end > 0) { if(string_to_match[end] == '.') { num_found++; if(num_found == 2) { end++; break; } } end--; } strncpy(flow->l4.tcp.host_server_name, &string_to_match[end], ndpi_min(sizeof(flow->l4.tcp.host_server_name)-1, string_to_match_len-end)); #ifdef AHOCORASICK matching_protocol_id = -1; ac_input_text.astring = string_to_match; ac_input_text.length = string_to_match_len; ac_automata_search (ac_automa, &ac_input_text, 0); ac_automata_reset(ac_automa); if (matching_protocol_id != -1) { packet->detected_protocol_stack[0] = matching_protocol_id; return(packet->detected_protocol_stack[0]); } #else for (i = 0; i < host_match_num_items; i++) { if(ndpi_strnstr(string_to_match, host_match[i].string_to_match, string_to_match_len) != NULL) { packet->detected_protocol_stack[0] = host_match[i].protocol_id; return(packet->detected_protocol_stack[0]); } else i++; } #endif #ifdef DEBUG string_to_match[string_to_match_len] = '\0'; printf("[NTOP] Unable to find a match for '%s'\n", string_to_match); #endif return(-1); }
static void ndpi_check_citrix(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; u_int32_t payload_len = packet->payload_packet_len; #if 0 printf("[len=%u][%02X %02X %02X %02X]\n", payload_len, packet->payload[0] & 0xFF, packet->payload[1] & 0xFF, packet->payload[2] & 0xFF, packet->payload[3] & 0xFF); #endif if(packet->tcp != NULL) { flow->l4.tcp.citrix_packet_id++; if((flow->l4.tcp.citrix_packet_id == 3) /* We have seen the 3-way handshake */ && flow->l4.tcp.seen_syn && flow->l4.tcp.seen_syn_ack && flow->l4.tcp.seen_ack) { if(payload_len == 6) { char citrix_header[] = { 0x07, 0x07, 0x49, 0x43, 0x41, 0x00 }; if(memcmp(packet->payload, citrix_header, sizeof(citrix_header)) == 0) { NDPI_LOG(NDPI_PROTOCOL_CITRIX, ndpi_struct, NDPI_LOG_DEBUG, "Found citrix.\n"); ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_CITRIX, NDPI_REAL_PROTOCOL); } return; } else if(payload_len > 4) { char citrix_header[] = { 0x1a, 0x43, 0x47, 0x50, 0x2f, 0x30, 0x31 }; if((memcmp(packet->payload, citrix_header, sizeof(citrix_header)) == 0) || (ndpi_strnstr(packet->payload, "Citrix.TcpProxyService", payload_len) != NULL)) { NDPI_LOG(NDPI_PROTOCOL_CITRIX, ndpi_struct, NDPI_LOG_DEBUG, "Found citrix.\n"); ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_CITRIX, NDPI_REAL_PROTOCOL); } return; } NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_CITRIX); } else if(flow->l4.tcp.citrix_packet_id > 3) NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_CITRIX); return; } }
static void check_content_type_and_change_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, u_int16_t x) { struct ndpi_packet_struct *packet = &flow->packet; int i, left = packet->payload_packet_len-x; if(left <= 0) return; for(i=0; jabber_strings[i].string != NULL; i++) { if(ndpi_strnstr((const char*)&packet->payload[x], jabber_strings[i].string, left) != NULL) { ndpi_int_jabber_add_connection(ndpi_struct, flow, jabber_strings[i].ndpi_protocol); return; } } }
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, const u_int8_t save_detection, const u_int8_t encrypted_connection) { if(check_hash) { const char *bt_hash = NULL; /* 20 bytes long */ const char *peer_id = NULL; /* 20 bytes long */ if(bt_offset == -1) { const char *bt_magic = ndpi_strnstr((const char *)flow->packet.payload, "BitTorrent protocol", flow->packet.payload_packet_len); if(bt_magic) bt_hash = &bt_magic[19], peer_id = &bt_magic[39]; } else bt_hash = (const char*)&flow->packet.payload[28], peer_id = (const char*)&flow->packet.payload[48]; if(bt_hash) memcpy(flow->bittorent_hash, bt_hash, 20); } ndpi_int_change_protocol(ndpi_struct, flow, NDPI_PROTOCOL_BITTORRENT, NDPI_PROTOCOL_UNKNOWN); }
void ndpi_search_jabber_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; struct ndpi_id_struct *src = flow->src; struct ndpi_id_struct *dst = flow->dst; u_int16_t x; NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_TRACE, "JABBER detection....\n"); /* search for jabber file transfer */ /* this part is working asymmetrically */ if (packet->tcp != NULL && packet->tcp->syn != 0 && packet->payload_packet_len == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "check jabber syn\n"); if (src != NULL && src->jabber_file_transfer_port[0] != 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src jabber ft port set, ports are: %u, %u\n", ntohs(src->jabber_file_transfer_port[0]), ntohs(src->jabber_file_transfer_port[1])); if (((u_int32_t) (packet->tick_timestamp - src->jabber_stun_or_ft_ts)) >= ndpi_struct->jabber_file_transfer_timeout) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER src stun timeout %u %u\n", src->jabber_stun_or_ft_ts, packet->tick_timestamp); src->jabber_file_transfer_port[0] = 0; src->jabber_file_transfer_port[1] = 0; } else if (src->jabber_file_transfer_port[0] == packet->tcp->dest || src->jabber_file_transfer_port[0] == packet->tcp->source || src->jabber_file_transfer_port[1] == packet->tcp->dest || src->jabber_file_transfer_port[1] == packet->tcp->source) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "found jabber file transfer.\n"); ndpi_int_jabber_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER); } } if (dst != NULL && dst->jabber_file_transfer_port[0] != 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst jabber ft port set, ports are: %u, %u\n", ntohs(dst->jabber_file_transfer_port[0]), ntohs(dst->jabber_file_transfer_port[1])); if (((u_int32_t) (packet->tick_timestamp - dst->jabber_stun_or_ft_ts)) >= ndpi_struct->jabber_file_transfer_timeout) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER dst stun timeout %u %u\n", dst->jabber_stun_or_ft_ts, packet->tick_timestamp); dst->jabber_file_transfer_port[0] = 0; dst->jabber_file_transfer_port[1] = 0; } else if (dst->jabber_file_transfer_port[0] == packet->tcp->dest || dst->jabber_file_transfer_port[0] == packet->tcp->source || dst->jabber_file_transfer_port[1] == packet->tcp->dest || dst->jabber_file_transfer_port[1] == packet->tcp->source) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "found jabber file transfer.\n"); ndpi_int_jabber_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER); } } return; } if (packet->tcp != 0 && packet->payload_packet_len == 0) { return; } /* this part parses a packet and searches for port=. it works asymmetrically. */ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNENCRYPED_JABBER) { u_int16_t lastlen; u_int16_t j_port = 0; /* check for google jabber voip connections ... */ /* need big packet */ if (packet->payload_packet_len < 100) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "packet too small, return.\n"); return; } /* need message to or type for file-transfer */ if (memcmp(packet->payload, "<iq from=\"", 8) == 0 || memcmp(packet->payload, "<iq from=\'", 8) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER <iq from=\".\n"); lastlen = packet->payload_packet_len - 11; for (x = 10; x < lastlen; x++) { if (packet->payload[x] == 'p') { if (memcmp(&packet->payload[x], "port=", 5) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "port=\n"); if (src != NULL) { src->jabber_stun_or_ft_ts = packet->tick_timestamp; } if (dst != NULL) { dst->jabber_stun_or_ft_ts = packet->tick_timestamp; } x += 6; j_port = ntohs_ndpi_bytestream_to_number(&packet->payload[x], packet->payload_packet_len, &x); NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER port : %u\n", ntohs(j_port)); if (src != NULL) { if (src->jabber_file_transfer_port[0] == 0 || src->jabber_file_transfer_port[0] == j_port) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[0] = j_port; } else { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[1] = j_port; } } if (dst != NULL) { if (dst->jabber_file_transfer_port[0] == 0 || dst->jabber_file_transfer_port[0] == j_port) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[0] = j_port; } else { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[1] = j_port; } } } } } } else if (memcmp(packet->payload, "<iq to=\"", 8) == 0 || memcmp(packet->payload, "<iq to=\'", 8) == 0 || memcmp(packet->payload, "<iq type=", 9) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER <iq to=\"/type=\"\n"); lastlen = packet->payload_packet_len - 21; for (x = 8; x < lastlen; x++) { /* invalid character */ if (packet->payload[x] < 32 || packet->payload[x] > 127) { return; } if (packet->payload[x] == '@') { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER @\n"); break; } } if (x >= lastlen) { return; } lastlen = packet->payload_packet_len - 10; for (; x < lastlen; x++) { if (packet->payload[x] == 'p') { if (memcmp(&packet->payload[x], "port=", 5) == 0) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "port=\n"); if (src != NULL) { src->jabber_stun_or_ft_ts = packet->tick_timestamp; } if (dst != NULL) { dst->jabber_stun_or_ft_ts = packet->tick_timestamp; } x += 6; j_port = ntohs_ndpi_bytestream_to_number(&packet->payload[x], packet->payload_packet_len, &x); NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER port : %u\n", ntohs(j_port)); if (src != NULL && src->jabber_voice_stun_used_ports < JABBER_MAX_STUN_PORTS - 1) { if (packet->payload[5] == 'o') { src->jabber_voice_stun_port[src->jabber_voice_stun_used_ports++] = j_port; } else { if (src->jabber_file_transfer_port[0] == 0 || src->jabber_file_transfer_port[0] == j_port) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[0] = j_port; } else { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); src->jabber_file_transfer_port[1] = j_port; } } } if (dst != NULL && dst->jabber_voice_stun_used_ports < JABBER_MAX_STUN_PORTS - 1) { if (packet->payload[5] == 'o') { dst->jabber_voice_stun_port[dst->jabber_voice_stun_used_ports++] = j_port; } else { if (dst->jabber_file_transfer_port[0] == 0 || dst->jabber_file_transfer_port[0] == j_port) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[0] = j_port; } else { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[1] = j_port = %u;\n", ntohs(j_port)); dst->jabber_file_transfer_port[1] = j_port; } } } return; } } } } return; } /* search for jabber here */ /* this part is working asymmetrically */ if ((packet->payload_packet_len > 13 && memcmp(packet->payload, "<?xml version=", 14) == 0) || (packet->payload_packet_len >= NDPI_STATICSTRING_LEN("<stream:stream ") && memcmp(packet->payload, "<stream:stream ", NDPI_STATICSTRING_LEN("<stream:stream ")) == 0)) { int start = packet->payload_packet_len-13; if(ndpi_strnstr((const char *)&packet->payload[13], "xmlns:stream='http://etherx.jabber.org/streams'", start) || ndpi_strnstr((const char *)&packet->payload[13], "xmlns:stream=\"http://etherx.jabber.org/streams\"", start)) { /* Protocol family */ ndpi_int_jabber_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER); /* search for subprotocols */ check_content_type_and_change_protocol(ndpi_struct, flow, 13); return; } } if (flow->packet_counter < 3) { NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "packet_counter: %u\n", flow->packet_counter); return; } NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_TRACE, "JABBER Excluded.\n"); NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER); #ifdef NDPI_PROTOCOL_TRUPHONE NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TRUPHONE); #endif }
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); }