Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-ositp.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-ositp.c
2
 * Routines for ISO/OSI transport protocol (connection-oriented
3
 * and connectionless) packet disassembly
4
 *
5
 * Laurent Deniel <laurent.deniel@free.fr>
6
 * Ralf Schneider <Ralf.Schneider@t-online.de>
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
#include "config.h"
16
17
#include <epan/packet.h>
18
#include <epan/prefs.h>
19
#include <epan/reassemble.h>
20
#include <epan/conversation.h>
21
#include <epan/ipproto.h>
22
#include <epan/expert.h>
23
#include <epan/proto_data.h>
24
#include <epan/tfs.h>
25
#include <wsutil/array.h>
26
27
#include <wsutil/str_util.h>
28
#include "packet-frame.h"
29
#include "packet-osi.h"
30
31
void proto_register_cotp(void);
32
void proto_register_cltp(void);
33
void proto_reg_handoff_cotp(void);
34
35
/* protocols and fields */
36
37
static int  proto_clnp;
38
39
static int  proto_cotp;
40
static int ett_cotp;
41
static int ett_cotp_segments;
42
static int ett_cotp_segment;
43
44
static int hf_cotp_li;
45
static int hf_cotp_type;
46
static int hf_cotp_srcref;
47
static int hf_cotp_destref;
48
static int hf_cotp_class;
49
static int hf_cotp_opts_extended_formats;
50
static int hf_cotp_opts_no_explicit_flow_control;
51
static int hf_cotp_tpdu_number;
52
static int hf_cotp_tpdu_number_extended;
53
static int hf_cotp_next_tpdu_number;
54
static int hf_cotp_next_tpdu_number_extended;
55
static int hf_cotp_eot;
56
static int hf_cotp_eot_extended;
57
/* Generated from convert_proto_tree_add_text.pl */
58
static int hf_cotp_parameter_code;
59
static int hf_cotp_parameter_length;
60
static int hf_cotp_parameter_value;
61
static int hf_cotp_atn_extended_checksum16;
62
static int hf_cotp_atn_extended_checksum32;
63
static int hf_cotp_atn_extended_checksum_status;
64
static int hf_cotp_ack_time;
65
static int hf_cotp_res_error_rate_target_value;
66
static int hf_cotp_res_error_rate_min_accept;
67
static int hf_cotp_res_error_rate_tdsu;
68
static int hf_cotp_vp_priority;
69
static int hf_cotp_transit_delay_targ_calling_called;
70
static int hf_cotp_transit_delay_max_accept_calling_called;
71
static int hf_cotp_transit_delay_targ_called_calling;
72
static int hf_cotp_transit_delay_max_accept_called_calling;
73
static int hf_cotp_max_throughput_targ_calling_called;
74
static int hf_cotp_max_throughput_min_accept_calling_called;
75
static int hf_cotp_max_throughput_targ_called_calling;
76
static int hf_cotp_max_throughput_min_accept_called_calling;
77
static int hf_cotp_avg_throughput_targ_calling_called;
78
static int hf_cotp_avg_throughput_min_accept_calling_called;
79
static int hf_cotp_avg_throughput_targ_called_calling;
80
static int hf_cotp_avg_throughput_min_accept_called_calling;
81
static int hf_cotp_sequence_number;
82
static int hf_cotp_reassignment_time;
83
static int hf_cotp_lower_window_edge;
84
static int hf_cotp_credit;
85
static int hf_cotp_tpdu_size;
86
static int hf_cotp_checksum;
87
static int hf_cotp_checksum_status;
88
static int hf_cotp_vp_version_nr;
89
static int hf_cotp_network_expedited_data;
90
static int hf_cotp_vp_opt_sel_class1_use;
91
static int hf_cotp_use_16_bit_checksum;
92
static int hf_cotp_transport_expedited_data_transfer;
93
static int hf_cotp_preferred_maximum_tpdu_size;
94
static int hf_cotp_inactivity_timer;
95
static int hf_cotp_cause;
96
static int hf_cotp_segment_data;
97
static int hf_cotp_credit_cdt;
98
static int hf_cotp_reject_cause;
99
100
static int hf_cotp_segments;
101
static int hf_cotp_segment;
102
static int hf_cotp_segment_overlap;
103
static int hf_cotp_segment_overlap_conflict;
104
static int hf_cotp_segment_multiple_tails;
105
static int hf_cotp_segment_too_long_segment;
106
static int hf_cotp_segment_error;
107
static int hf_cotp_segment_count;
108
static int hf_cotp_reassembled_in;
109
static int hf_cotp_reassembled_length;
110
111
static expert_field ei_cotp_disconnect_confirm;
112
static expert_field ei_cotp_multiple_tpdus;
113
static expert_field ei_cotp_reject;
114
static expert_field ei_cotp_connection;
115
static expert_field ei_cotp_disconnect_request;
116
static expert_field ei_cotp_preferred_maximum_tpdu_size;
117
static expert_field ei_cotp_atn_extended_checksum;
118
static expert_field ei_cotp_checksum;
119
120
121
static int  proto_cltp;
122
static int ett_cltp;
123
124
static int hf_cltp_li;
125
static int hf_cltp_type;
126
127
static const fragment_items cotp_frag_items = {
128
  &ett_cotp_segment,
129
  &ett_cotp_segments,
130
  &hf_cotp_segments,
131
  &hf_cotp_segment,
132
  &hf_cotp_segment_overlap,
133
  &hf_cotp_segment_overlap_conflict,
134
  &hf_cotp_segment_multiple_tails,
135
  &hf_cotp_segment_too_long_segment,
136
  &hf_cotp_segment_error,
137
  &hf_cotp_segment_count,
138
  &hf_cotp_reassembled_in,
139
  &hf_cotp_reassembled_length,
140
  /* Reassembled data field */
141
  NULL,
142
  "segments"
143
};
144
145
static dissector_handle_t rdp_cr_handle;
146
static dissector_handle_t rdp_cc_handle;
147
static dissector_handle_t ositp_handle;
148
149
150
/*
151
 * ISO8073 OSI COTP definition
152
 * See http://standards.iso.org/ittf/PubliclyAvailableStandards/index.html
153
 * (or RFC905 for historic, and now-outdated information)
154
 */
155
156
/* don't use specific TPDU types to avoid alignment problems & copy overhead */
157
158
/* TPDU definition */
159
160
150
#define ED_TPDU             0x1 /* COTP */
161
164
#define EA_TPDU             0x2 /* COTP */
162
9.46k
#define UD_TPDU             0x4 /* CLTP */
163
63
#define RJ_TPDU             0x5 /* COTP */
164
78
#define AK_TPDU             0x6 /* COTP */
165
33
#define ER_TPDU             0x7 /* COTP */
166
128
#define DR_TPDU             0x8 /* COTP */
167
48
#define DC_TPDU             0xC /* COTP */
168
183
#define CC_TPDU             0xD /* COTP */
169
1.23k
#define CR_TPDU             0xE /* COTP */
170
6.28k
#define DT_TPDU             0xF /* COTP */
171
172
static const value_string cotp_tpdu_type_abbrev_vals[] = {
173
  { ED_TPDU, "ED Expedited Data" },
174
  { EA_TPDU, "EA Expedited Data Acknowledgement" },
175
  { RJ_TPDU, "RJ Reject" },
176
  { AK_TPDU, "AK Data Acknowledgement" },
177
  { ER_TPDU, "ER TPDU Error" },
178
  { DR_TPDU, "DR Disconnect Request" },
179
  { DC_TPDU, "DC Disconnect Confirm" },
180
  { CC_TPDU, "CC Connect Confirm" },
181
  { CR_TPDU, "CR Connect Request" },
182
  { DT_TPDU, "DT Data" },
183
  { 0,       NULL }
184
};
185
186
static const value_string cltp_tpdu_type_abbrev_vals[] = {
187
  { UD_TPDU, "UD" },
188
  { 0,       NULL }
189
};
190
191
#if 0
192
static const value_string class_option_vals[] = {
193
  {0, "Class 0"},
194
  {1, "Class 1"},
195
  {2, "Class 2"},
196
  {3, "Class 3"},
197
  {4, "Class 4"},
198
  {0, NULL}
199
};
200
#endif
201
202
/* field position */
203
204
8.34k
#define P_LI                0
205
8.10k
#define P_TPDU              1
206
8.10k
#define P_CDT               1
207
1.36k
#define P_DST_REF           2
208
493
#define P_SRC_REF           4
209
5.37k
#define P_TPDU_NR_0_1       2
210
948
#define P_TPDU_NR_234       4
211
72
#define P_VAR_PART_NDT      5
212
34
#define P_VAR_PART_EDT      8
213
#define P_VAR_PART_DC       6
214
19
#define P_CDT_IN_AK         8
215
2
#define P_CDT_IN_RJ         8
216
24
#define P_REJECT_ER         4
217
83
#define P_REASON_IN_DR      6
218
378
#define P_CLASS_OPTION      6
219
220
/*
221
 * TPDU length indicator values.
222
 * Checksum parameter is 4 octets - 1 octet of parameter code, 1 octet
223
 * of parameter length, 2 octets of checksum.
224
 */
225
226
11.6k
#define LI_NORMAL_DT_CLASS_01           2
227
731
#define LI_NORMAL_DT_WITHOUT_CHECKSUM   4
228
64
#define LI_NORMAL_DT_WITH_CHECKSUM      (LI_NORMAL_DT_WITHOUT_CHECKSUM+4)
229
182
#define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
230
20
#define LI_EXTENDED_DT_WITH_CHECKSUM    (LI_EXTENDED_DT_WITHOUT_CHECKSUM+4)
231
16
#define LI_NORMAL_EA_WITHOUT_CHECKSUM   4
232
8
#define LI_NORMAL_EA_WITH_CHECKSUM      (LI_NORMAL_EA_WITHOUT_CHECKSUM+4)
233
49
#define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
234
14
#define LI_EXTENDED_EA_WITH_CHECKSUM    (LI_EXTENDED_EA_WITHOUT_CHECKSUM+4)
235
50
#define LI_NORMAL_RJ                    4
236
2
#define LI_EXTENDED_RJ                  9
237
128
#define LI_MIN_DR                       6
238
48
#define LI_MAX_DC                       9
239
78
#define LI_MAX_AK                       27
240
164
#define LI_MAX_EA                       11
241
33
#define LI_MAX_ER                       8
242
/* XXX - can we always decide this based on whether the length
243
   indicator is odd or not?  What if the variable part has an odd
244
   number of octets? */
245
58
#define is_LI_NORMAL_AK(p)               ((p & 0x01) == 0)
246
247
/*
248
 * Modified TPDU length indicator values due to ATN 4-octet extended
249
 * checksum.
250
 * Checksum parameter is 6 octets - 1 octet of parameter code, 1 octet
251
 * of parameter length, 4 octets of checksum.  That adds 2 octets to
252
 * the lengths with a 2-octet checksum.
253
 */
254
0
#define LI_ATN_NORMAL_DT_WITH_CHECKSUM       (LI_NORMAL_DT_WITH_CHECKSUM+2)
255
0
#define LI_ATN_EXTENDED_DT_WITH_CHECKSUM     (LI_EXTENDED_DT_WITH_CHECKSUM+2)
256
0
#define LI_ATN_NORMAL_EA_WITH_CHECKSUM       (LI_NORMAL_EA_WITH_CHECKSUM+2)
257
0
#define LI_ATN_EXTENDED_EA_WITH_CHECKSUM     (LI_EXTENDED_EA_WITH_CHECKSUM+2)
258
0
#define LI_ATN_NORMAL_RJ                     (LI_NORMAL_RJ+2)
259
0
#define LI_ATN_EXTENDED_RJ                   (LI_EXTENDED_RJ+2)
260
0
#define LI_ATN_MAX_DC                        (LI_MAX_DC+2)
261
0
#define LI_ATN_MAX_AK                        (LI_MAX_AK+2+1) /* +1 for padding? */
262
0
#define LI_ATN_MAX_EA                        (LI_MAX_EA+2)
263
0
#define LI_ATN_MAX_ER                        (LI_MAX_ER+2)
264
265
/* variant part */
266
267
24
#define VP_ACK_TIME             0x85
268
74
#define VP_RES_ERROR            0x86
269
28
#define VP_PRIORITY             0x87
270
77
#define VP_TRANSIT_DEL          0x88
271
26
#define VP_THROUGHPUT           0x89
272
9
#define VP_SEQ_NR               0x8A        /* in AK */
273
8
#define VP_REASSIGNMENT         0x8B
274
87
#define VP_FLOW_CNTL            0x8C        /* in AK */
275
16
#define VP_TPDU_SIZE            0xC0
276
45
#define VP_SRC_TSAP             0xC1        /* in CR/CC */
277
22
#define VP_DST_TSAP             0xC2
278
163
#define VP_CHECKSUM             0xC3
279
9
#define VP_VERSION_NR           0xC4
280
0
#define VP_PROTECTION           0xC5
281
9
#define VP_OPT_SEL              0xC6
282
0
#define VP_PROTO_CLASS          0xC7
283
0
#define VP_CLEARING_INFO        0xE0        /* in DR */
284
21
#define VP_PREF_MAX_TPDU_SIZE   0xF0
285
5
#define VP_INACTIVITY_TIMER     0xF2
286
287
/* ATN */
288
/* Parameter codes with bits 7 and 8 are explicitly not */
289
/* assigned by ISO/IEC 8073, nor is their use precluded. */
290
/* Parameter codes for ATN defined in ICAO doc 9507 Ed3 SV 5 section 5.5.2.4.3.1 */
291
79
#define VP_ATN_EC_32            0x08        /* 4 octet ATN Extended Transport Checksum parameter */
292
48
#define VP_ATN_EC_16            0x09        /* 2 octet ATN Extended Transport Checksum parameter */
293
/* ATN end */
294
295
static const value_string tp_vpart_type_vals[] = {
296
  { VP_ATN_EC_16,           "ATN extended checksum - 16 bit" },
297
  { VP_ATN_EC_32,           "ATN extended checksum - 32 bit" },
298
  { VP_ACK_TIME,            "ack time" },
299
  { VP_RES_ERROR,           "res error" },
300
  { VP_PRIORITY,            "priority" },
301
  { VP_TRANSIT_DEL,         "transit delay" },
302
  { VP_THROUGHPUT,          "throughput" },
303
  { VP_SEQ_NR,              "seq number" },
304
  { VP_REASSIGNMENT,        "reassignment" },
305
  { VP_FLOW_CNTL,           "flow control" },
306
  { VP_TPDU_SIZE,           "tpdu-size" },
307
  { VP_SRC_TSAP,            "src-tsap" },
308
  { VP_DST_TSAP,            "dst-tsap" },
309
  { VP_CHECKSUM,            "checksum" },
310
  { VP_VERSION_NR,          "version" },
311
  { VP_PROTECTION,          "protection" },
312
  { VP_OPT_SEL,             "options" },
313
  { VP_PROTO_CLASS,         "proto class" },
314
  { VP_CLEARING_INFO,       "additional connection clearing info" },
315
  { VP_PREF_MAX_TPDU_SIZE,  "preferred max TPDU size" },
316
  { VP_INACTIVITY_TIMER,    "inactivity timer" },
317
  { 0,                      NULL }
318
};
319
320
static int hf_cotp_vp_src_tsap;
321
static int hf_cotp_vp_dst_tsap;
322
static int hf_cotp_vp_src_tsap_bytes;
323
static int hf_cotp_vp_dst_tsap_bytes;
324
325
/* global variables */
326
327
/* List of dissectors to call for the variable part of CR PDUs. */
328
static heur_dissector_list_t cotp_cr_heur_subdissector_list;
329
/* List of dissectors to call for the variable part of CC PDUs. */
330
static heur_dissector_list_t cotp_cc_heur_subdissector_list;
331
/* List of dissectors to call for COTP packets put atop the Inactive
332
   Subset of CLNP. */
