Ejemplo n.º 1
0
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);
    }
  }
}
Ejemplo n.º 2
0
static u_int8_t ndpi_int_search_bittorrent_tcp_zero(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 a = 0;

  if (packet->payload_packet_len == 1 && packet->payload[0] == 0x13) {
    /* reset stage back to 0 so we will see the next packet here too */
    flow->bittorrent_stage = 0;
    return 0;
  }
  if (flow->packet_counter == 2 && packet->payload_packet_len > 20) {

    if (memcmp(&packet->payload[0], "BitTorrent protocol", 19) == 0) {
      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 1;
    }
  }


  if (packet->payload_packet_len > 20) {
    /* test for match 0x13+"BitTorrent protocol" */
    if (packet->payload[0] == 0x13) {
      if (memcmp(&packet->payload[1], "BitTorrent protocol", 19) == 0) {
	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 1;
      }
    }
  }

  if (packet->payload_packet_len > 23 && memcmp(packet->payload, "GET /webseed?info_hash=", 23) == 0) {
    NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
	     NDPI_LOG_TRACE, "BT: plain webseed BitTorrent protocol detected\n");
    ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
				      NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
				      NDPI_CORRELATED_PROTOCOL);
    return 1;
  }
  /* seen Azureus as server for webseed, possibly other servers existing, to implement */
  /* is Server: hypertracker Bittorrent? */
  /* no asymmetric detection possible for answer of pattern "GET /data?fid=". */
  if (packet->payload_packet_len > 60
      && memcmp(packet->payload, "GET /data?fid=", 14) == 0 && memcmp(&packet->payload[54], "&size=", 6) == 0) {
    NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
	     NDPI_LOG_TRACE, "BT: plain Bitcomet persistent seed protocol detected\n");
    ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
				      NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
				      NDPI_CORRELATED_PROTOCOL);
    return 1;
  }


  if (packet->payload_packet_len > 90 && (memcmp(packet->payload, "GET ", 4) == 0
					  || memcmp(packet->payload, "POST ", 5) == 0)) {
    const u_int8_t *ptr = &packet->payload[4];
    u_int16_t len = packet->payload_packet_len - 4;
    a = 0;


    /* parse complete get packet here into line structure elements */
    ndpi_parse_packet_line_info(ndpi_struct, flow);
    /* answer to this pattern is HTTP....Server: hypertracker */
    if (packet->user_agent_line.ptr != NULL
	&& ((packet->user_agent_line.len > 8 && memcmp(packet->user_agent_line.ptr, "Azureus ", 8) == 0)
	    || (packet->user_agent_line.len >= 10 && memcmp(packet->user_agent_line.ptr, "BitTorrent", 10) == 0)
	    || (packet->user_agent_line.len >= 11 && memcmp(packet->user_agent_line.ptr, "BTWebClient", 11) == 0))) {
      NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
	       NDPI_LOG_TRACE, "Azureus /Bittorrent user agent line detected\n");
      ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
					NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
					NDPI_CORRELATED_PROTOCOL);
      return 1;
    }

    if (packet->user_agent_line.ptr != NULL
	&& (packet->user_agent_line.len >= 9 && memcmp(packet->user_agent_line.ptr, "Shareaza ", 9) == 0)
	&& (packet->parsed_lines > 8 && packet->line[8].ptr != 0
	    && packet->line[8].len >= 9 && memcmp(packet->line[8].ptr, "X-Queue: ", 9) == 0)) {
      NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
	       NDPI_LOG_TRACE, "Bittorrent Shareaza detected.\n");
      ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
					NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
					NDPI_CORRELATED_PROTOCOL);
      return 1;
    }

    /* this is a self built client, not possible to catch asymmetrically */
    if ((packet->parsed_lines == 10 || (packet->parsed_lines == 11 && packet->line[11].len == 0))
	&& packet->user_agent_line.ptr != NULL
	&& packet->user_agent_line.len > 12
	&& memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 ",
		  12) == 0
	&& packet->host_line.ptr != NULL
	&& packet->host_line.len >= 7
	&& packet->line[2].ptr != NULL
	&& packet->line[2].len > 14
	&& memcmp(packet->line[2].ptr, "Keep-Alive: 300", 15) == 0
	&& packet->line[3].ptr != NULL
	&& packet->line[3].len > 21
	&& memcmp(packet->line[3].ptr, "Connection: Keep-alive", 22) == 0
	&& packet->line[4].ptr != NULL
	&& packet->line[4].len > 10
	&& (memcmp(packet->line[4].ptr, "Accpet: */*", 11) == 0
	    || memcmp(packet->line[4].ptr, "Accept: */*", 11) == 0)

	&& packet->line[5].ptr != NULL
	&& packet->line[5].len > 12
	&& memcmp(packet->line[5].ptr, "Range: bytes=", 13) == 0
	&& packet->line[7].ptr != NULL
	&& packet->line[7].len > 15
	&& memcmp(packet->line[7].ptr, "Pragma: no-cache", 16) == 0
	&& packet->line[8].ptr != NULL
	&& packet->line[8].len > 22 && memcmp(packet->line[8].ptr, "Cache-Control: no-cache", 23) == 0) {

      NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "Bitcomet LTS detected\n");
      ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
					NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
					NDPI_CORRELATED_PROTOCOL);
      return 1;

    }

    /* FlashGet pattern */
    if (packet->parsed_lines == 8
	&& packet->user_agent_line.ptr != NULL
	&& packet->user_agent_line.len > (sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1)
	&& memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 (compatible; MSIE 6.0;",
		  sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) == 0
	&& packet->host_line.ptr != NULL
	&& packet->host_line.len >= 7
	&& packet->line[2].ptr != NULL
	&& packet->line[2].len == 11
	&& memcmp(packet->line[2].ptr, "Accept: */*", 11) == 0
	&& packet->line[3].ptr != NULL && packet->line[3].len >= (sizeof("Referer: ") - 1)
	&& memcmp(packet->line[3].ptr, "Referer: ", sizeof("Referer: ") - 1) == 0
	&& packet->line[5].ptr != NULL
	&& packet->line[5].len > 13
	&& memcmp(packet->line[5].ptr, "Range: bytes=", 13) == 0
	&& packet->line[6].ptr != NULL
	&& packet->line[6].len > 21 && memcmp(packet->line[6].ptr, "Connection: Keep-Alive", 22) == 0) {

      NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "FlashGet detected\n");
      ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
					NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
					NDPI_CORRELATED_PROTOCOL);
      return 1;

    }
    if (packet->parsed_lines == 7
	&& packet->user_agent_line.ptr != NULL
	&& packet->user_agent_line.len > (sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1)
	&& memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 (compatible; MSIE 6.0;",
		  sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) == 0
	&& packet->host_line.ptr != NULL
	&& packet->host_line.len >= 7
	&& packet->line[2].ptr != NULL
	&& packet->line[2].len == 11
	&& memcmp(packet->line[2].ptr, "Accept: */*", 11) == 0
	&& packet->line[3].ptr != NULL && packet->line[3].len >= (sizeof("Referer: ") - 1)
	&& memcmp(packet->line[3].ptr, "Referer: ", sizeof("Referer: ") - 1) == 0
	&& packet->line[5].ptr != NULL
	&& packet->line[5].len > 21 && memcmp(packet->line[5].ptr, "Connection: Keep-Alive", 22) == 0) {

      NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "FlashGet detected\n");
      ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
					NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
					NDPI_CORRELATED_PROTOCOL);
      return 1;

    }

    /* answer to this pattern is not possible to implement asymmetrically */
    while (1) {
      if (len < 50 || ptr[0] == 0x0d) {
	goto ndpi_end_bt_tracker_check;
      }
      if (memcmp(ptr, "info_hash=", 10) == 0) {
	break;
      }
      len--;
      ptr++;
    }

    NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
	     NDPI_LOG_TRACE, " BT stat: tracker info hash found\n");

    /* len is > 50, so save operation here */
    len -= 10;
    ptr += 10;

    /* parse bt hash */
    for (a = 0; a < 20; a++) {
      if (len < 3) {
	goto ndpi_end_bt_tracker_check;
      }
      if (*ptr == '%') {
	u_int8_t x1 = 0xFF;
	u_int8_t x2 = 0xFF;


	if (ptr[1] >= '0' && ptr[1] <= '9') {
	  x1 = ptr[1] - '0';
	}
	if (ptr[1] >= 'a' && ptr[1] <= 'f') {
	  x1 = 10 + ptr[1] - 'a';
	}
	if (ptr[1] >= 'A' && ptr[1] <= 'F') {
	  x1 = 10 + ptr[1] - 'A';
	}

	if (ptr[2] >= '0' && ptr[2] <= '9') {
	  x2 = ptr[2] - '0';
	}
	if (ptr[2] >= 'a' && ptr[2] <= 'f') {
	  x2 = 10 + ptr[2] - 'a';
	}
	if (ptr[2] >= 'A' && ptr[2] <= 'F') {
	  x2 = 10 + ptr[2] - 'A';
	}

	if (x1 == 0xFF || x2 == 0xFF) {
	  goto ndpi_end_bt_tracker_check;
	}
	ptr += 3;
	len -= 3;
      } else if (*ptr >= 32 && *ptr < 127) {
	ptr++;
	len--;
      } else {
	goto ndpi_end_bt_tracker_check;
      }
    }

    NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
	     NDPI_LOG_TRACE, " BT stat: tracker info hash parsed\n");
    ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
				      NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
				      NDPI_CORRELATED_PROTOCOL);
    return 1;
  }

 ndpi_end_bt_tracker_check:

  if (packet->payload_packet_len == 80) {
    /* Warez 80 Bytes Packet
     * +----------------+---------------+-----------------+-----------------+
     * |20 BytesPattern | 32 Bytes Value| 12 BytesPattern | 16 Bytes Data   |
     * +----------------+---------------+-----------------+-----------------+
     * 20 BytesPattern : 4c 00 00 00 ff ff ff ff 57 00 00 00 00 00 00 00 20 00 00 00
     * 12 BytesPattern : 28 23 00 00 01 00 00 00 10 00 00 00
     * */
    static const char pattern_20_bytes[20] = { 0x4c, 0x00, 0x00, 0x00, 0xff,
					       0xff, 0xff, 0xff, 0x57, 0x00,
					       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
    };
    static const char pattern_12_bytes[12] = { 0x28, 0x23, 0x00, 0x00, 0x01,
					       0x00, 0x00, 0x00, 0x10, 0x00,
					       0x00, 0x00
    };

    /* did not see this pattern anywhere */
    if ((memcmp(&packet->payload[0], pattern_20_bytes, 20) == 0)
	&& (memcmp(&packet->payload[52], pattern_12_bytes, 12) == 0)) {
      NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
	       NDPI_LOG_TRACE, "BT: Warez - 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 1;
    }
  }

  else if (packet->payload_packet_len > 50) {
    if (memcmp(packet->payload, "GET", 3) == 0) {

      ndpi_parse_packet_line_info(ndpi_struct, flow);
      /* haven't fount this pattern anywhere */
      if (packet->host_line.ptr != NULL
	  && packet->host_line.len >= 9 && memcmp(packet->host_line.ptr, "ip2p.com:", 9) == 0) {
	NDPI_LOG(NDPI_PROTOCOL_BITTORRENT,
		 ndpi_struct, NDPI_LOG_TRACE,
		 "BT: Warez - Plain BitTorrent protocol detected due to Host: ip2p.com: pattern\n");
	ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
					  NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
					  NDPI_CORRELATED_PROTOCOL);
	return 1;
      }
    }
  }
  return 0;
}
Ejemplo n.º 3
0
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);
    }
Ejemplo n.º 4
0
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);
    }