diff --git a/AUTHORS b/AUTHORS index 7ed2fedf73..c79c2793cf 100644 --- a/AUTHORS +++ b/AUTHORS @@ -294,6 +294,11 @@ Graham Bloice { add version/copyright/etc. information to Win32 executables } +Ralf Schneider { + Enhancements to OSI CLNP, CLTP, and ISIS support + OSI ESIS support +} + Alain Magloire was kind enough to give his permission to use his version of snprintf.c. diff --git a/Makefile.am b/Makefile.am index 813c2ec05e..245910c5a3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.184 2000/04/15 04:10:27 guy Exp $ +# $Id: Makefile.am,v 1.185 2000/04/15 22:11:07 guy Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs @@ -58,11 +58,15 @@ DISSECTOR_SOURCES = \ packet-cgmp.h \ packet-clip.c \ packet-clip.h \ + packet-clnp.c \ + packet-clnp.h \ packet-data.c \ packet-ddtp.c \ packet-ddtp.h \ packet-dns.c \ packet-dns.h \ + packet-esis.h \ + packet-esis.c \ packet-eth.c \ packet-eth.h \ packet-ethertype.c \ @@ -140,6 +144,8 @@ DISSECTOR_SOURCES = \ packet-null.h \ packet-osi.c \ packet-osi.h \ + packet-osi-options.c \ + packet-osi-options.h \ packet-ospf.c \ packet-ospf.h \ packet-pim.c \ diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template index 896800d88a..0d4615666d 100644 --- a/doc/ethereal.pod.template +++ b/doc/ethereal.pod.template @@ -840,6 +840,7 @@ B. Andreas Sikkema Mark Muhlestein Graham Bloice + Ralf Schneider Alain Magloire was kind enough to give his permission to use his version of snprintf.c. diff --git a/nlpid.h b/nlpid.h index 2ddc5994ae..cec1e25df0 100644 --- a/nlpid.h +++ b/nlpid.h @@ -2,7 +2,7 @@ * Definitions of OSI NLPIDs (Network Layer Protocol IDs) * Laurent Deniel * - * $Id: nlpid.h,v 1.3 2000/01/30 05:50:02 guy Exp $ + * $Id: nlpid.h,v 1.4 2000/04/15 22:11:07 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -36,7 +36,7 @@ #define NLPID_ISO8473_CLNP 0x81 /* X.233 */ #define NLPID_ISO9542_ESIS 0x82 #define NLPID_ISO10589_ISIS 0x83 -#define NLPID_ISO10747 0x85 +#define NLPID_ISO10747_IDRP 0x85 #define NLPID_ISO9542X25_ESIS 0x8a #define NLPID_ISO10030 0x8c #define NLPID_ISO11577 0x8d /* X.273 */ diff --git a/packet-clnp.c b/packet-clnp.c new file mode 100644 index 0000000000..7a7478a428 --- /dev/null +++ b/packet-clnp.c @@ -0,0 +1,1777 @@ +/* packet-clnp.c + * Routines for ISO/OSI network and transport protocol packet disassembly + * + * $Id: packet-clnp.c,v 1.1 2000/04/15 22:11:07 guy Exp $ + * Laurent Deniel + * Ralf Schneider + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * To do: + * + * - add other network protocols (IS-IS) + * - add NSAP decoding & resolution + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#include +#include +#include +#include +#include "packet.h" +#include "packet-osi.h" +#include "packet-osi-options.h" +#include "packet-clnp.h" +#include "packet-isis.h" +#include "packet-esis.h" +#include "packet-h1.h" +#include "nlpid.h" + +/* protocols and fields */ + +static int proto_clnp = -1; +static int proto_cotp = -1; +static gint ett_clnp = -1; +static gint ett_cotp = -1; + +static int hf_clnp_id = -1; +static int hf_clnp_length = -1; +static int hf_clnp_version = -1; +static int hf_clnp_ttl = -1; +static int hf_clnp_type = -1; +static int hf_clnp_pdu_length = -1; +static int hf_clnp_checksum = -1; +static int hf_clnp_dest_length = -1; +static int hf_clnp_dest = -1; +static int hf_clnp_src_length = -1; +static int hf_clnp_src = -1; + + + +/* + * ISO 8473 OSI CLNP definition (see RFC994) + * + * _________________________________ + * | Fixed Part | + * |_________________________________| + * | Address Part | + * |_________________________________| + * | Segmentation Part (optional) | + * |_________________________________| + * | Options Part (optional) | + * |_________________________________| + * | Data (optional) | + * |_________________________________| + */ + +#define ISO8473_V1 0x01 /* CLNP version 1 */ + +/* Fixed part */ + +struct clnp_header { + u_char cnf_proto_id; /* network layer protocol identifier */ + u_char cnf_hdr_len; /* length indicator (octets) */ + u_char cnf_vers; /* version/protocol identifier extension */ + u_char cnf_ttl; /* lifetime (500 milliseconds) */ + u_char cnf_type; /* type code */ + u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */ + u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */ + u_char cnf_cksum_msb; /* checksum high byte */ + u_char cnf_cksum_lsb; /* checksum low byte */ +}; + +#define CNF_TYPE 0x1f +#define CNF_ERR_OK 0x20 +#define CNF_MORE_SEGS 0x40 +#define CNF_SEG_OK 0x80 + +#define DT_NPDU 0x1C +#define MD_NPDU 0x1D +#define ER_NPDU 0x01 +#define ERQ_NPDU 0x1E +#define ERP_NPDU 0x1F + +static const value_string npdu_type_vals[] = { + { DT_NPDU, "DT" }, + { MD_NPDU, "MD" }, + { ER_NPDU, "ER" }, + { ERQ_NPDU, "ERQ" }, + { ERP_NPDU, "ERP" }, + { 0, NULL } +}; + +/* field position */ + +#define P_ADDRESS_PART 9 + +/* Segmentation part */ + +struct clnp_segment { + u_short cng_id; /* data unit identifier */ + u_short cng_off; /* segment offset */ + u_short cng_tot_len; /* total length */ +}; + +/* NSAP selector */ + +#define NSEL_NET 0x00 +#define NSEL_NP 0x20 +#define NSEL_TP 0x21 + +/* + * ISO8073 OSI COTP definition (see RFC905) + */ + +/* don't use specific TPDU types to avoid alignment problems & copy overhead */ + +/* 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 + +/* field position */ + +#define P_LI 0 +#define P_TPDU 1 +#define P_CDT 1 +#define P_DST_REF 2 +#define P_SRC_REF 4 +#define P_TPDU_NR_0_1 2 +#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 +#define P_REASON_IN_DR 6 +#define P_CLASS_OPTION 6 + +/* TPDU length indicator */ + +#define LI_NORMAL_DT_CLASS_01 2 +#define LI_NORMAL_DT_WITH_CHECKSUM 8 +#define LI_NORMAL_DT_WITHOUT_CHECKSUM 4 +#define LI_EXTENDED_DT_WITH_CHECKSUM 11 +#define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7 +#define LI_NORMAL_EA_WITH_CHECKSUM 8 +#define LI_NORMAL_EA_WITHOUT_CHECKSUM 4 +#define LI_EXTENDED_EA_WITH_CHECKSUM 11 +#define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7 +#define LI_NORMAL_RJ 4 +#define LI_EXTENDED_RJ 9 +#define LI_MIN_DR 6 +#define LI_MAX_DC 9 +#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 ) + +/* variant part */ + +#define VP_ACK_TIME 0x85 +#define VP_RES_ERROR 0x86 +#define VP_PRIORITY 0x87 +#define VP_TRANSIT_DEL 0x88 +#define VP_THROUGHPUT 0x89 +#define VP_SEQ_NR 0x8A /* in AK */ +#define VP_REASSIGNMENT 0x8B +#define VP_FLOW_CNTL 0x8C /* in AK */ +#define VP_TPDU_SIZE 0xC0 +#define VP_SRC_TSAP 0xC1 /* in CR/CC */ +#define VP_DST_TSAP 0xC2 +#define VP_CHECKSUM 0xC3 +#define VP_VERSION_NR 0xC4 +#define VP_PROTECTION 0xC5 +#define VP_OPT_SEL 0xC6 +#define VP_PROTO_CLASS 0xC7 + +/* misc */ + +#define EXTRACT_SHORT(p) pntohs(p) +#define EXTRACT_LONG(p) pntohl(p) + +/* global variables */ + +static u_char li, tpdu, cdt; /* common fields */ +static u_short dst_ref; + +/* function definitions */ + +static int osi_decode_DR(const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) +{ + proto_tree *cotp_tree; + proto_item *ti; + u_short src_ref; + u_char reason; + char *str; + + if (li < LI_MIN_DR) + return -1; + + src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]); + reason = pd[offset + P_REASON_IN_DR]; + + switch(reason) { + case (128+0): str = "Normal Disconnect"; break; + case (128+1): str = "Remote transport entity congestion"; break; + case (128+2): str = "Connection negotiation failed"; break; + case (128+3): str = "Duplicate source reference"; break; + case (128+4): str = "Mismatched references"; break; + case (128+5): str = "Protocol error"; break; + case (128+7): str = "Reference overflow"; break; + case (128+8): str = "Connection requestion refused"; break; + case (128+10):str = "Header or parameter length invalid"; break; + case (0): str = "Reason not specified"; break; + case (1): str = "Congestion at TSAP"; break; + case (2): str = "Session entity not attached to TSAP"; break; + case (3): str = "Address unknown"; break; + default: return -1; + /*NOTREACHED*/ + break; + } + + if (check_col(fd, COL_INFO)) + col_append_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x", + src_ref, dst_ref); + + if (tree) { + ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (DR)", tpdu); + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + proto_tree_add_text(cotp_tree, offset + 4, 2, + "Source reference: 0x%04x", src_ref); + proto_tree_add_text(cotp_tree, offset + 6, 1, + "Cause: %s", str); + } + + offset += li + 1; + dissect_data(pd, offset, fd, tree); + + return pi.captured_len; /* we dissected all of the containing PDU */ + +} /* osi_decode_DR */ + +/* Returns TRUE if we called a sub-dissector, FALSE if not. */ +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_item *ti; + u_int tpdu_nr ; + u_short checksum = 0; + u_char code = 0, length = 0; + u_int fragment = 0; + + 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 + return -1; + break; + 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; + 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 + return -1; + break; + 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; + 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; + break; + default : /* bad TPDU */ + return -1; + /*NOTREACHED*/ + break; + } + + if (check_col(fd, COL_INFO)) + col_append_fstr(fd, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x %s", + tpdu_nr, + dst_ref, + (fragment)? "(fragment)" : ""); + + if (tree) { + ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (DT)", tpdu); + + if (li != LI_NORMAL_DT_CLASS_01) + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + + switch (li) { + case LI_NORMAL_DT_WITH_CHECKSUM : + proto_tree_add_text(cotp_tree, offset + 4, 1, + "TPDU number: 0x%02x (%s)", + tpdu_nr, + (fragment)? "fragment":"complete"); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NDT, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NDT + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NDT + 2, length, + "Checksum: 0x%04x", checksum); + break; + case LI_NORMAL_DT_WITHOUT_CHECKSUM : + proto_tree_add_text(cotp_tree, 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, offset + 4, 4, + "TPDU number: 0x%08x (%s)", + tpdu_nr, + (fragment)? "fragment":"complete"); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EDT, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EDT + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EDT + 2, length, + "Checksum: 0x%04x", checksum); + break; + case LI_EXTENDED_DT_WITHOUT_CHECKSUM : + proto_tree_add_text(cotp_tree, 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, offset + 2, 1, + "TPDU number: 0x%02x (%s)", + tpdu_nr, + (fragment)? "fragment":"complete"); + break; + } + } /* tree */ + + offset += li + 1; + if (uses_inactive_subset){ + dissect_h1(pd, offset, fd, tree); + return TRUE; + } + else { + dissect_data(pd, offset, fd, tree); + return FALSE; + } +} /* osi_decode_DT */ + +static int osi_decode_ED(const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) +{ + proto_tree *cotp_tree; + proto_item *ti; + u_int tpdu_nr ; + u_short checksum = 0; + u_char code = 0, length = 0; + + /* ED TPDUs are never fragmented */ + + 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 + 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; + 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; + 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 + 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; + 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; + break; + default : /* bad TPDU */ + return -1; + /*NOTREACHED*/ + break; + } /* li */ + + if (check_col(fd, COL_INFO)) + col_append_fstr(fd, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x", + tpdu_nr, dst_ref); + + if (tree) { + ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (ED)", tpdu); + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + + switch (li) { + case LI_NORMAL_DT_WITH_CHECKSUM : + proto_tree_add_text(cotp_tree, offset + 4, 1, + "TPDU number: 0x%02x", tpdu_nr); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NDT, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NDT + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NDT + 2, length, + "Checksum: 0x%04x", checksum); + break; + case LI_NORMAL_DT_WITHOUT_CHECKSUM : + proto_tree_add_text(cotp_tree, offset + 4, 1, + "TPDU number: 0x%02x", tpdu_nr); + break; + case LI_EXTENDED_DT_WITH_CHECKSUM : + proto_tree_add_text(cotp_tree, offset + 4, 4, + "TPDU number: 0x%02x", tpdu_nr); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EDT, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EDT + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EDT + 2, length, + "Checksum: 0x%04x", checksum); + break; + case LI_EXTENDED_DT_WITHOUT_CHECKSUM : + proto_tree_add_text(cotp_tree, offset + 4, 4, + "TPDU number: 0x%02x", tpdu_nr); + break; + } + } /* tree */ + + offset += li + 1; + dissect_data(pd, offset, fd, tree); + + return pi.captured_len; /* we dissected all of the containing PDU */ + +} /* osi_decode_ED */ + +static int osi_decode_RJ(const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) +{ + proto_tree *cotp_tree; + proto_item *ti; + u_int tpdu_nr ; + u_short credit = 0; + + switch(li) { + case LI_NORMAL_RJ : + tpdu_nr = pd[offset + P_TPDU_NR_234]; + break; + case LI_EXTENDED_RJ : + tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); + credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]); + break; + default : + return -1; + /*NOTREACHED*/ + break; + } + + if (check_col(fd, COL_INFO)) + col_append_fstr(fd, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x", + tpdu_nr, dst_ref); + + if (tree) { + ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (RJ)", tpdu); + if (li == LI_NORMAL_RJ) + proto_tree_add_text(cotp_tree, offset + 1, 1, + "Credit: %u", cdt); + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + if (li == LI_NORMAL_RJ) + proto_tree_add_text(cotp_tree, offset + 4, 1, + "Your TPDU number: 0x%02x", tpdu_nr); + else { + proto_tree_add_text(cotp_tree, offset + 4, 4, + "Your TPDU number: 0x%02x", tpdu_nr); + proto_tree_add_text(cotp_tree, offset + 8, 2, + "Credit: 0x%02x", credit); + } + } + + offset += li + 1; + + return 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; + if (class_option > 4) + return -1; + + if (check_col(fd, COL_INFO)) + col_append_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x", + (tpdu == CR_TPDU) ? "CR" : "CC", + src_ref, + dst_ref); + + if (tree) { + ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (%s)", tpdu, + (tpdu == CR_TPDU) ? "CR" : "CC"); + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + proto_tree_add_text(cotp_tree, offset + 4, 2, + "Source reference: 0x%04x", src_ref); + proto_tree_add_text(cotp_tree, offset + 6, 1, + "Class option: 0x%02x", class_option); + } + + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (src-tsap)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (dst-tsap)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (tpdu-size)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (options)", code); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i + 2, 1, + "Use of network expedited data"); + else + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 2, 1, + "Non use of network expedited data"); + if (c1 & 0x4) + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 2, 1, + "Use of Receipt confirmation"); + else + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i + 2, 1, + "Use 16 bit checksum "); + else + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 2, 1, + "Non-use 16 bit checksum in class 4"); + } + if (c1 & 0x1) + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 2, 1, + "Use of transport expedited data transfer\n"); + else + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (ack time)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (throughput)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 2, 4, + "Target value / calling-called: %u o/s", t1); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 6, 4, + "Minimum / calling-called: %u o/s", t2); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 10, 4, + "Target value / called-calling: %u o/s", t3); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (transit delay)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 2, 2, + "Target value / calling-called: %u ms", s1); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 4, 2, + "Minimum / calling-called: %u ms", s2); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 6, 2, + "Target value / called-calling: %u ms", s3); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (priority)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_CC + i, 1, + "Parameter code: 0x%02x (version)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 2, length, + "Version: %u", c1); + i += length + 2; + break; + + 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, + offset + P_VAR_PART_CC + i + 0, 1, + "Parameter code: 0x%02x", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_CC + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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 */ + +} /* osi_decode_CC */ + +static int osi_decode_DC(const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) +{ + proto_tree *cotp_tree; + proto_item *ti; + u_short src_ref, checksum = 0; + u_char length = 0, code = 0; + + 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, + dst_ref); + + if (tree) { + ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (DC)", tpdu); + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + proto_tree_add_text(cotp_tree, offset + 4, 2, + "Source reference: 0x%04x", src_ref); + if (code) { + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_DC + 0, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_DC + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_DC + 2, 2, + "Checksum: 0x%04x", checksum); + } + } + + offset += li + 1; + + return offset; + +} /* osi_decode_DC */ + +static int osi_decode_AK(const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) +{ + proto_tree *cotp_tree = NULL; + proto_item *ti; + u_int tpdu_nr,i =0, r_lower_window_edge ; + 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)) { + 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, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (AK)", tpdu); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "Credit: %u", cdt); + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + proto_tree_add_text(cotp_tree, offset + 4, 1, + "Your TPDU number: 0x%02x", tpdu_nr); + } + + 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, + offset + P_VAR_PART_NAK + i + 0, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NAK + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_NAK + i + 0, 1, + "Parameter code: 0x%02x (flow control)", + code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NAK + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NAK + i + 2, 4, + "Lower window edge: 0x%08x", + r_lower_window_edge); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NAK + i + 6, 2, + "Sequence number: 0x%04x", + r_seq_nr); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_NAK + i + 0, 1, + "Parameter code: 0x%02x (seq number)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NAK + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_NAK + i + 0, 1, + "Parameter code: 0x%02x (unknown)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_NAK + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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]); + cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]); + + 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, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (AK)", tpdu); + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + proto_tree_add_text(cotp_tree, offset + 4, 4, + "Your TPDU number: 0x%08x", tpdu_nr); + proto_tree_add_text(cotp_tree, offset + 8, 2, + "Credit: 0x%04x", cdt_in_ak); + } + + 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, + offset + P_VAR_PART_EAK + i + 0, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EAK + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_EAK + i + 0, 1, + "Parameter code: 0x%02x (flow control)", + code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EAK + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EAK + i + 2, 4, + "Lower window edge: 0x%08x", + r_lower_window_edge); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EAK + i + 6, 2, + "Sequence number: 0x%04x", + r_seq_nr); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_EAK + i + 0, 1, + "Parameter code: 0x%02x (seq number)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EAK + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + 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, + offset + P_VAR_PART_EAK + i + 0, 1, + "Parameter code: 0x%02x (unknown)", code); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EAK + i + 1, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, + offset + P_VAR_PART_EAK + i + 2, length, + "Parameter value: "); + } + i += length + 2; + break; + } /* code */ + } + + } /* is_LI_NORMAL_AK */ + + offset += li + 1; + + return offset; + +} /* osi_decode_AK */ + +static int osi_decode_EA(const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) +{ + proto_tree *cotp_tree; + proto_item *ti; + u_int tpdu_nr ; + u_short checksum = 0; + u_char code = 0; + u_char length = 0; + + if (li > LI_MAX_EA) + return -1; + + 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) + return -1; + checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]); + break; + case LI_NORMAL_EA_WITHOUT_CHECKSUM : + tpdu_nr = pd[offset + P_TPDU_NR_234]; + 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) + return -1; + checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]); + break; + case LI_EXTENDED_EA_WITHOUT_CHECKSUM : + tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); + break; + default : /* bad TPDU */ + return -1; + /*NOTREACHED*/ + break; + } /* li */ + + if (check_col(fd, COL_INFO)) + col_append_fstr(fd, COL_INFO, + "EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref); + + if (tree) { + ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (EA)", tpdu); + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + + switch (li) { + case LI_NORMAL_EA_WITH_CHECKSUM : + proto_tree_add_text(cotp_tree, offset + 4, 1, + "Your TPDU number: 0x%02x", tpdu_nr); + proto_tree_add_text(cotp_tree, offset + 5, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, offset + 6, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, offset + 7, 2, + "Checksum: 0x%04x", checksum); + break; + case LI_NORMAL_EA_WITHOUT_CHECKSUM : + proto_tree_add_text(cotp_tree, offset + 4, 1, + "Your TPDU number: 0x%02x", tpdu_nr); + break; + case LI_EXTENDED_EA_WITH_CHECKSUM : + proto_tree_add_text(cotp_tree, offset + 4, 4, + "Your TPDU number: 0x%08x", tpdu_nr); + proto_tree_add_text(cotp_tree, offset + 8, 1, + "Parameter code: 0x%02x (checksum)", code); + proto_tree_add_text(cotp_tree, offset + 9, 1, + "Parameter length: %u", length); + proto_tree_add_text(cotp_tree, offset + 10, 2, + "Checksum: 0x%04x", checksum); + break; + case LI_EXTENDED_EA_WITHOUT_CHECKSUM : + proto_tree_add_text(cotp_tree, offset + 4, 4, + "Your TPDU number: 0x%08x", tpdu_nr); + break; + default : + break; + } /* li */ + } /* tree */ + + offset += li + 1; + + return offset; + +} /* osi_decode_EA */ + +static int osi_decode_ER(const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) +{ + proto_tree *cotp_tree; + proto_item *ti; + u_char *str; + + if (li > LI_MAX_ER) + return -1; + + switch(pd[offset + P_REJECT_ER]) { + case 0 : + str = "Reason not specified"; + break; + case 1 : + str = "Invalid parameter code"; + break; + case 2 : + str = "Invalid TPDU type"; + break; + case 3 : + str = "Invalid parameter value"; + break; + default: + return -1; + /*NOTREACHED*/ + break; + } + + if (check_col(fd, COL_INFO)) + col_append_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref); + + if (tree) { + ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); + cotp_tree = proto_item_add_subtree(ti, ett_cotp); + proto_tree_add_text(cotp_tree, offset, 1, + "Length indicator: %u", li); + proto_tree_add_text(cotp_tree, offset + 1, 1, + "TPDU code: 0x%x (ER)", tpdu); + proto_tree_add_text(cotp_tree, offset + 2, 2, + "Destination reference: 0x%04x", dst_ref); + proto_tree_add_text(cotp_tree, offset + 4, 1, + "Reject cause: %s", str); + } + + offset += li + 1; + + return 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, + frame_data *fd, proto_tree *tree, + gboolean uses_inactive_subset) +{ + gboolean first_tpdu = TRUE; + int new_offset; + gboolean found_cotp = FALSE; + gboolean subdissector_found = FALSE; + + /* Initialize the COL_INFO field; each of the TPDUs will have its + information appended. */ + if (check_col(fd, COL_INFO)) + col_add_str(fd, COL_INFO, ""); + + while (IS_DATA_IN_FRAME(offset)) { + if (!first_tpdu) { + if (check_col(fd, COL_INFO)) + col_append_str(fd, COL_INFO, ", "); + } + if ((li = pd[offset + P_LI]) == 0) { + if (check_col(fd, COL_INFO)) + col_append_str(fd, COL_INFO, "Length indicator is zero"); + if (!first_tpdu) + dissect_data(pd, offset, fd, tree); + return found_cotp; + } + 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; + } + + tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F; + cdt = pd[offset + P_CDT] & 0x0F; + dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]); + + switch (tpdu) { + case CC_TPDU : + case CR_TPDU : + new_offset = osi_decode_CC(pd, offset, fd, tree); + break; + case DR_TPDU : + new_offset = osi_decode_DR(pd, offset, fd, tree); + break; + case DT_TPDU : + if (osi_decode_DT(pd, offset, fd, tree, uses_inactive_subset)) + subdissector_found = TRUE; + new_offset = pi.captured_len; /* DT PDUs run to the end of the packet */ + break; + case ED_TPDU : + new_offset = osi_decode_ED(pd, offset, fd, tree); + break; + case RJ_TPDU : + new_offset = osi_decode_RJ(pd, offset, fd, tree); + break; + case DC_TPDU : + new_offset = osi_decode_DC(pd, offset, fd, tree); + break; + case AK_TPDU : + new_offset = osi_decode_AK(pd, offset, fd, tree); + break; + case EA_TPDU : + new_offset = osi_decode_EA(pd, offset, fd, tree); + break; + case ER_TPDU : + new_offset = osi_decode_ER(pd, offset, fd, tree); + break; + default : + if (first_tpdu && check_col(fd, COL_INFO)) + col_append_fstr(fd, COL_INFO, "Unknown TPDU type (0x%x)", tpdu); + new_offset = -1; /* bad PDU type */ + break; + } + + if (new_offset == -1) { /* incorrect TPDU */ + if (!first_tpdu) + dissect_data(pd, offset, fd, tree); + break; + } + + if (first_tpdu) { + /* Well, we found at least one valid COTP PDU, so I guess this + is COTP. */ + if (!subdissector_found && check_col(fd, COL_PROTOCOL)) + col_add_str(fd, COL_PROTOCOL, "COTP"); + found_cotp = TRUE; + } + + offset = new_offset; + first_tpdu = FALSE; + } + return found_cotp; +} /* dissect_cotp_internal */ + +void dissect_cotp(const u_char *pd, int offset, frame_data *fd, + proto_tree *tree) +{ + if (!dissect_cotp_internal(pd, offset, fd, tree, FALSE)) + dissect_data(pd, offset, fd, tree); +} + + +/* + * CLNP part / main entry point +*/ + +void dissect_clnp(const u_char *pd, int offset, frame_data *fd, + proto_tree *tree) +{ + + struct clnp_header clnp; + proto_tree *clnp_tree = NULL; + proto_item *ti; + u_char src_len, dst_len, nsel, opt_len = 0; + u_int first_offset = offset; + char flag_string[6+1]; + char *pdu_type_string; + guint16 segment_length; + guint16 segment_offset = 0; + guint len; + + if (check_col(fd, COL_PROTOCOL)) + col_add_str(fd, COL_PROTOCOL, "CLNP"); + + /* avoid alignment problem */ + memcpy(&clnp, &pd[offset], sizeof(clnp)); + + if (clnp.cnf_proto_id == NLPID_NULL) { + if (check_col(fd, COL_INFO)) + col_add_str(fd, COL_INFO, "Inactive subset"); + if (tree) { + ti = proto_tree_add_item(tree, proto_clnp, offset, 1, NULL); + clnp_tree = proto_item_add_subtree(ti, ett_clnp); + proto_tree_add_uint_format(clnp_tree, hf_clnp_id, offset, 1, + clnp.cnf_proto_id, + "Inactive subset"); + } + dissect_cotp_internal(pd, offset+1, fd, tree, TRUE); + return; + } + + if (!BYTES_ARE_IN_FRAME(offset, sizeof(clnp))) { + dissect_data(pd, offset, fd, tree); + return; + } + + /* return if version not known */ + if (clnp.cnf_vers != ISO8473_V1) { + dissect_data(pd, offset, fd, tree); + return; + } + + /* fixed part decoding */ + opt_len = clnp.cnf_hdr_len; + + segment_length = EXTRACT_SHORT(&clnp.cnf_seglen_msb); + flag_string[0] = '\0'; + if (clnp.cnf_type & CNF_SEG_OK) + strcat(flag_string, "S "); + if (clnp.cnf_type & CNF_MORE_SEGS) + strcat(flag_string, "M "); + if (clnp.cnf_type & CNF_ERR_OK) + strcat(flag_string, "E "); + pdu_type_string = val_to_str(clnp.cnf_type & CNF_TYPE, npdu_type_vals, + "Unknown (0x%02x)"); + if (tree) { + ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL); + clnp_tree = proto_item_add_subtree(ti, ett_clnp); + proto_tree_add_item(clnp_tree, hf_clnp_id, offset, 1, + clnp.cnf_proto_id); + proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1, + clnp.cnf_hdr_len); + proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1, + clnp.cnf_vers); + proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, offset + 3, 1, + clnp.cnf_ttl, + "Holding Time : %u (%u secs)", + clnp.cnf_ttl, clnp.cnf_ttl / 2); + proto_tree_add_uint_format(clnp_tree, hf_clnp_type, offset + 4, 1, + clnp.cnf_type, + "PDU Type : 0x%02x (%s%s)", + clnp.cnf_type, + flag_string, + pdu_type_string); + proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2, + segment_length); + proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, offset + 7, 2, + EXTRACT_SHORT(&clnp.cnf_cksum_msb), + "Checksum : 0x%04x", + EXTRACT_SHORT(&clnp.cnf_cksum_msb)); + opt_len -= 9; /* Fixed part of Hesder */ + } /* tree */ + + /* stop here if header is not complete */ + + if (!BYTES_ARE_IN_FRAME(offset, clnp.cnf_hdr_len)) { + if (check_col(fd, COL_INFO)) + col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); + dissect_data(pd, offset, fd, tree); + return; + } + + /* address part */ + + offset += P_ADDRESS_PART; + dst_len = pd[offset]; + nsel = pd[offset + dst_len]; + src_len = pd[offset + dst_len + 1]; + + if (tree) { + proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1, + dst_len); + proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len, + &pd[offset + 1], + " DA : %s", + print_nsap_net(&pd[offset + 1], dst_len)); + proto_tree_add_item(clnp_tree, hf_clnp_src_length, + offset + 1 + dst_len, 1, src_len); + proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, + offset + dst_len + 2, src_len, + &pd[offset + dst_len + 2], + " SA : %s", + print_nsap_net(&pd[offset + dst_len + 2], src_len)); + + opt_len -= dst_len + src_len +2; + } + + if (check_col(fd, COL_RES_NET_SRC)) + col_add_fstr(fd, COL_RES_NET_SRC, "%s", + print_nsap_net(&pd[offset + dst_len + 2], src_len)); + if (check_col(fd, COL_RES_NET_DST)) + col_add_fstr(fd, COL_RES_NET_DST, "%s", + print_nsap_net(&pd[offset + 1], dst_len)); + + /* Segmentation Part */ + + offset += dst_len + src_len + 2; + + if (clnp.cnf_type & CNF_SEG_OK) { + struct clnp_segment seg; /* XXX - not used */ + memcpy(&seg, &pd[offset], sizeof(seg)); /* XXX - not used */ + + segment_offset = EXTRACT_SHORT(&pd[offset + 2]); + if (tree) { + proto_tree_add_text(clnp_tree, offset, 2, + "Data unit identifier: %06u", + EXTRACT_SHORT(&pd[offset])); + proto_tree_add_text(clnp_tree, offset + 2 , 2, + "Segment offset : %6u", + segment_offset); + proto_tree_add_text(clnp_tree, offset + 4 , 2, + "Total length : %6u", + EXTRACT_SHORT(&pd[offset + 4])); + } + + offset += 6; + opt_len -= 6; + } + + if (tree) { + /* To do : decode options */ +/* + proto_tree_add_text(clnp_tree, offset, + clnp.cnf_hdr_len + first_offset - offset, + "Options/Data: "); +*/ +/* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/ + + dissect_osi_options( 0xff, + opt_len, + pd, offset, fd, clnp_tree ); + } + + /* Length of CLNP datagram plus headers above it. */ + len = segment_length + first_offset; + + /* Set the payload and captured-payload lengths to the minima of (the + datagram length plus the length of the headers above it) and the + frame lengths. */ + if (pi.len > len) + pi.len = len; + if (pi.captured_len > len) + pi.captured_len = len; + + offset = first_offset + clnp.cnf_hdr_len; + + /* For now, dissect the payload of segments other than the initial + segment as data, rather than handing them off to the transport + protocol, just as we do with fragments other than the first + fragment in a fragmented IP datagram; in the future, we will + probably reassemble fragments for IP, and may reassemble segments + for CLNP. */ + if ((clnp.cnf_type & CNF_SEG_OK) && segment_offset != 0) { + if (check_col(fd, COL_INFO)) + col_add_fstr(fd, COL_INFO, "Fragmented %s NPDU %s(off=%u)", + pdu_type_string, flag_string, segment_offset); + dissect_data(pd, offset, fd, tree); + return; + } + + if (IS_DATA_IN_FRAME(offset)) { + switch (clnp.cnf_type & CNF_TYPE) { + + case DT_NPDU: + case MD_NPDU: + /* Continue with COTP if any data. + XXX - if this isn't the first Derived PDU of a segmented Initial + 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 */ + } + break; + + case ER_NPDU: + /* The payload is the header and "none, some, or all of the data + part of the discarded PDU", i.e. it's like an ICMP error; + just as we don't yet trust ourselves to be able to dissect + the payload of an ICMP error packet, we don't yet trust + ourselves to dissect the payload of a CLNP ER packet. */ + break; + + case ERQ_NPDU: + case ERP_NPDU: + /* XXX - dissect this */ + break; + } + } + if (check_col(fd, COL_INFO)) + col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); + dissect_data(pd, offset, fd, tree); + +} /* dissect_clnp */ + + +void proto_register_clnp(void) +{ + static hf_register_info hf[] = { + { &hf_clnp_id, + { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX, + VALS(nlpid_vals), 0x0, "" }}, + + { &hf_clnp_length, + { "HDR Length ", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + + { &hf_clnp_version, + { "Version ", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + + { &hf_clnp_ttl, + { "Holding Time ", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + + { &hf_clnp_type, + { "PDU Type ", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + + { &hf_clnp_pdu_length, + { "PDU length ", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, "" }}, + + { &hf_clnp_checksum, + { "Checksum ", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, "" }}, + + { &hf_clnp_dest_length, + { "DAL ", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + + { &hf_clnp_dest, + { " DA ", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }}, + + { &hf_clnp_src_length, + { "SAL ", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + + { &hf_clnp_src, + { " SA ", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, "" }}, + }; + static gint *ett[] = { + &ett_clnp, + }; + + proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "clnp"); + proto_register_field_array(proto_clnp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + +void proto_register_cotp(void) +{ + /* static hf_register_info hf[] = { + { &variable, + { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }}, + };*/ + static gint *ett[] = { + &ett_cotp, + }; + + proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "cotp"); + /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/ + proto_register_subtree_array(ett, array_length(ett)); +} diff --git a/packet-clnp.h b/packet-clnp.h new file mode 100644 index 0000000000..9d76fd0ff3 --- /dev/null +++ b/packet-clnp.h @@ -0,0 +1,41 @@ +/* packet-clnp.h + * Defines and such for CLNP (and COTP) protocol decode. + * + * $Id: packet-clnp.h,v 1.1 2000/04/15 22:11:08 guy Exp $ + * Ralf Schneider + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + */ + +#ifndef _PACKET_CLNP_H +#define _PACKET_CLNP_H + +/* + * published API functions + */ + +extern +void dissect_clnp( const u_char *, int, frame_data *, proto_tree * ); +extern +void dissect_cotp(const u_char *, int, frame_data *, proto_tree *); + +#endif /* _PACKET_CLNP_H */ diff --git a/packet-esis.c b/packet-esis.c new file mode 100644 index 0000000000..8186990714 --- /dev/null +++ b/packet-esis.c @@ -0,0 +1,438 @@ +/* packet-esis.c + * Routines for ISO/OSI End System to Intermediate System + * Routeing Exchange Protocol ISO 9542. + * + * $Id: packet-esis.c,v 1.1 2000/04/15 22:11:08 guy Exp $ + * Ralf Schneider + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#include +#include +#include +#include "packet.h" +#include "nlpid.h" +#include "packet-osi.h" +#include "packet-osi-options.h" +#include "packet-esis.h" + + +/* esis base header */ +static int proto_esis = -1; + +static int hf_esis_nlpi = -1; +static int hf_esis_length = -1; +static int hf_esis_version = -1; +static int hf_esis_reserved = -1; +static int hf_esis_type = -1; +static int hf_esis_holdtime = -1; +static int hf_esis_checksum = -1; + +static gint ett_esis = -1; +static gint ett_esis_area_addr = -1; + +static const value_string esis_vals[] = { + { ESIS_ESH_PDU, "ES HELLO"}, + { ESIS_ISH_PDU, "IS HELLO"}, + { ESIS_RD_PDU, "RD REQUEST"}, + { 0, NULL} }; + +/* internal prototypes */ + +void esis_dissect_esh_pdu( u_char len, const u_char *pd, int offset, + frame_data *fd, proto_tree *treepd); +void esis_dissect_ish_pdu( u_char len, const u_char *pd, int offset, + frame_data *fd, proto_tree *tree); +void esis_dissect_redirect_pdu( u_char len, const u_char *pd, int offset, + frame_data *fd, proto_tree *tree); + +/* ################## Descriptions ###########################################*/ +/* Parameters for the ESH PDU + * Source Address Parameter: + * + * Octet: Length: Parameter Type: + * 10 1 Number of Source Adresses ( NSAPs served by this Network + * 11 1 Source Address Length Indicator ( SAL ) # Entity ) + * 12-m-1 variable Source Address ( NSAP ) + * m Options, dissected in osi.c + * + * + * Parameter for the ISH PDU: + * Network Entity Title Parameter: + * + * Octet: Length: Parameter Type: + * 10 1 Network Entity Title Length Indicator ( NETL ) + * 11-m-1 variable Network Entity Title ( NET ) + * m Options, dissected in osi.c + * + * + * Parameter for the RD PDU: + * When re-directed to an IS: + * + * Octet: Length: Parameter Type: + * 10 1 Destination Address Length Indicator ( DAL ) + * 11>m-1 variable Destination Address ( DA ) + * m 1 Subnetwork Address Length Indicator ( BSNPAL ) + * m+1>n-1 variable Subnetwork Address ( BSNPA ) + * n 1 Network Entity Title Length Indicator ( NETL ) + * n+1>p-1 variable Network Entity Title ( NET ) + * p Options, dissected in osi.c + * + * + * Parameter for the RD PDU: + * When re-directed to an ES: + * + * Octet: Length: Parameter Type: + * 10 1 Destination Address Length Indicator ( DAL ) + * 11>m-1 variable Destination Address ( DA ) + * m 1 Subnetwork Address Length Indicator ( BSNPAL ) + * m+1>n-1 variable Subnetwork Address ( BSNPA ) + * n 1 Network Entity Title Length Indicator ( NETL ) == 0 + * n+1 Options, dissected in osi.c + * + */ + +/* ############################ Tool Functions ############################## */ + + +/* ############################## Dissection Functions ###################### */ +/* + * Name: dissect_esis_unknown() + * + * Description: + * There was some error in the protocol and we are in unknown space + * here. Add a tree item to cover the error and go on. Note + * that we make sure we don't go off the end of the bleedin packet here! + * + * This is just a copy of isis.c and isis.h, so I keep the stuff also + * and adapt the names to cover possible protocol errors! Ive really no + * idea wether I need this or not. + * + * Input + * int offset : Current offset into packet data. + * int len : length of to dump. + * proto_tree * : tree of display data. May be NULL. + * frame_data * fd : frame data + * char * : format text + * + * Output: + * void (may modify proto tree) + */ +void +esis_dissect_unknown(int offset,guint length,proto_tree *tree,frame_data *fd, + char *fmat, ...){ + va_list ap; + + if ( !IS_DATA_IN_FRAME(offset) ) { + /* + * big oops They were off the end of the packet already. + * Just ignore this one. + */ + return; + } + if ( !BYTES_ARE_IN_FRAME(offset, length) ) { + /* + * length will take us past eop. Truncate length. + */ + length = END_OF_FRAME; + } + + va_start(ap, fmat); + proto_tree_add_text(tree, offset, length, fmat, ap); + va_end(ap); +} + + +void +esis_dissect_esh_pdu( u_char len, const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) { + proto_tree *esis_area_tree; + int no_sa = 0; + int sal = 0; + + proto_item *ti; + + if (tree) { + offset += ESIS_HDR_FIXED_LENGTH; + + no_sa = pd[offset]; + len -= 1; + + ti = proto_tree_add_text( tree, offset++, END_OF_FRAME, + "Number of Source Addresses (SA, Format: NSAP) : %u", no_sa ); + + esis_area_tree = proto_item_add_subtree( ti, ett_esis_area_addr ); + while ( no_sa-- > 0 ) { + sal = (int) pd[offset++]; + proto_tree_add_text(esis_area_tree, offset, 1, "SAL: %2u Octets", sal); + proto_tree_add_text(esis_area_tree, offset + 1, sal, + " SA: %s", print_nsap_net( &pd[offset], sal ) ); + offset += sal; + len -= ( sal + 1 ); + } + dissect_osi_options( PDU_TYPE_ESIS_ESH, len, pd, offset, fd, tree ); + } +} /* esis_dissect_esh_pdu */ ; + +void +esis_dissect_ish_pdu( u_char len, const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) { + + int netl = 0; + + if (tree) { + offset += ESIS_HDR_FIXED_LENGTH; + + netl = (int) pd[ offset ]; + proto_tree_add_text( tree, offset, netl + 1, + "### Network Entity Titel Section ###"); + proto_tree_add_text( tree, offset++, 1, "NETL: %2u Octets", netl); + proto_tree_add_text( tree, offset, netl, + " NET: %s", print_nsap_net( &pd[offset], netl ) ); + offset += netl; + len -= ( netl + 1 ); + + dissect_osi_options( PDU_TYPE_ESIS_ISH, len, pd, offset, fd, tree ); + } +}; + +void +esis_dissect_redirect_pdu( u_char len, const u_char *pd, int offset, + frame_data *fd, proto_tree *tree) { + + int tmpl = 0; + + if (tree) { + offset += ESIS_HDR_FIXED_LENGTH; + + tmpl = (int) pd[ offset ]; + proto_tree_add_text( tree, offset, tmpl + 1, + "### Destination Address Section ###" ); + proto_tree_add_text( tree, offset++, 1, "DAL: %2u Octets", tmpl); + proto_tree_add_text( tree, offset, tmpl, + " DA : %s", print_nsap_net( &pd[offset], tmpl ) ); + offset += tmpl; + len -= ( tmpl + 1 ); + tmpl = (int) pd[ offset ]; + + proto_tree_add_text( tree, offset, tmpl + 1, + "### Subnetwork Address Section ###"); + proto_tree_add_text( tree, offset++, 1, "BSNPAL: %2u Octets", tmpl); + proto_tree_add_text( tree, offset, tmpl, + " BSNPA: %s", print_system_id( &pd[offset], tmpl ) ); + offset += tmpl; + len -= ( tmpl + 1 ); + tmpl = (int) pd[ offset ]; + + if ( 0 == tmpl ) { + proto_tree_add_text( tree, offset, 1, + "### No Network Entity Title Section ###" ); + offset++; + len--; + } + else { + proto_tree_add_text( tree, offset, 1, + "### Network Entity Title Section ###" ); + proto_tree_add_text( tree, offset++, 1, "NETL: %2u Octets", tmpl ); + proto_tree_add_text( tree, offset, tmpl, + " NET: %s", print_nsap_net( &pd[offset], tmpl ) ); + offset += tmpl; + len -= ( tmpl + 1 ); + } + dissect_osi_options( PDU_TYPE_ESIS_RD, len, pd, offset, fd, tree ); + } +} + + +/* + * Name: dissect_esis() + * + * Description: + * Main entry area for esis de-mangling. This will build the + * main esis tree data and call the sub-protocols as needed. + * + * Input: + * u_char * : packet data + * int : offset into packet where we are (packet_data[offset]== start + * of what we care about) + * frame_data * : frame data (whole packet with extra info) + * proto_tree * : tree of display data. May be NULL. + * + * Output: + * void, but we will add to the proto_tree if it is not NULL. + */ +void +dissect_esis(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { + char *pdu_type_string = NULL; + char *pdu_type_format_string = "PDU Type : %s (R:%s%s%s)"; + esis_hdr_t *ehdr; + proto_item *ti; + proto_tree *esis_tree = NULL; + int variable_len = 0; + u_int tmp_uint = 0; + + if (check_col(fd, COL_PROTOCOL)) + col_add_str(fd, COL_PROTOCOL, "ESIS"); + + if (!BYTES_ARE_IN_FRAME(offset, sizeof(*ehdr))) { + esis_dissect_unknown(offset, sizeof(*ehdr), tree, fd, + "Not enough capture data for header (%d vs %d)", + sizeof(*ehdr), END_OF_FRAME); + return; + } + + ehdr = (esis_hdr_t *) &pd[offset]; + + if (ehdr->esis_version != ESIS_REQUIRED_VERSION){ + esis_dissect_unknown(offset, END_OF_FRAME, tree, fd, + "Unknown ESIS version (%d vs %d)", + ehdr->esis_version, ESIS_REQUIRED_VERSION ); + return; + } + + if (tree) { + ti = proto_tree_add_item(tree, proto_esis, offset, END_OF_FRAME, NULL ); + esis_tree = proto_item_add_subtree(ti, ett_esis); + + proto_tree_add_item( esis_tree, hf_esis_nlpi, offset, 1, ehdr->esis_nlpi ); + proto_tree_add_item( esis_tree, hf_esis_length, + offset + 1, 1, ehdr->esis_length ); + proto_tree_add_item( esis_tree, hf_esis_version, offset + 2, 1, + ehdr->esis_version ); + proto_tree_add_item( esis_tree, hf_esis_reserved, offset + 3, 1, + ehdr->esis_reserved ); + + pdu_type_string = val_to_str(ehdr->esis_type&OSI_PDU_TYPE_MASK, + esis_vals, "Unknown (0x%x)"); + + proto_tree_add_uint_format( esis_tree, hf_esis_type, offset + 4, 1, + ehdr->esis_type, + pdu_type_format_string, + pdu_type_string, + (ehdr->esis_type&BIT_8) ? "1" : "0", + (ehdr->esis_type&BIT_7) ? "1" : "0", + (ehdr->esis_type&BIT_6) ? "1" : "0"); + + tmp_uint = pntohs( ehdr->esis_holdtime ); + proto_tree_add_uint_format(esis_tree, hf_esis_holdtime, offset + 5, 2, + tmp_uint, "Holding Time : %u seconds", + tmp_uint ); + + tmp_uint = pntohs( ehdr->esis_checksum ); + + proto_tree_add_uint_format( esis_tree, hf_esis_checksum, offset + 7, 2, + tmp_uint, "Checksum : 0x%x ( %s )", + tmp_uint, calc_checksum( &pd[offset], + ehdr->esis_length , + tmp_uint ) ); + } + + + /* + * Let us make sure we use the same names for all our decodes + * here. First, dump the name into info column, and THEN + * dispatch the sub-type. + */ + if (check_col(fd, COL_INFO)) { + col_add_str(fd, COL_INFO, + val_to_str( ehdr->esis_type&OSI_PDU_TYPE_MASK, esis_vals, + "Unknown (0x%x)" ) ); + } + + variable_len = ehdr->esis_length - ESIS_HDR_FIXED_LENGTH; + + switch (ehdr->esis_type) { + case ESIS_ESH_PDU: + esis_dissect_esh_pdu( variable_len, pd, offset, fd, esis_tree); + break; + case ESIS_ISH_PDU: + esis_dissect_ish_pdu( variable_len, pd, offset, fd, esis_tree); + break; + case ESIS_RD_PDU: + esis_dissect_redirect_pdu( variable_len, pd, offset, fd, + esis_tree); + break; + default: + esis_dissect_unknown(offset, END_OF_FRAME, tree, fd, + "unknown esis packet type" ); + } +} /* dissect_esis */ + + +/* + * Name: proto_register_esisesis() + * + * Description: + * main register for esis protocol set. We register some display + * formats and the protocol module variables. + * + * NOTE: this procedure to autolinked by the makefile process that + * builds register.c + * + * Input: + * void + * + * Output: + * void + */ +void +proto_register_esis(void) { + static hf_register_info hf[] = { + { &hf_esis_nlpi, + { "Network Layer Protocol Identifier", "esis.nlpi", + FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "" }}, + { &hf_esis_length, + { "PDU Length ", "esis.length", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + { &hf_esis_version, + { "Version (==1) ", "esis.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + { &hf_esis_reserved, + { "Reserved(==0) ", "esis.res", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + { &hf_esis_type, + { "PDU Type ", "esis.type", FT_UINT8, BASE_DEC, VALS(esis_vals), + 0xff, "" }}, + { &hf_esis_holdtime, + { "Holding Time ", "esis.htime", FT_UINT16, BASE_DEC, NULL, 0x0, " s"}}, + { &hf_esis_checksum, + { "Checksum ", "esis.chksum", FT_UINT16, BASE_HEX, NULL, 0x0, "" }} + }; + /* + * + * + */ + static gint *ett[] = { + &ett_esis, + &ett_esis_area_addr, + }; + + proto_esis = proto_register_protocol( PROTO_STRING_ESIS, "esis"); + proto_register_field_array(proto_esis, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +}; diff --git a/packet-esis.h b/packet-esis.h new file mode 100644 index 0000000000..c6e49b24a7 --- /dev/null +++ b/packet-esis.h @@ -0,0 +1,69 @@ +/* packet-esis.h + * Defines and such for ESIS protocol decode. + * + * $Id: packet-esis.h,v 1.1 2000/04/15 22:11:09 guy Exp $ + * Ralf Schneider + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + */ + +#ifndef _PACKET_ESIS_H +#define _PACKET_ESIS_H + +/* The version we support is 1 */ +#define ESIS_REQUIRED_VERSION 1 + +/* ESIS PDU types */ +#define ESIS_ESH_PDU 02 +#define ESIS_ISH_PDU 04 +#define ESIS_RD_PDU 06 + +/* The length of the fixed part */ +#define ESIS_HDR_FIXED_LENGTH 9 + +/* Inline Defines for masking */ +#define esis_type esis_type_reserved&OSI_PDU_TYPE_MASK +#define esis_r8 esis_type_reserved&BIT_8 +#define esis_r7 esis_type_reserved&BIT_7 +#define esis_r6 esis_type_reserved&BIT_6 + +/* The fixed part (9 octets) of the ESIS protocol header */ +typedef struct { + guint8 esis_nlpi; /* Network Layer Protocol Identifier == 0x82 */ + guint8 esis_length; /* Header ( PDU too, NoData ) length in octets */ + guint8 esis_version; /* ISIS version, must be 0x01 */ + guint8 esis_reserved; /* reserved byte, must be 0 */ + guint8 esis_type_reserved; /* packet type & MS-Bits (8-6) reserved */ + guint8 esis_holdtime[2]; /* Maximum time (sec) this PDU is valid */ + guint8 esis_checksum[2]; /* Computed on whole PDU Header, 0 means ignore */ +} esis_hdr_t; + +/* + * published API functions + */ +extern void dissect_esis(const u_char *pd, int offset, frame_data *fd, + proto_tree *tree); +extern void proto_register_esis(void); +extern void esis_dissect_unknown(int offset,guint length, proto_tree *tree, + frame_data *fd, char *fmat, ...); + +#endif /* _PACKET_ESIS_H */ diff --git a/packet-isis-clv.c b/packet-isis-clv.c index 8cbfc6f539..1de98279c9 100644 --- a/packet-isis-clv.c +++ b/packet-isis-clv.c @@ -1,7 +1,7 @@ /* packet-isis-clv.c * Common CLV decode routines. * - * $Id: packet-isis-clv.c,v 1.2 1999/12/15 22:52:04 guy Exp $ + * $Id: packet-isis-clv.c,v 1.3 2000/04/15 22:11:09 guy Exp $ * Stuart Stanley * * Ethereal - Network traffic analyzer @@ -47,6 +47,7 @@ #include #include #include "packet.h" +#include "packet-osi.h" #include "packet-isis.h" #include "packet-isis-clv.h" @@ -93,7 +94,8 @@ isis_dissect_area_address_clv(const u_char *pd, int offset, * Lets turn the area address into "standard" 0000.0000.etc * format string. */ - sbuf = isis_address_to_string ( pd, offset + 1, mylen ); +/* sbuf = isis_address_to_string ( pd, offset + 1, mylen );*/ + sbuf = print_nsap_net( pd + offset + 1, mylen ); /* and spit it out */ if ( tree ) { proto_tree_add_text ( tree, offset, mylen + 1, diff --git a/packet-isis-hello.c b/packet-isis-hello.c index a9ae715ffe..3c53125469 100644 --- a/packet-isis-hello.c +++ b/packet-isis-hello.c @@ -1,7 +1,7 @@ /* packet-isis-hello.c * Routines for decoding isis hello packets and their CLVs * - * $Id: packet-isis-hello.c,v 1.5 2000/03/28 06:12:15 guy Exp $ + * $Id: packet-isis-hello.c,v 1.6 2000/04/15 22:11:09 guy Exp $ * Stuart Stanley * * Ethereal - Network traffic analyzer @@ -38,28 +38,29 @@ #include #include #include "packet.h" +#include "packet-osi.h" #include "packet-isis.h" #include "packet-isis-clv.h" #include "packet-isis-hello.h" /* hello packets */ -static int proto_isis_hello = -1; -static int hf_isis_hello_circuit_reserved = -1; -static int hf_isis_hello_source_id = -1; -static int hf_isis_hello_holding_timer = -1; -static int hf_isis_hello_pdu_length = -1; -static int hf_isis_hello_priority_reserved = -1; -static int hf_isis_hello_lan_id = -1; -static int hf_isis_hello_local_circuit_id = -1; -static int hf_isis_hello_clv_ipv4_int_addr = -1; +static int proto_isis_hello = -1; +static int hf_isis_hello_circuit_reserved = -1; +static int hf_isis_hello_source_id = -1; +static int hf_isis_hello_holding_timer = -1; +static int hf_isis_hello_pdu_length = -1; +static int hf_isis_hello_priority_reserved = -1; +static int hf_isis_hello_lan_id = -1; +static int hf_isis_hello_local_circuit_id = -1; +static int hf_isis_hello_clv_ipv4_int_addr = -1; -static gint ett_isis_hello = -1; -static gint ett_isis_hello_clv_area_addr = -1; -static gint ett_isis_hello_clv_is_neighbors = -1; -static gint ett_isis_hello_clv_padding = -1; -static gint ett_isis_hello_clv_unknown = -1; -static gint ett_isis_hello_clv_nlpid = -1; -static gint ett_isis_hello_clv_auth = -1; +static gint ett_isis_hello = -1; +static gint ett_isis_hello_clv_area_addr = -1; +static gint ett_isis_hello_clv_is_neighbors = -1; +static gint ett_isis_hello_clv_padding = -1; +static gint ett_isis_hello_clv_unknown = -1; +static gint ett_isis_hello_clv_nlpid = -1; +static gint ett_isis_hello_clv_auth = -1; static gint ett_isis_hello_clv_ipv4_int_addr = -1; static const value_string isis_hello_circuit_type_vals[] = { @@ -360,9 +361,7 @@ dissect_hello_is_neighbors_clv(const u_char *pd, int offset, */ if ( tree ) { proto_tree_add_text ( tree, offset, 6, - "IS Neighbor: %02x%02x.%02x%02x.%02x%02x", - pd[offset], pd[offset+1], pd[offset+2], - pd[offset+3], pd[offset+4], pd[offset+5] ); + "IS Neighbor: %s", print_system_id( pd + offset, 6 ) ); } offset += 6; length -= 6; @@ -443,7 +442,7 @@ isis_dissect_isis_hello(int hello_type, int header_length, proto_tree_add_uint_format(hello_tree, hf_isis_hello_circuit_reserved, offset, 1, ihp->isis_hello_circuit_reserved, - "Circuit type: %s, reserved(0x%02x == 0)", + "Circuit type : %s, reserved(0x%02x == 0)", val_to_str(ihp->isis_hello_circuit, isis_hello_circuit_type_vals, "Unknown (0x%x)"), @@ -451,40 +450,25 @@ isis_dissect_isis_hello(int hello_type, int header_length, ); proto_tree_add_string_format(hello_tree, hf_isis_hello_lan_id, - offset + 1, 6, ihp->isis_hello_source_id, - "Lan ID: %02x%02x.%02x%02x.%02x%02x", - ihp->isis_hello_lan_id[0], - ihp->isis_hello_lan_id[1], - ihp->isis_hello_lan_id[2], - ihp->isis_hello_lan_id[3], - ihp->isis_hello_lan_id[4], - ihp->isis_hello_lan_id[5]); + offset + 1, 6, ihp->isis_hello_source_id, + "SystemID{ Sender of PDU } : %s", + print_system_id( pd + offset + 1, 6 ) ); proto_tree_add_item(hello_tree, hf_isis_hello_holding_timer, - offset + 7, 2,pntohs(&ihp->isis_hello_holding_timer[0])); + offset + 7, 2,pntohs(&ihp->isis_hello_holding_timer[0])); proto_tree_add_item(hello_tree, hf_isis_hello_pdu_length, - offset + 9, 2,pntohs(&ihp->isis_hello_pdu_length[0])); - proto_tree_add_uint_format(hello_tree, - hf_isis_hello_priority_reserved, - offset + 11, 1, ihp->isis_hello_priority_reserved, - "Priority: %d, reserved(0x%02x == 0)", - ihp->isis_hello_priority, - ihp->isis_hello_preserved ); + offset + 9, 2,pntohs(&ihp->isis_hello_pdu_length[0])); + proto_tree_add_uint_format(hello_tree, hf_isis_hello_priority_reserved, + offset + 11, 1, ihp->isis_hello_priority_reserved, + "Priority : %d, reserved(0x%02x == 0)", + ihp->isis_hello_priority, ihp->isis_hello_preserved ); if (hello_type == ISIS_TYPE_PTP_HELLO) { - proto_tree_add_item(hello_tree, - hf_isis_hello_local_circuit_id, - offset + 12, 1, ihp->isis_hello_lan_id[0] ); + proto_tree_add_item(hello_tree, hf_isis_hello_local_circuit_id, + offset + 12, 1, ihp->isis_hello_lan_id[0] ); } else { - proto_tree_add_string_format(hello_tree, - hf_isis_hello_lan_id, offset + 12, 7, - ihp->isis_hello_lan_id, - "Lan ID: %02x%02x.%02x%02x.%02x%02x-%02d", - ihp->isis_hello_lan_id[0], - ihp->isis_hello_lan_id[1], - ihp->isis_hello_lan_id[2], - ihp->isis_hello_lan_id[3], - ihp->isis_hello_lan_id[4], - ihp->isis_hello_lan_id[5], - ihp->isis_hello_lan_id[6]); + proto_tree_add_string_format(hello_tree, hf_isis_hello_lan_id, + offset + 12, 7, ihp->isis_hello_lan_id, + "SystemID{ Designated IS } : %s", + print_system_id( pd + offset + 12, 7 ) ); } } @@ -531,34 +515,35 @@ void proto_register_isis_hello(void) { static hf_register_info hf[] = { { &hf_isis_hello_circuit_reserved, - { "Circuit type", "isis_hello.circuite_type", + { "Circuit type ", "isis_hello.circuite_type", FT_UINT8, BASE_HEX, NULL, 0x0, "" }}, { &hf_isis_hello_source_id, - { "Source ID", "isis_hello.source_id", + { "SystemID{ Sender of PDU } ", "isis_hello.source_id", FT_ETHER, BASE_HEX, NULL, 0x0, "" }}, { &hf_isis_hello_holding_timer, - { "Holding timer", "isis_hello.holding_timer", + { "Holding timer ", "isis_hello.holding_timer", FT_UINT16, BASE_DEC, NULL, 0x0, "" }}, { &hf_isis_hello_pdu_length, - { "PDU length", "isis_hello.pdu_length", + { "PDU length ", "isis_hello.pdu_length", FT_UINT16, BASE_DEC, NULL, 0x0, "" }}, { &hf_isis_hello_priority_reserved, - { "Priority", "isis_hello.priority",FT_UINT8, BASE_DEC, NULL, - ISIS_HELLO_P_RESERVED_MASK, "" }}, + { "Priority ", "isis_hello.priority",FT_UINT8, BASE_DEC, NULL, + ISIS_HELLO_P_RESERVED_MASK, "" }}, { &hf_isis_hello_lan_id, - { "LAN ID", "isis_hello.lan_id", FT_STRING, BASE_DEC, NULL, 0x0, "" }}, + { "SystemID{ Designated IS } ", "isis_hello.lan_id", FT_STRING, BASE_DEC, NULL, + 0x0, "" }}, { &hf_isis_hello_local_circuit_id, - { "Local circuit ID", "isis_hello.local_circuit_id", FT_UINT8, + { "Local circuit ID ", "isis_hello.local_circuit_id", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, { &hf_isis_hello_clv_ipv4_int_addr, - { "IPv4 interface address", "isis_hello.clv_ipv4_int_addr", FT_IPv4, + { "IPv4 interface address ", "isis_hello.clv_ipv4_int_addr", FT_IPv4, BASE_NONE, NULL, 0x0, "" }}, }; @@ -573,7 +558,7 @@ proto_register_isis_hello(void) { &ett_isis_hello_clv_ipv4_int_addr, }; - proto_isis_hello = proto_register_protocol("ISIS hello", "isis_hello"); + proto_isis_hello = proto_register_protocol("ISIS HELLO", "isis_hello"); proto_register_field_array(proto_isis_hello, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } diff --git a/packet-isis-lsp.c b/packet-isis-lsp.c index ef8793ace4..296123d7f0 100644 --- a/packet-isis-lsp.c +++ b/packet-isis-lsp.c @@ -1,7 +1,7 @@ /* packet-isis-lsp.c * Routines for decoding isis lsp packets and their CLVs * - * $Id: packet-isis-lsp.c,v 1.4 2000/03/20 22:52:42 gram Exp $ + * $Id: packet-isis-lsp.c,v 1.5 2000/04/15 22:11:09 guy Exp $ * Stuart Stanley * * Ethereal - Network traffic analyzer @@ -43,6 +43,7 @@ #endif #include "packet.h" +#include "packet-osi.h" #include "packet-isis.h" #include "packet-isis-clv.h" #include "packet-isis-lsp.h" @@ -515,17 +516,12 @@ dissect_lsp_eis_neighbors_clv_inner(const u_char *pd, int offset, if ( tree ) { if ( is_eis ) { ti = proto_tree_add_text ( tree, offset, 11, - "ES Neighbor: %02x%02x.%02x%02x.%02x%02x", - pd[offset+4], pd[offset+5], - pd[offset+6], pd[offset+7], - pd[offset+8], pd[offset+9] ); + "ES Neighbor: %s", + print_system_id( pd + offset + 4, 6 ) ); } else { ti = proto_tree_add_text ( tree, offset, 11, - "IS Neighbor: %02x%02x.%02x%02x.%02x%02x-%02x", - pd[offset+4], pd[offset+5], - pd[offset+6], pd[offset+7], - pd[offset+8], pd[offset+9], - pd[offset+10] ); + "IS Neighbor: %s", + print_system_id( pd + offset + 4, 6 ) ); } ntree = proto_item_add_subtree(ti, ett_isis_lsp_clv_is_neighbors); @@ -648,9 +644,8 @@ dissect_lsp_partition_dis_clv(const u_char *pd, int offset, */ if ( tree ) { proto_tree_add_text ( tree, offset+4, 6, - "Partition designated L2 IS: %02x%02x.%02x%02x.%02x%02x", - pd[offset], pd[offset+1], pd[offset+2], - pd[offset+3], pd[offset+4], pd[offset+5]); + "Partition designated L2 IS: %s", + print_system_id( pd + offset, 6 ) ); } length -= 6; offset += 6; @@ -720,7 +715,7 @@ dissect_lsp_prefix_neighbors_clv(const u_char *pd, int offset, * Lets turn the area address into "standard" 0000.0000.etc * format string. */ - sbuf = isis_address_to_string ( pd, offset + 1, mylen ); + sbuf = print_area( pd + offset + 1, mylen ); /* and spit it out */ if ( tree ) { proto_tree_add_text ( tree, offset, mylen + 1, @@ -750,13 +745,8 @@ void isis_lsp_decode_lsp_id(char *tstr, proto_tree *tree, int offset, isis_lsp_id_t *id ) { proto_tree_add_text(tree, offset, 8, - "%s: %02x%02x.%02x%02x.%02x%02x.%02x-%02x", tstr, - id->source_id[0], - id->source_id[1], - id->source_id[2], - id->source_id[3], - id->source_id[4], - id->source_id[5], + "%s: %s.%02x-%02x", tstr, + print_system_id( id->source_id, 6 ), id->psuodonode_id, id->lsp_number ); } @@ -923,7 +913,7 @@ proto_register_isis_lsp(void) { &ett_isis_lsp_clv_ip_reachability, }; - proto_isis_lsp = proto_register_protocol("ISIS lsp", "ISIS-lsp"); + proto_isis_lsp = proto_register_protocol( PROTO_STRING_LSP, "isis_lsp"); proto_register_field_array(proto_isis_lsp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } diff --git a/packet-isis-snp.c b/packet-isis-snp.c index b5853f3528..6b37ac5f0d 100644 --- a/packet-isis-snp.c +++ b/packet-isis-snp.c @@ -1,7 +1,7 @@ /* packet-isis-snp.c * Routines for decoding isis complete & partial SNP and their payload * - * $Id: packet-isis-snp.c,v 1.2 2000/01/24 03:33:32 guy Exp $ + * $Id: packet-isis-snp.c,v 1.3 2000/04/15 22:11:10 guy Exp $ * Stuart Stanley * * Ethereal - Network traffic analyzer @@ -38,6 +38,7 @@ #include #include #include "packet.h" +#include "packet-osi.h" #include "packet-isis.h" #include "packet-isis-clv.h" #include "packet-isis-lsp.h" @@ -196,16 +197,16 @@ dissect_snp_lsp_entries(const u_char *pd, int offset, guint length, return; } - proto_tree_add_text(tree, offset, 2, "Remaining life: %d", + proto_tree_add_text(tree, offset, 2, "Remaining life : %d", pntohs(&ps->isis_snp_remaining_lifetime)); - isis_lsp_decode_lsp_id( "LSP ID", tree, offset + 2, + isis_lsp_decode_lsp_id( "LSP ID ", tree, offset + 2, &ps->isis_snp_lsp_id ); proto_tree_add_text(tree, offset+10, 4, - "LSP Sequence Number: 0x%04x", + "LSP Sequence Number : 0x%04x", pntohl(&ps->isis_snp_sequence_number)); proto_tree_add_text(tree, offset+14, 2, - "LSP checksum: 0x%02x", - pntohl(&ps->isis_snp_checksum)); + "LSP checksum : 0x%02x", + pntohs(&ps->isis_snp_checksum)); length -= sizeof ( isis_snp_t ); offset += sizeof ( isis_snp_t ); ps++; @@ -258,18 +259,12 @@ isis_dissect_isis_csnp(int type, int header_length, const u_char *pd, proto_tree_add_item(csnp_tree, hf_isis_csnp_pdu_length, offset, 2, pntohs(&ilp->isis_csnp_pdu_length)); proto_tree_add_text(csnp_tree, offset + 2, 7, - "Source id: %02x%02x.%02x%02x.%02x%02x.%02x", - ilp->isis_csnp_source_id[0], - ilp->isis_csnp_source_id[1], - ilp->isis_csnp_source_id[2], - ilp->isis_csnp_source_id[3], - ilp->isis_csnp_source_id[4], - ilp->isis_csnp_source_id[5], - ilp->isis_csnp_source_id[6] ); - isis_lsp_decode_lsp_id( "Start LSP id", csnp_tree, offset + 9, - &ilp->isis_csnp_start_lsp_id ); - isis_lsp_decode_lsp_id( "End LSP id", csnp_tree, offset + 17, + "Source id : %s", + print_system_id( pd + offset + 2, 7 ) ); + isis_lsp_decode_lsp_id( "Start LSP id ", csnp_tree, offset + 9, &ilp->isis_csnp_start_lsp_id ); + isis_lsp_decode_lsp_id( "End LSP id ", csnp_tree, offset + 17, + &ilp->isis_csnp_end_lsp_id ); } offset += hlen; @@ -332,14 +327,8 @@ isis_dissect_isis_psnp(int type, int header_length, const u_char *pd, proto_tree_add_item(psnp_tree, hf_isis_psnp_pdu_length, offset, 2, pntohs(&ilp->isis_psnp_pdu_length)); proto_tree_add_text(psnp_tree, offset + 2, 7, - "Source id: %02x%02x.%02x%02x.%02x%02x.%02x", - ilp->isis_psnp_source_id[0], - ilp->isis_psnp_source_id[1], - ilp->isis_psnp_source_id[2], - ilp->isis_psnp_source_id[3], - ilp->isis_psnp_source_id[4], - ilp->isis_psnp_source_id[5], - ilp->isis_psnp_source_id[6] ); + "Source id: %s", + print_system_id( pd + offset + 2, 7 ) ); } offset += hlen; @@ -441,7 +430,7 @@ proto_register_isis_csnp(void) { &ett_isis_csnp_clv_unknown, }; - proto_isis_csnp = proto_register_protocol("ISIS csnp", "ISIS-csnp"); + proto_isis_csnp = proto_register_protocol(PROTO_STRING_CSNP, "isis_csnp"); proto_register_field_array(proto_isis_csnp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } @@ -479,7 +468,7 @@ proto_register_isis_psnp(void) { &ett_isis_psnp_clv_unknown, }; - proto_isis_psnp = proto_register_protocol("ISIS psnp", "ISIS-psnp"); + proto_isis_psnp = proto_register_protocol(PROTO_STRING_PSNP, "isis_psnp"); proto_register_field_array(proto_isis_psnp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } diff --git a/packet-isis.c b/packet-isis.c index ead27120e9..ef764fbeb2 100644 --- a/packet-isis.c +++ b/packet-isis.c @@ -2,7 +2,7 @@ * Routines for ISO/OSI network and transport protocol packet disassembly, core * bits. * - * $Id: packet-isis.c,v 1.6 2000/04/13 08:14:35 guy Exp $ + * $Id: packet-isis.c,v 1.7 2000/04/15 22:11:11 guy Exp $ * Stuart Stanley * * Ethereal - Network traffic analyzer @@ -40,37 +40,38 @@ #include #include "packet.h" #include "nlpid.h" +#include "packet-osi.h" #include "packet-isis.h" #include "packet-isis-lsp.h" #include "packet-isis-hello.h" #include "packet-isis-snp.h" + /* isis base header */ -static int proto_isis = -1; +static int proto_isis = -1; -static int hf_isis_irpd = -1; -static int hf_isis_header_length = -1; -static int hf_isis_version = -1; -static int hf_isis_reserved = -1; -static int hf_isis_type = -1; -static int hf_isis_version2 = -1; -static int hf_isis_eco = -1; -static int hf_isis_user_eco = -1; +static int hf_isis_irpd = -1; +static int hf_isis_header_length = -1; +static int hf_isis_version = -1; +static int hf_isis_system_id_length = -1; +static int hf_isis_type = -1; +static int hf_isis_version2 = -1; +static int hf_isis_reserved = -1; +static int hf_isis_max_area_adr = -1; -static gint ett_isis = -1; +static gint ett_isis = -1; static const value_string isis_vals[] = { - { ISIS_TYPE_L1_HELLO, "L1 HELLO"}, - { ISIS_TYPE_L2_HELLO, "L2 HELLO"}, - { ISIS_TYPE_PTP_HELLO, "P2P HELLO"}, - { ISIS_TYPE_L1_LSP, "L1 LSP"}, - { ISIS_TYPE_L2_LSP, "L2 LSP"}, - { ISIS_TYPE_L1_CSNP, "L1 CSNP"}, - { ISIS_TYPE_L2_CSNP, "L2 CSNP"}, - { ISIS_TYPE_L1_PSNP, "L1 PSNP"}, - { ISIS_TYPE_L2_PSNP, "L2 PSNP"}, - { 0, NULL} }; - + { ISIS_TYPE_L1_HELLO, "L1 HELLO"}, + { ISIS_TYPE_L2_HELLO, "L2 HELLO"}, + { ISIS_TYPE_PTP_HELLO, "P2P HELLO"}, + { ISIS_TYPE_L1_LSP, "L1 LSP"}, + { ISIS_TYPE_L2_LSP, "L2 LSP"}, + { ISIS_TYPE_L1_CSNP, "L1 CSNP"}, + { ISIS_TYPE_L2_CSNP, "L2 CSNP"}, + { ISIS_TYPE_L1_PSNP, "L1 PSNP"}, + { ISIS_TYPE_L2_PSNP, "L2 PSNP"}, + { 0, NULL} }; /* * Name: dissect_isis_unknown() @@ -113,47 +114,6 @@ isis_dissect_unknown(int offset,guint length,proto_tree *tree,frame_data *fd, proto_tree_add_text(tree, offset, length, fmat, ap); va_end(ap); } - -/* - * Name: isis_address_to_string() - * - * Description: - * Function for taking a byte string and turn it into a "0000.0000...." - * format ISIS address. - * - * Input: - * u_char * : Packet data - * unt offset : Current offset into packet data. - * int len : length of to dump. - * - * Output: - * static char * : print string - */ -char -*isis_address_to_string ( const u_char *pd, int offset, int len ) { - static char sbuf[768]; - char *s; - - sbuf[0] = 0; - s = sbuf; - while ( len > 0 ) { - /* special case: len is 1, put ending on it */ - if ( len == 1 ) { - s += sprintf ( s, "%02x", pd[offset++] ); - len--; - } else { - /* general case, just add 2 bytes */ - s+= sprintf ( s, "%02x%02x", pd[offset++], - pd[offset++] ); - len -= 2; - } - if ( len > 0 ) { - s += sprintf ( s, "." ); - } - } - return sbuf; -} - /* * Name: dissect_isis() * @@ -208,22 +168,22 @@ dissect_isis(const u_char *pd, int offset, frame_data *fd, offset + 1, 1, ihdr->isis_header_length ); proto_tree_add_item(isis_tree, hf_isis_version, offset + 2, 1, ihdr->isis_version ); - proto_tree_add_item(isis_tree, hf_isis_reserved, - offset + 3, 1, ihdr->isis_reserved ); + proto_tree_add_item(isis_tree, hf_isis_system_id_length, + offset + 3, 1, ihdr->isis_system_id_len ); proto_tree_add_uint_format(isis_tree, hf_isis_type, offset + 4, 1, ihdr->isis_type, - "Type: %s (R:%s%s%s)", + "Type : %s (R:%s%s%s)", val_to_str(ihdr->isis_type & ISIS_TYPE_MASK, isis_vals, - "Unknown (0x%x)"), + "Unknown (0x%x)"), (ihdr->isis_type & ISIS_R8_MASK) ? "1" : "0", (ihdr->isis_type & ISIS_R7_MASK) ? "1" : "0", (ihdr->isis_type & ISIS_R6_MASK) ? "1" : "0"); proto_tree_add_item(isis_tree, hf_isis_version2, offset + 5, 1, ihdr->isis_version2 ); - proto_tree_add_item(isis_tree, hf_isis_eco, - offset + 6, 1, ihdr->isis_eco ); - proto_tree_add_item(isis_tree, hf_isis_user_eco, - offset + 7, 1, ihdr->isis_user_eco ); + proto_tree_add_item(isis_tree, hf_isis_reserved, + offset + 6, 1, ihdr->isis_reserved ); + proto_tree_add_item(isis_tree, hf_isis_max_area_adr, + offset + 7, 1, ihdr->isis_max_area_adr ); } @@ -304,49 +264,48 @@ dissect_isis(const u_char *pd, int offset, frame_data *fd, */ void proto_register_isis(void) { - static hf_register_info hf[] = { - { &hf_isis_irpd, - { "Intradomain Routing Protocol Discriminator", "isis.irpd", - FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "" }}, + static hf_register_info hf[] = { + { &hf_isis_irpd, + { "Intra Domain Routing Protocol Discriminator", "isis.irpd", + FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "" }}, - { &hf_isis_header_length, - { "HDR Length", "isis.hdr_len", FT_UINT8, BASE_DEC, - NULL, 0x0, "" }}, + { &hf_isis_header_length, + { "PDU Header Length ", "isis.len", FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, - { &hf_isis_version, - { "Version (==1)", "isis.version", FT_UINT8, - BASE_DEC, NULL, 0x0, "" }}, + { &hf_isis_version, + { "Version (==1) ", "isis.version", FT_UINT8, + BASE_DEC, NULL, 0x0, "" }}, - { &hf_isis_reserved, - { "Reserved(==0)", "isis.reserved", - FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, + { &hf_isis_system_id_length, + { "System ID Length ", "isis.sysid_len", + FT_UINT8, BASE_DEC, NULL, 0x0, "" }}, - { &hf_isis_type, - { "Type code", "isis.type", FT_UINT8, BASE_DEC, - VALS(isis_vals), 0xff, "" }}, + { &hf_isis_type, + { "PDU Type :", "isis.type", FT_UINT8, BASE_DEC, + VALS(isis_vals), 0xff, "" }}, - { &hf_isis_version2, - { "Version2(==1)", "isis.version2", FT_UINT8, BASE_DEC, NULL, - 0x0, "" }}, + { &hf_isis_version2, + { "Version2 (==1) ", "isis.version2", FT_UINT8, BASE_DEC, NULL, + 0x0, "" }}, - { &hf_isis_eco, - { "ECO (==0)", "isis.eco",FT_UINT8, BASE_DEC, NULL, - 0x0, "" }}, + { &hf_isis_reserved, + { "Reserved (==0) ", "isis.reserved", FT_UINT8, BASE_DEC, NULL, + 0x0, "" }}, - { &hf_isis_user_eco, - { "User ECO (==0)", "isis.user_eco", FT_UINT8, BASE_DEC, NULL, - 0x0, "" }}, + { &hf_isis_max_area_adr, + { "Max.AREAs: (0==3) ", "isis.max_area_adr", FT_UINT8, BASE_DEC, NULL, + 0x0, "" }}, - }; - /* - * Note, we pull in the unknown CLV handler here, since it - * is used by all ISIS packet types. - */ - static gint *ett[] = { - &ett_isis, - }; + }; + /* + * Note, we pull in the unknown CLV handler here, since it + * is used by all ISIS packet types. + */ + static gint *ett[] = { + &ett_isis, + }; - proto_isis = proto_register_protocol("clnp ISIS", "isis"); - proto_register_field_array(proto_isis, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); + proto_isis = proto_register_protocol(PROTO_STRING_ISIS, "isis"); + proto_register_field_array(proto_isis, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); } diff --git a/packet-isis.h b/packet-isis.h index 9ebc600a28..1c49542a9c 100644 --- a/packet-isis.h +++ b/packet-isis.h @@ -1,7 +1,7 @@ /* packet-isis.h * Defines and such for core isis protcol decode. * - * $Id: packet-isis.h,v 1.2 2000/01/13 06:07:52 guy Exp $ + * $Id: packet-isis.h,v 1.3 2000/04/15 22:11:11 guy Exp $ * Stuart Stanley * * Ethereal - Network traffic analyzer @@ -37,48 +37,50 @@ /* * ISIS type field values */ -#define ISIS_TYPE_L1_HELLO 15 -#define ISIS_TYPE_L2_HELLO 16 -#define ISIS_TYPE_PTP_HELLO 17 -#define ISIS_TYPE_L1_LSP 18 -#define ISIS_TYPE_L2_LSP 20 -#define ISIS_TYPE_L1_CSNP 24 -#define ISIS_TYPE_L2_CSNP 25 -#define ISIS_TYPE_L1_PSNP 26 -#define ISIS_TYPE_L2_PSNP 27 +#define ISIS_TYPE_L1_HELLO 15 +#define ISIS_TYPE_L2_HELLO 16 +#define ISIS_TYPE_PTP_HELLO 17 +#define ISIS_TYPE_L1_LSP 18 +#define ISIS_TYPE_L2_LSP 20 +#define ISIS_TYPE_L1_CSNP 24 +#define ISIS_TYPE_L2_CSNP 25 +#define ISIS_TYPE_L1_PSNP 26 +#define ISIS_TYPE_L2_PSNP 27 + +#define ISIS_TYPE_MASK 0x1f +#define ISIS_R8_MASK 0x80 +#define ISIS_R7_MASK 0x40 +#define ISIS_R6_MASK 0x20 /* * The common first 8 octets of the ISIS protocol header. */ typedef struct { - guint8 isis_irpd; /* Intradomain Routing Protocol Descriminator. Must be 0x83 */ - guint8 isis_header_length; /* header length in octets */ - guint8 isis_version; /* isis version, must be 0x01 */ - guint8 isis_reserved; /* res byte, must be 0 */ - guint8 isis_type_reserved; /* packet type & reserved */ -#define ISIS_TYPE_MASK 0x1f -#define ISIS_R8_MASK 0x80 -#define ISIS_R7_MASK 0x40 -#define ISIS_R6_MASK 0x20 - guint8 isis_version2; /* another version(?!), must be 0x01 */ - - guint8 isis_eco; /* ECO, must be 0 */ - guint8 isis_user_eco; /* user ECO, must be 0 */ -} isis_hdr_t; + guint8 isis_irpd; /* Intradomain Routing Protocol Descriminator: 0x83 */ + guint8 isis_header_length; /* header length in octets */ + guint8 isis_version; /* isis version, must be 0x01 */ + guint8 isis_system_id_len; /* length of the system ID fields */ + guint8 isis_type_reserved; /* packet type & reserved */ + guint8 isis_version2; /* another version(?!), must be 0x01 */ + guint8 isis_reserved; /* reserved, must be 0 */ + guint8 isis_max_area_adr; /* Maximum Number of AREA Addresses permitted */ +} isis_hdr_t; /* for this AREA. Value of 0 allows 3 Addresses */ #define isis_type isis_type_reserved&ISIS_TYPE_MASK -#define isis_r8 isis_type_reserved&ISIS_R8_MASK -#define isis_r7 isis_type_reserved&ISIS_R7_MASK -#define isis_r6 isis_type_reserved&ISIS_R6_MASK +#define isis_r8 isis_type_reserved&ISIS_R8_MASK +#define isis_r7 isis_type_reserved&ISIS_R7_MASK +#define isis_r6 isis_type_reserved&ISIS_R6_MASK + /* * published API functions */ + extern char *isis_address_to_string ( const u_char *pd, int offset, int len ); -extern void dissect_isis(const u_char *pd, int offset, frame_data *fd, - proto_tree *tree); +extern void dissect_isis( const u_char *pd, int offset, frame_data *fd, + proto_tree *tree); extern void proto_register_isis(void); -extern void isis_dissect_unknown(int offset,guint length,proto_tree *tree,frame_data *fd, - char *fmat, ...); +extern void isis_dissect_unknown( int offset, guint length, proto_tree *tree, + frame_data *fd, char *fmat, ...); #endif /* _PACKET_ISIS_H */ diff --git a/packet-osi-options.c b/packet-osi-options.c new file mode 100644 index 0000000000..9db8f89d7a --- /dev/null +++ b/packet-osi-options.c @@ -0,0 +1,466 @@ +/* packet-osi-options.c + * Routines for the decode of ISO/OSI option part + * Covers: + * ISO 8473 CLNP (ConnectionLess Mode Network Service Protocol) + * ISO 10589 ISIS (Intradomain Routeing Information Exchange Protocol) + * ISO 9542 ESIS (End System To Intermediate System Routeing Exchange Protocol) + * + * $Id: packet-osi-options.c,v 1.1 2000/04/15 22:11:11 guy Exp $ + * Ralf Schneider + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#include +#include +#include +#include "packet.h" +#include "nlpid.h" +#include "packet-osi.h" +#include "packet-isis.h" +#include "packet-isis-clv.h" +#include "packet-isis-hello.h" +#include "packet-isis-lsp.h" +#include "packet-isis-snp.h" +#include "packet-esis.h" +#include "packet-clnp.h" +#include "packet-osi-options.h" + +#define OSI_OPT_SECURITY 0xc5 +#define OSI_OPT_QOS_MAINTANANCE 0xc3 +#define OSI_OPT_PRIORITY 0xcd +#define OSI_OPT_ADDRESS_MASK 0xe1 +#define OSI_OPT_SNPA_MASK 0xe2 +#define OSI_OPT_ES_CONFIG_TIMER 0xc6 + +#define OSI_OPT_MAX_PRIORITY 0x0e + +#define OSI_OPT_PADDING 0xcc +#define OSI_OPT_SOURCE_ROUTING 0xc8 +#define OSI_OPT_RECORD_OF_ROUTE 0xcb +#define OSI_OPT_REASON_OF_DISCARD 0xc1 + +#define OSI_OPT_SEC_MASK 0xc0 +#define OSI_OPT_SEC_RESERVED 0x00 +#define OSI_OPT_SEC_SRC_ADR_SPEC 0x40 +#define OSI_OPT_SEC_DST_ADR_SPEC 0x80 +#define OSI_OPT_SEC_GLOBAL_UNIQUE 0xc0 + +#define OSI_OPT_QOS_MASK 0xc0 +#define OSI_OPT_QOS_RESERVED 0x00 +#define OSI_OPT_QOS_SRC_ADR_SPEC 0x40 +#define OSI_OPT_QOS_DST_ADR_SPEC 0x80 +#define OSI_OPT_QOS_GLOBAL_UNIQUE 0xc0 + +#define OSI_OPT_QOS_SUB_MASK 0x3f +#define OSI_OPT_QOS_SUB_RSVD 0x20 +#define OSI_OPT_QOS_SUB_SEQ_VS_TRS 0x10 +#define OSI_OPT_QOS_SUB_CONG_EXPED 0x08 +#define OSI_OPT_QOS_SUB_TSD_VS_COST 0x04 +#define OSI_OPT_QOS_SUB_RESERR_TRS 0x02 +#define OSI_OPT_QOS_SUB_RESERR_COST 0x01 + +#define OSI_OPT_RFD_GENERAL 0x00 +#define OSI_OPT_RFD_ADDRESS 0x80 +#define OSI_OPT_RFD_SOURCE_ROUTEING 0x90 +#define OSI_OPT_RFD_LIFETIME 0xa0 +#define OSI_OPT_RFD_PDU_DISCARDED 0xb0 +#define OSI_OPT_RFD_REASSEMBLY 0xc0 + +#define OSI_OPT_RFD_MASK 0xf0 +#define OSI_OPT_RFD_SUB_MASK 0x0f + + + + +static gint ott_osi_options = -1; +static gint ott_osi_qos = -1; +static gint ott_osi_route = -1; +static gint ott_osi_redirect = -1; + +static const value_string osi_opt_sec_vals[] = { + { OSI_OPT_SEC_RESERVED, "Reserved"}, + { OSI_OPT_SEC_SRC_ADR_SPEC, "Source Address Specific"}, + { OSI_OPT_SEC_DST_ADR_SPEC, "Destination Address Specific"}, + { OSI_OPT_SEC_GLOBAL_UNIQUE, "Globally Unique"}, + { 0, NULL} }; + +static const value_string osi_opt_qos_vals[] = { + { OSI_OPT_QOS_RESERVED, "Reserved"}, + { OSI_OPT_QOS_SRC_ADR_SPEC, "Source Address Specific"}, + { OSI_OPT_QOS_DST_ADR_SPEC, "Destination Address Specific"}, + { OSI_OPT_QOS_GLOBAL_UNIQUE, "Globally Unique"}, + { 0, NULL} }; + +static const value_string osi_opt_qos_sub_vals[] = { + { 0x20, " xx10 0000 Reserved"}, + { 0x10, " xx01 0000 Sequencing versus transit delay"}, + { 0x08, " xx00 1000 Congestion experienced"}, + { 0x04, " xx00 0100 Transit delay versus cost"}, + { 0x02, " xx00 0010 Residual error probability versus transit delay"}, + { 0x01, " xx00 0001 Residual error probability versus cost"}, + { 0, NULL} }; + +static const value_string osi_opt_rfd_general[] = { + { 0x00, "Reason not specified"}, + { 0x01, "Protocol procedure error"}, + { 0x02, "Incorrect checksum"}, + { 0x03, "PDU discarded due to congestion"}, + { 0x04, "Header syntax error ( cannot be parsed )"}, + { 0x05, "Segmentation needed but not permitted"}, + { 0x06, "Incomplete PDU received"}, + { 0x07, "Duplicate option"}, + { 0, NULL} }; + +static const value_string osi_opt_rfd_address[] = { + { 0x00, "Destination Address unreachable"}, + { 0x01, "Destination Address unknown"}, + { 0, NULL} }; + +static const value_string osi_opt_rfd_src_route[] = { + { 0x00, "Unspecified source routeing error"}, + { 0x01, "Syntax error in source routeing field"}, + { 0x02, "Unknown address in source routeing field"}, + { 0x03, "Path not acceptable"}, + { 0, NULL} }; + +static const value_string osi_opt_rfd_lifetime[] = { + { 0x00, "Lifetime expired while data unit in transit"}, + { 0x01, "Lifetime expired during reassembly"}, + { 0, NULL} }; + +static const value_string osi_opt_rfd_discarded[] = { + { 0x00, "Unsupported option not specified"}, + { 0x01, "Unsupported protocol version"}, + { 0x02, "Unsupported security option"}, + { 0x03, "Unsupported source routeing option"}, + { 0x04, "Unsupported recording of route option"}, + { 0, NULL} }; + +static const value_string osi_opt_rfd_reassembly[] = { + { 0x00, "Reassembly interference"}, + { 0, NULL} }; + + +void +dissect_option_qos( const u_char type, const u_char sub_type, u_char offset, + u_char len, const u_char *pd, proto_tree *tree ) { + + u_char tmp_type = 0; + proto_item *ti; + proto_tree *osi_qos_tree = NULL; + + + ti = proto_tree_add_text( tree, offset, len, + "Quality of service maintenance: %s", + val_to_str( type, osi_opt_qos_vals, "Unknown (0x%x)") ); + + osi_qos_tree = proto_item_add_subtree( ti, ott_osi_qos ); + + if ( OSI_OPT_SEC_MASK == type ) { /* Analye BIT field to get all Values */ + + tmp_type = sub_type & OSI_OPT_QOS_SUB_RSVD; + if ( tmp_type ) { + proto_tree_add_text( osi_qos_tree, offset, len, + val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") ); + } + tmp_type = sub_type & OSI_OPT_QOS_SUB_SEQ_VS_TRS; + if ( tmp_type ) { + proto_tree_add_text( osi_qos_tree, offset, len, + val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") ); + } + tmp_type = sub_type &OSI_OPT_QOS_SUB_CONG_EXPED; + if ( tmp_type ) { + proto_tree_add_text( osi_qos_tree, offset, len, + val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") ); + } + tmp_type = sub_type & OSI_OPT_QOS_SUB_TSD_VS_COST; + + if ( tmp_type ) { + proto_tree_add_text( osi_qos_tree, offset, len, + val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") ); + } + tmp_type = sub_type & OSI_OPT_QOS_SUB_RESERR_TRS; + if ( tmp_type ) { + proto_tree_add_text( osi_qos_tree, offset, len, + val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") ); + } + tmp_type = sub_type & OSI_OPT_QOS_SUB_RESERR_COST; + if ( tmp_type ) { + proto_tree_add_text( osi_qos_tree, offset, len, + val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") ); + } + } +}; +void +dissect_option_route( u_char parm_type, u_char offset, u_char parm_len, + const u_char *pd, proto_tree *tree ) { + + u_char next_hop = 0; + u_char this_hop = 0; + u_char netl = 0; + u_char last_hop = 0; + u_char cnt_hops = 0; + + proto_item *ti; + proto_tree *osi_route_tree = NULL; + + static const value_string osi_opt_route[] = { + { 0x03, "No Network Entity Titles Recorded Yet"}, + { 0xff, "Recording Terminated !"}, + { 0, NULL} }; + + if ( parm_type == OSI_OPT_SOURCE_ROUTING ) { + next_hop = pd[offset + 1 ]; + netl = pd[next_hop + 2 ]; + this_hop = offset + 3; /* points to first netl */ + + ti = proto_tree_add_text( tree, offset + next_hop, netl, + "Source Routing: %s ( Next Hop Highlighted In Data Buffer )", + (pd[offset] == 0) ? "Partial Source Routeing" : + "Complete Source Routeing" ); + } + else { + last_hop = pd[offset + 1 ]; /* points to the end of the list */ + netl = pd[ last_hop ]; /* mis-used to highlight buffer */ + + ti = proto_tree_add_text( tree, offset + next_hop, netl, + "Record of Route: %s : %s", + (pd[offset] == 0) ? "Partial Source Routeing" : + "Complete Source Routeing" , + val_to_str( last_hop, osi_opt_route, "Unknown (0x%x" ) ); + if ( 255 == last_hop ) + this_hop = parm_len + 1; /* recording terminated, nothing to show */ + else + this_hop = offset + 3; + } + osi_route_tree = proto_item_add_subtree( ti, ott_osi_route ); + + while ( this_hop < parm_len ) { + netl = pd[this_hop + 1]; + proto_tree_add_text( osi_route_tree, offset + this_hop, netl, + "Hop #%3u NETL: %2u, NET: %s", + cnt_hops++, + netl, + print_nsap_net( &pd[this_hop + 1], netl ) ); + this_hop += 1 + netl; + } +}; + + + + + +void +dissect_option_rfd( const u_char error, const u_char field, u_char offset, + u_char len, const u_char *pd, proto_tree *tree ) { + u_char error_class = 0; + char *format_string[] = + { "Reason for discard {General} : %s, in field %u", + "Reason for discard {Address} : %s, in field %u", + "Reason for discard {Source Routeing}: %s, in field %u", + "Reason for discard {Lifetime} : %s, in field %u", + "Reason for discard {PDU discarded} : %s, in field %u", + "Reason for discard {Reassembly} : %s, in field %u" + }; + + error_class = error & OSI_OPT_RFD_MASK; + + if ( OSI_OPT_RFD_GENERAL == error_class ) { + proto_tree_add_text( tree, offset + field, 1, format_string[0], + val_to_str( error & OSI_OPT_RFD_SUB_MASK, + osi_opt_rfd_general, "Unknown (0x%x)"), field ); + } + else if ( OSI_OPT_RFD_ADDRESS == error_class ) { + proto_tree_add_text( tree, offset + field, 1, format_string[1], + val_to_str( error & OSI_OPT_RFD_SUB_MASK, + osi_opt_rfd_address, "Unknown (0x%x)"), field ); + } + else if ( OSI_OPT_RFD_SOURCE_ROUTEING == error_class ) { + proto_tree_add_text( tree, offset + field, 1, format_string[2], + val_to_str( error & OSI_OPT_RFD_SUB_MASK, + osi_opt_rfd_src_route, "Unknown (0x%x)"), field ); + } + else if ( OSI_OPT_RFD_LIFETIME == error_class ) { + proto_tree_add_text( tree, offset + field, 1, format_string[3], + val_to_str( error & OSI_OPT_RFD_SUB_MASK, + osi_opt_rfd_lifetime, "Unknown (0x%x)"), field ); + } + else if ( OSI_OPT_RFD_PDU_DISCARDED == error_class ) { + proto_tree_add_text( tree, offset + field, 1, format_string[4], + val_to_str( error & OSI_OPT_RFD_SUB_MASK, + osi_opt_rfd_discarded, "Unknown (0x%x)"), field ); + } + else if ( OSI_OPT_RFD_REASSEMBLY == error_class ) { + proto_tree_add_text( tree, offset + field, 1, format_string[5], + val_to_str( error & OSI_OPT_RFD_SUB_MASK, + osi_opt_rfd_reassembly, "Unknown (0x%x)"), field ); + } + else { + proto_tree_add_text( tree, offset, len, + "Reason for discard: UNKNOWN Error Class" ); + } +}; + +/* ############################## Dissection Functions ###################### */ + +/* + * Name: dissect_osi_options() + * + * Description: + * Main entry area for esis de-mangling. This will build the + * main esis tree data and call the sub-protocols as needed. + * + * Input: + * u_char : PDU type to check if option is allowed or not + * u_char : length of option section + * u_char * : packet data + * int : offset into packet where we are (packet_data[offset]== start + * of what we care about) + * frame_data * : frame data (whole packet with extra info) + * proto_tree * : tree of display data. May be NULL. + * + * Output: + * void, but we will add to the proto_tree if it is not NULL. + */ +void +dissect_osi_options( u_char pdu_type, u_char opt_len, const u_char *pd, + int offset, frame_data *fd, proto_tree *tree) { + proto_item *ti; + proto_tree *osi_option_tree = NULL; + u_char parm_len = 0; + u_char parm_type = 0; + + if (tree) { + if ( 0 == opt_len ) { + proto_tree_add_text( tree, offset, 0, + "### No Options for this PDU ###" ); + return; + } + + if ( opt_len > END_OF_FRAME ) { + proto_tree_add_text( tree, offset, END_OF_FRAME, + "### Options go past the end of the captured data in this PDU ###" ); + return; + } + + ti = proto_tree_add_text( tree, offset, opt_len, + "### Option Section ###" ); + osi_option_tree = proto_item_add_subtree( ti, ott_osi_options ); + + while ( 0 < opt_len ) { + parm_type = (int) pd[offset++]; + parm_len = (int) pd[offset++]; + + switch ( parm_type ) { + case OSI_OPT_QOS_MAINTANANCE: + dissect_option_qos( pd[offset]&OSI_OPT_QOS_MASK, + pd[offset]&OSI_OPT_QOS_SUB_MASK, + offset, parm_len, pd, osi_option_tree ); + break; + case OSI_OPT_SECURITY: + proto_tree_add_text( osi_option_tree, offset, parm_len, + "Security type: %s", + val_to_str( pd[offset]&OSI_OPT_SEC_MASK, + osi_opt_sec_vals, "Unknown (0x%x)") ); + break; + case OSI_OPT_PRIORITY: + if ( OSI_OPT_MAX_PRIORITY >= pd[offset] ) { + proto_tree_add_text( osi_option_tree, offset, parm_len, + "Priority : %u", pd[offset] ); + } + else { + proto_tree_add_text( osi_option_tree, offset, parm_len, + "Priority : %u ( Invalid )", + pd[offset] ); + } + break; + case OSI_OPT_ADDRESS_MASK: + proto_tree_add_text( osi_option_tree, offset, parm_len, + "Address Mask: %s", print_area( &pd[offset], parm_len ) ); + break; + case OSI_OPT_SNPA_MASK: + proto_tree_add_text( osi_option_tree, offset, parm_len, + "SNPA Mask : %s", print_system_id( &pd[offset], parm_len )); + break; + case OSI_OPT_ES_CONFIG_TIMER: + proto_tree_add_text( osi_option_tree, offset, parm_len, + "ESCT : %u seconds", pntohs( &pd[offset] ) ); + break; + case OSI_OPT_PADDING: + proto_tree_add_text( osi_option_tree, offset, parm_len, + "Padding : %u Octets", parm_len ) ; + break; + case OSI_OPT_SOURCE_ROUTING: + case OSI_OPT_RECORD_OF_ROUTE: + dissect_option_route( parm_type, + offset, parm_len, pd, osi_option_tree ); + break; + case OSI_OPT_REASON_OF_DISCARD: + dissect_option_rfd( pd[offset], + pd[offset + 1], + offset, parm_len, pd, osi_option_tree ); + break; + } + opt_len -= parm_len + 2; + offset += parm_len; + } + } +}; /* dissect-osi-options */ + + +/* + * Name: proto_register_osi_options() + * + * Description: + * main register for esis protocol set. We register some display + * formats and the protocol module variables. + * + * NOTE: this procedure to autolinked by the makefile process that + * builds register.c + * + * Input: + * void + * + * Output: + * void + */ + +void +proto_register_osi_options(void) { + static gint *ott[] = { + &ott_osi_options, + &ott_osi_qos, + &ott_osi_route, + &ott_osi_redirect, + }; + proto_register_subtree_array( ott, array_length(ott)); +}; + diff --git a/packet-osi-options.h b/packet-osi-options.h new file mode 100644 index 0000000000..fdd54d8368 --- /dev/null +++ b/packet-osi-options.h @@ -0,0 +1,39 @@ +/* packet-osi-options.h + * Defines for OSI options part decode + * + * $Id: packet-osi-options.h,v 1.1 2000/04/15 22:11:12 guy Exp $ + * Ralf Schneider + * + * Ethereal - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + */ + +#ifndef _PACKET_OSI_OPTION_H +#define _PACKET_OSI_OPTIONS_H + +/* + * published API functions + */ +extern void dissect_osi_options( u_char, u_char, const u_char *, int, + frame_data *, proto_tree *); +extern void proto_register_osi_options(void); + +#endif /* _PACKET_OSI_OPTIONS_H */ diff --git a/packet-osi.c b/packet-osi.c index ebd5c015a4..2b242597b6 100644 --- a/packet-osi.c +++ b/packet-osi.c @@ -1,8 +1,10 @@ /* packet-osi.c * Routines for ISO/OSI network and transport protocol packet disassembly + * Main entrance point and common functions * - * $Id: packet-osi.c,v 1.29 2000/04/15 21:27:12 guy Exp $ + * $Id: packet-osi.c,v 1.30 2000/04/15 22:11:12 guy Exp $ * Laurent Deniel + * Ralf Schneider * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -26,9 +28,9 @@ * * To do: * - * - add other network protocols (ES,IS-IS) + * - add other network protocols (IS-IS) * - add NSAP decoding & resolution - * - complete CLNP decoding (options) + * * */ @@ -45,1693 +47,161 @@ #include #include #include "packet.h" -#include "packet-isis.h" #include "packet-h1.h" #include "nlpid.h" +#include "packet-osi.h" +#include "packet-clnp.h" +#include "packet-isis.h" +#include "packet-esis.h" -/* protocols and fields */ -static int proto_clnp = -1; - -static int hf_clnp_id = -1; -static int hf_clnp_length = -1; -static int hf_clnp_version = -1; -static int hf_clnp_ttl = -1; -static int hf_clnp_type = -1; -static int hf_clnp_pdu_length = -1; -static int hf_clnp_checksum = -1; -static int hf_clnp_dest_length = -1; -static int hf_clnp_dest = -1; -static int hf_clnp_src_length = -1; -static int hf_clnp_src = -1; - -static gint ett_clnp = -1; - -static int proto_cotp = -1; - -static gint ett_cotp = -1; - -/* - * ISO8473 OSI CLNP definition (see RFC994) - * - * _________________________________ - * | Fixed Part | - * |_________________________________| - * | Address Part | - * |_________________________________| - * | Segmentation Part (optional) | - * |_________________________________| - * | Options Part (optional) | - * |_________________________________| - * | Data (optional) | - * |_________________________________| - */ - -#define ISO8473_V1 0x01 /* CLNP version 1 */ - -/* Fixed part */ - -struct clnp_header { - u_char cnf_proto_id; /* network layer protocol identifier */ - u_char cnf_hdr_len; /* length indicator (octets) */ - u_char cnf_vers; /* version/protocol identifier extension */ - u_char cnf_ttl; /* lifetime (500 milliseconds) */ - u_char cnf_type; /* type code */ - u_char cnf_seglen_msb; /* pdu segment length (octets) high byte */ - u_char cnf_seglen_lsb; /* pdu segment length (octets) low byte */ - u_char cnf_cksum_msb; /* checksum high byte */ - u_char cnf_cksum_lsb; /* checksum low byte */ -}; - -#define CNF_TYPE 0x1f -#define CNF_ERR_OK 0x20 -#define CNF_MORE_SEGS 0x40 -#define CNF_SEG_OK 0x80 - -#define DT_NPDU 0x1C -#define MD_NPDU 0x1D -#define ER_NPDU 0x01 -#define ERQ_NPDU 0x1E -#define ERP_NPDU 0x1F - -static const value_string npdu_type_vals[] = { - { DT_NPDU, "DT" }, - { MD_NPDU, "MD" }, - { ER_NPDU, "ER" }, - { ERQ_NPDU, "ERQ" }, - { ERP_NPDU, "ERP" }, - { 0, NULL } -}; - -/* field position */ - -#define P_ADDRESS_PART 9 - -/* Segmentation part */ - -struct clnp_segment { - u_short cng_id; /* data unit identifier */ - u_short cng_off; /* segment offset */ - u_short cng_tot_len; /* total length */ -}; - -/* NSAP selector */ - -#define NSEL_NET 0x00 -#define NSEL_NP 0x20 -#define NSEL_TP 0x21 - -/* - * ISO8073 OSI COTP definition (see RFC905) - */ - -/* don't use specific TPDU types to avoid alignment problems & copy overhead */ - -/* 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 - -/* field position */ - -#define P_LI 0 -#define P_TPDU 1 -#define P_CDT 1 -#define P_DST_REF 2 -#define P_SRC_REF 4 -#define P_TPDU_NR_0_1 2 -#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 -#define P_REASON_IN_DR 6 -#define P_CLASS_OPTION 6 - -/* TPDU length indicator */ - -#define LI_NORMAL_DT_CLASS_01 2 -#define LI_NORMAL_DT_WITH_CHECKSUM 8 -#define LI_NORMAL_DT_WITHOUT_CHECKSUM 4 -#define LI_EXTENDED_DT_WITH_CHECKSUM 11 -#define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7 -#define LI_NORMAL_EA_WITH_CHECKSUM 8 -#define LI_NORMAL_EA_WITHOUT_CHECKSUM 4 -#define LI_EXTENDED_EA_WITH_CHECKSUM 11 -#define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7 -#define LI_NORMAL_RJ 4 -#define LI_EXTENDED_RJ 9 -#define LI_MIN_DR 6 -#define LI_MAX_DC 9 -#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 ) - -/* variant part */ - -#define VP_ACK_TIME 0x85 -#define VP_RES_ERROR 0x86 -#define VP_PRIORITY 0x87 -#define VP_TRANSIT_DEL 0x88 -#define VP_THROUGHPUT 0x89 -#define VP_SEQ_NR 0x8A /* in AK */ -#define VP_REASSIGNMENT 0x8B -#define VP_FLOW_CNTL 0x8C /* in AK */ -#define VP_TPDU_SIZE 0xC0 -#define VP_SRC_TSAP 0xC1 /* in CR/CC */ -#define VP_DST_TSAP 0xC2 -#define VP_CHECKSUM 0xC3 -#define VP_VERSION_NR 0xC4 -#define VP_PROTECTION 0xC5 -#define VP_OPT_SEL 0xC6 -#define VP_PROTO_CLASS 0xC7 - -/* misc */ - -#define EXTRACT_SHORT(p) pntohs(p) -#define EXTRACT_LONG(p) pntohl(p) - -/* global variables */ - -static u_char li, tpdu, cdt; /* common fields */ -static u_short dst_ref; - -/* function definitions */ - -static int osi_decode_DR(const u_char *pd, int offset, - frame_data *fd, proto_tree *tree) -{ - proto_tree *cotp_tree; - proto_item *ti; - u_short src_ref; - u_char reason; - char *str; - - if (li < LI_MIN_DR) - return -1; - - src_ref = EXTRACT_SHORT(&pd[offset + P_SRC_REF]); - reason = pd[offset + P_REASON_IN_DR]; - - switch(reason) { - case (128+0): str = "Normal Disconnect"; break; - case (128+1): str = "Remote transport entity congestion"; break; - case (128+2): str = "Connection negotiation failed"; break; - case (128+3): str = "Duplicate source reference"; break; - case (128+4): str = "Mismatched references"; break; - case (128+5): str = "Protocol error"; break; - case (128+7): str = "Reference overflow"; break; - case (128+8): str = "Connection requestion refused"; break; - case (128+10):str = "Header or parameter length invalid"; break; - case (0): str = "Reason not specified"; break; - case (1): str = "Congestion at TSAP"; break; - case (2): str = "Session entity not attached to TSAP"; break; - case (3): str = "Address unknown"; break; - default: return -1; - /*NOTREACHED*/ - break; - } - - if (check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x", - src_ref, dst_ref); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (DR)", tpdu); - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, offset + 4, 2, - "Source reference: 0x%04x", src_ref); - proto_tree_add_text(cotp_tree, offset + 6, 1, - "Cause: %s", str); - } - - offset += li + 1; - dissect_data(pd, offset, fd, tree); - - return pi.captured_len; /* we dissected all of the containing PDU */ - -} /* osi_decode_DR */ - -/* Returns TRUE if we called a sub-dissector, FALSE if not. */ -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_item *ti; - u_int tpdu_nr ; - u_short checksum = 0; - u_char code = 0, length = 0; - u_int fragment = 0; - - 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 - return -1; - break; - 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; - 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 - return -1; - break; - 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; - 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; - break; - default : /* bad TPDU */ - return -1; - /*NOTREACHED*/ - break; - } - - if (check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, "DT TPDU (%d) dst-ref: 0x%04x %s", - tpdu_nr, - dst_ref, - (fragment)? "(fragment)" : ""); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (DT)", tpdu); - - if (li != LI_NORMAL_DT_CLASS_01) - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - - switch (li) { - case LI_NORMAL_DT_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, offset + 4, 1, - "TPDU number: 0x%02x (%s)", - tpdu_nr, - (fragment)? "fragment":"complete"); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NDT, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NDT + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NDT + 2, length, - "Checksum: 0x%04x", checksum); - break; - case LI_NORMAL_DT_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, 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, offset + 4, 4, - "TPDU number: 0x%08x (%s)", - tpdu_nr, - (fragment)? "fragment":"complete"); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EDT, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EDT + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EDT + 2, length, - "Checksum: 0x%04x", checksum); - break; - case LI_EXTENDED_DT_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, 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, offset + 2, 1, - "TPDU number: 0x%02x (%s)", - tpdu_nr, - (fragment)? "fragment":"complete"); - break; +gchar *print_system_id( const u_char *buffer, int length ) { + int tmp; + u_char *cur; + static gchar str[MAX_SYSTEMID_LEN * 3 + 5]; /* Don't trust exact matching */ + + if ( ( length <= 0 ) || ( length > MAX_SYSTEMID_LEN ) ) { + sprintf( str, ""); + return( str ); + } + + cur = str; + if ( ( 6 == length ) || ( 7 == length ) ) { /* Special case, print as MAC */ + cur += sprintf(str, "[%02x:%02x:%02x_%02x:%02x:%02x]", buffer[0], buffer[1], + buffer[2], buffer[3], buffer[4], buffer[5] ); + if ( 7 == length ) { + sprintf( cur, "-%02x", buffer[6] ); } - } /* tree */ - - offset += li + 1; - if (uses_inactive_subset){ - dissect_h1(pd, offset, fd, tree); - return TRUE; - } + } else { - dissect_data(pd, offset, fd, tree); - return FALSE; - } -} /* osi_decode_DT */ - -static int osi_decode_ED(const u_char *pd, int offset, - frame_data *fd, proto_tree *tree) -{ - proto_tree *cotp_tree; - proto_item *ti; - u_int tpdu_nr ; - u_short checksum = 0; - u_char code = 0, length = 0; - - /* ED TPDUs are never fragmented */ - - 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 - 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; - 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; - 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 - 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; - 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; - break; - default : /* bad TPDU */ - return -1; - /*NOTREACHED*/ - break; - } /* li */ - - if (check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, "ED TPDU (%d) dst-ref: 0x%04x", - tpdu_nr, dst_ref); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (ED)", tpdu); - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - - switch (li) { - case LI_NORMAL_DT_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, offset + 4, 1, - "TPDU number: 0x%02x", tpdu_nr); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NDT, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NDT + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NDT + 2, length, - "Checksum: 0x%04x", checksum); - break; - case LI_NORMAL_DT_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, offset + 4, 1, - "TPDU number: 0x%02x", tpdu_nr); - break; - case LI_EXTENDED_DT_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, offset + 4, 4, - "TPDU number: 0x%02x", tpdu_nr); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EDT, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EDT + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EDT + 2, length, - "Checksum: 0x%04x", checksum); - break; - case LI_EXTENDED_DT_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, offset + 4, 4, - "TPDU number: 0x%02x", tpdu_nr); - break; + tmp = 0; + while ( tmp < length / 4 ) { /* 16 / 4 == 4 > four Octets left to print */ + cur += sprintf( str, "%02x%02x%02x%02x.", buffer[tmp++], buffer[tmp++], + buffer[tmp++], buffer[tmp++] ); + } + if ( 1 == tmp ) { /* Special case for Designated IS */ + sprintf( --cur, "-%02x", buffer[tmp] ); } - } /* tree */ - - offset += li + 1; - dissect_data(pd, offset, fd, tree); - - return pi.captured_len; /* we dissected all of the containing PDU */ - -} /* osi_decode_ED */ - -static int osi_decode_RJ(const u_char *pd, int offset, - frame_data *fd, proto_tree *tree) -{ - proto_tree *cotp_tree; - proto_item *ti; - u_int tpdu_nr ; - u_short credit = 0; - - switch(li) { - case LI_NORMAL_RJ : - tpdu_nr = pd[offset + P_TPDU_NR_234]; - break; - case LI_EXTENDED_RJ : - tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); - credit = EXTRACT_SHORT(&pd[offset + P_CDT_IN_RJ]); - break; - default : - return -1; - /*NOTREACHED*/ - break; - } - - if (check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, "RJ TPDU (%d) dst-ref: 0x%04x", - tpdu_nr, dst_ref); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (RJ)", tpdu); - if (li == LI_NORMAL_RJ) - proto_tree_add_text(cotp_tree, offset + 1, 1, - "Credit: %d", cdt); - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - if (li == LI_NORMAL_RJ) - proto_tree_add_text(cotp_tree, offset + 4, 1, - "Your TPDU number: 0x%02x", tpdu_nr); else { - proto_tree_add_text(cotp_tree, offset + 4, 4, - "Your TPDU number: 0x%02x", tpdu_nr); - proto_tree_add_text(cotp_tree, offset + 8, 2, - "Credit: 0x%02x", credit); - } - } - - offset += li + 1; - - return 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; - if (class_option > 4) - return -1; - - if (check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x", - (tpdu == CR_TPDU) ? "CR" : "CC", - src_ref, - dst_ref); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (%s)", tpdu, - (tpdu == CR_TPDU) ? "CR" : "CC"); - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, offset + 4, 2, - "Source reference: 0x%04x", src_ref); - proto_tree_add_text(cotp_tree, offset + 6, 1, - "Class option: 0x%02x", class_option); - } - - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (src-tsap)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (dst-tsap)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (tpdu-size)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (options)", code); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i + 2, 1, - "Use of network expedited data"); - else - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 2, 1, - "Non use of network expedited data"); - if (c1 & 0x4) - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 2, 1, - "Use of Receipt confirmation"); - else - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i + 2, 1, - "Use 16 bit checksum "); - else - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 2, 1, - "Non-use 16 bit checksum in class 4"); - } - if (c1 & 0x1) - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 2, 1, - "Use of transport expedited data transfer\n"); - else - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (ack time)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (throughput)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 2, 4, - "Target value / calling-called: %u o/s", t1); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 6, 4, - "Minimum / calling-called: %u o/s", t2); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 10, 4, - "Target value / called-calling: %u o/s", t3); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (transit delay)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 2, 2, - "Target value / calling-called: %u ms", s1); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 4, 2, - "Minimum / calling-called: %u ms", s2); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 6, 2, - "Target value / called-calling: %u ms", s3); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (priority)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_CC + i, 1, - "Parameter code: 0x%02x (version)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 2, length, - "Version: %u", c1); - i += length + 2; - break; - - 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, - offset + P_VAR_PART_CC + i + 0, 1, - "Parameter code: 0x%02x", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_CC + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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 */ - -} /* osi_decode_CC */ - -static int osi_decode_DC(const u_char *pd, int offset, - frame_data *fd, proto_tree *tree) -{ - proto_tree *cotp_tree; - proto_item *ti; - u_short src_ref, checksum = 0; - u_char length = 0, code = 0; - - 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, - dst_ref); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (DC)", tpdu); - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, offset + 4, 2, - "Source reference: 0x%04x", src_ref); - if (code) { - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_DC + 0, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_DC + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_DC + 2, 2, - "Checksum: 0x%04x", checksum); - } - } - - offset += li + 1; - - return offset; - -} /* osi_decode_DC */ - -static int osi_decode_AK(const u_char *pd, int offset, - frame_data *fd, proto_tree *tree) -{ - proto_tree *cotp_tree = NULL; - proto_item *ti; - u_int tpdu_nr,i =0, r_lower_window_edge ; - 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)) { - tpdu_nr = pd[offset + P_TPDU_NR_234]; - - if (check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x", - tpdu_nr, dst_ref); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (AK)", tpdu); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "Credit: %d", cdt); - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, offset + 4, 1, - "Your TPDU number: 0x%02x", tpdu_nr); - } - - 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, - offset + P_VAR_PART_NAK + i + 0, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_NAK + i + 0, 1, - "Parameter code: 0x%02x (flow control)", - code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NAK + i + 2, 4, - "Lower window edge: 0x%08x", - r_lower_window_edge); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NAK + i + 6, 2, - "Sequence number: 0x%04x", - r_seq_nr); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_NAK + i + 0, 1, - "Parameter code: 0x%02x (seq number)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_NAK + i + 0, 1, - "Parameter code: 0x%02x (unknown)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_NAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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]); - cdt_in_ak = EXTRACT_SHORT(&pd[offset + P_CDT_IN_AK]); - - if (check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, "AK TPDU (%d) dst-ref: 0x%04x", - tpdu_nr, dst_ref); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (AK)", tpdu); - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, offset + 4, 4, - "Your TPDU number: 0x%08x", tpdu_nr); - proto_tree_add_text(cotp_tree, offset + 8, 2, - "Credit: 0x%04x", cdt_in_ak); - } - - 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, - offset + P_VAR_PART_EAK + i + 0, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_EAK + i + 0, 1, - "Parameter code: 0x%02x (flow control)", - code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EAK + i + 2, 4, - "Lower window edge: 0x%08x", - r_lower_window_edge); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EAK + i + 6, 2, - "Sequence number: 0x%04x", - r_seq_nr); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_EAK + i + 0, 1, - "Parameter code: 0x%02x (seq number)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - 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, - offset + P_VAR_PART_EAK + i + 0, 1, - "Parameter code: 0x%02x (unknown)", code); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EAK + i + 1, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, - offset + P_VAR_PART_EAK + i + 2, length, - "Parameter value: "); - } - i += length + 2; - break; - } /* code */ - } - - } /* is_LI_NORMAL_AK */ - - offset += li + 1; - - return offset; - -} /* osi_decode_AK */ - -static int osi_decode_EA(const u_char *pd, int offset, - frame_data *fd, proto_tree *tree) -{ - proto_tree *cotp_tree; - proto_item *ti; - u_int tpdu_nr ; - u_short checksum = 0; - u_char code = 0; - u_char length = 0; - - if (li > LI_MAX_EA) - return -1; - - 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) - return -1; - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_NDT + 2]); - break; - case LI_NORMAL_EA_WITHOUT_CHECKSUM : - tpdu_nr = pd[offset + P_TPDU_NR_234]; - 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) - return -1; - checksum = EXTRACT_SHORT(&pd[offset + P_VAR_PART_EDT + 2]); - break; - case LI_EXTENDED_EA_WITHOUT_CHECKSUM : - tpdu_nr = EXTRACT_LONG(&pd[offset + P_TPDU_NR_234]); - break; - default : /* bad TPDU */ - return -1; - /*NOTREACHED*/ - break; - } /* li */ - - if (check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, - "EA TPDU (%d) dst-ref: 0x%04x", tpdu_nr, dst_ref); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (EA)", tpdu); - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - - switch (li) { - case LI_NORMAL_EA_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, offset + 4, 1, - "Your TPDU number: 0x%02x", tpdu_nr); - proto_tree_add_text(cotp_tree, offset + 5, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, offset + 6, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, offset + 7, 2, - "Checksum: 0x%04x", checksum); - break; - case LI_NORMAL_EA_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, offset + 4, 1, - "Your TPDU number: 0x%02x", tpdu_nr); - break; - case LI_EXTENDED_EA_WITH_CHECKSUM : - proto_tree_add_text(cotp_tree, offset + 4, 4, - "Your TPDU number: 0x%08x", tpdu_nr); - proto_tree_add_text(cotp_tree, offset + 8, 1, - "Parameter code: 0x%02x (checksum)", code); - proto_tree_add_text(cotp_tree, offset + 9, 1, - "Parameter length: %u", length); - proto_tree_add_text(cotp_tree, offset + 10, 2, - "Checksum: 0x%04x", checksum); - break; - case LI_EXTENDED_EA_WITHOUT_CHECKSUM : - proto_tree_add_text(cotp_tree, offset + 4, 4, - "Your TPDU number: 0x%08x", tpdu_nr); - break; - default : - break; - } /* li */ - } /* tree */ - - offset += li + 1; - - return offset; - -} /* osi_decode_EA */ - -static int osi_decode_ER(const u_char *pd, int offset, - frame_data *fd, proto_tree *tree) -{ - proto_tree *cotp_tree; - proto_item *ti; - u_char *str; - - if (li > LI_MAX_ER) - return -1; - - switch(pd[offset + P_REJECT_ER]) { - case 0 : - str = "Reason not specified"; - break; - case 1 : - str = "Invalid parameter code"; - break; - case 2 : - str = "Invalid TPDU type"; - break; - case 3 : - str = "Invalid parameter value"; - break; - default: - return -1; - /*NOTREACHED*/ - break; - } - - if (check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref); - - if (tree) { - ti = proto_tree_add_item(tree, proto_cotp, offset, li + 1, NULL); - cotp_tree = proto_item_add_subtree(ti, ett_cotp); - proto_tree_add_text(cotp_tree, offset, 1, - "Length indicator: %d", li); - proto_tree_add_text(cotp_tree, offset + 1, 1, - "TPDU code: 0x%x (ER)", tpdu); - proto_tree_add_text(cotp_tree, offset + 2, 2, - "Destination reference: 0x%04x", dst_ref); - proto_tree_add_text(cotp_tree, offset + 4, 1, - "Reject cause: %s", str); - } - - offset += li + 1; - - return 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, - frame_data *fd, proto_tree *tree, - gboolean uses_inactive_subset) -{ - gboolean first_tpdu = TRUE; - int new_offset; - gboolean found_cotp = FALSE; - gboolean subdissector_found = FALSE; - - /* Initialize the COL_INFO field; each of the TPDUs will have its - information appended. */ - if (check_col(fd, COL_INFO)) - col_add_str(fd, COL_INFO, ""); - - while (IS_DATA_IN_FRAME(offset)) { - if (!first_tpdu) { - if (check_col(fd, COL_INFO)) - col_append_str(fd, COL_INFO, ", "); - } - if ((li = pd[offset + P_LI]) == 0) { - if (check_col(fd, COL_INFO)) - col_append_str(fd, COL_INFO, "Length indicator is zero"); - if (!first_tpdu) - dissect_data(pd, offset, fd, tree); - return found_cotp; - } - 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; - } - - tpdu = (pd[offset + P_TPDU] >> 4) & 0x0F; - cdt = pd[offset + P_CDT] & 0x0F; - dst_ref = EXTRACT_SHORT(&pd[offset + P_DST_REF]); - - switch (tpdu) { - case CC_TPDU : - case CR_TPDU : - new_offset = osi_decode_CC(pd, offset, fd, tree); - break; - case DR_TPDU : - new_offset = osi_decode_DR(pd, offset, fd, tree); - break; - case DT_TPDU : - if (osi_decode_DT(pd, offset, fd, tree, uses_inactive_subset)) - subdissector_found = TRUE; - new_offset = pi.captured_len; /* DT PDUs run to the end of the packet */ - break; - case ED_TPDU : - new_offset = osi_decode_ED(pd, offset, fd, tree); - break; - case RJ_TPDU : - new_offset = osi_decode_RJ(pd, offset, fd, tree); - break; - case DC_TPDU : - new_offset = osi_decode_DC(pd, offset, fd, tree); - break; - case AK_TPDU : - new_offset = osi_decode_AK(pd, offset, fd, tree); - break; - case EA_TPDU : - new_offset = osi_decode_EA(pd, offset, fd, tree); - break; - case ER_TPDU : - new_offset = osi_decode_ER(pd, offset, fd, tree); - break; - default : - if (first_tpdu && check_col(fd, COL_INFO)) - col_append_fstr(fd, COL_INFO, "Unknown TPDU type (0x%x)", tpdu); - new_offset = -1; /* bad PDU type */ - break; - } - - if (new_offset == -1) { /* incorrect TPDU */ - if (!first_tpdu) - dissect_data(pd, offset, fd, tree); - break; - } - - if (first_tpdu) { - /* Well, we found at least one valid COTP PDU, so I guess this - is COTP. */ - if (!subdissector_found && check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, "COTP"); - found_cotp = TRUE; - } - - offset = new_offset; - first_tpdu = FALSE; - } - return found_cotp; -} /* dissect_cotp_internal */ - -void dissect_cotp(const u_char *pd, int offset, frame_data *fd, - proto_tree *tree) -{ - if (!dissect_cotp_internal(pd, offset, fd, tree, FALSE)) - dissect_data(pd, offset, fd, tree); + return( str ); } - -/* - * CLNP part - */ - -#define MAX_NSAP_LEN 20 - -static gchar *print_nsap(const u_char *nsap, int length) +gchar *print_area(const u_char *buffer, int length) { + /* to do : all real area decoding now: NET is assumed if id len is 1 more byte + * and take away all these stupid resource consuming local statics + */ + + static gchar str[MAX_AREA_LEN * 3 + 20]; /* reserve space for nice layout */ + gchar *cur; + u_int tmp = 0; - /* to do : real NSAP decoding */ + cur = str; - static gchar str[3][MAX_NSAP_LEN * 3 + 1]; - static gchar *cur; - gchar tmp[5]; - - if (cur == &str[0][0]) { - cur = &str[1][0]; - } else if (cur == &str[1][0]) { - cur = &str[2][0]; - } else { - cur = &str[0][0]; + if (length <= 0 || length > MAX_AREA_LEN) { + sprintf( str, ""); + return( str ); } - - cur[0] = '\0'; - if (length <= 0 || length > MAX_NSAP_LEN) - sprintf(cur, ""); - else - while (length != 1) { - sprintf(tmp, "%02x:", *nsap ++); - strcat(cur, tmp); - length --; + + if ( ( ( NSAP_IDI_ISODCC == *buffer ) + || ( NSAP_IDI_GOSIP2 == *buffer ) + ) + && + ( ( RFC1237_FULLAREA_LEN == length ) + || ( RFC1237_FULLAREA_LEN + 1 == length ) + ) + ) { /* AFI is good and length is long enough */ + + if ( length > RFC1237_FULLAREA_LEN + 1 ) { /* Special Case Designated IS */ + sprintf( str, ""); + return( str ); } - sprintf(tmp, "%02x", *nsap); - strcat(cur, tmp); - return cur; + + cur += sprintf( cur, "[%02x|%02x:%02x][%02x|%02x:%02x:%02x|%02x:%02x]", + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], + buffer[5], buffer[6], buffer[7], buffer[8] ); + cur += sprintf( cur, "[%02x:%02x|%02x:%02x]", + buffer[9], buffer[10], buffer[11], buffer[12] ); + if ( RFC1237_FULLAREA_LEN + 1 == length ) { + sprintf( cur, "-[%02x]", buffer[20] ); + } + return str; + } + else { /* print standard format */ + if ( 4 < length ) { + while ( tmp < length / 4 ) { /* 16/4==4 four Octets left to print */ + cur += sprintf( str, "%02x%02x%02x%02x.", buffer[tmp++], buffer[tmp++], + buffer[tmp++], buffer[tmp++] ); + } + if ( 1 == tmp ) { /* Special case for Designated IS */ + sprintf( --cur, "-%02x", buffer[tmp] ); + } + else { + for ( ; tmp < length; ) { /* print the rest without dot */ + cur += sprintf( cur, "%02x", buffer[tmp++] ); + } + } + } + return( str ); + } +} /* print_area */ + +gchar *print_nsap_net( const u_char *buffer, int length) +{ + /* to do : NSAP / NET decoding */ + + static gchar str[MAX_NSAP_LEN * 3 + 50]; /* reserve space for nice layout */ + gchar *cur; + + cur = str; + + if ( (length <= 0 ) || ( length > MAX_NSAP_LEN ) ) { + sprintf( str, ""); + return( str ); + } + if ( ( length == RFC1237_NSAP_LEN ) || ( length == RFC1237_NSAP_LEN + 1 ) ) { + cur += sprintf( cur, "%s", print_area( buffer, RFC1237_FULLAREA_LEN ) ); + cur += sprintf( cur, "%s", print_system_id( buffer + RFC1237_FULLAREA_LEN, + RFC1237_SYSTEMID_LEN ) ); + cur += sprintf( cur, "[%02x]", + buffer[ RFC1237_FULLAREA_LEN + RFC1237_SYSTEMID_LEN ] ); + if ( length == RFC1237_NSAP_LEN + 1 ) { + cur += sprintf( cur, "-%02x", buffer[ length -1 ] ); + } + return ( str ); + } + else { /* probably format as standard */ + return( print_area( buffer, length ) ); + } } /* print_nsap */ -void dissect_clnp(const u_char *pd, int offset, frame_data *fd, - proto_tree *tree) -{ - struct clnp_header clnp; - proto_tree *clnp_tree = NULL; - proto_item *ti; - u_char src_len, dst_len, nsel; - u_int first_offset = offset; - char flag_string[6+1]; - char *pdu_type_string; - guint16 segment_length; - guint16 segment_offset = 0; - guint len; +gchar *calc_checksum( const u_char *buffer, u_int len, u_int checksum) { + u_int calc_sum = 0; + u_int count = 0; - if (check_col(fd, COL_PROTOCOL)) - col_add_str(fd, COL_PROTOCOL, "CLNP"); + static char *checksum_string[] = { "Not Used", + "Is good", + "Is wrong" }; + if ( 0 == checksum ) + return( checksum_string[0] ); - /* avoid alignment problem */ - memcpy(&clnp, &pd[offset], sizeof(clnp)); - - if (clnp.cnf_proto_id == NLPID_NULL) { - if (check_col(fd, COL_INFO)) - col_add_str(fd, COL_INFO, "Inactive subset"); - if (tree) { - ti = proto_tree_add_item(tree, proto_clnp, offset, 1, NULL); - clnp_tree = proto_item_add_subtree(ti, ett_clnp); - proto_tree_add_uint_format(clnp_tree, hf_clnp_id, offset, 1, - clnp.cnf_proto_id, - "Inactive subset"); - } - dissect_cotp_internal(pd, offset+1, fd, tree, TRUE); - return; - } - - if (!BYTES_ARE_IN_FRAME(offset, sizeof(clnp))) { - dissect_data(pd, offset, fd, tree); - return; + for ( count = 0; count < len; count++ ) { + calc_sum += (u_int) buffer[count]; } - - /* return if version not known */ - if (clnp.cnf_vers != ISO8473_V1) { - dissect_data(pd, offset, fd, tree); - return; - } - - /* fixed part decoding */ - - segment_length = EXTRACT_SHORT(&clnp.cnf_seglen_msb); - flag_string[0] = '\0'; - if (clnp.cnf_type & CNF_SEG_OK) - strcat(flag_string, "S "); - if (clnp.cnf_type & CNF_MORE_SEGS) - strcat(flag_string, "M "); - if (clnp.cnf_type & CNF_ERR_OK) - strcat(flag_string, "E "); - pdu_type_string = val_to_str(clnp.cnf_type & CNF_TYPE, npdu_type_vals, - "Unknown (0x%02x)"); - if (tree) { - ti = proto_tree_add_item(tree, proto_clnp, offset, clnp.cnf_hdr_len, NULL); - clnp_tree = proto_item_add_subtree(ti, ett_clnp); - proto_tree_add_item(clnp_tree, hf_clnp_id, offset, 1, - clnp.cnf_proto_id); - proto_tree_add_item(clnp_tree, hf_clnp_length, offset + 1, 1, - clnp.cnf_hdr_len); - proto_tree_add_item(clnp_tree, hf_clnp_version, offset + 2, 1, - clnp.cnf_vers); - proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, offset + 3, 1, - clnp.cnf_ttl, - "TTL: %d (%d secs)", - clnp.cnf_ttl, clnp.cnf_ttl / 2); - proto_tree_add_uint_format(clnp_tree, hf_clnp_type, offset + 4, 1, - clnp.cnf_type, - "Type code: 0x%02x (%s%s)", - clnp.cnf_type, - flag_string, - pdu_type_string); - proto_tree_add_item(clnp_tree, hf_clnp_pdu_length, offset + 5, 2, - segment_length); - proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, offset + 7, 2, - EXTRACT_SHORT(&clnp.cnf_cksum_msb), - "Checksum: 0x%04x", - EXTRACT_SHORT(&clnp.cnf_cksum_msb)); - } /* tree */ - - /* stop here if header is not complete */ - - if (!BYTES_ARE_IN_FRAME(offset, clnp.cnf_hdr_len)) { - if (check_col(fd, COL_INFO)) - col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); - dissect_data(pd, offset, fd, tree); - return; - } - - /* address part */ + calc_sum %= 255; /* modulo 255 divison */ - offset += P_ADDRESS_PART; - dst_len = pd[offset]; - nsel = pd[offset + dst_len]; - src_len = pd[offset + dst_len + 1]; - - if (tree) { - proto_tree_add_item(clnp_tree, hf_clnp_dest_length, offset, 1, - dst_len); - proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, offset + 1 , dst_len, - &pd[offset + 1], - "Destination address: %s", - print_nsap(&pd[offset + 1], dst_len)); - proto_tree_add_item(clnp_tree, hf_clnp_src_length, - offset + 1 + dst_len, 1, src_len); - proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, - offset + dst_len + 2, src_len, - &pd[offset + dst_len + 2], - "Source address: %s", - print_nsap(&pd[offset + dst_len + 2], src_len)); - } - - if (check_col(fd, COL_RES_NET_SRC)) - col_add_fstr(fd, COL_RES_NET_SRC, "%s", - print_nsap(&pd[offset + dst_len + 2], src_len)); - if (check_col(fd, COL_RES_NET_DST)) - col_add_fstr(fd, COL_RES_NET_DST, "%s", - print_nsap(&pd[offset + 1], dst_len)); - - /* Segmentation Part */ - - offset += dst_len + src_len + 2; - - if (clnp.cnf_type & CNF_SEG_OK) { - struct clnp_segment seg; /* XXX - not used */ - memcpy(&seg, &pd[offset], sizeof(seg)); /* XXX - not used */ - - segment_offset = EXTRACT_SHORT(&pd[offset + 2]); - if (tree) { - proto_tree_add_text(clnp_tree, offset, 2, - "Data unit identifier: 0x%04x", - EXTRACT_SHORT(&pd[offset])); - proto_tree_add_text(clnp_tree, offset + 2 , 2, - "Segment offset: %u", - segment_offset); - proto_tree_add_text(clnp_tree, offset + 4 , 2, - "Total length: %u", - EXTRACT_SHORT(&pd[offset + 4])); - } - - offset += 6; - } - - if (tree) { - /* To do : decode options */ - - proto_tree_add_text(clnp_tree, offset, - clnp.cnf_hdr_len + first_offset - offset, - "Options/Data: "); - } - - /* Length of CLNP datagram plus headers above it. */ - len = segment_length + first_offset; - - /* Set the payload and captured-payload lengths to the minima of (the - datagram length plus the length of the headers above it) and the - frame lengths. */ - if (pi.len > len) - pi.len = len; - if (pi.captured_len > len) - pi.captured_len = len; - - offset = first_offset + clnp.cnf_hdr_len; - - /* For now, dissect the payload of segments other than the initial - segment as data, rather than handing them off to the transport - protocol, just as we do with fragments other than the first - fragment in a fragmented IP datagram; in the future, we will - probably reassemble fragments for IP, and may reassemble segments - for CLNP. */ - if ((clnp.cnf_type & CNF_SEG_OK) && segment_offset != 0) { - if (check_col(fd, COL_INFO)) - col_add_fstr(fd, COL_INFO, "Fragmented %s NPDU %s(off=%u)", - pdu_type_string, flag_string, segment_offset); - dissect_data(pd, offset, fd, tree); - return; - } - - if (IS_DATA_IN_FRAME(offset)) { - switch (clnp.cnf_type & CNF_TYPE) { - - case DT_NPDU: - case MD_NPDU: - /* Continue with COTP if any data. - XXX - if this isn't the first Derived PDU of a segmented Initial - 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 */ - } - break; - - case ER_NPDU: - /* The payload is the header and "none, some, or all of the data - part of the discarded PDU", i.e. it's like an ICMP error; - just as we don't yet trust ourselves to be able to dissect - the payload of an ICMP error packet, we don't yet trust - ourselves to dissect the payload of a CLNP ER packet. */ - break; - - case ERQ_NPDU: - case ERP_NPDU: - /* XXX - dissect this */ - break; - } - } - if (check_col(fd, COL_INFO)) - col_add_fstr(fd, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string); - dissect_data(pd, offset, fd, tree); - -} /* dissect_clnp */ + if ( 0 == calc_sum ) + return( checksum_string[1] ); + else + return( checksum_string[2] ); +} /* main entry point */ @@ -1747,7 +217,7 @@ const value_string nlpid_vals[] = { { NLPID_ISO8473_CLNP, "CLNP" }, { NLPID_ISO9542_ESIS, "ESIS" }, { NLPID_ISO10589_ISIS, "ISIS" }, - { NLPID_ISO10747, "ISO 10747" }, + { NLPID_ISO10747_IDRP, "IDRP" }, { NLPID_ISO9542X25_ESIS, "ESIS (X.25)" }, { NLPID_ISO10030, "ISO 10030" }, { NLPID_ISO11577, "ISO 11577" }, @@ -1759,20 +229,16 @@ const value_string nlpid_vals[] = { void dissect_osi(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { - switch (pd[offset]) { - /* ESIS is not currently decoded */ + /* ESIS (X.25) is not currently decoded */ case NLPID_ISO8473_CLNP: case NLPID_NULL: /* "Inactive Subset" of ISO 8473 CLNP */ dissect_clnp(pd, offset, fd, tree); break; case NLPID_ISO9542_ESIS: - if (check_col(fd, COL_PROTOCOL)) { - col_add_str(fd, COL_PROTOCOL, "ESIS"); - } - dissect_data(pd, offset, fd, tree); + dissect_esis(pd, offset, fd, tree); break; case NLPID_ISO9542X25_ESIS: if (check_col(fd, COL_PROTOCOL)) { @@ -1783,6 +249,12 @@ void dissect_osi(const u_char *pd, int offset, frame_data *fd, case NLPID_ISO10589_ISIS: dissect_isis(pd, offset, fd, tree); break; + case NLPID_ISO10747_IDRP: + if (check_col(fd, COL_PROTOCOL)) { + col_add_str(fd, COL_PROTOCOL, "IDRP"); + } + dissect_data(pd, offset, fd, tree); + break; default: if (check_col(fd, COL_PROTOCOL)) { col_add_str(fd, COL_PROTOCOL, "ISO"); @@ -1793,76 +265,4 @@ void dissect_osi(const u_char *pd, int offset, frame_data *fd, dissect_data(pd, offset, fd, tree); break; } - } /* dissect_osi */ - -void proto_register_clnp(void) -{ - static hf_register_info hf[] = { - { &hf_clnp_id, - { "Protocol identifier", "clnp.id", FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, - "" }}, - - { &hf_clnp_length, - { "Length", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_clnp_version, - { "Version", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_clnp_ttl, - { "TTL", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_clnp_type, - { "Type code", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_clnp_pdu_length, - { "PDU segment length", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_clnp_checksum, - { "Checksum", "clnp.checksum",FT_UINT16, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_clnp_dest_length, - { "Destination address length", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_clnp_dest, - { "Destination address", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, - "" }}, - - { &hf_clnp_src_length, - { "Source address length","clnp.ssap.len",FT_UINT8, BASE_DEC, NULL, 0x0, - "" }}, - - { &hf_clnp_src, - { "Source address", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, - "" }}, - }; - static gint *ett[] = { - &ett_clnp, - }; - - proto_clnp = proto_register_protocol("ISO CLNP", "clnp"); - proto_register_field_array(proto_clnp, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); -} - -void proto_register_cotp(void) -{ - /* static hf_register_info hf[] = { - { &variable, - { "Name", "cotp.abbreviation", TYPE, VALS_POINTER }}, - };*/ - static gint *ett[] = { - &ett_cotp, - }; - - proto_cotp = proto_register_protocol("ISO COTP", "cotp"); - /* proto_register_field_array(proto_cotp, hf, array_length(hf));*/ - proto_register_subtree_array(ett, array_length(ett)); -} diff --git a/packet-osi.h b/packet-osi.h index 31ebed81a2..985a74ea66 100644 --- a/packet-osi.h +++ b/packet-osi.h @@ -1,6 +1,6 @@ /* packet-osi.h * - * $Id: packet-osi.h,v 1.1 2000/02/15 21:02:48 gram Exp $ + * $Id: packet-osi.h,v 1.2 2000/04/15 22:11:12 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -20,8 +20,92 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _PACKET_OSI_H +#define _PACKET_OSI_H + +/* OSI Global defines, common for all OSI protocols */ + +#define MAX_NSAP_LEN 30 +#define MAX_SYSTEMID_LEN 15 +#define MAX_AREA_LEN 30 + +#define RFC1237_NSAP_LEN 20 +#define RFC1237_FULLAREA_LEN 13 +#define RFC1237_SYSTEMID_LEN 6 +#define RFC1237_SELECTOR_LEN 1 + +#define RFC1237_IDI_LEN 2 +#define RFC1237_AFI_LEN 1 +#define RFC1237_DFI_LEN 1 +#define RFC1237_ORG_LEN 3 +#define RFC1237_AA_LEN 3 +#define RFC1237_RSVD_LEN 2 +#define RFC1237_RD_LEN 2 +#define RFC1237_AREA_LEN 3 + + +#define NSAP_IDI_ISODCC 0x39 +#define NSAP_IDI_GOSIP2 0x47 + +#define PDU_TYPE_ESIS_ESH 100 +#define PDU_TYPE_ESIS_ISH 101 +#define PDU_TYPE_ESIS_RD 102 + +#define PDU_TYPE_ISIS_L1_HELLO 201 +#define PDU_TYPE_ISIS_L2_HELLO 202 +#define PDU_TYPE_ISIS_PTP_HELLO 203 +#define PDU_TYPE_ISIS_L1_CSNP 204 +#define PDU_TYPE_ISIS_L1_PSNP 205 +#define PDU_TYPE_ISIS_L2_CSNP 206 +#define PDU_TYPE_ISIS_L2_PSNP 207 + + + + + +#define PROTO_STRING_ISIS "ISO 10598 ISIS InTRA Domain Routeing Information Exchange Protocol" +#define PROTO_STRING_IDRP "ISO 10747 IDRP InTER Domain Routeing Information Exchange Protocol" +#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_LSP "ISO 10598 ISIS Link State Protocol Data Unit" +#define PROTO_STRING_CSNP "ISO 10598 ISIS Complete Sequence Numbers Protocol Data Unit" +#define PROTO_STRING_PSNP "ISO 10598 ISIS Partial Sequence Numbers Protocol Data Unit" + +#define OSI_PDU_TYPE_MASK 0x1f +#define BIS_PDU_TYPE MASK 0xff + + +#define BIT_1 0x01 +#define BIT_2 0x02 +#define BIT_3 0x04 +#define BIT_4 0x08 +#define BIT_5 0x10 +#define BIT_6 0x20 +#define BIT_7 0x40 +#define BIT_8 0x80 + +#define BIT_9 0x0100 +#define BIT_10 0x0200 +#define BIT_11 0x0400 +#define BIT_12 0x0800 +#define BIT_13 0x1000 +#define BIT_14 0x2000 +#define BIT_15 0x4000 +#define BIT_16 0x8000 + + +/* + * published API functions */ +extern void dissect_osi( const u_char *, int, frame_data *, proto_tree *); +extern gchar *print_nsap_net ( const u_char *, int ); +extern gchar *print_area ( const u_char *, int ); +extern gchar *print_system_id( const u_char *, int ); +extern gchar *calc_checksum ( const u_char *, u_int, u_int ); + +#endif /* _PACKET_OSI_H */ -void dissect_cotp(const u_char *, int, frame_data *, proto_tree *); -void dissect_osi(const u_char *, int, frame_data *, proto_tree *); diff --git a/packet-x25.c b/packet-x25.c index 51141f7969..e6977c2c60 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.23 2000/04/13 18:18:53 gram Exp $ + * $Id: packet-x25.c,v 1.24 2000/04/15 22:11:12 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -40,6 +40,7 @@ #include "packet.h" #include "packet-ip.h" #include "packet-osi.h" +#include "packet-clnp.h" #include "nlpid.h" #define FROM_DCE 0x80