333
static heur_dissector_list_t cotp_is_heur_subdissector_list;
334
/* List of dissectors to call for COTP packets put atop CLNP */
335
static heur_dissector_list_t cotp_heur_subdissector_list;
336
/* List of dissectors to call for CLTP packets put atop CLNP */
337
static heur_dissector_list_t cltp_heur_subdissector_list;
338
339
/*
340
 * Reassembly of COTP.
341
 */
342
static reassembly_table cotp_reassembly_table;
343
static uint16_t   cotp_dst_ref;
344
static bool       cotp_frame_reset;
345
static bool       cotp_last_fragment;
346
347
124
#define TSAP_DISPLAY_AUTO   0
348
124
#define TSAP_DISPLAY_STRING 1
349
#define TSAP_DISPLAY_BYTES  2
350
351
/* options */
352
static bool cotp_reassemble = true;
353
static int32_t  tsap_display = TSAP_DISPLAY_AUTO;
354
static bool cotp_decode_atn;
355
356
static const enum_val_t tsap_display_options[] = {
357
  {"auto", "As strings if printable", TSAP_DISPLAY_AUTO},
358
  {"string", "As strings", TSAP_DISPLAY_STRING},
359
  {"bytes", "As bytes", TSAP_DISPLAY_BYTES},
360
  {NULL, NULL, -1}
361
};
362
363
/* function definitions */
364
365
90
#define MAX_TSAP_LEN    32
366
367
static void cotp_frame_end(void)
368
2.12k
{
369
2.12k
  if (!cotp_last_fragment) {
370
    /* Last COTP in frame is not fragmented.
371
     * No need for incrementing the dst_ref, so we decrement it here.
372
     */
373
1.11k
    cotp_dst_ref--;
374
1.11k
  }
375
2.12k
  cotp_frame_reset = true;
376
2.12k
}
377
378
static char *print_tsap(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
379
56
{
380
56
  const unsigned char *tsap = tvb_get_ptr(tvb, offset, length);
381
56
  char     *cur;
382
56
  bool      allprintable;
383
56
  int       idx = 0, returned_length;
384
385
56
  cur=(char *)wmem_alloc(scope, MAX_TSAP_LEN * 2 + 3);
386
56
  cur[0] = '\0';
387
56
  if (length <= 0 || length > MAX_TSAP_LEN)
388
41
    snprintf(cur, MAX_TSAP_LEN * 2 + 3, "<unsupported TSAP length>");
389
15
  else {
390
15
    allprintable = tvb_ascii_isprint(tvb, offset, length);
391
15
    if (!allprintable) {
392
13
      returned_length = snprintf(cur, MAX_TSAP_LEN * 2 + 3, "0x");
393
13
      idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - 1);
394
13
    }
395
121
    while (length != 0) {
396
106
      if (allprintable) {
397
4
        returned_length = snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
398
4
                                     "%c", *tsap ++);
399
4
        idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
400
102
      } else {
401
102
        returned_length = snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
402
102
                                     "%02x", *tsap ++);
403
102
        idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
404
102
      }
405
106
      length --;
406
106
    }
407
15
  }
408
56
  return cur;
409
410
56
} /* print_tsap */
411
412
static const true_false_string tfs_vp_opt_sel_class1_use = { "Receipt confirmation", "Explicit AK variant" };
413
414
static bool ositp_decode_var_part(tvbuff_t *tvb, int offset, int vp_length,
415
                                      int class_option, int tpdu_len,
416
                                      packet_info *pinfo, proto_tree *tree)
417
6.79k
{
418
6.79k
  uint8_t         code, length;
419
6.79k
  uint8_t         c1;
420
6.79k
  uint16_t        s;
421
6.79k
  uint32_t        offset_iso8073_checksum = 0;
422
6.79k
  int32_t         i                       = 0;
423
6.79k
  uint8_t         tmp_code                = 0;
424
6.79k
  unsigned        tmp_len                 = 0;
425
6.79k
  uint32_t        pref_max_tpdu_size;
426
6.79k
  proto_item     *hidden_item;
427
428
9.17k
  while (vp_length != 0) {
429
2.90k
    code = tvb_get_uint8(tvb, offset);
430
2.90k
    proto_tree_add_item(tree, hf_cotp_parameter_code, tvb, offset, 1, ENC_NA);
431
2.90k
    offset += 1;
432
2.90k
    vp_length -= 1;
433
434
2.90k
    if (vp_length == 0)
435
128
      break;
436
2.78k
    length = tvb_get_uint8(tvb, offset);
437
2.78k
    proto_tree_add_item(tree, hf_cotp_parameter_length, tvb, offset, 1, ENC_NA);
438
2.78k
    offset += 1;
439
2.78k
    vp_length -= 1;
440
441
2.78k
    switch (code) {
442
443
48
    case VP_ATN_EC_16 : /* ATN */
444
48
      if (cotp_decode_atn) {
445
0
        uint16_t sum;
446
        /* if an alternate OSI checksum is present in the currently unprocessed
447
         * VP section to the checksum algorithm has to know.
448
         * this may be the case for backward compatible CR TPDU */
449
0
        if (!offset_iso8073_checksum) {
450
          /* search following parameters in VP part for ISO checksum */
451
0
          for (i = offset + length; i < vp_length;) {
452
0
            tmp_code = tvb_get_uint8(tvb, i++);
453
0
            tmp_len = tvb_get_uint8(tvb, i++);
454
0
            if (tmp_code == VP_CHECKSUM) {
455
0
              offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
456
0
              break;
457
0
            }
458
0
            i += tmp_len;
459
0
          }
460
0
        }
461
0
        sum = check_atn_ec_16(tvb, tpdu_len , offset,
462
0
                                      offset_iso8073_checksum,
463
0
                                      pinfo->dst.len, (const uint8_t *)pinfo->dst.data,
464
0
                                      pinfo->src.len, (const uint8_t *)pinfo->src.data);
465
0
        proto_tree_add_checksum(tree, tvb, offset, hf_cotp_atn_extended_checksum16, hf_cotp_atn_extended_checksum_status, &ei_cotp_atn_extended_checksum,
466
0
                                pinfo, sum, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_ZERO);
467
48
      } else {
468
48
        proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
469
48
      }
470
48
      offset += length;
471
48
      vp_length -= length;
472
48
      break;
473
474
79
    case VP_ATN_EC_32 : /* ATN */
475
79
      if (cotp_decode_atn) {
476
0
        uint32_t sum;
477
        /* if an alternate OSI checksum is present in the currently unprocessed
478
         * VP section the checksum algorithm has to know.
479
         * this may be the case for backward compatible CR TPDU */
480
0
        if (!offset_iso8073_checksum) {
481
          /* search following parameters in VP part for ISO checksum */
482
0
          for (i = offset + length; i < vp_length;) {
483
0
            tmp_code = tvb_get_uint8(tvb, i++);
484
0
            tmp_len = tvb_get_uint8(tvb, i++);
485
0
            if (tmp_code == VP_CHECKSUM) {
486
0
              offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
487
0
              break;
488
0
            }
489
0
            i += tmp_len;
490
0
          }
491
0
        }
492
0
        sum = check_atn_ec_32(tvb, tpdu_len , offset,
493
0
                                      offset_iso8073_checksum,
494
0
                                      pinfo->dst.len, (const uint8_t *)pinfo->dst.data,
495
0
                                      pinfo->src.len, (const uint8_t *)pinfo->src.data);
496
0
        proto_tree_add_checksum(tree, tvb, offset, hf_cotp_atn_extended_checksum32, hf_cotp_atn_extended_checksum_status, &ei_cotp_atn_extended_checksum,
497
0
                                pinfo, sum, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_ZERO);
498
79
      } else {
499
79
        proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
500
79
      }
501
79
      offset += length;
502
79
      vp_length -= length;
503
79
      break;
504
505
24
    case VP_ACK_TIME:
506
24
      proto_tree_add_item(tree, hf_cotp_ack_time, tvb, offset, length, ENC_BIG_ENDIAN);
507
24
      offset += length;
508
24
      vp_length -= length;
509
24
      break;
510
511
74
    case VP_RES_ERROR:
512
74
      s = tvb_get_uint8(tvb, offset);
513
74
      proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_target_value, tvb, offset, 1, s, "10^%u", s);
514
74
      offset += 1;
515
74
      vp_length -= 1;
516
517
74
      s = tvb_get_uint8(tvb, offset);
518
74
      proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_min_accept, tvb, offset, 1, s, "10^%u", s);
519
74
      offset += 1;
520
74
      vp_length -= 1;
521
522
74
      s = tvb_get_uint8(tvb, offset);
523
74
      proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_tdsu, tvb, offset, 1, s, "2^%u", s);
524
74
      offset += 1;
525
74
      vp_length -= 1;
526
74
      break;
527
528
28
    case VP_PRIORITY:
529
28
      proto_tree_add_item(tree, hf_cotp_vp_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
530
28
      offset += length;
531
28
      vp_length -= length;
532
28
      break;
533
534
77
    case VP_TRANSIT_DEL:
535
77
      proto_tree_add_item(tree, hf_cotp_transit_delay_targ_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
536
77
      offset += 2;
537
77
      vp_length -= 2;
538
539
77
      proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
540
77
      offset += 2;
541
77
      vp_length -= 2;
542
543
77
      proto_tree_add_item(tree, hf_cotp_transit_delay_targ_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
544
77
      offset += 2;
545
77
      vp_length -= 2;
546
547
77
      proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
548
77
      offset += 2;
549
77
      vp_length -= 2;
550
77
      break;
551
552
26
    case VP_THROUGHPUT:
553
26
      proto_tree_add_item(tree, hf_cotp_max_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
554
26
      offset += 3;
555
26
      length -= 3;
556
26
      vp_length -= 3;
557
558
26
      proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
559
26
      offset += 3;
560
26
      length -= 3;
561
26
      vp_length -= 3;
562
563
26
      proto_tree_add_item(tree, hf_cotp_max_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
564
26
      offset += 3;
565
26
      length -= 3;
566
26
      vp_length -= 3;
567
568
26
      proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
569
26
      offset += 3;
570
26
      length -= 3;
571
26
      vp_length -= 3;
572
573
26
      if (length != 0) {    /* XXX - should be 0 or 12 */
574
24
        proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
575
24
        offset += 3;
576
24
        vp_length -= 3;
577
578
24
        proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
579
24
        offset += 3;
580
24
        vp_length -= 3;
581
582
24
        proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
583
24
        offset += 3;
584
24
        vp_length -= 3;
585
586
24
        proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
587
24
        offset += 3;
588
24
        vp_length -= 3;
589
24
      }
590
26
      break;
591
592
9
    case VP_SEQ_NR:
593
9
      proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
594
9
      offset += length;
595
9
      vp_length -= length;
596
9
      break;
597
598
8
    case VP_REASSIGNMENT:
599
8
      proto_tree_add_item(tree, hf_cotp_reassignment_time, tvb, offset, 2, ENC_BIG_ENDIAN);
600
8
      offset += length;
601
8
      vp_length -= length;
602
8
      break;
603
604
87
    case VP_FLOW_CNTL:
605
87
      proto_tree_add_item(tree, hf_cotp_lower_window_edge, tvb, offset, 4, ENC_BIG_ENDIAN);
606
87
      offset += 4;
607
87
      vp_length -= 4;
608
609
87
      proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
610
87
      offset += 2;
611
87
      vp_length -= 2;
612
613
87
      proto_tree_add_item(tree, hf_cotp_credit, tvb, offset, 2, ENC_BIG_ENDIAN);
614
87
      offset += 2;
615
87
      vp_length -= 2;
616
617
87
      break;
618
619
16
    case VP_TPDU_SIZE:
620
16
      c1 = tvb_get_uint8(tvb, offset) & 0x0F;
621
16
      proto_tree_add_uint(tree, hf_cotp_tpdu_size, tvb, offset, 1, 1 << c1);
622
16
      offset += length;
623
16
      vp_length -= length;
624
16
      break;
625
626
43
    case VP_SRC_TSAP:
627
      /* if our preference is set to STRING or the TSAP is not printable,
628
       * add as bytes and hidden as string; otherwise vice-versa */
629
43
      if (tsap_display==TSAP_DISPLAY_STRING ||
630
43
          (tsap_display==TSAP_DISPLAY_AUTO &&
631
43
            tvb_ascii_isprint(tvb, offset, length))) {
632
21
        proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
633
21
                              print_tsap(pinfo->pool, tvb, offset, length));
634
21
        hidden_item = proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb,
635
21
                                          offset, length, ENC_NA);
636
21
        proto_item_set_hidden(hidden_item);
637
22
      } else {
638
22
        hidden_item = proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb,
639
22
                                            offset, length,
640
22
                                            print_tsap(pinfo->pool, tvb, offset, length));
641
22
        proto_item_set_hidden(hidden_item);
642
22
        proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset,
643
22
                            length, ENC_NA);
644
22
      }
645
43
      offset += length;
646
43
      vp_length -= length;
647
43
      break;
648
649
19
    case VP_DST_TSAP:
650
      /* if our preference is set to STRING or the TSAP is not printable,
651
       * add as bytes and hidden as string; otherwise vice-versa */
652
19
      if (tsap_display==TSAP_DISPLAY_STRING ||
653
19
          (tsap_display==TSAP_DISPLAY_AUTO &&
654
19
            tvb_ascii_isprint(tvb, offset, length))) {
655
3
        proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
656
3
                              print_tsap(pinfo->pool, tvb, offset, length));
657
3
        hidden_item = proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb,
658
3
                                          offset, length, ENC_NA);
