2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-clnp.c,v 1.85 2004/05/24 02:25:18 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 fd_head = fragment_add_seq_check(next_tvb, 0, pinfo, dst_ref,
996 cotp_reassembled_table,
998 fragment_length, fragment);
1000 if (fd_head->next) {
1001 /* This is the last packet */
1002 reassembled_tvb = tvb_new_real_data(fd_head->data,
1005 tvb_set_child_real_data_tvbuff(next_tvb, reassembled_tvb);
1006 add_new_data_source(pinfo, reassembled_tvb, "Reassembled COTP");
1008 show_fragment_seq_tree(fd_head,
1011 pinfo, reassembled_tvb);
1012 pinfo->fragmented = fragment;
1013 next_tvb = reassembled_tvb;
1016 if (fragment && reassembled_tvb == NULL) {
1017 proto_tree_add_text(cotp_tree, tvb, offset, -1,
1018 "User data (%u byte%s)", fragment_length,
1019 plurality(fragment_length, "", "s"));
1024 if (uses_inactive_subset) {
1025 if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1027 *subdissector_found = TRUE;
1029 /* Fill in other Dissectors using inactive subset here */
1030 call_dissector(data_handle,next_tvb, pinfo, tree);
1034 * We dissect payload if one of the following is TRUE:
1036 * - Reassembly option for COTP in preferences is unchecked
1037 * - Reassembly option is checked and this packet is the last fragment
1039 if ( (!cotp_reassemble) ||
1040 ((cotp_reassemble) && (!fragment))) {
1041 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb,
1043 *subdissector_found = TRUE;
1045 call_dissector(data_handle,next_tvb, pinfo, tree);
1050 offset += tvb_length_remaining(tvb, offset);
1051 /* we dissected all of the containing PDU */
1055 } /* ositp_decode_DT */
1057 static int ositp_decode_ED(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1058 packet_info *pinfo, proto_tree *tree)
1060 proto_tree *cotp_tree = NULL;
1062 gboolean is_extended;
1067 /* ED TPDUs are never fragmented */
1069 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1070 (This means we may misdissect this if the packet is bad and
1071 contains other parameters.) */
1074 case LI_NORMAL_DT_WITH_CHECKSUM :
1075 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1079 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
1080 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1081 if ( tpdu_nr & 0x80 )
1082 tpdu_nr = tpdu_nr & 0x7F;
1085 is_extended = FALSE;
1088 case LI_EXTENDED_DT_WITH_CHECKSUM :
1089 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1093 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1094 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1095 if ( tpdu_nr & 0x80000000 )
1096 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1102 default : /* bad TPDU */
1108 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1110 /* pinfo->destport = dst_ref; */
1111 /* pinfo->srcport = 0; */
1112 if (check_col(pinfo->cinfo, COL_INFO))
1113 col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
1117 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1118 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1119 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1120 "Length indicator: %u", li);
1125 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1126 "TPDU code: 0x%x (ED)", tpdu);
1132 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1138 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1139 "TPDU number: 0x%02x", tpdu_nr);
1145 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1146 "TPDU number: 0x%02x", tpdu_nr);
1153 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1156 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1157 call_dissector(data_handle,next_tvb, pinfo, tree);
1159 offset += tvb_length_remaining(tvb, offset);
1160 /* we dissected all of the containing PDU */
1164 } /* ositp_decode_ED */
1166 static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1167 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1169 proto_tree *cotp_tree;
1177 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1179 case LI_EXTENDED_RJ :
1180 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1181 credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1189 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1191 /* pinfo->destport = dst_ref; */
1192 /* pinfo->srcport = 0; */
1193 if (check_col(pinfo->cinfo, COL_INFO))
1194 col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
1198 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1199 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1200 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1201 "Length indicator: %u", li);
1202 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
1203 "TPDU code: 0x%x (RJ)", tpdu);
1204 if (li == LI_NORMAL_RJ)
1205 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
1207 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
1208 if (li == LI_NORMAL_RJ)
1209 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
1210 "Your TPDU number: 0x%02x", tpdu_nr);
1212 proto_tree_add_text(cotp_tree, tvb, offset + 4, 4,
1213 "Your TPDU number: 0x%02x", tpdu_nr);
1214 proto_tree_add_text(cotp_tree, tvb, offset + 8, 2,
1215 "Credit: 0x%02x", credit);
1223 } /* ositp_decode_RJ */
1225 static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1226 packet_info *pinfo, proto_tree *tree,
1227 gboolean uses_inactive_subset,
1228 gboolean *subdissector_found)
1231 /* CC & CR decoding in the same function */
1233 proto_tree *cotp_tree = NULL;
1235 guint16 dst_ref, src_ref;
1236 guchar class_option;
1239 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1241 class_option = (tvb_get_guint8(tvb, offset + P_CLASS_OPTION) >> 4 ) & 0x0F;
1242 if (class_option > 4)
1245 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1246 /* pinfo->srcport = src_ref; */
1247 /* pinfo->destport = dst_ref; */
1248 if (check_col(pinfo->cinfo, COL_INFO))
1249 col_append_fstr(pinfo->cinfo, COL_INFO,
1250 "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1251 (tpdu == CR_TPDU) ? "CR" : "CC",
1256 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1257 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1258 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1259 "Length indicator: %u", li);
1264 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1265 "TPDU code: 0x%x (%s)", tpdu,
1266 (tpdu == CR_TPDU) ? "CR" : "CC");
1272 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1277 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1282 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1283 "Class option: 0x%02x", class_option);
1289 ositp_decode_var_part(tvb, offset, li, class_option, cotp_tree);
1292 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1293 if (!uses_inactive_subset){
1294 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb,
1296 *subdissector_found = TRUE;
1298 call_dissector(data_handle,next_tvb, pinfo, tree);
1302 call_dissector(data_handle, next_tvb, pinfo, tree);
1303 offset += tvb_length_remaining(tvb, offset);
1304 /* we dissected all of the containing PDU */
1308 } /* ositp_decode_CC */
1310 static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1311 packet_info *pinfo, proto_tree *tree)
1313 proto_tree *cotp_tree = NULL;
1315 guint16 dst_ref, src_ref;
1320 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1321 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1323 /* pinfo->srcport = src_ref; */
1324 /* pinfo->destport = dst_ref; */
1325 if (check_col(pinfo->cinfo, COL_INFO))
1326 col_append_fstr(pinfo->cinfo, COL_INFO,
1327 "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1332 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1333 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1334 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1335 "Length indicator: %u", li);
1340 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1341 "TPDU code: 0x%x (DC)", tpdu);
1347 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1352 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1357 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1362 } /* ositp_decode_DC */
1364 static int ositp_decode_AK(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1365 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1367 proto_tree *cotp_tree = NULL;
1376 if (is_LI_NORMAL_AK(li)) {
1378 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1379 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1381 /* pinfo->srcport = 0; */
1382 /* pinfo->destport = dst_ref; */
1383 if (check_col(pinfo->cinfo, COL_INFO))
1384 col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1388 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1389 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1390 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1391 "Length indicator: %u", li);
1396 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1397 "TPDU code: 0x%x (AK)", tpdu);
1398 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1405 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1410 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1411 "Your TPDU number: 0x%02x", tpdu_nr);
1417 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1420 } else { /* extended format */
1422 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1423 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1424 cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1426 if (check_col(pinfo->cinfo, COL_INFO))
1427 col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1431 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1432 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1433 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1434 "Length indicator: %u", li);
1439 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1440 "TPDU code: 0x%x (AK)", tpdu);
1446 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1451 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1452 "Your TPDU number: 0x%08x", tpdu_nr);
1458 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1459 "Credit: 0x%04x", cdt_in_ak);
1465 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1468 } /* is_LI_NORMAL_AK */
1472 } /* ositp_decode_AK */
1474 static int ositp_decode_EA(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1475 packet_info *pinfo, proto_tree *tree)
1477 proto_tree *cotp_tree = NULL;
1479 gboolean is_extended;
1486 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1487 (This means we may misdissect this if the packet is bad and
1488 contains other parameters.) */
1491 case LI_NORMAL_EA_WITH_CHECKSUM :
1492 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
1493 tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1497 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1498 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1499 is_extended = FALSE;
1502 case LI_EXTENDED_EA_WITH_CHECKSUM :
1503 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
1504 tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1508 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1509 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1513 default : /* bad TPDU */
1519 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1520 /* pinfo->srcport = 0; */
1521 /* pinfo->destport = dst_ref; */
1522 if (check_col(pinfo->cinfo, COL_INFO))
1523 col_append_fstr(pinfo->cinfo, COL_INFO,
1524 "EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1527 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1528 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1529 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1530 "Length indicator: %u", li);
1535 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1536 "TPDU code: 0x%x (EA)", tpdu);
1542 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1548 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1549 "Your TPDU number: 0x%08x", tpdu_nr);
1555 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1556 "Your TPDU number: 0x%02x", tpdu_nr);
1563 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1568 } /* ositp_decode_EA */
1570 static int ositp_decode_ER(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1571 packet_info *pinfo, proto_tree *tree)
1573 proto_tree *cotp_tree;
1581 switch(tvb_get_guint8(tvb, offset + P_REJECT_ER)) {
1583 str = "Reason not specified";
1586 str = "Invalid parameter code";
1589 str = "Invalid TPDU type";
1592 str = "Invalid parameter value";
1600 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1601 /* pinfo->srcport = 0; */
1602 /* pinfo->destport = dst_ref; */
1603 if (check_col(pinfo->cinfo, COL_INFO))
1604 col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1607 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1608 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1609 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1610 "Length indicator: %u", li);
1611 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
1612 "TPDU code: 0x%x (ER)", tpdu);
1613 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
1614 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
1615 "Reject cause: %s", str);
1622 } /* ositp_decode_ER */
1624 static int ositp_decode_UD(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1625 packet_info *pinfo, proto_tree *tree)
1628 proto_tree *cltp_tree = NULL;
1631 if (check_col(pinfo->cinfo, COL_INFO))
1632 col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
1635 ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, FALSE);
1636 cltp_tree = proto_item_add_subtree(ti, ett_cltp);
1637 proto_tree_add_text(cltp_tree, tvb, offset, 1,
1638 "Length indicator: %u", li);
1643 proto_tree_add_uint_format(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu,
1644 "TPDU code: 0x%x (UD)", tpdu);
1650 ositp_decode_var_part(tvb, offset, li, 0, cltp_tree);
1653 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1654 call_dissector(data_handle,next_tvb, pinfo, tree);
1655 offset += tvb_length_remaining(tvb, offset);
1656 /* we dissected all of the containing PDU */
1660 } /* ositp_decode_UD */
1662 /* Returns TRUE if we found at least one valid COTP or CLTP PDU, FALSE
1665 There doesn't seem to be any way in which the OSI network layer protocol
1666 distinguishes between COTP and CLTP, but the first two octets of both
1667 protocols' headers mean the same thing - length and PDU type - and the
1668 only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
1669 both of them here. */
1670 static gboolean dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
1671 proto_tree *tree, gboolean uses_inactive_subset)
1674 guint8 li, tpdu, cdt;
1675 gboolean first_tpdu = TRUE;
1677 gboolean found_ositp = FALSE;
1678 gboolean is_cltp = FALSE;
1679 gboolean subdissector_found = FALSE;
1681 if (!proto_is_protocol_enabled(find_protocol_by_id(proto_cotp)))
1682 return FALSE; /* COTP has been disabled */
1683 /* XXX - what about CLTP? */
1685 pinfo->current_proto = "COTP";
1687 /* Initialize the COL_INFO field; each of the TPDUs will have its
1688 information appended. */
1689 if (check_col(pinfo->cinfo, COL_INFO))
1690 col_add_str(pinfo->cinfo, COL_INFO, "");
1692 while (tvb_offset_exists(tvb, offset)) {
1694 if (check_col(pinfo->cinfo, COL_INFO))
1695 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1697 if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
1698 if (check_col(pinfo->cinfo, COL_INFO))
1699 col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
1701 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
1706 tpdu = (tvb_get_guint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
1707 if (tpdu == UD_TPDU)
1708 pinfo->current_proto = "CLTP"; /* connectionless transport */
1709 cdt = tvb_get_guint8(tvb, offset + P_CDT) & 0x0F;
1714 new_offset = ositp_decode_CC(tvb, offset, li, tpdu, pinfo, tree,
1715 uses_inactive_subset, &subdissector_found);
1718 new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
1721 new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
1722 uses_inactive_subset, &subdissector_found);
1725 new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree);
1728 new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
1731 new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
1734 new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
1737 new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
1740 new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
1743 new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree);
1747 if (first_tpdu && check_col(pinfo->cinfo, COL_INFO))
1748 col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
1749 new_offset = -1; /* bad PDU type */
1753 if (new_offset == -1) { /* incorrect TPDU */
1755 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
1761 /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
1762 is either COTP or CLTP. */
1763 if (!subdissector_found && check_col(pinfo->cinfo, COL_PROTOCOL))
1764 col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
1768 offset = new_offset;
1772 } /* dissect_ositp_internal */
1774 static void dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1776 if (!dissect_ositp_internal(tvb, pinfo, tree, FALSE))
1777 call_dissector(data_handle,tvb, pinfo, tree);
1781 * CLNP part / main entry point
1784 static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1786 proto_tree *clnp_tree = NULL;
1788 guint8 cnf_proto_id;
1793 char flag_string[6+1];
1794 char *pdu_type_string;
1795 proto_tree *type_tree;
1796 guint16 segment_length;
1798 guint16 segment_offset = 0;
1800 cksum_status_t cksum_status;
1802 guchar src_len, dst_len, nsel, opt_len = 0;
1803 const guint8 *dst_addr, *src_addr;
1806 proto_tree *discpdu_tree;
1807 gboolean save_in_error_pkt;
1808 fragment_data *fd_head;
1810 gboolean update_col_info = TRUE;
1811 gboolean save_fragmented;
1813 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1814 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP");
1815 if (check_col(pinfo->cinfo, COL_INFO))
1816 col_clear(pinfo->cinfo, COL_INFO);
1818 cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
1819 if (cnf_proto_id == NLPID_NULL) {
1820 if (check_col(pinfo->cinfo, COL_INFO))
1821 col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
1823 ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, FALSE);
1824 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1825 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1829 next_tvb = tvb_new_subset(tvb, 1, -1, -1);
1830 dissect_ositp_internal(next_tvb, pinfo, tree, TRUE);
1834 /* return if version not known */
1835 cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
1836 if (cnf_vers != ISO8473_V1) {
1837 call_dissector(data_handle,tvb, pinfo, tree);
1841 /* fixed part decoding */
1842 cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
1843 opt_len = cnf_hdr_len;
1846 ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, FALSE);
1847 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1848 proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1850 proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
1852 proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
1854 cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
1855 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
1857 "Holding Time : %u (%u.%u secs)",
1858 cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
1861 cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
1862 pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
1863 "Unknown (0x%02x)");
1864 flag_string[0] = '\0';
1865 if (cnf_type & CNF_SEG_OK)
1866 strcat(flag_string, "S ");
1867 if (cnf_type & CNF_MORE_SEGS)
1868 strcat(flag_string, "M ");
1869 if (cnf_type & CNF_ERR_OK)
1870 strcat(flag_string, "E ");
1872 ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
1874 "PDU Type : 0x%02x (%s%s)",
1878 type_tree = proto_item_add_subtree(ti, ett_clnp_type);
1879 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1880 decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8,
1881 "Segmentation permitted",
1882 "Segmentation not permitted"));
1883 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1884 decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8,
1887 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1888 decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8,
1889 "Report error if PDU discarded",
1890 "Don't report error if PDU discarded"));
1891 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1892 decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8,
1893 npdu_type_vals, "%s"));
1896 /* If we don't have the full header - i.e., not enough to see the
1897 segmentation part and determine whether this datagram is segmented
1898 or not - set the Info column now; we'll get an exception before
1899 we set it otherwise. */
1901 if (!tvb_bytes_exist(tvb, 0, cnf_hdr_len)) {
1902 if (check_col(pinfo->cinfo, COL_INFO))
1903 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1906 segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
1907 cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
1908 cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
1910 proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
1912 switch (cksum_status) {
1916 * No checksum present, or not enough of the header present to
1919 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
1922 "Checksum : 0x%04x",
1928 * Checksum is correct.
1930 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
1933 "Checksum : 0x%04x (correct)",
1939 * Checksum is not correct.
1941 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
1944 "Checksum : 0x%04x (incorrect)",
1948 opt_len -= 9; /* Fixed part of Hesder */
1953 offset = P_CLNP_ADDRESS_PART;
1954 dst_len = tvb_get_guint8(tvb, offset);
1955 dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
1956 nsel = tvb_get_guint8(tvb, offset + dst_len);
1957 src_len = tvb_get_guint8(tvb, offset + dst_len + 1);
1958 src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);
1961 proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
1963 proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
1966 print_nsap_net(dst_addr, dst_len));
1967 proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
1968 offset + 1 + dst_len, 1, src_len);
1969 proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
1970 offset + dst_len + 2, src_len,
1973 print_nsap_net(src_addr, src_len));
1975 opt_len -= dst_len + src_len +2;
1978 SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
1979 SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
1980 SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
1981 SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);
1983 /* Segmentation Part */
1985 offset += dst_len + src_len + 2;
1987 if (cnf_type & CNF_SEG_OK) {
1988 struct clnp_segment seg; /* XXX - not used */
1989 tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg)); /* XXX - not used */
1991 segment_offset = tvb_get_ntohs(tvb, offset + 2);
1992 du_id = tvb_get_ntohs(tvb, offset);
1994 proto_tree_add_text(clnp_tree, tvb, offset, 2,
1995 "Data unit identifier: %06u",
1997 proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
1998 "Segment offset : %6u",
2000 proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
2001 "Total length : %6u",
2002 tvb_get_ntohs(tvb, offset + 4));
2010 /* To do : decode options */
2012 proto_tree_add_text(clnp_tree, tvb, offset,
2013 cnf_hdr_len - offset,
2014 "Options/Data: <not shown>");
2016 /* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/
2018 dissect_osi_options( opt_len,
2019 tvb, offset, clnp_tree );
2022 /* Length of CLNP datagram plus headers above it. */
2023 len = segment_length;
2025 offset = cnf_hdr_len;
2027 /* If clnp_reassemble is on, this is a segment, we have all the
2028 * data in the segment, and the checksum is valid, then just add the
2029 * segment to the hashtable.
2031 save_fragmented = pinfo->fragmented;
2032 if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
2033 ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
2034 tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
2035 cksum_status != CKSUM_NOT_OK) {
2036 fd_head = fragment_add_check(tvb, offset, pinfo, du_id, clnp_segment_table,
2037 clnp_reassembled_table, segment_offset,
2038 segment_length - cnf_hdr_len,
2039 cnf_type & CNF_MORE_SEGS);
2041 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
2042 fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
2044 /* If this is the first segment, dissect its contents, otherwise
2045 just show it as a segment.
2047 XXX - if we eventually don't save the reassembled contents of all
2048 segmented datagrams, we may want to always reassemble. */
2049 if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
2050 /* Not the first segment - don't dissect it. */
2053 /* First segment, or not segmented. Dissect what we have here. */
2055 /* Get a tvbuff for the payload. */
2056 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
2059 * If this is the first segment, but not the only segment,
2060 * tell the next protocol that.
2062 if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
2063 pinfo->fragmented = TRUE;
2065 pinfo->fragmented = FALSE;
2069 if (next_tvb == NULL) {
2070 /* Just show this as a segment. */
2071 if (check_col(pinfo->cinfo, COL_INFO))
2072 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
2073 pdu_type_string, flag_string, segment_offset);
2075 /* As we haven't reassembled anything, we haven't changed "pi", so
2076 we don't have to restore it. */
2077 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
2079 pinfo->fragmented = save_fragmented;
2083 if (tvb_offset_exists(tvb, offset)) {
2084 switch (cnf_type & CNF_TYPE) {
2088 /* Continue with COTP if any data.
2089 XXX - if this isn't the first Derived PDU of a segmented Initial
2092 if (nsel == (char)tp_nsap_selector || always_decode_transport) {
2093 if (dissect_ositp_internal(next_tvb, pinfo, tree, FALSE)) {
2094 pinfo->fragmented = save_fragmented;
2095 return; /* yes, it appears to be COTP or CLTP */
2098 if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
2100 pinfo->fragmented = save_fragmented;
2101 return; /* yes, it appears to be COTP or CLTP */
2107 /* The payload is the header and "none, some, or all of the data
2108 part of the discarded PDU", i.e. it's like an ICMP error;
2109 dissect it as a CLNP PDU. */
2110 if (check_col(pinfo->cinfo, COL_INFO))
2111 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
2113 next_length = tvb_length_remaining(tvb, offset);
2114 if (next_length != 0) {
2115 /* We have payload; dissect it. */
2116 ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
2118 discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);
2120 /* Save the current value of the "we're inside an error packet"
2121 flag, and set that flag; subdissectors may treat packets
2122 that are the payload of error packets differently from
2124 save_in_error_pkt = pinfo->in_error_pkt;
2125 pinfo->in_error_pkt = TRUE;
2127 call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);
2129 /* Restore the "we're inside an error packet" flag. */
2130 pinfo->in_error_pkt = save_in_error_pkt;
2133 pinfo->fragmented = save_fragmented;
2134 return; /* we're done with this PDU */
2138 /* XXX - dissect this */
2142 if (check_col(pinfo->cinfo, COL_INFO))
2143 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
2144 call_dissector(data_handle,next_tvb, pinfo, tree);
2145 pinfo->fragmented = save_fragmented;
2146 } /* dissect_clnp */
2149 clnp_reassemble_init(void)
2151 fragment_table_init(&clnp_segment_table);
2152 reassembled_table_init(&clnp_reassembled_table);
2156 cotp_reassemble_init(void)
2158 fragment_table_init(&cotp_segment_table);
2159 reassembled_table_init(&cotp_reassembled_table);
2162 void proto_register_clnp(void)
2164 static hf_register_info hf[] = {
2166 { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
2167 VALS(nlpid_vals), 0x0, "", HFILL }},
2170 { "HDR Length ", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2173 { "Version ", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2176 { "Holding Time ", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2179 { "PDU Type ", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2181 { &hf_clnp_pdu_length,
2182 { "PDU length ", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2184 { &hf_clnp_checksum,
2185 { "Checksum ", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2187 { &hf_clnp_dest_length,
2188 { "DAL ", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2191 { " DA ", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
2193 { &hf_clnp_src_length,
2194 { "SAL ", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2197 { " SA ", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
2199 { &hf_clnp_segment_overlap,
2200 { "Segment overlap", "clnp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2201 "Segment overlaps with other segments", HFILL }},
2203 { &hf_clnp_segment_overlap_conflict,
2204 { "Conflicting data in segment overlap", "clnp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2205 "Overlapping segments contained conflicting data", HFILL }},
2207 { &hf_clnp_segment_multiple_tails,
2208 { "Multiple tail segments found", "clnp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2209 "Several tails were found when reassembling the packet", HFILL }},
2211 { &hf_clnp_segment_too_long_segment,
2212 { "Segment too long", "clnp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2213 "Segment contained data past end of packet", HFILL }},
2215 { &hf_clnp_segment_error,
2216 { "Reassembly error", "clnp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2217 "Reassembly error due to illegal segments", HFILL }},
2220 { "CLNP Segment", "clnp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2221 "CLNP Segment", HFILL }},
2223 { &hf_clnp_segments,
2224 { "CLNP Segments", "clnp.segments", FT_NONE, BASE_DEC, NULL, 0x0,
2225 "CLNP Segments", HFILL }},
2227 { &hf_clnp_reassembled_in,
2228 { "Reassembled CLNP in frame", "clnp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2229 "This CLNP packet is reassembled in this frame", HFILL }}
2231 static gint *ett[] = {
2239 module_t *clnp_module;
2241 proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "CLNP", "clnp");
2242 proto_register_field_array(proto_clnp, hf, array_length(hf));
2243 proto_register_subtree_array(ett, array_length(ett));
2244 register_dissector("clnp", dissect_clnp, proto_clnp);
2245 register_heur_dissector_list("clnp", &clnp_heur_subdissector_list);
2246 register_init_routine(clnp_reassemble_init);
2247 register_init_routine(cotp_reassemble_init);
2249 clnp_module = prefs_register_protocol(proto_clnp, NULL);
2250 prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
2251 "NSAP selector for Transport Protocol (last byte in hex)",
2252 "NSAP selector for Transport Protocol (last byte in hex)",
2253 16, &tp_nsap_selector);
2254 prefs_register_bool_preference(clnp_module, "always_decode_transport",
2255 "Always try to decode NSDU as transport PDUs",
2256 "Always try to decode NSDU as transport PDUs",
2257 &always_decode_transport);
2258 prefs_register_bool_preference(clnp_module, "reassemble",
2259 "Reassemble segmented CLNP datagrams",
2260 "Whether segmented CLNP datagrams should be reassembled",
2265 proto_reg_handoff_clnp(void)
2267 data_handle = find_dissector("data");
2269 clnp_handle = create_dissector_handle(dissect_clnp, proto_clnp);
2270 dissector_add("osinl", NLPID_ISO8473_CLNP, clnp_handle);
2271 dissector_add("osinl", NLPID_NULL, clnp_handle); /* Inactive subset */
2272 dissector_add("x.25.spi", NLPID_ISO8473_CLNP, clnp_handle);
2275 void proto_register_cotp(void)
2277 static hf_register_info hf[] = {
2279 { "Source reference", "cotp.srcref", FT_UINT16, BASE_HEX, NULL, 0x0,
2280 "Source address reference", HFILL}},
2282 { "Destination reference", "cotp.destref", FT_UINT16, BASE_HEX, NULL, 0x0,
2283 "Destination address reference", HFILL}},
2285 { "COTP PDU Type", "cotp.type", FT_UINT8, BASE_HEX, VALS(cotp_tpdu_type_abbrev_vals), 0x0,
2286 "COTP PDU Type", HFILL}},
2287 { &hf_cotp_segment_overlap,
2288 { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2289 "Segment overlaps with other segments", HFILL }},
2290 { &hf_cotp_segment_overlap_conflict,
2291 { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2292 "Overlapping segments contained conflicting data", HFILL }},
2293 { &hf_cotp_segment_multiple_tails,
2294 { "Multiple tail segments found", "cotp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2295 "Several tails were found when reassembling the packet", HFILL }},
2296 { &hf_cotp_segment_too_long_segment,
2297 { "Segment too long", "cotp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2298 "Segment contained data past end of packet", HFILL }},
2299 { &hf_cotp_segment_error,
2300 { "Reassembly error", "cotp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2301 "Reassembly error due to illegal segments", HFILL }},
2303 { "COTP Segment", "cotp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2304 "COTP Segment", HFILL }},
2305 { &hf_cotp_segments,
2306 { "COTP Segments", "cotp.segments", FT_NONE, BASE_DEC, NULL, 0x0,
2307 "COTP Segments", HFILL }},
2308 { &hf_cotp_reassembled_in,
2309 { "Reassembled COTP in frame", "cotp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2310 "This COTP packet is reassembled in this frame", HFILL }},
2311 /* ISO DP 8073 i13.3.4(a) Source and destination TSAPs are defined as
2312 identifiers of unspecified type and length.
2313 Some implementations of COTP use printable strings, others use raw bytes.
2314 We always add both representations to the tree; one will always be hidden
2315 depending on the tsap display preference */
2316 { &hf_cotp_vp_src_tsap,
2317 { "Source TSAP", "cotp.src-tsap", FT_STRING, BASE_NONE, NULL, 0x0,
2318 "Calling TSAP", HFILL }},
2319 { &hf_cotp_vp_src_tsap_bytes,
2320 { "Source TSAP", "cotp.src-tsap-bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
2321 "Calling TSAP (bytes representation)", HFILL }},
2322 { &hf_cotp_vp_dst_tsap,
2323 { "Destination TSAP", "cotp.dst-tsap", FT_STRING, BASE_NONE, NULL, 0x0,
2324 "Called TSAP", HFILL }},
2325 { &hf_cotp_vp_dst_tsap_bytes,
2326 { "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
2327 "Called TSAP (bytes representation)", HFILL }},
2330 static gint *ett[] = {
2336 module_t *cotp_module;
2338 proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "COTP", "cotp");
2339 proto_register_field_array(proto_cotp, hf, array_length(hf));
2340 proto_register_subtree_array(ett, array_length(ett));
2341 cotp_module = prefs_register_protocol(proto_cotp, NULL);
2343 prefs_register_bool_preference(cotp_module, "reassemble",
2344 "Reassemble segmented COTP datagrams",
2345 "Whether segmented COTP datagrams should be reassembled",
2348 prefs_register_enum_preference(cotp_module, "tsap_display",
2349 "Display TSAPs as strings or bytes",
2350 "How TSAPs should be displayed",
2352 tsap_display_options,
2355 /* subdissector code in inactive subset */
2356 register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
2358 /* other COTP/ISO 8473 subdissectors */
2359 register_heur_dissector_list("cotp", &cotp_heur_subdissector_list);
2361 /* XXX - what about CLTP and proto_cltp? */
2362 register_dissector("ositp", dissect_ositp, proto_cotp);
2366 proto_reg_handoff_cotp(void)
2368 dissector_handle_t ositp_handle;
2370 ositp_handle = find_dissector("ositp");
2371 dissector_add("ip.proto", IP_PROTO_TP, ositp_handle);
2374 void proto_register_cltp(void)
2376 static hf_register_info hf[] = {
2378 { "CLTP PDU Type", "cltp.type", FT_UINT8, BASE_HEX, VALS(cltp_tpdu_type_abbrev_vals), 0x0,
2379 "CLTP PDU Type", HFILL}},
2381 static gint *ett[] = {
2385 proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "CLTP", "cltp");
2386 proto_register_field_array(proto_cltp, hf, array_length(hf));
2387 proto_register_subtree_array(ett, array_length(ett));