2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-osi.c,v 1.23 2000/03/12 04:47:45 gram 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
116 #define P_ADDRESS_PART 9
118 /* Segmentation part */
120 struct clnp_segment {
121 u_short cng_id; /* data unit identifier */
122 u_short cng_off; /* segment offset */
123 u_short cng_tot_len; /* total length */
128 #define NSEL_NET 0x00
133 * ISO8073 OSI COTP definition (see RFC905)
136 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
138 /* TPDU definition */
158 #define P_TPDU_NR_0_1 2
159 #define P_TPDU_NR_234 4
160 #define P_VAR_PART_NDT 5
161 #define P_VAR_PART_EDT 8
162 #define P_VAR_PART_NAK 5
163 #define P_VAR_PART_CC 7
164 #define P_VAR_PART_EAK 10
165 #define P_VAR_PART_DC 6
166 #define P_VAR_PART_DR 7
167 #define P_CDT_IN_AK 8
168 #define P_CDT_IN_RJ 8
169 #define P_REJECT_ER 4
170 #define P_REASON_IN_DR 6
171 #define P_CLASS_OPTION 6
173 /* TPDU length indicator */
175 #define LI_NORMAL_DT_CLASS_01 2
176 #define LI_NORMAL_DT_WITH_CHECKSUM 8
177 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
178 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
179 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
180 #define LI_NORMAL_EA_WITH_CHECKSUM 8
181 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
182 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
183 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
184 #define LI_NORMAL_RJ 4
185 #define LI_EXTENDED_RJ 9
191 #define LI_DC_WITH_CHECKSUM 9
192 #define LI_DC_WITHOUT_CHECKSUM 5
193 #define is_LI_NORMAL_AK(p) ( p & 0x01 )
197 #define VP_ACK_TIME 0x85
198 #define VP_RES_ERROR 0x86
199 #define VP_PRIORITY 0x87
200 #define VP_TRANSIT_DEL 0x88
201 #define VP_THROUGHPUT 0x89
202 #define VP_SEQ_NR 0x8A /* in AK */
203 #define VP_REASSIGNMENT 0x8B
204 #define VP_FLOW_CNTL 0x8C /* in AK */
205 #define VP_TPDU_SIZE 0xC0
206 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
207 #define VP_DST_TSAP 0xC2
208 #define VP_CHECKSUM 0xC3
209 #define VP_VERSION_NR 0xC4
210 #define VP_PROTECTION 0xC5
211 #define VP_OPT_SEL 0xC6
212 #define VP_PROTO_CLASS 0xC7
216 #define EXTRACT_SHORT(p) pntohs(p)
217 #define EXTRACT_LONG(p) pntohl(p)
219 /* global variables */
221 static u_char li, tpdu, cdt; /* common fields */
222 static u_short dst_ref;
224 /* function definitions */
226 static int osi_decode_DR(const u_char *pd, int offset,
227 frame_data *fd, proto_tree *tree)
229 proto_tree *cotp_tree;
238 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
239 reason = pd[offset + P_REASON_IN_DR];
242 case (128+0): str = "Normal Disconnect"; break;
243 case (128+1): str = "Remote transport enity congestion"; break;
244 case (128+2): str = "Connection negotiation failed"; break;
245 case (128+3): str = "Duplicate source reference"; break;
246 case (128+4): str = "Mismatched references"; break;
247 case (128+5): str = "Protocol error"; break;
248 case (128+7): str = "Reference overflow"; break;
249 case (128+8): str = "Connection requestion refused"; break;
250 case (128+10):str = "Header or parameter length invalid"; break;
251 case (0): str = "Reason not specified"; break;
252 case (1): str = "Congestion at TSAP"; break;
253 case (2): str = "Session entity not attached to TSAP"; break;
254 case (3): str = "Address unknown"; break;
260 if (check_col(fd, COL_PROTOCOL))
261 col_add_str(fd, COL_PROTOCOL, "COTP");
262 if (check_col(fd, COL_INFO))
263 col_add_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
267 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
268 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
269 proto_tree_add_text(cotp_tree, offset, 1,
270 "Length indicator: %d", li);
271 proto_tree_add_text(cotp_tree, offset + 1, 1,
272 "TPDU code: Ox%x (DR)", tpdu);
273 proto_tree_add_text(cotp_tree, offset + 2, 2,
274 "Destination reference: 0x%04x", dst_ref);
275 proto_tree_add_text(cotp_tree, offset + 4, 2,
276 "Source reference: 0x%04x", src_ref);
277 proto_tree_add_text(cotp_tree, offset + 6, 1,
282 dissect_data(pd, offset, fd, tree);
286 } /* osi_decode_DR */
288 static int osi_decode_DT(const u_char *pd, int offset,
289 frame_data *fd, proto_tree *tree,
290 gboolean uses_inactive_subset)
292 proto_tree *cotp_tree;
295 u_short checksum = 0;
296 u_char code = 0, length = 0;
300 case LI_NORMAL_DT_WITH_CHECKSUM :
301 tpdu_nr = pd[offset + P_TPDU_NR_234];
302 if ( tpdu_nr & 0x80 )
303 tpdu_nr = tpdu_nr & 0x7F;
306 code = pd[offset + P_VAR_PART_NDT];
307 if (code == VP_CHECKSUM)
308 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
312 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
313 tpdu_nr = pd[offset + P_TPDU_NR_234];
314 if ( tpdu_nr & 0x80 )
315 tpdu_nr = tpdu_nr & 0x7F;
319 case LI_EXTENDED_DT_WITH_CHECKSUM :
320 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
321 if ( tpdu_nr & 0x80000000 )
322 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
325 code = pd[offset + P_VAR_PART_EDT];
326 if (code == VP_CHECKSUM)
327 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
331 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
332 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
333 if ( tpdu_nr & 0x80000000 )
334 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
338 case LI_NORMAL_DT_CLASS_01 :
339 tpdu_nr = pd[offset + P_TPDU_NR_0_1];
340 if ( tpdu_nr & 0x80 )
341 tpdu_nr = tpdu_nr & 0x7F;
345 default : /* bad TPDU */
351 if (check_col(fd, COL_PROTOCOL))
352 col_add_str(fd, COL_PROTOCOL, "COTP");
353 if (check_col(fd, COL_INFO))
354 col_add_fstr(fd, COL_INFO, "DT TPDU (%d) dst-ref: 0x%04x %s",
357 (fragment)? "(fragment)" : "");
360 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
361 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
362 proto_tree_add_text(cotp_tree, offset, 1,
363 "Length indicator: %d", li);
364 proto_tree_add_text(cotp_tree, offset + 1, 1,
365 "TPDU code: Ox%x (DT)", tpdu);
367 if (li != LI_NORMAL_DT_CLASS_01)
368 proto_tree_add_text(cotp_tree, offset + 2, 2,
369 "Destination reference: 0x%04x", dst_ref);
372 case LI_NORMAL_DT_WITH_CHECKSUM :
373 proto_tree_add_text(cotp_tree, offset + 4, 1,
374 "TPDU number: 0x%02x (%s)",
376 (fragment)? "fragment":"complete");
377 proto_tree_add_text(cotp_tree,
378 offset + P_VAR_PART_NDT, 1,
379 "Parameter code: 0x%02x (checksum)", code);
380 proto_tree_add_text(cotp_tree,
381 offset + P_VAR_PART_NDT + 1, 1,
382 "Parameter length: 0x%02x", length);
383 proto_tree_add_text(cotp_tree,
384 offset + P_VAR_PART_NDT + 2, length,
385 "Checksum: 0x%04x", checksum);
387 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
388 proto_tree_add_text(cotp_tree, offset + 4, 1,
389 "TPDU number: 0x%02x (%s)",
391 (fragment)? "fragment":"complete");
393 case LI_EXTENDED_DT_WITH_CHECKSUM :
394 proto_tree_add_text(cotp_tree, offset + 4, 4,
395 "TPDU number: 0x%08x (%s)",
397 (fragment)? "fragment":"complete");
398 proto_tree_add_text(cotp_tree,
399 offset + P_VAR_PART_EDT, 1,
400 "Parameter code: 0x%02x (checksum)", code);
401 proto_tree_add_text(cotp_tree,
402 offset + P_VAR_PART_EDT + 1, 1,
403 "Parameter length: 0x%02x", length);
404 proto_tree_add_text(cotp_tree,
405 offset + P_VAR_PART_EDT + 2, length,
406 "Checksum: 0x%04x", checksum);
408 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
409 proto_tree_add_text(cotp_tree, offset + 4, 4,
410 "TPDU number: 0x%08x (%s)",
412 (fragment)? "fragment":"complete");
414 case LI_NORMAL_DT_CLASS_01 :
415 proto_tree_add_text(cotp_tree, offset + 2, 1,
416 "TPDU number: 0x%02x (%s)",
418 (fragment)? "fragment":"complete");
424 if (uses_inactive_subset){
425 dissect_h1(pd, offset, fd, tree);
428 dissect_data(pd, offset, fd, tree);
433 } /* osi_decode_DT */
435 static int osi_decode_ED(const u_char *pd, int offset,
436 frame_data *fd, proto_tree *tree)
438 proto_tree *cotp_tree;
441 u_short checksum = 0;
442 u_char code = 0, length = 0;
444 /* ED TPDUs are never fragmented */
447 case LI_NORMAL_DT_WITH_CHECKSUM :
448 tpdu_nr = pd[offset + P_TPDU_NR_234];
449 if ( tpdu_nr & 0x80 )
450 tpdu_nr = tpdu_nr & 0x7F;
453 code = pd[offset + P_VAR_PART_NDT];
454 length = pd[offset + P_VAR_PART_NDT + 1];
455 if (code == VP_CHECKSUM)
456 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
460 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
461 tpdu_nr = pd[offset + P_TPDU_NR_234];
462 if ( tpdu_nr & 0x80 )
463 tpdu_nr = tpdu_nr & 0x7F;
467 case LI_EXTENDED_DT_WITH_CHECKSUM :
468 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
469 if ( tpdu_nr & 0x80000000 )
470 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
473 code = pd[offset + P_VAR_PART_EDT];
474 length = pd[offset + P_VAR_PART_EDT + 1];
475 if (code == VP_CHECKSUM)
476 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
480 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
481 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
482 if ( tpdu_nr & 0x80000000 )
483 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
487 default : /* bad TPDU */
493 if (check_col(fd, COL_PROTOCOL))
494 col_add_str(fd, COL_PROTOCOL, "COTP");
495 if (check_col(fd, COL_INFO))
496 col_add_fstr(fd, COL_INFO, "ED TPDU (%d) dst-ref: 0x%04x",
500 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
501 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
502 proto_tree_add_text(cotp_tree, offset, 1,
503 "Length indicator: %d", li);
504 proto_tree_add_text(cotp_tree, offset + 1, 1,
505 "TPDU code: Ox%x (ED)", tpdu);
506 proto_tree_add_text(cotp_tree, offset + 2, 2,
507 "Destination reference: 0x%04x", dst_ref);
510 case LI_NORMAL_DT_WITH_CHECKSUM :
511 proto_tree_add_text(cotp_tree, offset + 4, 1,
512 "TPDU number: 0x%02x", tpdu_nr);
513 proto_tree_add_text(cotp_tree,
514 offset + P_VAR_PART_NDT, 1,
515 "Parameter code: 0x%02x (checksum)", code);
516 proto_tree_add_text(cotp_tree,
517 offset + P_VAR_PART_NDT + 1, 1,
518 "Parameter length: 0x%02x", length);
519 proto_tree_add_text(cotp_tree,
520 offset + P_VAR_PART_NDT + 2, length,
521 "Checksum: 0x%04x", checksum);
523 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
524 proto_tree_add_text(cotp_tree, offset + 4, 1,
525 "TPDU number: 0x%02x", tpdu_nr);
527 case LI_EXTENDED_DT_WITH_CHECKSUM :
528 proto_tree_add_text(cotp_tree, offset + 4, 4,
529 "TPDU number: 0x%02x", tpdu_nr);
530 proto_tree_add_text(cotp_tree,
531 offset + P_VAR_PART_EDT, 1,
532 "Parameter code: 0x%02x (checksum)", code);
533 proto_tree_add_text(cotp_tree,
534 offset + P_VAR_PART_EDT + 1, 1,
535 "Parameter length: 0x%02x", length);
536 proto_tree_add_text(cotp_tree,
537 offset + P_VAR_PART_EDT + 2, length,
538 "Checksum: 0x%04x", checksum);
540 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
541 proto_tree_add_text(cotp_tree, offset + 4, 4,
542 "TPDU number: 0x%02x", tpdu_nr);
548 dissect_data(pd, offset, fd, tree);
552 } /* osi_decode_ED */
554 static int osi_decode_RJ(const u_char *pd, int offset,
555 frame_data *fd, proto_tree *tree)
557 proto_tree *cotp_tree;
564 tpdu_nr = pd[offset + P_TPDU_NR_234];
566 case LI_EXTENDED_RJ :
567 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
568 credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
576 if (check_col(fd, COL_PROTOCOL))
577 col_add_str(fd, COL_PROTOCOL, "COTP");
578 if (check_col(fd, COL_INFO))
579 col_add_fstr(fd, COL_INFO, "RJ TPDU (%d) dst-ref: 0x%04x",
583 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
584 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
585 proto_tree_add_text(cotp_tree, offset, 1,
586 "Length indicator: %d", li);
587 proto_tree_add_text(cotp_tree, offset + 1, 1,
588 "TPDU code: Ox%x (RJ)", tpdu);
589 if (li == LI_NORMAL_RJ)
590 proto_tree_add_text(cotp_tree, offset + 1, 1,
592 proto_tree_add_text(cotp_tree, offset + 2, 2,
593 "Destination reference: 0x%04x", dst_ref);
594 if (li == LI_NORMAL_RJ)
595 proto_tree_add_text(cotp_tree, offset + 4, 1,
596 "Your TPDU number: 0x%02x", tpdu_nr);
598 proto_tree_add_text(cotp_tree, offset + 4, 4,
599 "Your TPDU number: 0x%02x", tpdu_nr);
600 proto_tree_add_text(cotp_tree, offset + 8, 2,
601 "Credit: 0x%02x", credit);
606 dissect_data(pd, offset, fd, tree);
610 } /* osi_decode_RJ */
612 #define MAX_TSAP_LEN 32
614 static gchar *print_tsap(const u_char *tsap, int length)
617 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
620 gboolean allprintable;
623 if (cur == &str[0][0]) {
625 } else if (cur == &str[1][0]) {
633 if (length <= 0 || length > MAX_TSAP_LEN)
634 sprintf(cur, "<unsupported TSAP length>");
637 for (i=0;i<length;i++) {
638 if (!isprint(tsap[i])) { /* if any byte is not printable */
639 allprintable=FALSE; /* switch to hexdump */
646 while (length != 0) {
648 sprintf(tmp, "%c", *tsap ++);
650 sprintf(tmp, "%02x", *tsap ++);
659 static int osi_decode_CC(const u_char *pd, int offset,
660 frame_data *fd, proto_tree *tree)
663 /* CC & CR decoding in the same function */
665 proto_tree *cotp_tree = NULL;
667 u_short src_ref, checksum;
668 u_char class_option, code, length;
671 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
672 class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
673 if (class_option > 4)
676 if (check_col(fd, COL_PROTOCOL))
677 col_add_str(fd, COL_PROTOCOL, "COTP");
678 if (check_col(fd, COL_INFO))
679 col_add_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
680 (tpdu == CR_TPDU) ? "CR" : "CC",
685 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
686 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
687 proto_tree_add_text(cotp_tree, offset, 1,
688 "Length indicator: %d", li);
689 proto_tree_add_text(cotp_tree, offset + 1, 1,
690 "TPDU code: Ox%x (%s)", tpdu,
691 (tpdu == CR_TPDU) ? "CR" : "CC");
692 proto_tree_add_text(cotp_tree, offset + 2, 2,
693 "Destination reference: 0x%04x", dst_ref);
694 proto_tree_add_text(cotp_tree, offset + 4, 2,
695 "Source reference: 0x%04x", src_ref);
696 proto_tree_add_text(cotp_tree, offset + 6, 1,
697 "Class option: 0x%02x", class_option);
701 while(li > P_VAR_PART_CC + i - 1) {
704 u_short s, s1,s2,s3,s4;
707 switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
709 length = pd[offset + P_VAR_PART_CC + i + 1];
710 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
711 proto_tree_add_text(cotp_tree,
712 offset + P_VAR_PART_CC + i, 1,
713 "Parameter code: 0x%02x (checksum)", code);
714 proto_tree_add_text(cotp_tree,
715 offset + P_VAR_PART_CC + i + 1, 1,
716 "Parameter length: 0x%02x", length);
717 proto_tree_add_text(cotp_tree,
718 offset + P_VAR_PART_CC + i + 2, length,
719 "Checksum: 0x%04x", checksum);
723 length = pd[offset + P_VAR_PART_CC + i + 1];
724 proto_tree_add_text(cotp_tree,
725 offset + P_VAR_PART_CC + i, 1,
726 "Parameter code: 0x%02x (src-tsap)", code);
727 proto_tree_add_text(cotp_tree,
728 offset + P_VAR_PART_CC + i + 1, 1,
729 "Parameter length: 0x%02x", length);
730 proto_tree_add_text(cotp_tree,
731 offset + P_VAR_PART_CC + i + 2, length,
733 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
738 length = pd[offset + P_VAR_PART_CC + i + 1];
739 proto_tree_add_text(cotp_tree,
740 offset + P_VAR_PART_CC + i, 1,
741 "Parameter code: 0x%02x (dst-tsap)", code);
742 proto_tree_add_text(cotp_tree,
743 offset + P_VAR_PART_CC + i + 1, 1,
744 "Parameter length: 0x%02x", length);
745 proto_tree_add_text(cotp_tree,
746 offset + P_VAR_PART_CC + i + 2, length,
748 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
753 length = pd[offset + P_VAR_PART_CC + i + 1];
754 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
755 proto_tree_add_text(cotp_tree,
756 offset + P_VAR_PART_CC + i, 1,
757 "Parameter code: 0x%02x (tpdu-size)", code);
758 proto_tree_add_text(cotp_tree,
759 offset + P_VAR_PART_CC + i + 1, 1,
760 "Parameter length: 0x%02x", length);
761 proto_tree_add_text(cotp_tree,
762 offset + P_VAR_PART_CC + i + 2, length,
763 "TPDU size: %d", 2 << c1);
767 length = pd[offset + P_VAR_PART_CC + i + 1];
768 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
769 proto_tree_add_text(cotp_tree,
770 offset + P_VAR_PART_CC + i, 1,
771 "Parameter code: 0x%02x (options)", code);
772 proto_tree_add_text(cotp_tree,
773 offset + P_VAR_PART_CC + i + 1, 1,
774 "Parameter length: 0x%02x", length);
775 if (class_option == 1) {
777 proto_tree_add_text(cotp_tree,
778 offset + P_VAR_PART_CC + i + 2, 1,
779 "Use of network expedited data");
781 proto_tree_add_text(cotp_tree,
782 offset + P_VAR_PART_CC + i + 2, 1,
783 "Non use of network expedited data");
785 proto_tree_add_text(cotp_tree,
786 offset + P_VAR_PART_CC + i + 2, 1,
787 "Use of Receipt confirmation");
789 proto_tree_add_text(cotp_tree,
790 offset + P_VAR_PART_CC + i + 2, 1,
791 "Use of explicit AK variant");
792 } else if (class_option == 4) {
794 proto_tree_add_text(cotp_tree,
795 offset + P_VAR_PART_CC + i + 2, 1,
796 "Use 16 bit checksum ");
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");
803 proto_tree_add_text(cotp_tree,
804 offset + P_VAR_PART_CC + i + 2, 1,
805 "Use of transport expedited data transfer\n");
807 proto_tree_add_text(cotp_tree,
808 offset + P_VAR_PART_CC + i + 2, 1,
809 "Non-use of transport expedited data transfer");
813 length = pd[offset + P_VAR_PART_CC + i + 1];
814 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
815 proto_tree_add_text(cotp_tree,
816 offset + P_VAR_PART_CC + i, 1,
817 "Parameter code: 0x%02x (ack time)", code);
818 proto_tree_add_text(cotp_tree,
819 offset + P_VAR_PART_CC + i + 1, 1,
820 "Parameter length: 0x%02x", length);
821 proto_tree_add_text(cotp_tree,
822 offset + P_VAR_PART_CC + i + 2, length,
823 "Ack time (ms): %d", s);
827 length = pd[offset + P_VAR_PART_CC + i + 1];
828 t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
829 t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
830 t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
831 t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
832 proto_tree_add_text(cotp_tree,
833 offset + P_VAR_PART_CC + i, 1,
834 "Parameter code: 0x%02x (throughput)", code);
835 proto_tree_add_text(cotp_tree,
836 offset + P_VAR_PART_CC + i + 1, 1,
837 "Parameter length: 0x%02x", length);
838 proto_tree_add_text(cotp_tree,
839 offset + P_VAR_PART_CC + i + 2, 4,
840 "Target value / calling-called: %d o/s", t1);
841 proto_tree_add_text(cotp_tree,
842 offset + P_VAR_PART_CC + i + 6, 4,
843 "Minimum / calling-called: %d o/s", t2);
844 proto_tree_add_text(cotp_tree,
845 offset + P_VAR_PART_CC + i + 10, 4,
846 "Target value / called-calling: %d o/s", t3);
847 proto_tree_add_text(cotp_tree,
848 offset + P_VAR_PART_CC + i + 14, 4,
849 "Minimum / called-calling: %d o/s", t4);
852 case VP_TRANSIT_DEL :
853 length = pd[offset + P_VAR_PART_CC + i + 1];
854 s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
855 s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
856 s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
857 s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
858 proto_tree_add_text(cotp_tree,
859 offset + P_VAR_PART_CC + i, 1,
860 "Parameter code: 0x%02x (transit delay)", code);
861 proto_tree_add_text(cotp_tree,
862 offset + P_VAR_PART_CC + i + 1, 1,
863 "Parameter length: 0x%02x", length);
864 proto_tree_add_text(cotp_tree,
865 offset + P_VAR_PART_CC + i + 2, 2,
866 "Target value / calling-called: %d ms", s1);
867 proto_tree_add_text(cotp_tree,
868 offset + P_VAR_PART_CC + i + 4, 2,
869 "Minimum / calling-called: %d ms", s2);
870 proto_tree_add_text(cotp_tree,
871 offset + P_VAR_PART_CC + i + 6, 2,
872 "Target value / called-calling: %d ms", s3);
873 proto_tree_add_text(cotp_tree,
874 offset + P_VAR_PART_CC + i + 8, 2,
875 "Minimum / called-calling: %d ms", s4);
879 length = pd[offset + P_VAR_PART_CC + i + 1];
880 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
881 proto_tree_add_text(cotp_tree,
882 offset + P_VAR_PART_CC + i, 1,
883 "Parameter code: 0x%02x (priority)", code);
884 proto_tree_add_text(cotp_tree,
885 offset + P_VAR_PART_CC + i + 1, 1,
886 "Parameter length: 0x%02x", length);
887 proto_tree_add_text(cotp_tree,
888 offset + P_VAR_PART_CC + i + 2, length,
894 length = pd[offset + P_VAR_PART_CC + i + 1];
895 c1 = pd[offset + P_VAR_PART_CC + i + 2];
896 proto_tree_add_text(cotp_tree,
897 offset + P_VAR_PART_CC + i, 1,
898 "Parameter code: 0x%02x (version)", code);
899 proto_tree_add_text(cotp_tree,
900 offset + P_VAR_PART_CC + i + 1, 1,
901 "Parameter length: 0x%02x", length);
902 proto_tree_add_text(cotp_tree,
903 offset + P_VAR_PART_CC + i + 2, length,
908 case VP_REASSIGNMENT: /* todo */
911 case VP_PROTO_CLASS :
912 default : /* no decoding */
913 length = pd[offset + P_VAR_PART_CC + i + 1];
914 proto_tree_add_text(cotp_tree,
915 offset + P_VAR_PART_CC + i + 0, 1,
916 "Parameter code: 0x%02x", code);
917 proto_tree_add_text(cotp_tree,
918 offset + P_VAR_PART_CC + i + 1, 1,
919 "Parameter length: 0x%02x", length);
920 proto_tree_add_text(cotp_tree,
921 offset + P_VAR_PART_CC + i + 2, length,
922 "Parameter value: <not shown>");
929 dissect_data(pd, offset, fd, tree);
933 } /* osi_decode_CC */
935 static int osi_decode_DC(const u_char *pd, int offset,
936 frame_data *fd, proto_tree *tree)
938 proto_tree *cotp_tree;
940 u_short src_ref, checksum = 0;
941 u_char length = 0, code = 0;
946 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
949 case LI_DC_WITHOUT_CHECKSUM :
951 case LI_DC_WITH_CHECKSUM :
952 if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
954 length = pd[offset + P_VAR_PART_DC + 1];
955 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
963 if (check_col(fd, COL_PROTOCOL))
964 col_add_str(fd, COL_PROTOCOL, "COTP");
965 if (check_col(fd, COL_INFO))
966 col_add_fstr(fd, COL_INFO, "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
971 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
972 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
973 proto_tree_add_text(cotp_tree, offset, 1,
974 "Length indicator: %d", li);
975 proto_tree_add_text(cotp_tree, offset + 1, 1,
976 "TPDU code: Ox%x (DC)", tpdu);
977 proto_tree_add_text(cotp_tree, offset + 2, 2,
978 "Destination reference: 0x%04x", dst_ref);
979 proto_tree_add_text(cotp_tree, offset + 4, 2,
980 "Source reference: 0x%04x", src_ref);
982 proto_tree_add_text(cotp_tree,
983 offset + P_VAR_PART_DC + 0, 1,
984 "Parameter code: 0x%02x (checksum)", code);
985 proto_tree_add_text(cotp_tree,
986 offset + P_VAR_PART_DC + 1, 1,
987 "Parameter length: 0x%02x", length);
988 proto_tree_add_text(cotp_tree,
989 offset + P_VAR_PART_DC + 2, 2,
990 "Checksum: 0x%04x", checksum);
995 dissect_data(pd, offset, fd, tree);
999 } /* osi_decode_DC */
1001 static int osi_decode_AK(const u_char *pd, int offset,
1002 frame_data *fd, proto_tree *tree)
1004 proto_tree *cotp_tree = NULL;
1006 u_int tpdu_nr,i =0, r_lower_window_edge ;
1008 u_short checksum, seq_nr, r_seq_nr, r_cdt;
1009 u_char code, length;
1014 if (!is_LI_NORMAL_AK(li)) {
1015 tpdu_nr = pd[offset + P_TPDU_NR_234];
1017 if (check_col(fd, COL_PROTOCOL))
1018 col_add_str(fd, COL_PROTOCOL, "COTP");
1019 if (check_col(fd, COL_INFO))
1020 col_add_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
1024 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1025 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1026 proto_tree_add_text(cotp_tree, offset, 1,
1027 "Length indicator: %d", li);
1028 proto_tree_add_text(cotp_tree, offset + 1, 1,
1029 "TPDU code: Ox%x (AK)", tpdu);
1030 proto_tree_add_text(cotp_tree, offset + 1, 1,
1032 proto_tree_add_text(cotp_tree, offset + 2, 2,
1033 "Destination reference: 0x%04x", dst_ref);
1034 proto_tree_add_text(cotp_tree, offset + 4, 1,
1035 "Your TPDU number: 0x%02x", tpdu_nr);
1038 while(li > P_VAR_PART_NAK + i - 1) {
1039 switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
1041 length = pd[offset + P_VAR_PART_NAK + i + 1];
1042 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1044 proto_tree_add_text(cotp_tree,
1045 offset + P_VAR_PART_NAK + i + 0, 1,
1046 "Parameter code: 0x%02x (checksum)", code);
1047 proto_tree_add_text(cotp_tree,
1048 offset + P_VAR_PART_NAK + i + 1, 1,
1049 "Parameter length: 0x%02x", length);
1050 proto_tree_add_text(cotp_tree,
1051 offset + P_VAR_PART_NAK + i + 2, 2,
1052 "Checksum: 0x%04x", checksum);
1057 length = pd[offset + P_VAR_PART_NAK + i + 1];
1058 r_lower_window_edge =
1059 EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
1060 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
1061 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
1063 proto_tree_add_text(cotp_tree,
1064 offset + P_VAR_PART_NAK + i + 0, 1,
1065 "Parameter code: 0x%02x (flow control)",
1067 proto_tree_add_text(cotp_tree,
1068 offset + P_VAR_PART_NAK + i + 1, 1,
1069 "Parameter length: 0x%02x", length);
1070 proto_tree_add_text(cotp_tree,
1071 offset + P_VAR_PART_NAK + i + 2, 4,
1072 "Lower window edge: 0x%08x",
1073 r_lower_window_edge);
1074 proto_tree_add_text(cotp_tree,
1075 offset + P_VAR_PART_NAK + i + 6, 2,
1076 "Sequence number: 0x%04x",
1078 proto_tree_add_text(cotp_tree,
1079 offset + P_VAR_PART_NAK + i + 8, 2,
1086 length = pd[offset + P_VAR_PART_NAK + i + 1];
1087 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1089 proto_tree_add_text(cotp_tree,
1090 offset + P_VAR_PART_NAK + i + 0, 1,
1091 "Parameter code: 0x%02x (seq number)", code);
1092 proto_tree_add_text(cotp_tree,
1093 offset + P_VAR_PART_NAK + i + 1, 1,
1094 "Parameter length: 0x%02x", length);
1095 proto_tree_add_text(cotp_tree,
1096 offset + P_VAR_PART_NAK + i + 2, 2,
1097 "Sequence number: 0x%04x", seq_nr);
1102 length = pd[offset + P_VAR_PART_NAK + i + 1];
1104 proto_tree_add_text(cotp_tree,
1105 offset + P_VAR_PART_NAK + i + 0, 1,
1106 "Parameter code: 0x%02x (unknown)", code);
1107 proto_tree_add_text(cotp_tree,
1108 offset + P_VAR_PART_NAK + i + 1, 1,
1109 "Parameter length: 0x%02x", length);
1110 proto_tree_add_text(cotp_tree,
1111 offset + P_VAR_PART_NAK + i + 2, length,
1112 "Parameter value: <not shown>");
1118 } else { /* extended format */
1120 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1121 cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
1123 if (check_col(fd, COL_PROTOCOL))
1124 col_add_str(fd, COL_PROTOCOL, "COTP");
1125 if (check_col(fd, COL_INFO))
1126 col_add_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
1130 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1131 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1132 proto_tree_add_text(cotp_tree, offset, 1,
1133 "Length indicator: %d", li);
1134 proto_tree_add_text(cotp_tree, offset + 1, 1,
1135 "TPDU code: Ox%x (AK)", tpdu);
1136 proto_tree_add_text(cotp_tree, offset + 2, 2,
1137 "Destination reference: 0x%04x", dst_ref);
1138 proto_tree_add_text(cotp_tree, offset + 4, 4,
1139 "Your TPDU number: 0x%08x", tpdu_nr);
1140 proto_tree_add_text(cotp_tree, offset + 8, 2,
1141 "Credit: 0x%04x", cdt_in_ak);
1144 while(li > P_VAR_PART_EAK + i - 1) {
1145 switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
1147 length = pd[offset + P_VAR_PART_EAK + i + 1];
1148 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1150 proto_tree_add_text(cotp_tree,
1151 offset + P_VAR_PART_EAK + i + 0, 1,
1152 "Parameter code: 0x%02x (checksum)", code);
1153 proto_tree_add_text(cotp_tree,
1154 offset + P_VAR_PART_EAK + i + 1, 1,
1155 "Parameter length: 0x%02x", length);
1156 proto_tree_add_text(cotp_tree,
1157 offset + P_VAR_PART_EAK + i + 2, 2,
1158 "Checksum: 0x%04x", checksum);
1163 length = pd[offset + P_VAR_PART_EAK + i + 1];
1164 r_lower_window_edge =
1165 EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
1166 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
1167 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
1169 proto_tree_add_text(cotp_tree,
1170 offset + P_VAR_PART_EAK + i + 0, 1,
1171 "Parameter code: 0x%02x (flow control)",
1173 proto_tree_add_text(cotp_tree,
1174 offset + P_VAR_PART_EAK + i + 1, 1,
1175 "Parameter length: 0x%02x", length);
1176 proto_tree_add_text(cotp_tree,
1177 offset + P_VAR_PART_EAK + i + 2, 4,
1178 "Lower window edge: 0x%08x",
1179 r_lower_window_edge);
1180 proto_tree_add_text(cotp_tree,
1181 offset + P_VAR_PART_EAK + i + 6, 2,
1182 "Sequence number: 0x%04x",
1184 proto_tree_add_text(cotp_tree,
1185 offset + P_VAR_PART_EAK + i + 8, 2,
1192 length = pd[offset + P_VAR_PART_EAK + i + 1];
1193 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1195 proto_tree_add_text(cotp_tree,
1196 offset + P_VAR_PART_EAK + i + 0, 1,
1197 "Parameter code: 0x%02x (seq number)", code);
1198 proto_tree_add_text(cotp_tree,
1199 offset + P_VAR_PART_EAK + i + 1, 1,
1200 "Parameter length: 0x%02x", length);
1201 proto_tree_add_text(cotp_tree,
1202 offset + P_VAR_PART_EAK + i + 2, 2,
1203 "Sequence number: 0x%04x", seq_nr);
1208 length = pd[offset + P_VAR_PART_EAK + i + 1];
1210 proto_tree_add_text(cotp_tree,
1211 offset + P_VAR_PART_EAK + i + 0, 1,
1212 "Parameter code: 0x%02x (unknown)", code);
1213 proto_tree_add_text(cotp_tree,
1214 offset + P_VAR_PART_EAK + i + 1, 1,
1215 "Parameter length: 0x%02x", length);
1216 proto_tree_add_text(cotp_tree,
1217 offset + P_VAR_PART_EAK + i + 2, length,
1218 "Parameter value: <not shown>");
1225 } /* is_LI_NORMAL_AK */
1228 dissect_data(pd, offset, fd, tree);
1232 } /* osi_decode_AK */
1234 static int osi_decode_EA(const u_char *pd, int offset,
1235 frame_data *fd, proto_tree *tree)
1237 proto_tree *cotp_tree;
1240 u_short checksum = 0;
1248 case LI_NORMAL_EA_WITH_CHECKSUM :
1249 tpdu_nr = pd[offset + P_TPDU_NR_234];
1250 code = pd[offset + P_VAR_PART_NDT];
1251 length = pd[offset + P_VAR_PART_NDT + 1];
1252 if (code != VP_CHECKSUM || length != 1)
1254 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
1256 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1257 tpdu_nr = pd[offset + P_TPDU_NR_234];
1259 case LI_EXTENDED_EA_WITH_CHECKSUM :
1260 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1261 code = pd[offset + P_VAR_PART_EDT];
1262 length = pd[offset + P_VAR_PART_EDT + 1];
1263 if (code != VP_CHECKSUM || length != 1)
1265 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
1267 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1268 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1270 default : /* bad TPDU */
1276 if (check_col(fd, COL_PROTOCOL))
1277 col_add_str(fd, COL_PROTOCOL, "COTP");
1278 if (check_col(fd, COL_INFO))
1279 col_add_fstr(fd, COL_INFO,
1280 "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1283 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1284 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1285 proto_tree_add_text(cotp_tree, offset, 1,
1286 "Length indicator: %d", li);
1287 proto_tree_add_text(cotp_tree, offset + 1, 1,
1288 "TPDU code: Ox%x (EA)", tpdu);
1289 proto_tree_add_text(cotp_tree, offset + 2, 2,
1290 "Destination reference: 0x%04x", dst_ref);
1293 case LI_NORMAL_EA_WITH_CHECKSUM :
1294 proto_tree_add_text(cotp_tree, offset + 4, 1,
1295 "Your TPDU number: 0x%02x", tpdu_nr);
1296 proto_tree_add_text(cotp_tree, offset + 5, 1,
1297 "Parameter code: 0x%02x (checksum)", code);
1298 proto_tree_add_text(cotp_tree, offset + 6, 1,
1299 "Parameter length: 0x%02x", length);
1300 proto_tree_add_text(cotp_tree, offset + 7, 2,
1301 "Checksum: 0x%04x", checksum);
1303 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1304 proto_tree_add_text(cotp_tree, offset + 4, 1,
1305 "Your TPDU number: 0x%02x", tpdu_nr);
1307 case LI_EXTENDED_EA_WITH_CHECKSUM :
1308 proto_tree_add_text(cotp_tree, offset + 4, 4,
1309 "Your TPDU number: 0x%08x", tpdu_nr);
1310 proto_tree_add_text(cotp_tree, offset + 8, 1,
1311 "Parameter code: 0x%02x (checksum)", code);
1312 proto_tree_add_text(cotp_tree, offset + 9, 1,
1313 "Parameter length: 0x%02x", length);
1314 proto_tree_add_text(cotp_tree, offset + 10, 2,
1315 "Checksum: 0x%04x", checksum);
1317 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1318 proto_tree_add_text(cotp_tree, offset + 4, 4,
1319 "Your TPDU number: 0x%08x", tpdu_nr);
1327 dissect_data(pd, offset, fd, tree);
1331 } /* osi_decode_EA */
1333 static int osi_decode_ER(const u_char *pd, int offset,
1334 frame_data *fd, proto_tree *tree)
1336 proto_tree *cotp_tree;
1343 switch(pd[offset + P_REJECT_ER]) {
1345 str = "Reason not specified";
1348 str = "Invalid parameter code";
1351 str = "Invalid TPDU type";
1354 str = "Invalid parameter value";
1362 if (check_col(fd, COL_PROTOCOL))
1363 col_add_str(fd, COL_PROTOCOL, "COTP");
1364 if (check_col(fd, COL_INFO))
1365 col_add_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1368 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1369 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1370 proto_tree_add_text(cotp_tree, offset, 1,
1371 "Length indicator: %d", li);
1372 proto_tree_add_text(cotp_tree, offset + 1, 1,
1373 "TPDU code: Ox%x (ER)", tpdu);
1374 proto_tree_add_text(cotp_tree, offset + 2, 2,
1375 "Destination reference: 0x%04x", dst_ref);
1376 proto_tree_add_text(cotp_tree, offset + 4, 1,
1377 "Reject cause: %s", str);
1381 dissect_data(pd, offset, fd, tree);
1385 } /* osi_decode_ER */
1387 static void dissect_cotp_internal(const u_char *pd, int offset, frame_data *fd,
1388 proto_tree *tree, gboolean uses_inactive_subset)
1392 if (((li = pd[offset + P_LI]) == 0) ||
1393 (!BYTES_ARE_IN_FRAME(offset, P_LI + li + 1))) {
1394 dissect_data(pd, offset, fd, tree);
1398 tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
1399 cdt = pd[offset + P_CDT] & 0x0F;
1400 dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
1405 status = osi_decode_CC(pd, offset, fd, tree);
1408 status = osi_decode_DR(pd, offset, fd, tree);
1411 status = osi_decode_DT(pd, offset, fd, tree, uses_inactive_subset);
1414 status = osi_decode_ED(pd, offset, fd, tree);
1417 status = osi_decode_RJ(pd, offset, fd, tree);
1420 status = osi_decode_DC(pd, offset, fd, tree);
1423 status = osi_decode_AK(pd, offset, fd, tree);
1426 status = osi_decode_EA(pd, offset, fd, tree);
1429 status = osi_decode_ER(pd, offset, fd, tree);
1435 if (status == -1) /* incorrect TPDU */
1436 dissect_data(pd, offset, fd, tree);
1438 } /* dissect_cotp_internal */
1440 void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
1443 dissect_cotp_internal(pd, offset, fd, tree, FALSE);
1451 #define MAX_NSAP_LEN 20
1453 static gchar *print_nsap(const u_char *nsap, int length)
1456 /* to do : real NSAP decoding */
1458 static gchar str[3][MAX_NSAP_LEN * 3 + 1];
1462 if (cur == &str[0][0]) {
1464 } else if (cur == &str[1][0]) {
1471 if (length <= 0 || length > MAX_NSAP_LEN)
1472 sprintf(cur, "<invalid NSAP>");
1474 while (length != 1) {
1475 sprintf(tmp, "%02x:", *nsap ++);
1479 sprintf(tmp, "%02x", *nsap);
1485 void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
1489 struct clnp_header clnp;
1490 proto_tree *clnp_tree = NULL;
1492 u_char src_len, dst_len, nsel;
1493 u_int first_offset = offset;
1495 /* avoid alignment problem */
1496 memcpy(&clnp, &pd[offset], sizeof(clnp));
1498 if (clnp.cnf_proto_id == NLPID_NULL) {
1500 ti = proto_tree_add_item(tree, proto_clnp, offset, 1, NULL);
1501 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1502 proto_tree_add_uint_format(clnp_tree, hf_clnp_id, offset, 1,
1506 dissect_cotp_internal(pd, offset+1, fd, tree, TRUE);
1510 if (!BYTES_ARE_IN_FRAME(offset, sizeof(clnp))) {
1511 dissect_data(pd, offset, fd, tree);
1515 /* return if version not known */
1516 if (clnp.cnf_vers != ISO8473_V1) {
1517 dissect_data(pd, offset, fd, tree);
1521 /* fixed part decoding */
1524 ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL);
1525 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1526 proto_tree_add_item(clnp_tree, hf_clnp_id, offset, 1,
1528 proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1,
1530 proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1,
1532 proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, offset + 3, 1,
1534 "TTL: %d (%d secs)",
1535 clnp.cnf_ttl, clnp.cnf_ttl / 2);
1536 proto_tree_add_uint_format(clnp_tree, hf_clnp_type, offset + 4, 1,
1538 "Type code: 0x%02x (%s%s%s%s)",
1540 (clnp.cnf_type & CNF_SEG_OK) ? "S " : "",
1541 (clnp.cnf_type & CNF_MORE_SEGS) ? "M " : "",
1542 (clnp.cnf_type & CNF_ERR_OK) ? "E " : "",
1543 (clnp.cnf_type & CNF_TYPE) == DT_NPDU ?
1545 proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2,
1546 EXTRACT_SHORT(&clnp.cnf_seglen_msb));
1547 proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, offset + 7, 2,
1548 EXTRACT_SHORT(&clnp.cnf_cksum_msb),
1550 EXTRACT_SHORT(&clnp.cnf_cksum_msb));
1553 /* stop here if header is not complete */
1555 if (!BYTES_ARE_IN_FRAME(offset, clnp.cnf_hdr_len)) {
1556 dissect_data(pd, offset, fd, tree);
1562 offset += P_ADDRESS_PART;
1563 dst_len = pd[offset];
1564 nsel = pd[offset + dst_len];
1565 src_len = pd[offset + dst_len + 1];
1568 proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1,
1570 proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len,
1572 "Destination address: %s",
1573 print_nsap(&pd[offset + 1], dst_len));
1574 proto_tree_add_item(clnp_tree, hf_clnp_src_length,
1575 offset + 1 + dst_len, 1, src_len);
1576 proto_tree_add_bytes_format(clnp_tree, hf_clnp_src,
1577 offset + dst_len + 2, src_len,
1578 &pd[offset + dst_len + 2],
1579 "Source address: %s",
1580 print_nsap(&pd[offset + dst_len + 2], src_len));
1583 if (check_col(fd, COL_RES_NET_SRC))
1584 col_add_fstr(fd, COL_RES_NET_SRC, "%s",
1585 print_nsap(&pd[offset + dst_len + 2], src_len));
1586 if (check_col(fd, COL_RES_NET_DST))
1587 col_add_fstr(fd, COL_RES_NET_DST, "%s",
1588 print_nsap(&pd[offset + 1], dst_len));
1590 /* Segmentation Part */
1592 offset += dst_len + src_len + 2;
1594 if (tree && (clnp.cnf_type & CNF_SEG_OK)) {
1595 struct clnp_segment seg;
1596 memcpy(&seg, &pd[offset], sizeof(seg));
1598 proto_tree_add_text(clnp_tree, offset, 2,
1599 "Data unit identifier: 0x%04x",
1600 EXTRACT_SHORT(&pd[offset]));
1601 proto_tree_add_text(clnp_tree, offset + 2 , 2,
1602 "Segment offset: 0x%04x",
1603 EXTRACT_SHORT(&pd[offset + 2]));
1604 proto_tree_add_text(clnp_tree, offset + 4 , 2,
1605 "Total length: 0x%04x",
1606 EXTRACT_SHORT(&pd[offset + 4]));
1612 /* To do : decode options */
1614 proto_tree_add_text(clnp_tree, offset,
1615 clnp.cnf_hdr_len + first_offset - offset,
1616 "Options/Data: <not shown>");
1620 offset = first_offset + clnp.cnf_hdr_len;
1622 if (!IS_DATA_IN_FRAME(offset))
1625 /* continue with COTP if any */
1627 if (nsel == NSEL_TP) /* just guessing here - valid for DECNet-OSI */
1628 dissect_cotp_internal(pd, offset, fd, tree, FALSE);
1630 dissect_data(pd, offset, fd, tree);
1632 } /* dissect_clnp */
1635 /* main entry point */
1637 const value_string nlpid_vals[] = {
1638 { NLPID_NULL, "NULL" },
1639 { NLPID_T_70, "T.70" },
1640 { NLPID_X_633, "X.633" },
1641 { NLPID_Q_931, "Q.931" },
1642 { NLPID_Q_2931, "Q.2931" },
1643 { NLPID_Q_2119, "Q.2119" },
1644 { NLPID_SNAP, "SNAP" },
1645 { NLPID_ISO8473_CLNP, "CLNP" },
1646 { NLPID_ISO9542_ESIS, "ESIS" },
1647 { NLPID_ISO10589_ISIS, "ISIS" },
1648 { NLPID_ISO10747, "ISO 10747" },
1649 { NLPID_ISO9542X25_ESIS, "ESIS (X.25)" },
1650 { NLPID_ISO10030, "ISO 10030" },
1651 { NLPID_ISO11577, "ISO 11577" },
1653 { NLPID_PPP, "PPP" },
1657 void dissect_osi(const u_char *pd, int offset, frame_data *fd,
1661 switch (pd[offset]) {
1663 /* ESIS is not currently decoded */
1665 case NLPID_ISO8473_CLNP:
1666 case NLPID_NULL: /* "Inactive Subset" of ISO 8473 CLNP */
1667 if (check_col(fd, COL_PROTOCOL)) {
1668 col_add_str(fd, COL_PROTOCOL, "CLNP");
1670 dissect_clnp(pd, offset, fd, tree);
1672 case NLPID_ISO9542_ESIS:
1673 if (check_col(fd, COL_PROTOCOL)) {
1674 col_add_str(fd, COL_PROTOCOL, "ESIS");
1676 dissect_data(pd, offset, fd, tree);
1678 case NLPID_ISO9542X25_ESIS:
1679 if (check_col(fd, COL_PROTOCOL)) {
1680 col_add_str(fd, COL_PROTOCOL, "ESIS (X.25)");
1682 dissect_data(pd, offset, fd, tree);
1684 case NLPID_ISO10589_ISIS:
1685 if (check_col(fd, COL_PROTOCOL)) {
1686 col_add_str(fd, COL_PROTOCOL, "ISIS");
1688 dissect_isis(pd, offset, fd, tree);
1691 if (check_col(fd, COL_PROTOCOL)) {
1692 col_add_str(fd, COL_PROTOCOL, "ISO");
1694 if (check_col(fd, COL_INFO)) {
1695 col_add_fstr(fd, COL_INFO, "Unknown ISO protocol (%02x)", pd[offset]);
1697 dissect_data(pd, offset, fd, tree);
1703 void proto_register_clnp(void)
1705 static hf_register_info hf[] = {
1707 { "Protocol identifier", "clnp.id", FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0,
1711 { "Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1715 { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1719 { "TTL", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1723 { "Type code", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1726 { &hf_clnp_pdu_length,
1727 { "PDU segment length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1730 { &hf_clnp_checksum,
1731 { "Checksum", "clnp.checksum",FT_UINT16, BASE_DEC, NULL, 0x0,
1734 { &hf_clnp_dest_length,
1735 { "Destination address length", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1739 { "Destination address", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0,
1742 { &hf_clnp_src_length,
1743 { "Source address length","clnp.ssap.len",FT_UINT8, BASE_DEC, NULL, 0x0,
1747 { "Source address", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0,
1750 static gint *ett[] = {
1754 proto_clnp = proto_register_protocol("ISO CLNP", "clnp");
1755 proto_register_field_array(proto_clnp, hf, array_length(hf));
1756 proto_register_subtree_array(ett, array_length(ett));
1759 void proto_register_cotp(void)
1761 /* static hf_register_info hf[] = {
1763 { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
1765 static gint *ett[] = {
1769 proto_cotp = proto_register_protocol("ISO COTP", "cotp");
1770 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
1771 proto_register_subtree_array(ett, array_length(ett));