659
3
        proto_item_set_hidden(hidden_item);
660
16
      } else {
661
16
        hidden_item = proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb,
662
16
                                            offset, length,
663
16
                                            print_tsap(pinfo->pool, tvb, offset, length));
664
16
        proto_item_set_hidden(hidden_item);
665
16
        proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset,
666
16
                            length, ENC_NA);
667
16
      }
668
19
      offset += length;
669
19
      vp_length -= length;
670
19
      break;
671
672
30
    case VP_CHECKSUM:
673
30
      offset_iso8073_checksum = offset; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
674
675
30
      if (tvb_get_ntohs(tvb, offset) == 0) {
676
        /* No checksum present */
677
7
        proto_tree_add_checksum(tree, tvb, offset, hf_cotp_checksum, hf_cotp_checksum_status, &ei_cotp_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NOT_PRESENT);
678
23
      } else {
679
23
        uint32_t calc_c0 = 0, calc_c1 = 0;
680
681
23
        if (osi_calc_checksum(tvb, 0, length, &calc_c0, &calc_c1)) {
682
            /* Successfully processed checksum, verify it */
683
21
            proto_tree_add_checksum(tree, tvb, offset, hf_cotp_checksum, hf_cotp_checksum_status, &ei_cotp_checksum, pinfo, calc_c0 | calc_c1, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_ZERO);
684
21
        } else {
685
2
            proto_tree_add_checksum(tree, tvb, offset, hf_cotp_checksum, hf_cotp_checksum_status, &ei_cotp_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
686
2
        }
687
23
      }
688
689
30
      offset += length;
690
30
      vp_length -= length;
691
30
      break;
692
693
9
    case VP_VERSION_NR:
694
9
      proto_tree_add_item(tree, hf_cotp_vp_version_nr, tvb, offset, 1, ENC_NA);
695
9
      offset += length;
696
9
      vp_length -= length;
697
9
      break;
698
699
9
    case VP_OPT_SEL:
700
9
      switch (class_option) {
701
702
0
      case 1:
703
0
        proto_tree_add_item(tree, hf_cotp_network_expedited_data, tvb, offset, 1, ENC_NA);
704
705
0
        proto_tree_add_item(tree, hf_cotp_vp_opt_sel_class1_use, tvb, offset, 1, ENC_NA);
706
0
        break;
707
708
3
      case 4:
709
3
        proto_tree_add_item(tree, hf_cotp_use_16_bit_checksum, tvb, offset, 1, ENC_NA);
710
3
        break;
711
9
      }
712
713
9
      proto_tree_add_item(tree, hf_cotp_transport_expedited_data_transfer, tvb, offset, 1, ENC_NA);
714
9
      offset += length;
715
9
      vp_length -= length;
716
9
      break;
717
718
21
    case VP_PREF_MAX_TPDU_SIZE:
719
21
      switch (length) {
720
721
1
      case 1:
722
1
        pref_max_tpdu_size = tvb_get_uint8(tvb, offset);
723
1
        break;
724
725
0
      case 2:
726
0
        pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
727
0
        break;
728
729
6
      case 3:
730
6
        pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
731
6
        break;
732
733
0
      case 4:
734
0
        pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
735
0
        break;
736
737
14
      default:
738
14
        proto_tree_add_expert_format(tree, pinfo, &ei_cotp_preferred_maximum_tpdu_size, tvb, offset, length,
739
14
                            "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)", length);
740
14
        return false;
741
21
      }
742
7
      proto_tree_add_uint(tree, hf_cotp_preferred_maximum_tpdu_size, tvb, offset, length, pref_max_tpdu_size*128);
743
7
      offset += length;
744
7
      vp_length -= length;
745
7
      break;
746
747
5
    case VP_INACTIVITY_TIMER:
748
5
      proto_tree_add_item(tree, hf_cotp_inactivity_timer, tvb, offset, length, ENC_BIG_ENDIAN);
749
5
      offset += length;
750
5
      vp_length -= length;
751
5
      break;
752
753
0
    case VP_PROTECTION:             /* user-defined */
754
0
    case VP_PROTO_CLASS:            /* todo */
755
0
    case VP_CLEARING_INFO:          /* user-defined */
756
2.07k
    default:                        /* unknown, no decoding */
757
2.07k
      proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
758
2.07k
      offset += length;
759
2.07k
      vp_length -= length;
760
2.07k
      break;
761
2.78k
    }
762
2.78k
  } /* while */
763
764
6.39k
  return true;
765
6.79k
}
766
767
static const value_string cotp_cause_vals[] = {
768
  { 0, "Reason not specified" },
769
  { 1, "Congestion at TSAP" },
770
  { 2, "Session entity not attached to TSAP" },
771
  { 3, "Address unknown" },
772
  { 128+0, "Normal Disconnect" },
773
  { 128+1, "Remote transport entity congestion" },
774
  { 128+2, "Connection negotiation failed" },
775
  { 128+3, "Duplicate source reference" },
776
  { 128+4, "Mismatched references" },
777
  { 128+5, "Protocol error" },
778
  { 128+7, "Reference overflow" },
779
  { 128+8, "Connection request refused" },
780
  { 128+10, "Header or parameter length invalid" },
781
  { 0,       NULL }
782
};
783
784
static int ositp_decode_DR(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
785
                           packet_info *pinfo, proto_tree *tree)
786
128
{
787
128
  proto_tree *cotp_tree = NULL;
788
128
  proto_item *ti        = NULL;
789
128
  uint16_t    dst_ref, src_ref;
790
128
  unsigned char      reason;
791
128
  unsigned    tpdu_len;
792
793
  /* ATN TPDU's tend to be larger than normal OSI,
794
   * so nothing to do with respect to LI checks */
795
128
  if (li < LI_MIN_DR)
796
45
    return -1;
797
798
  /* DR TPDUs can have user data, so they run to the end of the containing PDU */
799
83
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
800
801
83
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
802
803
83
  src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
804
805
83
  reason  = tvb_get_uint8(tvb, offset + P_REASON_IN_DR);
806
807
83
  pinfo->clnp_dstref = dst_ref;
808
83
  pinfo->clnp_srcref = src_ref;
809
810
  /* the settings of the TCP srcport and destport are currently disabled,
811
   * for the following reasons:
812
   * a) only used for ISO conversation handling (which currently doesn't work)
813
   * b) will prevent "ISO on TCP" (RFC1006) packets from using
814
   *    "follow TCP stream" correctly
815
   *
816
   * A future conversation handling might be able to handle different kinds of
817
   * conversations (TCP, ISO, TCP on TCP, ...), but in that case this has to be
818
   * fixed in any case.
819
   */
820
  /*pinfo->srcport = src_ref;*/
821
  /*pinfo->destport = dst_ref;*/
822
83
  if (try_val_to_str(reason, cotp_cause_vals) == NULL)
823
26
      return -1;
824
825
57
  col_append_fstr(pinfo->cinfo, COL_INFO,
826
57
                  "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
827
828
57
  if (tree) {
829
56
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
830
56
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
831
56
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
832
56
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1, tpdu);
833
56
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
834
56
                        dst_ref);
835
56
    proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset +  4, 2,
836
56
                        src_ref);
837
56
    proto_tree_add_item(cotp_tree, hf_cotp_cause, tvb, offset + 6, 1, ENC_NA);
838
56
  }
839
57
  offset += 7;
840
57
  li -= 6;
841
842
57
  if (tree)
843
56
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
844
57
  offset += li;
845
846
57
  expert_add_info_format(pinfo, ti, &ei_cotp_disconnect_request, "Disconnect Request(DR): 0x%x -> 0x%x", src_ref, dst_ref);
847
848
  /* User data */
849
57
  call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
850
57
  offset += tvb_captured_length_remaining(tvb, offset);
851
     /* we dissected all of the containing PDU */
852
853
57
  return offset;
854
855
83
} /* ositp_decode_DR */
856
857
static int ositp_decode_DT(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
858
                           packet_info *pinfo, proto_tree *tree,
859
                           bool uses_inactive_subset,
860
                           bool *subdissector_found)
861
6.28k
{
862
6.28k
  proto_tree        *cotp_tree       = NULL;
863
6.28k
  proto_item        *ti;
864
6.28k
  bool               is_extended;
865
6.28k
  bool               is_class_234;
866
6.28k
  uint32_t           dst_ref;
867
6.28k
  uint32_t          *prev_dst_ref;
868
6.28k
  unsigned           tpdu_nr;
869
6.28k
  bool               fragment        = false;
870
6.28k
  uint32_t           fragment_length = 0;
871
6.28k
  tvbuff_t          *next_tvb;
872
6.28k
  fragment_head     *fd_head;
873
6.28k
  conversation_t    *conv;
874
6.28k
  unsigned           tpdu_len;
875
6.28k
  heur_dtbl_entry_t *hdtbl_entry;
876
877
  /* DT TPDUs have user data, so they run to the end of the containing PDU */
878
6.28k
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
879
880
  /* The fixed part is 2 octets long, not including the length indicator,
881
     for classes 0 and 1; it is at least 4 octets long, not including
882
     the length indicator, for classes 2, 3, and 4. */
883
6.28k
  is_class_234 = (li > LI_NORMAL_DT_CLASS_01);
884
885
  /* note: in the ATN the user is up to chose between 3 different checksums:
886
   *       standard OSI, 2 or 4 octet extended checksum.
887
   * The differences for DT are that the TPDU headers may be enlarged by 2
888
   * octets and that checksum related option codes and option lengths are
889
   * different.  To not mess up the original OSI dissector LI checking was
890
   * implemented separately. */
891
6.28k
  if (!cotp_decode_atn) { /* non ATN, plain OSI*/
892
    /* VP_CHECKSUM is the only parameter allowed in the variable part.
893
     * (This means we may misdissect this if the packet is bad and
894
     * contains other parameters.).
895
896
     * XXX - not true; ISO/IEC 8073:1997 (E) says that "if the use of
897
     * non-blocking expedited data transfer service is negotiated (class
898
     * 4 only), the variable part shall contain the ED-TPDU-NR for the
899
     * first DT-TPDU created from a T-DATA request subsequent to the
900
     * T-EXPEDITED DATA request". */
901
6.28k
    switch (li) {
902
903
8
      case LI_NORMAL_DT_WITH_CHECKSUM      :
904
8
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
905
8
          return -1;
906
        /* FALLTHROUGH */
907
908
649
      case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
909
649
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
910
649
        if (tpdu_nr & 0x80)
911
276
          tpdu_nr = tpdu_nr & 0x7F;
912
373
        else
913
373
          fragment = true;
914
649
        is_extended = false;
915
649
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
916
649
        break;
917
918
19
      case LI_EXTENDED_DT_WITH_CHECKSUM    :
919
19
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
920
19
          return -1;
921
        /* FALLTHROUGH */
922
923
125
      case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
924
125
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
925
125
        if (tpdu_nr & 0x80000000)
926
53
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
927
72
        else
928
72
          fragment = true;
929
125
        is_extended = true;
930
125
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
931
125
        break;
932
933
5.37k
      case LI_NORMAL_DT_CLASS_01           :
934
5.37k
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_0_1);
935
5.37k
        if (tpdu_nr & 0x80)
936
2.12k
          tpdu_nr = tpdu_nr & 0x7F;
937
3.24k
        else
938
3.24k
          fragment = true;
939
5.37k
        is_extended = false;
940
5.37k
        prev_dst_ref = (uint32_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_clnp, 0);
941
5.37k
        if (!prev_dst_ref) {
942
          /* First COTP in frame - save previous dst_ref as offset */
943
1.16k
          prev_dst_ref = wmem_new(wmem_file_scope(), uint32_t);
944
1.16k
          *prev_dst_ref = cotp_dst_ref;
945
1.16k
          p_add_proto_data(wmem_file_scope(), pinfo, proto_clnp, 0, prev_dst_ref);
946
4.20k
        } else if (cotp_frame_reset) {
947
0
          cotp_dst_ref = *prev_dst_ref;
948
0
        }
949
5.37k
        cotp_frame_reset = false;
950
5.37k
        cotp_last_fragment = fragment;
951
5.37k
        dst_ref = cotp_dst_ref;
952
5.37k
        conv = find_conversation_pinfo(pinfo, 0);
953
5.37k
        if (conv) {
954
          /* Found a conversation, also use index for the generated dst_ref */
955
437
          dst_ref += (conv->conv_index << 16);
956
437
        }
957
5.37k
        if (!fragment) {
958
2.12k
          cotp_dst_ref++;
959
2.12k
          register_frame_end_routine(pinfo, cotp_frame_end);
960
2.12k
        }
961
5.37k
        break;
962
963
118
      default : /* bad TPDU */
964
118
        return -1;
965
6.28k
    } /* li */
966
6.28k
  } else {
967
    /* check ATN class4 TPDU's here */
968
969
    /* check packet length indicators of DaTa(DT) TPDU
970
     * note: use of checksum depends on the selected RER
971
     *       (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
972
     *
973
     * note: sole use of TP4 class in the ATN
974
     * note: normal/extended TPDU numbering is negociable */
975
0
    switch (li) {
976
977
      /* normal DT with 2 octets of OSI or of ATN Extended Checksum */
978
0
      case LI_NORMAL_DT_WITH_CHECKSUM      :
979
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM &&
980
0
            tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16)
981
0
          return -1;
982
        /* FALLTHROUGH */
983
984
0
      case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
985
0
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
986
0
        if (tpdu_nr & 0x80)
987
0
          tpdu_nr = tpdu_nr & 0x7F;
988
0
        else
989
0
          fragment = true;
990
0
        is_extended = false;
991
0
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
992
0
        break;
993
994
      /* extended DT with 2 octets of OSI or of ATN Extended Checksum */
995
0
      case LI_EXTENDED_DT_WITH_CHECKSUM    :
996
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM &&
997
0
            tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16)
998
0
          return -1;
999
        /* FALLTHROUGH */
1000
1001
0
      case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1002
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1003
0
        if (tpdu_nr & 0x80000000)
1004
0
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1005
0
        else
1006
0
          fragment = true;
1007
0
        is_extended = true;
1008
0
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1009
0
        break;
1010
1011
      /* normal DT with ATN Extended Checksum (4 octets)*/
1012
0
      case LI_ATN_NORMAL_DT_WITH_CHECKSUM      :
1013
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1014
0
          return -1;
1015
1016
0
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1017
1018
0
        if (tpdu_nr & 0x80)
1019
0
          tpdu_nr = tpdu_nr & 0x7F;
1020
0
        else
1021
0
          fragment = true;
1022
0
        is_extended = false;
1023
0
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1024
0
        break;
1025
1026
      /* extended DT with 4 octets ATN Extended Checksum  */
1027
0
      case LI_ATN_EXTENDED_DT_WITH_CHECKSUM:
1028
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1029
0
          return -1;
1030
1031
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1032
0
        if (tpdu_nr & 0x80000000)
1033
0
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1034
0
        else
1035
0
          fragment = true;
1036
0
        is_extended = true;
1037
0
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1038
0
        break;
1039
1040
0
      default : /* bad TPDU */
1041
0
        return -1;
1042
0
    } /* li */
1043
0
  } /* cotp_decode_atn */
1044
1045
6.13k
  pinfo->clnp_dstref = dst_ref;
1046
1047
6.13k
  pinfo->fragmented = fragment;
1048
6.13k
  if (is_class_234) {
1049
769
      col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x",
1050
769
                      tpdu_nr, dst_ref);
1051
5.36k
    } else {
1052
5.36k
      col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u)", tpdu_nr);
1053
5.36k
    }
1054
1055
6.13k
  if (tree) {
1056
6.13k
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1057
6.13k
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1058
6.13k
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1059
6.13k
  }
1060
6.13k
  offset += 1;
1061
1062
6.13k
  if (tree) {
1063
6.13k
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1064
6.13k
  }
1065
6.13k
  offset += 1;
1066
6.13k
  li -= 1;
1067
1068
6.13k
  if (is_class_234) {
1069
769
    if (tree)
1070
769
      proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1071
769
    offset += 2;
1072
769
    li -= 2;
1073
5.36k
  } else if (tree) {
1074
5.36k
    ti = proto_tree_add_uint (cotp_tree, hf_cotp_destref, tvb, offset, 0,
1075
5.36k
                              dst_ref);
1076
5.36k
    proto_item_set_generated (ti);
1077
5.36k
  }
1078
1079
6.13k
  if (is_extended) {
1080
124
    if (tree) {
1081
124
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1082
124
                          4, tpdu_nr);
1083
124
      proto_tree_add_item(cotp_tree, hf_cotp_eot_extended, tvb, offset, 4,
1084
124
                          ENC_BIG_ENDIAN);
1085
124
    }
1086
124
    offset += 4;
1087
124
    li -= 4;
1088
6.00k
  } else {
1089
6.00k
    if (tree) {
1090
6.00k
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1091
6.00k
                          tpdu_nr);
1092
6.00k
      proto_tree_add_item(cotp_tree, hf_cotp_eot, tvb, offset, 1,
1093
6.00k
                          ENC_BIG_ENDIAN);
1094
6.00k
    }
1095
6.00k
    offset += 1;
1096
6.00k
    li -= 1;
1097
6.00k
  }
1098
1099
6.13k
  if (tree)
1100
6.13k
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1101
6.13k
  offset += li;
1102
1103
6.13k
  next_tvb = tvb_new_subset_remaining(tvb, offset);
1104
6.13k
  fragment_length = tvb_captured_length(next_tvb);
1105
6.13k
  if (fragment) {
1106
3.67k
    col_append_fstr(pinfo->cinfo, COL_INFO, " [COTP fragment, %u byte%s]",
1107
3.67k
        fragment_length, plurality(fragment_length, "", "s"));
1108
3.67k
  } else {
1109
2.45k
    col_append_str(pinfo->cinfo, COL_INFO, " EOT");
1110
2.45k
  }
1111
1112
6.13k
  if (cotp_reassemble) {
1113
    /*
1114
     * XXX - these sequence numbers are connection sequence number,
1115
     * not segment sequence numbers - the first segment of a
1116
     * segmented packet doesn't have a specific sequence number (e.g., 0
1117
     * or 1), it has whatever the appropriate sequence number is for
1118
     * it in the connection.
1119
     *
1120
     * For now, we assume segments arrive in order, and just supply
1121
     * the negation of the EOT flag as the "more flags" argument.
1122
     * We should probably handle out-of-order packets separately,
1123
     * so that we can deliver them in order even when *not*
1124
     * reassembling.
1125
     *
1126
     * Note also that TP0 has no sequence number, and relies on
1127
     *      the protocol atop which it runs to guarantee in-order delivery.
1128
     */
1129
6.13k
    fd_head = fragment_add_seq_next(&cotp_reassembly_table, next_tvb, 0, pinfo,
1130
6.13k
                                    dst_ref, NULL, fragment_length, fragment);
1131
6.13k
    if (fd_head && fd_head->next) {
1132
      /* don't use -1 if fragment length is zero (throws Exception) */
1133
1.11k
      proto_tree_add_bytes_format(cotp_tree, hf_cotp_segment_data, tvb, offset, (fragment_length) ? -1 : 0,
1134
1.11k
                          NULL, "COTP segment data (%u byte%s)", fragment_length,
1135
1.11k
                          plurality(fragment_length, "", "s"));
1136
1137
1.11k
      if (!fragment) {
1138
        /* This is the last packet */
1139
1.11k
        next_tvb = process_reassembled_data (next_tvb, offset, pinfo,
1140
1.11k
                                             "Reassembled COTP", fd_head,
1141
1.11k
                                             &cotp_frag_items, NULL, tree);
1142
1.11k
      } else if (pinfo->num != fd_head->reassembled_in) {
1143
        /* Add a "Reassembled in" link if not reassembled in this frame */
1144
0
        proto_tree_add_uint(cotp_tree, *(cotp_frag_items.hf_reassembled_in),
1145
0
                            next_tvb, 0, 0, fd_head->reassembled_in);
1146
0
      }
1147
1.11k
      pinfo->fragmented = fragment;
1148
1.11k
    }
1149
6.13k
  }
1150
1151
6.13k
  if (uses_inactive_subset) {
1152
5.89k
    if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1153
5.89k
                                pinfo, tree, &hdtbl_entry, NULL)) {
1154
1.42k
      *subdissector_found = true;
1155
4.47k
    } else {
1156
      /* Fill in other Dissectors using inactive subset here */
1157
4.47k
      call_data_dissector(next_tvb, pinfo, tree);
1158
4.47k
    }
1159
5.89k
  } else {
1160
    /*
1161
     * We dissect payload if one of the following is true:
1162
     *
1163
     * - Reassembly option for COTP in preferences is unchecked
1164
     * - Reassembly option is checked and this packet is the last fragment
1165
     */
1166
232
    if ((!cotp_reassemble) || ((cotp_reassemble) && (!fragment))) {
1167
225
      if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1168
225
                                  tree, &hdtbl_entry, NULL)) {
1169
52
        *subdissector_found = true;
1170
173
      } else {
1171
173
        call_data_dissector(next_tvb, pinfo, tree);
1172
173
      }
1173
225
    }
1174
232
  }
1175
1176
6.13k
  offset += tvb_captured_length_remaining(tvb, offset);
1177
  /* we dissected all of the containing PDU */
1178
1179
6.13k
  return offset;
1180
1181
6.28k
} /* ositp_decode_DT */
1182
1183
static int ositp_decode_ED(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
1184
                           packet_info *pinfo, proto_tree *tree,
1185
                           bool uses_inactive_subset,
1186
                           bool *subdissector_found)
1187
150
{
1188
150
  proto_tree *cotp_tree = NULL;
1189
150
  proto_item *ti;
1190
150
  bool        is_extended;
1191
150
  uint16_t    dst_ref;
1192
150
  unsigned    tpdu_nr;
1193
150
  tvbuff_t   *next_tvb;
1194
150
  unsigned    tpdu_len;
1195
150
  heur_dtbl_entry_t *hdtbl_entry;
1196
1197
  /* ED TPDUs have user data, so they run to the end of the containing PDU */
1198
150
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
1199
1200
  /* note: in the ATN the user is up to chose between 3 different checksums:
1201
   *       standard OSI, 2 or 4 octet extended checksum.
1202
   * The differences for ED (as for DT) are that the TPDU headers may be
1203
   * enlarged by 2 octets and that checksum related option codes and option
1204
   * lengths are different.  To not mess up the original OSI dissector LI
1205
   * checking was implemented separately.
1206
   *
1207
   * note: this could not be tested, because no sample was avail for expedited
1208
   *       data */
1209
150
  if (!cotp_decode_atn) {  /* non ATN, plain OSI*/
1210
    /* ED TPDUs are never fragmented */
1211
1212
    /* VP_CHECKSUM is the only parameter allowed in the variable part.
1213
      (This means we may misdissect this if the packet is bad and
1214
      contains other parameters.) */
1215
150
    switch (li) {
1216
1217
56
      case LI_NORMAL_DT_WITH_CHECKSUM      :
1218
56
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1219
56
          return -1;
1220
        /* FALLTHROUGH */
1221
1222
18
      case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
1223
18
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1224
18
        if (tpdu_nr & 0x80)
1225
4
          tpdu_nr = tpdu_nr & 0x7F;
1226
14
        else
1227
14
          return -1;
1228
4
        is_extended = false;
1229
4
        break;
1230
1231
1
      case LI_EXTENDED_DT_WITH_CHECKSUM    :
1232
1
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1233
1
          return -1;
1234
        /* FALLTHROUGH */
1235
1236
37
      case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1237
37
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1238
37
        if (tpdu_nr & 0x80000000)
1239
33
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1240
4
        else
1241
4
          return -1;
1242
33
        is_extended = true;
1243
33
        break;
1244
1245
38
      default : /* bad TPDU */
1246
38
        return -1;
1247
150
    } /* li */
1248
150
  } else {
1249
    /* check packet length indicators of ATN Expedited Data (ED) TPDU
1250
     * note: use of checksum depends on the selected RER
1251
     *       (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
1252
     *
1253
     * note: sole use of TP4 class in the ATN
1254
     * note: normal/extended TPDU numbering is negociable */
1255
0
    switch (li) {
1256
1257
0
      case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
1258
0
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1259
0
        if (tpdu_nr & 0x80)
1260
0
          tpdu_nr = tpdu_nr & 0x7F;
1261
0
        else
1262
0
          return -1;
1263
0
        is_extended = false;
1264
0
        break;
1265
1266
0
      case LI_NORMAL_DT_WITH_CHECKSUM      :
1267
0
        if ((tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
1268
0
             (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16))
1269
0
          return -1;
1270
1271
0
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1272
0
        if (tpdu_nr & 0x80)
1273
0
          tpdu_nr = tpdu_nr & 0x7F;
1274
0
        else
1275
0
          return -1;
1276
0
        is_extended = false;
1277
0
        break;
1278
1279
0
      case LI_ATN_NORMAL_DT_WITH_CHECKSUM      :
1280
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1281
0
          return -1;
1282
1283
0
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1284
0
        if (tpdu_nr & 0x80)
1285
0
          tpdu_nr = tpdu_nr & 0x7F;
1286
0
        else
1287
0
          return -1;
1288
0
        is_extended = false;
1289
0
        break;
1290
1291
0
      case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1292
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1293
0
        if (tpdu_nr & 0x80000000)
1294
0
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1295
0
        else
1296
0
          return -1;
1297
0
        is_extended = true;
1298
0
        break;
1299
1300
0
      case LI_EXTENDED_DT_WITH_CHECKSUM    :
1301
0
        if ((tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM) &&
1302
0
              (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16))
1303
0
          return -1;
1304
1305
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1306
0
        if (tpdu_nr & 0x80000000)
1307
0
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1308
0
        else
1309
0
          return -1;
1310
0
        is_extended = true;
1311
0
        break;
1312
1313
0
      case LI_ATN_EXTENDED_DT_WITH_CHECKSUM    :
1314
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1315
0
          return -1;
1316
1317
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1318
0
        if (tpdu_nr & 0x80000000)
1319
0
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1320
0
        else
1321
0
          return -1;
1322
0
        is_extended = true;
1323
0
        break;
1324
1325
0
      default : /* bad TPDU */
1326
0
        return -1;
1327
0
    } /* li */
1328
0
  } /* cotp_decode_atn */
1329
1330
37
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1331
37
  pinfo->clnp_dstref = dst_ref;
1332
1333
37
  col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
1334
37
                  tpdu_nr, dst_ref);
1335
1336
37
  if (tree) {
1337
37
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1338
37
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1339
37
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1340
37
  }
1341
37
  offset += 1;
1342
1343
37
  if (tree) {
1344
37
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1345
37
  }
1346
37
  offset += 1;
1347
37
  li -= 1;
1348
1349
37
  if (tree)
1350
37
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1351
37
  offset += 2;
1352
37
  li -= 2;
1353
1354
37
  if (is_extended) {
1355
33
    if (tree) {
1356
33
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1357
33
                          4, tpdu_nr);
1358
33
    }
1359
33
    offset += 4;
1360
33
    li -= 4;
1361
33
  } else {
1362
4
    if (tree) {
1363
4
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1364
4
                          tpdu_nr);
1365
4
    }
