Coverage Report

Created: 2026-08-14 06:45

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
137
#define ED_TPDU             0x1 /* COTP */
161
149
#define EA_TPDU             0x2 /* COTP */
162
9.76k
#define UD_TPDU             0x4 /* CLTP */
163
64
#define RJ_TPDU             0x5 /* COTP */
164
101
#define AK_TPDU             0x6 /* COTP */
165
116
#define ER_TPDU             0x7 /* COTP */
166
164
#define DR_TPDU             0x8 /* COTP */
167
29
#define DC_TPDU             0xC /* COTP */
168
136
#define CC_TPDU             0xD /* COTP */
169
1.07k
#define CR_TPDU             0xE /* COTP */
170
6.69k
#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.61k
#define P_LI                0
205
8.40k
#define P_TPDU              1
206
8.40k
#define P_CDT               1
207
1.47k
#define P_DST_REF           2
208
436
#define P_SRC_REF           4
209
5.52k
#define P_TPDU_NR_0_1       2
210
1.15k
#define P_TPDU_NR_234       4
211
32
#define P_VAR_PART_NDT      5
212
22
#define P_VAR_PART_EDT      8
213
#define P_VAR_PART_DC       6
214
21
#define P_CDT_IN_AK         8
215
0
#define P_CDT_IN_RJ         8
216
99
#define P_REJECT_ER         4
217
115
#define P_REASON_IN_DR      6
218
305
#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.52k
#define LI_NORMAL_DT_CLASS_01           2
227
846
#define LI_NORMAL_DT_WITHOUT_CHECKSUM   4
228
24
#define LI_NORMAL_DT_WITH_CHECKSUM      (LI_NORMAL_DT_WITHOUT_CHECKSUM+4)
229
217
#define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
230
20
#define LI_EXTENDED_DT_WITH_CHECKSUM    (LI_EXTENDED_DT_WITHOUT_CHECKSUM+4)
231
24
#define LI_NORMAL_EA_WITHOUT_CHECKSUM   4
232
8
#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
57
#define LI_NORMAL_RJ                    4
236
0
#define LI_EXTENDED_RJ                  9
237
164
#define LI_MIN_DR                       6
238
29
#define LI_MAX_DC                       9
239
101
#define LI_MAX_AK                       27
240
149
#define LI_MAX_EA                       11
241
116
#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
84
#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
11
#define VP_ACK_TIME             0x85
268
36
#define VP_RES_ERROR            0x86
269
17
#define VP_PRIORITY             0x87
270
82
#define VP_TRANSIT_DEL          0x88
271
29
#define VP_THROUGHPUT           0x89
272
15
#define VP_SEQ_NR               0x8A        /* in AK */
273
10
#define VP_REASSIGNMENT         0x8B
274
68
#define VP_FLOW_CNTL            0x8C        /* in AK */
275
17
#define VP_TPDU_SIZE            0xC0
276
35
#define VP_SRC_TSAP             0xC1        /* in CR/CC */
277
23
#define VP_DST_TSAP             0xC2
278
87
#define VP_CHECKSUM             0xC3
279
8
#define VP_VERSION_NR           0xC4
280
0
#define VP_PROTECTION           0xC5
281
32
#define VP_OPT_SEL              0xC6
282
0
#define VP_PROTO_CLASS          0xC7
283
1
#define VP_CLEARING_INFO        0xE0        /* in DR */
284
23
#define VP_PREF_MAX_TPDU_SIZE   0xF0
285
8
#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
107
#define VP_ATN_EC_32            0x08        /* 4 octet ATN Extended Transport Checksum parameter */
292
59
#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
98
#define TSAP_DISPLAY_AUTO   0
345
98
#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
83
#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.56k
{
379
5.56k
  conversation_t *conv;
380
5.56k
  cotp_conv_info_t *conv_info;
381
5.56k
  int direction;
382
383
5.56k
  conv = find_or_create_conversation(pinfo);
384
5.56k
  conv_info = conversation_get_proto_data(conv, proto_cotp);
385
5.56k
  if (!conv_info) {
386
536
    conv_info = wmem_new0(wmem_file_scope(), cotp_conv_info_t);
387
536
    conversation_add_proto_data(conv, proto_cotp, conv_info);
388
536
  }
389
390
  /* check direction; first compare addreses, then ports. */
391
5.56k
  direction = cmp_address(&pinfo->src, &pinfo->dst);
392
5.56k
  if (direction==0) {
393
97
    direction = (pinfo->srcport > pinfo->destport) ? 1 : -1;
394
97
  }
395
396
5.56k
  if (direction >= 0) {
397
1.93k
    conv_info->fwd = &(conv_info->flow[0]);
398
1.93k
    conv_info->rev = &(conv_info->flow[1]);
399
3.62k
  } else {
400
3.62k
    conv_info->fwd = &(conv_info->flow[1]);
401
3.62k
    conv_info->rev = &(conv_info->flow[0]);
402
3.62k
  }
403
404
5.56k
  return conv_info;
405
5.56k
}
406
407
static uint16_t get_cotp_frag_id(packet_info *pinfo, cotp_flow_info_t *flow_info, bool fragment)
408
5.50k
{
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.50k
  uint16_t           frag_id;
421
5.50k
  unsigned           flow_index = 0;
422
5.50k
  bool               flow_first_seen = true;
423
5.50k
  wmem_list_t       *used_flow_list;
424
5.50k
  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.50k
  used_flow_list = (wmem_list_t *)p_get_proto_data(pinfo->pool, pinfo, proto_cotp, 0);
431
5.50k
  if (!used_flow_list) {
432
1.20k
    used_flow_list = wmem_list_new(pinfo->pool);
433
1.20k
    p_add_proto_data(pinfo->pool, pinfo, proto_cotp, 0, used_flow_list);
434
4.30k
  } else {
435
4.30k
    if (wmem_list_find(used_flow_list, flow_info)) {
436
4.21k
      flow_first_seen = false;
437
4.21k
    } else {
438
91
      flow_index = wmem_list_count(used_flow_list);
439
91
    }
440
4.30k
  }
441
5.50k
  wmem_list_append(used_flow_list, flow_info);
442
5.50k
  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.29k
    if (!flow_info->last_fragment) {
448
753
      flow_info->frag_id = 0;
449
753
    }
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.29k
    prev_dst_ref = (uint32_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_cotp, flow_index);
456
1.29k
    if (!prev_dst_ref) {
457
1.29k
      DISSECTOR_ASSERT(!PINFO_FD_VISITED(pinfo));
458
1.29k
      prev_dst_ref = wmem_new(wmem_file_scope(), uint32_t);
459
1.29k
      *prev_dst_ref = flow_info->frag_id;
460
1.29k
      p_add_proto_data(wmem_file_scope(), pinfo, proto_cotp, flow_index, prev_dst_ref);
461
1.29k
    } else {
462
0
      flow_info->frag_id = *prev_dst_ref;
463
0
    }
464
1.29k
  }
