2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-osi.c,v 1.4 1998/11/12 00:06:35 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)
44 #ifdef HAVE_SYS_TYPES_H
45 # include <sys/types.h>
51 /* Network layer protocol identifiers */
53 #define ISO8473_CLNP 0x81
54 #define ISO9542_ESIS 0x82
55 #define ISO10589_ISIS 0x83
56 #define ISO9542X25_ESIS 0x8a
59 * ISO8473 OSI CLNP definition (see RFC994)
61 * _________________________________
63 * |_________________________________|
65 * |_________________________________|
66 * | Segmentation Part (optional) |
67 * |_________________________________|
68 * | Options Part (optional) |
69 * |_________________________________|
71 * |_________________________________|
74 #define ISO8473_V1 0x01 /* CLNP version 1 */
79 u_char cnf_proto_id; /* network layer protocol identifier */
80 u_char cnf_hdr_len; /* length indicator (octets) */
81 u_char cnf_vers; /* version/protocol identifier extension */
82 u_char cnf_ttl; /* lifetime (500 milliseconds) */
83 u_char cnf_type; /* type code */
84 u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
85 u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
86 u_char cnf_cksum_msb; /* checksum high byte */
87 u_char cnf_cksum_lsb; /* checksum low byte */
91 #define CNF_ERR_OK 0x20
92 #define CNF_MORE_SEGS 0x40
93 #define CNF_SEG_OK 0x80
100 #define P_ADDRESS_PART 9
102 /* Segmentation part */
104 struct clnp_segment {
105 u_short cng_id; /* data unit identifier */
106 u_short cng_off; /* segment offset */
107 u_short cng_tot_len; /* total length */
112 #define NSEL_NET 0x00
117 * ISO8073 OSI COTP definition (see RFC905)
120 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
122 /* TPDU definition */
142 #define P_TPDU_NR_0_1 2
143 #define P_TPDU_NR_234 4
144 #define P_VAR_PART_NDT 5
145 #define P_VAR_PART_EDT 8
146 #define P_VAR_PART_NAK 5
147 #define P_VAR_PART_CC 7
148 #define P_VAR_PART_EAK 10
149 #define P_VAR_PART_DC 6
150 #define P_VAR_PART_DR 7
151 #define P_CDT_IN_AK 8
152 #define P_CDT_IN_RJ 8
153 #define P_REJECT_ER 4
154 #define P_REASON_IN_DR 6
155 #define P_CLASS_OPTION 6
157 /* TPDU length indicator */
159 #define LI_NORMAL_DT_CLASS_01 2
160 #define LI_NORMAL_DT_WITH_CHECKSUM 8
161 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
162 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
163 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
164 #define LI_NORMAL_EA_WITH_CHECKSUM 8
165 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
166 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
167 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
168 #define LI_NORMAL_RJ 4
169 #define LI_EXTENDED_RJ 9
175 #define LI_DC_WITH_CHECKSUM 9
176 #define LI_DC_WITHOUT_CHECKSUM 5
177 #define is_LI_NORMAL_AK(p) ( p & 0x01 )
181 #define VP_ACK_TIME 0x85
182 #define VP_RES_ERROR 0x86
183 #define VP_PRIORITY 0x87
184 #define VP_TRANSIT_DEL 0x88
185 #define VP_THROUGHPUT 0x89
186 #define VP_SEQ_NR 0x8A /* in AK */
187 #define VP_REASSIGNMENT 0x8B
188 #define VP_FLOW_CNTL 0x8C /* in AK */
189 #define VP_TPDU_SIZE 0xC0
190 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
191 #define VP_DST_TSAP 0xC2
192 #define VP_CHECKSUM 0xC3
193 #define VP_VERSION_NR 0xC4
194 #define VP_PROTECTION 0xC5
195 #define VP_OPT_SEL 0xC6
196 #define VP_PROTO_CLASS 0xC7
200 #define EXTRACT_SHORT(p) pntohs(p)
201 #define EXTRACT_LONG(p) pntohl(p)
203 /* global variables */
205 static u_char li, tpdu, cdt; /* common fields */
206 static u_short dst_ref;
208 /* function definitions */
210 static int osi_decode_DR(const u_char *pd, int offset,
211 frame_data *fd, GtkTree *tree)
213 GtkWidget *cotp_tree, *ti;
221 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
222 reason = pd[offset + P_REASON_IN_DR];
225 case (128+0): str = "Normal Disconnect"; break;
226 case (128+1): str = "Remote transport enity congestion"; break;
227 case (128+2): str = "Connection negotiation failed"; break;
228 case (128+3): str = "Duplicate source reference"; break;
229 case (128+4): str = "Mismatched references"; break;
230 case (128+5): str = "Protocol error"; break;
231 case (128+7): str = "Reference overflow"; break;
232 case (128+8): str = "Connection requestion refused"; break;
233 case (128+10):str = "Header or parameter length invalid"; break;
234 case (0): str = "Reason not specified"; break;
235 case (1): str = "Congestion at TSAP"; break;
236 case (2): str = "Session entity not attached to TSAP"; break;
237 case (3): str = "Address unknown"; break;
243 if (fd->win_info[COL_NUM]) {
244 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
245 sprintf(fd->win_info[COL_INFO], "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
250 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
252 cotp_tree = gtk_tree_new();
253 add_subtree(ti, cotp_tree, ETT_COTP);
254 add_item_to_tree(cotp_tree, offset, 1,
255 "Length indicator: %d", li);
256 add_item_to_tree(cotp_tree, offset + 1, 1,
257 "TPDU code: Ox%x (DR)", tpdu);
258 add_item_to_tree(cotp_tree, offset + 2, 2,
259 "Destination reference: 0x%04x", dst_ref);
260 add_item_to_tree(cotp_tree, offset + 4, 2,
261 "Source reference: 0x%04x", src_ref);
262 add_item_to_tree(cotp_tree, offset + 6, 1,
267 dissect_data(pd, offset, fd, tree);
271 } /* osi_decode_DR */
273 static int osi_decode_DT(const u_char *pd, int offset,
274 frame_data *fd, GtkTree *tree)
276 GtkWidget *cotp_tree, *ti;
278 u_short checksum = 0;
279 u_char code = 0, length = 0;
283 case LI_NORMAL_DT_WITH_CHECKSUM :
284 tpdu_nr = pd[offset + P_TPDU_NR_234];
285 if ( tpdu_nr & 0x80 )
286 tpdu_nr = tpdu_nr & 0x7F;
289 code = pd[offset + P_VAR_PART_NDT];
290 if (code == VP_CHECKSUM)
291 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
295 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
296 tpdu_nr = pd[offset + P_TPDU_NR_234];
297 if ( tpdu_nr & 0x80 )
298 tpdu_nr = tpdu_nr & 0x7F;
302 case LI_EXTENDED_DT_WITH_CHECKSUM :
303 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
304 if ( tpdu_nr & 0x80000000 )
305 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
308 code = pd[offset + P_VAR_PART_EDT];
309 if (code == VP_CHECKSUM)
310 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
314 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
315 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
316 if ( tpdu_nr & 0x80000000 )
317 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
321 case LI_NORMAL_DT_CLASS_01 :
322 tpdu_nr = pd[offset + P_TPDU_NR_0_1];
323 if ( tpdu_nr & 0x80 )
324 tpdu_nr = tpdu_nr & 0x7F;
328 default : /* bad TPDU */
334 if (fd->win_info[COL_NUM]) {
335 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
336 sprintf(fd->win_info[COL_INFO], "DT TPDU (%d) dst-ref: 0x%04x %s",
339 (fragment)? "(fragment)" : "");
343 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
345 cotp_tree = gtk_tree_new();
346 add_subtree(ti, cotp_tree, ETT_COTP);
347 add_item_to_tree(cotp_tree, offset, 1,
348 "Length indicator: %d", li);
349 add_item_to_tree(cotp_tree, offset + 1, 1,
350 "TPDU code: Ox%x (DT)", tpdu);
352 if (li != LI_NORMAL_DT_CLASS_01)
353 add_item_to_tree(cotp_tree, offset + 2, 2,
354 "Destination reference: 0x%04x", dst_ref);
357 case LI_NORMAL_DT_WITH_CHECKSUM :
358 add_item_to_tree(cotp_tree, offset + 4, 1,
359 "TPDU number: 0x%02x (%s)",
361 (fragment)? "fragment":"complete");
362 add_item_to_tree(cotp_tree,
363 offset + P_VAR_PART_NDT, 1,
364 "Parameter code: 0x%02x (checksum)", code);
365 add_item_to_tree(cotp_tree,
366 offset + P_VAR_PART_NDT + 1, 1,
367 "Parameter length: 0x%02x", length);
368 add_item_to_tree(cotp_tree,
369 offset + P_VAR_PART_NDT + 2, length,
370 "Checksum: 0x%04x", checksum);
372 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
373 add_item_to_tree(cotp_tree, offset + 4, 1,
374 "TPDU number: 0x%02x (%s)",
376 (fragment)? "fragment":"complete");
378 case LI_EXTENDED_DT_WITH_CHECKSUM :
379 add_item_to_tree(cotp_tree, offset + 4, 4,
380 "TPDU number: 0x%08x (%s)",
382 (fragment)? "fragment":"complete");
383 add_item_to_tree(cotp_tree,
384 offset + P_VAR_PART_EDT, 1,
385 "Parameter code: 0x%02x (checksum)", code);
386 add_item_to_tree(cotp_tree,
387 offset + P_VAR_PART_EDT + 1, 1,
388 "Parameter length: 0x%02x", length);
389 add_item_to_tree(cotp_tree,
390 offset + P_VAR_PART_EDT + 2, length,
391 "Checksum: 0x%04x", checksum);
393 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
394 add_item_to_tree(cotp_tree, offset + 4, 4,
395 "TPDU number: 0x%08x (%s)",
397 (fragment)? "fragment":"complete");
399 case LI_NORMAL_DT_CLASS_01 :
400 add_item_to_tree(cotp_tree, offset + 2, 1,
401 "TPDU number: 0x%02x (%s)",
403 (fragment)? "fragment":"complete");
409 dissect_data(pd, offset, fd, tree);
413 } /* osi_decode_DT */
415 static int osi_decode_ED(const u_char *pd, int offset,
416 frame_data *fd, GtkTree *tree)
418 GtkWidget *cotp_tree, *ti;
420 u_short checksum = 0;
421 u_char code = 0, length = 0;
423 /* ED TPDUs are never fragmented */
426 case LI_NORMAL_DT_WITH_CHECKSUM :
427 tpdu_nr = pd[offset + P_TPDU_NR_234];
428 if ( tpdu_nr & 0x80 )
429 tpdu_nr = tpdu_nr & 0x7F;
432 code = pd[offset + P_VAR_PART_NDT];
433 length = pd[offset + P_VAR_PART_NDT + 1];
434 if (code == VP_CHECKSUM)
435 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
439 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
440 tpdu_nr = pd[offset + P_TPDU_NR_234];
441 if ( tpdu_nr & 0x80 )
442 tpdu_nr = tpdu_nr & 0x7F;
446 case LI_EXTENDED_DT_WITH_CHECKSUM :
447 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
448 if ( tpdu_nr & 0x80000000 )
449 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
452 code = pd[offset + P_VAR_PART_EDT];
453 length = pd[offset + P_VAR_PART_EDT + 1];
454 if (code == VP_CHECKSUM)
455 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
459 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
460 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
461 if ( tpdu_nr & 0x80000000 )
462 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
466 default : /* bad TPDU */
472 if (fd->win_info[COL_NUM]) {
473 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
474 sprintf(fd->win_info[COL_INFO], "ED TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
478 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
480 cotp_tree = gtk_tree_new();
481 add_subtree(ti, cotp_tree, ETT_COTP);
482 add_item_to_tree(cotp_tree, offset, 1,
483 "Length indicator: %d", li);
484 add_item_to_tree(cotp_tree, offset + 1, 1,
485 "TPDU code: Ox%x (ED)", tpdu);
486 add_item_to_tree(cotp_tree, offset + 2, 2,
487 "Destination reference: 0x%04x", dst_ref);
490 case LI_NORMAL_DT_WITH_CHECKSUM :
491 add_item_to_tree(cotp_tree, offset + 4, 1,
492 "TPDU number: 0x%02x", tpdu_nr);
493 add_item_to_tree(cotp_tree,
494 offset + P_VAR_PART_NDT, 1,
495 "Parameter code: 0x%02x (checksum)", code);
496 add_item_to_tree(cotp_tree,
497 offset + P_VAR_PART_NDT + 1, 1,
498 "Parameter length: 0x%02x", length);
499 add_item_to_tree(cotp_tree,
500 offset + P_VAR_PART_NDT + 2, length,
501 "Checksum: 0x%04x", checksum);
503 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
504 add_item_to_tree(cotp_tree, offset + 4, 1,
505 "TPDU number: 0x%02x", tpdu_nr);
507 case LI_EXTENDED_DT_WITH_CHECKSUM :
508 add_item_to_tree(cotp_tree, offset + 4, 4,
509 "TPDU number: 0x%02x", tpdu_nr);
510 add_item_to_tree(cotp_tree,
511 offset + P_VAR_PART_EDT, 1,
512 "Parameter code: 0x%02x (checksum)", code);
513 add_item_to_tree(cotp_tree,
514 offset + P_VAR_PART_EDT + 1, 1,
515 "Parameter length: 0x%02x", length);
516 add_item_to_tree(cotp_tree,
517 offset + P_VAR_PART_EDT + 2, length,
518 "Checksum: 0x%04x", checksum);
520 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
521 add_item_to_tree(cotp_tree, offset + 4, 4,
522 "TPDU number: 0x%02x", tpdu_nr);
528 dissect_data(pd, offset, fd, tree);
532 } /* osi_decode_ED */
534 static int osi_decode_RJ(const u_char *pd, int offset,
535 frame_data *fd, GtkTree *tree)
537 GtkWidget *cotp_tree, *ti;
543 tpdu_nr = pd[offset + P_TPDU_NR_234];
545 case LI_EXTENDED_RJ :
546 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
547 credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
555 if (fd->win_info[COL_NUM]) {
556 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
557 sprintf(fd->win_info[COL_INFO], "RJ TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
561 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
563 cotp_tree = gtk_tree_new();
564 add_subtree(ti, cotp_tree, ETT_COTP);
565 add_item_to_tree(cotp_tree, offset, 1,
566 "Length indicator: %d", li);
567 add_item_to_tree(cotp_tree, offset + 1, 1,
568 "TPDU code: Ox%x (RJ)", tpdu);
569 if (li == LI_NORMAL_RJ)
570 add_item_to_tree(cotp_tree, offset + 1, 1,
572 add_item_to_tree(cotp_tree, offset + 2, 2,
573 "Destination reference: 0x%04x", dst_ref);
574 if (li == LI_NORMAL_RJ)
575 add_item_to_tree(cotp_tree, offset + 4, 1,
576 "Your TPDU number: 0x%02x", tpdu_nr);
578 add_item_to_tree(cotp_tree, offset + 4, 4,
579 "Your TPDU number: 0x%02x", tpdu_nr);
580 add_item_to_tree(cotp_tree, offset + 8, 2,
581 "Credit: 0x%02x", credit);
586 dissect_data(pd, offset, fd, tree);
590 } /* osi_decode_RJ */
592 #define MAX_TSAP_LEN 32
594 static gchar *print_tsap(const u_char *tsap, int length)
597 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
601 if (cur == &str[0][0]) {
603 } else if (cur == &str[1][0]) {
609 /* to do: test if all bytes are printable */
612 if (length <= 0 || length > MAX_TSAP_LEN)
613 sprintf(cur, "<unsupported TSAP length>");
615 while (length != 0) {
616 sprintf(tmp, "%02x", *tsap ++);
625 static int osi_decode_CC(const u_char *pd, int offset,
626 frame_data *fd, GtkTree *tree)
629 /* CC & CR decoding in the same function */
631 GtkWidget *cotp_tree = NULL, *ti;
632 u_short src_ref, checksum;
633 u_char class_option, code, length;
636 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
637 class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
638 if (class_option > 4)
641 if (fd->win_info[COL_NUM]) {
642 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
643 sprintf(fd->win_info[COL_INFO], "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
644 (tpdu == CR_TPDU) ? "CR" : "CC",
650 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
652 cotp_tree = gtk_tree_new();
653 add_subtree(ti, cotp_tree, ETT_COTP);
654 add_item_to_tree(cotp_tree, offset, 1,
655 "Length indicator: %d", li);
656 add_item_to_tree(cotp_tree, offset + 1, 1,
657 "TPDU code: Ox%x (%s)", tpdu,
658 (tpdu == CR_TPDU) ? "CR" : "CC");
659 add_item_to_tree(cotp_tree, offset + 2, 2,
660 "Destination reference: 0x%04x", dst_ref);
661 add_item_to_tree(cotp_tree, offset + 4, 2,
662 "Source reference: 0x%04x", src_ref);
663 add_item_to_tree(cotp_tree, offset + 6, 1,
664 "Class option: 0x%02x", class_option);
668 while(li > P_VAR_PART_CC + i - 1) {
671 u_short s, s1,s2,s3,s4;
674 switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
676 length = pd[offset + P_VAR_PART_CC + i + 1];
677 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
678 add_item_to_tree(cotp_tree,
679 offset + P_VAR_PART_CC + i, 1,
680 "Parameter code: 0x%02x (checksum)", code);
681 add_item_to_tree(cotp_tree,
682 offset + P_VAR_PART_CC + i + 1, 1,
683 "Parameter length: 0x%02x", length);
684 add_item_to_tree(cotp_tree,
685 offset + P_VAR_PART_CC + i + 2, length,
686 "Checksum: 0x%04x", checksum);
690 length = pd[offset + P_VAR_PART_CC + i + 1];
691 add_item_to_tree(cotp_tree,
692 offset + P_VAR_PART_CC + i, 1,
693 "Parameter code: 0x%02x (src-tsap)", code);
694 add_item_to_tree(cotp_tree,
695 offset + P_VAR_PART_CC + i + 1, 1,
696 "Parameter length: 0x%02x", length);
697 add_item_to_tree(cotp_tree,
698 offset + P_VAR_PART_CC + i + 2, length,
699 "Calling TSAP: 0x%s",
700 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
705 length = pd[offset + P_VAR_PART_CC + i + 1];
706 add_item_to_tree(cotp_tree,
707 offset + P_VAR_PART_CC + i, 1,
708 "Parameter code: 0x%02x (dst-tsap)", code);
709 add_item_to_tree(cotp_tree,
710 offset + P_VAR_PART_CC + i + 1, 1,
711 "Parameter length: 0x%02x", length);
712 add_item_to_tree(cotp_tree,
713 offset + P_VAR_PART_CC + i + 2, length,
715 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
720 length = pd[offset + P_VAR_PART_CC + i + 1];
721 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
722 add_item_to_tree(cotp_tree,
723 offset + P_VAR_PART_CC + i, 1,
724 "Parameter code: 0x%02x (tpdu-size)", code);
725 add_item_to_tree(cotp_tree,
726 offset + P_VAR_PART_CC + i + 1, 1,
727 "Parameter length: 0x%02x", length);
728 add_item_to_tree(cotp_tree,
729 offset + P_VAR_PART_CC + i + 2, length,
730 "TPDU size: %d", 2 << c1);
734 length = pd[offset + P_VAR_PART_CC + i + 1];
735 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
736 add_item_to_tree(cotp_tree,
737 offset + P_VAR_PART_CC + i, 1,
738 "Parameter code: 0x%02x (options)", code);
739 add_item_to_tree(cotp_tree,
740 offset + P_VAR_PART_CC + i + 1, 1,
741 "Parameter length: 0x%02x", length);
742 if (class_option == 1) {
744 add_item_to_tree(cotp_tree,
745 offset + P_VAR_PART_CC + i + 2, 1,
746 "Use of network expedited data");
748 add_item_to_tree(cotp_tree,
749 offset + P_VAR_PART_CC + i + 2, 1,
750 "Non use of network expedited data");
752 add_item_to_tree(cotp_tree,
753 offset + P_VAR_PART_CC + i + 2, 1,
754 "Use of Receipt confirmation");
756 add_item_to_tree(cotp_tree,
757 offset + P_VAR_PART_CC + i + 2, 1,
758 "Use of explicit AK variant");
759 } else if (class_option == 4) {
761 add_item_to_tree(cotp_tree,
762 offset + P_VAR_PART_CC + i + 2, 1,
763 "Use 16 bit checksum ");
765 add_item_to_tree(cotp_tree,
766 offset + P_VAR_PART_CC + i + 2, 1,
767 "Non-use 16 bit checksum in class 4");
770 add_item_to_tree(cotp_tree,
771 offset + P_VAR_PART_CC + i + 2, 1,
772 "Use of transport expedited data transfer\n");
774 add_item_to_tree(cotp_tree,
775 offset + P_VAR_PART_CC + i + 2, 1,
776 "Non-use of transport expedited data transfer");
780 length = pd[offset + P_VAR_PART_CC + i + 1];
781 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
782 add_item_to_tree(cotp_tree,
783 offset + P_VAR_PART_CC + i, 1,
784 "Parameter code: 0x%02x (ack time)", code);
785 add_item_to_tree(cotp_tree,
786 offset + P_VAR_PART_CC + i + 1, 1,
787 "Parameter length: 0x%02x", length);
788 add_item_to_tree(cotp_tree,
789 offset + P_VAR_PART_CC + i + 2, length,
790 "Ack time (ms): %d", s);
794 length = pd[offset + P_VAR_PART_CC + i + 1];
795 t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
796 t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
797 t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
798 t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
799 add_item_to_tree(cotp_tree,
800 offset + P_VAR_PART_CC + i, 1,
801 "Parameter code: 0x%02x (throughput)", code);
802 add_item_to_tree(cotp_tree,
803 offset + P_VAR_PART_CC + i + 1, 1,
804 "Parameter length: 0x%02x", length);
805 add_item_to_tree(cotp_tree,
806 offset + P_VAR_PART_CC + i + 2, 4,
807 "Target value / calling-called: %d o/s", t1);
808 add_item_to_tree(cotp_tree,
809 offset + P_VAR_PART_CC + i + 6, 4,
810 "Minimum / calling-called: %d o/s", t2);
811 add_item_to_tree(cotp_tree,
812 offset + P_VAR_PART_CC + i + 10, 4,
813 "Target value / called-calling: %d o/s", t3);
814 add_item_to_tree(cotp_tree,
815 offset + P_VAR_PART_CC + i + 14, 4,
816 "Minimum / called-calling: %d o/s", t4);
819 case VP_TRANSIT_DEL :
820 length = pd[offset + P_VAR_PART_CC + i + 1];
821 s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
822 s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
823 s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
824 s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
825 add_item_to_tree(cotp_tree,
826 offset + P_VAR_PART_CC + i, 1,
827 "Parameter code: 0x%02x (transit delay)", code);
828 add_item_to_tree(cotp_tree,
829 offset + P_VAR_PART_CC + i + 1, 1,
830 "Parameter length: 0x%02x", length);
831 add_item_to_tree(cotp_tree,
832 offset + P_VAR_PART_CC + i + 2, 2,
833 "Target value / calling-called: %d ms", s1);
834 add_item_to_tree(cotp_tree,
835 offset + P_VAR_PART_CC + i + 4, 2,
836 "Minimum / calling-called: %d ms", s2);
837 add_item_to_tree(cotp_tree,
838 offset + P_VAR_PART_CC + i + 6, 2,
839 "Target value / called-calling: %d ms", s3);
840 add_item_to_tree(cotp_tree,
841 offset + P_VAR_PART_CC + i + 8, 2,
842 "Minimum / called-calling: %d ms", s4);
846 length = pd[offset + P_VAR_PART_CC + i + 1];
847 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
848 add_item_to_tree(cotp_tree,
849 offset + P_VAR_PART_CC + i, 1,
850 "Parameter code: 0x%02x (priority)", code);
851 add_item_to_tree(cotp_tree,
852 offset + P_VAR_PART_CC + i + 1, 1,
853 "Parameter length: 0x%02x", length);
854 add_item_to_tree(cotp_tree,
855 offset + P_VAR_PART_CC + i + 2, length,
860 case VP_REASSIGNMENT: /* todo */
864 case VP_PROTO_CLASS :
865 default : /* no decoding */
866 length = pd[offset + P_VAR_PART_CC + i + 1];
867 add_item_to_tree(cotp_tree,
868 offset + P_VAR_PART_CC + i + 0, 1,
869 "Parameter code: 0x%02x", code);
870 add_item_to_tree(cotp_tree,
871 offset + P_VAR_PART_CC + i + 1, 1,
872 "Parameter length: 0x%02x", length);
873 add_item_to_tree(cotp_tree,
874 offset + P_VAR_PART_CC + i + 2, length,
875 "Parameter value: <not shown>");
882 dissect_data(pd, offset, fd, tree);
886 } /* osi_decode_CC */
888 static int osi_decode_DC(const u_char *pd, int offset,
889 frame_data *fd, GtkTree *tree)
891 GtkWidget *cotp_tree, *ti;
892 u_short src_ref, checksum = 0;
893 u_char length = 0, code = 0;
898 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
901 case LI_DC_WITHOUT_CHECKSUM :
903 case LI_DC_WITH_CHECKSUM :
904 if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
906 length = pd[offset + P_VAR_PART_DC + 1];
907 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
915 if (fd->win_info[COL_NUM]) {
916 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
917 sprintf(fd->win_info[COL_INFO], "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
923 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
925 cotp_tree = gtk_tree_new();
926 add_subtree(ti, cotp_tree, ETT_COTP);
927 add_item_to_tree(cotp_tree, offset, 1,
928 "Length indicator: %d", li);
929 add_item_to_tree(cotp_tree, offset + 1, 1,
930 "TPDU code: Ox%x (DC)", tpdu);
931 add_item_to_tree(cotp_tree, offset + 2, 2,
932 "Destination reference: 0x%04x", dst_ref);
933 add_item_to_tree(cotp_tree, offset + 4, 2,
934 "Source reference: 0x%04x", src_ref);
936 add_item_to_tree(cotp_tree,
937 offset + P_VAR_PART_DC + 0, 1,
938 "Parameter code: 0x%02x (checksum)", code);
939 add_item_to_tree(cotp_tree,
940 offset + P_VAR_PART_DC + 1, 1,
941 "Parameter length: 0x%02x", length);
942 add_item_to_tree(cotp_tree,
943 offset + P_VAR_PART_DC + 2, 2,
944 "Checksum: 0x%04x", checksum);
949 dissect_data(pd, offset, fd, tree);
953 } /* osi_decode_DC */
955 static int osi_decode_AK(const u_char *pd, int offset,
956 frame_data *fd, GtkTree *tree)
958 GtkWidget *cotp_tree = NULL, *ti;
959 u_int tpdu_nr,i =0, r_lower_window_edge ;
961 u_short checksum, seq_nr, r_seq_nr, r_cdt;
967 if (!is_LI_NORMAL_AK(li)) {
968 tpdu_nr = pd[offset + P_TPDU_NR_234];
970 if (fd->win_info[COL_NUM]) {
971 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
972 sprintf(fd->win_info[COL_INFO], "AK TPDU (%d) dst-ref: 0x%04x",
977 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
979 cotp_tree = gtk_tree_new();
980 add_subtree(ti, cotp_tree, ETT_COTP);
981 add_item_to_tree(cotp_tree, offset, 1,
982 "Length indicator: %d", li);
983 add_item_to_tree(cotp_tree, offset + 1, 1,
984 "TPDU code: Ox%x (AK)", tpdu);
985 add_item_to_tree(cotp_tree, offset + 1, 1,
987 add_item_to_tree(cotp_tree, offset + 2, 2,
988 "Destination reference: 0x%04x", dst_ref);
989 add_item_to_tree(cotp_tree, offset + 4, 1,
990 "Your TPDU number: 0x%02x", tpdu_nr);
993 while(li > P_VAR_PART_NAK + i - 1) {
994 switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
996 length = pd[offset + P_VAR_PART_NAK + i + 1];
997 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
999 add_item_to_tree(cotp_tree,
1000 offset + P_VAR_PART_NAK + i + 0, 1,
1001 "Parameter code: 0x%02x (checksum)", code);
1002 add_item_to_tree(cotp_tree,
1003 offset + P_VAR_PART_NAK + i + 1, 1,
1004 "Parameter length: 0x%02x", length);
1005 add_item_to_tree(cotp_tree,
1006 offset + P_VAR_PART_NAK + i + 2, 2,
1007 "Checksum: 0x%04x", checksum);
1012 length = pd[offset + P_VAR_PART_NAK + i + 1];
1013 r_lower_window_edge =
1014 EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
1015 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
1016 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
1018 add_item_to_tree(cotp_tree,
1019 offset + P_VAR_PART_NAK + i + 0, 1,
1020 "Parameter code: 0x%02x (flow control)",
1022 add_item_to_tree(cotp_tree,
1023 offset + P_VAR_PART_NAK + i + 1, 1,
1024 "Parameter length: 0x%02x", length);
1025 add_item_to_tree(cotp_tree,
1026 offset + P_VAR_PART_NAK + i + 2, 4,
1027 "Lower window edge: 0x%08x",
1028 r_lower_window_edge);
1029 add_item_to_tree(cotp_tree,
1030 offset + P_VAR_PART_NAK + i + 6, 2,
1031 "Sequence number: 0x%04x",
1033 add_item_to_tree(cotp_tree,
1034 offset + P_VAR_PART_NAK + i + 8, 2,
1041 length = pd[offset + P_VAR_PART_NAK + i + 1];
1042 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1044 add_item_to_tree(cotp_tree,
1045 offset + P_VAR_PART_NAK + i + 0, 1,
1046 "Parameter code: 0x%02x (seq number)", code);
1047 add_item_to_tree(cotp_tree,
1048 offset + P_VAR_PART_NAK + i + 1, 1,
1049 "Parameter length: 0x%02x", length);
1050 add_item_to_tree(cotp_tree,
1051 offset + P_VAR_PART_NAK + i + 2, 2,
1052 "Sequence number: 0x%04x", seq_nr);
1057 length = pd[offset + P_VAR_PART_NAK + i + 1];
1059 add_item_to_tree(cotp_tree,
1060 offset + P_VAR_PART_NAK + i + 0, 1,
1061 "Parameter code: 0x%02x (unknown)", code);
1062 add_item_to_tree(cotp_tree,
1063 offset + P_VAR_PART_NAK + i + 1, 1,
1064 "Parameter length: 0x%02x", length);
1065 add_item_to_tree(cotp_tree,
1066 offset + P_VAR_PART_NAK + i + 2, length,
1067 "Parameter value: <not shown>");
1073 } else { /* extended format */
1075 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1076 cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
1078 if (fd->win_info[COL_NUM]) {
1079 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
1080 sprintf(fd->win_info[COL_INFO], "AK TPDU (%d) dst-ref: 0x%04x",
1085 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
1087 cotp_tree = gtk_tree_new();
1088 add_subtree(ti, cotp_tree, ETT_COTP);
1089 add_item_to_tree(cotp_tree, offset, 1,
1090 "Length indicator: %d", li);
1091 add_item_to_tree(cotp_tree, offset + 1, 1,
1092 "TPDU code: Ox%x (AK)", tpdu);
1093 add_item_to_tree(cotp_tree, offset + 2, 2,
1094 "Destination reference: 0x%04x", dst_ref);
1095 add_item_to_tree(cotp_tree, offset + 4, 4,
1096 "Your TPDU number: 0x%08x", tpdu_nr);
1097 add_item_to_tree(cotp_tree, offset + 8, 2,
1098 "Credit: 0x%04x", cdt_in_ak);
1101 while(li > P_VAR_PART_EAK + i - 1) {
1102 switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
1104 length = pd[offset + P_VAR_PART_EAK + i + 1];
1105 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1107 add_item_to_tree(cotp_tree,
1108 offset + P_VAR_PART_EAK + i + 0, 1,
1109 "Parameter code: 0x%02x (checksum)", code);
1110 add_item_to_tree(cotp_tree,
1111 offset + P_VAR_PART_EAK + i + 1, 1,
1112 "Parameter length: 0x%02x", length);
1113 add_item_to_tree(cotp_tree,
1114 offset + P_VAR_PART_EAK + i + 2, 2,
1115 "Checksum: 0x%04x", checksum);
1120 length = pd[offset + P_VAR_PART_EAK + i + 1];
1121 r_lower_window_edge =
1122 EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
1123 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
1124 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
1126 add_item_to_tree(cotp_tree,
1127 offset + P_VAR_PART_EAK + i + 0, 1,
1128 "Parameter code: 0x%02x (flow control)",
1130 add_item_to_tree(cotp_tree,
1131 offset + P_VAR_PART_EAK + i + 1, 1,
1132 "Parameter length: 0x%02x", length);
1133 add_item_to_tree(cotp_tree,
1134 offset + P_VAR_PART_EAK + i + 2, 4,
1135 "Lower window edge: 0x%08x",
1136 r_lower_window_edge);
1137 add_item_to_tree(cotp_tree,
1138 offset + P_VAR_PART_EAK + i + 6, 2,
1139 "Sequence number: 0x%04x",
1141 add_item_to_tree(cotp_tree,
1142 offset + P_VAR_PART_EAK + i + 8, 2,
1149 length = pd[offset + P_VAR_PART_EAK + i + 1];
1150 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1152 add_item_to_tree(cotp_tree,
1153 offset + P_VAR_PART_EAK + i + 0, 1,
1154 "Parameter code: 0x%02x (seq number)", code);
1155 add_item_to_tree(cotp_tree,
1156 offset + P_VAR_PART_EAK + i + 1, 1,
1157 "Parameter length: 0x%02x", length);
1158 add_item_to_tree(cotp_tree,
1159 offset + P_VAR_PART_EAK + i + 2, 2,
1160 "Sequence number: 0x%04x", seq_nr);
1165 length = pd[offset + P_VAR_PART_EAK + i + 1];
1167 add_item_to_tree(cotp_tree,
1168 offset + P_VAR_PART_EAK + i + 0, 1,
1169 "Parameter code: 0x%02x (unknown)", code);
1170 add_item_to_tree(cotp_tree,
1171 offset + P_VAR_PART_EAK + i + 1, 1,
1172 "Parameter length: 0x%02x", length);
1173 add_item_to_tree(cotp_tree,
1174 offset + P_VAR_PART_EAK + i + 2, length,
1175 "Parameter value: <not shown>");
1182 } /* is_LI_NORMAL_AK */
1185 dissect_data(pd, offset, fd, tree);
1189 } /* osi_decode_AK */
1191 static int osi_decode_EA(const u_char *pd, int offset,
1192 frame_data *fd, GtkTree *tree)
1194 GtkWidget *cotp_tree, *ti;
1196 u_short checksum = 0;
1204 case LI_NORMAL_EA_WITH_CHECKSUM :
1205 tpdu_nr = pd[offset + P_TPDU_NR_234];
1206 code = pd[offset + P_VAR_PART_NDT];
1207 length = pd[offset + P_VAR_PART_NDT + 1];
1208 if (code != VP_CHECKSUM || length != 1)
1210 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
1212 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1213 tpdu_nr = pd[offset + P_TPDU_NR_234];
1215 case LI_EXTENDED_EA_WITH_CHECKSUM :
1216 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1217 code = pd[offset + P_VAR_PART_EDT];
1218 length = pd[offset + P_VAR_PART_EDT + 1];
1219 if (code != VP_CHECKSUM || length != 1)
1221 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
1223 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1224 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1226 default : /* bad TPDU */
1232 if (fd->win_info[COL_NUM]) {
1233 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
1234 sprintf(fd->win_info[COL_INFO], "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1238 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
1240 cotp_tree = gtk_tree_new();
1241 add_subtree(ti, cotp_tree, ETT_COTP);
1242 add_item_to_tree(cotp_tree, offset, 1,
1243 "Length indicator: %d", li);
1244 add_item_to_tree(cotp_tree, offset + 1, 1,
1245 "TPDU code: Ox%x (EA)", tpdu);
1246 add_item_to_tree(cotp_tree, offset + 2, 2,
1247 "Destination reference: 0x%04x", dst_ref);
1250 case LI_NORMAL_EA_WITH_CHECKSUM :
1251 add_item_to_tree(cotp_tree, offset + 4, 1,
1252 "Your TPDU number: 0x%02x", tpdu_nr);
1253 add_item_to_tree(cotp_tree, offset + 5, 1,
1254 "Parameter code: 0x%02x (checksum)", code);
1255 add_item_to_tree(cotp_tree, offset + 6, 1,
1256 "Parameter length: 0x%02x", length);
1257 add_item_to_tree(cotp_tree, offset + 7, 2,
1258 "Checksum: 0x%04x", checksum);
1260 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1261 add_item_to_tree(cotp_tree, offset + 4, 1,
1262 "Your TPDU number: 0x%02x", tpdu_nr);
1264 case LI_EXTENDED_EA_WITH_CHECKSUM :
1265 add_item_to_tree(cotp_tree, offset + 4, 4,
1266 "Your TPDU number: 0x%08x", tpdu_nr);
1267 add_item_to_tree(cotp_tree, offset + 8, 1,
1268 "Parameter code: 0x%02x (checksum)", code);
1269 add_item_to_tree(cotp_tree, offset + 9, 1,
1270 "Parameter length: 0x%02x", length);
1271 add_item_to_tree(cotp_tree, offset + 10, 2,
1272 "Checksum: 0x%04x", checksum);
1274 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1275 add_item_to_tree(cotp_tree, offset + 4, 4,
1276 "Your TPDU number: 0x%08x", tpdu_nr);
1284 dissect_data(pd, offset, fd, tree);
1288 } /* osi_decode_EA */
1290 static int osi_decode_ER(const u_char *pd, int offset,
1291 frame_data *fd, GtkTree *tree)
1293 GtkWidget *cotp_tree, *ti;
1299 switch(pd[offset + P_REJECT_ER]) {
1301 str = "Reason not specified";
1304 str = "Invalid parameter code";
1307 str = "Invalid TPDU type";
1310 str = "Invalid parameter value";
1318 if (fd->win_info[COL_NUM]) {
1319 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
1320 sprintf(fd->win_info[COL_INFO], "ER TPDU dst-ref: 0x%04x", dst_ref);
1324 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
1326 cotp_tree = gtk_tree_new();
1327 add_subtree(ti, cotp_tree, ETT_COTP);
1328 add_item_to_tree(cotp_tree, offset, 1,
1329 "Length indicator: %d", li);
1330 add_item_to_tree(cotp_tree, offset + 1, 1,
1331 "TPDU code: Ox%x (ER)", tpdu);
1332 add_item_to_tree(cotp_tree, offset + 2, 2,
1333 "Destination reference: 0x%04x", dst_ref);
1334 add_item_to_tree(cotp_tree, offset + 4, 1,
1335 "Reject cause: %s", str);
1339 dissect_data(pd, offset, fd, tree);
1343 } /* osi_decode_ER */
1345 void dissect_cotp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
1350 if (((li = pd[offset + P_LI]) == 0) ||
1351 (offset + P_LI + li + 1 > fd->cap_len)) {
1352 dissect_data(pd, offset, fd, tree);
1356 tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
1357 cdt = pd[offset + P_CDT] & 0x0F;
1358 dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
1363 status = osi_decode_CC(pd, offset, fd, tree);
1366 status = osi_decode_DR(pd, offset, fd, tree);
1369 status = osi_decode_DT(pd, offset, fd, tree);
1372 status = osi_decode_ED(pd, offset, fd, tree);
1375 status = osi_decode_RJ(pd, offset, fd, tree);
1378 status = osi_decode_DC(pd, offset, fd, tree);
1381 status = osi_decode_AK(pd, offset, fd, tree);
1384 status = osi_decode_EA(pd, offset, fd, tree);
1387 status = osi_decode_ER(pd, offset, fd, tree);
1393 if (status == -1) /* incorrect TPDU */
1394 dissect_data(pd, offset, fd, tree);
1396 } /* dissect_cotp */
1403 #define MAX_NSAP_LEN 20
1405 static gchar *print_nsap(const u_char *nsap, int length)
1408 /* to do : real NSAP decoding */
1410 static gchar str[3][MAX_NSAP_LEN * 3 + 1];
1414 if (cur == &str[0][0]) {
1416 } else if (cur == &str[1][0]) {
1423 if (length <= 0 || length > MAX_NSAP_LEN)
1424 sprintf(cur, "<invalid NSAP>");
1426 while (length != 1) {
1427 sprintf(tmp, "%02x:", *nsap ++);
1431 sprintf(tmp, "%02x", *nsap);
1437 void dissect_clnp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
1440 struct clnp_header clnp;
1441 GtkWidget *clnp_tree = NULL, *ti;
1442 u_char src_len, dst_len, nsel;
1443 u_int first_offset = offset;
1445 if (fd->cap_len < offset + sizeof(clnp)) {
1446 dissect_data(pd, offset, fd, tree);
1450 /* avoid alignment problem */
1451 memcpy(&clnp, &pd[offset], sizeof(clnp));
1453 /* return if version not known */
1454 if (clnp.cnf_vers != ISO8473_V1) {
1455 dissect_data(pd, offset, fd, tree);
1459 /* fixed part decoding */
1462 ti = add_item_to_tree(GTK_WIDGET(tree), offset, clnp.cnf_hdr_len,
1464 clnp_tree = gtk_tree_new();
1465 add_subtree(ti, clnp_tree, ETT_CLNP);
1466 add_item_to_tree(clnp_tree, offset, 1,
1467 "Protocol identifier: 0x%02x", clnp.cnf_proto_id);
1468 add_item_to_tree(clnp_tree, offset + 1, 1,
1469 "Length: %d", clnp.cnf_hdr_len);
1470 add_item_to_tree(clnp_tree, offset + 2, 1,
1471 "Version: %d", clnp.cnf_vers);
1472 add_item_to_tree(clnp_tree, offset + 3, 1,
1473 "TTL: %d (%d secs)",
1474 clnp.cnf_ttl, clnp.cnf_ttl / 2);
1475 add_item_to_tree(clnp_tree, offset + 4, 1,
1476 "Type code: 0x%02x (%s%s%s%s)",
1478 (clnp.cnf_type & CNF_SEG_OK) ? "S " : "",
1479 (clnp.cnf_type & CNF_MORE_SEGS) ? "M " : "",
1480 (clnp.cnf_type & CNF_ERR_OK) ? "E " : "",
1481 (clnp.cnf_type & CNF_TYPE) == DT_NPDU ? "DT" : "ER");
1482 add_item_to_tree(clnp_tree, offset + 5, 2,
1483 "PDU segment length: %d",
1484 EXTRACT_SHORT(&clnp.cnf_seglen_msb));
1485 add_item_to_tree(clnp_tree, offset + 7, 2,
1487 EXTRACT_SHORT(&clnp.cnf_cksum_msb));
1490 /* stop here if header is not complete */
1492 if (fd->cap_len < offset + clnp.cnf_hdr_len) {
1493 dissect_data(pd, offset, fd, tree);
1499 offset += P_ADDRESS_PART;
1500 dst_len = pd[offset];
1501 nsel = pd[offset + dst_len];
1502 src_len = pd[offset + dst_len + 1];
1505 add_item_to_tree(clnp_tree, offset, 1,
1506 "Destination address length: 0x%02x", dst_len);
1507 add_item_to_tree(clnp_tree, offset + 1 , dst_len,
1508 "Destination address: %s",
1509 print_nsap(&pd[offset + 1], dst_len));
1510 add_item_to_tree(clnp_tree, offset + 1 + dst_len, 1,
1511 "Source address length: 0x%02x", src_len);
1512 add_item_to_tree(clnp_tree, offset + dst_len + 2, src_len,
1513 "Source address: %s",
1514 print_nsap(&pd[offset + dst_len + 2], src_len));
1517 if (fd->win_info[COL_NUM]) {
1518 sprintf(fd->win_info[COL_SOURCE], "%s",
1519 print_nsap(&pd[offset + dst_len + 2], src_len));
1520 sprintf(fd->win_info[COL_DESTINATION], "%s",
1521 print_nsap(&pd[offset + 1], dst_len));
1524 /* Segmentation Part */
1526 offset += dst_len + src_len + 2;
1528 if (tree && (clnp.cnf_type & CNF_SEG_OK)) {
1529 struct clnp_segment seg;
1530 memcpy(&seg, &pd[offset], sizeof(seg));
1532 add_item_to_tree(clnp_tree, offset, 2,
1533 "Data unit identifier: 0x%04x",
1534 EXTRACT_SHORT(&pd[offset]));
1535 add_item_to_tree(clnp_tree, offset + 2 , 2,
1536 "Segment offset: 0x%04x",
1537 EXTRACT_SHORT(&pd[offset + 2]));
1538 add_item_to_tree(clnp_tree, offset + 4 , 2,
1539 "Total length: 0x%04x",
1540 EXTRACT_SHORT(&pd[offset + 4]));
1546 /* To do : decode options */
1548 add_item_to_tree(clnp_tree, offset,
1549 clnp.cnf_hdr_len + first_offset - offset,
1550 "Options/Data: <not shown>");
1554 offset = first_offset + clnp.cnf_hdr_len;
1556 if (offset == fd->cap_len)
1559 /* continue with COTP if any */
1561 if (nsel == NSEL_TP) /* just guessing here - valid for DECNet-OSI */
1562 dissect_cotp(pd, offset, fd, tree);
1564 dissect_data(pd, offset, fd, tree);
1566 } /* dissect_clnp */
1569 /* main entry point */
1571 void dissect_osi(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
1574 switch (pd[offset]) {
1576 /* only CLNP is currently decoded */
1579 if (fd->win_info[COL_NUM])
1581 strcpy(fd->win_info[COL_PROTOCOL], "CLNP");
1583 dissect_clnp(pd, offset, fd, tree);
1586 if (fd->win_info[COL_NUM])
1588 strcpy(fd->win_info[COL_PROTOCOL], "ESIS");
1590 dissect_data(pd, offset, fd, tree);
1592 case ISO9542X25_ESIS:
1593 if (fd->win_info[COL_NUM])
1595 strcpy(fd->win_info[COL_PROTOCOL], "ESIS(X25)");
1597 dissect_data(pd, offset, fd, tree);
1600 if (fd->win_info[COL_NUM])
1602 strcpy(fd->win_info[COL_PROTOCOL], "ISIS");
1604 dissect_data(pd, offset, fd, tree);
1607 if (fd->win_info[COL_NUM])
1609 strcpy(fd->win_info[COL_PROTOCOL], "ISO");
1610 sprintf(fd->win_info[COL_INFO], "Unknown ISO protocol (%02x)", pd[offset]);
1612 dissect_data(pd, offset, fd, tree);