Coverage Report

Created: 2025-12-10 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ndpi/src/lib/protocols/telegram.c
Line
Count
Source
1
/*
2
 * telegram.c
3
 *
4
 * Copyright (C) 2012-22 - ntop.org
5
 * Copyright (C) 2014 by Gianluca Costa xplico.org
6
 *
7
 * This file is part of nDPI, an open source deep packet inspection
8
 * library based on the OpenDPI and PACE technology by ipoque GmbH
9
 *
10
 * nDPI is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Lesser General Public License as published by
12
 * the Free Software Foundation, either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * nDPI is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public License
21
 * along with nDPI.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
25
26
#include "ndpi_protocol_ids.h"
27
28
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_TELEGRAM
29
30
#include "ndpi_api.h"
31
#include "ndpi_private.h"
32
33
static void ndpi_int_telegram_add_connection(struct ndpi_detection_module_struct
34
                                             *ndpi_struct, struct ndpi_flow_struct *flow,
35
3.11k
               ndpi_confidence_t confidence) {
36
3.11k
  ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_TELEGRAM, NDPI_PROTOCOL_UNKNOWN, confidence);
37
3.11k
  NDPI_LOG_INFO(ndpi_struct, "found telegram\n");
38
3.11k
}
39
40
760k
static u_int8_t is_telegram_port_range(u_int16_t port) {
41
760k
  if((port >= 500) && (port <= 600))
42
11.2k
    return(1);
43
44
45
749k
  return(0);
46
760k
}
47
48
static void ndpi_search_telegram(struct ndpi_detection_module_struct *ndpi_struct,
49
2.79M
         struct ndpi_flow_struct *flow) {
50
2.79M
  struct ndpi_packet_struct *packet = &ndpi_struct->packet;
51
52
2.79M
  NDPI_LOG_DBG(ndpi_struct, "search telegram\n");
53
54
2.79M
  if(packet->tcp != NULL) {
55
    /* With MTProto 2.0 telegram via app is no longer TLS-based (althought based on TCP/443) so
56
       we need to detect it with Telegram IPs.
57
       Basically, we want a fast classification by ip. Note that, real Telegram traffic over
58
       TLS (i.e. Telegram Web) is correctly classified as TLS/Telegram because TLS dissector
59
       already kicked in.
60
       Let's check every port for the time being */
61
2.17M
    if(flow->guessed_protocol_id_by_ip == NDPI_PROTOCOL_TELEGRAM) {
62
905
      ndpi_int_telegram_add_connection(ndpi_struct, flow, NDPI_CONFIDENCE_MATCH_BY_IP);
63
905
      return;
64
905
    }
65
2.17M
  } else if(packet->udp != NULL) {
66
    /*
67
      The latest telegram protocol
68
      - contains a sequence of 12 consecutive 0xFF packets
69
      - it uses low UDP ports in the 500 range
70
     */
71
72
625k
    if(packet->payload_packet_len >= 40) {
73
383k
      u_int16_t sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
74
75
383k
      if(is_telegram_port_range(sport) || is_telegram_port_range(dport)) {
76
11.2k
  u_int i, found = 0;
77
78
3.20M
  for(i=0; i<packet->payload_packet_len; i++) {
79
3.20M
    if(packet->payload[i] == 0xFF) {
80
5.40k
      found = 1;
81
5.40k
      break;
82
5.40k
    }
83
3.20M
  }
84
85
11.2k
  if(!found) return;
86
87
51.2k
  for(i += 1; i<packet->payload_packet_len; i++) {
88
51.1k
    if(packet->payload[i] == 0xFF)
89
45.8k
      found++;
90
5.23k
    else
91
5.23k
      break;
92
51.1k
  }
93
94
5.40k
  if(found == 12)  {
95
2.21k
    ndpi_int_telegram_add_connection(ndpi_struct, flow, NDPI_CONFIDENCE_DPI);
96
    /* It seems this kind of traffic is used:
97
             * for "normal" stuff (at least years ago... and now? TODO)
98
             * for calls, as a custom encapsulation of STUN/DTLS/RTP packets
99
             Since we are not able to tell the former from the latter, always
100
             switch to STUN dissection. If we find STUN/DTLS/RTP stuff we will
101
             update the classification to something like STUN/Telegram_voip,
102
             otherwise it will remain Telegram */
103
2.21k
    switch_extra_dissection_to_stun(ndpi_struct, flow, 0);
104
2.21k
    return;
105
2.21k
  }
106
5.40k
      }
107
383k
    }
108
625k
  }
109
110
2.78M
  NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
111
2.78M
}
112
113
114
void init_telegram_dissector(struct ndpi_detection_module_struct *ndpi_struct)
115
16.3k
{
116
16.3k
  register_dissector("Telegram", ndpi_struct,
117
16.3k
                     ndpi_search_telegram,
118
16.3k
                     NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
119
16.3k
                     1, NDPI_PROTOCOL_TELEGRAM);
120
16.3k
}