2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-osi.c,v 1.11 1999/10/12 06:20:12 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 /* 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 int proto_cotp = -1;
66 /* Network layer protocol identifiers */
68 #define ISO8473_CLNP 0x81
69 #define ISO9542_ESIS 0x82
70 #define ISO10589_ISIS 0x83
71 #define ISO9542X25_ESIS 0x8a
74 * ISO8473 OSI CLNP definition (see RFC994)
76 * _________________________________
78 * |_________________________________|
80 * |_________________________________|
81 * | Segmentation Part (optional) |
82 * |_________________________________|
83 * | Options Part (optional) |
84 * |_________________________________|
86 * |_________________________________|
89 #define ISO8473_V1 0x01 /* CLNP version 1 */
94 u_char cnf_proto_id; /* network layer protocol identifier */
95 u_char cnf_hdr_len; /* length indicator (octets) */
96 u_char cnf_vers; /* version/protocol identifier extension */
97 u_char cnf_ttl; /* lifetime (500 milliseconds) */
98 u_char cnf_type; /* type code */
99 u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
100 u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
101 u_char cnf_cksum_msb; /* checksum high byte */
102 u_char cnf_cksum_lsb; /* checksum low byte */
105 #define CNF_TYPE 0x1f
106 #define CNF_ERR_OK 0x20
107 #define CNF_MORE_SEGS 0x40
108 #define CNF_SEG_OK 0x80
115 #define P_ADDRESS_PART 9
117 /* Segmentation part */
119 struct clnp_segment {
120 u_short cng_id; /* data unit identifier */
121 u_short cng_off; /* segment offset */
122 u_short cng_tot_len; /* total length */
127 #define NSEL_NET 0x00
132 * ISO8073 OSI COTP definition (see RFC905)
135 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
137 /* TPDU definition */
157 #define P_TPDU_NR_0_1 2
158 #define P_TPDU_NR_234 4
159 #define P_VAR_PART_NDT 5
160 #define P_VAR_PART_EDT 8
161 #define P_VAR_PART_NAK 5
162 #define P_VAR_PART_CC 7
163 #define P_VAR_PART_EAK 10
164 #define P_VAR_PART_DC 6
165 #define P_VAR_PART_DR 7
166 #define P_CDT_IN_AK 8
167 #define P_CDT_IN_RJ 8
168 #define P_REJECT_ER 4
169 #define P_REASON_IN_DR 6
170 #define P_CLASS_OPTION 6
172 /* TPDU length indicator */
174 #define LI_NORMAL_DT_CLASS_01 2
175 #define LI_NORMAL_DT_WITH_CHECKSUM 8
176 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
177 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
178 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
179 #define LI_NORMAL_EA_WITH_CHECKSUM 8
180 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
181 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
182 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
183 #define LI_NORMAL_RJ 4
184 #define LI_EXTENDED_RJ 9
190 #define LI_DC_WITH_CHECKSUM 9
191 #define LI_DC_WITHOUT_CHECKSUM 5
192 #define is_LI_NORMAL_AK(p) ( p & 0x01 )
196 #define VP_ACK_TIME 0x85
197 #define VP_RES_ERROR 0x86
198 #define VP_PRIORITY 0x87
199 #define VP_TRANSIT_DEL 0x88
200 #define VP_THROUGHPUT 0x89
201 #define VP_SEQ_NR 0x8A /* in AK */
202 #define VP_REASSIGNMENT 0x8B
203 #define VP_FLOW_CNTL 0x8C /* in AK */
204 #define VP_TPDU_SIZE 0xC0
205 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
206 #define VP_DST_TSAP 0xC2
207 #define VP_CHECKSUM 0xC3
208 #define VP_VERSION_NR 0xC4
209 #define VP_PROTECTION 0xC5
210 #define VP_OPT_SEL 0xC6
211 #define VP_PROTO_CLASS 0xC7
215 #define EXTRACT_SHORT(p) pntohs(p)
216 #define EXTRACT_LONG(p) pntohl(p)
218 /* global variables */
220 static u_char li, tpdu, cdt; /* common fields */
221 static u_short dst_ref;
223 /* function definitions */
225 static int osi_decode_DR(const u_char *pd, int offset,
226 frame_data *fd, proto_tree *tree)
228 proto_tree *cotp_tree;
237 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
238 reason = pd[offset + P_REASON_IN_DR];
241 case (128+0): str = "Normal Disconnect"; break;
242 case (128+1): str = "Remote transport enity congestion"; break;
243 case (128+2): str = "Connection negotiation failed"; break;
244 case (128+3): str = "Duplicate source reference"; break;
245 case (128+4): str = "Mismatched references"; break;
246 case (128+5): str = "Protocol error"; break;
247 case (128+7): str = "Reference overflow"; break;
248 case (128+8): str = "Connection requestion refused"; break;
249 case (128+10):str = "Header or parameter length invalid"; break;
250 case (0): str = "Reason not specified"; break;
251 case (1): str = "Congestion at TSAP"; break;
252 case (2): str = "Session entity not attached to TSAP"; break;
253 case (3): str = "Address unknown"; break;
259 if (check_col(fd, COL_PROTOCOL))
260 col_add_str(fd, COL_PROTOCOL, "COTP");
261 if (check_col(fd, COL_INFO))
262 col_add_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
266 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
267 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
268 proto_tree_add_text(cotp_tree, offset, 1,
269 "Length indicator: %d", li);
270 proto_tree_add_text(cotp_tree, offset + 1, 1,
271 "TPDU code: Ox%x (DR)", tpdu);
272 proto_tree_add_text(cotp_tree, offset + 2, 2,
273 "Destination reference: 0x%04x", dst_ref);
274 proto_tree_add_text(cotp_tree, offset + 4, 2,
275 "Source reference: 0x%04x", src_ref);
276 proto_tree_add_text(cotp_tree, offset + 6, 1,
281 dissect_data(pd, offset, fd, tree);
285 } /* osi_decode_DR */
287 static int osi_decode_DT(const u_char *pd, int offset,
288 frame_data *fd, proto_tree *tree)
290 proto_tree *cotp_tree;
293 u_short checksum = 0;
294 u_char code = 0, length = 0;
298 case LI_NORMAL_DT_WITH_CHECKSUM :
299 tpdu_nr = pd[offset + P_TPDU_NR_234];
300 if ( tpdu_nr & 0x80 )
301 tpdu_nr = tpdu_nr & 0x7F;
304 code = pd[offset + P_VAR_PART_NDT];
305 if (code == VP_CHECKSUM)
306 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
310 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
311 tpdu_nr = pd[offset + P_TPDU_NR_234];
312 if ( tpdu_nr & 0x80 )
313 tpdu_nr = tpdu_nr & 0x7F;
317 case LI_EXTENDED_DT_WITH_CHECKSUM :
318 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
319 if ( tpdu_nr & 0x80000000 )
320 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
323 code = pd[offset + P_VAR_PART_EDT];
324 if (code == VP_CHECKSUM)
325 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
329 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
330 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
331 if ( tpdu_nr & 0x80000000 )
332 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
336 case LI_NORMAL_DT_CLASS_01 :
337 tpdu_nr = pd[offset + P_TPDU_NR_0_1];
338 if ( tpdu_nr & 0x80 )
339 tpdu_nr = tpdu_nr & 0x7F;
343 default : /* bad TPDU */
349 if (check_col(fd, COL_PROTOCOL))
350 col_add_str(fd, COL_PROTOCOL, "COTP");
351 if (check_col(fd, COL_INFO))
352 col_add_fstr(fd, COL_INFO, "DT TPDU (%d) dst-ref: 0x%04x %s",
355 (fragment)? "(fragment)" : "");
358 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
359 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
360 proto_tree_add_text(cotp_tree, offset, 1,
361 "Length indicator: %d", li);
362 proto_tree_add_text(cotp_tree, offset + 1, 1,
363 "TPDU code: Ox%x (DT)", tpdu);
365 if (li != LI_NORMAL_DT_CLASS_01)
366 proto_tree_add_text(cotp_tree, offset + 2, 2,
367 "Destination reference: 0x%04x", dst_ref);
370 case LI_NORMAL_DT_WITH_CHECKSUM :
371 proto_tree_add_text(cotp_tree, offset + 4, 1,
372 "TPDU number: 0x%02x (%s)",
374 (fragment)? "fragment":"complete");
375 proto_tree_add_text(cotp_tree,
376 offset + P_VAR_PART_NDT, 1,
377 "Parameter code: 0x%02x (checksum)", code);
378 proto_tree_add_text(cotp_tree,
379 offset + P_VAR_PART_NDT + 1, 1,
380 "Parameter length: 0x%02x", length);
381 proto_tree_add_text(cotp_tree,
382 offset + P_VAR_PART_NDT + 2, length,
383 "Checksum: 0x%04x", checksum);
385 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
386 proto_tree_add_text(cotp_tree, offset + 4, 1,
387 "TPDU number: 0x%02x (%s)",
389 (fragment)? "fragment":"complete");
391 case LI_EXTENDED_DT_WITH_CHECKSUM :
392 proto_tree_add_text(cotp_tree, offset + 4, 4,
393 "TPDU number: 0x%08x (%s)",
395 (fragment)? "fragment":"complete");
396 proto_tree_add_text(cotp_tree,
397 offset + P_VAR_PART_EDT, 1,
398 "Parameter code: 0x%02x (checksum)", code);
399 proto_tree_add_text(cotp_tree,
400 offset + P_VAR_PART_EDT + 1, 1,
401 "Parameter length: 0x%02x", length);
402 proto_tree_add_text(cotp_tree,
403 offset + P_VAR_PART_EDT + 2, length,
404 "Checksum: 0x%04x", checksum);
406 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
407 proto_tree_add_text(cotp_tree, offset + 4, 4,
408 "TPDU number: 0x%08x (%s)",
410 (fragment)? "fragment":"complete");
412 case LI_NORMAL_DT_CLASS_01 :
413 proto_tree_add_text(cotp_tree, offset + 2, 1,
414 "TPDU number: 0x%02x (%s)",
416 (fragment)? "fragment":"complete");
422 dissect_data(pd, offset, fd, tree);
426 } /* osi_decode_DT */
428 static int osi_decode_ED(const u_char *pd, int offset,
429 frame_data *fd, proto_tree *tree)
431 proto_tree *cotp_tree;
434 u_short checksum = 0;
435 u_char code = 0, length = 0;
437 /* ED TPDUs are never fragmented */
440 case LI_NORMAL_DT_WITH_CHECKSUM :
441 tpdu_nr = pd[offset + P_TPDU_NR_234];
442 if ( tpdu_nr & 0x80 )
443 tpdu_nr = tpdu_nr & 0x7F;
446 code = pd[offset + P_VAR_PART_NDT];
447 length = pd[offset + P_VAR_PART_NDT + 1];
448 if (code == VP_CHECKSUM)
449 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
453 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
454 tpdu_nr = pd[offset + P_TPDU_NR_234];
455 if ( tpdu_nr & 0x80 )
456 tpdu_nr = tpdu_nr & 0x7F;
460 case LI_EXTENDED_DT_WITH_CHECKSUM :
461 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
462 if ( tpdu_nr & 0x80000000 )
463 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
466 code = pd[offset + P_VAR_PART_EDT];
467 length = pd[offset + P_VAR_PART_EDT + 1];
468 if (code == VP_CHECKSUM)
469 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
473 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
474 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
475 if ( tpdu_nr & 0x80000000 )
476 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
480 default : /* bad TPDU */
486 if (check_col(fd, COL_PROTOCOL))
487 col_add_str(fd, COL_PROTOCOL, "COTP");
488 if (check_col(fd, COL_INFO))
489 col_add_fstr(fd, COL_INFO, "ED TPDU (%d) dst-ref: 0x%04x",
493 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
494 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
495 proto_tree_add_text(cotp_tree, offset, 1,
496 "Length indicator: %d", li);
497 proto_tree_add_text(cotp_tree, offset + 1, 1,
498 "TPDU code: Ox%x (ED)", tpdu);
499 proto_tree_add_text(cotp_tree, offset + 2, 2,
500 "Destination reference: 0x%04x", dst_ref);
503 case LI_NORMAL_DT_WITH_CHECKSUM :
504 proto_tree_add_text(cotp_tree, offset + 4, 1,
505 "TPDU number: 0x%02x", tpdu_nr);
506 proto_tree_add_text(cotp_tree,
507 offset + P_VAR_PART_NDT, 1,
508 "Parameter code: 0x%02x (checksum)", code);
509 proto_tree_add_text(cotp_tree,
510 offset + P_VAR_PART_NDT + 1, 1,
511 "Parameter length: 0x%02x", length);
512 proto_tree_add_text(cotp_tree,
513 offset + P_VAR_PART_NDT + 2, length,
514 "Checksum: 0x%04x", checksum);
516 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
517 proto_tree_add_text(cotp_tree, offset + 4, 1,
518 "TPDU number: 0x%02x", tpdu_nr);
520 case LI_EXTENDED_DT_WITH_CHECKSUM :
521 proto_tree_add_text(cotp_tree, offset + 4, 4,
522 "TPDU number: 0x%02x", tpdu_nr);
523 proto_tree_add_text(cotp_tree,
524 offset + P_VAR_PART_EDT, 1,
525 "Parameter code: 0x%02x (checksum)", code);
526 proto_tree_add_text(cotp_tree,
527 offset + P_VAR_PART_EDT + 1, 1,
528 "Parameter length: 0x%02x", length);
529 proto_tree_add_text(cotp_tree,
530 offset + P_VAR_PART_EDT + 2, length,
531 "Checksum: 0x%04x", checksum);
533 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
534 proto_tree_add_text(cotp_tree, offset + 4, 4,
535 "TPDU number: 0x%02x", tpdu_nr);
541 dissect_data(pd, offset, fd, tree);
545 } /* osi_decode_ED */
547 static int osi_decode_RJ(const u_char *pd, int offset,
548 frame_data *fd, proto_tree *tree)
550 proto_tree *cotp_tree;
557 tpdu_nr = pd[offset + P_TPDU_NR_234];
559 case LI_EXTENDED_RJ :
560 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
561 credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
569 if (check_col(fd, COL_PROTOCOL))
570 col_add_str(fd, COL_PROTOCOL, "COTP");
571 if (check_col(fd, COL_INFO))
572 col_add_fstr(fd, COL_INFO, "RJ TPDU (%d) dst-ref: 0x%04x",
576 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
577 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
578 proto_tree_add_text(cotp_tree, offset, 1,
579 "Length indicator: %d", li);
580 proto_tree_add_text(cotp_tree, offset + 1, 1,
581 "TPDU code: Ox%x (RJ)", tpdu);
582 if (li == LI_NORMAL_RJ)
583 proto_tree_add_text(cotp_tree, offset + 1, 1,
585 proto_tree_add_text(cotp_tree, offset + 2, 2,
586 "Destination reference: 0x%04x", dst_ref);
587 if (li == LI_NORMAL_RJ)
588 proto_tree_add_text(cotp_tree, offset + 4, 1,
589 "Your TPDU number: 0x%02x", tpdu_nr);
591 proto_tree_add_text(cotp_tree, offset + 4, 4,
592 "Your TPDU number: 0x%02x", tpdu_nr);
593 proto_tree_add_text(cotp_tree, offset + 8, 2,
594 "Credit: 0x%02x", credit);
599 dissect_data(pd, offset, fd, tree);
603 } /* osi_decode_RJ */
605 #define MAX_TSAP_LEN 32
607 static gchar *print_tsap(const u_char *tsap, int length)
610 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
614 if (cur == &str[0][0]) {
616 } else if (cur == &str[1][0]) {
622 /* to do: test if all bytes are printable */
625 if (length <= 0 || length > MAX_TSAP_LEN)
626 sprintf(cur, "<unsupported TSAP length>");
628 while (length != 0) {
629 sprintf(tmp, "%02x", *tsap ++);
638 static int osi_decode_CC(const u_char *pd, int offset,
639 frame_data *fd, proto_tree *tree)
642 /* CC & CR decoding in the same function */
644 proto_tree *cotp_tree = NULL;
646 u_short src_ref, checksum;
647 u_char class_option, code, length;
650 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
651 class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
652 if (class_option > 4)
655 if (check_col(fd, COL_PROTOCOL))
656 col_add_str(fd, COL_PROTOCOL, "COTP");
657 if (check_col(fd, COL_INFO))
658 col_add_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
659 (tpdu == CR_TPDU) ? "CR" : "CC",
664 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
665 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
666 proto_tree_add_text(cotp_tree, offset, 1,
667 "Length indicator: %d", li);
668 proto_tree_add_text(cotp_tree, offset + 1, 1,
669 "TPDU code: Ox%x (%s)", tpdu,
670 (tpdu == CR_TPDU) ? "CR" : "CC");
671 proto_tree_add_text(cotp_tree, offset + 2, 2,
672 "Destination reference: 0x%04x", dst_ref);
673 proto_tree_add_text(cotp_tree, offset + 4, 2,
674 "Source reference: 0x%04x", src_ref);
675 proto_tree_add_text(cotp_tree, offset + 6, 1,
676 "Class option: 0x%02x", class_option);
680 while(li > P_VAR_PART_CC + i - 1) {
683 u_short s, s1,s2,s3,s4;
686 switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
688 length = pd[offset + P_VAR_PART_CC + i + 1];
689 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
690 proto_tree_add_text(cotp_tree,
691 offset + P_VAR_PART_CC + i, 1,
692 "Parameter code: 0x%02x (checksum)", code);
693 proto_tree_add_text(cotp_tree,
694 offset + P_VAR_PART_CC + i + 1, 1,
695 "Parameter length: 0x%02x", length);
696 proto_tree_add_text(cotp_tree,
697 offset + P_VAR_PART_CC + i + 2, length,
698 "Checksum: 0x%04x", checksum);
702 length = pd[offset + P_VAR_PART_CC + i + 1];
703 proto_tree_add_text(cotp_tree,
704 offset + P_VAR_PART_CC + i, 1,
705 "Parameter code: 0x%02x (src-tsap)", code);
706 proto_tree_add_text(cotp_tree,
707 offset + P_VAR_PART_CC + i + 1, 1,
708 "Parameter length: 0x%02x", length);
709 proto_tree_add_text(cotp_tree,
710 offset + P_VAR_PART_CC + i + 2, length,
711 "Calling TSAP: 0x%s",
712 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
717 length = pd[offset + P_VAR_PART_CC + i + 1];
718 proto_tree_add_text(cotp_tree,
719 offset + P_VAR_PART_CC + i, 1,
720 "Parameter code: 0x%02x (dst-tsap)", code);
721 proto_tree_add_text(cotp_tree,
722 offset + P_VAR_PART_CC + i + 1, 1,
723 "Parameter length: 0x%02x", length);
724 proto_tree_add_text(cotp_tree,
725 offset + P_VAR_PART_CC + i + 2, length,
727 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
732 length = pd[offset + P_VAR_PART_CC + i + 1];
733 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
734 proto_tree_add_text(cotp_tree,
735 offset + P_VAR_PART_CC + i, 1,
736 "Parameter code: 0x%02x (tpdu-size)", code);
737 proto_tree_add_text(cotp_tree,
738 offset + P_VAR_PART_CC + i + 1, 1,
739 "Parameter length: 0x%02x", length);
740 proto_tree_add_text(cotp_tree,
741 offset + P_VAR_PART_CC + i + 2, length,
742 "TPDU size: %d", 2 << c1);
746 length = pd[offset + P_VAR_PART_CC + i + 1];
747 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
748 proto_tree_add_text(cotp_tree,
749 offset + P_VAR_PART_CC + i, 1,
750 "Parameter code: 0x%02x (options)", code);
751 proto_tree_add_text(cotp_tree,
752 offset + P_VAR_PART_CC + i + 1, 1,
753 "Parameter length: 0x%02x", length);
754 if (class_option == 1) {
756 proto_tree_add_text(cotp_tree,
757 offset + P_VAR_PART_CC + i + 2, 1,
758 "Use of network expedited data");
760 proto_tree_add_text(cotp_tree,
761 offset + P_VAR_PART_CC + i + 2, 1,
762 "Non use of network expedited data");
764 proto_tree_add_text(cotp_tree,
765 offset + P_VAR_PART_CC + i + 2, 1,
766 "Use of Receipt confirmation");
768 proto_tree_add_text(cotp_tree,
769 offset + P_VAR_PART_CC + i + 2, 1,
770 "Use of explicit AK variant");
771 } else if (class_option == 4) {
773 proto_tree_add_text(cotp_tree,
774 offset + P_VAR_PART_CC + i + 2, 1,
775 "Use 16 bit checksum ");
777 proto_tree_add_text(cotp_tree,
778 offset + P_VAR_PART_CC + i + 2, 1,
779 "Non-use 16 bit checksum in class 4");
782 proto_tree_add_text(cotp_tree,
783 offset + P_VAR_PART_CC + i + 2, 1,
784 "Use of transport expedited data transfer\n");
786 proto_tree_add_text(cotp_tree,
787 offset + P_VAR_PART_CC + i + 2, 1,
788 "Non-use of transport expedited data transfer");
792 length = pd[offset + P_VAR_PART_CC + i + 1];
793 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
794 proto_tree_add_text(cotp_tree,
795 offset + P_VAR_PART_CC + i, 1,
796 "Parameter code: 0x%02x (ack time)", code);
797 proto_tree_add_text(cotp_tree,
798 offset + P_VAR_PART_CC + i + 1, 1,
799 "Parameter length: 0x%02x", length);
800 proto_tree_add_text(cotp_tree,
801 offset + P_VAR_PART_CC + i + 2, length,
802 "Ack time (ms): %d", s);
806 length = pd[offset + P_VAR_PART_CC + i + 1];
807 t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
808 t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
809 t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
810 t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
811 proto_tree_add_text(cotp_tree,
812 offset + P_VAR_PART_CC + i, 1,
813 "Parameter code: 0x%02x (throughput)", code);
814 proto_tree_add_text(cotp_tree,
815 offset + P_VAR_PART_CC + i + 1, 1,
816 "Parameter length: 0x%02x", length);
817 proto_tree_add_text(cotp_tree,
818 offset + P_VAR_PART_CC + i + 2, 4,
819 "Target value / calling-called: %d o/s", t1);
820 proto_tree_add_text(cotp_tree,
821 offset + P_VAR_PART_CC + i + 6, 4,
822 "Minimum / calling-called: %d o/s", t2);
823 proto_tree_add_text(cotp_tree,
824 offset + P_VAR_PART_CC + i + 10, 4,
825 "Target value / called-calling: %d o/s", t3);
826 proto_tree_add_text(cotp_tree,
827 offset + P_VAR_PART_CC + i + 14, 4,
828 "Minimum / called-calling: %d o/s", t4);
831 case VP_TRANSIT_DEL :
832 length = pd[offset + P_VAR_PART_CC + i + 1];
833 s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
834 s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
835 s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
836 s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
837 proto_tree_add_text(cotp_tree,
838 offset + P_VAR_PART_CC + i, 1,
839 "Parameter code: 0x%02x (transit delay)", code);
840 proto_tree_add_text(cotp_tree,
841 offset + P_VAR_PART_CC + i + 1, 1,
842 "Parameter length: 0x%02x", length);
843 proto_tree_add_text(cotp_tree,
844 offset + P_VAR_PART_CC + i + 2, 2,
845 "Target value / calling-called: %d ms", s1);
846 proto_tree_add_text(cotp_tree,
847 offset + P_VAR_PART_CC + i + 4, 2,
848 "Minimum / calling-called: %d ms", s2);
849 proto_tree_add_text(cotp_tree,
850 offset + P_VAR_PART_CC + i + 6, 2,
851 "Target value / called-calling: %d ms", s3);
852 proto_tree_add_text(cotp_tree,
853 offset + P_VAR_PART_CC + i + 8, 2,
854 "Minimum / called-calling: %d ms", s4);
858 length = pd[offset + P_VAR_PART_CC + i + 1];
859 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
860 proto_tree_add_text(cotp_tree,
861 offset + P_VAR_PART_CC + i, 1,
862 "Parameter code: 0x%02x (priority)", code);
863 proto_tree_add_text(cotp_tree,
864 offset + P_VAR_PART_CC + i + 1, 1,
865 "Parameter length: 0x%02x", length);
866 proto_tree_add_text(cotp_tree,
867 offset + P_VAR_PART_CC + i + 2, length,
872 case VP_REASSIGNMENT: /* todo */
876 case VP_PROTO_CLASS :
877 default : /* no decoding */
878 length = pd[offset + P_VAR_PART_CC + i + 1];
879 proto_tree_add_text(cotp_tree,
880 offset + P_VAR_PART_CC + i + 0, 1,
881 "Parameter code: 0x%02x", code);
882 proto_tree_add_text(cotp_tree,
883 offset + P_VAR_PART_CC + i + 1, 1,
884 "Parameter length: 0x%02x", length);
885 proto_tree_add_text(cotp_tree,
886 offset + P_VAR_PART_CC + i + 2, length,
887 "Parameter value: <not shown>");
894 dissect_data(pd, offset, fd, tree);
898 } /* osi_decode_CC */
900 static int osi_decode_DC(const u_char *pd, int offset,
901 frame_data *fd, proto_tree *tree)
903 proto_tree *cotp_tree;
905 u_short src_ref, checksum = 0;
906 u_char length = 0, code = 0;
911 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
914 case LI_DC_WITHOUT_CHECKSUM :
916 case LI_DC_WITH_CHECKSUM :
917 if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
919 length = pd[offset + P_VAR_PART_DC + 1];
920 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
928 if (check_col(fd, COL_PROTOCOL))
929 col_add_str(fd, COL_PROTOCOL, "COTP");
930 if (check_col(fd, COL_INFO))
931 col_add_fstr(fd, COL_INFO, "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
936 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
937 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
938 proto_tree_add_text(cotp_tree, offset, 1,
939 "Length indicator: %d", li);
940 proto_tree_add_text(cotp_tree, offset + 1, 1,
941 "TPDU code: Ox%x (DC)", tpdu);
942 proto_tree_add_text(cotp_tree, offset + 2, 2,
943 "Destination reference: 0x%04x", dst_ref);
944 proto_tree_add_text(cotp_tree, offset + 4, 2,
945 "Source reference: 0x%04x", src_ref);
947 proto_tree_add_text(cotp_tree,
948 offset + P_VAR_PART_DC + 0, 1,
949 "Parameter code: 0x%02x (checksum)", code);
950 proto_tree_add_text(cotp_tree,
951 offset + P_VAR_PART_DC + 1, 1,
952 "Parameter length: 0x%02x", length);
953 proto_tree_add_text(cotp_tree,
954 offset + P_VAR_PART_DC + 2, 2,
955 "Checksum: 0x%04x", checksum);
960 dissect_data(pd, offset, fd, tree);
964 } /* osi_decode_DC */
966 static int osi_decode_AK(const u_char *pd, int offset,
967 frame_data *fd, proto_tree *tree)
969 proto_tree *cotp_tree = NULL;
971 u_int tpdu_nr,i =0, r_lower_window_edge ;
973 u_short checksum, seq_nr, r_seq_nr, r_cdt;
979 if (!is_LI_NORMAL_AK(li)) {
980 tpdu_nr = pd[offset + P_TPDU_NR_234];
982 if (check_col(fd, COL_PROTOCOL))
983 col_add_str(fd, COL_PROTOCOL, "COTP");
984 if (check_col(fd, COL_INFO))
985 col_add_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
989 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
990 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
991 proto_tree_add_text(cotp_tree, offset, 1,
992 "Length indicator: %d", li);
993 proto_tree_add_text(cotp_tree, offset + 1, 1,
994 "TPDU code: Ox%x (AK)", tpdu);
995 proto_tree_add_text(cotp_tree, offset + 1, 1,
997 proto_tree_add_text(cotp_tree, offset + 2, 2,
998 "Destination reference: 0x%04x", dst_ref);
999 proto_tree_add_text(cotp_tree, offset + 4, 1,
1000 "Your TPDU number: 0x%02x", tpdu_nr);
1003 while(li > P_VAR_PART_NAK + i - 1) {
1004 switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
1006 length = pd[offset + P_VAR_PART_NAK + i + 1];
1007 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1009 proto_tree_add_text(cotp_tree,
1010 offset + P_VAR_PART_NAK + i + 0, 1,
1011 "Parameter code: 0x%02x (checksum)", code);
1012 proto_tree_add_text(cotp_tree,
1013 offset + P_VAR_PART_NAK + i + 1, 1,
1014 "Parameter length: 0x%02x", length);
1015 proto_tree_add_text(cotp_tree,
1016 offset + P_VAR_PART_NAK + i + 2, 2,
1017 "Checksum: 0x%04x", checksum);
1022 length = pd[offset + P_VAR_PART_NAK + i + 1];
1023 r_lower_window_edge =
1024 EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
1025 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
1026 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
1028 proto_tree_add_text(cotp_tree,
1029 offset + P_VAR_PART_NAK + i + 0, 1,
1030 "Parameter code: 0x%02x (flow control)",
1032 proto_tree_add_text(cotp_tree,
1033 offset + P_VAR_PART_NAK + i + 1, 1,
1034 "Parameter length: 0x%02x", length);
1035 proto_tree_add_text(cotp_tree,
1036 offset + P_VAR_PART_NAK + i + 2, 4,
1037 "Lower window edge: 0x%08x",
1038 r_lower_window_edge);
1039 proto_tree_add_text(cotp_tree,
1040 offset + P_VAR_PART_NAK + i + 6, 2,
1041 "Sequence number: 0x%04x",
1043 proto_tree_add_text(cotp_tree,
1044 offset + P_VAR_PART_NAK + i + 8, 2,
1051 length = pd[offset + P_VAR_PART_NAK + i + 1];
1052 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1054 proto_tree_add_text(cotp_tree,
1055 offset + P_VAR_PART_NAK + i + 0, 1,
1056 "Parameter code: 0x%02x (seq number)", code);
1057 proto_tree_add_text(cotp_tree,
1058 offset + P_VAR_PART_NAK + i + 1, 1,
1059 "Parameter length: 0x%02x", length);
1060 proto_tree_add_text(cotp_tree,
1061 offset + P_VAR_PART_NAK + i + 2, 2,
1062 "Sequence number: 0x%04x", seq_nr);
1067 length = pd[offset + P_VAR_PART_NAK + i + 1];
1069 proto_tree_add_text(cotp_tree,
1070 offset + P_VAR_PART_NAK + i + 0, 1,
1071 "Parameter code: 0x%02x (unknown)", code);
1072 proto_tree_add_text(cotp_tree,
1073 offset + P_VAR_PART_NAK + i + 1, 1,
1074 "Parameter length: 0x%02x", length);
1075 proto_tree_add_text(cotp_tree,
1076 offset + P_VAR_PART_NAK + i + 2, length,
1077 "Parameter value: <not shown>");
1083 } else { /* extended format */
1085 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1086 cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
1088 if (check_col(fd, COL_PROTOCOL))
1089 col_add_str(fd, COL_PROTOCOL, "COTP");
1090 if (check_col(fd, COL_INFO))
1091 col_add_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
1095 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1096 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
1097 proto_tree_add_text(cotp_tree, offset, 1,
1098 "Length indicator: %d", li);
1099 proto_tree_add_text(cotp_tree, offset + 1, 1,
1100 "TPDU code: Ox%x (AK)", tpdu);
1101 proto_tree_add_text(cotp_tree, offset + 2, 2,
1102 "Destination reference: 0x%04x", dst_ref);
1103 proto_tree_add_text(cotp_tree, offset + 4, 4,
1104 "Your TPDU number: 0x%08x", tpdu_nr);
1105 proto_tree_add_text(cotp_tree, offset + 8, 2,
1106 "Credit: 0x%04x", cdt_in_ak);
1109 while(li > P_VAR_PART_EAK + i - 1) {
1110 switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
1112 length = pd[offset + P_VAR_PART_EAK + i + 1];
1113 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1115 proto_tree_add_text(cotp_tree,
1116 offset + P_VAR_PART_EAK + i + 0, 1,
1117 "Parameter code: 0x%02x (checksum)", code);
1118 proto_tree_add_text(cotp_tree,
1119 offset + P_VAR_PART_EAK + i + 1, 1,
1120 "Parameter length: 0x%02x", length);
1121 proto_tree_add_text(cotp_tree,
1122 offset + P_VAR_PART_EAK + i + 2, 2,
1123 "Checksum: 0x%04x", checksum);
1128 length = pd[offset + P_VAR_PART_EAK + i + 1];
1129 r_lower_window_edge =
1130 EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
1131 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
1132 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
1134 proto_tree_add_text(cotp_tree,
1135 offset + P_VAR_PART_EAK + i + 0, 1,
1136 "Parameter code: 0x%02x (flow control)",
1138 proto_tree_add_text(cotp_tree,
1139 offset + P_VAR_PART_EAK + i + 1, 1,
1140 "Parameter length: 0x%02x", length);
1141 proto_tree_add_text(cotp_tree,
1142 offset + P_VAR_PART_EAK + i + 2, 4,
1143 "Lower window edge: 0x%08x",
1144 r_lower_window_edge);
1145 proto_tree_add_text(cotp_tree,
1146 offset + P_VAR_PART_EAK + i + 6, 2,
1147 "Sequence number: 0x%04x",
1149 proto_tree_add_text(cotp_tree,
1150 offset + P_VAR_PART_EAK + i + 8, 2,
1157 length = pd[offset + P_VAR_PART_EAK + i + 1];
1158 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1160 proto_tree_add_text(cotp_tree,
1161 offset + P_VAR_PART_EAK + i + 0, 1,
1162 "Parameter code: 0x%02x (seq number)", code);
1163 proto_tree_add_text(cotp_tree,
1164 offset + P_VAR_PART_EAK + i + 1, 1,
1165 "Parameter length: 0x%02x", length);
1166 proto_tree_add_text(cotp_tree,
1167 offset + P_VAR_PART_EAK + i + 2, 2,
1168 "Sequence number: 0x%04x", seq_nr);
1173 length = pd[offset + P_VAR_PART_EAK + i + 1];
1175 proto_tree_add_text(cotp_tree,
1176 offset + P_VAR_PART_EAK + i + 0, 1,
1177 "Parameter code: 0x%02x (unknown)", code);
1178 proto_tree_add_text(cotp_tree,
1179 offset + P_VAR_PART_EAK + i + 1, 1,
1180 "Parameter length: 0x%02x", length);
1181 proto_tree_add_text(cotp_tree,
1182 offset + P_VAR_PART_EAK + i + 2, length,
1183 "Parameter value: <not shown>");
1190 } /* is_LI_NORMAL_AK */
1193 dissect_data(pd, offset, fd, tree);
1197 } /* osi_decode_AK */
1199 static int osi_decode_EA(const u_char *pd, int offset,
1200 frame_data *fd, proto_tree *tree)
1202 proto_tree *cotp_tree;
1205 u_short checksum = 0;
1213 case LI_NORMAL_EA_WITH_CHECKSUM :
1214 tpdu_nr = pd[offset + P_TPDU_NR_234];
1215 code = pd[offset + P_VAR_PART_NDT];
1216 length = pd[offset + P_VAR_PART_NDT + 1];
1217 if (code != VP_CHECKSUM || length != 1)
1219 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
1221 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1222 tpdu_nr = pd[offset + P_TPDU_NR_234];
1224 case LI_EXTENDED_EA_WITH_CHECKSUM :
1225 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1226 code = pd[offset + P_VAR_PART_EDT];
1227 length = pd[offset + P_VAR_PART_EDT + 1];
1228 if (code != VP_CHECKSUM || length != 1)
1230 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
1232 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1233 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1235 default : /* bad TPDU */
1241 if (check_col(fd, COL_PROTOCOL))
1242 col_add_str(fd, COL_PROTOCOL, "COTP");
1243 if (check_col(fd, COL_INFO))
1244 col_add_fstr(fd, COL_INFO,
1245 "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1248 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1249 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
1250 proto_tree_add_text(cotp_tree, offset, 1,
1251 "Length indicator: %d", li);
1252 proto_tree_add_text(cotp_tree, offset + 1, 1,
1253 "TPDU code: Ox%x (EA)", tpdu);
1254 proto_tree_add_text(cotp_tree, offset + 2, 2,
1255 "Destination reference: 0x%04x", dst_ref);
1258 case LI_NORMAL_EA_WITH_CHECKSUM :
1259 proto_tree_add_text(cotp_tree, offset + 4, 1,
1260 "Your TPDU number: 0x%02x", tpdu_nr);
1261 proto_tree_add_text(cotp_tree, offset + 5, 1,
1262 "Parameter code: 0x%02x (checksum)", code);
1263 proto_tree_add_text(cotp_tree, offset + 6, 1,
1264 "Parameter length: 0x%02x", length);
1265 proto_tree_add_text(cotp_tree, offset + 7, 2,
1266 "Checksum: 0x%04x", checksum);
1268 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1269 proto_tree_add_text(cotp_tree, offset + 4, 1,
1270 "Your TPDU number: 0x%02x", tpdu_nr);
1272 case LI_EXTENDED_EA_WITH_CHECKSUM :
1273 proto_tree_add_text(cotp_tree, offset + 4, 4,
1274 "Your TPDU number: 0x%08x", tpdu_nr);
1275 proto_tree_add_text(cotp_tree, offset + 8, 1,
1276 "Parameter code: 0x%02x (checksum)", code);
1277 proto_tree_add_text(cotp_tree, offset + 9, 1,
1278 "Parameter length: 0x%02x", length);
1279 proto_tree_add_text(cotp_tree, offset + 10, 2,
1280 "Checksum: 0x%04x", checksum);
1282 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1283 proto_tree_add_text(cotp_tree, offset + 4, 4,
1284 "Your TPDU number: 0x%08x", tpdu_nr);
1292 dissect_data(pd, offset, fd, tree);
1296 } /* osi_decode_EA */
1298 static int osi_decode_ER(const u_char *pd, int offset,
1299 frame_data *fd, proto_tree *tree)
1301 proto_tree *cotp_tree;
1308 switch(pd[offset + P_REJECT_ER]) {
1310 str = "Reason not specified";
1313 str = "Invalid parameter code";
1316 str = "Invalid TPDU type";
1319 str = "Invalid parameter value";
1327 if (check_col(fd, COL_PROTOCOL))
1328 col_add_str(fd, COL_PROTOCOL, "COTP");
1329 if (check_col(fd, COL_INFO))
1330 col_add_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1333 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1334 cotp_tree = proto_item_add_subtree(ti, ETT_COTP);
1335 proto_tree_add_text(cotp_tree, offset, 1,
1336 "Length indicator: %d", li);
1337 proto_tree_add_text(cotp_tree, offset + 1, 1,
1338 "TPDU code: Ox%x (ER)", tpdu);
1339 proto_tree_add_text(cotp_tree, offset + 2, 2,
1340 "Destination reference: 0x%04x", dst_ref);
1341 proto_tree_add_text(cotp_tree, offset + 4, 1,
1342 "Reject cause: %s", str);
1346 dissect_data(pd, offset, fd, tree);
1350 } /* osi_decode_ER */
1352 void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
1358 if (((li = pd[offset + P_LI]) == 0) ||
1359 (offset + P_LI + li + 1 > fd->cap_len)) {
1360 dissect_data(pd, offset, fd, tree);
1364 tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
1365 cdt = pd[offset + P_CDT] & 0x0F;
1366 dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
1371 status = osi_decode_CC(pd, offset, fd, tree);
1374 status = osi_decode_DR(pd, offset, fd, tree);
1377 status = osi_decode_DT(pd, offset, fd, tree);
1380 status = osi_decode_ED(pd, offset, fd, tree);
1383 status = osi_decode_RJ(pd, offset, fd, tree);
1386 status = osi_decode_DC(pd, offset, fd, tree);
1389 status = osi_decode_AK(pd, offset, fd, tree);
1392 status = osi_decode_EA(pd, offset, fd, tree);
1395 status = osi_decode_ER(pd, offset, fd, tree);
1401 if (status == -1) /* incorrect TPDU */
1402 dissect_data(pd, offset, fd, tree);
1404 } /* dissect_cotp */
1411 #define MAX_NSAP_LEN 20
1413 static gchar *print_nsap(const u_char *nsap, int length)
1416 /* to do : real NSAP decoding */
1418 static gchar str[3][MAX_NSAP_LEN * 3 + 1];
1422 if (cur == &str[0][0]) {
1424 } else if (cur == &str[1][0]) {
1431 if (length <= 0 || length > MAX_NSAP_LEN)
1432 sprintf(cur, "<invalid NSAP>");
1434 while (length != 1) {
1435 sprintf(tmp, "%02x:", *nsap ++);
1439 sprintf(tmp, "%02x", *nsap);
1445 void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
1449 struct clnp_header clnp;
1450 proto_tree *clnp_tree = NULL;
1452 u_char src_len, dst_len, nsel;
1453 u_int first_offset = offset;
1455 if (fd->cap_len < offset + sizeof(clnp)) {
1456 dissect_data(pd, offset, fd, tree);
1460 /* avoid alignment problem */
1461 memcpy(&clnp, &pd[offset], sizeof(clnp));
1463 /* return if version not known */
1464 if (clnp.cnf_vers != ISO8473_V1) {
1465 dissect_data(pd, offset, fd, tree);
1469 /* fixed part decoding */
1472 ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL);
1473 clnp_tree = proto_item_add_subtree(ti, ETT_CLNP);
1474 proto_tree_add_item_format(clnp_tree, hf_clnp_id, offset, 1,
1476 "Protocol identifier: 0x%02x",
1478 proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1,
1480 proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1,
1482 proto_tree_add_item_format(clnp_tree, hf_clnp_ttl, offset + 3, 1,
1484 "TTL: %d (%d secs)",
1485 clnp.cnf_ttl, clnp.cnf_ttl / 2);
1486 proto_tree_add_item_format(clnp_tree, hf_clnp_type, offset + 4, 1,
1488 "Type code: 0x%02x (%s%s%s%s)",
1490 (clnp.cnf_type & CNF_SEG_OK) ? "S " : "",
1491 (clnp.cnf_type & CNF_MORE_SEGS) ? "M " : "",
1492 (clnp.cnf_type & CNF_ERR_OK) ? "E " : "",
1493 (clnp.cnf_type & CNF_TYPE) == DT_NPDU ?
1495 proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2,
1496 EXTRACT_SHORT(&clnp.cnf_seglen_msb));
1497 proto_tree_add_item_format(clnp_tree, hf_clnp_checksum, offset + 7, 2,
1498 EXTRACT_SHORT(&clnp.cnf_cksum_msb),
1500 EXTRACT_SHORT(&clnp.cnf_cksum_msb));
1503 /* stop here if header is not complete */
1505 if (fd->cap_len < offset + clnp.cnf_hdr_len) {
1506 dissect_data(pd, offset, fd, tree);
1512 offset += P_ADDRESS_PART;
1513 dst_len = pd[offset];
1514 nsel = pd[offset + dst_len];
1515 src_len = pd[offset + dst_len + 1];
1518 proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1,
1520 proto_tree_add_item_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len,
1522 "Destination address: %s",
1523 print_nsap(&pd[offset + 1], dst_len));
1524 proto_tree_add_item(clnp_tree, hf_clnp_src_length,
1525 offset + 1 + dst_len, 1, src_len);
1526 proto_tree_add_item_format(clnp_tree, hf_clnp_src,
1527 offset + dst_len + 2, src_len,
1528 &pd[offset + dst_len + 2],
1529 "Source address: %s",
1530 print_nsap(&pd[offset + dst_len + 2], src_len));
1533 if (check_col(fd, COL_RES_NET_SRC))
1534 col_add_fstr(fd, COL_RES_NET_SRC, "%s",
1535 print_nsap(&pd[offset + dst_len + 2], src_len));
1536 if (check_col(fd, COL_RES_NET_DST))
1537 col_add_fstr(fd, COL_RES_NET_DST, "%s",
1538 print_nsap(&pd[offset + 1], dst_len));
1540 /* Segmentation Part */
1542 offset += dst_len + src_len + 2;
1544 if (tree && (clnp.cnf_type & CNF_SEG_OK)) {
1545 struct clnp_segment seg;
1546 memcpy(&seg, &pd[offset], sizeof(seg));
1548 proto_tree_add_text(clnp_tree, offset, 2,
1549 "Data unit identifier: 0x%04x",
1550 EXTRACT_SHORT(&pd[offset]));
1551 proto_tree_add_text(clnp_tree, offset + 2 , 2,
1552 "Segment offset: 0x%04x",
1553 EXTRACT_SHORT(&pd[offset + 2]));
1554 proto_tree_add_text(clnp_tree, offset + 4 , 2,
1555 "Total length: 0x%04x",
1556 EXTRACT_SHORT(&pd[offset + 4]));
1562 /* To do : decode options */
1564 proto_tree_add_text(clnp_tree, offset,
1565 clnp.cnf_hdr_len + first_offset - offset,
1566 "Options/Data: <not shown>");
1570 offset = first_offset + clnp.cnf_hdr_len;
1572 if (offset == fd->cap_len)
1575 /* continue with COTP if any */
1577 if (nsel == NSEL_TP) /* just guessing here - valid for DECNet-OSI */
1578 dissect_cotp(pd, offset, fd, tree);
1580 dissect_data(pd, offset, fd, tree);
1582 } /* dissect_clnp */
1585 /* main entry point */
1587 void dissect_osi(const u_char *pd, int offset, frame_data *fd,
1591 switch (pd[offset]) {
1593 /* only CLNP is currently decoded */
1596 if (check_col(fd, COL_PROTOCOL)) {
1597 col_add_str(fd, COL_PROTOCOL, "CLNP");
1599 dissect_clnp(pd, offset, fd, tree);
1602 if (check_col(fd, COL_PROTOCOL)) {
1603 col_add_str(fd, COL_PROTOCOL, "ESIS");
1605 dissect_data(pd, offset, fd, tree);
1607 case ISO9542X25_ESIS:
1608 if (check_col(fd, COL_PROTOCOL)) {
1609 col_add_str(fd, COL_PROTOCOL, "ESIS(X25)");
1611 dissect_data(pd, offset, fd, tree);
1614 if (check_col(fd, COL_PROTOCOL)) {
1615 col_add_str(fd, COL_PROTOCOL, "ISIS");
1617 dissect_data(pd, offset, fd, tree);
1620 if (check_col(fd, COL_PROTOCOL)) {
1621 col_add_str(fd, COL_PROTOCOL, "ISO");
1623 if (check_col(fd, COL_INFO)) {
1624 col_add_fstr(fd, COL_INFO, "Unknown ISO protocol (%02x)", pd[offset]);
1626 dissect_data(pd, offset, fd, tree);
1632 void proto_register_clnp(void)
1634 static hf_register_info hf[] = {
1636 { "Protocol identifier", "clnp.id", FT_UINT8, BASE_DEC, NULL, 0x0,
1640 { "Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1644 { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1648 { "TTL", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1652 { "Type code", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1655 { &hf_clnp_pdu_length,
1656 { "PDU segment length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1659 { &hf_clnp_checksum,
1660 { "Checksum", "clnp.checksum",FT_UINT16, BASE_DEC, NULL, 0x0,
1663 { &hf_clnp_dest_length,
1664 { "Destination address length", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1668 { "Destination address", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0,
1671 { &hf_clnp_src_length,
1672 { "Source address length","clnp.ssap.len",FT_UINT8, BASE_DEC, NULL, 0x0,
1676 { "Source address", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0,
1680 proto_clnp = proto_register_protocol("ISO CLNP", "clnp");
1681 proto_register_field_array(proto_clnp, hf, array_length(hf));
1684 void proto_register_cotp(void)
1686 /* static hf_register_info hf[] = {
1688 { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
1691 proto_cotp = proto_register_protocol("ISO COTP", "cotp");
1692 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/