Coverage Report

Created: 2026-06-30 07:22

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
73
#define ED_TPDU             0x1 /* COTP */
161
74
#define EA_TPDU             0x2 /* COTP */
162
5.82k
#define UD_TPDU             0x4 /* CLTP */
163
18
#define RJ_TPDU             0x5 /* COTP */
164
70
#define AK_TPDU             0x6 /* COTP */
165
44
#define ER_TPDU             0x7 /* COTP */
166
64
#define DR_TPDU             0x8 /* COTP */
167
10
#define DC_TPDU             0xC /* COTP */
168
66
#define CC_TPDU             0xD /* COTP */
169
598
#define CR_TPDU             0xE /* COTP */
170
3.99k
#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
5.02k
#define P_LI                0
205
4.88k
#define P_TPDU              1
206
4.88k
#define P_CDT               1
207
871
#define P_DST_REF           2
208
239
#define P_SRC_REF           4
209
3.32k
#define P_TPDU_NR_0_1       2
210
697
#define P_TPDU_NR_234       4
211
14
#define P_VAR_PART_NDT      5
212
19
#define P_VAR_PART_EDT      8
213
#define P_VAR_PART_DC       6
214
20
#define P_CDT_IN_AK         8
215
0
#define P_CDT_IN_RJ         8
216
34
#define P_REJECT_ER         4
217
54
#define P_REASON_IN_DR      6
218
177
#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
3.32k
#define LI_NORMAL_DT_CLASS_01           2
227
465
#define LI_NORMAL_DT_WITHOUT_CHECKSUM   4
228
11
#define LI_NORMAL_DT_WITH_CHECKSUM      (LI_NORMAL_DT_WITHOUT_CHECKSUM+4)
229
184
#define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
230
17
#define LI_EXTENDED_DT_WITH_CHECKSUM    (LI_EXTENDED_DT_WITHOUT_CHECKSUM+4)
231
11
#define LI_NORMAL_EA_WITHOUT_CHECKSUM   4
232
3
#define LI_NORMAL_EA_WITH_CHECKSUM      (LI_NORMAL_EA_WITHOUT_CHECKSUM+4)
233
4
#define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
234
2
#define LI_EXTENDED_EA_WITH_CHECKSUM    (LI_EXTENDED_EA_WITHOUT_CHECKSUM+4)
235
3
#define LI_NORMAL_RJ                    4
236
0
#define LI_EXTENDED_RJ                  9
237
64
#define LI_MIN_DR                       6
238
10
#define LI_MAX_DC                       9
239
70
#define LI_MAX_AK                       27
240
74
#define LI_MAX_EA                       11
241
44
#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
65
#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
6
#define VP_ACK_TIME             0x85
268
56
#define VP_RES_ERROR            0x86
269
11
#define VP_PRIORITY             0x87
270
30
#define VP_TRANSIT_DEL          0x88
271
22
#define VP_THROUGHPUT           0x89
272
8
#define VP_SEQ_NR               0x8A        /* in AK */
273
5
#define VP_REASSIGNMENT         0x8B
274
20
#define VP_FLOW_CNTL            0x8C        /* in AK */
275
3
#define VP_TPDU_SIZE            0xC0
276
9
#define VP_SRC_TSAP             0xC1        /* in CR/CC */
277
23
#define VP_DST_TSAP             0xC2
278
49
#define VP_CHECKSUM             0xC3
279
4
#define VP_VERSION_NR           0xC4
280
0
#define VP_PROTECTION           0xC5
281
16
#define VP_OPT_SEL              0xC6
282
0
#define VP_PROTO_CLASS          0xC7
283
1
#define VP_CLEARING_INFO        0xE0        /* in DR */
284
14
#define VP_PREF_MAX_TPDU_SIZE   0xF0
285
3
#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
55
#define VP_ATN_EC_32            0x08        /* 4 octet ATN Extended Transport Checksum parameter */
292
23
#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
54
#define TSAP_DISPLAY_AUTO   0
345
54
#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
52
#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
3.33k
{
379
3.33k
  conversation_t *conv;
380
3.33k
  cotp_conv_info_t *conv_info;
381
3.33k
  int direction;
382
383
3.33k
  conv = find_or_create_conversation(pinfo);
384
3.33k
  conv_info = conversation_get_proto_data(conv, proto_cotp);
385
3.33k
  if (!conv_info) {
386
285
    conv_info = wmem_new0(wmem_file_scope(), cotp_conv_info_t);
387
285
    conversation_add_proto_data(conv, proto_cotp, conv_info);
388
285
  }
389
390
  /* check direction; first compare addreses, then ports. */
391
3.33k
  direction = cmp_address(&pinfo->src, &pinfo->dst);
392
3.33k
  if (direction==0) {
393
20
    direction = (pinfo->srcport > pinfo->destport) ? 1 : -1;
394
20
  }
395
396
3.33k
  if (direction >= 0) {
397
984
    conv_info->fwd = &(conv_info->flow[0]);
398
984
    conv_info->rev = &(conv_info->flow[1]);
399
2.35k
  } else {
400
2.35k
    conv_info->fwd = &(conv_info->flow[1]);
401
2.35k
    conv_info->rev = &(conv_info->flow[0]);
402
2.35k
  }
403
404
3.33k
  return conv_info;
405
3.33k
}
406
407
static uint16_t get_cotp_frag_id(packet_info *pinfo, cotp_flow_info_t *flow_info, bool fragment)
408
3.32k
{
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
3.32k
  uint16_t           frag_id;
421
3.32k
  unsigned           flow_index = 0;
422
3.32k
  bool               flow_first_seen = true;
423
3.32k
  wmem_list_t       *used_flow_list;
424
3.32k
  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
3.32k
  used_flow_list = (wmem_list_t *)p_get_proto_data(pinfo->pool, pinfo, proto_cotp, 0);
431
3.32k
  if (!used_flow_list) {
432
636
    used_flow_list = wmem_list_new(pinfo->pool);
433
636
    p_add_proto_data(pinfo->pool, pinfo, proto_cotp, 0, used_flow_list);
434
2.68k
  } else {
435
2.68k
    if (wmem_list_find(used_flow_list, flow_info)) {
436
2.68k
      flow_first_seen = false;
437
2.68k
    } else {
438
3
      flow_index = wmem_list_count(used_flow_list);
439
3
    }
440
2.68k
  }
441
3.32k
  wmem_list_append(used_flow_list, flow_info);
442
3.32k
  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
639
    if (!flow_info->last_fragment) {
448
381
      flow_info->frag_id = 0;
449
381
    }
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
639
    prev_dst_ref = (uint32_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_cotp, flow_index);
456
639
    if (!prev_dst_ref) {
457
639
      DISSECTOR_ASSERT(!PINFO_FD_VISITED(pinfo));
458
639
      prev_dst_ref = wmem_new(wmem_file_scope(), uint32_t);
459
639
      *prev_dst_ref = flow_info->frag_id;
460
639
      p_add_proto_data(wmem_file_scope(), pinfo, proto_cotp, flow_index, prev_dst_ref);
461
639
    } else {
462
0
      flow_info->frag_id = *prev_dst_ref;
463
0
    }
464
639
  }
465
3.32k
  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
3.32k
  flow_info->last_fragment = fragment;
470
3.32k
  if (!fragment) {
471
1.17k
    flow_info->frag_id++;
472
1.17k
  }
473
3.32k
  return frag_id;
474
3.32k
}
475
476
static char *print_tsap(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
477
27
{
478
27
  const unsigned char *tsap = tvb_get_ptr(tvb, offset, length);
479
27
  char     *cur;
480
27
  bool      allprintable;
481
27
  int       idx = 0, returned_length;
482
483
27
  cur=(char *)wmem_alloc(scope, MAX_TSAP_LEN * 2 + 3);
484
27
  cur[0] = '\0';
485
27
  if (length <= 0 || length > MAX_TSAP_LEN)
486
27
    snprintf(cur, MAX_TSAP_LEN * 2 + 3, "<unsupported TSAP length>");
487
8
  else {
488
8
    allprintable = tvb_ascii_isprint(tvb, offset, length);
489
8
    if (!allprintable) {
490
7
      returned_length = snprintf(cur, MAX_TSAP_LEN * 2 + 3, "0x");
491
7
      idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - 1);
492
7
    }
493
53
    while (length != 0) {
494
45
      if (allprintable) {
495
1
        returned_length = snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
496
1
                                     "%c", *tsap ++);
497
1
        idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
498
44
      } else {
499
44
        returned_length = snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
500
44
                                     "%02x", *tsap ++);
501
44
        idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
502
44
      }
503
45
      length --;
504
45
    }
505
8
  }
506
27
  return cur;
507
508
27
} /* 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
4.15k
{
516
4.15k
  uint8_t         code, length;
517
4.15k
  uint8_t         c1;
518
4.15k
  uint16_t        s;
519
4.15k
  uint32_t        offset_iso8073_checksum = 0;
520
4.15k
  int32_t         i                       = 0;
521
4.15k
  uint8_t         tmp_code                = 0;
522
4.15k
  unsigned        tmp_len                 = 0;
523
4.15k
  uint32_t        pref_max_tpdu_size;
524
4.15k
  proto_item     *hidden_item;
525
526
5.51k
  while (vp_length != 0) {
527
1.63k
    proto_tree_add_item_ret_uint8(tree, hf_cotp_parameter_code, tvb, offset, 1, ENC_NA, &code);
528
1.63k
    offset += 1;
529
1.63k
    vp_length -= 1;
530
531
1.63k
    if (vp_length == 0)
532
57
      break;
533
1.57k
    proto_tree_add_item_ret_uint8(tree, hf_cotp_parameter_length, tvb, offset, 1, ENC_NA, &length);
534
1.57k
    offset += 1;
535
1.57k
    vp_length -= 1;
536
537
1.57k
    switch (code) {
538
539
23
    case VP_ATN_EC_16 : /* ATN */
540
23
      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
23
      } else {
564
23
        proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
565
23
      }
566
23
      offset += length;
567
23
      vp_length -= length;
568
23
      break;
569
570
55
    case VP_ATN_EC_32 : /* ATN */
571
55
      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
55
      } else {
595
55
        proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
596
55
      }
597
55
      offset += length;
598
55
      vp_length -= length;
599
55
      break;
600
601
6
    case VP_ACK_TIME:
602
6
      proto_tree_add_item(tree, hf_cotp_ack_time, tvb, offset, length, ENC_BIG_ENDIAN);
603
6
      offset += length;
604
6
      vp_length -= length;
605
6
      break;
606
607
56
    case VP_RES_ERROR:
608
56
      s = tvb_get_uint8(tvb, offset);
609
56
      proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_target_value, tvb, offset, 1, s, "10^%u", s);
610
56
      offset += 1;
611
56
      vp_length -= 1;
612
613
56
      s = tvb_get_uint8(tvb, offset);
614
56
      proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_min_accept, tvb, offset, 1, s, "10^%u", s);
615
56
      offset += 1;
616
56
      vp_length -= 1;
617
618
56
      s = tvb_get_uint8(tvb, offset);
619
56
      proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_tdsu, tvb, offset, 1, s, "2^%u", s);
620
56
      offset += 1;
621
56
      vp_length -= 1;
622
56
      break;
623
624
11
    case VP_PRIORITY:
625
11
      proto_tree_add_item(tree, hf_cotp_vp_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
626
11
      offset += length;
627
11
      vp_length -= length;
628
11
      break;
629
630
30
    case VP_TRANSIT_DEL:
631
30
      proto_tree_add_item(tree, hf_cotp_transit_delay_targ_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
632
30
      offset += 2;
633
30
      vp_length -= 2;
634
635
30
      proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
636
30
      offset += 2;
637
30
      vp_length -= 2;
638
639
30
      proto_tree_add_item(tree, hf_cotp_transit_delay_targ_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
640
30
      offset += 2;
641
30
      vp_length -= 2;
642
643
30
      proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
644
30
      offset += 2;
645
30
      vp_length -= 2;
646
30
      break;
647
648
22
    case VP_THROUGHPUT:
649
22
      proto_tree_add_item(tree, hf_cotp_max_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
650
22
      offset += 3;
651
22
      length -= 3;
652
22
      vp_length -= 3;
653
654
22
      proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
655
22
      offset += 3;
656
22
      length -= 3;
657
22
      vp_length -= 3;
658
659
22
      proto_tree_add_item(tree, hf_cotp_max_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
660
22
      offset += 3;
661
22
      length -= 3;
662
22
      vp_length -= 3;
663
664
22
      proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
665
22
      offset += 3;
666
22
      length -= 3;
667
22
      vp_length -= 3;
668
669
22
      if (length != 0) {    /* XXX - should be 0 or 12 */
670
22
        proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
671
22
        offset += 3;
672
22
        vp_length -= 3;
673
674
22
        proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
675
22
        offset += 3;
676
22
        vp_length -= 3;
677
678
22
        proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
679
22
        offset += 3;
680
22
        vp_length -= 3;
681
682
22
        proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
683
22
        offset += 3;
684
22
        vp_length -= 3;
685
22
      }
686
22
      break;
687
688
8
    case VP_SEQ_NR:
689
8
      proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
690
8
      offset += length;
691
8
      vp_length -= length;
692
8
      break;
693
694
5
    case VP_REASSIGNMENT:
695
5
      proto_tree_add_item(tree, hf_cotp_reassignment_time, tvb, offset, 2, ENC_BIG_ENDIAN);
696
5
      offset += length;
697
5
      vp_length -= length;
698
5
      break;
699
700
20
    case VP_FLOW_CNTL:
701
20
      proto_tree_add_item(tree, hf_cotp_lower_window_edge, tvb, offset, 4, ENC_BIG_ENDIAN);
702
20
      offset += 4;
703
20
      vp_length -= 4;
704
705
20
      proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
706
20
      offset += 2;
707
20
      vp_length -= 2;
708
709
20
      proto_tree_add_item(tree, hf_cotp_credit, tvb, offset, 2, ENC_BIG_ENDIAN);
710
20
      offset += 2;
711
20
      vp_length -= 2;
712
713
20
      break;
714
715
3
    case VP_TPDU_SIZE:
716
3
      c1 = tvb_get_uint8(tvb, offset) & 0x0F;
717
3
      proto_tree_add_uint(tree, hf_cotp_tpdu_size, tvb, offset, 1, 1 << c1);
718
3
      offset += length;
719
3
      vp_length -= length;
720
3
      break;
721
722
7
    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
7
      if (tsap_display==TSAP_DISPLAY_STRING ||
726
7
          (tsap_display==TSAP_DISPLAY_AUTO &&
727
7
            tvb_ascii_isprint(tvb, offset, length))) {
728
0
        proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
729
0
                              print_tsap(pinfo->pool, tvb, offset, length));
730
0
        hidden_item = proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb,
731
0
                                          offset, length, ENC_NA);
732
0
        proto_item_set_hidden(hidden_item);
733
7
      } else {
734
7
        hidden_item = proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb,
735
7
                                            offset, length,
736
7
                                            print_tsap(pinfo->pool, tvb, offset, length));
737
7
        proto_item_set_hidden(hidden_item);
738
7
        proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset,
739
7
                            length, ENC_NA);
740
7
      }
741
7
      offset += length;
742
7
      vp_length -= length;
743
7
      break;
744
745
20
    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
20
      if (tsap_display==TSAP_DISPLAY_STRING ||
749
20
          (tsap_display==TSAP_DISPLAY_AUTO &&
750
20
            tvb_ascii_isprint(tvb, offset, length))) {
751
3
        proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
752
3
                              print_tsap(pinfo->pool, tvb, offset, length));
753
3
        hidden_item = proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb,
754
3
                                          offset, length, ENC_NA);
755
3
        proto_item_set_hidden(hidden_item);
756
17
      } else {
757
17
        hidden_item = proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb,
758
17
                                            offset, length,
759
17
                                            print_tsap(pinfo->pool, tvb, offset, length));
760
17
        proto_item_set_hidden(hidden_item);
761
17
        proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset,
762
17
                            length, ENC_NA);
763
17
      }
764
20
      offset += length;
765
20
      vp_length -= length;
766
20
      break;
767
768
6
    case VP_CHECKSUM:
769
6
      offset_iso8073_checksum = offset; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
770
771
6
      if (tvb_get_ntohs(tvb, offset) == 0) {
772
        /* No checksum present */
773
1
        proto_tree_add_checksum(tree, tvb, offset, hf_cotp_checksum, hf_cotp_checksum_status, &ei_cotp_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NOT_PRESENT);
774
5
      } else {
775
5
        uint32_t calc_c0 = 0, calc_c1 = 0;
776
777
5
        if (osi_calc_checksum(tvb, 0, tpdu_len, &calc_c0, &calc_c1)) {
778
            /* Successfully processed checksum, verify it */
779
5
            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
5
        } 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
5
      }
784
785
6
      offset += length;
786
6
      vp_length -= length;
787
6
      break;
788
789
4
    case VP_VERSION_NR:
790
4
      proto_tree_add_item(tree, hf_cotp_vp_version_nr, tvb, offset, 1, ENC_NA);
791
4
      offset += length;
792
4
      vp_length -= length;
793
4
      break;
794
795
16
    case VP_OPT_SEL:
796
16
      switch (class_option) {
797
798
2
      case 1:
799
2
        proto_tree_add_item(tree, hf_cotp_network_expedited_data, tvb, offset, 1, ENC_NA);
800
801
2
        proto_tree_add_item(tree, hf_cotp_vp_opt_sel_class1_use, tvb, offset, 1, ENC_NA);
802
2
        break;
803
804
8
      case 4:
805
8
        proto_tree_add_item(tree, hf_cotp_use_16_bit_checksum, tvb, offset, 1, ENC_NA);
806
8
        break;
807
16
      }
808
809
16
      proto_tree_add_item(tree, hf_cotp_transport_expedited_data_transfer, tvb, offset, 1, ENC_NA);
810
16
      offset += length;
811
16
      vp_length -= length;
812
16
      break;
813
814
14
    case VP_PREF_MAX_TPDU_SIZE:
815
14
      switch (length) {
816
817
0
      case 1:
818
0
        pref_max_tpdu_size = tvb_get_uint8(tvb, offset);
819
0
        break;
820
821
0
      case 2:
822
0
        pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
823
0
        break;
824
825
1
      case 3:
826
1
        pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
827
1
        break;
828
829
0
      case 4:
830
0
        pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
831
0
        break;
832
833
13
      default:
834
13
        proto_tree_add_expert_format(tree, pinfo, &ei_cotp_preferred_maximum_tpdu_size, tvb, offset, length,
835
13
                            "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)", length);
836
13
        return false;
837
14
      }
838
1
      proto_tree_add_uint(tree, hf_cotp_preferred_maximum_tpdu_size, tvb, offset, length, pref_max_tpdu_size*128);
839
1
      offset += length;
840
1
      vp_length -= length;
841
1
      break;
842
843
3
    case VP_INACTIVITY_TIMER:
844
3
      proto_tree_add_item(tree, hf_cotp_inactivity_timer, tvb, offset, length, ENC_BIG_ENDIAN);
845
3
      offset += length;
846
3
      vp_length -= length;
847
3
      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
1.23k
    default:                        /* unknown, no decoding */
853
1.23k
      proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
854
1.23k
      offset += length;
855
1.23k
      vp_length -= length;
856
1.23k
      break;
857
1.57k
    }
858
1.57k
  } /* while */
859
860
3.93k
  return true;
861
4.15k
}
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
64
{
883
64
  proto_tree *cotp_tree = NULL;
884
64
  proto_item *ti        = NULL;
885
64
  uint16_t    dst_ref, src_ref;
886
64
  unsigned char      reason;
887
64
  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
64
  if (li < LI_MIN_DR)
892
10
    return -1;
893
894
  /* DR TPDUs can have user data, so they run to the end of the containing PDU */
895
54
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
896
897
54
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
898
899
54
  src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
900
901
54
  reason  = tvb_get_uint8(tvb, offset + P_REASON_IN_DR);
902
903
54
  pinfo->clnp_dstref = dst_ref;
904
54
  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
54
  if (try_val_to_str(reason, cotp_cause_vals) == NULL)
919
27
      return -1;
920
921
27
  col_append_fstr(pinfo->cinfo, COL_INFO,
922
27
                  "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
923
924
27
  if (tree) {
925
27
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
926
27
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
927
27
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
928
27
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1, tpdu);
929
27
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
930
27
                        dst_ref);
931
27
    proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset +  4, 2,
932
27
                        src_ref);
933
27
    proto_tree_add_item(cotp_tree, hf_cotp_cause, tvb, offset + 6, 1, ENC_NA);
934
27
  }
935
27
  offset += 7;
936
27
  li -= 6;
937
938
27
  if (tree)
939
27
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
940
27
  offset += li;
941
942
27
  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
27
  call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
946
27
  offset += tvb_captured_length_remaining(tvb, offset);
947
     /* we dissected all of the containing PDU */
948
949
27
  return offset;
950
951
54
} /* 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
3.99k
{
958
3.99k
  proto_tree        *cotp_tree       = NULL;
959
3.99k
  proto_item        *ti;
960
3.99k
  bool               is_extended;
961
3.99k
  bool               is_class_234;
962
3.99k
  cotp_conv_info_t  *conv_info;
963
3.99k
  uint32_t           dst_ref;
964
3.99k
  unsigned           tpdu_nr;
965
3.99k
  bool               fragment        = false;
966
3.99k
  uint32_t           fragment_length = 0;
967
3.99k
  tvbuff_t          *next_tvb;
968
3.99k
  fragment_head     *fd_head;
969
3.99k
  unsigned           tpdu_len;
970
3.99k
  heur_dtbl_entry_t *hdtbl_entry;
971
972
  /* DT TPDUs have user data, so they run to the end of the containing PDU */
973
3.99k
  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
3.99k
  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
3.99k
  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
3.99k
    switch (li) {
997
998
8
      case LI_NORMAL_DT_WITH_CHECKSUM      :
999
8
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1000
8
          return -1;
1001
        /* FALLTHROUGH */
1002
1003
403
      case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
1004
403
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1005
403
        if (tpdu_nr & 0x80)
1006
142
          tpdu_nr = tpdu_nr & 0x7F;
1007
261
        else
1008
261
          fragment = true;
1009
403
        is_extended = false;
1010
403
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1011
403
        break;
1012
1013
17
      case LI_EXTENDED_DT_WITH_CHECKSUM    :
1014
17
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1015
17
          return -1;
1016
        /* FALLTHROUGH */
1017
1018
160
      case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1019
160
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1020
160
        if (tpdu_nr & 0x80000000)
1021
39
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1022
121
        else
1023
121
          fragment = true;
1024
160
        is_extended = true;
1025
160
        dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1026
160
        break;
1027
1028
3.32k
      case LI_NORMAL_DT_CLASS_01           :
1029
3.32k
        is_class_234 = false;
1030
3.32k
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_0_1);
1031
3.32k
        if (tpdu_nr & 0x80)
1032
1.17k
          tpdu_nr = tpdu_nr & 0x7F;
1033
2.15k
        else
1034
2.15k
          fragment = true;
1035
3.32k
        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
3.32k
        conv_info = get_cotp_conv_info(pinfo);
1039
3.32k
        dst_ref = conv_info->fwd->ref; // Note this may default to zero if not set
1040
3.32k
        break;
1041
1042
77
      default : /* bad TPDU */
1043
77
        return -1;
1044
3.99k
    } /* li */
1045
3.99k
  } 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
3.82k
  pinfo->clnp_dstref = dst_ref;
1125
1126
3.82k
  pinfo->fragmented = fragment;
1127
3.82k
  if (is_class_234 || conv_info->fwd->ref_set) {
1128
507
    col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x",
1129
507
                      tpdu_nr, dst_ref);
1130
3.31k
  } else {
1131
3.31k
    col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u)", tpdu_nr);
1132
3.31k
  }
1133
1134
3.82k
  if (tree) {
1135
3.82k
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1136
3.82k
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1137
3.82k
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1138
3.82k
  }
1139
3.82k
  offset += 1;
1140
1141
3.82k
  if (tree) {
1142
3.82k
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1143
3.82k
  }
1144
3.82k
  offset += 1;
1145
3.82k
  li -= 1;
1146
1147
3.82k
  if (is_class_234) {
1148
503
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1149
503
    offset += 2;
1150
503
    li -= 2;
1151
3.32k
  } else if (conv_info->fwd->ref_set) {
1152
4
    ti = proto_tree_add_uint (cotp_tree, hf_cotp_destref, tvb, offset, 0,
1153
4
                              conv_info->fwd->ref);
1154
4
    proto_item_set_generated (ti);
1155
4
  }
1156
1157
3.82k
  if (is_extended) {
1158
157
    if (tree) {
1159
157
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1160
157
                          4, tpdu_nr);
1161
157
      proto_tree_add_item(cotp_tree, hf_cotp_eot_extended, tvb, offset, 4,
1162
157
                          ENC_BIG_ENDIAN);
1163
157
    }
1164
157
    offset += 4;
1165
157
    li -= 4;
1166
3.66k
  } else {
1167
3.66k
    if (tree) {
1168
3.66k
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1169
3.66k
                          tpdu_nr);
1170
3.66k
      proto_tree_add_item(cotp_tree, hf_cotp_eot, tvb, offset, 1,
1171
3.66k
                          ENC_BIG_ENDIAN);
1172
3.66k
    }
1173
3.66k
    offset += 1;
1174
3.66k
    li -= 1;
1175
3.66k
  }
1176
1177
3.82k
  if (tree)
1178
3.82k
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1179
3.82k
  offset += li;
1180
1181
3.82k
  next_tvb = tvb_new_subset_remaining(tvb, offset);
1182
3.82k
  fragment_length = tvb_captured_length(next_tvb);
1183
3.82k
  if (fragment) {
1184
2.46k
    col_append_fstr(pinfo->cinfo, COL_INFO, " [COTP fragment, %u byte%s]",
1185
2.46k
        fragment_length, plurality(fragment_length, "", "s"));
1186
2.46k
  } else {
1187
1.35k
    col_append_str(pinfo->cinfo, COL_INFO, " EOT");
1188
1.35k
  }
1189
1190
3.82k
  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
3.82k
    uint32_t frag_id;
1212
3.82k
    if (is_class_234) {
1213
503
        frag_id = dst_ref;
1214
3.32k
    } else {
1215
3.32k
        frag_id = get_cotp_frag_id(pinfo, conv_info->fwd, fragment);
1216
3.32k
    }
1217
3.82k
    fd_head = fragment_add_seq_next(&cotp_reassembly_table, next_tvb, 0, pinfo,
1218
3.82k
                                    frag_id, NULL, fragment_length, fragment);
1219
3.82k
    if (fd_head && fd_head->next) {
1220
      /* don't use -1 if fragment length is zero (throws Exception) */
1221
795
      proto_tree_add_bytes_format(cotp_tree, hf_cotp_segment_data, tvb, offset, (fragment_length) ? -1 : 0,
1222
795
                          NULL, "COTP segment data (%u byte%s)", fragment_length,
1223
795
                          plurality(fragment_length, "", "s"));
1224
1225
795
      if (!fragment) {
1226
        /* This is the last packet */
1227
795
        next_tvb = process_reassembled_data (next_tvb, offset, pinfo,
1228
795
                                             "Reassembled COTP", fd_head,
1229
795
                                             &cotp_frag_items, NULL, tree);
1230
795
      } 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
795
      pinfo->fragmented = fragment;
1236
795
    }
1237
3.82k
  }
1238
1239
3.82k
  if (uses_inactive_subset) {
1240
3.80k
    if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1241
3.80k
                                pinfo, tree, &hdtbl_entry, NULL)) {
1242
875
      *subdissector_found = true;
1243
2.93k
    } else {
1244
      /* Fill in other Dissectors using inactive subset here */
1245
2.93k
      call_data_dissector(next_tvb, pinfo, tree);
1246
2.93k
    }
1247
3.80k
  } 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
14
    if (!cotp_reassemble || !fragment) {
1255
12
      if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1256
12
                                  tree, &hdtbl_entry, NULL)) {
1257
3
        *subdissector_found = true;
1258
9
      } else {
1259
9
        call_data_dissector(next_tvb, pinfo, tree);
1260
9
      }
1261
12
    }
1262
14
  }
1263
1264
3.82k
  offset += tvb_captured_length_remaining(tvb, offset);
1265
  /* we dissected all of the containing PDU */
1266
1267
3.82k
  return offset;
1268
1269
3.99k
} /* 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
73
{
1276
73
  proto_tree *cotp_tree = NULL;
1277
73
  proto_item *ti;
1278
73
  bool        is_extended;
1279
73
  uint16_t    dst_ref;
1280
73
  unsigned    tpdu_nr;
1281
73
  tvbuff_t   *next_tvb;
1282
73
  unsigned    tpdu_len;
1283
73
  heur_dtbl_entry_t *hdtbl_entry;
1284
1285
  /* ED TPDUs have user data, so they run to the end of the containing PDU */
1286
73
  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
73
  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
73
    switch (li) {
1304
1305
3
      case LI_NORMAL_DT_WITH_CHECKSUM      :
1306
3
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1307
3
          return -1;
1308
        /* FALLTHROUGH */
1309
1310
51
      case LI_NORMAL_DT_WITHOUT_CHECKSUM   :
1311
51
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1312
51
        if (tpdu_nr & 0x80)
1313
22
          tpdu_nr = tpdu_nr & 0x7F;
1314
29
        else
1315
29
          return -1;
1316
22
        is_extended = false;
1317
22
        break;
1318
1319
0
      case LI_EXTENDED_DT_WITH_CHECKSUM    :
1320
0
        if (tvb_get_uint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1321
0
          return -1;
1322
        /* FALLTHROUGH */
1323
1324
7
      case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1325
7
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1326
7
        if (tpdu_nr & 0x80000000)
1327
0
          tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1328
7
        else
1329
7
          return -1;
1330
0
        is_extended = true;
1331
0
        break;
1332
1333
12
      default : /* bad TPDU */
1334
12
        return -1;
1335
73
    } /* li */
1336
73
  } 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
22
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1419
22
  pinfo->clnp_dstref = dst_ref;
1420
1421
22
  col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
1422
22
                  tpdu_nr, dst_ref);
1423
1424
22
  if (tree) {
1425
22
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1426
22
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1427
22
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1428
22
  }
1429
22
  offset += 1;
1430
1431
22
  if (tree) {
1432
22
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1433
22
  }
1434
22
  offset += 1;
1435
22
  li -= 1;
1436
1437
22
  if (tree)
1438
22
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1439
22
  offset += 2;
1440
22
  li -= 2;
1441
1442
22
  if (is_extended) {
1443
0
    if (tree) {
1444
0
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1445
0
                          4, tpdu_nr);
1446
0
    }
1447
0
    offset += 4;
1448
0
    li -= 4;
1449
22
  } else {
1450
22
    if (tree) {
1451
22
      proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1452
22
                          tpdu_nr);
1453
22
    }
1454
22
    offset += 1;
1455
22
    li -= 1;
1456
22
  }
1457
1458
22
  if (tree)
1459
22
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1460
22
  offset += li;
1461
1462
  /*
1463
   * Tell subdissectors that this is in an ED packet?
1464
   */
1465
22
  next_tvb = tvb_new_subset_remaining(tvb, offset);
1466
22
  if (uses_inactive_subset) {
1467
16
    if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1468
16
                                pinfo, tree, &hdtbl_entry, NULL)) {
1469
4
      *subdissector_found = true;
1470
12
    } else {
1471
      /* Fill in other Dissectors using inactive subset here */
1472
12
      call_data_dissector(next_tvb, pinfo, tree);
1473
12
    }
1474
16
  } else {
1475
    /*
1476
     * ED TPDUs are never fragmented
1477
     */
1478
6
    if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1479
6
                                tree, &hdtbl_entry, NULL)) {
1480
2
      *subdissector_found = true;
1481
4
    } else {
1482
4
      call_data_dissector(next_tvb, pinfo, tree);
1483
4
    }
1484
6
  }
1485
1486
22
  offset += tvb_captured_length_remaining(tvb, offset);
1487
     /* we dissected all of the containing PDU */
1488
1489
22
  return offset;
1490
1491
73
} /* 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
18
{
1496
18
  proto_tree *cotp_tree;
1497
18
  proto_item *ti;
1498
18
  proto_item *item = NULL;
1499
18
  uint16_t dst_ref;
1500
18
  unsigned tpdu_nr;
1501
18
  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
18
  if (!cotp_decode_atn) {  /* non ATN, plain OSI */
1508
18
    switch(li) {
1509
1
      case LI_NORMAL_RJ   :
1510
1
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1511
1
        break;
1512
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
17
      default :
1517
17
        return -1;
1518
18
    }
1519
18
  } 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
1
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1540
1
  pinfo->clnp_dstref = dst_ref;
1541
1542
1
  col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
1543
1
                  tpdu_nr, dst_ref);
1544
1545
1
  if (tree) {
1546
1
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1547
1
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1548
1
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1549
1
    item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1,
1550
1
                               tpdu);
1551
1
    if (li == LI_NORMAL_RJ) {
1552
1
      proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset +  1, 1, cdt);
1553
1
    }
1554
1
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
1555
1
                        dst_ref);
1556
1
    if (li == LI_NORMAL_RJ)
1557
1
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset + 4,
1558
1
                          1, tpdu_nr);
1559
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
1
  }
1565
1566
1
  offset += li + 1;
1567
1568
1
  expert_add_info_format(pinfo, item, &ei_cotp_reject, "Reject(RJ): -> 0x%x", dst_ref);
1569
1570
1
  return offset;
1571
1572
18
} /* 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
177
{
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
177
  proto_tree *cotp_tree = NULL;
1586
177
  proto_item *ti;
1587
177
  proto_item *item = NULL;
1588
177
  uint16_t dst_ref, src_ref;
1589
177
  uint8_t class_option;
1590
177
  tvbuff_t *next_tvb;
1591
177
  unsigned   tpdu_len;
1592
177
  heur_dtbl_entry_t *hdtbl_entry;
1593
177
  static int * const class_options[] = {
1594
177
     &hf_cotp_class,
1595
177
     &hf_cotp_opts_extended_formats,
1596
177
     &hf_cotp_opts_no_explicit_flow_control,
1597
177
     NULL,
1598
177
  };
1599
1600
177
  src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1601
1602
177
  class_option = tvb_get_uint8(tvb, offset + P_CLASS_OPTION);
1603
177
  if (((class_option & 0xF0) >> 4) > 4) /* class 0..4 allowed */
1604
34
    return -1;
1605
1606
  /* CR and CC TPDUs can have user data, so they run to the end of the
1607
   * containing PDU */
1608
143
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
1609
1610
143
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1611
143
  pinfo->clnp_srcref = src_ref;
1612
143
  pinfo->clnp_dstref = dst_ref;
1613
1614
143
  col_append_fstr(pinfo->cinfo, COL_INFO,
1615
143
                  "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1616
143
                  (tpdu == CR_TPDU) ? "CR" : "CC", src_ref, dst_ref);
1617
1618
143
  ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1619
143
  cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1620
143
  proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1621
143
  offset += 1;
1622
1623
143
  item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1624
143
  offset += 1;
1625
143
  li -= 1;
1626
1627
143
  proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1628
143
  offset += 2;
1629
143
  li -= 2;
1630
1631
143
  proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1632
143
  offset += 2;
1633
143
  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
143
  if (pinfo->destport == 0) {
1638
120
    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
120
  } else {
1640
23
    cotp_conv_info_t *conv_info = get_cotp_conv_info(pinfo);
1641
23
    conv_info->rev->ref = src_ref;
1642
23
    conv_info->rev->ref_set = true;
1643
23
    if (tpdu == CR_TPDU) {
1644
11
      conv_info->fwd->ref = dst_ref;
1645
11
      conv_info->fwd->ref_set = true;
1646
11
    }
1647
23
  }
1648
1649
143
  proto_tree_add_bitmask_list(cotp_tree, tvb, offset, 1, class_options, ENC_NA);
1650
143
  offset += 1;
1651
143
  li -= 1;
1652
1653
143
  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
135
    next_tvb = tvb_new_subset_length(tvb, offset, li);
1662
135
    if (dissector_try_heuristic((tpdu == CR_TPDU) ?
1663
102
                                 cotp_cr_heur_subdissector_list :
1664
135
                                 cotp_cc_heur_subdissector_list,
1665
135
                                next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
1666
      /* A subdissector claimed this, so it really belongs to them. */
1667
12
      *subdissector_found = true;
1668
123
    } else {
1669
      /* No heuristic dissector claimed it, so dissect it as a regular
1670
         variable part. */
1671
123
      ositp_decode_var_part(tvb, offset, li, class_option, tpdu_len, pinfo,
1672
123
                            cotp_tree);
1673
123
    }
1674
135
    offset += li;
1675
135
  }
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
143
  if (tvb_captured_length_remaining(tvb, offset)) {
1682
12
    next_tvb = tvb_new_subset_remaining(tvb, offset);
1683
12
    if (!uses_inactive_subset){
1684
11
      if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1685
11
                                  tree, &hdtbl_entry, NULL)) {
1686
3
        *subdissector_found = true;
1687
8
      } else {
1688
8
        call_data_dissector(next_tvb, pinfo, tree);
1689
8
      }
1690
11
    }
1691
1
    else
1692
1
      call_data_dissector( next_tvb, pinfo, tree);
1693
12
    offset += tvb_captured_length_remaining(tvb, offset);
1694
    /* we dissected all of the containing PDU */
1695
12
  }
1696
1697
143
  return offset;
1698
1699
177
} /* 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
10
{
1704
10
  proto_tree *cotp_tree = NULL;
1705
10
  proto_item *ti;
1706
10
  proto_item *item = NULL;
1707
10
  uint16_t dst_ref, src_ref;
1708
10
  unsigned   tpdu_len;
1709
1710
  /* ATN may use checksums different from OSI */
1711
  /* which may result in different TPDU header length. */
1712
10
  if (!cotp_decode_atn) {
1713
10
    if (li > LI_MAX_DC)
1714
2
      return -1;
1715
10
  } 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
8
  tpdu_len = li + 1;
1723
1724
8
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1725
8
  src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1726
8
  pinfo->clnp_dstref = dst_ref;
1727
8
  pinfo->clnp_srcref = src_ref;
1728
1729
8
  col_append_fstr(pinfo->cinfo, COL_INFO,
1730
8
                  "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
1731
1732
8
  if (tree) {
1733
8
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1734
8
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1735
8
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1736
8
  }
1737
8
  offset += 1;
1738
1739
8
  if (tree) {
1740
8
    item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1741
8
  }
1742
8
  offset += 1;
1743
8
  li -= 1;
1744
1745
8
  if (tree)
1746
8
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1747
8
  offset += 2;
1748
8
  li -= 2;
1749
1750
8
  if (tree)
1751
8
    proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1752
8
  offset += 2;
1753
8
  li -= 2;
1754
1755
8
  if (tree)
1756
8
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1757
8
  offset += li;
1758
1759
8
  expert_add_info_format(pinfo, item, &ei_cotp_disconnect_confirm, "Disconnect Confirm(DC): 0x%x -> 0x%x", src_ref, dst_ref);
1760
1761
8
  return offset;
1762
1763
10
} /* 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
70
{
1768
70
  proto_tree *cotp_tree = NULL;
1769
70
  proto_item *ti;
1770
70
  uint16_t   dst_ref;
1771
70
  unsigned   tpdu_nr;
1772
70
  uint16_t   cdt_in_ak;
1773
70
  unsigned   tpdu_len;
1774
1775
70
  if (!cotp_decode_atn) {
1776
70
    if (li > LI_MAX_AK)
1777
5
      return -1;
1778
70
  } 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
65
  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
65
  if (is_LI_NORMAL_AK(li)) {
1790
1791
45
    dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1792
45
    tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1793
45
    pinfo->clnp_dstref = dst_ref;
1794
1795
45
    col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1796
45
                    tpdu_nr, dst_ref);
1797
1798
45
    if (tree) {
1799
44
      ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1800
44
      cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1801
44
      proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1802
44
    }
1803
45
    offset += 1;
1804
1805
45
    if (tree) {
1806
44
      proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1807
44
      proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset, 1, cdt);
1808
44
    }
1809
45
    offset += 1;
1810
45
    li -= 1;
1811
1812
45
    if (tree)
1813
44
      proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1814
45
    offset += 2;
1815
45
    li -= 2;
1816
1817
45
    if (tree) {
1818
44
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1819
44
                          tpdu_nr);
1820
44
    }
1821
45
    offset += 1;
1822
45
    li -= 1;
1823
1824
45
    if (tree)
1825
44
      ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1826
45
    offset += li;
1827
1828
45
  } else { /* extended format */
1829
1830
20
    dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1831
20
    tpdu_nr   = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1832
20
    cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1833
20
    pinfo->clnp_dstref = dst_ref;
1834
1835
20
    col_append_fstr(pinfo->cinfo, COL_INFO,
1836
20
                    "AK TPDU (%u) dst-ref: 0x%04x Credit: %u",
1837
20
                    tpdu_nr, dst_ref, cdt_in_ak);
1838
1839
20
    if (tree) {
1840
8
      ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1841
8
      cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1842
8
      proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1843
8
    }
1844
20
    offset += 1;
1845
1846
20
    if (tree) {
1847
8
      proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1848
8
    }
1849
20
    offset += 1;
1850
20
    li -= 1;
1851
1852
20
    if (tree)
1853
8
      proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1854
20
    offset += 2;
1855
20
    li -= 2;
1856
1857
20
    if (tree) {
1858
8
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1859
8
                          offset, 4, tpdu_nr);
1860
8
    }
1861
20
    offset += 4;
1862
20
    li -= 4;
1863
1864
20
    if (tree) {
1865
8
      proto_tree_add_uint(cotp_tree, hf_cotp_credit, tvb, offset, 2, cdt_in_ak);
1866
8
    }
1867
20
    offset += 2;
1868
20
    li -= 2;
1869
1870
20
    if (tree)
1871
8
      ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1872
20
    offset += li;
1873
1874
20
  } /* is_LI_NORMAL_AK */
1875
1876
65
  return offset;
1877
1878
70
} /* 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
74
{
1883
74
  proto_tree *cotp_tree = NULL;
1884
74
  proto_item *ti;
1885
74
  bool is_extended;
1886
74
  uint16_t dst_ref;
1887
74
  unsigned tpdu_nr;
1888
74
  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
74
  if (!cotp_decode_atn) {
1897
74
    if (li > LI_MAX_EA)
1898
44
      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
30
    switch (li) {
1904
1905
3
      case LI_NORMAL_EA_WITH_CHECKSUM      :
1906
3
        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
3
            return -1;
1909
        /* FALLTHROUGH */
1910
1911
8
      case LI_NORMAL_EA_WITHOUT_CHECKSUM   :
1912
8
        tpdu_nr = tvb_get_uint8(tvb, offset + P_TPDU_NR_234);
1913
8
        is_extended = false;
1914
8
        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
2
      case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1923
2
        tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1924
2
        is_extended = true;
1925
2
        break;
1926
1927
15
      default : /* bad TPDU */
1928
15
        return -1;
1929
30
    } /* li */
1930
30
  } 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
8
  tpdu_len = li + 1;
2017
2018
8
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
2019
8
  pinfo->clnp_dstref = dst_ref;
2020
2021
8
  col_append_fstr(pinfo->cinfo, COL_INFO, "EA TPDU (%u) dst-ref: 0x%04x",
2022
8
                  tpdu_nr, dst_ref);
2023
2024
8
  if (tree) {
2025
8
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
2026
8
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
2027
8
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
2028
8
  }
2029
8
  offset += 1;
2030
2031
8
  if (tree) {
2032
8
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
2033
8
  }
2034
8
  offset += 1;
2035
8
  li -= 1;
2036
2037
8
  if (tree)
2038
8
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
2039
8
  offset += 2;
2040
8
  li -= 2;
2041
2042
8
  if (is_extended) {
2043
2
    if (tree) {
2044
2
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
2045
2
                          offset, 4, tpdu_nr);
2046
2
    }
2047
2
    offset += 4;
2048
2
    li -= 4;
2049
6
  } else {
2050
6
    if (tree) {
2051
6
      proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
2052
6
                          tpdu_nr);
2053
6
    }
2054
6
    offset += 1;
2055
6
    li -= 1;
2056
6
  }
2057
2058
8
  if (tree)
2059
8
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len,  pinfo, cotp_tree);
2060
8
  offset += li;
2061
2062
8
  return offset;
2063
2064
74
} /* 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
44
{
2077
44
  proto_tree *cotp_tree = NULL;
2078
44
  proto_item *ti;
2079
44
  uint16_t dst_ref;
2080
44
  uint8_t tpdu_len;
2081
2082
  /* ATN: except for modified LI checking nothing to be done here */
2083
44
  if (!cotp_decode_atn) {
2084
44
    if (li > LI_MAX_ER)
2085
10
      return -1;
2086
44
  } 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
34
  tpdu_len = li + 1;
2094
2095
34
  if(try_val_to_str(tvb_get_uint8(tvb, offset + P_REJECT_ER), cotp_reject_vals) == NULL)
2096
27
      return -1;
2097
2098
7
  dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
2099
7
  pinfo->clnp_dstref = dst_ref;
2100
2101
7
  col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
2102
2103
7
  if (tree) {
2104
7
    ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
2105
7
    cotp_tree = proto_item_add_subtree(ti, ett_cotp);
2106
7
    proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
2107
7
    proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset +  1, 1, tpdu);
2108
7
    proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset +  2, 2,
2109
7
                        dst_ref);
2110
7
    proto_tree_add_item(cotp_tree, hf_cotp_reject_cause, tvb, offset + 4, 1, ENC_NA);
2111
7
  }
2112
7
  offset += 5;
2113
7
  li -= 4;
2114
2115
7
  if (tree)
2116
7
    ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
2117
7
  offset += li;
2118
2119
7
  return offset;
2120
2121
34
} /* 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
96
{
2127
96
  proto_item *ti;
2128
96
  proto_tree *cltp_tree = NULL;
2129
96
  tvbuff_t   *next_tvb;
2130
96
  unsigned   tpdu_len;
2131
96
  heur_dtbl_entry_t *hdtbl_entry;
2132
2133
  /* UD TPDUs have user data, so they run to the end of the containing PDU */
2134
96
  tpdu_len = tvb_reported_length_remaining(tvb, offset);
2135
2136
96
  col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
2137
2138
96
  if (tree) {
2139
96
    ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, ENC_NA);
2140
96
    cltp_tree = proto_item_add_subtree(ti, ett_cltp);
2141
96
    proto_tree_add_uint(cltp_tree, hf_cltp_li, tvb, offset, 1,li);
2142
96
  }
2143
96
  offset += 1;
2144
2145
96
  if (tree) {
2146
96
    proto_tree_add_uint(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu);
2147
96
  }
2148
96
  offset += 1;
2149
96
  li -= 1;
2150
2151
96
  if (tree)
2152
96
    ositp_decode_var_part(tvb, offset, li, 0, tpdu_len, pinfo, cltp_tree);
2153
96
  offset += li;
2154
2155
96
  next_tvb = tvb_new_subset_remaining(tvb, offset);
2156
2157
96
  if (dissector_try_heuristic(cltp_heur_subdissector_list, next_tvb,
2158
96
                              pinfo, tree, &hdtbl_entry, NULL)) {
2159
2
    *subdissector_found = true;
2160
94
  } else {
2161
94
    call_data_dissector(next_tvb, pinfo, tree);
2162
94
  }
2163
2164
2165
  /*call_data_dissector(next_tvb, pinfo, tree); */
2166
2167
96
  offset += tvb_captured_length_remaining(tvb, offset);
2168
  /* we dissected all of the containing PDU */
2169
2170
96
  return offset;
2171
2172
96
} /* 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
5.26k
{
2186
5.26k
  int offset = 0;
2187
5.26k
  uint8_t li, tpdu, cdt;
2188
5.26k
  bool first_tpdu = true;
2189
5.26k
  int new_offset;
2190
5.26k
  bool found_ositp = false;
2191
5.26k
  bool is_cltp = false;
2192
5.26k
  bool subdissector_found = false;
2193
2194
  /* Initialize the COL_INFO field; each of the TPDUs will have its
2195
     information appended. */
2196
5.26k
  col_clear(pinfo->cinfo, COL_INFO);
2197
2198
7.66k
  while (tvb_offset_exists(tvb, offset)) {
2199
5.02k
    if (!first_tpdu) {
2200
25
      col_append_str(pinfo->cinfo, COL_INFO, ", ");
2201
25
      expert_add_info(pinfo, NULL, &ei_cotp_multiple_tpdus);
2202
      /* adjust tvb and offset to the start of the current PDU */
2203
25
      tvb = tvb_new_subset_remaining(tvb, offset);
2204
25
      offset = 0 ;
2205
25
    }
2206
5.02k
    if ((li = tvb_get_uint8(tvb, offset + P_LI)) == 0) {
2207
142
      col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
2208
142
      if (!first_tpdu)
2209
14
        call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2210
14
                       pinfo, tree);
2211
142
      return found_ositp;
2212
142
    }
2213
2214
4.88k
    tpdu = (tvb_get_uint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
2215
4.88k
    if (tpdu == UD_TPDU)
2216
96
      pinfo->current_proto = "CLTP";    /* connectionless transport */
2217
4.88k
    cdt = tvb_get_uint8(tvb, offset + P_CDT) & 0x0F;
2218
2219
4.88k
    switch (tpdu) {
2220
66
      case CC_TPDU :
2221
177
      case CR_TPDU :
2222
177
        new_offset = ositp_decode_CR_CC(tvb, offset, li, tpdu, pinfo, tree,
2223
177
                                        uses_inactive_subset, &subdissector_found);
2224
177
        break;
2225
64
      case DR_TPDU :
2226
64
        new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
2227
64
        break;
2228
3.99k
      case DT_TPDU :
2229
3.99k
        new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
2230
3.99k
                                     uses_inactive_subset, &subdissector_found);
2231
3.99k
        break;
2232
73
      case ED_TPDU :
2233
73
        new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree,
2234
73
                                     uses_inactive_subset, &subdissector_found);
2235
73
        break;
2236
18
      case RJ_TPDU :
2237
18
        new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
2238
18
        break;
2239
10
      case DC_TPDU :
2240
10
        new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
2241
10
        break;
2242
70
      case AK_TPDU :
2243
70
        new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
2244
70
        break;
2245
74
      case EA_TPDU :
2246
74
        new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
2247
74
        break;
2248
44
      case ER_TPDU :
2249
44
        new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
2250
44
        break;
2251
96
      case UD_TPDU :
2252
96
        new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree,
2253
96
                                     &subdissector_found);
2254
96
        is_cltp = true;
2255
96
        break;
2256
247
      default      :
2257
247
        if (first_tpdu)
2258
243
          col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)",
2259
243
                          tpdu);
2260
247
        new_offset = -1;    /* bad PDU type */
2261
247
        break;
2262
4.88k
    }
2263
2264
2.99k
    if (new_offset == -1) { /* incorrect TPDU */
2265
596
      if (!first_tpdu)
2266
10
        call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2267
10
                       pinfo, tree);
2268
596
      break;
2269
596
    }
2270
2271
2.39k
    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
2.39k
      if (!subdissector_found)
2275
1.49k
        col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
2276
2.39k
      found_ositp = true;
2277
2.39k
    }
2278
2279
2.39k
    offset = new_offset;
2280
2.39k
    first_tpdu = false;
2281
2.39k
  }
2282
3.23k
  return found_ositp ? offset : 0;
2283
5.26k
} /* dissect_ositp_internal */
2284
2285
static int dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2286
                          void *data _U_)
2287
78
{
2288
78
  return dissect_ositp_internal(tvb, pinfo, tree, false);
2289
78
}
2290
2291
static int dissect_ositp_inactive(tvbuff_t *tvb, packet_info *pinfo,
2292
                                   proto_tree *tree, void *data _U_)
2293
5.18k
{
2294
5.18k
  return dissect_ositp_internal(tvb, pinfo, tree, true);
2295
5.18k
}
2296
2297
static bool
2298
test_cltp_var_part(tvbuff_t *tvb)
2299
85
{
2300
85
  int offset = 0;
2301
85
  uint8_t li;
2302
87
  while (tvb_captured_length_remaining(tvb, offset)) {
2303
78
    if (tvb_captured_length_remaining(tvb, offset) < 2) {
2304
4
      return false;
2305
4
    }
2306
74
    switch (tvb_get_uint8(tvb, offset++)) {
2307
    /* These are the only 3 legal parameters for CLTP per RFC 1240 and X.234 */
2308
2
    case VP_SRC_TSAP:
2309
3
    case VP_DST_TSAP:
2310
5
    case VP_CHECKSUM: // Not required as redundant with UDP checksum, per RFC 1240
2311
5
      break;
2312
69
    default:
2313
69
      return false;
2314
74
    }
2315
5
    li = tvb_get_uint8(tvb, offset++);
2316
5
    if (li == 255) {
2317
0
      return false;
2318
0
    }
2319
5
    if (tvb_captured_length_remaining(tvb, offset) < li) {
2320
3
      return false;
2321
3
    }
2322
2
    offset += li;
2323
2
  }
2324
9
  return true;
2325
85
}
2326
2327
static bool
2328
dissect_cltp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
2329
          void *data)
2330
1.18k
{
2331
1.18k
  uint8_t li, tpdu, spdu;
2332
1.18k
  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.18k
  if (tvb_captured_length(tvb) < 2) {
2342
81
    return false;
2343
81
  }
2344
2345
1.10k
  li = tvb_get_uint8(tvb, offset++);
2346
2347
  /* LI must include TPDU, and 255 is reserved */
2348
1.10k
  if (li == 0 || li == 255) {
2349
263
    return false;
2350
263
  }
2351
2352
  /* Is it OSI on top of the UDP? */
2353
844
  tpdu = (tvb_get_uint8(tvb, offset++) & 0xF0) >> 4;
2354
844
  if (tpdu != UD_TPDU) {
2355
759
    return false;
2356
759
  }
2357
2358
  /* LI includes TPDU */
2359
85
  li--;
2360
2361
85
  if (!test_cltp_var_part(tvb_new_subset_length(tvb, offset, li))) {
2362
76
    return false;
2363
76
  }
2364
9
  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
9
  if (tvb_captured_length_remaining(tvb, offset) < 1) {
2372
6
    return false;
2373
6
  }
2374
2375
  /* And let's see if it is GOOSE SPDU */
2376
3
  spdu = tvb_get_uint8(tvb, offset);
2377
3
  if (spdu != 0xA1) {
2378
2
    return false;
2379
2
  }
2380
2381
1
  dissect_ositp(tvb, pinfo, parent_tree, data);
2382
1
  return true;
2383
3
}
2384
2385
void proto_register_cotp(void)
2386
14
{
2387
14
  static hf_register_info hf[] = {
2388
14
    { &hf_cotp_li,
2389
14
      { "Length", "cotp.li", FT_UINT8, BASE_DEC,
2390
14
        NULL, 0x0, "Length Indicator, length of this header", HFILL}},
2391
14
    { &hf_cotp_type,
2392
14
      { "PDU Type", "cotp.type", FT_UINT8, BASE_HEX,
2393
14
        VALS(cotp_tpdu_type_abbrev_vals), 0x0,
2394
14
        "PDU Type - upper nibble of byte", HFILL}},
2395
14
    { &hf_cotp_srcref,
2396
14
      { "Source reference", "cotp.srcref", FT_UINT16, BASE_HEX,
2397
14
        NULL, 0x0, "Source address reference", HFILL}},
2398
14
    { &hf_cotp_destref,
2399
14
      { "Destination reference", "cotp.destref", FT_UINT16, BASE_HEX,
2400
14
        NULL, 0x0, "Destination address reference", HFILL}},
2401
14
    { &hf_cotp_class,
2402
14
      { "Class", "cotp.class", FT_UINT8, BASE_DEC, NULL,
2403
14
        0xF0, "Transport protocol class", HFILL}},
2404
14
    { &hf_cotp_opts_extended_formats,
2405
14
      { "Extended formats", "cotp.opts.extended_formats", FT_BOOLEAN, 8,
2406
14
        NULL, 0x02, "Use of extended formats in classes 2, 3, and 4", HFILL}},
2407
14
    { &hf_cotp_opts_no_explicit_flow_control,
2408
14
      { "No explicit flow control", "cotp.opts.no_explicit_flow_control",
2409
14
        FT_BOOLEAN, 8, NULL, 0x01, "No explicit flow control in class 2",
2410
14
        HFILL}},
2411
14
    { &hf_cotp_tpdu_number,
2412
14
      { "TPDU number", "cotp.tpdu-number", FT_UINT8, BASE_HEX,
2413
14
        NULL, 0x7f, NULL, HFILL}},
2414
14
    { &hf_cotp_tpdu_number_extended,
2415
14
      { "TPDU number", "cotp.tpdu-number", FT_UINT32, BASE_HEX,
2416
14
        NULL, 0x0 /* XXX - 0x7fff? */, NULL, HFILL}},
2417
14
    { &hf_cotp_next_tpdu_number,
2418
14
      { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT8, BASE_HEX,
2419
14
        NULL, 0x0, NULL, HFILL}},
2420
14
    { &hf_cotp_next_tpdu_number_extended,
2421
14
      { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT32, BASE_HEX,
2422
14
        NULL, 0x0, NULL, HFILL}},
2423
14
    { &hf_cotp_eot,
2424
14
      { "Last data unit", "cotp.eot", FT_BOOLEAN, 8,
2425
14
        TFS(&tfs_yes_no),  0x80,
2426
14
        "Is current TPDU the last data unit of a complete DT TPDU sequence "
2427
14
        "(End of TSDU)?", HFILL}},
2428
14
    { &hf_cotp_eot_extended,
2429
14
      { "Last data unit", "cotp.eot", FT_BOOLEAN, 32,
2430
14
        TFS(&tfs_yes_no),  0x80000000,
2431
14
        "Is current TPDU the last data unit of a complete DT TPDU sequence "
2432
14
        "(End of TSDU)?", HFILL}},
2433
14
    { &hf_cotp_segment_overlap,
2434
14
      { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN, BASE_NONE,
2435
14
        NULL, 0x0, "Segment overlaps with other segments", HFILL }},
2436
14
    { &hf_cotp_segment_overlap_conflict,
2437
14
      { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict",
2438
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2439
14
        "Overlapping segments contained conflicting data", HFILL }},
2440
14
    { &hf_cotp_segment_multiple_tails,
2441
14
      { "Multiple tail segments found", "cotp.segment.multipletails",
2442
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2443
14
        "Several tails were found when reassembling the packet", HFILL }},
2444
14
    { &hf_cotp_segment_too_long_segment,
2445
14
      { "Segment too long", "cotp.segment.toolongsegment",
2446
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2447
14
        "Segment contained data past end of packet", HFILL }},
2448
14
    { &hf_cotp_segment_error,
2449
14
      { "Reassembly error", "cotp.segment.error", FT_FRAMENUM, BASE_NONE,
2450
14
        NULL, 0x0, "Reassembly error due to illegal segments", HFILL }},
2451
14
    { &hf_cotp_segment_count,
2452
14
      { "Segment count", "cotp.segment.count", FT_UINT32, BASE_DEC,
2453
14
        NULL, 0x0, NULL, HFILL }},
2454
14
    { &hf_cotp_segment,
2455
14
      { "COTP Segment", "cotp.segment", FT_FRAMENUM, BASE_NONE,
2456
14
        NULL, 0x0, NULL, HFILL }},
2457
14
    { &hf_cotp_segments,
2458
14
      { "COTP Segments", "cotp.segments", FT_NONE, BASE_NONE,
2459
14
        NULL, 0x0, NULL, HFILL }},
2460
14
    { &hf_cotp_reassembled_in,
2461
14
      { "Reassembled COTP in frame", "cotp.reassembled_in",
2462
14
        FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2463
14
        "This COTP packet is reassembled in this frame", HFILL }},
2464
14
    { &hf_cotp_reassembled_length,
2465
14
      { "Reassembled COTP length", "cotp.reassembled.length",
2466
14
        FT_UINT32, BASE_DEC, NULL, 0x0,
2467
14
        "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
14
    { &hf_cotp_vp_src_tsap,
2474
14
      { "Source TSAP", "cotp.src-tsap", FT_STRING, BASE_NONE,
2475
14
        NULL, 0x0, "Calling TSAP", HFILL }},
2476
14
    { &hf_cotp_vp_src_tsap_bytes,
2477
14
      { "Source TSAP", "cotp.src-tsap-bytes", FT_BYTES, BASE_NONE,
2478
14
        NULL, 0x0, "Calling TSAP (bytes representation)", HFILL }},
2479
14
    { &hf_cotp_vp_dst_tsap,
2480
14
      { "Destination TSAP", "cotp.dst-tsap", FT_STRING, BASE_NONE,
2481
14
        NULL, 0x0, "Called TSAP", HFILL }},
2482
14
    { &hf_cotp_vp_dst_tsap_bytes,
2483
14
      { "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES, BASE_NONE,
2484
14
        NULL, 0x0, "Called TSAP (bytes representation)", HFILL }},
2485
      /* Generated from convert_proto_tree_add_text.pl */
2486
14
      { &hf_cotp_parameter_code, { "Parameter code", "cotp.parameter_code", FT_UINT8, BASE_HEX, VALS(tp_vpart_type_vals), 0x0, NULL, HFILL }},
2487
14
      { &hf_cotp_parameter_length, { "Parameter length", "cotp.parameter_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2488
14
      { &hf_cotp_parameter_value, { "Parameter value", "cotp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2489
14
      { &hf_cotp_atn_extended_checksum16, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2490
14
      { &hf_cotp_atn_extended_checksum32, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2491
14
      { &hf_cotp_atn_extended_checksum_status, { "ATN extended checksum Status", "cotp.atn_extended_checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
2492
14
      { &hf_cotp_ack_time, { "Ack time (ms)", "cotp.ack_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2493
14
      { &hf_cotp_res_error_rate_target_value, { "Residual error rate, target value", "cotp.res_error_rate.target_value", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2494
14
      { &hf_cotp_res_error_rate_min_accept, { "Residual error rate, minimum acceptable", "cotp.res_error_rate.min_accept", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2495
14
      { &hf_cotp_res_error_rate_tdsu, { "Residual error rate, TSDU size of interest", "cotp.res_error_rate.tdsu", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2496
14
      { &hf_cotp_vp_priority, { "Priority", "cotp.vp_priority", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2497
14
      { &hf_cotp_transit_delay_targ_calling_called, { "Transit delay, target value, calling-called (ms)", "cotp.transit_delay.targ_calling_called", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2498
14
      { &hf_cotp_transit_delay_max_accept_calling_called, { "Transit delay, maximum acceptable, calling-called (ms)", "cotp.transit_delay.max_accept_calling_called", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2499
14
      { &hf_cotp_transit_delay_targ_called_calling, { "Transit delay, target value, called-calling (ms)", "cotp.transit_delay.targ_called_calling", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2500
14
      { &hf_cotp_transit_delay_max_accept_called_calling, { "Transit delay, maximum acceptable, called-calling (ms)", "cotp.transit_delay.max_accept_called_calling", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2501
14
      { &hf_cotp_max_throughput_targ_calling_called, { "Maximum throughput, target value, calling-called (o/s)", "cotp.max_throughput.targ_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2502
14
      { &hf_cotp_max_throughput_min_accept_calling_called, { "Maximum throughput, minimum acceptable, calling-called (o/s)", "cotp.max_throughput.min_accept_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2503
14
      { &hf_cotp_max_throughput_targ_called_calling, { "Maximum throughput, target value, called-calling (o/s)", "cotp.max_throughput.targ_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2504
14
      { &hf_cotp_max_throughput_min_accept_called_calling, { "Maximum throughput, minimum acceptable, called-calling (o/s)", "cotp.max_throughput.min_accept_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2505
14
      { &hf_cotp_avg_throughput_targ_calling_called, { "Average throughput, target value, calling-called (o/s)", "cotp.avg_throughput.targ_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2506
14
      { &hf_cotp_avg_throughput_min_accept_calling_called, { "Average throughput, minimum acceptable, calling-called (o/s)", "cotp.avg_throughput.min_accept_calling_called", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2507
14
      { &hf_cotp_avg_throughput_targ_called_calling, { "Average throughput, target value, called-calling (o/s)", "cotp.avg_throughput.targ_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2508
14
      { &hf_cotp_avg_throughput_min_accept_called_calling, { "Average throughput, minimum acceptable, called-calling (o/s)", "cotp.avg_throughput.min_accept_called_calling", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2509
14
      { &hf_cotp_sequence_number, { "Sequence number", "cotp.sequence_number", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2510
14
      { &hf_cotp_reassignment_time, { "Reassignment time (secs)", "cotp.reassignment_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2511
14
      { &hf_cotp_lower_window_edge, { "Lower window edge", "cotp.lower_window_edge", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2512
14
      { &hf_cotp_credit, { "Credit", "cotp.credit", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2513
14
      { &hf_cotp_tpdu_size, { "TPDU size", "cotp.tpdu_size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2514
14
      { &hf_cotp_checksum, { "Checksum", "cotp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2515
14
      { &hf_cotp_checksum_status, { "Checksum Status", "cotp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
2516
14
      { &hf_cotp_vp_version_nr, { "Version", "cotp.vp_version_nr", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2517
14
      { &hf_cotp_network_expedited_data, { "Use of network expedited data", "cotp.network_expedited_data", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x08, NULL, HFILL }},
2518
14
      { &hf_cotp_vp_opt_sel_class1_use, { "Use", "cotp.vp_opt_sel_class1_use", FT_BOOLEAN, 8, TFS(&tfs_vp_opt_sel_class1_use), 0x04, NULL, HFILL }},
2519
14
      { &hf_cotp_use_16_bit_checksum, { "16 bit checksum", "cotp.use_16_bit_checksum", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x02, NULL, HFILL }},
2520
14
      { &hf_cotp_transport_expedited_data_transfer, { "Transport expedited data transfer", "cotp.transport_expedited_data_transfer", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x01, NULL, HFILL }},
2521
14
      { &hf_cotp_preferred_maximum_tpdu_size, { "Preferred maximum TPDU size", "cotp.preferred_maximum_tpdu_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2522
14
      { &hf_cotp_inactivity_timer, { "Inactivity timer (ms)", "cotp.inactivity_timer", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2523
14
      { &hf_cotp_cause, { "Cause", "cotp.cause", FT_UINT8, BASE_DEC, VALS(cotp_cause_vals), 0x0, NULL, HFILL }},
2524
14
      { &hf_cotp_segment_data, { "COTP segment data", "cotp.segment_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2525
14
      { &hf_cotp_credit_cdt, { "Credit", "cotp.credit", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2526
14
      { &hf_cotp_reject_cause, { "Reject cause", "cotp.reject_cause", FT_UINT8, BASE_DEC, VALS(cotp_reject_vals), 0x0, NULL, HFILL }},
2527
14
  };
2528
14
  static int *ett[] = {
2529
14
    &ett_cotp,
2530
14
    &ett_cotp_segment,
2531
14
    &ett_cotp_segments
2532
14
  };
2533
14
  static ei_register_info ei[] = {
2534
14
      { &ei_cotp_disconnect_request, { "cotp.disconnect_request", PI_SEQUENCE, PI_CHAT, "Disconnect Request(DR)", EXPFILL }},
2535
14
      { &ei_cotp_reject, { "cotp.reject", PI_SEQUENCE, PI_NOTE, "Reject(RJ)", EXPFILL }},
2536
14
      { &ei_cotp_connection, { "cotp.connection", PI_SEQUENCE, PI_CHAT, "Connection", EXPFILL }},
2537
14
      { &ei_cotp_disconnect_confirm, { "cotp.disconnect_confirm", PI_SEQUENCE, PI_CHAT, "Disconnect Confirm(DC)", EXPFILL }},
2538
14
      { &ei_cotp_multiple_tpdus, { "cotp.multiple_tpdus", PI_SEQUENCE, PI_NOTE, "Multiple TPDUs in one packet", EXPFILL }},
2539
14
      { &ei_cotp_preferred_maximum_tpdu_size, { "cotp.preferred_maximum_tpdu_size.invalid", PI_PROTOCOL, PI_WARN, "Preferred maximum TPDU size: bogus length", EXPFILL }},
2540
14
      { &ei_cotp_atn_extended_checksum, { "cotp.bad_atn_ext_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2541
14
      { &ei_cotp_checksum, { "cotp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2542
14
  };
2543
2544
14
  module_t *cotp_module;
2545
14
  expert_module_t* expert_cotp;
2546
2547
14
  proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "COTP", "cotp");
2548
14
  proto_register_field_array(proto_cotp, hf, array_length(hf));
2549
14
  proto_register_subtree_array(ett, array_length(ett));
2550
14
  expert_cotp = expert_register_protocol(proto_cotp);
2551
14
  expert_register_field_array(expert_cotp, ei, array_length(ei));
2552
14
  cotp_module = prefs_register_protocol(proto_cotp, NULL);
2553
2554
14
  prefs_register_bool_preference(cotp_module, "reassemble",
2555
14
                                 "Reassemble segmented COTP datagrams",
2556
14
                                 "Whether segmented COTP datagrams should be "
2557
14
                                 "reassembled. To use this option, you must "
2558
14
                                 "also enable \"Allow subdissectors to "
2559
14
                                 "reassemble TCP streams\" in the TCP "
2560
14
                                 "protocol settings.",
2561
14
                                 &cotp_reassemble);
2562
2563
14
  prefs_register_enum_preference(cotp_module, "tsap_display",
2564
14
                                 "Display TSAPs as strings or bytes",
2565
14
                                 "How TSAPs should be displayed",
2566
14
                                 &tsap_display, tsap_display_options, false);
2567
2568
14
  prefs_register_bool_preference(cotp_module, "decode_atn", "Decode ATN TPDUs",
2569
14
                                 "Whether to decode OSI TPDUs with ATN "
2570
14
                                 "(Aeronautical Telecommunications Network) "
2571
14
                                 "extensions. To use this option, you must "
2572
14
                                 "also enable \"Always try to decode NSDU as "
2573
14
                                 "transport PDUs\" in the CLNP protocol "
2574
14
                                 "settings.", &cotp_decode_atn);
2575
2576
  /* For handling protocols hijacking the variable part of CR or CC PDUs */
2577
14
  cotp_cr_heur_subdissector_list = register_heur_dissector_list_with_description("cotp_cr", "COTP CR (Connect Request) payload", proto_cotp);
2578
14
  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
14
  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
14
  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
14
  ositp_handle = register_dissector("ositp", dissect_ositp, proto_cotp);
2588
14
  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
14
  reassembly_table_register(&cotp_reassembly_table,
2599
14
                        &addresses_reassembly_table_functions);
2600
14
}
2601
2602
void proto_register_cltp(void)
2603
14
{
2604
14
  static hf_register_info hf[] = {
2605
14
    { &hf_cltp_li,
2606
14
      { "Length", "cltp.li", FT_UINT8, BASE_DEC, NULL, 0x0,
2607
14
        "Length Indicator, length of this header", HFILL}},
2608
14
    { &hf_cltp_type,
2609
14
      { "PDU Type", "cltp.type", FT_UINT8, BASE_HEX,
2610
14
        VALS(cltp_tpdu_type_abbrev_vals), 0x0, NULL, HFILL}}
2611
14
  };
2612
14
  static int *ett[] = {
2613
14
    &ett_cltp
2614
14
  };
2615
2616
14
  proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "CLTP", "cltp");
2617
14
  proto_register_field_array(proto_cltp, hf, array_length(hf));
2618
14
  proto_register_subtree_array(ett, array_length(ett));
2619
2620
14
  cltp_heur_subdissector_list = register_heur_dissector_list_with_description("cltp", "CLTP data atop CLNP", proto_cltp);
2621
14
}
2622
2623
void
2624
proto_reg_handoff_cotp(void)
2625
14
{
2626
14
  dissector_add_uint("ip.proto", IP_PROTO_TP, ositp_handle);
2627
2628
14
  rdp_cr_handle = find_dissector("rdp_cr");
2629
14
  rdp_cc_handle = find_dissector("rdp_cc");
2630
2631
14
  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
14
  heur_dissector_add("udp", dissect_cltp_heur, "CLTP over UDP",
2638
14
        "cltp_udp", proto_cltp, HEURISTIC_ENABLE);
2639
14
}
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
 */