diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-dec-dnart.c | |
parent | Initial commit. (diff) | |
download | wireshark-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.c | 1487 |
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: + */ |