465
5.50k
  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.50k
  flow_info->last_fragment = fragment;
470
5.50k
  if (!fragment) {
471
1.93k
    flow_info->frag_id++;
472
1.93k
  }
473
5.50k
  return frag_id;
474
5.50k
}
475
476
static char *print_tsap(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
477
46
{
478
46
  const unsigned char *tsap = tvb_get_ptr(tvb, offset, length);
479
46
  char     *cur;
480
46
  bool      allprintable;
481
46
  int       idx = 0, returned_length;
482
483
46
  cur=(char *)wmem_alloc(scope, MAX_TSAP_LEN * 2 + 3);
484
46
  cur[0] = '\0';
485
46
  if (length <= 0 || length > MAX_TSAP_LEN)
486
46
    snprintf(cur, MAX_TSAP_LEN * 2 + 3, "<unsupported TSAP length>");
487
18
  else {
488
18
    allprintable = tvb_ascii_isprint(tvb, offset, length);
489
18
    if (!allprintable) {
490
13
      returned_length = snprintf(cur, MAX_TSAP_LEN * 2 + 3, "0x");
491
13
      idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - 1);
492
13
    }
493
107
    while (length != 0) {
494
89
      if (allprintable) {
495
6
        returned_length = snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
496
6
                                     "%c", *tsap ++);
497
6
        idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
498
83
      } else {
499
83
        returned_length = snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
500
83
                                     "%02x", *tsap ++);
501
83
        idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
502
83
      }
503
89
      length --;
504
89
    }
505
18
  }
506
46
  return cur;
507
508
46
} /* 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.97k
{
516
6.97k
  uint8_t         code, length;
517
6.97k
  uint8_t         c1;
518
6.97k
  uint16_t        s;
519
6.97k
  uint32_t        offset_iso8073_checksum = 0;
520
6.97k
  int32_t         i                       = 0;
521
6.97k
  uint8_t         tmp_code                = 0;
522
6.97k
  unsigned        tmp_len                 = 0;
523
6.97k
  uint32_t        pref_max_tpdu_size;
524
6.97k
  proto_item     *hidden_item;
525
526
9.32k
  while (vp_length != 0) {
527
2.85k
    proto_tree_add_item_ret_uint8(tree, hf_cotp_parameter_code, tvb, offset, 1, ENC_NA, &code);
528
2.85k
    offset += 1;
529
2.85k
    vp_length -= 1;
530
531
2.85k
    if (vp_length == 0)
532
134
      break;
533
2.72k
    proto_tree_add_item_ret_uint8(tree, hf_cotp_parameter_length, tvb, offset, 1, ENC_NA, &length);
534
2.72k
    offset += 1;
535
2.72k
    vp_length -= 1;
536
537
2.72k
    switch (code) {
538
539
59
    case VP_ATN_EC_16 : /* ATN */
540
59
      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
59
      } else {
564
59
        proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
565
59
      }
566
59
      offset += length;
567
59
      vp_length -= length;
568
59
      break;
569
570
107
    case VP_ATN_EC_32 : /* ATN */
571
107
      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
107
      } else {
595
107
        proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
596
107
      }
597
107
      offset += length;
598
107
      vp_length -= length;
599
107
      break;
600
601
11
    case VP_ACK_TIME:
602
11
      proto_tree_add_item(tree, hf_cotp_ack_time, tvb, offset, length, ENC_BIG_ENDIAN);
603
11
      offset += length;
604
11
      vp_length -= length;
605
11
      break;
606
607
36
    case VP_RES_ERROR:
608
36
      s = tvb_get_uint8(tvb, offset);
609
36
      proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_target_value, tvb, offset, 1, s, "10^%u", s);
610
36
      offset += 1;
611
36
      vp_length -= 1;
612
613
36
      s = tvb_get_uint8(tvb, offset);
614
36
      proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_min_accept, tvb, offset, 1, s, "10^%u", s);
615
36
      offset += 1;
616
36
      vp_length -= 1;
617
618
36
      s = tvb_get_uint8(tvb, offset);
619
36
      proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_tdsu, tvb, offset, 1, s, "2^%u", s);
620
36
      offset += 1;
621
36
      vp_length -= 1;
622
36
      break;
623
624
17
    case VP_PRIORITY:
625
17
      proto_tree_add_item(tree, hf_cotp_vp_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
626
17
      offset += length;
627
17
      vp_length -= length;
628
17
      break;
629
630
82
    case VP_TRANSIT_DEL:
631
82
      proto_tree_add_item(tree, hf_cotp_transit_delay_targ_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
632
82
      offset += 2;
633
82
      vp_length -= 2;
634
635
82
      proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
636
82
      offset += 2;
637
82
      vp_length -= 2;
638
639
82
      proto_tree_add_item(tree, hf_cotp_transit_delay_targ_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
640
82
      offset += 2;
641
82
      vp_length -= 2;
642
643
82
      proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
644
82
      offset += 2;
645
82
      vp_length -= 2;
646
82
      break;
647
648
29
    case VP_THROUGHPUT:
649
29
      proto_tree_add_item(tree, hf_cotp_max_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
650
29
      offset += 3;
651
29
      length -= 3;
652
29
      vp_length -= 3;
653
654
29
      proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
655
29
      offset += 3;
656
29
      length -= 3;
657
29
      vp_length -= 3;
658
659
29
      proto_tree_add_item(tree, hf_cotp_max_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
660
29
      offset += 3;
661
29
      length -= 3;
662
29
      vp_length -= 3;
663
664
29
      proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
665
29
      offset += 3;
666
29
      length -= 3;
667
29
      vp_length -= 3;
668
669
29
      if (length != 0) {    /* XXX - should be 0 or 12 */
670
29
        proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
671
29
        offset += 3;
672
29
        vp_length -= 3;
673
674
29
        proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
675
29
        offset += 3;
676
29
        vp_length -= 3;
677
678
29
        proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
679
29
        offset += 3;
680
29
        vp_length -= 3;
681
682
29
        proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
683
29
        offset += 3;
684
29
        vp_length -= 3;
685
29
      }
686
29
      break;
687
688
15
    case VP_SEQ_NR:
689
15
      proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
690
15
      offset += length;
691
15
      vp_length -= length;
692
15
      break;
693
694
10
    case VP_REASSIGNMENT:
695
10
      proto_tree_add_item(tree, hf_cotp_reassignment_time, tvb, offset, 2, ENC_BIG_ENDIAN);
696
10
      offset += length;
697
10
      vp_length -= length;
698
10
      break;
699
700
68
    case VP_FLOW_CNTL:
701
68
      proto_tree_add_item(tree, hf_cotp_lower_window_edge, tvb, offset, 4, ENC_BIG_ENDIAN);
702
68
      offset += 4;
703
68
      vp_length -= 4;
704
705
68
      proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
706
68
      offset += 2;
707
68
      vp_length -= 2;
708
709
68
      proto_tree_add_item(tree, hf_cotp_credit, tvb, offset, 2, ENC_BIG_ENDIAN);
710
68
      offset += 2;
711
68
      vp_length -= 2;
712
713
68
      break;
714
715
17
    case VP_TPDU_SIZE:
716
17
      c1 = tvb_get_uint8(tvb, offset) & 0x0F;
717
17
      proto_tree_add_uint(tree, hf_cotp_tpdu_size, tvb, offset, 1, 1 << c1);
718
17
      offset += length;
719
17
      vp_length -= length;
720
17
      break;
721
722
31
    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
31
      if (tsap_display==TSAP_DISPLAY_STRING ||
726
31
          (tsap_display==TSAP_DISPLAY_AUTO &&
727
31
            tvb_ascii_isprint(tvb, offset, length))) {
728
9
        proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
729
9
                              print_tsap(pinfo->pool, tvb, offset, length));
730
9
        hidden_item = proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb,
731
9
                                          offset, length, ENC_NA);
732
9
        proto_item_set_hidden(hidden_item);
733
22
      } else {
734
22
        hidden_item = proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb,
735
22
                                            offset, length,
736
22
                                            print_tsap(pinfo->pool, tvb, offset, length));
737
22
        proto_item_set_hidden(hidden_item);
738
22
        proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset,
739
22
                            length, ENC_NA);
740
22
      }
741
31
      offset += length;
742
31
      vp_length -= length;
743
31
      break;
744
745
18
    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
18
      if (tsap_display==TSAP_DISPLAY_STRING ||
749
18
          (tsap_display==TSAP_DISPLAY_AUTO &&
750
18
            tvb_ascii_isprint(tvb, offset, length))) {
751
5
        proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
752
5
                              print_tsap(pinfo->pool, tvb, offset, length));
753
5
        hidden_item = proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb,
754
5
                                          offset, length, ENC_NA);
755
5
        proto_item_set_hidden(hidden_item);
756
13
      } else {
757
13
        hidden_item = proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb,
758
13
                                            offset, length,
759
13
                                            print_tsap(pinfo->pool, tvb, offset, length));
760
13
        proto_item_set_hidden(hidden_item);
761
13
        proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset,
762
13
                            length, ENC_NA);
763
13
      }
764
18
      offset += length;
765
18
      vp_length -= length;
766
18
      break;
767
768
16
    case VP_CHECKSUM:
769
16
      offset_iso8073_checksum = offset; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
770
771
16
      if (tvb_get_ntohs(tvb, offset) == 0) {
772
        /* No checksum present */
773
2
        proto_tree_add_checksum(tree, tvb, offset, hf_cotp_checksum, hf_cotp_checksum_status, &ei_cotp_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NOT_PRESENT);
774
14
      } else {
775
14
        uint32_t calc_c0 = 0, calc_c1 = 0;
776
777
14
        if (osi_calc_checksum(tvb, 0, tpdu_len, &calc_c0, &calc_c1)) {
778
            /* Successfully processed checksum, verify it */
779
14
            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
14
        } 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
14
      }
784
785
16
      offset += length;
786
16
      vp_length -= length;
787
16
      break;
788
789
8
    case VP_VERSION_NR:
790
8
      proto_tree_add_item(tree, hf_cotp_vp_version_nr, tvb, offset, 1, ENC_NA);
791
8
      offset += length;
792
8
      vp_length -= length;
793
8
      break;
794
795
32
    case VP_OPT_SEL:
796
32
      switch (class_option) {
797
798
6
      case 1:
799
6
        proto_tree_add_item(tree, hf_cotp_network_expedited_data, tvb, offset, 1, ENC_NA);
800
801
6
        proto_tree_add_item(tree, hf_cotp_vp_opt_sel_class1_use, tvb, offset, 1, ENC_NA);
802
6
        break;
803
804
16
      case 4:
805
16
        proto_tree_add_item(tree, hf_cotp_use_16_bit_checksum, tvb, offset, 1, ENC_NA);
806
16
        break;
807
32
      }
808
809
32
      proto_tree_add_item(tree, hf_cotp_transport_expedited_data_transfer, tvb, offset, 1, ENC_NA);
810
32
      offset += length;
811
32
      vp_length -= length;
812
32
      break;
813
814
23
    case VP_PREF_MAX_TPDU_SIZE:
815
23
      switch (length) {
816
817
2
      case 1:
818
2
        pref_max_tpdu_size = tvb_get_uint8(tvb, offset);
819
2
        break;
820
821
2
      case 2:
822
2
        pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
823
2
        break;
824
825
2
      case 3:
826
2
        pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
827
2
        break;
828
829
0
      case 4:
830
0
        pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
831
0
        break;
832
833
17
      default:
834
17
        proto_tree_add_expert_format(tree, pinfo, &ei_cotp_preferred_maximum_tpdu_size, tvb, offset, length,
835
17
                            "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)", length);
836
17
        return false;
837
23
      }
838
6
      proto_tree_add_uint(tree, hf_cotp_preferred_maximum_tpdu_size, tvb, offset, length, pref_max_tpdu_size*128);
839
6
      offset += length;
840
6
      vp_length -= length;
841
6
      break;
842
843
8
    case VP_INACTIVITY_TIMER:
844
8
      proto_tree_add_item(tree, hf_cotp_inactivity_timer, tvb, offset, length, ENC_BIG_ENDIAN);
845
8
      offset += length;
846
8
      vp_length -= length;
847
8
      break;
848
849
0
    case VP_PROTECTION:             /* user-defined */
850
0
    case VP_PROTO_CLASS:            /* todo */
851
1
    case VP_CLEARING_INFO:          /* user-defined */
852
2.07k
    default:                        /* unknown, no decoding */
853
2.07k
      proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
854
2.07k
      offset += length;
855
2.07k
      vp_length -= length;
856
2.07k
      break;
857
2.72k
    }
858
2.72k
  } /* while */
859
860
6.60k
  return true;
861
6.97k
}
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
164
{
883
164
  proto_tree *cotp_tree = NULL;
884
164
  proto_item *ti        = NULL;
885
164
  uint16_t    dst_ref, src_ref;
886
164
  unsigned char      reason;
887
164
  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
164
  if (li < LI_MIN_DR)
892
49
    return -1;
893
894
  /* DR TPDUs can have user data, so they run to the end of the containing PDU */
895
115
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
896
897
115
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
898
899
115
  src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
900
901
115
  reason  = tvb_get_uint8(tvb, offset + P_REASON_IN_DR);
902
903
115
  pinfo->clnp_dstref = dst_ref;
904
115
  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
115
  if (try_val_to_str(reason, cotp_cause_vals) == NULL)
919
53
      return -1;
920
921
62
  col_append_fstr(pinfo->cinfo, COL_INFO,
922
62
                  "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
923
924
62
  if (tree) {
925
60
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
926
60
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
927
60
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
928
60
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1, tpdu);
929
60
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
930
60
                        dst_ref);
931
60
    proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset +  4, 2,
932
60
                        src_ref);
