diff --git a/packet-clnp.c b/packet-clnp.c index de43f67ec1..3ca796c43f 100644 --- a/packet-clnp.c +++ b/packet-clnp.c @@ -1,7 +1,7 @@ /* packet-clnp.c * Routines for ISO/OSI network and transport protocol packet disassembly * - * $Id: packet-clnp.c,v 1.8 2000/05/31 05:06:58 guy Exp $ + * $Id: packet-clnp.c,v 1.9 2000/07/01 08:55:26 guy Exp $ * Laurent Deniel * Ralf Schneider * @@ -49,9 +49,11 @@ /* protocols and fields */ static int proto_clnp = -1; -static int proto_cotp = -1; static gint ett_clnp = -1; +static int proto_cotp = -1; static gint ett_cotp = -1; +static int proto_cltp = -1; +static gint ett_cltp = -1; static int hf_clnp_id = -1; static int hf_clnp_length = -1; @@ -143,16 +145,17 @@ struct clnp_segment { /* TPDU definition */ -#define ED_TPDU 0x1 -#define EA_TPDU 0x2 -#define RJ_TPDU 0x5 -#define AK_TPDU 0x6 -#define ER_TPDU 0x7 -#define DR_TPDU 0x8 -#define DC_TPDU 0xC -#define CC_TPDU 0xD -#define CR_TPDU 0xE -#define DT_TPDU 0xF +#define ED_TPDU 0x1 /* COTP */ +#define EA_TPDU 0x2 /* COTP */ +#define UD_TPDU 0x4 /* CLTP */ +#define RJ_TPDU 0x5 /* COTP */ +#define AK_TPDU 0x6 /* COTP */ +#define ER_TPDU 0x7 /* COTP */ +#define DR_TPDU 0x8 /* COTP */ +#define DC_TPDU 0xC /* COTP */ +#define CC_TPDU 0xD /* COTP */ +#define CR_TPDU 0xE /* COTP */ +#define DT_TPDU 0xF /* COTP */ /* field position */ @@ -165,11 +168,7 @@ struct clnp_segment { #define P_TPDU_NR_234 4 #define P_VAR_PART_NDT 5 #define P_VAR_PART_EDT 8 -#define P_VAR_PART_NAK 5 -#define P_VAR_PART_CC 7 -#define P_VAR_PART_EAK 10 #define P_VAR_PART_DC 6 -#define P_VAR_PART_DR 7 #define P_CDT_IN_AK 8 #define P_CDT_IN_RJ 8 #define P_REJECT_ER 4 @@ -194,9 +193,10 @@ struct clnp_segment { #define LI_MAX_AK 27 #define LI_MAX_EA 11 #define LI_MAX_ER 8 -#define LI_DC_WITH_CHECKSUM 9 -#define LI_DC_WITHOUT_CHECKSUM 5 -#define is_LI_NORMAL_AK(p) ( p & 0x01 ) +/* XXX - can we always decide this based on whether the length + indicator is odd or not? What if the variable part has an odd + number of octets? */ +#define is_LI_NORMAL_AK(p) ( ( p & 0x01 ) == 0 ) /* variant part */ @@ -216,6 +216,29 @@ struct clnp_segment { #define VP_PROTECTION 0xC5 #define VP_OPT_SEL 0xC6 #define VP_PROTO_CLASS 0xC7 +#define VP_PREF_MAX_TPDU_SIZE 0xF0 +#define VP_INACTIVITY_TIMER 0xF2 + +static const value_string tp_vpart_type_vals[] = { + { VP_ACK_TIME, "ack time" }, + { VP_RES_ERROR, "res error" }, + { VP_PRIORITY, "priority" }, + { VP_TRANSIT_DEL, "transit delay" }, + { VP_THROUGHPUT, "throughput" }, + { VP_SEQ_NR, "seq number" }, + { VP_REASSIGNMENT, "reassignment" }, + { VP_FLOW_CNTL, "flow control" }, + { VP_TPDU_SIZE, "tpdu-size" }, + { VP_SRC_TSAP, "src-tsap" }, + { VP_DST_TSAP, "dst-tsap" }, + { VP_CHECKSUM, "checksum" }, + { VP_VERSION_NR, "version" }, + { VP_PROTECTION, "protection" }, + { VP_OPT_SEL, "options" }, + { VP_PROTO_CLASS, "proto class" }, + { VP_PREF_MAX_TPDU_SIZE, "preferred max TPDU size" }, + { 0, NULL } +}; /* misc */ @@ -233,6 +256,375 @@ static heur_dissector_list_t cotp_is_heur_subdissector_list; /* function definitions */ +#define MAX_TSAP_LEN 32 +static gchar *print_tsap(const u_char *tsap, int length) +{ + + static gchar str[3][MAX_TSAP_LEN * 2 + 1]; + static gchar *cur; + gchar tmp[3]; + gboolean allprintable; + int i; + + if (cur == &str[0][0]) { + cur = &str[1][0]; + } else if (cur == &str[1][0]) { + cur = &str[2][0]; + } else { + cur = &str[0][0]; + } + + + cur[0] = '\0'; + if (length <= 0 || length > MAX_TSAP_LEN) + sprintf(cur, ""); + else { + allprintable=TRUE; + for (i=0;i"); + offset += length; + vp_length -= length; + break; + } + } /* while */ + + return TRUE; +} + static int osi_decode_DR(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { @@ -298,59 +690,58 @@ static gboolean osi_decode_DT(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, gboolean uses_inactive_subset) { - proto_tree *cotp_tree; + proto_tree *cotp_tree = NULL; proto_item *ti; + gboolean is_extended; + gboolean is_class_234; u_int tpdu_nr ; - u_short checksum = 0; - u_char code = 0, length = 0; u_int fragment = 0; + /* VP_CHECKSUM is the only parameter allowed in the variable part. + (This means we may misdissect this if the packet is bad and + contains other parameters.) */ switch (li) { + case LI_NORMAL_DT_WITH_CHECKSUM : - tpdu_nr = pd[offset + P_TPDU_NR_234]; - if ( tpdu_nr & 0x80 ) - tpdu_nr = tpdu_nr & 0x7F; - else - fragment = 1; - code = pd[offset + P_VAR_PART_NDT]; - if (code == VP_CHECKSUM) - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]); - else + if (pd[offset + P_VAR_PART_NDT] != VP_CHECKSUM) return -1; - break; + /* FALLTHROUGH */ + case LI_NORMAL_DT_WITHOUT_CHECKSUM : tpdu_nr = pd[offset + P_TPDU_NR_234]; if ( tpdu_nr & 0x80 ) tpdu_nr = tpdu_nr & 0x7F; else fragment = 1; + is_extended = FALSE; + is_class_234 = TRUE; break; + case LI_EXTENDED_DT_WITH_CHECKSUM : - tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); - if ( tpdu_nr & 0x80000000 ) - tpdu_nr = tpdu_nr & 0x7FFFFFFF; - else - fragment = 1; - code = pd[offset + P_VAR_PART_EDT]; - if (code == VP_CHECKSUM) - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]); - else + if (pd[offset + P_VAR_PART_EDT] != VP_CHECKSUM) return -1; - break; + /* FALLTHROUGH */ + case LI_EXTENDED_DT_WITHOUT_CHECKSUM : tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); if ( tpdu_nr & 0x80000000 ) tpdu_nr = tpdu_nr & 0x7FFFFFFF; else fragment = 1; + is_extended = TRUE; + is_class_234 = TRUE; break; + case LI_NORMAL_DT_CLASS_01 : tpdu_nr = pd[offset + P_TPDU_NR_0_1]; if ( tpdu_nr & 0x80 ) tpdu_nr = tpdu_nr & 0x7F; else fragment = 1; + is_extended = FALSE; + is_class_234 = FALSE; break; + default : /* bad TPDU */ return -1; /*NOTREACHED*/ @@ -366,68 +757,52 @@ static gboolean osi_decode_DT(const u_char *pd, int offset, if (tree) { ti = proto_tree_add_item(tree, proto_cotp, NullTVB, offset, li + 1, FALSE); cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Length indicator: %u", li); - proto_tree_add_text(cotp_tree, NullTVB, offset + 1, 1, + } + offset += 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "TPDU code: 0x%x (DT)", tpdu); - if (li != LI_NORMAL_DT_CLASS_01) - proto_tree_add_text(cotp_tree, NullTVB, offset + 2, 2, + } + offset += 1; + li -= 1; + + if (is_class_234) { + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, "Destination reference: 0x%04x", dst_ref); - - switch (li) { - case LI_NORMAL_DT_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 1, - "TPDU number: 0x%02x (%s)", - tpdu_nr, - (fragment)? "fragment":"complete"); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NDT, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NDT + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NDT + 2, length, - "Checksum: 0x%04x", checksum); - break; - case LI_NORMAL_DT_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 1, - "TPDU number: 0x%02x (%s)", - tpdu_nr, - (fragment)? "fragment":"complete"); - break; - case LI_EXTENDED_DT_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 4, - "TPDU number: 0x%08x (%s)", - tpdu_nr, - (fragment)? "fragment":"complete"); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EDT, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EDT + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EDT + 2, length, - "Checksum: 0x%04x", checksum); - break; - case LI_EXTENDED_DT_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 4, - "TPDU number: 0x%08x (%s)", - tpdu_nr, - (fragment)? "fragment":"complete"); - break; - case LI_NORMAL_DT_CLASS_01 : - proto_tree_add_text(cotp_tree, NullTVB, offset + 2, 1, - "TPDU number: 0x%02x (%s)", - tpdu_nr, - (fragment)? "fragment":"complete"); - break; } - } /* tree */ + offset += 2; + li -= 2; + } + + if (is_extended) { + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 4, + "TPDU number: 0x%08x (%s)", + tpdu_nr, + (fragment)? "fragment":"complete"); + } + offset += 4; + li -= 4; + } else { + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + "TPDU number: 0x%02x (%s)", + tpdu_nr, + (fragment)? "fragment":"complete"); + } + offset += 1; + li -= 1; + } + + if (tree) + osi_decode_tp_var_part(pd, offset, li, 4, cotp_tree); + offset += li; - offset += li + 1; if (uses_inactive_subset){ if (dissector_try_heuristic(cotp_is_heur_subdissector_list, pd, offset, fd, tree)) { @@ -446,55 +821,46 @@ static gboolean osi_decode_DT(const u_char *pd, int offset, static int osi_decode_ED(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { - proto_tree *cotp_tree; + proto_tree *cotp_tree = NULL; proto_item *ti; + gboolean is_extended; u_int tpdu_nr ; - u_short checksum = 0; - u_char code = 0, length = 0; /* ED TPDUs are never fragmented */ + /* VP_CHECKSUM is the only parameter allowed in the variable part. + (This means we may misdissect this if the packet is bad and + contains other parameters.) */ switch (li) { + case LI_NORMAL_DT_WITH_CHECKSUM : - tpdu_nr = pd[offset + P_TPDU_NR_234]; - if ( tpdu_nr & 0x80 ) - tpdu_nr = tpdu_nr & 0x7F; - else + if (pd[offset + P_VAR_PART_NDT] != VP_CHECKSUM) return -1; - code = pd[offset + P_VAR_PART_NDT]; - length = pd[offset + P_VAR_PART_NDT + 1]; - if (code == VP_CHECKSUM) - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]); - else - return -1; - break; + /* FALLTHROUGH */ + case LI_NORMAL_DT_WITHOUT_CHECKSUM : tpdu_nr = pd[offset + P_TPDU_NR_234]; if ( tpdu_nr & 0x80 ) tpdu_nr = tpdu_nr & 0x7F; else return -1; + is_extended = FALSE; break; + case LI_EXTENDED_DT_WITH_CHECKSUM : - tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); - if ( tpdu_nr & 0x80000000 ) - tpdu_nr = tpdu_nr & 0x7FFFFFFF; - else + if (pd[offset + P_VAR_PART_EDT] != VP_CHECKSUM) return -1; - code = pd[offset + P_VAR_PART_EDT]; - length = pd[offset + P_VAR_PART_EDT + 1]; - if (code == VP_CHECKSUM) - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]); - else - return -1; - break; + /* FALLTHROUGH */ + case LI_EXTENDED_DT_WITHOUT_CHECKSUM : tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); if ( tpdu_nr & 0x80000000 ) tpdu_nr = tpdu_nr & 0x7FFFFFFF; else return -1; + is_extended = TRUE; break; + default : /* bad TPDU */ return -1; /*NOTREACHED*/ @@ -508,52 +874,45 @@ static int osi_decode_ED(const u_char *pd, int offset, if (tree) { ti = proto_tree_add_item(tree, proto_cotp, NullTVB, offset, li + 1, FALSE); cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Length indicator: %u", li); - proto_tree_add_text(cotp_tree, NullTVB, offset + 1, 1, - "TPDU code: 0x%x (ED)", tpdu); - proto_tree_add_text(cotp_tree, NullTVB, offset + 2, 2, + } + offset += 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + "TPDU code: 0x%x (ED)", tpdu); + } + offset += 1; + li -= 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, "Destination reference: 0x%04x", dst_ref); + } + offset += 2; + li -= 2; - switch (li) { - case LI_NORMAL_DT_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 1, - "TPDU number: 0x%02x", tpdu_nr); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NDT, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NDT + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NDT + 2, length, - "Checksum: 0x%04x", checksum); - break; - case LI_NORMAL_DT_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 1, + if (is_extended) { + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 4, "TPDU number: 0x%02x", tpdu_nr); - break; - case LI_EXTENDED_DT_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 4, - "TPDU number: 0x%02x", tpdu_nr); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EDT, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EDT + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EDT + 2, length, - "Checksum: 0x%04x", checksum); - break; - case LI_EXTENDED_DT_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 4, - "TPDU number: 0x%02x", tpdu_nr); - break; } - } /* tree */ + offset += 4; + li -= 4; + } else { + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + "TPDU number: 0x%02x", tpdu_nr); + } + offset += 1; + li -= 1; + } + + if (tree) + osi_decode_tp_var_part(pd, offset, li, 4, cotp_tree); + offset += li; - offset += li + 1; dissect_data(pd, offset, fd, tree); return pi.captured_len; /* we dissected all of the containing PDU */ @@ -615,53 +974,6 @@ static int osi_decode_RJ(const u_char *pd, int offset, } /* osi_decode_RJ */ -#define MAX_TSAP_LEN 32 - -static gchar *print_tsap(const u_char *tsap, int length) -{ - - static gchar str[3][MAX_TSAP_LEN * 2 + 1]; - static gchar *cur; - gchar tmp[3]; - gboolean allprintable; - int i; - - if (cur == &str[0][0]) { - cur = &str[1][0]; - } else if (cur == &str[1][0]) { - cur = &str[2][0]; - } else { - cur = &str[0][0]; - } - - - cur[0] = '\0'; - if (length <= 0 || length > MAX_TSAP_LEN) - sprintf(cur, ""); - else { - allprintable=TRUE; - for (i=0;i> 4 ) & 0x0F; @@ -688,248 +999,44 @@ static int osi_decode_CC(const u_char *pd, int offset, if (tree) { ti = proto_tree_add_item(tree, proto_cotp, NullTVB, offset, li + 1, FALSE); cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Length indicator: %u", li); - proto_tree_add_text(cotp_tree, NullTVB, offset + 1, 1, + } + offset += 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "TPDU code: 0x%x (%s)", tpdu, - (tpdu == CR_TPDU) ? "CR" : "CC"); - proto_tree_add_text(cotp_tree, NullTVB, offset + 2, 2, + (tpdu == CR_TPDU) ? "CR" : "CC"); + } + offset += 1; + li -= 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 2, + } + offset += 2; + li -= 2; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, "Source reference: 0x%04x", src_ref); - proto_tree_add_text(cotp_tree, NullTVB, offset + 6, 1, + } + offset += 2; + li -= 2; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Class option: 0x%02x", class_option); } + offset += 1; + li -= 1; if (tree) - while(li > P_VAR_PART_CC + i - 1) { - - u_char c1; - u_short s, s1,s2,s3,s4; - u_int t1,t2,t3,t4; - - switch( (code = pd[offset + P_VAR_PART_CC + i]) ) { - case VP_CHECKSUM : - length = pd[offset + P_VAR_PART_CC + i + 1]; - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, length, - "Checksum: 0x%04x", checksum); - i += length + 2; - break; - case VP_SRC_TSAP : - length = pd[offset + P_VAR_PART_CC + i + 1]; - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (src-tsap)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, length, - "Calling TSAP: %s", - print_tsap(&pd[offset + P_VAR_PART_CC + i + 2], - length)); - i += length + 2; - break; - case VP_DST_TSAP : - length = pd[offset + P_VAR_PART_CC + i + 1]; - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (dst-tsap)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, length, - "Called TSAP: %s", - print_tsap(&pd[offset + P_VAR_PART_CC + i + 2], - length)); - i += length + 2; - break; - case VP_TPDU_SIZE : - length = pd[offset + P_VAR_PART_CC + i + 1]; - c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F; - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (tpdu-size)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, length, - "TPDU size: %u", 2 << c1); - i += length + 2; - break; - case VP_OPT_SEL : - length = pd[offset + P_VAR_PART_CC + i + 1]; - c1 = pd[offset + P_VAR_PART_CC + i + 2] & 0x0F; - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (options)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - if (class_option == 1) { - if (c1 & 0x8) - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 1, - "Use of network expedited data"); - else - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 1, - "Non use of network expedited data"); - if (c1 & 0x4) - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 1, - "Use of Receipt confirmation"); - else - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 1, - "Use of explicit AK variant"); - } else if (class_option == 4) { - if (c1 & 0x2) - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 1, - "Non-use 16 bit checksum in class 4"); - else - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 1, - "Use 16 bit checksum "); - } - if (c1 & 0x1) - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 1, - "Use of transport expedited data transfer\n"); - else - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 1, - "Non-use of transport expedited data transfer"); - i += length + 2; - break; - case VP_ACK_TIME : - length = pd[offset + P_VAR_PART_CC + i + 1]; - s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (ack time)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, length, - "Ack time (ms): %u", s); - i += length + 2; - break; - case VP_THROUGHPUT : - length = pd[offset + P_VAR_PART_CC + i + 1]; - t1 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 1]); - t2 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 4]); - t3 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 7]); - t4 = EXTRACT_LONG(&pd[offset + P_VAR_PART_CC + i + 10]); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (throughput)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 4, - "Target value / calling-called: %u o/s", t1); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 6, 4, - "Minimum / calling-called: %u o/s", t2); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 10, 4, - "Target value / called-calling: %u o/s", t3); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 14, 4, - "Minimum / called-calling: %u o/s", t4); - i += length + 2; - break; - case VP_TRANSIT_DEL : - length = pd[offset + P_VAR_PART_CC + i + 1]; - s1 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]); - s2 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 4]); - s3 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 6]); - s4 = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 8]); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (transit delay)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, 2, - "Target value / calling-called: %u ms", s1); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 4, 2, - "Minimum / calling-called: %u ms", s2); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 6, 2, - "Target value / called-calling: %u ms", s3); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 8, 2, - "Minimum / called-calling: %u ms", s4); - i += length + 2; - break; - case VP_PRIORITY : - length = pd[offset + P_VAR_PART_CC + i + 1]; - s = EXTRACT_SHORT(&pd[offset + P_VAR_PART_CC + i + 2]); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (priority)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, length, - "Priority: %u", s); - i += length + 2; - break; - - case VP_VERSION_NR : - length = pd[offset + P_VAR_PART_CC + i + 1]; - c1 = pd[offset + P_VAR_PART_CC + i + 2]; - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (version)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, length, - "Version: %u", c1); - i += length + 2; - break; + osi_decode_tp_var_part(pd, offset, li, class_option, cotp_tree); + offset += li; - case VP_REASSIGNMENT: /* todo */ - case VP_RES_ERROR : - case VP_PROTECTION : - case VP_PROTO_CLASS : - default : /* no decoding */ - length = pd[offset + P_VAR_PART_CC + i + 1]; - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 0, 1, - "Parameter code: 0x%02x", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_CC + i + 2, length, - "Parameter value: "); - i += length + 2; - break; - } - } /* while */ - - offset += li + 1; dissect_data(pd, offset, fd, tree); return pi.captured_len; /* we dissected all of the containing PDU */ @@ -939,31 +1046,15 @@ static int osi_decode_CC(const u_char *pd, int offset, static int osi_decode_DC(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { - proto_tree *cotp_tree; + proto_tree *cotp_tree = NULL; proto_item *ti; - u_short src_ref, checksum = 0; - u_char length = 0, code = 0; + u_short src_ref; if (li > LI_MAX_DC) return -1; src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]); - switch(li) { - case LI_DC_WITHOUT_CHECKSUM : - break; - case LI_DC_WITH_CHECKSUM : - if ((code = pd[offset + P_VAR_PART_DC]) != VP_CHECKSUM) - return -1; - length = pd[offset + P_VAR_PART_DC + 1]; - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_DC + 2]); - break; - default : - return -1; - /*NOTREACHED*/ - break; - } /* li */ - if (check_col(fd, COL_INFO)) col_append_fstr(fd, COL_INFO, "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x", src_ref, @@ -972,28 +1063,35 @@ static int osi_decode_DC(const u_char *pd, int offset, if (tree) { ti = proto_tree_add_item(tree, proto_cotp, NullTVB, offset, li + 1, FALSE); cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Length indicator: %u", li); - proto_tree_add_text(cotp_tree, NullTVB, offset + 1, 1, - "TPDU code: 0x%x (DC)", tpdu); - proto_tree_add_text(cotp_tree, NullTVB, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 2, - "Source reference: 0x%04x", src_ref); - if (code) { - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_DC + 0, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_DC + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_DC + 2, 2, - "Checksum: 0x%04x", checksum); - } } + offset += 1; - offset += li + 1; + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + "TPDU code: 0x%x (DC)", tpdu); + } + offset += 1; + li -= 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, + "Destination reference: 0x%04x", dst_ref); + } + offset += 2; + li -= 2; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, + "Source reference: 0x%04x", src_ref); + } + offset += 2; + li -= 2; + + if (tree) + osi_decode_tp_var_part(pd, offset, li, 4, cotp_tree); + offset += li; return offset; @@ -1004,116 +1102,55 @@ static int osi_decode_AK(const u_char *pd, int offset, { proto_tree *cotp_tree = NULL; proto_item *ti; - u_int tpdu_nr,i =0, r_lower_window_edge ; + u_int tpdu_nr; u_short cdt_in_ak; - u_short checksum, seq_nr, r_seq_nr, r_cdt; - u_char code, length; if (li > LI_MAX_AK) return -1; - if (!is_LI_NORMAL_AK(li)) { + if (is_LI_NORMAL_AK(li)) { + tpdu_nr = pd[offset + P_TPDU_NR_234]; if (check_col(fd, COL_INFO)) col_append_fstr(fd, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref); - + if (tree) { ti = proto_tree_add_item(tree, proto_cotp, NullTVB, offset, li + 1, FALSE); cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Length indicator: %u", li); - proto_tree_add_text(cotp_tree, NullTVB, offset + 1, 1, - "TPDU code: 0x%x (AK)", tpdu); - proto_tree_add_text(cotp_tree, NullTVB, offset + 1, 1, + } + offset += 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + "TPDU code: 0x%x (AK)", tpdu); + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Credit: %u", cdt); - proto_tree_add_text(cotp_tree, NullTVB, offset + 2, 2, + } + offset += 1; + li -= 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 1, + } + offset += 2; + li -= 2; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Your TPDU number: 0x%02x", tpdu_nr); } + offset += 1; + li -= 1; + + if (tree) + osi_decode_tp_var_part(pd, offset, li, 4, cotp_tree); + offset += li; - while(li > P_VAR_PART_NAK + i - 1) { - switch( (code = pd[offset + P_VAR_PART_NAK + i]) ) { - case VP_CHECKSUM : - length = pd[offset + P_VAR_PART_NAK + i + 1]; - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]); - if (tree) { - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 0, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 2, 2, - "Checksum: 0x%04x", checksum); - } - i += length + 2; - break; - case VP_FLOW_CNTL : - length = pd[offset + P_VAR_PART_NAK + i + 1]; - r_lower_window_edge = - EXTRACT_LONG(&pd[offset + P_VAR_PART_NAK + i + 2]); - r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 6]); - r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 8]); - if (tree) { - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 0, 1, - "Parameter code: 0x%02x (flow control)", - code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 2, 4, - "Lower window edge: 0x%08x", - r_lower_window_edge); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 6, 2, - "Sequence number: 0x%04x", - r_seq_nr); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 8, 2, - "Credit: 0x%04x", - r_cdt); - } - i += length + 2; - break; - case VP_SEQ_NR : - length = pd[offset + P_VAR_PART_NAK + i + 1]; - seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NAK + i + 2]); - if (tree) { - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 0, 1, - "Parameter code: 0x%02x (seq number)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 2, 2, - "Sequence number: 0x%04x", seq_nr); - } - i += length + 2; - break; - default : - length = pd[offset + P_VAR_PART_NAK + i + 1]; - if (tree) { - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 0, 1, - "Parameter code: 0x%02x (unknown)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_NAK + i + 2, length, - "Parameter value: "); - } - i += length + 2; - break; - } /* code */ - } } else { /* extended format */ tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); @@ -1126,102 +1163,44 @@ static int osi_decode_AK(const u_char *pd, int offset, if (tree) { ti = proto_tree_add_item(tree, proto_cotp, NullTVB, offset, li + 1, FALSE); cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Length indicator: %u", li); - proto_tree_add_text(cotp_tree, NullTVB, offset + 1, 1, - "TPDU code: 0x%x (AK)", tpdu); - proto_tree_add_text(cotp_tree, NullTVB, offset + 2, 2, + } + offset += 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + "TPDU code: 0x%x (AK)", tpdu); + } + offset += 1; + li -= 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 4, + } + offset += 2; + li -= 2; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 4, "Your TPDU number: 0x%08x", tpdu_nr); - proto_tree_add_text(cotp_tree, NullTVB, offset + 8, 2, + } + offset += 4; + li -= 4; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, "Credit: 0x%04x", cdt_in_ak); } + offset += 2; + li -= 2; - while(li > P_VAR_PART_EAK + i - 1) { - switch( (code = pd[offset + P_VAR_PART_EAK + i]) ) { - case VP_CHECKSUM : - length = pd[offset + P_VAR_PART_EAK + i + 1]; - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]); - if (tree) { - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 0, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 2, 2, - "Checksum: 0x%04x", checksum); - } - i += length + 2; - break; - case VP_FLOW_CNTL : - length = pd[offset + P_VAR_PART_EAK + i + 1]; - r_lower_window_edge = - EXTRACT_LONG(&pd[offset + P_VAR_PART_EAK + i + 2]); - r_seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 6]); - r_cdt = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 8]); - if (tree) { - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 0, 1, - "Parameter code: 0x%02x (flow control)", - code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 2, 4, - "Lower window edge: 0x%08x", - r_lower_window_edge); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 6, 2, - "Sequence number: 0x%04x", - r_seq_nr); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 8, 2, - "Credit: 0x%04x", - r_cdt); - } - i += length + 2; - break; - case VP_SEQ_NR : - length = pd[offset + P_VAR_PART_EAK + i + 1]; - seq_nr = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EAK + i + 2]); - if (tree) { - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 0, 1, - "Parameter code: 0x%02x (seq number)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 2, 2, - "Sequence number: 0x%04x", seq_nr); - } - i += length + 2; - break; - default : - length = pd[offset + P_VAR_PART_EAK + i + 1]; - if (tree) { - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 0, 1, - "Parameter code: 0x%02x (unknown)", code); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, - offset + P_VAR_PART_EAK + i + 2, length, - "Parameter value: "); - } - i += length + 2; - break; - } /* code */ - } - - } /* is_LI_NORMAL_AK */ + if (tree) + osi_decode_tp_var_part(pd, offset, li, 4, cotp_tree); + offset += li; - offset += li + 1; + } /* is_LI_NORMAL_AK */ return offset; @@ -1230,39 +1209,41 @@ static int osi_decode_AK(const u_char *pd, int offset, static int osi_decode_EA(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { - proto_tree *cotp_tree; + proto_tree *cotp_tree = NULL; proto_item *ti; + gboolean is_extended; u_int tpdu_nr ; - u_short checksum = 0; - u_char code = 0; - u_char length = 0; if (li > LI_MAX_EA) return -1; + /* VP_CHECKSUM is the only parameter allowed in the variable part. + (This means we may misdissect this if the packet is bad and + contains other parameters.) */ switch (li) { + case LI_NORMAL_EA_WITH_CHECKSUM : - tpdu_nr = pd[offset + P_TPDU_NR_234]; - code = pd[offset + P_VAR_PART_NDT]; - length = pd[offset + P_VAR_PART_NDT + 1]; - if (code != VP_CHECKSUM || length != 1) + if (pd[offset + P_VAR_PART_NDT] != VP_CHECKSUM || + pd[offset + P_VAR_PART_NDT + 1] != 2) return -1; - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]); - break; + /* FALLTHROUGH */ + case LI_NORMAL_EA_WITHOUT_CHECKSUM : tpdu_nr = pd[offset + P_TPDU_NR_234]; + is_extended = FALSE; break; + case LI_EXTENDED_EA_WITH_CHECKSUM : - tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); - code = pd[offset + P_VAR_PART_EDT]; - length = pd[offset + P_VAR_PART_EDT + 1]; - if (code != VP_CHECKSUM || length != 1) + if (pd[offset + P_VAR_PART_EDT] != VP_CHECKSUM || + pd[offset + P_VAR_PART_EDT + 1] != 2) return -1; - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]); - break; + /* FALLTHROUGH */ + case LI_EXTENDED_EA_WITHOUT_CHECKSUM : tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); + is_extended = TRUE; break; + default : /* bad TPDU */ return -1; /*NOTREACHED*/ @@ -1276,48 +1257,44 @@ static int osi_decode_EA(const u_char *pd, int offset, if (tree) { ti = proto_tree_add_item(tree, proto_cotp, NullTVB, offset, li + 1, FALSE); cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, "Length indicator: %u", li); - proto_tree_add_text(cotp_tree, NullTVB, offset + 1, 1, - "TPDU code: 0x%x (EA)", tpdu); - proto_tree_add_text(cotp_tree, NullTVB, offset + 2, 2, + } + offset += 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + "TPDU code: 0x%x (EA)", tpdu); + } + offset += 1; + li -= 1; + + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 2, "Destination reference: 0x%04x", dst_ref); + } + offset += 2; + li -= 2; - switch (li) { - case LI_NORMAL_EA_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 1, - "Your TPDU number: 0x%02x", tpdu_nr); - proto_tree_add_text(cotp_tree, NullTVB, offset + 5, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, offset + 6, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, offset + 7, 2, - "Checksum: 0x%04x", checksum); - break; - case LI_NORMAL_EA_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 1, - "Your TPDU number: 0x%02x", tpdu_nr); - break; - case LI_EXTENDED_EA_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 4, + if (is_extended) { + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 4, "Your TPDU number: 0x%08x", tpdu_nr); - proto_tree_add_text(cotp_tree, NullTVB, offset + 8, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, NullTVB, offset + 9, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, NullTVB, offset + 10, 2, - "Checksum: 0x%04x", checksum); - break; - case LI_EXTENDED_EA_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, NullTVB, offset + 4, 4, - "Your TPDU number: 0x%08x", tpdu_nr); - break; - default : - break; - } /* li */ - } /* tree */ + } + offset += 4; + li -= 4; + } else { + if (tree) { + proto_tree_add_text(cotp_tree, NullTVB, offset, 1, + "Your TPDU number: 0x%02x", tpdu_nr); + } + offset += 1; + li -= 1; + } - offset += li + 1; + if (tree) + osi_decode_tp_var_part(pd, offset, li, 4, cotp_tree); + offset += li; return offset; @@ -1374,15 +1351,55 @@ static int osi_decode_ER(const u_char *pd, int offset, } /* osi_decode_ER */ -/* Returns TRUE if we found at least one valid COTP PDU, FALSE - otherwise. */ -static gboolean dissect_cotp_internal(const u_char *pd, int offset, +/* Returns TRUE if we called a sub-dissector, FALSE if not. */ +static gboolean osi_decode_UD(const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) +{ + proto_item *ti; + proto_tree *cltp_tree = NULL; + + if (check_col(fd, COL_INFO)) + col_append_str(fd, COL_INFO, "UD TPDU"); + + if (tree) { + ti = proto_tree_add_item(tree, proto_cltp, NullTVB, offset, li + 1, FALSE); + cltp_tree = proto_item_add_subtree(ti, ett_cltp); + proto_tree_add_text(cltp_tree, NullTVB, offset, 1, + "Length indicator: %u", li); + } + offset += 1; + + if (tree) { + proto_tree_add_text(cltp_tree, NullTVB, offset, 1, + "TPDU code: 0x%x (UD)", tpdu); + } + offset += 1; + li -= 1; + + if (tree) + osi_decode_tp_var_part(pd, offset, li, 0, cltp_tree); + offset += li; + + dissect_data(pd, offset, fd, tree); + return FALSE; +} /* osi_decode_UD */ + +/* Returns TRUE if we found at least one valid COTP or CLTP PDU, FALSE + otherwise. + + There doesn't seem to be any way in which the OSI network layer protocol + distinguishes between COTP and CLTP, but the first two octets of both + protocols' headers mean the same thing - length and PDU type - and the + only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle + both of them here. */ +static gboolean dissect_ositp_internal(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, gboolean uses_inactive_subset) { gboolean first_tpdu = TRUE; int new_offset; - gboolean found_cotp = FALSE; + gboolean found_ositp = FALSE; + gboolean is_cltp = FALSE; gboolean subdissector_found = FALSE; /* Initialize the COL_INFO field; each of the TPDUs will have its @@ -1400,14 +1417,14 @@ static gboolean dissect_cotp_internal(const u_char *pd, int offset, col_append_str(fd, COL_INFO, "Length indicator is zero"); if (!first_tpdu) dissect_data(pd, offset, fd, tree); - return found_cotp; + return found_ositp; } if (!BYTES_ARE_IN_FRAME(offset, P_LI + li + 1)) { if (check_col(fd, COL_INFO)) col_append_str(fd, COL_INFO, "Captured data in frame doesn't include entire frame"); if (!first_tpdu) dissect_data(pd, offset, fd, tree); - return found_cotp; + return found_ositp; } tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F; @@ -1445,6 +1462,12 @@ static gboolean dissect_cotp_internal(const u_char *pd, int offset, case ER_TPDU : new_offset = osi_decode_ER(pd, offset, fd, tree); break; + case UD_TPDU : + if (osi_decode_UD(pd, offset, fd, tree)) + subdissector_found = TRUE; + new_offset = pi.captured_len; /* UD PDUs run to the end of the packet */ + is_cltp = TRUE; + break; default : if (first_tpdu && check_col(fd, COL_INFO)) col_append_fstr(fd, COL_INFO, "Unknown TPDU type (0x%x)", tpdu); @@ -1459,23 +1482,23 @@ static gboolean dissect_cotp_internal(const u_char *pd, int offset, } if (first_tpdu) { - /* Well, we found at least one valid COTP PDU, so I guess this - is COTP. */ + /* Well, we found at least one valid COTP or CLTP PDU, so I guess this + is either COTP or CLTP. */ if (!subdissector_found && check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, "COTP"); - found_cotp = TRUE; + col_add_str(fd, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP"); + found_ositp = TRUE; } offset = new_offset; first_tpdu = FALSE; } - return found_cotp; -} /* dissect_cotp_internal */ + return found_ositp; +} /* dissect_ositp_internal */ -void dissect_cotp(const u_char *pd, int offset, frame_data *fd, +void dissect_ositp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { - if (!dissect_cotp_internal(pd, offset, fd, tree, FALSE)) + if (!dissect_ositp_internal(pd, offset, fd, tree, FALSE)) dissect_data(pd, offset, fd, tree); } @@ -1515,7 +1538,7 @@ static void dissect_clnp(const u_char *pd, int offset, frame_data *fd, clnp.cnf_proto_id, "Inactive subset"); } - dissect_cotp_internal(pd, offset+1, fd, tree, TRUE); + dissect_ositp_internal(pd, offset+1, fd, tree, TRUE); return; } @@ -1688,8 +1711,8 @@ static void dissect_clnp(const u_char *pd, int offset, frame_data *fd, PDU, skip that? */ if (nsel == NSEL_TP) { /* just guessing here - valid for DECNet-OSI */ - if (dissect_cotp_internal(pd, offset, fd, tree, FALSE)) - return; /* yes, it appears to be COTP */ + if (dissect_ositp_internal(pd, offset, fd, tree, FALSE)) + return; /* yes, it appears to be COTP or CLTP */ } break; @@ -1778,6 +1801,21 @@ void proto_register_cotp(void) register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list); } +void proto_register_cltp(void) +{ + /* static hf_register_info hf[] = { + { &variable, + { "Name", "cltp.abbreviation", TYPE, VALS_POINTER }}, + };*/ + static gint *ett[] = { + &ett_cltp, + }; + + proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "cltp"); + /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/ + proto_register_subtree_array(ett, array_length(ett)); +} + void proto_reg_handoff_clnp(void) { diff --git a/packet-clnp.h b/packet-clnp.h index 9adfe8aca2..2aee4c4569 100644 --- a/packet-clnp.h +++ b/packet-clnp.h @@ -1,7 +1,7 @@ /* packet-clnp.h * Defines and such for CLNP (and COTP) protocol decode. * - * $Id: packet-clnp.h,v 1.2 2000/04/17 01:36:30 guy Exp $ + * $Id: packet-clnp.h,v 1.3 2000/07/01 08:55:27 guy Exp $ * Ralf Schneider * * Ethereal - Network traffic analyzer @@ -34,6 +34,6 @@ */ extern -void dissect_cotp(const u_char *, int, frame_data *, proto_tree *); +void dissect_ositp(const u_char *, int, frame_data *, proto_tree *); #endif /* _PACKET_CLNP_H */ diff --git a/packet-osi.h b/packet-osi.h index 4f5de29144..04e310cacc 100644 --- a/packet-osi.h +++ b/packet-osi.h @@ -1,6 +1,6 @@ /* packet-osi.h * - * $Id: packet-osi.h,v 1.3 2000/06/19 04:49:36 guy Exp $ + * $Id: packet-osi.h,v 1.4 2000/07/01 08:55:28 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -70,6 +70,7 @@ #define PROTO_STRING_ESIS "ISO 9542 ESIS Routeing Information Exchange Protocol" #define PROTO_STRING_CLNP "ISO 8473 CLNP ConnectionLess Network Protocol" #define PROTO_STRING_COTP "ISO 8073 COTP Connection-Oriented Transport Protocol" +#define PROTO_STRING_CLTP "ISO 8602 CLTP ConnectionLess Transport Protocol" #define PROTO_STRING_LSP "ISO 10589 ISIS Link State Protocol Data Unit" #define PROTO_STRING_CSNP "ISO 10589 ISIS Complete Sequence Numbers Protocol Data Unit" #define PROTO_STRING_PSNP "ISO 10589 ISIS Partial Sequence Numbers Protocol Data Unit" diff --git a/packet-x25.c b/packet-x25.c index 710e5fb2ce..0d8fe93df1 100644 --- a/packet-x25.c +++ b/packet-x25.c @@ -2,7 +2,7 @@ * Routines for x25 packet disassembly * Olivier Abad * - * $Id: packet-x25.c,v 1.32 2000/05/31 05:07:54 guy Exp $ + * $Id: packet-x25.c,v 1.33 2000/07/01 08:55:28 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -1542,7 +1542,7 @@ dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) case PRT_ID_ISO_8073: /* ISO 8073 COTP */ x25_hash_add_proto_start(vc, pinfo->fd->abs_secs, - pinfo->fd->abs_usecs, dissect_cotp); + pinfo->fd->abs_usecs, dissect_ositp); break; default: