Coverage Report

Created: 2026-09-28 06:52

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