1366
4
    offset += 1;
1367
4
    li -= 1;
1368
4
  }
1369
1370
37
  if (tree)
1371
37
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1372
37
  offset += li;
1373
1374
  /*
1375
   * Tell subdissectors that this is in an ED packet?
1376
   */
1377
37
  next_tvb = tvb_new_subset_remaining(tvb, offset);
1378
37
  if (uses_inactive_subset) {
1379
20
    if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1380
20
                                pinfo, tree, &hdtbl_entry, NULL)) {
1381
1
      *subdissector_found = true;
1382
19
    } else {
1383
      /* Fill in other Dissectors using inactive subset here */
1384
19
      call_data_dissector(next_tvb, pinfo, tree);
1385
19
    }
1386
20
  } else {
1387
    /*
1388
     * ED TPDUs are never fragmented
1389
     */
1390
17
    if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1391
17
                                tree, &hdtbl_entry, NULL)) {
1392
2
      *subdissector_found = true;
1393
15
    } else {
1394
15
      call_data_dissector(next_tvb, pinfo, tree);
1395
15
    }
1396
17
  }
1397
1398
37
  offset += tvb_captured_length_remaining(tvb, offset);
1399
     /* we dissected all of the containing PDU */
1400
1401
37
  return offset;
1402
1403
150
} /* ositp_decode_ED */
1404
1405
static int ositp_decode_RJ(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
1406
                           uint8_t cdt, packet_info *pinfo, proto_tree *tree)
1407
63
{
1408
63
  proto_tree *cotp_tree;
1409
63
  proto_item *ti;
1410
63
  proto_item *item = NULL;
1411
63
  uint16_t dst_ref;
1412
63
  unsigned tpdu_nr;
1413
63
  uint16_t credit = 0;
1414
1415
  /* note: in the ATN the user is up to chose between 3 different checksums:
1416
   *       standard OSI, 2 or 4 octet extended checksum.
1417
   * The difference for RJ is that the TPDU header may be enlarged by 2 octets
1418
   * for checksum parameters are not going to be checked here */
1419
63
  if (!cotp_decode_atn) {  /* non ATN, plain OSI */
1420
63
    switch(li) {
1421
16
      case LI_NORMAL_RJ   :
1422
16
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1423
16
        break;
1424
2
      case LI_EXTENDED_RJ :
1425
2
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1426
2
        credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1427
2
        break;
1428
45
      default :
1429
45
        return -1;
1430
63
    }
1431
63
  } else {
1432
0
    switch(li) {
1433
      /* normal with 2 octets of OSI or ATN checksum */
1434
0
      case LI_NORMAL_RJ   :
1435
      /* with 4 octets of ATN checksum */
1436
0
      case LI_ATN_NORMAL_RJ   :
1437
0
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1438
0
        break;
1439
      /* extended with 2 octets of OSI or ATN checksum */
1440
0
      case LI_EXTENDED_RJ :
1441
      /* with 4 octets of ATN checksum */
1442
0
      case LI_ATN_EXTENDED_RJ :
1443
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1444
0
        credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1445
0
        break;
1446
0
      default :
1447
0
        return -1;
1448
0
    }
1449
0
  }
1450
1451
17
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1452
17
  pinfo->clnp_dstref = dst_ref;
1453
1454
17
  col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
1455
17
                  tpdu_nr, dst_ref);
1456
1457
17
  if (tree) {
1458
17
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1459
17
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1460
17
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1461
17
    item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1,
1462
17
                               tpdu);
1463
17
    if (li == LI_NORMAL_RJ) {
1464
15
      proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset +  1, 1, cdt);
1465
15
    }
1466
17
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
1467
17
                        dst_ref);
1468
17
    if (li == LI_NORMAL_RJ)
1469
15
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset + 4,
1470
15
                          1, tpdu_nr);
1471
2
    else {
1472
2
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1473
2
                          offset + 4, 4, tpdu_nr);
1474
2
      proto_tree_add_uint(cotp_tree, hf_cotp_credit, tvb, offset +  8, 2, credit);
1475
2
    }
1476
17
  }
1477
1478
17
  offset += li + 1;
1479
1480
17
  expert_add_info_format(pinfo, item, &ei_cotp_reject, "Reject(RJ): -> 0x%x", dst_ref);
1481
1482
17
  return offset;
1483
1484
63
} /* ositp_decode_RJ */
1485
1486
static int ositp_decode_CR_CC(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
1487
                              packet_info *pinfo, proto_tree *tree,
1488
                              bool uses_inactive_subset,
1489
                              bool *subdissector_found)
1490
378
{
1491
  /* note: in the ATN the user is up to chose between 3 different checksums:
1492
   *       standard OSI, 2 or 4 octet extended checksum.
1493
   * Nothing has to be done here, for all ATN specifics are handled in VP. */
1494
1495
  /* CC & CR decoding in the same function */
1496
1497
378
  proto_tree *cotp_tree = NULL;
1498
378
  proto_item *ti;
1499
378
  proto_item *item = NULL;
1500
378
  uint16_t dst_ref, src_ref;
1501
378
  uint8_t class_option;
1502
378
  tvbuff_t *next_tvb;
1503
378
  unsigned   tpdu_len;
1504
378
  heur_dtbl_entry_t *hdtbl_entry;
1505
378
  static int * const class_options[] = {
1506
378
     &hf_cotp_class,
1507
378
     &hf_cotp_opts_extended_formats,
1508
378
     &hf_cotp_opts_no_explicit_flow_control,
1509
378
     NULL,
1510
378
  };
1511
1512
378
  src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1513
1514
378
  class_option = tvb_get_uint8(tvb, offset + P_CLASS_OPTION);
1515
378
  if (((class_option & 0xF0) >> 4) > 4) /* class 0..4 allowed */
1516
70
    return -1;
1517
1518
  /* CR and CC TPDUs can have user data, so they run to the end of the
1519
   * containing PDU */
1520
308
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
1521
1522
308
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1523
308
  pinfo->clnp_srcref = src_ref;
1524
308
  pinfo->clnp_dstref = dst_ref;
1525
1526
308
  col_append_fstr(pinfo->cinfo, COL_INFO,
1527
308
                  "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1528
308
                  (tpdu == CR_TPDU) ? "CR" : "CC", src_ref, dst_ref);
1529
1530
308
  ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1531
308
  cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1532
308
  proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1533
308
  offset += 1;
1534
1535
308
  item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1536
308
  offset += 1;
1537
308
  li -= 1;
1538
1539
308
  proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1540
308
  offset += 2;
1541
308
  li -= 2;
1542
1543
308
  proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1544
308
  offset += 2;
1545
308
  li -= 2;
1546
1547
  /* expert info, but only if not encapsulated in TCP/SMB */
1548
  /* XXX - the best way to detect seems to be if we have a port set */
1549
308
  if (pinfo->destport == 0) {
1550
268
    expert_add_info_format(pinfo, item, &ei_cotp_connection, "Connection %s: 0x%x -> 0x%x", tpdu == CR_TPDU ? "Request(CR)" : "Confirm(CC)", src_ref, dst_ref);
1551
268
  }
1552
1553
308
  proto_tree_add_bitmask_list(cotp_tree, tvb, offset, 1, class_options, ENC_NA);
1554
308
  offset += 1;
1555
308
  li -= 1;
1556
1557
308
  if (li > 0) {
1558
    /* There's more data left, so we have the variable part.
1559
1560
       Microsoft's RDP hijacks the variable part of CR and CC PDUs
1561
       for their own user data (RDP runs atop Class 0, which doesn't
1562
       support user data).
1563
1564
       Try what heuristic dissectors we have. */
1565
278
    next_tvb = tvb_new_subset_length(tvb, offset, li);
1566
278
    if (dissector_try_heuristic((tpdu == CR_TPDU) ?
1567
167
                                 cotp_cr_heur_subdissector_list :
1568
278
                                 cotp_cc_heur_subdissector_list,
1569
278
                                next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
1570
      /* A subdissector claimed this, so it really belongs to them. */
1571
29
      *subdissector_found = true;
1572
249
    } else {
1573
      /* No heuristic dissector claimed it, so dissect it as a regular
1574
         variable part. */
1575
249
      ositp_decode_var_part(tvb, offset, li, class_option, tpdu_len, pinfo,
1576
249
                            cotp_tree);
1577
249
    }
1578
278
    offset += li;
1579
278
  }
1580
1581
  /*
1582
   * XXX - tell the subdissector that this is user data in a CR or
1583
   * CC packet rather than a DT packet?
1584
   */
1585
308
  if (tvb_captured_length_remaining(tvb, offset)) {
1586
74
    next_tvb = tvb_new_subset_remaining(tvb, offset);
1587
74
    if (!uses_inactive_subset){
1588
72
      if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1589
72
                                  tree, &hdtbl_entry, NULL)) {
1590
19
        *subdissector_found = true;
1591
53
      } else {
1592
53
        call_data_dissector(next_tvb, pinfo, tree);
1593
53
      }
1594
72
    }
1595
2
    else
1596
2
      call_data_dissector( next_tvb, pinfo, tree);
1597
74
    offset += tvb_captured_length_remaining(tvb, offset);
1598
    /* we dissected all of the containing PDU */
1599
74
  }
1600
1601
308
  return offset;
1602
1603
378
} /* ositp_decode_CR_CC */
1604
1605
static int ositp_decode_DC(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
1606
                           packet_info *pinfo, proto_tree *tree)
1607
48
{
1608
48
  proto_tree *cotp_tree = NULL;
1609
48
  proto_item *ti;
1610
48
  proto_item *item = NULL;
1611
48
  uint16_t dst_ref, src_ref;
1612
48
  unsigned   tpdu_len;
1613
1614
  /* ATN may use checksums different from OSI */
1615
  /* which may result in different TPDU header length. */
1616
48
  if (!cotp_decode_atn) {
1617
48
    if (li > LI_MAX_DC)
1618
16
      return -1;
1619
48
  } else {
1620
0
    if (li > LI_ATN_MAX_DC)
1621
0
      return -1;
1622
0
  }
1623
1624
  /* DC TPDUs have no user data, so the length indicator determines the
1625
   * length */
1626
32
  tpdu_len = li + 1;
1627
1628
32
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1629
32
  src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1630
32
  pinfo->clnp_dstref = dst_ref;
1631
32
  pinfo->clnp_srcref = src_ref;
1632
1633
32
  col_append_fstr(pinfo->cinfo, COL_INFO,
1634
32
                  "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
1635
1636
32
  if (tree) {
1637
31
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1638
31
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1639
31
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1640
31
  }
1641
32
  offset += 1;
1642
1643
32
  if (tree) {
1644
31
    item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1645
31
  }
1646
32
  offset += 1;
1647
32
  li -= 1;
1648
1649
32
  if (tree)
1650
31
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1651
32
  offset += 2;
1652
32
  li -= 2;
1653
1654
32
  if (tree)
1655
31
    proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1656
32
  offset += 2;
1657
32
  li -= 2;
1658
1659
32
  if (tree)
1660
31
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1661
32
  offset += li;
1662
1663
32
  expert_add_info_format(pinfo, item, &ei_cotp_disconnect_confirm, "Disconnect Confirm(DC): 0x%x -> 0x%x", src_ref, dst_ref);
1664
1665
32
  return offset;
1666
1667
48
} /* ositp_decode_DC */
1668
1669
static int ositp_decode_AK(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
1670
                           uint8_t cdt, packet_info *pinfo, proto_tree *tree)
1671
78
{
1672
78
  proto_tree *cotp_tree = NULL;
1673
78
  proto_item *ti;
1674
78
  uint16_t   dst_ref;
1675
78
  unsigned   tpdu_nr;
1676
78
  uint16_t   cdt_in_ak;
1677
78
  unsigned   tpdu_len;
1678
1679
78
  if (!cotp_decode_atn) {
1680
78
    if (li > LI_MAX_AK)
1681
20
      return -1;
1682
78
  } else {
1683
0
    if (li > LI_ATN_MAX_AK)
1684
0
      return -1;
1685
0
  }
1686
1687
  /* AK TPDUs have no user data, so the length indicator determines the
1688
   * length */
1689
58
  tpdu_len = li + 1;
1690
1691
  /* is_LI_NORMAL_AK() works for normal ATN AK's, */
1692
  /* for the TPDU header size may be enlarged by 2 octets */
1693
58
  if (is_LI_NORMAL_AK(li)) {
1694
1695
39
    dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1696
39
    tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1697
39
    pinfo->clnp_dstref = dst_ref;
1698
1699
39
    col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1700
39
                    tpdu_nr, dst_ref);
1701
1702
39
    if (tree) {
1703
38
      ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1704
38
      cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1705
38
      proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1706
38
    }
1707
39
    offset += 1;
1708
1709
39
    if (tree) {
1710
38
      proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1711
38
      proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset, 1, cdt);
1712
38
    }
1713
39
    offset += 1;
1714
39
    li -= 1;
1715
1716
39
    if (tree)
1717
38
      proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1718
39
    offset += 2;
1719
39
    li -= 2;
1720
1721
39
    if (tree) {
1722
38
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1723
38
                          tpdu_nr);
1724
38
    }
