2 * Routines for ISO/OSI network and transport protocol packet disassembly
4 * $Id: packet-osi.c,v 1.16 2000/01/13 06:07:53 guy Exp $
5 * Laurent Deniel <deniel@worldnet.fr>
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
9 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 * - add other network protocols (ES,IS-IS)
30 * - add NSAP decoding & resolution
31 * - complete CLNP decoding (options)
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
49 /* protocols and fields */
51 static int proto_clnp = -1;
53 static int hf_clnp_id = -1;
54 static int hf_clnp_length = -1;
55 static int hf_clnp_version = -1;
56 static int hf_clnp_ttl = -1;
57 static int hf_clnp_type = -1;
58 static int hf_clnp_pdu_length = -1;
59 static int hf_clnp_checksum = -1;
60 static int hf_clnp_dest_length = -1;
61 static int hf_clnp_dest = -1;
62 static int hf_clnp_src_length = -1;
63 static int hf_clnp_src = -1;
65 static gint ett_clnp = -1;
67 static int proto_cotp = -1;
69 static gint ett_cotp = -1;
72 * ISO8473 OSI CLNP definition (see RFC994)
74 * _________________________________
76 * |_________________________________|
78 * |_________________________________|
79 * | Segmentation Part (optional) |
80 * |_________________________________|
81 * | Options Part (optional) |
82 * |_________________________________|
84 * |_________________________________|
87 #define ISO8473_V1 0x01 /* CLNP version 1 */
92 u_char cnf_proto_id; /* network layer protocol identifier */
93 u_char cnf_hdr_len; /* length indicator (octets) */
94 u_char cnf_vers; /* version/protocol identifier extension */
95 u_char cnf_ttl; /* lifetime (500 milliseconds) */
96 u_char cnf_type; /* type code */
97 u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */
98 u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */
99 u_char cnf_cksum_msb; /* checksum high byte */
100 u_char cnf_cksum_lsb; /* checksum low byte */
103 #define CNF_TYPE 0x1f
104 #define CNF_ERR_OK 0x20
105 #define CNF_MORE_SEGS 0x40
106 #define CNF_SEG_OK 0x80
113 #define P_ADDRESS_PART 9
115 /* Segmentation part */
117 struct clnp_segment {
118 u_short cng_id; /* data unit identifier */
119 u_short cng_off; /* segment offset */
120 u_short cng_tot_len; /* total length */
125 #define NSEL_NET 0x00
130 * ISO8073 OSI COTP definition (see RFC905)
133 /* don't use specific TPDU types to avoid alignment problems & copy overhead */
135 /* TPDU definition */
155 #define P_TPDU_NR_0_1 2
156 #define P_TPDU_NR_234 4
157 #define P_VAR_PART_NDT 5
158 #define P_VAR_PART_EDT 8
159 #define P_VAR_PART_NAK 5
160 #define P_VAR_PART_CC 7
161 #define P_VAR_PART_EAK 10
162 #define P_VAR_PART_DC 6
163 #define P_VAR_PART_DR 7
164 #define P_CDT_IN_AK 8
165 #define P_CDT_IN_RJ 8
166 #define P_REJECT_ER 4
167 #define P_REASON_IN_DR 6
168 #define P_CLASS_OPTION 6
170 /* TPDU length indicator */
172 #define LI_NORMAL_DT_CLASS_01 2
173 #define LI_NORMAL_DT_WITH_CHECKSUM 8
174 #define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
175 #define LI_EXTENDED_DT_WITH_CHECKSUM 11
176 #define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
177 #define LI_NORMAL_EA_WITH_CHECKSUM 8
178 #define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
179 #define LI_EXTENDED_EA_WITH_CHECKSUM 11
180 #define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
181 #define LI_NORMAL_RJ 4
182 #define LI_EXTENDED_RJ 9
188 #define LI_DC_WITH_CHECKSUM 9
189 #define LI_DC_WITHOUT_CHECKSUM 5
190 #define is_LI_NORMAL_AK(p) ( p & 0x01 )
194 #define VP_ACK_TIME 0x85
195 #define VP_RES_ERROR 0x86
196 #define VP_PRIORITY 0x87
197 #define VP_TRANSIT_DEL 0x88
198 #define VP_THROUGHPUT 0x89
199 #define VP_SEQ_NR 0x8A /* in AK */
200 #define VP_REASSIGNMENT 0x8B
201 #define VP_FLOW_CNTL 0x8C /* in AK */
202 #define VP_TPDU_SIZE 0xC0
203 #define VP_SRC_TSAP 0xC1 /* in CR/CC */
204 #define VP_DST_TSAP 0xC2
205 #define VP_CHECKSUM 0xC3
206 #define VP_VERSION_NR 0xC4
207 #define VP_PROTECTION 0xC5
208 #define VP_OPT_SEL 0xC6
209 #define VP_PROTO_CLASS 0xC7
213 #define EXTRACT_SHORT(p) pntohs(p)
214 #define EXTRACT_LONG(p) pntohl(p)
216 /* global variables */
218 static u_char li, tpdu, cdt; /* common fields */
219 static u_short dst_ref;
221 /* function definitions */
223 static int osi_decode_DR(const u_char *pd, int offset,
224 frame_data *fd, proto_tree *tree)
226 proto_tree *cotp_tree;
235 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
236 reason = pd[offset + P_REASON_IN_DR];
239 case (128+0): str = "Normal Disconnect"; break;
240 case (128+1): str = "Remote transport enity congestion"; break;
241 case (128+2): str = "Connection negotiation failed"; break;
242 case (128+3): str = "Duplicate source reference"; break;
243 case (128+4): str = "Mismatched references"; break;
244 case (128+5): str = "Protocol error"; break;
245 case (128+7): str = "Reference overflow"; break;
246 case (128+8): str = "Connection requestion refused"; break;
247 case (128+10):str = "Header or parameter length invalid"; break;
248 case (0): str = "Reason not specified"; break;
249 case (1): str = "Congestion at TSAP"; break;
250 case (2): str = "Session entity not attached to TSAP"; break;
251 case (3): str = "Address unknown"; break;
257 if (check_col(fd, COL_PROTOCOL))
258 col_add_str(fd, COL_PROTOCOL, "COTP");
259 if (check_col(fd, COL_INFO))
260 col_add_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
264 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
265 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
266 proto_tree_add_text(cotp_tree, offset, 1,
267 "Length indicator: %d", li);
268 proto_tree_add_text(cotp_tree, offset + 1, 1,
269 "TPDU code: Ox%x (DR)", tpdu);
270 proto_tree_add_text(cotp_tree, offset + 2, 2,
271 "Destination reference: 0x%04x", dst_ref);
272 proto_tree_add_text(cotp_tree, offset + 4, 2,
273 "Source reference: 0x%04x", src_ref);
274 proto_tree_add_text(cotp_tree, offset + 6, 1,
279 dissect_data(pd, offset, fd, tree);
283 } /* osi_decode_DR */
285 static int osi_decode_DT(const u_char *pd, int offset,
286 frame_data *fd, proto_tree *tree)
288 proto_tree *cotp_tree;
291 u_short checksum = 0;
292 u_char code = 0, length = 0;
296 case LI_NORMAL_DT_WITH_CHECKSUM :
297 tpdu_nr = pd[offset + P_TPDU_NR_234];
298 if ( tpdu_nr & 0x80 )
299 tpdu_nr = tpdu_nr & 0x7F;
302 code = pd[offset + P_VAR_PART_NDT];
303 if (code == VP_CHECKSUM)
304 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
308 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
309 tpdu_nr = pd[offset + P_TPDU_NR_234];
310 if ( tpdu_nr & 0x80 )
311 tpdu_nr = tpdu_nr & 0x7F;
315 case LI_EXTENDED_DT_WITH_CHECKSUM :
316 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
317 if ( tpdu_nr & 0x80000000 )
318 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
321 code = pd[offset + P_VAR_PART_EDT];
322 if (code == VP_CHECKSUM)
323 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
327 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
328 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
329 if ( tpdu_nr & 0x80000000 )
330 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
334 case LI_NORMAL_DT_CLASS_01 :
335 tpdu_nr = pd[offset + P_TPDU_NR_0_1];
336 if ( tpdu_nr & 0x80 )
337 tpdu_nr = tpdu_nr & 0x7F;
341 default : /* bad TPDU */
347 if (check_col(fd, COL_PROTOCOL))
348 col_add_str(fd, COL_PROTOCOL, "COTP");
349 if (check_col(fd, COL_INFO))
350 col_add_fstr(fd, COL_INFO, "DT TPDU (%d) dst-ref: 0x%04x %s",
353 (fragment)? "(fragment)" : "");
356 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
357 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
358 proto_tree_add_text(cotp_tree, offset, 1,
359 "Length indicator: %d", li);
360 proto_tree_add_text(cotp_tree, offset + 1, 1,
361 "TPDU code: Ox%x (DT)", tpdu);
363 if (li != LI_NORMAL_DT_CLASS_01)
364 proto_tree_add_text(cotp_tree, offset + 2, 2,
365 "Destination reference: 0x%04x", dst_ref);
368 case LI_NORMAL_DT_WITH_CHECKSUM :
369 proto_tree_add_text(cotp_tree, offset + 4, 1,
370 "TPDU number: 0x%02x (%s)",
372 (fragment)? "fragment":"complete");
373 proto_tree_add_text(cotp_tree,
374 offset + P_VAR_PART_NDT, 1,
375 "Parameter code: 0x%02x (checksum)", code);
376 proto_tree_add_text(cotp_tree,
377 offset + P_VAR_PART_NDT + 1, 1,
378 "Parameter length: 0x%02x", length);
379 proto_tree_add_text(cotp_tree,
380 offset + P_VAR_PART_NDT + 2, length,
381 "Checksum: 0x%04x", checksum);
383 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
384 proto_tree_add_text(cotp_tree, offset + 4, 1,
385 "TPDU number: 0x%02x (%s)",
387 (fragment)? "fragment":"complete");
389 case LI_EXTENDED_DT_WITH_CHECKSUM :
390 proto_tree_add_text(cotp_tree, offset + 4, 4,
391 "TPDU number: 0x%08x (%s)",
393 (fragment)? "fragment":"complete");
394 proto_tree_add_text(cotp_tree,
395 offset + P_VAR_PART_EDT, 1,
396 "Parameter code: 0x%02x (checksum)", code);
397 proto_tree_add_text(cotp_tree,
398 offset + P_VAR_PART_EDT + 1, 1,
399 "Parameter length: 0x%02x", length);
400 proto_tree_add_text(cotp_tree,
401 offset + P_VAR_PART_EDT + 2, length,
402 "Checksum: 0x%04x", checksum);
404 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
405 proto_tree_add_text(cotp_tree, offset + 4, 4,
406 "TPDU number: 0x%08x (%s)",
408 (fragment)? "fragment":"complete");
410 case LI_NORMAL_DT_CLASS_01 :
411 proto_tree_add_text(cotp_tree, offset + 2, 1,
412 "TPDU number: 0x%02x (%s)",
414 (fragment)? "fragment":"complete");
420 dissect_data(pd, offset, fd, tree);
424 } /* osi_decode_DT */
426 static int osi_decode_ED(const u_char *pd, int offset,
427 frame_data *fd, proto_tree *tree)
429 proto_tree *cotp_tree;
432 u_short checksum = 0;
433 u_char code = 0, length = 0;
435 /* ED TPDUs are never fragmented */
438 case LI_NORMAL_DT_WITH_CHECKSUM :
439 tpdu_nr = pd[offset + P_TPDU_NR_234];
440 if ( tpdu_nr & 0x80 )
441 tpdu_nr = tpdu_nr & 0x7F;
444 code = pd[offset + P_VAR_PART_NDT];
445 length = pd[offset + P_VAR_PART_NDT + 1];
446 if (code == VP_CHECKSUM)
447 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
451 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
452 tpdu_nr = pd[offset + P_TPDU_NR_234];
453 if ( tpdu_nr & 0x80 )
454 tpdu_nr = tpdu_nr & 0x7F;
458 case LI_EXTENDED_DT_WITH_CHECKSUM :
459 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
460 if ( tpdu_nr & 0x80000000 )
461 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
464 code = pd[offset + P_VAR_PART_EDT];
465 length = pd[offset + P_VAR_PART_EDT + 1];
466 if (code == VP_CHECKSUM)
467 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
471 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
472 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
473 if ( tpdu_nr & 0x80000000 )
474 tpdu_nr = tpdu_nr & 0x7FFFFFFF;
478 default : /* bad TPDU */
484 if (check_col(fd, COL_PROTOCOL))
485 col_add_str(fd, COL_PROTOCOL, "COTP");
486 if (check_col(fd, COL_INFO))
487 col_add_fstr(fd, COL_INFO, "ED TPDU (%d) dst-ref: 0x%04x",
491 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
492 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
493 proto_tree_add_text(cotp_tree, offset, 1,
494 "Length indicator: %d", li);
495 proto_tree_add_text(cotp_tree, offset + 1, 1,
496 "TPDU code: Ox%x (ED)", tpdu);
497 proto_tree_add_text(cotp_tree, offset + 2, 2,
498 "Destination reference: 0x%04x", dst_ref);
501 case LI_NORMAL_DT_WITH_CHECKSUM :
502 proto_tree_add_text(cotp_tree, offset + 4, 1,
503 "TPDU number: 0x%02x", tpdu_nr);
504 proto_tree_add_text(cotp_tree,
505 offset + P_VAR_PART_NDT, 1,
506 "Parameter code: 0x%02x (checksum)", code);
507 proto_tree_add_text(cotp_tree,
508 offset + P_VAR_PART_NDT + 1, 1,
509 "Parameter length: 0x%02x", length);
510 proto_tree_add_text(cotp_tree,
511 offset + P_VAR_PART_NDT + 2, length,
512 "Checksum: 0x%04x", checksum);
514 case LI_NORMAL_DT_WITHOUT_CHECKSUM :
515 proto_tree_add_text(cotp_tree, offset + 4, 1,
516 "TPDU number: 0x%02x", tpdu_nr);
518 case LI_EXTENDED_DT_WITH_CHECKSUM :
519 proto_tree_add_text(cotp_tree, offset + 4, 4,
520 "TPDU number: 0x%02x", tpdu_nr);
521 proto_tree_add_text(cotp_tree,
522 offset + P_VAR_PART_EDT, 1,
523 "Parameter code: 0x%02x (checksum)", code);
524 proto_tree_add_text(cotp_tree,
525 offset + P_VAR_PART_EDT + 1, 1,
526 "Parameter length: 0x%02x", length);
527 proto_tree_add_text(cotp_tree,
528 offset + P_VAR_PART_EDT + 2, length,
529 "Checksum: 0x%04x", checksum);
531 case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
532 proto_tree_add_text(cotp_tree, offset + 4, 4,
533 "TPDU number: 0x%02x", tpdu_nr);
539 dissect_data(pd, offset, fd, tree);
543 } /* osi_decode_ED */
545 static int osi_decode_RJ(const u_char *pd, int offset,
546 frame_data *fd, proto_tree *tree)
548 proto_tree *cotp_tree;
555 tpdu_nr = pd[offset + P_TPDU_NR_234];
557 case LI_EXTENDED_RJ :
558 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
559 credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]);
567 if (check_col(fd, COL_PROTOCOL))
568 col_add_str(fd, COL_PROTOCOL, "COTP");
569 if (check_col(fd, COL_INFO))
570 col_add_fstr(fd, COL_INFO, "RJ TPDU (%d) dst-ref: 0x%04x",
574 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
575 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
576 proto_tree_add_text(cotp_tree, offset, 1,
577 "Length indicator: %d", li);
578 proto_tree_add_text(cotp_tree, offset + 1, 1,
579 "TPDU code: Ox%x (RJ)", tpdu);
580 if (li == LI_NORMAL_RJ)
581 proto_tree_add_text(cotp_tree, offset + 1, 1,
583 proto_tree_add_text(cotp_tree, offset + 2, 2,
584 "Destination reference: 0x%04x", dst_ref);
585 if (li == LI_NORMAL_RJ)
586 proto_tree_add_text(cotp_tree, offset + 4, 1,
587 "Your TPDU number: 0x%02x", tpdu_nr);
589 proto_tree_add_text(cotp_tree, offset + 4, 4,
590 "Your TPDU number: 0x%02x", tpdu_nr);
591 proto_tree_add_text(cotp_tree, offset + 8, 2,
592 "Credit: 0x%02x", credit);
597 dissect_data(pd, offset, fd, tree);
601 } /* osi_decode_RJ */
603 #define MAX_TSAP_LEN 32
605 static gchar *print_tsap(const u_char *tsap, int length)
608 static gchar str[3][MAX_TSAP_LEN * 2 + 1];
612 if (cur == &str[0][0]) {
614 } else if (cur == &str[1][0]) {
620 /* to do: test if all bytes are printable */
623 if (length <= 0 || length > MAX_TSAP_LEN)
624 sprintf(cur, "<unsupported TSAP length>");
626 while (length != 0) {
627 sprintf(tmp, "%02x", *tsap ++);
636 static int osi_decode_CC(const u_char *pd, int offset,
637 frame_data *fd, proto_tree *tree)
640 /* CC & CR decoding in the same function */
642 proto_tree *cotp_tree = NULL;
644 u_short src_ref, checksum;
645 u_char class_option, code, length;
648 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
649 class_option = (pd[offset + P_CLASS_OPTION] >> 4 ) & 0x0F;
650 if (class_option > 4)
653 if (check_col(fd, COL_PROTOCOL))
654 col_add_str(fd, COL_PROTOCOL, "COTP");
655 if (check_col(fd, COL_INFO))
656 col_add_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
657 (tpdu == CR_TPDU) ? "CR" : "CC",
662 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
663 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
664 proto_tree_add_text(cotp_tree, offset, 1,
665 "Length indicator: %d", li);
666 proto_tree_add_text(cotp_tree, offset + 1, 1,
667 "TPDU code: Ox%x (%s)", tpdu,
668 (tpdu == CR_TPDU) ? "CR" : "CC");
669 proto_tree_add_text(cotp_tree, offset + 2, 2,
670 "Destination reference: 0x%04x", dst_ref);
671 proto_tree_add_text(cotp_tree, offset + 4, 2,
672 "Source reference: 0x%04x", src_ref);
673 proto_tree_add_text(cotp_tree, offset + 6, 1,
674 "Class option: 0x%02x", class_option);
678 while(li > P_VAR_PART_CC + i - 1) {
681 u_short s, s1,s2,s3,s4;
684 switch( (code = pd[offset + P_VAR_PART_CC + i]) ) {
686 length = pd[offset + P_VAR_PART_CC + i + 1];
687 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
688 proto_tree_add_text(cotp_tree,
689 offset + P_VAR_PART_CC + i, 1,
690 "Parameter code: 0x%02x (checksum)", code);
691 proto_tree_add_text(cotp_tree,
692 offset + P_VAR_PART_CC + i + 1, 1,
693 "Parameter length: 0x%02x", length);
694 proto_tree_add_text(cotp_tree,
695 offset + P_VAR_PART_CC + i + 2, length,
696 "Checksum: 0x%04x", checksum);
700 length = pd[offset + P_VAR_PART_CC + i + 1];
701 proto_tree_add_text(cotp_tree,
702 offset + P_VAR_PART_CC + i, 1,
703 "Parameter code: 0x%02x (src-tsap)", code);
704 proto_tree_add_text(cotp_tree,
705 offset + P_VAR_PART_CC + i + 1, 1,
706 "Parameter length: 0x%02x", length);
707 proto_tree_add_text(cotp_tree,
708 offset + P_VAR_PART_CC + i + 2, length,
709 "Calling TSAP: 0x%s",
710 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
715 length = pd[offset + P_VAR_PART_CC + i + 1];
716 proto_tree_add_text(cotp_tree,
717 offset + P_VAR_PART_CC + i, 1,
718 "Parameter code: 0x%02x (dst-tsap)", code);
719 proto_tree_add_text(cotp_tree,
720 offset + P_VAR_PART_CC + i + 1, 1,
721 "Parameter length: 0x%02x", length);
722 proto_tree_add_text(cotp_tree,
723 offset + P_VAR_PART_CC + i + 2, length,
725 print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
730 length = pd[offset + P_VAR_PART_CC + i + 1];
731 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
732 proto_tree_add_text(cotp_tree,
733 offset + P_VAR_PART_CC + i, 1,
734 "Parameter code: 0x%02x (tpdu-size)", code);
735 proto_tree_add_text(cotp_tree,
736 offset + P_VAR_PART_CC + i + 1, 1,
737 "Parameter length: 0x%02x", length);
738 proto_tree_add_text(cotp_tree,
739 offset + P_VAR_PART_CC + i + 2, length,
740 "TPDU size: %d", 2 << c1);
744 length = pd[offset + P_VAR_PART_CC + i + 1];
745 c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F;
746 proto_tree_add_text(cotp_tree,
747 offset + P_VAR_PART_CC + i, 1,
748 "Parameter code: 0x%02x (options)", code);
749 proto_tree_add_text(cotp_tree,
750 offset + P_VAR_PART_CC + i + 1, 1,
751 "Parameter length: 0x%02x", length);
752 if (class_option == 1) {
754 proto_tree_add_text(cotp_tree,
755 offset + P_VAR_PART_CC + i + 2, 1,
756 "Use of network expedited data");
758 proto_tree_add_text(cotp_tree,
759 offset + P_VAR_PART_CC + i + 2, 1,
760 "Non use of network expedited data");
762 proto_tree_add_text(cotp_tree,
763 offset + P_VAR_PART_CC + i + 2, 1,
764 "Use of Receipt confirmation");
766 proto_tree_add_text(cotp_tree,
767 offset + P_VAR_PART_CC + i + 2, 1,
768 "Use of explicit AK variant");
769 } else if (class_option == 4) {
771 proto_tree_add_text(cotp_tree,
772 offset + P_VAR_PART_CC + i + 2, 1,
773 "Use 16 bit checksum ");
775 proto_tree_add_text(cotp_tree,
776 offset + P_VAR_PART_CC + i + 2, 1,
777 "Non-use 16 bit checksum in class 4");
780 proto_tree_add_text(cotp_tree,
781 offset + P_VAR_PART_CC + i + 2, 1,
782 "Use of transport expedited data transfer\n");
784 proto_tree_add_text(cotp_tree,
785 offset + P_VAR_PART_CC + i + 2, 1,
786 "Non-use of transport expedited data transfer");
790 length = pd[offset + P_VAR_PART_CC + i + 1];
791 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
792 proto_tree_add_text(cotp_tree,
793 offset + P_VAR_PART_CC + i, 1,
794 "Parameter code: 0x%02x (ack time)", code);
795 proto_tree_add_text(cotp_tree,
796 offset + P_VAR_PART_CC + i + 1, 1,
797 "Parameter length: 0x%02x", length);
798 proto_tree_add_text(cotp_tree,
799 offset + P_VAR_PART_CC + i + 2, length,
800 "Ack time (ms): %d", s);
804 length = pd[offset + P_VAR_PART_CC + i + 1];
805 t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]);
806 t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]);
807 t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]);
808 t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]);
809 proto_tree_add_text(cotp_tree,
810 offset + P_VAR_PART_CC + i, 1,
811 "Parameter code: 0x%02x (throughput)", code);
812 proto_tree_add_text(cotp_tree,
813 offset + P_VAR_PART_CC + i + 1, 1,
814 "Parameter length: 0x%02x", length);
815 proto_tree_add_text(cotp_tree,
816 offset + P_VAR_PART_CC + i + 2, 4,
817 "Target value / calling-called: %d o/s", t1);
818 proto_tree_add_text(cotp_tree,
819 offset + P_VAR_PART_CC + i + 6, 4,
820 "Minimum / calling-called: %d o/s", t2);
821 proto_tree_add_text(cotp_tree,
822 offset + P_VAR_PART_CC + i + 10, 4,
823 "Target value / called-calling: %d o/s", t3);
824 proto_tree_add_text(cotp_tree,
825 offset + P_VAR_PART_CC + i + 14, 4,
826 "Minimum / called-calling: %d o/s", t4);
829 case VP_TRANSIT_DEL :
830 length = pd[offset + P_VAR_PART_CC + i + 1];
831 s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
832 s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]);
833 s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]);
834 s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]);
835 proto_tree_add_text(cotp_tree,
836 offset + P_VAR_PART_CC + i, 1,
837 "Parameter code: 0x%02x (transit delay)", code);
838 proto_tree_add_text(cotp_tree,
839 offset + P_VAR_PART_CC + i + 1, 1,
840 "Parameter length: 0x%02x", length);
841 proto_tree_add_text(cotp_tree,
842 offset + P_VAR_PART_CC + i + 2, 2,
843 "Target value / calling-called: %d ms", s1);
844 proto_tree_add_text(cotp_tree,
845 offset + P_VAR_PART_CC + i + 4, 2,
846 "Minimum / calling-called: %d ms", s2);
847 proto_tree_add_text(cotp_tree,
848 offset + P_VAR_PART_CC + i + 6, 2,
849 "Target value / called-calling: %d ms", s3);
850 proto_tree_add_text(cotp_tree,
851 offset + P_VAR_PART_CC + i + 8, 2,
852 "Minimum / called-calling: %d ms", s4);
856 length = pd[offset + P_VAR_PART_CC + i + 1];
857 s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]);
858 proto_tree_add_text(cotp_tree,
859 offset + P_VAR_PART_CC + i, 1,
860 "Parameter code: 0x%02x (priority)", code);
861 proto_tree_add_text(cotp_tree,
862 offset + P_VAR_PART_CC + i + 1, 1,
863 "Parameter length: 0x%02x", length);
864 proto_tree_add_text(cotp_tree,
865 offset + P_VAR_PART_CC + i + 2, length,
870 case VP_REASSIGNMENT: /* todo */
874 case VP_PROTO_CLASS :
875 default : /* no decoding */
876 length = pd[offset + P_VAR_PART_CC + i + 1];
877 proto_tree_add_text(cotp_tree,
878 offset + P_VAR_PART_CC + i + 0, 1,
879 "Parameter code: 0x%02x", code);
880 proto_tree_add_text(cotp_tree,
881 offset + P_VAR_PART_CC + i + 1, 1,
882 "Parameter length: 0x%02x", length);
883 proto_tree_add_text(cotp_tree,
884 offset + P_VAR_PART_CC + i + 2, length,
885 "Parameter value: <not shown>");
892 dissect_data(pd, offset, fd, tree);
896 } /* osi_decode_CC */
898 static int osi_decode_DC(const u_char *pd, int offset,
899 frame_data *fd, proto_tree *tree)
901 proto_tree *cotp_tree;
903 u_short src_ref, checksum = 0;
904 u_char length = 0, code = 0;
909 src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]);
912 case LI_DC_WITHOUT_CHECKSUM :
914 case LI_DC_WITH_CHECKSUM :
915 if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM)
917 length = pd[offset + P_VAR_PART_DC + 1];
918 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]);
926 if (check_col(fd, COL_PROTOCOL))
927 col_add_str(fd, COL_PROTOCOL, "COTP");
928 if (check_col(fd, COL_INFO))
929 col_add_fstr(fd, COL_INFO, "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
934 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
935 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
936 proto_tree_add_text(cotp_tree, offset, 1,
937 "Length indicator: %d", li);
938 proto_tree_add_text(cotp_tree, offset + 1, 1,
939 "TPDU code: Ox%x (DC)", tpdu);
940 proto_tree_add_text(cotp_tree, offset + 2, 2,
941 "Destination reference: 0x%04x", dst_ref);
942 proto_tree_add_text(cotp_tree, offset + 4, 2,
943 "Source reference: 0x%04x", src_ref);
945 proto_tree_add_text(cotp_tree,
946 offset + P_VAR_PART_DC + 0, 1,
947 "Parameter code: 0x%02x (checksum)", code);
948 proto_tree_add_text(cotp_tree,
949 offset + P_VAR_PART_DC + 1, 1,
950 "Parameter length: 0x%02x", length);
951 proto_tree_add_text(cotp_tree,
952 offset + P_VAR_PART_DC + 2, 2,
953 "Checksum: 0x%04x", checksum);
958 dissect_data(pd, offset, fd, tree);
962 } /* osi_decode_DC */
964 static int osi_decode_AK(const u_char *pd, int offset,
965 frame_data *fd, proto_tree *tree)
967 proto_tree *cotp_tree = NULL;
969 u_int tpdu_nr,i =0, r_lower_window_edge ;
971 u_short checksum, seq_nr, r_seq_nr, r_cdt;
977 if (!is_LI_NORMAL_AK(li)) {
978 tpdu_nr = pd[offset + P_TPDU_NR_234];
980 if (check_col(fd, COL_PROTOCOL))
981 col_add_str(fd, COL_PROTOCOL, "COTP");
982 if (check_col(fd, COL_INFO))
983 col_add_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
987 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
988 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
989 proto_tree_add_text(cotp_tree, offset, 1,
990 "Length indicator: %d", li);
991 proto_tree_add_text(cotp_tree, offset + 1, 1,
992 "TPDU code: Ox%x (AK)", tpdu);
993 proto_tree_add_text(cotp_tree, offset + 1, 1,
995 proto_tree_add_text(cotp_tree, offset + 2, 2,
996 "Destination reference: 0x%04x", dst_ref);
997 proto_tree_add_text(cotp_tree, offset + 4, 1,
998 "Your TPDU number: 0x%02x", tpdu_nr);
1001 while(li > P_VAR_PART_NAK + i - 1) {
1002 switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) {
1004 length = pd[offset + P_VAR_PART_NAK + i + 1];
1005 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1007 proto_tree_add_text(cotp_tree,
1008 offset + P_VAR_PART_NAK + i + 0, 1,
1009 "Parameter code: 0x%02x (checksum)", code);
1010 proto_tree_add_text(cotp_tree,
1011 offset + P_VAR_PART_NAK + i + 1, 1,
1012 "Parameter length: 0x%02x", length);
1013 proto_tree_add_text(cotp_tree,
1014 offset + P_VAR_PART_NAK + i + 2, 2,
1015 "Checksum: 0x%04x", checksum);
1020 length = pd[offset + P_VAR_PART_NAK + i + 1];
1021 r_lower_window_edge =
1022 EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]);
1023 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]);
1024 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]);
1026 proto_tree_add_text(cotp_tree,
1027 offset + P_VAR_PART_NAK + i + 0, 1,
1028 "Parameter code: 0x%02x (flow control)",
1030 proto_tree_add_text(cotp_tree,
1031 offset + P_VAR_PART_NAK + i + 1, 1,
1032 "Parameter length: 0x%02x", length);
1033 proto_tree_add_text(cotp_tree,
1034 offset + P_VAR_PART_NAK + i + 2, 4,
1035 "Lower window edge: 0x%08x",
1036 r_lower_window_edge);
1037 proto_tree_add_text(cotp_tree,
1038 offset + P_VAR_PART_NAK + i + 6, 2,
1039 "Sequence number: 0x%04x",
1041 proto_tree_add_text(cotp_tree,
1042 offset + P_VAR_PART_NAK + i + 8, 2,
1049 length = pd[offset + P_VAR_PART_NAK + i + 1];
1050 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]);
1052 proto_tree_add_text(cotp_tree,
1053 offset + P_VAR_PART_NAK + i + 0, 1,
1054 "Parameter code: 0x%02x (seq number)", code);
1055 proto_tree_add_text(cotp_tree,
1056 offset + P_VAR_PART_NAK + i + 1, 1,
1057 "Parameter length: 0x%02x", length);
1058 proto_tree_add_text(cotp_tree,
1059 offset + P_VAR_PART_NAK + i + 2, 2,
1060 "Sequence number: 0x%04x", seq_nr);
1065 length = pd[offset + P_VAR_PART_NAK + i + 1];
1067 proto_tree_add_text(cotp_tree,
1068 offset + P_VAR_PART_NAK + i + 0, 1,
1069 "Parameter code: 0x%02x (unknown)", code);
1070 proto_tree_add_text(cotp_tree,
1071 offset + P_VAR_PART_NAK + i + 1, 1,
1072 "Parameter length: 0x%02x", length);
1073 proto_tree_add_text(cotp_tree,
1074 offset + P_VAR_PART_NAK + i + 2, length,
1075 "Parameter value: <not shown>");
1081 } else { /* extended format */
1083 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1084 cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]);
1086 if (check_col(fd, COL_PROTOCOL))
1087 col_add_str(fd, COL_PROTOCOL, "COTP");
1088 if (check_col(fd, COL_INFO))
1089 col_add_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x",
1093 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1094 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1095 proto_tree_add_text(cotp_tree, offset, 1,
1096 "Length indicator: %d", li);
1097 proto_tree_add_text(cotp_tree, offset + 1, 1,
1098 "TPDU code: Ox%x (AK)", tpdu);
1099 proto_tree_add_text(cotp_tree, offset + 2, 2,
1100 "Destination reference: 0x%04x", dst_ref);
1101 proto_tree_add_text(cotp_tree, offset + 4, 4,
1102 "Your TPDU number: 0x%08x", tpdu_nr);
1103 proto_tree_add_text(cotp_tree, offset + 8, 2,
1104 "Credit: 0x%04x", cdt_in_ak);
1107 while(li > P_VAR_PART_EAK + i - 1) {
1108 switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) {
1110 length = pd[offset + P_VAR_PART_EAK + i + 1];
1111 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1113 proto_tree_add_text(cotp_tree,
1114 offset + P_VAR_PART_EAK + i + 0, 1,
1115 "Parameter code: 0x%02x (checksum)", code);
1116 proto_tree_add_text(cotp_tree,
1117 offset + P_VAR_PART_EAK + i + 1, 1,
1118 "Parameter length: 0x%02x", length);
1119 proto_tree_add_text(cotp_tree,
1120 offset + P_VAR_PART_EAK + i + 2, 2,
1121 "Checksum: 0x%04x", checksum);
1126 length = pd[offset + P_VAR_PART_EAK + i + 1];
1127 r_lower_window_edge =
1128 EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]);
1129 r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]);
1130 r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]);
1132 proto_tree_add_text(cotp_tree,
1133 offset + P_VAR_PART_EAK + i + 0, 1,
1134 "Parameter code: 0x%02x (flow control)",
1136 proto_tree_add_text(cotp_tree,
1137 offset + P_VAR_PART_EAK + i + 1, 1,
1138 "Parameter length: 0x%02x", length);
1139 proto_tree_add_text(cotp_tree,
1140 offset + P_VAR_PART_EAK + i + 2, 4,
1141 "Lower window edge: 0x%08x",
1142 r_lower_window_edge);
1143 proto_tree_add_text(cotp_tree,
1144 offset + P_VAR_PART_EAK + i + 6, 2,
1145 "Sequence number: 0x%04x",
1147 proto_tree_add_text(cotp_tree,
1148 offset + P_VAR_PART_EAK + i + 8, 2,
1155 length = pd[offset + P_VAR_PART_EAK + i + 1];
1156 seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]);
1158 proto_tree_add_text(cotp_tree,
1159 offset + P_VAR_PART_EAK + i + 0, 1,
1160 "Parameter code: 0x%02x (seq number)", code);
1161 proto_tree_add_text(cotp_tree,
1162 offset + P_VAR_PART_EAK + i + 1, 1,
1163 "Parameter length: 0x%02x", length);
1164 proto_tree_add_text(cotp_tree,
1165 offset + P_VAR_PART_EAK + i + 2, 2,
1166 "Sequence number: 0x%04x", seq_nr);
1171 length = pd[offset + P_VAR_PART_EAK + i + 1];
1173 proto_tree_add_text(cotp_tree,
1174 offset + P_VAR_PART_EAK + i + 0, 1,
1175 "Parameter code: 0x%02x (unknown)", code);
1176 proto_tree_add_text(cotp_tree,
1177 offset + P_VAR_PART_EAK + i + 1, 1,
1178 "Parameter length: 0x%02x", length);
1179 proto_tree_add_text(cotp_tree,
1180 offset + P_VAR_PART_EAK + i + 2, length,
1181 "Parameter value: <not shown>");
1188 } /* is_LI_NORMAL_AK */
1191 dissect_data(pd, offset, fd, tree);
1195 } /* osi_decode_AK */
1197 static int osi_decode_EA(const u_char *pd, int offset,
1198 frame_data *fd, proto_tree *tree)
1200 proto_tree *cotp_tree;
1203 u_short checksum = 0;
1211 case LI_NORMAL_EA_WITH_CHECKSUM :
1212 tpdu_nr = pd[offset + P_TPDU_NR_234];
1213 code = pd[offset + P_VAR_PART_NDT];
1214 length = pd[offset + P_VAR_PART_NDT + 1];
1215 if (code != VP_CHECKSUM || length != 1)
1217 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]);
1219 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1220 tpdu_nr = pd[offset + P_TPDU_NR_234];
1222 case LI_EXTENDED_EA_WITH_CHECKSUM :
1223 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1224 code = pd[offset + P_VAR_PART_EDT];
1225 length = pd[offset + P_VAR_PART_EDT + 1];
1226 if (code != VP_CHECKSUM || length != 1)
1228 checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]);
1230 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1231 tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]);
1233 default : /* bad TPDU */
1239 if (check_col(fd, COL_PROTOCOL))
1240 col_add_str(fd, COL_PROTOCOL, "COTP");
1241 if (check_col(fd, COL_INFO))
1242 col_add_fstr(fd, COL_INFO,
1243 "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref);
1246 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1247 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1248 proto_tree_add_text(cotp_tree, offset, 1,
1249 "Length indicator: %d", li);
1250 proto_tree_add_text(cotp_tree, offset + 1, 1,
1251 "TPDU code: Ox%x (EA)", tpdu);
1252 proto_tree_add_text(cotp_tree, offset + 2, 2,
1253 "Destination reference: 0x%04x", dst_ref);
1256 case LI_NORMAL_EA_WITH_CHECKSUM :
1257 proto_tree_add_text(cotp_tree, offset + 4, 1,
1258 "Your TPDU number: 0x%02x", tpdu_nr);
1259 proto_tree_add_text(cotp_tree, offset + 5, 1,
1260 "Parameter code: 0x%02x (checksum)", code);
1261 proto_tree_add_text(cotp_tree, offset + 6, 1,
1262 "Parameter length: 0x%02x", length);
1263 proto_tree_add_text(cotp_tree, offset + 7, 2,
1264 "Checksum: 0x%04x", checksum);
1266 case LI_NORMAL_EA_WITHOUT_CHECKSUM :
1267 proto_tree_add_text(cotp_tree, offset + 4, 1,
1268 "Your TPDU number: 0x%02x", tpdu_nr);
1270 case LI_EXTENDED_EA_WITH_CHECKSUM :
1271 proto_tree_add_text(cotp_tree, offset + 4, 4,
1272 "Your TPDU number: 0x%08x", tpdu_nr);
1273 proto_tree_add_text(cotp_tree, offset + 8, 1,
1274 "Parameter code: 0x%02x (checksum)", code);
1275 proto_tree_add_text(cotp_tree, offset + 9, 1,
1276 "Parameter length: 0x%02x", length);
1277 proto_tree_add_text(cotp_tree, offset + 10, 2,
1278 "Checksum: 0x%04x", checksum);
1280 case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
1281 proto_tree_add_text(cotp_tree, offset + 4, 4,
1282 "Your TPDU number: 0x%08x", tpdu_nr);
1290 dissect_data(pd, offset, fd, tree);
1294 } /* osi_decode_EA */
1296 static int osi_decode_ER(const u_char *pd, int offset,
1297 frame_data *fd, proto_tree *tree)
1299 proto_tree *cotp_tree;
1306 switch(pd[offset + P_REJECT_ER]) {
1308 str = "Reason not specified";
1311 str = "Invalid parameter code";
1314 str = "Invalid TPDU type";
1317 str = "Invalid parameter value";
1325 if (check_col(fd, COL_PROTOCOL))
1326 col_add_str(fd, COL_PROTOCOL, "COTP");
1327 if (check_col(fd, COL_INFO))
1328 col_add_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
1331 ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL);
1332 cotp_tree = proto_item_add_subtree(ti, ett_cotp);
1333 proto_tree_add_text(cotp_tree, offset, 1,
1334 "Length indicator: %d", li);
1335 proto_tree_add_text(cotp_tree, offset + 1, 1,
1336 "TPDU code: Ox%x (ER)", tpdu);
1337 proto_tree_add_text(cotp_tree, offset + 2, 2,
1338 "Destination reference: 0x%04x", dst_ref);
1339 proto_tree_add_text(cotp_tree, offset + 4, 1,
1340 "Reject cause: %s", str);
1344 dissect_data(pd, offset, fd, tree);
1348 } /* osi_decode_ER */
1350 void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
1356 if (((li = pd[offset + P_LI]) == 0) ||
1357 (offset + P_LI + li + 1 > fd->cap_len)) {
1358 dissect_data(pd, offset, fd, tree);
1362 tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F;
1363 cdt = pd[offset + P_CDT] & 0x0F;
1364 dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]);
1369 status = osi_decode_CC(pd, offset, fd, tree);
1372 status = osi_decode_DR(pd, offset, fd, tree);
1375 status = osi_decode_DT(pd, offset, fd, tree);
1378 status = osi_decode_ED(pd, offset, fd, tree);
1381 status = osi_decode_RJ(pd, offset, fd, tree);
1384 status = osi_decode_DC(pd, offset, fd, tree);
1387 status = osi_decode_AK(pd, offset, fd, tree);
1390 status = osi_decode_EA(pd, offset, fd, tree);
1393 status = osi_decode_ER(pd, offset, fd, tree);
1399 if (status == -1) /* incorrect TPDU */
1400 dissect_data(pd, offset, fd, tree);
1402 } /* dissect_cotp */
1409 #define MAX_NSAP_LEN 20
1411 static gchar *print_nsap(const u_char *nsap, int length)
1414 /* to do : real NSAP decoding */
1416 static gchar str[3][MAX_NSAP_LEN * 3 + 1];
1420 if (cur == &str[0][0]) {
1422 } else if (cur == &str[1][0]) {
1429 if (length <= 0 || length > MAX_NSAP_LEN)
1430 sprintf(cur, "<invalid NSAP>");
1432 while (length != 1) {
1433 sprintf(tmp, "%02x:", *nsap ++);
1437 sprintf(tmp, "%02x", *nsap);
1443 void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
1447 struct clnp_header clnp;
1448 proto_tree *clnp_tree = NULL;
1450 u_char src_len, dst_len, nsel;
1451 u_int first_offset = offset;
1453 if (fd->cap_len < offset + sizeof(clnp)) {
1454 dissect_data(pd, offset, fd, tree);
1458 /* avoid alignment problem */
1459 memcpy(&clnp, &pd[offset], sizeof(clnp));
1461 /* return if version not known */
1462 if (clnp.cnf_vers != ISO8473_V1) {
1463 dissect_data(pd, offset, fd, tree);
1467 /* fixed part decoding */
1470 ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL);
1471 clnp_tree = proto_item_add_subtree(ti, ett_clnp);
1472 proto_tree_add_item(clnp_tree, hf_clnp_id, offset, 1,
1474 proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1,
1476 proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1,
1478 proto_tree_add_item_format(clnp_tree, hf_clnp_ttl, offset + 3, 1,
1480 "TTL: %d (%d secs)",
1481 clnp.cnf_ttl, clnp.cnf_ttl / 2);
1482 proto_tree_add_item_format(clnp_tree, hf_clnp_type, offset + 4, 1,
1484 "Type code: 0x%02x (%s%s%s%s)",
1486 (clnp.cnf_type & CNF_SEG_OK) ? "S " : "",
1487 (clnp.cnf_type & CNF_MORE_SEGS) ? "M " : "",
1488 (clnp.cnf_type & CNF_ERR_OK) ? "E " : "",
1489 (clnp.cnf_type & CNF_TYPE) == DT_NPDU ?
1491 proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2,
1492 EXTRACT_SHORT(&clnp.cnf_seglen_msb));
1493 proto_tree_add_item_format(clnp_tree, hf_clnp_checksum, offset + 7, 2,
1494 EXTRACT_SHORT(&clnp.cnf_cksum_msb),
1496 EXTRACT_SHORT(&clnp.cnf_cksum_msb));
1499 /* stop here if header is not complete */
1501 if (fd->cap_len < offset + clnp.cnf_hdr_len) {
1502 dissect_data(pd, offset, fd, tree);
1508 offset += P_ADDRESS_PART;
1509 dst_len = pd[offset];
1510 nsel = pd[offset + dst_len];
1511 src_len = pd[offset + dst_len + 1];
1514 proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1,
1516 proto_tree_add_item_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len,
1518 "Destination address: %s",
1519 print_nsap(&pd[offset + 1], dst_len));
1520 proto_tree_add_item(clnp_tree, hf_clnp_src_length,
1521 offset + 1 + dst_len, 1, src_len);
1522 proto_tree_add_item_format(clnp_tree, hf_clnp_src,
1523 offset + dst_len + 2, src_len,
1524 &pd[offset + dst_len + 2],
1525 "Source address: %s",
1526 print_nsap(&pd[offset + dst_len + 2], src_len));
1529 if (check_col(fd, COL_RES_NET_SRC))
1530 col_add_fstr(fd, COL_RES_NET_SRC, "%s",
1531 print_nsap(&pd[offset + dst_len + 2], src_len));
1532 if (check_col(fd, COL_RES_NET_DST))
1533 col_add_fstr(fd, COL_RES_NET_DST, "%s",
1534 print_nsap(&pd[offset + 1], dst_len));
1536 /* Segmentation Part */
1538 offset += dst_len + src_len + 2;
1540 if (tree && (clnp.cnf_type & CNF_SEG_OK)) {
1541 struct clnp_segment seg;
1542 memcpy(&seg, &pd[offset], sizeof(seg));
1544 proto_tree_add_text(clnp_tree, offset, 2,
1545 "Data unit identifier: 0x%04x",
1546 EXTRACT_SHORT(&pd[offset]));
1547 proto_tree_add_text(clnp_tree, offset + 2 , 2,
1548 "Segment offset: 0x%04x",
1549 EXTRACT_SHORT(&pd[offset + 2]));
1550 proto_tree_add_text(clnp_tree, offset + 4 , 2,
1551 "Total length: 0x%04x",
1552 EXTRACT_SHORT(&pd[offset + 4]));
1558 /* To do : decode options */
1560 proto_tree_add_text(clnp_tree, offset,
1561 clnp.cnf_hdr_len + first_offset - offset,
1562 "Options/Data: <not shown>");
1566 offset = first_offset + clnp.cnf_hdr_len;
1568 if (offset == fd->cap_len)
1571 /* continue with COTP if any */
1573 if (nsel == NSEL_TP) /* just guessing here - valid for DECNet-OSI */
1574 dissect_cotp(pd, offset, fd, tree);
1576 dissect_data(pd, offset, fd, tree);
1578 } /* dissect_clnp */
1581 /* main entry point */
1583 const value_string nlpid_vals[] = {
1584 { NLPID_NULL, "NULL" },
1585 { NLPID_SNAP, "SNAP" },
1586 { NLPID_ISO8473_CLNP, "CLNP" },
1587 { NLPID_ISO9542_ESIS, "ESIS" },
1588 { NLPID_ISO10589_ISIS, "ISIS" },
1589 { NLPID_ISO9542X25_ESIS, "ESIS (X.25)" },
1591 { NLPID_PPP, "PPP" },
1595 void dissect_osi(const u_char *pd, int offset, frame_data *fd,
1599 switch (pd[offset]) {
1601 /* ESIS is not currently decoded */
1603 case NLPID_ISO8473_CLNP:
1604 if (check_col(fd, COL_PROTOCOL)) {
1605 col_add_str(fd, COL_PROTOCOL, "CLNP");
1607 dissect_clnp(pd, offset, fd, tree);
1609 case NLPID_ISO9542_ESIS:
1610 if (check_col(fd, COL_PROTOCOL)) {
1611 col_add_str(fd, COL_PROTOCOL, "ESIS");
1613 dissect_data(pd, offset, fd, tree);
1615 case NLPID_ISO9542X25_ESIS:
1616 if (check_col(fd, COL_PROTOCOL)) {
1617 col_add_str(fd, COL_PROTOCOL, "ESIS (X.25)");
1619 dissect_data(pd, offset, fd, tree);
1621 case NLPID_ISO10589_ISIS:
1622 if (check_col(fd, COL_PROTOCOL)) {
1623 col_add_str(fd, COL_PROTOCOL, "ISIS");
1625 dissect_isis(pd, offset, fd, tree);
1628 if (check_col(fd, COL_PROTOCOL)) {
1629 col_add_str(fd, COL_PROTOCOL, "ISO");
1631 if (check_col(fd, COL_INFO)) {
1632 col_add_fstr(fd, COL_INFO, "Unknown ISO protocol (%02x)", pd[offset]);
1634 dissect_data(pd, offset, fd, tree);
1640 void proto_register_clnp(void)
1642 static hf_register_info hf[] = {
1644 { "Protocol identifier", "clnp.id", FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0,
1648 { "Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1652 { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
1656 { "TTL", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
1660 { "Type code", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
1663 { &hf_clnp_pdu_length,
1664 { "PDU segment length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1667 { &hf_clnp_checksum,
1668 { "Checksum", "clnp.checksum",FT_UINT16, BASE_DEC, NULL, 0x0,
1671 { &hf_clnp_dest_length,
1672 { "Destination address length", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0,
1676 { "Destination address", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0,
1679 { &hf_clnp_src_length,
1680 { "Source address length","clnp.ssap.len",FT_UINT8, BASE_DEC, NULL, 0x0,
1684 { "Source address", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0,
1687 static gint *ett[] = {
1691 proto_clnp = proto_register_protocol("ISO CLNP", "clnp");
1692 proto_register_field_array(proto_clnp, hf, array_length(hf));
1693 proto_register_subtree_array(ett, array_length(ett));
1696 void proto_register_cotp(void)
1698 /* static hf_register_info hf[] = {
1700 { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }},
1702 static gint *ett[] = {
1706 proto_cotp = proto_register_protocol("ISO COTP", "cotp");
1707 /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/
1708 proto_register_subtree_array(ett, array_length(ett));