2 * Routines for ISO/OSI network and transport protocol packet disassembly
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.
34 #include <epan/prefs.h>
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"
42 #include <epan/ipproto.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_tpdu_number = -1;
81 static int hf_cotp_tpdu_number_extended = -1;
82 static int hf_cotp_next_tpdu_number = -1;
83 static int hf_cotp_next_tpdu_number_extended = -1;
84 static int hf_cotp_eot = -1;
85 static int hf_cotp_eot_extended = -1;
87 static int hf_cotp_type = -1;
88 static int hf_cotp_segments = -1;
89 static int hf_cotp_segment = -1;
90 static int hf_cotp_segment_overlap = -1;
91 static int hf_cotp_segment_overlap_conflict = -1;
92 static int hf_cotp_segment_multiple_tails = -1;
93 static int hf_cotp_segment_too_long_segment = -1;
94 static int hf_cotp_segment_error = -1;
95 static int hf_cotp_reassembled_in = -1;
97 static const true_false_string fragment_descriptions = {
102 static int proto_cltp = -1;
103 static gint ett_cltp = -1;
105 static int hf_cltp_type = -1;
107 static const fragment_items clnp_frag_items = {
112 &hf_clnp_segment_overlap,
113 &hf_clnp_segment_overlap_conflict,
114 &hf_clnp_segment_multiple_tails,
115 &hf_clnp_segment_too_long_segment,
116 &hf_clnp_segment_error,
117 &hf_clnp_reassembled_in,
121 static const fragment_items cotp_frag_items = {
126 &hf_cotp_segment_overlap,
127 &hf_cotp_segment_overlap_conflict,
128 &hf_cotp_segment_multiple_tails,
129 &hf_cotp_segment_too_long_segment,
130 &hf_cotp_segment_error,
131 &hf_cotp_reassembled_in,
135 static dissector_handle_t clnp_handle;
136 static dissector_handle_t data_handle;
139 * ISO 8473 OSI CLNP definition (see RFC994)
141 * _________________________________
143 * |_________________________________|
145 * |_________________________________|
146 * | Segmentation Part (optional) |
147 * |_________________________________|
148 * | Options Part (optional) |
149 * |_________________________________|
150 * | Data (optional) |
151 * |_________________________________|
154 #define ISO8473_V1 0x01 /* CLNP version 1 */
158 #define CNF_TYPE 0x1f
159 #define CNF_ERR_OK 0x20
160 #define CNF_MORE_SEGS 0x40
161 #define CNF_SEG_OK 0x80
166 #define ERQ_NPDU 0x1E
167 #define ERP_NPDU 0x1F
169 static const value_string npdu_type_abbrev_vals[] = {
178 static const value_string npdu_type_vals[] = {
180 { MD_NPDU, "Multicast Data" },
181 { ER_NPDU, "Error Report" },
182 { ERQ_NPDU, "Echo Request" },
183 { ERP_NPDU, "Echo Response" },
189 #define P_CLNP_PROTO_ID 0
190 #define P_CLNP_HDR_LEN 1
191 #define P_CLNP_VERS 2
193 #define P_CLNP_TYPE 4
194 #define P_CLNP_SEGLEN 5
195 #define P_CLNP_CKSUM 7
196 #define P_CLNP_ADDRESS_PART 9
198 /* Segmentation part */
200 struct clnp_segment {
201 gushort cng_id; /* data unit identifier */
202 gushort cng_off; /* segment offset */
203 gushort cng_tot_len; /* total length */
208 #define NSEL_NET 0x00
213 * ISO8073 OSI COTP definition (see RFC905)
216 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
218 /* TPDU definition */
220 #define ED_TPDU 0x1 /* COTP */
221 #define EA_TPDU 0x2 /* COTP */
222 #define UD_TPDU 0x4 /* CLTP */
223 #define RJ_TPDU 0x5 /* COTP */
224 #define AK_TPDU 0x6 /* COTP */
225 #define ER_TPDU 0x7 /* COTP */
226 #define DR_TPDU 0x8 /* COTP */
227 #define DC_TPDU 0xC /* COTP */
228 #define CC_TPDU 0xD /* COTP */
229 #define CR_TPDU 0xE /* COTP */
230 #define DT_TPDU 0xF /* COTP */
232 static const value_string cotp_tpdu_type_abbrev_vals[] = {
246 static const value_string cltp_tpdu_type_abbrev_vals[] = {
258 #define P_TPDU_NR_0_1 2
259 #define P_TPDU_NR_234 4
260 #define P_VAR_PART_NDT 5
261 #define P_VAR_PART_EDT 8
262 #define P_VAR_PART_DC 6
263 #define P_CDT_IN_AK 8
264 #define P_CDT_IN_RJ 8
265 #define P_REJECT_ER 4
266 #define P_REASON_IN_DR 6
267 #define P_CLASS_OPTION 6
269 /* TPDU length indicator */
271 #define LI_NORMAL_DT_CLASS_01 2
272 #define LI_NORMAL_DT_WITH_CHECKSUM 8
273 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
274 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
275 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
276 #define LI_NORMAL_EA_WITH_CHECKSUM 8
277 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
278 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
279 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
280 #define LI_NORMAL_RJ 4
281 #define LI_EXTENDED_RJ 9
287 /* XXX - can we always decide this based on whether the length
288 indicator is odd or not? What if the variable part has an odd
290 #define is_LI_NORMAL_AK(p) ( ( p & 0x01 ) == 0 )
294 #define VP_ACK_TIME 0x85
295 #define VP_RES_ERROR 0x86
296 #define VP_PRIORITY 0x87
297 #define VP_TRANSIT_DEL 0x88
298 #define VP_THROUGHPUT 0x89
299 #define VP_SEQ_NR 0x8A /* in AK */
300 #define VP_REASSIGNMENT 0x8B
301 #define VP_FLOW_CNTL 0x8C /* in AK */
302 #define VP_TPDU_SIZE 0xC0
303 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
304 #define VP_DST_TSAP 0xC2
305 #define VP_CHECKSUM 0xC3
306 #define VP_VERSION_NR 0xC4
307 #define VP_PROTECTION 0xC5
308 #define VP_OPT_SEL 0xC6
309 #define VP_PROTO_CLASS 0xC7
310 #define VP_PREF_MAX_TPDU_SIZE 0xF0
311 #define VP_INACTIVITY_TIMER 0xF2
313 static const value_string tp_vpart_type_vals[] = {
314 { VP_ACK_TIME, "ack time" },
315 { VP_RES_ERROR, "res error" },
316 { VP_PRIORITY, "priority" },
317 { VP_TRANSIT_DEL, "transit delay" },
318 { VP_THROUGHPUT, "throughput" },
319 { VP_SEQ_NR, "seq number" },
320 { VP_REASSIGNMENT, "reassignment" },
321 { VP_FLOW_CNTL, "flow control" },
322 { VP_TPDU_SIZE, "tpdu-size" },
323 { VP_SRC_TSAP, "src-tsap" },
324 { VP_DST_TSAP, "dst-tsap" },
325 { VP_CHECKSUM, "checksum" },
326 { VP_VERSION_NR, "version" },
327 { VP_PROTECTION, "protection" },
328 { VP_OPT_SEL, "options" },
329 { VP_PROTO_CLASS, "proto class" },
330 { VP_PREF_MAX_TPDU_SIZE, "preferred max TPDU size" },
334 static int hf_cotp_vp_src_tsap = -1;
335 static int hf_cotp_vp_dst_tsap = -1;
336 static int hf_cotp_vp_src_tsap_bytes = -1;
337 static int hf_cotp_vp_dst_tsap_bytes = -1;
342 #define EXTRACT_SHORT(p) pntohs(p)
343 #define EXTRACT_LONG(p) pntohl(p)
345 /* global variables */
347 /* List of dissectors to call for COTP packets put atop the Inactive
349 static heur_dissector_list_t cotp_is_heur_subdissector_list;
350 /* List of dissectors to call for COTP packets put atop CLNP */
351 static heur_dissector_list_t cotp_heur_subdissector_list;
352 /* List of dissectors to call for CLNP packets */
353 static heur_dissector_list_t clnp_heur_subdissector_list;
356 * Reassembly of CLNP.
358 static GHashTable *clnp_segment_table = NULL;
359 static GHashTable *clnp_reassembled_table = NULL;
362 * Reassembly of COTP.
364 static GHashTable *cotp_segment_table = NULL;
365 static GHashTable *cotp_reassembled_table = NULL;
367 #define TSAP_DISPLAY_AUTO 0
368 #define TSAP_DISPLAY_STRING 1
369 #define TSAP_DISPLAY_BYTES 2
373 static guint tp_nsap_selector = NSEL_TP;
374 static gboolean always_decode_transport = FALSE;
375 static gboolean clnp_reassemble = FALSE;
376 static gboolean cotp_reassemble = FALSE;
377 static gint32 tsap_display = TSAP_DISPLAY_AUTO;
379 const enum_val_t tsap_display_options[] = {
380 {"auto", "As strings if printable", TSAP_DISPLAY_AUTO},
381 {"string", "As strings", TSAP_DISPLAY_STRING},
382 {"bytes", "As bytes", TSAP_DISPLAY_BYTES},
387 /* function definitions */
389 #define MAX_TSAP_LEN 32
390 static gboolean is_all_printable(const guchar *stringtocheck, int length)
392 gboolean allprintable;
396 for (i=0;i<length;i++) {
397 if (!(isascii(stringtocheck[i]) && isprint(stringtocheck[i]))) {
403 } /* is_all_printable */
406 static gchar *print_tsap(const guchar *tsap, int length)
409 static gchar str[3][MAX_TSAP_LEN * 2 + 3]; /* TSAP in hex + '0x' + NULL */
412 gboolean allprintable;
414 if (cur == &str[0][0]) {
416 } else if (cur == &str[1][0]) {
424 if (length <= 0 || length > MAX_TSAP_LEN)
425 sprintf(cur, "<unsupported TSAP length>");
427 allprintable = is_all_printable(tsap,length);
430 while (length != 0) {
432 sprintf(tmp, "%c", *tsap ++);
434 sprintf(tmp, "%02x", *tsap ++);
443 static gboolean ositp_decode_var_part(tvbuff_t *tvb, int offset,
444 int vp_length, int class_option,
449 guint16 s, s1,s2,s3,s4;
450 guint32 t1, t2, t3, t4;
451 guint32 pref_max_tpdu_size;
453 while (vp_length != 0) {
454 code = tvb_get_guint8(tvb, offset);
455 proto_tree_add_text(tree, tvb, offset, 1,
456 "Parameter code: 0x%02x (%s)",
458 val_to_str(code, tp_vpart_type_vals, "Unknown"));
464 length = tvb_get_guint8(tvb, offset);
465 proto_tree_add_text(tree, tvb, offset, 1,
466 "Parameter length: %u", length);
473 s = tvb_get_ntohs(tvb, offset);
474 proto_tree_add_text(tree, tvb, offset, length,
475 "Ack time (ms): %u", s);
481 proto_tree_add_text(tree, tvb, offset, 1,
482 "Residual error rate, target value: 10^%u",
483 tvb_get_guint8(tvb, offset));
488 proto_tree_add_text(tree, tvb, offset, 1,
489 "Residual error rate, minimum acceptable: 10^%u",
490 tvb_get_guint8(tvb, offset));
496 proto_tree_add_text(tree, tvb, offset, 1,
497 "Residual error rate, TSDU size of interest: %u",
498 1<<tvb_get_guint8(tvb, offset));
506 s = tvb_get_ntohs(tvb, offset);
507 proto_tree_add_text(tree, tvb, offset, length,
514 s1 = tvb_get_ntohs(tvb, offset);
515 proto_tree_add_text(tree, tvb, offset, 2,
516 "Transit delay, target value, calling-called: %u ms", s1);
521 s2 = tvb_get_ntohs(tvb, offset);
522 proto_tree_add_text(tree, tvb, offset, 2,
523 "Transit delay, maximum acceptable, calling-called: %u ms", s2);
528 s3 = tvb_get_ntohs(tvb, offset);
529 proto_tree_add_text(tree, tvb, offset, 2,
530 "Transit delay, target value, called-calling: %u ms", s3);
535 s4 = tvb_get_ntohs(tvb, offset);
536 proto_tree_add_text(tree, tvb, offset, 2,
537 "Transit delay, maximum acceptable, called-calling: %u ms", s4);
544 t1 = tvb_get_ntoh24(tvb, offset);
545 proto_tree_add_text(tree, tvb, offset, 3,
546 "Maximum throughput, target value, calling-called: %u o/s", t1);
551 t2 = tvb_get_ntoh24(tvb, offset);
552 proto_tree_add_text(tree, tvb, offset, 3,
553 "Maximum throughput, minimum acceptable, calling-called: %u o/s", t2);
558 t3 = tvb_get_ntoh24(tvb, offset);
559 proto_tree_add_text(tree, tvb, offset, 3,
560 "Maximum throughput, target value, called-calling: %u o/s", t3);
565 t4 = tvb_get_ntoh24(tvb, offset);
566 proto_tree_add_text(tree, tvb, offset, 3,
567 "Maximum throughput, minimum acceptable, called-calling: %u o/s", t4);
572 if (length != 0) { /* XXX - should be 0 or 12 */
573 t1 = tvb_get_ntoh24(tvb, offset);
574 proto_tree_add_text(tree, tvb, offset, 3,
575 "Average throughput, target value, calling-called: %u o/s", t1);
580 t2 = tvb_get_ntoh24(tvb, offset);
581 proto_tree_add_text(tree, tvb, offset, 3,
582 "Average throughput, minimum acceptable, calling-called: %u o/s", t2);
587 t3 = tvb_get_ntoh24(tvb, offset);
588 proto_tree_add_text(tree, tvb, offset, 3,
589 "Average throughput, target value, called-calling: %u o/s", t3);
594 t4 = tvb_get_ntoh24(tvb, offset);
595 proto_tree_add_text(tree, tvb, offset, 3,
596 "Average throughput, minimum acceptable, called-calling: %u o/s", t4);
604 proto_tree_add_text(tree, tvb, offset, 2,
605 "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
610 case VP_REASSIGNMENT:
611 proto_tree_add_text(tree, tvb, offset, 2,
612 "Reassignment time: %u secs", tvb_get_ntohs(tvb, offset));
618 proto_tree_add_text(tree, tvb, offset, 4,
619 "Lower window edge: 0x%08x", tvb_get_ntohl(tvb, offset));
624 proto_tree_add_text(tree, tvb, offset, 2,
625 "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
630 proto_tree_add_text(tree, tvb, offset, 2,
631 "Credit: 0x%04x", tvb_get_ntohs(tvb, offset));
639 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
640 proto_tree_add_text(tree, tvb, offset, length,
641 "TPDU size: %u", 1 << c1);
647 /* if our preference is set to STRING or the
648 TSAP is not printable, add as bytes and hidden as string;
649 otherwise vice-versa */
650 if (tsap_display==TSAP_DISPLAY_STRING ||
651 (tsap_display==TSAP_DISPLAY_AUTO && is_all_printable(tvb_get_ptr(tvb,offset,length),length))) {
652 proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
653 print_tsap(tvb_get_ptr(tvb, offset, length),length));
654 proto_tree_add_item_hidden(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset, length, TRUE);
656 proto_tree_add_string_hidden(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
657 print_tsap(tvb_get_ptr(tvb, offset, length),length));
658 proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset, length, TRUE);
665 /* if our preference is set to STRING or the
666 TSAP is not printable, add as bytes and hidden as string;
667 otherwise vice-versa */
668 if (tsap_display==TSAP_DISPLAY_STRING ||
669 (tsap_display==TSAP_DISPLAY_AUTO && is_all_printable(tvb_get_ptr(tvb,offset,length),length))) {
670 proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
671 print_tsap(tvb_get_ptr(tvb, offset, length),length));
672 proto_tree_add_item_hidden(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset, length, TRUE);
674 proto_tree_add_string_hidden(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
675 print_tsap(tvb_get_ptr(tvb, offset, length),length));
676 proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset, length, TRUE);
683 proto_tree_add_text(tree, tvb, offset, length,
684 "Checksum: 0x%04x", tvb_get_ntohs(tvb, offset));
690 c1 = tvb_get_guint8(tvb, offset);
691 proto_tree_add_text(tree, tvb, offset, length,
698 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
699 switch (class_option) {
703 proto_tree_add_text(tree, tvb, offset, 1,
704 "Use of network expedited data");
706 proto_tree_add_text(tree, tvb, offset, 1,
707 "Non use of network expedited data");
709 proto_tree_add_text(tree, tvb, offset, 1,
710 "Use of Receipt confirmation");
712 proto_tree_add_text(tree, tvb, offset, 1,
713 "Use of explicit AK variant");
718 proto_tree_add_text(tree, tvb, offset, 1,
719 "Non-use 16 bit checksum in class 4");
721 proto_tree_add_text(tree, tvb, offset, 1,
722 "Use 16 bit checksum ");
726 proto_tree_add_text(tree, tvb, offset, 1,
727 "Use of transport expedited data transfer");
729 proto_tree_add_text(tree, tvb, offset, 1,
730 "Non-use of transport expedited data transfer");
735 case VP_PREF_MAX_TPDU_SIZE:
739 pref_max_tpdu_size = tvb_get_guint8(tvb, offset);
743 pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
747 pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
751 pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
755 proto_tree_add_text(tree, tvb, offset, length,
756 "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)",
760 proto_tree_add_text(tree, tvb, offset, length,
761 "Preferred maximum TPDU size: %u", pref_max_tpdu_size*128);
766 case VP_INACTIVITY_TIMER:
767 proto_tree_add_text(tree, tvb, offset, length,
768 "Inactivity timer: %u ms", tvb_get_ntohl(tvb, offset));
773 case VP_PROTECTION: /* user-defined */
774 case VP_PROTO_CLASS: /* todo */
775 default: /* unknown, no decoding */
776 proto_tree_add_text(tree, tvb, offset, length,
777 "Parameter value: <not shown>");
787 static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
788 packet_info *pinfo, proto_tree *tree)
790 proto_tree *cotp_tree;
792 guint16 dst_ref, src_ref;
799 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
801 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
803 reason = tvb_get_guint8(tvb, offset + P_REASON_IN_DR);
805 /* the settings of the TCP srcport and destport are currently disables,
806 * for the following reasons:
807 * a) only used for ISO conversation handling (which currently doesn't work)
808 * b) will prevent "ISO on TCP" (RFC1006) packets from using "follow TCP stream" correctly
810 * A future conversation handling might be able to handle different kinds of conversations
811 * (TCP, ISO, TCP on TCP, ...), but in that case this has to be fixed in any case.
813 /*pinfo->srcport = src_ref;*/
814 /*pinfo->destport = dst_ref;*/
816 case (128+0): str = "Normal Disconnect"; break;
817 case (128+1): str = "Remote transport entity congestion"; break;
818 case (128+2): str = "Connection negotiation failed"; break;
819 case (128+3): str = "Duplicate source reference"; break;
820 case (128+4): str = "Mismatched references"; break;
821 case (128+5): str = "Protocol error"; break;
822 case (128+7): str = "Reference overflow"; break;
823 case (128+8): str = "Connection requestion refused"; break;
824 case (128+10):str = "Header or parameter length invalid"; break;
825 case (0): str = "Reason not specified"; break;
826 case (1): str = "Congestion at TSAP"; break;
827 case (2): str = "Session entity not attached to TSAP"; break;
828 case (3): str = "Address unknown"; break;
834 if (check_col(pinfo->cinfo, COL_INFO))
835 col_append_fstr(pinfo->cinfo, COL_INFO,
836 "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
840 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
841 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
842 proto_tree_add_text(cotp_tree, tvb, offset, 1,
843 "Length indicator: %u", li);
844 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
845 "TPDU code: 0x%x (DR)", tpdu);
846 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
847 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset + 4, 2, src_ref);
848 proto_tree_add_text(cotp_tree, tvb, offset + 6, 1,
855 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
856 offset += tvb_length_remaining(tvb, offset);
857 /* we dissected all of the containing PDU */
861 } /* ositp_decode_DR */
863 static int ositp_decode_DT(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
864 packet_info *pinfo, proto_tree *tree,
865 gboolean uses_inactive_subset,
866 gboolean *subdissector_found)
868 proto_tree *cotp_tree = NULL;
870 gboolean is_extended;
871 gboolean is_class_234;
874 gboolean fragment = FALSE;
875 guint32 fragment_length = 0;
877 tvbuff_t *reassembled_tvb = NULL;
878 fragment_data *fd_head;
880 /* VP_CHECKSUM is the only parameter allowed in the variable part.
881 (This means we may misdissect this if the packet is bad and
882 contains other parameters.) */
885 case LI_NORMAL_DT_WITH_CHECKSUM :
886 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
890 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
891 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
892 if ( tpdu_nr & 0x80 )
893 tpdu_nr = tpdu_nr & 0x7F;
898 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
901 case LI_EXTENDED_DT_WITH_CHECKSUM :
902 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
906 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
907 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
908 if ( tpdu_nr & 0x80000000 )
909 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
914 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
917 case LI_NORMAL_DT_CLASS_01 :
918 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
919 if ( tpdu_nr & 0x80 )
920 tpdu_nr = tpdu_nr & 0x7F;
924 is_class_234 = FALSE;
928 default : /* bad TPDU */
934 /* pinfo->destport = dst_ref; */
935 /* pinfo->srcport = 0; */
936 pinfo->fragmented = fragment;
937 if (check_col(pinfo->cinfo, COL_INFO)) {
939 col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x %s",
942 (fragment)? "(fragment)" : "");
944 col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) %s",
946 (fragment)? "(fragment)" : "");
951 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
952 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
953 proto_tree_add_text(cotp_tree, tvb, offset, 1,
954 "Length indicator: %u", li);
959 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
960 "TPDU code: 0x%x (DT)", tpdu);
967 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
974 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb, offset, 4,
976 proto_tree_add_item(cotp_tree, hf_cotp_eot_extended, tvb, offset, 4,
983 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
985 proto_tree_add_item(cotp_tree, hf_cotp_eot, tvb, offset, 1, TRUE);
992 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
995 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
996 if (cotp_reassemble) {
997 fragment_length = tvb_length(next_tvb);
999 * XXX - these sequence numbers are connection sequence number,
1000 * not segment sequence numbers - the first segment of a
1001 * segmented packet doesn't have a specific sequence number (e.g., 0
1002 * or 1), it has whatever the appropriate sequence number is for
1003 * it in the connection.
1005 * For now, we assume segments arrive in order, and just supply
1006 * the negation of the EOT flag as the "more flags" argument.
1007 * We should probably handle out-of-order packets separately,
1008 * so that we can deliver them in order even when *not*
1011 * Note also that TP0 has no sequence number, and relies on
1012 * the protocol atop which it runs to guarantee in-order delivery.
1014 fd_head = fragment_add_seq_next(next_tvb, 0, pinfo, dst_ref,
1016 cotp_reassembled_table,
1017 fragment_length, fragment);
1019 if (fd_head->next) {
1020 /* This is the last packet */
1021 reassembled_tvb = tvb_new_real_data(fd_head->data,
1024 tvb_set_child_real_data_tvbuff(next_tvb, reassembled_tvb);
1025 add_new_data_source(pinfo, reassembled_tvb, "Reassembled COTP");
1027 show_fragment_seq_tree(fd_head,
1030 pinfo, reassembled_tvb);
1031 pinfo->fragmented = fragment;
1032 next_tvb = reassembled_tvb;
1035 if (fragment && reassembled_tvb == NULL) {
1036 proto_tree_add_text(cotp_tree, tvb, offset, -1,
1037 "User data (%u byte%s)", fragment_length,
1038 plurality(fragment_length, "", "s"));
1043 if (uses_inactive_subset) {
1044 if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
1046 *subdissector_found = TRUE;
1048 /* Fill in other Dissectors using inactive subset here */
1049 call_dissector(data_handle,next_tvb, pinfo, tree);
1053 * We dissect payload if one of the following is TRUE:
1055 * - Reassembly option for COTP in preferences is unchecked
1056 * - Reassembly option is checked and this packet is the last fragment
1058 if ( (!cotp_reassemble) ||
1059 ((cotp_reassemble) && (!fragment))) {
1060 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb,
1062 *subdissector_found = TRUE;
1064 call_dissector(data_handle,next_tvb, pinfo, tree);
1069 offset += tvb_length_remaining(tvb, offset);
1070 /* we dissected all of the containing PDU */
1074 } /* ositp_decode_DT */
1076 static int ositp_decode_ED(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1077 packet_info *pinfo, proto_tree *tree)
1079 proto_tree *cotp_tree = NULL;
1081 gboolean is_extended;
1086 /* ED TPDUs are never fragmented */
1088 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1089 (This means we may misdissect this if the packet is bad and
1090 contains other parameters.) */
1093 case LI_NORMAL_DT_WITH_CHECKSUM :
1094 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
1098 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
1099 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1100 if ( tpdu_nr & 0x80 )
1101 tpdu_nr = tpdu_nr & 0x7F;
1104 is_extended = FALSE;
1107 case LI_EXTENDED_DT_WITH_CHECKSUM :
1108 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
1112 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
1113 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1114 if ( tpdu_nr & 0x80000000 )
1115 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
1121 default : /* bad TPDU */
1127 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1129 /* pinfo->destport = dst_ref; */
1130 /* pinfo->srcport = 0; */
1131 if (check_col(pinfo->cinfo, COL_INFO))
1132 col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
1136 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1137 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1138 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1139 "Length indicator: %u", li);
1144 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1145 "TPDU code: 0x%x (ED)", tpdu);
1151 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1157 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number_extended, tvb,
1158 offset, 4, tpdu_nr);
1164 proto_tree_add_uint(cotp_tree, hf_cotp_tpdu_number, tvb, offset, 1,
1172 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1175 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1176 call_dissector(data_handle,next_tvb, pinfo, tree);
1178 offset += tvb_length_remaining(tvb, offset);
1179 /* we dissected all of the containing PDU */
1183 } /* ositp_decode_ED */
1185 static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1186 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1188 proto_tree *cotp_tree;
1196 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1198 case LI_EXTENDED_RJ :
1199 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1200 credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
1208 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1210 /* pinfo->destport = dst_ref; */
1211 /* pinfo->srcport = 0; */
1212 if (check_col(pinfo->cinfo, COL_INFO))
1213 col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
1217 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1218 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1219 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1220 "Length indicator: %u", li);
1221 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
1222 "TPDU code: 0x%x (RJ)", tpdu);
1223 if (li == LI_NORMAL_RJ)
1224 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
1226 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
1227 if (li == LI_NORMAL_RJ)
1228 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset + 4,
1231 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1232 offset + 4, 4, tpdu_nr);
1233 proto_tree_add_text(cotp_tree, tvb, offset + 8, 2,
1234 "Credit: 0x%02x", credit);
1242 } /* ositp_decode_RJ */
1244 static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1245 packet_info *pinfo, proto_tree *tree,
1246 gboolean uses_inactive_subset,
1247 gboolean *subdissector_found)
1250 /* CC & CR decoding in the same function */
1252 proto_tree *cotp_tree = NULL;
1254 guint16 dst_ref, src_ref;
1255 guchar class_option;
1258 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1260 class_option = (tvb_get_guint8(tvb, offset + P_CLASS_OPTION) >> 4 ) & 0x0F;
1261 if (class_option > 4)
1264 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1265 /* pinfo->srcport = src_ref; */
1266 /* pinfo->destport = dst_ref; */
1267 if (check_col(pinfo->cinfo, COL_INFO))
1268 col_append_fstr(pinfo->cinfo, COL_INFO,
1269 "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1270 (tpdu == CR_TPDU) ? "CR" : "CC",
1275 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1276 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1277 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1278 "Length indicator: %u", li);
1283 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1284 "TPDU code: 0x%x (%s)", tpdu,
1285 (tpdu == CR_TPDU) ? "CR" : "CC");
1291 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1296 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1301 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1302 "Class option: 0x%02x", class_option);
1308 ositp_decode_var_part(tvb, offset, li, class_option, cotp_tree);
1311 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1312 if (!uses_inactive_subset){
1313 if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb,
1315 *subdissector_found = TRUE;
1317 call_dissector(data_handle,next_tvb, pinfo, tree);
1321 call_dissector(data_handle, next_tvb, pinfo, tree);
1322 offset += tvb_length_remaining(tvb, offset);
1323 /* we dissected all of the containing PDU */
1327 } /* ositp_decode_CC */
1329 static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1330 packet_info *pinfo, proto_tree *tree)
1332 proto_tree *cotp_tree = NULL;
1334 guint16 dst_ref, src_ref;
1339 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1340 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1342 /* pinfo->srcport = src_ref; */
1343 /* pinfo->destport = dst_ref; */
1344 if (check_col(pinfo->cinfo, COL_INFO))
1345 col_append_fstr(pinfo->cinfo, COL_INFO,
1346 "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1351 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1352 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1353 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1354 "Length indicator: %u", li);
1359 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1360 "TPDU code: 0x%x (DC)", tpdu);
1366 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1371 proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
1376 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1381 } /* ositp_decode_DC */
1383 static int ositp_decode_AK(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1384 guint8 cdt, packet_info *pinfo, proto_tree *tree)
1386 proto_tree *cotp_tree = NULL;
1395 if (is_LI_NORMAL_AK(li)) {
1397 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1398 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1400 /* pinfo->srcport = 0; */
1401 /* pinfo->destport = dst_ref; */
1402 if (check_col(pinfo->cinfo, COL_INFO))
1403 col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1407 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1408 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1409 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1410 "Length indicator: %u", li);
1415 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1416 "TPDU code: 0x%x (AK)", tpdu);
1417 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1424 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1429 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1436 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1439 } else { /* extended format */
1441 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1442 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1443 cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1445 if (check_col(pinfo->cinfo, COL_INFO))
1446 col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1450 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1451 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1452 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1453 "Length indicator: %u", li);
1458 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1459 "TPDU code: 0x%x (AK)", tpdu);
1465 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1470 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1471 offset, 4, tpdu_nr);
1477 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1478 "Credit: 0x%04x", cdt_in_ak);
1484 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1487 } /* is_LI_NORMAL_AK */
1491 } /* ositp_decode_AK */
1493 static int ositp_decode_EA(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1494 packet_info *pinfo, proto_tree *tree)
1496 proto_tree *cotp_tree = NULL;
1498 gboolean is_extended;
1505 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1506 (This means we may misdissect this if the packet is bad and
1507 contains other parameters.) */
1510 case LI_NORMAL_EA_WITH_CHECKSUM :
1511 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
1512 tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1516 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1517 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1518 is_extended = FALSE;
1521 case LI_EXTENDED_EA_WITH_CHECKSUM :
1522 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
1523 tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1527 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1528 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1532 default : /* bad TPDU */
1538 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1539 /* pinfo->srcport = 0; */
1540 /* pinfo->destport = dst_ref; */
1541 if (check_col(pinfo->cinfo, COL_INFO))
1542 col_append_fstr(pinfo->cinfo, COL_INFO,
1543 "EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1546 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1547 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1548 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1549 "Length indicator: %u", li);
1554 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
1555 "TPDU code: 0x%x (EA)", tpdu);
1561 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
1567 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number_extended, tvb,
1568 offset, 4, tpdu_nr);
1574 proto_tree_add_uint(cotp_tree, hf_cotp_next_tpdu_number, tvb, offset, 1,
1582 ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
1587 } /* ositp_decode_EA */
1589 static int ositp_decode_ER(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1590 packet_info *pinfo, proto_tree *tree)
1592 proto_tree *cotp_tree;
1600 switch(tvb_get_guint8(tvb, offset + P_REJECT_ER)) {
1602 str = "Reason not specified";
1605 str = "Invalid parameter code";
1608 str = "Invalid TPDU type";
1611 str = "Invalid parameter value";
1619 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1620 /* pinfo->srcport = 0; */
1621 /* pinfo->destport = dst_ref; */
1622 if (check_col(pinfo->cinfo, COL_INFO))
1623 col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1626 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1627 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1628 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1629 "Length indicator: %u", li);
1630 proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
1631 "TPDU code: 0x%x (ER)", tpdu);
1632 proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
1633 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
1634 "Reject cause: %s", str);
1641 } /* ositp_decode_ER */
1643 static int ositp_decode_UD(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
1644 packet_info *pinfo, proto_tree *tree)
1647 proto_tree *cltp_tree = NULL;
1650 if (check_col(pinfo->cinfo, COL_INFO))
1651 col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
1654 ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, FALSE);
1655 cltp_tree = proto_item_add_subtree(ti, ett_cltp);
1656 proto_tree_add_text(cltp_tree, tvb, offset, 1,
1657 "Length indicator: %u", li);
1662 proto_tree_add_uint_format(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu,
1663 "TPDU code: 0x%x (UD)", tpdu);
1669 ositp_decode_var_part(tvb, offset, li, 0, cltp_tree);
1672 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1673 call_dissector(data_handle,next_tvb, pinfo, tree);
1674 offset += tvb_length_remaining(tvb, offset);
1675 /* we dissected all of the containing PDU */
1679 } /* ositp_decode_UD */
1681 /* Returns TRUE if we found at least one valid COTP or CLTP PDU, FALSE
1684 There doesn't seem to be any way in which the OSI network layer protocol
1685 distinguishes between COTP and CLTP, but the first two octets of both
1686 protocols' headers mean the same thing - length and PDU type - and the
1687 only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
1688 both of them here. */
1689 static gboolean dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
1690 proto_tree *tree, gboolean uses_inactive_subset)
1693 guint8 li, tpdu, cdt;
1694 gboolean first_tpdu = TRUE;
1696 gboolean found_ositp = FALSE;
1697 gboolean is_cltp = FALSE;
1698 gboolean subdissector_found = FALSE;
1700 if (!proto_is_protocol_enabled(find_protocol_by_id(proto_cotp)))
1701 return FALSE; /* COTP has been disabled */
1702 /* XXX - what about CLTP? */
1704 pinfo->current_proto = "COTP";
1706 /* Initialize the COL_INFO field; each of the TPDUs will have its
1707 information appended. */
1708 if (check_col(pinfo->cinfo, COL_INFO))
1709 col_add_str(pinfo->cinfo, COL_INFO, "");
1711 while (tvb_offset_exists(tvb, offset)) {
1713 if (check_col(pinfo->cinfo, COL_INFO))
1714 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1716 if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
1717 if (check_col(pinfo->cinfo, COL_INFO))
1718 col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
1720 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
1725 tpdu = (tvb_get_guint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
1726 if (tpdu == UD_TPDU)
1727 pinfo->current_proto = "CLTP"; /* connectionless transport */
1728 cdt = tvb_get_guint8(tvb, offset + P_CDT) & 0x0F;
1733 new_offset = ositp_decode_CC(tvb, offset, li, tpdu, pinfo, tree,
1734 uses_inactive_subset, &subdissector_found);
1737 new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
1740 new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
1741 uses_inactive_subset, &subdissector_found);
1744 new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree);
1747 new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
1750 new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
1753 new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
1756 new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
1759 new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
1762 new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree);
1766 if (first_tpdu && check_col(pinfo->cinfo, COL_INFO))
1767 col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
1768 new_offset = -1; /* bad PDU type */
1772 if (new_offset == -1) { /* incorrect TPDU */
1774 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
1780 /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
1781 is either COTP or CLTP. */
1782 if (!subdissector_found && check_col(pinfo->cinfo, COL_PROTOCOL))
1783 col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
1787 offset = new_offset;
1791 } /* dissect_ositp_internal */
1793 static void dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1795 if (!dissect_ositp_internal(tvb, pinfo, tree, FALSE))
1796 call_dissector(data_handle,tvb, pinfo, tree);
1800 * CLNP part / main entry point
1803 static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1805 proto_tree *clnp_tree = NULL;
1807 guint8 cnf_proto_id;
1812 char flag_string[6+1];
1813 char *pdu_type_string;
1814 proto_tree *type_tree;
1815 guint16 segment_length;
1817 guint16 segment_offset = 0;
1819 cksum_status_t cksum_status;
1821 guchar src_len, dst_len, nsel, opt_len = 0;
1822 const guint8 *dst_addr, *src_addr;
1825 proto_tree *discpdu_tree;
1826 gboolean save_in_error_pkt;
1827 fragment_data *fd_head;
1829 gboolean update_col_info = TRUE;
1830 gboolean save_fragmented;
1832 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1833 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP");
1834 if (check_col(pinfo->cinfo, COL_INFO))
1835 col_clear(pinfo->cinfo, COL_INFO);
1837 cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
1838 if (cnf_proto_id == NLPID_NULL) {
1839 if (check_col(pinfo->cinfo, COL_INFO))
1840 col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
1842 ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, FALSE);
1843 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1844 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1848 next_tvb = tvb_new_subset(tvb, 1, -1, -1);
1849 dissect_ositp_internal(next_tvb, pinfo, tree, TRUE);
1853 /* return if version not known */
1854 cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
1855 if (cnf_vers != ISO8473_V1) {
1856 call_dissector(data_handle,tvb, pinfo, tree);
1860 /* fixed part decoding */
1861 cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
1862 opt_len = cnf_hdr_len;
1865 ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, FALSE);
1866 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1867 proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1869 proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
1871 proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
1873 cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
1874 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
1876 "Holding Time : %u (%u.%u secs)",
1877 cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
1880 cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
1881 pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
1882 "Unknown (0x%02x)");
1883 flag_string[0] = '\0';
1884 if (cnf_type & CNF_SEG_OK)
1885 strcat(flag_string, "S ");
1886 if (cnf_type & CNF_MORE_SEGS)
1887 strcat(flag_string, "M ");
1888 if (cnf_type & CNF_ERR_OK)
1889 strcat(flag_string, "E ");
1891 ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
1893 "PDU Type : 0x%02x (%s%s)",
1897 type_tree = proto_item_add_subtree(ti, ett_clnp_type);
1898 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1899 decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8,
1900 "Segmentation permitted",
1901 "Segmentation not permitted"));
1902 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1903 decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8,
1906 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1907 decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8,
1908 "Report error if PDU discarded",
1909 "Don't report error if PDU discarded"));
1910 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1911 decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8,
1912 npdu_type_vals, "%s"));
1915 /* If we don't have the full header - i.e., not enough to see the
1916 segmentation part and determine whether this datagram is segmented
1917 or not - set the Info column now; we'll get an exception before
1918 we set it otherwise. */
1920 if (!tvb_bytes_exist(tvb, 0, cnf_hdr_len)) {
1921 if (check_col(pinfo->cinfo, COL_INFO))
1922 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1925 segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
1926 cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
1927 cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
1929 proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
1931 switch (cksum_status) {
1935 * No checksum present, or not enough of the header present to
1938 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
1941 "Checksum : 0x%04x",
1947 * Checksum is correct.
1949 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
1952 "Checksum : 0x%04x (correct)",
1958 * Checksum is not correct.
1960 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
1963 "Checksum : 0x%04x (incorrect)",
1967 opt_len -= 9; /* Fixed part of Hesder */
1972 offset = P_CLNP_ADDRESS_PART;
1973 dst_len = tvb_get_guint8(tvb, offset);
1974 dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
1975 nsel = tvb_get_guint8(tvb, offset + dst_len);
1976 src_len = tvb_get_guint8(tvb, offset + dst_len + 1);
1977 src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);
1980 proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
1982 proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
1985 print_nsap_net(dst_addr, dst_len));
1986 proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
1987 offset + 1 + dst_len, 1, src_len);
1988 proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
1989 offset + dst_len + 2, src_len,
1992 print_nsap_net(src_addr, src_len));
1994 opt_len -= dst_len + src_len +2;
1997 SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
1998 SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
1999 SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
2000 SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);
2002 /* Segmentation Part */
2004 offset += dst_len + src_len + 2;
2006 if (cnf_type & CNF_SEG_OK) {
2007 struct clnp_segment seg; /* XXX - not used */
2008 tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg)); /* XXX - not used */
2010 segment_offset = tvb_get_ntohs(tvb, offset + 2);
2011 du_id = tvb_get_ntohs(tvb, offset);
2013 proto_tree_add_text(clnp_tree, tvb, offset, 2,
2014 "Data unit identifier: %06u",
2016 proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
2017 "Segment offset : %6u",
2019 proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
2020 "Total length : %6u",
2021 tvb_get_ntohs(tvb, offset + 4));
2029 /* To do : decode options */
2031 proto_tree_add_text(clnp_tree, tvb, offset,
2032 cnf_hdr_len - offset,
2033 "Options/Data: <not shown>");
2035 /* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/
2037 dissect_osi_options( opt_len,
2038 tvb, offset, clnp_tree );
2041 /* Length of CLNP datagram plus headers above it. */
2042 len = segment_length;
2044 offset = cnf_hdr_len;
2046 /* If clnp_reassemble is on, this is a segment, we have all the
2047 * data in the segment, and the checksum is valid, then just add the
2048 * segment to the hashtable.
2050 save_fragmented = pinfo->fragmented;
2051 if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
2052 ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
2053 tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
2054 cksum_status != CKSUM_NOT_OK) {
2055 fd_head = fragment_add_check(tvb, offset, pinfo, du_id, clnp_segment_table,
2056 clnp_reassembled_table, segment_offset,
2057 segment_length - cnf_hdr_len,
2058 cnf_type & CNF_MORE_SEGS);
2060 next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
2061 fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
2063 /* If this is the first segment, dissect its contents, otherwise
2064 just show it as a segment.
2066 XXX - if we eventually don't save the reassembled contents of all
2067 segmented datagrams, we may want to always reassemble. */
2068 if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
2069 /* Not the first segment - don't dissect it. */
2072 /* First segment, or not segmented. Dissect what we have here. */
2074 /* Get a tvbuff for the payload. */
2075 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
2078 * If this is the first segment, but not the only segment,
2079 * tell the next protocol that.
2081 if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
2082 pinfo->fragmented = TRUE;
2084 pinfo->fragmented = FALSE;
2088 if (next_tvb == NULL) {
2089 /* Just show this as a segment. */
2090 if (check_col(pinfo->cinfo, COL_INFO))
2091 col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
2092 pdu_type_string, flag_string, segment_offset);
2094 /* As we haven't reassembled anything, we haven't changed "pi", so
2095 we don't have to restore it. */
2096 call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
2098 pinfo->fragmented = save_fragmented;
2102 if (tvb_offset_exists(tvb, offset)) {
2103 switch (cnf_type & CNF_TYPE) {
2107 /* Continue with COTP if any data.
2108 XXX - if this isn't the first Derived PDU of a segmented Initial
2111 if (nsel == (char)tp_nsap_selector || always_decode_transport) {
2112 if (dissect_ositp_internal(next_tvb, pinfo, tree, FALSE)) {
2113 pinfo->fragmented = save_fragmented;
2114 return; /* yes, it appears to be COTP or CLTP */
2117 if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
2119 pinfo->fragmented = save_fragmented;
2120 return; /* yes, it appears to be COTP or CLTP */
2126 /* The payload is the header and "none, some, or all of the data
2127 part of the discarded PDU", i.e. it's like an ICMP error;
2128 dissect it as a CLNP PDU. */
2129 if (check_col(pinfo->cinfo, COL_INFO))
2130 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
2132 next_length = tvb_length_remaining(tvb, offset);
2133 if (next_length != 0) {
2134 /* We have payload; dissect it. */
2135 ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
2137 discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);
2139 /* Save the current value of the "we're inside an error packet"
2140 flag, and set that flag; subdissectors may treat packets
2141 that are the payload of error packets differently from
2143 save_in_error_pkt = pinfo->in_error_pkt;
2144 pinfo->in_error_pkt = TRUE;
2146 call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);
2148 /* Restore the "we're inside an error packet" flag. */
2149 pinfo->in_error_pkt = save_in_error_pkt;
2152 pinfo->fragmented = save_fragmented;
2153 return; /* we're done with this PDU */
2157 /* XXX - dissect this */
2161 if (check_col(pinfo->cinfo, COL_INFO))
2162 col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
2163 call_dissector(data_handle,next_tvb, pinfo, tree);
2164 pinfo->fragmented = save_fragmented;
2165 } /* dissect_clnp */
2168 clnp_reassemble_init(void)
2170 fragment_table_init(&clnp_segment_table);
2171 reassembled_table_init(&clnp_reassembled_table);
2175 cotp_reassemble_init(void)
2177 fragment_table_init(&cotp_segment_table);
2178 reassembled_table_init(&cotp_reassembled_table);
2181 void proto_register_clnp(void)
2183 static hf_register_info hf[] = {
2185 { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
2186 VALS(nlpid_vals), 0x0, "", HFILL }},
2189 { "HDR Length ", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2192 { "Version ", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2195 { "Holding Time ", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2198 { "PDU Type ", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2200 { &hf_clnp_pdu_length,
2201 { "PDU length ", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2203 { &hf_clnp_checksum,
2204 { "Checksum ", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
2206 { &hf_clnp_dest_length,
2207 { "DAL ", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2210 { " DA ", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
2212 { &hf_clnp_src_length,
2213 { "SAL ", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
2216 { " SA ", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
2218 { &hf_clnp_segment_overlap,
2219 { "Segment overlap", "clnp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2220 "Segment overlaps with other segments", HFILL }},
2222 { &hf_clnp_segment_overlap_conflict,
2223 { "Conflicting data in segment overlap", "clnp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2224 "Overlapping segments contained conflicting data", HFILL }},
2226 { &hf_clnp_segment_multiple_tails,
2227 { "Multiple tail segments found", "clnp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2228 "Several tails were found when reassembling the packet", HFILL }},
2230 { &hf_clnp_segment_too_long_segment,
2231 { "Segment too long", "clnp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2232 "Segment contained data past end of packet", HFILL }},
2234 { &hf_clnp_segment_error,
2235 { "Reassembly error", "clnp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2236 "Reassembly error due to illegal segments", HFILL }},
2239 { "CLNP Segment", "clnp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2240 "CLNP Segment", HFILL }},
2242 { &hf_clnp_segments,
2243 { "CLNP Segments", "clnp.segments", FT_NONE, BASE_DEC, NULL, 0x0,
2244 "CLNP Segments", HFILL }},
2246 { &hf_clnp_reassembled_in,
2247 { "Reassembled CLNP in frame", "clnp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2248 "This CLNP packet is reassembled in this frame", HFILL }}
2250 static gint *ett[] = {
2258 module_t *clnp_module;
2260 proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "CLNP", "clnp");
2261 proto_register_field_array(proto_clnp, hf, array_length(hf));
2262 proto_register_subtree_array(ett, array_length(ett));
2263 register_dissector("clnp", dissect_clnp, proto_clnp);
2264 register_heur_dissector_list("clnp", &clnp_heur_subdissector_list);
2265 register_init_routine(clnp_reassemble_init);
2266 register_init_routine(cotp_reassemble_init);
2268 clnp_module = prefs_register_protocol(proto_clnp, NULL);
2269 prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
2270 "NSAP selector for Transport Protocol (last byte in hex)",
2271 "NSAP selector for Transport Protocol (last byte in hex)",
2272 16, &tp_nsap_selector);
2273 prefs_register_bool_preference(clnp_module, "always_decode_transport",
2274 "Always try to decode NSDU as transport PDUs",
2275 "Always try to decode NSDU as transport PDUs",
2276 &always_decode_transport);
2277 prefs_register_bool_preference(clnp_module, "reassemble",
2278 "Reassemble segmented CLNP datagrams",
2279 "Whether segmented CLNP datagrams should be reassembled",
2284 proto_reg_handoff_clnp(void)
2286 data_handle = find_dissector("data");
2288 clnp_handle = create_dissector_handle(dissect_clnp, proto_clnp);
2289 dissector_add("osinl", NLPID_ISO8473_CLNP, clnp_handle);
2290 dissector_add("osinl", NLPID_NULL, clnp_handle); /* Inactive subset */
2291 dissector_add("x.25.spi", NLPID_ISO8473_CLNP, clnp_handle);
2294 void proto_register_cotp(void)
2296 static hf_register_info hf[] = {
2298 { "Source reference", "cotp.srcref", FT_UINT16, BASE_HEX, NULL, 0x0,
2299 "Source address reference", HFILL}},
2301 { "Destination reference", "cotp.destref", FT_UINT16, BASE_HEX, NULL, 0x0,
2302 "Destination address reference", HFILL}},
2304 { "COTP PDU Type", "cotp.type", FT_UINT8, BASE_HEX, VALS(cotp_tpdu_type_abbrev_vals), 0x0,
2305 "COTP PDU Type", HFILL}},
2306 { &hf_cotp_tpdu_number,
2307 { "TPDU number", "cotp.tpdu-number", FT_UINT8, BASE_HEX, NULL, 0x0,
2308 "TPDU number", HFILL}},
2309 { &hf_cotp_tpdu_number_extended,
2310 { "TPDU number", "cotp.tpdu-number", FT_UINT32, BASE_HEX, NULL, 0x0,
2311 "TPDU number", HFILL}},
2312 { &hf_cotp_next_tpdu_number,
2313 { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT8, BASE_HEX, NULL, 0x0,
2314 "Your TPDU number", HFILL}},
2315 { &hf_cotp_next_tpdu_number_extended,
2316 { "Your TPDU number", "cotp.next-tpdu-number", FT_UINT32, BASE_HEX, NULL, 0x0,
2317 "Your TPDU number", HFILL}},
2319 { "Last data unit", "cotp.eot", FT_BOOLEAN, 8, TFS(&fragment_descriptions), 0x80,
2320 "Is current TPDU the last data unit of a complete DT TPDU sequence?", HFILL}},
2321 { &hf_cotp_eot_extended,
2322 { "Last data unit", "cotp.eot", FT_BOOLEAN, 32, TFS(&fragment_descriptions), 0x80000000,
2323 "Is current TPDU the last data unit of a complete DT TPDU sequence?", HFILL}},
2324 { &hf_cotp_segment_overlap,
2325 { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2326 "Segment overlaps with other segments", HFILL }},
2327 { &hf_cotp_segment_overlap_conflict,
2328 { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2329 "Overlapping segments contained conflicting data", HFILL }},
2330 { &hf_cotp_segment_multiple_tails,
2331 { "Multiple tail segments found", "cotp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2332 "Several tails were found when reassembling the packet", HFILL }},
2333 { &hf_cotp_segment_too_long_segment,
2334 { "Segment too long", "cotp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2335 "Segment contained data past end of packet", HFILL }},
2336 { &hf_cotp_segment_error,
2337 { "Reassembly error", "cotp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2338 "Reassembly error due to illegal segments", HFILL }},
2340 { "COTP Segment", "cotp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2341 "COTP Segment", HFILL }},
2342 { &hf_cotp_segments,
2343 { "COTP Segments", "cotp.segments", FT_NONE, BASE_DEC, NULL, 0x0,
2344 "COTP Segments", HFILL }},
2345 { &hf_cotp_reassembled_in,
2346 { "Reassembled COTP in frame", "cotp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2347 "This COTP packet is reassembled in this frame", HFILL }},
2348 /* ISO DP 8073 i13.3.4(a) Source and destination TSAPs are defined as
2349 identifiers of unspecified type and length.
2350 Some implementations of COTP use printable strings, others use raw bytes.
2351 We always add both representations to the tree; one will always be hidden
2352 depending on the tsap display preference */
2353 { &hf_cotp_vp_src_tsap,
2354 { "Source TSAP", "cotp.src-tsap", FT_STRING, BASE_NONE, NULL, 0x0,
2355 "Calling TSAP", HFILL }},
2356 { &hf_cotp_vp_src_tsap_bytes,
2357 { "Source TSAP", "cotp.src-tsap-bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
2358 "Calling TSAP (bytes representation)", HFILL }},
2359 { &hf_cotp_vp_dst_tsap,
2360 { "Destination TSAP", "cotp.dst-tsap", FT_STRING, BASE_NONE, NULL, 0x0,
2361 "Called TSAP", HFILL }},
2362 { &hf_cotp_vp_dst_tsap_bytes,
2363 { "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
2364 "Called TSAP (bytes representation)", HFILL }},
2367 static gint *ett[] = {
2373 module_t *cotp_module;
2375 proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "COTP", "cotp");
2376 proto_register_field_array(proto_cotp, hf, array_length(hf));
2377 proto_register_subtree_array(ett, array_length(ett));
2378 cotp_module = prefs_register_protocol(proto_cotp, NULL);
2380 prefs_register_bool_preference(cotp_module, "reassemble",
2381 "Reassemble segmented COTP datagrams",
2382 "Whether segmented COTP datagrams should be reassembled."
2383 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2386 prefs_register_enum_preference(cotp_module, "tsap_display",
2387 "Display TSAPs as strings or bytes",
2388 "How TSAPs should be displayed",
2390 tsap_display_options,
2393 /* subdissector code in inactive subset */
2394 register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
2396 /* other COTP/ISO 8473 subdissectors */
2397 register_heur_dissector_list("cotp", &cotp_heur_subdissector_list);
2399 /* XXX - what about CLTP and proto_cltp? */
2400 register_dissector("ositp", dissect_ositp, proto_cotp);
2404 proto_reg_handoff_cotp(void)
2406 dissector_handle_t ositp_handle;
2408 ositp_handle = find_dissector("ositp");
2409 dissector_add("ip.proto", IP_PROTO_TP, ositp_handle);
2412 void proto_register_cltp(void)
2414 static hf_register_info hf[] = {
2416 { "CLTP PDU Type", "cltp.type", FT_UINT8, BASE_HEX, VALS(cltp_tpdu_type_abbrev_vals), 0x0,
2417 "CLTP PDU Type", HFILL}},
2419 static gint *ett[] = {
2423 proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "CLTP", "cltp");
2424 proto_register_field_array(proto_cltp, hf, array_length(hf));
2425 proto_register_subtree_array(ett, array_length(ett));