summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-dec-dnart.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-dec-dnart.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-dec-dnart.c')
-rw-r--r--epan/dissectors/packet-dec-dnart.c1487
1 files changed, 1487 insertions, 0 deletions
diff --git a/epan/dissectors/packet-dec-dnart.c b/epan/dissectors/packet-dec-dnart.c
new file mode 100644
index 00000000..bc6f82b2
--- /dev/null
+++ b/epan/dissectors/packet-dec-dnart.c
@@ -0,0 +1,1487 @@
+/* packet-dec-dnart.c
+ *
+ * Routines for DECnet NSP/RT disassembly
+ *
+ * Copyright 2003-2005 Philips Medical Systems
+ * Copyright 2003-2005 Fred Hoekstra, Philips Medical Systems.
+ * (fred.hoekstra@philips.com)
+ *
+ * Use was made of the following documentation:
+ *
+ * DECnet DIGITAL Network Architecture
+ * Routing Layer Functional Specification
+ * Version 2.0.0 May, 1983
+ *
+ * DECnet DIGITAL Network Architecture
+ * NSP Functional Specification
+ * Phase IV, Version 4.0.1, July 1984
+ *
+ * DNA FS SESSION CONTROL
+ * SECON.RNO [31,1]
+ * EDITED 10/17/80
+ *
+ * See
+ *
+ * http://h71000.www7.hp.com/wizard/decnet/
+ *
+ * for some DECnet specifications.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/etypes.h>
+#include <epan/expert.h>
+#include <epan/ppptypes.h>
+
+typedef enum {
+ RT_CTL_INITIALIZATION,
+ RT_CTL_VERIFICATION,
+ RT_CTL_HELLO_TEST,
+ RT_CTL_LVL1_ROUTING,
+ RT_CTL_LVL2_ROUTING,
+ RT_CTL_ETH_ROUTER_HELLO_MSG,
+ RT_CTL_ETH_ENDNODE_HELLO_MSG
+} ctl_msg_types;
+
+#define DEC_RT_SIZE 27
+
+#define DATA_SEGMENT_MSG 0x00 /* "Data segment" */
+#define LINK_SERVICE_MSG 0x10 /* "Link service message" */
+#define BOM_MSG 0x20 /* "Beginning of segment (BOM)message" */
+#define EOM_MSG 0x40 /* "End of segment (EOM)message" */
+#define BOM_EOM_MSG 0x60 /* "BOM / EOM message" */
+#define INTERRUPT_MSG 0x30 /* "Interrupt message" */
+#define DATA_ACK_MSG 0x04 /* "Data acknowledgement message" */
+#define OTHER_DATA_ACK_MSG 0x14 /* "Other data acknowledgement message" */
+#define CONN_ACK_MSG 0x24 /* "Connect acknowledgement message" */
+#define NOP_MSG 0x08 /* "NOP" */
+#define CONN_INITIATE_MSG 0x18 /* "Connect initiate" */
+#define CONN_CONFIRM_MSG 0x28 /* "Connect confirm" */
+#define DISCONN_INITIATE_MSG 0x38 /* "Disconnect initiate" */
+#define DISCONN_CONFIRM_MSG 0x48 /* "Disconnect confirm" */
+#define RE_XMT_CONN_INIT_MSG 0x68 /* "Retransmitted connect initiate" */
+
+/* Flag bits */
+
+#define RT_FLAGS_CTRL_MSG 0x01
+#define RT_FLAGS_LONG_MSG 0x04 /* Actually: 0x06->long, 0x02->short*/
+#define RT_FLAGS_RQR 0x08
+#define RT_FLAGS_RTS 0x10
+#define RT_FLAGS_INTRA_ETHER 0x20
+#define RT_FLAGS_DISCARD 0x40
+#define RT_FLAGS_PAD 0x80
+
+void proto_register_dec_rt(void);
+void proto_reg_handoff_dec_rt(void);
+
+static dissector_handle_t dec_rt_handle;
+
+static int proto_dec_rt = -1;
+
+static int hf_dec_routing_flags = -1;
+static int hf_dec_rt_ctrl_msg = -1;
+static int hf_dec_rt_long_msg = -1;
+static int hf_dec_rt_short_msg = -1;
+static int hf_dec_rt_rqr = -1;
+static int hf_dec_rt_rts = -1;
+static int hf_dec_rt_inter_eth = -1;
+static int hf_dec_rt_discard = -1;
+static int hf_dec_rt_dst_addr = -1;
+static int hf_dec_rt_src_addr = -1;
+static int hf_dec_rt_nl2 = -1;
+static int hf_dec_rt_service_class = -1;
+static int hf_dec_rt_protocol_type = -1;
+static int hf_dec_rt_visit_count = -1;
+static int hf_dec_rt_dst_node = -1;
+static int hf_dec_rt_src_node = -1;
+/* Routing control messages */
+static int hf_dec_rt_visited_nodes = -1;
+static int hf_dec_ctl_msgs = -1;
+static int hf_dec_ctl_msg_hdr = -1;
+static int hf_dec_nsp_msgs = -1;
+static int hf_dec_rt_tiinfo = -1;
+static int hf_dec_rt_blk_size = -1;
+static int hf_dec_rt_version = -1;
+static int hf_dec_rt_timer = -1;
+static int hf_dec_rt_reserved = -1;
+static int hf_dec_rt_fcnval = -1;
+static int hf_dec_rt_test_data = -1;
+static int hf_dec_rt_segment = -1;
+static int hf_dec_rt_checksum = -1;
+static int hf_dec_rt_checksum_status = -1;
+static int hf_dec_rt_id = -1;
+static int hf_dec_rt_iinfo = -1;
+static int hf_dec_rt_iinfo_node_type = -1;
+static int hf_dec_rt_iinfo_vrf = -1;
+static int hf_dec_rt_iinfo_rej = -1;
+static int hf_dec_rt_iinfo_verf = -1;
+static int hf_dec_rt_iinfo_mta = -1;
+static int hf_dec_rt_iinfo_blkreq = -1;
+static int hf_dec_rt_iprio = -1;
+static int hf_dec_rt_neighbor = -1;
+static int hf_dec_rt_seed = -1;
+static int hf_dec_rt_elist = -1;
+static int hf_dec_rt_ename = -1;
+static int hf_dec_rt_router_id = -1;
+static int hf_dec_rt_router_state = -1;
+static int hf_dec_rt_router_prio = -1;
+static int hf_dec_rt_seg_size = -1;
+static int hf_dec_rt_acknum = -1;
+static int hf_dec_rt_segnum = -1;
+static int hf_dec_rt_delay = -1;
+static int hf_dec_flow_control = -1;
+static int hf_dec_rt_fc_val = -1;
+static int hf_dec_rt_services = -1;
+static int hf_dec_rt_info = -1;
+static int hf_dec_disc_reason = -1;
+static int hf_dec_conn_contents = -1;
+static int hf_dec_sess_obj_type = -1;
+static int hf_dec_sess_grp_code = -1;
+static int hf_dec_sess_usr_code = -1;
+static int hf_dec_sess_dst_name = -1;
+static int hf_dec_sess_src_name = -1;
+static int hf_dec_sess_menu_ver = -1;
+static int hf_dec_sess_rqstr_id = -1;
+
+static gint ett_dec_rt = -1;
+static gint ett_dec_routing_flags = -1;
+static gint ett_dec_msg_flags = -1;
+static gint ett_dec_rt_ctl_msg = -1;
+static gint ett_dec_rt_nsp_msg = -1;
+static gint ett_dec_rt_info_flags = -1;
+static gint ett_dec_rt_list = -1;
+static gint ett_dec_rt_rlist = -1;
+static gint ett_dec_rt_state = -1;
+static gint ett_dec_flow_control = -1;
+static gint ett_dec_sess_contents = -1;
+
+static expert_field ei_dec_rt_checksum = EI_INIT;
+
+static gint dec_dna_total_bytes_this_segment = 0;
+static gint dec_dna_previous_total = 0;
+
+static const value_string rt_msg_type_vals[] = {
+ { 0x0 , "Initialization message" },
+ { 0x1 , "Verification message" },
+ { 0x2 , "Hello and test message" },
+ { 0x3 , "Level 1 routing message" },
+ { 0x4 , "Level 2 routing message" },
+ { 0x5 , "Ethernet router hello message" },
+ { 0x6 , "Ethernet endnode hello message" },
+ { 0, NULL }
+};
+
+static const value_string nsp_msg_type_vals[] = {
+ { 0x00 , "Data segment continuation" },
+ { 0x04 , "Data acknowledgement message" },
+ { 0x08 , "NOP" },
+ { 0x10 , "Link service message" },
+ { 0x14 , "Other data acknowledgement message" },
+ { 0x18 , "Connect initiate" },
+ { 0x20 , "Beginning of segment message" },
+ { 0x24 , "Connect acknowledgement message" },
+ { 0x28 , "Connect confirm" },
+ { 0x30 , "Interrupt message" },
+ { 0x38 , "Disconnect initiate" },
+ { 0x40 , "End of segment message" },
+ { 0x48 , "Disconnect confirm" },
+ { 0x60 , "Begin of segment / End of segment" },
+ { 0x68 , "Retransmitted connect initiate" },
+ { 0, NULL }
+};
+
+static const value_string rt_tiinfo_vals[] = {
+ {0x01, "Level 2 router"},
+ {0x02, "Level 1 router"},
+ {0x03, "End node"},
+ {0x04, "Routing layer verification required"},
+ {0x08, "Blocking requested"},
+ {0x0, NULL}
+};
+
+static const value_string rt_iinfo_node_type_vals[] = {
+ {0x01, "Level 2 router"},
+ {0x02, "Level 1 router"},
+ {0x03, "End node"},
+ {0x0, NULL}
+};
+
+static const value_string rt_flow_control_vals[] = {
+ {0x00, "no change"},
+ {0x01, "do not send data"},
+ {0x02, "send data"},
+ {0x03, "reserved"},
+ {0x0, NULL}
+};
+
+static const value_string rt_services_vals[] = {
+ {0x00, "none"},
+ {0x04, "segment request count"},
+ {0x08, "Session control message request count"},
+ {0x0c, "reserved"},
+ {0x0, NULL}
+};
+
+static const value_string rt_info_version_vals[] = {
+ {0x00, "version 3.2"},
+ {0x01, "version 3.1"},
+ {0x02, "version 4.0"},
+ {0x03, "reserved"},
+ {0x0, NULL}
+};
+
+static const value_string rt_disc_reason_vals[] = {
+ { 0, "no error"},
+ { 3, "The node is shutting down"},
+ { 4, "The destination end user does not exist"},
+ { 5, "A connect message contains an invalid end user name"},
+ { 6, "Destination end user has insufficient resources"},
+ { 7, "Unspecified error"},
+ { 8, "A third party has disconnected the link"},
+ { 9, "An end user has aborted the logical link"},
+ { 32, "The node has insufficient resources"},
+ { 33, "Destination end user has insufficient resources"},
+ { 34, "Connect request rejected because incorrect RQSTRID or PASSWORD"},
+ { 36, "Connect request rejected because of unacceptable ACCOUNT info"},
+ { 38, "End user has timed out, aborted or cancelled a connect request"},
+ { 43, "Connect request RQSTRID, PASSWORD, ACCOUNT or USRDATA too long"},
+ { 0, NULL}
+};
+
+#define RT_TYPE_TOPOLOGY_CHANGE 2
+#define RT_TYPE_HELLO 25
+
+#if ! defined true
+#define true 1
+#endif
+#if ! defined false
+#define false 0
+#endif
+
+static int
+handle_nsp_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint offset,
+ guint8 nsp_msg_type);
+
+
+static int
+do_initialization_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *ctl_msg_tree,
+ guint offset);
+
+static int
+do_verification_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *ctl_msg_tree,
+ guint offset);
+
+static int
+do_hello_test_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *ctl_msg_tree,
+ guint offset);
+
+static int
+do_routing_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *ctl_msg_tree,
+ guint offset,
+ guint msg);
+
+static int
+do_hello_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *ctl_msg_tree,
+ guint offset,
+ guint msg);
+
+static int
+handle_connect_contents(
+ tvbuff_t *tvb,
+ proto_tree *tree,
+ guint offset);
+
+static int
+handle_disc_init_contents(
+ guint offset);
+
+static char *
+dnet_ntoa(wmem_allocator_t *pool, const guint8 *data)
+{
+ if (data[0] == 0xAA && data[1] == 0x00 && data[2] == 0x04 && data[3] == 0x00) {
+ guint16 dnet_addr = data[4] | (data[5] << 8);
+ return wmem_strdup_printf(pool, "%d.%d", dnet_addr >> 10, dnet_addr & 0x03FF);
+ }
+ return NULL;
+}
+
+static void
+set_dnet_address(packet_info *pinfo, address *paddr_src, address *paddr_tgt)
+{
+ if (paddr_tgt->type != AT_STRINGZ && paddr_src->type == AT_ETHER) {
+ char *addr = dnet_ntoa(pinfo->pool, (const guint8 *)paddr_src->data);
+ if (addr != NULL)
+ set_address(paddr_tgt, AT_STRINGZ, 1,
+ wmem_strdup(pinfo->pool, addr));
+ }
+}
+
+static int
+dissect_dec_rt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ guint8 padding_length;
+ guint8 forward;
+ guint8 msg_flags;
+ guint rt_visit_count, rt_zero = 0;
+ gint offset;
+ proto_tree *rt_tree;
+ proto_tree *flags_tree;
+ proto_item *ti;
+ char *addr;
+
+ offset = 0;
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DEC DNA");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ set_dnet_address(pinfo, &pinfo->dl_src, &pinfo->net_src);
+ set_dnet_address(pinfo, &pinfo->dl_src, &pinfo->src);
+ set_dnet_address(pinfo, &pinfo->dl_dst, &pinfo->net_dst);
+ set_dnet_address(pinfo, &pinfo->dl_dst, &pinfo->dst);
+
+ offset += 2;
+ msg_flags = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_item(tree, proto_dec_rt, tvb, 0, -1, ENC_NA);
+ rt_tree = proto_item_add_subtree(ti, ett_dec_rt);
+ /* When padding, the first byte after the padding has
+ the real routing flags */
+ if (msg_flags & 0x80) {
+ /* There is padding present, skip it */
+ padding_length = msg_flags & 0x7f;
+ offset += padding_length;
+ }
+
+ /* The real routing flag */
+ msg_flags = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_uint(rt_tree, hf_dec_routing_flags, tvb,
+ offset, 1, msg_flags);
+ flags_tree = proto_item_add_subtree(ti, ett_dec_routing_flags);
+
+ if (msg_flags & RT_FLAGS_CTRL_MSG) {
+ guint8 ctl_msg_type;
+ proto_tree *ctl_msg_tree;
+
+ ctl_msg_type = (msg_flags >> 1) & 0x7;
+ proto_tree_add_boolean(flags_tree, hf_dec_rt_ctrl_msg, tvb, offset, 1,
+ msg_flags);
+ proto_tree_add_uint(flags_tree, hf_dec_ctl_msgs, tvb, offset, 1,
+ msg_flags);
+
+ ti = proto_tree_add_uint(rt_tree, hf_dec_ctl_msg_hdr, tvb, offset, 1,
+ ctl_msg_type);
+ ctl_msg_tree = proto_item_add_subtree(ti, ett_dec_rt_ctl_msg);
+
+ /* Get past the msg_flags */
+ offset++;
+ switch (ctl_msg_type) {
+ case RT_CTL_INITIALIZATION:
+ do_initialization_msg(
+ tvb, pinfo, ctl_msg_tree, offset);
+ break;
+ case RT_CTL_VERIFICATION:
+ do_verification_msg(
+ tvb, pinfo, ctl_msg_tree, offset);
+ break;
+ case RT_CTL_HELLO_TEST:
+ do_hello_test_msg(
+ tvb, pinfo, ctl_msg_tree, offset);
+ break;
+ case RT_CTL_LVL1_ROUTING:
+ case RT_CTL_LVL2_ROUTING:
+ do_routing_msg(
+ tvb, pinfo, ctl_msg_tree, offset, msg_flags >> 1);
+ break;
+ case RT_CTL_ETH_ROUTER_HELLO_MSG:
+ case RT_CTL_ETH_ENDNODE_HELLO_MSG:
+ do_hello_msg(
+ tvb, pinfo, ctl_msg_tree, offset, msg_flags >> 1);
+ break;
+ default:
+ break;
+ }
+ } else if (msg_flags & RT_FLAGS_LONG_MSG){
+ static int * const msg_bit_flags[] = {
+ &hf_dec_rt_long_msg,
+ &hf_dec_rt_rqr,
+ &hf_dec_rt_rts,
+ &hf_dec_rt_inter_eth,
+ &hf_dec_rt_discard,
+ NULL
+ };
+
+ proto_tree_add_bitmask_list_value(flags_tree, tvb, offset, 1, msg_bit_flags, msg_flags);
+
+ /* Increment offset by three:
+ 1 to get past the flags field
+ 2 to skip the DEC area/subarea field
+ */
+ offset += 3;
+ ti = proto_tree_add_item(rt_tree, hf_dec_rt_dst_addr, tvb,
+ offset, 6, ENC_NA);
+ addr = dnet_ntoa(pinfo->pool, (const guint8 *)tvb_memdup(pinfo->pool, tvb, offset, 6));
+ if (addr != NULL) {
+ proto_item_append_text(ti, " (%s)", addr);
+ }
+
+ /* Skip 6 bytes for the MAC and
+ 2 bytes for DEC area/subarea
+ */
+ offset += 8;
+ ti = proto_tree_add_item(rt_tree, hf_dec_rt_src_addr, tvb,
+ offset, 6, ENC_NA);
+ addr = dnet_ntoa(pinfo->pool, (const guint8 *)tvb_memdup(pinfo->pool, tvb, offset, 6));
+ if (addr != NULL) {
+ proto_item_append_text(ti, " (%s)", addr);
+ }
+
+ /* Proceed to the NL2 byte */
+ offset += 6;
+ proto_tree_add_uint(rt_tree, hf_dec_rt_nl2, tvb,
+ offset, 1, rt_zero);
+ offset++;
+ rt_visit_count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(rt_tree, hf_dec_rt_visit_count, tvb,
+ offset, 1, rt_visit_count);
+ offset++;
+ proto_tree_add_uint(rt_tree, hf_dec_rt_service_class, tvb,
+ offset, 1, rt_zero);
+ offset++;
+ proto_tree_add_uint(rt_tree, hf_dec_rt_protocol_type, tvb,
+ offset, 1, rt_zero);
+ offset++;
+ } else {
+ proto_tree_add_uint(flags_tree, hf_dec_rt_short_msg,
+ tvb, offset, 1, msg_flags);
+ proto_tree_add_boolean(flags_tree, hf_dec_rt_rqr, tvb,
+ offset, 1, msg_flags);
+ proto_tree_add_boolean(flags_tree, hf_dec_rt_rts, tvb,
+ offset, 1, msg_flags);
+
+ /* Increment offset to get past the flags field
+ */
+ offset++;
+ proto_tree_add_item(rt_tree, hf_dec_rt_dst_node, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(rt_tree, hf_dec_rt_src_node, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ forward = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(rt_tree, hf_dec_rt_visited_nodes, tvb,
+ offset, 1, forward);
+ offset++;
+ }
+
+ if (!(msg_flags & RT_FLAGS_CTRL_MSG)) {
+ /* It is not a routing control message */
+ proto_tree *nsp_msg_tree;
+ proto_item *ti_local;
+ guint8 nsp_msg_type;
+
+ nsp_msg_type = tvb_get_guint8(tvb, offset);
+ ti_local = proto_tree_add_uint(
+ tree, hf_dec_nsp_msgs, tvb, offset, 1, nsp_msg_type);
+ if (nsp_msg_type == NOP_MSG) {
+ /* Only test data in this msg */
+ return offset;
+ }
+ nsp_msg_tree = proto_item_add_subtree(ti_local, ett_dec_rt_nsp_msg);
+ /* Get past the nsp_msg_type */
+ offset++;
+ proto_tree_add_item(nsp_msg_tree, hf_dec_rt_dst_node, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+ if (nsp_msg_type == CONN_ACK_MSG) {
+ col_set_str(pinfo->cinfo, COL_INFO, "NSP connect acknowledgement");
+ /* Done with this msg type */
+ return offset;
+ }
+ /* All other messages have a source node */
+ proto_tree_add_item(nsp_msg_tree, hf_dec_rt_src_node, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ handle_nsp_msg(tvb,
+ pinfo,
+ nsp_msg_tree,
+ offset,
+ nsp_msg_type);
+ }
+ return tvb_captured_length(tvb);
+}
+
+static int
+do_initialization_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint offset)
+{
+ guint my_offset = offset;
+ guint8 version, eco_nr, user_eco;
+ guint8 remainder_count;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Routing control, initialization message");
+ proto_tree_add_item(tree, hf_dec_rt_src_node, tvb,
+ my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ proto_tree_add_item(tree, hf_dec_rt_tiinfo, tvb,
+ my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ proto_tree_add_item(tree, hf_dec_rt_blk_size, tvb,
+ my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ version = tvb_get_guint8(tvb, my_offset);
+ eco_nr = tvb_get_guint8(tvb, my_offset + 1);
+ user_eco = tvb_get_guint8(tvb, my_offset + 2);
+ proto_tree_add_none_format(tree, hf_dec_rt_version, tvb,
+ my_offset, 3, "Routing Layer version: %d.%d.%d.",
+ version, eco_nr, user_eco);
+ my_offset +=3;
+ proto_tree_add_item(tree, hf_dec_rt_timer, tvb,
+ my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ remainder_count = tvb_get_guint8(tvb, my_offset);
+ if (remainder_count != 0) {
+ proto_tree_add_item(tree, hf_dec_rt_reserved, tvb,
+ my_offset, remainder_count, ENC_NA);
+ my_offset += remainder_count;
+ }
+ return (my_offset);
+}
+
+static int
+do_verification_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint offset)
+{
+ guint my_offset = offset;
+ guint8 remainder_count;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Routing control, verification message");
+ proto_tree_add_item(tree, hf_dec_rt_src_node, tvb,
+ my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ remainder_count = tvb_get_guint8(tvb, my_offset);
+ if (remainder_count != 0) {
+ proto_tree_add_item(tree, hf_dec_rt_fcnval, tvb,
+ my_offset, remainder_count, ENC_NA);
+ my_offset += remainder_count;
+ }
+ return (my_offset);
+}
+
+static int
+do_hello_test_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint offset)
+{
+ guint my_offset = offset;
+ guint remainder_count;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Routing control, hello/test message");
+ proto_tree_add_item(tree, hf_dec_rt_src_node, tvb,
+ my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ remainder_count = tvb_reported_length_remaining(tvb, my_offset);
+ if (remainder_count != 0) {
+ proto_tree_add_item(tree, hf_dec_rt_test_data, tvb,
+ my_offset, remainder_count, ENC_NA);
+ my_offset += remainder_count;
+ }
+ return (my_offset);
+}
+
+static int
+do_routing_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint offset,
+ guint msg)
+{
+ guint my_offset = offset;
+ guint32 my_checksum = 1;
+ guint16 count, startid, rtginfo;
+ guint remainder_count;
+
+ proto_tree_add_item(tree, hf_dec_rt_src_node, tvb,
+ my_offset, 2, ENC_LITTLE_ENDIAN);
+ /* Skip the 1-byte reserved field */
+ my_offset += 3;
+ remainder_count = tvb_reported_length_remaining(tvb, my_offset);
+ do {
+ /* if the remainder_count == 1, only the checksum remains */
+ count = tvb_get_letohs(tvb, my_offset);
+ startid = tvb_get_letohs(tvb, my_offset + 2);
+ rtginfo = tvb_get_letohs(tvb, my_offset + 4);
+ if (msg == 3) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Routing control, Level 1 routing message");
+ proto_tree_add_none_format(tree, hf_dec_rt_segment, tvb,
+ my_offset, 6,
+ "Segment: count:%d, start Id: %d, hops:%d, cost: %d",
+ count, startid, (rtginfo & 0x7c00) >> 10, rtginfo & 0x3ff);
+ } else {
+ col_set_str(pinfo->cinfo, COL_INFO, "Routing control, Level 2 routing message");
+ proto_tree_add_none_format(tree, hf_dec_rt_segment, tvb,
+ my_offset, 6,
+ "Segment: count:%d, start area: %d, hops:%d, cost: %d",
+ count, startid, (rtginfo & 0x7c00) >> 10, rtginfo & 0x3ff);
+ };
+ my_checksum += (count + startid + rtginfo);
+ my_offset += 6;
+ remainder_count -= 6;
+ } while (remainder_count > 6);
+ my_offset += remainder_count - 2;
+ /* fold 32 bit sum into 16 bits */
+ while (my_checksum>>16)
+ my_checksum = (my_checksum & 0xffff) + (my_checksum >> 16);
+
+ proto_tree_add_checksum(tree, tvb, my_offset, hf_dec_rt_checksum, hf_dec_rt_checksum_status, &ei_dec_rt_checksum, pinfo, my_checksum, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
+ my_offset += 2;
+ return (my_offset);
+}
+
+static int
+do_hello_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint offset,
+ guint msg)
+{
+ guint my_offset = offset;
+ guint8 priority;
+ guint16 version, eco_nr, user_eco;
+ proto_item *ti;
+ char *addr;
+ static int * const info_flags[] = {
+ &hf_dec_rt_iinfo_node_type,
+ &hf_dec_rt_iinfo_vrf,
+ &hf_dec_rt_iinfo_rej,
+ &hf_dec_rt_iinfo_verf,
+ &hf_dec_rt_iinfo_mta,
+ &hf_dec_rt_iinfo_blkreq,
+ NULL
+ };
+
+ version = tvb_get_guint8(tvb, my_offset);
+ eco_nr = tvb_get_guint8(tvb, my_offset + 1);
+ user_eco = tvb_get_guint8(tvb, my_offset + 2);
+ proto_tree_add_none_format(tree, hf_dec_rt_version, tvb,
+ my_offset, 3, "Routing Layer Version: %d.%d.%d",
+ version, eco_nr, user_eco);
+ my_offset +=3;
+ ti = proto_tree_add_item(tree, hf_dec_rt_id, tvb,
+ my_offset, 6, ENC_NA);
+ addr = dnet_ntoa(pinfo->pool, (const guint8 *)tvb_memdup(pinfo->pool, tvb, my_offset, 6));
+ if (addr != NULL) {
+ proto_item_append_text(ti, " (%s)", addr);
+ }
+ my_offset += 6;
+ proto_tree_add_bitmask(tree, tvb, my_offset, hf_dec_rt_iinfo, ett_dec_rt_info_flags, info_flags, ENC_NA);
+ my_offset++;
+
+ proto_tree_add_item(tree, hf_dec_rt_blk_size, tvb,
+ my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ if (msg == 5) {
+ /* Ethernet router hello message
+ Has a 'priority' field in this position */
+ col_set_str(pinfo->cinfo, COL_INFO, "Routing control, Ethernet Router Hello message");
+ priority = tvb_get_guint8(tvb, my_offset);
+ proto_tree_add_uint(
+ tree, hf_dec_rt_iprio, tvb, my_offset, 1, priority);
+ my_offset++;
+ }
+ /* Skip the 'area' field common to both hello messages */
+ my_offset += 1;
+ if (msg == 6) {
+ /* The endnode hello message has 'seed' and 'neighbor' fields */
+ col_set_str(pinfo->cinfo, COL_INFO, "Routing control, Endnode Hello message");
+ proto_tree_add_item(tree, hf_dec_rt_seed, tvb,
+ my_offset, 8, ENC_NA);
+ my_offset += 8;
+ ti = proto_tree_add_item(tree, hf_dec_rt_neighbor, tvb,
+ my_offset, 6, ENC_NA);
+ addr = dnet_ntoa(pinfo->pool, (const guint8 *)tvb_memdup(pinfo->pool, tvb, my_offset, 6));
+ if (addr != NULL) {
+ proto_item_append_text(ti, " (%s)", addr);
+ }
+ my_offset += 6;
+ }
+ /*'Timer' and 'mpd' fields are common
+ 'mpd' field is reserved */
+ proto_tree_add_item(tree, hf_dec_rt_timer, tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 3;
+ if (msg == 5) {
+ /* The Ethernet router hello message contains
+ a list of router states
+ The Ethernet Endnode Hello Message contains
+ up to 128 bytes of test data at the end.
+ These data are left to be dissected as 'data'.
+ */
+ proto_item *ti_locala, *ti_ether;
+ proto_tree *list_tree, *list_ether;
+ guint8 image_len;
+ guint8 item_len;
+
+ /* image field is preceded by count of remainder of field */
+ image_len = tvb_get_guint8(tvb, my_offset);
+ my_offset++;
+
+ ti_locala = proto_tree_add_item(tree, hf_dec_rt_elist, tvb,
+ my_offset, image_len, ENC_NA);
+ list_tree = proto_item_add_subtree(ti_locala, ett_dec_rt_list);
+
+ while (image_len > 0) {
+ ti_ether = proto_tree_add_item(list_tree, hf_dec_rt_ename, tvb,
+ my_offset, 7, ENC_NA);
+ list_ether = proto_item_add_subtree(ti_ether, ett_dec_rt_rlist);
+ my_offset += 7;
+ image_len -= 7;
+
+ /* image field is preceded by count of remainder of field */
+ item_len = tvb_get_guint8(tvb, my_offset);
+ my_offset++;
+ image_len -= 1;
+ while (item_len > 0)
+ {
+ guint8 pristate;
+ proto_item *ti_localb;
+ proto_tree *pstate_tree;
+
+ ti_localb = proto_tree_add_item(list_ether, hf_dec_rt_router_id,
+ tvb, my_offset, 6, ENC_NA);
+ addr = dnet_ntoa(pinfo->pool, (const guint8 *)tvb_memdup(pinfo->pool, tvb, my_offset, 6));
+ if (addr != NULL) {
+ proto_item_append_text(ti_localb, " (%s)", addr);
+ }
+ my_offset += 6;
+ pstate_tree = proto_item_add_subtree(ti_localb, ett_dec_rt_state);
+ pristate = tvb_get_guint8(tvb, my_offset);
+ proto_tree_add_string(pstate_tree, hf_dec_rt_router_state,
+ tvb, my_offset, 1,
+ ((pristate & 0x80) ? "known 2-way": "unknown"));
+ proto_tree_add_uint(pstate_tree, hf_dec_rt_router_prio,
+ tvb, my_offset, 1, pristate);
+ my_offset++;
+ item_len -= 7;
+ image_len -= 7;
+ }
+ }
+ }
+ return (my_offset);
+}
+
+static int
+handle_nsp_msg(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint offset,
+ guint8 nsp_msg_type)
+{
+ /* Offset in tvb now points at the first byte still to be handled */
+ guint my_offset = offset;
+ gint data_length;
+ guint16 ack_num, ack_dat, ack_oth, seg_num;
+ guint8 ls_flags, fc_val, services;
+ proto_item *ti;
+ proto_tree *flow_control_tree;
+
+ /* 'tree' is now the subtree for the NSP message */
+ switch (nsp_msg_type) {
+ case DATA_SEGMENT_MSG: /* "Data segment" */
+ case BOM_MSG: /* "Beginning of segment message" */
+ case EOM_MSG: /* "End of segment message" */
+ case BOM_EOM_MSG: /* "BOM / EOM message" */
+ ack_num = tvb_get_letohs(tvb, my_offset);
+ if (ack_num & 0x8000) {
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Last data segment %s acknowledged: %d",
+ (ack_num & 0x1000) ? "negatively" : "positively",
+ ack_num & 0xfff);
+ my_offset += 2;
+ /* There may still be an ackoth field */
+ ack_oth = tvb_get_letohs(tvb, my_offset);
+ if (ack_oth & 0x8000) {
+ /* There is an ack_oth field */
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Cross sub-channel %s of other data msg %d",
+ ((ack_oth & 0x3000) == 0x2000) ? "ACK" : "NAK",
+ ack_oth & 0xfff);
+ my_offset += 2;
+ }
+ }
+ /*
+ * The optional ACKNUM and ACKOTH fields are not present
+ * There is still the segnum field
+ */
+ seg_num = tvb_get_letohs(tvb, my_offset);
+ if (nsp_msg_type == BOM_MSG) {
+ dec_dna_total_bytes_this_segment = 0;
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "msg nr. %d: start of segment",
+ seg_num & 0xfff);
+ } else if (nsp_msg_type == DATA_SEGMENT_MSG) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "msg nr. %d: continuation segment ",
+ seg_num & 0xfff);
+ } else if (nsp_msg_type == EOM_MSG) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "msg nr. %d: end of segment",
+ seg_num & 0xfff);
+ } else if (nsp_msg_type == BOM_EOM_MSG) {
+ dec_dna_total_bytes_this_segment = 0;
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "msg nr. %d single segment",
+ seg_num & 0xfff);
+ }
+ /* This is the last field, the rest are data */
+ proto_tree_add_item(tree, hf_dec_rt_segnum,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(tree, hf_dec_rt_delay,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ /* Compute the number of bytes in this data segment */
+ data_length =
+ tvb_reported_length_remaining(tvb, my_offset);
+ dec_dna_previous_total = dec_dna_total_bytes_this_segment;
+ dec_dna_total_bytes_this_segment += data_length;
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", bytes this segment: %d, total so far:%d",
+ data_length, dec_dna_total_bytes_this_segment);
+ /* We are done, return my_offset */
+ break;
+ case INTERRUPT_MSG: /* "Interrupt message" */
+ col_set_str(pinfo->cinfo, COL_INFO, "NSP interrupt message");
+ ack_num = tvb_get_letohs(tvb, my_offset);
+ if (ack_num & 0x8000) {
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Last interrupt/link service msg %s acknowledged: %d",
+ (ack_num & 0x1000) ? "negatively" : "positively",
+ ack_num & 0xfff);
+ my_offset += 2;
+ /* There may still be an ack_dat field */
+ } else {
+ /* There are no ack/nak fields */
+ proto_tree_add_item(tree, hf_dec_rt_segnum,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(tree, hf_dec_rt_delay,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ /* We are done, return my_offset */
+ break;
+ }
+ ack_dat = tvb_get_letohs(tvb, my_offset);
+ if (ack_dat & 0x8000) {
+ /* There is an ack_dat field */
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Cross sub-channel %s of data segment msg: %d",
+ ((ack_dat & 0x3000) == 0x2000) ? "ACK" : "NAK",
+ ack_dat & 0xfff);
+ my_offset += 2;
+ }
+ /* This is the last field, the rest are data */
+ proto_tree_add_item(tree, hf_dec_rt_segnum,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(tree, hf_dec_rt_delay,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ /* We are done, return my_offset */
+ break;
+ case LINK_SERVICE_MSG: /* "Link service message" */
+ col_set_str(pinfo->cinfo, COL_INFO, "NSP link control message");
+ ack_num = tvb_get_letohs(tvb, my_offset);
+ if (ack_num & 0x8000) {
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Last interrupt/link service msg %s acknowledged: %d",
+ (ack_num & 0x1000) ? "negatively" : "positively",
+ ack_num & 0xfff);
+ my_offset += 2;
+ /* There may still be an ack_dat field */
+ } else {
+ /* There are no ack/nak fields */
+ proto_tree_add_item(tree, hf_dec_rt_segnum,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(tree, hf_dec_rt_delay,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ /* We are done, return my_offset */
+ break;
+ }
+ ack_dat = tvb_get_letohs(tvb, my_offset);
+ if (ack_dat & 0x8000) {
+ /* There is an ack_dat field */
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Cross sub-channel %s of data segment msg: %d",
+ ((ack_dat & 0x3000) == 0x2000) ? "ACK" : "NAK",
+ ack_dat & 0xfff);
+ my_offset += 2;
+ }
+ proto_tree_add_item(tree, hf_dec_rt_segnum,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(tree, hf_dec_rt_delay,
+ tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ /* Now follows the ls_flags field */
+ ls_flags = tvb_get_guint8(tvb, my_offset);
+ switch(ls_flags) {
+ case 0: /* no change */
+ col_append_str(pinfo->cinfo, COL_INFO,
+ "(no change)");
+ break;
+ case 1: /* stop sending data */
+ col_append_str(pinfo->cinfo, COL_INFO,
+ "(stop)");
+ break;
+ case 2: /* send data */
+ col_append_str(pinfo->cinfo, COL_INFO,
+ "(go)");
+ break;
+ default:
+ break;
+ }
+ fc_val = tvb_get_guint8(tvb, my_offset + 1);
+ ti = proto_tree_add_uint(tree, hf_dec_flow_control, tvb,
+ my_offset, 1, ls_flags);
+ flow_control_tree =
+ proto_item_add_subtree(ti, ett_dec_flow_control);
+ proto_tree_add_none_format(flow_control_tree, hf_dec_rt_fc_val,
+ tvb, my_offset, 2,
+ "Request for additional %d %s msgs",
+ fc_val, ((ls_flags & 0x04) ? "interrupt" : "data"));
+ my_offset += 2;
+ break;
+ case DATA_ACK_MSG: /* "Data acknowledgement message" */
+ ack_num = tvb_get_letohs(tvb, my_offset);
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Last data segment %s acknowledged: %d",
+ (ack_num & 0x1000) ? "negatively" : "positively",
+ ack_num & 0xfff);
+ my_offset += 2;
+ /* There may be an optional ack_oth field */
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "NSP data %s message(%d)",
+ (ack_num & 0x1000) ? "NAK" : "ACK",
+ ack_num & 0xfff);
+
+ if (tvb_reported_length_remaining(tvb, my_offset) > 0) {
+ ack_oth = tvb_get_letohs(tvb, my_offset);
+ if (ack_oth & 0x8000) {
+ /* There is an ack_oth field */
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Cross sub-channel %s of other data msg %d",
+ ((ack_oth & 0x3000) == 0x2000) ? "ACK" : "NAK",
+ ack_oth & 0xfff);
+ my_offset += 2;
+ }
+ }
+ /* We are done, return my_offset */
+ break;
+ case OTHER_DATA_ACK_MSG: /* "Other data acknowledgement message" */
+ col_set_str(pinfo->cinfo, COL_INFO, "NSP other data ACK message");
+ ack_num = tvb_get_letohs(tvb, my_offset);
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Last interrupt/link service msg %s acknowledged: %d",
+ (ack_num & 0x1000) ? "negatively" : "positively",
+ ack_num & 0xfff);
+ my_offset += 2;
+ /* There may be an optional ack_dat field */
+ if (tvb_reported_length_remaining(tvb, my_offset) > 0) {
+ ack_dat = tvb_get_letohs(tvb, my_offset);
+ if (ack_dat & 0x8000) {
+ /* There is an ack_dat field */
+ proto_tree_add_none_format(tree, hf_dec_rt_acknum,
+ tvb, my_offset, 2,
+ "Cross sub-channel %s of data msg %d",
+ ((ack_dat & 0x3000) == 0x2000) ? "ACK" : "NAK",
+ ack_dat & 0xfff);
+ my_offset += 2;
+ }
+ }
+ /* We are done, return my_offset */
+ break;
+ case CONN_CONFIRM_MSG: /* "Connect confirm" */
+ case CONN_INITIATE_MSG: /* "Connect initiate" */
+ col_set_str(pinfo->cinfo, COL_INFO, "NSP connect confirm/initiate message");
+ services = tvb_get_guint8(tvb, my_offset);
+ proto_tree_add_uint(tree, hf_dec_rt_services, tvb,
+ my_offset, 1, services);
+ my_offset++;
+ proto_tree_add_item(tree, hf_dec_rt_info, tvb, my_offset, 1, ENC_LITTLE_ENDIAN);
+ my_offset++;
+ proto_tree_add_item(tree, hf_dec_rt_seg_size, tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ my_offset = handle_connect_contents(tvb, tree, my_offset);
+ break;
+ case DISCONN_INITIATE_MSG: /* "Disconnect initiate" */
+ case DISCONN_CONFIRM_MSG: /* "Disconnect confirm" */
+ col_set_str(pinfo->cinfo, COL_INFO, "NSP disconnect initiate/confirm message");
+ proto_tree_add_item(tree, hf_dec_disc_reason, tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ if (nsp_msg_type == DISCONN_INITIATE_MSG) {
+ my_offset =
+ handle_disc_init_contents( my_offset);
+ }
+ break;
+ default:
+ break;
+ }
+ return (my_offset);
+}
+
+static int
+handle_connect_contents(
+ tvbuff_t *tvb,
+ proto_tree *tree,
+ guint offset)
+{
+ guint my_offset = offset;
+ proto_item *ti;
+ proto_tree *contents_tree;
+ guint8 dst_format, src_format, obj_type, image_len, menu_ver;
+
+ ti = proto_tree_add_item(tree, hf_dec_conn_contents,
+ tvb, my_offset, -1, ENC_NA);
+ contents_tree = proto_item_add_subtree(ti, ett_dec_sess_contents);
+ /* The destination end user */
+ dst_format = tvb_get_guint8(tvb, my_offset);
+ my_offset++;
+ obj_type = tvb_get_guint8(tvb, my_offset);
+ proto_tree_add_uint(contents_tree, hf_dec_sess_obj_type, tvb, my_offset, 1, obj_type);
+ my_offset++;
+ if (dst_format == 2) {
+ proto_tree_add_item(contents_tree, hf_dec_sess_grp_code, tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ proto_tree_add_item(contents_tree, hf_dec_sess_usr_code, tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ }
+ if (dst_format != 0) {
+ /* The name field for formats 1 and 2 */
+ image_len = tvb_get_guint8(tvb, my_offset);
+ my_offset++;
+ proto_tree_add_item(contents_tree, hf_dec_sess_dst_name, tvb, my_offset, image_len, ENC_ASCII);
+ my_offset += image_len;
+ }
+ /* The source end user */
+ src_format = tvb_get_guint8(tvb, my_offset);
+ my_offset++;
+ obj_type = tvb_get_guint8(tvb, my_offset);
+ proto_tree_add_uint(contents_tree, hf_dec_sess_obj_type,
+ tvb, my_offset, 1, obj_type);
+ my_offset++;
+ if (src_format == 2) {
+ proto_tree_add_item(contents_tree, hf_dec_sess_grp_code, tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ proto_tree_add_item(contents_tree, hf_dec_sess_usr_code, tvb, my_offset, 2, ENC_LITTLE_ENDIAN);
+ my_offset += 2;
+ }
+ if (dst_format != 0) {
+ /* The name field for formats 1 and 2 */
+ image_len = tvb_get_guint8(tvb, my_offset);
+ my_offset++;
+ proto_tree_add_item(contents_tree, hf_dec_sess_src_name,
+ tvb, my_offset, image_len, ENC_ASCII);
+ my_offset += image_len;
+ }
+ /* Now the MENUVER field */
+ menu_ver = tvb_get_guint8(tvb, my_offset);
+ switch (menu_ver) {
+ case 1:
+ case 3:
+ proto_tree_add_string(contents_tree, hf_dec_sess_menu_ver,
+ tvb, my_offset, 1,
+ "Version 1.0: RQSTRID, PASSWRD and ACCOUNT fields included");
+ my_offset++;
+ image_len = tvb_get_guint8(tvb, my_offset);
+ my_offset++;
+ proto_tree_add_item(contents_tree, hf_dec_sess_rqstr_id,
+ tvb, my_offset, image_len, ENC_ASCII);
+ my_offset += image_len;
+ image_len = tvb_get_guint8(tvb, my_offset);
+ my_offset++;
+ proto_tree_add_item(contents_tree, hf_dec_sess_rqstr_id,
+ tvb, my_offset, image_len, ENC_ASCII);
+ my_offset += image_len;
+ image_len = tvb_get_guint8(tvb, my_offset);
+ my_offset++;
+ proto_tree_add_item(contents_tree, hf_dec_sess_rqstr_id,
+ tvb, my_offset, image_len, ENC_ASCII);
+ my_offset += image_len;
+
+
+ break;
+ case 2:
+ /* A USRDATA field is handled by dissect_data */
+ proto_tree_add_string(contents_tree, hf_dec_sess_menu_ver,
+ tvb, my_offset, 1,
+ "Version 1.0: USRDATA field included");
+ break;
+ default:
+ proto_tree_add_string(contents_tree, hf_dec_sess_menu_ver,
+ tvb, my_offset, 1,
+ "Session control version 1.0");
+ break;
+ }
+ return (my_offset);
+}
+
+static int
+handle_disc_init_contents(
+ guint offset)
+{
+ guint my_offset = offset;
+
+ return (my_offset);
+}
+
+
+void
+proto_register_dec_rt(void)
+{
+
+ static hf_register_info hf[] = {
+ /* Message header items */
+ { &hf_dec_routing_flags,
+ { "Routing flags", "dec_dna.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "DNA routing flag", HFILL }},
+ { &hf_dec_rt_ctrl_msg,
+ { "Control packet", "dec_dna.flags.control",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), RT_FLAGS_CTRL_MSG,
+ NULL, HFILL }},
+ { &hf_dec_rt_long_msg,
+ { "Long data packet format", "dec_dna.flags.msglen",
+ FT_UINT8, BASE_HEX, NULL, 0x06,
+ "Long message indicator", HFILL }},
+ { &hf_dec_rt_short_msg,
+ { "Short data packet format", "dec_dna.flags.msglen",
+ FT_UINT8, BASE_HEX, NULL, 0x06,
+ "Short message indicator", HFILL }},
+ { &hf_dec_rt_rqr,
+ { "Return to Sender Request", "dec_dna.flags.RQR",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), RT_FLAGS_RQR,
+ "Return to Sender", HFILL }},
+ { &hf_dec_rt_rts,
+ { "Packet on return trip", "dec_dna.flags.RTS",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), RT_FLAGS_RTS,
+ NULL, HFILL }},
+ { &hf_dec_rt_inter_eth,
+ { "Intra-ethernet packet", "dec_dna.flags.intra_eth",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), RT_FLAGS_INTRA_ETHER,
+ NULL, HFILL }},
+ { &hf_dec_rt_discard,
+ { "Discarded packet", "dec_dna.flags.discard",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), RT_FLAGS_DISCARD,
+ NULL, HFILL }},
+ { &hf_dec_rt_dst_addr,
+ { "Destination Address", "dec_dna.dst.address",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_src_addr,
+ { "Source Address", "dec_dna.src.addr",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_nl2,
+ { "Next level 2 router", "dec_dna.nl2",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "reserved", HFILL }},
+ { &hf_dec_rt_service_class,
+ { "Service class", "dec_dna.svc_cls",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "reserved", HFILL }},
+ { &hf_dec_rt_protocol_type,
+ { "Protocol type", "dec_dna.proto_type",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "reserved", HFILL }},
+ { &hf_dec_rt_visit_count,
+ { "Visit count", "dec_dna.visit_cnt",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_flow_control,
+ { "Flow control", "dec_dna.nsp.flow_control",
+ FT_UINT8, BASE_HEX, VALS(rt_flow_control_vals), 0x3,
+ "Flow control(stop, go)", HFILL }},
+ { &hf_dec_rt_services,
+ { "Requested services", "dec_dna.nsp.services",
+ FT_UINT8, BASE_HEX, VALS(rt_services_vals), 0x0c,
+ "Services requested", HFILL }},
+ { &hf_dec_rt_info,
+ { "Version info", "dec_dna.nsp.info",
+ FT_UINT8, BASE_HEX, VALS(rt_info_version_vals), 0x03,
+ NULL, HFILL }},
+ { &hf_dec_rt_dst_node,
+ { "Destination node", "dec_dna.dst_node",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_seg_size,
+ { "Maximum data segment size", "dec_dna.nsp.segsize",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Max. segment size", HFILL }},
+ { &hf_dec_rt_src_node,
+ { "Source node", "dec_dna.src_node",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_segnum,
+ { "Message number", "dec_dna.nsp.segnum",
+ FT_UINT16, BASE_DEC, NULL, 0x0fff,
+ "Segment number", HFILL }},
+ { &hf_dec_rt_delay,
+ { "Delayed ACK allowed", "dec_dna.nsp.delay",
+ FT_BOOLEAN, 16, TFS(&tfs_yes_no), 0x1000,
+ "Delayed ACK allowed?", HFILL }},
+ { &hf_dec_rt_visited_nodes,
+ { "Nodes visited by this package", "dec_dna.vst_node",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Nodes visited", HFILL }},
+ /* Control message items */
+ { &hf_dec_ctl_msgs,
+ { "Routing control message", "dec_dna.rt.msg_type",
+ FT_UINT8, BASE_HEX, VALS(rt_msg_type_vals), 0xe,
+ "Routing control", HFILL }},
+ { &hf_dec_ctl_msg_hdr,
+ { "Routing control message", "dec_dna.rt.msg_type",
+ FT_UINT8, BASE_HEX, VALS(rt_msg_type_vals), 0xe,
+ "Routing control", HFILL }},
+ { &hf_dec_nsp_msgs,
+ { "DNA NSP message", "dec_dna.nsp.msg_type",
+ FT_UINT8, BASE_HEX, VALS(nsp_msg_type_vals), 0x0,
+ "NSP message", HFILL }},
+ { &hf_dec_rt_acknum,
+ { "Ack/Nak", "dec_dna.ctl.acknum",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "ack/nak number", HFILL }},
+ { &hf_dec_rt_fc_val,
+ { "Flow control", "dec_dna.nsp.fc_val",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_tiinfo,
+ { "Routing information", "dec_dna.ctl.tiinfo",
+ FT_UINT16, BASE_HEX, VALS(rt_tiinfo_vals), 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_blk_size,
+ { "Block size", "dec_dna.ctl.blk_size",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_disc_reason,
+ { "Reason for disconnect","dec_dna.nsp.disc_reason",
+ FT_UINT16, BASE_HEX, VALS(rt_disc_reason_vals), 0x0,
+ "Disconnect reason", HFILL }},
+ { &hf_dec_rt_version,
+ { "Version", "dec_dna.ctl.version",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Control protocol version", HFILL }},
+ { &hf_dec_rt_timer,
+ { "Hello timer(seconds)", "dec_dna.ctl.timer",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Hello timer in seconds", HFILL }},
+ { &hf_dec_rt_reserved,
+ { "Reserved", "dec_dna.ctl.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_fcnval,
+ { "Verification message function value", "dec_dna.ctl.fcnval",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Routing Verification function", HFILL }},
+ { &hf_dec_rt_test_data,
+ { "Test message data", "dec_dna.ctl.test_data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Routing Test message data", HFILL }},
+ { &hf_dec_rt_segment,
+ { "Segment", "dec_dna.ctl.segment",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Routing Segment", HFILL }},
+ { &hf_dec_rt_checksum,
+ { "Checksum", "dec_dna.ctl.checksum",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_checksum_status,
+ { "Checksum Status", "dec_dna.ctl.checksum.status",
+ FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_id,
+ { "Transmitting system ID", "dec_dna.ctl.id",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_iinfo,
+ { "Routing information", "dec_dna.ctl.tiinfo",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_iinfo_node_type,
+ { "Node type", "dec_dna.ctl.iinfo.node_type",
+ FT_UINT8, BASE_HEX, VALS(rt_iinfo_node_type_vals), 0x03,
+ NULL, HFILL }},
+ { &hf_dec_rt_iinfo_vrf,
+ { "Verification required", "dec_dna.ctl.iinfo.vrf",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x4,
+ "Verification required?", HFILL }},
+ { &hf_dec_rt_iinfo_rej,
+ { "Rejected", "dec_dna.ctl.iinfo.rej",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x8,
+ "Rejected message", HFILL }},
+ { &hf_dec_rt_iinfo_verf,
+ { "Verification failed", "dec_dna.ctl.iinfo.verf",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
+ "Verification failed?", HFILL }},
+ { &hf_dec_rt_iinfo_mta,
+ { "Accepts multicast traffic", "dec_dna.ctl.iinfo.mta",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
+ "Accepts multicast traffic?", HFILL }},
+ { &hf_dec_rt_iinfo_blkreq,
+ { "Blocking requested", "dec_dna.ctl.iinfo.blkreq",
+ FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
+ "Blocking requested?", HFILL }},
+ { &hf_dec_rt_iprio,
+ { "Routing priority", "dec_dna.ctl.prio",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_neighbor,
+ { "Neighbor", "dec_dna.ctl_neighbor",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Neighbour ID", HFILL }},
+ { &hf_dec_rt_seed,
+ { "Verification seed", "dec_dna.ctl.seed",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_elist,
+ { "List of router states", "dec_dna.ctl.elist",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Router states", HFILL }},
+ { &hf_dec_rt_ename,
+ { "Ethernet name", "dec_dna.ctl.ename",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_router_id,
+ { "Router ID", "dec_dna.ctl.router_id",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_router_state,
+ { "Router state", "dec_dna.ctl.router_state",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_conn_contents,
+ { "Session connect data", "dec_dna.sess.conn",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_rt_router_prio,
+ { "Router priority", "dec_dna.ctl.router_prio",
+ FT_UINT8, BASE_HEX, NULL, 0x7f,
+ NULL, HFILL }},
+ { &hf_dec_sess_grp_code,
+ { "Session Group code", "dec_dna.sess.grp_code",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_sess_usr_code,
+ { "Session User code", "dec_dna.sess.usr_code",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_sess_dst_name,
+ { "Session Destination end user", "dec_dna.sess.dst_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_sess_src_name,
+ { "Session Source end user", "dec_dna.sess.src_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_sess_obj_type,
+ { "Session Object type", "dec_dna.sess.obj_type",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_sess_menu_ver,
+ { "Session Menu version", "dec_dna.sess.menu_ver",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_dec_sess_rqstr_id,
+ { "Session Requestor ID", "dec_dna.sess.rqstr_id",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+
+
+ };
+ static gint *ett[] = {
+ &ett_dec_rt,
+ &ett_dec_routing_flags,
+ &ett_dec_msg_flags,
+ &ett_dec_rt_ctl_msg,
+ &ett_dec_rt_nsp_msg,
+ &ett_dec_rt_info_flags,
+ &ett_dec_rt_list,
+ &ett_dec_rt_rlist,
+ &ett_dec_rt_state,
+ &ett_dec_flow_control,
+ &ett_dec_sess_contents,
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_dec_rt_checksum, { "dec_dna.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
+ };
+
+ expert_module_t* expert_dec_rt;
+
+ proto_dec_rt = proto_register_protocol("DEC DNA Routing Protocol", "DEC_DNA", "dec_dna");
+ proto_register_field_array(proto_dec_rt, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_dec_rt = expert_register_protocol(proto_dec_rt);
+ expert_register_field_array(expert_dec_rt, ei, array_length(ei));
+
+ dec_rt_handle = register_dissector("dec_dna", dissect_dec_rt,
+ proto_dec_rt);
+}
+
+void
+proto_reg_handoff_dec_rt(void)
+{
+ dissector_add_uint("ethertype", ETHERTYPE_DNA_RT, dec_rt_handle);
+ dissector_add_uint("chdlc.protocol", ETHERTYPE_DNA_RT, dec_rt_handle);
+ dissector_add_uint("ppp.protocol", PPP_DEC4, dec_rt_handle);
+/* dissector_add_uint("ppp.protocol", PPP_DECNETCP, dec_rt_handle);*/
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */