Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-mstp.c
Line
Count
Source
1
/* packet-mstp.c
2
 * Routines for BACnet MS/TP datalink dissection
3
 * Copyright 2008 Steve Karg <skarg@users.sourceforge.net> Alabama
4
 *
5
 * This is described in Clause 9 of ANSI/ASHRAE Standard 135-2024,
6
 * BACnet - A Data Communication Protocol for Building Automation
7
 * and Control Networks; clause 9 "describes a Multidrop Serial Bus/Token
8
 * Passing (MS/TP) data link protocol, which provides the same services to the
9
 * network layer as ISO 8802-2 Logical Link Control. It uses services
10
 * provided by the EIA-485 physical layer."  See section 9.3 for the
11
 * frame format.
12
 *
13
 * Wireshark - Network traffic analyzer
14
 * By Gerald Combs <gerald@wireshark.org>
15
 * Copyright 1998 Gerald Combs
16
 *
17
 * SPDX-License-Identifier: GPL-2.0-or-later
18
 */
19
20
#include "config.h"
21
22
#include <epan/packet.h>
23
#include <wiretap/wtap.h>
24
#include <epan/expert.h>
25
#include <epan/address_types.h>
26
#include <epan/to_str.h>
27
#include <epan/crc16-tvb.h>
28
#include <epan/exceptions.h>
29
#include "packet-mstp.h"
30
31
void proto_register_mstp(void);
32
void proto_reg_handoff_mstp(void);
33
34
/* Probably should be a preference, but here for now */
35
#define BACNET_MSTP_SUMMARY_IN_TREE
36
#define BACNET_MSTP_CHECKSUM_VALIDATE
37
38
/* MS/TP Frame Type */
39
/* Frame Types 8 through 31 and 35 through 127 are reserved by ASHRAE. */
40
#define MSTP_TOKEN                                    0x00
41
#define MSTP_POLL_FOR_MANAGER                         0x01
42
#define MSTP_REPLY_TO_POLL_FOR_MANAGER                0x02
43
#define MSTP_TEST_REQUEST                             0x03
44
#define MSTP_TEST_RESPONSE                            0x04
45
16
#define MSTP_BACNET_DATA_EXPECTING_REPLY              0x05
46
16
#define MSTP_BACNET_DATA_NOT_EXPECTING_REPLY          0x06
47
#define MSTP_REPLY_POSTPONED                          0x07
48
16
#define MSTP_BACNET_EXTENDED_DATA_EXPECTING_REPLY     0x20
49
16
#define MSTP_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY 0x21
50
16
#define MSTP_IPV6_ENCAPSULATION                       0x22
51
52
/* Frame Types 32 through 127 are COBS-encoded (Nmin_COBS_type through
53
 * Nmax_COBS_type in Clause 9). */
54
2
#define MSTP_COBS_TYPE_MIN                            32
55
1
#define MSTP_COBS_TYPE_MAX                            127
56
57
/* Valid Length of any COBS-encoded frame: Nmin_COBS_length through
58
 * Nmax_COBS_length (Clause 9.5.3). */
59
3
#define MSTP_COBS_LENGTH_MIN                          5
60
2
#define MSTP_COBS_LENGTH_MAX                          2043
61
62
/* BACnet NPDUs of 502 through 1497 octets go in Frame Types 32 and 33,
63
 * smaller ones in Frame Types 5 and 6 (Clauses 9.2 and 9.3; tested by
64
 * ANSI/ASHRAE 135.1 12.1.3.20). */
65
0
#define MSTP_BACNET_EXTENDED_NPDU_MIN                 502
66
0
#define MSTP_BACNET_EXTENDED_NPDU_MAX                 1497
67
68
/* Largest Length of an IPv6 over MS/TP frame: a 1500-octet IPv6 packet
69
 * becomes an MSDU of at most 1501 octets, plus at most 6 octets of COBS
70
 * overhead, plus 3 (draft-ietf-6lo-rfc8163-bis; RFC 8163 says 1509). */
71
0
#define MSTP_IPV6_LENGTH_MAX                          1510
72
73
74
static const value_string
75
bacnet_mstp_frame_type_name[] = {
76
  {MSTP_TOKEN,                                    "Token"},
77
  {MSTP_POLL_FOR_MANAGER,                         "Poll For Manager"},
78
  {MSTP_REPLY_TO_POLL_FOR_MANAGER,                "Reply To Poll For Manager"},
79
  {MSTP_TEST_REQUEST,                             "Test_Request"},
80
  {MSTP_TEST_RESPONSE,                            "Test_Response"},
81
  {MSTP_BACNET_DATA_EXPECTING_REPLY,              "BACnet Data Expecting Reply"},
82
  {MSTP_BACNET_DATA_NOT_EXPECTING_REPLY,          "BACnet Data Not Expecting Reply"},
83
  {MSTP_REPLY_POSTPONED,                          "Reply Postponed"},
84
  {MSTP_BACNET_EXTENDED_DATA_EXPECTING_REPLY,     "BACnet Extended Data Expecting Reply"},
85
  {MSTP_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY, "BACnet Extended Data Not Expecting Reply"},
86
  {MSTP_IPV6_ENCAPSULATION,                       "IPv6 over MS/TP (LoBAC) Encapsulation"},
87
  /* Frame Types 128 through 255: Proprietary Frames */
88
  {0, NULL }
89
};
90
91
static dissector_table_t subdissector_table;
92
93
static int proto_mstp;
94
95
static int ett_bacnet_mstp;
96
97
static int hf_mstp_preamble_55;
98
static int hf_mstp_preamble_FF;
99
static int hf_mstp_frame_type;
100
static int hf_mstp_frame_destination;
101
static int hf_mstp_frame_source;
102
static int hf_mstp_frame_vendor_id;
103
static int hf_mstp_frame_pdu_len;
104
static int hf_mstp_frame_crc8;
105
static int hf_mstp_frame_crc16;
106
static int hf_mstp_frame_crc32k;
107
static int hf_mstp_frame_checksum_status;
108
109
static expert_field ei_mstp_frame_pdu_len;
110
static expert_field ei_mstp_frame_checksum_bad;
111
static expert_field ei_mstp_cobs_bad;
112
static expert_field ei_mstp_bacnet_npdu_len;
113
static expert_field ei_mstp_ipv6_len;
114
115
static int mstp_address_type = -1;
116
117
static dissector_handle_t mstp_handle;
118
119
#if defined(BACNET_MSTP_CHECKSUM_VALIDATE)
120
/* Accumulate "dataValue" into the CRC in crcValue. */
121
/* Return value is updated CRC */
122
/*  The ^ operator means exclusive OR. */
123
/* Note: This function is copied directly from the BACnet standard. */
124
static uint8_t
125
CRC_Calc_Header(
126
  uint8_t dataValue,
127
  uint8_t crcValue)
128
5
{
129
5
  uint16_t crc;
130
131
5
  crc = crcValue ^ dataValue; /* XOR C7..C0 with D7..D0 */
132
133
  /* Exclusive OR the terms in the table (top down) */
134
5
  crc = crc ^ (crc << 1) ^ (crc << 2) ^ (crc << 3)
135
5
    ^ (crc << 4) ^ (crc << 5) ^ (crc << 6)
136
5
    ^ (crc << 7);
137
138
  /* Combine bits shifted out left hand end */
139
5
  return (crc & 0xfe) ^ ((crc >> 8) & 1);
140
5
}
141
#endif
142
143
/* Common frame type text */
144
const char *
145
mstp_frame_type_text(wmem_allocator_t* scope, uint32_t val)
146
2
{
147
2
  return val_to_str(scope, val,
148
2
    bacnet_mstp_frame_type_name,
149
2
    "Unknown Frame Type (%u)");
150
2
}
151
152
static int mstp_str_len(const address* addr _U_)
153
0
{
154
0
  return 5;
155
0
}
156
157
static int mstp_to_str(const address* addr, char *buf, int buf_len _U_)
158
0
{
159
0
  *buf++ = '0';
160
0
  *buf++ = 'x';
161
0
  buf = bytes_to_hexstr(buf, (const uint8_t *)addr->data, 1);
162
0
  *buf = '\0'; /* NULL terminate */
163
164
0
  return mstp_str_len(addr);
165
0
}
166
167
static const char* mstp_col_filter_str(const address* addr _U_, bool is_src)
168
0
{
169
0
  if (is_src)
170
0
    return "mstp.src";
171
172
0
  return "mstp.dst";
173
0
}
174
175
static int mstp_len(void)
176
0
{
177
0
  return 1;
178
0
}
179
180
/* See ANSI/ASHRAE Standard 135-2024 [BACnet], Annex G.3.1 */
181
1
#define CRC32K_INITIAL_VALUE  0xFFFFFFFF
182
/* CRC-32K polynomial, 1 + x**1 + ... + x**30 (+ x**32) */
183
2.79k
#define CRC32K_POLY   0xEB31D82E
184
185
/*
186
 * Accumulate 'data_value' into the CRC in 'crc_value'.
187
 * Return updated CRC.
188
 *
189
 * Note: crc_value must be set to CRC32K_INITIAL_VALUE
190
 * before initial call.
191
 */
192
static uint32_t
193
calc_crc32K(uint8_t data_value, uint32_t crc_value)
194
688
{
195
688
  int b;
196
197
6.19k
  for (b = 0; b < 8; b++) {
198
5.50k
    if ((data_value & 1) ^ (crc_value & 1)) {
199
2.79k
      crc_value >>= 1;
200
2.79k
      crc_value ^= CRC32K_POLY;
201
2.79k
    } else {
202
2.70k
      crc_value >>= 1;
203
2.70k
    }
204
5.50k
    data_value >>= 1;
205
5.50k
  }
206
688
  return crc_value;
207
688
}
208
209
typedef enum {
210
  COBS_OK,
211
  COBS_BAD_OCTET, /* an encoded octet equals the mask (an encoded zero) */
212
  COBS_OVERRUN  /* a code octet runs past the end of the data */
213
} cobs_result_t;
214
215
/*
216
 * Decodes 'length' octets of COBS-encoded data at 'from', removing the
217
 * 'mask' applied to every encoded octet, and writes the decoded data at
218
 * 'to'. Sets '*decoded_len' to the number of octets written.
219
 *
220
 * On error, sets '*error_offset' to the offset of the octet in error,
221
 * and 'to' holds the octets decoded before the error (for a code octet
222
 * that runs past the end, the data octets that follow it).
223
 * Note: Safe to call with 'to' <= 'from' (decodes in place).
224
 *
225
 * Based on the reference code in ANSI/ASHRAE 135-2024, extended to
226
 * report where decoding fails and to reject encoded zero data octets,
227
 * which COBS never produces.
228
 */
229
static cobs_result_t
230
cobs_decode(uint8_t *to, const uint8_t *from, size_t length, uint8_t mask,
231
  size_t *decoded_len, size_t *error_offset)
232
1
{
233
1
  size_t read_index = 0;
234
1
  size_t write_index = 0;
235
1
  cobs_result_t result = COBS_OK;
236
1
  uint8_t code;
237
1
  uint8_t last_code;
238
1
  uint8_t data;
239
240
16
  while (read_index < length) {
241
16
    code = from[read_index] ^ mask;
242
16
    last_code = code;
243
    /*
244
     * A code octet equal to zero or greater than the length is
245
     * illegal. For the latter, keep the data octets that are there,
246
     * for display.
247
     */
248
16
    if (code == 0) {
249
0
      *error_offset = read_index;
250
0
      result = COBS_BAD_OCTET;
251
0
      break;
252
0
    }
253
16
    if (read_index + code > length) {
254
1
      *error_offset = read_index;
255
1
      result = COBS_OVERRUN;
256
1
      code = (uint8_t)(length - read_index);
257
1
    }
258
259
16
    read_index++;
260
    /*
261
     * Decode data octets. The code octet is included in the length,
262
     * but the terminating zero octet is not. A data octet of zero
263
     * cannot occur, since the whole point of COBS encoding is to
264
     * remove zeroes.
265
     */
266
688
    while (--code > 0) {
267
672
      data = from[read_index] ^ mask;
268
672
      if (data == 0) {
269
0
        *error_offset = read_index;
270
0
        result = COBS_BAD_OCTET;
271
0
        break;
272
0
      }
273
672
      to[write_index++] = data;
274
672
      read_index++;
275
672
    }
276
16
    if (result != COBS_OK)
277
1
      break;
278
279
    /*
280
     * Restore the implicit zero at the end of each decoded block
281
     * except when it contains exactly 254 non-zero octets or the
282
     * end of data has been reached.
283
     */
284
15
    if ((last_code != 255) && (read_index < length))
285
15
      to[write_index++] = 0;
286
15
  }
287
288
1
  *decoded_len = write_index;
289
1
  return result;
290
1
}
291
292
1
#define MSTP_ENC_CRC32K_LEN (5)  /* the Encoded CRC-32K field is always 5 octets */
293
689
#define MSTP_PREAMBLE_X55 (0x55)
294
295
static void
296
mstp_cobs_error(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
297
  unsigned offset, cobs_result_t result, const char *field)
298
0
{
299
0
  if (result == COBS_BAD_OCTET) {
300
0
    proto_tree_add_expert_format(tree, pinfo, &ei_mstp_cobs_bad, tvb,
301
0
      offset, 1,
302
0
      "Octet 0x55 (an encoded zero) in the %s field: octets may be missing, or the frame ended early",
303
0
      field);
304
0
  } else {
305
0
    proto_tree_add_expert_format(tree, pinfo, &ei_mstp_cobs_bad, tvb,
306
0
      offset, 1,
307
0
      "COBS code octet runs past the end of the %s field: octets may be missing or corrupted",
308
0
      field);
309
0
  }
310
0
}
311
312
/*
313
 * Dissects the Encoded Data and Encoded CRC-32K fields of a COBS-encoded
314
 * frame (Frame Types 32 through 127). The Length field is two octets less
315
 * than the encoded data plus the 5-octet Encoded CRC-32K, so that devices
316
 * that do not know about COBS-encoded frames can skip them as unknown.
317
 * The CRC-32K is calculated over the encoded data.
318
 */
319
static void
320
dissect_mstp_cobs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
321
  proto_tree *subtree, unsigned offset, uint8_t frame_type,
322
  uint32_t frame_pdu_len, proto_item *len_item)
323
1
{
324
1
  unsigned encoded_len = frame_pdu_len + 2;
325
1
  unsigned captured_len;
326
1
  unsigned data_len;
327
1
  unsigned scan_len;
328
1
  unsigned bad_offset = 0;
329
1
  const char *bad_field = NULL;
330
1
  cobs_result_t bad_result = COBS_OK;
331
1
  uint8_t *buf;
332
1
  size_t decoded_len = 0;
333
1
  size_t error_offset = 0;
334
1
  size_t crc_len = 0;
335
1
  size_t crc_error_offset = 0;
336
1
  cobs_result_t result;
337
1
  uint32_t crc32k = CRC32K_INITIAL_VALUE;
338
1
  tvbuff_t *decoded_tvb;
339
1
  tvbuff_t *payload_tvb;
340
1
  unsigned i;
341
342
  /* Too short to hold the Encoded CRC-32K (dissect_mstp() reports it). */
343
1
  if (encoded_len < MSTP_ENC_CRC32K_LEN) {
344
0
    call_data_dissector(tvb_new_subset_length(tvb, offset, encoded_len),
345
0
      pinfo, tree);
346
0
    return;
347
0
  }
348
349
  /*
350
   * Decode what was captured, even if the frame is shorter than the
351
   * Length field says (the length check in dissect_mstp() flags that).
352
   */
353
1
  captured_len = MIN(tvb_captured_length_remaining(tvb, offset), encoded_len);
354
1
  if (captured_len == 0)
355
0
    return;
356
1
  data_len = MIN(captured_len, encoded_len - MSTP_ENC_CRC32K_LEN);
357
1
  buf = (uint8_t *)tvb_memdup(pinfo->pool, tvb, offset, captured_len);
358
359
  /*
360
   * COBS never produces an encoded zero (0x55), so the first 0x55 marks
361
   * where the frame went wrong, typically because octets were lost and
362
   * the next frame's preamble was read as part of this one. Only the
363
   * octets before it are decoded.
364
   */
365
689
  for (scan_len = 0; scan_len < captured_len; scan_len++) {
366
688
    if (buf[scan_len] == MSTP_PREAMBLE_X55)
367
0
      break;
368
688
  }
369
370
  /*
371
   * The CRC-32K covers the encoded data, so calculate it before
372
   * decoding in place.
373
   */
374
689
  for (i = 0; i < data_len; i++)
375
688
    crc32k = calc_crc32K(buf[i], crc32k);
376
377
1
  result = cobs_decode(buf, buf, MIN(data_len, scan_len),
378
1
    MSTP_PREAMBLE_X55, &decoded_len, &error_offset);
379
380
1
  if (scan_len < captured_len) {
381
0
    bad_result = COBS_BAD_OCTET;
382
0
    bad_offset = scan_len;
383
0
    bad_field = (scan_len < data_len) ? "Encoded Data" : "Encoded CRC-32K";
384
1
  } else if (result != COBS_OK) {
385
    /* Running out of data is expected in a frame that was cut short. */
386
1
    if (!(result == COBS_OVERRUN && captured_len < encoded_len)) {
387
0
      bad_result = result;
388
0
      bad_offset = (unsigned)error_offset;
389
0
      bad_field = "Encoded Data";
390
0
    }
391
1
  } else if (captured_len == encoded_len) {
392
0
    result = cobs_decode(buf + decoded_len, buf + data_len,
393
0
      MSTP_ENC_CRC32K_LEN, MSTP_PREAMBLE_X55,
394
0
      &crc_len, &crc_error_offset);
395
0
    if (result == COBS_OK && crc_len == sizeof(uint32_t)) {
396
0
      decoded_tvb = tvb_new_child_real_data(tvb, buf,
397
0
        (unsigned)(decoded_len + crc_len),
398
0
        (unsigned)(decoded_len + crc_len));
399
0
      add_new_data_source(pinfo, decoded_tvb, "Decoded Data and CRC32K");
400
401
      /*
402
       * Compares received CRC-32K to computed CRC-32K.
403
       * The CRC-32K is sent least significant octet first. Like
404
       * the Ethernet FCS, show it as the octets appear on the wire.
405
       */
406
0
      proto_tree_add_checksum(subtree, decoded_tvb, (unsigned)decoded_len,
407
0
        hf_mstp_frame_crc32k, hf_mstp_frame_checksum_status,
408
0
        &ei_mstp_frame_checksum_bad, pinfo,
409
0
        GUINT32_SWAP_LE_BE(~crc32k), ENC_BIG_ENDIAN,
410
0
        PROTO_CHECKSUM_VERIFY);
411
412
0
      if ((frame_type == MSTP_BACNET_EXTENDED_DATA_EXPECTING_REPLY ||
413
0
           frame_type == MSTP_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY) &&
414
0
          (decoded_len < MSTP_BACNET_EXTENDED_NPDU_MIN ||
415
0
           decoded_len > MSTP_BACNET_EXTENDED_NPDU_MAX)) {
416
0
        expert_add_info_format(pinfo, len_item, &ei_mstp_bacnet_npdu_len,
417
0
          "BACnet NPDU of %u octets: Frame Types 32 and 33 carry NPDUs of %u to %u octets",
418
0
          (unsigned)decoded_len, (unsigned)MSTP_BACNET_EXTENDED_NPDU_MIN,
419
0
          (unsigned)MSTP_BACNET_EXTENDED_NPDU_MAX);
420
0
      }
421
422
0
      if (decoded_len > 0) {
423
0
        payload_tvb = tvb_new_subset_length(decoded_tvb, 0,
424
0
          (unsigned)decoded_len);
425
        /* Dissect the payload even if the CRC-32K is bad. */
426
0
        if (!dissector_try_uint(subdissector_table,
427
0
          (0/*VendorID ASHRAE*/ << 16) + frame_type,
428
0
          payload_tvb, pinfo, tree)) {
429
0
          call_data_dissector(payload_tvb, pinfo, tree);
430
0
        }
431
0
      }
432
0
      return;
433
0
    }
434
0
    bad_result = (result == COBS_OK) ? COBS_OVERRUN : result;
435
0
    bad_offset = data_len + (unsigned)crc_error_offset;
436
0
    bad_field = "Encoded CRC-32K";
437
0
  }
438
439
  /* Report where decoding failed, and show the octets decoded so far. */
440
1
  if (bad_field != NULL)
441
0
    mstp_cobs_error(subtree, pinfo, tvb, offset + bad_offset, bad_result,
442
0
      bad_field);
443
1
  if (decoded_len > 0) {
444
1
    decoded_tvb = tvb_new_child_real_data(tvb, buf,
445
1
      (unsigned)decoded_len, (unsigned)decoded_len);
446
1
    add_new_data_source(pinfo, decoded_tvb, "Decoded Data (partial)");
447
1
    call_data_dissector(decoded_tvb, pinfo, tree);
448
1
  } else {
449
0
    call_data_dissector(tvb_new_subset_length(tvb, offset, captured_len),
450
0
      pinfo, tree);
451
0
  }
452
1
}
453
454
/* dissects a BACnet MS/TP frame */
455
/* preamble 0x55 0xFF is not included in Cimetrics U+4 output */
456
void
457
dissect_mstp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
458
  proto_tree *subtree, int offset)
459
1
{
460
1
  uint8_t mstp_frame_type = 0;
461
1
  uint32_t mstp_frame_pdu_len = 0; /* PDU length reported in the header */
462
1
  uint16_t mstp_tvb_pdu_len = 0; /* Reported space in parent tvb for PDU */
463
1
  uint16_t vendorid = 0;
464
1
  tvbuff_t *next_tvb = NULL;
465
1
  proto_item *item;
466
1
#if defined(BACNET_MSTP_CHECKSUM_VALIDATE)
467
  /* used to calculate the crc value */
468
1
  uint8_t crc8 = 0xFF;
469
1
  uint16_t crc16;
470
1
  uint8_t crcdata;
471
1
  uint16_t i; /* loop counter */
472
1
#endif
473
474
1
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet");
475
1
  col_set_str(pinfo->cinfo, COL_INFO, "BACnet MS/TP");
476
1
  mstp_frame_type = tvb_get_uint8(tvb, offset);
477
1
  col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
478
1
      mstp_frame_type_text(pinfo->pool, mstp_frame_type));
479
480
  /* Add the items to the tree */
481
1
  proto_tree_add_item(subtree, hf_mstp_frame_type, tvb,
482
1
      offset, 1, ENC_LITTLE_ENDIAN);
483
1
  proto_tree_add_item(subtree, hf_mstp_frame_destination, tvb,
484
1
      offset+1, 1, ENC_LITTLE_ENDIAN);
485
1
  proto_tree_add_item(subtree, hf_mstp_frame_source, tvb,
486
1
      offset+2, 1, ENC_LITTLE_ENDIAN);
487
1
  item = proto_tree_add_item_ret_uint(subtree, hf_mstp_frame_pdu_len, tvb,
488
1
      offset+3, 2, ENC_BIG_ENDIAN, &mstp_frame_pdu_len);
489
1
  mstp_tvb_pdu_len = tvb_reported_length_remaining(tvb, offset+6);
490
  /* check the length - which does not include the crc16 checksum */
491
1
  if (mstp_frame_pdu_len > 0) {
492
1
    if (mstp_frame_pdu_len + 2 > mstp_tvb_pdu_len) {
493
      /* We should get a ContainedBoundsError later. */
494
1
      expert_add_info(pinfo, item, &ei_mstp_frame_pdu_len);
495
1
    }
496
1
  }
497
1
#if defined(BACNET_MSTP_CHECKSUM_VALIDATE)
498
  /* calculate checksum to validate */
499
6
  for (i = 0; i < 5; i++) {
500
5
    crcdata = tvb_get_uint8(tvb, offset+i);
501
5
    crc8 = CRC_Calc_Header(crcdata, crc8);
502
5
  }
503
1
  crc8 = ~crc8;
504
1
  proto_tree_add_checksum(subtree, tvb, offset+5, hf_mstp_frame_crc8, hf_mstp_frame_checksum_status, &ei_mstp_frame_checksum_bad, pinfo, crc8,
505
1
              ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
506
#else
507
  proto_tree_add_checksum(subtree, tvb, offset+5, hf_mstp_frame_crc8, hf_mstp_frame_checksum_status, &ei_mstp_frame_checksum_bad, pinfo, 0,
508
              ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
509
#endif
510
511
  /* dissect BACnet PDU if there is one */
512
1
  offset += 6;
513
514
1
  if (mstp_frame_type >= MSTP_COBS_TYPE_MIN &&
515
1
      mstp_frame_type <= MSTP_COBS_TYPE_MAX) {
516
1
    if (mstp_frame_pdu_len < MSTP_COBS_LENGTH_MIN ||
517
1
        mstp_frame_pdu_len > MSTP_COBS_LENGTH_MAX) {
518
1
      expert_add_info_format(pinfo, item, &ei_mstp_frame_pdu_len,
519
1
        "Length %u is outside %u to %u, the range for COBS-encoded frames",
520
1
        mstp_frame_pdu_len, (unsigned)MSTP_COBS_LENGTH_MIN,
521
1
        (unsigned)MSTP_COBS_LENGTH_MAX);
522
1
    } else if (mstp_frame_type == MSTP_IPV6_ENCAPSULATION &&
523
0
         mstp_frame_pdu_len > MSTP_IPV6_LENGTH_MAX) {
524
0
      expert_add_info(pinfo, item, &ei_mstp_ipv6_len);
525
0
    }
526
    /* COBS-encoded frames must be decoded before they are dissected */
527
1
    if (mstp_frame_pdu_len) {
528
1
      dissect_mstp_cobs(tvb, pinfo, tree, subtree, offset,
529
1
        mstp_frame_type, mstp_frame_pdu_len, item);
530
1
    }
531
1
  }
532
0
  else if (mstp_frame_pdu_len) {
533
    /* frame_pdu_len does not include the 16-bit crc bytes */
534
0
    if (mstp_frame_type < 128) {
535
0
      vendorid = 0;
536
0
      next_tvb = tvb_new_subset_length(tvb, offset,
537
0
        mstp_frame_pdu_len);
538
0
    } else {
539
      /* With Vendor ID */
540
0
      vendorid = tvb_get_ntohs(tvb, offset);
541
542
      /* Write Vendor ID as tree */
543
0
      proto_tree_add_item(subtree, hf_mstp_frame_vendor_id, tvb,
544
0
        offset, 2, ENC_BIG_ENDIAN);
545
546
0
      if (mstp_frame_pdu_len < 2) {
547
0
        expert_add_info_format(pinfo, item, &ei_mstp_frame_pdu_len, "Length field value is not large enough for Vendor ID");
548
        /* Remaining length can't be negative. */
549
0
        THROW(ReportedBoundsError);
550
0
      }
551
      /* NPDU - call the Vendor specific dissector */
552
0
      next_tvb = tvb_new_subset_length(tvb, offset+2,
553
0
        mstp_frame_pdu_len - 2);
554
0
    }
555
556
0
    if (!(dissector_try_uint(subdissector_table, (vendorid<<16) + mstp_frame_type,
557
0
      next_tvb, pinfo, tree))) {
558
        /* Unknown function - dissect the payload as data */
559
0
        call_data_dissector(next_tvb, pinfo, tree);
560
0
    }
561
0
#if defined(BACNET_MSTP_CHECKSUM_VALIDATE)
562
    /* 16-bit checksum - calculate to validate */
563
    /* It is sent least significant octet first */
564
0
    crc16 = crc16_ccitt_tvb_offset(tvb, offset, mstp_frame_pdu_len);
565
566
0
    proto_tree_add_checksum(subtree, tvb, offset+mstp_frame_pdu_len, hf_mstp_frame_crc16, hf_mstp_frame_checksum_status, &ei_mstp_frame_checksum_bad, pinfo, crc16,
567
0
              ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
568
#else
569
    proto_tree_add_checksum(subtree, tvb, offset+mstp_frame_pdu_len, hf_mstp_frame_crc16, hf_mstp_frame_checksum_status, &ei_mstp_frame_checksum_bad, pinfo, 0,
570
              ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
571
#endif
572
0
  }
573
1
}
574
575
static int
576
dissect_mstp_wtap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
577
1
{
578
1
  proto_item *ti;
579
1
  proto_tree *subtree;
580
1
  unsigned offset = 0;
581
1
#ifdef BACNET_MSTP_SUMMARY_IN_TREE
582
1
  uint8_t mstp_frame_type = 0;
583
1
  uint8_t mstp_frame_source = 0;
584
1
  uint8_t mstp_frame_destination = 0;
585
1
#endif
586
587
  /* set the MS/TP MAC address in the source/destination */
588
1
  set_address_tvb(&pinfo->dl_dst, mstp_address_type, 1, tvb, offset+3);
589
1
  copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
590
1
  set_address_tvb(&pinfo->dl_src, mstp_address_type, 1, tvb, offset+4);
591
1
  copy_address_shallow(&pinfo->src, &pinfo->dl_src);
592
593
1
#ifdef BACNET_MSTP_SUMMARY_IN_TREE
594
1
  mstp_frame_type = tvb_get_uint8(tvb, offset+2);
595
1
  mstp_frame_destination = tvb_get_uint8(tvb, offset+3);
596
1
  mstp_frame_source = tvb_get_uint8(tvb, offset+4);
597
1
  ti = proto_tree_add_protocol_format(tree, proto_mstp, tvb, offset, 8,
598
1
    "BACnet MS/TP, Src (%u), Dst (%u), %s",
599
1
    mstp_frame_source, mstp_frame_destination,
600
1
    mstp_frame_type_text(pinfo->pool, mstp_frame_type));
601
#else
602
  ti = proto_tree_add_item(tree, proto_mstp, tvb, offset, 8, ENC_NA);
603
#endif
604
1
  subtree = proto_item_add_subtree(ti, ett_bacnet_mstp);
605
1
  proto_tree_add_item(subtree, hf_mstp_preamble_55, tvb,
606
1
      offset, 1, ENC_LITTLE_ENDIAN);
607
1
  proto_tree_add_item(subtree, hf_mstp_preamble_FF, tvb,
608
1
      offset+1, 1, ENC_LITTLE_ENDIAN);
609
1
  dissect_mstp(tvb, pinfo, tree, subtree, offset+2);
610
1
  return tvb_captured_length(tvb);
611
1
}
612
613
void
614
proto_register_mstp(void)
615
16
{
616
16
  static hf_register_info hf[] = {
617
16
    { &hf_mstp_preamble_55,
618
16
      { "Preamble 55", "mstp.preamble_55",
619
16
      FT_UINT8, BASE_HEX, NULL, 0,
620
16
      "MS/TP Preamble 55", HFILL }
621
16
    },
622
16
    { &hf_mstp_preamble_FF,
623
16
      { "Preamble FF", "mstp.preamble_FF",
624
16
      FT_UINT8, BASE_HEX, NULL, 0,
625
16
      "MS/TP Preamble FF", HFILL }
626
16
    },
627
16
    { &hf_mstp_frame_type,
628
16
      { "Frame Type", "mstp.frame_type",
629
16
      FT_UINT8, BASE_DEC, VALS(bacnet_mstp_frame_type_name), 0,
630
16
      "MS/TP Frame Type", HFILL }
631
16
    },
632
16
    { &hf_mstp_frame_destination,
633
16
      { "Destination Address", "mstp.dst",
634
16
      FT_UINT8, BASE_DEC, NULL, 0,
635
16
      "Destination MS/TP MAC Address", HFILL }
636
16
    },
637
16
    { &hf_mstp_frame_source,
638
16
      { "Source Address", "mstp.src",
639
16
      FT_UINT8, BASE_DEC, NULL, 0,
640
16
      "Source MS/TP MAC Address", HFILL }
641
16
    },
642
16
    { &hf_mstp_frame_vendor_id,
643
16
      { "VendorID", "mstp.vendorid",
644
16
      FT_UINT16, BASE_DEC, NULL, 0,
645
16
      "MS/TP Vendor ID of proprietary frametypes", HFILL }
646
16
    },
647
16
    { &hf_mstp_frame_pdu_len,
648
16
      { "Length", "mstp.len",
649
16
      FT_UINT16, BASE_DEC, NULL, 0,
650
16
      "MS/TP Data Length", HFILL }
651
16
    },
652
16
    { &hf_mstp_frame_crc8,
653
16
      { "Header CRC",  "mstp.hdr_crc",
654
16
      FT_UINT8, BASE_HEX, NULL, 0,
655
16
      "MS/TP Header CRC", HFILL }
656
16
    },
657
16
    { &hf_mstp_frame_crc16,
658
16
      { "Data CRC",  "mstp.data_crc",
659
16
      FT_UINT16, BASE_HEX, NULL, 0,
660
16
      "MS/TP Data CRC", HFILL }
661
16
    },
662
16
    { &hf_mstp_frame_crc32k,
663
16
      { "Extended Data CRC",  "mstp.ext_data_crc",
664
16
      FT_UINT32, BASE_HEX, NULL, 0,
665
16
      "MS/TP Extended Data CRC (CRC-32K)", HFILL }
666
16
    },
667
16
    { &hf_mstp_frame_checksum_status,
668
16
      { "Checksum status", "mstp.checksum.status",
669
16
      FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
670
16
      NULL, HFILL }
671
16
    },
672
16
  };
673
674
16
  static int *ett[] = {
675
16
    &ett_bacnet_mstp,
676
16
  };
677
678
16
  static ei_register_info ei[] = {
679
16
    { &ei_mstp_frame_pdu_len, { "mstp.len.bad", PI_MALFORMED, PI_ERROR, "Length field value goes past the end of the payload", EXPFILL }},
680
16
    { &ei_mstp_frame_checksum_bad, { "mstp.checksum_bad.expert", PI_CHECKSUM, PI_WARN, "Bad Checksum", EXPFILL }},
681
16
    { &ei_mstp_cobs_bad, { "mstp.cobs.bad", PI_MALFORMED, PI_ERROR, "Invalid COBS encoding", EXPFILL }},
682
16
    { &ei_mstp_bacnet_npdu_len, { "mstp.bacnet_npdu_len.unexpected", PI_PROTOCOL, PI_WARN, "BACnet NPDU length outside the range for Frame Types 32 and 33", EXPFILL }},
683
16
    { &ei_mstp_ipv6_len, { "mstp.ipv6_len.too_long", PI_PROTOCOL, PI_WARN, "Length above 1510, the largest IPv6 over MS/TP frame", EXPFILL }},
684
16
  };
685
686
16
  expert_module_t* expert_mstp;
687
688
16
  proto_mstp = proto_register_protocol("BACnet MS/TP", "BACnet MS/TP", "mstp");
689
690
16
  proto_register_field_array(proto_mstp, hf, array_length(hf));
691
16
  proto_register_subtree_array(ett, array_length(ett));
692
16
  expert_mstp = expert_register_protocol(proto_mstp);
693
16
  expert_register_field_array(expert_mstp, ei, array_length(ei));
694
695
16
  mstp_handle = register_dissector("mstp", dissect_mstp_wtap, proto_mstp);
696
697
16
  subdissector_table = register_dissector_table("mstp.vendor_frame_type",
698
16
      "MSTP Vendor specific Frametypes", proto_mstp, FT_UINT24, BASE_DEC);
699
  /* Table_type: (Vendor ID << 16) + Frametype */
700
701
16
  mstp_address_type = address_type_dissector_register("AT_MSTP", "BACnet MS/TP Address", mstp_to_str, mstp_str_len, NULL, mstp_col_filter_str, mstp_len, NULL, NULL);
702
16
}
703
704
void
705
proto_reg_handoff_mstp(void)
706
16
{
707
16
  dissector_handle_t bacnet_handle;
708
709
16
  dissector_add_uint("wtap_encap", WTAP_ENCAP_BACNET_MS_TP, mstp_handle);
710
16
  dissector_add_uint("wtap_encap", WTAP_ENCAP_BACNET_MS_TP_WITH_PHDR, mstp_handle);
711
712
16
  bacnet_handle = find_dissector("bacnet");
713
714
16
  dissector_add_uint("mstp.vendor_frame_type", (0/*VendorID ASHRAE*/ << 16) + MSTP_BACNET_DATA_EXPECTING_REPLY, bacnet_handle);
715
16
  dissector_add_uint("mstp.vendor_frame_type", (0/*VendorID ASHRAE*/ << 16) + MSTP_BACNET_DATA_NOT_EXPECTING_REPLY, bacnet_handle);
716
16
  dissector_add_uint("mstp.vendor_frame_type", (0/*VendorID ASHRAE*/ << 16) + MSTP_BACNET_EXTENDED_DATA_EXPECTING_REPLY, bacnet_handle);
717
16
  dissector_add_uint("mstp.vendor_frame_type", (0/*VendorID ASHRAE*/ << 16) + MSTP_BACNET_EXTENDED_DATA_NOT_EXPECTING_REPLY, bacnet_handle);
718
16
  dissector_add_uint("mstp.vendor_frame_type", (0/*VendorID ASHRAE*/ << 16) + MSTP_IPV6_ENCAPSULATION,
719
16
    find_dissector_add_dependency("6lowpan", proto_mstp));
720
16
}
721
722
/*
723
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
724
 *
725
 * Local variables:
726
 * c-basic-offset: 8
727
 * tab-width: 8
728
 * indent-tabs-mode: t
729
 * End:
730
 *
731
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
732
 * :indentSize=8:tabSize=8:noTabs=false:
733
 */