2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-osi.c,v 1.3 1998/10/13 17:56:41 deniel 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)
45 #ifdef HAVE_SYS_TYPES_H
46 # include <sys/types.h>
52 /* Network layer protocol identifiers */
54 #define ISO8473_CLNP 0x81
55 #define ISO9542_ESIS 0x82
56 #define ISO10589_ISIS 0x83
57 #define ISO9542X25_ESIS 0x8a
60 * ISO8473 OSI CLNP definition (see RFC994)
62 * _________________________________
64 * |_________________________________|
66 * |_________________________________|
67 * | Segmentation Part (optional) |
68 * |_________________________________|
69 * | Options Part (optional) |
70 * |_________________________________|
72 * |_________________________________|
75 #define ISO8473_V1 0x01 /* CLNP version 1 */
80 u_char cnf_proto_id; /* network layer protocol identifier */
81 u_char cnf_hdr_len; /* length indicator (octets) */
82 u_char cnf_vers; /* version/protocol identifier extension */
83 u_char cnf_ttl; /* lifetime (500 milliseconds) */
84 u_char cnf_type; /* type code */
85 u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
86 u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
87 u_char cnf_cksum_msb; /* checksum high byte */
88 u_char cnf_cksum_lsb; /* checksum low byte */
92 #define CNF_ERR_OK 0x20
93 #define CNF_MORE_SEGS 0x40
94 #define CNF_SEG_OK 0x80
101 #define P_ADDRESS_PART 9
103 /* Segmentation part */
105 struct clnp_segment {
106 u_short cng_id; /* data unit identifier */
107 u_short cng_off; /* segment offset */
108 u_short cng_tot_len; /* total length */
113 #define NSEL_NET 0x00
118 * ISO8073 OSI COTP definition (see RFC905)
121 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
123 /* TPDU definition */
143 #define P_TPDU_NR_0_1 2
144 #define P_TPDU_NR_234 4
145 #define P_VAR_PART_NDT 5
146 #define P_VAR_PART_EDT 8
147 #define P_VAR_PART_NAK 5
148 #define P_VAR_PART_CC 7
149 #define P_VAR_PART_EAK 10
150 #define P_VAR_PART_DC 6
151 #define P_VAR_PART_DR 7
152 #define P_CDT_IN_AK 8
153 #define P_CDT_IN_RJ 8
154 #define P_REJECT_ER 4
155 #define P_REASON_IN_DR 6
156 #define P_CLASS_OPTION 6
158 /* TPDU length indicator */
160 #define LI_NORMAL_DT_CLASS_01 2
161 #define LI_NORMAL_DT_WITH_CHECKSUM 8
162 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
163 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
164 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
165 #define LI_NORMAL_EA_WITH_CHECKSUM 8
166 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
167 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
168 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
169 #define LI_NORMAL_RJ 4
170 #define LI_EXTENDED_RJ 9
176 #define LI_DC_WITH_CHECKSUM 9
177 #define LI_DC_WITHOUT_CHECKSUM 5
178 #define is_LI_NORMAL_AK(p) ( p & 0x01 )
182 #define VP_ACK_TIME 0x85
183 #define VP_RES_ERROR 0x86
184 #define VP_PRIORITY 0x87
185 #define VP_TRANSIT_DEL 0x88
186 #define VP_THROUGHPUT 0x89
187 #define VP_SEQ_NR 0x8A /* in AK */
188 #define VP_REASSIGNMENT 0x8B
189 #define VP_FLOW_CNTL 0x8C /* in AK */
190 #define VP_TPDU_SIZE 0xC0
191 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
192 #define VP_DST_TSAP 0xC2
193 #define VP_CHECKSUM 0xC3
194 #define VP_VERSION_NR 0xC4
195 #define VP_PROTECTION 0xC5
196 #define VP_OPT_SEL 0xC6
197 #define VP_PROTO_CLASS 0xC7
201 #define EXTRACT_SHORT(p) pntohs(p)
202 #define EXTRACT_LONG(p) pntohl(p)
204 /* global variables */
206 static u_char li, tpdu, cdt; /* common fields */
207 static u_short dst_ref;
209 /* function definitions */
211 static int osi_decode_DR(const u_char *pd, int offset,
212 frame_data *fd, GtkTree *tree)
214 GtkWidget *cotp_tree, *ti;
222 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
223 reason = pd[offset + P_REASON_IN_DR];
226 case (128+0): str = "Normal Disconnect"; break;
227 case (128+1): str = "Remote transport enity congestion"; break;
228 case (128+2): str = "Connection negotiation failed"; break;
229 case (128+3): str = "Duplicate source reference"; break;
230 case (128+4): str = "Mismatched references"; break;
231 case (128+5): str = "Protocol error"; break;
232 case (128+7): str = "Reference overflow"; break;
233 case (128+8): str = "Connection requestion refused"; break;
234 case (128+10):str = "Header or parameter length invalid"; break;
235 case (0): str = "Reason not specified"; break;
236 case (1): str = "Congestion at TSAP"; break;
237 case (2): str = "Session entity not attached to TSAP"; break;
238 case (3): str = "Address unknown"; break;
244 if (fd->win_info[COL_NUM]) {
245 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
246 sprintf(fd->win_info[COL_INFO], "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
251 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
253 cotp_tree = gtk_tree_new();
254 add_subtree(ti, cotp_tree, ETT_COTP);
255 add_item_to_tree(cotp_tree, offset, 1,
256 "Length indicator: %d", li);
257 add_item_to_tree(cotp_tree, offset + 1, 1,
258 "TPDU code: Ox%x (DR)", tpdu);
259 add_item_to_tree(cotp_tree, offset + 2, 2,
260 "Destination reference: 0x%04x", dst_ref);
261 add_item_to_tree(cotp_tree, offset + 4, 2,
262 "Source reference: 0x%04x", src_ref);
263 add_item_to_tree(cotp_tree, offset + 6, 1,
268 dissect_data(pd, offset, fd, tree);
272 } /* osi_decode_DR */
274 static int osi_decode_DT(const u_char *pd, int offset,
275 frame_data *fd, GtkTree *tree)
277 GtkWidget *cotp_tree, *ti;
279 u_short checksum = 0;
280 u_char code = 0, length = 0;
284 case LI_NORMAL_DT_WITH_CHECKSUM :
285 tpdu_nr = pd[offset + P_TPDU_NR_234];
286 if ( tpdu_nr & 0x80 )
287 tpdu_nr = tpdu_nr & 0x7F;
290 code = pd[offset + P_VAR_PART_NDT];
291 if (code == VP_CHECKSUM)
292 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
296 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
297 tpdu_nr = pd[offset + P_TPDU_NR_234];
298 if ( tpdu_nr & 0x80 )
299 tpdu_nr = tpdu_nr & 0x7F;
303 case LI_EXTENDED_DT_WITH_CHECKSUM :
304 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
305 if ( tpdu_nr & 0x80000000 )
306 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
309 code = pd[offset + P_VAR_PART_EDT];
310 if (code == VP_CHECKSUM)
311 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
315 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
316 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
317 if ( tpdu_nr & 0x80000000 )
318 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
322 case LI_NORMAL_DT_CLASS_01 :
323 tpdu_nr = pd[offset + P_TPDU_NR_0_1];
324 if ( tpdu_nr & 0x80 )
325 tpdu_nr = tpdu_nr & 0x7F;
329 default : /* bad TPDU */
335 if (fd->win_info[COL_NUM]) {
336 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
337 sprintf(fd->win_info[COL_INFO], "DT TPDU (%d) dst-ref: 0x%04x %s",
340 (fragment)? "(fragment)" : "");
344 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
346 cotp_tree = gtk_tree_new();
347 add_subtree(ti, cotp_tree, ETT_COTP);
348 add_item_to_tree(cotp_tree, offset, 1,
349 "Length indicator: %d", li);
350 add_item_to_tree(cotp_tree, offset + 1, 1,
351 "TPDU code: Ox%x (DT)", tpdu);
353 if (li != LI_NORMAL_DT_CLASS_01)
354 add_item_to_tree(cotp_tree, offset + 2, 2,
355 "Destination reference: 0x%04x", dst_ref);
358 case LI_NORMAL_DT_WITH_CHECKSUM :
359 add_item_to_tree(cotp_tree, offset + 4, 1,
360 "TPDU number: 0x%02x (%s)",
362 (fragment)? "fragment":"complete");
363 add_item_to_tree(cotp_tree,
364 offset + P_VAR_PART_NDT, 1,
365 "Parameter code: 0x%02x (checksum)", code);
366 add_item_to_tree(cotp_tree,
367 offset + P_VAR_PART_NDT + 1, 1,
368 "Parameter length: 0x%02x", length);
369 add_item_to_tree(cotp_tree,
370 offset + P_VAR_PART_NDT + 2, length,
371 "Checksum: 0x%04x", checksum);
373 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
374 add_item_to_tree(cotp_tree, offset + 4, 1,
375 "TPDU number: 0x%02x (%s)",
377 (fragment)? "fragment":"complete");
379 case LI_EXTENDED_DT_WITH_CHECKSUM :
380 add_item_to_tree(cotp_tree, offset + 4, 4,
381 "TPDU number: 0x%08x (%s)",
383 (fragment)? "fragment":"complete");
384 add_item_to_tree(cotp_tree,
385 offset + P_VAR_PART_EDT, 1,
386 "Parameter code: 0x%02x (checksum)", code);
387 add_item_to_tree(cotp_tree,
388 offset + P_VAR_PART_EDT + 1, 1,
389 "Parameter length: 0x%02x", length);
390 add_item_to_tree(cotp_tree,
391 offset + P_VAR_PART_EDT + 2, length,
392 "Checksum: 0x%04x", checksum);
394 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
395 add_item_to_tree(cotp_tree, offset + 4, 4,
396 "TPDU number: 0x%08x (%s)",
398 (fragment)? "fragment":"complete");
400 case LI_NORMAL_DT_CLASS_01 :
401 add_item_to_tree(cotp_tree, offset + 2, 1,
402 "TPDU number: 0x%02x (%s)",
404 (fragment)? "fragment":"complete");
410 dissect_data(pd, offset, fd, tree);
414 } /* osi_decode_DT */
416 static int osi_decode_ED(const u_char *pd, int offset,
417 frame_data *fd, GtkTree *tree)
419 GtkWidget *cotp_tree, *ti;
421 u_short checksum = 0;
422 u_char code = 0, length = 0;
424 /* ED TPDUs are never fragmented */
427 case LI_NORMAL_DT_WITH_CHECKSUM :
428 tpdu_nr = pd[offset + P_TPDU_NR_234];
429 if ( tpdu_nr & 0x80 )
430 tpdu_nr = tpdu_nr & 0x7F;
433 code = pd[offset + P_VAR_PART_NDT];
434 length = pd[offset + P_VAR_PART_NDT + 1];
435 if (code == VP_CHECKSUM)
436 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
440 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
441 tpdu_nr = pd[offset + P_TPDU_NR_234];
442 if ( tpdu_nr & 0x80 )
443 tpdu_nr = tpdu_nr & 0x7F;
447 case LI_EXTENDED_DT_WITH_CHECKSUM :
448 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
449 if ( tpdu_nr & 0x80000000 )
450 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
453 code = pd[offset + P_VAR_PART_EDT];
454 length = pd[offset + P_VAR_PART_EDT + 1];
455 if (code == VP_CHECKSUM)
456 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
460 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
461 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
462 if ( tpdu_nr & 0x80000000 )
463 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
467 default : /* bad TPDU */
473 if (fd->win_info[COL_NUM]) {
474 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
475 sprintf(fd->win_info[COL_INFO], "ED TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
479 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
481 cotp_tree = gtk_tree_new();
482 add_subtree(ti, cotp_tree, ETT_COTP);
483 add_item_to_tree(cotp_tree, offset, 1,
484 "Length indicator: %d", li);
485 add_item_to_tree(cotp_tree, offset + 1, 1,
486 "TPDU code: Ox%x (ED)", tpdu);
487 add_item_to_tree(cotp_tree, offset + 2, 2,
488 "Destination reference: 0x%04x", dst_ref);
491 case LI_NORMAL_DT_WITH_CHECKSUM :
492 add_item_to_tree(cotp_tree, offset + 4, 1,
493 "TPDU number: 0x%02x", tpdu_nr);
494 add_item_to_tree(cotp_tree,
495 offset + P_VAR_PART_NDT, 1,
496 "Parameter code: 0x%02x (checksum)", code);
497 add_item_to_tree(cotp_tree,
498 offset + P_VAR_PART_NDT + 1, 1,
499 "Parameter length: 0x%02x", length);
500 add_item_to_tree(cotp_tree,
501 offset + P_VAR_PART_NDT + 2, length,
502 "Checksum: 0x%04x", checksum);
504 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
505 add_item_to_tree(cotp_tree, offset + 4, 1,
506 "TPDU number: 0x%02x", tpdu_nr);
508 case LI_EXTENDED_DT_WITH_CHECKSUM :
509 add_item_to_tree(cotp_tree, offset + 4, 4,
510 "TPDU number: 0x%02x", tpdu_nr);
511 add_item_to_tree(cotp_tree,
512 offset + P_VAR_PART_EDT, 1,
513 "Parameter code: 0x%02x (checksum)", code);
514 add_item_to_tree(cotp_tree,
515 offset + P_VAR_PART_EDT + 1, 1,
516 "Parameter length: 0x%02x", length);
517 add_item_to_tree(cotp_tree,
518 offset + P_VAR_PART_EDT + 2, length,
519 "Checksum: 0x%04x", checksum);
521 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
522 add_item_to_tree(cotp_tree, offset + 4, 4,
523 "TPDU number: 0x%02x", tpdu_nr);
529 dissect_data(pd, offset, fd, tree);
533 } /* osi_decode_ED */
535 static int osi_decode_RJ(const u_char *pd, int offset,
536 frame_data *fd, GtkTree *tree)
538 GtkWidget *cotp_tree, *ti;
544 tpdu_nr = pd[offset + P_TPDU_NR_234];
546 case LI_EXTENDED_RJ :
547 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
548 credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
556 if (fd->win_info[COL_NUM]) {
557 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
558 sprintf(fd->win_info[COL_INFO], "RJ TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
562 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
564 cotp_tree = gtk_tree_new();
565 add_subtree(ti, cotp_tree, ETT_COTP);
566 add_item_to_tree(cotp_tree, offset, 1,
567 "Length indicator: %d", li);
568 add_item_to_tree(cotp_tree, offset + 1, 1,
569 "TPDU code: Ox%x (RJ)", tpdu);
570 if (li == LI_NORMAL_RJ)
571 add_item_to_tree(cotp_tree, offset + 1, 1,
573 add_item_to_tree(cotp_tree, offset + 2, 2,
574 "Destination reference: 0x%04x", dst_ref);
575 if (li == LI_NORMAL_RJ)
576 add_item_to_tree(cotp_tree, offset + 4, 1,
577 "Your TPDU number: 0x%02x", tpdu_nr);
579 add_item_to_tree(cotp_tree, offset + 4, 4,
580 "Your TPDU number: 0x%02x", tpdu_nr);
581 add_item_to_tree(cotp_tree, offset + 8, 2,
582 "Credit: 0x%02x", credit);
587 dissect_data(pd, offset, fd, tree);
591 } /* osi_decode_RJ */
593 #define MAX_TSAP_LEN 32
595 static gchar *print_tsap(const u_char *tsap, int length)
598 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
602 if (cur == &str[0][0]) {
604 } else if (cur == &str[1][0]) {
610 /* to do: test if all bytes are printable */
613 if (length <= 0 || length > MAX_TSAP_LEN)
614 sprintf(cur, "<unsupported TSAP length>");
616 while (length != 0) {
617 sprintf(tmp, "%02x", *tsap ++);
626 static int osi_decode_CC(const u_char *pd, int offset,
627 frame_data *fd, GtkTree *tree)
630 /* CC & CR decoding in the same function */
632 GtkWidget *cotp_tree = NULL, *ti;
633 u_short src_ref, checksum;
634 u_char class_option, code, length;
637 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
638 class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
639 if (class_option > 4)
642 if (fd->win_info[COL_NUM]) {
643 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
644 sprintf(fd->win_info[COL_INFO], "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
645 (tpdu == CR_TPDU) ? "CR" : "CC",
651 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
653 cotp_tree = gtk_tree_new();
654 add_subtree(ti, cotp_tree, ETT_COTP);
655 add_item_to_tree(cotp_tree, offset, 1,
656 "Length indicator: %d", li);
657 add_item_to_tree(cotp_tree, offset + 1, 1,
658 "TPDU code: Ox%x (%s)", tpdu,
659 (tpdu == CR_TPDU) ? "CR" : "CC");
660 add_item_to_tree(cotp_tree, offset + 2, 2,
661 "Destination reference: 0x%04x", dst_ref);
662 add_item_to_tree(cotp_tree, offset + 4, 2,
663 "Source reference: 0x%04x", src_ref);
664 add_item_to_tree(cotp_tree, offset + 6, 1,
665 "Class option: 0x%02x", class_option);
669 while(li > P_VAR_PART_CC + i - 1) {
672 u_short s, s1,s2,s3,s4;
675 switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
677 length = pd[offset + P_VAR_PART_CC + i + 1];
678 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
679 add_item_to_tree(cotp_tree,
680 offset + P_VAR_PART_CC + i, 1,
681 "Parameter code: 0x%02x (checksum)", code);
682 add_item_to_tree(cotp_tree,
683 offset + P_VAR_PART_CC + i + 1, 1,
684 "Parameter length: 0x%02x", length);
685 add_item_to_tree(cotp_tree,
686 offset + P_VAR_PART_CC + i + 2, length,
687 "Checksum: 0x%04x", checksum);
691 length = pd[offset + P_VAR_PART_CC + i + 1];
692 add_item_to_tree(cotp_tree,
693 offset + P_VAR_PART_CC + i, 1,
694 "Parameter code: 0x%02x (src-tsap)", code);
695 add_item_to_tree(cotp_tree,
696 offset + P_VAR_PART_CC + i + 1, 1,
697 "Parameter length: 0x%02x", length);
698 add_item_to_tree(cotp_tree,
699 offset + P_VAR_PART_CC + i + 2, length,
700 "Calling TSAP: 0x%s",
701 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
706 length = pd[offset + P_VAR_PART_CC + i + 1];
707 add_item_to_tree(cotp_tree,
708 offset + P_VAR_PART_CC + i, 1,
709 "Parameter code: 0x%02x (dst-tsap)", code);
710 add_item_to_tree(cotp_tree,
711 offset + P_VAR_PART_CC + i + 1, 1,
712 "Parameter length: 0x%02x", length);
713 add_item_to_tree(cotp_tree,
714 offset + P_VAR_PART_CC + i + 2, length,
716 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
721 length = pd[offset + P_VAR_PART_CC + i + 1];
722 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
723 add_item_to_tree(cotp_tree,
724 offset + P_VAR_PART_CC + i, 1,
725 "Parameter code: 0x%02x (tpdu-size)", code);
726 add_item_to_tree(cotp_tree,
727 offset + P_VAR_PART_CC + i + 1, 1,
728 "Parameter length: 0x%02x", length);
729 add_item_to_tree(cotp_tree,
730 offset + P_VAR_PART_CC + i + 2, length,
731 "TPDU size: %d", 2 << c1);
735 length = pd[offset + P_VAR_PART_CC + i + 1];
736 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
737 add_item_to_tree(cotp_tree,
738 offset + P_VAR_PART_CC + i, 1,
739 "Parameter code: 0x%02x (options)", code);
740 add_item_to_tree(cotp_tree,
741 offset + P_VAR_PART_CC + i + 1, 1,
742 "Parameter length: 0x%02x", length);
743 if (class_option == 1) {
745 add_item_to_tree(cotp_tree,
746 offset + P_VAR_PART_CC + i + 2, 1,
747 "Use of network expedited data");
749 add_item_to_tree(cotp_tree,
750 offset + P_VAR_PART_CC + i + 2, 1,
751 "Non use of network expedited data");
753 add_item_to_tree(cotp_tree,
754 offset + P_VAR_PART_CC + i + 2, 1,
755 "Use of Receipt confirmation");
757 add_item_to_tree(cotp_tree,
758 offset + P_VAR_PART_CC + i + 2, 1,
759 "Use of explicit AK variant");
760 } else if (class_option == 4) {
762 add_item_to_tree(cotp_tree,
763 offset + P_VAR_PART_CC + i + 2, 1,
764 "Use 16 bit checksum ");
766 add_item_to_tree(cotp_tree,
767 offset + P_VAR_PART_CC + i + 2, 1,
768 "Non-use 16 bit checksum in class 4");
771 add_item_to_tree(cotp_tree,
772 offset + P_VAR_PART_CC + i + 2, 1,
773 "Use of transport expedited data transfer\n");
775 add_item_to_tree(cotp_tree,
776 offset + P_VAR_PART_CC + i + 2, 1,
777 "Non-use of transport expedited data transfer");
781 length = pd[offset + P_VAR_PART_CC + i + 1];
782 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
783 add_item_to_tree(cotp_tree,
784 offset + P_VAR_PART_CC + i, 1,
785 "Parameter code: 0x%02x (ack time)", code);
786 add_item_to_tree(cotp_tree,
787 offset + P_VAR_PART_CC + i + 1, 1,
788 "Parameter length: 0x%02x", length);
789 add_item_to_tree(cotp_tree,
790 offset + P_VAR_PART_CC + i + 2, length,
791 "Ack time (ms): %d", s);
795 length = pd[offset + P_VAR_PART_CC + i + 1];
796 t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
797 t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
798 t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
799 t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
800 add_item_to_tree(cotp_tree,
801 offset + P_VAR_PART_CC + i, 1,
802 "Parameter code: 0x%02x (throughput)", code);
803 add_item_to_tree(cotp_tree,
804 offset + P_VAR_PART_CC + i + 1, 1,
805 "Parameter length: 0x%02x", length);
806 add_item_to_tree(cotp_tree,
807 offset + P_VAR_PART_CC + i + 2, 4,
808 "Target value / calling-called: %d o/s", t1);
809 add_item_to_tree(cotp_tree,
810 offset + P_VAR_PART_CC + i + 6, 4,
811 "Minimum / calling-called: %d o/s", t2);
812 add_item_to_tree(cotp_tree,
813 offset + P_VAR_PART_CC + i + 10, 4,
814 "Target value / called-calling: %d o/s", t3);
815 add_item_to_tree(cotp_tree,
816 offset + P_VAR_PART_CC + i + 14, 4,
817 "Minimum / called-calling: %d o/s", t4);
820 case VP_TRANSIT_DEL :
821 length = pd[offset + P_VAR_PART_CC + i + 1];
822 s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
823 s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
824 s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
825 s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
826 add_item_to_tree(cotp_tree,
827 offset + P_VAR_PART_CC + i, 1,
828 "Parameter code: 0x%02x (transit delay)", code);
829 add_item_to_tree(cotp_tree,
830 offset + P_VAR_PART_CC + i + 1, 1,
831 "Parameter length: 0x%02x", length);
832 add_item_to_tree(cotp_tree,
833 offset + P_VAR_PART_CC + i + 2, 2,
834 "Target value / calling-called: %d ms", s1);
835 add_item_to_tree(cotp_tree,
836 offset + P_VAR_PART_CC + i + 4, 2,
837 "Minimum / calling-called: %d ms", s2);
838 add_item_to_tree(cotp_tree,
839 offset + P_VAR_PART_CC + i + 6, 2,
840 "Target value / called-calling: %d ms", s3);
841 add_item_to_tree(cotp_tree,
842 offset + P_VAR_PART_CC + i + 8, 2,
843 "Minimum / called-calling: %d ms", s4);
847 length = pd[offset + P_VAR_PART_CC + i + 1];
848 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
849 add_item_to_tree(cotp_tree,
850 offset + P_VAR_PART_CC + i, 1,
851 "Parameter code: 0x%02x (priority)", code);
852 add_item_to_tree(cotp_tree,
853 offset + P_VAR_PART_CC + i + 1, 1,
854 "Parameter length: 0x%02x", length);
855 add_item_to_tree(cotp_tree,
856 offset + P_VAR_PART_CC + i + 2, length,
861 case VP_REASSIGNMENT: /* todo */
865 case VP_PROTO_CLASS :
866 default : /* no decoding */
867 length = pd[offset + P_VAR_PART_CC + i + 1];
868 add_item_to_tree(cotp_tree,
869 offset + P_VAR_PART_CC + i + 0, 1,
870 "Parameter code: 0x%02x", code);
871 add_item_to_tree(cotp_tree,
872 offset + P_VAR_PART_CC + i + 1, 1,
873 "Parameter length: 0x%02x", length);
874 add_item_to_tree(cotp_tree,
875 offset + P_VAR_PART_CC + i + 2, length,
876 "Parameter value: <not shown>");
883 dissect_data(pd, offset, fd, tree);
887 } /* osi_decode_CC */
889 static int osi_decode_DC(const u_char *pd, int offset,
890 frame_data *fd, GtkTree *tree)
892 GtkWidget *cotp_tree, *ti;
893 u_short src_ref, checksum = 0;
894 u_char length = 0, code = 0;
899 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
902 case LI_DC_WITHOUT_CHECKSUM :
904 case LI_DC_WITH_CHECKSUM :
905 if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
907 length = pd[offset + P_VAR_PART_DC + 1];
908 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
916 if (fd->win_info[COL_NUM]) {
917 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
918 sprintf(fd->win_info[COL_INFO], "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
924 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
926 cotp_tree = gtk_tree_new();
927 add_subtree(ti, cotp_tree, ETT_COTP);
928 add_item_to_tree(cotp_tree, offset, 1,
929 "Length indicator: %d", li);
930 add_item_to_tree(cotp_tree, offset + 1, 1,
931 "TPDU code: Ox%x (DC)", tpdu);
932 add_item_to_tree(cotp_tree, offset + 2, 2,
933 "Destination reference: 0x%04x", dst_ref);
934 add_item_to_tree(cotp_tree, offset + 4, 2,
935 "Source reference: 0x%04x", src_ref);
937 add_item_to_tree(cotp_tree,
938 offset + P_VAR_PART_DC + 0, 1,
939 "Parameter code: 0x%02x (checksum)", code);
940 add_item_to_tree(cotp_tree,
941 offset + P_VAR_PART_DC + 1, 1,
942 "Parameter length: 0x%02x", length);
943 add_item_to_tree(cotp_tree,
944 offset + P_VAR_PART_DC + 2, 2,
945 "Checksum: 0x%04x", checksum);
950 dissect_data(pd, offset, fd, tree);
954 } /* osi_decode_DC */
956 static int osi_decode_AK(const u_char *pd, int offset,
957 frame_data *fd, GtkTree *tree)
959 GtkWidget *cotp_tree = NULL, *ti;
960 u_int tpdu_nr,i =0, r_lower_window_edge ;
962 u_short checksum, seq_nr, r_seq_nr, r_cdt;
968 if (!is_LI_NORMAL_AK(li)) {
969 tpdu_nr = pd[offset + P_TPDU_NR_234];
971 if (fd->win_info[COL_NUM]) {
972 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
973 sprintf(fd->win_info[COL_INFO], "AK TPDU (%d) dst-ref: 0x%04x",
978 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
980 cotp_tree = gtk_tree_new();
981 add_subtree(ti, cotp_tree, ETT_COTP);
982 add_item_to_tree(cotp_tree, offset, 1,
983 "Length indicator: %d", li);
984 add_item_to_tree(cotp_tree, offset + 1, 1,
985 "TPDU code: Ox%x (AK)", tpdu);
986 add_item_to_tree(cotp_tree, offset + 1, 1,
988 add_item_to_tree(cotp_tree, offset + 2, 2,
989 "Destination reference: 0x%04x", dst_ref);
990 add_item_to_tree(cotp_tree, offset + 4, 1,
991 "Your TPDU number: 0x%02x", tpdu_nr);
994 while(li > P_VAR_PART_NAK + i - 1) {
995 switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
997 length = pd[offset + P_VAR_PART_NAK + i + 1];
998 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1000 add_item_to_tree(cotp_tree,
1001 offset + P_VAR_PART_NAK + i + 0, 1,
1002 "Parameter code: 0x%02x (checksum)", code);
1003 add_item_to_tree(cotp_tree,
1004 offset + P_VAR_PART_NAK + i + 1, 1,
1005 "Parameter length: 0x%02x", length);
1006 add_item_to_tree(cotp_tree,
1007 offset + P_VAR_PART_NAK + i + 2, 2,
1008 "Checksum: 0x%04x", checksum);
1013 length = pd[offset + P_VAR_PART_NAK + i + 1];
1014 r_lower_window_edge =
1015 EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
1016 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
1017 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
1019 add_item_to_tree(cotp_tree,
1020 offset + P_VAR_PART_NAK + i + 0, 1,
1021 "Parameter code: 0x%02x (flow control)",
1023 add_item_to_tree(cotp_tree,
1024 offset + P_VAR_PART_NAK + i + 1, 1,
1025 "Parameter length: 0x%02x", length);
1026 add_item_to_tree(cotp_tree,
1027 offset + P_VAR_PART_NAK + i + 2, 4,
1028 "Lower window edge: 0x%08x",
1029 r_lower_window_edge);
1030 add_item_to_tree(cotp_tree,
1031 offset + P_VAR_PART_NAK + i + 6, 2,
1032 "Sequence number: 0x%04x",
1034 add_item_to_tree(cotp_tree,
1035 offset + P_VAR_PART_NAK + i + 8, 2,
1042 length = pd[offset + P_VAR_PART_NAK + i + 1];
1043 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1045 add_item_to_tree(cotp_tree,
1046 offset + P_VAR_PART_NAK + i + 0, 1,
1047 "Parameter code: 0x%02x (seq number)", code);
1048 add_item_to_tree(cotp_tree,
1049 offset + P_VAR_PART_NAK + i + 1, 1,
1050 "Parameter length: 0x%02x", length);
1051 add_item_to_tree(cotp_tree,
1052 offset + P_VAR_PART_NAK + i + 2, 2,
1053 "Sequence number: 0x%04x", seq_nr);
1058 length = pd[offset + P_VAR_PART_NAK + i + 1];
1060 add_item_to_tree(cotp_tree,
1061 offset + P_VAR_PART_NAK + i + 0, 1,
1062 "Parameter code: 0x%02x (unknown)", code);
1063 add_item_to_tree(cotp_tree,
1064 offset + P_VAR_PART_NAK + i + 1, 1,
1065 "Parameter length: 0x%02x", length);
1066 add_item_to_tree(cotp_tree,
1067 offset + P_VAR_PART_NAK + i + 2, length,
1068 "Parameter value: <not shown>");
1074 } else { /* extended format */
1076 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1077 cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
1079 if (fd->win_info[COL_NUM]) {
1080 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
1081 sprintf(fd->win_info[COL_INFO], "AK TPDU (%d) dst-ref: 0x%04x",
1086 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
1088 cotp_tree = gtk_tree_new();
1089 add_subtree(ti, cotp_tree, ETT_COTP);
1090 add_item_to_tree(cotp_tree, offset, 1,
1091 "Length indicator: %d", li);
1092 add_item_to_tree(cotp_tree, offset + 1, 1,
1093 "TPDU code: Ox%x (AK)", tpdu);
1094 add_item_to_tree(cotp_tree, offset + 2, 2,
1095 "Destination reference: 0x%04x", dst_ref);
1096 add_item_to_tree(cotp_tree, offset + 4, 4,
1097 "Your TPDU number: 0x%08x", tpdu_nr);
1098 add_item_to_tree(cotp_tree, offset + 8, 2,
1099 "Credit: 0x%04x", cdt_in_ak);
1102 while(li > P_VAR_PART_EAK + i - 1) {
1103 switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
1105 length = pd[offset + P_VAR_PART_EAK + i + 1];
1106 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1108 add_item_to_tree(cotp_tree,
1109 offset + P_VAR_PART_EAK + i + 0, 1,
1110 "Parameter code: 0x%02x (checksum)", code);
1111 add_item_to_tree(cotp_tree,
1112 offset + P_VAR_PART_EAK + i + 1, 1,
1113 "Parameter length: 0x%02x", length);
1114 add_item_to_tree(cotp_tree,
1115 offset + P_VAR_PART_EAK + i + 2, 2,
1116 "Checksum: 0x%04x", checksum);
1121 length = pd[offset + P_VAR_PART_EAK + i + 1];
1122 r_lower_window_edge =
1123 EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
1124 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
1125 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
1127 add_item_to_tree(cotp_tree,
1128 offset + P_VAR_PART_EAK + i + 0, 1,
1129 "Parameter code: 0x%02x (flow control)",
1131 add_item_to_tree(cotp_tree,
1132 offset + P_VAR_PART_EAK + i + 1, 1,
1133 "Parameter length: 0x%02x", length);
1134 add_item_to_tree(cotp_tree,
1135 offset + P_VAR_PART_EAK + i + 2, 4,
1136 "Lower window edge: 0x%08x",
1137 r_lower_window_edge);
1138 add_item_to_tree(cotp_tree,
1139 offset + P_VAR_PART_EAK + i + 6, 2,
1140 "Sequence number: 0x%04x",
1142 add_item_to_tree(cotp_tree,
1143 offset + P_VAR_PART_EAK + i + 8, 2,
1150 length = pd[offset + P_VAR_PART_EAK + i + 1];
1151 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1153 add_item_to_tree(cotp_tree,
1154 offset + P_VAR_PART_EAK + i + 0, 1,
1155 "Parameter code: 0x%02x (seq number)", code);
1156 add_item_to_tree(cotp_tree,
1157 offset + P_VAR_PART_EAK + i + 1, 1,
1158 "Parameter length: 0x%02x", length);
1159 add_item_to_tree(cotp_tree,
1160 offset + P_VAR_PART_EAK + i + 2, 2,
1161 "Sequence number: 0x%04x", seq_nr);
1166 length = pd[offset + P_VAR_PART_EAK + i + 1];
1168 add_item_to_tree(cotp_tree,
1169 offset + P_VAR_PART_EAK + i + 0, 1,
1170 "Parameter code: 0x%02x (unknown)", code);
1171 add_item_to_tree(cotp_tree,
1172 offset + P_VAR_PART_EAK + i + 1, 1,
1173 "Parameter length: 0x%02x", length);
1174 add_item_to_tree(cotp_tree,
1175 offset + P_VAR_PART_EAK + i + 2, length,
1176 "Parameter value: <not shown>");
1183 } /* is_LI_NORMAL_AK */
1186 dissect_data(pd, offset, fd, tree);
1190 } /* osi_decode_AK */
1192 static int osi_decode_EA(const u_char *pd, int offset,
1193 frame_data *fd, GtkTree *tree)
1195 GtkWidget *cotp_tree, *ti;
1197 u_short checksum = 0;
1205 case LI_NORMAL_EA_WITH_CHECKSUM :
1206 tpdu_nr = pd[offset + P_TPDU_NR_234];
1207 code = pd[offset + P_VAR_PART_NDT];
1208 length = pd[offset + P_VAR_PART_NDT + 1];
1209 if (code != VP_CHECKSUM || length != 1)
1211 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
1213 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1214 tpdu_nr = pd[offset + P_TPDU_NR_234];
1216 case LI_EXTENDED_EA_WITH_CHECKSUM :
1217 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1218 code = pd[offset + P_VAR_PART_EDT];
1219 length = pd[offset + P_VAR_PART_EDT + 1];
1220 if (code != VP_CHECKSUM || length != 1)
1222 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
1224 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1225 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1227 default : /* bad TPDU */
1233 if (fd->win_info[COL_NUM]) {
1234 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
1235 sprintf(fd->win_info[COL_INFO], "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1239 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
1241 cotp_tree = gtk_tree_new();
1242 add_subtree(ti, cotp_tree, ETT_COTP);
1243 add_item_to_tree(cotp_tree, offset, 1,
1244 "Length indicator: %d", li);
1245 add_item_to_tree(cotp_tree, offset + 1, 1,
1246 "TPDU code: Ox%x (EA)", tpdu);
1247 add_item_to_tree(cotp_tree, offset + 2, 2,
1248 "Destination reference: 0x%04x", dst_ref);
1251 case LI_NORMAL_EA_WITH_CHECKSUM :
1252 add_item_to_tree(cotp_tree, offset + 4, 1,
1253 "Your TPDU number: 0x%02x", tpdu_nr);
1254 add_item_to_tree(cotp_tree, offset + 5, 1,
1255 "Parameter code: 0x%02x (checksum)", code);
1256 add_item_to_tree(cotp_tree, offset + 6, 1,
1257 "Parameter length: 0x%02x", length);
1258 add_item_to_tree(cotp_tree, offset + 7, 2,
1259 "Checksum: 0x%04x", checksum);
1261 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1262 add_item_to_tree(cotp_tree, offset + 4, 1,
1263 "Your TPDU number: 0x%02x", tpdu_nr);
1265 case LI_EXTENDED_EA_WITH_CHECKSUM :
1266 add_item_to_tree(cotp_tree, offset + 4, 4,
1267 "Your TPDU number: 0x%08x", tpdu_nr);
1268 add_item_to_tree(cotp_tree, offset + 8, 1,
1269 "Parameter code: 0x%02x (checksum)", code);
1270 add_item_to_tree(cotp_tree, offset + 9, 1,
1271 "Parameter length: 0x%02x", length);
1272 add_item_to_tree(cotp_tree, offset + 10, 2,
1273 "Checksum: 0x%04x", checksum);
1275 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1276 add_item_to_tree(cotp_tree, offset + 4, 4,
1277 "Your TPDU number: 0x%08x", tpdu_nr);
1285 dissect_data(pd, offset, fd, tree);
1289 } /* osi_decode_EA */
1291 static int osi_decode_ER(const u_char *pd, int offset,
1292 frame_data *fd, GtkTree *tree)
1294 GtkWidget *cotp_tree, *ti;
1300 switch(pd[offset + P_REJECT_ER]) {
1302 str = "Reason not specified";
1305 str = "Invalid parameter code";
1308 str = "Invalid TPDU type";
1311 str = "Invalid parameter value";
1319 if (fd->win_info[COL_NUM]) {
1320 strcpy(fd->win_info[COL_PROTOCOL], "COTP");
1321 sprintf(fd->win_info[COL_INFO], "ER TPDU dst-ref: 0x%04x", dst_ref);
1325 ti = add_item_to_tree(GTK_WIDGET(tree), offset, li + 1,
1327 cotp_tree = gtk_tree_new();
1328 add_subtree(ti, cotp_tree, ETT_COTP);
1329 add_item_to_tree(cotp_tree, offset, 1,
1330 "Length indicator: %d", li);
1331 add_item_to_tree(cotp_tree, offset + 1, 1,
1332 "TPDU code: Ox%x (ER)", tpdu);
1333 add_item_to_tree(cotp_tree, offset + 2, 2,
1334 "Destination reference: 0x%04x", dst_ref);
1335 add_item_to_tree(cotp_tree, offset + 4, 1,
1336 "Reject cause: %s", str);
1340 dissect_data(pd, offset, fd, tree);
1344 } /* osi_decode_ER */
1346 void dissect_cotp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
1351 if (((li = pd[offset + P_LI]) == 0) ||
1352 (offset + P_LI + li + 1 > fd->cap_len)) {
1353 dissect_data(pd, offset, fd, tree);
1357 tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
1358 cdt = pd[offset + P_CDT] & 0x0F;
1359 dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
1364 status = osi_decode_CC(pd, offset, fd, tree);
1367 status = osi_decode_DR(pd, offset, fd, tree);
1370 status = osi_decode_DT(pd, offset, fd, tree);
1373 status = osi_decode_ED(pd, offset, fd, tree);
1376 status = osi_decode_RJ(pd, offset, fd, tree);
1379 status = osi_decode_DC(pd, offset, fd, tree);
1382 status = osi_decode_AK(pd, offset, fd, tree);
1385 status = osi_decode_EA(pd, offset, fd, tree);
1388 status = osi_decode_ER(pd, offset, fd, tree);
1394 if (status == -1) /* incorrect TPDU */
1395 dissect_data(pd, offset, fd, tree);
1397 } /* dissect_cotp */
1404 #define MAX_NSAP_LEN 20
1406 static gchar *print_nsap(const u_char *nsap, int length)
1409 /* to do : real NSAP decoding */
1411 static gchar str[3][MAX_NSAP_LEN * 3 + 1];
1415 if (cur == &str[0][0]) {
1417 } else if (cur == &str[1][0]) {
1424 if (length <= 0 || length > MAX_NSAP_LEN)
1425 sprintf(cur, "<invalid NSAP>");
1427 while (length != 1) {
1428 sprintf(tmp, "%02x:", *nsap ++);
1432 sprintf(tmp, "%02x", *nsap);
1438 void dissect_clnp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
1441 struct clnp_header clnp;
1442 GtkWidget *clnp_tree = NULL, *ti;
1443 u_char src_len, dst_len, nsel;
1444 u_int first_offset = offset;
1446 if (fd->cap_len < offset + sizeof(clnp)) {
1447 dissect_data(pd, offset, fd, tree);
1451 /* avoid alignment problem */
1452 memcpy(&clnp, &pd[offset], sizeof(clnp));
1454 /* return if version not known */
1455 if (clnp.cnf_vers != ISO8473_V1) {
1456 dissect_data(pd, offset, fd, tree);
1460 /* fixed part decoding */
1463 ti = add_item_to_tree(GTK_WIDGET(tree), offset, clnp.cnf_hdr_len,
1465 clnp_tree = gtk_tree_new();
1466 add_subtree(ti, clnp_tree, ETT_CLNP);
1467 add_item_to_tree(clnp_tree, offset, 1,
1468 "Protocol identifier: 0x%02x", clnp.cnf_proto_id);
1469 add_item_to_tree(clnp_tree, offset + 1, 1,
1470 "Length: %d", clnp.cnf_hdr_len);
1471 add_item_to_tree(clnp_tree, offset + 2, 1,
1472 "Version: %d", clnp.cnf_vers);
1473 add_item_to_tree(clnp_tree, offset + 3, 1,
1474 "TTL: %d (%d secs)",
1475 clnp.cnf_ttl, clnp.cnf_ttl / 2);
1476 add_item_to_tree(clnp_tree, offset + 4, 1,
1477 "Type code: 0x%02x (%s%s%s%s)",
1479 (clnp.cnf_type & CNF_SEG_OK) ? "S " : "",
1480 (clnp.cnf_type & CNF_MORE_SEGS) ? "M " : "",
1481 (clnp.cnf_type & CNF_ERR_OK) ? "E " : "",
1482 (clnp.cnf_type & CNF_TYPE) == DT_NPDU ? "DT" : "ER");
1483 add_item_to_tree(clnp_tree, offset + 5, 2,
1484 "PDU segment length: %d",
1485 EXTRACT_SHORT(&clnp.cnf_seglen_msb));
1486 add_item_to_tree(clnp_tree, offset + 7, 2,
1488 EXTRACT_SHORT(&clnp.cnf_cksum_msb));
1491 /* stop here if header is not complete */
1493 if (fd->cap_len < offset + clnp.cnf_hdr_len) {
1494 dissect_data(pd, offset, fd, tree);
1500 offset += P_ADDRESS_PART;
1501 dst_len = pd[offset];
1502 nsel = pd[offset + dst_len];
1503 src_len = pd[offset + dst_len + 1];
1506 add_item_to_tree(clnp_tree, offset, 1,
1507 "Destination address length: 0x%02x", dst_len);
1508 add_item_to_tree(clnp_tree, offset + 1 , dst_len,
1509 "Destination address: %s",
1510 print_nsap(&pd[offset + 1], dst_len));
1511 add_item_to_tree(clnp_tree, offset + 1 + dst_len, 1,
1512 "Source address length: 0x%02x", src_len);
1513 add_item_to_tree(clnp_tree, offset + dst_len + 2, src_len,
1514 "Source address: %s",
1515 print_nsap(&pd[offset + dst_len + 2], src_len));
1518 if (fd->win_info[COL_NUM]) {
1519 sprintf(fd->win_info[COL_SOURCE], "%s",
1520 print_nsap(&pd[offset + dst_len + 2], src_len));
1521 sprintf(fd->win_info[COL_DESTINATION], "%s",
1522 print_nsap(&pd[offset + 1], dst_len));
1525 /* Segmentation Part */
1527 offset += dst_len + src_len + 2;
1529 if (tree && (clnp.cnf_type & CNF_SEG_OK)) {
1530 struct clnp_segment seg;
1531 memcpy(&seg, &pd[offset], sizeof(seg));
1533 add_item_to_tree(clnp_tree, offset, 2,
1534 "Data unit identifier: 0x%04x",
1535 EXTRACT_SHORT(&pd[offset]));
1536 add_item_to_tree(clnp_tree, offset + 2 , 2,
1537 "Segment offset: 0x%04x",
1538 EXTRACT_SHORT(&pd[offset + 2]));
1539 add_item_to_tree(clnp_tree, offset + 4 , 2,
1540 "Total length: 0x%04x",
1541 EXTRACT_SHORT(&pd[offset + 4]));
1547 /* To do : decode options */
1549 add_item_to_tree(clnp_tree, offset,
1550 clnp.cnf_hdr_len + first_offset - offset,
1551 "Options/Data: <not shown>");
1555 offset = first_offset + clnp.cnf_hdr_len;
1557 if (offset == fd->cap_len)
1560 /* continue with COTP if any */
1562 if (nsel == NSEL_TP) /* just guessing here - valid for DECNet-OSI */
1563 dissect_cotp(pd, offset, fd, tree);
1565 dissect_data(pd, offset, fd, tree);
1567 } /* dissect_clnp */
1570 /* main entry point */
1572 void dissect_osi(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
1575 switch (pd[offset]) {
1577 /* only CLNP is currently decoded */
1580 if (fd->win_info[COL_NUM])
1582 strcpy(fd->win_info[COL_PROTOCOL], "CLNP");
1584 dissect_clnp(pd, offset, fd, tree);
1587 if (fd->win_info[COL_NUM])
1589 strcpy(fd->win_info[COL_PROTOCOL], "ESIS");
1591 dissect_data(pd, offset, fd, tree);
1593 case ISO9542X25_ESIS:
1594 if (fd->win_info[COL_NUM])
1596 strcpy(fd->win_info[COL_PROTOCOL], "ESIS(X25)");
1598 dissect_data(pd, offset, fd, tree);
1601 if (fd->win_info[COL_NUM])
1603 strcpy(fd->win_info[COL_PROTOCOL], "ISIS");
1605 dissect_data(pd, offset, fd, tree);
1608 if (fd->win_info[COL_NUM])
1610 strcpy(fd->win_info[COL_PROTOCOL], "ISO");
1611 sprintf(fd->win_info[COL_INFO], "Unknown ISO protocol (%02x)", pd[offset]);
1613 dissect_data(pd, offset, fd, tree);