2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-clnp.c,v 1.14 2000/11/18 10:38:24 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-clnp.h"
46 #include "packet-isis.h"
47 #include "packet-esis.h"
50 /* protocols and fields */
52 static int proto_clnp = -1;
53 static gint ett_clnp = -1;
54 static int proto_cotp = -1;
55 static gint ett_cotp = -1;
56 static int proto_cltp = -1;
57 static gint ett_cltp = -1;
59 static int hf_clnp_id = -1;
60 static int hf_clnp_length = -1;
61 static int hf_clnp_version = -1;
62 static int hf_clnp_ttl = -1;
63 static int hf_clnp_type = -1;
64 static int hf_clnp_pdu_length = -1;
65 static int hf_clnp_checksum = -1;
66 static int hf_clnp_dest_length = -1;
67 static int hf_clnp_dest = -1;
68 static int hf_clnp_src_length = -1;
69 static int hf_clnp_src = -1;
72 * ISO 8473 OSI CLNP definition (see RFC994)
74 * _________________________________
76 * |_________________________________|
78 * |_________________________________|
79 * | Segmentation Part (optional) |
80 * |_________________________________|
81 * | Options Part (optional) |
82 * |_________________________________|
84 * |_________________________________|
87 #define ISO8473_V1 0x01 /* CLNP version 1 */
92 #define CNF_ERR_OK 0x20
93 #define CNF_MORE_SEGS 0x40
94 #define CNF_SEG_OK 0x80
100 #define ERP_NPDU 0x1F
102 static const value_string npdu_type_vals[] = {
113 #define P_CLNP_PROTO_ID 0
114 #define P_CLNP_HDR_LEN 1
115 #define P_CLNP_VERS 2
117 #define P_CLNP_TYPE 4
118 #define P_CLNP_SEGLEN 5
119 #define P_CLNP_CKSUM 7
120 #define P_CLNP_ADDRESS_PART 9
122 /* Segmentation part */
124 struct clnp_segment {
125 u_short cng_id; /* data unit identifier */
126 u_short cng_off; /* segment offset */
127 u_short cng_tot_len; /* total length */
132 #define NSEL_NET 0x00
137 * ISO8073 OSI COTP definition (see RFC905)
140 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
142 /* TPDU definition */
144 #define ED_TPDU 0x1 /* COTP */
145 #define EA_TPDU 0x2 /* COTP */
146 #define UD_TPDU 0x4 /* CLTP */
147 #define RJ_TPDU 0x5 /* COTP */
148 #define AK_TPDU 0x6 /* COTP */
149 #define ER_TPDU 0x7 /* COTP */
150 #define DR_TPDU 0x8 /* COTP */
151 #define DC_TPDU 0xC /* COTP */
152 #define CC_TPDU 0xD /* COTP */
153 #define CR_TPDU 0xE /* COTP */
154 #define DT_TPDU 0xF /* COTP */
163 #define P_TPDU_NR_0_1 2
164 #define P_TPDU_NR_234 4
165 #define P_VAR_PART_NDT 5
166 #define P_VAR_PART_EDT 8
167 #define P_VAR_PART_DC 6
168 #define P_CDT_IN_AK 8
169 #define P_CDT_IN_RJ 8
170 #define P_REJECT_ER 4
171 #define P_REASON_IN_DR 6
172 #define P_CLASS_OPTION 6
174 /* TPDU length indicator */
176 #define LI_NORMAL_DT_CLASS_01 2
177 #define LI_NORMAL_DT_WITH_CHECKSUM 8
178 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
179 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
180 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
181 #define LI_NORMAL_EA_WITH_CHECKSUM 8
182 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
183 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
184 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
185 #define LI_NORMAL_RJ 4
186 #define LI_EXTENDED_RJ 9
192 /* XXX - can we always decide this based on whether the length
193 indicator is odd or not? What if the variable part has an odd
195 #define is_LI_NORMAL_AK(p) ( ( p & 0x01 ) == 0 )
199 #define VP_ACK_TIME 0x85
200 #define VP_RES_ERROR 0x86
201 #define VP_PRIORITY 0x87
202 #define VP_TRANSIT_DEL 0x88
203 #define VP_THROUGHPUT 0x89
204 #define VP_SEQ_NR 0x8A /* in AK */
205 #define VP_REASSIGNMENT 0x8B
206 #define VP_FLOW_CNTL 0x8C /* in AK */
207 #define VP_TPDU_SIZE 0xC0
208 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
209 #define VP_DST_TSAP 0xC2
210 #define VP_CHECKSUM 0xC3
211 #define VP_VERSION_NR 0xC4
212 #define VP_PROTECTION 0xC5
213 #define VP_OPT_SEL 0xC6
214 #define VP_PROTO_CLASS 0xC7
215 #define VP_PREF_MAX_TPDU_SIZE 0xF0
216 #define VP_INACTIVITY_TIMER 0xF2
218 static const value_string tp_vpart_type_vals[] = {
219 { VP_ACK_TIME, "ack time" },
220 { VP_RES_ERROR, "res error" },
221 { VP_PRIORITY, "priority" },
222 { VP_TRANSIT_DEL, "transit delay" },
223 { VP_THROUGHPUT, "throughput" },
224 { VP_SEQ_NR, "seq number" },
225 { VP_REASSIGNMENT, "reassignment" },
226 { VP_FLOW_CNTL, "flow control" },
227 { VP_TPDU_SIZE, "tpdu-size" },
228 { VP_SRC_TSAP, "src-tsap" },
229 { VP_DST_TSAP, "dst-tsap" },
230 { VP_CHECKSUM, "checksum" },
231 { VP_VERSION_NR, "version" },
232 { VP_PROTECTION, "protection" },
233 { VP_OPT_SEL, "options" },
234 { VP_PROTO_CLASS, "proto class" },
235 { VP_PREF_MAX_TPDU_SIZE, "preferred max TPDU size" },
241 #define EXTRACT_SHORT(p) pntohs(p)
242 #define EXTRACT_LONG(p) pntohl(p)
244 /* global variables */
246 static u_char li, tpdu, cdt; /* common fields */
247 static u_short dst_ref;
249 /* List of dissectors to call for COTP packets put atop the Inactive
251 static heur_dissector_list_t cotp_is_heur_subdissector_list;
254 static guint tp_nsap_selector = NSEL_TP;
255 static gboolean always_decode_transport = FALSE;
257 /* function definitions */
259 #define MAX_TSAP_LEN 32
260 static gchar *print_tsap(const u_char *tsap, int length)
263 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
266 gboolean allprintable;
269 if (cur == &str[0][0]) {
271 } else if (cur == &str[1][0]) {
279 if (length <= 0 || length > MAX_TSAP_LEN)
280 sprintf(cur, "<unsupported TSAP length>");
283 for (i=0;i<length;i++) {
284 /* If any byte is not printable ASCII, display the TSAP as a
285 series of hex byte values rather than as a string; this
286 means that, for example, accented letters will cause it
287 to be displayed as hex, but it also means that byte values
288 such as 0xff and 0xfe, which *are* printable ISO 8859/x
289 characters, won't be treated as printable - 0xfffffffe
290 is probably binary, not text. */
291 if (!(isascii(tsap[i]) && isprint(tsap[i]))) {
299 while (length != 0) {
301 sprintf(tmp, "%c", *tsap ++);
303 sprintf(tmp, "%02x", *tsap ++);
312 static gboolean osi_decode_tp_var_part(tvbuff_t *tvb, int offset,
313 int vp_length, int class_option,
318 guint16 s, s1,s2,s3,s4;
319 guint32 t1, t2, t3, t4;
320 guint32 pref_max_tpdu_size;
322 while (vp_length != 0) {
323 code = tvb_get_guint8(tvb, offset);
324 proto_tree_add_text(tree, tvb, offset, 1,
325 "Parameter code: 0x%02x (%s)",
327 val_to_str(code, tp_vpart_type_vals, "Unknown"));
333 length = tvb_get_guint8(tvb, offset);
334 proto_tree_add_text(tree, tvb, offset, 1,
335 "Parameter length: %u", length);
342 s = tvb_get_ntohs(tvb, offset);
343 proto_tree_add_text(tree, tvb, offset, length,
344 "Ack time (ms): %u", s);
350 proto_tree_add_text(tree, tvb, offset, 1,
351 "Residual error rate, target value: 10^%u",
352 tvb_get_guint8(tvb, offset));
357 proto_tree_add_text(tree, tvb, offset, 1,
358 "Residual error rate, minimum acceptable: 10^%u",
359 tvb_get_guint8(tvb, offset));
365 proto_tree_add_text(tree, tvb, offset, 1,
366 "Residual error rate, TSDU size of interest: %u",
367 1<<tvb_get_guint8(tvb, offset));
375 s = tvb_get_ntohs(tvb, offset);
376 proto_tree_add_text(tree, tvb, offset, length,
383 s1 = tvb_get_ntohs(tvb, offset);
384 proto_tree_add_text(tree, tvb, offset, 2,
385 "Transit delay, target value, calling-called: %u ms", s1);
390 s2 = tvb_get_ntohs(tvb, offset);
391 proto_tree_add_text(tree, tvb, offset, 2,
392 "Transit delay, maximum acceptable, calling-called: %u ms", s2);
397 s3 = tvb_get_ntohs(tvb, offset);
398 proto_tree_add_text(tree, tvb, offset, 2,
399 "Transit delay, target value, called-calling: %u ms", s3);
404 s4 = tvb_get_ntohs(tvb, offset);
405 proto_tree_add_text(tree, tvb, offset, 2,
406 "Transit delay, maximum acceptable, called-calling: %u ms", s4);
413 t1 = tvb_get_ntoh24(tvb, offset);
414 proto_tree_add_text(tree, tvb, offset, 3,
415 "Maximum throughput, target value, calling-called: %u o/s", t1);
420 t2 = tvb_get_ntoh24(tvb, offset);
421 proto_tree_add_text(tree, tvb, offset, 3,
422 "Maximum throughput, minimum acceptable, calling-called: %u o/s", t2);
427 t3 = tvb_get_ntoh24(tvb, offset);
428 proto_tree_add_text(tree, tvb, offset, 3,
429 "Maximum throughput, target value, called-calling: %u o/s", t3);
434 t4 = tvb_get_ntoh24(tvb, offset);
435 proto_tree_add_text(tree, tvb, offset, 3,
436 "Maximum throughput, minimum acceptable, called-calling: %u o/s", t4);
441 if (length != 0) { /* XXX - should be 0 or 12 */
442 t1 = tvb_get_ntoh24(tvb, offset);
443 proto_tree_add_text(tree, tvb, offset, 3,
444 "Average throughput, target value, calling-called: %u o/s", t1);
449 t2 = tvb_get_ntoh24(tvb, offset);
450 proto_tree_add_text(tree, tvb, offset, 3,
451 "Average throughput, minimum acceptable, calling-called: %u o/s", t2);
456 t3 = tvb_get_ntoh24(tvb, offset);
457 proto_tree_add_text(tree, tvb, offset, 3,
458 "Average throughput, target value, called-calling: %u o/s", t3);
463 t4 = tvb_get_ntoh24(tvb, offset);
464 proto_tree_add_text(tree, tvb, offset, 3,
465 "Average throughput, minimum acceptable, called-calling: %u o/s", t4);
473 proto_tree_add_text(tree, tvb, offset, 2,
474 "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
479 case VP_REASSIGNMENT:
480 proto_tree_add_text(tree, tvb, offset, 2,
481 "Reassignment time: %u secs", tvb_get_ntohs(tvb, offset));
487 proto_tree_add_text(tree, tvb, offset, 4,
488 "Lower window edge: 0x%08x", tvb_get_ntohl(tvb, offset));
493 proto_tree_add_text(tree, tvb, offset, 2,
494 "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
499 proto_tree_add_text(tree, tvb, offset, 2,
500 "Credit: 0x%04x", tvb_get_ntohs(tvb, offset));
508 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
509 proto_tree_add_text(tree, tvb, offset, length,
510 "TPDU size: %u", 2 << c1);
516 proto_tree_add_text(tree, tvb, offset, length,
518 print_tsap(tvb_get_ptr(tvb, offset, length), length));
524 proto_tree_add_text(tree, tvb, offset, length,
526 print_tsap(tvb_get_ptr(tvb, offset, length), length));
532 proto_tree_add_text(tree, tvb, offset, length,
533 "Checksum: 0x%04x", tvb_get_ntohs(tvb, offset));
539 c1 = tvb_get_guint8(tvb, offset);
540 proto_tree_add_text(tree, tvb, offset, length,
547 c1 = tvb_get_guint8(tvb, offset) & 0x0F;
548 switch (class_option) {
552 proto_tree_add_text(tree, tvb, offset, 1,
553 "Use of network expedited data");
555 proto_tree_add_text(tree, tvb, offset, 1,
556 "Non use of network expedited data");
558 proto_tree_add_text(tree, tvb, offset, 1,
559 "Use of Receipt confirmation");
561 proto_tree_add_text(tree, tvb, offset, 1,
562 "Use of explicit AK variant");
567 proto_tree_add_text(tree, tvb, offset, 1,
568 "Non-use 16 bit checksum in class 4");
570 proto_tree_add_text(tree, tvb, offset, 1,
571 "Use 16 bit checksum ");
575 proto_tree_add_text(tree, tvb, offset, 1,
576 "Use of transport expedited data transfer\n");
578 proto_tree_add_text(tree, tvb, offset, 1,
579 "Non-use of transport expedited data transfer");
584 case VP_PREF_MAX_TPDU_SIZE:
588 pref_max_tpdu_size = tvb_get_guint8(tvb, offset);
592 pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
596 pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
600 pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
604 proto_tree_add_text(tree, tvb, offset, length,
605 "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)",
609 proto_tree_add_text(tree, tvb, offset, length,
610 "Preferred maximum TPDU size: %u", pref_max_tpdu_size*128);
615 case VP_INACTIVITY_TIMER:
616 proto_tree_add_text(tree, tvb, offset, length,
617 "Inactivity timer: %u ms", tvb_get_ntohl(tvb, offset));
622 case VP_PROTECTION: /* user-defined */
623 case VP_PROTO_CLASS: /* todo */
624 default: /* unknown, no decoding */
625 proto_tree_add_text(tree, tvb, offset, length,
626 "Parameter value: <not shown>");
636 static int osi_decode_DR(tvbuff_t *tvb, int offset,
637 packet_info *pinfo, proto_tree *tree)
639 proto_tree *cotp_tree;
648 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
649 reason = tvb_get_guint8(tvb, offset + P_REASON_IN_DR);
652 case (128+0): str = "Normal Disconnect"; break;
653 case (128+1): str = "Remote transport entity congestion"; break;
654 case (128+2): str = "Connection negotiation failed"; break;
655 case (128+3): str = "Duplicate source reference"; break;
656 case (128+4): str = "Mismatched references"; break;
657 case (128+5): str = "Protocol error"; break;
658 case (128+7): str = "Reference overflow"; break;
659 case (128+8): str = "Connection requestion refused"; break;
660 case (128+10):str = "Header or parameter length invalid"; break;
661 case (0): str = "Reason not specified"; break;
662 case (1): str = "Congestion at TSAP"; break;
663 case (2): str = "Session entity not attached to TSAP"; break;
664 case (3): str = "Address unknown"; break;
670 if (check_col(pinfo->fd, COL_INFO))
671 col_append_fstr(pinfo->fd, COL_INFO,
672 "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
676 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
677 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
678 proto_tree_add_text(cotp_tree, tvb, offset, 1,
679 "Length indicator: %u", li);
680 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
681 "TPDU code: 0x%x (DR)", tpdu);
682 proto_tree_add_text(cotp_tree, tvb, offset + 2, 2,
683 "Destination reference: 0x%04x", dst_ref);
684 proto_tree_add_text(cotp_tree, tvb, offset + 4, 2,
685 "Source reference: 0x%04x", src_ref);
686 proto_tree_add_text(cotp_tree, tvb, offset + 6, 1,
693 dissect_data(tvb, offset, pinfo, tree);
694 offset += tvb_length_remaining(tvb, offset);
695 /* we dissected all of the containing PDU */
699 } /* osi_decode_DR */
701 static int osi_decode_DT(tvbuff_t *tvb, int offset,
702 packet_info *pinfo, proto_tree *tree,
703 gboolean uses_inactive_subset,
704 gboolean *subdissector_found)
706 proto_tree *cotp_tree = NULL;
708 gboolean is_extended;
709 gboolean is_class_234;
714 /* VP_CHECKSUM is the only parameter allowed in the variable part.
715 (This means we may misdissect this if the packet is bad and
716 contains other parameters.) */
719 case LI_NORMAL_DT_WITH_CHECKSUM :
720 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
724 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
725 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
726 if ( tpdu_nr & 0x80 )
727 tpdu_nr = tpdu_nr & 0x7F;
734 case LI_EXTENDED_DT_WITH_CHECKSUM :
735 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
739 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
740 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
741 if ( tpdu_nr & 0x80000000 )
742 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
749 case LI_NORMAL_DT_CLASS_01 :
750 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
751 if ( tpdu_nr & 0x80 )
752 tpdu_nr = tpdu_nr & 0x7F;
756 is_class_234 = FALSE;
759 default : /* bad TPDU */
765 if (check_col(pinfo->fd, COL_INFO))
766 col_append_fstr(pinfo->fd, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x %s",
769 (fragment)? "(fragment)" : "");
772 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
773 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
774 proto_tree_add_text(cotp_tree, tvb, offset, 1,
775 "Length indicator: %u", li);
780 proto_tree_add_text(cotp_tree, tvb, offset, 1,
781 "TPDU code: 0x%x (DT)", tpdu);
789 proto_tree_add_text(cotp_tree, tvb, offset, 2,
790 "Destination reference: 0x%04x", dst_ref);
798 proto_tree_add_text(cotp_tree, tvb, offset, 4,
799 "TPDU number: 0x%08x (%s)",
801 (fragment)? "fragment":"complete");
807 proto_tree_add_text(cotp_tree, tvb, offset, 1,
808 "TPDU number: 0x%02x (%s)",
810 (fragment)? "fragment":"complete");
817 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
820 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
821 if (uses_inactive_subset){
822 if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
824 *subdissector_found = TRUE;
826 /* Fill in other Dissectors using inactive subset here */
827 dissect_data(next_tvb, 0, pinfo, tree);
830 dissect_data(next_tvb, 0, pinfo, tree);
831 offset += tvb_length_remaining(tvb, offset);
832 /* we dissected all of the containing PDU */
836 } /* osi_decode_DT */
838 static int osi_decode_ED(tvbuff_t *tvb, int offset,
839 packet_info *pinfo, proto_tree *tree)
841 proto_tree *cotp_tree = NULL;
843 gboolean is_extended;
847 /* ED TPDUs are never fragmented */
849 /* VP_CHECKSUM is the only parameter allowed in the variable part.
850 (This means we may misdissect this if the packet is bad and
851 contains other parameters.) */
854 case LI_NORMAL_DT_WITH_CHECKSUM :
855 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
859 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
860 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
861 if ( tpdu_nr & 0x80 )
862 tpdu_nr = tpdu_nr & 0x7F;
868 case LI_EXTENDED_DT_WITH_CHECKSUM :
869 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
873 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
874 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
875 if ( tpdu_nr & 0x80000000 )
876 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
882 default : /* bad TPDU */
888 if (check_col(pinfo->fd, COL_INFO))
889 col_append_fstr(pinfo->fd, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
893 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
894 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
895 proto_tree_add_text(cotp_tree, tvb, offset, 1,
896 "Length indicator: %u", li);
901 proto_tree_add_text(cotp_tree, tvb, offset, 1,
902 "TPDU code: 0x%x (ED)", tpdu);
908 proto_tree_add_text(cotp_tree, tvb, offset, 2,
909 "Destination reference: 0x%04x", dst_ref);
916 proto_tree_add_text(cotp_tree, tvb, offset, 4,
917 "TPDU number: 0x%02x", tpdu_nr);
923 proto_tree_add_text(cotp_tree, tvb, offset, 1,
924 "TPDU number: 0x%02x", tpdu_nr);
931 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
934 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
935 dissect_data(next_tvb, 0, pinfo, tree);
937 offset += tvb_length_remaining(tvb, offset);
938 /* we dissected all of the containing PDU */
942 } /* osi_decode_ED */
944 static int osi_decode_RJ(tvbuff_t *tvb, int offset,
945 packet_info *pinfo, proto_tree *tree)
947 proto_tree *cotp_tree;
954 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
956 case LI_EXTENDED_RJ :
957 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
958 credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
966 if (check_col(pinfo->fd, COL_INFO))
967 col_append_fstr(pinfo->fd, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
971 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
972 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
973 proto_tree_add_text(cotp_tree, tvb, offset, 1,
974 "Length indicator: %u", li);
975 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
976 "TPDU code: 0x%x (RJ)", tpdu);
977 if (li == LI_NORMAL_RJ)
978 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
980 proto_tree_add_text(cotp_tree, tvb, offset + 2, 2,
981 "Destination reference: 0x%04x", dst_ref);
982 if (li == LI_NORMAL_RJ)
983 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
984 "Your TPDU number: 0x%02x", tpdu_nr);
986 proto_tree_add_text(cotp_tree, tvb, offset + 4, 4,
987 "Your TPDU number: 0x%02x", tpdu_nr);
988 proto_tree_add_text(cotp_tree, tvb, offset + 8, 2,
989 "Credit: 0x%02x", credit);
997 } /* osi_decode_RJ */
999 static int osi_decode_CC(tvbuff_t *tvb, int offset,
1000 packet_info *pinfo, proto_tree *tree)
1003 /* CC & CR decoding in the same function */
1005 proto_tree *cotp_tree = NULL;
1008 u_char class_option;
1010 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1011 class_option = (tvb_get_guint8(tvb, offset + P_CLASS_OPTION) >> 4 ) & 0x0F;
1012 if (class_option > 4)
1015 if (check_col(pinfo->fd, COL_INFO))
1016 col_append_fstr(pinfo->fd, COL_INFO,
1017 "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1018 (tpdu == CR_TPDU) ? "CR" : "CC",
1023 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1024 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1025 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1026 "Length indicator: %u", li);
1031 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1032 "TPDU code: 0x%x (%s)", tpdu,
1033 (tpdu == CR_TPDU) ? "CR" : "CC");
1039 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1040 "Destination reference: 0x%04x", dst_ref);
1046 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1047 "Source reference: 0x%04x", src_ref);
1053 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1054 "Class option: 0x%02x", class_option);
1060 osi_decode_tp_var_part(tvb, offset, li, class_option, cotp_tree);
1064 dissect_data(tvb, offset, pinfo, tree);
1065 offset += tvb_length_remaining(tvb, offset);
1066 /* we dissected all of the containing PDU */
1070 } /* osi_decode_CC */
1072 static int osi_decode_DC(tvbuff_t *tvb, int offset,
1073 packet_info *pinfo, proto_tree *tree)
1075 proto_tree *cotp_tree = NULL;
1082 src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
1084 if (check_col(pinfo->fd, COL_INFO))
1085 col_append_fstr(pinfo->fd, COL_INFO,
1086 "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
1091 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1092 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1093 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1094 "Length indicator: %u", li);
1099 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1100 "TPDU code: 0x%x (DC)", tpdu);
1106 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1107 "Destination reference: 0x%04x", dst_ref);
1113 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1114 "Source reference: 0x%04x", src_ref);
1120 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
1125 } /* osi_decode_DC */
1127 static int osi_decode_AK(tvbuff_t *tvb, int offset,
1128 packet_info *pinfo, proto_tree *tree)
1130 proto_tree *cotp_tree = NULL;
1138 if (is_LI_NORMAL_AK(li)) {
1140 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1142 if (check_col(pinfo->fd, COL_INFO))
1143 col_append_fstr(pinfo->fd, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1147 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1148 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1149 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1150 "Length indicator: %u", li);
1155 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1156 "TPDU code: 0x%x (AK)", tpdu);
1157 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1164 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1165 "Destination reference: 0x%04x", dst_ref);
1171 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1172 "Your TPDU number: 0x%02x", tpdu_nr);
1178 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
1181 } else { /* extended format */
1183 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1184 cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
1186 if (check_col(pinfo->fd, COL_INFO))
1187 col_append_fstr(pinfo->fd, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1191 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1192 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1193 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1194 "Length indicator: %u", li);
1199 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1200 "TPDU code: 0x%x (AK)", tpdu);
1206 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1207 "Destination reference: 0x%04x", dst_ref);
1213 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1214 "Your TPDU number: 0x%08x", tpdu_nr);
1220 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1221 "Credit: 0x%04x", cdt_in_ak);
1227 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
1230 } /* is_LI_NORMAL_AK */
1234 } /* osi_decode_AK */
1236 static int osi_decode_EA(tvbuff_t *tvb, int offset,
1237 packet_info *pinfo, proto_tree *tree)
1239 proto_tree *cotp_tree = NULL;
1241 gboolean is_extended;
1247 /* VP_CHECKSUM is the only parameter allowed in the variable part.
1248 (This means we may misdissect this if the packet is bad and
1249 contains other parameters.) */
1252 case LI_NORMAL_EA_WITH_CHECKSUM :
1253 if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
1254 tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
1258 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1259 tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
1260 is_extended = FALSE;
1263 case LI_EXTENDED_EA_WITH_CHECKSUM :
1264 if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
1265 tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
1269 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1270 tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
1274 default : /* bad TPDU */
1280 if (check_col(pinfo->fd, COL_INFO))
1281 col_append_fstr(pinfo->fd, COL_INFO,
1282 "EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1285 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1286 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1287 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1288 "Length indicator: %u", li);
1293 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1294 "TPDU code: 0x%x (EA)", tpdu);
1300 proto_tree_add_text(cotp_tree, tvb, offset, 2,
1301 "Destination reference: 0x%04x", dst_ref);
1308 proto_tree_add_text(cotp_tree, tvb, offset, 4,
1309 "Your TPDU number: 0x%08x", tpdu_nr);
1315 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1316 "Your TPDU number: 0x%02x", tpdu_nr);
1323 osi_decode_tp_var_part(tvb, offset, li, 4, cotp_tree);
1328 } /* osi_decode_EA */
1330 static int osi_decode_ER(tvbuff_t *tvb, int offset,
1331 packet_info *pinfo, proto_tree *tree)
1333 proto_tree *cotp_tree;
1340 switch(tvb_get_guint8(tvb, offset + P_REJECT_ER)) {
1342 str = "Reason not specified";
1345 str = "Invalid parameter code";
1348 str = "Invalid TPDU type";
1351 str = "Invalid parameter value";
1359 if (check_col(pinfo->fd, COL_INFO))
1360 col_append_fstr(pinfo->fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1363 ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
1364 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1365 proto_tree_add_text(cotp_tree, tvb, offset, 1,
1366 "Length indicator: %u", li);
1367 proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
1368 "TPDU code: 0x%x (ER)", tpdu);
1369 proto_tree_add_text(cotp_tree, tvb, offset + 2, 2,
1370 "Destination reference: 0x%04x", dst_ref);
1371 proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
1372 "Reject cause: %s", str);
1379 } /* osi_decode_ER */
1381 static int osi_decode_UD(tvbuff_t *tvb, int offset,
1382 packet_info *pinfo, proto_tree *tree,
1383 gboolean *subdissector_found)
1386 proto_tree *cltp_tree = NULL;
1389 if (check_col(pinfo->fd, COL_INFO))
1390 col_append_str(pinfo->fd, COL_INFO, "UD TPDU");
1393 ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, FALSE);
1394 cltp_tree = proto_item_add_subtree(ti, ett_cltp);
1395 proto_tree_add_text(cltp_tree, tvb, offset, 1,
1396 "Length indicator: %u", li);
1401 proto_tree_add_text(cltp_tree, tvb, offset, 1,
1402 "TPDU code: 0x%x (UD)", tpdu);
1408 osi_decode_tp_var_part(tvb, offset, li, 0, cltp_tree);
1411 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1412 dissect_data(next_tvb, 0, pinfo, tree);
1413 offset += tvb_length_remaining(tvb, offset);
1414 /* we dissected all of the containing PDU */
1418 } /* osi_decode_UD */
1420 /* Returns TRUE if we found at least one valid COTP or CLTP PDU, FALSE
1423 There doesn't seem to be any way in which the OSI network layer protocol
1424 distinguishes between COTP and CLTP, but the first two octets of both
1425 protocols' headers mean the same thing - length and PDU type - and the
1426 only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
1427 both of them here. */
1428 static gboolean dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
1429 proto_tree *tree, gboolean uses_inactive_subset)
1432 gboolean first_tpdu = TRUE;
1434 gboolean found_ositp = FALSE;
1435 gboolean is_cltp = FALSE;
1436 gboolean subdissector_found = FALSE;
1438 if (!proto_is_protocol_enabled(proto_cotp))
1439 return FALSE; /* COTP has been disabled */
1440 /* XXX - what about CLTP? */
1442 pinfo->current_proto = "COTP";
1444 /* Initialize the COL_INFO field; each of the TPDUs will have its
1445 information appended. */
1446 if (check_col(pinfo->fd, COL_INFO))
1447 col_add_str(pinfo->fd, COL_INFO, "");
1449 while (tvb_offset_exists(tvb, offset)) {
1451 if (check_col(pinfo->fd, COL_INFO))
1452 col_append_str(pinfo->fd, COL_INFO, ", ");
1454 if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
1455 if (check_col(pinfo->fd, COL_INFO))
1456 col_append_str(pinfo->fd, COL_INFO, "Length indicator is zero");
1458 dissect_data(tvb, offset, pinfo, tree);
1462 tpdu = (tvb_get_guint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
1463 if (tpdu == UD_TPDU)
1464 pinfo->current_proto = "CLTP"; /* connectionless transport */
1465 cdt = tvb_get_guint8(tvb, offset + P_CDT) & 0x0F;
1466 dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
1471 new_offset = osi_decode_CC(tvb, offset, pinfo, tree);
1474 new_offset = osi_decode_DR(tvb, offset, pinfo, tree);
1477 new_offset = osi_decode_DT(tvb, offset, pinfo, tree,
1478 uses_inactive_subset, &subdissector_found);
1481 new_offset = osi_decode_ED(tvb, offset, pinfo, tree);
1484 new_offset = osi_decode_RJ(tvb, offset, pinfo, tree);
1487 new_offset = osi_decode_DC(tvb, offset, pinfo, tree);
1490 new_offset = osi_decode_AK(tvb, offset, pinfo, tree);
1493 new_offset = osi_decode_EA(tvb, offset, pinfo, tree);
1496 new_offset = osi_decode_ER(tvb, offset, pinfo, tree);
1499 new_offset = osi_decode_UD(tvb, offset, pinfo, tree,
1500 &subdissector_found);
1504 if (first_tpdu && check_col(pinfo->fd, COL_INFO))
1505 col_append_fstr(pinfo->fd, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
1506 new_offset = -1; /* bad PDU type */
1510 if (new_offset == -1) { /* incorrect TPDU */
1512 dissect_data(tvb, offset, pinfo, tree);
1517 /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
1518 is either COTP or CLTP. */
1519 if (!subdissector_found && check_col(pinfo->fd, COL_PROTOCOL))
1520 col_add_str(pinfo->fd, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
1524 offset = new_offset;
1528 } /* dissect_ositp_internal */
1530 void dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1532 if (!dissect_ositp_internal(tvb, pinfo, tree, FALSE))
1533 dissect_data(tvb, 0, pinfo, tree);
1538 * CLNP part / main entry point
1541 static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1543 proto_tree *clnp_tree = NULL;
1545 guint8 cnf_proto_id;
1550 char flag_string[6+1];
1551 char *pdu_type_string;
1552 guint16 segment_length;
1553 guint16 segment_offset = 0;
1556 u_char src_len, dst_len, nsel, opt_len = 0;
1557 guint8 *dst_addr, *src_addr;
1561 CHECK_DISPLAY_AS_DATA(proto_clnp, tvb, pinfo, tree);
1563 pinfo->current_proto = "CLNP";
1565 if (check_col(pinfo->fd, COL_PROTOCOL))
1566 col_add_str(pinfo->fd, COL_PROTOCOL, "CLNP");
1568 cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
1569 if (cnf_proto_id == NLPID_NULL) {
1570 if (check_col(pinfo->fd, COL_INFO))
1571 col_add_str(pinfo->fd, COL_INFO, "Inactive subset");
1573 ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, FALSE);
1574 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1575 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1579 next_tvb = tvb_new_subset(tvb, 1, -1, -1);
1580 dissect_ositp_internal(next_tvb, pinfo, tree, TRUE);
1584 /* return if version not known */
1585 cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
1586 if (cnf_vers != ISO8473_V1) {
1587 dissect_data(tvb, 0, pinfo, tree);
1591 /* fixed part decoding */
1592 cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
1593 opt_len = cnf_hdr_len;
1596 ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, FALSE);
1597 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1598 proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
1600 proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
1602 proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
1604 cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
1605 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
1607 "Holding Time : %u (%u secs)",
1608 cnf_ttl, cnf_ttl / 2);
1611 cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
1612 pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_vals,
1613 "Unknown (0x%02x)");
1614 flag_string[0] = '\0';
1615 if (cnf_type & CNF_SEG_OK)
1616 strcat(flag_string, "S ");
1617 if (cnf_type & CNF_MORE_SEGS)
1618 strcat(flag_string, "M ");
1619 if (cnf_type & CNF_ERR_OK)
1620 strcat(flag_string, "E ");
1622 proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
1624 "PDU Type : 0x%02x (%s%s)",
1630 /* If we don't have the full header - i.e., not enough to see the
1631 segmentation part and determine whether this datagram is segmented
1632 or not - set the Info column now; we'll get an exception before
1633 we set it otherwise. */
1635 if (!tvb_bytes_exist(tvb, 0, cnf_hdr_len)) {
1636 if (check_col(pinfo->fd, COL_INFO))
1637 col_add_fstr(pinfo->fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1640 segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
1642 proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
1644 cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
1645 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb, P_CLNP_CKSUM, 2,
1647 "Checksum : 0x%04x",
1649 opt_len -= 9; /* Fixed part of Hesder */
1654 offset = P_CLNP_ADDRESS_PART;
1655 dst_len = tvb_get_guint8(tvb, offset);
1656 dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
1657 nsel = tvb_get_guint8(tvb, offset + dst_len);
1658 src_len = tvb_get_guint8(tvb, offset + dst_len + 1);
1659 src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);
1662 proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
1664 proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
1667 print_nsap_net(dst_addr, dst_len));
1668 proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
1669 offset + 1 + dst_len, 1, src_len);
1670 proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
1671 offset + dst_len + 2, src_len,
1674 print_nsap_net(src_addr, src_len));
1676 opt_len -= dst_len + src_len +2;
1679 if (check_col(pinfo->fd, COL_RES_NET_SRC))
1680 col_add_fstr(pinfo->fd, COL_RES_NET_SRC, "%s", print_nsap_net(src_addr, src_len));
1681 if (check_col(pinfo->fd, COL_RES_NET_DST))
1682 col_add_fstr(pinfo->fd, COL_RES_NET_DST, "%s", print_nsap_net(dst_addr, dst_len));
1684 /* Segmentation Part */
1686 offset += dst_len + src_len + 2;
1688 if (cnf_type & CNF_SEG_OK) {
1689 struct clnp_segment seg; /* XXX - not used */
1690 tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg)); /* XXX - not used */
1692 segment_offset = tvb_get_ntohs(tvb, offset + 2);
1694 proto_tree_add_text(clnp_tree, tvb, offset, 2,
1695 "Data unit identifier: %06u",
1696 tvb_get_ntohs(tvb, offset));
1697 proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
1698 "Segment offset : %6u",
1700 proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
1701 "Total length : %6u",
1702 tvb_get_ntohs(tvb, offset + 4));
1710 /* To do : decode options */
1712 proto_tree_add_text(clnp_tree, tvb, offset,
1713 cnf_hdr_len - offset,
1714 "Options/Data: <not shown>");
1716 /* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/
1718 dissect_osi_options( 0xff,
1720 tvb, offset, pinfo, clnp_tree );
1723 /* Length of CLNP datagram plus headers above it. */
1724 len = segment_length;
1726 /* Set the payload and captured-payload lengths to the minima of (the
1727 datagram length plus the length of the headers above it) and the
1729 if (pinfo->len > len)
1731 if (pinfo->captured_len > len)
1732 pinfo->captured_len = len;
1734 offset = cnf_hdr_len;
1736 /* For now, dissect the payload of segments other than the initial
1737 segment as data, rather than handing them off to the transport
1738 protocol, just as we do with fragments other than the first
1739 fragment in a fragmented IP datagram; in the future, we will
1740 probably reassemble fragments for IP, and may reassemble segments
1742 if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
1743 if (check_col(pinfo->fd, COL_INFO))
1744 col_add_fstr(pinfo->fd, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
1745 pdu_type_string, flag_string, segment_offset);
1746 dissect_data(tvb, offset, pinfo, tree);
1750 if (tvb_offset_exists(tvb, offset)) {
1751 switch (cnf_type & CNF_TYPE) {
1755 /* Continue with COTP if any data.
1756 XXX - if this isn't the first Derived PDU of a segmented Initial
1759 if (nsel == (char)tp_nsap_selector || always_decode_transport) {
1760 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1761 if (dissect_ositp_internal(next_tvb, pinfo, tree, FALSE))
1762 return; /* yes, it appears to be COTP or CLTP */
1767 /* The payload is the header and "none, some, or all of the data
1768 part of the discarded PDU", i.e. it's like an ICMP error;
1769 just as we don't yet trust ourselves to be able to dissect
1770 the payload of an ICMP error packet, we don't yet trust
1771 ourselves to dissect the payload of a CLNP ER packet. */
1776 /* XXX - dissect this */
1780 if (check_col(pinfo->fd, COL_INFO))
1781 col_add_fstr(pinfo->fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1782 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1783 dissect_data(next_tvb, 0, pinfo, tree);
1785 } /* dissect_clnp */
1788 void proto_register_clnp(void)
1790 static hf_register_info hf[] = {
1792 { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
1793 VALS(nlpid_vals), 0x0, "" }},
1796 { "HDR Length ", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1799 { "Version ", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1802 { "Holding Time ", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1805 { "PDU Type ", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1807 { &hf_clnp_pdu_length,
1808 { "PDU length ", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
1810 { &hf_clnp_checksum,
1811 { "Checksum ", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
1813 { &hf_clnp_dest_length,
1814 { "DAL ", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1817 { " DA ", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }},
1819 { &hf_clnp_src_length,
1820 { "SAL ", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1823 { " SA ", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }},
1825 static gint *ett[] = {
1829 module_t *clnp_module;
1831 proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "clnp");
1832 proto_register_field_array(proto_clnp, hf, array_length(hf));
1833 proto_register_subtree_array(ett, array_length(ett));
1835 clnp_module = prefs_register_module("clnp", "CLNP", NULL);
1836 prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
1837 "NSAP selector for Transport Protocol (last byte in hexa)",
1838 "NSAP selector for Transport Protocol (last byte in hexa)",
1839 16, &tp_nsap_selector);
1840 prefs_register_bool_preference(clnp_module, "always_decode_transport",
1841 "Always try to decode NSDU as transport PDUs",
1842 "Always try to decode NSDU as transport PDUs",
1843 &always_decode_transport);
1847 void proto_register_cotp(void)
1849 /* static hf_register_info hf[] = {
1851 { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
1853 static gint *ett[] = {
1857 proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "cotp");
1858 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
1859 proto_register_subtree_array(ett, array_length(ett));
1861 /* subdissector code */
1862 register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
1865 void proto_register_cltp(void)
1867 /* static hf_register_info hf[] = {
1869 { "Name", "cltp.abbreviation", TYPE, VALS_POINTER }},
1871 static gint *ett[] = {
1875 proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "cltp");
1876 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
1877 proto_register_subtree_array(ett, array_length(ett));
1881 proto_reg_handoff_clnp(void)
1883 dissector_add("osinl", NLPID_ISO8473_CLNP, dissect_clnp);
1884 dissector_add("osinl", NLPID_NULL, dissect_clnp); /* Inactive subset */