@@ -61,7 +61,8 @@ static int stun_search_again(struct ndpi_detection_module_struct *ndpi_struct,
6161
6262
6363/* Valid classifications:
64- * STUN, DTLS, STUN/RTP, DTLS/SRTP, RTP or RTCP (the last two, only from RTP dissector)
64+ * STUN, DTLS, STUN/RTP, DTLS/SRTP, RTP or RTCP (only from RTP dissector)
65+ and TELEGRAM (only from Telegram dissector, note that TELEGRAM != TELEGRAM_VOIP!!)
6566 * STUN/APP, DTLS/APP, SRTP/APP ["real" sub-classification]
6667 The idea is:
6768 * the specific "real" application (WA/FB/Signal/...), if present, should
@@ -79,7 +80,8 @@ static int is_subclassification_real_by_proto(u_int16_t proto)
7980 proto == NDPI_PROTOCOL_RTP ||
8081 proto == NDPI_PROTOCOL_RTCP ||
8182 proto == NDPI_PROTOCOL_SRTP ||
82- proto == NDPI_PROTOCOL_DTLS )
83+ proto == NDPI_PROTOCOL_DTLS ||
84+ proto == NDPI_PROTOCOL_TELEGRAM )
8385 return 0 ;
8486 return 1 ;
8587}
@@ -493,6 +495,9 @@ int is_stun(struct ndpi_detection_module_struct *ndpi_struct,
493495 * app_proto = NDPI_PROTOCOL_SIGNAL_VOIP ;
494496 }
495497
498+ if (flow -> detected_protocol_stack [0 ] == NDPI_PROTOCOL_TELEGRAM )
499+ * app_proto = NDPI_PROTOCOL_TELEGRAM_VOIP ;
500+
496501 off = STUN_HDR_LEN ;
497502 while (off + 4 < payload_length ) {
498503 u_int16_t attribute = ntohs (* ((u_int16_t * )& payload [off ]));
@@ -783,7 +788,8 @@ static u_int32_t __get_master(struct ndpi_flow_struct *flow) {
783788
784789 if (flow -> detected_protocol_stack [1 ] != NDPI_PROTOCOL_UNKNOWN )
785790 return flow -> detected_protocol_stack [1 ];
786- if (flow -> detected_protocol_stack [0 ] != NDPI_PROTOCOL_UNKNOWN )
791+ if (flow -> detected_protocol_stack [0 ] != NDPI_PROTOCOL_UNKNOWN &&
792+ flow -> detected_protocol_stack [0 ] != NDPI_PROTOCOL_TELEGRAM )
787793 return flow -> detected_protocol_stack [0 ];
788794 return NDPI_PROTOCOL_STUN ;
789795}
@@ -1039,6 +1045,62 @@ static int stun_search_again(struct ndpi_detection_module_struct *ndpi_struct,
10391045
10401046/* ************************************************************ */
10411047
1048+ static int stun_telegram_search_again (struct ndpi_detection_module_struct * ndpi_struct ,
1049+ struct ndpi_flow_struct * flow )
1050+ {
1051+ struct ndpi_packet_struct * packet = & ndpi_struct -> packet ;
1052+ const u_int8_t * orig_payload ;
1053+ u_int16_t orig_payload_length ;
1054+ char pattern [12 ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
1055+ 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF };
1056+ u_int16_t length ;
1057+
1058+ NDPI_LOG_DBG2 (ndpi_struct , "[T] Packet counter %d protos %d/%d Monitoring? %d\n" ,
1059+ flow -> packet_counter ,
1060+ flow -> detected_protocol_stack [0 ], flow -> detected_protocol_stack [1 ],
1061+ flow -> monitoring );
1062+
1063+ /* For SOME of its STUN flows, Telegram uses a custom encapsulation
1064+ There is no documentation. It seems:
1065+ * some unknown packets (especially at the beginning/end of the flow) have a bunch of 0xFF
1066+ * the other packets encapsulate standard STUN/DTLS/RTP payload at offset 24
1067+ (with a previous field containing the payload length)
1068+ */
1069+
1070+ if (packet -> payload_packet_len <= 28 ) {
1071+ NDPI_LOG_DBG (ndpi_struct , "Malformed custom Telegram packet (too short)\n" );
1072+ return keep_extra_dissection (ndpi_struct , flow );
1073+ }
1074+
1075+ if (memcmp (& packet -> payload [16 ], pattern , sizeof (pattern )) == 0 ) {
1076+ NDPI_LOG_DBG (ndpi_struct , "Custom/Unknown Telegram packet\n" );
1077+ return keep_extra_dissection (ndpi_struct , flow );
1078+ }
1079+
1080+ /* It should be STUN/DTLS/RTP */
1081+
1082+ length = ntohs (* (u_int16_t * )& packet -> payload [22 ]);
1083+ if (24 + length > packet -> payload_packet_len ) {
1084+ NDPI_LOG_DBG (ndpi_struct , "Malformed custom Telegram packet (too long: %d %d)\n" ,
1085+ length , packet -> payload_packet_len );
1086+ return keep_extra_dissection (ndpi_struct , flow );
1087+ }
1088+
1089+ orig_payload = packet -> payload ;
1090+ orig_payload_length = packet -> payload_packet_len ;
1091+ packet -> payload = packet -> payload + 24 ;
1092+ packet -> payload_packet_len = length ;
1093+
1094+ stun_search_again (ndpi_struct , flow );
1095+
1096+ packet -> payload = orig_payload ;
1097+ packet -> payload_packet_len = orig_payload_length ;
1098+
1099+ return keep_extra_dissection (ndpi_struct , flow );
1100+ }
1101+
1102+ /* ************************************************************ */
1103+
10421104static u_int64_t get_stun_lru_key (struct ndpi_flow_struct * flow , u_int8_t rev ) {
10431105 if (rev ) {
10441106 if (flow -> is_ipv6 )
@@ -1150,19 +1212,23 @@ static void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *nd
11501212 }
11511213 }
11521214
1153- switch_extra_dissection_to_stun (ndpi_struct , flow );
1215+ switch_extra_dissection_to_stun (ndpi_struct , flow , 1 );
11541216}
11551217
11561218/* ************************************************************ */
11571219
11581220void switch_extra_dissection_to_stun (struct ndpi_detection_module_struct * ndpi_struct ,
1159- struct ndpi_flow_struct * flow )
1221+ struct ndpi_flow_struct * flow ,
1222+ int std_callback )
11601223{
11611224 if (!flow -> extra_packets_func ) {
11621225 if (keep_extra_dissection (ndpi_struct , flow )) {
11631226 NDPI_LOG_DBG (ndpi_struct , "Enabling extra dissection\n" );
11641227 flow -> max_extra_packets_to_check = ndpi_struct -> cfg .stun_max_packets_extra_dissection ;
1165- flow -> extra_packets_func = stun_search_again ;
1228+ if (std_callback )
1229+ flow -> extra_packets_func = stun_search_again ;
1230+ else
1231+ flow -> extra_packets_func = stun_telegram_search_again ;
11661232 }
11671233 }
11681234}
0 commit comments