2 * Routines for ISO/OSI transport protocol (connection-oriented
3 * and connectionless) packet disassembly
5 * Laurent Deniel <laurent.deniel@free.fr>
6 * Ralf Schneider <Ralf.Schneider@t-online.de>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include <epan/packet.h>
18 #include <epan/prefs.h>
19 #include <epan/reassemble.h>
20 #include <epan/conversation.h>
21 #include <epan/ipproto.h>
22 #include <epan/expert.h>
23 #include <epan/proto_data.h>
25 #include <wsutil/array.h>
27 #include <wsutil/str_util.h>
28 #include "packet-frame.h"
29 #include "packet-osi.h"
31 void proto_register_cotp(void);
32 void proto_register_cltp(void);
33 void proto_reg_handoff_cotp(void);
35 /* protocols and fields */
37 static int proto_clnp
;
39 static int proto_cotp
;
41 static int ett_cotp_segments
;
42 static int ett_cotp_segment
;
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
;
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
;
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
;
121 static int proto_cltp
;
124 static int hf_cltp_li
;
125 static int hf_cltp_type
;
127 static const fragment_items cotp_frag_items
= {
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 */
145 static dissector_handle_t rdp_cr_handle
;
146 static dissector_handle_t rdp_cc_handle
;
147 static dissector_handle_t ositp_handle
;
151 * ISO8073 OSI COTP definition
152 * See http://standards.iso.org/ittf/PubliclyAvailableStandards/index.html
153 * (or RFC905 for historic, and now-outdated information)
156 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
158 /* TPDU definition */
160 #define ED_TPDU 0x1 /* COTP */
161 #define EA_TPDU 0x2 /* COTP */
162 #define UD_TPDU 0x4 /* CLTP */
163 #define RJ_TPDU 0x5 /* COTP */
164 #define AK_TPDU 0x6 /* COTP */
165 #define ER_TPDU 0x7 /* COTP */
166 #define DR_TPDU 0x8 /* COTP */
167 #define DC_TPDU 0xC /* COTP */
168 #define CC_TPDU 0xD /* COTP */
169 #define CR_TPDU 0xE /* COTP */
170 #define DT_TPDU 0xF /* COTP */
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" },
186 static const value_string cltp_tpdu_type_abbrev_vals
[] = {
192 static const value_string class_option_vals
[] = {
209 #define P_TPDU_NR_0_1 2
210 #define P_TPDU_NR_234 4
211 #define P_VAR_PART_NDT 5
212 #define P_VAR_PART_EDT 8
213 #define P_VAR_PART_DC 6
214 #define P_CDT_IN_AK 8
215 #define P_CDT_IN_RJ 8
216 #define P_REJECT_ER 4
217 #define P_REASON_IN_DR 6
218 #define P_CLASS_OPTION 6
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.
226 #define LI_NORMAL_DT_CLASS_01 2
227 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
228 #define LI_NORMAL_DT_WITH_CHECKSUM (LI_NORMAL_DT_WITHOUT_CHECKSUM+4)
229 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
230 #define LI_EXTENDED_DT_WITH_CHECKSUM (LI_EXTENDED_DT_WITHOUT_CHECKSUM+4)
231 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
232 #define LI_NORMAL_EA_WITH_CHECKSUM (LI_NORMAL_EA_WITHOUT_CHECKSUM+4)
233 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
234 #define LI_EXTENDED_EA_WITH_CHECKSUM (LI_EXTENDED_EA_WITHOUT_CHECKSUM+4)
235 #define LI_NORMAL_RJ 4
236 #define LI_EXTENDED_RJ 9
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
245 #define is_LI_NORMAL_AK(p) ((p & 0x01) == 0)
248 * Modified TPDU length indicator values due to ATN 4-octet extended
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.
254 #define LI_ATN_NORMAL_DT_WITH_CHECKSUM (LI_NORMAL_DT_WITH_CHECKSUM+2)
255 #define LI_ATN_EXTENDED_DT_WITH_CHECKSUM (LI_EXTENDED_DT_WITH_CHECKSUM+2)
256 #define LI_ATN_NORMAL_EA_WITH_CHECKSUM (LI_NORMAL_EA_WITH_CHECKSUM+2)
257 #define LI_ATN_EXTENDED_EA_WITH_CHECKSUM (LI_EXTENDED_EA_WITH_CHECKSUM+2)
258 #define LI_ATN_NORMAL_RJ (LI_NORMAL_RJ+2)
259 #define LI_ATN_EXTENDED_RJ (LI_EXTENDED_RJ+2)
260 #define LI_ATN_MAX_DC (LI_MAX_DC+2)
261 #define LI_ATN_MAX_AK (LI_MAX_AK+2+1) /* +1 for padding? */
262 #define LI_ATN_MAX_EA (LI_MAX_EA+2)
263 #define LI_ATN_MAX_ER (LI_MAX_ER+2)
267 #define VP_ACK_TIME 0x85
268 #define VP_RES_ERROR 0x86
269 #define VP_PRIORITY 0x87
270 #define VP_TRANSIT_DEL 0x88
271 #define VP_THROUGHPUT 0x89
272 #define VP_SEQ_NR 0x8A /* in AK */
273 #define VP_REASSIGNMENT 0x8B
274 #define VP_FLOW_CNTL 0x8C /* in AK */
275 #define VP_TPDU_SIZE 0xC0
276 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
277 #define VP_DST_TSAP 0xC2
278 #define VP_CHECKSUM 0xC3
279 #define VP_VERSION_NR 0xC4
280 #define VP_PROTECTION 0xC5
281 #define VP_OPT_SEL 0xC6
282 #define VP_PROTO_CLASS 0xC7
283 #define VP_CLEARING_INFO 0xE0 /* in DR */
284 #define VP_PREF_MAX_TPDU_SIZE 0xF0
285 #define VP_INACTIVITY_TIMER 0xF2
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 #define VP_ATN_EC_32 0x08 /* 4 octet ATN Extended Transport Checksum parameter */
292 #define VP_ATN_EC_16 0x09 /* 2 octet ATN Extended Transport Checksum parameter */
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" },
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
;
325 /* global variables */
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
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
;
340 * Reassembly of COTP.
342 static reassembly_table cotp_reassembly_table
;
343 static uint16_t cotp_dst_ref
;
344 static bool cotp_frame_reset
;
345 static bool cotp_last_fragment
;
347 #define TSAP_DISPLAY_AUTO 0
348 #define TSAP_DISPLAY_STRING 1
349 #define TSAP_DISPLAY_BYTES 2
352 static bool cotp_reassemble
= true;
353 static int32_t tsap_display
= TSAP_DISPLAY_AUTO
;
354 static bool cotp_decode_atn
;
356 static const enum_val_t tsap_display_options
[] = {
357 {"auto", "As strings if printable", TSAP_DISPLAY_AUTO
},
358 {"string", "As strings", TSAP_DISPLAY_STRING
},
359 {"bytes", "As bytes", TSAP_DISPLAY_BYTES
},
363 /* function definitions */
365 #define MAX_TSAP_LEN 32
367 static void cotp_frame_end(void)
369 if (!cotp_last_fragment
) {
370 /* Last COTP in frame is not fragmented.
371 * No need for incrementing the dst_ref, so we decrement it here.
375 cotp_frame_reset
= true;
378 static char *print_tsap(wmem_allocator_t
*scope
, tvbuff_t
*tvb
, int offset
, int length
)
380 const unsigned char *tsap
= tvb_get_ptr(tvb
, offset
, length
);
383 int idx
= 0, returned_length
;
385 cur
=(char *)wmem_alloc(scope
, MAX_TSAP_LEN
* 2 + 3);
387 if (length
<= 0 || length
> MAX_TSAP_LEN
)
388 snprintf(cur
, MAX_TSAP_LEN
* 2 + 3, "<unsupported TSAP length>");
390 allprintable
= tvb_ascii_isprint(tvb
, offset
, length
);
392 returned_length
= snprintf(cur
, MAX_TSAP_LEN
* 2 + 3, "0x");
393 idx
+= MIN(returned_length
, MAX_TSAP_LEN
* 2 + 3 - 1);
395 while (length
!= 0) {
397 returned_length
= snprintf(&cur
[idx
], MAX_TSAP_LEN
* 2 + 3 - idx
,
399 idx
+= MIN(returned_length
, MAX_TSAP_LEN
* 2 + 3 - idx
- 1);
401 returned_length
= snprintf(&cur
[idx
], MAX_TSAP_LEN
* 2 + 3 - idx
,
403 idx
+= MIN(returned_length
, MAX_TSAP_LEN
* 2 + 3 - idx
- 1);
412 static const true_false_string tfs_vp_opt_sel_class1_use
= { "Receipt confirmation", "Explicit AK variant" };
414 static bool ositp_decode_var_part(tvbuff_t
*tvb
, int offset
, int vp_length
,
415 int class_option
, int tpdu_len
,
416 packet_info
*pinfo
, proto_tree
*tree
)
418 uint8_t code
, length
;
421 uint32_t offset_iso8073_checksum
= 0;
423 uint8_t tmp_code
= 0;
424 unsigned tmp_len
= 0;
425 uint32_t pref_max_tpdu_size
;
426 proto_item
*hidden_item
;
428 while (vp_length
!= 0) {
429 code
= tvb_get_uint8(tvb
, offset
);
430 proto_tree_add_item(tree
, hf_cotp_parameter_code
, tvb
, offset
, 1, ENC_NA
);
436 length
= tvb_get_uint8(tvb
, offset
);
437 proto_tree_add_item(tree
, hf_cotp_parameter_length
, tvb
, offset
, 1, ENC_NA
);
443 case VP_ATN_EC_16
: /* ATN */
444 if (cotp_decode_atn
) {
446 /* if an alternate OSI checksum is present in the currently unprocessed
447 * VP section to the checksum algorithm has to know.
448 * this may be the case for backward compatible CR TPDU */
449 if (!offset_iso8073_checksum
) {
450 /* search following parameters in VP part for ISO checksum */
451 for (i
= offset
+ length
; i
< vp_length
;) {
452 tmp_code
= tvb_get_uint8(tvb
, i
++);
453 tmp_len
= tvb_get_uint8(tvb
, i
++);
454 if (tmp_code
== VP_CHECKSUM
) {
455 offset_iso8073_checksum
= i
; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
461 sum
= check_atn_ec_16(tvb
, tpdu_len
, offset
,
462 offset_iso8073_checksum
,
463 pinfo
->dst
.len
, (const uint8_t *)pinfo
->dst
.data
,
464 pinfo
->src
.len
, (const uint8_t *)pinfo
->src
.data
);
465 proto_tree_add_checksum(tree
, tvb
, offset
, hf_cotp_atn_extended_checksum16
, hf_cotp_atn_extended_checksum_status
, &ei_cotp_atn_extended_checksum
,
466 pinfo
, sum
, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_VERIFY
|PROTO_CHECKSUM_ZERO
);
468 proto_tree_add_bytes_format_value(tree
, hf_cotp_parameter_value
, tvb
, offset
, length
, NULL
, "<not shown>");
474 case VP_ATN_EC_32
: /* ATN */
475 if (cotp_decode_atn
) {
477 /* if an alternate OSI checksum is present in the currently unprocessed
478 * VP section the checksum algorithm has to know.
479 * this may be the case for backward compatible CR TPDU */
480 if (!offset_iso8073_checksum
) {
481 /* search following parameters in VP part for ISO checksum */
482 for (i
= offset
+ length
; i
< vp_length
;) {
483 tmp_code
= tvb_get_uint8(tvb
, i
++);
484 tmp_len
= tvb_get_uint8(tvb
, i
++);
485 if (tmp_code
== VP_CHECKSUM
) {
486 offset_iso8073_checksum
= i
; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
492 sum
= check_atn_ec_32(tvb
, tpdu_len
, offset
,
493 offset_iso8073_checksum
,
494 pinfo
->dst
.len
, (const uint8_t *)pinfo
->dst
.data
,
495 pinfo
->src
.len
, (const uint8_t *)pinfo
->src
.data
);
496 proto_tree_add_checksum(tree
, tvb
, offset
, hf_cotp_atn_extended_checksum32
, hf_cotp_atn_extended_checksum_status
, &ei_cotp_atn_extended_checksum
,
497 pinfo
, sum
, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_VERIFY
|PROTO_CHECKSUM_ZERO
);
499 proto_tree_add_bytes_format_value(tree
, hf_cotp_parameter_value
, tvb
, offset
, length
, NULL
, "<not shown>");
506 proto_tree_add_item(tree
, hf_cotp_ack_time
, tvb
, offset
, length
, ENC_BIG_ENDIAN
);
512 s
= tvb_get_uint8(tvb
, offset
);
513 proto_tree_add_uint_format_value(tree
, hf_cotp_res_error_rate_target_value
, tvb
, offset
, 1, s
, "10^%u", s
);
517 s
= tvb_get_uint8(tvb
, offset
);
518 proto_tree_add_uint_format_value(tree
, hf_cotp_res_error_rate_min_accept
, tvb
, offset
, 1, s
, "10^%u", s
);
522 s
= tvb_get_uint8(tvb
, offset
);
523 proto_tree_add_uint_format_value(tree
, hf_cotp_res_error_rate_tdsu
, tvb
, offset
, 1, s
, "2^%u", s
);
529 proto_tree_add_item(tree
, hf_cotp_vp_priority
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
535 proto_tree_add_item(tree
, hf_cotp_transit_delay_targ_calling_called
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
539 proto_tree_add_item(tree
, hf_cotp_transit_delay_max_accept_calling_called
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
543 proto_tree_add_item(tree
, hf_cotp_transit_delay_targ_called_calling
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
547 proto_tree_add_item(tree
, hf_cotp_transit_delay_max_accept_called_calling
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
553 proto_tree_add_item(tree
, hf_cotp_max_throughput_targ_calling_called
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
558 proto_tree_add_item(tree
, hf_cotp_max_throughput_min_accept_calling_called
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
563 proto_tree_add_item(tree
, hf_cotp_max_throughput_targ_called_calling
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
568 proto_tree_add_item(tree
, hf_cotp_max_throughput_min_accept_called_calling
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
573 if (length
!= 0) { /* XXX - should be 0 or 12 */
574 proto_tree_add_item(tree
, hf_cotp_avg_throughput_targ_calling_called
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
578 proto_tree_add_item(tree
, hf_cotp_avg_throughput_min_accept_calling_called
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
582 proto_tree_add_item(tree
, hf_cotp_avg_throughput_targ_called_calling
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
586 proto_tree_add_item(tree
, hf_cotp_avg_throughput_min_accept_called_calling
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
593 proto_tree_add_item(tree
, hf_cotp_sequence_number
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
598 case VP_REASSIGNMENT
:
599 proto_tree_add_item(tree
, hf_cotp_reassignment_time
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
605 proto_tree_add_item(tree
, hf_cotp_lower_window_edge
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
609 proto_tree_add_item(tree
, hf_cotp_sequence_number
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
613 proto_tree_add_item(tree
, hf_cotp_credit
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
620 c1
= tvb_get_uint8(tvb
, offset
) & 0x0F;
621 proto_tree_add_uint(tree
, hf_cotp_tpdu_size
, tvb
, offset
, 1, 1 << c1
);
627 /* if our preference is set to STRING or the TSAP is not printable,
628 * add as bytes and hidden as string; otherwise vice-versa */
629 if (tsap_display
==TSAP_DISPLAY_STRING
||
630 (tsap_display
==TSAP_DISPLAY_AUTO
&&
631 tvb_ascii_isprint(tvb
, offset
, length
))) {
632 proto_tree_add_string(tree
, hf_cotp_vp_src_tsap
, tvb
, offset
, length
,
633 print_tsap(pinfo
->pool
, tvb
, offset
, length
));
634 hidden_item
= proto_tree_add_item(tree
, hf_cotp_vp_src_tsap_bytes
, tvb
,
635 offset
, length
, ENC_NA
);
636 proto_item_set_hidden(hidden_item
);
638 hidden_item
= proto_tree_add_string(tree
, hf_cotp_vp_src_tsap
, tvb
,
640 print_tsap(pinfo
->pool
, tvb
, offset
, length
));
641 proto_item_set_hidden(hidden_item
);
642 proto_tree_add_item(tree
, hf_cotp_vp_src_tsap_bytes
, tvb
, offset
,
650 /* if our preference is set to STRING or the TSAP is not printable,
651 * add as bytes and hidden as string; otherwise vice-versa */
652 if (tsap_display
==TSAP_DISPLAY_STRING
||
653 (tsap_display
==TSAP_DISPLAY_AUTO
&&
654 tvb_ascii_isprint(tvb
, offset
, length
))) {
655 proto_tree_add_string(tree
, hf_cotp_vp_dst_tsap
, tvb
, offset
, length
,
656 print_tsap(pinfo
->pool
, tvb
, offset
, length
));
657 hidden_item
= proto_tree_add_item(tree
, hf_cotp_vp_dst_tsap_bytes
, tvb
,
658 offset
, length
, ENC_NA
);
659 proto_item_set_hidden(hidden_item
);
661 hidden_item
= proto_tree_add_string(tree
, hf_cotp_vp_dst_tsap
, tvb
,
663 print_tsap(pinfo
->pool
, tvb
, offset
, length
));
664 proto_item_set_hidden(hidden_item
);
665 proto_tree_add_item(tree
, hf_cotp_vp_dst_tsap_bytes
, tvb
, offset
,
673 offset_iso8073_checksum
= offset
; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
675 if (tvb_get_ntohs(tvb
, offset
) == 0) {
676 /* No checksum present */
677 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
);
679 uint32_t calc_c0
= 0, calc_c1
= 0;
681 if (osi_calc_checksum(tvb
, 0, length
, &calc_c0
, &calc_c1
)) {
682 /* Successfully processed checksum, verify it */
683 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
);
685 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
);
694 proto_tree_add_item(tree
, hf_cotp_vp_version_nr
, tvb
, offset
, 1, ENC_NA
);
700 switch (class_option
) {
703 proto_tree_add_item(tree
, hf_cotp_network_expedited_data
, tvb
, offset
, 1, ENC_NA
);
705 proto_tree_add_item(tree
, hf_cotp_vp_opt_sel_class1_use
, tvb
, offset
, 1, ENC_NA
);
709 proto_tree_add_item(tree
, hf_cotp_use_16_bit_checksum
, tvb
, offset
, 1, ENC_NA
);
713 proto_tree_add_item(tree
, hf_cotp_transport_expedited_data_transfer
, tvb
, offset
, 1, ENC_NA
);
718 case VP_PREF_MAX_TPDU_SIZE
:
722 pref_max_tpdu_size
= tvb_get_uint8(tvb
, offset
);
726 pref_max_tpdu_size
= tvb_get_ntohs(tvb
, offset
);
730 pref_max_tpdu_size
= tvb_get_ntoh24(tvb
, offset
);
734 pref_max_tpdu_size
= tvb_get_ntohl(tvb
, offset
);
738 proto_tree_add_expert_format(tree
, pinfo
, &ei_cotp_preferred_maximum_tpdu_size
, tvb
, offset
, length
,
739 "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)", length
);
742 proto_tree_add_uint(tree
, hf_cotp_preferred_maximum_tpdu_size
, tvb
, offset
, length
, pref_max_tpdu_size
*128);
747 case VP_INACTIVITY_TIMER
:
748 proto_tree_add_item(tree
, hf_cotp_inactivity_timer
, tvb
, offset
, length
, ENC_BIG_ENDIAN
);
753 case VP_PROTECTION
: /* user-defined */
754 case VP_PROTO_CLASS
: /* todo */
755 case VP_CLEARING_INFO
: /* user-defined */
756 default: /* unknown, no decoding */
757 proto_tree_add_bytes_format_value(tree
, hf_cotp_parameter_value
, tvb
, offset
, length
, NULL
, "<not shown>");
767 static const value_string cotp_cause_vals
[] = {
768 { 0, "Reason not specified" },
769 { 1, "Congestion at TSAP" },
770 { 2, "Session entity not attached to TSAP" },
771 { 3, "Address unknown" },
772 { 128+0, "Normal Disconnect" },
773 { 128+1, "Remote transport entity congestion" },
774 { 128+2, "Connection negotiation failed" },
775 { 128+3, "Duplicate source reference" },
776 { 128+4, "Mismatched references" },
777 { 128+5, "Protocol error" },
778 { 128+7, "Reference overflow" },
779 { 128+8, "Connection request refused" },
780 { 128+10, "Header or parameter length invalid" },
784 static int ositp_decode_DR(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
785 packet_info
*pinfo
, proto_tree
*tree
)
787 proto_tree
*cotp_tree
= NULL
;
788 proto_item
*ti
= NULL
;
789 uint16_t dst_ref
, src_ref
;
790 unsigned char reason
;
793 /* ATN TPDU's tend to be larger than normal OSI,
794 * so nothing to do with respect to LI checks */
798 /* DR TPDUs can have user data, so they run to the end of the containing PDU */
799 tpdu_len
= tvb_reported_length_remaining(tvb
, offset
);
801 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
803 src_ref
= tvb_get_ntohs(tvb
, offset
+ P_SRC_REF
);
805 reason
= tvb_get_uint8(tvb
, offset
+ P_REASON_IN_DR
);
807 pinfo
->clnp_dstref
= dst_ref
;
808 pinfo
->clnp_srcref
= src_ref
;
810 /* the settings of the TCP srcport and destport are currently disabled,
811 * for the following reasons:
812 * a) only used for ISO conversation handling (which currently doesn't work)
813 * b) will prevent "ISO on TCP" (RFC1006) packets from using
814 * "follow TCP stream" correctly
816 * A future conversation handling might be able to handle different kinds of
817 * conversations (TCP, ISO, TCP on TCP, ...), but in that case this has to be
820 /*pinfo->srcport = src_ref;*/
821 /*pinfo->destport = dst_ref;*/
822 if (try_val_to_str(reason
, cotp_cause_vals
) == NULL
)
825 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
826 "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref
, dst_ref
);
829 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
830 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
831 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
832 proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
+ 1, 1, tpdu
);
833 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
+ 2, 2,
835 proto_tree_add_uint(cotp_tree
, hf_cotp_srcref
, tvb
, offset
+ 4, 2,
837 proto_tree_add_item(cotp_tree
, hf_cotp_cause
, tvb
, offset
+ 6, 1, ENC_NA
);
843 ositp_decode_var_part(tvb
, offset
, li
, 4, tpdu_len
, pinfo
, cotp_tree
);
846 expert_add_info_format(pinfo
, ti
, &ei_cotp_disconnect_request
, "Disconnect Request(DR): 0x%x -> 0x%x", src_ref
, dst_ref
);
849 call_data_dissector(tvb_new_subset_remaining(tvb
, offset
), pinfo
, tree
);
850 offset
+= tvb_captured_length_remaining(tvb
, offset
);
851 /* we dissected all of the containing PDU */
855 } /* ositp_decode_DR */
857 static int ositp_decode_DT(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
858 packet_info
*pinfo
, proto_tree
*tree
,
859 bool uses_inactive_subset
,
860 bool *subdissector_found
)
862 proto_tree
*cotp_tree
= NULL
;
867 uint32_t *prev_dst_ref
;
869 bool fragment
= false;
870 uint32_t fragment_length
= 0;
872 fragment_head
*fd_head
;
873 conversation_t
*conv
;
875 heur_dtbl_entry_t
*hdtbl_entry
;
877 /* DT TPDUs have user data, so they run to the end of the containing PDU */
878 tpdu_len
= tvb_reported_length_remaining(tvb
, offset
);
880 /* The fixed part is 2 octets long, not including the length indicator,
881 for classes 0 and 1; it is at least 4 octets long, not including
882 the length indicator, for classes 2, 3, and 4. */
883 is_class_234
= (li
> LI_NORMAL_DT_CLASS_01
);
885 /* note: in the ATN the user is up to chose between 3 different checksums:
886 * standard OSI, 2 or 4 octet extended checksum.
887 * The differences for DT are that the TPDU headers may be enlarged by 2
888 * octets and that checksum related option codes and option lengths are
889 * different. To not mess up the original OSI dissector LI checking was
890 * implemented separately. */
891 if (!cotp_decode_atn
) { /* non ATN, plain OSI*/
892 /* VP_CHECKSUM is the only parameter allowed in the variable part.
893 * (This means we may misdissect this if the packet is bad and
894 * contains other parameters.).
896 * XXX - not true; ISO/IEC 8073:1997 (E) says that "if the use of
897 * non-blocking expedited data transfer service is negotiated (class
898 * 4 only), the variable part shall contain the ED-TPDU-NR for the
899 * first DT-TPDU created from a T-DATA request subsequent to the
900 * T-EXPEDITED DATA request". */
903 case LI_NORMAL_DT_WITH_CHECKSUM
:
904 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_CHECKSUM
)
908 case LI_NORMAL_DT_WITHOUT_CHECKSUM
:
909 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
911 tpdu_nr
= tpdu_nr
& 0x7F;
915 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
918 case LI_EXTENDED_DT_WITH_CHECKSUM
:
919 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_CHECKSUM
)
923 case LI_EXTENDED_DT_WITHOUT_CHECKSUM
:
924 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
925 if (tpdu_nr
& 0x80000000)
926 tpdu_nr
= tpdu_nr
& 0x7FFFFFFF;
930 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
933 case LI_NORMAL_DT_CLASS_01
:
934 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_0_1
);
936 tpdu_nr
= tpdu_nr
& 0x7F;
940 prev_dst_ref
= (uint32_t *)p_get_proto_data(wmem_file_scope(), pinfo
, proto_clnp
, 0);
942 /* First COTP in frame - save previous dst_ref as offset */
943 prev_dst_ref
= wmem_new(wmem_file_scope(), uint32_t);
944 *prev_dst_ref
= cotp_dst_ref
;
945 p_add_proto_data(wmem_file_scope(), pinfo
, proto_clnp
, 0, prev_dst_ref
);
946 } else if (cotp_frame_reset
) {
947 cotp_dst_ref
= *prev_dst_ref
;
949 cotp_frame_reset
= false;
950 cotp_last_fragment
= fragment
;
951 dst_ref
= cotp_dst_ref
;
952 conv
= find_conversation_pinfo(pinfo
, 0);
954 /* Found a conversation, also use index for the generated dst_ref */
955 dst_ref
+= (conv
->conv_index
<< 16);
959 register_frame_end_routine(pinfo
, cotp_frame_end
);
963 default : /* bad TPDU */
967 /* check ATN class4 TPDU's here */
969 /* check packet length indicators of DaTa(DT) TPDU
970 * note: use of checksum depends on the selected RER
971 * (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
973 * note: sole use of TP4 class in the ATN
974 * note: normal/extended TPDU numbering is negociable */
977 /* normal DT with 2 octets of OSI or of ATN Extended Checksum */
978 case LI_NORMAL_DT_WITH_CHECKSUM
:
979 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_CHECKSUM
&&
980 tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_ATN_EC_16
)
984 case LI_NORMAL_DT_WITHOUT_CHECKSUM
:
985 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
987 tpdu_nr
= tpdu_nr
& 0x7F;
991 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
994 /* extended DT with 2 octets of OSI or of ATN Extended Checksum */
995 case LI_EXTENDED_DT_WITH_CHECKSUM
:
996 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_CHECKSUM
&&
997 tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_ATN_EC_16
)
1001 case LI_EXTENDED_DT_WITHOUT_CHECKSUM
:
1002 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1003 if (tpdu_nr
& 0x80000000)
1004 tpdu_nr
= tpdu_nr
& 0x7FFFFFFF;
1008 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1011 /* normal DT with ATN Extended Checksum (4 octets)*/
1012 case LI_ATN_NORMAL_DT_WITH_CHECKSUM
:
1013 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_ATN_EC_32
)
1016 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1019 tpdu_nr
= tpdu_nr
& 0x7F;
1022 is_extended
= false;
1023 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1026 /* extended DT with 4 octets ATN Extended Checksum */
1027 case LI_ATN_EXTENDED_DT_WITH_CHECKSUM
:
1028 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_ATN_EC_32
)
1031 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1032 if (tpdu_nr
& 0x80000000)
1033 tpdu_nr
= tpdu_nr
& 0x7FFFFFFF;
1037 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1040 default : /* bad TPDU */
1043 } /* cotp_decode_atn */
1045 pinfo
->clnp_dstref
= dst_ref
;
1047 pinfo
->fragmented
= fragment
;
1049 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "DT TPDU (%u) dst-ref: 0x%04x",
1052 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "DT TPDU (%u)", tpdu_nr
);
1056 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
1057 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
1058 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
1063 proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
, 1, tpdu
);
1070 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
, 2, dst_ref
);
1074 ti
= proto_tree_add_uint (cotp_tree
, hf_cotp_destref
, tvb
, offset
, 0,
1076 proto_item_set_generated (ti
);
1081 proto_tree_add_uint(cotp_tree
, hf_cotp_tpdu_number_extended
, tvb
, offset
,
1083 proto_tree_add_item(cotp_tree
, hf_cotp_eot_extended
, tvb
, offset
, 4,
1090 proto_tree_add_uint(cotp_tree
, hf_cotp_tpdu_number
, tvb
, offset
, 1,
1092 proto_tree_add_item(cotp_tree
, hf_cotp_eot
, tvb
, offset
, 1,
1100 ositp_decode_var_part(tvb
, offset
, li
, 4, tpdu_len
, pinfo
, cotp_tree
);
1103 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1104 fragment_length
= tvb_captured_length(next_tvb
);
1106 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [COTP fragment, %u byte%s]",
1107 fragment_length
, plurality(fragment_length
, "", "s"));
1109 col_append_str(pinfo
->cinfo
, COL_INFO
, " EOT");
1112 if (cotp_reassemble
) {
1114 * XXX - these sequence numbers are connection sequence number,
1115 * not segment sequence numbers - the first segment of a
1116 * segmented packet doesn't have a specific sequence number (e.g., 0
1117 * or 1), it has whatever the appropriate sequence number is for
1118 * it in the connection.
1120 * For now, we assume segments arrive in order, and just supply
1121 * the negation of the EOT flag as the "more flags" argument.
1122 * We should probably handle out-of-order packets separately,
1123 * so that we can deliver them in order even when *not*
1126 * Note also that TP0 has no sequence number, and relies on
1127 * the protocol atop which it runs to guarantee in-order delivery.
1129 fd_head
= fragment_add_seq_next(&cotp_reassembly_table
, next_tvb
, 0, pinfo
,
1130 dst_ref
, NULL
, fragment_length
, fragment
);
1131 if (fd_head
&& fd_head
->next
) {
1132 /* don't use -1 if fragment length is zero (throws Exception) */
1133 proto_tree_add_bytes_format(cotp_tree
, hf_cotp_segment_data
, tvb
, offset
, (fragment_length
) ? -1 : 0,
1134 NULL
, "COTP segment data (%u byte%s)", fragment_length
,
1135 plurality(fragment_length
, "", "s"));
1138 /* This is the last packet */
1139 next_tvb
= process_reassembled_data (next_tvb
, offset
, pinfo
,
1140 "Reassembled COTP", fd_head
,
1141 &cotp_frag_items
, NULL
, tree
);
1142 } else if (pinfo
->num
!= fd_head
->reassembled_in
) {
1143 /* Add a "Reassembled in" link if not reassembled in this frame */
1144 proto_tree_add_uint(cotp_tree
, *(cotp_frag_items
.hf_reassembled_in
),
1145 next_tvb
, 0, 0, fd_head
->reassembled_in
);
1147 pinfo
->fragmented
= fragment
;
1151 if (uses_inactive_subset
) {
1152 if (dissector_try_heuristic(cotp_is_heur_subdissector_list
, next_tvb
,
1153 pinfo
, tree
, &hdtbl_entry
, NULL
)) {
1154 *subdissector_found
= true;
1156 /* Fill in other Dissectors using inactive subset here */
1157 call_data_dissector(next_tvb
, pinfo
, tree
);
1161 * We dissect payload if one of the following is true:
1163 * - Reassembly option for COTP in preferences is unchecked
1164 * - Reassembly option is checked and this packet is the last fragment
1166 if ((!cotp_reassemble
) || ((cotp_reassemble
) && (!fragment
))) {
1167 if (dissector_try_heuristic(cotp_heur_subdissector_list
, next_tvb
, pinfo
,
1168 tree
, &hdtbl_entry
, NULL
)) {
1169 *subdissector_found
= true;
1171 call_data_dissector(next_tvb
, pinfo
, tree
);
1176 offset
+= tvb_captured_length_remaining(tvb
, offset
);
1177 /* we dissected all of the containing PDU */
1181 } /* ositp_decode_DT */
1183 static int ositp_decode_ED(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
1184 packet_info
*pinfo
, proto_tree
*tree
,
1185 bool uses_inactive_subset
,
1186 bool *subdissector_found
)
1188 proto_tree
*cotp_tree
= NULL
;
1195 heur_dtbl_entry_t
*hdtbl_entry
;
1197 /* ED TPDUs have user data, so they run to the end of the containing PDU */
1198 tpdu_len
= tvb_reported_length_remaining(tvb
, offset
);
1200 /* note: in the ATN the user is up to chose between 3 different checksums:
1201 * standard OSI, 2 or 4 octet extended checksum.
1202 * The differences for ED (as for DT) are that the TPDU headers may be
1203 * enlarged by 2 octets and that checksum related option codes and option
1204 * lengths are different. To not mess up the original OSI dissector LI
1205 * checking was implemented separately.
1207 * note: this could not be tested, because no sample was avail for expedited
1209 if (!cotp_decode_atn
) { /* non ATN, plain OSI*/
1210 /* ED TPDUs are never fragmented */
1212 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1213 (This means we may misdissect this if the packet is bad and
1214 contains other parameters.) */
1217 case LI_NORMAL_DT_WITH_CHECKSUM
:
1218 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_CHECKSUM
)
1222 case LI_NORMAL_DT_WITHOUT_CHECKSUM
:
1223 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1225 tpdu_nr
= tpdu_nr
& 0x7F;
1228 is_extended
= false;
1231 case LI_EXTENDED_DT_WITH_CHECKSUM
:
1232 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_CHECKSUM
)
1236 case LI_EXTENDED_DT_WITHOUT_CHECKSUM
:
1237 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1238 if (tpdu_nr
& 0x80000000)
1239 tpdu_nr
= tpdu_nr
& 0x7FFFFFFF;
1245 default : /* bad TPDU */
1249 /* check packet length indicators of ATN Expedited Data (ED) TPDU
1250 * note: use of checksum depends on the selected RER
1251 * (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
1253 * note: sole use of TP4 class in the ATN
1254 * note: normal/extended TPDU numbering is negociable */
1257 case LI_NORMAL_DT_WITHOUT_CHECKSUM
:
1258 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1260 tpdu_nr
= tpdu_nr
& 0x7F;
1263 is_extended
= false;
1266 case LI_NORMAL_DT_WITH_CHECKSUM
:
1267 if ((tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_CHECKSUM
) &&
1268 (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_ATN_EC_16
))
1271 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1273 tpdu_nr
= tpdu_nr
& 0x7F;
1276 is_extended
= false;
1279 case LI_ATN_NORMAL_DT_WITH_CHECKSUM
:
1280 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_ATN_EC_32
)
1283 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1285 tpdu_nr
= tpdu_nr
& 0x7F;
1288 is_extended
= false;
1291 case LI_EXTENDED_DT_WITHOUT_CHECKSUM
:
1292 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1293 if (tpdu_nr
& 0x80000000)
1294 tpdu_nr
= tpdu_nr
& 0x7FFFFFFF;
1300 case LI_EXTENDED_DT_WITH_CHECKSUM
:
1301 if ((tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_CHECKSUM
) &&
1302 (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_ATN_EC_16
))
1305 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1306 if (tpdu_nr
& 0x80000000)
1307 tpdu_nr
= tpdu_nr
& 0x7FFFFFFF;
1313 case LI_ATN_EXTENDED_DT_WITH_CHECKSUM
:
1314 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_ATN_EC_32
)
1317 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1318 if (tpdu_nr
& 0x80000000)
1319 tpdu_nr
= tpdu_nr
& 0x7FFFFFFF;
1325 default : /* bad TPDU */
1328 } /* cotp_decode_atn */
1330 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1331 pinfo
->clnp_dstref
= dst_ref
;
1333 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "ED TPDU (%u) dst-ref: 0x%04x",
1337 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
1338 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
1339 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
1344 proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
, 1, tpdu
);
1350 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
, 2, dst_ref
);
1356 proto_tree_add_uint(cotp_tree
, hf_cotp_tpdu_number_extended
, tvb
, offset
,
1363 proto_tree_add_uint(cotp_tree
, hf_cotp_tpdu_number
, tvb
, offset
, 1,
1371 ositp_decode_var_part(tvb
, offset
, li
, 4, tpdu_len
, pinfo
, cotp_tree
);
1375 * Tell subdissectors that this is in an ED packet?
1377 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1378 if (uses_inactive_subset
) {
1379 if (dissector_try_heuristic(cotp_is_heur_subdissector_list
, next_tvb
,
1380 pinfo
, tree
, &hdtbl_entry
, NULL
)) {
1381 *subdissector_found
= true;
1383 /* Fill in other Dissectors using inactive subset here */
1384 call_data_dissector(next_tvb
, pinfo
, tree
);
1388 * ED TPDUs are never fragmented
1390 if (dissector_try_heuristic(cotp_heur_subdissector_list
, next_tvb
, pinfo
,
1391 tree
, &hdtbl_entry
, NULL
)) {
1392 *subdissector_found
= true;
1394 call_data_dissector(next_tvb
, pinfo
, tree
);
1398 offset
+= tvb_captured_length_remaining(tvb
, offset
);
1399 /* we dissected all of the containing PDU */
1403 } /* ositp_decode_ED */
1405 static int ositp_decode_RJ(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
1406 uint8_t cdt
, packet_info
*pinfo
, proto_tree
*tree
)
1408 proto_tree
*cotp_tree
;
1410 proto_item
*item
= NULL
;
1413 uint16_t credit
= 0;
1415 /* note: in the ATN the user is up to chose between 3 different checksums:
1416 * standard OSI, 2 or 4 octet extended checksum.
1417 * The difference for RJ is that the TPDU header may be enlarged by 2 octets
1418 * for checksum parameters are not going to be checked here */
1419 if (!cotp_decode_atn
) { /* non ATN, plain OSI */
1422 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1424 case LI_EXTENDED_RJ
:
1425 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1426 credit
= tvb_get_ntohs(tvb
, offset
+ P_CDT_IN_RJ
);
1433 /* normal with 2 octets of OSI or ATN checksum */
1435 /* with 4 octets of ATN checksum */
1436 case LI_ATN_NORMAL_RJ
:
1437 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1439 /* extended with 2 octets of OSI or ATN checksum */
1440 case LI_EXTENDED_RJ
:
1441 /* with 4 octets of ATN checksum */
1442 case LI_ATN_EXTENDED_RJ
:
1443 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1444 credit
= tvb_get_ntohs(tvb
, offset
+ P_CDT_IN_RJ
);
1451 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1452 pinfo
->clnp_dstref
= dst_ref
;
1454 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "RJ TPDU (%u) dst-ref: 0x%04x",
1458 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
1459 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
1460 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
1461 item
= proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
+ 1, 1,
1463 if (li
== LI_NORMAL_RJ
) {
1464 proto_tree_add_uint(cotp_tree
, hf_cotp_credit_cdt
, tvb
, offset
+ 1, 1, cdt
);
1466 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
+ 2, 2,
1468 if (li
== LI_NORMAL_RJ
)
1469 proto_tree_add_uint(cotp_tree
, hf_cotp_next_tpdu_number
, tvb
, offset
+ 4,
1472 proto_tree_add_uint(cotp_tree
, hf_cotp_next_tpdu_number_extended
, tvb
,
1473 offset
+ 4, 4, tpdu_nr
);
1474 proto_tree_add_uint(cotp_tree
, hf_cotp_credit
, tvb
, offset
+ 8, 2, credit
);
1480 expert_add_info_format(pinfo
, item
, &ei_cotp_reject
, "Reject(RJ): -> 0x%x", dst_ref
);
1484 } /* ositp_decode_RJ */
1486 static int ositp_decode_CR_CC(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
1487 packet_info
*pinfo
, proto_tree
*tree
,
1488 bool uses_inactive_subset
,
1489 bool *subdissector_found
)
1491 /* note: in the ATN the user is up to chose between 3 different checksums:
1492 * standard OSI, 2 or 4 octet extended checksum.
1493 * Nothing has to be done here, for all ATN specifics are handled in VP. */
1495 /* CC & CR decoding in the same function */
1497 proto_tree
*cotp_tree
= NULL
;
1499 proto_item
*item
= NULL
;
1500 uint16_t dst_ref
, src_ref
;
1501 uint8_t class_option
;
1504 heur_dtbl_entry_t
*hdtbl_entry
;
1505 static int * const class_options
[] = {
1507 &hf_cotp_opts_extended_formats
,
1508 &hf_cotp_opts_no_explicit_flow_control
,
1512 src_ref
= tvb_get_ntohs(tvb
, offset
+ P_SRC_REF
);
1514 class_option
= tvb_get_uint8(tvb
, offset
+ P_CLASS_OPTION
);
1515 if (((class_option
& 0xF0) >> 4) > 4) /* class 0..4 allowed */
1518 /* CR and CC TPDUs can have user data, so they run to the end of the
1520 tpdu_len
= tvb_reported_length_remaining(tvb
, offset
);
1522 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1523 pinfo
->clnp_srcref
= src_ref
;
1524 pinfo
->clnp_dstref
= dst_ref
;
1526 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
1527 "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1528 (tpdu
== CR_TPDU
) ? "CR" : "CC", src_ref
, dst_ref
);
1530 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
1531 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
1532 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
1535 item
= proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
, 1, tpdu
);
1539 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
, 2, dst_ref
);
1543 proto_tree_add_uint(cotp_tree
, hf_cotp_srcref
, tvb
, offset
, 2, src_ref
);
1547 /* expert info, but only if not encapsulated in TCP/SMB */
1548 /* XXX - the best way to detect seems to be if we have a port set */
1549 if (pinfo
->destport
== 0) {
1550 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
);
1553 proto_tree_add_bitmask_list(cotp_tree
, tvb
, offset
, 1, class_options
, ENC_NA
);
1558 /* There's more data left, so we have the variable part.
1560 Microsoft's RDP hijacks the variable part of CR and CC PDUs
1561 for their own user data (RDP runs atop Class 0, which doesn't
1564 Try what heuristic dissectors we have. */
1565 next_tvb
= tvb_new_subset_length(tvb
, offset
, li
);
1566 if (dissector_try_heuristic((tpdu
== CR_TPDU
) ?
1567 cotp_cr_heur_subdissector_list
:
1568 cotp_cc_heur_subdissector_list
,
1569 next_tvb
, pinfo
, tree
, &hdtbl_entry
, NULL
)) {
1570 /* A subdissector claimed this, so it really belongs to them. */
1571 *subdissector_found
= true;
1573 /* No heuristic dissector claimed it, so dissect it as a regular
1575 ositp_decode_var_part(tvb
, offset
, li
, class_option
, tpdu_len
, pinfo
,
1582 * XXX - tell the subdissector that this is user data in a CR or
1583 * CC packet rather than a DT packet?
1585 if (tvb_captured_length_remaining(tvb
, offset
)) {
1586 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1587 if (!uses_inactive_subset
){
1588 if (dissector_try_heuristic(cotp_heur_subdissector_list
, next_tvb
, pinfo
,
1589 tree
, &hdtbl_entry
, NULL
)) {
1590 *subdissector_found
= true;
1592 call_data_dissector(next_tvb
, pinfo
, tree
);
1596 call_data_dissector( next_tvb
, pinfo
, tree
);
1597 offset
+= tvb_captured_length_remaining(tvb
, offset
);
1598 /* we dissected all of the containing PDU */
1603 } /* ositp_decode_CR_CC */
1605 static int ositp_decode_DC(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
1606 packet_info
*pinfo
, proto_tree
*tree
)
1608 proto_tree
*cotp_tree
= NULL
;
1610 proto_item
*item
= NULL
;
1611 uint16_t dst_ref
, src_ref
;
1614 /* ATN may use checksums different from OSI */
1615 /* which may result in different TPDU header length. */
1616 if (!cotp_decode_atn
) {
1620 if (li
> LI_ATN_MAX_DC
)
1624 /* DC TPDUs have no user data, so the length indicator determines the
1628 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1629 src_ref
= tvb_get_ntohs(tvb
, offset
+ P_SRC_REF
);
1630 pinfo
->clnp_dstref
= dst_ref
;
1631 pinfo
->clnp_srcref
= src_ref
;
1633 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
1634 "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref
, dst_ref
);
1637 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
1638 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
1639 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
1644 item
= proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
, 1, tpdu
);
1650 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
, 2, dst_ref
);
1655 proto_tree_add_uint(cotp_tree
, hf_cotp_srcref
, tvb
, offset
, 2, src_ref
);
1660 ositp_decode_var_part(tvb
, offset
, li
, 4, tpdu_len
, pinfo
, cotp_tree
);
1663 expert_add_info_format(pinfo
, item
, &ei_cotp_disconnect_confirm
, "Disconnect Confirm(DC): 0x%x -> 0x%x", src_ref
, dst_ref
);
1667 } /* ositp_decode_DC */
1669 static int ositp_decode_AK(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
1670 uint8_t cdt
, packet_info
*pinfo
, proto_tree
*tree
)
1672 proto_tree
*cotp_tree
= NULL
;
1679 if (!cotp_decode_atn
) {
1683 if (li
> LI_ATN_MAX_AK
)
1687 /* AK TPDUs have no user data, so the length indicator determines the
1691 /* is_LI_NORMAL_AK() works for normal ATN AK's, */
1692 /* for the TPDU header size may be enlarged by 2 octets */
1693 if (is_LI_NORMAL_AK(li
)) {
1695 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1696 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1697 pinfo
->clnp_dstref
= dst_ref
;
1699 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "AK TPDU (%u) dst-ref: 0x%04x",
1703 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
1704 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
1705 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
1710 proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
, 1, tpdu
);
1711 proto_tree_add_uint(cotp_tree
, hf_cotp_credit_cdt
, tvb
, offset
, 1, cdt
);
1717 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
, 2, dst_ref
);
1722 proto_tree_add_uint(cotp_tree
, hf_cotp_next_tpdu_number
, tvb
, offset
, 1,
1729 ositp_decode_var_part(tvb
, offset
, li
, 4, tpdu_len
, pinfo
, cotp_tree
);
1732 } else { /* extended format */
1734 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1735 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1736 cdt_in_ak
= tvb_get_ntohs(tvb
, offset
+ P_CDT_IN_AK
);
1737 pinfo
->clnp_dstref
= dst_ref
;
1739 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
1740 "AK TPDU (%u) dst-ref: 0x%04x Credit: %u",
1741 tpdu_nr
, dst_ref
, cdt_in_ak
);
1744 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
1745 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
1746 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
1751 proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
, 1, tpdu
);
1757 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
, 2, dst_ref
);
1762 proto_tree_add_uint(cotp_tree
, hf_cotp_next_tpdu_number_extended
, tvb
,
1763 offset
, 4, tpdu_nr
);
1769 proto_tree_add_uint(cotp_tree
, hf_cotp_credit
, tvb
, offset
, 2, cdt_in_ak
);
1775 ositp_decode_var_part(tvb
, offset
, li
, 4, tpdu_len
, pinfo
, cotp_tree
);
1778 } /* is_LI_NORMAL_AK */
1782 } /* ositp_decode_AK */
1784 static int ositp_decode_EA(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
1785 packet_info
*pinfo
, proto_tree
*tree
)
1787 proto_tree
*cotp_tree
= NULL
;
1794 /* Due to different checksums in the ATN the TPDU header sizes
1795 * as well as the checksum parameters may be different than plain OSI EA
1796 * because these are heavily checked for EA these checks had to be
1798 * note: this could not be tested, because no sample was avail for expedited
1800 if (!cotp_decode_atn
) {
1804 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1805 (This means we may misdissect this if the packet is bad and
1806 contains other parameters.) */
1809 case LI_NORMAL_EA_WITH_CHECKSUM
:
1810 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_CHECKSUM
||
1811 tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
+ 1) != 2)
1815 case LI_NORMAL_EA_WITHOUT_CHECKSUM
:
1816 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1817 is_extended
= false;
1820 case LI_EXTENDED_EA_WITH_CHECKSUM
:
1821 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_CHECKSUM
||
1822 tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
+ 1) != 2)
1826 case LI_EXTENDED_EA_WITHOUT_CHECKSUM
:
1827 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1831 default : /* bad TPDU */
1834 } else { /* cotp_decode_atn */
1835 /* check for ATN length: TPDU may be 2 octets longer due to checksum */
1836 if (li
> LI_ATN_MAX_EA
)
1841 /* extended TPDU numbering EA with no checksum */
1842 case LI_NORMAL_EA_WITHOUT_CHECKSUM
:
1843 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1844 is_extended
= false;
1847 /* normal TPDU numbering EA with 2 octets of OSI or ATN extended
1849 case LI_NORMAL_EA_WITH_CHECKSUM
:
1850 /* check checksum parameter (in VP) parameter code octet */
1851 if ((tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_CHECKSUM
) &&
1852 (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_ATN_EC_16
))
1855 /* check checksum parameter (in VP) length octet */
1856 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
+ 1) != 2)
1859 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1860 is_extended
= false;
1863 /* normal TPDU numbering EA with 4 octets of ATN extended checksum */
1864 case LI_ATN_NORMAL_EA_WITH_CHECKSUM
:
1865 /* check checksum parameter (in VP) parameter code octet */
1866 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
) != VP_ATN_EC_32
)
1869 /* check checksum parameter (in VP) length octet */
1870 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_NDT
+ 1) != 4)
1873 tpdu_nr
= tvb_get_uint8(tvb
, offset
+ P_TPDU_NR_234
);
1874 is_extended
= false;
1877 /* extended TPDU numbering EA with no checksum */
1878 case LI_EXTENDED_EA_WITHOUT_CHECKSUM
:
1879 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1883 /* extended TPDU numbering EA with 2 octets of OSI or ATN extended
1885 case LI_EXTENDED_EA_WITH_CHECKSUM
:
1886 /* check checksum parameter (in VP) parameter code octet */
1887 if ((tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_CHECKSUM
) &&
1888 (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_ATN_EC_16
))
1891 /* check checksum parameter (in VP) length octet */
1892 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
+ 1) != 2)
1895 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1899 /* extended EA with 4 octets ATN extended checksum */
1900 case LI_ATN_EXTENDED_EA_WITH_CHECKSUM
:
1901 /* check checksum parameter (in VP) parameter code octet */
1902 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
) != VP_ATN_EC_32
)
1905 /* check checksum parameter (in VP) length octet */
1906 if (tvb_get_uint8(tvb
, offset
+ P_VAR_PART_EDT
+ 1) != 2)
1909 tpdu_nr
= tvb_get_ntohl(tvb
, offset
+ P_TPDU_NR_234
);
1913 default : /* bad TPDU */
1918 /* ER TPDUs have no user data, so the length indicator determines the
1922 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
1923 pinfo
->clnp_dstref
= dst_ref
;
1925 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "EA TPDU (%u) dst-ref: 0x%04x",
1929 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
1930 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
1931 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
1936 proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
, 1, tpdu
);
1942 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
, 2, dst_ref
);
1948 proto_tree_add_uint(cotp_tree
, hf_cotp_next_tpdu_number_extended
, tvb
,
1949 offset
, 4, tpdu_nr
);
1955 proto_tree_add_uint(cotp_tree
, hf_cotp_next_tpdu_number
, tvb
, offset
, 1,
1963 ositp_decode_var_part(tvb
, offset
, li
, 4, tpdu_len
, pinfo
, cotp_tree
);
1968 } /* ositp_decode_EA */
1970 static const value_string cotp_reject_vals
[] = {
1971 { 0, "Reason not specified" },
1972 { 1, "Invalid parameter code" },
1973 { 2, "Invalid TPDU type" },
1974 { 3, "Invalid parameter value" },
1978 static int ositp_decode_ER(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
1979 packet_info
*pinfo
, proto_tree
*tree
)
1981 proto_tree
*cotp_tree
= NULL
;
1986 /* ATN: except for modified LI checking nothing to be done here */
1987 if (!cotp_decode_atn
) {
1991 if (li
> LI_ATN_MAX_ER
)
1995 /* ER TPDUs have no user data, so the length indicator determines the
1999 if(try_val_to_str(tvb_get_uint8(tvb
, offset
+ P_REJECT_ER
), cotp_reject_vals
) == NULL
)
2002 dst_ref
= tvb_get_ntohs(tvb
, offset
+ P_DST_REF
);
2003 pinfo
->clnp_dstref
= dst_ref
;
2005 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "ER TPDU dst-ref: 0x%04x", dst_ref
);
2008 ti
= proto_tree_add_item(tree
, proto_cotp
, tvb
, offset
, li
+ 1, ENC_NA
);
2009 cotp_tree
= proto_item_add_subtree(ti
, ett_cotp
);
2010 proto_tree_add_uint(cotp_tree
, hf_cotp_li
, tvb
, offset
, 1,li
);
2011 proto_tree_add_uint(cotp_tree
, hf_cotp_type
, tvb
, offset
+ 1, 1, tpdu
);
2012 proto_tree_add_uint(cotp_tree
, hf_cotp_destref
, tvb
, offset
+ 2, 2,
2014 proto_tree_add_item(cotp_tree
, hf_cotp_reject_cause
, tvb
, offset
+ 4, 1, ENC_NA
);
2020 ositp_decode_var_part(tvb
, offset
, li
, 4, tpdu_len
, pinfo
, cotp_tree
);
2025 } /* ositp_decode_ER */
2027 static int ositp_decode_UD(tvbuff_t
*tvb
, int offset
, uint8_t li
, uint8_t tpdu
,
2028 packet_info
*pinfo
, proto_tree
*tree
,
2029 bool *subdissector_found
)
2032 proto_tree
*cltp_tree
= NULL
;
2035 heur_dtbl_entry_t
*hdtbl_entry
;
2037 /* UD TPDUs have user data, so they run to the end of the containing PDU */
2038 tpdu_len
= tvb_reported_length_remaining(tvb
, offset
);
2040 col_append_str(pinfo
->cinfo
, COL_INFO
, "UD TPDU");
2043 ti
= proto_tree_add_item(tree
, proto_cltp
, tvb
, offset
, li
+ 1, ENC_NA
);
2044 cltp_tree
= proto_item_add_subtree(ti
, ett_cltp
);
2045 proto_tree_add_uint(cltp_tree
, hf_cltp_li
, tvb
, offset
, 1,li
);
2050 proto_tree_add_uint(cltp_tree
, hf_cltp_type
, tvb
, offset
, 1, tpdu
);
2056 ositp_decode_var_part(tvb
, offset
, li
, 0, tpdu_len
, pinfo
, cltp_tree
);
2059 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
2061 if (dissector_try_heuristic(cltp_heur_subdissector_list
, next_tvb
,
2062 pinfo
, tree
, &hdtbl_entry
, NULL
)) {
2063 *subdissector_found
= true;
2065 call_data_dissector(next_tvb
, pinfo
, tree
);
2069 /*call_data_dissector(next_tvb, pinfo, tree); */
2071 offset
+= tvb_captured_length_remaining(tvb
, offset
);
2072 /* we dissected all of the containing PDU */
2076 } /* ositp_decode_UD */
2078 /* Returns the offset past the last valid COTP or CLTP PDU if we found
2079 at least one valid COTP or CLTP PDU, 0 otherwise.
2081 There doesn't seem to be any way in which the OSI network layer protocol
2082 distinguishes between COTP and CLTP, but the first two octets of both
2083 protocols' headers mean the same thing - length and PDU type - and the
2084 only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
2085 both of them here. */
2086 static int dissect_ositp_internal(tvbuff_t
*tvb
, packet_info
*pinfo
,
2088 bool uses_inactive_subset
)
2091 uint8_t li
, tpdu
, cdt
;
2092 bool first_tpdu
= true;
2094 bool found_ositp
= false;
2095 bool is_cltp
= false;
2096 bool subdissector_found
= false;
2098 /* Initialize the COL_INFO field; each of the TPDUs will have its
2099 information appended. */
2100 col_clear(pinfo
->cinfo
, COL_INFO
);
2102 while (tvb_offset_exists(tvb
, offset
)) {
2104 col_append_str(pinfo
->cinfo
, COL_INFO
, ", ");
2105 expert_add_info(pinfo
, NULL
, &ei_cotp_multiple_tpdus
);
2106 /* adjust tvb and offset to the start of the current PDU */
2107 tvb
= tvb_new_subset_remaining(tvb
, offset
);
2110 if ((li
= tvb_get_uint8(tvb
, offset
+ P_LI
)) == 0) {
2111 col_append_str(pinfo
->cinfo
, COL_INFO
, "Length indicator is zero");
2113 call_data_dissector( tvb_new_subset_remaining(tvb
, offset
),
2118 tpdu
= (tvb_get_uint8(tvb
, offset
+ P_TPDU
) >> 4) & 0x0F;
2119 if (tpdu
== UD_TPDU
)
2120 pinfo
->current_proto
= "CLTP"; /* connectionless transport */
2121 cdt
= tvb_get_uint8(tvb
, offset
+ P_CDT
) & 0x0F;
2126 new_offset
= ositp_decode_CR_CC(tvb
, offset
, li
, tpdu
, pinfo
, tree
,
2127 uses_inactive_subset
, &subdissector_found
);
2130 new_offset
= ositp_decode_DR(tvb
, offset
, li
, tpdu
, pinfo
, tree
);
2133 new_offset
= ositp_decode_DT(tvb
, offset
, li
, tpdu
, pinfo
, tree
,
2134 uses_inactive_subset
, &subdissector_found
);
2137 new_offset
= ositp_decode_ED(tvb
, offset
, li
, tpdu
, pinfo
, tree
,
2138 uses_inactive_subset
, &subdissector_found
);
2141 new_offset
= ositp_decode_RJ(tvb
, offset
, li
, tpdu
, cdt
, pinfo
, tree
);
2144 new_offset
= ositp_decode_DC(tvb
, offset
, li
, tpdu
, pinfo
, tree
);
2147 new_offset
= ositp_decode_AK(tvb
, offset
, li
, tpdu
, cdt
, pinfo
, tree
);
2150 new_offset
= ositp_decode_EA(tvb
, offset
, li
, tpdu
, pinfo
, tree
);
2153 new_offset
= ositp_decode_ER(tvb
, offset
, li
, tpdu
, pinfo
, tree
);
2156 new_offset
= ositp_decode_UD(tvb
, offset
, li
, tpdu
, pinfo
, tree
,
2157 &subdissector_found
);
2162 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Unknown TPDU type (0x%x)",
2164 new_offset
= -1; /* bad PDU type */
2168 if (new_offset
== -1) { /* incorrect TPDU */
2170 call_data_dissector( tvb_new_subset_remaining(tvb
, offset
),
2176 /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
2177 is either COTP or CLTP. */
2178 if (!subdissector_found
)
2179 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, is_cltp
? "CLTP" : "COTP");
2183 offset
= new_offset
;
2186 return found_ositp
? offset
: 0;
2187 } /* dissect_ositp_internal */
2189 static int dissect_ositp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
2192 return dissect_ositp_internal(tvb
, pinfo
, tree
, false);
2195 static int dissect_ositp_inactive(tvbuff_t
*tvb
, packet_info
*pinfo
,
2196 proto_tree
*tree
, void *data _U_
)
2198 return dissect_ositp_internal(tvb
, pinfo
, tree
, true);
2202 test_cltp_var_part(tvbuff_t
*tvb
)
2206 while (tvb_captured_length_remaining(tvb
, offset
)) {
2207 if (tvb_captured_length_remaining(tvb
, offset
) < 2) {
2210 switch (tvb_get_uint8(tvb
, offset
++)) {
2211 /* These are the only 3 legal parameters for CLTP per RFC 1240 and X.234 */
2214 case VP_CHECKSUM
: // Not required as redundant with UDP checksum, per RFC 1240
2219 li
= tvb_get_uint8(tvb
, offset
++);
2223 if (tvb_captured_length_remaining(tvb
, offset
) < li
) {
2232 dissect_cltp_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
,
2235 uint8_t li
, tpdu
, spdu
;
2238 /* RFC 1240: OSI Connectionless Transport Services on top of UDP
2239 * was made Historic by RFC 2556, which noted that "at this time
2240 * there do not seem to be any implementations" and recommended
2241 * TPKT (RFC 2126, ISO Transport Service on top of TCP) instead.
2244 /* First, check do we have at least 2 bytes (length + tpdu) */
2245 if (tvb_captured_length(tvb
) < 2) {
2249 li
= tvb_get_uint8(tvb
, offset
++);
2251 /* LI must include TPDU, and 255 is reserved */
2252 if (li
== 0 || li
== 255) {
2256 /* Is it OSI on top of the UDP? */
2257 tpdu
= (tvb_get_uint8(tvb
, offset
++) & 0xF0) >> 4;
2258 if (tpdu
!= UD_TPDU
) {
2262 /* LI includes TPDU */
2265 if (!test_cltp_var_part(tvb_new_subset_length(tvb
, offset
, li
))) {
2270 /* Since R-GOOSE is the only known user of CLTP over UDP, just
2274 /* Check do we have SPDU ID byte, too */
2275 if (tvb_captured_length_remaining(tvb
, offset
) < 1) {
2279 /* And let's see if it is GOOSE SPDU */
2280 spdu
= tvb_get_uint8(tvb
, offset
);
2285 dissect_ositp(tvb
, pinfo
, parent_tree
, data
);
2290 cotp_reassemble_init(void)
2295 void proto_register_cotp(void)
2297 static hf_register_info hf
[] = {
2299 { "Length", "cotp.li", FT_UINT8
, BASE_DEC
,
2300 NULL
, 0x0, "Length Indicator, length of this header", HFILL
}},
2302 { "PDU Type", "cotp.type", FT_UINT8
, BASE_HEX
,
2303 VALS(cotp_tpdu_type_abbrev_vals
), 0x0,
2304 "PDU Type - upper nibble of byte", HFILL
}},
2306 { "Source reference", "cotp.srcref", FT_UINT16
, BASE_HEX
,
2307 NULL
, 0x0, "Source address reference", HFILL
}},
2309 { "Destination reference", "cotp.destref", FT_UINT16
, BASE_HEX
,
2310 NULL
, 0x0, "Destination address reference", HFILL
}},
2312 { "Class", "cotp.class", FT_UINT8
, BASE_DEC
, NULL
,
2313 0xF0, "Transport protocol class", HFILL
}},
2314 { &hf_cotp_opts_extended_formats
,
2315 { "Extended formats", "cotp.opts.extended_formats", FT_BOOLEAN
, 8,
2316 NULL
, 0x02, "Use of extended formats in classes 2, 3, and 4", HFILL
}},
2317 { &hf_cotp_opts_no_explicit_flow_control
,
2318 { "No explicit flow control", "cotp.opts.no_explicit_flow_control",
2319 FT_BOOLEAN
, 8, NULL
, 0x01, "No explicit flow control in class 2",
2321 { &hf_cotp_tpdu_number
,
2322 { "TPDU number", "cotp.tpdu-number", FT_UINT8
, BASE_HEX
,
2323 NULL
, 0x7f, NULL
, HFILL
}},
2324 { &hf_cotp_tpdu_number_extended
,
2325 { "TPDU number", "cotp.tpdu-number", FT_UINT32
, BASE_HEX
,
2326 NULL
, 0x0 /* XXX - 0x7fff? */, NULL
, HFILL
}},
2327 { &hf_cotp_next_tpdu_number
,
2328 { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT8
, BASE_HEX
,
2329 NULL
, 0x0, NULL
, HFILL
}},
2330 { &hf_cotp_next_tpdu_number_extended
,
2331 { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT32
, BASE_HEX
,
2332 NULL
, 0x0, NULL
, HFILL
}},
2334 { "Last data unit", "cotp.eot", FT_BOOLEAN
, 8,
2335 TFS(&tfs_yes_no
), 0x80,
2336 "Is current TPDU the last data unit of a complete DT TPDU sequence "
2337 "(End of TSDU)?", HFILL
}},
2338 { &hf_cotp_eot_extended
,
2339 { "Last data unit", "cotp.eot", FT_BOOLEAN
, 32,
2340 TFS(&tfs_yes_no
), 0x80000000,
2341 "Is current TPDU the last data unit of a complete DT TPDU sequence "
2342 "(End of TSDU)?", HFILL
}},
2343 { &hf_cotp_segment_overlap
,
2344 { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN
, BASE_NONE
,
2345 NULL
, 0x0, "Segment overlaps with other segments", HFILL
}},
2346 { &hf_cotp_segment_overlap_conflict
,
2347 { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict",
2348 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2349 "Overlapping segments contained conflicting data", HFILL
}},
2350 { &hf_cotp_segment_multiple_tails
,
2351 { "Multiple tail segments found", "cotp.segment.multipletails",
2352 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2353 "Several tails were found when reassembling the packet", HFILL
}},
2354 { &hf_cotp_segment_too_long_segment
,
2355 { "Segment too long", "cotp.segment.toolongsegment",
2356 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2357 "Segment contained data past end of packet", HFILL
}},
2358 { &hf_cotp_segment_error
,
2359 { "Reassembly error", "cotp.segment.error", FT_FRAMENUM
, BASE_NONE
,
2360 NULL
, 0x0, "Reassembly error due to illegal segments", HFILL
}},
2361 { &hf_cotp_segment_count
,
2362 { "Segment count", "cotp.segment.count", FT_UINT32
, BASE_DEC
,
2363 NULL
, 0x0, NULL
, HFILL
}},
2365 { "COTP Segment", "cotp.segment", FT_FRAMENUM
, BASE_NONE
,
2366 NULL
, 0x0, NULL
, HFILL
}},
2367 { &hf_cotp_segments
,
2368 { "COTP Segments", "cotp.segments", FT_NONE
, BASE_NONE
,
2369 NULL
, 0x0, NULL
, HFILL
}},
2370 { &hf_cotp_reassembled_in
,
2371 { "Reassembled COTP in frame", "cotp.reassembled_in",
2372 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
2373 "This COTP packet is reassembled in this frame", HFILL
}},
2374 { &hf_cotp_reassembled_length
,
2375 { "Reassembled COTP length", "cotp.reassembled.length",
2376 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2377 "The total length of the reassembled payload", HFILL
}},
2378 /* ISO DP 8073 i13.3.4(a) Source and destination TSAPs are defined as
2379 identifiers of unspecified type and length.
2380 Some implementations of COTP use printable strings, others use raw bytes.
2381 We always add both representations to the tree; one will always be hidden
2382 depending on the tsap display preference */
2383 { &hf_cotp_vp_src_tsap
,
2384 { "Source TSAP", "cotp.src-tsap", FT_STRING
, BASE_NONE
,
2385 NULL
, 0x0, "Calling TSAP", HFILL
}},
2386 { &hf_cotp_vp_src_tsap_bytes
,
2387 { "Source TSAP", "cotp.src-tsap-bytes", FT_BYTES
, BASE_NONE
,
2388 NULL
, 0x0, "Calling TSAP (bytes representation)", HFILL
}},
2389 { &hf_cotp_vp_dst_tsap
,
2390 { "Destination TSAP", "cotp.dst-tsap", FT_STRING
, BASE_NONE
,
2391 NULL
, 0x0, "Called TSAP", HFILL
}},
2392 { &hf_cotp_vp_dst_tsap_bytes
,
2393 { "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES
, BASE_NONE
,
2394 NULL
, 0x0, "Called TSAP (bytes representation)", HFILL
}},
2395 /* Generated from convert_proto_tree_add_text.pl */
2396 { &hf_cotp_parameter_code
, { "Parameter code", "cotp.parameter_code", FT_UINT8
, BASE_HEX
, VALS(tp_vpart_type_vals
), 0x0, NULL
, HFILL
}},
2397 { &hf_cotp_parameter_length
, { "Parameter length", "cotp.parameter_length", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2398 { &hf_cotp_parameter_value
, { "Parameter value", "cotp.parameter_value", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
2399 { &hf_cotp_atn_extended_checksum16
, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2400 { &hf_cotp_atn_extended_checksum32
, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2401 { &hf_cotp_atn_extended_checksum_status
, { "ATN extended checksum Status", "cotp.atn_extended_checksum.status", FT_UINT8
, BASE_NONE
, VALS(proto_checksum_vals
), 0x0, NULL
, HFILL
}},
2402 { &hf_cotp_ack_time
, { "Ack time (ms)", "cotp.ack_time", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2403 { &hf_cotp_res_error_rate_target_value
, { "Residual error rate, target value", "cotp.res_error_rate.target_value", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2404 { &hf_cotp_res_error_rate_min_accept
, { "Residual error rate, minimum acceptable", "cotp.res_error_rate.min_accept", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2405 { &hf_cotp_res_error_rate_tdsu
, { "Residual error rate, TSDU size of interest", "cotp.res_error_rate.tdsu", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2406 { &hf_cotp_vp_priority
, { "Priority", "cotp.vp_priority", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2407 { &hf_cotp_transit_delay_targ_calling_called
, { "Transit delay, target value, calling-called (ms)", "cotp.transit_delay.targ_calling_called", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2408 { &hf_cotp_transit_delay_max_accept_calling_called
, { "Transit delay, maximum acceptable, calling-called (ms)", "cotp.transit_delay.max_accept_calling_called", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2409 { &hf_cotp_transit_delay_targ_called_calling
, { "Transit delay, target value, called-calling (ms)", "cotp.transit_delay.targ_called_calling", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2410 { &hf_cotp_transit_delay_max_accept_called_calling
, { "Transit delay, maximum acceptable, called-calling (ms)", "cotp.transit_delay.max_accept_called_calling", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2411 { &hf_cotp_max_throughput_targ_calling_called
, { "Maximum throughput, target value, calling-called (o/s)", "cotp.max_throughput.targ_calling_called", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2412 { &hf_cotp_max_throughput_min_accept_calling_called
, { "Maximum throughput, minimum acceptable, calling-called (o/s)", "cotp.max_throughput.min_accept_calling_called", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2413 { &hf_cotp_max_throughput_targ_called_calling
, { "Maximum throughput, target value, called-calling (o/s)", "cotp.max_throughput.targ_called_calling", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2414 { &hf_cotp_max_throughput_min_accept_called_calling
, { "Maximum throughput, minimum acceptable, called-calling (o/s)", "cotp.max_throughput.min_accept_called_calling", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2415 { &hf_cotp_avg_throughput_targ_calling_called
, { "Average throughput, target value, calling-called (o/s)", "cotp.avg_throughput.targ_calling_called", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2416 { &hf_cotp_avg_throughput_min_accept_calling_called
, { "Average throughput, minimum acceptable, calling-called (o/s)", "cotp.avg_throughput.min_accept_calling_called", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2417 { &hf_cotp_avg_throughput_targ_called_calling
, { "Average throughput, target value, called-calling (o/s)", "cotp.avg_throughput.targ_called_calling", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2418 { &hf_cotp_avg_throughput_min_accept_called_calling
, { "Average throughput, minimum acceptable, called-calling (o/s)", "cotp.avg_throughput.min_accept_called_calling", FT_UINT24
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2419 { &hf_cotp_sequence_number
, { "Sequence number", "cotp.sequence_number", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2420 { &hf_cotp_reassignment_time
, { "Reassignment time (secs)", "cotp.reassignment_time", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2421 { &hf_cotp_lower_window_edge
, { "Lower window edge", "cotp.lower_window_edge", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2422 { &hf_cotp_credit
, { "Credit", "cotp.credit", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2423 { &hf_cotp_tpdu_size
, { "TPDU size", "cotp.tpdu_size", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2424 { &hf_cotp_checksum
, { "Checksum", "cotp.checksum", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
2425 { &hf_cotp_checksum_status
, { "Checksum Status", "cotp.checksum.status", FT_UINT8
, BASE_NONE
, VALS(proto_checksum_vals
), 0x0, NULL
, HFILL
}},
2426 { &hf_cotp_vp_version_nr
, { "Version", "cotp.vp_version_nr", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2427 { &hf_cotp_network_expedited_data
, { "Use of network expedited data", "cotp.network_expedited_data", FT_BOOLEAN
, 8, TFS(&tfs_used_notused
), 0x08, NULL
, HFILL
}},
2428 { &hf_cotp_vp_opt_sel_class1_use
, { "Use", "cotp.vp_opt_sel_class1_use", FT_BOOLEAN
, 8, TFS(&tfs_vp_opt_sel_class1_use
), 0x04, NULL
, HFILL
}},
2429 { &hf_cotp_use_16_bit_checksum
, { "16 bit checksum", "cotp.use_16_bit_checksum", FT_BOOLEAN
, 8, TFS(&tfs_used_notused
), 0x02, NULL
, HFILL
}},
2430 { &hf_cotp_transport_expedited_data_transfer
, { "Transport expedited data transfer", "cotp.transport_expedited_data_transfer", FT_BOOLEAN
, 8, TFS(&tfs_used_notused
), 0x01, NULL
, HFILL
}},
2431 { &hf_cotp_preferred_maximum_tpdu_size
, { "Preferred maximum TPDU size", "cotp.preferred_maximum_tpdu_size", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2432 { &hf_cotp_inactivity_timer
, { "Inactivity timer (ms)", "cotp.inactivity_timer", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2433 { &hf_cotp_cause
, { "Cause", "cotp.cause", FT_UINT8
, BASE_DEC
, VALS(cotp_cause_vals
), 0x0, NULL
, HFILL
}},
2434 { &hf_cotp_segment_data
, { "COTP segment data", "cotp.segment_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
2435 { &hf_cotp_credit_cdt
, { "Credit", "cotp.credit", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
2436 { &hf_cotp_reject_cause
, { "Reject cause", "cotp.reject_cause", FT_UINT8
, BASE_DEC
, VALS(cotp_reject_vals
), 0x0, NULL
, HFILL
}},
2438 static int *ett
[] = {
2443 static ei_register_info ei
[] = {
2444 { &ei_cotp_disconnect_request
, { "cotp.disconnect_request", PI_SEQUENCE
, PI_CHAT
, "Disconnect Request(DR)", EXPFILL
}},
2445 { &ei_cotp_reject
, { "cotp.reject", PI_SEQUENCE
, PI_NOTE
, "Reject(RJ)", EXPFILL
}},
2446 { &ei_cotp_connection
, { "cotp.connection", PI_SEQUENCE
, PI_CHAT
, "Connection", EXPFILL
}},
2447 { &ei_cotp_disconnect_confirm
, { "cotp.disconnect_confirm", PI_SEQUENCE
, PI_CHAT
, "Disconnect Confirm(DC)", EXPFILL
}},
2448 { &ei_cotp_multiple_tpdus
, { "cotp.multiple_tpdus", PI_SEQUENCE
, PI_NOTE
, "Multiple TPDUs in one packet", EXPFILL
}},
2449 { &ei_cotp_preferred_maximum_tpdu_size
, { "cotp.preferred_maximum_tpdu_size.invalid", PI_PROTOCOL
, PI_WARN
, "Preferred maximum TPDU size: bogus length", EXPFILL
}},
2450 { &ei_cotp_atn_extended_checksum
, { "cotp.bad_checksum", PI_CHECKSUM
, PI_ERROR
, "Bad checksum", EXPFILL
}},
2451 { &ei_cotp_checksum
, { "cotp.bad_checksum", PI_CHECKSUM
, PI_ERROR
, "Bad checksum", EXPFILL
}},
2454 module_t
*cotp_module
;
2455 expert_module_t
* expert_cotp
;
2457 proto_cotp
= proto_register_protocol(PROTO_STRING_COTP
, "COTP", "cotp");
2458 proto_register_field_array(proto_cotp
, hf
, array_length(hf
));
2459 proto_register_subtree_array(ett
, array_length(ett
));
2460 expert_cotp
= expert_register_protocol(proto_cotp
);
2461 expert_register_field_array(expert_cotp
, ei
, array_length(ei
));
2462 cotp_module
= prefs_register_protocol(proto_cotp
, NULL
);
2464 prefs_register_bool_preference(cotp_module
, "reassemble",
2465 "Reassemble segmented COTP datagrams",
2466 "Whether segmented COTP datagrams should be "
2467 "reassembled. To use this option, you must "
2468 "also enable \"Allow subdissectors to "
2469 "reassemble TCP streams\" in the TCP "
2470 "protocol settings.",
2473 prefs_register_enum_preference(cotp_module
, "tsap_display",
2474 "Display TSAPs as strings or bytes",
2475 "How TSAPs should be displayed",
2476 &tsap_display
, tsap_display_options
, false);
2478 prefs_register_bool_preference(cotp_module
, "decode_atn", "Decode ATN TPDUs",
2479 "Whether to decode OSI TPDUs with ATN "
2480 "(Aeronautical Telecommunications Network) "
2481 "extensions. To use this option, you must "
2482 "also enable \"Always try to decode NSDU as "
2483 "transport PDUs\" in the CLNP protocol "
2484 "settings.", &cotp_decode_atn
);
2486 /* For handling protocols hijacking the variable part of CR or CC PDUs */
2487 cotp_cr_heur_subdissector_list
= register_heur_dissector_list_with_description("cotp_cr", "COTP CR (Connect Request) payload", proto_cotp
);
2488 cotp_cc_heur_subdissector_list
= register_heur_dissector_list_with_description("cotp_cc", "COTP CC (Connect Confirm) payload", proto_cotp
);
2490 /* subdissector code in inactive subset */
2491 cotp_is_heur_subdissector_list
= register_heur_dissector_list_with_description("cotp_is", "COTP IS (Inactive Subset) payload", proto_cotp
);
2493 /* other COTP/ISO 8473 subdissectors */
2494 cotp_heur_subdissector_list
= register_heur_dissector_list_with_description("cotp", "COTP DT (Data) payload", proto_cotp
);
2496 /* XXX - what about CLTP and proto_cltp? */
2497 ositp_handle
= register_dissector("ositp", dissect_ositp
, proto_cotp
);
2498 register_dissector("ositp_inactive", dissect_ositp_inactive
, proto_cotp
);
2500 register_init_routine(cotp_reassemble_init
);
2502 * XXX - this is a connection-oriented transport-layer protocol,
2503 * so we should probably use more than just network-layer
2504 * endpoint addresses to match segments together, but the functions
2505 * in addresses_ports_reassembly_table_functions do matching based
2506 * on port numbers, so they won't let us ensure that segments from
2507 * different connections don't get assembled together.
2509 reassembly_table_register(&cotp_reassembly_table
,
2510 &addresses_reassembly_table_functions
);
2513 void proto_register_cltp(void)
2515 static hf_register_info hf
[] = {
2517 { "Length", "cltp.li", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2518 "Length Indicator, length of this header", HFILL
}},
2520 { "PDU Type", "cltp.type", FT_UINT8
, BASE_HEX
,
2521 VALS(cltp_tpdu_type_abbrev_vals
), 0x0, NULL
, HFILL
}}
2523 static int *ett
[] = {
2527 proto_cltp
= proto_register_protocol(PROTO_STRING_CLTP
, "CLTP", "cltp");
2528 proto_register_field_array(proto_cltp
, hf
, array_length(hf
));
2529 proto_register_subtree_array(ett
, array_length(ett
));
2531 cltp_heur_subdissector_list
= register_heur_dissector_list_with_description("cltp", "CLTP data atop CLNP", proto_cltp
);
2535 proto_reg_handoff_cotp(void)
2537 dissector_add_uint("ip.proto", IP_PROTO_TP
, ositp_handle
);
2539 rdp_cr_handle
= find_dissector("rdp_cr");
2540 rdp_cc_handle
= find_dissector("rdp_cc");
2542 proto_clnp
= proto_get_id_by_filter_name("clnp");
2544 /* Actual implementations of R-GOOSE seem to use UDP port 102, registered
2545 * for ISO-TSAP, cf. TPKT. Perhaps we should just register ositp_handle
2546 * to UDP port 102 instead of having a heuristic dissector?
2548 heur_dissector_add("udp", dissect_cltp_heur
, "CLTP over UDP",
2549 "cltp_udp", proto_cltp
, HEURISTIC_ENABLE
);
2553 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2558 * indent-tabs-mode: nil
2561 * vi: set shiftwidth=2 tabstop=8 expandtab:
2562 * :indentSize=2:tabSize=8:noTabs=true: