Coverage Report

Created: 2025-11-09 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ndpi/src/lib/protocols/modbus.c
Line
Count
Source
1
2
/*
3
 * modbus.c
4
 *
5
 * Copyright (C) 2018 - ntop.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
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_MODBUS
28
#include "ndpi_api.h"
29
#include "ndpi_private.h"
30
31
static void ndpi_search_modbus_tcp(struct ndpi_detection_module_struct *ndpi_struct,
32
2.24M
                                   struct ndpi_flow_struct *flow) {
33
2.24M
  struct ndpi_packet_struct *packet = &ndpi_struct->packet;
34
2.24M
  NDPI_LOG_DBG(ndpi_struct, "search Modbus\n");
35
2.24M
  u_int16_t modbus_port = htons(502); // port used by modbus
36
37
  /* Check connection over TCP */
38
    
39
2.24M
  if(packet->tcp) {
40
    /* The payload of Modbus-TCP segment must be at least 8 bytes (7 bytes of header application 
41
       packet plus 1 byte of minimum payload of application packet)
42
    */
43
2.24M
    if((packet->payload_packet_len >= 8) 
44
1.62M
       &&((packet->tcp->dest == modbus_port) || (packet->tcp->source == modbus_port))) {
45
      // Modbus uses the port 502   
46
1.48k
      u_int16_t modbus_len = htons(*((u_int16_t*)&packet->payload[4]));
47
48
      // the fourth parameter of the payload is the length of the segment            
49
1.48k
      if(((modbus_len-1) == (packet->payload_packet_len - 7 /* ModbusTCP header len */))
50
552
   && (packet->payload[2] == 0x0) && (packet->payload[3] == 0x0) /* Protocol identifier */) {
51
  /* Check Modbus function code. 0x5A (90) is reserved for UMAS protocol */
52
390
        if (packet->payload[7] == 0x5A) {
53
138
          NDPI_LOG_INFO(ndpi_struct, "found Schneider Electric UMAS\n");
54
138
          ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_UMAS, NDPI_PROTOCOL_MODBUS, NDPI_CONFIDENCE_DPI);
55
138
          return;
56
138
        }
57
58
252
        NDPI_LOG_INFO(ndpi_struct, "found MODBUS\n");
59
252
        ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MODBUS, NDPI_PROTOCOL_UNKNOWN, NDPI_CONFIDENCE_DPI);
60
252
        return;
61
390
      }
62
1.48k
    }
63
2.24M
  }
64
2.24M
  NDPI_EXCLUDE_DISSECTOR(ndpi_struct, flow);
65
   
66
2.24M
}
67
68
69
70
7.96k
void init_modbus_dissector(struct ndpi_detection_module_struct *ndpi_struct) {
71
72
7.96k
  register_dissector("Modbus", ndpi_struct,
73
7.96k
                     ndpi_search_modbus_tcp,
74
7.96k
                     NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
75
7.96k
                      1, NDPI_PROTOCOL_MODBUS);
76
7.96k
}