933
60
    proto_tree_add_item(cotp_tree, hf_cotp_cause, tvb, offset + 6, 1, ENC_NA);
934
60
  }
935
62
  offset += 7;
936
62
  li -= 6;
937
938
62
  if (tree)
939
60
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
940
62
  offset += li;
941
942
62
  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
62
  call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
946
62
  offset += tvb_captured_length_remaining(tvb, offset);
947
     /* we dissected all of the containing PDU */
948
949
62
  return offset;
950
951
115
} /* 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.69k
{
958
6.69k
  proto_tree        *cotp_tree       = NULL;
959
6.69k
  proto_item        *ti;
960
6.69k
  bool               is_extended;
961
6.69k
  bool               is_class_234;
962
6.69k
  cotp_conv_info_t  *conv_info;
963
6.69k
  uint32_t           dst_ref;
964
6.69k
  unsigned           tpdu_nr;
965
6.69k
  bool               fragment        = false;
966
6.69k
  uint32_t           fragment_length = 0;
967
6.69k
  tvbuff_t          *next_tvb;
968
6.69k
  fragment_head     *fd_head;
969
6.69k
  unsigned           tpdu_len;
970
6.69k
  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.69k
  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.69k
  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.69k
  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.69k
    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
20
          return -1;
1001
        /* FALLTHROUGH */
1002
1003
725
      case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
1004
725
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1005
725
        if (tpdu_nr & 0x80)
1006
249
          tpdu_nr = tpdu_nr & 0x7F;
1007
476
        else
1008
476
          fragment = true;
1009
725
        is_extended = false;
1010
725
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1011
725
        break;
1012
1013
19
      case LI_EXTENDED_DT_WITH_CHECKSUM    :
1014
19
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1015
19
          return -1;
1016
        /* FALLTHROUGH */
1017
1018
186
      case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1019
186
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1020
186
        if (tpdu_nr & 0x80000000)
1021
55
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1022
131
        else
1023
131
          fragment = true;
1024
186
        is_extended = true;
1025
186
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1026
186
        break;
1027
1028
5.52k
      case LI_NORMAL_DT_CLASS_01           :
1029
5.52k
        is_class_234 = false;
1030
5.52k
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_0_1);
1031
5.52k
        if (tpdu_nr & 0x80)
1032
1.93k
          tpdu_nr = tpdu_nr & 0x7F;
1033
3.59k
        else
1034
3.59k
          fragment = true;
1035
5.52k
        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.52k
        conv_info = get_cotp_conv_info(pinfo);
1039
5.52k
        dst_ref = conv_info->fwd->ref; // Note this may default to zero if not set
1040
5.52k
        break;
1041
1042
211
      default : /* bad TPDU */
1043
211
        return -1;
1044
6.69k
    } /* li */
1045
6.69k
  } 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.33k
  pinfo->clnp_dstref = dst_ref;
1125
1126
6.33k
  pinfo->fragmented = fragment;
1127
6.33k
  if (is_class_234 || conv_info->fwd->ref_set) {
1128
845
    col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x",
1129
845
                      tpdu_nr, dst_ref);
1130
5.48k
  } else {
1131
5.48k
    col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u)", tpdu_nr);
1132
5.48k
  }
1133
1134
6.33k
  if (tree) {
1135
6.33k
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1136
6.33k
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1137
6.33k
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1138
6.33k
  }
1139
6.33k
  offset += 1;
1140
1141
6.33k
  if (tree) {
1142
6.33k
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1143
6.33k
  }
1144
6.33k
  offset += 1;
1145
6.33k
  li -= 1;
1146
1147
6.33k
  if (is_class_234) {
1148
831
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1149
831
    offset += 2;
1150
831
    li -= 2;
1151
5.50k
  } else if (conv_info->fwd->ref_set) {
1152
14
    ti = proto_tree_add_uint (cotp_tree, hf_cotp_destref, tvb, offset, 0,
1153
14
                              conv_info->fwd->ref);
1154
14
    proto_item_set_generated (ti);
1155
14
  }
1156
1157
6.33k
  if (is_extended) {
1158
182
    if (tree) {
1159
182
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1160
182
                          4, tpdu_nr);
1161
182
      proto_tree_add_item(cotp_tree, hf_cotp_eot_extended, tvb, offset, 4,
1162
182
                          ENC_BIG_ENDIAN);
1163
182
    }
1164
182
    offset += 4;
1165
182
    li -= 4;
1166
6.15k
  } else {
1167
6.15k
    if (tree) {
1168
6.15k
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1169
6.15k
                          tpdu_nr);
1170
6.15k
      proto_tree_add_item(cotp_tree, hf_cotp_eot, tvb, offset, 1,
1171
6.15k
                          ENC_BIG_ENDIAN);
1172
6.15k
    }
1173
6.15k
    offset += 1;
1174
6.15k
    li -= 1;
1175
6.15k
  }
1176
1177
6.33k
  if (tree)
1178
6.33k
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1179
6.33k
  offset += li;
1180
1181
6.33k
  next_tvb = tvb_new_subset_remaining(tvb, offset);
1182
6.33k
  fragment_length = tvb_captured_length(next_tvb);
1183
6.33k
  if (fragment) {
1184
4.09k
    col_append_fstr(pinfo->cinfo, COL_INFO, " [COTP fragment, %u byte%s]",
1185
4.09k
        fragment_length, plurality(fragment_length, "", "s"));
1186
4.09k
  } else {
1187
2.23k
    col_append_str(pinfo->cinfo, COL_INFO, " EOT");
1188
2.23k
  }
1189
1190
6.33k
  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.33k
    uint32_t frag_id;
1212
6.33k
    if (is_class_234) {
1213
831
        frag_id = dst_ref;
1214
5.50k
    } else {
1215
5.50k
        frag_id = get_cotp_frag_id(pinfo, conv_info->fwd, fragment);
1216
5.50k
    }
1217
6.33k
    fd_head = fragment_add_seq_next(&cotp_reassembly_table, next_tvb, 0, pinfo,
1218
6.33k
                                    frag_id, NULL, fragment_length, fragment);
1219
6.33k
    if (fd_head && fd_head->next) {
1220
      /* don't use -1 if fragment length is zero (throws Exception) */
1221
1.21k
      proto_tree_add_bytes_format(cotp_tree, hf_cotp_segment_data, tvb, offset, (fragment_length) ? -1 : 0,
1222
1.21k
                          NULL, "COTP segment data (%u byte%s)", fragment_length,
1223
1.21k
                          plurality(fragment_length, "", "s"));
1224
1225
1.21k
      if (!fragment) {
1226
        /* This is the last packet */
1227
1.21k
        next_tvb = process_reassembled_data (next_tvb, offset, pinfo,
1228
1.21k
                                             "Reassembled COTP", fd_head,
1229
1.21k
                                             &cotp_frag_items, NULL, tree);
1230
1.21k
      } 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.21k
      pinfo->fragmented = fragment;
1236
1.21k
    }
