2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-clnp.c,v 1.6 2000/05/05 09:32:01 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>
42 #include "packet-osi.h"
43 #include "packet-osi-options.h"
44 #include "packet-clnp.h"
45 #include "packet-isis.h"
46 #include "packet-esis.h"
49 /* protocols and fields */
51 static int proto_clnp = -1;
52 static int proto_cotp = -1;
53 static gint ett_clnp = -1;
54 static gint ett_cotp = -1;
56 static int hf_clnp_id = -1;
57 static int hf_clnp_length = -1;
58 static int hf_clnp_version = -1;
59 static int hf_clnp_ttl = -1;
60 static int hf_clnp_type = -1;
61 static int hf_clnp_pdu_length = -1;
62 static int hf_clnp_checksum = -1;
63 static int hf_clnp_dest_length = -1;
64 static int hf_clnp_dest = -1;
65 static int hf_clnp_src_length = -1;
66 static int hf_clnp_src = -1;
69 * ISO 8473 OSI CLNP definition (see RFC994)
71 * _________________________________
73 * |_________________________________|
75 * |_________________________________|
76 * | Segmentation Part (optional) |
77 * |_________________________________|
78 * | Options Part (optional) |
79 * |_________________________________|
81 * |_________________________________|
84 #define ISO8473_V1 0x01 /* CLNP version 1 */
89 u_char cnf_proto_id; /* network layer protocol identifier */
90 u_char cnf_hdr_len; /* length indicator (octets) */
91 u_char cnf_vers; /* version/protocol identifier extension */
92 u_char cnf_ttl; /* lifetime (500 milliseconds) */
93 u_char cnf_type; /* type code */
94 u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
95 u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
96 u_char cnf_cksum_msb; /* checksum high byte */
97 u_char cnf_cksum_lsb; /* checksum low byte */
100 #define CNF_TYPE 0x1f
101 #define CNF_ERR_OK 0x20
102 #define CNF_MORE_SEGS 0x40
103 #define CNF_SEG_OK 0x80
108 #define ERQ_NPDU 0x1E
109 #define ERP_NPDU 0x1F
111 static const value_string npdu_type_vals[] = {
122 #define P_ADDRESS_PART 9
124 /* Segmentation part */
126 struct clnp_segment {
127 u_short cng_id; /* data unit identifier */
128 u_short cng_off; /* segment offset */
129 u_short cng_tot_len; /* total length */
134 #define NSEL_NET 0x00
139 * ISO8073 OSI COTP definition (see RFC905)
142 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
144 /* TPDU definition */
164 #define P_TPDU_NR_0_1 2
165 #define P_TPDU_NR_234 4
166 #define P_VAR_PART_NDT 5
167 #define P_VAR_PART_EDT 8
168 #define P_VAR_PART_NAK 5
169 #define P_VAR_PART_CC 7
170 #define P_VAR_PART_EAK 10
171 #define P_VAR_PART_DC 6
172 #define P_VAR_PART_DR 7
173 #define P_CDT_IN_AK 8
174 #define P_CDT_IN_RJ 8
175 #define P_REJECT_ER 4
176 #define P_REASON_IN_DR 6
177 #define P_CLASS_OPTION 6
179 /* TPDU length indicator */
181 #define LI_NORMAL_DT_CLASS_01 2
182 #define LI_NORMAL_DT_WITH_CHECKSUM 8
183 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
184 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
185 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
186 #define LI_NORMAL_EA_WITH_CHECKSUM 8
187 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
188 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
189 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
190 #define LI_NORMAL_RJ 4
191 #define LI_EXTENDED_RJ 9
197 #define LI_DC_WITH_CHECKSUM 9
198 #define LI_DC_WITHOUT_CHECKSUM 5
199 #define is_LI_NORMAL_AK(p) ( p & 0x01 )
203 #define VP_ACK_TIME 0x85
204 #define VP_RES_ERROR 0x86
205 #define VP_PRIORITY 0x87
206 #define VP_TRANSIT_DEL 0x88
207 #define VP_THROUGHPUT 0x89
208 #define VP_SEQ_NR 0x8A /* in AK */
209 #define VP_REASSIGNMENT 0x8B
210 #define VP_FLOW_CNTL 0x8C /* in AK */
211 #define VP_TPDU_SIZE 0xC0
212 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
213 #define VP_DST_TSAP 0xC2
214 #define VP_CHECKSUM 0xC3
215 #define VP_VERSION_NR 0xC4
216 #define VP_PROTECTION 0xC5
217 #define VP_OPT_SEL 0xC6
218 #define VP_PROTO_CLASS 0xC7
222 #define EXTRACT_SHORT(p) pntohs(p)
223 #define EXTRACT_LONG(p) pntohl(p)
225 /* global variables */
227 static u_char li, tpdu, cdt; /* common fields */
228 static u_short dst_ref;
230 /* List of dissectors to call for COTP packets put atop the Inactive
232 static heur_dissector_list_t cotp_is_heur_subdissector_list;
234 /* function definitions */
236 static int osi_decode_DR(const u_char *pd, int offset,
237 frame_data *fd, proto_tree *tree)
239 proto_tree *cotp_tree;
248 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
249 reason = pd[offset + P_REASON_IN_DR];
252 case (128+0): str = "Normal Disconnect"; break;
253 case (128+1): str = "Remote transport entity congestion"; break;
254 case (128+2): str = "Connection negotiation failed"; break;
255 case (128+3): str = "Duplicate source reference"; break;
256 case (128+4): str = "Mismatched references"; break;
257 case (128+5): str = "Protocol error"; break;
258 case (128+7): str = "Reference overflow"; break;
259 case (128+8): str = "Connection requestion refused"; break;
260 case (128+10):str = "Header or parameter length invalid"; break;
261 case (0): str = "Reason not specified"; break;
262 case (1): str = "Congestion at TSAP"; break;
263 case (2): str = "Session entity not attached to TSAP"; break;
264 case (3): str = "Address unknown"; break;
270 if (check_col(fd, COL_INFO))
271 col_append_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
275 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
276 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
277 proto_tree_add_text(cotp_tree, offset, 1,
278 "Length indicator: %u", li);
279 proto_tree_add_text(cotp_tree, offset + 1, 1,
280 "TPDU code: 0x%x (DR)", tpdu);
281 proto_tree_add_text(cotp_tree, offset + 2, 2,
282 "Destination reference: 0x%04x", dst_ref);
283 proto_tree_add_text(cotp_tree, offset + 4, 2,
284 "Source reference: 0x%04x", src_ref);
285 proto_tree_add_text(cotp_tree, offset + 6, 1,
290 dissect_data(pd, offset, fd, tree);
292 return pi.captured_len; /* we dissected all of the containing PDU */
294 } /* osi_decode_DR */
296 /* Returns TRUE if we called a sub-dissector, FALSE if not. */
297 static gboolean osi_decode_DT(const u_char *pd, int offset,
298 frame_data *fd, proto_tree *tree,
299 gboolean uses_inactive_subset)
301 proto_tree *cotp_tree;
304 u_short checksum = 0;
305 u_char code = 0, length = 0;
309 case LI_NORMAL_DT_WITH_CHECKSUM :
310 tpdu_nr = pd[offset + P_TPDU_NR_234];
311 if ( tpdu_nr & 0x80 )
312 tpdu_nr = tpdu_nr & 0x7F;
315 code = pd[offset + P_VAR_PART_NDT];
316 if (code == VP_CHECKSUM)
317 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
321 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
322 tpdu_nr = pd[offset + P_TPDU_NR_234];
323 if ( tpdu_nr & 0x80 )
324 tpdu_nr = tpdu_nr & 0x7F;
328 case LI_EXTENDED_DT_WITH_CHECKSUM :
329 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
330 if ( tpdu_nr & 0x80000000 )
331 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
334 code = pd[offset + P_VAR_PART_EDT];
335 if (code == VP_CHECKSUM)
336 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
340 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
341 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
342 if ( tpdu_nr & 0x80000000 )
343 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
347 case LI_NORMAL_DT_CLASS_01 :
348 tpdu_nr = pd[offset + P_TPDU_NR_0_1];
349 if ( tpdu_nr & 0x80 )
350 tpdu_nr = tpdu_nr & 0x7F;
354 default : /* bad TPDU */
360 if (check_col(fd, COL_INFO))
361 col_append_fstr(fd, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x %s",
364 (fragment)? "(fragment)" : "");
367 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
368 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
369 proto_tree_add_text(cotp_tree, offset, 1,
370 "Length indicator: %u", li);
371 proto_tree_add_text(cotp_tree, offset + 1, 1,
372 "TPDU code: 0x%x (DT)", tpdu);
374 if (li != LI_NORMAL_DT_CLASS_01)
375 proto_tree_add_text(cotp_tree, offset + 2, 2,
376 "Destination reference: 0x%04x", dst_ref);
379 case LI_NORMAL_DT_WITH_CHECKSUM :
380 proto_tree_add_text(cotp_tree, offset + 4, 1,
381 "TPDU number: 0x%02x (%s)",
383 (fragment)? "fragment":"complete");
384 proto_tree_add_text(cotp_tree,
385 offset + P_VAR_PART_NDT, 1,
386 "Parameter code: 0x%02x (checksum)", code);
387 proto_tree_add_text(cotp_tree,
388 offset + P_VAR_PART_NDT + 1, 1,
389 "Parameter length: %u", length);
390 proto_tree_add_text(cotp_tree,
391 offset + P_VAR_PART_NDT + 2, length,
392 "Checksum: 0x%04x", checksum);
394 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
395 proto_tree_add_text(cotp_tree, offset + 4, 1,
396 "TPDU number: 0x%02x (%s)",
398 (fragment)? "fragment":"complete");
400 case LI_EXTENDED_DT_WITH_CHECKSUM :
401 proto_tree_add_text(cotp_tree, offset + 4, 4,
402 "TPDU number: 0x%08x (%s)",
404 (fragment)? "fragment":"complete");
405 proto_tree_add_text(cotp_tree,
406 offset + P_VAR_PART_EDT, 1,
407 "Parameter code: 0x%02x (checksum)", code);
408 proto_tree_add_text(cotp_tree,
409 offset + P_VAR_PART_EDT + 1, 1,
410 "Parameter length: %u", length);
411 proto_tree_add_text(cotp_tree,
412 offset + P_VAR_PART_EDT + 2, length,
413 "Checksum: 0x%04x", checksum);
415 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
416 proto_tree_add_text(cotp_tree, offset + 4, 4,
417 "TPDU number: 0x%08x (%s)",
419 (fragment)? "fragment":"complete");
421 case LI_NORMAL_DT_CLASS_01 :
422 proto_tree_add_text(cotp_tree, offset + 2, 1,
423 "TPDU number: 0x%02x (%s)",
425 (fragment)? "fragment":"complete");
431 if (uses_inactive_subset){
432 if (dissector_try_heuristic(cotp_is_heur_subdissector_list, pd, offset,
436 /* Fill in other Dissectors using inactive subset here */
437 dissect_data(pd, offset, fd, tree);
441 dissect_data(pd, offset, fd, tree);
444 } /* osi_decode_DT */
446 static int osi_decode_ED(const u_char *pd, int offset,
447 frame_data *fd, proto_tree *tree)
449 proto_tree *cotp_tree;
452 u_short checksum = 0;
453 u_char code = 0, length = 0;
455 /* ED TPDUs are never fragmented */
458 case LI_NORMAL_DT_WITH_CHECKSUM :
459 tpdu_nr = pd[offset + P_TPDU_NR_234];
460 if ( tpdu_nr & 0x80 )
461 tpdu_nr = tpdu_nr & 0x7F;
464 code = pd[offset + P_VAR_PART_NDT];
465 length = pd[offset + P_VAR_PART_NDT + 1];
466 if (code == VP_CHECKSUM)
467 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
471 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
472 tpdu_nr = pd[offset + P_TPDU_NR_234];
473 if ( tpdu_nr & 0x80 )
474 tpdu_nr = tpdu_nr & 0x7F;
478 case LI_EXTENDED_DT_WITH_CHECKSUM :
479 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
480 if ( tpdu_nr & 0x80000000 )
481 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
484 code = pd[offset + P_VAR_PART_EDT];
485 length = pd[offset + P_VAR_PART_EDT + 1];
486 if (code == VP_CHECKSUM)
487 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
491 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
492 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
493 if ( tpdu_nr & 0x80000000 )
494 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
498 default : /* bad TPDU */
504 if (check_col(fd, COL_INFO))
505 col_append_fstr(fd, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
509 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
510 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
511 proto_tree_add_text(cotp_tree, offset, 1,
512 "Length indicator: %u", li);
513 proto_tree_add_text(cotp_tree, offset + 1, 1,
514 "TPDU code: 0x%x (ED)", tpdu);
515 proto_tree_add_text(cotp_tree, offset + 2, 2,
516 "Destination reference: 0x%04x", dst_ref);
519 case LI_NORMAL_DT_WITH_CHECKSUM :
520 proto_tree_add_text(cotp_tree, offset + 4, 1,
521 "TPDU number: 0x%02x", tpdu_nr);
522 proto_tree_add_text(cotp_tree,
523 offset + P_VAR_PART_NDT, 1,
524 "Parameter code: 0x%02x (checksum)", code);
525 proto_tree_add_text(cotp_tree,
526 offset + P_VAR_PART_NDT + 1, 1,
527 "Parameter length: %u", length);
528 proto_tree_add_text(cotp_tree,
529 offset + P_VAR_PART_NDT + 2, length,
530 "Checksum: 0x%04x", checksum);
532 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
533 proto_tree_add_text(cotp_tree, offset + 4, 1,
534 "TPDU number: 0x%02x", tpdu_nr);
536 case LI_EXTENDED_DT_WITH_CHECKSUM :
537 proto_tree_add_text(cotp_tree, offset + 4, 4,
538 "TPDU number: 0x%02x", tpdu_nr);
539 proto_tree_add_text(cotp_tree,
540 offset + P_VAR_PART_EDT, 1,
541 "Parameter code: 0x%02x (checksum)", code);
542 proto_tree_add_text(cotp_tree,
543 offset + P_VAR_PART_EDT + 1, 1,
544 "Parameter length: %u", length);
545 proto_tree_add_text(cotp_tree,
546 offset + P_VAR_PART_EDT + 2, length,
547 "Checksum: 0x%04x", checksum);
549 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
550 proto_tree_add_text(cotp_tree, offset + 4, 4,
551 "TPDU number: 0x%02x", tpdu_nr);
557 dissect_data(pd, offset, fd, tree);
559 return pi.captured_len; /* we dissected all of the containing PDU */
561 } /* osi_decode_ED */
563 static int osi_decode_RJ(const u_char *pd, int offset,
564 frame_data *fd, proto_tree *tree)
566 proto_tree *cotp_tree;
573 tpdu_nr = pd[offset + P_TPDU_NR_234];
575 case LI_EXTENDED_RJ :
576 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
577 credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
585 if (check_col(fd, COL_INFO))
586 col_append_fstr(fd, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
590 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
591 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
592 proto_tree_add_text(cotp_tree, offset, 1,
593 "Length indicator: %u", li);
594 proto_tree_add_text(cotp_tree, offset + 1, 1,
595 "TPDU code: 0x%x (RJ)", tpdu);
596 if (li == LI_NORMAL_RJ)
597 proto_tree_add_text(cotp_tree, offset + 1, 1,
599 proto_tree_add_text(cotp_tree, offset + 2, 2,
600 "Destination reference: 0x%04x", dst_ref);
601 if (li == LI_NORMAL_RJ)
602 proto_tree_add_text(cotp_tree, offset + 4, 1,
603 "Your TPDU number: 0x%02x", tpdu_nr);
605 proto_tree_add_text(cotp_tree, offset + 4, 4,
606 "Your TPDU number: 0x%02x", tpdu_nr);
607 proto_tree_add_text(cotp_tree, offset + 8, 2,
608 "Credit: 0x%02x", credit);
616 } /* osi_decode_RJ */
618 #define MAX_TSAP_LEN 32
620 static gchar *print_tsap(const u_char *tsap, int length)
623 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
626 gboolean allprintable;
629 if (cur == &str[0][0]) {
631 } else if (cur == &str[1][0]) {
639 if (length <= 0 || length > MAX_TSAP_LEN)
640 sprintf(cur, "<unsupported TSAP length>");
643 for (i=0;i<length;i++) {
644 if (!isprint(tsap[i])) { /* if any byte is not printable */
645 allprintable=FALSE; /* switch to hexdump */
652 while (length != 0) {
654 sprintf(tmp, "%c", *tsap ++);
656 sprintf(tmp, "%02x", *tsap ++);
665 static int osi_decode_CC(const u_char *pd, int offset,
666 frame_data *fd, proto_tree *tree)
669 /* CC & CR decoding in the same function */
671 proto_tree *cotp_tree = NULL;
673 u_short src_ref, checksum;
674 u_char class_option, code, length;
677 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
678 class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
679 if (class_option > 4)
682 if (check_col(fd, COL_INFO))
683 col_append_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
684 (tpdu == CR_TPDU) ? "CR" : "CC",
689 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
690 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
691 proto_tree_add_text(cotp_tree, offset, 1,
692 "Length indicator: %u", li);
693 proto_tree_add_text(cotp_tree, offset + 1, 1,
694 "TPDU code: 0x%x (%s)", tpdu,
695 (tpdu == CR_TPDU) ? "CR" : "CC");
696 proto_tree_add_text(cotp_tree, offset + 2, 2,
697 "Destination reference: 0x%04x", dst_ref);
698 proto_tree_add_text(cotp_tree, offset + 4, 2,
699 "Source reference: 0x%04x", src_ref);
700 proto_tree_add_text(cotp_tree, offset + 6, 1,
701 "Class option: 0x%02x", class_option);
705 while(li > P_VAR_PART_CC + i - 1) {
708 u_short s, s1,s2,s3,s4;
711 switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
713 length = pd[offset + P_VAR_PART_CC + i + 1];
714 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
715 proto_tree_add_text(cotp_tree,
716 offset + P_VAR_PART_CC + i, 1,
717 "Parameter code: 0x%02x (checksum)", code);
718 proto_tree_add_text(cotp_tree,
719 offset + P_VAR_PART_CC + i + 1, 1,
720 "Parameter length: %u", length);
721 proto_tree_add_text(cotp_tree,
722 offset + P_VAR_PART_CC + i + 2, length,
723 "Checksum: 0x%04x", checksum);
727 length = pd[offset + P_VAR_PART_CC + i + 1];
728 proto_tree_add_text(cotp_tree,
729 offset + P_VAR_PART_CC + i, 1,
730 "Parameter code: 0x%02x (src-tsap)", code);
731 proto_tree_add_text(cotp_tree,
732 offset + P_VAR_PART_CC + i + 1, 1,
733 "Parameter length: %u", length);
734 proto_tree_add_text(cotp_tree,
735 offset + P_VAR_PART_CC + i + 2, length,
737 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
742 length = pd[offset + P_VAR_PART_CC + i + 1];
743 proto_tree_add_text(cotp_tree,
744 offset + P_VAR_PART_CC + i, 1,
745 "Parameter code: 0x%02x (dst-tsap)", code);
746 proto_tree_add_text(cotp_tree,
747 offset + P_VAR_PART_CC + i + 1, 1,
748 "Parameter length: %u", length);
749 proto_tree_add_text(cotp_tree,
750 offset + P_VAR_PART_CC + i + 2, length,
752 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
757 length = pd[offset + P_VAR_PART_CC + i + 1];
758 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
759 proto_tree_add_text(cotp_tree,
760 offset + P_VAR_PART_CC + i, 1,
761 "Parameter code: 0x%02x (tpdu-size)", code);
762 proto_tree_add_text(cotp_tree,
763 offset + P_VAR_PART_CC + i + 1, 1,
764 "Parameter length: %u", length);
765 proto_tree_add_text(cotp_tree,
766 offset + P_VAR_PART_CC + i + 2, length,
767 "TPDU size: %u", 2 << c1);
771 length = pd[offset + P_VAR_PART_CC + i + 1];
772 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
773 proto_tree_add_text(cotp_tree,
774 offset + P_VAR_PART_CC + i, 1,
775 "Parameter code: 0x%02x (options)", code);
776 proto_tree_add_text(cotp_tree,
777 offset + P_VAR_PART_CC + i + 1, 1,
778 "Parameter length: %u", length);
779 if (class_option == 1) {
781 proto_tree_add_text(cotp_tree,
782 offset + P_VAR_PART_CC + i + 2, 1,
783 "Use of network expedited data");
785 proto_tree_add_text(cotp_tree,
786 offset + P_VAR_PART_CC + i + 2, 1,
787 "Non use of network expedited data");
789 proto_tree_add_text(cotp_tree,
790 offset + P_VAR_PART_CC + i + 2, 1,
791 "Use of Receipt confirmation");
793 proto_tree_add_text(cotp_tree,
794 offset + P_VAR_PART_CC + i + 2, 1,
795 "Use of explicit AK variant");
796 } else if (class_option == 4) {
798 proto_tree_add_text(cotp_tree,
799 offset + P_VAR_PART_CC + i + 2, 1,
800 "Non-use 16 bit checksum in class 4");
802 proto_tree_add_text(cotp_tree,
803 offset + P_VAR_PART_CC + i + 2, 1,
804 "Use 16 bit checksum ");
807 proto_tree_add_text(cotp_tree,
808 offset + P_VAR_PART_CC + i + 2, 1,
809 "Use of transport expedited data transfer\n");
811 proto_tree_add_text(cotp_tree,
812 offset + P_VAR_PART_CC + i + 2, 1,
813 "Non-use of transport expedited data transfer");
817 length = pd[offset + P_VAR_PART_CC + i + 1];
818 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
819 proto_tree_add_text(cotp_tree,
820 offset + P_VAR_PART_CC + i, 1,
821 "Parameter code: 0x%02x (ack time)", code);
822 proto_tree_add_text(cotp_tree,
823 offset + P_VAR_PART_CC + i + 1, 1,
824 "Parameter length: %u", length);
825 proto_tree_add_text(cotp_tree,
826 offset + P_VAR_PART_CC + i + 2, length,
827 "Ack time (ms): %u", s);
831 length = pd[offset + P_VAR_PART_CC + i + 1];
832 t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
833 t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
834 t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
835 t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
836 proto_tree_add_text(cotp_tree,
837 offset + P_VAR_PART_CC + i, 1,
838 "Parameter code: 0x%02x (throughput)", code);
839 proto_tree_add_text(cotp_tree,
840 offset + P_VAR_PART_CC + i + 1, 1,
841 "Parameter length: %u", length);
842 proto_tree_add_text(cotp_tree,
843 offset + P_VAR_PART_CC + i + 2, 4,
844 "Target value / calling-called: %u o/s", t1);
845 proto_tree_add_text(cotp_tree,
846 offset + P_VAR_PART_CC + i + 6, 4,
847 "Minimum / calling-called: %u o/s", t2);
848 proto_tree_add_text(cotp_tree,
849 offset + P_VAR_PART_CC + i + 10, 4,
850 "Target value / called-calling: %u o/s", t3);
851 proto_tree_add_text(cotp_tree,
852 offset + P_VAR_PART_CC + i + 14, 4,
853 "Minimum / called-calling: %u o/s", t4);
856 case VP_TRANSIT_DEL :
857 length = pd[offset + P_VAR_PART_CC + i + 1];
858 s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
859 s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
860 s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
861 s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
862 proto_tree_add_text(cotp_tree,
863 offset + P_VAR_PART_CC + i, 1,
864 "Parameter code: 0x%02x (transit delay)", code);
865 proto_tree_add_text(cotp_tree,
866 offset + P_VAR_PART_CC + i + 1, 1,
867 "Parameter length: %u", length);
868 proto_tree_add_text(cotp_tree,
869 offset + P_VAR_PART_CC + i + 2, 2,
870 "Target value / calling-called: %u ms", s1);
871 proto_tree_add_text(cotp_tree,
872 offset + P_VAR_PART_CC + i + 4, 2,
873 "Minimum / calling-called: %u ms", s2);
874 proto_tree_add_text(cotp_tree,
875 offset + P_VAR_PART_CC + i + 6, 2,
876 "Target value / called-calling: %u ms", s3);
877 proto_tree_add_text(cotp_tree,
878 offset + P_VAR_PART_CC + i + 8, 2,
879 "Minimum / called-calling: %u ms", s4);
883 length = pd[offset + P_VAR_PART_CC + i + 1];
884 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
885 proto_tree_add_text(cotp_tree,
886 offset + P_VAR_PART_CC + i, 1,
887 "Parameter code: 0x%02x (priority)", code);
888 proto_tree_add_text(cotp_tree,
889 offset + P_VAR_PART_CC + i + 1, 1,
890 "Parameter length: %u", length);
891 proto_tree_add_text(cotp_tree,
892 offset + P_VAR_PART_CC + i + 2, length,
898 length = pd[offset + P_VAR_PART_CC + i + 1];
899 c1 = pd[offset + P_VAR_PART_CC + i + 2];
900 proto_tree_add_text(cotp_tree,
901 offset + P_VAR_PART_CC + i, 1,
902 "Parameter code: 0x%02x (version)", code);
903 proto_tree_add_text(cotp_tree,
904 offset + P_VAR_PART_CC + i + 1, 1,
905 "Parameter length: %u", length);
906 proto_tree_add_text(cotp_tree,
907 offset + P_VAR_PART_CC + i + 2, length,
912 case VP_REASSIGNMENT: /* todo */
915 case VP_PROTO_CLASS :
916 default : /* no decoding */
917 length = pd[offset + P_VAR_PART_CC + i + 1];
918 proto_tree_add_text(cotp_tree,
919 offset + P_VAR_PART_CC + i + 0, 1,
920 "Parameter code: 0x%02x", code);
921 proto_tree_add_text(cotp_tree,
922 offset + P_VAR_PART_CC + i + 1, 1,
923 "Parameter length: %u", length);
924 proto_tree_add_text(cotp_tree,
925 offset + P_VAR_PART_CC + i + 2, length,
926 "Parameter value: <not shown>");
933 dissect_data(pd, offset, fd, tree);
935 return pi.captured_len; /* we dissected all of the containing PDU */
937 } /* osi_decode_CC */
939 static int osi_decode_DC(const u_char *pd, int offset,
940 frame_data *fd, proto_tree *tree)
942 proto_tree *cotp_tree;
944 u_short src_ref, checksum = 0;
945 u_char length = 0, code = 0;
950 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
953 case LI_DC_WITHOUT_CHECKSUM :
955 case LI_DC_WITH_CHECKSUM :
956 if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
958 length = pd[offset + P_VAR_PART_DC + 1];
959 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
967 if (check_col(fd, COL_INFO))
968 col_append_fstr(fd, COL_INFO, "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
973 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
974 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
975 proto_tree_add_text(cotp_tree, offset, 1,
976 "Length indicator: %u", li);
977 proto_tree_add_text(cotp_tree, offset + 1, 1,
978 "TPDU code: 0x%x (DC)", tpdu);
979 proto_tree_add_text(cotp_tree, offset + 2, 2,
980 "Destination reference: 0x%04x", dst_ref);
981 proto_tree_add_text(cotp_tree, offset + 4, 2,
982 "Source reference: 0x%04x", src_ref);
984 proto_tree_add_text(cotp_tree,
985 offset + P_VAR_PART_DC + 0, 1,
986 "Parameter code: 0x%02x (checksum)", code);
987 proto_tree_add_text(cotp_tree,
988 offset + P_VAR_PART_DC + 1, 1,
989 "Parameter length: %u", length);
990 proto_tree_add_text(cotp_tree,
991 offset + P_VAR_PART_DC + 2, 2,
992 "Checksum: 0x%04x", checksum);
1000 } /* osi_decode_DC */
1002 static int osi_decode_AK(const u_char *pd, int offset,
1003 frame_data *fd, proto_tree *tree)
1005 proto_tree *cotp_tree = NULL;
1007 u_int tpdu_nr,i =0, r_lower_window_edge ;
1009 u_short checksum, seq_nr, r_seq_nr, r_cdt;
1010 u_char code, length;
1015 if (!is_LI_NORMAL_AK(li)) {
1016 tpdu_nr = pd[offset + P_TPDU_NR_234];
1018 if (check_col(fd, COL_INFO))
1019 col_append_fstr(fd, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1023 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1024 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1025 proto_tree_add_text(cotp_tree, offset, 1,
1026 "Length indicator: %u", li);
1027 proto_tree_add_text(cotp_tree, offset + 1, 1,
1028 "TPDU code: 0x%x (AK)", tpdu);
1029 proto_tree_add_text(cotp_tree, offset + 1, 1,
1031 proto_tree_add_text(cotp_tree, offset + 2, 2,
1032 "Destination reference: 0x%04x", dst_ref);
1033 proto_tree_add_text(cotp_tree, offset + 4, 1,
1034 "Your TPDU number: 0x%02x", tpdu_nr);
1037 while(li > P_VAR_PART_NAK + i - 1) {
1038 switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
1040 length = pd[offset + P_VAR_PART_NAK + i + 1];
1041 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1043 proto_tree_add_text(cotp_tree,
1044 offset + P_VAR_PART_NAK + i + 0, 1,
1045 "Parameter code: 0x%02x (checksum)", code);
1046 proto_tree_add_text(cotp_tree,
1047 offset + P_VAR_PART_NAK + i + 1, 1,
1048 "Parameter length: %u", length);
1049 proto_tree_add_text(cotp_tree,
1050 offset + P_VAR_PART_NAK + i + 2, 2,
1051 "Checksum: 0x%04x", checksum);
1056 length = pd[offset + P_VAR_PART_NAK + i + 1];
1057 r_lower_window_edge =
1058 EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
1059 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
1060 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
1062 proto_tree_add_text(cotp_tree,
1063 offset + P_VAR_PART_NAK + i + 0, 1,
1064 "Parameter code: 0x%02x (flow control)",
1066 proto_tree_add_text(cotp_tree,
1067 offset + P_VAR_PART_NAK + i + 1, 1,
1068 "Parameter length: %u", length);
1069 proto_tree_add_text(cotp_tree,
1070 offset + P_VAR_PART_NAK + i + 2, 4,
1071 "Lower window edge: 0x%08x",
1072 r_lower_window_edge);
1073 proto_tree_add_text(cotp_tree,
1074 offset + P_VAR_PART_NAK + i + 6, 2,
1075 "Sequence number: 0x%04x",
1077 proto_tree_add_text(cotp_tree,
1078 offset + P_VAR_PART_NAK + i + 8, 2,
1085 length = pd[offset + P_VAR_PART_NAK + i + 1];
1086 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1088 proto_tree_add_text(cotp_tree,
1089 offset + P_VAR_PART_NAK + i + 0, 1,
1090 "Parameter code: 0x%02x (seq number)", code);
1091 proto_tree_add_text(cotp_tree,
1092 offset + P_VAR_PART_NAK + i + 1, 1,
1093 "Parameter length: %u", length);
1094 proto_tree_add_text(cotp_tree,
1095 offset + P_VAR_PART_NAK + i + 2, 2,
1096 "Sequence number: 0x%04x", seq_nr);
1101 length = pd[offset + P_VAR_PART_NAK + i + 1];
1103 proto_tree_add_text(cotp_tree,
1104 offset + P_VAR_PART_NAK + i + 0, 1,
1105 "Parameter code: 0x%02x (unknown)", code);
1106 proto_tree_add_text(cotp_tree,
1107 offset + P_VAR_PART_NAK + i + 1, 1,
1108 "Parameter length: %u", length);
1109 proto_tree_add_text(cotp_tree,
1110 offset + P_VAR_PART_NAK + i + 2, length,
1111 "Parameter value: <not shown>");
1117 } else { /* extended format */
1119 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1120 cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
1122 if (check_col(fd, COL_INFO))
1123 col_append_fstr(fd, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
1127 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1128 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1129 proto_tree_add_text(cotp_tree, offset, 1,
1130 "Length indicator: %u", li);
1131 proto_tree_add_text(cotp_tree, offset + 1, 1,
1132 "TPDU code: 0x%x (AK)", tpdu);
1133 proto_tree_add_text(cotp_tree, offset + 2, 2,
1134 "Destination reference: 0x%04x", dst_ref);
1135 proto_tree_add_text(cotp_tree, offset + 4, 4,
1136 "Your TPDU number: 0x%08x", tpdu_nr);
1137 proto_tree_add_text(cotp_tree, offset + 8, 2,
1138 "Credit: 0x%04x", cdt_in_ak);
1141 while(li > P_VAR_PART_EAK + i - 1) {
1142 switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
1144 length = pd[offset + P_VAR_PART_EAK + i + 1];
1145 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1147 proto_tree_add_text(cotp_tree,
1148 offset + P_VAR_PART_EAK + i + 0, 1,
1149 "Parameter code: 0x%02x (checksum)", code);
1150 proto_tree_add_text(cotp_tree,
1151 offset + P_VAR_PART_EAK + i + 1, 1,
1152 "Parameter length: %u", length);
1153 proto_tree_add_text(cotp_tree,
1154 offset + P_VAR_PART_EAK + i + 2, 2,
1155 "Checksum: 0x%04x", checksum);
1160 length = pd[offset + P_VAR_PART_EAK + i + 1];
1161 r_lower_window_edge =
1162 EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
1163 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
1164 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
1166 proto_tree_add_text(cotp_tree,
1167 offset + P_VAR_PART_EAK + i + 0, 1,
1168 "Parameter code: 0x%02x (flow control)",
1170 proto_tree_add_text(cotp_tree,
1171 offset + P_VAR_PART_EAK + i + 1, 1,
1172 "Parameter length: %u", length);
1173 proto_tree_add_text(cotp_tree,
1174 offset + P_VAR_PART_EAK + i + 2, 4,
1175 "Lower window edge: 0x%08x",
1176 r_lower_window_edge);
1177 proto_tree_add_text(cotp_tree,
1178 offset + P_VAR_PART_EAK + i + 6, 2,
1179 "Sequence number: 0x%04x",
1181 proto_tree_add_text(cotp_tree,
1182 offset + P_VAR_PART_EAK + i + 8, 2,
1189 length = pd[offset + P_VAR_PART_EAK + i + 1];
1190 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1192 proto_tree_add_text(cotp_tree,
1193 offset + P_VAR_PART_EAK + i + 0, 1,
1194 "Parameter code: 0x%02x (seq number)", code);
1195 proto_tree_add_text(cotp_tree,
1196 offset + P_VAR_PART_EAK + i + 1, 1,
1197 "Parameter length: %u", length);
1198 proto_tree_add_text(cotp_tree,
1199 offset + P_VAR_PART_EAK + i + 2, 2,
1200 "Sequence number: 0x%04x", seq_nr);
1205 length = pd[offset + P_VAR_PART_EAK + i + 1];
1207 proto_tree_add_text(cotp_tree,
1208 offset + P_VAR_PART_EAK + i + 0, 1,
1209 "Parameter code: 0x%02x (unknown)", code);
1210 proto_tree_add_text(cotp_tree,
1211 offset + P_VAR_PART_EAK + i + 1, 1,
1212 "Parameter length: %u", length);
1213 proto_tree_add_text(cotp_tree,
1214 offset + P_VAR_PART_EAK + i + 2, length,
1215 "Parameter value: <not shown>");
1222 } /* is_LI_NORMAL_AK */
1228 } /* osi_decode_AK */
1230 static int osi_decode_EA(const u_char *pd, int offset,
1231 frame_data *fd, proto_tree *tree)
1233 proto_tree *cotp_tree;
1236 u_short checksum = 0;
1244 case LI_NORMAL_EA_WITH_CHECKSUM :
1245 tpdu_nr = pd[offset + P_TPDU_NR_234];
1246 code = pd[offset + P_VAR_PART_NDT];
1247 length = pd[offset + P_VAR_PART_NDT + 1];
1248 if (code != VP_CHECKSUM || length != 1)
1250 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
1252 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1253 tpdu_nr = pd[offset + P_TPDU_NR_234];
1255 case LI_EXTENDED_EA_WITH_CHECKSUM :
1256 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1257 code = pd[offset + P_VAR_PART_EDT];
1258 length = pd[offset + P_VAR_PART_EDT + 1];
1259 if (code != VP_CHECKSUM || length != 1)
1261 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
1263 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1264 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1266 default : /* bad TPDU */
1272 if (check_col(fd, COL_INFO))
1273 col_append_fstr(fd, COL_INFO,
1274 "EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1277 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1278 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1279 proto_tree_add_text(cotp_tree, offset, 1,
1280 "Length indicator: %u", li);
1281 proto_tree_add_text(cotp_tree, offset + 1, 1,
1282 "TPDU code: 0x%x (EA)", tpdu);
1283 proto_tree_add_text(cotp_tree, offset + 2, 2,
1284 "Destination reference: 0x%04x", dst_ref);
1287 case LI_NORMAL_EA_WITH_CHECKSUM :
1288 proto_tree_add_text(cotp_tree, offset + 4, 1,
1289 "Your TPDU number: 0x%02x", tpdu_nr);
1290 proto_tree_add_text(cotp_tree, offset + 5, 1,
1291 "Parameter code: 0x%02x (checksum)", code);
1292 proto_tree_add_text(cotp_tree, offset + 6, 1,
1293 "Parameter length: %u", length);
1294 proto_tree_add_text(cotp_tree, offset + 7, 2,
1295 "Checksum: 0x%04x", checksum);
1297 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1298 proto_tree_add_text(cotp_tree, offset + 4, 1,
1299 "Your TPDU number: 0x%02x", tpdu_nr);
1301 case LI_EXTENDED_EA_WITH_CHECKSUM :
1302 proto_tree_add_text(cotp_tree, offset + 4, 4,
1303 "Your TPDU number: 0x%08x", tpdu_nr);
1304 proto_tree_add_text(cotp_tree, offset + 8, 1,
1305 "Parameter code: 0x%02x (checksum)", code);
1306 proto_tree_add_text(cotp_tree, offset + 9, 1,
1307 "Parameter length: %u", length);
1308 proto_tree_add_text(cotp_tree, offset + 10, 2,
1309 "Checksum: 0x%04x", checksum);
1311 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1312 proto_tree_add_text(cotp_tree, offset + 4, 4,
1313 "Your TPDU number: 0x%08x", tpdu_nr);
1324 } /* osi_decode_EA */
1326 static int osi_decode_ER(const u_char *pd, int offset,
1327 frame_data *fd, proto_tree *tree)
1329 proto_tree *cotp_tree;
1336 switch(pd[offset + P_REJECT_ER]) {
1338 str = "Reason not specified";
1341 str = "Invalid parameter code";
1344 str = "Invalid TPDU type";
1347 str = "Invalid parameter value";
1355 if (check_col(fd, COL_INFO))
1356 col_append_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1359 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1360 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1361 proto_tree_add_text(cotp_tree, offset, 1,
1362 "Length indicator: %u", li);
1363 proto_tree_add_text(cotp_tree, offset + 1, 1,
1364 "TPDU code: 0x%x (ER)", tpdu);
1365 proto_tree_add_text(cotp_tree, offset + 2, 2,
1366 "Destination reference: 0x%04x", dst_ref);
1367 proto_tree_add_text(cotp_tree, offset + 4, 1,
1368 "Reject cause: %s", str);
1375 } /* osi_decode_ER */
1377 /* Returns TRUE if we found at least one valid COTP PDU, FALSE
1379 static gboolean dissect_cotp_internal(const u_char *pd, int offset,
1380 frame_data *fd, proto_tree *tree,
1381 gboolean uses_inactive_subset)
1383 gboolean first_tpdu = TRUE;
1385 gboolean found_cotp = FALSE;
1386 gboolean subdissector_found = FALSE;
1388 /* Initialize the COL_INFO field; each of the TPDUs will have its
1389 information appended. */
1390 if (check_col(fd, COL_INFO))
1391 col_add_str(fd, COL_INFO, "");
1393 while (IS_DATA_IN_FRAME(offset)) {
1395 if (check_col(fd, COL_INFO))
1396 col_append_str(fd, COL_INFO, ", ");
1398 if ((li = pd[offset + P_LI]) == 0) {
1399 if (check_col(fd, COL_INFO))
1400 col_append_str(fd, COL_INFO, "Length indicator is zero");
1402 dissect_data(pd, offset, fd, tree);
1405 if (!BYTES_ARE_IN_FRAME(offset, P_LI + li + 1)) {
1406 if (check_col(fd, COL_INFO))
1407 col_append_str(fd, COL_INFO, "Captured data in frame doesn't include entire frame");
1409 dissect_data(pd, offset, fd, tree);
1413 tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
1414 cdt = pd[offset + P_CDT] & 0x0F;
1415 dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
1420 new_offset = osi_decode_CC(pd, offset, fd, tree);
1423 new_offset = osi_decode_DR(pd, offset, fd, tree);
1426 if (osi_decode_DT(pd, offset, fd, tree, uses_inactive_subset))
1427 subdissector_found = TRUE;
1428 new_offset = pi.captured_len; /* DT PDUs run to the end of the packet */
1431 new_offset = osi_decode_ED(pd, offset, fd, tree);
1434 new_offset = osi_decode_RJ(pd, offset, fd, tree);
1437 new_offset = osi_decode_DC(pd, offset, fd, tree);
1440 new_offset = osi_decode_AK(pd, offset, fd, tree);
1443 new_offset = osi_decode_EA(pd, offset, fd, tree);
1446 new_offset = osi_decode_ER(pd, offset, fd, tree);
1449 if (first_tpdu && check_col(fd, COL_INFO))
1450 col_append_fstr(fd, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
1451 new_offset = -1; /* bad PDU type */
1455 if (new_offset == -1) { /* incorrect TPDU */
1457 dissect_data(pd, offset, fd, tree);
1462 /* Well, we found at least one valid COTP PDU, so I guess this
1464 if (!subdissector_found && check_col(fd, COL_PROTOCOL))
1465 col_add_str(fd, COL_PROTOCOL, "COTP");
1469 offset = new_offset;
1473 } /* dissect_cotp_internal */
1475 void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
1478 if (!dissect_cotp_internal(pd, offset, fd, tree, FALSE))
1479 dissect_data(pd, offset, fd, tree);
1484 * CLNP part / main entry point
1487 static void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
1491 struct clnp_header clnp;
1492 proto_tree *clnp_tree = NULL;
1494 u_char src_len, dst_len, nsel, opt_len = 0;
1495 u_int first_offset = offset;
1496 char flag_string[6+1];
1497 char *pdu_type_string;
1498 guint16 segment_length;
1499 guint16 segment_offset = 0;
1502 if (check_col(fd, COL_PROTOCOL))
1503 col_add_str(fd, COL_PROTOCOL, "CLNP");
1505 /* avoid alignment problem */
1506 memcpy(&clnp, &pd[offset], sizeof(clnp));
1508 if (clnp.cnf_proto_id == NLPID_NULL) {
1509 if (check_col(fd, COL_INFO))
1510 col_add_str(fd, COL_INFO, "Inactive subset");
1512 ti = proto_tree_add_item(tree, proto_clnp, offset, 1, NULL);
1513 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1514 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, offset, 1,
1518 dissect_cotp_internal(pd, offset+1, fd, tree, TRUE);
1522 if (!BYTES_ARE_IN_FRAME(offset, sizeof(clnp))) {
1523 dissect_data(pd, offset, fd, tree);
1527 /* return if version not known */
1528 if (clnp.cnf_vers != ISO8473_V1) {
1529 dissect_data(pd, offset, fd, tree);
1533 /* fixed part decoding */
1534 opt_len = clnp.cnf_hdr_len;
1536 segment_length = EXTRACT_SHORT(&clnp.cnf_seglen_msb);
1537 flag_string[0] = '\0';
1538 if (clnp.cnf_type & CNF_SEG_OK)
1539 strcat(flag_string, "S ");
1540 if (clnp.cnf_type & CNF_MORE_SEGS)
1541 strcat(flag_string, "M ");
1542 if (clnp.cnf_type & CNF_ERR_OK)
1543 strcat(flag_string, "E ");
1544 pdu_type_string = val_to_str(clnp.cnf_type & CNF_TYPE, npdu_type_vals,
1545 "Unknown (0x%02x)");
1547 ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL);
1548 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1549 proto_tree_add_item(clnp_tree, hf_clnp_id, offset, 1,
1551 proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1,
1553 proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1,
1555 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, offset + 3, 1,
1557 "Holding Time : %u (%u secs)",
1558 clnp.cnf_ttl, clnp.cnf_ttl / 2);
1559 proto_tree_add_uint_format(clnp_tree, hf_clnp_type, offset + 4, 1,
1561 "PDU Type : 0x%02x (%s%s)",
1565 proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2,
1567 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, offset + 7, 2,
1568 EXTRACT_SHORT(&clnp.cnf_cksum_msb),
1569 "Checksum : 0x%04x",
1570 EXTRACT_SHORT(&clnp.cnf_cksum_msb));
1571 opt_len -= 9; /* Fixed part of Hesder */
1574 /* stop here if header is not complete */
1576 if (!BYTES_ARE_IN_FRAME(offset, clnp.cnf_hdr_len)) {
1577 if (check_col(fd, COL_INFO))
1578 col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1579 dissect_data(pd, offset, fd, tree);
1585 offset += P_ADDRESS_PART;
1586 dst_len = pd[offset];
1587 nsel = pd[offset + dst_len];
1588 src_len = pd[offset + dst_len + 1];
1591 proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1,
1593 proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len,
1596 print_nsap_net(&pd[offset + 1], dst_len));
1597 proto_tree_add_item(clnp_tree, hf_clnp_src_length,
1598 offset + 1 + dst_len, 1, src_len);
1599 proto_tree_add_bytes_format(clnp_tree, hf_clnp_src,
1600 offset + dst_len + 2, src_len,
1601 &pd[offset + dst_len + 2],
1603 print_nsap_net(&pd[offset + dst_len + 2], src_len));
1605 opt_len -= dst_len + src_len +2;
1608 if (check_col(fd, COL_RES_NET_SRC))
1609 col_add_fstr(fd, COL_RES_NET_SRC, "%s",
1610 print_nsap_net(&pd[offset + dst_len + 2], src_len));
1611 if (check_col(fd, COL_RES_NET_DST))
1612 col_add_fstr(fd, COL_RES_NET_DST, "%s",
1613 print_nsap_net(&pd[offset + 1], dst_len));
1615 /* Segmentation Part */
1617 offset += dst_len + src_len + 2;
1619 if (clnp.cnf_type & CNF_SEG_OK) {
1620 struct clnp_segment seg; /* XXX - not used */
1621 memcpy(&seg, &pd[offset], sizeof(seg)); /* XXX - not used */
1623 segment_offset = EXTRACT_SHORT(&pd[offset + 2]);
1625 proto_tree_add_text(clnp_tree, offset, 2,
1626 "Data unit identifier: %06u",
1627 EXTRACT_SHORT(&pd[offset]));
1628 proto_tree_add_text(clnp_tree, offset + 2 , 2,
1629 "Segment offset : %6u",
1631 proto_tree_add_text(clnp_tree, offset + 4 , 2,
1632 "Total length : %6u",
1633 EXTRACT_SHORT(&pd[offset + 4]));
1641 /* To do : decode options */
1643 proto_tree_add_text(clnp_tree, offset,
1644 clnp.cnf_hdr_len + first_offset - offset,
1645 "Options/Data: <not shown>");
1647 /* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/
1649 dissect_osi_options( 0xff,
1651 pd, offset, fd, clnp_tree );
1654 /* Length of CLNP datagram plus headers above it. */
1655 len = segment_length + first_offset;
1657 /* Set the payload and captured-payload lengths to the minima of (the
1658 datagram length plus the length of the headers above it) and the
1662 if (pi.captured_len > len)
1663 pi.captured_len = len;
1665 offset = first_offset + clnp.cnf_hdr_len;
1667 /* For now, dissect the payload of segments other than the initial
1668 segment as data, rather than handing them off to the transport
1669 protocol, just as we do with fragments other than the first
1670 fragment in a fragmented IP datagram; in the future, we will
1671 probably reassemble fragments for IP, and may reassemble segments
1673 if ((clnp.cnf_type & CNF_SEG_OK) && segment_offset != 0) {
1674 if (check_col(fd, COL_INFO))
1675 col_add_fstr(fd, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
1676 pdu_type_string, flag_string, segment_offset);
1677 dissect_data(pd, offset, fd, tree);
1681 if (IS_DATA_IN_FRAME(offset)) {
1682 switch (clnp.cnf_type & CNF_TYPE) {
1686 /* Continue with COTP if any data.
1687 XXX - if this isn't the first Derived PDU of a segmented Initial
1690 if (nsel == NSEL_TP) { /* just guessing here - valid for DECNet-OSI */
1691 if (dissect_cotp_internal(pd, offset, fd, tree, FALSE))
1692 return; /* yes, it appears to be COTP */
1697 /* The payload is the header and "none, some, or all of the data
1698 part of the discarded PDU", i.e. it's like an ICMP error;
1699 just as we don't yet trust ourselves to be able to dissect
1700 the payload of an ICMP error packet, we don't yet trust
1701 ourselves to dissect the payload of a CLNP ER packet. */
1706 /* XXX - dissect this */
1710 if (check_col(fd, COL_INFO))
1711 col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1712 dissect_data(pd, offset, fd, tree);
1714 } /* dissect_clnp */
1717 void proto_register_clnp(void)
1719 static hf_register_info hf[] = {
1721 { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
1722 VALS(nlpid_vals), 0x0, "" }},
1725 { "HDR Length ", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1728 { "Version ", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1731 { "Holding Time ", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1734 { "PDU Type ", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1736 { &hf_clnp_pdu_length,
1737 { "PDU length ", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
1739 { &hf_clnp_checksum,
1740 { "Checksum ", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
1742 { &hf_clnp_dest_length,
1743 { "DAL ", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1746 { " DA ", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }},
1748 { &hf_clnp_src_length,
1749 { "SAL ", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }},
1752 { " SA ", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }},
1754 static gint *ett[] = {
1758 proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "clnp");
1759 proto_register_field_array(proto_clnp, hf, array_length(hf));
1760 proto_register_subtree_array(ett, array_length(ett));
1763 void proto_register_cotp(void)
1765 /* static hf_register_info hf[] = {
1767 { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
1769 static gint *ett[] = {
1773 proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "cotp");
1774 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
1775 proto_register_subtree_array(ett, array_length(ett));
1777 /* subdissector code */
1778 register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
1782 proto_reg_handoff_clnp(void)
1784 dissector_add("osinl", NLPID_ISO8473_CLNP, dissect_clnp);
1785 dissector_add("osinl", NLPID_NULL, dissect_clnp); /* Inactive subset */