Coverage Report

Created: 2025-11-02 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ndpi/src/lib/protocols/line.c
Line
Count
Source
1
/*
2
 * line.c
3
 *
4
 * Copyright (C) 2022-23 - ntop.org
5
 *
6
 * nDPI is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * nDPI is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with nDPI.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 */
20
21
22
#include "ndpi_protocol_ids.h"
23
24
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_LINE_CALL
25
26
#include "ndpi_api.h"
27
#include "ndpi_private.h"
28
29
static void ndpi_int_line_add_connection(struct ndpi_detection_module_struct * const ndpi_struct,
30
                                         struct ndpi_flow_struct * const flow)
31
0
{
32
0
  NDPI_LOG_INFO(ndpi_struct, "found LineCall\n");
33
0
  ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_UNKNOWN,
34
0
                             NDPI_PROTOCOL_LINE_CALL, NDPI_CONFIDENCE_DPI);
35
0
}
36
37
static void ndpi_search_line(struct ndpi_detection_module_struct *ndpi_struct,
38
                             struct ndpi_flow_struct *flow)
39
0
{
40
0
  struct ndpi_packet_struct const * const packet = &ndpi_struct->packet;
41
0
  int rc;
42
43
0
  NDPI_LOG_DBG(ndpi_struct, "searching LineCall\n");
44
45
0
  if(packet->iph && (flow->guessed_protocol_id_by_ip == NDPI_PROTOCOL_LINE)) {
46
    /*
47
      The heuristic below (coming from reverse engineering packet traces)
48
      will apply only to IPv4 and Line IP addresses. This is to avoid puttin
49
      false positives in other nDPI-decoded protocols.
50
    */
51
52
0
    if ((packet->payload_packet_len == 110 &&
53
0
   ndpi_struct->packet.payload[0] == 0xB6 &&  ndpi_struct->packet.payload[1] == 0x18 && ndpi_struct->packet.payload[2] == 0x00 && ndpi_struct->packet.payload[3] == 0x6A) ||
54
0
  (packet->payload_packet_len >= 738 && (ndpi_struct->packet.payload[0] == 0xDA || ndpi_struct->packet.payload[0] == 0xDB) &&
55
0
   ndpi_struct->packet.payload[4] == 0x06 && ndpi_struct->packet.payload[5] == 0x02) ||
56
0
  (packet->payload_packet_len >= 150 && (ndpi_struct->packet.payload[0] == 0xD9 || ndpi_struct->packet.payload[0] == 0xD8) &&
57
0
   ((ndpi_struct->packet.payload[1] & 0xF0) == 0x90 || (ndpi_struct->packet.payload[1] & 0xF0) == 0xD0 || (ndpi_struct->packet.payload[1] & 0xF0) == 0xE0) && ndpi_struct->packet.payload[4] == 0x06 &&
58
0
   ndpi_struct->packet.payload[5] == 0x02)) {
59
0
      ndpi_int_line_add_connection(ndpi_struct, flow);
60
0
      return;
61
0
    }
62
63
0
    if ((packet->payload_packet_len == 46 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xb6130006) ||
64
0
  (packet->payload_packet_len == 8 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xb6070004) ||
65
0
  (packet->payload_packet_len == 16 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xb609000c) ||
66
0
  (packet->payload_packet_len >= 2 /* TODO */ && ndpi_struct->packet.payload[0] == 0xD0 &&
67
0
   (ndpi_struct->packet.payload[1] == 0xB3 || ndpi_struct->packet.payload[1] == 0xB4
68
0
    || ndpi_struct->packet.payload[1] == 0xDA || ndpi_struct->packet.payload[1] == 0xDB))) {
69
0
      ndpi_int_line_add_connection(ndpi_struct, flow);
70
0
      return;
71
0
    }
72
0
  }
73
74
  /* Some "random" UDP packets before the standard RTP stream:
75
     it seems that the 4th bytes of these packets is some kind of packet
76
     number. Look for 4 packets per direction with consecutive numbers. */
77
0
  if(packet->payload_packet_len > 10) {
78
0
    if(flow->l4.udp.line_pkts[packet->packet_direction] == 0) {
79
0
      flow->l4.udp.line_base_cnt[packet->packet_direction] = packet->payload[3];
80
0
      flow->l4.udp.line_pkts[packet->packet_direction] += 1;
81
0
      return;
82
0
    } else {
83
      /* It might be a RTP/RTCP packet. Ignore it and keep looking for the
84
         LINE packet numbers */
85
      /* Basic RTP detection */
86
0
      rc = is_rtp_or_rtcp(ndpi_struct, packet->payload, packet->payload_packet_len, NULL);
87
0
      if(rc == IS_RTCP || rc == IS_RTP) {
88
0
        if(flow->packet_counter < 10) {
89
0
          NDPI_LOG_DBG(ndpi_struct, "Probably RTP; keep looking for LINE\n");
90
0
          return;
91
0
  }
92
0
      } else {
93
0
        if((u_int8_t)(flow->l4.udp.line_base_cnt[packet->packet_direction] +
94
0
                      flow->l4.udp.line_pkts[packet->packet_direction]) == packet->payload[3]) {
95
0
          flow->l4.udp.line_pkts[packet->packet_direction] += 1;
96
0
          if(flow->l4.udp.line_pkts[0] >= 4 && flow->l4.udp.line_pkts[1] >= 4) {
97
            /* To avoid false positives: usually "base pkt numbers" per-direction are different */
98
0
            if(flow->l4.udp.line_base_cnt[0] != flow->l4.udp.line_base_cnt[1])
99
0
              ndpi_int_line_add_connection(ndpi_struct, flow);
100
0
            else
101
0
              NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
102
0
    }
103
0
          return;
104
0
        }
105
0
      }
106
0
    }
107
0
  }
108
109
0
  NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
110
0
  return;
111
0
}
112
113
void init_line_dissector(struct ndpi_detection_module_struct *ndpi_struct)
114
0
{
115
0
  register_dissector("LineCall", ndpi_struct,
116
0
                     ndpi_search_line,
117
0
                     NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
118
0
                      1, NDPI_PROTOCOL_LINE_CALL);
119
0
}