1237
6.33k
  }
1238
1239
6.33k
  if (uses_inactive_subset) {
1240
6.29k
    if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1241
6.29k
                                pinfo, tree, &hdtbl_entry, NULL)) {
1242
1.45k
      *subdissector_found = true;
1243
4.84k
    } else {
1244
      /* Fill in other Dissectors using inactive subset here */
1245
4.84k
      call_data_dissector(next_tvb, pinfo, tree);
1246
4.84k
    }
1247
6.29k
  } 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
38
    if (!cotp_reassemble || !fragment) {
1255
35
      if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1256
35
                                  tree, &hdtbl_entry, NULL)) {
1257
3
        *subdissector_found = true;
1258
32
      } else {
1259
32
        call_data_dissector(next_tvb, pinfo, tree);
1260
32
      }
1261
35
    }
1262
38
  }
1263
1264
6.33k
  offset += tvb_captured_length_remaining(tvb, offset);
1265
  /* we dissected all of the containing PDU */
1266
1267
6.33k
  return offset;
1268
1269
6.69k
} /* 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
137
{
1276
137
  proto_tree *cotp_tree = NULL;
1277
137
  proto_item *ti;
1278
137
  bool        is_extended;
1279
137
  uint16_t    dst_ref;
1280
137
  unsigned    tpdu_nr;
1281
137
  tvbuff_t   *next_tvb;
1282
137
  unsigned    tpdu_len;
1283
137
  heur_dtbl_entry_t *hdtbl_entry;
1284
1285
  /* ED TPDUs have user data, so they run to the end of the containing PDU */
1286
137
  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
137
  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
137
    switch (li) {
1304
1305
4
      case LI_NORMAL_DT_WITH_CHECKSUM      :
1306
4
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1307
4
          return -1;
1308
        /* FALLTHROUGH */
1309
1310
97
      case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
1311
97
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1312
97
        if (tpdu_nr & 0x80)
1313
31
          tpdu_nr = tpdu_nr & 0x7F;
1314
66
        else
1315
66
          return -1;
1316
31
        is_extended = false;
1317
31
        break;
1318
1319
1
      case LI_EXTENDED_DT_WITH_CHECKSUM    :
1320
1
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1321
1
          return -1;
1322
        /* FALLTHROUGH */
1323
1324
11
      case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1325
11
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1326
11
        if (tpdu_nr & 0x80000000)
1327
2
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1328
9
        else
1329
9
          return -1;
1330
2
        is_extended = true;
1331
2
        break;
1332
1333
24
      default : /* bad TPDU */
1334
24
        return -1;
1335
137
    } /* li */
1336
137
  } 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
33
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1419
33
  pinfo->clnp_dstref = dst_ref;
1420
1421
33
  col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
1422
33
                  tpdu_nr, dst_ref);
1423
1424
33
  if (tree) {
1425
33
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1426
33
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1427
33
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1428
33
  }
1429
33
  offset += 1;
1430
1431
33
  if (tree) {
1432
33
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1433
33
  }
1434
33
  offset += 1;
1435
33
  li -= 1;
1436
1437
33
  if (tree)
1438
33
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1439
33
  offset += 2;
1440
33
  li -= 2;
1441
1442
33
  if (is_extended) {
1443
2
    if (tree) {
1444
2
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1445
2
                          4, tpdu_nr);
1446
2
    }
1447
2
    offset += 4;
1448
2
    li -= 4;
1449
31
  } else {
1450
31
    if (tree) {
1451
31
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1452
31
                          tpdu_nr);
1453
31
    }
1454
31
    offset += 1;
1455
31
    li -= 1;
1456
31
  }
1457
1458
33
  if (tree)
1459
33
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1460
33
  offset += li;
1461
1462
  /*
1463
   * Tell subdissectors that this is in an ED packet?
1464
   */
1465
33
  next_tvb = tvb_new_subset_remaining(tvb, offset);
1466
33
  if (uses_inactive_subset) {
1467
25
    if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1468
25
                                pinfo, tree, &hdtbl_entry, NULL)) {
1469
8
      *subdissector_found = true;
1470
17
    } else {
1471
      /* Fill in other Dissectors using inactive subset here */
1472
17
      call_data_dissector(next_tvb, pinfo, tree);
1473
17
    }
1474
25
  } else {
1475
    /*
1476
     * ED TPDUs are never fragmented
1477
     */
1478
8
    if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1479
8
                                tree, &hdtbl_entry, NULL)) {
1480
2
      *subdissector_found = true;
1481
6
    } else {
1482
6
      call_data_dissector(next_tvb, pinfo, tree);
1483
6
    }
1484
8
  }
1485
1486
33
  offset += tvb_captured_length_remaining(tvb, offset);
1487
     /* we dissected all of the containing PDU */
1488
1489
33
  return offset;
1490
1491
137
} /* 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
64
{
1496
64
  proto_tree *cotp_tree;
1497
64
  proto_item *ti;
1498
64
  proto_item *item = NULL;
1499
64
  uint16_t dst_ref;
1500
64
  unsigned tpdu_nr;
1501
64
  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
64
  if (!cotp_decode_atn) {  /* non ATN, plain OSI */
1508
64
    switch(li) {
1509
19
      case LI_NORMAL_RJ   :
1510
19
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1511
19
        break;
1512
0
      case LI_EXTENDED_RJ :
1513
0
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1514
0
        credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1515
0
        break;
1516
45
      default :
1517
45
        return -1;
1518
64
    }
1519
64
  } 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
19
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1540
19
  pinfo->clnp_dstref = dst_ref;
1541
1542
19
  col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
1543
19
                  tpdu_nr, dst_ref);
1544
1545
19
  if (tree) {
1546
19
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1547
19
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1548
19
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1549
19
    item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1,
1550
19
                               tpdu);
1551
19
    if (li == LI_NORMAL_RJ) {
1552
19
      proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset +  1, 1, cdt);
1553
19
    }
1554
19
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
1555
19
                        dst_ref);
1556
19
    if (li == LI_NORMAL_RJ)
1557
19
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset + 4,
1558
19
                          1, tpdu_nr);
1559
0
    else {
1560
0
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1561
0
                          offset + 4, 4, tpdu_nr);
1562
0
      proto_tree_add_uint(cotp_tree, hf_cotp_credit, tvb, offset +  8, 2, credit);
1563
0
    }
1564
19
  }
1565
1566
19
  offset += li + 1;
1567
1568
19
  expert_add_info_format(pinfo, item, &ei_cotp_reject, "Reject(RJ): -> 0x%x", dst_ref);
1569
1570
19
  return offset;
1571
1572
64
} /* 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
305
{
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
305
  proto_tree *cotp_tree = NULL;
1586
305
  proto_item *ti;
1587
305
  proto_item *item = NULL;
1588
305
  uint16_t dst_ref, src_ref;
1589
305
  uint8_t class_option;
1590
305
  tvbuff_t *next_tvb;
1591
305
  unsigned   tpdu_len;
1592
305
  heur_dtbl_entry_t *hdtbl_entry;
1593
305
  static int * const class_options[] = {
1594
305
     &hf_cotp_class,
1595
305
     &hf_cotp_opts_extended_formats,
1596
305
     &hf_cotp_opts_no_explicit_flow_control,
1597
305
     NULL,
1598
305
  };
1599
1600
305
  src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1601
1602
305
  class_option = tvb_get_uint8(tvb, offset + P_CLASS_OPTION);
1603
305
  if (((class_option & 0xF0) >> 4) > 4) /* class 0..4 allowed */
1604
44
    return -1;
1605
1606
  /* CR and CC TPDUs can have user data, so they run to the end of the
1607
   * containing PDU */
1608
261
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
1609
1610
261
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1611
261
  pinfo->clnp_srcref = src_ref;
1612
261
  pinfo->clnp_dstref = dst_ref;
1613
1614
261
  col_append_fstr(pinfo->cinfo, COL_INFO,
1615
261
                  "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1616
261
                  (tpdu == CR_TPDU) ? "CR" : "CC", src_ref, dst_ref);
1617
1618
261
  ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1619
261
  cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1620
261
  proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1621
261
  offset += 1;
1622
1623
261
  item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1624
261
  offset += 1;
1625
261
  li -= 1;
1626
1627
261
  proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1628
261
  offset += 2;
1629
261
  li -= 2;
1630
1631
261
  proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1632
261
  offset += 2;
1633
261
  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
261
  if (pinfo->destport == 0) {
1638
195
    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
195
  } else {
1640
66
    cotp_conv_info_t *conv_info = get_cotp_conv_info(pinfo);
1641
66
    conv_info->rev->ref = src_ref;
1642
66
    conv_info->rev->ref_set = true;
1643
66
    if (tpdu == CR_TPDU) {
1644
39
      conv_info->fwd->ref = dst_ref;
1645
39
      conv_info->fwd->ref_set = true;
1646
39
    }
1647
66
  }
1648
1649
261
  proto_tree_add_bitmask_list(cotp_tree, tvb, offset, 1, class_options, ENC_NA);
1650
261
  offset += 1;
1651
261
  li -= 1;
1652
1653
261
  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
252
    next_tvb = tvb_new_subset_length(tvb, offset, li);
1662
252
    if (dissector_try_heuristic((tpdu == CR_TPDU) ?
1663
155
                                 cotp_cr_heur_subdissector_list :
1664
252
                                 cotp_cc_heur_subdissector_list,
1665
252
                                next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
1666
      /* A subdissector claimed this, so it really belongs to them. */
1667
21
      *subdissector_found = true;
1668
231
    } else {
1669
      /* No heuristic dissector claimed it, so dissect it as a regular
1670
         variable part. */
1671
231
      ositp_decode_var_part(tvb, offset, li, class_option, tpdu_len, pinfo,
1672
231
                            cotp_tree);
1673
231
    }
1674
252
    offset += li;
1675
252
  }
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
261
  if (tvb_captured_length_remaining(tvb, offset)) {
1682
33
    next_tvb = tvb_new_subset_remaining(tvb, offset);
1683
33
    if (!uses_inactive_subset){
1684
25
      if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1685
25
                                  tree, &hdtbl_entry, NULL)) {
1686
9
        *subdissector_found = true;
1687
16
      } else {
1688
16
        call_data_dissector(next_tvb, pinfo, tree);
1689
16
      }
1690
25
    }
1691
8
    else
1692
8
      call_data_dissector( next_tvb, pinfo, tree);
1693
33
    offset += tvb_captured_length_remaining(tvb, offset);
1694
    /* we dissected all of the containing PDU */
1695
33
  }
1696
1697
261
  return offset;
1698
1699
305
} /* 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
29
{
1704
29
  proto_tree *cotp_tree = NULL;
1705
29
  proto_item *ti;
1706
29
  proto_item *item = NULL;
1707
29
  uint16_t dst_ref, src_ref;
1708
29
  unsigned   tpdu_len;
1709
1710
  /* ATN may use checksums different from OSI */
1711
  /* which may result in different TPDU header length. */
1712
29
  if (!cotp_decode_atn) {
1713
29
    if (li > LI_MAX_DC)
1714
13
      return -1;
1715
29
  } 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
16
  tpdu_len = li + 1;
1723
1724
16
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1725
16
  src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1726
16
  pinfo->clnp_dstref = dst_ref;
1727
16
  pinfo->clnp_srcref = src_ref;
1728
1729
16
  col_append_fstr(pinfo->cinfo, COL_INFO,
1730
16
                  "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
1731
1732
16
  if (tree) {
1733
16
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1734
16
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1735
16
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1736
16
  }
1737
16
  offset += 1;
1738
1739
16
  if (tree) {
1740
16
    item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1741
16
  }
1742
16
  offset += 1;
1743
16
  li -= 1;
1744
1745
16
  if (tree)
1746
16
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1747
16
  offset += 2;
1748
16
  li -= 2;
1749
1750
16
  if (tree)
1751
16
    proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1752
16
  offset += 2;
1753
16
  li -= 2;
1754
1755
16
  if (tree)
1756
16
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1757
16
  offset += li;
1758
1759
16
  expert_add_info_format(pinfo, item, &ei_cotp_disconnect_confirm, "Disconnect Confirm(DC): 0x%x -> 0x%x", src_ref, dst_ref);
1760
1761
16
  return offset;
1762
1763
29
} /* 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
101
{
1768
101
  proto_tree *cotp_tree = NULL;
1769
101
  proto_item *ti;
1770
101
  uint16_t   dst_ref;
1771
101
  unsigned   tpdu_nr;
1772
101
  uint16_t   cdt_in_ak;
1773
101
  unsigned   tpdu_len;
1774
1775
101
  if (!cotp_decode_atn) {
1776
101
    if (li > LI_MAX_AK)
1777
17
      return -1;
1778
101
  } 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
84
  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
84
  if (is_LI_NORMAL_AK(li)) {
1790
1791
63
    dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1792
63
    tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1793
63
    pinfo->clnp_dstref = dst_ref;
1794
1795
63
    col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1796
63
                    tpdu_nr, dst_ref);
1797
1798
63
    if (tree) {
1799
62
      ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1800
62
      cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1801
62
      proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1802
62
    }
1803
63
    offset += 1;
1804
1805
63
    if (tree) {
1806
62
      proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1807
62
      proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset, 1, cdt);
1808
62
    }
1809
63
    offset += 1;
1810
63
    li -= 1;
1811
1812
63
    if (tree)
1813
62
      proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1814
63
    offset += 2;
1815
63
    li -= 2;
1816
1817
63
    if (tree) {
1818
62
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1819
62
                          tpdu_nr);
1820
62
    }
1821
63
    offset += 1;
1822
63
    li -= 1;
1823
1824
63
    if (tree)
1825
62
      ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1826
63
    offset += li;
1827
1828
63
  } else { /* extended format */
1829
1830
21
    dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1831
21
    tpdu_nr   = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1832
21
    cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1833
21
    pinfo->clnp_dstref = dst_ref;
1834
1835
21
    col_append_fstr(pinfo->cinfo, COL_INFO,
1836
21
                    "AK TPDU (%u) dst-ref: 0x%04x Credit: %u",
1837
21
                    tpdu_nr, dst_ref, cdt_in_ak);
1838
1839
21
    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
21
    offset += 1;
1845
1846
21
    if (tree) {
1847
9
      proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1848
9
    }
1849
21
    offset += 1;
1850
21
    li -= 1;
1851
1852
21
    if (tree)
1853
9
      proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1854
21
    offset += 2;
1855
21
    li -= 2;
1856
1857
21
    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
21
    offset += 4;
1862
21
    li -= 4;
1863
1864
21
    if (tree) {
1865
9
      proto_tree_add_uint(cotp_tree, hf_cotp_credit, tvb, offset, 2, cdt_in_ak);
1866
9
    }
1867
21
    offset += 2;
1868
21
    li -= 2;
1869
1870
21
    if (tree)
1871
9
      ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1872
21
    offset += li;
1873
1874
21
  } /* is_LI_NORMAL_AK */
1875
1876
84
  return offset;
1877
1878
101
} /* 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
149
{
1883
149
  proto_tree *cotp_tree = NULL;
1884
149
  proto_item *ti;
1885
149
  bool is_extended;
1886
149
  uint16_t dst_ref;
1887
149
  unsigned tpdu_nr;
1888
149
  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
149
  if (!cotp_decode_atn) {
1897
149
    if (li > LI_MAX_EA)
1898
63
      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
86
    switch (li) {
1904
1905
8
      case LI_NORMAL_EA_WITH_CHECKSUM      :
1906
8
        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
8
            return -1;
1909
        /* FALLTHROUGH */
1910
1911
16
      case LI_NORMAL_EA_WITHOUT_CHECKSUM   :
1912
16
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1913
16
        is_extended = false;
1914
16
        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
46
      default : /* bad TPDU */
1928
46
        return -1;
1929
86
    } /* li */
1930
86
  } 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
29
  tpdu_len = li + 1;
2017
2018
29
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
2019
29
  pinfo->clnp_dstref = dst_ref;
2020
2021
29
  col_append_fstr(pinfo->cinfo, COL_INFO, "EA TPDU (%u) dst-ref: 0x%04x",
2022
29
                  tpdu_nr, dst_ref);
2023
2024
29
  if (tree) {
2025
29
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
2026
29
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
2027
29
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
2028
29
  }
2029
29
  offset += 1;
2030
2031
29
  if (tree) {
2032
29
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
2033
29
  }
2034
29
  offset += 1;
2035
29
  li -= 1;
2036
2037
29
  if (tree)
2038
29
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
2039
29
  offset += 2;
2040
29
  li -= 2;
2041
2042
29
  if (is_extended) {
2043
14
    if (tree) {
2044
14
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
2045
14
                          offset, 4, tpdu_nr);
2046
14
    }
2047
14
    offset += 4;
2048
14
    li -= 4;
2049
15
  } else {
2050
15
    if (tree) {
2051
15
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
2052
15
                          tpdu_nr);
2053
15
    }
2054
15
    offset += 1;
2055
15
    li -= 1;
2056
15
  }
2057
2058
29
  if (tree)
2059
29
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len,  pinfo, cotp_tree);
2060
29
  offset += li;
2061
2062
29
  return offset;
2063
2064
149
} /* 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
116
{
2077
116
  proto_tree *cotp_tree = NULL;
2078
116
  proto_item *ti;
2079
116
  uint16_t dst_ref;
2080
116
  uint8_t tpdu_len;
2081
2082
  /* ATN: except for modified LI checking nothing to be done here */
2083
116
  if (!cotp_decode_atn) {
2084
116
    if (li > LI_MAX_ER)
2085
17
      return -1;
2086
116
  } 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
99
  tpdu_len = li + 1;
2094
2095
99
  if(try_val_to_str(tvb_get_uint8(tvb, offset + P_REJECT_ER), cotp_reject_vals) == NULL)
2096
88
      return -1;
2097
2098
11
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
2099
11
  pinfo->clnp_dstref = dst_ref;
2100
2101
11
  col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
2102
2103
11
  if (tree) {
2104
11
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
2105
11
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
2106
11
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
2107
11
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1, tpdu);
2108
11
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
2109
11
                        dst_ref);
2110
11
    proto_tree_add_item(cotp_tree, hf_cotp_reject_cause, tvb, offset + 4, 1, ENC_NA);
2111
11
  }
2112
11
  offset += 5;
2113
11
  li -= 4;
2114
2115
11
  if (tree)
2116
11
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
2117
11
  offset += li;
2118
2119
11
  return offset;
2120
2121
99
} /* 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
201
{
2127
201
  proto_item *ti;
2128
201
  proto_tree *cltp_tree = NULL;
2129
201
  tvbuff_t   *next_tvb;
2130
201
  unsigned   tpdu_len;
2131
201
  heur_dtbl_entry_t *hdtbl_entry;
2132
2133
  /* UD TPDUs have user data, so they run to the end of the containing PDU */
2134
201
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
2135
2136
201
  col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
2137
2138
201
  if (tree) {
2139
201
    ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, ENC_NA);
2140
201
    cltp_tree = proto_item_add_subtree(ti, ett_cltp);
2141
201
    proto_tree_add_uint(cltp_tree, hf_cltp_li, tvb, offset, 1,li);
2142
201
  }
2143
201
  offset += 1;
2144
2145
201
  if (tree) {
2146
201
    proto_tree_add_uint(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu);
2147
201
  }
2148
201
  offset += 1;
2149
201
  li -= 1;
2150
2151
201
  if (tree)
2152
201
    ositp_decode_var_part(tvb, offset, li, 0, tpdu_len, pinfo, cltp_tree);
2153
201
  offset += li;
2154
2155
201
  next_tvb = tvb_new_subset_remaining(tvb, offset);
2156
2157
201
  if (dissector_try_heuristic(cltp_heur_subdissector_list, next_tvb,
2158
201
                              pinfo, tree, &hdtbl_entry, NULL)) {
2159
12
    *subdissector_found = true;
2160
189
  } else {
2161
189
    call_data_dissector(next_tvb, pinfo, tree);
2162
189
  }
2163
2164
2165
  /*call_data_dissector(next_tvb, pinfo, tree); */
2166
2167
201
  offset += tvb_captured_length_remaining(tvb, offset);
2168
  /* we dissected all of the containing PDU */
2169
2170
201
  return offset;
2171
2172
201
} /* 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
9.21k
{
2186
9.21k
  int offset = 0;
2187
9.21k
  uint8_t li, tpdu, cdt;
2188
9.21k
  bool first_tpdu = true;
2189
9.21k
  int new_offset;
2190
9.21k
  bool found_ositp = false;
2191
9.21k
  bool is_cltp = false;
2192
9.21k
  bool subdissector_found = false;
2193
2194
  /* Initialize the COL_INFO field; each of the TPDUs will have its
2195
     information appended. */
2196
9.21k
  col_clear(pinfo->cinfo, COL_INFO);
2197
2198
13.2k
  while (tvb_offset_exists(tvb, offset)) {
2199
8.61k
    if (!first_tpdu) {
2200
79
      col_append_str(pinfo->cinfo, COL_INFO, ", ");
2201
79
      expert_add_info(pinfo, NULL, &ei_cotp_multiple_tpdus);
2202
      /* adjust tvb and offset to the start of the current PDU */
2203
79
      tvb = tvb_new_subset_remaining(tvb, offset);
2204
79
      offset = 0 ;
2205
79
    }
2206
8.61k
    if ((li = tvb_get_uint8(tvb, offset + P_LI)) == 0) {
2207
214
      col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
2208
214
      if (!first_tpdu)
2209
19
        call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2210
19
                       pinfo, tree);
2211
214
      return found_ositp;
2212
214
    }
2213
2214
8.40k
    tpdu = (tvb_get_uint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
2215
8.40k
    if (tpdu == UD_TPDU)
2216
201
      pinfo->current_proto = "CLTP";    /* connectionless transport */
2217
8.40k
    cdt = tvb_get_uint8(tvb, offset + P_CDT) & 0x0F;
2218
2219
8.40k
    switch (tpdu) {
2220
136
      case CC_TPDU :
2221
305
      case CR_TPDU :
2222
305
        new_offset = ositp_decode_CR_CC(tvb, offset, li, tpdu, pinfo, tree,
2223
305
                                        uses_inactive_subset, &subdissector_found);
2224
305
        break;
2225
164
      case DR_TPDU :
2226
164
        new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
2227
164
        break;
2228
6.69k
      case DT_TPDU :
2229
6.69k
        new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
2230
6.69k
                                     uses_inactive_subset, &subdissector_found);
2231
6.69k
        break;
2232
137
      case ED_TPDU :
2233
137
        new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree,
2234
137
                                     uses_inactive_subset, &subdissector_found);
2235
137
        break;
2236
64
      case RJ_TPDU :
2237
64
        new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
2238
64
        break;
2239
29
      case DC_TPDU :
2240
29
        new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
2241
29
        break;
2242
101
      case AK_TPDU :
2243
101
        new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
2244
101
        break;
2245
149
      case EA_TPDU :
2246
149
        new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
2247
149
        break;
2248
116
      case ER_TPDU :
2249
116
        new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
2250
116
        break;
2251
201
      case UD_TPDU :
2252
201
        new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree,
2253
201
                                     &subdissector_found);
2254
201
        is_cltp = true;
2255
201
        break;
2256
409
      default      :
2257
409
        if (first_tpdu)
2258
403
          col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)",
2259
403
                          tpdu);
2260
409
        new_offset = -1;    /* bad PDU type */
2261
409
        break;
2262
8.40k
    }
2263
2264
5.19k
    if (new_offset == -1) { /* incorrect TPDU */
2265
1.20k
      if (!first_tpdu)
2266
33
        call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2267
33
                       pinfo, tree);
2268
1.20k
      break;
2269
1.20k
    }
2270
2271
3.98k
    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.96k
      if (!subdissector_found)
2275
2.46k
        col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
2276
3.96k
      found_ositp = true;
2277
3.96k
    }
2278
2279
3.98k
    offset = new_offset;
2280
3.98k
    first_tpdu = false;
2281
3.98k
  }
2282
5.80k
  return found_ositp ? offset : 0;
2283
9.21k
} /* dissect_ositp_internal */
2284
2285
static int dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2286
                          void *data _U_)
2287
168
{
2288
168
  return dissect_ositp_internal(tvb, pinfo, tree, false);
2289
168
}
2290
2291
static int dissect_ositp_inactive(tvbuff_t *tvb, packet_info *pinfo,
2292
                                   proto_tree *tree, void *data _U_)
2293
9.05k
{
2294
9.05k
  return dissect_ositp_internal(tvb, pinfo, tree, true);
2295
9.05k
}
2296
2297
static bool
2298
test_cltp_var_part(tvbuff_t *tvb)
2299
153
{
2300
153
  int offset = 0;
2301
153
  uint8_t li;
2302
157
  while (tvb_captured_length_remaining(tvb, offset)) {
2303
143
    if (tvb_captured_length_remaining(tvb, offset) < 2) {
2304
3
      return false;
2305
3
    }
2306
140
    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
7
    case VP_CHECKSUM: // Not required as redundant with UDP checksum, per RFC 1240
2311
7
      break;
2312
133
    default:
2313
133
      return false;
2314
140
    }
2315
7
    li = tvb_get_uint8(tvb, offset++);
2316
7
    if (li == 255) {
2317
1
      return false;
2318
1
    }
2319
6
    if (tvb_captured_length_remaining(tvb, offset) < li) {
2320
2
      return false;
2321
2
    }
2322
4
    offset += li;
2323
4
  }
2324
14
  return true;
2325
153
}
2326
2327
static bool
2328
dissect_cltp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
2329
          void *data)
2330
1.64k
{
2331
1.64k
  uint8_t li, tpdu, spdu;
2332
1.64k
  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.64k
  if (tvb_captured_length(tvb) < 2) {
2342
106
    return false;
2343
106
  }
2344
2345
1.53k
  li = tvb_get_uint8(tvb, offset++);
2346
2347
  /* LI must include TPDU, and 255 is reserved */
2348
1.53k
  if (li == 0 || li == 255) {
2349
370
    return false;
2350
370
  }
2351
2352
  /* Is it OSI on top of the UDP? */
2353
1.16k
  tpdu = (tvb_get_uint8(tvb, offset++) & 0xF0) >> 4;
2354
1.16k
  if (tpdu != UD_TPDU) {
2355
1.01k
    return false;
2356
1.01k
  }
2357
2358
  /* LI includes TPDU */
2359
153
  li--;
2360
2361
153
  if (!test_cltp_var_part(tvb_new_subset_length(tvb, offset, li))) {
2362
139
    return false;
2363
139
  }
2364
14
  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
14
  if (tvb_captured_length_remaining(tvb, offset) < 1) {
2372
8
    return false;
2373
8
  }
2374
2375
  /* And let's see if it is GOOSE SPDU */
2376
6
  spdu = tvb_get_uint8(tvb, offset);
2377
6
  if (spdu != 0xA1) {
2378
2
    return false;
2379
2
  }
2380
2381
4
  dissect_ositp(tvb, pinfo, parent_tree, data);
2382
4
  return true;
2383
6
}
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
 */