1725
39
    offset += 1;
1726
39
    li -= 1;
1727
1728
39
    if (tree)
1729
38
      ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1730
39
    offset += li;
1731
1732
39
  } else { /* extended format */
1733
1734
19
    dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1735
19
    tpdu_nr   = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1736
19
    cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1737
19
    pinfo->clnp_dstref = dst_ref;
1738
1739
19
    col_append_fstr(pinfo->cinfo, COL_INFO,
1740
19
                    "AK TPDU (%u) dst-ref: 0x%04x Credit: %u",
1741
19
                    tpdu_nr, dst_ref, cdt_in_ak);
1742
1743
19
    if (tree) {
1744
19
      ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1745
19
      cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1746
19
      proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1747
19
    }
1748
19
    offset += 1;
1749
1750
19
    if (tree) {
1751
19
      proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1752
19
    }
1753
19
    offset += 1;
1754
19
    li -= 1;
1755
1756
19
    if (tree)
1757
19
      proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1758
19
    offset += 2;
1759
19
    li -= 2;
1760
1761
19
    if (tree) {
1762
19
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1763
19
                          offset, 4, tpdu_nr);
1764
19
    }
1765
19
    offset += 4;
1766
19
    li -= 4;
1767
1768
19
    if (tree) {
1769
19
      proto_tree_add_uint(cotp_tree, hf_cotp_credit, tvb, offset, 2, cdt_in_ak);
1770
19
    }
1771
19
    offset += 2;
1772
19
    li -= 2;
1773
1774
19
    if (tree)
1775
19
      ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1776
19
    offset += li;
1777
1778
19
  } /* is_LI_NORMAL_AK */
1779
1780
58
  return offset;
1781
1782
78
} /* ositp_decode_AK */
1783
1784
static int ositp_decode_EA(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
1785
                           packet_info *pinfo, proto_tree *tree)
1786
164
{
1787
164
  proto_tree *cotp_tree = NULL;
1788
164
  proto_item *ti;
1789
164
  bool is_extended;
1790
164
  uint16_t dst_ref;
1791
164
  unsigned tpdu_nr;
1792
164
  unsigned tpdu_len;
1793
1794
  /* Due to different checksums in the ATN the TPDU header sizes
1795
   * as well as the checksum parameters may be different than plain OSI EA
1796
   * because these are heavily checked for EA these checks had to be
1797
   * re-implemented.
1798
   * note: this could not be tested, because no sample was avail for expedited
1799
   *       data */
1800
164
  if (!cotp_decode_atn) {
1801
164
    if (li > LI_MAX_EA)
1802
49
      return -1;
1803
1804
    /* VP_CHECKSUM is the only parameter allowed in the variable part.
1805
     (This means we may misdissect this if the packet is bad and
1806
     contains other parameters.) */
1807
115
    switch (li) {
1808
1809
8
      case LI_NORMAL_EA_WITH_CHECKSUM      :
1810
8
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
1811
8
          tvb_get_uint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1812
8
            return -1;
1813
        /* FALLTHROUGH */
1814
1815
8
      case LI_NORMAL_EA_WITHOUT_CHECKSUM   :
1816
8
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1817
8
        is_extended = false;
1818
8
        break;
1819
1820
14
      case LI_EXTENDED_EA_WITH_CHECKSUM    :
1821
14
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
1822
14
            tvb_get_uint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1823
14
          return -1;
1824
        /* FALLTHROUGH */
1825
1826
35
      case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1827
35
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1828
35
        is_extended = true;
1829
35
        break;
1830
1831
50
      default : /* bad TPDU */
1832
50
        return -1;
1833
115
    } /* li */
1834
115
  } else { /* cotp_decode_atn */
1835
    /* check for ATN length: TPDU may be 2 octets longer due to checksum */
1836
0
    if (li > LI_ATN_MAX_EA)
1837
0
      return -1;
1838
1839
0
    switch (li) {
1840
1841
      /* extended TPDU numbering EA with  no checksum  */
1842
0
      case LI_NORMAL_EA_WITHOUT_CHECKSUM   :
1843
0
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1844
0
        is_extended = false;
1845
0
        break;
1846
1847
      /* normal TPDU numbering EA with 2 octets of OSI or ATN extended
1848
       * checksum */
1849
0
      case LI_NORMAL_EA_WITH_CHECKSUM      :
1850
        /* check checksum parameter (in VP) parameter code octet */
1851
0
        if ((tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
1852
0
            (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16))
1853
0
          return -1;
1854
1855
        /* check checksum parameter (in VP) length octet */
1856
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1857
0
          return -1;
1858
1859
0
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1860
0
        is_extended = false;
1861
0
        break;
1862
1863
      /* normal TPDU numbering EA with 4 octets of ATN extended checksum  */
1864
0
      case LI_ATN_NORMAL_EA_WITH_CHECKSUM      :
1865
        /* check checksum parameter (in VP) parameter code octet */
1866
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1867
0
          return -1;
1868
1869
        /* check checksum parameter (in VP) length octet */
1870
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT + 1) != 4)
1871
0
          return -1;
1872
1873
0
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1874
0
        is_extended = false;
1875
0
        break;
1876
1877
      /* extended TPDU numbering EA with no checksum  */
1878
0
      case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1879
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1880
0
        is_extended = true;
1881
0
        break;
1882
1883
      /* extended TPDU numbering EA with 2 octets of OSI or ATN extended
1884
       * checksum */
1885
0
      case LI_EXTENDED_EA_WITH_CHECKSUM    :
1886
        /* check checksum parameter (in VP) parameter code octet */
1887
0
        if ((tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM) &&
1888
0
             (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16))
1889
0
          return -1;
1890
1891
        /* check checksum parameter (in VP) length octet */
1892
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1893
0
          return -1;
1894
1895
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1896
0
        is_extended = true;
1897
0
        break;
1898
1899
        /* extended EA with 4 octets ATN extended checksum  */
1900
0
      case LI_ATN_EXTENDED_EA_WITH_CHECKSUM    :
1901
        /* check checksum parameter (in VP) parameter code octet */
1902
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1903
0
          return -1;
1904
1905
        /* check checksum parameter (in VP) length octet */
1906
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1907
0
          return -1;
1908
1909
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1910
0
        is_extended = true;
1911
0
        break;
1912
1913
0
      default : /* bad TPDU */
1914
0
        return -1;
1915
0
    }
1916
0
  }
1917
1918
  /* ER TPDUs have no user data, so the length indicator determines the
1919
   * length */
1920
43
  tpdu_len = li + 1;
1921
1922
43
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1923
43
  pinfo->clnp_dstref = dst_ref;
1924
1925
43
  col_append_fstr(pinfo->cinfo, COL_INFO, "EA TPDU (%u) dst-ref: 0x%04x",
1926
43
                  tpdu_nr, dst_ref);
1927
1928
43
  if (tree) {
1929
43
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1930
43
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1931
43
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1932
43
  }
1933
43
  offset += 1;
1934
1935
43
  if (tree) {
1936
43
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1937
43
  }
1938
43
  offset += 1;
1939
43
  li -= 1;
1940
1941
43
  if (tree)
1942
43
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1943
43
  offset += 2;
1944
43
  li -= 2;
1945
1946
43
  if (is_extended) {
1947
35
    if (tree) {
1948
35
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1949
35
                          offset, 4, tpdu_nr);
1950
35
    }
1951
35
    offset += 4;
1952
35
    li -= 4;
1953
35
  } else {
1954
8
    if (tree) {
1955
8
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1956
8
                          tpdu_nr);
1957
8
    }
1958
8
    offset += 1;
1959
8
    li -= 1;
1960
8
  }
1961
1962
43
  if (tree)
1963
43
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len,  pinfo, cotp_tree);
1964
43
  offset += li;
1965
1966
43
  return offset;
1967
1968
164
} /* ositp_decode_EA */
1969
1970
static const value_string cotp_reject_vals[] = {
1971
  { 0, "Reason not specified" },
1972
  { 1, "Invalid parameter code" },
1973
  { 2, "Invalid TPDU type" },
1974
  { 3, "Invalid parameter value" },
1975
  { 0,       NULL }
1976
};
1977
1978
static int ositp_decode_ER(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
1979
                           packet_info *pinfo, proto_tree *tree)
1980
33
{
1981
33
  proto_tree *cotp_tree = NULL;
1982
33
  proto_item *ti;
1983
33
  uint16_t dst_ref;
1984
33
  uint8_t tpdu_len;
1985
1986
  /* ATN: except for modified LI checking nothing to be done here */
1987
33
  if (!cotp_decode_atn) {
1988
33
    if (li > LI_MAX_ER)
1989
9
      return -1;
1990
33
  } else {
1991
0
    if (li > LI_ATN_MAX_ER)
1992
0
      return -1;
1993
0
  }
1994
1995
  /* ER TPDUs have no user data, so the length indicator determines the
1996
   * length */
1997
24
  tpdu_len = li + 1;
1998
1999
24
  if(try_val_to_str(tvb_get_uint8(tvb, offset + P_REJECT_ER), cotp_reject_vals) == NULL)
2000
11
      return -1;
2001
2002
13
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
2003
13
  pinfo->clnp_dstref = dst_ref;
2004
2005
13
  col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
2006
2007
13
  if (tree) {
2008
11
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
2009
11
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
2010
11
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
2011
11
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1, tpdu);
2012
11
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
2013
11
                        dst_ref);
2014
11
    proto_tree_add_item(cotp_tree, hf_cotp_reject_cause, tvb, offset + 4, 1, ENC_NA);
2015
11
  }
2016
13
  offset += 5;
2017
13
  li -= 4;
2018
2019
13
  if (tree)
2020
11
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
2021
13
  offset += li;
2022
2023
13
  return offset;
2024
2025
24
} /* ositp_decode_ER */
2026
2027
static int ositp_decode_UD(tvbuff_t *tvb, int offset, uint8_t li, uint8_t tpdu,
2028
                           packet_info *pinfo, proto_tree *tree,
2029
                           bool *subdissector_found)
2030
198
{
2031
198
  proto_item *ti;
2032
198
  proto_tree *cltp_tree = NULL;
2033
198
  tvbuff_t   *next_tvb;
2034
198
  unsigned   tpdu_len;
2035
198
  heur_dtbl_entry_t *hdtbl_entry;
2036
2037
  /* UD TPDUs have user data, so they run to the end of the containing PDU */
2038
198
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
2039
2040
198
  col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
2041
2042
198
  if (tree) {
2043
198
    ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, ENC_NA);
2044
198
    cltp_tree = proto_item_add_subtree(ti, ett_cltp);
2045
198
    proto_tree_add_uint(cltp_tree, hf_cltp_li, tvb, offset, 1,li);
2046
198
  }
2047
198
  offset += 1;
2048
2049
198
  if (tree) {
2050
198
    proto_tree_add_uint(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu);
2051
198
  }
2052
198
  offset += 1;
2053
198
  li -= 1;
2054
2055
198
  if (tree)
2056
198
    ositp_decode_var_part(tvb, offset, li, 0, tpdu_len, pinfo, cltp_tree);
2057
198
  offset += li;
2058
2059
198
  next_tvb = tvb_new_subset_remaining(tvb, offset);
2060
2061
198
  if (dissector_try_heuristic(cltp_heur_subdissector_list, next_tvb,
2062
198
                              pinfo, tree, &hdtbl_entry, NULL)) {
2063
22
    *subdissector_found = true;
2064
176
  } else {
2065
176
    call_data_dissector(next_tvb, pinfo, tree);
2066
176
  }
2067
2068
2069
  /*call_data_dissector(next_tvb, pinfo, tree); */
2070
2071
198
  offset += tvb_captured_length_remaining(tvb, offset);
2072
  /* we dissected all of the containing PDU */
2073
2074
198
  return offset;
2075
2076
198
} /* ositp_decode_UD */
2077
2078
/* Returns the offset past the last valid COTP or CLTP PDU if we found
2079
   at least one valid COTP or CLTP PDU, 0 otherwise.
2080
2081
   There doesn't seem to be any way in which the OSI network layer protocol
2082
   distinguishes between COTP and CLTP, but the first two octets of both
2083
   protocols' headers mean the same thing - length and PDU type - and the
2084
   only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
2085
   both of them here. */
2086
static int dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
2087
                                   proto_tree *tree,
2088
                                   bool uses_inactive_subset)
2089
8.68k
{
2090
8.68k
  int offset = 0;
2091
8.68k
  uint8_t li, tpdu, cdt;
2092
8.68k
  bool first_tpdu = true;
2093
8.68k
  int new_offset;
2094
8.68k
  bool found_ositp = false;
2095
8.68k
  bool is_cltp = false;
2096
8.68k
  bool subdissector_found = false;
2097
2098
  /* Initialize the COL_INFO field; each of the TPDUs will have its
2099
     information appended. */
2100
8.68k
  col_clear(pinfo->cinfo, COL_INFO);
2101
2102
12.4k
  while (tvb_offset_exists(tvb, offset)) {
2103
8.34k
    if (!first_tpdu) {
2104
82
      col_append_str(pinfo->cinfo, COL_INFO, ", ");
2105
82
      expert_add_info(pinfo, NULL, &ei_cotp_multiple_tpdus);
2106
      /* adjust tvb and offset to the start of the current PDU */
2107
82
      tvb = tvb_new_subset_remaining(tvb, offset);
2108
82
      offset = 0 ;
2109
82
    }
2110
8.34k
    if ((li = tvb_get_uint8(tvb, offset + P_LI)) == 0) {
2111
247
      col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
2112
247
      if (!first_tpdu)
2113
14
        call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2114
14
                       pinfo, tree);
2115
247
      return found_ositp;
2116
247
    }
2117
2118
8.10k
    tpdu = (tvb_get_uint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
2119
8.10k
    if (tpdu == UD_TPDU)
2120
198
      pinfo->current_proto = "CLTP";    /* connectionless transport */
2121
8.10k
    cdt = tvb_get_uint8(tvb, offset + P_CDT) & 0x0F;
2122
2123
8.10k
    switch (tpdu) {
2124
183
      case CC_TPDU :
2125
378
      case CR_TPDU :
2126
378
        new_offset = ositp_decode_CR_CC(tvb, offset, li, tpdu, pinfo, tree,
2127
378
                                        uses_inactive_subset, &subdissector_found);
2128
378
        break;
2129
128
      case DR_TPDU :
2130
128
        new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
2131
128
        break;
2132
6.28k
      case DT_TPDU :
2133
6.28k
        new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
2134
6.28k
                                     uses_inactive_subset, &subdissector_found);
2135
6.28k
        break;
2136
150
      case ED_TPDU :
2137
150
        new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree,
2138
150
                                     uses_inactive_subset, &subdissector_found);
2139
150
        break;
2140
63
      case RJ_TPDU :
2141
63
        new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
2142
63
        break;
2143
48
      case DC_TPDU :
2144
48
        new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
2145
48
        break;
2146
78
      case AK_TPDU :
2147
78
        new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
2148
78
        break;
2149
164
      case EA_TPDU :
2150
164
        new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
2151
164
        break;
2152
33
      case ER_TPDU :
2153
33
        new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
2154
33
        break;
2155
198
      case UD_TPDU :
2156
198
        new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree,
2157
198
                                     &subdissector_found);
2158
198
        is_cltp = true;
2159
198
        break;
2160
510
      default      :
2161
510
        if (first_tpdu)
2162
482
          col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)",
2163
482
                          tpdu);
2164
510
        new_offset = -1;    /* bad PDU type */
2165
510
        break;
2166
8.10k
    }
2167
2168
4.87k
    if (new_offset == -1) { /* incorrect TPDU */
2169
1.13k
      if (!first_tpdu)
2170
43
        call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2171
43
                       pinfo, tree);
2172
1.13k
      break;
2173
1.13k
    }
2174
2175
3.74k
    if (first_tpdu) {
2176
      /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
2177
         is either COTP or CLTP. */
2178
3.72k
      if (!subdissector_found)
2179
2.17k
        col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
2180
3.72k
      found_ositp = true;
2181
3.72k
    }
2182
2183
3.74k
    offset = new_offset;
2184
3.74k
    first_tpdu = false;
2185
3.74k
  }
2186
5.20k
  return found_ositp ? offset : 0;
2187
8.68k
} /* dissect_ositp_internal */
2188
2189
static int dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2190
                          void *data _U_)
2191
488
{
2192
488
  return dissect_ositp_internal(tvb, pinfo, tree, false);
2193
488
}
2194
2195
static int dissect_ositp_inactive(tvbuff_t *tvb, packet_info *pinfo,
2196
                                   proto_tree *tree, void *data _U_)
2197
8.19k
{
2198
8.19k
  return dissect_ositp_internal(tvb, pinfo, tree, true);
2199
8.19k
}
2200
2201
static bool
2202
test_cltp_var_part(tvbuff_t *tvb)
2203
106
{
2204
106
  int offset = 0;
2205
106
  uint8_t li;
2206
109
  while (tvb_captured_length_remaining(tvb, offset)) {
2207
95
    if (tvb_captured_length_remaining(tvb, offset) < 2) {
2208
6
      return false;
2209
6
    }
2210
89
    switch (tvb_get_uint8(tvb, offset++)) {
2211
    /* These are the only 3 legal parameters for CLTP per RFC 1240 and X.234 */
2212
2
    case VP_SRC_TSAP:
2213
3
    case VP_DST_TSAP:
2214
5
    case VP_CHECKSUM: // Not required as redundant with UDP checksum, per RFC 1240
2215
5
      break;
2216
84
    default:
2217
84
      return false;
2218
89
    }
2219
5
    li = tvb_get_uint8(tvb, offset++);
2220
5
    if (li == 255) {
2221
1
      return false;
2222
1
    }
2223
4
    if (tvb_captured_length_remaining(tvb, offset) < li) {
2224
1
      return false;
2225
1
    }
2226
3
    offset += li;
2227
3
  }
2228
14
  return true;
2229
106
}
2230
2231
static bool
2232
dissect_cltp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
2233
          void *data)
2234
1.54k
{
2235
1.54k
  uint8_t li, tpdu, spdu;
2236
1.54k
  int offset = 0;
2237
2238
  /* RFC 1240: OSI Connectionless Transport Services on top of UDP
2239
   * was made Historic by RFC 2556, which noted that "at this time
2240
   * there do not seem to be any implementations" and recommended
2241
   * TPKT (RFC 2126, ISO Transport Service on top of TCP) instead.
2242
   */
2243
2244
  /* First, check do we have at least 2 bytes (length + tpdu) */
2245
1.54k
  if (tvb_captured_length(tvb) < 2) {
2246
3
    return false;
2247
3
  }
2248
2249
1.54k
  li = tvb_get_uint8(tvb, offset++);
2250
2251
  /* LI must include TPDU, and 255 is reserved */
2252
1.54k
  if (li == 0 || li == 255) {
2253
383
    return false;
2254
383
  }
2255
2256
  /* Is it OSI on top of the UDP? */
2257
1.16k
  tpdu = (tvb_get_uint8(tvb, offset++) & 0xF0) >> 4;
2258
1.16k
  if (tpdu != UD_TPDU) {
2259
1.05k
    return false;
2260
1.05k
  }
2261
2262
  /* LI includes TPDU */
2263
106
  li--;
2264
2265
106
  if (!test_cltp_var_part(tvb_new_subset_length(tvb, offset, li))) {
2266
92
    return false;
2267
92
  }
2268
14
  offset += li;
2269
2270
  /* Since R-GOOSE is the only known user of CLTP over UDP, just
2271
   * check for that.
2272
   */
2273
2274
  /* Check do we have SPDU ID byte, too */
2275
14
  if (tvb_captured_length_remaining(tvb, offset) < 1) {
2276
7
    return false;
2277
7
  }
2278
2279
  /* And let's see if it is GOOSE SPDU */
2280
7
  spdu = tvb_get_uint8(tvb, offset);
2281
7
  if (spdu != 0xA1) {
2282
5
    return false;
2283
5
  }
2284
2285
2
  dissect_ositp(tvb, pinfo, parent_tree, data);
2286
2
  return true;
2287
7
}
2288
2289
static void
2290
cotp_reassemble_init(void)
2291
14
{
2292
14
  cotp_dst_ref = 0;
2293
14
}
2294
2295
void proto_register_cotp(void)
2296
14
{
2297
14
  static hf_register_info hf[] = {
2298
14
    { &hf_cotp_li,
2299
14
      { "Length", "cotp.li", FT_UINT8, BASE_DEC,
2300
14
        NULL, 0x0, "Length Indicator, length of this header", HFILL}},
2301
14
    { &hf_cotp_type,
2302
14
      { "PDU Type", "cotp.type", FT_UINT8, BASE_HEX,
2303
14
        VALS(cotp_tpdu_type_abbrev_vals), 0x0,
2304
14
        "PDU Type - upper nibble of byte", HFILL}},
2305
14
    { &hf_cotp_srcref,
2306
14
      { "Source reference", "cotp.srcref", FT_UINT16, BASE_HEX,
2307
14
        NULL, 0x0, "Source address reference", HFILL}},
2308
14
    { &hf_cotp_destref,
2309
14
      { "Destination reference", "cotp.destref", FT_UINT16, BASE_HEX,
2310
14
        NULL, 0x0, "Destination address reference", HFILL}},
2311
14
    { &hf_cotp_class,
2312
14
      { "Class", "cotp.class", FT_UINT8, BASE_DEC, NULL,
2313
14
        0xF0, "Transport protocol class", HFILL}},
2314
14
    { &hf_cotp_opts_extended_formats,
2315
14
      { "Extended formats", "cotp.opts.extended_formats", FT_BOOLEAN, 8,
2316
14
        NULL, 0x02, "Use of extended formats in classes 2, 3, and 4", HFILL}},
2317
14
    { &hf_cotp_opts_no_explicit_flow_control,
2318
14
      { "No explicit flow control", "cotp.opts.no_explicit_flow_control",
2319
14
        FT_BOOLEAN, 8, NULL, 0x01, "No explicit flow control in class 2",
2320
14
        HFILL}},
2321
14
    { &hf_cotp_tpdu_number,
2322
14
      { "TPDU number", "cotp.tpdu-number", FT_UINT8, BASE_HEX,
2323
14
        NULL, 0x7f, NULL, HFILL}},
2324
14
    { &hf_cotp_tpdu_number_extended,
2325
14
      { "TPDU number", "cotp.tpdu-number", FT_UINT32, BASE_HEX,
2326
14
        NULL, 0x0 /* XXX - 0x7fff? */, NULL, HFILL}},
2327
14
    { &hf_cotp_next_tpdu_number,
2328
14
      { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT8, BASE_HEX,
2329
14
        NULL, 0x0, NULL, HFILL}},
2330
14
    { &hf_cotp_next_tpdu_number_extended,
2331
14
      { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT32, BASE_HEX,
2332
14
        NULL, 0x0, NULL, HFILL}},
2333
14
    { &hf_cotp_eot,
2334
14
      { "Last data unit", "cotp.eot", FT_BOOLEAN, 8,
2335
14
        TFS(&tfs_yes_no),  0x80,
2336
14
        "Is current TPDU the last data unit of a complete DT TPDU sequence "
2337
14
        "(End of TSDU)?", HFILL}},
2338
14
    { &hf_cotp_eot_extended,
2339
14
      { "Last data unit", "cotp.eot", FT_BOOLEAN, 32,
2340
14
        TFS(&tfs_yes_no),  0x80000000,
2341
14
        "Is current TPDU the last data unit of a complete DT TPDU sequence "
2342
14
        "(End of TSDU)?", HFILL}},
2343
14
    { &hf_cotp_segment_overlap,
2344
14
      { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN, BASE_NONE,
2345
14
        NULL, 0x0, "Segment overlaps with other segments", HFILL }},
2346
14
    { &hf_cotp_segment_overlap_conflict,
2347
14
      { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict",
2348
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2349
14
        "Overlapping segments contained conflicting data", HFILL }},
2350
14
    { &hf_cotp_segment_multiple_tails,
2351
14
      { "Multiple tail segments found", "cotp.segment.multipletails",
2352
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2353
14
        "Several tails were found when reassembling the packet", HFILL }},
2354
14
    { &hf_cotp_segment_too_long_segment,
2355
14
      { "Segment too long", "cotp.segment.toolongsegment",
2356
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2357
14
        "Segment contained data past end of packet", HFILL }},
2358
14
    { &hf_cotp_segment_error,
2359
14
      { "Reassembly error", "cotp.segment.error", FT_FRAMENUM, BASE_NONE,
2360
14
        NULL, 0x0, "Reassembly error due to illegal segments", HFILL }},
2361
14
    { &hf_cotp_segment_count,
2362
14
      { "Segment count", "cotp.segment.count", FT_UINT32, BASE_DEC,
2363
14
        NULL, 0x0, NULL, HFILL }},
2364
14
    { &hf_cotp_segment,
2365
14
      { "COTP Segment", "cotp.segment", FT_FRAMENUM, BASE_NONE,
2366
14
        NULL, 0x0, NULL, HFILL }},
2367
14
    { &hf_cotp_segments,
2368
14
      { "COTP Segments", "cotp.segments", FT_NONE, BASE_NONE,
2369
14
        NULL, 0x0, NULL, HFILL }},
2370
14
    { &hf_cotp_reassembled_in,
2371
14
      { "Reassembled COTP in frame", "cotp.reassembled_in",
2372
14
        FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2373
14
        "This COTP packet is reassembled in this frame", HFILL }},
2374
14
    { &hf_cotp_reassembled_length,
2375
14
      { "Reassembled COTP length", "cotp.reassembled.length",
2376
14
        FT_UINT32, BASE_DEC, NULL, 0x0,
2377
14
        "The total length of the reassembled payload", HFILL }},
2378
/* ISO DP 8073 i13.3.4(a) Source and destination TSAPs are defined as
2379
   identifiers of unspecified type and length.
2380
   Some implementations of COTP use printable strings, others use raw bytes.
2381
   We always add both representations to the tree; one will always be hidden
2382
   depending on the tsap display preference */
2383
14
    { &hf_cotp_vp_src_tsap,
2384
14
      { "Source TSAP", "cotp.src-tsap", FT_STRING, BASE_NONE,
2385
14
        NULL, 0x0, "Calling TSAP", HFILL }},
2386
14
    { &hf_cotp_vp_src_tsap_bytes,
2387
14
      { "Source TSAP", "cotp.src-tsap-bytes", FT_BYTES, BASE_NONE,
2388
14
        NULL, 0x0, "Calling TSAP (bytes representation)", HFILL }},
2389
14
    { &hf_cotp_vp_dst_tsap,
2390
14
      { "Destination TSAP", "cotp.dst-tsap", FT_STRING, BASE_NONE,
2391
14
        NULL, 0x0, "Called TSAP", HFILL }},
2392
14
    { &hf_cotp_vp_dst_tsap_bytes,
2393
14
      { "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES, BASE_NONE,
2394
14
        NULL, 0x0, "Called TSAP (bytes representation)", HFILL }},
2395
      /* Generated from convert_proto_tree_add_text.pl */
2396
14
      { &hf_cotp_parameter_code, { "Parameter code", "cotp.parameter_code", FT_UINT8, BASE_HEX, VALS(tp_vpart_type_vals), 0x0, NULL, HFILL }},
2397
14
      { &hf_cotp_parameter_length, { "Parameter length", "cotp.parameter_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2398
14
      { &hf_cotp_parameter_value, { "Parameter value", "cotp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2399
14
      { &hf_cotp_atn_extended_checksum16, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2400
14
      { &hf_cotp_atn_extended_checksum32, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2401
14
      { &hf_cotp_atn_extended_checksum_status, { "ATN extended checksum Status", "cotp.atn_extended_checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
2402
14
      { &hf_cotp_ack_time, { "Ack time (ms)", "cotp.ack_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2403
14
      { &hf_cotp_res_error_rate_target_value, { "Residual error rate, target value", "cotp.res_error_rate.target_value", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2404
14
      { &hf_cotp_res_error_rate_min_accept, { "Residual error rate, minimum acceptable", "cotp.res_error_rate.min_accept", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2405
14
      { &hf_cotp_res_error_rate_tdsu, { "Residual error rate, TSDU size of interest", "cotp.res_error_rate.tdsu", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2406
14
      { &hf_cotp_vp_priority, { "Priority", "cotp.vp_priority", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2407
14
      { &hf_cotp_transit_delay_targ_calling_called, { "Transit delay, target value, calling-called (ms)", "cotp.transit_delay.targ_calling_called", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2408
14
      { &hf_cotp_transit_delay_max_accept_calling_called, { "Transit delay, maximum acceptable, calling-called (ms)", "cotp.transit_delay.max_accept_calling_called", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2409
14
      { &hf_cotp_transit_delay_targ_called_calling, { "Transit delay, target value, called-calling (ms)", "cotp.transit_delay.targ_called_calling", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2410
14
      { &hf_cotp_transit_delay_max_accept_called_calling, { "Transit delay, maximum acceptable, called-calling (ms)", "cotp.transit_delay.max_accept_called_calling", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2411
14
      { &hf_cotp_max_throughput_targ_calling_called, { "Maximum throughput, target value, calling-called (o/s)", "cotp.max_throughput.targ_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2412
14
      { &hf_cotp_max_throughput_min_accept_calling_called, { "Maximum throughput, minimum acceptable, calling-called (o/s)", "cotp.max_throughput.min_accept_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2413
14
      { &hf_cotp_max_throughput_targ_called_calling, { "Maximum throughput, target value, called-calling (o/s)", "cotp.max_throughput.targ_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2414
14
      { &hf_cotp_max_throughput_min_accept_called_calling, { "Maximum throughput, minimum acceptable, called-calling (o/s)", "cotp.max_throughput.min_accept_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2415
14
      { &hf_cotp_avg_throughput_targ_calling_called, { "Average throughput, target value, calling-called (o/s)", "cotp.avg_throughput.targ_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2416
14
      { &hf_cotp_avg_throughput_min_accept_calling_called, { "Average throughput, minimum acceptable, calling-called (o/s)", "cotp.avg_throughput.min_accept_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2417
14
      { &hf_cotp_avg_throughput_targ_called_calling, { "Average throughput, target value, called-calling (o/s)", "cotp.avg_throughput.targ_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2418
14
      { &hf_cotp_avg_throughput_min_accept_called_calling, { "Average throughput, minimum acceptable, called-calling (o/s)", "cotp.avg_throughput.min_accept_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2419
14
      { &hf_cotp_sequence_number, { "Sequence number", "cotp.sequence_number", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2420
14
      { &hf_cotp_reassignment_time, { "Reassignment time (secs)", "cotp.reassignment_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2421
14
      { &hf_cotp_lower_window_edge, { "Lower window edge", "cotp.lower_window_edge", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2422
14
      { &hf_cotp_credit, { "Credit", "cotp.credit", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2423
14
      { &hf_cotp_tpdu_size, { "TPDU size", "cotp.tpdu_size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2424
14
      { &hf_cotp_checksum, { "Checksum", "cotp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2425
14
      { &hf_cotp_checksum_status, { "Checksum Status", "cotp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
2426
14
      { &hf_cotp_vp_version_nr, { "Version", "cotp.vp_version_nr", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2427
14
      { &hf_cotp_network_expedited_data, { "Use of network expedited data", "cotp.network_expedited_data", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x08, NULL, HFILL }},
2428
14
      { &hf_cotp_vp_opt_sel_class1_use, { "Use", "cotp.vp_opt_sel_class1_use", FT_BOOLEAN, 8, TFS(&tfs_vp_opt_sel_class1_use), 0x04, NULL, HFILL }},
2429
14
      { &hf_cotp_use_16_bit_checksum, { "16 bit checksum", "cotp.use_16_bit_checksum", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x02, NULL, HFILL }},
2430
14
      { &hf_cotp_transport_expedited_data_transfer, { "Transport expedited data transfer", "cotp.transport_expedited_data_transfer", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x01, NULL, HFILL }},
2431
14
      { &hf_cotp_preferred_maximum_tpdu_size, { "Preferred maximum TPDU size", "cotp.preferred_maximum_tpdu_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2432
14
      { &hf_cotp_inactivity_timer, { "Inactivity timer (ms)", "cotp.inactivity_timer", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2433
14
      { &hf_cotp_cause, { "Cause", "cotp.cause", FT_UINT8, BASE_DEC, VALS(cotp_cause_vals), 0x0, NULL, HFILL }},
2434
14
      { &hf_cotp_segment_data, { "COTP segment data", "cotp.segment_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2435
14
      { &hf_cotp_credit_cdt, { "Credit", "cotp.credit", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2436
14
      { &hf_cotp_reject_cause, { "Reject cause", "cotp.reject_cause", FT_UINT8, BASE_DEC, VALS(cotp_reject_vals), 0x0, NULL, HFILL }},
2437
14
  };
2438
14
  static int *ett[] = {
2439
14
    &ett_cotp,
2440
14
    &ett_cotp_segment,
2441
14
    &ett_cotp_segments
2442
14
  };
2443
14
  static ei_register_info ei[] = {
2444
14
      { &ei_cotp_disconnect_request, { "cotp.disconnect_request", PI_SEQUENCE, PI_CHAT, "Disconnect Request(DR)", EXPFILL }},
2445
14
      { &ei_cotp_reject, { "cotp.reject", PI_SEQUENCE, PI_NOTE, "Reject(RJ)", EXPFILL }},
2446
14
      { &ei_cotp_connection, { "cotp.connection", PI_SEQUENCE, PI_CHAT, "Connection", EXPFILL }},
2447
14
      { &ei_cotp_disconnect_confirm, { "cotp.disconnect_confirm", PI_SEQUENCE, PI_CHAT, "Disconnect Confirm(DC)", EXPFILL }},
2448
14
      { &ei_cotp_multiple_tpdus, { "cotp.multiple_tpdus", PI_SEQUENCE, PI_NOTE, "Multiple TPDUs in one packet", EXPFILL }},
2449
14
      { &ei_cotp_preferred_maximum_tpdu_size, { "cotp.preferred_maximum_tpdu_size.invalid", PI_PROTOCOL, PI_WARN, "Preferred maximum TPDU size: bogus length", EXPFILL }},
2450
14
      { &ei_cotp_atn_extended_checksum, { "cotp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2451
14
      { &ei_cotp_checksum, { "cotp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2452
14
  };
2453
2454
14
  module_t *cotp_module;
2455
14
  expert_module_t* expert_cotp;
2456
2457
14
  proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "COTP", "cotp");
2458
14
  proto_register_field_array(proto_cotp, hf, array_length(hf));
2459
14
  proto_register_subtree_array(ett, array_length(ett));
2460
14
  expert_cotp = expert_register_protocol(proto_cotp);
2461
14
  expert_register_field_array(expert_cotp, ei, array_length(ei));
2462
14
  cotp_module = prefs_register_protocol(proto_cotp, NULL);
2463
2464
14
  prefs_register_bool_preference(cotp_module, "reassemble",
2465
14
                                 "Reassemble segmented COTP datagrams",
2466
14
                                 "Whether segmented COTP datagrams should be "
2467
14
                                 "reassembled. To use this option, you must "
2468
14
                                 "also enable \"Allow subdissectors to "
2469
14
                                 "reassemble TCP streams\" in the TCP "
2470
14
                                 "protocol settings.",
2471
14
                                 &cotp_reassemble);
2472
2473
14
  prefs_register_enum_preference(cotp_module, "tsap_display",
2474
14
                                 "Display TSAPs as strings or bytes",
2475
14
                                 "How TSAPs should be displayed",
2476
14
                                 &tsap_display, tsap_display_options, false);
2477
2478
14
  prefs_register_bool_preference(cotp_module, "decode_atn", "Decode ATN TPDUs",
2479
14
                                 "Whether to decode OSI TPDUs with ATN "
2480
14
                                 "(Aeronautical Telecommunications Network) "
2481
14
                                 "extensions. To use this option, you must "
2482
14
                                 "also enable \"Always try to decode NSDU as "
2483
14
                                 "transport PDUs\" in the CLNP protocol "
2484
14
                                 "settings.", &cotp_decode_atn);
2485
2486
  /* For handling protocols hijacking the variable part of CR or CC PDUs */
2487
14
  cotp_cr_heur_subdissector_list = register_heur_dissector_list_with_description("cotp_cr", "COTP CR (Connect Request) payload", proto_cotp);
2488
14
  cotp_cc_heur_subdissector_list = register_heur_dissector_list_with_description("cotp_cc", "COTP CC (Connect Confirm) payload", proto_cotp);
2489
2490
  /* subdissector code in inactive subset */
2491
14
  cotp_is_heur_subdissector_list = register_heur_dissector_list_with_description("cotp_is", "COTP IS (Inactive Subset) payload", proto_cotp);
2492
2493
  /* other COTP/ISO 8473 subdissectors */
2494
14
  cotp_heur_subdissector_list = register_heur_dissector_list_with_description("cotp", "COTP DT (Data) payload", proto_cotp);
2495
2496
  /* XXX - what about CLTP and proto_cltp? */
2497
14
  ositp_handle = register_dissector("ositp", dissect_ositp, proto_cotp);
2498
14
  register_dissector("ositp_inactive", dissect_ositp_inactive, proto_cotp);
2499
2500
14
  register_init_routine(cotp_reassemble_init);
2501
  /*
2502
   * XXX - this is a connection-oriented transport-layer protocol,
2503
   * so we should probably use more than just network-layer
2504
   * endpoint addresses to match segments together, but the functions
2505
   * in addresses_ports_reassembly_table_functions do matching based
2506
   * on port numbers, so they won't let us ensure that segments from
2507
   * different connections don't get assembled together.
2508
   */
2509
14
  reassembly_table_register(&cotp_reassembly_table,
2510
14
                        &addresses_reassembly_table_functions);
2511
14
}
2512
2513
void proto_register_cltp(void)
2514
14
{
2515
14
  static hf_register_info hf[] = {
2516
14
    { &hf_cltp_li,
2517
14
      { "Length", "cltp.li", FT_UINT8, BASE_DEC, NULL, 0x0,
2518
14
        "Length Indicator, length of this header", HFILL}},
2519
14
    { &hf_cltp_type,
2520
14
      { "PDU Type", "cltp.type", FT_UINT8, BASE_HEX,
2521
14
        VALS(cltp_tpdu_type_abbrev_vals), 0x0, NULL, HFILL}}
2522
14
  };
2523
14
  static int *ett[] = {
2524
14
    &ett_cltp
2525
14
  };
2526
2527
14
  proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "CLTP", "cltp");
2528
14
  proto_register_field_array(proto_cltp, hf, array_length(hf));
2529
14
  proto_register_subtree_array(ett, array_length(ett));
2530
2531
14
  cltp_heur_subdissector_list = register_heur_dissector_list_with_description("cltp", "CLTP data atop CLNP", proto_cltp);
2532
14
}
2533
2534
void
2535
proto_reg_handoff_cotp(void)
2536
14
{
2537
14
  dissector_add_uint("ip.proto", IP_PROTO_TP, ositp_handle);
2538
2539
14
  rdp_cr_handle = find_dissector("rdp_cr");
2540
14
  rdp_cc_handle = find_dissector("rdp_cc");
2541
2542
14
  proto_clnp = proto_get_id_by_filter_name("clnp");
2543
2544
  /* Actual implementations of R-GOOSE seem to use UDP port 102, registered
2545
   * for ISO-TSAP, cf. TPKT. Perhaps we should just register ositp_handle
2546
   * to UDP port 102 instead of having a heuristic dissector?
2547
   */
2548
14
  heur_dissector_add("udp", dissect_cltp_heur, "CLTP over UDP",
2549
14
        "cltp_udp", proto_cltp, HEURISTIC_ENABLE);
2550
14
}
2551
2552
/*
2553
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2554
 *
2555
 * Local variables:
2556
 * c-basic-offset: 2
2557
 * tab-width: 8
2558
 * indent-tabs-mode: nil
2559
 * End:
2560
 *
2561
 * vi: set shiftwidth=2 tabstop=8 expandtab:
2562
 * :indentSize=2:tabSize=8:noTabs=true:
2563
 */