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/str_util.h>
26 #include "packet-frame.h"
27 #include "packet-osi.h"
29 void proto_register_cotp(void);
30 void proto_register_cltp(void);
31 void proto_reg_handoff_cotp(void);
33 /* protocols and fields */
35 static int proto_clnp;
37 static int proto_cotp = -1;
38 static gint ett_cotp = -1;
39 static gint ett_cotp_segments = -1;
40 static gint ett_cotp_segment = -1;
42 static int hf_cotp_li = -1;
43 static int hf_cotp_type = -1;
44 static int hf_cotp_srcref = -1;
45 static int hf_cotp_destref = -1;
46 static int hf_cotp_class = -1;
47 static int hf_cotp_opts_extended_formats = -1;
48 static int hf_cotp_opts_no_explicit_flow_control = -1;
49 static int hf_cotp_tpdu_number = -1;
50 static int hf_cotp_tpdu_number_extended = -1;
51 static int hf_cotp_next_tpdu_number = -1;
52 static int hf_cotp_next_tpdu_number_extended = -1;
53 static int hf_cotp_eot = -1;
54 static int hf_cotp_eot_extended = -1;
55 /* Generated from convert_proto_tree_add_text.pl */
56 static int hf_cotp_parameter_code = -1;
57 static int hf_cotp_parameter_length = -1;
58 static int hf_cotp_parameter_value = -1;
59 static int hf_cotp_atn_extended_checksum16 = -1;
60 static int hf_cotp_atn_extended_checksum32 = -1;
61 static int hf_cotp_atn_extended_checksum_status = -1;
62 static int hf_cotp_ack_time = -1;
63 static int hf_cotp_res_error_rate_target_value = -1;
64 static int hf_cotp_res_error_rate_min_accept = -1;
65 static int hf_cotp_res_error_rate_tdsu = -1;
66 static int hf_cotp_vp_priority = -1;
67 static int hf_cotp_transit_delay_targ_calling_called = -1;
68 static int hf_cotp_transit_delay_max_accept_calling_called = -1;
69 static int hf_cotp_transit_delay_targ_called_calling = -1;
70 static int hf_cotp_transit_delay_max_accept_called_calling = -1;
71 static int hf_cotp_max_throughput_targ_calling_called = -1;
72 static int hf_cotp_max_throughput_min_accept_calling_called = -1;
73 static int hf_cotp_max_throughput_targ_called_calling = -1;
74 static int hf_cotp_max_throughput_min_accept_called_calling = -1;
75 static int hf_cotp_avg_throughput_targ_calling_called = -1;
76 static int hf_cotp_avg_throughput_min_accept_calling_called = -1;
77 static int hf_cotp_avg_throughput_targ_called_calling = -1;
78 static int hf_cotp_avg_throughput_min_accept_called_calling = -1;
79 static int hf_cotp_sequence_number = -1;
80 static int hf_cotp_reassignment_time = -1;
81 static int hf_cotp_lower_window_edge = -1;
82 static int hf_cotp_credit = -1;
83 static int hf_cotp_tpdu_size = -1;
84 static int hf_cotp_checksum = -1;
85 static int hf_cotp_checksum_status = -1;
86 static int hf_cotp_vp_version_nr = -1;
87 static int hf_cotp_network_expedited_data = -1;
88 static int hf_cotp_vp_opt_sel_class1_use = -1;
89 static int hf_cotp_use_16_bit_checksum = -1;
90 static int hf_cotp_transport_expedited_data_transfer = -1;
91 static int hf_cotp_preferred_maximum_tpdu_size = -1;
92 static int hf_cotp_inactivity_timer = -1;
93 static int hf_cotp_cause = -1;
94 static int hf_cotp_segment_data = -1;
95 static int hf_cotp_credit_cdt = -1;
96 static int hf_cotp_reject_cause = -1;
98 static int hf_cotp_segments = -1;
99 static int hf_cotp_segment = -1;
100 static int hf_cotp_segment_overlap = -1;
101 static int hf_cotp_segment_overlap_conflict = -1;
102 static int hf_cotp_segment_multiple_tails = -1;
103 static int hf_cotp_segment_too_long_segment = -1;
104 static int hf_cotp_segment_error = -1;
105 static int hf_cotp_segment_count = -1;
106 static int hf_cotp_reassembled_in = -1;
107 static int hf_cotp_reassembled_length = -1;
109 static expert_field ei_cotp_disconnect_confirm = EI_INIT;
110 static expert_field ei_cotp_multiple_tpdus = EI_INIT;
111 static expert_field ei_cotp_reject = EI_INIT;
112 static expert_field ei_cotp_connection = EI_INIT;
113 static expert_field ei_cotp_disconnect_request = EI_INIT;
114 static expert_field ei_cotp_preferred_maximum_tpdu_size = EI_INIT;
115 static expert_field ei_cotp_atn_extended_checksum = EI_INIT;
116 static expert_field ei_cotp_checksum = EI_INIT;
119 static int proto_cltp = -1;
120 static gint ett_cltp = -1;
122 static int hf_cltp_li = -1;
123 static int hf_cltp_type = -1;
125 static const fragment_items cotp_frag_items = {
130 &hf_cotp_segment_overlap,
131 &hf_cotp_segment_overlap_conflict,
132 &hf_cotp_segment_multiple_tails,
133 &hf_cotp_segment_too_long_segment,
134 &hf_cotp_segment_error,
135 &hf_cotp_segment_count,
136 &hf_cotp_reassembled_in,
137 &hf_cotp_reassembled_length,
138 /* Reassembled data field */
143 static dissector_handle_t rdp_cr_handle;
144 static dissector_handle_t rdp_cc_handle;
145 static dissector_handle_t ositp_handle;
149 * ISO8073 OSI COTP definition
150 * See http://standards.iso.org/ittf/PubliclyAvailableStandards/index.html
151 * (or RFC905 for historic, and now-outdated information)
154 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
156 /* TPDU definition */
158 #define ED_TPDU 0x1 /* COTP */
159 #define EA_TPDU 0x2 /* COTP */
160 #define UD_TPDU 0x4 /* CLTP */
161 #define RJ_TPDU 0x5 /* COTP */
162 #define AK_TPDU 0x6 /* COTP */
163 #define ER_TPDU 0x7 /* COTP */
164 #define DR_TPDU 0x8 /* COTP */
165 #define DC_TPDU 0xC /* COTP */
166 #define CC_TPDU 0xD /* COTP */
167 #define CR_TPDU 0xE /* COTP */
168 #define DT_TPDU 0xF /* COTP */
170 static const value_string cotp_tpdu_type_abbrev_vals[] = {
171 { ED_TPDU, "ED Expedited Data" },
172 { EA_TPDU, "EA Expedited Data Acknowledgement" },
173 { RJ_TPDU, "RJ Reject" },
174 { AK_TPDU, "AK Data Acknowledgement" },
175 { ER_TPDU, "ER TPDU Error" },
176 { DR_TPDU, "DR Disconnect Request" },
177 { DC_TPDU, "DC Disconnect Confirm" },
178 { CC_TPDU, "CC Connect Confirm" },
179 { CR_TPDU, "CR Connect Request" },
180 { DT_TPDU, "DT Data" },
184 static const value_string cltp_tpdu_type_abbrev_vals[] = {
190 static const value_string class_option_vals[] = {
207 #define P_TPDU_NR_0_1 2
208 #define P_TPDU_NR_234 4
209 #define P_VAR_PART_NDT 5
210 #define P_VAR_PART_EDT 8
211 #define P_VAR_PART_DC 6
212 #define P_CDT_IN_AK 8
213 #define P_CDT_IN_RJ 8
214 #define P_REJECT_ER 4
215 #define P_REASON_IN_DR 6
216 #define P_CLASS_OPTION 6
219 * TPDU length indicator values.
220 * Checksum parameter is 4 octets - 1 octet of parameter code, 1 octet
221 * of parameter length, 2 octets of checksum.
224 #define LI_NORMAL_DT_CLASS_01 2
225 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
226 #define LI_NORMAL_DT_WITH_CHECKSUM (LI_NORMAL_DT_WITHOUT_CHECKSUM+4)
227 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
228 #define LI_EXTENDED_DT_WITH_CHECKSUM (LI_EXTENDED_DT_WITHOUT_CHECKSUM+4)
229 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
230 #define LI_NORMAL_EA_WITH_CHECKSUM (LI_NORMAL_EA_WITHOUT_CHECKSUM+4)
231 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
232 #define LI_EXTENDED_EA_WITH_CHECKSUM (LI_EXTENDED_EA_WITHOUT_CHECKSUM+4)
233 #define LI_NORMAL_RJ 4
234 #define LI_EXTENDED_RJ 9
240 /* XXX - can we always decide this based on whether the length
241 indicator is odd or not? What if the variable part has an odd
243 #define is_LI_NORMAL_AK(p) ((p & 0x01) == 0)
246 * Modified TPDU length indicator values due to ATN 4-octet extended
248 * Checksum parameter is 6 octets - 1 octet of parameter code, 1 octet
249 * of parameter length, 4 octets of checksum. That adds 2 octets to
250 * the lengths with a 2-octet checksum.
252 #define LI_ATN_NORMAL_DT_WITH_CHECKSUM (LI_NORMAL_DT_WITH_CHECKSUM+2)
253 #define LI_ATN_EXTENDED_DT_WITH_CHECKSUM (LI_EXTENDED_DT_WITH_CHECKSUM+2)
254 #define LI_ATN_NORMAL_EA_WITH_CHECKSUM (LI_NORMAL_EA_WITH_CHECKSUM+2)
255 #define LI_ATN_EXTENDED_EA_WITH_CHECKSUM (LI_EXTENDED_EA_WITH_CHECKSUM+2)
256 #define LI_ATN_NORMAL_RJ (LI_NORMAL_RJ+2)
257 #define LI_ATN_EXTENDED_RJ (LI_EXTENDED_RJ+2)
258 #define LI_ATN_MAX_DC (LI_MAX_DC+2)
259 #define LI_ATN_MAX_AK (LI_MAX_AK+2+1) /* +1 for padding? */
260 #define LI_ATN_MAX_EA (LI_MAX_EA+2)
261 #define LI_ATN_MAX_ER (LI_MAX_ER+2)
265 #define VP_ACK_TIME 0x85
266 #define VP_RES_ERROR 0x86
267 #define VP_PRIORITY 0x87
268 #define VP_TRANSIT_DEL 0x88
269 #define VP_THROUGHPUT 0x89
270 #define VP_SEQ_NR 0x8A /* in AK */
271 #define VP_REASSIGNMENT 0x8B
272 #define VP_FLOW_CNTL 0x8C /* in AK */
273 #define VP_TPDU_SIZE 0xC0
274 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
275 #define VP_DST_TSAP 0xC2
276 #define VP_CHECKSUM 0xC3
277 #define VP_VERSION_NR 0xC4
278 #define VP_PROTECTION 0xC5
279 #define VP_OPT_SEL 0xC6
280 #define VP_PROTO_CLASS 0xC7
281 #define VP_CLEARING_INFO 0xE0 /* in DR */
282 #define VP_PREF_MAX_TPDU_SIZE 0xF0
283 #define VP_INACTIVITY_TIMER 0xF2
286 /* Parameter codes with bits 7 and 8 are explicitly not */
287 /* assigned by ISO/IEC 8073, nor is their use precluded. */
288 /* Parameter codes for ATN defined in ICAO doc 9507 Ed3 SV 5 section 5.5.2.4.3.1 */
289 #define VP_ATN_EC_32 0x08 /* 4 octet ATN Extended Transport Checksum parameter */
290 #define VP_ATN_EC_16 0x09 /* 2 octet ATN Extended Transport Checksum parameter */
293 static const value_string tp_vpart_type_vals[] = {
294 { VP_ATN_EC_16, "ATN extended checksum - 16 bit" },
295 { VP_ATN_EC_32, "ATN extended checksum - 32 bit" },
296 { VP_ACK_TIME, "ack time" },
297 { VP_RES_ERROR, "res error" },
298 { VP_PRIORITY, "priority" },
299 { VP_TRANSIT_DEL, "transit delay" },
300 { VP_THROUGHPUT, "throughput" },
301 { VP_SEQ_NR, "seq number" },
302 { VP_REASSIGNMENT, "reassignment" },
303 { VP_FLOW_CNTL, "flow control" },
304 { VP_TPDU_SIZE, "tpdu-size" },
305 { VP_SRC_TSAP, "src-tsap" },
306 { VP_DST_TSAP, "dst-tsap" },
307 { VP_CHECKSUM, "checksum" },
308 { VP_VERSION_NR, "version" },
309 { VP_PROTECTION, "protection" },
310 { VP_OPT_SEL, "options" },
311 { VP_PROTO_CLASS, "proto class" },
312 { VP_CLEARING_INFO, "additional connection clearing info" },
313 { VP_PREF_MAX_TPDU_SIZE, "preferred max TPDU size" },
314 { VP_INACTIVITY_TIMER, "inactivity timer" },
318 static int hf_cotp_vp_src_tsap = -1;
319 static int hf_cotp_vp_dst_tsap = -1;
320 static int hf_cotp_vp_src_tsap_bytes = -1;
321 static int hf_cotp_vp_dst_tsap_bytes = -1;
323 /* global variables */
325 /* List of dissectors to call for the variable part of CR PDUs. */
326 static heur_dissector_list_t cotp_cr_heur_subdissector_list;
327 /* List of dissectors to call for the variable part of CC PDUs. */
328 static heur_dissector_list_t cotp_cc_heur_subdissector_list;
329 /* List of dissectors to call for COTP packets put atop the Inactive
331 static heur_dissector_list_t cotp_is_heur_subdissector_list;
332 /* List of dissectors to call for COTP packets put atop CLNP */
333 static heur_dissector_list_t cotp_heur_subdissector_list;
334 /* List of dissectors to call for CLTP packets put atop CLNP */
335 static heur_dissector_list_t cltp_heur_subdissector_list;
338 * Reassembly of COTP.
340 static reassembly_table cotp_reassembly_table;
341 static guint16 cotp_dst_ref = 0;
342 static gboolean cotp_frame_reset = FALSE;
343 static gboolean cotp_last_fragment = FALSE;
345 #define TSAP_DISPLAY_AUTO 0
346 #define TSAP_DISPLAY_STRING 1
347 #define TSAP_DISPLAY_BYTES 2
350 static gboolean cotp_reassemble = TRUE;
351 static gint32 tsap_display = TSAP_DISPLAY_AUTO;
352 static gboolean cotp_decode_atn = FALSE;
354 static const enum_val_t tsap_display_options[] = {
355 {"auto", "As strings if printable", TSAP_DISPLAY_AUTO},
356 {"string", "As strings", TSAP_DISPLAY_STRING},
357 {"bytes", "As bytes", TSAP_DISPLAY_BYTES},
361 /* function definitions */
363 #define MAX_TSAP_LEN 32
365 static void cotp_frame_end(void)
367 if (!cotp_last_fragment) {
368 /* Last COTP in frame is not fragmented.
369 * No need for incrementing the dst_ref, so we decrement it here.
373 cotp_frame_reset = TRUE;
376 static gchar *print_tsap(tvbuff_t *tvb, int offset, int length)
378 const guchar *tsap = tvb_get_ptr(tvb, offset, length);
380 gboolean allprintable;
381 gint idx = 0, returned_length;
383 cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_TSAP_LEN * 2 + 3);
385 if (length <= 0 || length > MAX_TSAP_LEN)
386 g_snprintf(cur, MAX_TSAP_LEN * 2 + 3, "<unsupported TSAP length>");
388 allprintable = tvb_ascii_isprint(tvb, offset, length);
390 returned_length = g_snprintf(cur, MAX_TSAP_LEN * 2 + 3, "0x");
391 idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - 1);
393 while (length != 0) {
395 returned_length = g_snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
397 idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
399 returned_length = g_snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
401 idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
410 static const true_false_string tfs_vp_opt_sel_class1_use = { "Receipt confirmation", "explicit AK variant" };
412 static gboolean ositp_decode_var_part(tvbuff_t *tvb, int offset, int vp_length,
413 int class_option, int tpdu_len,
414 packet_info *pinfo, proto_tree *tree)
419 guint32 offset_iso8073_checksum = 0;
423 guint32 pref_max_tpdu_size;
424 proto_item *hidden_item;
426 while (vp_length != 0) {
427 code = tvb_get_guint8(tvb, offset);
428 proto_tree_add_item(tree, hf_cotp_parameter_code, tvb, offset, 1, ENC_NA);
434 length = tvb_get_guint8(tvb, offset);
435 proto_tree_add_item(tree, hf_cotp_parameter_length, tvb, offset, 1, ENC_NA);
441 case VP_ATN_EC_16 : /* ATN */
442 if (cotp_decode_atn) {
444 /* if an alternate OSI checksum is present in the currently unprocessed
445 * VP section to the checksum algorithm has to know.
446 * this may be the case for backward compatible CR TPDU */
447 if (!offset_iso8073_checksum) {
448 /* search following parameters in VP part for ISO checksum */
449 for (i = offset + length; i < vp_length;) {
450 tmp_code = tvb_get_guint8(tvb, i++);
451 tmp_len = tvb_get_guint8(tvb, i++);
452 if (tmp_code == VP_CHECKSUM) {
453 offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
459 sum = check_atn_ec_16(tvb, tpdu_len , offset,
460 offset_iso8073_checksum,
461 pinfo->dst.len, (const guint8 *)pinfo->dst.data,
462 pinfo->src.len, (const guint8 *)pinfo->src.data);
463 proto_tree_add_checksum(tree, tvb, offset, hf_cotp_atn_extended_checksum16, hf_cotp_atn_extended_checksum_status, &ei_cotp_atn_extended_checksum,
464 pinfo, sum, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_ZERO);
466 proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
472 case VP_ATN_EC_32 : /* ATN */
473 if (cotp_decode_atn) {
475 /* if an alternate OSI checksum is present in the currently unprocessed
476 * VP section the checksum algorithm has to know.
477 * this may be the case for backward compatible CR TPDU */
478 if (!offset_iso8073_checksum) {
479 /* search following parameters in VP part for ISO checksum */
480 for (i = offset + length; i < vp_length;) {
481 tmp_code = tvb_get_guint8(tvb, i++);
482 tmp_len = tvb_get_guint8(tvb, i++);
483 if (tmp_code == VP_CHECKSUM) {
484 offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
490 sum = check_atn_ec_32(tvb, tpdu_len , offset,
491 offset_iso8073_checksum,
492 pinfo->dst.len, (const guint8 *)pinfo->dst.data,
493 pinfo->src.len, (const guint8 *)pinfo->src.data);
494 proto_tree_add_checksum(tree, tvb, offset, hf_cotp_atn_extended_checksum32, hf_cotp_atn_extended_checksum_status, &ei_cotp_atn_extended_checksum,
495 pinfo, sum, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_ZERO);
497 proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
504 proto_tree_add_item(tree, hf_cotp_ack_time, tvb, offset, length, ENC_BIG_ENDIAN);
510 s = tvb_get_guint8(tvb, offset);
511 proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_target_value, tvb, offset, 1, s, "10^%u", s);
515 s = tvb_get_guint8(tvb, offset);
516 proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_min_accept, tvb, offset, 1, s, "10^%u", s);
520 s = tvb_get_guint8(tvb, offset);
521 proto_tree_add_uint_format_value(tree, hf_cotp_res_error_rate_tdsu, tvb, offset, 1, s, "2^%u", s);
527 proto_tree_add_item(tree, hf_cotp_vp_priority, tvb, offset, 2, ENC_BIG_ENDIAN);
533 proto_tree_add_item(tree, hf_cotp_transit_delay_targ_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
537 proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_calling_called, tvb, offset, 2, ENC_BIG_ENDIAN);
541 proto_tree_add_item(tree, hf_cotp_transit_delay_targ_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
545 proto_tree_add_item(tree, hf_cotp_transit_delay_max_accept_called_calling, tvb, offset, 2, ENC_BIG_ENDIAN);
551 proto_tree_add_item(tree, hf_cotp_max_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
556 proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
561 proto_tree_add_item(tree, hf_cotp_max_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
566 proto_tree_add_item(tree, hf_cotp_max_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
571 if (length != 0) { /* XXX - should be 0 or 12 */
572 proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
576 proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_calling_called, tvb, offset, 3, ENC_BIG_ENDIAN);
580 proto_tree_add_item(tree, hf_cotp_avg_throughput_targ_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
584 proto_tree_add_item(tree, hf_cotp_avg_throughput_min_accept_called_calling, tvb, offset, 3, ENC_BIG_ENDIAN);
591 proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
596 case VP_REASSIGNMENT:
597 proto_tree_add_item(tree, hf_cotp_reassignment_time, tvb, offset, 2, ENC_BIG_ENDIAN);
603 proto_tree_add_item(tree, hf_cotp_lower_window_edge, tvb, offset, 4, ENC_BIG_ENDIAN);
607 proto_tree_add_item(tree, hf_cotp_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN);
611 proto_tree_add_item(tree, hf_cotp_credit, tvb, offset, 2, ENC_BIG_ENDIAN);
618 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
619 proto_tree_add_uint(tree, hf_cotp_tpdu_size, tvb, offset, 1, 1 << c1);
625 /* if our preference is set to STRING or the TSAP is not printable,
626 * add as bytes and hidden as string; otherwise vice-versa */
627 if (tsap_display==TSAP_DISPLAY_STRING ||
628 (tsap_display==TSAP_DISPLAY_AUTO &&
629 tvb_ascii_isprint(tvb, offset, length))) {
630 proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
631 print_tsap(tvb, offset, length));
632 hidden_item = proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb,
633 offset, length, ENC_NA);
634 proto_item_set_hidden(hidden_item);
636 hidden_item = proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb,
638 print_tsap(tvb, offset, length));
639 proto_item_set_hidden(hidden_item);
640 proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset,
648 /* if our preference is set to STRING or the TSAP is not printable,
649 * add as bytes and hidden as string; otherwise vice-versa */
650 if (tsap_display==TSAP_DISPLAY_STRING ||
651 (tsap_display==TSAP_DISPLAY_AUTO &&
652 tvb_ascii_isprint(tvb, offset, length))) {
653 proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
654 print_tsap(tvb, offset, length));
655 hidden_item = proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb,
656 offset, length, ENC_NA);
657 proto_item_set_hidden(hidden_item);
659 hidden_item = proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb,
661 print_tsap(tvb, offset, length));
662 proto_item_set_hidden(hidden_item);
663 proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset,
671 offset_iso8073_checksum = offset; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
673 if (tvb_get_ntohs(tvb, offset) == 0) {
674 /* No checksum present */
675 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);
677 guint32 calc_c0 = 0, calc_c1 = 0;
679 if (osi_calc_checksum(tvb, 0, length, &calc_c0, &calc_c1)) {
680 /* Successfully processed checksum, verify it */
681 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);
683 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);
692 proto_tree_add_item(tree, hf_cotp_vp_version_nr, tvb, offset, 1, ENC_NA);
698 switch (class_option) {
701 proto_tree_add_item(tree, hf_cotp_network_expedited_data, tvb, offset, 1, ENC_NA);
703 proto_tree_add_item(tree, hf_cotp_vp_opt_sel_class1_use, tvb, offset, 1, ENC_NA);
707 proto_tree_add_item(tree, hf_cotp_use_16_bit_checksum, tvb, offset, 1, ENC_NA);
711 proto_tree_add_item(tree, hf_cotp_transport_expedited_data_transfer, tvb, offset, 1, ENC_NA);
716 case VP_PREF_MAX_TPDU_SIZE:
720 pref_max_tpdu_size = tvb_get_guint8(tvb, offset);
724 pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
728 pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
732 pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
736 proto_tree_add_expert_format(tree, pinfo, &ei_cotp_preferred_maximum_tpdu_size, tvb, offset, length,
737 "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)", length);
740 proto_tree_add_uint(tree, hf_cotp_preferred_maximum_tpdu_size, tvb, offset, length, pref_max_tpdu_size*128);
745 case VP_INACTIVITY_TIMER:
746 proto_tree_add_item(tree, hf_cotp_inactivity_timer, tvb, offset, length, ENC_BIG_ENDIAN);
751 case VP_PROTECTION: /* user-defined */
752 case VP_PROTO_CLASS: /* todo */
753 case VP_CLEARING_INFO: /* user-defined */
754 default: /* unknown, no decoding */
755 proto_tree_add_bytes_format_value(tree, hf_cotp_parameter_value, tvb, offset, length, NULL, "<not shown>");
765 static const value_string cotp_cause_vals[] = {
766 { 0, "Reason not specified" },
767 { 1, "Congestion at TSAP" },
768 { 2, "Session entity not attached to TSAP" },
769 { 3, "Address unknown" },
770 { 128+0, "Normal Disconnect" },
771 { 128+1, "Remote transport entity congestion" },
772 { 128+2, "Connection negotiation failed" },
773 { 128+3, "Duplicate source reference" },
774 { 128+4, "Mismatched references" },
775 { 128+5, "Protocol error" },
776 { 128+7, "Reference overflow" },
777 { 128+8, "Connection request refused" },
778 { 128+10, "Header or parameter length invalid" },
782 static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
783 packet_info *pinfo, proto_tree *tree)
785 proto_tree *cotp_tree = NULL;
786 proto_item *ti = NULL;
787 guint16 dst_ref, src_ref;
791 /* ATN TPDU's tend to be larger than normal OSI,
792 * so nothing to do with respect to LI checks */
796 /* DR TPDUs can have user data, so they run to the end of the containing PDU */
797 tpdu_len = tvb_reported_length_remaining(tvb, offset);
799 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
801 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
803 reason = tvb_get_guint8(tvb, offset + P_REASON_IN_DR);
805 pinfo->clnp_dstref = dst_ref;
806 pinfo->clnp_srcref = src_ref;
808 /* the settings of the TCP srcport and destport are currently disabled,
809 * for the following reasons:
810 * a) only used for ISO conversation handling (which currently doesn't work)
811 * b) will prevent "ISO on TCP" (RFC1006) packets from using
812 * "follow TCP stream" correctly
814 * A future conversation handling might be able to handle different kinds of
815 * conversations (TCP, ISO, TCP on TCP, ...), but in that case this has to be
818 /*pinfo->srcport = src_ref;*/
819 /*pinfo->destport = dst_ref;*/
820 if (try_val_to_str(reason, cotp_cause_vals) == NULL)
823 col_append_fstr(pinfo->cinfo, COL_INFO,
824 "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
827 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
828 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
829 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
830 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu);
831 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2,
833 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset + 4, 2,
835 proto_tree_add_item(cotp_tree, hf_cotp_cause, tvb, offset + 6, 1, ENC_NA);
841 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
844 expert_add_info_format(pinfo, ti, &ei_cotp_disconnect_request, "Disconnect Request(DR): 0x%x -> 0x%x", src_ref, dst_ref);
847 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
848 offset += tvb_captured_length_remaining(tvb, offset);
849 /* we dissected all of the containing PDU */
853 } /* ositp_decode_DR */
855 static int ositp_decode_DT(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
856 packet_info *pinfo, proto_tree *tree,
857 gboolean uses_inactive_subset,
858 gboolean *subdissector_found)
860 proto_tree *cotp_tree = NULL;
862 gboolean is_extended;
863 gboolean is_class_234;
865 guint32 *prev_dst_ref;
867 gboolean fragment = FALSE;
868 guint32 fragment_length = 0;
870 fragment_head *fd_head;
871 conversation_t *conv;
873 heur_dtbl_entry_t *hdtbl_entry;
875 /* DT TPDUs have user data, so they run to the end of the containing PDU */
876 tpdu_len = tvb_reported_length_remaining(tvb, offset);
878 /* The fixed part is 2 octets long, not including the length indicator,
879 for classes 0 and 1; it is at least 4 octets long, not including
880 the length indicator, for classes 2, 3, and 4. */
881 is_class_234 = (li > LI_NORMAL_DT_CLASS_01);
883 /* note: in the ATN the user is up to chose between 3 different checksums:
884 * standard OSI, 2 or 4 octet extended checksum.
885 * The differences for DT are that the TPDU headers may be enlarged by 2
886 * octets and that checksum related option codes and option lengths are
887 * different. To not mess up the original OSI dissector LI checking was
888 * implemented separately. */
889 if (!cotp_decode_atn) { /* non ATN, plain OSI*/
890 /* VP_CHECKSUM is the only parameter allowed in the variable part.
891 * (This means we may misdissect this if the packet is bad and
892 * contains other parameters.).
894 * XXX - not true; ISO/IEC 8073:1997 (E) says that "if the use of
895 * non-blocking expedited data transfer service is negotiated (class
896 * 4 only), the variable part shall contain the ED-TPDU-NR for the
897 * first DT-TPDU created from a T-DATA request subsequent to the
898 * T-EXPEDITED DATA request". */
901 case LI_NORMAL_DT_WITH_CHECKSUM :
902 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
906 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
907 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
909 tpdu_nr = tpdu_nr & 0x7F;
913 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
916 case LI_EXTENDED_DT_WITH_CHECKSUM :
917 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
921 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
922 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
923 if (tpdu_nr & 0x80000000)
924 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
928 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
931 case LI_NORMAL_DT_CLASS_01 :
932 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
934 tpdu_nr = tpdu_nr & 0x7F;
938 prev_dst_ref = (guint32 *)p_get_proto_data(wmem_file_scope(), pinfo, proto_clnp, 0);
940 /* First COTP in frame - save previous dst_ref as offset */
941 prev_dst_ref = wmem_new(wmem_file_scope(), guint32);
942 *prev_dst_ref = cotp_dst_ref;
943 p_add_proto_data(wmem_file_scope(), pinfo, proto_clnp, 0, prev_dst_ref);
944 } else if (cotp_frame_reset) {
945 cotp_dst_ref = *prev_dst_ref;
947 cotp_frame_reset = FALSE;
948 cotp_last_fragment = fragment;
949 dst_ref = cotp_dst_ref;
950 conv = find_conversation_pinfo(pinfo, 0);
952 /* Found a conversation, also use index for the generated dst_ref */
953 dst_ref += (conv->conv_index << 16);
957 register_frame_end_routine(pinfo, cotp_frame_end);
961 default : /* bad TPDU */
965 /* check ATN class4 TPDU's here */
967 /* check packet length indicators of DaTa(DT) TPDU
968 * note: use of checksum depends on the selected RER
969 * (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
971 * note: sole use of TP4 class in the ATN
972 * note: normal/extended TPDU numbering is negociable */
975 /* normal DT with 2 octets of OSI or of ATN Extended Checksum */
976 case LI_NORMAL_DT_WITH_CHECKSUM :
977 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM &&
978 tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16)
982 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
983 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
985 tpdu_nr = tpdu_nr & 0x7F;
989 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
992 /* extended DT with 2 octets of OSI or of ATN Extended Checksum */
993 case LI_EXTENDED_DT_WITH_CHECKSUM :
994 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM &&
995 tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16)
999 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1000 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1001 if (tpdu_nr & 0x80000000)
1002 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1006 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1009 /* normal DT with ATN Extended Checksum (4 octets)*/
1010 case LI_ATN_NORMAL_DT_WITH_CHECKSUM :
1011 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1014 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1017 tpdu_nr = tpdu_nr & 0x7F;
1020 is_extended = FALSE;
1021 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1024 /* extended DT with 4 octets ATN Extended Checksum */
1025 case LI_ATN_EXTENDED_DT_WITH_CHECKSUM:
1026 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1029 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1030 if (tpdu_nr & 0x80000000)
1031 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1035 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1038 default : /* bad TPDU */
1041 } /* cotp_decode_atn */
1043 pinfo->clnp_dstref = dst_ref;
1045 pinfo->fragmented = fragment;
1047 col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x",
1050 col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u)", tpdu_nr);
1054 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1055 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1056 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1061 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1068 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1072 ti = proto_tree_add_uint (cotp_tree, hf_cotp_destref, tvb, offset, 0,
1074 proto_item_set_generated (ti);
1079 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1081 proto_tree_add_item(cotp_tree, hf_cotp_eot_extended, tvb, offset, 4,
1088 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1090 proto_tree_add_item(cotp_tree, hf_cotp_eot, tvb, offset, 1,
1098 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1101 next_tvb = tvb_new_subset_remaining(tvb, offset);
1102 fragment_length = tvb_captured_length(next_tvb);
1104 col_append_fstr(pinfo->cinfo, COL_INFO, " [COTP fragment, %u byte%s]",
1105 fragment_length, plurality(fragment_length, "", "s"));
1107 col_append_fstr(pinfo->cinfo, COL_INFO, " EOT");
1110 if (cotp_reassemble) {
1112 * XXX - these sequence numbers are connection sequence number,
1113 * not segment sequence numbers - the first segment of a
1114 * segmented packet doesn't have a specific sequence number (e.g., 0
1115 * or 1), it has whatever the appropriate sequence number is for
1116 * it in the connection.
1118 * For now, we assume segments arrive in order, and just supply
1119 * the negation of the EOT flag as the "more flags" argument.
1120 * We should probably handle out-of-order packets separately,
1121 * so that we can deliver them in order even when *not*
1124 * Note also that TP0 has no sequence number, and relies on
1125 * the protocol atop which it runs to guarantee in-order delivery.
1127 fd_head = fragment_add_seq_next(&cotp_reassembly_table, next_tvb, 0, pinfo,
1128 dst_ref, NULL, fragment_length, fragment);
1129 if (fd_head && fd_head->next) {
1130 /* don't use -1 if fragment length is zero (throws Exception) */
1131 proto_tree_add_bytes_format(cotp_tree, hf_cotp_segment_data, tvb, offset, (fragment_length) ? -1 : 0,
1132 NULL, "COTP segment data (%u byte%s)", fragment_length,
1133 plurality(fragment_length, "", "s"));
1136 /* This is the last packet */
1137 next_tvb = process_reassembled_data (next_tvb, offset, pinfo,
1138 "Reassembled COTP", fd_head,
1139 &cotp_frag_items, NULL, tree);
1140 } else if (pinfo->num != fd_head->reassembled_in) {
1141 /* Add a "Reassembled in" link if not reassembled in this frame */
1142 proto_tree_add_uint(cotp_tree, *(cotp_frag_items.hf_reassembled_in),
1143 next_tvb, 0, 0, fd_head->reassembled_in);
1145 pinfo->fragmented = fragment;
1149 if (uses_inactive_subset) {
1150 if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1151 pinfo, tree, &hdtbl_entry, NULL)) {
1152 *subdissector_found = TRUE;
1154 /* Fill in other Dissectors using inactive subset here */
1155 call_data_dissector(next_tvb, pinfo, tree);
1159 * We dissect payload if one of the following is TRUE:
1161 * - Reassembly option for COTP in preferences is unchecked
1162 * - Reassembly option is checked and this packet is the last fragment
1164 if ((!cotp_reassemble) || ((cotp_reassemble) && (!fragment))) {
1165 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1166 tree, &hdtbl_entry, NULL)) {
1167 *subdissector_found = TRUE;
1169 call_data_dissector(next_tvb, pinfo, tree);
1174 offset += tvb_captured_length_remaining(tvb, offset);
1175 /* we dissected all of the containing PDU */
1179 } /* ositp_decode_DT */
1181 static int ositp_decode_ED(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1182 packet_info *pinfo, proto_tree *tree)
1184 proto_tree *cotp_tree = NULL;
1186 gboolean is_extended;
1192 /* ED TPDUs have user data, so they run to the end of the containing PDU */
1193 tpdu_len = tvb_reported_length_remaining(tvb, offset);
1195 /* note: in the ATN the user is up to chose between 3 different checksums:
1196 * standard OSI, 2 or 4 octet extended checksum.
1197 * The differences for ED (as for DT) are that the TPDU headers may be
1198 * enlarged by 2 octets and that checksum related option codes and option
1199 * lengths are different. To not mess up the original OSI dissector LI
1200 * checking was implemented separately.
1202 * note: this could not be tested, because no sample was avail for expedited
1204 if (!cotp_decode_atn) { /* non ATN, plain OSI*/
1205 /* ED TPDUs are never fragmented */
1207 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1208 (This means we may misdissect this if the packet is bad and
1209 contains other parameters.) */
1212 case LI_NORMAL_DT_WITH_CHECKSUM :
1213 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1217 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
1218 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1220 tpdu_nr = tpdu_nr & 0x7F;
1223 is_extended = FALSE;
1226 case LI_EXTENDED_DT_WITH_CHECKSUM :
1227 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1231 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1232 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1233 if (tpdu_nr & 0x80000000)
1234 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1240 default : /* bad TPDU */
1244 /* check packet length indicators of ATN Expedited Data (ED) TPDU
1245 * note: use of checksum depends on the selected RER
1246 * (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
1248 * note: sole use of TP4 class in the ATN
1249 * note: normal/extended TPDU numbering is negociable */
1252 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
1253 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1255 tpdu_nr = tpdu_nr & 0x7F;
1258 is_extended = FALSE;
1261 case LI_NORMAL_DT_WITH_CHECKSUM :
1262 if ((tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
1263 (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16))
1266 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1268 tpdu_nr = tpdu_nr & 0x7F;
1271 is_extended = FALSE;
1274 case LI_ATN_NORMAL_DT_WITH_CHECKSUM :
1275 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1278 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1280 tpdu_nr = tpdu_nr & 0x7F;
1283 is_extended = FALSE;
1286 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1287 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1288 if (tpdu_nr & 0x80000000)
1289 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1295 case LI_EXTENDED_DT_WITH_CHECKSUM :
1296 if ((tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM) &&
1297 (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16))
1300 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1301 if (tpdu_nr & 0x80000000)
1302 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1308 case LI_ATN_EXTENDED_DT_WITH_CHECKSUM :
1309 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1312 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1313 if (tpdu_nr & 0x80000000)
1314 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1320 default : /* bad TPDU */
1323 } /* cotp_decode_atn */
1325 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1326 pinfo->clnp_dstref = dst_ref;
1328 col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
1332 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1333 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1334 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1339 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1345 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1351 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1358 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1366 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1370 * XXX - hand this to subdissectors but tell them that this is
1373 next_tvb = tvb_new_subset_remaining(tvb, offset);
1374 call_data_dissector(next_tvb, pinfo, tree);
1376 offset += tvb_captured_length_remaining(tvb, offset);
1377 /* we dissected all of the containing PDU */
1381 } /* ositp_decode_ED */
1383 static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1384 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1386 proto_tree *cotp_tree;
1388 proto_item *item = NULL;
1393 /* note: in the ATN the user is up to chose between 3 different checksums:
1394 * standard OSI, 2 or 4 octet extended checksum.
1395 * The difference for RJ is that the TPDU header may be enlarged by 2 octets
1396 * for checksum parameters are not going to be checked here */
1397 if (!cotp_decode_atn) { /* non ATN, plain OSI */
1400 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1402 case LI_EXTENDED_RJ :
1403 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1404 credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1411 /* normal with 2 octets of OSI or ATN checksum */
1413 /* with 4 octets of ATN checksum */
1414 case LI_ATN_NORMAL_RJ :
1415 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1417 /* extended with 2 octets of OSI or ATN checksum */
1418 case LI_EXTENDED_RJ :
1419 /* with 4 octets of ATN checksum */
1420 case LI_ATN_EXTENDED_RJ :
1421 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1422 credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1429 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1430 pinfo->clnp_dstref = dst_ref;
1432 col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
1436 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1437 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1438 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1439 item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset + 1, 1,
1441 if (li == LI_NORMAL_RJ) {
1442 proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset + 1, 1, cdt);
1444 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2,
1446 if (li == LI_NORMAL_RJ)
1447 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset + 4,
1450 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1451 offset + 4, 4, tpdu_nr);
1452 proto_tree_add_uint(cotp_tree, hf_cotp_credit, tvb, offset + 8, 2, credit);
1458 expert_add_info_format(pinfo, item, &ei_cotp_reject, "Reject(RJ): -> 0x%x", dst_ref);
1462 } /* ositp_decode_RJ */
1464 static int ositp_decode_CR_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1465 packet_info *pinfo, proto_tree *tree,
1466 gboolean uses_inactive_subset,
1467 gboolean *subdissector_found)
1469 /* note: in the ATN the user is up to chose between 3 different checksums:
1470 * standard OSI, 2 or 4 octet extended checksum.
1471 * Nothing has to be done here, for all ATN specifics are handled in VP. */
1473 /* CC & CR decoding in the same function */
1475 proto_tree *cotp_tree = NULL;
1477 proto_item *item = NULL;
1478 guint16 dst_ref, src_ref;
1479 guint8 class_option;
1482 heur_dtbl_entry_t *hdtbl_entry;
1483 static const int * class_options[] = {
1485 &hf_cotp_opts_extended_formats,
1486 &hf_cotp_opts_no_explicit_flow_control,
1490 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1492 class_option = tvb_get_guint8(tvb, offset + P_CLASS_OPTION);
1493 if (((class_option & 0xF0) >> 4) > 4) /* class 0..4 allowed */
1496 /* CR and CC TPDUs can have user data, so they run to the end of the
1498 tpdu_len = tvb_reported_length_remaining(tvb, offset);
1500 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1501 pinfo->clnp_srcref = src_ref;
1502 pinfo->clnp_dstref = dst_ref;
1504 col_append_fstr(pinfo->cinfo, COL_INFO,
1505 "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1506 (tpdu == CR_TPDU) ? "CR" : "CC", src_ref, dst_ref);
1508 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1509 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1510 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1513 item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1517 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1521 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1525 /* expert info, but only if not encapsulated in TCP/SMB */
1526 /* XXX - the best way to detect seems to be if we have a port set */
1527 if (pinfo->destport == 0) {
1528 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);
1531 proto_tree_add_bitmask_list(cotp_tree, tvb, offset, 1, class_options, ENC_NA);
1536 /* There's more data left, so we have the variable part.
1538 Microsoft's RDP hijacks the variable part of CR and CC PDUs
1539 for their own user data (RDP runs atop Class 0, which doesn't
1542 Try what heuristic dissectors we have. */
1543 next_tvb = tvb_new_subset_length(tvb, offset, li);
1544 if (dissector_try_heuristic((tpdu == CR_TPDU) ?
1545 cotp_cr_heur_subdissector_list :
1546 cotp_cc_heur_subdissector_list,
1547 next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
1548 /* A subdissector claimed this, so it really belongs to them. */
1549 *subdissector_found = TRUE;
1551 /* No heuristic dissector claimed it, so dissect it as a regular
1553 ositp_decode_var_part(tvb, offset, li, class_option, tpdu_len, pinfo,
1560 * XXX - tell the subdissector that this is user data in a CR or
1561 * CC packet rather than a DT packet?
1563 if (tvb_captured_length_remaining(tvb, offset)) {
1564 next_tvb = tvb_new_subset_remaining(tvb, offset);
1565 if (!uses_inactive_subset){
1566 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1567 tree, &hdtbl_entry, NULL)) {
1568 *subdissector_found = TRUE;
1570 call_data_dissector(next_tvb, pinfo, tree);
1574 call_data_dissector( next_tvb, pinfo, tree);
1575 offset += tvb_captured_length_remaining(tvb, offset);
1576 /* we dissected all of the containing PDU */
1581 } /* ositp_decode_CR_CC */
1583 static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1584 packet_info *pinfo, proto_tree *tree)
1586 proto_tree *cotp_tree = NULL;
1588 proto_item *item = NULL;
1589 guint16 dst_ref, src_ref;
1592 /* ATN may use checksums different from OSI */
1593 /* which may result in different TPDU header length. */
1594 if (!cotp_decode_atn) {
1598 if (li > LI_ATN_MAX_DC)
1602 /* DC TPDUs have no user data, so the length indicator determines the
1606 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1607 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1608 pinfo->clnp_dstref = dst_ref;
1609 pinfo->clnp_srcref = src_ref;
1611 col_append_fstr(pinfo->cinfo, COL_INFO,
1612 "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
1615 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1616 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1617 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1622 item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1628 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1633 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1638 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1641 expert_add_info_format(pinfo, item, &ei_cotp_disconnect_confirm, "Disconnect Confirm(DC): 0x%x -> 0x%x", src_ref, dst_ref);
1645 } /* ositp_decode_DC */
1647 static int ositp_decode_AK(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1648 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1650 proto_tree *cotp_tree = NULL;
1657 if (!cotp_decode_atn) {
1661 if (li > LI_ATN_MAX_AK)
1665 /* AK TPDUs have no user data, so the length indicator determines the
1669 /* is_LI_NORMAL_AK() works for normal ATN AK's, */
1670 /* for the TPDU header size may be enlarged by 2 octets */
1671 if (is_LI_NORMAL_AK(li)) {
1673 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1674 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1675 pinfo->clnp_dstref = dst_ref;
1677 col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1681 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1682 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1683 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1688 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1689 proto_tree_add_uint(cotp_tree, hf_cotp_credit_cdt, tvb, offset, 1, cdt);
1695 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1700 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1707 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1710 } else { /* extended format */
1712 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1713 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1714 cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1715 pinfo->clnp_dstref = dst_ref;
1717 col_append_fstr(pinfo->cinfo, COL_INFO,
1718 "AK TPDU (%u) dst-ref: 0x%04x Credit: %u",
1719 tpdu_nr, dst_ref, cdt_in_ak);
1722 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1723 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1724 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1729 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1735 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1740 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1741 offset, 4, tpdu_nr);
1747 proto_tree_add_uint(cotp_tree, hf_cotp_credit, tvb, offset, 2, cdt_in_ak);
1753 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1756 } /* is_LI_NORMAL_AK */
1760 } /* ositp_decode_AK */
1762 static int ositp_decode_EA(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1763 packet_info *pinfo, proto_tree *tree)
1765 proto_tree *cotp_tree = NULL;
1767 gboolean is_extended;
1772 /* Due to different checksums in the ATN the TPDU header sizes
1773 * as well as the checksum parameters may be different than plain OSI EA
1774 * because these are heavily checked for EA these checks had to be
1776 * note: this could not be tested, because no sample was avail for expedited
1778 if (!cotp_decode_atn) {
1782 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1783 (This means we may misdissect this if the packet is bad and
1784 contains other parameters.) */
1787 case LI_NORMAL_EA_WITH_CHECKSUM :
1788 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
1789 tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1793 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1794 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1795 is_extended = FALSE;
1798 case LI_EXTENDED_EA_WITH_CHECKSUM :
1799 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
1800 tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1804 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1805 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1809 default : /* bad TPDU */
1812 } else { /* cotp_decode_atn */
1813 /* check for ATN length: TPDU may be 2 octets longer due to checksum */
1814 if (li > LI_ATN_MAX_EA)
1819 /* extended TPDU numbering EA with no checksum */
1820 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1821 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1822 is_extended = FALSE;
1825 /* normal TPDU numbering EA with 2 octets of OSI or ATN extended
1827 case LI_NORMAL_EA_WITH_CHECKSUM :
1828 /* check checksum parameter (in VP) parameter code octet */
1829 if ((tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
1830 (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16))
1833 /* check checksum parameter (in VP) length octet */
1834 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1837 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1838 is_extended = FALSE;
1841 /* normal TPDU numbering EA with 4 octets of ATN extended checksum */
1842 case LI_ATN_NORMAL_EA_WITH_CHECKSUM :
1843 /* check checksum parameter (in VP) parameter code octet */
1844 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1847 /* check checksum parameter (in VP) length octet */
1848 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 4)
1851 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1852 is_extended = FALSE;
1855 /* extended TPDU numbering EA with no checksum */
1856 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1857 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1861 /* extended TPDU numbering EA with 2 octets of OSI or ATN extended
1863 case LI_EXTENDED_EA_WITH_CHECKSUM :
1864 /* check checksum parameter (in VP) parameter code octet */
1865 if ((tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM) &&
1866 (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16))
1869 /* check checksum parameter (in VP) length octet */
1870 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1873 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1877 /* extended EA with 4 octets ATN extended checksum */
1878 case LI_ATN_EXTENDED_EA_WITH_CHECKSUM :
1879 /* check checksum parameter (in VP) parameter code octet */
1880 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1883 /* check checksum parameter (in VP) length octet */
1884 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1887 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1891 default : /* bad TPDU */
1896 /* ER TPDUs have no user data, so the length indicator determines the
1900 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1901 pinfo->clnp_dstref = dst_ref;
1903 col_append_fstr(pinfo->cinfo, COL_INFO, "EA TPDU (%u) dst-ref: 0x%04x",
1907 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1908 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1909 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1914 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1920 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1926 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1927 offset, 4, tpdu_nr);
1933 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1941 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1946 } /* ositp_decode_EA */
1948 static const value_string cotp_reject_vals[] = {
1949 { 0, "Reason not specified" },
1950 { 1, "Invalid parameter code" },
1951 { 2, "Invalid TPDU type" },
1952 { 3, "Invalid parameter value" },
1956 static int ositp_decode_ER(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1957 packet_info *pinfo, proto_tree *tree)
1959 proto_tree *cotp_tree = NULL;
1964 /* ATN: except for modified LI checking nothing to be done here */
1965 if (!cotp_decode_atn) {
1969 if (li > LI_ATN_MAX_ER)
1973 /* ER TPDUs have no user data, so the length indicator determines the
1977 if(try_val_to_str(tvb_get_guint8(tvb, offset + P_REJECT_ER), cotp_reject_vals) == NULL)
1980 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1981 pinfo->clnp_dstref = dst_ref;
1983 col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1986 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1987 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1988 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1989 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu);
1990 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2,
1992 proto_tree_add_item(cotp_tree, hf_cotp_reject_cause, tvb, offset + 4, 1, ENC_NA);
1998 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
2003 } /* ositp_decode_ER */
2005 static int ositp_decode_UD(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
2006 packet_info *pinfo, proto_tree *tree,
2007 gboolean *subdissector_found)
2010 proto_tree *cltp_tree = NULL;
2013 heur_dtbl_entry_t *hdtbl_entry;
2015 /* UD TPDUs have user data, so they run to the end of the containing PDU */
2016 tpdu_len = tvb_reported_length_remaining(tvb, offset);
2018 col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
2021 ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, ENC_NA);
2022 cltp_tree = proto_item_add_subtree(ti, ett_cltp);
2023 proto_tree_add_uint(cltp_tree, hf_cltp_li, tvb, offset, 1,li);
2028 proto_tree_add_uint(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu);
2034 ositp_decode_var_part(tvb, offset, li, 0, tpdu_len, pinfo, cltp_tree);
2037 next_tvb = tvb_new_subset_remaining(tvb, offset);
2039 if (dissector_try_heuristic(cltp_heur_subdissector_list, next_tvb,
2040 pinfo, tree, &hdtbl_entry, NULL)) {
2041 *subdissector_found = TRUE;
2043 call_data_dissector(next_tvb, pinfo, tree);
2047 /*call_data_dissector(next_tvb, pinfo, tree); */
2049 offset += tvb_captured_length_remaining(tvb, offset);
2050 /* we dissected all of the containing PDU */
2054 } /* ositp_decode_UD */
2056 /* Returns the offset past the last valid COTP or CLTP PDU if we found
2057 at least one valid COTP or CLTP PDU, 0 otherwise.
2059 There doesn't seem to be any way in which the OSI network layer protocol
2060 distinguishes between COTP and CLTP, but the first two octets of both
2061 protocols' headers mean the same thing - length and PDU type - and the
2062 only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
2063 both of them here. */
2064 static gint dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
2066 gboolean uses_inactive_subset)
2069 guint8 li, tpdu, cdt;
2070 gboolean first_tpdu = TRUE;
2072 gboolean found_ositp = FALSE;
2073 gboolean is_cltp = FALSE;
2074 gboolean subdissector_found = FALSE;
2076 /* Initialize the COL_INFO field; each of the TPDUs will have its
2077 information appended. */
2078 col_set_str(pinfo->cinfo, COL_INFO, "");
2080 while (tvb_offset_exists(tvb, offset)) {
2082 col_append_str(pinfo->cinfo, COL_INFO, ", ");
2083 expert_add_info(pinfo, NULL, &ei_cotp_multiple_tpdus);
2084 /* adjust tvb and offset to the start of the current PDU */
2085 tvb = tvb_new_subset_remaining(tvb, offset);
2088 if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
2089 col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
2091 call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2096 tpdu = (tvb_get_guint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
2097 if (tpdu == UD_TPDU)
2098 pinfo->current_proto = "CLTP"; /* connectionless transport */
2099 cdt = tvb_get_guint8(tvb, offset + P_CDT) & 0x0F;
2104 new_offset = ositp_decode_CR_CC(tvb, offset, li, tpdu, pinfo, tree,
2105 uses_inactive_subset, &subdissector_found);
2108 new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
2111 new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
2112 uses_inactive_subset, &subdissector_found);
2115 new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree);
2118 new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
2121 new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
2124 new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
2127 new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
2130 new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
2133 new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree,
2134 &subdissector_found);
2139 col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)",
2141 new_offset = -1; /* bad PDU type */
2145 if (new_offset == -1) { /* incorrect TPDU */
2147 call_data_dissector( tvb_new_subset_remaining(tvb, offset),
2153 /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
2154 is either COTP or CLTP. */
2155 if (!subdissector_found)
2156 col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
2160 offset = new_offset;
2163 return found_ositp ? offset : 0;
2164 } /* dissect_ositp_internal */
2166 static gint dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2169 return dissect_ositp_internal(tvb, pinfo, tree, FALSE);
2172 static gint dissect_ositp_inactive(tvbuff_t *tvb, packet_info *pinfo,
2173 proto_tree *tree, void *data _U_)
2175 return dissect_ositp_internal(tvb, pinfo, tree, TRUE);
2179 cotp_reassemble_init(void)
2184 void proto_register_cotp(void)
2186 static hf_register_info hf[] = {
2188 { "Length", "cotp.li", FT_UINT8, BASE_DEC,
2189 NULL, 0x0, "Length Indicator, length of this header", HFILL}},
2191 { "PDU Type", "cotp.type", FT_UINT8, BASE_HEX,
2192 VALS(cotp_tpdu_type_abbrev_vals), 0x0,
2193 "PDU Type - upper nibble of byte", HFILL}},
2195 { "Source reference", "cotp.srcref", FT_UINT16, BASE_HEX,
2196 NULL, 0x0, "Source address reference", HFILL}},
2198 { "Destination reference", "cotp.destref", FT_UINT16, BASE_HEX,
2199 NULL, 0x0, "Destination address reference", HFILL}},
2201 { "Class", "cotp.class", FT_UINT8, BASE_DEC, NULL,
2202 0xF0, "Transport protocol class", HFILL}},
2203 { &hf_cotp_opts_extended_formats,
2204 { "Extended formats", "cotp.opts.extended_formats", FT_BOOLEAN, 8,
2205 NULL, 0x02, "Use of extended formats in classes 2, 3, and 4", HFILL}},
2206 { &hf_cotp_opts_no_explicit_flow_control,
2207 { "No explicit flow control", "cotp.opts.no_explicit_flow_control",
2208 FT_BOOLEAN, 8, NULL, 0x01, "No explicit flow control in class 2",
2210 { &hf_cotp_tpdu_number,
2211 { "TPDU number", "cotp.tpdu-number", FT_UINT8, BASE_HEX,
2212 NULL, 0x7f, NULL, HFILL}},
2213 { &hf_cotp_tpdu_number_extended,
2214 { "TPDU number", "cotp.tpdu-number", FT_UINT32, BASE_HEX,
2215 NULL, 0x0 /* XXX - 0x7fff? */, NULL, HFILL}},
2216 { &hf_cotp_next_tpdu_number,
2217 { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT8, BASE_HEX,
2218 NULL, 0x0, NULL, HFILL}},
2219 { &hf_cotp_next_tpdu_number_extended,
2220 { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT32, BASE_HEX,
2221 NULL, 0x0, NULL, HFILL}},
2223 { "Last data unit", "cotp.eot", FT_BOOLEAN, 8,
2224 TFS(&tfs_yes_no), 0x80,
2225 "Is current TPDU the last data unit of a complete DT TPDU sequence "
2226 "(End of TSDU)?", HFILL}},
2227 { &hf_cotp_eot_extended,
2228 { "Last data unit", "cotp.eot", FT_BOOLEAN, 32,
2229 TFS(&tfs_yes_no), 0x80000000,
2230 "Is current TPDU the last data unit of a complete DT TPDU sequence "
2231 "(End of TSDU)?", HFILL}},
2232 { &hf_cotp_segment_overlap,
2233 { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN, BASE_NONE,
2234 NULL, 0x0, "Segment overlaps with other segments", HFILL }},
2235 { &hf_cotp_segment_overlap_conflict,
2236 { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict",
2237 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2238 "Overlapping segments contained conflicting data", HFILL }},
2239 { &hf_cotp_segment_multiple_tails,
2240 { "Multiple tail segments found", "cotp.segment.multipletails",
2241 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2242 "Several tails were found when reassembling the packet", HFILL }},
2243 { &hf_cotp_segment_too_long_segment,
2244 { "Segment too long", "cotp.segment.toolongsegment",
2245 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2246 "Segment contained data past end of packet", HFILL }},
2247 { &hf_cotp_segment_error,
2248 { "Reassembly error", "cotp.segment.error", FT_FRAMENUM, BASE_NONE,
2249 NULL, 0x0, "Reassembly error due to illegal segments", HFILL }},
2250 { &hf_cotp_segment_count,
2251 { "Segment count", "cotp.segment.count", FT_UINT32, BASE_DEC,
2252 NULL, 0x0, NULL, HFILL }},
2254 { "COTP Segment", "cotp.segment", FT_FRAMENUM, BASE_NONE,
2255 NULL, 0x0, NULL, HFILL }},
2256 { &hf_cotp_segments,
2257 { "COTP Segments", "cotp.segments", FT_NONE, BASE_NONE,
2258 NULL, 0x0, NULL, HFILL }},
2259 { &hf_cotp_reassembled_in,
2260 { "Reassembled COTP in frame", "cotp.reassembled_in",
2261 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2262 "This COTP packet is reassembled in this frame", HFILL }},
2263 { &hf_cotp_reassembled_length,
2264 { "Reassembled COTP length", "cotp.reassembled.length",
2265 FT_UINT32, BASE_DEC, NULL, 0x0,
2266 "The total length of the reassembled payload", HFILL }},
2267 /* ISO DP 8073 i13.3.4(a) Source and destination TSAPs are defined as
2268 identifiers of unspecified type and length.
2269 Some implementations of COTP use printable strings, others use raw bytes.
2270 We always add both representations to the tree; one will always be hidden
2271 depending on the tsap display preference */
2272 { &hf_cotp_vp_src_tsap,
2273 { "Source TSAP", "cotp.src-tsap", FT_STRING, BASE_NONE,
2274 NULL, 0x0, "Calling TSAP", HFILL }},
2275 { &hf_cotp_vp_src_tsap_bytes,
2276 { "Source TSAP", "cotp.src-tsap-bytes", FT_BYTES, BASE_NONE,
2277 NULL, 0x0, "Calling TSAP (bytes representation)", HFILL }},
2278 { &hf_cotp_vp_dst_tsap,
2279 { "Destination TSAP", "cotp.dst-tsap", FT_STRING, BASE_NONE,
2280 NULL, 0x0, "Called TSAP", HFILL }},
2281 { &hf_cotp_vp_dst_tsap_bytes,
2282 { "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES, BASE_NONE,
2283 NULL, 0x0, "Called TSAP (bytes representation)", HFILL }},
2284 /* Generated from convert_proto_tree_add_text.pl */
2285 { &hf_cotp_parameter_code, { "Parameter code", "cotp.parameter_code", FT_UINT8, BASE_HEX, VALS(tp_vpart_type_vals), 0x0, NULL, HFILL }},
2286 { &hf_cotp_parameter_length, { "Parameter length", "cotp.parameter_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2287 { &hf_cotp_parameter_value, { "Parameter value", "cotp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2288 { &hf_cotp_atn_extended_checksum16, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2289 { &hf_cotp_atn_extended_checksum32, { "ATN extended checksum", "cotp.atn_extended_checksum", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2290 { &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 }},
2291 { &hf_cotp_ack_time, { "Ack time (ms)", "cotp.ack_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2292 { &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 }},
2293 { &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 }},
2294 { &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 }},
2295 { &hf_cotp_vp_priority, { "Priority", "cotp.vp_priority", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2296 { &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 }},
2297 { &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 }},
2298 { &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 }},
2299 { &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 }},
2300 { &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 }},
2301 { &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 }},
2302 { &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 }},
2303 { &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 }},
2304 { &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 }},
2305 { &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 }},
2306 { &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 }},
2307 { &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 }},
2308 { &hf_cotp_sequence_number, { "Sequence number", "cotp.sequence_number", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2309 { &hf_cotp_reassignment_time, { "Reassignment time (secs)", "cotp.reassignment_time", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2310 { &hf_cotp_lower_window_edge, { "Lower window edge", "cotp.lower_window_edge", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2311 { &hf_cotp_credit, { "Credit", "cotp.credit", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2312 { &hf_cotp_tpdu_size, { "TPDU size", "cotp.tpdu_size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2313 { &hf_cotp_checksum, { "Checksum", "cotp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
2314 { &hf_cotp_checksum_status, { "Checksum Status", "cotp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
2315 { &hf_cotp_vp_version_nr, { "Version", "cotp.vp_version_nr", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2316 { &hf_cotp_network_expedited_data, { "Use of network expedited data", "cotp.network_expedited_data", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x08, NULL, HFILL }},
2317 { &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 }},
2318 { &hf_cotp_use_16_bit_checksum, { "16 bit checksum", "cotp.use_16_bit_checksum", FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x02, NULL, HFILL }},
2319 { &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 }},
2320 { &hf_cotp_preferred_maximum_tpdu_size, { "Preferred maximum TPDU size", "cotp.preferred_maximum_tpdu_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2321 { &hf_cotp_inactivity_timer, { "Inactivity timer (ms)", "cotp.inactivity_timer", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2322 { &hf_cotp_cause, { "Cause", "cotp.cause", FT_UINT8, BASE_DEC, VALS(cotp_cause_vals), 0x0, NULL, HFILL }},
2323 { &hf_cotp_segment_data, { "COTP segment data", "cotp.segment_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
2324 { &hf_cotp_credit_cdt, { "Credit", "cotp.credit", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
2325 { &hf_cotp_reject_cause, { "Reject cause", "cotp.reject_cause", FT_UINT8, BASE_DEC, VALS(cotp_reject_vals), 0x0, NULL, HFILL }},
2327 static gint *ett[] = {
2332 static ei_register_info ei[] = {
2333 { &ei_cotp_disconnect_request, { "cotp.disconnect_request", PI_SEQUENCE, PI_CHAT, "Disconnect Request(DR): 0x%x -> 0x%x", EXPFILL }},
2334 { &ei_cotp_reject, { "cotp.reject", PI_SEQUENCE, PI_NOTE, "Reject(RJ): -> 0x%x", EXPFILL }},
2335 { &ei_cotp_connection, { "cotp.connection", PI_SEQUENCE, PI_CHAT, "Connection %s: 0x%x -> 0x%x", EXPFILL }},
2336 { &ei_cotp_disconnect_confirm, { "cotp.disconnect_confirm", PI_SEQUENCE, PI_CHAT, "Disconnect Confirm(DC): 0x%x -> 0x%x", EXPFILL }},
2337 { &ei_cotp_multiple_tpdus, { "cotp.multiple_tpdus", PI_SEQUENCE, PI_NOTE, "Multiple TPDUs in one packet", EXPFILL }},
2338 { &ei_cotp_preferred_maximum_tpdu_size, { "cotp.preferred_maximum_tpdu_size.invalid", PI_PROTOCOL, PI_WARN, "Preferred maximum TPDU size: bogus length", EXPFILL }},
2339 { &ei_cotp_atn_extended_checksum, { "cotp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2340 { &ei_cotp_checksum, { "cotp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2343 module_t *cotp_module;
2344 expert_module_t* expert_cotp;
2346 proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "COTP", "cotp");
2347 proto_register_field_array(proto_cotp, hf, array_length(hf));
2348 proto_register_subtree_array(ett, array_length(ett));
2349 expert_cotp = expert_register_protocol(proto_cotp);
2350 expert_register_field_array(expert_cotp, ei, array_length(ei));
2351 cotp_module = prefs_register_protocol(proto_cotp, NULL);
2353 prefs_register_bool_preference(cotp_module, "reassemble",
2354 "Reassemble segmented COTP datagrams",
2355 "Whether segmented COTP datagrams should be "
2356 "reassembled. To use this option, you must "
2357 "also enable \"Allow subdissectors to "
2358 "reassemble TCP streams\" in the TCP "
2359 "protocol settings.",
2362 prefs_register_enum_preference(cotp_module, "tsap_display",
2363 "Display TSAPs as strings or bytes",
2364 "How TSAPs should be displayed",
2365 &tsap_display, tsap_display_options, FALSE);
2367 prefs_register_bool_preference(cotp_module, "decode_atn", "Decode ATN TPDUs",
2368 "Whether to decode OSI TPDUs with ATN "
2369 "(Aereonautical Telecommunications Network) "
2370 "extensions. To use this option, you must "
2371 "also enable \"Always try to decode NSDU as "
2372 "transport PDUs\" in the CLNP protocol "
2373 "settings.", &cotp_decode_atn);
2375 /* For handling protocols hijacking the variable part of CR or CC PDUs */
2376 cotp_cr_heur_subdissector_list = register_heur_dissector_list("cotp_cr", proto_cotp);
2377 cotp_cc_heur_subdissector_list = register_heur_dissector_list("cotp_cc", proto_cotp);
2379 /* subdissector code in inactive subset */
2380 cotp_is_heur_subdissector_list = register_heur_dissector_list("cotp_is", proto_cotp);
2382 /* other COTP/ISO 8473 subdissectors */
2383 cotp_heur_subdissector_list = register_heur_dissector_list("cotp", proto_cotp);
2385 /* XXX - what about CLTP and proto_cltp? */
2386 ositp_handle = register_dissector("ositp", dissect_ositp, proto_cotp);
2387 register_dissector("ositp_inactive", dissect_ositp_inactive, proto_cotp);
2389 register_init_routine(cotp_reassemble_init);
2391 * XXX - this is a connection-oriented transport-layer protocol,
2392 * so we should probably use more than just network-layer
2393 * endpoint addresses to match segments together, but the functions
2394 * in addresses_ports_reassembly_table_functions do matching based
2395 * on port numbers, so they won't let us ensure that segments from
2396 * different connections don't get assembled together.
2398 reassembly_table_register(&cotp_reassembly_table,
2399 &addresses_reassembly_table_functions);
2402 void proto_register_cltp(void)
2404 static hf_register_info hf[] = {
2406 { "Length", "cltp.li", FT_UINT8, BASE_DEC, NULL, 0x0,
2407 "Length Indicator, length of this header", HFILL}},
2409 { "PDU Type", "cltp.type", FT_UINT8, BASE_HEX,
2410 VALS(cltp_tpdu_type_abbrev_vals), 0x0, NULL, HFILL}}
2412 static gint *ett[] = {
2416 proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "CLTP", "cltp");
2417 proto_register_field_array(proto_cltp, hf, array_length(hf));
2418 proto_register_subtree_array(ett, array_length(ett));
2420 cltp_heur_subdissector_list = register_heur_dissector_list("cltp", proto_cltp);
2424 proto_reg_handoff_cotp(void)
2426 dissector_add_uint("ip.proto", IP_PROTO_TP, ositp_handle);
2428 rdp_cr_handle = find_dissector("rdp_cr");
2429 rdp_cc_handle = find_dissector("rdp_cc");
2431 proto_clnp = proto_get_id_by_filter_name("clnp");
2435 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2440 * indent-tabs-mode: nil
2443 * vi: set shiftwidth=2 tabstop=8 expandtab:
2444 * :indentSize=2:tabSize=8:noTabs=true: