2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-osi.c,v 1.28 2000/04/15 07:26:57 guy Exp $
5 * Laurent Deniel <deniel@worldnet.fr>
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
9 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 * - add other network protocols (ES,IS-IS)
30 * - add NSAP decoding & resolution
31 * - complete CLNP decoding (options)
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
48 #include "packet-isis.h"
49 #include "packet-h1.h"
52 /* protocols and fields */
54 static int proto_clnp = -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;
68 static gint ett_clnp = -1;
70 static int proto_cotp = -1;
72 static gint ett_cotp = -1;
75 * ISO8473 OSI CLNP definition (see RFC994)
77 * _________________________________
79 * |_________________________________|
81 * |_________________________________|
82 * | Segmentation Part (optional) |
83 * |_________________________________|
84 * | Options Part (optional) |
85 * |_________________________________|
87 * |_________________________________|
90 #define ISO8473_V1 0x01 /* CLNP version 1 */
95 u_char cnf_proto_id; /* network layer protocol identifier */
96 u_char cnf_hdr_len; /* length indicator (octets) */
97 u_char cnf_vers; /* version/protocol identifier extension */
98 u_char cnf_ttl; /* lifetime (500 milliseconds) */
99 u_char cnf_type; /* type code */
100 u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
101 u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
102 u_char cnf_cksum_msb; /* checksum high byte */
103 u_char cnf_cksum_lsb; /* checksum low byte */
106 #define CNF_TYPE 0x1f
107 #define CNF_ERR_OK 0x20
108 #define CNF_MORE_SEGS 0x40
109 #define CNF_SEG_OK 0x80
114 #define ERQ_NPDU 0x1E
115 #define ERP_NPDU 0x1F
117 static const value_string npdu_type_vals[] = {
128 #define P_ADDRESS_PART 9
130 /* Segmentation part */
132 struct clnp_segment {
133 u_short cng_id; /* data unit identifier */
134 u_short cng_off; /* segment offset */
135 u_short cng_tot_len; /* total length */
140 #define NSEL_NET 0x00
145 * ISO8073 OSI COTP definition (see RFC905)
148 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
150 /* TPDU definition */
170 #define P_TPDU_NR_0_1 2
171 #define P_TPDU_NR_234 4
172 #define P_VAR_PART_NDT 5
173 #define P_VAR_PART_EDT 8
174 #define P_VAR_PART_NAK 5
175 #define P_VAR_PART_CC 7
176 #define P_VAR_PART_EAK 10
177 #define P_VAR_PART_DC 6
178 #define P_VAR_PART_DR 7
179 #define P_CDT_IN_AK 8
180 #define P_CDT_IN_RJ 8
181 #define P_REJECT_ER 4
182 #define P_REASON_IN_DR 6
183 #define P_CLASS_OPTION 6
185 /* TPDU length indicator */
187 #define LI_NORMAL_DT_CLASS_01 2
188 #define LI_NORMAL_DT_WITH_CHECKSUM 8
189 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
190 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
191 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
192 #define LI_NORMAL_EA_WITH_CHECKSUM 8
193 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
194 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
195 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
196 #define LI_NORMAL_RJ 4
197 #define LI_EXTENDED_RJ 9
203 #define LI_DC_WITH_CHECKSUM 9
204 #define LI_DC_WITHOUT_CHECKSUM 5
205 #define is_LI_NORMAL_AK(p) ( p & 0x01 )
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
228 #define EXTRACT_SHORT(p) pntohs(p)
229 #define EXTRACT_LONG(p) pntohl(p)
231 /* global variables */
233 static u_char li, tpdu, cdt; /* common fields */
234 static u_short dst_ref;
236 /* function definitions */
238 static int osi_decode_DR(const u_char *pd, int offset,
239 frame_data *fd, proto_tree *tree)
241 proto_tree *cotp_tree;
250 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
251 reason = pd[offset + P_REASON_IN_DR];
254 case (128+0): str = "Normal Disconnect"; break;
255 case (128+1): str = "Remote transport entity congestion"; break;
256 case (128+2): str = "Connection negotiation failed"; break;
257 case (128+3): str = "Duplicate source reference"; break;
258 case (128+4): str = "Mismatched references"; break;
259 case (128+5): str = "Protocol error"; break;
260 case (128+7): str = "Reference overflow"; break;
261 case (128+8): str = "Connection requestion refused"; break;
262 case (128+10):str = "Header or parameter length invalid"; break;
263 case (0): str = "Reason not specified"; break;
264 case (1): str = "Congestion at TSAP"; break;
265 case (2): str = "Session entity not attached to TSAP"; break;
266 case (3): str = "Address unknown"; break;
272 if (check_col(fd, COL_INFO))
273 col_append_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
277 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
278 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
279 proto_tree_add_text(cotp_tree, offset, 1,
280 "Length indicator: %d", li);
281 proto_tree_add_text(cotp_tree, offset + 1, 1,
282 "TPDU code: 0x%x (DR)", tpdu);
283 proto_tree_add_text(cotp_tree, offset + 2, 2,
284 "Destination reference: 0x%04x", dst_ref);
285 proto_tree_add_text(cotp_tree, offset + 4, 2,
286 "Source reference: 0x%04x", src_ref);
287 proto_tree_add_text(cotp_tree, offset + 6, 1,
292 dissect_data(pd, offset, fd, tree);
294 return pi.captured_len; /* we dissected all of the containing PDU */
296 } /* osi_decode_DR */
298 static int osi_decode_DT(const u_char *pd, int offset,
299 frame_data *fd, proto_tree *tree,
300 gboolean uses_inactive_subset)
302 proto_tree *cotp_tree;
305 u_short checksum = 0;
306 u_char code = 0, length = 0;
310 case LI_NORMAL_DT_WITH_CHECKSUM :
311 tpdu_nr = pd[offset + P_TPDU_NR_234];
312 if ( tpdu_nr & 0x80 )
313 tpdu_nr = tpdu_nr & 0x7F;
316 code = pd[offset + P_VAR_PART_NDT];
317 if (code == VP_CHECKSUM)
318 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
322 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
323 tpdu_nr = pd[offset + P_TPDU_NR_234];
324 if ( tpdu_nr & 0x80 )
325 tpdu_nr = tpdu_nr & 0x7F;
329 case LI_EXTENDED_DT_WITH_CHECKSUM :
330 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
331 if ( tpdu_nr & 0x80000000 )
332 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
335 code = pd[offset + P_VAR_PART_EDT];
336 if (code == VP_CHECKSUM)
337 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
341 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
342 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
343 if ( tpdu_nr & 0x80000000 )
344 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
348 case LI_NORMAL_DT_CLASS_01 :
349 tpdu_nr = pd[offset + P_TPDU_NR_0_1];
350 if ( tpdu_nr & 0x80 )
351 tpdu_nr = tpdu_nr & 0x7F;
355 default : /* bad TPDU */
361 if (check_col(fd, COL_INFO))
362 col_append_fstr(fd, COL_INFO, "DT TPDU (%d) dst-ref: 0x%04x %s",
365 (fragment)? "(fragment)" : "");
368 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
369 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
370 proto_tree_add_text(cotp_tree, offset, 1,
371 "Length indicator: %d", li);
372 proto_tree_add_text(cotp_tree, offset + 1, 1,
373 "TPDU code: 0x%x (DT)", tpdu);
375 if (li != LI_NORMAL_DT_CLASS_01)
376 proto_tree_add_text(cotp_tree, offset + 2, 2,
377 "Destination reference: 0x%04x", dst_ref);
380 case LI_NORMAL_DT_WITH_CHECKSUM :
381 proto_tree_add_text(cotp_tree, offset + 4, 1,
382 "TPDU number: 0x%02x (%s)",
384 (fragment)? "fragment":"complete");
385 proto_tree_add_text(cotp_tree,
386 offset + P_VAR_PART_NDT, 1,
387 "Parameter code: 0x%02x (checksum)", code);
388 proto_tree_add_text(cotp_tree,
389 offset + P_VAR_PART_NDT + 1, 1,
390 "Parameter length: %u", length);
391 proto_tree_add_text(cotp_tree,
392 offset + P_VAR_PART_NDT + 2, length,
393 "Checksum: 0x%04x", checksum);
395 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
396 proto_tree_add_text(cotp_tree, offset + 4, 1,
397 "TPDU number: 0x%02x (%s)",
399 (fragment)? "fragment":"complete");
401 case LI_EXTENDED_DT_WITH_CHECKSUM :
402 proto_tree_add_text(cotp_tree, offset + 4, 4,
403 "TPDU number: 0x%08x (%s)",
405 (fragment)? "fragment":"complete");
406 proto_tree_add_text(cotp_tree,
407 offset + P_VAR_PART_EDT, 1,
408 "Parameter code: 0x%02x (checksum)", code);
409 proto_tree_add_text(cotp_tree,
410 offset + P_VAR_PART_EDT + 1, 1,
411 "Parameter length: %u", length);
412 proto_tree_add_text(cotp_tree,
413 offset + P_VAR_PART_EDT + 2, length,
414 "Checksum: 0x%04x", checksum);
416 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
417 proto_tree_add_text(cotp_tree, offset + 4, 4,
418 "TPDU number: 0x%08x (%s)",
420 (fragment)? "fragment":"complete");
422 case LI_NORMAL_DT_CLASS_01 :
423 proto_tree_add_text(cotp_tree, offset + 2, 1,
424 "TPDU number: 0x%02x (%s)",
426 (fragment)? "fragment":"complete");
432 if (uses_inactive_subset){
433 dissect_h1(pd, offset, fd, tree);
436 dissect_data(pd, offset, fd, tree);
439 return pi.captured_len; /* we dissected all of the containing PDU */
441 } /* osi_decode_DT */
443 static int osi_decode_ED(const u_char *pd, int offset,
444 frame_data *fd, proto_tree *tree)
446 proto_tree *cotp_tree;
449 u_short checksum = 0;
450 u_char code = 0, length = 0;
452 /* ED TPDUs are never fragmented */
455 case LI_NORMAL_DT_WITH_CHECKSUM :
456 tpdu_nr = pd[offset + P_TPDU_NR_234];
457 if ( tpdu_nr & 0x80 )
458 tpdu_nr = tpdu_nr & 0x7F;
461 code = pd[offset + P_VAR_PART_NDT];
462 length = pd[offset + P_VAR_PART_NDT + 1];
463 if (code == VP_CHECKSUM)
464 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
468 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
469 tpdu_nr = pd[offset + P_TPDU_NR_234];
470 if ( tpdu_nr & 0x80 )
471 tpdu_nr = tpdu_nr & 0x7F;
475 case LI_EXTENDED_DT_WITH_CHECKSUM :
476 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
477 if ( tpdu_nr & 0x80000000 )
478 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
481 code = pd[offset + P_VAR_PART_EDT];
482 length = pd[offset + P_VAR_PART_EDT + 1];
483 if (code == VP_CHECKSUM)
484 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
488 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
489 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
490 if ( tpdu_nr & 0x80000000 )
491 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
495 default : /* bad TPDU */
501 if (check_col(fd, COL_INFO))
502 col_append_fstr(fd, COL_INFO, "ED TPDU (%d) dst-ref: 0x%04x",
506 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
507 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
508 proto_tree_add_text(cotp_tree, offset, 1,
509 "Length indicator: %d", li);
510 proto_tree_add_text(cotp_tree, offset + 1, 1,
511 "TPDU code: 0x%x (ED)", tpdu);
512 proto_tree_add_text(cotp_tree, offset + 2, 2,
513 "Destination reference: 0x%04x", dst_ref);
516 case LI_NORMAL_DT_WITH_CHECKSUM :
517 proto_tree_add_text(cotp_tree, offset + 4, 1,
518 "TPDU number: 0x%02x", tpdu_nr);
519 proto_tree_add_text(cotp_tree,
520 offset + P_VAR_PART_NDT, 1,
521 "Parameter code: 0x%02x (checksum)", code);
522 proto_tree_add_text(cotp_tree,
523 offset + P_VAR_PART_NDT + 1, 1,
524 "Parameter length: %u", length);
525 proto_tree_add_text(cotp_tree,
526 offset + P_VAR_PART_NDT + 2, length,
527 "Checksum: 0x%04x", checksum);
529 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
530 proto_tree_add_text(cotp_tree, offset + 4, 1,
531 "TPDU number: 0x%02x", tpdu_nr);
533 case LI_EXTENDED_DT_WITH_CHECKSUM :
534 proto_tree_add_text(cotp_tree, offset + 4, 4,
535 "TPDU number: 0x%02x", tpdu_nr);
536 proto_tree_add_text(cotp_tree,
537 offset + P_VAR_PART_EDT, 1,
538 "Parameter code: 0x%02x (checksum)", code);
539 proto_tree_add_text(cotp_tree,
540 offset + P_VAR_PART_EDT + 1, 1,
541 "Parameter length: %u", length);
542 proto_tree_add_text(cotp_tree,
543 offset + P_VAR_PART_EDT + 2, length,
544 "Checksum: 0x%04x", checksum);
546 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
547 proto_tree_add_text(cotp_tree, offset + 4, 4,
548 "TPDU number: 0x%02x", tpdu_nr);
554 dissect_data(pd, offset, fd, tree);
556 return pi.captured_len; /* we dissected all of the containing PDU */
558 } /* osi_decode_ED */
560 static int osi_decode_RJ(const u_char *pd, int offset,
561 frame_data *fd, proto_tree *tree)
563 proto_tree *cotp_tree;
570 tpdu_nr = pd[offset + P_TPDU_NR_234];
572 case LI_EXTENDED_RJ :
573 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
574 credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
582 if (check_col(fd, COL_INFO))
583 col_append_fstr(fd, COL_INFO, "RJ TPDU (%d) dst-ref: 0x%04x",
587 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
588 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
589 proto_tree_add_text(cotp_tree, offset, 1,
590 "Length indicator: %d", li);
591 proto_tree_add_text(cotp_tree, offset + 1, 1,
592 "TPDU code: 0x%x (RJ)", tpdu);
593 if (li == LI_NORMAL_RJ)
594 proto_tree_add_text(cotp_tree, offset + 1, 1,
596 proto_tree_add_text(cotp_tree, offset + 2, 2,
597 "Destination reference: 0x%04x", dst_ref);
598 if (li == LI_NORMAL_RJ)
599 proto_tree_add_text(cotp_tree, offset + 4, 1,
600 "Your TPDU number: 0x%02x", tpdu_nr);
602 proto_tree_add_text(cotp_tree, offset + 4, 4,
603 "Your TPDU number: 0x%02x", tpdu_nr);
604 proto_tree_add_text(cotp_tree, offset + 8, 2,
605 "Credit: 0x%02x", credit);
613 } /* osi_decode_RJ */
615 #define MAX_TSAP_LEN 32
617 static gchar *print_tsap(const u_char *tsap, int length)
620 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
623 gboolean allprintable;
626 if (cur == &str[0][0]) {
628 } else if (cur == &str[1][0]) {
636 if (length <= 0 || length > MAX_TSAP_LEN)
637 sprintf(cur, "<unsupported TSAP length>");
640 for (i=0;i<length;i++) {
641 if (!isprint(tsap[i])) { /* if any byte is not printable */
642 allprintable=FALSE; /* switch to hexdump */
649 while (length != 0) {
651 sprintf(tmp, "%c", *tsap ++);
653 sprintf(tmp, "%02x", *tsap ++);
662 static int osi_decode_CC(const u_char *pd, int offset,
663 frame_data *fd, proto_tree *tree)
666 /* CC & CR decoding in the same function */
668 proto_tree *cotp_tree = NULL;
670 u_short src_ref, checksum;
671 u_char class_option, code, length;
674 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
675 class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
676 if (class_option > 4)
679 if (check_col(fd, COL_INFO))
680 col_append_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
681 (tpdu == CR_TPDU) ? "CR" : "CC",
686 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
687 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
688 proto_tree_add_text(cotp_tree, offset, 1,
689 "Length indicator: %d", li);
690 proto_tree_add_text(cotp_tree, offset + 1, 1,
691 "TPDU code: 0x%x (%s)", tpdu,
692 (tpdu == CR_TPDU) ? "CR" : "CC");
693 proto_tree_add_text(cotp_tree, offset + 2, 2,
694 "Destination reference: 0x%04x", dst_ref);
695 proto_tree_add_text(cotp_tree, offset + 4, 2,
696 "Source reference: 0x%04x", src_ref);
697 proto_tree_add_text(cotp_tree, offset + 6, 1,
698 "Class option: 0x%02x", class_option);
702 while(li > P_VAR_PART_CC + i - 1) {
705 u_short s, s1,s2,s3,s4;
708 switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
710 length = pd[offset + P_VAR_PART_CC + i + 1];
711 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
712 proto_tree_add_text(cotp_tree,
713 offset + P_VAR_PART_CC + i, 1,
714 "Parameter code: 0x%02x (checksum)", code);
715 proto_tree_add_text(cotp_tree,
716 offset + P_VAR_PART_CC + i + 1, 1,
717 "Parameter length: %u", length);
718 proto_tree_add_text(cotp_tree,
719 offset + P_VAR_PART_CC + i + 2, length,
720 "Checksum: 0x%04x", checksum);
724 length = pd[offset + P_VAR_PART_CC + i + 1];
725 proto_tree_add_text(cotp_tree,
726 offset + P_VAR_PART_CC + i, 1,
727 "Parameter code: 0x%02x (src-tsap)", code);
728 proto_tree_add_text(cotp_tree,
729 offset + P_VAR_PART_CC + i + 1, 1,
730 "Parameter length: %u", length);
731 proto_tree_add_text(cotp_tree,
732 offset + P_VAR_PART_CC + i + 2, length,
734 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
739 length = pd[offset + P_VAR_PART_CC + i + 1];
740 proto_tree_add_text(cotp_tree,
741 offset + P_VAR_PART_CC + i, 1,
742 "Parameter code: 0x%02x (dst-tsap)", code);
743 proto_tree_add_text(cotp_tree,
744 offset + P_VAR_PART_CC + i + 1, 1,
745 "Parameter length: %u", length);
746 proto_tree_add_text(cotp_tree,
747 offset + P_VAR_PART_CC + i + 2, length,
749 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
754 length = pd[offset + P_VAR_PART_CC + i + 1];
755 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
756 proto_tree_add_text(cotp_tree,
757 offset + P_VAR_PART_CC + i, 1,
758 "Parameter code: 0x%02x (tpdu-size)", code);
759 proto_tree_add_text(cotp_tree,
760 offset + P_VAR_PART_CC + i + 1, 1,
761 "Parameter length: %u", length);
762 proto_tree_add_text(cotp_tree,
763 offset + P_VAR_PART_CC + i + 2, length,
764 "TPDU size: %u", 2 << c1);
768 length = pd[offset + P_VAR_PART_CC + i + 1];
769 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
770 proto_tree_add_text(cotp_tree,
771 offset + P_VAR_PART_CC + i, 1,
772 "Parameter code: 0x%02x (options)", code);
773 proto_tree_add_text(cotp_tree,
774 offset + P_VAR_PART_CC + i + 1, 1,
775 "Parameter length: %u", length);
776 if (class_option == 1) {
778 proto_tree_add_text(cotp_tree,
779 offset + P_VAR_PART_CC + i + 2, 1,
780 "Use of network expedited data");
782 proto_tree_add_text(cotp_tree,
783 offset + P_VAR_PART_CC + i + 2, 1,
784 "Non use of network expedited data");
786 proto_tree_add_text(cotp_tree,
787 offset + P_VAR_PART_CC + i + 2, 1,
788 "Use of Receipt confirmation");
790 proto_tree_add_text(cotp_tree,
791 offset + P_VAR_PART_CC + i + 2, 1,
792 "Use of explicit AK variant");
793 } else if (class_option == 4) {
795 proto_tree_add_text(cotp_tree,
796 offset + P_VAR_PART_CC + i + 2, 1,
797 "Use 16 bit checksum ");
799 proto_tree_add_text(cotp_tree,
800 offset + P_VAR_PART_CC + i + 2, 1,
801 "Non-use 16 bit checksum in class 4");
804 proto_tree_add_text(cotp_tree,
805 offset + P_VAR_PART_CC + i + 2, 1,
806 "Use of transport expedited data transfer\n");
808 proto_tree_add_text(cotp_tree,
809 offset + P_VAR_PART_CC + i + 2, 1,
810 "Non-use of transport expedited data transfer");
814 length = pd[offset + P_VAR_PART_CC + i + 1];
815 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
816 proto_tree_add_text(cotp_tree,
817 offset + P_VAR_PART_CC + i, 1,
818 "Parameter code: 0x%02x (ack time)", code);
819 proto_tree_add_text(cotp_tree,
820 offset + P_VAR_PART_CC + i + 1, 1,
821 "Parameter length: %u", length);
822 proto_tree_add_text(cotp_tree,
823 offset + P_VAR_PART_CC + i + 2, length,
824 "Ack time (ms): %u", s);
828 length = pd[offset + P_VAR_PART_CC + i + 1];
829 t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
830 t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
831 t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
832 t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
833 proto_tree_add_text(cotp_tree,
834 offset + P_VAR_PART_CC + i, 1,
835 "Parameter code: 0x%02x (throughput)", code);
836 proto_tree_add_text(cotp_tree,
837 offset + P_VAR_PART_CC + i + 1, 1,
838 "Parameter length: %u", length);
839 proto_tree_add_text(cotp_tree,
840 offset + P_VAR_PART_CC + i + 2, 4,
841 "Target value / calling-called: %u o/s", t1);
842 proto_tree_add_text(cotp_tree,
843 offset + P_VAR_PART_CC + i + 6, 4,
844 "Minimum / calling-called: %u o/s", t2);
845 proto_tree_add_text(cotp_tree,
846 offset + P_VAR_PART_CC + i + 10, 4,
847 "Target value / called-calling: %u o/s", t3);
848 proto_tree_add_text(cotp_tree,
849 offset + P_VAR_PART_CC + i + 14, 4,
850 "Minimum / called-calling: %u o/s", t4);
853 case VP_TRANSIT_DEL :
854 length = pd[offset + P_VAR_PART_CC + i + 1];
855 s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
856 s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
857 s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
858 s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
859 proto_tree_add_text(cotp_tree,
860 offset + P_VAR_PART_CC + i, 1,
861 "Parameter code: 0x%02x (transit delay)", code);
862 proto_tree_add_text(cotp_tree,
863 offset + P_VAR_PART_CC + i + 1, 1,
864 "Parameter length: %u", length);
865 proto_tree_add_text(cotp_tree,
866 offset + P_VAR_PART_CC + i + 2, 2,
867 "Target value / calling-called: %u ms", s1);
868 proto_tree_add_text(cotp_tree,
869 offset + P_VAR_PART_CC + i + 4, 2,
870 "Minimum / calling-called: %u ms", s2);
871 proto_tree_add_text(cotp_tree,
872 offset + P_VAR_PART_CC + i + 6, 2,
873 "Target value / called-calling: %u ms", s3);
874 proto_tree_add_text(cotp_tree,
875 offset + P_VAR_PART_CC + i + 8, 2,
876 "Minimum / called-calling: %u ms", s4);
880 length = pd[offset + P_VAR_PART_CC + i + 1];
881 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
882 proto_tree_add_text(cotp_tree,
883 offset + P_VAR_PART_CC + i, 1,
884 "Parameter code: 0x%02x (priority)", code);
885 proto_tree_add_text(cotp_tree,
886 offset + P_VAR_PART_CC + i + 1, 1,
887 "Parameter length: %u", length);
888 proto_tree_add_text(cotp_tree,
889 offset + P_VAR_PART_CC + i + 2, length,
895 length = pd[offset + P_VAR_PART_CC + i + 1];
896 c1 = pd[offset + P_VAR_PART_CC + i + 2];
897 proto_tree_add_text(cotp_tree,
898 offset + P_VAR_PART_CC + i, 1,
899 "Parameter code: 0x%02x (version)", code);
900 proto_tree_add_text(cotp_tree,
901 offset + P_VAR_PART_CC + i + 1, 1,
902 "Parameter length: %u", length);
903 proto_tree_add_text(cotp_tree,
904 offset + P_VAR_PART_CC + i + 2, length,
909 case VP_REASSIGNMENT: /* todo */
912 case VP_PROTO_CLASS :
913 default : /* no decoding */
914 length = pd[offset + P_VAR_PART_CC + i + 1];
915 proto_tree_add_text(cotp_tree,
916 offset + P_VAR_PART_CC + i + 0, 1,
917 "Parameter code: 0x%02x", code);
918 proto_tree_add_text(cotp_tree,
919 offset + P_VAR_PART_CC + i + 1, 1,
920 "Parameter length: %u", length);
921 proto_tree_add_text(cotp_tree,
922 offset + P_VAR_PART_CC + i + 2, length,
923 "Parameter value: <not shown>");
930 dissect_data(pd, offset, fd, tree);
932 return pi.captured_len; /* we dissected all of the containing PDU */
934 } /* osi_decode_CC */
936 static int osi_decode_DC(const u_char *pd, int offset,
937 frame_data *fd, proto_tree *tree)
939 proto_tree *cotp_tree;
941 u_short src_ref, checksum = 0;
942 u_char length = 0, code = 0;
947 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
950 case LI_DC_WITHOUT_CHECKSUM :
952 case LI_DC_WITH_CHECKSUM :
953 if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
955 length = pd[offset + P_VAR_PART_DC + 1];
956 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
964 if (check_col(fd, COL_INFO))
965 col_append_fstr(fd, COL_INFO, "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
970 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
971 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
972 proto_tree_add_text(cotp_tree, offset, 1,
973 "Length indicator: %d", li);
974 proto_tree_add_text(cotp_tree, offset + 1, 1,
975 "TPDU code: 0x%x (DC)", tpdu);
976 proto_tree_add_text(cotp_tree, offset + 2, 2,
977 "Destination reference: 0x%04x", dst_ref);
978 proto_tree_add_text(cotp_tree, offset + 4, 2,
979 "Source reference: 0x%04x", src_ref);
981 proto_tree_add_text(cotp_tree,
982 offset + P_VAR_PART_DC + 0, 1,
983 "Parameter code: 0x%02x (checksum)", code);
984 proto_tree_add_text(cotp_tree,
985 offset + P_VAR_PART_DC + 1, 1,
986 "Parameter length: %u", length);
987 proto_tree_add_text(cotp_tree,
988 offset + P_VAR_PART_DC + 2, 2,
989 "Checksum: 0x%04x", checksum);
997 } /* osi_decode_DC */
999 static int osi_decode_AK(const u_char *pd, int offset,
1000 frame_data *fd, proto_tree *tree)
1002 proto_tree *cotp_tree = NULL;
1004 u_int tpdu_nr,i =0, r_lower_window_edge ;
1006 u_short checksum, seq_nr, r_seq_nr, r_cdt;
1007 u_char code, length;
1012 if (!is_LI_NORMAL_AK(li)) {
1013 tpdu_nr = pd[offset + P_TPDU_NR_234];
1015 if (check_col(fd, COL_INFO))
1016 col_append_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
1020 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1021 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1022 proto_tree_add_text(cotp_tree, offset, 1,
1023 "Length indicator: %d", li);
1024 proto_tree_add_text(cotp_tree, offset + 1, 1,
1025 "TPDU code: 0x%x (AK)", tpdu);
1026 proto_tree_add_text(cotp_tree, offset + 1, 1,
1028 proto_tree_add_text(cotp_tree, offset + 2, 2,
1029 "Destination reference: 0x%04x", dst_ref);
1030 proto_tree_add_text(cotp_tree, offset + 4, 1,
1031 "Your TPDU number: 0x%02x", tpdu_nr);
1034 while(li > P_VAR_PART_NAK + i - 1) {
1035 switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
1037 length = pd[offset + P_VAR_PART_NAK + i + 1];
1038 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1040 proto_tree_add_text(cotp_tree,
1041 offset + P_VAR_PART_NAK + i + 0, 1,
1042 "Parameter code: 0x%02x (checksum)", code);
1043 proto_tree_add_text(cotp_tree,
1044 offset + P_VAR_PART_NAK + i + 1, 1,
1045 "Parameter length: %u", length);
1046 proto_tree_add_text(cotp_tree,
1047 offset + P_VAR_PART_NAK + i + 2, 2,
1048 "Checksum: 0x%04x", checksum);
1053 length = pd[offset + P_VAR_PART_NAK + i + 1];
1054 r_lower_window_edge =
1055 EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
1056 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
1057 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
1059 proto_tree_add_text(cotp_tree,
1060 offset + P_VAR_PART_NAK + i + 0, 1,
1061 "Parameter code: 0x%02x (flow control)",
1063 proto_tree_add_text(cotp_tree,
1064 offset + P_VAR_PART_NAK + i + 1, 1,
1065 "Parameter length: %u", length);
1066 proto_tree_add_text(cotp_tree,
1067 offset + P_VAR_PART_NAK + i + 2, 4,
1068 "Lower window edge: 0x%08x",
1069 r_lower_window_edge);
1070 proto_tree_add_text(cotp_tree,
1071 offset + P_VAR_PART_NAK + i + 6, 2,
1072 "Sequence number: 0x%04x",
1074 proto_tree_add_text(cotp_tree,
1075 offset + P_VAR_PART_NAK + i + 8, 2,
1082 length = pd[offset + P_VAR_PART_NAK + i + 1];
1083 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1085 proto_tree_add_text(cotp_tree,
1086 offset + P_VAR_PART_NAK + i + 0, 1,
1087 "Parameter code: 0x%02x (seq number)", code);
1088 proto_tree_add_text(cotp_tree,
1089 offset + P_VAR_PART_NAK + i + 1, 1,
1090 "Parameter length: %u", length);
1091 proto_tree_add_text(cotp_tree,
1092 offset + P_VAR_PART_NAK + i + 2, 2,
1093 "Sequence number: 0x%04x", seq_nr);
1098 length = pd[offset + P_VAR_PART_NAK + i + 1];
1100 proto_tree_add_text(cotp_tree,
1101 offset + P_VAR_PART_NAK + i + 0, 1,
1102 "Parameter code: 0x%02x (unknown)", code);
1103 proto_tree_add_text(cotp_tree,
1104 offset + P_VAR_PART_NAK + i + 1, 1,
1105 "Parameter length: %u", length);
1106 proto_tree_add_text(cotp_tree,
1107 offset + P_VAR_PART_NAK + i + 2, length,
1108 "Parameter value: <not shown>");
1114 } else { /* extended format */
1116 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1117 cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
1119 if (check_col(fd, COL_INFO))
1120 col_append_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
1124 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1125 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1126 proto_tree_add_text(cotp_tree, offset, 1,
1127 "Length indicator: %d", li);
1128 proto_tree_add_text(cotp_tree, offset + 1, 1,
1129 "TPDU code: 0x%x (AK)", tpdu);
1130 proto_tree_add_text(cotp_tree, offset + 2, 2,
1131 "Destination reference: 0x%04x", dst_ref);
1132 proto_tree_add_text(cotp_tree, offset + 4, 4,
1133 "Your TPDU number: 0x%08x", tpdu_nr);
1134 proto_tree_add_text(cotp_tree, offset + 8, 2,
1135 "Credit: 0x%04x", cdt_in_ak);
1138 while(li > P_VAR_PART_EAK + i - 1) {
1139 switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
1141 length = pd[offset + P_VAR_PART_EAK + i + 1];
1142 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1144 proto_tree_add_text(cotp_tree,
1145 offset + P_VAR_PART_EAK + i + 0, 1,
1146 "Parameter code: 0x%02x (checksum)", code);
1147 proto_tree_add_text(cotp_tree,
1148 offset + P_VAR_PART_EAK + i + 1, 1,
1149 "Parameter length: %u", length);
1150 proto_tree_add_text(cotp_tree,
1151 offset + P_VAR_PART_EAK + i + 2, 2,
1152 "Checksum: 0x%04x", checksum);
1157 length = pd[offset + P_VAR_PART_EAK + i + 1];
1158 r_lower_window_edge =
1159 EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
1160 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
1161 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
1163 proto_tree_add_text(cotp_tree,
1164 offset + P_VAR_PART_EAK + i + 0, 1,
1165 "Parameter code: 0x%02x (flow control)",
1167 proto_tree_add_text(cotp_tree,
1168 offset + P_VAR_PART_EAK + i + 1, 1,
1169 "Parameter length: %u", length);
1170 proto_tree_add_text(cotp_tree,
1171 offset + P_VAR_PART_EAK + i + 2, 4,
1172 "Lower window edge: 0x%08x",
1173 r_lower_window_edge);
1174 proto_tree_add_text(cotp_tree,
1175 offset + P_VAR_PART_EAK + i + 6, 2,
1176 "Sequence number: 0x%04x",
1178 proto_tree_add_text(cotp_tree,
1179 offset + P_VAR_PART_EAK + i + 8, 2,
1186 length = pd[offset + P_VAR_PART_EAK + i + 1];
1187 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1189 proto_tree_add_text(cotp_tree,
1190 offset + P_VAR_PART_EAK + i + 0, 1,
1191 "Parameter code: 0x%02x (seq number)", code);
1192 proto_tree_add_text(cotp_tree,
1193 offset + P_VAR_PART_EAK + i + 1, 1,
1194 "Parameter length: %u", length);
1195 proto_tree_add_text(cotp_tree,
1196 offset + P_VAR_PART_EAK + i + 2, 2,
1197 "Sequence number: 0x%04x", seq_nr);
1202 length = pd[offset + P_VAR_PART_EAK + i + 1];
1204 proto_tree_add_text(cotp_tree,
1205 offset + P_VAR_PART_EAK + i + 0, 1,
1206 "Parameter code: 0x%02x (unknown)", code);
1207 proto_tree_add_text(cotp_tree,
1208 offset + P_VAR_PART_EAK + i + 1, 1,
1209 "Parameter length: %u", length);
1210 proto_tree_add_text(cotp_tree,
1211 offset + P_VAR_PART_EAK + i + 2, length,
1212 "Parameter value: <not shown>");
1219 } /* is_LI_NORMAL_AK */
1225 } /* osi_decode_AK */
1227 static int osi_decode_EA(const u_char *pd, int offset,
1228 frame_data *fd, proto_tree *tree)
1230 proto_tree *cotp_tree;
1233 u_short checksum = 0;
1241 case LI_NORMAL_EA_WITH_CHECKSUM :
1242 tpdu_nr = pd[offset + P_TPDU_NR_234];
1243 code = pd[offset + P_VAR_PART_NDT];
1244 length = pd[offset + P_VAR_PART_NDT + 1];
1245 if (code != VP_CHECKSUM || length != 1)
1247 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
1249 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1250 tpdu_nr = pd[offset + P_TPDU_NR_234];
1252 case LI_EXTENDED_EA_WITH_CHECKSUM :
1253 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1254 code = pd[offset + P_VAR_PART_EDT];
1255 length = pd[offset + P_VAR_PART_EDT + 1];
1256 if (code != VP_CHECKSUM || length != 1)
1258 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
1260 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1261 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1263 default : /* bad TPDU */
1269 if (check_col(fd, COL_INFO))
1270 col_append_fstr(fd, COL_INFO,
1271 "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1274 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1275 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1276 proto_tree_add_text(cotp_tree, offset, 1,
1277 "Length indicator: %d", li);
1278 proto_tree_add_text(cotp_tree, offset + 1, 1,
1279 "TPDU code: 0x%x (EA)", tpdu);
1280 proto_tree_add_text(cotp_tree, offset + 2, 2,
1281 "Destination reference: 0x%04x", dst_ref);
1284 case LI_NORMAL_EA_WITH_CHECKSUM :
1285 proto_tree_add_text(cotp_tree, offset + 4, 1,
1286 "Your TPDU number: 0x%02x", tpdu_nr);
1287 proto_tree_add_text(cotp_tree, offset + 5, 1,
1288 "Parameter code: 0x%02x (checksum)", code);
1289 proto_tree_add_text(cotp_tree, offset + 6, 1,
1290 "Parameter length: %u", length);
1291 proto_tree_add_text(cotp_tree, offset + 7, 2,
1292 "Checksum: 0x%04x", checksum);
1294 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1295 proto_tree_add_text(cotp_tree, offset + 4, 1,
1296 "Your TPDU number: 0x%02x", tpdu_nr);
1298 case LI_EXTENDED_EA_WITH_CHECKSUM :
1299 proto_tree_add_text(cotp_tree, offset + 4, 4,
1300 "Your TPDU number: 0x%08x", tpdu_nr);
1301 proto_tree_add_text(cotp_tree, offset + 8, 1,
1302 "Parameter code: 0x%02x (checksum)", code);
1303 proto_tree_add_text(cotp_tree, offset + 9, 1,
1304 "Parameter length: %u", length);
1305 proto_tree_add_text(cotp_tree, offset + 10, 2,
1306 "Checksum: 0x%04x", checksum);
1308 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1309 proto_tree_add_text(cotp_tree, offset + 4, 4,
1310 "Your TPDU number: 0x%08x", tpdu_nr);
1321 } /* osi_decode_EA */
1323 static int osi_decode_ER(const u_char *pd, int offset,
1324 frame_data *fd, proto_tree *tree)
1326 proto_tree *cotp_tree;
1333 switch(pd[offset + P_REJECT_ER]) {
1335 str = "Reason not specified";
1338 str = "Invalid parameter code";
1341 str = "Invalid TPDU type";
1344 str = "Invalid parameter value";
1352 if (check_col(fd, COL_INFO))
1353 col_append_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1356 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1357 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1358 proto_tree_add_text(cotp_tree, offset, 1,
1359 "Length indicator: %d", li);
1360 proto_tree_add_text(cotp_tree, offset + 1, 1,
1361 "TPDU code: 0x%x (ER)", tpdu);
1362 proto_tree_add_text(cotp_tree, offset + 2, 2,
1363 "Destination reference: 0x%04x", dst_ref);
1364 proto_tree_add_text(cotp_tree, offset + 4, 1,
1365 "Reject cause: %s", str);
1372 } /* osi_decode_ER */
1374 /* Returns TRUE if we found at least one valid COTP PDU, FALSE
1376 static gboolean dissect_cotp_internal(const u_char *pd, int offset,
1377 frame_data *fd, proto_tree *tree,
1378 gboolean uses_inactive_subset)
1380 gboolean first_tpdu = TRUE;
1382 gboolean found_cotp = FALSE;
1384 /* Initialize the COL_INFO field; each of the TPDUs will have its
1385 information appended. */
1386 if (check_col(fd, COL_INFO))
1387 col_add_str(fd, COL_INFO, "");
1389 while (IS_DATA_IN_FRAME(offset)) {
1391 if (check_col(fd, COL_INFO))
1392 col_append_str(fd, COL_INFO, ", ");
1394 if ((li = pd[offset + P_LI]) == 0) {
1395 if (check_col(fd, COL_INFO))
1396 col_append_str(fd, COL_INFO, "Length indicator is zero");
1398 dissect_data(pd, offset, fd, tree);
1401 if (!BYTES_ARE_IN_FRAME(offset, P_LI + li + 1)) {
1402 if (check_col(fd, COL_INFO))
1403 col_append_str(fd, COL_INFO, "Captured data in frame doesn't include entire frame");
1405 dissect_data(pd, offset, fd, tree);
1409 tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
1410 cdt = pd[offset + P_CDT] & 0x0F;
1411 dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
1416 new_offset = osi_decode_CC(pd, offset, fd, tree);
1419 new_offset = osi_decode_DR(pd, offset, fd, tree);
1422 new_offset = osi_decode_DT(pd, offset, fd, tree, uses_inactive_subset);
1425 new_offset = osi_decode_ED(pd, offset, fd, tree);
1428 new_offset = osi_decode_RJ(pd, offset, fd, tree);
1431 new_offset = osi_decode_DC(pd, offset, fd, tree);
1434 new_offset = osi_decode_AK(pd, offset, fd, tree);
1437 new_offset = osi_decode_EA(pd, offset, fd, tree);
1440 new_offset = osi_decode_ER(pd, offset, fd, tree);
1443 if (first_tpdu && check_col(fd, COL_INFO))
1444 col_append_fstr(fd, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
1445 new_offset = -1; /* bad PDU type */
1449 if (new_offset == -1) { /* incorrect TPDU */
1451 dissect_data(pd, offset, fd, tree);
1456 /* Well, we found at least one valid COTP PDU, so I guess this
1458 if (check_col(fd, COL_PROTOCOL))
1459 col_add_str(fd, COL_PROTOCOL, "COTP");
1463 offset = new_offset;
1467 } /* dissect_cotp_internal */
1469 void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
1472 if (!dissect_cotp_internal(pd, offset, fd, tree, FALSE))
1473 dissect_data(pd, offset, fd, tree);
1481 #define MAX_NSAP_LEN 20
1483 static gchar *print_nsap(const u_char *nsap, int length)
1486 /* to do : real NSAP decoding */
1488 static gchar str[3][MAX_NSAP_LEN * 3 + 1];
1492 if (cur == &str[0][0]) {
1494 } else if (cur == &str[1][0]) {
1501 if (length <= 0 || length > MAX_NSAP_LEN)
1502 sprintf(cur, "<invalid NSAP>");
1504 while (length != 1) {
1505 sprintf(tmp, "%02x:", *nsap ++);
1509 sprintf(tmp, "%02x", *nsap);
1515 void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
1519 struct clnp_header clnp;
1520 proto_tree *clnp_tree = NULL;
1522 u_char src_len, dst_len, nsel;
1523 u_int first_offset = offset;
1524 char flag_string[6+1];
1525 char *pdu_type_string;
1526 guint16 segment_length;
1527 guint16 segment_offset = 0;
1530 if (check_col(fd, COL_PROTOCOL))
1531 col_add_str(fd, COL_PROTOCOL, "CLNP");
1533 /* avoid alignment problem */
1534 memcpy(&clnp, &pd[offset], sizeof(clnp));
1536 if (clnp.cnf_proto_id == NLPID_NULL) {
1537 if (check_col(fd, COL_INFO))
1538 col_add_str(fd, COL_INFO, "Inactive subset");
1540 ti = proto_tree_add_item(tree, proto_clnp, offset, 1, NULL);
1541 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1542 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, offset, 1,
1546 dissect_cotp_internal(pd, offset+1, fd, tree, TRUE);
1550 if (!BYTES_ARE_IN_FRAME(offset, sizeof(clnp))) {
1551 dissect_data(pd, offset, fd, tree);
1555 /* return if version not known */
1556 if (clnp.cnf_vers != ISO8473_V1) {
1557 dissect_data(pd, offset, fd, tree);
1561 /* fixed part decoding */
1563 segment_length = EXTRACT_SHORT(&clnp.cnf_seglen_msb);
1564 flag_string[0] = '\0';
1565 if (clnp.cnf_type & CNF_SEG_OK)
1566 strcat(flag_string, "S ");
1567 if (clnp.cnf_type & CNF_MORE_SEGS)
1568 strcat(flag_string, "M ");
1569 if (clnp.cnf_type & CNF_ERR_OK)
1570 strcat(flag_string, "E ");
1571 pdu_type_string = val_to_str(clnp.cnf_type & CNF_TYPE, npdu_type_vals,
1572 "Unknown (0x%02x)");
1574 ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL);
1575 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1576 proto_tree_add_item(clnp_tree, hf_clnp_id, offset, 1,
1578 proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1,
1580 proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1,
1582 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, offset + 3, 1,
1584 "TTL: %d (%d secs)",
1585 clnp.cnf_ttl, clnp.cnf_ttl / 2);
1586 proto_tree_add_uint_format(clnp_tree, hf_clnp_type, offset + 4, 1,
1588 "Type code: 0x%02x (%s%s)",
1592 proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2,
1594 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, offset + 7, 2,
1595 EXTRACT_SHORT(&clnp.cnf_cksum_msb),
1597 EXTRACT_SHORT(&clnp.cnf_cksum_msb));
1600 /* stop here if header is not complete */
1602 if (!BYTES_ARE_IN_FRAME(offset, clnp.cnf_hdr_len)) {
1603 if (check_col(fd, COL_INFO))
1604 col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1605 dissect_data(pd, offset, fd, tree);
1611 offset += P_ADDRESS_PART;
1612 dst_len = pd[offset];
1613 nsel = pd[offset + dst_len];
1614 src_len = pd[offset + dst_len + 1];
1617 proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1,
1619 proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len,
1621 "Destination address: %s",
1622 print_nsap(&pd[offset + 1], dst_len));
1623 proto_tree_add_item(clnp_tree, hf_clnp_src_length,
1624 offset + 1 + dst_len, 1, src_len);
1625 proto_tree_add_bytes_format(clnp_tree, hf_clnp_src,
1626 offset + dst_len + 2, src_len,
1627 &pd[offset + dst_len + 2],
1628 "Source address: %s",
1629 print_nsap(&pd[offset + dst_len + 2], src_len));
1632 if (check_col(fd, COL_RES_NET_SRC))
1633 col_add_fstr(fd, COL_RES_NET_SRC, "%s",
1634 print_nsap(&pd[offset + dst_len + 2], src_len));
1635 if (check_col(fd, COL_RES_NET_DST))
1636 col_add_fstr(fd, COL_RES_NET_DST, "%s",
1637 print_nsap(&pd[offset + 1], dst_len));
1639 /* Segmentation Part */
1641 offset += dst_len + src_len + 2;
1643 if (clnp.cnf_type & CNF_SEG_OK) {
1644 struct clnp_segment seg; /* XXX - not used */
1645 memcpy(&seg, &pd[offset], sizeof(seg)); /* XXX - not used */
1647 segment_offset = EXTRACT_SHORT(&pd[offset + 2]);
1649 proto_tree_add_text(clnp_tree, offset, 2,
1650 "Data unit identifier: 0x%04x",
1651 EXTRACT_SHORT(&pd[offset]));
1652 proto_tree_add_text(clnp_tree, offset + 2 , 2,
1653 "Segment offset: %u",
1655 proto_tree_add_text(clnp_tree, offset + 4 , 2,
1657 EXTRACT_SHORT(&pd[offset + 4]));
1664 /* To do : decode options */
1666 proto_tree_add_text(clnp_tree, offset,
1667 clnp.cnf_hdr_len + first_offset - offset,
1668 "Options/Data: <not shown>");
1671 /* Length of CLNP datagram plus headers above it. */
1672 len = segment_length + first_offset;
1674 /* Set the payload and captured-payload lengths to the minima of (the
1675 datagram length plus the length of the headers above it) and the
1679 if (pi.captured_len > len)
1680 pi.captured_len = len;
1682 offset = first_offset + clnp.cnf_hdr_len;
1684 /* For now, dissect the payload of segments other than the initial
1685 segment as data, rather than handing them off to the transport
1686 protocol, just as we do with fragments other than the first
1687 fragment in a fragmented IP datagram; in the future, we will
1688 probably reassemble fragments for IP, and may reassemble segments
1690 if ((clnp.cnf_type & CNF_SEG_OK) && segment_offset != 0) {
1691 if (check_col(fd, COL_INFO))
1692 col_add_fstr(fd, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
1693 pdu_type_string, flag_string, segment_offset);
1694 dissect_data(pd, offset, fd, tree);
1698 if (IS_DATA_IN_FRAME(offset)) {
1699 switch (clnp.cnf_type & CNF_TYPE) {
1703 /* Continue with COTP if any data.
1704 XXX - if this isn't the first Derived PDU of a segmented Initial
1707 if (nsel == NSEL_TP) { /* just guessing here - valid for DECNet-OSI */
1708 if (dissect_cotp_internal(pd, offset, fd, tree, FALSE))
1709 return; /* yes, it appears to be COTP */
1714 /* The payload is the header and "none, some, or all of the data
1715 part of the discarded PDU", i.e. it's like an ICMP error;
1716 just as we don't yet trust ourselves to be able to dissect
1717 the payload of an ICMP error packet, we don't yet trust
1718 ourselves to dissect the payload of a CLNP ER packet. */
1723 /* XXX - dissect this */
1727 if (check_col(fd, COL_INFO))
1728 col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
1729 dissect_data(pd, offset, fd, tree);
1731 } /* dissect_clnp */
1734 /* main entry point */
1736 const value_string nlpid_vals[] = {
1737 { NLPID_NULL, "NULL" },
1738 { NLPID_T_70, "T.70" },
1739 { NLPID_X_633, "X.633" },
1740 { NLPID_Q_931, "Q.931" },
1741 { NLPID_Q_2931, "Q.2931" },
1742 { NLPID_Q_2119, "Q.2119" },
1743 { NLPID_SNAP, "SNAP" },
1744 { NLPID_ISO8473_CLNP, "CLNP" },
1745 { NLPID_ISO9542_ESIS, "ESIS" },
1746 { NLPID_ISO10589_ISIS, "ISIS" },
1747 { NLPID_ISO10747, "ISO 10747" },
1748 { NLPID_ISO9542X25_ESIS, "ESIS (X.25)" },
1749 { NLPID_ISO10030, "ISO 10030" },
1750 { NLPID_ISO11577, "ISO 11577" },
1752 { NLPID_PPP, "PPP" },
1756 void dissect_osi(const u_char *pd, int offset, frame_data *fd,
1760 switch (pd[offset]) {
1762 /* ESIS is not currently decoded */
1764 case NLPID_ISO8473_CLNP:
1765 case NLPID_NULL: /* "Inactive Subset" of ISO 8473 CLNP */
1766 dissect_clnp(pd, offset, fd, tree);
1768 case NLPID_ISO9542_ESIS:
1769 if (check_col(fd, COL_PROTOCOL)) {
1770 col_add_str(fd, COL_PROTOCOL, "ESIS");
1772 dissect_data(pd, offset, fd, tree);
1774 case NLPID_ISO9542X25_ESIS:
1775 if (check_col(fd, COL_PROTOCOL)) {
1776 col_add_str(fd, COL_PROTOCOL, "ESIS (X.25)");
1778 dissect_data(pd, offset, fd, tree);
1780 case NLPID_ISO10589_ISIS:
1781 dissect_isis(pd, offset, fd, tree);
1784 if (check_col(fd, COL_PROTOCOL)) {
1785 col_add_str(fd, COL_PROTOCOL, "ISO");
1787 if (check_col(fd, COL_INFO)) {
1788 col_add_fstr(fd, COL_INFO, "Unknown ISO protocol (%02x)", pd[offset]);
1790 dissect_data(pd, offset, fd, tree);
1796 void proto_register_clnp(void)
1798 static hf_register_info hf[] = {
1800 { "Protocol identifier", "clnp.id", FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0,
1804 { "Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1808 { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1812 { "TTL", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1816 { "Type code", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1819 { &hf_clnp_pdu_length,
1820 { "PDU segment length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1823 { &hf_clnp_checksum,
1824 { "Checksum", "clnp.checksum",FT_UINT16, BASE_DEC, NULL, 0x0,
1827 { &hf_clnp_dest_length,
1828 { "Destination address length", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1832 { "Destination address", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0,
1835 { &hf_clnp_src_length,
1836 { "Source address length","clnp.ssap.len",FT_UINT8, BASE_DEC, NULL, 0x0,
1840 { "Source address", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0,
1843 static gint *ett[] = {
1847 proto_clnp = proto_register_protocol("ISO CLNP", "clnp");
1848 proto_register_field_array(proto_clnp, hf, array_length(hf));
1849 proto_register_subtree_array(ett, array_length(ett));
1852 void proto_register_cotp(void)
1854 /* static hf_register_info hf[] = {
1856 { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
1858 static gint *ett[] = {
1862 proto_cotp = proto_register_protocol("ISO COTP", "cotp");
1863 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
1864 proto_register_subtree_array(ett, array_length(ett));