2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-clnp.c,v 1.86 2004/06/20 01:05:07 guy Exp $
5 * Laurent Deniel <laurent.deniel@free.fr>
6 * Ralf Schneider <Ralf.Schneider@t-online.de>
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include <epan/packet.h>
36 #include "reassemble.h"
37 #include "packet-osi.h"
38 #include "packet-osi-options.h"
39 #include "packet-isis.h"
40 #include "packet-esis.h"
44 /* protocols and fields */
46 static int proto_clnp = -1;
47 static gint ett_clnp = -1;
48 static gint ett_clnp_type = -1;
49 static gint ett_clnp_segments = -1;
50 static gint ett_clnp_segment = -1;
51 static gint ett_clnp_disc_pdu = -1;
53 static int hf_clnp_id = -1;
54 static int hf_clnp_length = -1;
55 static int hf_clnp_version = -1;
56 static int hf_clnp_ttl = -1;
57 static int hf_clnp_type = -1;
58 static int hf_clnp_pdu_length = -1;
59 static int hf_clnp_checksum = -1;
60 static int hf_clnp_dest_length = -1;
61 static int hf_clnp_dest = -1;
62 static int hf_clnp_src_length = -1;
63 static int hf_clnp_src = -1;
64 static int hf_clnp_segments = -1;
65 static int hf_clnp_segment = -1;
66 static int hf_clnp_segment_overlap = -1;
67 static int hf_clnp_segment_overlap_conflict = -1;
68 static int hf_clnp_segment_multiple_tails = -1;
69 static int hf_clnp_segment_too_long_segment = -1;
70 static int hf_clnp_segment_error = -1;
71 static int hf_clnp_reassembled_in = -1;
73 static int proto_cotp = -1;
74 static gint ett_cotp = -1;
75 static gint ett_cotp_segments = -1;
76 static gint ett_cotp_segment = -1;
78 static int hf_cotp_srcref = -1;
79 static int hf_cotp_destref = -1;
80 static int hf_cotp_type = -1;
81 static int hf_cotp_segments = -1;
82 static int hf_cotp_segment = -1;
83 static int hf_cotp_segment_overlap = -1;
84 static int hf_cotp_segment_overlap_conflict = -1;
85 static int hf_cotp_segment_multiple_tails = -1;
86 static int hf_cotp_segment_too_long_segment = -1;
87 static int hf_cotp_segment_error = -1;
88 static int hf_cotp_reassembled_in = -1;
90 static int proto_cltp = -1;
91 static gint ett_cltp = -1;
93 static int hf_cltp_type = -1;
95 static const fragment_items clnp_frag_items = {
100 &hf_clnp_segment_overlap,
101 &hf_clnp_segment_overlap_conflict,
102 &hf_clnp_segment_multiple_tails,
103 &hf_clnp_segment_too_long_segment,
104 &hf_clnp_segment_error,
105 &hf_clnp_reassembled_in,
109 static const fragment_items cotp_frag_items = {
114 &hf_cotp_segment_overlap,
115 &hf_cotp_segment_overlap_conflict,
116 &hf_cotp_segment_multiple_tails,
117 &hf_cotp_segment_too_long_segment,
118 &hf_cotp_segment_error,
119 &hf_cotp_reassembled_in,
123 static dissector_handle_t clnp_handle;
124 static dissector_handle_t data_handle;
127 * ISO 8473 OSI CLNP definition (see RFC994)
129 * _________________________________
131 * |_________________________________|
133 * |_________________________________|
134 * | Segmentation Part (optional) |
135 * |_________________________________|
136 * | Options Part (optional) |
137 * |_________________________________|
138 * | Data (optional) |
139 * |_________________________________|
142 #define ISO8473_V1 0x01 /* CLNP version 1 */
146 #define CNF_TYPE 0x1f
147 #define CNF_ERR_OK 0x20
148 #define CNF_MORE_SEGS 0x40
149 #define CNF_SEG_OK 0x80
154 #define ERQ_NPDU 0x1E
155 #define ERP_NPDU 0x1F
157 static const value_string npdu_type_abbrev_vals[] = {
166 static const value_string npdu_type_vals[] = {
168 { MD_NPDU, "Multicast Data" },
169 { ER_NPDU, "Error Report" },
170 { ERQ_NPDU, "Echo Request" },
171 { ERP_NPDU, "Echo Response" },
177 #define P_CLNP_PROTO_ID 0
178 #define P_CLNP_HDR_LEN 1
179 #define P_CLNP_VERS 2
181 #define P_CLNP_TYPE 4
182 #define P_CLNP_SEGLEN 5
183 #define P_CLNP_CKSUM 7
184 #define P_CLNP_ADDRESS_PART 9
186 /* Segmentation part */
188 struct clnp_segment {
189 gushort cng_id; /* data unit identifier */
190 gushort cng_off; /* segment offset */
191 gushort cng_tot_len; /* total length */
196 #define NSEL_NET 0x00
201 * ISO8073 OSI COTP definition (see RFC905)
204 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
206 /* TPDU definition */
208 #define ED_TPDU 0x1 /* COTP */
209 #define EA_TPDU 0x2 /* COTP */
210 #define UD_TPDU 0x4 /* CLTP */
211 #define RJ_TPDU 0x5 /* COTP */
212 #define AK_TPDU 0x6 /* COTP */
213 #define ER_TPDU 0x7 /* COTP */
214 #define DR_TPDU 0x8 /* COTP */
215 #define DC_TPDU 0xC /* COTP */
216 #define CC_TPDU 0xD /* COTP */
217 #define CR_TPDU 0xE /* COTP */
218 #define DT_TPDU 0xF /* COTP */
220 static const value_string cotp_tpdu_type_abbrev_vals[] = {
234 static const value_string cltp_tpdu_type_abbrev_vals[] = {
246 #define P_TPDU_NR_0_1 2
247 #define P_TPDU_NR_234 4
248 #define P_VAR_PART_NDT 5
249 #define P_VAR_PART_EDT 8
250 #define P_VAR_PART_DC 6
251 #define P_CDT_IN_AK 8
252 #define P_CDT_IN_RJ 8
253 #define P_REJECT_ER 4
254 #define P_REASON_IN_DR 6
255 #define P_CLASS_OPTION 6
257 /* TPDU length indicator */
259 #define LI_NORMAL_DT_CLASS_01 2
260 #define LI_NORMAL_DT_WITH_CHECKSUM 8
261 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
262 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
263 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
264 #define LI_NORMAL_EA_WITH_CHECKSUM 8
265 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
266 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
267 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
268 #define LI_NORMAL_RJ 4
269 #define LI_EXTENDED_RJ 9
275 /* XXX - can we always decide this based on whether the length
276 indicator is odd or not? What if the variable part has an odd
278 #define is_LI_NORMAL_AK(p) ( ( p & 0x01 ) == 0 )
282 #define VP_ACK_TIME 0x85
283 #define VP_RES_ERROR 0x86
284 #define VP_PRIORITY 0x87
285 #define VP_TRANSIT_DEL 0x88
286 #define VP_THROUGHPUT 0x89
287 #define VP_SEQ_NR 0x8A /* in AK */
288 #define VP_REASSIGNMENT 0x8B
289 #define VP_FLOW_CNTL 0x8C /* in AK */
290 #define VP_TPDU_SIZE 0xC0
291 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
292 #define VP_DST_TSAP 0xC2
293 #define VP_CHECKSUM 0xC3
294 #define VP_VERSION_NR 0xC4
295 #define VP_PROTECTION 0xC5
296 #define VP_OPT_SEL 0xC6
297 #define VP_PROTO_CLASS 0xC7
298 #define VP_PREF_MAX_TPDU_SIZE 0xF0
299 #define VP_INACTIVITY_TIMER 0xF2
301 static const value_string tp_vpart_type_vals[] = {
302 { VP_ACK_TIME, "ack time" },
303 { VP_RES_ERROR, "res error" },
304 { VP_PRIORITY, "priority" },
305 { VP_TRANSIT_DEL, "transit delay" },
306 { VP_THROUGHPUT, "throughput" },
307 { VP_SEQ_NR, "seq number" },
308 { VP_REASSIGNMENT, "reassignment" },
309 { VP_FLOW_CNTL, "flow control" },
310 { VP_TPDU_SIZE, "tpdu-size" },
311 { VP_SRC_TSAP, "src-tsap" },
312 { VP_DST_TSAP, "dst-tsap" },
313 { VP_CHECKSUM, "checksum" },
314 { VP_VERSION_NR, "version" },
315 { VP_PROTECTION, "protection" },
316 { VP_OPT_SEL, "options" },
317 { VP_PROTO_CLASS, "proto class" },
318 { VP_PREF_MAX_TPDU_SIZE, "preferred max TPDU size" },
322 static int hf_cotp_vp_src_tsap = -1;
323 static int hf_cotp_vp_dst_tsap = -1;
324 static int hf_cotp_vp_src_tsap_bytes = -1;
325 static int hf_cotp_vp_dst_tsap_bytes = -1;
330 #define EXTRACT_SHORT(p) pntohs(p)
331 #define EXTRACT_LONG(p) pntohl(p)
333 /* global variables */
335 /* List of dissectors to call for COTP packets put atop the Inactive
337 static heur_dissector_list_t cotp_is_heur_subdissector_list;
338 /* List of dissectors to call for COTP packets put atop CLNP */
339 static heur_dissector_list_t cotp_heur_subdissector_list;
340 /* List of dissectors to call for CLNP packets */
341 static heur_dissector_list_t clnp_heur_subdissector_list;
344 * Reassembly of CLNP.
346 static GHashTable *clnp_segment_table = NULL;
347 static GHashTable *clnp_reassembled_table = NULL;
350 * Reassembly of COTP.
352 static GHashTable *cotp_segment_table = NULL;
353 static GHashTable *cotp_reassembled_table = NULL;
355 #define TSAP_DISPLAY_AUTO 0
356 #define TSAP_DISPLAY_STRING 1
357 #define TSAP_DISPLAY_BYTES 2
361 static guint tp_nsap_selector = NSEL_TP;
362 static gboolean always_decode_transport = FALSE;
363 static gboolean clnp_reassemble = FALSE;
364 static gboolean cotp_reassemble = FALSE;
365 static gint32 tsap_display = TSAP_DISPLAY_AUTO;
367 const enum_val_t tsap_display_options[] = {
368 {"auto", "As strings if printable", TSAP_DISPLAY_AUTO},
369 {"string", "As strings", TSAP_DISPLAY_STRING},
370 {"bytes", "As bytes", TSAP_DISPLAY_BYTES},
375 /* function definitions */
377 #define MAX_TSAP_LEN 32
378 static gboolean is_all_printable(const guchar *stringtocheck, int length)
380 gboolean allprintable;
384 for (i=0;i<length;i++) {
385 if (!(isascii(stringtocheck[i]) && isprint(stringtocheck[i]))) {
391 } /* is_all_printable */
394 static gchar *print_tsap(const guchar *tsap, int length)
397 static gchar str[3][MAX_TSAP_LEN * 2 + 3]; /* TSAP in hex + '0x' + NULL */
400 gboolean allprintable;
402 if (cur == &str[0][0]) {
404 } else if (cur == &str[1][0]) {
412 if (length <= 0 || length > MAX_TSAP_LEN)
413 sprintf(cur, "<unsupported TSAP length>");
415 allprintable = is_all_printable(tsap,length);
418 while (length != 0) {
420 sprintf(tmp, "%c", *tsap ++);
422 sprintf(tmp, "%02x", *tsap ++);
431 static gboolean ositp_decode_var_part(tvbuff_t *tvb, int offset,
432 int vp_length, int class_option,
437 guint16 s, s1,s2,s3,s4;
438 guint32 t1, t2, t3, t4;
439 guint32 pref_max_tpdu_size;
441 while (vp_length != 0) {
442 code = tvb_get_guint8(tvb, offset);
443 proto_tree_add_text(tree, tvb, offset, 1,
444 "Parameter code: 0x%02x (%s)",
446 val_to_str(code, tp_vpart_type_vals, "Unknown"));
452 length = tvb_get_guint8(tvb, offset);
453 proto_tree_add_text(tree, tvb, offset, 1,
454 "Parameter length: %u", length);
461 s = tvb_get_ntohs(tvb, offset);
462 proto_tree_add_text(tree, tvb, offset, length,
463 "Ack time (ms): %u", s);
469 proto_tree_add_text(tree, tvb, offset, 1,
470 "Residual error rate, target value: 10^%u",
471 tvb_get_guint8(tvb, offset));
476 proto_tree_add_text(tree, tvb, offset, 1,
477 "Residual error rate, minimum acceptable: 10^%u",
478 tvb_get_guint8(tvb, offset));
484 proto_tree_add_text(tree, tvb, offset, 1,
485 "Residual error rate, TSDU size of interest: %u",
486 1<<tvb_get_guint8(tvb, offset));
494 s = tvb_get_ntohs(tvb, offset);
495 proto_tree_add_text(tree, tvb, offset, length,
502 s1 = tvb_get_ntohs(tvb, offset);
503 proto_tree_add_text(tree, tvb, offset, 2,
504 "Transit delay, target value, calling-called: %u ms", s1);
509 s2 = tvb_get_ntohs(tvb, offset);
510 proto_tree_add_text(tree, tvb, offset, 2,
511 "Transit delay, maximum acceptable, calling-called: %u ms", s2);
516 s3 = tvb_get_ntohs(tvb, offset);
517 proto_tree_add_text(tree, tvb, offset, 2,
518 "Transit delay, target value, called-calling: %u ms", s3);
523 s4 = tvb_get_ntohs(tvb, offset);
524 proto_tree_add_text(tree, tvb, offset, 2,
525 "Transit delay, maximum acceptable, called-calling: %u ms", s4);
532 t1 = tvb_get_ntoh24(tvb, offset);
533 proto_tree_add_text(tree, tvb, offset, 3,
534 "Maximum throughput, target value, calling-called: %u o/s", t1);
539 t2 = tvb_get_ntoh24(tvb, offset);
540 proto_tree_add_text(tree, tvb, offset, 3,
541 "Maximum throughput, minimum acceptable, calling-called: %u o/s", t2);
546 t3 = tvb_get_ntoh24(tvb, offset);
547 proto_tree_add_text(tree, tvb, offset, 3,
548 "Maximum throughput, target value, called-calling: %u o/s", t3);
553 t4 = tvb_get_ntoh24(tvb, offset);
554 proto_tree_add_text(tree, tvb, offset, 3,
555 "Maximum throughput, minimum acceptable, called-calling: %u o/s", t4);
560 if (length != 0) { /* XXX - should be 0 or 12 */
561 t1 = tvb_get_ntoh24(tvb, offset);
562 proto_tree_add_text(tree, tvb, offset, 3,
563 "Average throughput, target value, calling-called: %u o/s", t1);
568 t2 = tvb_get_ntoh24(tvb, offset);
569 proto_tree_add_text(tree, tvb, offset, 3,
570 "Average throughput, minimum acceptable, calling-called: %u o/s", t2);
575 t3 = tvb_get_ntoh24(tvb, offset);
576 proto_tree_add_text(tree, tvb, offset, 3,
577 "Average throughput, target value, called-calling: %u o/s", t3);
582 t4 = tvb_get_ntoh24(tvb, offset);
583 proto_tree_add_text(tree, tvb, offset, 3,
584 "Average throughput, minimum acceptable, called-calling: %u o/s", t4);
592 proto_tree_add_text(tree, tvb, offset, 2,
593 "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
598 case VP_REASSIGNMENT:
599 proto_tree_add_text(tree, tvb, offset, 2,
600 "Reassignment time: %u secs", tvb_get_ntohs(tvb, offset));
606 proto_tree_add_text(tree, tvb, offset, 4,
607 "Lower window edge: 0x%08x", tvb_get_ntohl(tvb, offset));
612 proto_tree_add_text(tree, tvb, offset, 2,
613 "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
618 proto_tree_add_text(tree, tvb, offset, 2,
619 "Credit: 0x%04x", tvb_get_ntohs(tvb, offset));
627 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
628 proto_tree_add_text(tree, tvb, offset, length,
629 "TPDU size: %u", 1 << c1);
635 /* if our preference is set to STRING or the
636 TSAP is not printable, add as bytes and hidden as string;
637 otherwise vice-versa */
638 if (tsap_display==TSAP_DISPLAY_STRING ||
639 (tsap_display==TSAP_DISPLAY_AUTO && is_all_printable(tvb_get_ptr(tvb,offset,length),length))) {
640 proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
641 print_tsap(tvb_get_ptr(tvb, offset, length),length));
642 proto_tree_add_item_hidden(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset, length, TRUE);
644 proto_tree_add_string_hidden(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
645 print_tsap(tvb_get_ptr(tvb, offset, length),length));
646 proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset, length, TRUE);
653 /* if our preference is set to STRING or the
654 TSAP is not printable, add as bytes and hidden as string;
655 otherwise vice-versa */
656 if (tsap_display==TSAP_DISPLAY_STRING ||
657 (tsap_display==TSAP_DISPLAY_AUTO && is_all_printable(tvb_get_ptr(tvb,offset,length),length))) {
658 proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
659 print_tsap(tvb_get_ptr(tvb, offset, length),length));
660 proto_tree_add_item_hidden(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset, length, TRUE);
662 proto_tree_add_string_hidden(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
663 print_tsap(tvb_get_ptr(tvb, offset, length),length));
664 proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset, length, TRUE);
671 proto_tree_add_text(tree, tvb, offset, length,
672 "Checksum: 0x%04x", tvb_get_ntohs(tvb, offset));
678 c1 = tvb_get_guint8(tvb, offset);
679 proto_tree_add_text(tree, tvb, offset, length,
686 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
687 switch (class_option) {
691 proto_tree_add_text(tree, tvb, offset, 1,
692 "Use of network expedited data");
694 proto_tree_add_text(tree, tvb, offset, 1,
695 "Non use of network expedited data");
697 proto_tree_add_text(tree, tvb, offset, 1,
698 "Use of Receipt confirmation");
700 proto_tree_add_text(tree, tvb, offset, 1,
701 "Use of explicit AK variant");
706 proto_tree_add_text(tree, tvb, offset, 1,
707 "Non-use 16 bit checksum in class 4");
709 proto_tree_add_text(tree, tvb, offset, 1,
710 "Use 16 bit checksum ");
714 proto_tree_add_text(tree, tvb, offset, 1,
715 "Use of transport expedited data transfer");
717 proto_tree_add_text(tree, tvb, offset, 1,
718 "Non-use of transport expedited data transfer");
723 case VP_PREF_MAX_TPDU_SIZE:
727 pref_max_tpdu_size = tvb_get_guint8(tvb, offset);
731 pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
735 pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
739 pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
743 proto_tree_add_text(tree, tvb, offset, length,
744 "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)",
748 proto_tree_add_text(tree, tvb, offset, length,
749 "Preferred maximum TPDU size: %u", pref_max_tpdu_size*128);
754 case VP_INACTIVITY_TIMER:
755 proto_tree_add_text(tree, tvb, offset, length,
756 "Inactivity timer: %u ms", tvb_get_ntohl(tvb, offset));
761 case VP_PROTECTION: /* user-defined */
762 case VP_PROTO_CLASS: /* todo */
763 default: /* unknown, no decoding */
764 proto_tree_add_text(tree, tvb, offset, length,
765 "Parameter value: <not shown>");
775 static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
776 packet_info *pinfo, proto_tree *tree)
778 proto_tree *cotp_tree;
780 guint16 dst_ref, src_ref;
787 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
789 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
791 reason = tvb_get_guint8(tvb, offset + P_REASON_IN_DR);
793 /* the settings of the TCP srcport and destport are currently disables,
794 * for the following reasons:
795 * a) only used for ISO conversation handling (which currently doesn't work)
796 * b) will prevent "ISO on TCP" (RFC1006) packets from using "follow TCP stream" correctly
798 * A future conversation handling might be able to handle different kinds of conversations
799 * (TCP, ISO, TCP on TCP, ...), but in that case this has to be fixed in any case.
801 /*pinfo->srcport = src_ref;*/
802 /*pinfo->destport = dst_ref;*/
804 case (128+0): str = "Normal Disconnect"; break;
805 case (128+1): str = "Remote transport entity congestion"; break;
806 case (128+2): str = "Connection negotiation failed"; break;
807 case (128+3): str = "Duplicate source reference"; break;
808 case (128+4): str = "Mismatched references"; break;
809 case (128+5): str = "Protocol error"; break;
810 case (128+7): str = "Reference overflow"; break;
811 case (128+8): str = "Connection requestion refused"; break;
812 case (128+10):str = "Header or parameter length invalid"; break;
813 case (0): str = "Reason not specified"; break;
814 case (1): str = "Congestion at TSAP"; break;
815 case (2): str = "Session entity not attached to TSAP"; break;
816 case (3): str = "Address unknown"; break;
822 if (check_col(pinfo->cinfo, COL_INFO))
823 col_append_fstr(pinfo->cinfo, COL_INFO,
824 "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
828 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
829 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
830 proto_tree_add_text(cotp_tree, tvb, offset, 1,
831 "Length indicator: %u", li);
832 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
833 "TPDU code: 0x%x (DR)", tpdu);
834 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
835 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset + 4, 2, src_ref);
836 proto_tree_add_text(cotp_tree, tvb, offset + 6, 1,
843 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
844 offset += tvb_length_remaining(tvb, offset);
845 /* we dissected all of the containing PDU */
849 } /* ositp_decode_DR */
851 static int ositp_decode_DT(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
852 packet_info *pinfo, proto_tree *tree,
853 gboolean uses_inactive_subset,
854 gboolean *subdissector_found)
856 proto_tree *cotp_tree = NULL;
858 gboolean is_extended;
859 gboolean is_class_234;
863 guint32 fragment_length = 0;
865 tvbuff_t *reassembled_tvb = NULL;
866 fragment_data *fd_head;
868 /* VP_CHECKSUM is the only parameter allowed in the variable part.
869 (This means we may misdissect this if the packet is bad and
870 contains other parameters.) */
873 case LI_NORMAL_DT_WITH_CHECKSUM :
874 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
878 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
879 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
880 if ( tpdu_nr & 0x80 )
881 tpdu_nr = tpdu_nr & 0x7F;
886 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
889 case LI_EXTENDED_DT_WITH_CHECKSUM :
890 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
894 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
895 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
896 if ( tpdu_nr & 0x80000000 )
897 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
902 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
905 case LI_NORMAL_DT_CLASS_01 :
906 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
907 if ( tpdu_nr & 0x80 )
908 tpdu_nr = tpdu_nr & 0x7F;
912 is_class_234 = FALSE;
916 default : /* bad TPDU */
922 /* pinfo->destport = dst_ref; */
923 /* pinfo->srcport = 0; */
924 pinfo->fragmented = fragment;
925 if (check_col(pinfo->cinfo, COL_INFO)) {
927 col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x %s",
930 (fragment)? "(fragment)" : "");
932 col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) %s",
934 (fragment)? "(fragment)" : "");
939 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
940 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
941 proto_tree_add_text(cotp_tree, tvb, offset, 1,
942 "Length indicator: %u", li);
947 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
948 "TPDU code: 0x%x (DT)", tpdu);
955 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
962 proto_tree_add_text(cotp_tree, tvb, offset, 4,
963 "TPDU number: 0x%08x (%s)",
965 (fragment)? "fragment":"complete");
971 proto_tree_add_text(cotp_tree, tvb, offset, 1,
972 "TPDU number: 0x%02x (%s)",
974 (fragment)? "fragment":"complete");
981 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
984 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
985 if (cotp_reassemble) {
986 fragment_length = tvb_length(next_tvb);
988 * XXX - these sequence numbers are connection sequence number,
989 * not segment sequence numbers - the first segment of a
990 * segmented packet doesn't have a specific sequence number (e.g., 0
991 * or 1), it has whatever the appropriate sequence number is for
992 * it in the connection.
994 * For now, we assume segments arrive in order, and just supply
995 * the negation of the EOT flag as the "more flags" argument.
996 * We should probably handle out-of-order packets separately,
997 * so that we can deliver them in order even when *not*
1000 * Note also that TP0 has no sequence number, and relies on
1001 * the protocol atop which it runs to guarantee in-order delivery.
1003 fd_head = fragment_add_seq_next(next_tvb, 0, pinfo, dst_ref,
1005 cotp_reassembled_table,
1006 fragment_length, fragment);
1008 if (fd_head->next) {
1009 /* This is the last packet */
1010 reassembled_tvb = tvb_new_real_data(fd_head->data,
1013 tvb_set_child_real_data_tvbuff(next_tvb, reassembled_tvb);
1014 add_new_data_source(pinfo, reassembled_tvb, "Reassembled COTP");
1016 show_fragment_seq_tree(fd_head,
1019 pinfo, reassembled_tvb);
1020 pinfo->fragmented = fragment;
1021 next_tvb = reassembled_tvb;
1024 if (fragment && reassembled_tvb == NULL) {
1025 proto_tree_add_text(cotp_tree, tvb, offset, -1,
1026 "User data (%u byte%s)", fragment_length,
1027 plurality(fragment_length, "", "s"));
1032 if (uses_inactive_subset) {
1033 if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1035 *subdissector_found = TRUE;
1037 /* Fill in other Dissectors using inactive subset here */
1038 call_dissector(data_handle,next_tvb, pinfo, tree);
1042 * We dissect payload if one of the following is TRUE:
1044 * - Reassembly option for COTP in preferences is unchecked
1045 * - Reassembly option is checked and this packet is the last fragment
1047 if ( (!cotp_reassemble) ||
1048 ((cotp_reassemble) && (!fragment))) {
1049 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb,
1051 *subdissector_found = TRUE;
1053 call_dissector(data_handle,next_tvb, pinfo, tree);
1058 offset += tvb_length_remaining(tvb, offset);
1059 /* we dissected all of the containing PDU */
1063 } /* ositp_decode_DT */
1065 static int ositp_decode_ED(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1066 packet_info *pinfo, proto_tree *tree)
1068 proto_tree *cotp_tree = NULL;
1070 gboolean is_extended;
1075 /* ED TPDUs are never fragmented */
1077 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1078 (This means we may misdissect this if the packet is bad and
1079 contains other parameters.) */
1082 case LI_NORMAL_DT_WITH_CHECKSUM :
1083 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1087 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
1088 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1089 if ( tpdu_nr & 0x80 )
1090 tpdu_nr = tpdu_nr & 0x7F;
1093 is_extended = FALSE;
1096 case LI_EXTENDED_DT_WITH_CHECKSUM :
1097 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1101 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1102 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1103 if ( tpdu_nr & 0x80000000 )
1104 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1110 default : /* bad TPDU */
1116 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1118 /* pinfo->destport = dst_ref; */
1119 /* pinfo->srcport = 0; */
1120 if (check_col(pinfo->cinfo, COL_INFO))
1121 col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
1125 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1126 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1127 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1128 "Length indicator: %u", li);
1133 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1134 "TPDU code: 0x%x (ED)", tpdu);
1140 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1146 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1147 "TPDU number: 0x%02x", tpdu_nr);
1153 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1154 "TPDU number: 0x%02x", tpdu_nr);
1161 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1164 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1165 call_dissector(data_handle,next_tvb, pinfo, tree);
1167 offset += tvb_length_remaining(tvb, offset);
1168 /* we dissected all of the containing PDU */
1172 } /* ositp_decode_ED */
1174 static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1175 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1177 proto_tree *cotp_tree;
1185 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1187 case LI_EXTENDED_RJ :
1188 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1189 credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1197 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1199 /* pinfo->destport = dst_ref; */
1200 /* pinfo->srcport = 0; */
1201 if (check_col(pinfo->cinfo, COL_INFO))
1202 col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
1206 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1207 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1208 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1209 "Length indicator: %u", li);
1210 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
1211 "TPDU code: 0x%x (RJ)", tpdu);
1212 if (li == LI_NORMAL_RJ)
1213 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
1215 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
1216 if (li == LI_NORMAL_RJ)
1217 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
1218 "Your TPDU number: 0x%02x", tpdu_nr);
1220 proto_tree_add_text(cotp_tree, tvb, offset + 4, 4,
1221 "Your TPDU number: 0x%02x", tpdu_nr);
1222 proto_tree_add_text(cotp_tree, tvb, offset + 8, 2,
1223 "Credit: 0x%02x", credit);
1231 } /* ositp_decode_RJ */
1233 static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1234 packet_info *pinfo, proto_tree *tree,
1235 gboolean uses_inactive_subset,
1236 gboolean *subdissector_found)
1239 /* CC & CR decoding in the same function */
1241 proto_tree *cotp_tree = NULL;
1243 guint16 dst_ref, src_ref;
1244 guchar class_option;
1247 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1249 class_option = (tvb_get_guint8(tvb, offset + P_CLASS_OPTION) >> 4 ) & 0x0F;
1250 if (class_option > 4)
1253 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1254 /* pinfo->srcport = src_ref; */
1255 /* pinfo->destport = dst_ref; */
1256 if (check_col(pinfo->cinfo, COL_INFO))
1257 col_append_fstr(pinfo->cinfo, COL_INFO,
1258 "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1259 (tpdu == CR_TPDU) ? "CR" : "CC",
1264 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1265 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1266 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1267 "Length indicator: %u", li);
1272 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1273 "TPDU code: 0x%x (%s)", tpdu,
1274 (tpdu == CR_TPDU) ? "CR" : "CC");
1280 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1285 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1290 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1291 "Class option: 0x%02x", class_option);
1297 ositp_decode_var_part(tvb, offset, li, class_option, cotp_tree);
1300 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1301 if (!uses_inactive_subset){
1302 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb,
1304 *subdissector_found = TRUE;
1306 call_dissector(data_handle,next_tvb, pinfo, tree);
1310 call_dissector(data_handle, next_tvb, pinfo, tree);
1311 offset += tvb_length_remaining(tvb, offset);
1312 /* we dissected all of the containing PDU */
1316 } /* ositp_decode_CC */
1318 static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1319 packet_info *pinfo, proto_tree *tree)
1321 proto_tree *cotp_tree = NULL;
1323 guint16 dst_ref, src_ref;
1328 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1329 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1331 /* pinfo->srcport = src_ref; */
1332 /* pinfo->destport = dst_ref; */
1333 if (check_col(pinfo->cinfo, COL_INFO))
1334 col_append_fstr(pinfo->cinfo, COL_INFO,
1335 "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1340 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1341 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1342 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1343 "Length indicator: %u", li);
1348 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1349 "TPDU code: 0x%x (DC)", tpdu);
1355 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1360 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1365 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1370 } /* ositp_decode_DC */
1372 static int ositp_decode_AK(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1373 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1375 proto_tree *cotp_tree = NULL;
1384 if (is_LI_NORMAL_AK(li)) {
1386 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1387 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1389 /* pinfo->srcport = 0; */
1390 /* pinfo->destport = dst_ref; */
1391 if (check_col(pinfo->cinfo, COL_INFO))
1392 col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1396 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1397 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1398 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1399 "Length indicator: %u", li);
1404 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1405 "TPDU code: 0x%x (AK)", tpdu);
1406 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1413 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1418 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1419 "Your TPDU number: 0x%02x", tpdu_nr);
1425 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1428 } else { /* extended format */
1430 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1431 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1432 cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1434 if (check_col(pinfo->cinfo, COL_INFO))
1435 col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1439 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1440 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1441 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1442 "Length indicator: %u", li);
1447 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1448 "TPDU code: 0x%x (AK)", tpdu);
1454 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1459 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1460 "Your TPDU number: 0x%08x", tpdu_nr);
1466 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1467 "Credit: 0x%04x", cdt_in_ak);
1473 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1476 } /* is_LI_NORMAL_AK */
1480 } /* ositp_decode_AK */
1482 static int ositp_decode_EA(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1483 packet_info *pinfo, proto_tree *tree)
1485 proto_tree *cotp_tree = NULL;
1487 gboolean is_extended;
1494 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1495 (This means we may misdissect this if the packet is bad and
1496 contains other parameters.) */
1499 case LI_NORMAL_EA_WITH_CHECKSUM :
1500 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
1501 tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1505 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1506 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1507 is_extended = FALSE;
1510 case LI_EXTENDED_EA_WITH_CHECKSUM :
1511 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
1512 tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1516 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1517 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1521 default : /* bad TPDU */
1527 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1528 /* pinfo->srcport = 0; */
1529 /* pinfo->destport = dst_ref; */
1530 if (check_col(pinfo->cinfo, COL_INFO))
1531 col_append_fstr(pinfo->cinfo, COL_INFO,
1532 "EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1535 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1536 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1537 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1538 "Length indicator: %u", li);
1543 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1544 "TPDU code: 0x%x (EA)", tpdu);
1550 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1556 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1557 "Your TPDU number: 0x%08x", tpdu_nr);
1563 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1564 "Your TPDU number: 0x%02x", tpdu_nr);
1571 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1576 } /* ositp_decode_EA */
1578 static int ositp_decode_ER(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1579 packet_info *pinfo, proto_tree *tree)
1581 proto_tree *cotp_tree;
1589 switch(tvb_get_guint8(tvb, offset + P_REJECT_ER)) {
1591 str = "Reason not specified";
1594 str = "Invalid parameter code";
1597 str = "Invalid TPDU type";
1600 str = "Invalid parameter value";
1608 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1609 /* pinfo->srcport = 0; */
1610 /* pinfo->destport = dst_ref; */
1611 if (check_col(pinfo->cinfo, COL_INFO))
1612 col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1615 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1616 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1617 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1618 "Length indicator: %u", li);
1619 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
1620 "TPDU code: 0x%x (ER)", tpdu);
1621 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
1622 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
1623 "Reject cause: %s", str);
1630 } /* ositp_decode_ER */
1632 static int ositp_decode_UD(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1633 packet_info *pinfo, proto_tree *tree)
1636 proto_tree *cltp_tree = NULL;
1639 if (check_col(pinfo->cinfo, COL_INFO))
1640 col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
1643 ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, FALSE);
1644 cltp_tree = proto_item_add_subtree(ti, ett_cltp);
1645 proto_tree_add_text(cltp_tree, tvb, offset, 1,
1646 "Length indicator: %u", li);
1651 proto_tree_add_uint_format(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu,
1652 "TPDU code: 0x%x (UD)", tpdu);
1658 ositp_decode_var_part(tvb, offset, li, 0, cltp_tree);
1661 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1662 call_dissector(data_handle,next_tvb, pinfo, tree);
1663 offset += tvb_length_remaining(tvb, offset);
1664 /* we dissected all of the containing PDU */
1668 } /* ositp_decode_UD */
1670 /* Returns TRUE if we found at least one valid COTP or CLTP PDU, FALSE
1673 There doesn't seem to be any way in which the OSI network layer protocol
1674 distinguishes between COTP and CLTP, but the first two octets of both
1675 protocols' headers mean the same thing - length and PDU type - and the
1676 only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
1677 both of them here. */
1678 static gboolean dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
1679 proto_tree *tree, gboolean uses_inactive_subset)
1682 guint8 li, tpdu, cdt;
1683 gboolean first_tpdu = TRUE;
1685 gboolean found_ositp = FALSE;
1686 gboolean is_cltp = FALSE;
1687 gboolean subdissector_found = FALSE;
1689 if (!proto_is_protocol_enabled(find_protocol_by_id(proto_cotp)))
1690 return FALSE; /* COTP has been disabled */
1691 /* XXX - what about CLTP? */
1693 pinfo->current_proto = "COTP";
1695 /* Initialize the COL_INFO field; each of the TPDUs will have its
1696 information appended. */
1697 if (check_col(pinfo->cinfo, COL_INFO))
1698 col_add_str(pinfo->cinfo, COL_INFO, "");
1700 while (tvb_offset_exists(tvb, offset)) {
1702 if (check_col(pinfo->cinfo, COL_INFO))
1703 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1705 if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
1706 if (check_col(pinfo->cinfo, COL_INFO))
1707 col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
1709 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
1714 tpdu = (tvb_get_guint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
1715 if (tpdu == UD_TPDU)
1716 pinfo->current_proto = "CLTP"; /* connectionless transport */
1717 cdt = tvb_get_guint8(tvb, offset + P_CDT) & 0x0F;
1722 new_offset = ositp_decode_CC(tvb, offset, li, tpdu, pinfo, tree,
1723 uses_inactive_subset, &subdissector_found);
1726 new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
1729 new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
1730 uses_inactive_subset, &subdissector_found);
1733 new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree);
1736 new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
1739 new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
1742 new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
1745 new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
1748 new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
1751 new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree);
1755 if (first_tpdu && check_col(pinfo->cinfo, COL_INFO))
1756 col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
1757 new_offset = -1; /* bad PDU type */
1761 if (new_offset == -1) { /* incorrect TPDU */
1763 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
1769 /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
1770 is either COTP or CLTP. */
1771 if (!subdissector_found && check_col(pinfo->cinfo, COL_PROTOCOL))
1772 col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
1776 offset = new_offset;
1780 } /* dissect_ositp_internal */
1782 static void dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1784 if (!dissect_ositp_internal(tvb, pinfo, tree, FALSE))
1785 call_dissector(data_handle,tvb, pinfo, tree);
1789 * CLNP part / main entry point
1792 static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1794 proto_tree *clnp_tree = NULL;
1796 guint8 cnf_proto_id;
1801 char flag_string[6+1];
1802 char *pdu_type_string;
1803 proto_tree *type_tree;
1804 guint16 segment_length;
1806 guint16 segment_offset = 0;
1808 cksum_status_t cksum_status;
1810 guchar src_len, dst_len, nsel, opt_len = 0;
1811 const guint8 *dst_addr, *src_addr;
1814 proto_tree *discpdu_tree;
1815 gboolean save_in_error_pkt;
1816 fragment_data *fd_head;
1818 gboolean update_col_info = TRUE;
1819 gboolean save_fragmented;
1821 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1822 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP");
1823 if (check_col(pinfo->cinfo, COL_INFO))
1824 col_clear(pinfo->cinfo, COL_INFO);
1826 cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
1827 if (cnf_proto_id == NLPID_NULL) {
1828 if (check_col(pinfo->cinfo, COL_INFO))
1829 col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
1831 ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, FALSE);
1832 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1833 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1837 next_tvb = tvb_new_subset(tvb, 1, -1, -1);
1838 dissect_ositp_internal(next_tvb, pinfo, tree, TRUE);
1842 /* return if version not known */
1843 cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
1844 if (cnf_vers != ISO8473_V1) {
1845 call_dissector(data_handle,tvb, pinfo, tree);
1849 /* fixed part decoding */
1850 cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
1851 opt_len = cnf_hdr_len;
1854 ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, FALSE);
1855 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1856 proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1858 proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
1860 proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
1862 cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
1863 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
1865 "Holding Time : %u (%u.%u secs)",
1866 cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
1869 cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
1870 pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
1871 "Unknown (0x%02x)");
1872 flag_string[0] = '\0';
1873 if (cnf_type & CNF_SEG_OK)
1874 strcat(flag_string, "S ");
1875 if (cnf_type & CNF_MORE_SEGS)
1876 strcat(flag_string, "M ");
1877 if (cnf_type & CNF_ERR_OK)
1878 strcat(flag_string, "E ");
1880 ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
1882 "PDU Type : 0x%02x (%s%s)",
1886 type_tree = proto_item_add_subtree(ti, ett_clnp_type);
1887 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1888 decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8,
1889 "Segmentation permitted",
1890 "Segmentation not permitted"));
1891 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1892 decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8,
1895 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1896 decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8,
1897 "Report error if PDU discarded",
1898 "Don't report error if PDU discarded"));
1899 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1900 decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8,
1901 npdu_type_vals, "%s"));
1904 /* If we don't have the full header - i.e., not enough to see the
1905 segmentation part and determine whether this datagram is segmented
1906 or not - set the Info column now; we'll get an exception before
1907 we set it otherwise. */
1909 if (!tvb_bytes_exist(tvb, 0, cnf_hdr_len)) {
1910 if (check_col(pinfo->cinfo, COL_INFO))
1911 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1914 segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
1915 cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
1916 cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
1918 proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
1920 switch (cksum_status) {
1924 * No checksum present, or not enough of the header present to
1927 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
1930 "Checksum : 0x%04x",
1936 * Checksum is correct.
1938 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
1941 "Checksum : 0x%04x (correct)",
1947 * Checksum is not correct.
1949 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
1952 "Checksum : 0x%04x (incorrect)",
1956 opt_len -= 9; /* Fixed part of Hesder */
1961 offset = P_CLNP_ADDRESS_PART;
1962 dst_len = tvb_get_guint8(tvb, offset);
1963 dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
1964 nsel = tvb_get_guint8(tvb, offset + dst_len);
1965 src_len = tvb_get_guint8(tvb, offset + dst_len + 1);
1966 src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);
1969 proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
1971 proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
1974 print_nsap_net(dst_addr, dst_len));
1975 proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
1976 offset + 1 + dst_len, 1, src_len);
1977 proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
1978 offset + dst_len + 2, src_len,
1981 print_nsap_net(src_addr, src_len));
1983 opt_len -= dst_len + src_len +2;
1986 SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
1987 SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
1988 SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
1989 SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);
1991 /* Segmentation Part */
1993 offset += dst_len + src_len + 2;
1995 if (cnf_type & CNF_SEG_OK) {
1996 struct clnp_segment seg; /* XXX - not used */
1997 tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg)); /* XXX - not used */
1999 segment_offset = tvb_get_ntohs(tvb, offset + 2);
2000 du_id = tvb_get_ntohs(tvb, offset);
2002 proto_tree_add_text(clnp_tree, tvb, offset, 2,
2003 "Data unit identifier: %06u",
2005 proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
2006 "Segment offset : %6u",
2008 proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
2009 "Total length : %6u",
2010 tvb_get_ntohs(tvb, offset + 4));
2018 /* To do : decode options */
2020 proto_tree_add_text(clnp_tree, tvb, offset,
2021 cnf_hdr_len - offset,
2022 "Options/Data: <not shown>");
2024 /* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/
2026 dissect_osi_options( opt_len,
2027 tvb, offset, clnp_tree );
2030 /* Length of CLNP datagram plus headers above it. */
2031 len = segment_length;
2033 offset = cnf_hdr_len;
2035 /* If clnp_reassemble is on, this is a segment, we have all the
2036 * data in the segment, and the checksum is valid, then just add the
2037 * segment to the hashtable.
2039 save_fragmented = pinfo->fragmented;
2040 if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
2041 ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
2042 tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
2043 cksum_status != CKSUM_NOT_OK) {
2044 fd_head = fragment_add_check(tvb, offset, pinfo, du_id, clnp_segment_table,
2045 clnp_reassembled_table, segment_offset,
2046 segment_length - cnf_hdr_len,
2047 cnf_type & CNF_MORE_SEGS);
2049 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
2050 fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
2052 /* If this is the first segment, dissect its contents, otherwise
2053 just show it as a segment.
2055 XXX - if we eventually don't save the reassembled contents of all
2056 segmented datagrams, we may want to always reassemble. */
2057 if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
2058 /* Not the first segment - don't dissect it. */
2061 /* First segment, or not segmented. Dissect what we have here. */
2063 /* Get a tvbuff for the payload. */
2064 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
2067 * If this is the first segment, but not the only segment,
2068 * tell the next protocol that.
2070 if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
2071 pinfo->fragmented = TRUE;
2073 pinfo->fragmented = FALSE;
2077 if (next_tvb == NULL) {
2078 /* Just show this as a segment. */
2079 if (check_col(pinfo->cinfo, COL_INFO))
2080 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
2081 pdu_type_string, flag_string, segment_offset);
2083 /* As we haven't reassembled anything, we haven't changed "pi", so
2084 we don't have to restore it. */
2085 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
2087 pinfo->fragmented = save_fragmented;
2091 if (tvb_offset_exists(tvb, offset)) {
2092 switch (cnf_type & CNF_TYPE) {
2096 /* Continue with COTP if any data.
2097 XXX - if this isn't the first Derived PDU of a segmented Initial
2100 if (nsel == (char)tp_nsap_selector || always_decode_transport) {
2101 if (dissect_ositp_internal(next_tvb, pinfo, tree, FALSE)) {
2102 pinfo->fragmented = save_fragmented;
2103 return; /* yes, it appears to be COTP or CLTP */
2106 if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
2108 pinfo->fragmented = save_fragmented;
2109 return; /* yes, it appears to be COTP or CLTP */
2115 /* The payload is the header and "none, some, or all of the data
2116 part of the discarded PDU", i.e. it's like an ICMP error;
2117 dissect it as a CLNP PDU. */
2118 if (check_col(pinfo->cinfo, COL_INFO))
2119 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
2121 next_length = tvb_length_remaining(tvb, offset);
2122 if (next_length != 0) {
2123 /* We have payload; dissect it. */
2124 ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
2126 discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);
2128 /* Save the current value of the "we're inside an error packet"
2129 flag, and set that flag; subdissectors may treat packets
2130 that are the payload of error packets differently from
2132 save_in_error_pkt = pinfo->in_error_pkt;
2133 pinfo->in_error_pkt = TRUE;
2135 call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);
2137 /* Restore the "we're inside an error packet" flag. */
2138 pinfo->in_error_pkt = save_in_error_pkt;
2141 pinfo->fragmented = save_fragmented;
2142 return; /* we're done with this PDU */
2146 /* XXX - dissect this */
2150 if (check_col(pinfo->cinfo, COL_INFO))
2151 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
2152 call_dissector(data_handle,next_tvb, pinfo, tree);
2153 pinfo->fragmented = save_fragmented;
2154 } /* dissect_clnp */
2157 clnp_reassemble_init(void)
2159 fragment_table_init(&clnp_segment_table);
2160 reassembled_table_init(&clnp_reassembled_table);
2164 cotp_reassemble_init(void)
2166 fragment_table_init(&cotp_segment_table);
2167 reassembled_table_init(&cotp_reassembled_table);
2170 void proto_register_clnp(void)
2172 static hf_register_info hf[] = {
2174 { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
2175 VALS(nlpid_vals), 0x0, "", HFILL }},
2178 { "HDR Length ", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2181 { "Version ", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2184 { "Holding Time ", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2187 { "PDU Type ", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2189 { &hf_clnp_pdu_length,
2190 { "PDU length ", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2192 { &hf_clnp_checksum,
2193 { "Checksum ", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2195 { &hf_clnp_dest_length,
2196 { "DAL ", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2199 { " DA ", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
2201 { &hf_clnp_src_length,
2202 { "SAL ", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2205 { " SA ", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
2207 { &hf_clnp_segment_overlap,
2208 { "Segment overlap", "clnp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2209 "Segment overlaps with other segments", HFILL }},
2211 { &hf_clnp_segment_overlap_conflict,
2212 { "Conflicting data in segment overlap", "clnp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2213 "Overlapping segments contained conflicting data", HFILL }},
2215 { &hf_clnp_segment_multiple_tails,
2216 { "Multiple tail segments found", "clnp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2217 "Several tails were found when reassembling the packet", HFILL }},
2219 { &hf_clnp_segment_too_long_segment,
2220 { "Segment too long", "clnp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2221 "Segment contained data past end of packet", HFILL }},
2223 { &hf_clnp_segment_error,
2224 { "Reassembly error", "clnp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2225 "Reassembly error due to illegal segments", HFILL }},
2228 { "CLNP Segment", "clnp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2229 "CLNP Segment", HFILL }},
2231 { &hf_clnp_segments,
2232 { "CLNP Segments", "clnp.segments", FT_NONE, BASE_DEC, NULL, 0x0,
2233 "CLNP Segments", HFILL }},
2235 { &hf_clnp_reassembled_in,
2236 { "Reassembled CLNP in frame", "clnp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2237 "This CLNP packet is reassembled in this frame", HFILL }}
2239 static gint *ett[] = {
2247 module_t *clnp_module;
2249 proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "CLNP", "clnp");
2250 proto_register_field_array(proto_clnp, hf, array_length(hf));
2251 proto_register_subtree_array(ett, array_length(ett));
2252 register_dissector("clnp", dissect_clnp, proto_clnp);
2253 register_heur_dissector_list("clnp", &clnp_heur_subdissector_list);
2254 register_init_routine(clnp_reassemble_init);
2255 register_init_routine(cotp_reassemble_init);
2257 clnp_module = prefs_register_protocol(proto_clnp, NULL);
2258 prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
2259 "NSAP selector for Transport Protocol (last byte in hex)",
2260 "NSAP selector for Transport Protocol (last byte in hex)",
2261 16, &tp_nsap_selector);
2262 prefs_register_bool_preference(clnp_module, "always_decode_transport",
2263 "Always try to decode NSDU as transport PDUs",
2264 "Always try to decode NSDU as transport PDUs",
2265 &always_decode_transport);
2266 prefs_register_bool_preference(clnp_module, "reassemble",
2267 "Reassemble segmented CLNP datagrams",
2268 "Whether segmented CLNP datagrams should be reassembled",
2273 proto_reg_handoff_clnp(void)
2275 data_handle = find_dissector("data");
2277 clnp_handle = create_dissector_handle(dissect_clnp, proto_clnp);
2278 dissector_add("osinl", NLPID_ISO8473_CLNP, clnp_handle);
2279 dissector_add("osinl", NLPID_NULL, clnp_handle); /* Inactive subset */
2280 dissector_add("x.25.spi", NLPID_ISO8473_CLNP, clnp_handle);
2283 void proto_register_cotp(void)
2285 static hf_register_info hf[] = {
2287 { "Source reference", "cotp.srcref", FT_UINT16, BASE_HEX, NULL, 0x0,
2288 "Source address reference", HFILL}},
2290 { "Destination reference", "cotp.destref", FT_UINT16, BASE_HEX, NULL, 0x0,
2291 "Destination address reference", HFILL}},
2293 { "COTP PDU Type", "cotp.type", FT_UINT8, BASE_HEX, VALS(cotp_tpdu_type_abbrev_vals), 0x0,
2294 "COTP PDU Type", HFILL}},
2295 { &hf_cotp_segment_overlap,
2296 { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2297 "Segment overlaps with other segments", HFILL }},
2298 { &hf_cotp_segment_overlap_conflict,
2299 { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2300 "Overlapping segments contained conflicting data", HFILL }},
2301 { &hf_cotp_segment_multiple_tails,
2302 { "Multiple tail segments found", "cotp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2303 "Several tails were found when reassembling the packet", HFILL }},
2304 { &hf_cotp_segment_too_long_segment,
2305 { "Segment too long", "cotp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2306 "Segment contained data past end of packet", HFILL }},
2307 { &hf_cotp_segment_error,
2308 { "Reassembly error", "cotp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2309 "Reassembly error due to illegal segments", HFILL }},
2311 { "COTP Segment", "cotp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2312 "COTP Segment", HFILL }},
2313 { &hf_cotp_segments,
2314 { "COTP Segments", "cotp.segments", FT_NONE, BASE_DEC, NULL, 0x0,
2315 "COTP Segments", HFILL }},
2316 { &hf_cotp_reassembled_in,
2317 { "Reassembled COTP in frame", "cotp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2318 "This COTP packet is reassembled in this frame", HFILL }},
2319 /* ISO DP 8073 i13.3.4(a) Source and destination TSAPs are defined as
2320 identifiers of unspecified type and length.
2321 Some implementations of COTP use printable strings, others use raw bytes.
2322 We always add both representations to the tree; one will always be hidden
2323 depending on the tsap display preference */
2324 { &hf_cotp_vp_src_tsap,
2325 { "Source TSAP", "cotp.src-tsap", FT_STRING, BASE_NONE, NULL, 0x0,
2326 "Calling TSAP", HFILL }},
2327 { &hf_cotp_vp_src_tsap_bytes,
2328 { "Source TSAP", "cotp.src-tsap-bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
2329 "Calling TSAP (bytes representation)", HFILL }},
2330 { &hf_cotp_vp_dst_tsap,
2331 { "Destination TSAP", "cotp.dst-tsap", FT_STRING, BASE_NONE, NULL, 0x0,
2332 "Called TSAP", HFILL }},
2333 { &hf_cotp_vp_dst_tsap_bytes,
2334 { "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
2335 "Called TSAP (bytes representation)", HFILL }},
2338 static gint *ett[] = {
2344 module_t *cotp_module;
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 cotp_module = prefs_register_protocol(proto_cotp, NULL);
2351 prefs_register_bool_preference(cotp_module, "reassemble",
2352 "Reassemble segmented COTP datagrams",
2353 "Whether segmented COTP datagrams should be reassembled",
2356 prefs_register_enum_preference(cotp_module, "tsap_display",
2357 "Display TSAPs as strings or bytes",
2358 "How TSAPs should be displayed",
2360 tsap_display_options,
2363 /* subdissector code in inactive subset */
2364 register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
2366 /* other COTP/ISO 8473 subdissectors */
2367 register_heur_dissector_list("cotp", &cotp_heur_subdissector_list);
2369 /* XXX - what about CLTP and proto_cltp? */
2370 register_dissector("ositp", dissect_ositp, proto_cotp);
2374 proto_reg_handoff_cotp(void)
2376 dissector_handle_t ositp_handle;
2378 ositp_handle = find_dissector("ositp");
2379 dissector_add("ip.proto", IP_PROTO_TP, ositp_handle);
2382 void proto_register_cltp(void)
2384 static hf_register_info hf[] = {
2386 { "CLTP PDU Type", "cltp.type", FT_UINT8, BASE_HEX, VALS(cltp_tpdu_type_abbrev_vals), 0x0,
2387 "CLTP PDU Type", HFILL}},
2389 static gint *ett[] = {
2393 proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "CLTP", "cltp");
2394 proto_register_field_array(proto_cltp, hf, array_length(hf));
2395 proto_register_subtree_array(ett, array_length(ett));