2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-clnp.c,v 1.19 2000/12/23 23:06:50 guy Exp $
5 * Laurent Deniel <deniel@worldnet.fr>
6 * Ralf Schneider <Ralf.Schneider@t-online.de>
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@zing.org>
10 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
43 #include "packet-osi.h"
44 #include "packet-osi-options.h"
45 #include "packet-isis.h"
46 #include "packet-esis.h"
49 /* protocols and fields */
51 static int proto_clnp = -1;
52 static gint ett_clnp = -1;
53 static gint ett_clnp_type = -1;
54 static gint ett_clnp_disc_pdu = -1;
55 static int proto_cotp = -1;
56 static gint ett_cotp = -1;
57 static int proto_cltp = -1;
58 static gint ett_cltp = -1;
60 static int hf_clnp_id = -1;
61 static int hf_clnp_length = -1;
62 static int hf_clnp_version = -1;
63 static int hf_clnp_ttl = -1;
64 static int hf_clnp_type = -1;
65 static int hf_clnp_pdu_length = -1;
66 static int hf_clnp_checksum = -1;
67 static int hf_clnp_dest_length = -1;
68 static int hf_clnp_dest = -1;
69 static int hf_clnp_src_length = -1;
70 static int hf_clnp_src = -1;
73 * ISO 8473 OSI CLNP definition (see RFC994)
75 * _________________________________
77 * |_________________________________|
79 * |_________________________________|
80 * | Segmentation Part (optional) |
81 * |_________________________________|
82 * | Options Part (optional) |
83 * |_________________________________|
85 * |_________________________________|
88 #define ISO8473_V1 0x01 /* CLNP version 1 */
93 #define CNF_ERR_OK 0x20
94 #define CNF_MORE_SEGS 0x40
95 #define CNF_SEG_OK 0x80
100 #define ERQ_NPDU 0x1E
101 #define ERP_NPDU 0x1F
103 static const value_string npdu_type_abbrev_vals[] = {
112 static const value_string npdu_type_vals[] = {
114 { MD_NPDU, "Multicast Data" },
115 { ER_NPDU, "Error Report" },
116 { ERQ_NPDU, "Echo Request" },
117 { ERP_NPDU, "Echo Response" },
123 #define P_CLNP_PROTO_ID 0
124 #define P_CLNP_HDR_LEN 1
125 #define P_CLNP_VERS 2
127 #define P_CLNP_TYPE 4
128 #define P_CLNP_SEGLEN 5
129 #define P_CLNP_CKSUM 7
130 #define P_CLNP_ADDRESS_PART 9
132 /* Segmentation part */
134 struct clnp_segment {
135 u_short cng_id; /* data unit identifier */
136 u_short cng_off; /* segment offset */
137 u_short cng_tot_len; /* total length */
142 #define NSEL_NET 0x00
147 * ISO8073 OSI COTP definition (see RFC905)
150 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
152 /* TPDU definition */
154 #define ED_TPDU 0x1 /* COTP */
155 #define EA_TPDU 0x2 /* COTP */
156 #define UD_TPDU 0x4 /* CLTP */
157 #define RJ_TPDU 0x5 /* COTP */
158 #define AK_TPDU 0x6 /* COTP */
159 #define ER_TPDU 0x7 /* COTP */
160 #define DR_TPDU 0x8 /* COTP */
161 #define DC_TPDU 0xC /* COTP */
162 #define CC_TPDU 0xD /* COTP */
163 #define CR_TPDU 0xE /* COTP */
164 #define DT_TPDU 0xF /* COTP */
173 #define P_TPDU_NR_0_1 2
174 #define P_TPDU_NR_234 4
175 #define P_VAR_PART_NDT 5
176 #define P_VAR_PART_EDT 8
177 #define P_VAR_PART_DC 6
178 #define P_CDT_IN_AK 8
179 #define P_CDT_IN_RJ 8
180 #define P_REJECT_ER 4
181 #define P_REASON_IN_DR 6
182 #define P_CLASS_OPTION 6
184 /* TPDU length indicator */
186 #define LI_NORMAL_DT_CLASS_01 2
187 #define LI_NORMAL_DT_WITH_CHECKSUM 8
188 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
189 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
190 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
191 #define LI_NORMAL_EA_WITH_CHECKSUM 8
192 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
193 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
194 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
195 #define LI_NORMAL_RJ 4
196 #define LI_EXTENDED_RJ 9
202 /* XXX - can we always decide this based on whether the length
203 indicator is odd or not? What if the variable part has an odd
205 #define is_LI_NORMAL_AK(p) ( ( p & 0x01 ) == 0 )
209 #define VP_ACK_TIME 0x85
210 #define VP_RES_ERROR 0x86
211 #define VP_PRIORITY 0x87
212 #define VP_TRANSIT_DEL 0x88
213 #define VP_THROUGHPUT 0x89
214 #define VP_SEQ_NR 0x8A /* in AK */
215 #define VP_REASSIGNMENT 0x8B
216 #define VP_FLOW_CNTL 0x8C /* in AK */
217 #define VP_TPDU_SIZE 0xC0
218 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
219 #define VP_DST_TSAP 0xC2
220 #define VP_CHECKSUM 0xC3
221 #define VP_VERSION_NR 0xC4
222 #define VP_PROTECTION 0xC5
223 #define VP_OPT_SEL 0xC6
224 #define VP_PROTO_CLASS 0xC7
225 #define VP_PREF_MAX_TPDU_SIZE 0xF0
226 #define VP_INACTIVITY_TIMER 0xF2
228 static const value_string tp_vpart_type_vals[] = {
229 { VP_ACK_TIME, "ack time" },
230 { VP_RES_ERROR, "res error" },
231 { VP_PRIORITY, "priority" },
232 { VP_TRANSIT_DEL, "transit delay" },
233 { VP_THROUGHPUT, "throughput" },
234 { VP_SEQ_NR, "seq number" },
235 { VP_REASSIGNMENT, "reassignment" },
236 { VP_FLOW_CNTL, "flow control" },
237 { VP_TPDU_SIZE, "tpdu-size" },
238 { VP_SRC_TSAP, "src-tsap" },
239 { VP_DST_TSAP, "dst-tsap" },
240 { VP_CHECKSUM, "checksum" },
241 { VP_VERSION_NR, "version" },
242 { VP_PROTECTION, "protection" },
243 { VP_OPT_SEL, "options" },
244 { VP_PROTO_CLASS, "proto class" },
245 { VP_PREF_MAX_TPDU_SIZE, "preferred max TPDU size" },
251 #define EXTRACT_SHORT(p) pntohs(p)
252 #define EXTRACT_LONG(p) pntohl(p)
254 /* global variables */
256 static u_char li, tpdu, cdt; /* common fields */
257 static u_short dst_ref;
259 /* List of dissectors to call for COTP packets put atop the Inactive
261 static heur_dissector_list_t cotp_is_heur_subdissector_list;
264 static guint tp_nsap_selector = NSEL_TP;
265 static gboolean always_decode_transport = FALSE;
267 /* function definitions */
269 #define MAX_TSAP_LEN 32
270 static gchar *print_tsap(const u_char *tsap, int length)
273 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
276 gboolean allprintable;
279 if (cur == &str[0][0]) {
281 } else if (cur == &str[1][0]) {
289 if (length <= 0 || length > MAX_TSAP_LEN)
290 sprintf(cur, "<unsupported TSAP length>");
293 for (i=0;i<length;i++) {
294 /* If any byte is not printable ASCII, display the TSAP as a
295 series of hex byte values rather than as a string; this
296 means that, for example, accented letters will cause it
297 to be displayed as hex, but it also means that byte values
298 such as 0xff and 0xfe, which *are* printable ISO 8859/x
299 characters, won't be treated as printable - 0xfffffffe
300 is probably binary, not text. */
301 if (!(isascii(tsap[i]) && isprint(tsap[i]))) {
309 while (length != 0) {
311 sprintf(tmp, "%c", *tsap ++);
313 sprintf(tmp, "%02x", *tsap ++);
322 static gboolean osi_decode_tp_var_part(tvbuff_t *tvb, int offset,
323 int vp_length, int class_option,
328 guint16 s, s1,s2,s3,s4;
329 guint32 t1, t2, t3, t4;
330 guint32 pref_max_tpdu_size;
332 while (vp_length != 0) {
333 code = tvb_get_guint8(tvb, offset);
334 proto_tree_add_text(tree, tvb, offset, 1,
335 "Parameter code: 0x%02x (%s)",
337 val_to_str(code, tp_vpart_type_vals, "Unknown"));
343 length = tvb_get_guint8(tvb, offset);
344 proto_tree_add_text(tree, tvb, offset, 1,
345 "Parameter length: %u", length);
352 s = tvb_get_ntohs(tvb, offset);
353 proto_tree_add_text(tree, tvb, offset, length,
354 "Ack time (ms): %u", s);
360 proto_tree_add_text(tree, tvb, offset, 1,
361 "Residual error rate, target value: 10^%u",
362 tvb_get_guint8(tvb, offset));
367 proto_tree_add_text(tree, tvb, offset, 1,
368 "Residual error rate, minimum acceptable: 10^%u",
369 tvb_get_guint8(tvb, offset));
375 proto_tree_add_text(tree, tvb, offset, 1,
376 "Residual error rate, TSDU size of interest: %u",
377 1<<tvb_get_guint8(tvb, offset));
385 s = tvb_get_ntohs(tvb, offset);
386 proto_tree_add_text(tree, tvb, offset, length,
393 s1 = tvb_get_ntohs(tvb, offset);
394 proto_tree_add_text(tree, tvb, offset, 2,
395 "Transit delay, target value, calling-called: %u ms", s1);
400 s2 = tvb_get_ntohs(tvb, offset);
401 proto_tree_add_text(tree, tvb, offset, 2,
402 "Transit delay, maximum acceptable, calling-called: %u ms", s2);
407 s3 = tvb_get_ntohs(tvb, offset);
408 proto_tree_add_text(tree, tvb, offset, 2,
409 "Transit delay, target value, called-calling: %u ms", s3);
414 s4 = tvb_get_ntohs(tvb, offset);
415 proto_tree_add_text(tree, tvb, offset, 2,
416 "Transit delay, maximum acceptable, called-calling: %u ms", s4);
423 t1 = tvb_get_ntoh24(tvb, offset);
424 proto_tree_add_text(tree, tvb, offset, 3,
425 "Maximum throughput, target value, calling-called: %u o/s", t1);
430 t2 = tvb_get_ntoh24(tvb, offset);
431 proto_tree_add_text(tree, tvb, offset, 3,
432 "Maximum throughput, minimum acceptable, calling-called: %u o/s", t2);
437 t3 = tvb_get_ntoh24(tvb, offset);
438 proto_tree_add_text(tree, tvb, offset, 3,
439 "Maximum throughput, target value, called-calling: %u o/s", t3);
444 t4 = tvb_get_ntoh24(tvb, offset);
445 proto_tree_add_text(tree, tvb, offset, 3,
446 "Maximum throughput, minimum acceptable, called-calling: %u o/s", t4);
451 if (length != 0) { /* XXX - should be 0 or 12 */
452 t1 = tvb_get_ntoh24(tvb, offset);
453 proto_tree_add_text(tree, tvb, offset, 3,
454 "Average throughput, target value, calling-called: %u o/s", t1);
459 t2 = tvb_get_ntoh24(tvb, offset);
460 proto_tree_add_text(tree, tvb, offset, 3,
461 "Average throughput, minimum acceptable, calling-called: %u o/s", t2);
466 t3 = tvb_get_ntoh24(tvb, offset);
467 proto_tree_add_text(tree, tvb, offset, 3,
468 "Average throughput, target value, called-calling: %u o/s", t3);
473 t4 = tvb_get_ntoh24(tvb, offset);
474 proto_tree_add_text(tree, tvb, offset, 3,
475 "Average throughput, minimum acceptable, called-calling: %u o/s", t4);
483 proto_tree_add_text(tree, tvb, offset, 2,
484 "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
489 case VP_REASSIGNMENT:
490 proto_tree_add_text(tree, tvb, offset, 2,
491 "Reassignment time: %u secs", tvb_get_ntohs(tvb, offset));
497 proto_tree_add_text(tree, tvb, offset, 4,
498 "Lower window edge: 0x%08x", tvb_get_ntohl(tvb, offset));
503 proto_tree_add_text(tree, tvb, offset, 2,
504 "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
509 proto_tree_add_text(tree, tvb, offset, 2,
510 "Credit: 0x%04x", tvb_get_ntohs(tvb, offset));
518 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
519 proto_tree_add_text(tree, tvb, offset, length,
520 "TPDU size: %u", 2 << c1);
526 proto_tree_add_text(tree, tvb, offset, length,
528 print_tsap(tvb_get_ptr(tvb, offset, length), length));
534 proto_tree_add_text(tree, tvb, offset, length,
536 print_tsap(tvb_get_ptr(tvb, offset, length), length));
542 proto_tree_add_text(tree, tvb, offset, length,
543 "Checksum: 0x%04x", tvb_get_ntohs(tvb, offset));
549 c1 = tvb_get_guint8(tvb, offset);
550 proto_tree_add_text(tree, tvb, offset, length,
557 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
558 switch (class_option) {
562 proto_tree_add_text(tree, tvb, offset, 1,
563 "Use of network expedited data");
565 proto_tree_add_text(tree, tvb, offset, 1,
566 "Non use of network expedited data");
568 proto_tree_add_text(tree, tvb, offset, 1,
569 "Use of Receipt confirmation");
571 proto_tree_add_text(tree, tvb, offset, 1,
572 "Use of explicit AK variant");
577 proto_tree_add_text(tree, tvb, offset, 1,
578 "Non-use 16 bit checksum in class 4");
580 proto_tree_add_text(tree, tvb, offset, 1,
581 "Use 16 bit checksum ");
585 proto_tree_add_text(tree, tvb, offset, 1,
586 "Use of transport expedited data transfer\n");
588 proto_tree_add_text(tree, tvb, offset, 1,
589 "Non-use of transport expedited data transfer");
594 case VP_PREF_MAX_TPDU_SIZE:
598 pref_max_tpdu_size = tvb_get_guint8(tvb, offset);
602 pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
606 pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
610 pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
614 proto_tree_add_text(tree, tvb, offset, length,
615 "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)",
619 proto_tree_add_text(tree, tvb, offset, length,
620 "Preferred maximum TPDU size: %u", pref_max_tpdu_size*128);
625 case VP_INACTIVITY_TIMER:
626 proto_tree_add_text(tree, tvb, offset, length,
627 "Inactivity timer: %u ms", tvb_get_ntohl(tvb, offset));
632 case VP_PROTECTION: /* user-defined */
633 case VP_PROTO_CLASS: /* todo */
634 default: /* unknown, no decoding */
635 proto_tree_add_text(tree, tvb, offset, length,
636 "Parameter value: <not shown>");
646 static int osi_decode_DR(tvbuff_t *tvb, int offset,
647 packet_info *pinfo, proto_tree *tree)
649 proto_tree *cotp_tree;
658 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
659 reason = tvb_get_guint8(tvb, offset + P_REASON_IN_DR);
662 case (128+0): str = "Normal Disconnect"; break;
663 case (128+1): str = "Remote transport entity congestion"; break;
664 case (128+2): str = "Connection negotiation failed"; break;
665 case (128+3): str = "Duplicate source reference"; break;
666 case (128+4): str = "Mismatched references"; break;
667 case (128+5): str = "Protocol error"; break;
668 case (128+7): str = "Reference overflow"; break;
669 case (128+8): str = "Connection requestion refused"; break;
670 case (128+10):str = "Header or parameter length invalid"; break;
671 case (0): str = "Reason not specified"; break;
672 case (1): str = "Congestion at TSAP"; break;
673 case (2): str = "Session entity not attached to TSAP"; break;
674 case (3): str = "Address unknown"; break;
680 if (check_col(pinfo->fd, COL_INFO))
681 col_append_fstr(pinfo->fd, COL_INFO,
682 "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
686 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
687 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
688 proto_tree_add_text(cotp_tree, tvb, offset, 1,
689 "Length indicator: %u", li);
690 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
691 "TPDU code: 0x%x (DR)", tpdu);
692 proto_tree_add_text(cotp_tree, tvb, offset + 2, 2,
693 "Destination reference: 0x%04x", dst_ref);
694 proto_tree_add_text(cotp_tree, tvb, offset + 4, 2,
695 "Source reference: 0x%04x", src_ref);
696 proto_tree_add_text(cotp_tree, tvb, offset + 6, 1,
703 dissect_data(tvb, offset, pinfo, tree);
704 offset += tvb_length_remaining(tvb, offset);
705 /* we dissected all of the containing PDU */
709 } /* osi_decode_DR */
711 static int osi_decode_DT(tvbuff_t *tvb, int offset,
712 packet_info *pinfo, proto_tree *tree,
713 gboolean uses_inactive_subset,
714 gboolean *subdissector_found)
716 proto_tree *cotp_tree = NULL;
718 gboolean is_extended;
719 gboolean is_class_234;
724 /* VP_CHECKSUM is the only parameter allowed in the variable part.
725 (This means we may misdissect this if the packet is bad and
726 contains other parameters.) */
729 case LI_NORMAL_DT_WITH_CHECKSUM :
730 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
734 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
735 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
736 if ( tpdu_nr & 0x80 )
737 tpdu_nr = tpdu_nr & 0x7F;
744 case LI_EXTENDED_DT_WITH_CHECKSUM :
745 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
749 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
750 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
751 if ( tpdu_nr & 0x80000000 )
752 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
759 case LI_NORMAL_DT_CLASS_01 :
760 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
761 if ( tpdu_nr & 0x80 )
762 tpdu_nr = tpdu_nr & 0x7F;
766 is_class_234 = FALSE;
769 default : /* bad TPDU */
775 if (check_col(pinfo->fd, COL_INFO))
776 col_append_fstr(pinfo->fd, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x %s",
779 (fragment)? "(fragment)" : "");
782 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
783 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
784 proto_tree_add_text(cotp_tree, tvb, offset, 1,
785 "Length indicator: %u", li);
790 proto_tree_add_text(cotp_tree, tvb, offset, 1,
791 "TPDU code: 0x%x (DT)", tpdu);
799 proto_tree_add_text(cotp_tree, tvb, offset, 2,
800 "Destination reference: 0x%04x", dst_ref);
808 proto_tree_add_text(cotp_tree, tvb, offset, 4,
809 "TPDU number: 0x%08x (%s)",
811 (fragment)? "fragment":"complete");
817 proto_tree_add_text(cotp_tree, tvb, offset, 1,
818 "TPDU number: 0x%02x (%s)",
820 (fragment)? "fragment":"complete");
827 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
830 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
831 if (uses_inactive_subset){
832 if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
834 *subdissector_found = TRUE;
836 /* Fill in other Dissectors using inactive subset here */
837 dissect_data(next_tvb, 0, pinfo, tree);
840 dissect_data(next_tvb, 0, pinfo, tree);
841 offset += tvb_length_remaining(tvb, offset);
842 /* we dissected all of the containing PDU */
846 } /* osi_decode_DT */
848 static int osi_decode_ED(tvbuff_t *tvb, int offset,
849 packet_info *pinfo, proto_tree *tree)
851 proto_tree *cotp_tree = NULL;
853 gboolean is_extended;
857 /* ED TPDUs are never fragmented */
859 /* VP_CHECKSUM is the only parameter allowed in the variable part.
860 (This means we may misdissect this if the packet is bad and
861 contains other parameters.) */
864 case LI_NORMAL_DT_WITH_CHECKSUM :
865 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
869 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
870 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
871 if ( tpdu_nr & 0x80 )
872 tpdu_nr = tpdu_nr & 0x7F;
878 case LI_EXTENDED_DT_WITH_CHECKSUM :
879 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
883 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
884 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
885 if ( tpdu_nr & 0x80000000 )
886 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
892 default : /* bad TPDU */
898 if (check_col(pinfo->fd, COL_INFO))
899 col_append_fstr(pinfo->fd, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
903 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
904 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
905 proto_tree_add_text(cotp_tree, tvb, offset, 1,
906 "Length indicator: %u", li);
911 proto_tree_add_text(cotp_tree, tvb, offset, 1,
912 "TPDU code: 0x%x (ED)", tpdu);
918 proto_tree_add_text(cotp_tree, tvb, offset, 2,
919 "Destination reference: 0x%04x", dst_ref);
926 proto_tree_add_text(cotp_tree, tvb, offset, 4,
927 "TPDU number: 0x%02x", tpdu_nr);
933 proto_tree_add_text(cotp_tree, tvb, offset, 1,
934 "TPDU number: 0x%02x", tpdu_nr);
941 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
944 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
945 dissect_data(next_tvb, 0, pinfo, tree);
947 offset += tvb_length_remaining(tvb, offset);
948 /* we dissected all of the containing PDU */
952 } /* osi_decode_ED */
954 static int osi_decode_RJ(tvbuff_t *tvb, int offset,
955 packet_info *pinfo, proto_tree *tree)
957 proto_tree *cotp_tree;
964 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
966 case LI_EXTENDED_RJ :
967 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
968 credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
976 if (check_col(pinfo->fd, COL_INFO))
977 col_append_fstr(pinfo->fd, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
981 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
982 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
983 proto_tree_add_text(cotp_tree, tvb, offset, 1,
984 "Length indicator: %u", li);
985 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
986 "TPDU code: 0x%x (RJ)", tpdu);
987 if (li == LI_NORMAL_RJ)
988 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
990 proto_tree_add_text(cotp_tree, tvb, offset + 2, 2,
991 "Destination reference: 0x%04x", dst_ref);
992 if (li == LI_NORMAL_RJ)
993 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
994 "Your TPDU number: 0x%02x", tpdu_nr);
996 proto_tree_add_text(cotp_tree, tvb, offset + 4, 4,
997 "Your TPDU number: 0x%02x", tpdu_nr);
998 proto_tree_add_text(cotp_tree, tvb, offset + 8, 2,
999 "Credit: 0x%02x", credit);
1007 } /* osi_decode_RJ */
1009 static int osi_decode_CC(tvbuff_t *tvb, int offset,
1010 packet_info *pinfo, proto_tree *tree)
1013 /* CC & CR decoding in the same function */
1015 proto_tree *cotp_tree = NULL;
1018 u_char class_option;
1020 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1021 class_option = (tvb_get_guint8(tvb, offset + P_CLASS_OPTION) >> 4 ) & 0x0F;
1022 if (class_option > 4)
1025 if (check_col(pinfo->fd, COL_INFO))
1026 col_append_fstr(pinfo->fd, COL_INFO,
1027 "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1028 (tpdu == CR_TPDU) ? "CR" : "CC",
1033 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1034 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1035 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1036 "Length indicator: %u", li);
1041 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1042 "TPDU code: 0x%x (%s)", tpdu,
1043 (tpdu == CR_TPDU) ? "CR" : "CC");
1049 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1050 "Destination reference: 0x%04x", dst_ref);
1056 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1057 "Source reference: 0x%04x", src_ref);
1063 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1064 "Class option: 0x%02x", class_option);
1070 osi_decode_tp_var_part(tvb, offset, li, class_option, cotp_tree);
1074 dissect_data(tvb, offset, pinfo, tree);
1075 offset += tvb_length_remaining(tvb, offset);
1076 /* we dissected all of the containing PDU */
1080 } /* osi_decode_CC */
1082 static int osi_decode_DC(tvbuff_t *tvb, int offset,
1083 packet_info *pinfo, proto_tree *tree)
1085 proto_tree *cotp_tree = NULL;
1092 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1094 if (check_col(pinfo->fd, COL_INFO))
1095 col_append_fstr(pinfo->fd, COL_INFO,
1096 "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1101 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1102 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1103 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1104 "Length indicator: %u", li);
1109 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1110 "TPDU code: 0x%x (DC)", tpdu);
1116 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1117 "Destination reference: 0x%04x", dst_ref);
1123 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1124 "Source reference: 0x%04x", src_ref);
1130 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
1135 } /* osi_decode_DC */
1137 static int osi_decode_AK(tvbuff_t *tvb, int offset,
1138 packet_info *pinfo, proto_tree *tree)
1140 proto_tree *cotp_tree = NULL;
1148 if (is_LI_NORMAL_AK(li)) {
1150 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1152 if (check_col(pinfo->fd, COL_INFO))
1153 col_append_fstr(pinfo->fd, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1157 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1158 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1159 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1160 "Length indicator: %u", li);
1165 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1166 "TPDU code: 0x%x (AK)", tpdu);
1167 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1174 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1175 "Destination reference: 0x%04x", dst_ref);
1181 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1182 "Your TPDU number: 0x%02x", tpdu_nr);
1188 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
1191 } else { /* extended format */
1193 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1194 cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1196 if (check_col(pinfo->fd, COL_INFO))
1197 col_append_fstr(pinfo->fd, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1201 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1202 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1203 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1204 "Length indicator: %u", li);
1209 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1210 "TPDU code: 0x%x (AK)", tpdu);
1216 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1217 "Destination reference: 0x%04x", dst_ref);
1223 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1224 "Your TPDU number: 0x%08x", tpdu_nr);
1230 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1231 "Credit: 0x%04x", cdt_in_ak);
1237 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
1240 } /* is_LI_NORMAL_AK */
1244 } /* osi_decode_AK */
1246 static int osi_decode_EA(tvbuff_t *tvb, int offset,
1247 packet_info *pinfo, proto_tree *tree)
1249 proto_tree *cotp_tree = NULL;
1251 gboolean is_extended;
1257 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1258 (This means we may misdissect this if the packet is bad and
1259 contains other parameters.) */
1262 case LI_NORMAL_EA_WITH_CHECKSUM :
1263 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
1264 tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1268 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1269 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1270 is_extended = FALSE;
1273 case LI_EXTENDED_EA_WITH_CHECKSUM :
1274 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
1275 tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1279 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1280 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1284 default : /* bad TPDU */
1290 if (check_col(pinfo->fd, COL_INFO))
1291 col_append_fstr(pinfo->fd, COL_INFO,
1292 "EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1295 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1296 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1297 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1298 "Length indicator: %u", li);
1303 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1304 "TPDU code: 0x%x (EA)", tpdu);
1310 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1311 "Destination reference: 0x%04x", dst_ref);
1318 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1319 "Your TPDU number: 0x%08x", tpdu_nr);
1325 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1326 "Your TPDU number: 0x%02x", tpdu_nr);
1333 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
1338 } /* osi_decode_EA */
1340 static int osi_decode_ER(tvbuff_t *tvb, int offset,
1341 packet_info *pinfo, proto_tree *tree)
1343 proto_tree *cotp_tree;
1350 switch(tvb_get_guint8(tvb, offset + P_REJECT_ER)) {
1352 str = "Reason not specified";
1355 str = "Invalid parameter code";
1358 str = "Invalid TPDU type";
1361 str = "Invalid parameter value";
1369 if (check_col(pinfo->fd, COL_INFO))
1370 col_append_fstr(pinfo->fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1373 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1374 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1375 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1376 "Length indicator: %u", li);
1377 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
1378 "TPDU code: 0x%x (ER)", tpdu);
1379 proto_tree_add_text(cotp_tree, tvb, offset + 2, 2,
1380 "Destination reference: 0x%04x", dst_ref);
1381 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
1382 "Reject cause: %s", str);
1389 } /* osi_decode_ER */
1391 static int osi_decode_UD(tvbuff_t *tvb, int offset,
1392 packet_info *pinfo, proto_tree *tree,
1393 gboolean *subdissector_found)
1396 proto_tree *cltp_tree = NULL;
1399 if (check_col(pinfo->fd, COL_INFO))
1400 col_append_str(pinfo->fd, COL_INFO, "UD TPDU");
1403 ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, FALSE);
1404 cltp_tree = proto_item_add_subtree(ti, ett_cltp);
1405 proto_tree_add_text(cltp_tree, tvb, offset, 1,
1406 "Length indicator: %u", li);
1411 proto_tree_add_text(cltp_tree, tvb, offset, 1,
1412 "TPDU code: 0x%x (UD)", tpdu);
1418 osi_decode_tp_var_part(tvb, offset, li, 0, cltp_tree);
1421 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1422 dissect_data(next_tvb, 0, pinfo, tree);
1423 offset += tvb_length_remaining(tvb, offset);
1424 /* we dissected all of the containing PDU */
1428 } /* osi_decode_UD */
1430 /* Returns TRUE if we found at least one valid COTP or CLTP PDU, FALSE
1433 There doesn't seem to be any way in which the OSI network layer protocol
1434 distinguishes between COTP and CLTP, but the first two octets of both
1435 protocols' headers mean the same thing - length and PDU type - and the
1436 only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
1437 both of them here. */
1438 static gboolean dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
1439 proto_tree *tree, gboolean uses_inactive_subset)
1442 gboolean first_tpdu = TRUE;
1444 gboolean found_ositp = FALSE;
1445 gboolean is_cltp = FALSE;
1446 gboolean subdissector_found = FALSE;
1448 if (!proto_is_protocol_enabled(proto_cotp))
1449 return FALSE; /* COTP has been disabled */
1450 /* XXX - what about CLTP? */
1452 pinfo->current_proto = "COTP";
1454 /* Initialize the COL_INFO field; each of the TPDUs will have its
1455 information appended. */
1456 if (check_col(pinfo->fd, COL_INFO))
1457 col_add_str(pinfo->fd, COL_INFO, "");
1459 while (tvb_offset_exists(tvb, offset)) {
1461 if (check_col(pinfo->fd, COL_INFO))
1462 col_append_str(pinfo->fd, COL_INFO, ", ");
1464 if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
1465 if (check_col(pinfo->fd, COL_INFO))
1466 col_append_str(pinfo->fd, COL_INFO, "Length indicator is zero");
1468 dissect_data(tvb, offset, pinfo, tree);
1472 tpdu = (tvb_get_guint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
1473 if (tpdu == UD_TPDU)
1474 pinfo->current_proto = "CLTP"; /* connectionless transport */
1475 cdt = tvb_get_guint8(tvb, offset + P_CDT) & 0x0F;
1476 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1481 new_offset = osi_decode_CC(tvb, offset, pinfo, tree);
1484 new_offset = osi_decode_DR(tvb, offset, pinfo, tree);
1487 new_offset = osi_decode_DT(tvb, offset, pinfo, tree,
1488 uses_inactive_subset, &subdissector_found);
1491 new_offset = osi_decode_ED(tvb, offset, pinfo, tree);
1494 new_offset = osi_decode_RJ(tvb, offset, pinfo, tree);
1497 new_offset = osi_decode_DC(tvb, offset, pinfo, tree);
1500 new_offset = osi_decode_AK(tvb, offset, pinfo, tree);
1503 new_offset = osi_decode_EA(tvb, offset, pinfo, tree);
1506 new_offset = osi_decode_ER(tvb, offset, pinfo, tree);
1509 new_offset = osi_decode_UD(tvb, offset, pinfo, tree,
1510 &subdissector_found);
1514 if (first_tpdu && check_col(pinfo->fd, COL_INFO))
1515 col_append_fstr(pinfo->fd, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
1516 new_offset = -1; /* bad PDU type */
1520 if (new_offset == -1) { /* incorrect TPDU */
1522 dissect_data(tvb, offset, pinfo, tree);
1527 /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
1528 is either COTP or CLTP. */
1529 if (!subdissector_found && check_col(pinfo->fd, COL_PROTOCOL))
1530 col_set_str(pinfo->fd, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
1534 offset = new_offset;
1538 } /* dissect_ositp_internal */
1540 static void dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1542 if (!dissect_ositp_internal(tvb, pinfo, tree, FALSE))
1543 dissect_data(tvb, 0, pinfo, tree);
1548 * CLNP part / main entry point
1551 static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1553 proto_tree *clnp_tree = NULL;
1555 guint8 cnf_proto_id;
1560 char flag_string[6+1];
1561 char *pdu_type_string;
1562 proto_tree *type_tree;
1563 guint16 segment_length;
1564 guint16 segment_offset = 0;
1567 u_char src_len, dst_len, nsel, opt_len = 0;
1568 guint8 *dst_addr, *src_addr;
1571 proto_tree *discpdu_tree;
1574 CHECK_DISPLAY_AS_DATA(proto_clnp, tvb, pinfo, tree);
1576 pinfo->current_proto = "CLNP";
1578 if (check_col(pinfo->fd, COL_PROTOCOL))
1579 col_set_str(pinfo->fd, COL_PROTOCOL, "CLNP");
1581 cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
1582 if (cnf_proto_id == NLPID_NULL) {
1583 if (check_col(pinfo->fd, COL_INFO))
1584 col_set_str(pinfo->fd, COL_INFO, "Inactive subset");
1586 ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, FALSE);
1587 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1588 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1592 next_tvb = tvb_new_subset(tvb, 1, -1, -1);
1593 dissect_ositp_internal(next_tvb, pinfo, tree, TRUE);
1597 /* return if version not known */
1598 cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
1599 if (cnf_vers != ISO8473_V1) {
1600 dissect_data(tvb, 0, pinfo, tree);
1604 /* fixed part decoding */
1605 cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
1606 opt_len = cnf_hdr_len;
1609 ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, FALSE);
1610 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1611 proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1613 proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
1615 proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
1617 cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
1618 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
1620 "Holding Time : %u (%u.%u secs)",
1621 cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
1624 cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
1625 pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
1626 "Unknown (0x%02x)");
1627 flag_string[0] = '\0';
1628 if (cnf_type & CNF_SEG_OK)
1629 strcat(flag_string, "S ");
1630 if (cnf_type & CNF_MORE_SEGS)
1631 strcat(flag_string, "M ");
1632 if (cnf_type & CNF_ERR_OK)
1633 strcat(flag_string, "E ");
1635 ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
1637 "PDU Type : 0x%02x (%s%s)",
1641 type_tree = proto_item_add_subtree(ti, ett_clnp_type);
1642 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1643 decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8,
1644 "Segmentation permitted",
1645 "Segmentation not permitted"));
1646 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1647 decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8,
1650 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1651 decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8,
1652 "Report error if PDU discarded",
1653 "Don't report error if PDU discarded"));
1654 proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
1655 decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8,
1656 npdu_type_vals, "%s"));
1659 /* If we don't have the full header - i.e., not enough to see the
1660 segmentation part and determine whether this datagram is segmented
1661 or not - set the Info column now; we'll get an exception before
1662 we set it otherwise. */
1664 if (!tvb_bytes_exist(tvb, 0, cnf_hdr_len)) {
1665 if (check_col(pinfo->fd, COL_INFO))
1666 col_add_fstr(pinfo->fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1669 segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
1671 proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
1673 cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
1674 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2,
1676 "Checksum : 0x%04x",
1678 opt_len -= 9; /* Fixed part of Hesder */
1683 offset = P_CLNP_ADDRESS_PART;
1684 dst_len = tvb_get_guint8(tvb, offset);
1685 dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
1686 nsel = tvb_get_guint8(tvb, offset + dst_len);
1687 src_len = tvb_get_guint8(tvb, offset + dst_len + 1);
1688 src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);
1691 proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
1693 proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
1696 print_nsap_net(dst_addr, dst_len));
1697 proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
1698 offset + 1 + dst_len, 1, src_len);
1699 proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
1700 offset + dst_len + 2, src_len,
1703 print_nsap_net(src_addr, src_len));
1705 opt_len -= dst_len + src_len +2;
1708 if (check_col(pinfo->fd, COL_RES_NET_SRC))
1709 col_add_fstr(pinfo->fd, COL_RES_NET_SRC, "%s", print_nsap_net(src_addr, src_len));
1710 if (check_col(pinfo->fd, COL_RES_NET_DST))
1711 col_add_fstr(pinfo->fd, COL_RES_NET_DST, "%s", print_nsap_net(dst_addr, dst_len));
1713 /* Segmentation Part */
1715 offset += dst_len + src_len + 2;
1717 if (cnf_type & CNF_SEG_OK) {
1718 struct clnp_segment seg; /* XXX - not used */
1719 tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg)); /* XXX - not used */
1721 segment_offset = tvb_get_ntohs(tvb, offset + 2);
1723 proto_tree_add_text(clnp_tree, tvb, offset, 2,
1724 "Data unit identifier: %06u",
1725 tvb_get_ntohs(tvb, offset));
1726 proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
1727 "Segment offset : %6u",
1729 proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
1730 "Total length : %6u",
1731 tvb_get_ntohs(tvb, offset + 4));
1739 /* To do : decode options */
1741 proto_tree_add_text(clnp_tree, tvb, offset,
1742 cnf_hdr_len - offset,
1743 "Options/Data: <not shown>");
1745 /* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/
1747 dissect_osi_options( 0xff,
1749 tvb, offset, pinfo, clnp_tree );
1752 /* Length of CLNP datagram plus headers above it. */
1753 len = segment_length;
1755 /* Set the payload and captured-payload lengths to the minima of (the
1756 datagram length plus the length of the headers above it) and the
1758 if (pinfo->len > len)
1760 if (pinfo->captured_len > len)
1761 pinfo->captured_len = len;
1763 offset = cnf_hdr_len;
1765 /* For now, dissect the payload of segments other than the initial
1766 segment as data, rather than handing them off to the transport
1767 protocol, just as we do with fragments other than the first
1768 fragment in a fragmented IP datagram; in the future, we will
1769 probably reassemble fragments for IP, and may reassemble segments
1771 if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
1772 if (check_col(pinfo->fd, COL_INFO))
1773 col_add_fstr(pinfo->fd, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
1774 pdu_type_string, flag_string, segment_offset);
1775 dissect_data(tvb, offset, pinfo, tree);
1779 if (tvb_offset_exists(tvb, offset)) {
1780 switch (cnf_type & CNF_TYPE) {
1784 /* Continue with COTP if any data.
1785 XXX - if this isn't the first Derived PDU of a segmented Initial
1788 if (nsel == (char)tp_nsap_selector || always_decode_transport) {
1789 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1790 if (dissect_ositp_internal(next_tvb, pinfo, tree, FALSE))
1791 return; /* yes, it appears to be COTP or CLTP */
1796 /* The payload is the header and "none, some, or all of the data
1797 part of the discarded PDU", i.e. it's like an ICMP error;
1798 dissect it as a CLNP PDU. */
1800 next_length = tvb_length_remaining(tvb, offset);
1801 if (next_length != 0) {
1802 /* We have payload; dissect it.
1803 Make the columns non-writable, so the packet isn't shown
1804 in the summary based on what the discarded PDU's contents
1806 col_set_writable(pinfo->fd, FALSE);
1807 ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
1809 discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);
1810 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1811 dissect_clnp(next_tvb, pinfo, discpdu_tree);
1812 offset += next_length;
1819 /* XXX - dissect this */
1823 if (check_col(pinfo->fd, COL_INFO))
1824 col_add_fstr(pinfo->fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1825 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1826 dissect_data(next_tvb, 0, pinfo, tree);
1828 } /* dissect_clnp */
1831 void proto_register_clnp(void)
1833 static hf_register_info hf[] = {
1835 { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
1836 VALS(nlpid_vals), 0x0, "" }},
1839 { "HDR Length ", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1842 { "Version ", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1845 { "Holding Time ", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1848 { "PDU Type ", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1850 { &hf_clnp_pdu_length,
1851 { "PDU length ", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
1853 { &hf_clnp_checksum,
1854 { "Checksum ", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
1856 { &hf_clnp_dest_length,
1857 { "DAL ", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1860 { " DA ", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }},
1862 { &hf_clnp_src_length,
1863 { "SAL ", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1866 { " SA ", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }},
1868 static gint *ett[] = {
1874 module_t *clnp_module;
1876 proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "clnp");
1877 proto_register_field_array(proto_clnp, hf, array_length(hf));
1878 proto_register_subtree_array(ett, array_length(ett));
1880 clnp_module = prefs_register_module("clnp", "CLNP", NULL);
1881 prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
1882 "NSAP selector for Transport Protocol (last byte in hexa)",
1883 "NSAP selector for Transport Protocol (last byte in hexa)",
1884 16, &tp_nsap_selector);
1885 prefs_register_bool_preference(clnp_module, "always_decode_transport",
1886 "Always try to decode NSDU as transport PDUs",
1887 "Always try to decode NSDU as transport PDUs",
1888 &always_decode_transport);
1892 void proto_register_cotp(void)
1894 /* static hf_register_info hf[] = {
1896 { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
1898 static gint *ett[] = {
1902 proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "cotp");
1903 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
1904 proto_register_subtree_array(ett, array_length(ett));
1906 /* subdissector code */
1907 register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
1909 register_dissector("ositp", dissect_ositp);
1912 void proto_register_cltp(void)
1914 /* static hf_register_info hf[] = {
1916 { "Name", "cltp.abbreviation", TYPE, VALS_POINTER }},
1918 static gint *ett[] = {
1922 proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "cltp");
1923 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
1924 proto_register_subtree_array(ett, array_length(ett));
1928 proto_reg_handoff_clnp(void)
1930 dissector_add("osinl", NLPID_ISO8473_CLNP, dissect_clnp);
1931 dissector_add("osinl", NLPID_NULL, dissect_clnp); /* Inactive subset */