MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-ositp.c
blob77093a94bf7469cb67bd0d890c4704e3ae64c117
1 /* packet-ositp.c
2 * Routines for ISO/OSI transport protocol (connection-oriented
3 * and connectionless) packet disassembly
5 * $Id$
6 * Laurent Deniel <laurent.deniel@free.fr>
7 * Ralf Schneider <Ralf.Schneider@t-online.de>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "config.h"
30 #include <ctype.h>
32 #include <glib.h>
33 #include <epan/prefs.h>
34 #include <epan/packet.h>
35 #include <epan/reassemble.h>
36 #include <epan/conversation.h>
37 #include <epan/wmem/wmem.h>
38 #include "packet-frame.h"
39 #include "packet-osi.h"
40 #include "packet-osi-options.h"
41 #include "packet-isis.h"
42 #include "packet-esis.h"
43 #include <epan/nlpid.h>
44 #include <epan/ipproto.h>
45 #include <epan/expert.h>
46 #include <epan/strutil.h>
48 /* protocols and fields */
50 static int proto_clnp;
52 static int proto_cotp = -1;
53 static gint ett_cotp = -1;
54 static gint ett_cotp_segments = -1;
55 static gint ett_cotp_segment = -1;
57 static int hf_cotp_li = -1;
58 static int hf_cotp_type = -1;
59 static int hf_cotp_srcref = -1;
60 static int hf_cotp_destref = -1;
61 static int hf_cotp_class = -1;
62 static int hf_cotp_opts_extended_formats = -1;
63 static int hf_cotp_opts_no_explicit_flow_control = -1;
64 static int hf_cotp_tpdu_number = -1;
65 static int hf_cotp_tpdu_number_extended = -1;
66 static int hf_cotp_next_tpdu_number = -1;
67 static int hf_cotp_next_tpdu_number_extended = -1;
68 static int hf_cotp_eot = -1;
69 static int hf_cotp_eot_extended = -1;
71 static int hf_cotp_segments = -1;
72 static int hf_cotp_segment = -1;
73 static int hf_cotp_segment_overlap = -1;
74 static int hf_cotp_segment_overlap_conflict = -1;
75 static int hf_cotp_segment_multiple_tails = -1;
76 static int hf_cotp_segment_too_long_segment = -1;
77 static int hf_cotp_segment_error = -1;
78 static int hf_cotp_segment_count = -1;
79 static int hf_cotp_reassembled_in = -1;
80 static int hf_cotp_reassembled_length = -1;
82 static expert_field ei_cotp_disconnect_confirm = EI_INIT;
83 static expert_field ei_cotp_multiple_tpdus = EI_INIT;
84 static expert_field ei_cotp_reject = EI_INIT;
85 static expert_field ei_cotp_connection = EI_INIT;
86 static expert_field ei_cotp_disconnect_request = EI_INIT;
88 static int proto_cltp = -1;
89 static gint ett_cltp = -1;
91 static int hf_cltp_li = -1;
92 static int hf_cltp_type = -1;
94 static const fragment_items cotp_frag_items = {
95 &ett_cotp_segment,
96 &ett_cotp_segments,
97 &hf_cotp_segments,
98 &hf_cotp_segment,
99 &hf_cotp_segment_overlap,
100 &hf_cotp_segment_overlap_conflict,
101 &hf_cotp_segment_multiple_tails,
102 &hf_cotp_segment_too_long_segment,
103 &hf_cotp_segment_error,
104 &hf_cotp_segment_count,
105 &hf_cotp_reassembled_in,
106 &hf_cotp_reassembled_length,
107 /* Reassembled data field */
108 NULL,
109 "segments"
112 static dissector_handle_t data_handle;
115 * ISO8073 OSI COTP definition
116 * See http://standards.iso.org/ittf/PubliclyAvailableStandards/index.html
117 * (or RFC905 for historic, and now-outdated information)
120 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
122 /* TPDU definition */
124 #define ED_TPDU 0x1 /* COTP */
125 #define EA_TPDU 0x2 /* COTP */
126 #define UD_TPDU 0x4 /* CLTP */
127 #define RJ_TPDU 0x5 /* COTP */
128 #define AK_TPDU 0x6 /* COTP */
129 #define ER_TPDU 0x7 /* COTP */
130 #define DR_TPDU 0x8 /* COTP */
131 #define DC_TPDU 0xC /* COTP */
132 #define CC_TPDU 0xD /* COTP */
133 #define CR_TPDU 0xE /* COTP */
134 #define DT_TPDU 0xF /* COTP */
136 static const value_string cotp_tpdu_type_abbrev_vals[] = {
137 { ED_TPDU, "ED Expedited Data" },
138 { EA_TPDU, "EA Expedited Data Acknowledgement" },
139 { RJ_TPDU, "RJ Reject" },
140 { AK_TPDU, "AK Data Acknowledgement" },
141 { ER_TPDU, "ER TPDU Error" },
142 { DR_TPDU, "DR Disconnect Request" },
143 { DC_TPDU, "DC Disconnect Confirm" },
144 { CC_TPDU, "CC Connect Confirm" },
145 { CR_TPDU, "CR Connect Request" },
146 { DT_TPDU, "DT Data" },
147 { 0, NULL }
150 static const value_string cltp_tpdu_type_abbrev_vals[] = {
151 { UD_TPDU, "UD" },
152 { 0, NULL }
155 #if 0
156 static const value_string class_option_vals[] = {
157 {0, "Class 0"},
158 {1, "Class 1"},
159 {2, "Class 2"},
160 {3, "Class 3"},
161 {4, "Class 4"},
162 {0, NULL}
164 #endif
166 /* field position */
168 #define P_LI 0
169 #define P_TPDU 1
170 #define P_CDT 1
171 #define P_DST_REF 2
172 #define P_SRC_REF 4
173 #define P_TPDU_NR_0_1 2
174 #define P_TPDU_NR_234 4
175 #define P_VAR_PART_NDT 5
176 #define P_VAR_PART_EDT 8
177 #define P_VAR_PART_DC 6
178 #define P_CDT_IN_AK 8
179 #define P_CDT_IN_RJ 8
180 #define P_REJECT_ER 4
181 #define P_REASON_IN_DR 6
182 #define P_CLASS_OPTION 6
185 * TPDU length indicator values.
186 * Checksum parameter is 4 octets - 1 octet of parameter code, 1 octet
187 * of parameter length, 2 octets of checksum.
190 #define LI_NORMAL_DT_CLASS_01 2
191 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
192 #define LI_NORMAL_DT_WITH_CHECKSUM (LI_NORMAL_DT_WITHOUT_CHECKSUM+4)
193 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
194 #define LI_EXTENDED_DT_WITH_CHECKSUM (LI_EXTENDED_DT_WITHOUT_CHECKSUM+4)
195 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
196 #define LI_NORMAL_EA_WITH_CHECKSUM (LI_NORMAL_EA_WITHOUT_CHECKSUM+4)
197 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
198 #define LI_EXTENDED_EA_WITH_CHECKSUM (LI_EXTENDED_EA_WITHOUT_CHECKSUM+4)
199 #define LI_NORMAL_RJ 4
200 #define LI_EXTENDED_RJ 9
201 #define LI_MIN_DR 6
202 #define LI_MAX_DC 9
203 #define LI_MAX_AK 27
204 #define LI_MAX_EA 11
205 #define LI_MAX_ER 8
206 /* XXX - can we always decide this based on whether the length
207 indicator is odd or not? What if the variable part has an odd
208 number of octets? */
209 #define is_LI_NORMAL_AK(p) ((p & 0x01) == 0)
212 * Modified TPDU length indicator values due to ATN 4-octet extended
213 * checksum.
214 * Checksum parameter is 6 octets - 1 octet of parameter code, 1 octet
215 * of parameter length, 4 octets of checksum. That adds 2 octets to
216 * the lengths with a 2-octet checksum.
218 #define LI_ATN_NORMAL_DT_WITH_CHECKSUM (LI_NORMAL_DT_WITH_CHECKSUM+2)
219 #define LI_ATN_EXTENDED_DT_WITH_CHECKSUM (LI_EXTENDED_DT_WITH_CHECKSUM+2)
220 #define LI_ATN_NORMAL_EA_WITH_CHECKSUM (LI_NORMAL_EA_WITH_CHECKSUM+2)
221 #define LI_ATN_EXTENDED_EA_WITH_CHECKSUM (LI_EXTENDED_EA_WITH_CHECKSUM+2)
222 #define LI_ATN_NORMAL_RJ (LI_NORMAL_RJ+2)
223 #define LI_ATN_EXTENDED_RJ (LI_EXTENDED_RJ+2)
224 #define LI_ATN_MAX_DC (LI_MAX_DC+2)
225 #define LI_ATN_MAX_AK (LI_MAX_AK+2+1) /* +1 for padding? */
226 #define LI_ATN_MAX_EA (LI_MAX_EA+2)
227 #define LI_ATN_MAX_ER (LI_MAX_ER+2)
229 /* variant part */
231 #define VP_ACK_TIME 0x85
232 #define VP_RES_ERROR 0x86
233 #define VP_PRIORITY 0x87
234 #define VP_TRANSIT_DEL 0x88
235 #define VP_THROUGHPUT 0x89
236 #define VP_SEQ_NR 0x8A /* in AK */
237 #define VP_REASSIGNMENT 0x8B
238 #define VP_FLOW_CNTL 0x8C /* in AK */
239 #define VP_TPDU_SIZE 0xC0
240 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
241 #define VP_DST_TSAP 0xC2
242 #define VP_CHECKSUM 0xC3
243 #define VP_VERSION_NR 0xC4
244 #define VP_PROTECTION 0xC5
245 #define VP_OPT_SEL 0xC6
246 #define VP_PROTO_CLASS 0xC7
247 #define VP_CLEARING_INFO 0xE0 /* in DR */
248 #define VP_PREF_MAX_TPDU_SIZE 0xF0
249 #define VP_INACTIVITY_TIMER 0xF2
251 /* ATN */
252 /* Parameter codes with bits 7 and 8 are explicitly not */
253 /* assigned by ISO/IEC 8073, nor is their use precluded. */
254 /* Parameter codes for ATN defined in ICAO doc 9507 Ed3 SV 5 section 5.5.2.4.3.1 */
255 #define VP_ATN_EC_32 0x08 /* 4 octet ATN Extended Transport Checksum parameter */
256 #define VP_ATN_EC_16 0x09 /* 2 octet ATN Extended Transport Checksum parameter */
257 /* ATN end */
259 static const value_string tp_vpart_type_vals[] = {
260 { VP_ATN_EC_16, "ATN extended checksum - 16 bit" },
261 { VP_ATN_EC_32, "ATN extended checksum - 32 bit" },
262 { VP_ACK_TIME, "ack time" },
263 { VP_RES_ERROR, "res error" },
264 { VP_PRIORITY, "priority" },
265 { VP_TRANSIT_DEL, "transit delay" },
266 { VP_THROUGHPUT, "throughput" },
267 { VP_SEQ_NR, "seq number" },
268 { VP_REASSIGNMENT, "reassignment" },
269 { VP_FLOW_CNTL, "flow control" },
270 { VP_TPDU_SIZE, "tpdu-size" },
271 { VP_SRC_TSAP, "src-tsap" },
272 { VP_DST_TSAP, "dst-tsap" },
273 { VP_CHECKSUM, "checksum" },
274 { VP_VERSION_NR, "version" },
275 { VP_PROTECTION, "protection" },
276 { VP_OPT_SEL, "options" },
277 { VP_PROTO_CLASS, "proto class" },
278 { VP_CLEARING_INFO, "additional connection clearing info" },
279 { VP_PREF_MAX_TPDU_SIZE, "preferred max TPDU size" },
280 { VP_INACTIVITY_TIMER, "inactivity timer" },
281 { 0, NULL }
284 static int hf_cotp_vp_src_tsap = -1;
285 static int hf_cotp_vp_dst_tsap = -1;
286 static int hf_cotp_vp_src_tsap_bytes = -1;
287 static int hf_cotp_vp_dst_tsap_bytes = -1;
289 /* global variables */
291 /* List of dissectors to call for COTP packets put atop the Inactive
292 Subset of CLNP. */
293 static heur_dissector_list_t cotp_is_heur_subdissector_list;
294 /* List of dissectors to call for COTP packets put atop CLNP */
295 static heur_dissector_list_t cotp_heur_subdissector_list;
296 /* List of dissectors to call for CLTP packets put atop CLNP */
297 static heur_dissector_list_t cltp_heur_subdissector_list;
300 * Reassembly of COTP.
302 static reassembly_table cotp_reassembly_table;
303 static guint16 cotp_dst_ref = 0;
304 static gboolean cotp_frame_reset = FALSE;
305 static gboolean cotp_last_fragment = FALSE;
307 #define TSAP_DISPLAY_AUTO 0
308 #define TSAP_DISPLAY_STRING 1
309 #define TSAP_DISPLAY_BYTES 2
311 /* options */
312 static gboolean cotp_reassemble = TRUE;
313 static gint32 tsap_display = TSAP_DISPLAY_AUTO;
314 static gboolean cotp_decode_atn = FALSE;
316 static const enum_val_t tsap_display_options[] = {
317 {"auto", "As strings if printable", TSAP_DISPLAY_AUTO},
318 {"string", "As strings", TSAP_DISPLAY_STRING},
319 {"bytes", "As bytes", TSAP_DISPLAY_BYTES},
320 {NULL, NULL, -1}
323 /* function definitions */
325 #define MAX_TSAP_LEN 32
327 static void cotp_frame_end(void)
329 if (!cotp_last_fragment) {
330 /* Last COTP in frame is not fragmented.
331 * No need for incrementing the dst_ref, so we decrement it here.
333 cotp_dst_ref--;
335 cotp_frame_reset = TRUE;
338 static gboolean is_all_printable(const guchar *stringtocheck, int length)
340 gboolean allprintable;
341 int i;
343 allprintable=TRUE;
344 for (i=0;i<length;i++) {
345 if (!(isascii(stringtocheck[i]) && isprint(stringtocheck[i]))) {
346 allprintable=FALSE;
347 break;
350 return allprintable;
351 } /* is_all_printable */
354 static gchar *print_tsap(const guchar *tsap, int length)
357 gchar *cur;
358 gboolean allprintable;
359 gint idx = 0, returned_length;
361 cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_TSAP_LEN * 2 + 3);
362 cur[0] = '\0';
363 if (length <= 0 || length > MAX_TSAP_LEN)
364 g_snprintf(cur, MAX_TSAP_LEN * 2 + 3, "<unsupported TSAP length>");
365 else {
366 allprintable = is_all_printable(tsap,length);
367 if (!allprintable) {
368 returned_length = g_snprintf(cur, MAX_TSAP_LEN * 2 + 3, "0x");
369 idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - 1);
371 while (length != 0) {
372 if (allprintable) {
373 returned_length = g_snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
374 "%c", *tsap ++);
375 idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
376 } else {
377 returned_length = g_snprintf(&cur[idx], MAX_TSAP_LEN * 2 + 3 - idx,
378 "%02x", *tsap ++);
379 idx += MIN(returned_length, MAX_TSAP_LEN * 2 + 3 - idx - 1);
381 length --;
384 return cur;
386 } /* print_tsap */
388 static gboolean ositp_decode_var_part(tvbuff_t *tvb, int offset, int vp_length,
389 int class_option, int tpdu_len,
390 packet_info *pinfo, proto_tree *tree)
392 guint8 code, length;
393 guint8 c1;
394 guint16 s, s1,s2,s3,s4;
395 guint32 t1, t2, t3, t4;
396 guint32 offset_iso8073_checksum = 0;
397 gint32 i = 0;
398 guint8 tmp_code = 0;
399 guint tmp_len = 0;
400 cksum_status_t cksum_status;
401 gboolean checksum_ok = FALSE;
402 guint32 pref_max_tpdu_size;
403 proto_item *hidden_item;
405 while (vp_length != 0) {
406 code = tvb_get_guint8(tvb, offset);
407 proto_tree_add_text(tree, tvb, offset, 1,
408 "Parameter code: 0x%02x (%s)", code,
409 val_to_str_const(code, tp_vpart_type_vals, "Unknown"));
410 offset += 1;
411 vp_length -= 1;
413 if (vp_length == 0)
414 break;
415 length = tvb_get_guint8(tvb, offset);
416 proto_tree_add_text(tree, tvb, offset, 1, "Parameter length: %u", length);
417 offset += 1;
418 vp_length -= 1;
420 switch (code) {
422 case VP_ATN_EC_16 : /* ATN */
423 if (cotp_decode_atn) {
424 /* if an alternate OSI checksum is present in the currently unprocessed
425 * VP section to the checksum algorithm has to know.
426 * this may be the case for backward compatible CR TPDU */
427 if (!offset_iso8073_checksum) {
428 /* search following parameters in VP part for ISO checksum */
429 for (i = offset + length; i < vp_length;) {
430 tmp_code = tvb_get_guint8(tvb, i++);
431 tmp_len = tvb_get_guint8(tvb, i++);
432 if (tmp_code == VP_CHECKSUM) {
433 offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
434 break;
436 i += tmp_len;
439 checksum_ok = check_atn_ec_16(tvb, tpdu_len , offset,
440 offset_iso8073_checksum,
441 pinfo->dst.len, (guint8 *)pinfo->dst.data,
442 pinfo->src.len, (guint8 *)pinfo->src.data);
443 proto_tree_add_text(tree, tvb, offset, length,
444 "ATN extended checksum : 0x%04x (%s)",
445 tvb_get_ntohs(tvb, offset),
446 checksum_ok ? "correct" : "incorrect");
447 } else {
448 proto_tree_add_text(tree, tvb, offset, length,
449 "Parameter value: <not shown>");
451 offset += length;
452 vp_length -= length;
453 break;
455 case VP_ATN_EC_32 : /* ATN */
456 if (cotp_decode_atn) {
457 /* if an alternate OSI checksum is present in the currently unprocessed
458 * VP section the checksum algorithm has to know.
459 * this may be the case for backward compatible CR TPDU */
460 if (!offset_iso8073_checksum) {
461 /* search following parameters in VP part for ISO checksum */
462 for (i = offset + length; i < vp_length;) {
463 tmp_code = tvb_get_guint8(tvb, i++);
464 tmp_len = tvb_get_guint8(tvb, i++);
465 if (tmp_code == VP_CHECKSUM) {
466 offset_iso8073_checksum = i; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
467 break;
469 i += tmp_len;
472 checksum_ok = check_atn_ec_32(tvb, tpdu_len , offset,
473 offset_iso8073_checksum,
474 pinfo->dst.len, (guint8 *)pinfo->dst.data,
475 pinfo->src.len, (guint8 *)pinfo->src.data);
476 proto_tree_add_text(tree, tvb, offset, length,
477 "ATN extended checksum : 0x%08x (%s)",
478 tvb_get_ntohl(tvb, offset),
479 checksum_ok ? "correct" : "incorrect");
480 } else {
481 proto_tree_add_text(tree, tvb, offset, length,
482 "Parameter value: <not shown>");
484 offset += length;
485 vp_length -= length;
486 break;
488 case VP_ACK_TIME:
489 s = tvb_get_ntohs(tvb, offset);
490 proto_tree_add_text(tree, tvb, offset, length, "Ack time (ms): %u", s);
491 offset += length;
492 vp_length -= length;
493 break;
495 case VP_RES_ERROR:
496 proto_tree_add_text(tree, tvb, offset, 1,
497 "Residual error rate, target value: 10^%u",
498 tvb_get_guint8(tvb, offset));
499 offset += 1;
500 vp_length -= 1;
502 proto_tree_add_text(tree, tvb, offset, 1,
503 "Residual error rate, minimum acceptable: 10^%u",
504 tvb_get_guint8(tvb, offset));
505 offset += 1;
506 vp_length -= 1;
508 proto_tree_add_text(tree, tvb, offset, 1,
509 "Residual error rate, TSDU size of interest: %u",
510 1 << tvb_get_guint8(tvb, offset));
511 offset += 1;
512 vp_length -= 1;
513 break;
515 case VP_PRIORITY:
516 s = tvb_get_ntohs(tvb, offset);
517 proto_tree_add_text(tree, tvb, offset, length, "Priority: %u", s);
518 offset += length;
519 vp_length -= length;
520 break;
522 case VP_TRANSIT_DEL:
523 s1 = tvb_get_ntohs(tvb, offset);
524 proto_tree_add_text(tree, tvb, offset, 2,
525 "Transit delay, target value, calling-called: %u ms",
526 s1);
527 offset += 2;
528 vp_length -= 2;
530 s2 = tvb_get_ntohs(tvb, offset);
531 proto_tree_add_text(tree, tvb, offset, 2,
532 "Transit delay, maximum acceptable, calling-called: %u ms",
533 s2);
534 offset += 2;
535 vp_length -= 2;
537 s3 = tvb_get_ntohs(tvb, offset);
538 proto_tree_add_text(tree, tvb, offset, 2,
539 "Transit delay, target value, called-calling: %u ms",
540 s3);
541 offset += 2;
542 vp_length -= 2;
544 s4 = tvb_get_ntohs(tvb, offset);
545 proto_tree_add_text(tree, tvb, offset, 2,
546 "Transit delay, maximum acceptable, called-calling: %u ms",
547 s4);
548 offset += 2;
549 vp_length -= 2;
550 break;
552 case VP_THROUGHPUT:
553 t1 = tvb_get_ntoh24(tvb, offset);
554 proto_tree_add_text(tree, tvb, offset, 3,
555 "Maximum throughput, target value, calling-called: %u o/s",
556 t1);
557 offset += 3;
558 length -= 3;
559 vp_length -= 3;
561 t2 = tvb_get_ntoh24(tvb, offset);
562 proto_tree_add_text(tree, tvb, offset, 3,
563 "Maximum throughput, minimum acceptable, calling-called: %u o/s",
564 t2);
565 offset += 3;
566 length -= 3;
567 vp_length -= 3;
569 t3 = tvb_get_ntoh24(tvb, offset);
570 proto_tree_add_text(tree, tvb, offset, 3,
571 "Maximum throughput, target value, called-calling: %u o/s",
572 t3);
573 offset += 3;
574 length -= 3;
575 vp_length -= 3;
577 t4 = tvb_get_ntoh24(tvb, offset);
578 proto_tree_add_text(tree, tvb, offset, 3,
579 "Maximum throughput, minimum acceptable, called-calling: %u o/s",
580 t4);
581 offset += 3;
582 length -= 3;
583 vp_length -= 3;
585 if (length != 0) { /* XXX - should be 0 or 12 */
586 t1 = tvb_get_ntoh24(tvb, offset);
587 proto_tree_add_text(tree, tvb, offset, 3,
588 "Average throughput, target value, calling-called: %u o/s",
589 t1);
590 offset += 3;
591 vp_length -= 3;
593 t2 = tvb_get_ntoh24(tvb, offset);
594 proto_tree_add_text(tree, tvb, offset, 3,
595 "Average throughput, minimum acceptable, calling-called: %u o/s",
596 t2);
597 offset += 3;
598 vp_length -= 3;
600 t3 = tvb_get_ntoh24(tvb, offset);
601 proto_tree_add_text(tree, tvb, offset, 3,
602 "Average throughput, target value, called-calling: %u o/s",
603 t3);
604 offset += 3;
605 vp_length -= 3;
607 t4 = tvb_get_ntoh24(tvb, offset);
608 proto_tree_add_text(tree, tvb, offset, 3,
609 "Average throughput, minimum acceptable, called-calling: %u o/s",
610 t4);
611 offset += 3;
612 vp_length -= 3;
614 break;
616 case VP_SEQ_NR:
617 proto_tree_add_text(tree, tvb, offset, 2, "Sequence number: 0x%04x",
618 tvb_get_ntohs(tvb, offset));
619 offset += length;
620 vp_length -= length;
621 break;
623 case VP_REASSIGNMENT:
624 proto_tree_add_text(tree, tvb, offset, 2, "Reassignment time: %u secs",
625 tvb_get_ntohs(tvb, offset));
626 offset += length;
627 vp_length -= length;
628 break;
630 case VP_FLOW_CNTL:
631 proto_tree_add_text(tree, tvb, offset, 4, "Lower window edge: 0x%08x",
632 tvb_get_ntohl(tvb, offset));
633 offset += 4;
634 vp_length -= 4;
636 proto_tree_add_text(tree, tvb, offset, 2, "Sequence number: 0x%04x",
637 tvb_get_ntohs(tvb, offset));
638 offset += 2;
639 vp_length -= 2;
641 proto_tree_add_text(tree, tvb, offset, 2, "Credit: 0x%04x",
642 tvb_get_ntohs(tvb, offset));
643 offset += 2;
644 vp_length -= 2;
646 break;
648 case VP_TPDU_SIZE:
649 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
650 proto_tree_add_text(tree, tvb, offset, length, "TPDU size: %u", 1 << c1);
651 offset += length;
652 vp_length -= length;
653 break;
655 case VP_SRC_TSAP:
656 /* if our preference is set to STRING or the TSAP is not printable,
657 * add as bytes and hidden as string; otherwise vice-versa */
658 if (tsap_display==TSAP_DISPLAY_STRING ||
659 (tsap_display==TSAP_DISPLAY_AUTO &&
660 is_all_printable(tvb_get_ptr(tvb, offset,length),length))) {
661 proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
662 print_tsap(tvb_get_ptr(tvb, offset, length),
663 length));
664 hidden_item = proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb,
665 offset, length, ENC_NA);
666 PROTO_ITEM_SET_HIDDEN(hidden_item);
667 } else {
668 hidden_item = proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb,
669 offset, length,
670 print_tsap(tvb_get_ptr(tvb, offset,
671 length),
672 length));
673 PROTO_ITEM_SET_HIDDEN(hidden_item);
674 proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset,
675 length, ENC_NA);
677 offset += length;
678 vp_length -= length;
679 break;
681 case VP_DST_TSAP:
682 /* if our preference is set to STRING or the TSAP is not printable,
683 * add as bytes and hidden as string; otherwise vice-versa */
684 if (tsap_display==TSAP_DISPLAY_STRING ||
685 (tsap_display==TSAP_DISPLAY_AUTO &&
686 is_all_printable(tvb_get_ptr(tvb,offset,length),length))) {
687 proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
688 print_tsap(tvb_get_ptr(tvb, offset, length),
689 length));
690 hidden_item = proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb,
691 offset, length, ENC_NA);
692 PROTO_ITEM_SET_HIDDEN(hidden_item);
693 } else {
694 hidden_item = proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb,
695 offset, length,
696 print_tsap(tvb_get_ptr(tvb, offset,
697 length),
698 length));
699 PROTO_ITEM_SET_HIDDEN(hidden_item);
700 proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset,
701 length, ENC_NA);
703 offset += length;
704 vp_length -= length;
705 break;
707 case VP_CHECKSUM:
708 offset_iso8073_checksum = offset; /* save ISO 8073 checksum offset for ATN extended checksum calculation */
709 cksum_status = calc_checksum(tvb, 0, tpdu_len,
710 tvb_get_ntohs(tvb, offset));
711 switch (cksum_status) {
713 default:
715 * No checksum present, or not enough of the packet present to
716 * checksum it.
718 proto_tree_add_text(tree, tvb, offset, length,
719 "Checksum: 0x%04x", tvb_get_ntohs(tvb, offset));
720 break;
722 case CKSUM_OK:
724 * Checksum is correct.
726 proto_tree_add_text(tree, tvb, offset, length,
727 "Checksum: 0x%04x (correct)",
728 tvb_get_ntohs(tvb, offset));
729 break;
731 case CKSUM_NOT_OK:
733 * Checksum is not correct.
735 proto_tree_add_text(tree, tvb, offset, length,
736 "Checksum: 0x%04x (incorrect)",
737 tvb_get_ntohs(tvb, offset));
738 break;
740 offset += length;
741 vp_length -= length;
742 break;
744 case VP_VERSION_NR:
745 c1 = tvb_get_guint8(tvb, offset);
746 proto_tree_add_text(tree, tvb, offset, length, "Version: %u", c1);
747 offset += length;
748 vp_length -= length;
749 break;
751 case VP_OPT_SEL:
752 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
753 switch (class_option) {
755 case 1:
756 if (c1 & 0x8)
757 proto_tree_add_text(tree, tvb, offset, 1,
758 "Use of network expedited data");
759 else
760 proto_tree_add_text(tree, tvb, offset, 1,
761 "Non use of network expedited data");
762 if (c1 & 0x4)
763 proto_tree_add_text(tree, tvb, offset, 1,
764 "Use of Receipt confirmation");
765 else
766 proto_tree_add_text(tree, tvb, offset, 1,
767 "Use of explicit AK variant");
768 break;
770 case 4:
771 if (c1 & 0x2)
772 proto_tree_add_text(tree, tvb, offset, 1,
773 "Non-use 16 bit checksum in class 4");
774 else
775 proto_tree_add_text(tree, tvb, offset, 1, "Use 16 bit checksum ");
776 break;
779 if (c1 & 0x1)
780 proto_tree_add_text(tree, tvb, offset, 1,
781 "Use of transport expedited data transfer");
782 else
783 proto_tree_add_text(tree, tvb, offset, 1,
784 "Non-use of transport expedited data transfer");
785 offset += length;
786 vp_length -= length;
787 break;
789 case VP_PREF_MAX_TPDU_SIZE:
790 switch (length) {
792 case 1:
793 pref_max_tpdu_size = tvb_get_guint8(tvb, offset);
794 break;
796 case 2:
797 pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
798 break;
800 case 3:
801 pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
802 break;
804 case 4:
805 pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
806 break;
808 default:
809 proto_tree_add_text(tree, tvb, offset, length,
810 "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)",
811 length);
812 return FALSE;
814 proto_tree_add_text(tree, tvb, offset, length,
815 "Preferred maximum TPDU size: %u",
816 pref_max_tpdu_size*128);
817 offset += length;
818 vp_length -= length;
819 break;
821 case VP_INACTIVITY_TIMER:
822 proto_tree_add_text(tree, tvb, offset, length, "Inactivity timer: %u ms",
823 tvb_get_ntohl(tvb, offset));
824 offset += length;
825 vp_length -= length;
826 break;
828 case VP_PROTECTION: /* user-defined */
829 case VP_PROTO_CLASS: /* todo */
830 case VP_CLEARING_INFO: /* user-defined */
831 default: /* unknown, no decoding */
832 proto_tree_add_text(tree, tvb, offset, length,
833 "Parameter value: <not shown>");
834 offset += length;
835 vp_length -= length;
836 break;
838 } /* while */
840 return TRUE;
843 static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
844 packet_info *pinfo, proto_tree *tree)
846 proto_tree *cotp_tree = NULL;
847 proto_item *ti = NULL;
848 guint16 dst_ref, src_ref;
849 guchar reason;
850 const char *str;
851 guint tpdu_len;
853 /* ATN TPDU's tend to be larger than normal OSI,
854 * so nothing to do with respect to LI checks */
855 if (li < LI_MIN_DR)
856 return -1;
858 /* DR TPDUs can have user data, so they run to the end of the containing PDU */
859 tpdu_len = tvb_reported_length_remaining(tvb, offset);
861 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
863 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
865 reason = tvb_get_guint8(tvb, offset + P_REASON_IN_DR);
867 pinfo->clnp_dstref = dst_ref;
868 pinfo->clnp_srcref = src_ref;
870 /* the settings of the TCP srcport and destport are currently disables,
871 * for the following reasons:
872 * a) only used for ISO conversation handling (which currently doesn't work)
873 * b) will prevent "ISO on TCP" (RFC1006) packets from using
874 * "follow TCP stream" correctly
876 * A future conversation handling might be able to handle different kinds of
877 * conversations (TCP, ISO, TCP on TCP, ...), but in that case this has to be
878 * fixed in any case.
880 /*pinfo->srcport = src_ref;*/
881 /*pinfo->destport = dst_ref;*/
882 switch(reason) {
883 case (128+0): str = "Normal Disconnect"; break;
884 case (128+1): str = "Remote transport entity congestion"; break;
885 case (128+2): str = "Connection negotiation failed"; break;
886 case (128+3): str = "Duplicate source reference"; break;
887 case (128+4): str = "Mismatched references"; break;
888 case (128+5): str = "Protocol error"; break;
889 case (128+7): str = "Reference overflow"; break;
890 case (128+8): str = "Connection request refused"; break;
891 case (128+10):str = "Header or parameter length invalid"; break;
892 case (0): str = "Reason not specified"; break;
893 case (1): str = "Congestion at TSAP"; break;
894 case (2): str = "Session entity not attached to TSAP"; break;
895 case (3): str = "Address unknown"; break;
896 default: return -1;
899 col_append_fstr(pinfo->cinfo, COL_INFO,
900 "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
902 if (tree) {
903 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
904 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
905 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
906 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu);
907 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2,
908 dst_ref);
909 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset + 4, 2,
910 src_ref);
911 proto_tree_add_text(cotp_tree, tvb, offset + 6, 1, "Cause: %s", str);
913 offset += 7;
914 li -= 6;
916 if (tree)
917 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
918 offset += li;
920 expert_add_info_format(pinfo, ti, &ei_cotp_disconnect_request, "Disconnect Request(DR): 0x%x -> 0x%x", src_ref, dst_ref);
922 /* User data */
923 call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo,
924 tree);
925 offset += tvb_length_remaining(tvb, offset);
926 /* we dissected all of the containing PDU */
928 return offset;
930 } /* ositp_decode_DR */
932 static int ositp_decode_DT(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
933 packet_info *pinfo, proto_tree *tree,
934 gboolean uses_inactive_subset,
935 gboolean *subdissector_found)
937 proto_tree *cotp_tree = NULL;
938 proto_item *ti;
939 gboolean is_extended;
940 gboolean is_class_234;
941 guint32 dst_ref;
942 guint32 *prev_dst_ref;
943 guint tpdu_nr;
944 gboolean fragment = FALSE;
945 guint32 fragment_length = 0;
946 tvbuff_t *next_tvb;
947 fragment_head *fd_head;
948 conversation_t *conv;
949 guint tpdu_len;
951 /* DT TPDUs have user data, so they run to the end of the containing PDU */
952 tpdu_len = tvb_reported_length_remaining(tvb, offset);
954 /* The fixed part is 2 octets long, not including the length indicator,
955 for classes 0 and 1; it is at least 4 octets long, not including
956 the length indicator, for classes 2, 3, and 4. */
957 is_class_234 = (li > LI_NORMAL_DT_CLASS_01);
959 /* note: in the ATN the user is up to chose between 3 different checksums:
960 * standard OSI, 2 or 4 octet extended checksum.
961 * The differences for DT are that the TPDU headers may be enlarged by 2
962 * octets and that checksum related option codes and option lengths are
963 * different. To not mess up the original OSI dissector LI checking was
964 * implemented separately. */
965 if (!cotp_decode_atn) { /* non ATN, plain OSI*/
966 /* VP_CHECKSUM is the only parameter allowed in the variable part.
967 * (This means we may misdissect this if the packet is bad and
968 * contains other parameters.).
970 * XXX - not true; ISO/IEC 8073:1997 (E) says that "if the use of
971 * non-blocking expedited data transfer service is negotiated (class
972 * 4 only), the variable part shall contain the ED-TPDU-NR for the
973 * first DT-TPDU created from a T-DATA request subsequent to the
974 * T-EXPEDITED DATA request". */
975 switch (li) {
977 case LI_NORMAL_DT_WITH_CHECKSUM :
978 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
979 return -1;
980 /* FALLTHROUGH */
982 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
983 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
984 if (tpdu_nr & 0x80)
985 tpdu_nr = tpdu_nr & 0x7F;
986 else
987 fragment = TRUE;
988 is_extended = FALSE;
989 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
990 break;
992 case LI_EXTENDED_DT_WITH_CHECKSUM :
993 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
994 return -1;
995 /* FALLTHROUGH */
997 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
998 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
999 if (tpdu_nr & 0x80000000)
1000 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1001 else
1002 fragment = TRUE;
1003 is_extended = TRUE;
1004 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1005 break;
1007 case LI_NORMAL_DT_CLASS_01 :
1008 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
1009 if (tpdu_nr & 0x80)
1010 tpdu_nr = tpdu_nr & 0x7F;
1011 else
1012 fragment = TRUE;
1013 is_extended = FALSE;
1014 prev_dst_ref = (guint32 *)p_get_proto_data (pinfo->fd, proto_clnp, 0);
1015 if (!prev_dst_ref) {
1016 /* First COTP in frame - save previous dst_ref as offset */
1017 prev_dst_ref = wmem_new(wmem_file_scope(), guint32);
1018 *prev_dst_ref = cotp_dst_ref;
1019 p_add_proto_data (pinfo->fd, proto_clnp, 0, prev_dst_ref);
1020 } else if (cotp_frame_reset) {
1021 cotp_dst_ref = *prev_dst_ref;
1023 cotp_frame_reset = FALSE;
1024 cotp_last_fragment = fragment;
1025 dst_ref = cotp_dst_ref;
1026 conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
1027 pinfo->ptype, pinfo->srcport, pinfo->destport,
1029 if (conv) {
1030 /* Found a conversation, also use index for the generated dst_ref */
1031 dst_ref += (conv->index << 16);
1033 if (!fragment) {
1034 cotp_dst_ref++;
1035 register_frame_end_routine(pinfo, cotp_frame_end);
1037 break;
1039 default : /* bad TPDU */
1040 return -1;
1041 } /* li */
1042 } else {
1043 /* check ATN class4 TPDU's here */
1045 /* check packet length indicators of DaTa(DT) TPDU
1046 * note: use of checksum depends on the selected RER
1047 * (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
1049 * note: sole use of TP4 class in the ATN
1050 * note: normal/extended TPDU numbering is negociable */
1051 switch (li) {
1053 /* normal DT with 2 octets of OSI or of ATN Extended Checksum */
1054 case LI_NORMAL_DT_WITH_CHECKSUM :
1055 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM &&
1056 tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16)
1057 return -1;
1058 /* FALLTHROUGH */
1060 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
1061 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1062 if (tpdu_nr & 0x80)
1063 tpdu_nr = tpdu_nr & 0x7F;
1064 else
1065 fragment = TRUE;
1066 is_extended = FALSE;
1067 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1068 break;
1070 /* extended DT with 2 octets of OSI or of ATN Extended Checksum */
1071 case LI_EXTENDED_DT_WITH_CHECKSUM :
1072 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM &&
1073 tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16)
1074 return -1;
1075 /* FALLTHROUGH */
1077 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1078 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1079 if (tpdu_nr & 0x80000000)
1080 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1081 else
1082 fragment = TRUE;
1083 is_extended = TRUE;
1084 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1085 break;
1087 /* normal DT with ATN Extended Checksum (4 octets)*/
1088 case LI_ATN_NORMAL_DT_WITH_CHECKSUM :
1089 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1090 return -1;
1092 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1094 if (tpdu_nr & 0x80)
1095 tpdu_nr = tpdu_nr & 0x7F;
1096 else
1097 fragment = TRUE;
1098 is_extended = FALSE;
1099 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1100 break;
1102 /* extended DT with 4 octets ATN Extended Checksum */
1103 case LI_ATN_EXTENDED_DT_WITH_CHECKSUM:
1104 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1105 return -1;
1107 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1108 if (tpdu_nr & 0x80000000)
1109 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1110 else
1111 fragment = TRUE;
1112 is_extended = TRUE;
1113 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1114 break;
1116 default : /* bad TPDU */
1117 return -1;
1118 } /* li */
1119 } /* cotp_decode_atn */
1121 pinfo->clnp_dstref = dst_ref;
1123 pinfo->fragmented = fragment;
1124 if (is_class_234) {
1125 col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x",
1126 tpdu_nr, dst_ref);
1127 } else {
1128 col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u)", tpdu_nr);
1131 if (tree) {
1132 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1133 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1134 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1136 offset += 1;
1138 if (tree) {
1139 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1141 offset += 1;
1142 li -= 1;
1144 if (is_class_234) {
1145 if (tree)
1146 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1147 offset += 2;
1148 li -= 2;
1149 } else if (tree) {
1150 ti = proto_tree_add_uint (cotp_tree, hf_cotp_destref, tvb, offset, 0,
1151 dst_ref);
1152 PROTO_ITEM_SET_GENERATED (ti);
1155 if (is_extended) {
1156 if (tree) {
1157 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1158 4, tpdu_nr);
1159 proto_tree_add_item(cotp_tree, hf_cotp_eot_extended, tvb, offset, 4,
1160 ENC_BIG_ENDIAN);
1162 offset += 4;
1163 li -= 4;
1164 } else {
1165 if (tree) {
1166 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1167 tpdu_nr);
1168 proto_tree_add_item(cotp_tree, hf_cotp_eot, tvb, offset, 1,
1169 ENC_BIG_ENDIAN);
1171 offset += 1;
1172 li -= 1;
1175 if (tree)
1176 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1177 offset += li;
1179 next_tvb = tvb_new_subset_remaining(tvb, offset);
1180 fragment_length = tvb_length(next_tvb);
1181 if (fragment) {
1182 col_append_fstr(pinfo->cinfo, COL_INFO, " [COTP fragment, %u byte%s]",
1183 fragment_length, plurality(fragment_length, "", "s"));
1184 } else {
1185 col_append_fstr(pinfo->cinfo, COL_INFO, " EOT");
1188 if (cotp_reassemble) {
1190 * XXX - these sequence numbers are connection sequence number,
1191 * not segment sequence numbers - the first segment of a
1192 * segmented packet doesn't have a specific sequence number (e.g., 0
1193 * or 1), it has whatever the appropriate sequence number is for
1194 * it in the connection.
1196 * For now, we assume segments arrive in order, and just supply
1197 * the negation of the EOT flag as the "more flags" argument.
1198 * We should probably handle out-of-order packets separately,
1199 * so that we can deliver them in order even when *not*
1200 * reassembling.
1202 * Note also that TP0 has no sequence number, and relies on
1203 * the protocol atop which it runs to guarantee in-order delivery.
1205 fd_head = fragment_add_seq_next(&cotp_reassembly_table, next_tvb, 0, pinfo,
1206 dst_ref, NULL, fragment_length, fragment);
1207 if (fd_head && fd_head->next) {
1208 /* don't use -1 if fragment length is zero (throws Exception) */
1209 proto_tree_add_text(cotp_tree, tvb, offset, (fragment_length) ? -1 : 0,
1210 "COTP segment data (%u byte%s)", fragment_length,
1211 plurality(fragment_length, "", "s"));
1213 if (!fragment) {
1214 /* This is the last packet */
1215 next_tvb = process_reassembled_data (next_tvb, offset, pinfo,
1216 "Reassembled COTP", fd_head,
1217 &cotp_frag_items, NULL, tree);
1218 } else if (pinfo->fd->num != fd_head->reassembled_in) {
1219 /* Add a "Reassembled in" link if not reassembled in this frame */
1220 proto_tree_add_uint(cotp_tree, *(cotp_frag_items.hf_reassembled_in),
1221 next_tvb, 0, 0, fd_head->reassembled_in);
1223 pinfo->fragmented = fragment;
1227 if (uses_inactive_subset) {
1228 if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1229 pinfo, tree, NULL)) {
1230 *subdissector_found = TRUE;
1231 } else {
1232 /* Fill in other Dissectors using inactive subset here */
1233 call_dissector(data_handle,next_tvb, pinfo, tree);
1235 } else {
1237 * We dissect payload if one of the following is TRUE:
1239 * - Reassembly option for COTP in preferences is unchecked
1240 * - Reassembly option is checked and this packet is the last fragment
1242 if ((!cotp_reassemble) || ((cotp_reassemble) && (!fragment))) {
1243 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1244 tree, NULL)) {
1245 *subdissector_found = TRUE;
1246 } else {
1247 call_dissector(data_handle,next_tvb, pinfo, tree);
1252 offset += tvb_length_remaining(tvb, offset);
1253 /* we dissected all of the containing PDU */
1255 return offset;
1257 } /* ositp_decode_DT */
1259 static int ositp_decode_ED(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1260 packet_info *pinfo, proto_tree *tree)
1262 proto_tree *cotp_tree = NULL;
1263 proto_item *ti;
1264 gboolean is_extended;
1265 guint16 dst_ref;
1266 guint tpdu_nr;
1267 tvbuff_t *next_tvb;
1268 guint tpdu_len;
1270 /* ED TPDUs have user data, so they run to the end of the containing PDU */
1271 tpdu_len = tvb_reported_length_remaining(tvb, offset);
1273 /* note: in the ATN the user is up to chose between 3 different checksums:
1274 * standard OSI, 2 or 4 octet extended checksum.
1275 * The differences for ED (as for DT) are that the TPDU headers may be
1276 * enlarged by 2 octets and that checksum related option codes and option
1277 * lengths are different. To not mess up the original OSI dissector LI
1278 * checking was implemented separately.
1280 * note: this could not be tested, because no sample was avail for expedited
1281 * data */
1282 if (!cotp_decode_atn) { /* non ATN, plain OSI*/
1283 /* ED TPDUs are never fragmented */
1285 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1286 (This means we may misdissect this if the packet is bad and
1287 contains other parameters.) */
1288 switch (li) {
1290 case LI_NORMAL_DT_WITH_CHECKSUM :
1291 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1292 return -1;
1293 /* FALLTHROUGH */
1295 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
1296 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1297 if (tpdu_nr & 0x80)
1298 tpdu_nr = tpdu_nr & 0x7F;
1299 else
1300 return -1;
1301 is_extended = FALSE;
1302 break;
1304 case LI_EXTENDED_DT_WITH_CHECKSUM :
1305 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1306 return -1;
1307 /* FALLTHROUGH */
1309 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1310 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1311 if (tpdu_nr & 0x80000000)
1312 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1313 else
1314 return -1;
1315 is_extended = TRUE;
1316 break;
1318 default : /* bad TPDU */
1319 return -1;
1320 } /* li */
1321 } else {
1322 /* check packet length indicators of ATN Expedited Data (ED) TPDU
1323 * note: use of checksum depends on the selected RER
1324 * (high:non-use medium:16-bit OSI/16-bit ext.ATN low:32-bit ext. ATN)
1326 * note: sole use of TP4 class in the ATN
1327 * note: normal/extended TPDU numbering is negociable */
1328 switch (li) {
1330 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
1331 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1332 if (tpdu_nr & 0x80)
1333 tpdu_nr = tpdu_nr & 0x7F;
1334 else
1335 return -1;
1336 is_extended = FALSE;
1337 break;
1339 case LI_NORMAL_DT_WITH_CHECKSUM :
1340 if ((tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
1341 (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16))
1342 return -1;
1344 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1345 if (tpdu_nr & 0x80)
1346 tpdu_nr = tpdu_nr & 0x7F;
1347 else
1348 return -1;
1349 is_extended = FALSE;
1350 break;
1352 case LI_ATN_NORMAL_DT_WITH_CHECKSUM :
1353 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1354 return -1;
1356 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1357 if (tpdu_nr & 0x80)
1358 tpdu_nr = tpdu_nr & 0x7F;
1359 else
1360 return -1;
1361 is_extended = FALSE;
1362 break;
1364 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1365 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1366 if (tpdu_nr & 0x80000000)
1367 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1368 else
1369 return -1;
1370 is_extended = TRUE;
1371 break;
1373 case LI_EXTENDED_DT_WITH_CHECKSUM :
1374 if ((tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM) &&
1375 (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16))
1376 return -1;
1378 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1379 if (tpdu_nr & 0x80000000)
1380 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1381 else
1382 return -1;
1383 is_extended = TRUE;
1384 break;
1386 case LI_ATN_EXTENDED_DT_WITH_CHECKSUM :
1387 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1388 return -1;
1390 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1391 if (tpdu_nr & 0x80000000)
1392 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1393 else
1394 return -1;
1395 is_extended = TRUE;
1396 break;
1398 default : /* bad TPDU */
1399 return -1;
1400 } /* li */
1401 } /* cotp_decode_atn */
1403 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1404 pinfo->clnp_dstref = dst_ref;
1406 col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
1407 tpdu_nr, dst_ref);
1409 if (tree) {
1410 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1411 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1412 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1414 offset += 1;
1416 if (tree) {
1417 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1419 offset += 1;
1420 li -= 1;
1422 if (tree)
1423 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1424 offset += 2;
1425 li -= 2;
1427 if (is_extended) {
1428 if (tree) {
1429 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset,
1430 4, tpdu_nr);
1432 offset += 4;
1433 li -= 4;
1434 } else {
1435 if (tree) {
1436 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1437 tpdu_nr);
1439 offset += 1;
1440 li -= 1;
1443 if (tree)
1444 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1445 offset += li;
1448 * XXX - hand this to subdissectors but tell them that this is
1449 * in an ED packet?
1451 next_tvb = tvb_new_subset_remaining(tvb, offset);
1452 call_dissector(data_handle,next_tvb, pinfo, tree);
1454 offset += tvb_length_remaining(tvb, offset);
1455 /* we dissected all of the containing PDU */
1457 return offset;
1459 } /* ositp_decode_ED */
1461 static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1462 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1464 proto_tree *cotp_tree;
1465 proto_item *ti;
1466 proto_item *item = NULL;
1467 guint16 dst_ref;
1468 guint tpdu_nr;
1469 gushort credit = 0;
1471 /* note: in the ATN the user is up to chose between 3 different checksums:
1472 * standard OSI, 2 or 4 octet extended checksum.
1473 * The difference for RJ is that the TPDU header may be enlarged by 2 octets
1474 * for checksum parameters are not going to be checked here */
1475 if (!cotp_decode_atn) { /* non ATN, plain OSI */
1476 switch(li) {
1477 case LI_NORMAL_RJ :
1478 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1479 break;
1480 case LI_EXTENDED_RJ :
1481 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1482 credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1483 break;
1484 default :
1485 return -1;
1487 } else {
1488 switch(li) {
1489 /* normal with 2 octets of OSI or ATN checksum */
1490 case LI_NORMAL_RJ :
1491 /* with 4 octets of ATN checksum */
1492 case LI_ATN_NORMAL_RJ :
1493 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1494 break;
1495 /* extended with 2 octets of OSI or ATN checksum */
1496 case LI_EXTENDED_RJ :
1497 /* with 4 octets of ATN checksum */
1498 case LI_ATN_EXTENDED_RJ :
1499 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1500 credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1501 break;
1502 default :
1503 return -1;
1507 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1508 pinfo->clnp_dstref = dst_ref;
1510 col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
1511 tpdu_nr, dst_ref);
1513 if (tree) {
1514 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1515 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1516 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1517 item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset + 1, 1,
1518 tpdu);
1519 if (li == LI_NORMAL_RJ)
1520 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1, "Credit: %u", cdt);
1521 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2,
1522 dst_ref);
1523 if (li == LI_NORMAL_RJ)
1524 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset + 4,
1525 1, tpdu_nr);
1526 else {
1527 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1528 offset + 4, 4, tpdu_nr);
1529 proto_tree_add_text(cotp_tree, tvb, offset + 8, 2, "Credit: 0x%02x",
1530 credit);
1534 offset += li + 1;
1536 expert_add_info_format(pinfo, item, &ei_cotp_reject, "Reject(RJ): -> 0x%x", dst_ref);
1538 return offset;
1540 } /* ositp_decode_RJ */
1542 static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1543 packet_info *pinfo, proto_tree *tree,
1544 gboolean uses_inactive_subset,
1545 gboolean *subdissector_found)
1547 /* note: in the ATN the user is up to chose between 3 different checksums:
1548 * standard OSI, 2 or 4 octet extended checksum.
1549 * Nothing has to be done here, for all ATN specifics are handled in VP. */
1551 /* CC & CR decoding in the same function */
1553 proto_tree *cotp_tree = NULL;
1554 proto_item *ti;
1555 proto_item *item = NULL;
1556 guint16 dst_ref, src_ref;
1557 guint8 class_option;
1558 tvbuff_t *next_tvb;
1559 guint tpdu_len;
1561 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1563 class_option = tvb_get_guint8(tvb, offset + P_CLASS_OPTION);
1564 if (((class_option & 0xF0) >> 4) > 4) /* class 0..4 allowed */
1565 return -1;
1567 /* CR and CC TPDUs can have user data, so they run to the end of the
1568 * containing PDU */
1569 tpdu_len = tvb_reported_length_remaining(tvb, offset);
1571 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1572 pinfo->clnp_srcref = src_ref;
1573 pinfo->clnp_dstref = dst_ref;
1575 col_append_fstr(pinfo->cinfo, COL_INFO,
1576 "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1577 (tpdu == CR_TPDU) ? "CR" : "CC", src_ref, dst_ref);
1579 if (tree) {
1580 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1581 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1582 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1584 offset += 1;
1586 if (tree) {
1587 item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1589 offset += 1;
1590 li -= 1;
1592 if (tree)
1593 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1594 offset += 2;
1595 li -= 2;
1597 if (tree)
1598 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1599 offset += 2;
1600 li -= 2;
1602 /* expert info, but only if not encapsulated in TCP/SMB */
1603 /* XXX - the best way to detect seems to be if we have a port set */
1604 if (pinfo->destport == 0) {
1605 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);
1608 if (tree) {
1609 proto_tree_add_uint(cotp_tree, hf_cotp_class, tvb, offset, 1, class_option);
1610 proto_tree_add_boolean(cotp_tree, hf_cotp_opts_extended_formats, tvb,
1611 offset, 1, class_option);
1612 proto_tree_add_boolean(cotp_tree, hf_cotp_opts_no_explicit_flow_control,
1613 tvb, offset, 1, class_option);
1615 offset += 1;
1616 li -= 1;
1618 if (tree) {
1619 /* Microsoft runs their Remote Desktop Protocol atop ISO COTP
1620 atop TPKT, and does some weird stuff in the CR packet:
1622 http://msdn.microsoft.com/en-us/library/cc240470
1624 where they might stuff a string that begins with "Cookie: ",
1625 possibly followed by an RDP Negotiation Request, into the
1626 variable part of the CR packet. (See also
1628 http://download.microsoft.com/download/5/B/C/5BC37A4E-6304-45AB-8C2D-AE712526E7F7/TS_Session_Directory.pdf
1630 a/k/a "[MSFT-SDLBTS]", as linked to, under the name "Session
1631 Directory and Load Balancing Using Terminal Server", on
1633 http://msdn.microsoft.com/en-us/library/E4BD6494-06AD-4aed-9823-445E921C9624
1635 which indicates that the routingToken is a string of the form
1636 "Cookie: msts=...".)
1638 They also may stuff an RDP Negotiation Response into the CC
1639 packet.
1641 XXX - have TPKT know that a given session is an RDP session,
1642 and let us know, so we know whether to check for this stuff. */
1643 ositp_decode_var_part(tvb, offset, li, class_option, tpdu_len , pinfo,
1644 cotp_tree);
1646 offset += li;
1649 * XXX - tell the subdissector that this is user data in a CC or
1650 * CR packet rather than a DT packet?
1652 next_tvb = tvb_new_subset_remaining(tvb, offset);
1653 if (!uses_inactive_subset){
1654 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb, pinfo,
1655 tree, NULL)) {
1656 *subdissector_found = TRUE;
1657 } else {
1658 call_dissector(data_handle,next_tvb, pinfo, tree);
1661 else
1662 call_dissector(data_handle, next_tvb, pinfo, tree);
1663 offset += tvb_length_remaining(tvb, offset);
1664 /* we dissected all of the containing PDU */
1666 return offset;
1668 } /* ositp_decode_CC */
1670 static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1671 packet_info *pinfo, proto_tree *tree)
1673 proto_tree *cotp_tree = NULL;
1674 proto_item *ti;
1675 proto_item *item = NULL;
1676 guint16 dst_ref, src_ref;
1677 guint tpdu_len;
1679 /* ATN may use checksums different from OSI */
1680 /* which may result in different TPDU header length. */
1681 if (!cotp_decode_atn) {
1682 if (li > LI_MAX_DC)
1683 return -1;
1684 } else {
1685 if (li > LI_ATN_MAX_DC)
1686 return -1;
1689 /* DC TPDUs have no user data, so the length indicator determines the
1690 * length */
1691 tpdu_len = li + 1;
1693 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1694 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1695 pinfo->clnp_dstref = dst_ref;
1696 pinfo->clnp_dstref = src_ref;
1698 col_append_fstr(pinfo->cinfo, COL_INFO,
1699 "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, dst_ref);
1701 if (tree) {
1702 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1703 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1704 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1706 offset += 1;
1708 if (tree) {
1709 item = proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1711 offset += 1;
1712 li -= 1;
1714 if (tree)
1715 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1716 offset += 2;
1717 li -= 2;
1719 if (tree)
1720 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1721 offset += 2;
1722 li -= 2;
1724 if (tree)
1725 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1726 offset += li;
1728 expert_add_info_format(pinfo, item, &ei_cotp_disconnect_confirm, "Disconnect Confirm(DC): 0x%x -> 0x%x", src_ref, dst_ref);
1730 return offset;
1732 } /* ositp_decode_DC */
1734 static int ositp_decode_AK(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1735 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1737 proto_tree *cotp_tree = NULL;
1738 proto_item *ti;
1739 guint16 dst_ref;
1740 guint tpdu_nr;
1741 gushort cdt_in_ak;
1742 guint tpdu_len;
1744 if (!cotp_decode_atn) {
1745 if (li > LI_MAX_AK)
1746 return -1;
1747 } else {
1748 if (li > LI_ATN_MAX_AK)
1749 return -1;
1752 /* AK TPDUs have no user data, so the length indicator determines the
1753 * length */
1754 tpdu_len = li + 1;
1756 /* is_LI_NORMAL_AK() works for normal ATN AK's, */
1757 /* for the TPDU header size may be enlarged by 2 octets */
1758 if (is_LI_NORMAL_AK(li)) {
1760 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1761 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1762 pinfo->clnp_dstref = dst_ref;
1764 col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1765 tpdu_nr, dst_ref);
1767 if (tree) {
1768 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1769 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1770 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1772 offset += 1;
1774 if (tree) {
1775 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1776 proto_tree_add_text(cotp_tree, tvb, offset, 1, "Credit: %u", cdt);
1778 offset += 1;
1779 li -= 1;
1781 if (tree)
1782 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1783 offset += 2;
1784 li -= 2;
1786 if (tree) {
1787 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1788 tpdu_nr);
1790 offset += 1;
1791 li -= 1;
1793 if (tree)
1794 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1795 offset += li;
1797 } else { /* extended format */
1799 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1800 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1801 cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1802 pinfo->clnp_dstref = dst_ref;
1804 col_append_fstr(pinfo->cinfo, COL_INFO,
1805 "AK TPDU (%u) dst-ref: 0x%04x Credit: %u",
1806 tpdu_nr, dst_ref, cdt_in_ak);
1808 if (tree) {
1809 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1810 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1811 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1813 offset += 1;
1815 if (tree) {
1816 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
1818 offset += 1;
1819 li -= 1;
1821 if (tree)
1822 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1823 offset += 2;
1824 li -= 2;
1826 if (tree) {
1827 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1828 offset, 4, tpdu_nr);
1830 offset += 4;
1831 li -= 4;
1833 if (tree) {
1834 proto_tree_add_text(cotp_tree, tvb, offset, 2, "Credit: 0x%04x",
1835 cdt_in_ak);
1837 offset += 2;
1838 li -= 2;
1840 if (tree)
1841 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
1842 offset += li;
1844 } /* is_LI_NORMAL_AK */
1846 return offset;
1848 } /* ositp_decode_AK */
1850 static int ositp_decode_EA(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1851 packet_info *pinfo, proto_tree *tree)
1853 proto_tree *cotp_tree = NULL;
1854 proto_item *ti;
1855 gboolean is_extended;
1856 guint16 dst_ref;
1857 guint tpdu_nr;
1858 guint tpdu_len;
1860 /* Due to different checksums in the ATN the TPDU header sizes
1861 * as well as the checksum parameters may be different than plain OSI EA
1862 * because these are heavily checked for EA these checks had to be
1863 * re-implemented.
1864 * note: this could not be tested, because no sample was avail for expedited
1865 * data */
1866 if (!cotp_decode_atn) {
1867 if (li > LI_MAX_EA)
1868 return -1;
1870 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1871 (This means we may misdissect this if the packet is bad and
1872 contains other parameters.) */
1873 switch (li) {
1875 case LI_NORMAL_EA_WITH_CHECKSUM :
1876 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
1877 tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1878 return -1;
1879 /* FALLTHROUGH */
1881 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1882 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1883 is_extended = FALSE;
1884 break;
1886 case LI_EXTENDED_EA_WITH_CHECKSUM :
1887 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
1888 tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1889 return -1;
1890 /* FALLTHROUGH */
1892 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1893 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1894 is_extended = TRUE;
1895 break;
1897 default : /* bad TPDU */
1898 return -1;
1899 } /* li */
1900 } else { /* cotp_decode_atn */
1901 /* check for ATN length: TPDU may be 2 octets longer due to checksum */
1902 if (li > LI_ATN_MAX_EA)
1903 return -1;
1905 switch (li) {
1907 /* extended TPDU numbering EA with no checksum */
1908 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1909 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1910 is_extended = FALSE;
1911 break;
1913 /* normal TPDU numbering EA with 2 octets of OSI or ATN extended
1914 * checksum */
1915 case LI_NORMAL_EA_WITH_CHECKSUM :
1916 /* check checksum parameter (in VP) parameter code octet */
1917 if ((tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM) &&
1918 (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_16))
1919 return -1;
1921 /* check checksum parameter (in VP) length octet */
1922 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1923 return -1;
1925 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1926 is_extended = FALSE;
1927 break;
1929 /* normal TPDU numbering EA with 4 octets of ATN extended checksum */
1930 case LI_ATN_NORMAL_EA_WITH_CHECKSUM :
1931 /* check checksum parameter (in VP) parameter code octet */
1932 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_ATN_EC_32)
1933 return -1;
1935 /* check checksum parameter (in VP) length octet */
1936 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 4)
1937 return -1;
1939 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1940 is_extended = FALSE;
1941 break;
1943 /* extended TPDU numbering EA with no checksum */
1944 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1945 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1946 is_extended = TRUE;
1947 break;
1949 /* extended TPDU numbering EA with 2 octets of OSI or ATN extended
1950 * checksum */
1951 case LI_EXTENDED_EA_WITH_CHECKSUM :
1952 /* check checksum parameter (in VP) parameter code octet */
1953 if ((tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM) &&
1954 (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_16))
1955 return -1;
1957 /* check checksum parameter (in VP) length octet */
1958 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1959 return -1;
1961 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1962 is_extended = TRUE;
1963 break;
1965 /* extended EA with 4 octets ATN extended checksum */
1966 case LI_ATN_EXTENDED_EA_WITH_CHECKSUM :
1967 /* check checksum parameter (in VP) parameter code octet */
1968 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_ATN_EC_32)
1969 return -1;
1971 /* check checksum parameter (in VP) length octet */
1972 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1973 return -1;
1975 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1976 is_extended = TRUE;
1977 break;
1979 default : /* bad TPDU */
1980 return -1;
1984 /* ER TPDUs have no user data, so the length indicator determines the
1985 * length */
1986 tpdu_len = li + 1;
1988 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1989 pinfo->clnp_dstref = dst_ref;
1991 col_append_fstr(pinfo->cinfo, COL_INFO, "EA TPDU (%u) dst-ref: 0x%04x",
1992 tpdu_nr, dst_ref);
1994 if (tree) {
1995 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
1996 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1997 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
1999 offset += 1;
2001 if (tree) {
2002 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu);
2004 offset += 1;
2005 li -= 1;
2007 if (tree)
2008 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
2009 offset += 2;
2010 li -= 2;
2012 if (is_extended) {
2013 if (tree) {
2014 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
2015 offset, 4, tpdu_nr);
2017 offset += 4;
2018 li -= 4;
2019 } else {
2020 if (tree) {
2021 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
2022 tpdu_nr);
2024 offset += 1;
2025 li -= 1;
2028 if (tree)
2029 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
2030 offset += li;
2032 return offset;
2034 } /* ositp_decode_EA */
2036 static int ositp_decode_ER(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
2037 packet_info *pinfo, proto_tree *tree)
2039 proto_tree *cotp_tree = NULL;
2040 proto_item *ti;
2041 const char *str;
2042 guint16 dst_ref;
2043 guint8 tpdu_len;
2045 /* ATN: except for modified LI checking nothing to be done here */
2046 if (!cotp_decode_atn) {
2047 if (li > LI_MAX_ER)
2048 return -1;
2049 } else {
2050 if (li > LI_ATN_MAX_ER)
2051 return -1;
2054 /* ER TPDUs have no user data, so the length indicator determines the
2055 * length */
2056 tpdu_len = li + 1;
2058 switch(tvb_get_guint8(tvb, offset + P_REJECT_ER)) {
2059 case 0 :
2060 str = "Reason not specified";
2061 break;
2062 case 1 :
2063 str = "Invalid parameter code";
2064 break;
2065 case 2 :
2066 str = "Invalid TPDU type";
2067 break;
2068 case 3 :
2069 str = "Invalid parameter value";
2070 break;
2071 default:
2072 return -1;
2075 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
2076 pinfo->clnp_dstref = dst_ref;
2078 col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
2080 if (tree) {
2081 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, ENC_NA);
2082 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
2083 proto_tree_add_uint(cotp_tree, hf_cotp_li, tvb, offset, 1,li);
2084 proto_tree_add_uint(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu);
2085 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2,
2086 dst_ref);
2087 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1, "Reject cause: %s",
2088 str);
2090 offset += 5;
2091 li -= 4;
2093 if (tree)
2094 ositp_decode_var_part(tvb, offset, li, 4, tpdu_len, pinfo, cotp_tree);
2095 offset += li;
2097 return offset;
2099 } /* ositp_decode_ER */
2101 static int ositp_decode_UD(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
2102 packet_info *pinfo, proto_tree *tree,
2103 gboolean *subdissector_found)
2105 proto_item *ti;
2106 proto_tree *cltp_tree = NULL;
2107 tvbuff_t *next_tvb;
2108 guint tpdu_len;
2110 /* UD TPDUs have user data, so they run to the end of the containing PDU */
2111 tpdu_len = tvb_reported_length_remaining(tvb, offset);
2113 col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
2115 if (tree) {
2116 ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, ENC_NA);
2117 cltp_tree = proto_item_add_subtree(ti, ett_cltp);
2118 proto_tree_add_uint(cltp_tree, hf_cltp_li, tvb, offset, 1,li);
2120 offset += 1;
2122 if (tree) {
2123 proto_tree_add_uint(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu);
2125 offset += 1;
2126 li -= 1;
2128 if (tree)
2129 ositp_decode_var_part(tvb, offset, li, 0, tpdu_len, pinfo, cltp_tree);
2130 offset += li;
2132 next_tvb = tvb_new_subset_remaining(tvb, offset);
2134 if (dissector_try_heuristic(cltp_heur_subdissector_list, next_tvb,
2135 pinfo, tree, NULL)) {
2136 *subdissector_found = TRUE;
2137 } else {
2138 call_dissector(data_handle,next_tvb, pinfo, tree);
2142 /*call_dissector(data_handle,next_tvb, pinfo, tree); */
2144 offset += tvb_length_remaining(tvb, offset);
2145 /* we dissected all of the containing PDU */
2147 return offset;
2149 } /* ositp_decode_UD */
2151 /* Returns the offset past the last valid COTP or CLTP PDU if we found
2152 at least one valid COTP or CLTP PDU, 0 otherwise.
2154 There doesn't seem to be any way in which the OSI network layer protocol
2155 distinguishes between COTP and CLTP, but the first two octets of both
2156 protocols' headers mean the same thing - length and PDU type - and the
2157 only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
2158 both of them here. */
2159 static gint dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
2160 proto_tree *tree,
2161 gboolean uses_inactive_subset)
2163 int offset = 0;
2164 guint8 li, tpdu, cdt;
2165 gboolean first_tpdu = TRUE;
2166 int new_offset;
2167 gboolean found_ositp = FALSE;
2168 gboolean is_cltp = FALSE;
2169 gboolean subdissector_found = FALSE;
2171 if (!proto_is_protocol_enabled(find_protocol_by_id(proto_cotp)))
2172 return FALSE; /* COTP has been disabled */
2173 /* XXX - what about CLTP? */
2175 pinfo->current_proto = "COTP";
2177 /* Initialize the COL_INFO field; each of the TPDUs will have its
2178 information appended. */
2179 col_set_str(pinfo->cinfo, COL_INFO, "");
2181 while (tvb_offset_exists(tvb, offset)) {
2182 if (!first_tpdu) {
2183 col_append_str(pinfo->cinfo, COL_INFO, ", ");
2184 expert_add_info(pinfo, NULL, &ei_cotp_multiple_tpdus);
2185 /* adjust tvb and offset to the start of the current PDU */
2186 tvb = tvb_new_subset_remaining(tvb, offset);
2187 offset = 0 ;
2189 if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
2190 col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
2191 if (!first_tpdu)
2192 call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset),
2193 pinfo, tree);
2194 return found_ositp;
2197 tpdu = (tvb_get_guint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
2198 if (tpdu == UD_TPDU)
2199 pinfo->current_proto = "CLTP"; /* connectionless transport */
2200 cdt = tvb_get_guint8(tvb, offset + P_CDT) & 0x0F;
2202 switch (tpdu) {
2203 case CC_TPDU :
2204 case CR_TPDU :
2205 new_offset = ositp_decode_CC(tvb, offset, li, tpdu, pinfo, tree,
2206 uses_inactive_subset, &subdissector_found);
2207 break;
2208 case DR_TPDU :
2209 new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
2210 break;
2211 case DT_TPDU :
2212 new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
2213 uses_inactive_subset, &subdissector_found);
2214 break;
2215 case ED_TPDU :
2216 new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree);
2217 break;
2218 case RJ_TPDU :
2219 new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
2220 break;
2221 case DC_TPDU :
2222 new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
2223 break;
2224 case AK_TPDU :
2225 new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
2226 break;
2227 case EA_TPDU :
2228 new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
2229 break;
2230 case ER_TPDU :
2231 new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
2232 break;
2233 case UD_TPDU :
2234 new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree,
2235 &subdissector_found);
2236 is_cltp = TRUE;
2237 break;
2238 default :
2239 if (first_tpdu)
2240 col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)",
2241 tpdu);
2242 new_offset = -1; /* bad PDU type */
2243 break;
2246 if (new_offset == -1) { /* incorrect TPDU */
2247 if (!first_tpdu)
2248 call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset),
2249 pinfo, tree);
2250 break;
2253 if (first_tpdu) {
2254 /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
2255 is either COTP or CLTP. */
2256 if (!subdissector_found)
2257 col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
2258 found_ositp = TRUE;
2261 offset = new_offset;
2262 first_tpdu = FALSE;
2264 return found_ositp ? offset : 0;
2265 } /* dissect_ositp_internal */
2267 static gint dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2268 void *data _U_)
2270 return dissect_ositp_internal(tvb, pinfo, tree, FALSE);
2273 static gint dissect_ositp_inactive(tvbuff_t *tvb, packet_info *pinfo,
2274 proto_tree *tree, void *data _U_)
2276 return dissect_ositp_internal(tvb, pinfo, tree, TRUE);
2279 static void
2280 cotp_reassemble_init(void)
2283 * XXX - this is a connection-oriented transport-layer protocol,
2284 * so we should probably use more than just network-layer
2285 * endpoint addresses to match segments together, but the functions
2286 * in addresses_ports_reassembly_table_functions do matching based
2287 * on port numbers, so they won't let us ensure that segments from
2288 * different connections don't get assembled together.
2290 reassembly_table_init(&cotp_reassembly_table,
2291 &addresses_reassembly_table_functions);
2292 cotp_dst_ref = 0;
2295 void proto_register_cotp(void)
2297 static hf_register_info hf[] = {
2298 { &hf_cotp_li,
2299 { "Length", "cotp.li", FT_UINT8, BASE_DEC,
2300 NULL, 0x0, "Length Indicator, length of this header", HFILL}},
2301 { &hf_cotp_type,
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}},
2305 { &hf_cotp_srcref,
2306 { "Source reference", "cotp.srcref", FT_UINT16, BASE_HEX,
2307 NULL, 0x0, "Source address reference", HFILL}},
2308 { &hf_cotp_destref,
2309 { "Destination reference", "cotp.destref", FT_UINT16, BASE_HEX,
2310 NULL, 0x0, "Destination address reference", HFILL}},
2311 { &hf_cotp_class,
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",
2320 HFILL}},
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}},
2333 { &hf_cotp_eot,
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 }},
2364 { &hf_cotp_segment,
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 }}
2396 static gint *ett[] = {
2397 &ett_cotp,
2398 &ett_cotp_segment,
2399 &ett_cotp_segments
2401 static ei_register_info ei[] = {
2402 { &ei_cotp_disconnect_request, { "cotp.disconnect_request", PI_SEQUENCE, PI_CHAT, "Disconnect Request(DR): 0x%x -> 0x%x", EXPFILL }},
2403 { &ei_cotp_reject, { "cotp.reject", PI_SEQUENCE, PI_NOTE, "Reject(RJ): -> 0x%x", EXPFILL }},
2404 { &ei_cotp_connection, { "cotp.connection", PI_SEQUENCE, PI_CHAT, "Connection %s: 0x%x -> 0x%x", EXPFILL }},
2405 { &ei_cotp_disconnect_confirm, { "cotp.disconnect_confirm", PI_SEQUENCE, PI_CHAT, "Disconnect Confirm(DC): 0x%x -> 0x%x", EXPFILL }},
2406 { &ei_cotp_multiple_tpdus, { "cotp.multiple_tpdus", PI_SEQUENCE, PI_NOTE, "Multiple TPDUs in one packet", EXPFILL }},
2409 module_t *cotp_module;
2410 expert_module_t* expert_cotp;
2412 proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "COTP", "cotp");
2413 proto_register_field_array(proto_cotp, hf, array_length(hf));
2414 proto_register_subtree_array(ett, array_length(ett));
2415 expert_cotp = expert_register_protocol(proto_cotp);
2416 expert_register_field_array(expert_cotp, ei, array_length(ei));
2417 cotp_module = prefs_register_protocol(proto_cotp, NULL);
2419 prefs_register_bool_preference(cotp_module, "reassemble",
2420 "Reassemble segmented COTP datagrams",
2421 "Whether segmented COTP datagrams should be "
2422 "reassembled. To use this option, you must "
2423 "also enable \"Allow subdissectors to "
2424 "reassemble TCP streams\" in the TCP "
2425 "protocol settings.",
2426 &cotp_reassemble);
2428 prefs_register_enum_preference(cotp_module, "tsap_display",
2429 "Display TSAPs as strings or bytes",
2430 "How TSAPs should be displayed",
2431 &tsap_display, tsap_display_options, FALSE);
2433 prefs_register_bool_preference(cotp_module, "decode_atn", "Decode ATN TPDUs",
2434 "Whether to decode OSI TPDUs with ATN "
2435 "(Aereonautical Telecommunications Network) "
2436 "extensions. To use this option, you must "
2437 "also enable \"Always try to decode NSDU as "
2438 "transport PDUs\" in the CLNP protocol "
2439 "settings.", &cotp_decode_atn);
2441 /* subdissector code in inactive subset */
2442 register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
2444 /* other COTP/ISO 8473 subdissectors */
2445 register_heur_dissector_list("cotp", &cotp_heur_subdissector_list);
2447 /* XXX - what about CLTP and proto_cltp? */
2448 new_register_dissector("ositp", dissect_ositp, proto_cotp);
2449 new_register_dissector("ositp_inactive", dissect_ositp_inactive, proto_cotp);
2451 register_init_routine(cotp_reassemble_init);
2454 void proto_register_cltp(void)
2456 static hf_register_info hf[] = {
2457 { &hf_cltp_li,
2458 { "Length", "cltp.li", FT_UINT8, BASE_DEC, NULL, 0x0,
2459 "Length Indicator, length of this header", HFILL}},
2460 { &hf_cltp_type,
2461 { "PDU Type", "cltp.type", FT_UINT8, BASE_HEX,
2462 VALS(cltp_tpdu_type_abbrev_vals), 0x0, NULL, HFILL}}
2464 static gint *ett[] = {
2465 &ett_cltp
2468 proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "CLTP", "cltp");
2469 proto_register_field_array(proto_cltp, hf, array_length(hf));
2470 proto_register_subtree_array(ett, array_length(ett));
2472 register_heur_dissector_list("cltp", &cltp_heur_subdissector_list);
2475 void
2476 proto_reg_handoff_cotp(void)
2478 dissector_handle_t ositp_handle;
2480 ositp_handle = find_dissector("ositp");
2481 dissector_add_uint("ip.proto", IP_PROTO_TP, ositp_handle);
2483 data_handle = find_dissector("data");
2485 proto_clnp = proto_get_id_by_filter_name("clnp");
2489 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2491 * Local variables:
2492 * c-basic-offset: 2
2493 * tab-width: 2
2494 * indent-tabs-mode: nil
2495 * End:
2497 * vi: set shiftwidth=2 tabstop=2 expandtab:
2498 * :indentSize=2:tabSize=2:noTabs=true: