2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-osi.c,v 1.13 1999/12/15 04:34:19 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 /* protocols and fields */
50 static int proto_clnp = -1;
52 static int hf_clnp_id = -1;
53 static int hf_clnp_length = -1;
54 static int hf_clnp_version = -1;
55 static int hf_clnp_ttl = -1;
56 static int hf_clnp_type = -1;
57 static int hf_clnp_pdu_length = -1;
58 static int hf_clnp_checksum = -1;
59 static int hf_clnp_dest_length = -1;
60 static int hf_clnp_dest = -1;
61 static int hf_clnp_src_length = -1;
62 static int hf_clnp_src = -1;
64 static gint ett_clnp = -1;
66 static int proto_cotp = -1;
68 static gint ett_cotp = -1;
70 /* Network layer protocol identifiers */
72 #define ISO8473_CLNP 0x81
73 #define ISO9542_ESIS 0x82
74 #define ISO10589_ISIS 0x83
75 #define ISO9542X25_ESIS 0x8a
78 * ISO8473 OSI CLNP definition (see RFC994)
80 * _________________________________
82 * |_________________________________|
84 * |_________________________________|
85 * | Segmentation Part (optional) |
86 * |_________________________________|
87 * | Options Part (optional) |
88 * |_________________________________|
90 * |_________________________________|
93 #define ISO8473_V1 0x01 /* CLNP version 1 */
98 u_char cnf_proto_id; /* network layer protocol identifier */
99 u_char cnf_hdr_len; /* length indicator (octets) */
100 u_char cnf_vers; /* version/protocol identifier extension */
101 u_char cnf_ttl; /* lifetime (500 milliseconds) */
102 u_char cnf_type; /* type code */
103 u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
104 u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
105 u_char cnf_cksum_msb; /* checksum high byte */
106 u_char cnf_cksum_lsb; /* checksum low byte */
109 #define CNF_TYPE 0x1f
110 #define CNF_ERR_OK 0x20
111 #define CNF_MORE_SEGS 0x40
112 #define CNF_SEG_OK 0x80
119 #define P_ADDRESS_PART 9
121 /* Segmentation part */
123 struct clnp_segment {
124 u_short cng_id; /* data unit identifier */
125 u_short cng_off; /* segment offset */
126 u_short cng_tot_len; /* total length */
131 #define NSEL_NET 0x00
136 * ISO8073 OSI COTP definition (see RFC905)
139 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
141 /* TPDU definition */
161 #define P_TPDU_NR_0_1 2
162 #define P_TPDU_NR_234 4
163 #define P_VAR_PART_NDT 5
164 #define P_VAR_PART_EDT 8
165 #define P_VAR_PART_NAK 5
166 #define P_VAR_PART_CC 7
167 #define P_VAR_PART_EAK 10
168 #define P_VAR_PART_DC 6
169 #define P_VAR_PART_DR 7
170 #define P_CDT_IN_AK 8
171 #define P_CDT_IN_RJ 8
172 #define P_REJECT_ER 4
173 #define P_REASON_IN_DR 6
174 #define P_CLASS_OPTION 6
176 /* TPDU length indicator */
178 #define LI_NORMAL_DT_CLASS_01 2
179 #define LI_NORMAL_DT_WITH_CHECKSUM 8
180 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
181 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
182 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
183 #define LI_NORMAL_EA_WITH_CHECKSUM 8
184 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
185 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
186 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
187 #define LI_NORMAL_RJ 4
188 #define LI_EXTENDED_RJ 9
194 #define LI_DC_WITH_CHECKSUM 9
195 #define LI_DC_WITHOUT_CHECKSUM 5
196 #define is_LI_NORMAL_AK(p) ( p & 0x01 )
200 #define VP_ACK_TIME 0x85
201 #define VP_RES_ERROR 0x86
202 #define VP_PRIORITY 0x87
203 #define VP_TRANSIT_DEL 0x88
204 #define VP_THROUGHPUT 0x89
205 #define VP_SEQ_NR 0x8A /* in AK */
206 #define VP_REASSIGNMENT 0x8B
207 #define VP_FLOW_CNTL 0x8C /* in AK */
208 #define VP_TPDU_SIZE 0xC0
209 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
210 #define VP_DST_TSAP 0xC2
211 #define VP_CHECKSUM 0xC3
212 #define VP_VERSION_NR 0xC4
213 #define VP_PROTECTION 0xC5
214 #define VP_OPT_SEL 0xC6
215 #define VP_PROTO_CLASS 0xC7
219 #define EXTRACT_SHORT(p) pntohs(p)
220 #define EXTRACT_LONG(p) pntohl(p)
222 /* global variables */
224 static u_char li, tpdu, cdt; /* common fields */
225 static u_short dst_ref;
227 /* function definitions */
229 static int osi_decode_DR(const u_char *pd, int offset,
230 frame_data *fd, proto_tree *tree)
232 proto_tree *cotp_tree;
241 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
242 reason = pd[offset + P_REASON_IN_DR];
245 case (128+0): str = "Normal Disconnect"; break;
246 case (128+1): str = "Remote transport enity congestion"; break;
247 case (128+2): str = "Connection negotiation failed"; break;
248 case (128+3): str = "Duplicate source reference"; break;
249 case (128+4): str = "Mismatched references"; break;
250 case (128+5): str = "Protocol error"; break;
251 case (128+7): str = "Reference overflow"; break;
252 case (128+8): str = "Connection requestion refused"; break;
253 case (128+10):str = "Header or parameter length invalid"; break;
254 case (0): str = "Reason not specified"; break;
255 case (1): str = "Congestion at TSAP"; break;
256 case (2): str = "Session entity not attached to TSAP"; break;
257 case (3): str = "Address unknown"; break;
263 if (check_col(fd, COL_PROTOCOL))
264 col_add_str(fd, COL_PROTOCOL, "COTP");
265 if (check_col(fd, COL_INFO))
266 col_add_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
270 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
271 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
272 proto_tree_add_text(cotp_tree, offset, 1,
273 "Length indicator: %d", li);
274 proto_tree_add_text(cotp_tree, offset + 1, 1,
275 "TPDU code: Ox%x (DR)", tpdu);
276 proto_tree_add_text(cotp_tree, offset + 2, 2,
277 "Destination reference: 0x%04x", dst_ref);
278 proto_tree_add_text(cotp_tree, offset + 4, 2,
279 "Source reference: 0x%04x", src_ref);
280 proto_tree_add_text(cotp_tree, offset + 6, 1,
285 dissect_data(pd, offset, fd, tree);
289 } /* osi_decode_DR */
291 static int osi_decode_DT(const u_char *pd, int offset,
292 frame_data *fd, proto_tree *tree)
294 proto_tree *cotp_tree;
297 u_short checksum = 0;
298 u_char code = 0, length = 0;
302 case LI_NORMAL_DT_WITH_CHECKSUM :
303 tpdu_nr = pd[offset + P_TPDU_NR_234];
304 if ( tpdu_nr & 0x80 )
305 tpdu_nr = tpdu_nr & 0x7F;
308 code = pd[offset + P_VAR_PART_NDT];
309 if (code == VP_CHECKSUM)
310 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
314 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
315 tpdu_nr = pd[offset + P_TPDU_NR_234];
316 if ( tpdu_nr & 0x80 )
317 tpdu_nr = tpdu_nr & 0x7F;
321 case LI_EXTENDED_DT_WITH_CHECKSUM :
322 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
323 if ( tpdu_nr & 0x80000000 )
324 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
327 code = pd[offset + P_VAR_PART_EDT];
328 if (code == VP_CHECKSUM)
329 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
333 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
334 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
335 if ( tpdu_nr & 0x80000000 )
336 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
340 case LI_NORMAL_DT_CLASS_01 :
341 tpdu_nr = pd[offset + P_TPDU_NR_0_1];
342 if ( tpdu_nr & 0x80 )
343 tpdu_nr = tpdu_nr & 0x7F;
347 default : /* bad TPDU */
353 if (check_col(fd, COL_PROTOCOL))
354 col_add_str(fd, COL_PROTOCOL, "COTP");
355 if (check_col(fd, COL_INFO))
356 col_add_fstr(fd, COL_INFO, "DT TPDU (%d) dst-ref: 0x%04x %s",
359 (fragment)? "(fragment)" : "");
362 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
363 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
364 proto_tree_add_text(cotp_tree, offset, 1,
365 "Length indicator: %d", li);
366 proto_tree_add_text(cotp_tree, offset + 1, 1,
367 "TPDU code: Ox%x (DT)", tpdu);
369 if (li != LI_NORMAL_DT_CLASS_01)
370 proto_tree_add_text(cotp_tree, offset + 2, 2,
371 "Destination reference: 0x%04x", dst_ref);
374 case LI_NORMAL_DT_WITH_CHECKSUM :
375 proto_tree_add_text(cotp_tree, offset + 4, 1,
376 "TPDU number: 0x%02x (%s)",
378 (fragment)? "fragment":"complete");
379 proto_tree_add_text(cotp_tree,
380 offset + P_VAR_PART_NDT, 1,
381 "Parameter code: 0x%02x (checksum)", code);
382 proto_tree_add_text(cotp_tree,
383 offset + P_VAR_PART_NDT + 1, 1,
384 "Parameter length: 0x%02x", length);
385 proto_tree_add_text(cotp_tree,
386 offset + P_VAR_PART_NDT + 2, length,
387 "Checksum: 0x%04x", checksum);
389 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
390 proto_tree_add_text(cotp_tree, offset + 4, 1,
391 "TPDU number: 0x%02x (%s)",
393 (fragment)? "fragment":"complete");
395 case LI_EXTENDED_DT_WITH_CHECKSUM :
396 proto_tree_add_text(cotp_tree, offset + 4, 4,
397 "TPDU number: 0x%08x (%s)",
399 (fragment)? "fragment":"complete");
400 proto_tree_add_text(cotp_tree,
401 offset + P_VAR_PART_EDT, 1,
402 "Parameter code: 0x%02x (checksum)", code);
403 proto_tree_add_text(cotp_tree,
404 offset + P_VAR_PART_EDT + 1, 1,
405 "Parameter length: 0x%02x", length);
406 proto_tree_add_text(cotp_tree,
407 offset + P_VAR_PART_EDT + 2, length,
408 "Checksum: 0x%04x", checksum);
410 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
411 proto_tree_add_text(cotp_tree, offset + 4, 4,
412 "TPDU number: 0x%08x (%s)",
414 (fragment)? "fragment":"complete");
416 case LI_NORMAL_DT_CLASS_01 :
417 proto_tree_add_text(cotp_tree, offset + 2, 1,
418 "TPDU number: 0x%02x (%s)",
420 (fragment)? "fragment":"complete");
426 dissect_data(pd, offset, fd, tree);
430 } /* osi_decode_DT */
432 static int osi_decode_ED(const u_char *pd, int offset,
433 frame_data *fd, proto_tree *tree)
435 proto_tree *cotp_tree;
438 u_short checksum = 0;
439 u_char code = 0, length = 0;
441 /* ED TPDUs are never fragmented */
444 case LI_NORMAL_DT_WITH_CHECKSUM :
445 tpdu_nr = pd[offset + P_TPDU_NR_234];
446 if ( tpdu_nr & 0x80 )
447 tpdu_nr = tpdu_nr & 0x7F;
450 code = pd[offset + P_VAR_PART_NDT];
451 length = pd[offset + P_VAR_PART_NDT + 1];
452 if (code == VP_CHECKSUM)
453 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
457 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
458 tpdu_nr = pd[offset + P_TPDU_NR_234];
459 if ( tpdu_nr & 0x80 )
460 tpdu_nr = tpdu_nr & 0x7F;
464 case LI_EXTENDED_DT_WITH_CHECKSUM :
465 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
466 if ( tpdu_nr & 0x80000000 )
467 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
470 code = pd[offset + P_VAR_PART_EDT];
471 length = pd[offset + P_VAR_PART_EDT + 1];
472 if (code == VP_CHECKSUM)
473 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
477 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
478 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
479 if ( tpdu_nr & 0x80000000 )
480 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
484 default : /* bad TPDU */
490 if (check_col(fd, COL_PROTOCOL))
491 col_add_str(fd, COL_PROTOCOL, "COTP");
492 if (check_col(fd, COL_INFO))
493 col_add_fstr(fd, COL_INFO, "ED TPDU (%d) dst-ref: 0x%04x",
497 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
498 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
499 proto_tree_add_text(cotp_tree, offset, 1,
500 "Length indicator: %d", li);
501 proto_tree_add_text(cotp_tree, offset + 1, 1,
502 "TPDU code: Ox%x (ED)", tpdu);
503 proto_tree_add_text(cotp_tree, offset + 2, 2,
504 "Destination reference: 0x%04x", dst_ref);
507 case LI_NORMAL_DT_WITH_CHECKSUM :
508 proto_tree_add_text(cotp_tree, offset + 4, 1,
509 "TPDU number: 0x%02x", tpdu_nr);
510 proto_tree_add_text(cotp_tree,
511 offset + P_VAR_PART_NDT, 1,
512 "Parameter code: 0x%02x (checksum)", code);
513 proto_tree_add_text(cotp_tree,
514 offset + P_VAR_PART_NDT + 1, 1,
515 "Parameter length: 0x%02x", length);
516 proto_tree_add_text(cotp_tree,
517 offset + P_VAR_PART_NDT + 2, length,
518 "Checksum: 0x%04x", checksum);
520 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
521 proto_tree_add_text(cotp_tree, offset + 4, 1,
522 "TPDU number: 0x%02x", tpdu_nr);
524 case LI_EXTENDED_DT_WITH_CHECKSUM :
525 proto_tree_add_text(cotp_tree, offset + 4, 4,
526 "TPDU number: 0x%02x", tpdu_nr);
527 proto_tree_add_text(cotp_tree,
528 offset + P_VAR_PART_EDT, 1,
529 "Parameter code: 0x%02x (checksum)", code);
530 proto_tree_add_text(cotp_tree,
531 offset + P_VAR_PART_EDT + 1, 1,
532 "Parameter length: 0x%02x", length);
533 proto_tree_add_text(cotp_tree,
534 offset + P_VAR_PART_EDT + 2, length,
535 "Checksum: 0x%04x", checksum);
537 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
538 proto_tree_add_text(cotp_tree, offset + 4, 4,
539 "TPDU number: 0x%02x", tpdu_nr);
545 dissect_data(pd, offset, fd, tree);
549 } /* osi_decode_ED */
551 static int osi_decode_RJ(const u_char *pd, int offset,
552 frame_data *fd, proto_tree *tree)
554 proto_tree *cotp_tree;
561 tpdu_nr = pd[offset + P_TPDU_NR_234];
563 case LI_EXTENDED_RJ :
564 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
565 credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
573 if (check_col(fd, COL_PROTOCOL))
574 col_add_str(fd, COL_PROTOCOL, "COTP");
575 if (check_col(fd, COL_INFO))
576 col_add_fstr(fd, COL_INFO, "RJ TPDU (%d) dst-ref: 0x%04x",
580 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
581 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
582 proto_tree_add_text(cotp_tree, offset, 1,
583 "Length indicator: %d", li);
584 proto_tree_add_text(cotp_tree, offset + 1, 1,
585 "TPDU code: Ox%x (RJ)", tpdu);
586 if (li == LI_NORMAL_RJ)
587 proto_tree_add_text(cotp_tree, offset + 1, 1,
589 proto_tree_add_text(cotp_tree, offset + 2, 2,
590 "Destination reference: 0x%04x", dst_ref);
591 if (li == LI_NORMAL_RJ)
592 proto_tree_add_text(cotp_tree, offset + 4, 1,
593 "Your TPDU number: 0x%02x", tpdu_nr);
595 proto_tree_add_text(cotp_tree, offset + 4, 4,
596 "Your TPDU number: 0x%02x", tpdu_nr);
597 proto_tree_add_text(cotp_tree, offset + 8, 2,
598 "Credit: 0x%02x", credit);
603 dissect_data(pd, offset, fd, tree);
607 } /* osi_decode_RJ */
609 #define MAX_TSAP_LEN 32
611 static gchar *print_tsap(const u_char *tsap, int length)
614 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
618 if (cur == &str[0][0]) {
620 } else if (cur == &str[1][0]) {
626 /* to do: test if all bytes are printable */
629 if (length <= 0 || length > MAX_TSAP_LEN)
630 sprintf(cur, "<unsupported TSAP length>");
632 while (length != 0) {
633 sprintf(tmp, "%02x", *tsap ++);
642 static int osi_decode_CC(const u_char *pd, int offset,
643 frame_data *fd, proto_tree *tree)
646 /* CC & CR decoding in the same function */
648 proto_tree *cotp_tree = NULL;
650 u_short src_ref, checksum;
651 u_char class_option, code, length;
654 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
655 class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
656 if (class_option > 4)
659 if (check_col(fd, COL_PROTOCOL))
660 col_add_str(fd, COL_PROTOCOL, "COTP");
661 if (check_col(fd, COL_INFO))
662 col_add_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
663 (tpdu == CR_TPDU) ? "CR" : "CC",
668 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
669 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
670 proto_tree_add_text(cotp_tree, offset, 1,
671 "Length indicator: %d", li);
672 proto_tree_add_text(cotp_tree, offset + 1, 1,
673 "TPDU code: Ox%x (%s)", tpdu,
674 (tpdu == CR_TPDU) ? "CR" : "CC");
675 proto_tree_add_text(cotp_tree, offset + 2, 2,
676 "Destination reference: 0x%04x", dst_ref);
677 proto_tree_add_text(cotp_tree, offset + 4, 2,
678 "Source reference: 0x%04x", src_ref);
679 proto_tree_add_text(cotp_tree, offset + 6, 1,
680 "Class option: 0x%02x", class_option);
684 while(li > P_VAR_PART_CC + i - 1) {
687 u_short s, s1,s2,s3,s4;
690 switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
692 length = pd[offset + P_VAR_PART_CC + i + 1];
693 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
694 proto_tree_add_text(cotp_tree,
695 offset + P_VAR_PART_CC + i, 1,
696 "Parameter code: 0x%02x (checksum)", code);
697 proto_tree_add_text(cotp_tree,
698 offset + P_VAR_PART_CC + i + 1, 1,
699 "Parameter length: 0x%02x", length);
700 proto_tree_add_text(cotp_tree,
701 offset + P_VAR_PART_CC + i + 2, length,
702 "Checksum: 0x%04x", checksum);
706 length = pd[offset + P_VAR_PART_CC + i + 1];
707 proto_tree_add_text(cotp_tree,
708 offset + P_VAR_PART_CC + i, 1,
709 "Parameter code: 0x%02x (src-tsap)", code);
710 proto_tree_add_text(cotp_tree,
711 offset + P_VAR_PART_CC + i + 1, 1,
712 "Parameter length: 0x%02x", length);
713 proto_tree_add_text(cotp_tree,
714 offset + P_VAR_PART_CC + i + 2, length,
715 "Calling TSAP: 0x%s",
716 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
721 length = pd[offset + P_VAR_PART_CC + i + 1];
722 proto_tree_add_text(cotp_tree,
723 offset + P_VAR_PART_CC + i, 1,
724 "Parameter code: 0x%02x (dst-tsap)", code);
725 proto_tree_add_text(cotp_tree,
726 offset + P_VAR_PART_CC + i + 1, 1,
727 "Parameter length: 0x%02x", length);
728 proto_tree_add_text(cotp_tree,
729 offset + P_VAR_PART_CC + i + 2, length,
731 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
736 length = pd[offset + P_VAR_PART_CC + i + 1];
737 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
738 proto_tree_add_text(cotp_tree,
739 offset + P_VAR_PART_CC + i, 1,
740 "Parameter code: 0x%02x (tpdu-size)", code);
741 proto_tree_add_text(cotp_tree,
742 offset + P_VAR_PART_CC + i + 1, 1,
743 "Parameter length: 0x%02x", length);
744 proto_tree_add_text(cotp_tree,
745 offset + P_VAR_PART_CC + i + 2, length,
746 "TPDU size: %d", 2 << c1);
750 length = pd[offset + P_VAR_PART_CC + i + 1];
751 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
752 proto_tree_add_text(cotp_tree,
753 offset + P_VAR_PART_CC + i, 1,
754 "Parameter code: 0x%02x (options)", code);
755 proto_tree_add_text(cotp_tree,
756 offset + P_VAR_PART_CC + i + 1, 1,
757 "Parameter length: 0x%02x", length);
758 if (class_option == 1) {
760 proto_tree_add_text(cotp_tree,
761 offset + P_VAR_PART_CC + i + 2, 1,
762 "Use of network expedited data");
764 proto_tree_add_text(cotp_tree,
765 offset + P_VAR_PART_CC + i + 2, 1,
766 "Non use of network expedited data");
768 proto_tree_add_text(cotp_tree,
769 offset + P_VAR_PART_CC + i + 2, 1,
770 "Use of Receipt confirmation");
772 proto_tree_add_text(cotp_tree,
773 offset + P_VAR_PART_CC + i + 2, 1,
774 "Use of explicit AK variant");
775 } else if (class_option == 4) {
777 proto_tree_add_text(cotp_tree,
778 offset + P_VAR_PART_CC + i + 2, 1,
779 "Use 16 bit checksum ");
781 proto_tree_add_text(cotp_tree,
782 offset + P_VAR_PART_CC + i + 2, 1,
783 "Non-use 16 bit checksum in class 4");
786 proto_tree_add_text(cotp_tree,
787 offset + P_VAR_PART_CC + i + 2, 1,
788 "Use of transport expedited data transfer\n");
790 proto_tree_add_text(cotp_tree,
791 offset + P_VAR_PART_CC + i + 2, 1,
792 "Non-use of transport expedited data transfer");
796 length = pd[offset + P_VAR_PART_CC + i + 1];
797 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
798 proto_tree_add_text(cotp_tree,
799 offset + P_VAR_PART_CC + i, 1,
800 "Parameter code: 0x%02x (ack time)", code);
801 proto_tree_add_text(cotp_tree,
802 offset + P_VAR_PART_CC + i + 1, 1,
803 "Parameter length: 0x%02x", length);
804 proto_tree_add_text(cotp_tree,
805 offset + P_VAR_PART_CC + i + 2, length,
806 "Ack time (ms): %d", s);
810 length = pd[offset + P_VAR_PART_CC + i + 1];
811 t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
812 t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
813 t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
814 t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
815 proto_tree_add_text(cotp_tree,
816 offset + P_VAR_PART_CC + i, 1,
817 "Parameter code: 0x%02x (throughput)", 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, 4,
823 "Target value / calling-called: %d o/s", t1);
824 proto_tree_add_text(cotp_tree,
825 offset + P_VAR_PART_CC + i + 6, 4,
826 "Minimum / calling-called: %d o/s", t2);
827 proto_tree_add_text(cotp_tree,
828 offset + P_VAR_PART_CC + i + 10, 4,
829 "Target value / called-calling: %d o/s", t3);
830 proto_tree_add_text(cotp_tree,
831 offset + P_VAR_PART_CC + i + 14, 4,
832 "Minimum / called-calling: %d o/s", t4);
835 case VP_TRANSIT_DEL :
836 length = pd[offset + P_VAR_PART_CC + i + 1];
837 s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
838 s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
839 s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
840 s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
841 proto_tree_add_text(cotp_tree,
842 offset + P_VAR_PART_CC + i, 1,
843 "Parameter code: 0x%02x (transit delay)", code);
844 proto_tree_add_text(cotp_tree,
845 offset + P_VAR_PART_CC + i + 1, 1,
846 "Parameter length: 0x%02x", length);
847 proto_tree_add_text(cotp_tree,
848 offset + P_VAR_PART_CC + i + 2, 2,
849 "Target value / calling-called: %d ms", s1);
850 proto_tree_add_text(cotp_tree,
851 offset + P_VAR_PART_CC + i + 4, 2,
852 "Minimum / calling-called: %d ms", s2);
853 proto_tree_add_text(cotp_tree,
854 offset + P_VAR_PART_CC + i + 6, 2,
855 "Target value / called-calling: %d ms", s3);
856 proto_tree_add_text(cotp_tree,
857 offset + P_VAR_PART_CC + i + 8, 2,
858 "Minimum / called-calling: %d ms", s4);
862 length = pd[offset + P_VAR_PART_CC + i + 1];
863 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
864 proto_tree_add_text(cotp_tree,
865 offset + P_VAR_PART_CC + i, 1,
866 "Parameter code: 0x%02x (priority)", code);
867 proto_tree_add_text(cotp_tree,
868 offset + P_VAR_PART_CC + i + 1, 1,
869 "Parameter length: 0x%02x", length);
870 proto_tree_add_text(cotp_tree,
871 offset + P_VAR_PART_CC + i + 2, length,
876 case VP_REASSIGNMENT: /* todo */
880 case VP_PROTO_CLASS :
881 default : /* no decoding */
882 length = pd[offset + P_VAR_PART_CC + i + 1];
883 proto_tree_add_text(cotp_tree,
884 offset + P_VAR_PART_CC + i + 0, 1,
885 "Parameter code: 0x%02x", code);
886 proto_tree_add_text(cotp_tree,
887 offset + P_VAR_PART_CC + i + 1, 1,
888 "Parameter length: 0x%02x", length);
889 proto_tree_add_text(cotp_tree,
890 offset + P_VAR_PART_CC + i + 2, length,
891 "Parameter value: <not shown>");
898 dissect_data(pd, offset, fd, tree);
902 } /* osi_decode_CC */
904 static int osi_decode_DC(const u_char *pd, int offset,
905 frame_data *fd, proto_tree *tree)
907 proto_tree *cotp_tree;
909 u_short src_ref, checksum = 0;
910 u_char length = 0, code = 0;
915 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
918 case LI_DC_WITHOUT_CHECKSUM :
920 case LI_DC_WITH_CHECKSUM :
921 if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
923 length = pd[offset + P_VAR_PART_DC + 1];
924 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
932 if (check_col(fd, COL_PROTOCOL))
933 col_add_str(fd, COL_PROTOCOL, "COTP");
934 if (check_col(fd, COL_INFO))
935 col_add_fstr(fd, COL_INFO, "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
940 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
941 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
942 proto_tree_add_text(cotp_tree, offset, 1,
943 "Length indicator: %d", li);
944 proto_tree_add_text(cotp_tree, offset + 1, 1,
945 "TPDU code: Ox%x (DC)", tpdu);
946 proto_tree_add_text(cotp_tree, offset + 2, 2,
947 "Destination reference: 0x%04x", dst_ref);
948 proto_tree_add_text(cotp_tree, offset + 4, 2,
949 "Source reference: 0x%04x", src_ref);
951 proto_tree_add_text(cotp_tree,
952 offset + P_VAR_PART_DC + 0, 1,
953 "Parameter code: 0x%02x (checksum)", code);
954 proto_tree_add_text(cotp_tree,
955 offset + P_VAR_PART_DC + 1, 1,
956 "Parameter length: 0x%02x", length);
957 proto_tree_add_text(cotp_tree,
958 offset + P_VAR_PART_DC + 2, 2,
959 "Checksum: 0x%04x", checksum);
964 dissect_data(pd, offset, fd, tree);
968 } /* osi_decode_DC */
970 static int osi_decode_AK(const u_char *pd, int offset,
971 frame_data *fd, proto_tree *tree)
973 proto_tree *cotp_tree = NULL;
975 u_int tpdu_nr,i =0, r_lower_window_edge ;
977 u_short checksum, seq_nr, r_seq_nr, r_cdt;
983 if (!is_LI_NORMAL_AK(li)) {
984 tpdu_nr = pd[offset + P_TPDU_NR_234];
986 if (check_col(fd, COL_PROTOCOL))
987 col_add_str(fd, COL_PROTOCOL, "COTP");
988 if (check_col(fd, COL_INFO))
989 col_add_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
993 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
994 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
995 proto_tree_add_text(cotp_tree, offset, 1,
996 "Length indicator: %d", li);
997 proto_tree_add_text(cotp_tree, offset + 1, 1,
998 "TPDU code: Ox%x (AK)", tpdu);
999 proto_tree_add_text(cotp_tree, offset + 1, 1,
1001 proto_tree_add_text(cotp_tree, offset + 2, 2,
1002 "Destination reference: 0x%04x", dst_ref);
1003 proto_tree_add_text(cotp_tree, offset + 4, 1,
1004 "Your TPDU number: 0x%02x", tpdu_nr);
1007 while(li > P_VAR_PART_NAK + i - 1) {
1008 switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
1010 length = pd[offset + P_VAR_PART_NAK + i + 1];
1011 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1013 proto_tree_add_text(cotp_tree,
1014 offset + P_VAR_PART_NAK + i + 0, 1,
1015 "Parameter code: 0x%02x (checksum)", code);
1016 proto_tree_add_text(cotp_tree,
1017 offset + P_VAR_PART_NAK + i + 1, 1,
1018 "Parameter length: 0x%02x", length);
1019 proto_tree_add_text(cotp_tree,
1020 offset + P_VAR_PART_NAK + i + 2, 2,
1021 "Checksum: 0x%04x", checksum);
1026 length = pd[offset + P_VAR_PART_NAK + i + 1];
1027 r_lower_window_edge =
1028 EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
1029 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
1030 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
1032 proto_tree_add_text(cotp_tree,
1033 offset + P_VAR_PART_NAK + i + 0, 1,
1034 "Parameter code: 0x%02x (flow control)",
1036 proto_tree_add_text(cotp_tree,
1037 offset + P_VAR_PART_NAK + i + 1, 1,
1038 "Parameter length: 0x%02x", length);
1039 proto_tree_add_text(cotp_tree,
1040 offset + P_VAR_PART_NAK + i + 2, 4,
1041 "Lower window edge: 0x%08x",
1042 r_lower_window_edge);
1043 proto_tree_add_text(cotp_tree,
1044 offset + P_VAR_PART_NAK + i + 6, 2,
1045 "Sequence number: 0x%04x",
1047 proto_tree_add_text(cotp_tree,
1048 offset + P_VAR_PART_NAK + i + 8, 2,
1055 length = pd[offset + P_VAR_PART_NAK + i + 1];
1056 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1058 proto_tree_add_text(cotp_tree,
1059 offset + P_VAR_PART_NAK + i + 0, 1,
1060 "Parameter code: 0x%02x (seq number)", code);
1061 proto_tree_add_text(cotp_tree,
1062 offset + P_VAR_PART_NAK + i + 1, 1,
1063 "Parameter length: 0x%02x", length);
1064 proto_tree_add_text(cotp_tree,
1065 offset + P_VAR_PART_NAK + i + 2, 2,
1066 "Sequence number: 0x%04x", seq_nr);
1071 length = pd[offset + P_VAR_PART_NAK + i + 1];
1073 proto_tree_add_text(cotp_tree,
1074 offset + P_VAR_PART_NAK + i + 0, 1,
1075 "Parameter code: 0x%02x (unknown)", code);
1076 proto_tree_add_text(cotp_tree,
1077 offset + P_VAR_PART_NAK + i + 1, 1,
1078 "Parameter length: 0x%02x", length);
1079 proto_tree_add_text(cotp_tree,
1080 offset + P_VAR_PART_NAK + i + 2, length,
1081 "Parameter value: <not shown>");
1087 } else { /* extended format */
1089 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1090 cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
1092 if (check_col(fd, COL_PROTOCOL))
1093 col_add_str(fd, COL_PROTOCOL, "COTP");
1094 if (check_col(fd, COL_INFO))
1095 col_add_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
1099 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1100 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1101 proto_tree_add_text(cotp_tree, offset, 1,
1102 "Length indicator: %d", li);
1103 proto_tree_add_text(cotp_tree, offset + 1, 1,
1104 "TPDU code: Ox%x (AK)", tpdu);
1105 proto_tree_add_text(cotp_tree, offset + 2, 2,
1106 "Destination reference: 0x%04x", dst_ref);
1107 proto_tree_add_text(cotp_tree, offset + 4, 4,
1108 "Your TPDU number: 0x%08x", tpdu_nr);
1109 proto_tree_add_text(cotp_tree, offset + 8, 2,
1110 "Credit: 0x%04x", cdt_in_ak);
1113 while(li > P_VAR_PART_EAK + i - 1) {
1114 switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
1116 length = pd[offset + P_VAR_PART_EAK + i + 1];
1117 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1119 proto_tree_add_text(cotp_tree,
1120 offset + P_VAR_PART_EAK + i + 0, 1,
1121 "Parameter code: 0x%02x (checksum)", code);
1122 proto_tree_add_text(cotp_tree,
1123 offset + P_VAR_PART_EAK + i + 1, 1,
1124 "Parameter length: 0x%02x", length);
1125 proto_tree_add_text(cotp_tree,
1126 offset + P_VAR_PART_EAK + i + 2, 2,
1127 "Checksum: 0x%04x", checksum);
1132 length = pd[offset + P_VAR_PART_EAK + i + 1];
1133 r_lower_window_edge =
1134 EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
1135 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
1136 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
1138 proto_tree_add_text(cotp_tree,
1139 offset + P_VAR_PART_EAK + i + 0, 1,
1140 "Parameter code: 0x%02x (flow control)",
1142 proto_tree_add_text(cotp_tree,
1143 offset + P_VAR_PART_EAK + i + 1, 1,
1144 "Parameter length: 0x%02x", length);
1145 proto_tree_add_text(cotp_tree,
1146 offset + P_VAR_PART_EAK + i + 2, 4,
1147 "Lower window edge: 0x%08x",
1148 r_lower_window_edge);
1149 proto_tree_add_text(cotp_tree,
1150 offset + P_VAR_PART_EAK + i + 6, 2,
1151 "Sequence number: 0x%04x",
1153 proto_tree_add_text(cotp_tree,
1154 offset + P_VAR_PART_EAK + i + 8, 2,
1161 length = pd[offset + P_VAR_PART_EAK + i + 1];
1162 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1164 proto_tree_add_text(cotp_tree,
1165 offset + P_VAR_PART_EAK + i + 0, 1,
1166 "Parameter code: 0x%02x (seq number)", code);
1167 proto_tree_add_text(cotp_tree,
1168 offset + P_VAR_PART_EAK + i + 1, 1,
1169 "Parameter length: 0x%02x", length);
1170 proto_tree_add_text(cotp_tree,
1171 offset + P_VAR_PART_EAK + i + 2, 2,
1172 "Sequence number: 0x%04x", seq_nr);
1177 length = pd[offset + P_VAR_PART_EAK + i + 1];
1179 proto_tree_add_text(cotp_tree,
1180 offset + P_VAR_PART_EAK + i + 0, 1,
1181 "Parameter code: 0x%02x (unknown)", code);
1182 proto_tree_add_text(cotp_tree,
1183 offset + P_VAR_PART_EAK + i + 1, 1,
1184 "Parameter length: 0x%02x", length);
1185 proto_tree_add_text(cotp_tree,
1186 offset + P_VAR_PART_EAK + i + 2, length,
1187 "Parameter value: <not shown>");
1194 } /* is_LI_NORMAL_AK */
1197 dissect_data(pd, offset, fd, tree);
1201 } /* osi_decode_AK */
1203 static int osi_decode_EA(const u_char *pd, int offset,
1204 frame_data *fd, proto_tree *tree)
1206 proto_tree *cotp_tree;
1209 u_short checksum = 0;
1217 case LI_NORMAL_EA_WITH_CHECKSUM :
1218 tpdu_nr = pd[offset + P_TPDU_NR_234];
1219 code = pd[offset + P_VAR_PART_NDT];
1220 length = pd[offset + P_VAR_PART_NDT + 1];
1221 if (code != VP_CHECKSUM || length != 1)
1223 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
1225 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1226 tpdu_nr = pd[offset + P_TPDU_NR_234];
1228 case LI_EXTENDED_EA_WITH_CHECKSUM :
1229 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1230 code = pd[offset + P_VAR_PART_EDT];
1231 length = pd[offset + P_VAR_PART_EDT + 1];
1232 if (code != VP_CHECKSUM || length != 1)
1234 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
1236 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1237 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1239 default : /* bad TPDU */
1245 if (check_col(fd, COL_PROTOCOL))
1246 col_add_str(fd, COL_PROTOCOL, "COTP");
1247 if (check_col(fd, COL_INFO))
1248 col_add_fstr(fd, COL_INFO,
1249 "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1252 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1253 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1254 proto_tree_add_text(cotp_tree, offset, 1,
1255 "Length indicator: %d", li);
1256 proto_tree_add_text(cotp_tree, offset + 1, 1,
1257 "TPDU code: Ox%x (EA)", tpdu);
1258 proto_tree_add_text(cotp_tree, offset + 2, 2,
1259 "Destination reference: 0x%04x", dst_ref);
1262 case LI_NORMAL_EA_WITH_CHECKSUM :
1263 proto_tree_add_text(cotp_tree, offset + 4, 1,
1264 "Your TPDU number: 0x%02x", tpdu_nr);
1265 proto_tree_add_text(cotp_tree, offset + 5, 1,
1266 "Parameter code: 0x%02x (checksum)", code);
1267 proto_tree_add_text(cotp_tree, offset + 6, 1,
1268 "Parameter length: 0x%02x", length);
1269 proto_tree_add_text(cotp_tree, offset + 7, 2,
1270 "Checksum: 0x%04x", checksum);
1272 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1273 proto_tree_add_text(cotp_tree, offset + 4, 1,
1274 "Your TPDU number: 0x%02x", tpdu_nr);
1276 case LI_EXTENDED_EA_WITH_CHECKSUM :
1277 proto_tree_add_text(cotp_tree, offset + 4, 4,
1278 "Your TPDU number: 0x%08x", tpdu_nr);
1279 proto_tree_add_text(cotp_tree, offset + 8, 1,
1280 "Parameter code: 0x%02x (checksum)", code);
1281 proto_tree_add_text(cotp_tree, offset + 9, 1,
1282 "Parameter length: 0x%02x", length);
1283 proto_tree_add_text(cotp_tree, offset + 10, 2,
1284 "Checksum: 0x%04x", checksum);
1286 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1287 proto_tree_add_text(cotp_tree, offset + 4, 4,
1288 "Your TPDU number: 0x%08x", tpdu_nr);
1296 dissect_data(pd, offset, fd, tree);
1300 } /* osi_decode_EA */
1302 static int osi_decode_ER(const u_char *pd, int offset,
1303 frame_data *fd, proto_tree *tree)
1305 proto_tree *cotp_tree;
1312 switch(pd[offset + P_REJECT_ER]) {
1314 str = "Reason not specified";
1317 str = "Invalid parameter code";
1320 str = "Invalid TPDU type";
1323 str = "Invalid parameter value";
1331 if (check_col(fd, COL_PROTOCOL))
1332 col_add_str(fd, COL_PROTOCOL, "COTP");
1333 if (check_col(fd, COL_INFO))
1334 col_add_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1337 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1338 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1339 proto_tree_add_text(cotp_tree, offset, 1,
1340 "Length indicator: %d", li);
1341 proto_tree_add_text(cotp_tree, offset + 1, 1,
1342 "TPDU code: Ox%x (ER)", tpdu);
1343 proto_tree_add_text(cotp_tree, offset + 2, 2,
1344 "Destination reference: 0x%04x", dst_ref);
1345 proto_tree_add_text(cotp_tree, offset + 4, 1,
1346 "Reject cause: %s", str);
1350 dissect_data(pd, offset, fd, tree);
1354 } /* osi_decode_ER */
1356 void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
1362 if (((li = pd[offset + P_LI]) == 0) ||
1363 (offset + P_LI + li + 1 > fd->cap_len)) {
1364 dissect_data(pd, offset, fd, tree);
1368 tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
1369 cdt = pd[offset + P_CDT] & 0x0F;
1370 dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
1375 status = osi_decode_CC(pd, offset, fd, tree);
1378 status = osi_decode_DR(pd, offset, fd, tree);
1381 status = osi_decode_DT(pd, offset, fd, tree);
1384 status = osi_decode_ED(pd, offset, fd, tree);
1387 status = osi_decode_RJ(pd, offset, fd, tree);
1390 status = osi_decode_DC(pd, offset, fd, tree);
1393 status = osi_decode_AK(pd, offset, fd, tree);
1396 status = osi_decode_EA(pd, offset, fd, tree);
1399 status = osi_decode_ER(pd, offset, fd, tree);
1405 if (status == -1) /* incorrect TPDU */
1406 dissect_data(pd, offset, fd, tree);
1408 } /* dissect_cotp */
1415 #define MAX_NSAP_LEN 20
1417 static gchar *print_nsap(const u_char *nsap, int length)
1420 /* to do : real NSAP decoding */
1422 static gchar str[3][MAX_NSAP_LEN * 3 + 1];
1426 if (cur == &str[0][0]) {
1428 } else if (cur == &str[1][0]) {
1435 if (length <= 0 || length > MAX_NSAP_LEN)
1436 sprintf(cur, "<invalid NSAP>");
1438 while (length != 1) {
1439 sprintf(tmp, "%02x:", *nsap ++);
1443 sprintf(tmp, "%02x", *nsap);
1449 void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
1453 struct clnp_header clnp;
1454 proto_tree *clnp_tree = NULL;
1456 u_char src_len, dst_len, nsel;
1457 u_int first_offset = offset;
1459 if (fd->cap_len < offset + sizeof(clnp)) {
1460 dissect_data(pd, offset, fd, tree);
1464 /* avoid alignment problem */
1465 memcpy(&clnp, &pd[offset], sizeof(clnp));
1467 /* return if version not known */
1468 if (clnp.cnf_vers != ISO8473_V1) {
1469 dissect_data(pd, offset, fd, tree);
1473 /* fixed part decoding */
1476 ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL);
1477 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1478 proto_tree_add_item_format(clnp_tree, hf_clnp_id, offset, 1,
1480 "Protocol identifier: 0x%02x",
1482 proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1,
1484 proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1,
1486 proto_tree_add_item_format(clnp_tree, hf_clnp_ttl, offset + 3, 1,
1488 "TTL: %d (%d secs)",
1489 clnp.cnf_ttl, clnp.cnf_ttl / 2);
1490 proto_tree_add_item_format(clnp_tree, hf_clnp_type, offset + 4, 1,
1492 "Type code: 0x%02x (%s%s%s%s)",
1494 (clnp.cnf_type & CNF_SEG_OK) ? "S " : "",
1495 (clnp.cnf_type & CNF_MORE_SEGS) ? "M " : "",
1496 (clnp.cnf_type & CNF_ERR_OK) ? "E " : "",
1497 (clnp.cnf_type & CNF_TYPE) == DT_NPDU ?
1499 proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2,
1500 EXTRACT_SHORT(&clnp.cnf_seglen_msb));
1501 proto_tree_add_item_format(clnp_tree, hf_clnp_checksum, offset + 7, 2,
1502 EXTRACT_SHORT(&clnp.cnf_cksum_msb),
1504 EXTRACT_SHORT(&clnp.cnf_cksum_msb));
1507 /* stop here if header is not complete */
1509 if (fd->cap_len < offset + clnp.cnf_hdr_len) {
1510 dissect_data(pd, offset, fd, tree);
1516 offset += P_ADDRESS_PART;
1517 dst_len = pd[offset];
1518 nsel = pd[offset + dst_len];
1519 src_len = pd[offset + dst_len + 1];
1522 proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1,
1524 proto_tree_add_item_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len,
1526 "Destination address: %s",
1527 print_nsap(&pd[offset + 1], dst_len));
1528 proto_tree_add_item(clnp_tree, hf_clnp_src_length,
1529 offset + 1 + dst_len, 1, src_len);
1530 proto_tree_add_item_format(clnp_tree, hf_clnp_src,
1531 offset + dst_len + 2, src_len,
1532 &pd[offset + dst_len + 2],
1533 "Source address: %s",
1534 print_nsap(&pd[offset + dst_len + 2], src_len));
1537 if (check_col(fd, COL_RES_NET_SRC))
1538 col_add_fstr(fd, COL_RES_NET_SRC, "%s",
1539 print_nsap(&pd[offset + dst_len + 2], src_len));
1540 if (check_col(fd, COL_RES_NET_DST))
1541 col_add_fstr(fd, COL_RES_NET_DST, "%s",
1542 print_nsap(&pd[offset + 1], dst_len));
1544 /* Segmentation Part */
1546 offset += dst_len + src_len + 2;
1548 if (tree && (clnp.cnf_type & CNF_SEG_OK)) {
1549 struct clnp_segment seg;
1550 memcpy(&seg, &pd[offset], sizeof(seg));
1552 proto_tree_add_text(clnp_tree, offset, 2,
1553 "Data unit identifier: 0x%04x",
1554 EXTRACT_SHORT(&pd[offset]));
1555 proto_tree_add_text(clnp_tree, offset + 2 , 2,
1556 "Segment offset: 0x%04x",
1557 EXTRACT_SHORT(&pd[offset + 2]));
1558 proto_tree_add_text(clnp_tree, offset + 4 , 2,
1559 "Total length: 0x%04x",
1560 EXTRACT_SHORT(&pd[offset + 4]));
1566 /* To do : decode options */
1568 proto_tree_add_text(clnp_tree, offset,
1569 clnp.cnf_hdr_len + first_offset - offset,
1570 "Options/Data: <not shown>");
1574 offset = first_offset + clnp.cnf_hdr_len;
1576 if (offset == fd->cap_len)
1579 /* continue with COTP if any */
1581 if (nsel == NSEL_TP) /* just guessing here - valid for DECNet-OSI */
1582 dissect_cotp(pd, offset, fd, tree);
1584 dissect_data(pd, offset, fd, tree);
1586 } /* dissect_clnp */
1589 /* main entry point */
1591 void dissect_osi(const u_char *pd, int offset, frame_data *fd,
1595 switch (pd[offset]) {
1597 /* only CLNP is currently decoded */
1600 if (check_col(fd, COL_PROTOCOL)) {
1601 col_add_str(fd, COL_PROTOCOL, "CLNP");
1603 dissect_clnp(pd, offset, fd, tree);
1606 if (check_col(fd, COL_PROTOCOL)) {
1607 col_add_str(fd, COL_PROTOCOL, "ESIS");
1609 dissect_data(pd, offset, fd, tree);
1611 case ISO9542X25_ESIS:
1612 if (check_col(fd, COL_PROTOCOL)) {
1613 col_add_str(fd, COL_PROTOCOL, "ESIS(X25)");
1615 dissect_data(pd, offset, fd, tree);
1618 if (check_col(fd, COL_PROTOCOL)) {
1619 col_add_str(fd, COL_PROTOCOL, "ISIS");
1621 dissect_isis(pd, offset, fd, tree);
1624 if (check_col(fd, COL_PROTOCOL)) {
1625 col_add_str(fd, COL_PROTOCOL, "ISO");
1627 if (check_col(fd, COL_INFO)) {
1628 col_add_fstr(fd, COL_INFO, "Unknown ISO protocol (%02x)", pd[offset]);
1630 dissect_data(pd, offset, fd, tree);
1636 void proto_register_clnp(void)
1638 static hf_register_info hf[] = {
1640 { "Protocol identifier", "clnp.id", FT_UINT8, BASE_DEC, NULL, 0x0,
1644 { "Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1648 { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1652 { "TTL", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1656 { "Type code", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1659 { &hf_clnp_pdu_length,
1660 { "PDU segment length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1663 { &hf_clnp_checksum,
1664 { "Checksum", "clnp.checksum",FT_UINT16, BASE_DEC, NULL, 0x0,
1667 { &hf_clnp_dest_length,
1668 { "Destination address length", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1672 { "Destination address", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0,
1675 { &hf_clnp_src_length,
1676 { "Source address length","clnp.ssap.len",FT_UINT8, BASE_DEC, NULL, 0x0,
1680 { "Source address", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0,
1683 static gint *ett[] = {
1687 proto_clnp = proto_register_protocol("ISO CLNP", "clnp");
1688 proto_register_field_array(proto_clnp, hf, array_length(hf));
1689 proto_register_subtree_array(ett, array_length(ett));
1692 void proto_register_cotp(void)
1694 /* static hf_register_info hf[] = {
1696 { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
1698 static gint *ett[] = {
1702 proto_cotp = proto_register_protocol("ISO COTP", "cotp");
1703 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
1704 proto_register_subtree_array(ett, array_length(ett));