diff options
author | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-07-26 01:18:25 +0000 |
---|---|---|
committer | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-07-26 01:18:25 +0000 |
commit | 0e9e556e5acfca7cb947af4c8ca70e0bcf74f3e8 (patch) | |
tree | bd50fa49c5891daa9209ef829e93b1ce41d3c007 /epan/dissectors/packet-dec-dnart.c | |
parent | 86490343122244690f08d981651fcc038908bf41 (diff) |
From fred hoekstra
New protocol: DEC DNA Routing protocol
svn path=/trunk/; revision=15078
Diffstat (limited to 'epan/dissectors/packet-dec-dnart.c')
-rw-r--r-- | epan/dissectors/packet-dec-dnart.c | 1579 |
1 files changed, 1579 insertions, 0 deletions
diff --git a/epan/dissectors/packet-dec-dnart.c b/epan/dissectors/packet-dec-dnart.c new file mode 100644 index 0000000000..cbf32620d7 --- /dev/null +++ b/epan/dissectors/packet-dec-dnart.c @@ -0,0 +1,1579 @@ +/* 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) + * + * $Id: packet-dec-dnart.c 14135 2005-07-25 12:05:50Z fhoekstra $ + * + * Use was made of the following documentation: + * (See URL http://linux-decnet.sourceforge.net/docs). + * + * 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 + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <glib.h> +#include <gmodule.h> +#include <epan/packet.h> +#include <epan/proto.h> +#include <epan/dissectors/packet-tcp.h> +#include "etypes.h" +#include "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_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 + +static int proto_dec_rt = -1; + +static int hf_dec_routing_flags = -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_mac = -1; +static int hf_dec_rt_src_mac = -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_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_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_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_state = -1; +static gint ett_dec_flow_control = -1; +static gint ett_dec_sess_contents = -1; + +static gint dec_dna_total_bytes_this_segment = 0; +static gint dec_dna_previous_total = 0; + +/*static const value_string protocol_id_vals[] = { + { 0x6001, "DEC DNA dump/load" }, + { 0x6002, "DEC DNA Remote Console" }, + { 0x6003, "DEC DNA routing" }, + { 0x6004, "DEC DNA Local Area Transport" }, + { 0x6005, "DEC DNA diagnostics" }, + { 0x6006, "DEC DNA Customer specific" }, + { 0x6007, "DEC DNA System Communication Architecture" }, + { 0, NULL } +};*/ + +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 routing_flags[] = { + {0x02, "Short data packet format"}, + {0x06, "Long data packet format"}, + {0x08, "Return to sender request"}, + {0x10, "Packet on return trip"}, + {0x20, "Intra-Ethernet packet"}, + {0x40, "Discarded packet"}, + {0x0, NULL} +}; + +static const value_string rt_iinfo_flags[] = { + {0x01, "Level 2 router"}, + {0x02, "Level 1 router"}, + {0x04, "Verification required"}, + {0x08, "Rejected"}, + {0x10, "Verification failed"}, + {0x20, "Does not accept multicast"}, + {0x40, "Blocking requested"}, + {0x0, 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 conect 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 + +static const char initial_sep[] = " ("; +static const char cont_sep[] = ", "; + +#define APPEND_BOOLEAN_FLAG(flag, item, string) \ + if(flag){ \ + if(item) \ + proto_item_append_text(item, string, sep); \ + sep = cont_sep; \ + } + +#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 void +dissect_dec_rt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint8 padding_length; + guint8 forward; + guint8 msg_flags; + guint rt_visit_count, rt_zero = 0; + guint16 payload_length; + guint16 dst_node, src_node; + gint offset; + gboolean long_msg = false; + proto_tree *rt_tree; + proto_tree *flags_tree; + proto_item *ti; + const char *sep; + + offset = 0; + if (check_col(pinfo->cinfo, COL_PROTOCOL)) { + col_clear(pinfo->cinfo, COL_PROTOCOL); + } + if (check_col(pinfo->cinfo, COL_PROTOCOL)) { + col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSP"); + } + if (check_col(pinfo->cinfo, COL_INFO)) { + col_clear(pinfo->cinfo, COL_INFO); + } + payload_length = tvb_get_ntohs(tvb, offset); + offset += 2; + msg_flags = tvb_get_guint8(tvb, offset); + ti = proto_tree_add_item(tree, proto_dec_rt, tvb, 0, -1, + TRUE); + 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); + sep = initial_sep; + if (msg_flags & RT_FLAGS_LONG_MSG) { + APPEND_BOOLEAN_FLAG(msg_flags & RT_FLAGS_LONG_MSG, ti, + "%sLong message"); + proto_tree_add_uint(flags_tree, hf_dec_rt_long_msg, + tvb, offset, 1, msg_flags & 0x03); + long_msg = true; + } else { + APPEND_BOOLEAN_FLAG(msg_flags & RT_FLAGS_LONG_MSG, ti, + "%sShort message"); + proto_tree_add_item(flags_tree, hf_dec_rt_short_msg, + tvb, offset, 1, msg_flags & 0x03); + } + APPEND_BOOLEAN_FLAG(msg_flags & RT_FLAGS_RQR, ti, + "%sReturn to Sender"); + proto_tree_add_boolean(flags_tree, hf_dec_rt_rqr, tvb, + offset, 1, msg_flags); + APPEND_BOOLEAN_FLAG(msg_flags & RT_FLAGS_RTS, ti, + "%sReturn trip"); + proto_tree_add_boolean(flags_tree, hf_dec_rt_rts, tvb, + offset, 1, msg_flags); + APPEND_BOOLEAN_FLAG(msg_flags & RT_FLAGS_INTRA_ETHER, ti, + "%sIntra Ethernet"); + proto_tree_add_boolean(flags_tree, hf_dec_rt_inter_eth, tvb, + offset, 1, msg_flags); + APPEND_BOOLEAN_FLAG(msg_flags & RT_FLAGS_DISCARD, ti, + "%sDiscarded"); + proto_tree_add_boolean(flags_tree, hf_dec_rt_discard, tvb, + offset, 1, msg_flags); + if (sep != initial_sep) { + /* We put something in; put in the terminating ")" */ + proto_item_append_text(ti, ")"); + } + /* That finished the routing flags field + Now we must discriminate between short and long messages + We handle long messages first. + */ + if (long_msg) { + /* Increment offset by three: + 1 to get past the flags field + 2 to skip the DEC area/subarea field + */ + offset += 3; + proto_tree_add_item(rt_tree, hf_dec_rt_dst_mac, tvb, + offset, 6, FALSE); + /* Skip 6 bytes for the MAC and + 2 bytes for DEC area/subarea + */ + offset += 8; + proto_tree_add_item(rt_tree, hf_dec_rt_src_mac, tvb, + offset, 6, FALSE); + /* 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 { + /* Now the short message format + Increment offset to get past the flags field + */ + offset++; + dst_node = tvb_get_letohs(tvb, offset); + proto_tree_add_item(rt_tree, hf_dec_rt_dst_node, tvb, + offset, 2, TRUE); + offset += 2; + src_node = tvb_get_letohs(tvb, offset); + proto_tree_add_item(rt_tree, hf_dec_rt_src_node, tvb, + offset, 2, TRUE); + offset += 2; + forward = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(rt_tree, hf_dec_rt_visited_nodes, tvb, + offset, 1, forward); + offset++; + } + } + msg_flags = tvb_get_guint8(tvb, offset); + /* This gives us either the routing control msg flag or the + NSP message identifier + */ + if (msg_flags & 0x01) { + /* This is a control message + Documentation is somewhat confusing at this point + Data messages have a short or long header prepended, + however, the Routing Layer control messages do not have + a header prepended. Routing Layer control messages are + signalled by having the least significant bit set. + If this bit is set, ignore the header. + This branch is taken for Routing Layer control messages. + */ + guint new_offset; + proto_tree *ctl_msg_tree; + proto_item *ti; + + ti = proto_tree_add_uint( + rt_tree, hf_dec_ctl_msgs, tvb, offset, 1, msg_flags); + ctl_msg_tree = proto_item_add_subtree(ti, ett_dec_rt_ctl_msg); + /* Get past the msg_flags */ + offset++; + switch ((msg_flags >> 1) & 0x7) { + case RT_CTL_INITIALIZATION: + new_offset = + do_initialization_msg( + tvb, pinfo, ctl_msg_tree, offset); + break; + case RT_CTL_VERIFICATION: + new_offset = + do_verification_msg( + tvb, pinfo, ctl_msg_tree, offset); + break; + case RT_CTL_HELLO_TEST: + new_offset = + do_hello_test_msg( + tvb, pinfo, ctl_msg_tree, offset); + break; + case RT_CTL_LVL1_ROUTING: + case RT_CTL_LVL2_ROUTING: + new_offset = + 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: + new_offset = + do_hello_msg( + tvb, pinfo, ctl_msg_tree, offset, msg_flags >> 1); + break; + default: + break; + } + } else { + /* It is not a routing control message */ + proto_tree *nsp_msg_tree; + proto_item *ti; + guint8 nsp_msg_type; + guint16 dst_node, src_node; + + nsp_msg_type = tvb_get_guint8(tvb, offset); + ti = 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; + } + nsp_msg_tree = + proto_item_add_subtree(ti, ett_dec_rt_nsp_msg); + /* Get past the nsp_msg_type */ + offset++; + dst_node = tvb_get_letohs(tvb, offset); + proto_tree_add_item( + nsp_msg_tree, hf_dec_rt_dst_node, tvb, offset, 2, TRUE); + offset += 2; + if (nsp_msg_type == CONN_ACK_MSG) { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, + "NSP connect acknowledgement"); + /* Done with this msg type */ + return; + } + } + /* All other messages have a source node */ + src_node = tvb_get_letohs(tvb, offset); + proto_tree_add_item( + nsp_msg_tree, hf_dec_rt_src_node, tvb, offset, 2, TRUE); + offset += 2; + + offset = + handle_nsp_msg(tvb, + pinfo, + nsp_msg_tree, + offset, + nsp_msg_type); + } +} + +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; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, + "Routing control, initialization message"); + } + proto_tree_add_item(tree, hf_dec_rt_src_node, tvb, + my_offset, 2, TRUE); + offset += 2; + proto_tree_add_item(tree, hf_dec_rt_tiinfo, tvb, + my_offset, 2, TRUE); + my_offset += 2; + proto_tree_add_item(tree, hf_dec_rt_blk_size, tvb, + my_offset, 2, TRUE); + 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, TRUE); + my_offset += 2; + remainder_count = tvb_get_guint8(tvb, my_offset); + if (remainder_count != 0) { + proto_tree_add_bytes(tree, hf_dec_rt_reserved, tvb, + my_offset, remainder_count, + tvb_get_ptr(tvb, my_offset, remainder_count)); + 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; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, + "Routing control, verification message"); + } + proto_tree_add_item(tree, hf_dec_rt_src_node, tvb, + my_offset, 2, TRUE); + offset += 2; + remainder_count = tvb_get_guint8(tvb, my_offset); + if (remainder_count != 0) { + proto_tree_add_bytes(tree, hf_dec_rt_fcnval, tvb, + my_offset, remainder_count, + tvb_get_ptr(tvb, my_offset, remainder_count)); + 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; + guint8 remainder_count; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, + "Routing control, hello/test message"); + } + proto_tree_add_item(tree, hf_dec_rt_src_node, tvb, + my_offset, 2, TRUE); + my_offset += 2; + remainder_count = tvb_length_remaining(tvb, my_offset); + if (remainder_count != 0) { + proto_tree_add_bytes(tree, hf_dec_rt_test_data, tvb, + my_offset, remainder_count, + tvb_get_ptr(tvb, my_offset, remainder_count)); + 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; + guint16 checksum = 1; + guint16 count, startid, rtginfo; + guint8 remainder_count; + + proto_tree_add_item(tree, hf_dec_rt_src_node, tvb, + my_offset, 2, TRUE); + /* Skip the 1-byte reserved field */ + my_offset += 3; + remainder_count = tvb_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); + my_offset += 6; + if (msg == 3) { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_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 { + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_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); + }; + checksum += (count + startid + rtginfo); + remainder_count -= 6; + } while (remainder_count > 1); + if (checksum != tvb_get_letohs(tvb, my_offset)) { + proto_tree_add_none_format(tree, hf_dec_rt_segment, tvb, + my_offset, 2, + "Segment: checksum mismatch(computed 0x%x != received 0x%x)", + checksum, tvb_get_letohs(tvb, my_offset)); + } + 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 remainder_count, iinfo, priority; + guint16 version, eco_nr, user_eco, timer; + proto_item *ti; + proto_tree *iinfo_tree; + const char *sep; + + 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_id, tvb, + my_offset, 6, TRUE); + my_offset += 6; + iinfo = tvb_get_guint8(tvb, my_offset); + ti = proto_tree_add_uint( + tree, hf_dec_rt_iinfo, tvb, my_offset, 1, iinfo); + iinfo_tree = proto_item_add_subtree(ti, ett_dec_rt_info_flags); + sep = initial_sep; + proto_tree_add_uint( + iinfo_tree, hf_dec_rt_iinfo_node_type, tvb, my_offset, 1, iinfo); + APPEND_BOOLEAN_FLAG(iinfo & 0x4, ti, + "%sVerification required"); + proto_tree_add_boolean(iinfo_tree, hf_dec_rt_iinfo_vrf, + tvb, my_offset, 1, iinfo); + APPEND_BOOLEAN_FLAG(iinfo & 0x8, ti, + "%sRejected"); + proto_tree_add_boolean(iinfo_tree, hf_dec_rt_iinfo_rej, + tvb, my_offset, 1, iinfo); + APPEND_BOOLEAN_FLAG(iinfo & 0x10, ti, + "%sVerification failed"); + proto_tree_add_boolean(iinfo_tree, hf_dec_rt_iinfo_verf, + tvb, my_offset, 1, iinfo); + APPEND_BOOLEAN_FLAG(iinfo & 0x20, ti, + "%sNo multicast traffic"); + proto_tree_add_boolean(iinfo_tree, hf_dec_rt_iinfo_mta, + tvb, my_offset, 1, iinfo); + APPEND_BOOLEAN_FLAG(iinfo & 0x4, ti, + "%sBlocking requested"); + if (sep != initial_sep) { + /* We put something in; put in the terminating ")" */ + proto_item_append_text(ti, ")"); + } + proto_tree_add_boolean(iinfo_tree, hf_dec_rt_iinfo_blkreq, + tvb, my_offset, 1, iinfo); + my_offset++; + proto_tree_add_item(tree, hf_dec_rt_blk_size, tvb, + my_offset, 2, TRUE); + my_offset += 2; + if (msg == 5) { + /* Ethernet router hello message + Has a 'priority' field in this position */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_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 += 2; + if (msg == 6) { + /* The endnode hello message has 'seed' and 'neighbor' fields */ + guint8 seed; + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, + "Routing control, Endnode Hello message"); + } + seed = tvb_get_guint8(tvb, my_offset); + proto_tree_add_uint( + tree, hf_dec_rt_seed, tvb, my_offset, 1, seed); + my_offset++; + proto_tree_add_item(tree, hf_dec_rt_neighbor, tvb, + my_offset, 6, TRUE); + my_offset += 6; + } + /*'Timer' and 'mpd' fields are common + 'mpd' field is reserved */ + timer = tvb_get_letohs(tvb, my_offset); + proto_tree_add_item(tree, hf_dec_rt_timer, tvb, + my_offset, 2, TRUE); + my_offset += 2; + 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; + proto_tree *list_tree; + + ti = proto_tree_add_item(tree, hf_dec_rt_elist, tvb, + my_offset, 7, TRUE); + my_offset += 7; + list_tree = proto_item_add_subtree(ti, ett_dec_rt_list); + remainder_count = + tvb_reported_length_remaining(tvb, my_offset); + do { + /* if the remainder_count < 7, there are + no more router/state items */ + guint8 pristate; + proto_item *ti; + proto_tree *pstate_tree; + + ti = proto_tree_add_item(list_tree, hf_dec_rt_router_id, + tvb, my_offset, 6, TRUE); + my_offset += 6; + pstate_tree = proto_item_add_subtree(ti, ett_dec_rt_state); + pristate = tvb_get_guint8(tvb, my_offset); + proto_tree_add_string(list_tree, hf_dec_rt_router_state, + tvb, my_offset, 1, + ((pristate & 0x80) ? "known 2-way": "unknown")); + proto_tree_add_uint(list_tree, hf_dec_rt_router_prio, + tvb, my_offset, 1, pristate); + my_offset++; + remainder_count -= 7; + } while (remainder_count >= 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, seg_size, reason; + guint8 ls_flags, fc_val, services, info; + 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 (check_col(pinfo->cinfo, COL_INFO)) { + 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, TRUE); + proto_tree_add_boolean(tree, hf_dec_rt_delay, + tvb, my_offset, 2, seg_num); + 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; + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, + ", bytes this segment: %d, total sofar:%d", + data_length, dec_dna_total_bytes_this_segment); + } + /* We are done, return my_offset */ + break; + case INTERRUPT_MSG: /* "Interrupt message" */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_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, TRUE); + proto_tree_add_boolean(tree, hf_dec_rt_delay, + tvb, my_offset, 2, ack_num); + 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; + } + seg_num = tvb_get_letohs(tvb, my_offset); + /* This is the last field, the rest are data */ + proto_tree_add_item(tree, hf_dec_rt_segnum, + tvb, my_offset, 2, TRUE); + proto_tree_add_boolean(tree, hf_dec_rt_delay, + tvb, my_offset, 2, seg_num); + my_offset += 2; + /* We are done, return my_offset */ + break; + case LINK_SERVICE_MSG: /* "Link service message" */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_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, TRUE); + proto_tree_add_boolean(tree, hf_dec_rt_delay, + tvb, my_offset, 2, ack_num); + 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; + } + seg_num = tvb_get_letohs(tvb, my_offset); + proto_tree_add_item(tree, hf_dec_rt_segnum, + tvb, my_offset, 2, TRUE); + proto_tree_add_boolean(tree, hf_dec_rt_delay, + tvb, my_offset, 2, seg_num); + my_offset += 2; + /* Now follows the ls_flags field */ + ls_flags = tvb_get_guint8(tvb, my_offset); + if (check_col(pinfo->cinfo, COL_INFO)) { + 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 */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_fstr(pinfo->cinfo, COL_INFO, + "NSP data %s message(%d)", + (ack_num & 0x1000) ? "NAK" : "ACK", + ack_num & 0xfff); + } + if (tvb_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" */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_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_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" */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_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++; + info = tvb_get_guint8(tvb, my_offset); + proto_tree_add_uint(tree, hf_dec_rt_info, tvb, + my_offset, 1, info); + my_offset++; + seg_size = tvb_get_letohs(tvb, my_offset); + proto_tree_add_item(tree, hf_dec_rt_seg_size, tvb, + my_offset, 2, TRUE); + 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" */ + if (check_col(pinfo->cinfo, COL_INFO)) { + col_add_str(pinfo->cinfo, COL_INFO, + "NSP disconnect initiate/confirm message"); + } + reason = tvb_get_letohs(tvb, my_offset); + proto_tree_add_item(tree, hf_dec_disc_reason, tvb, + my_offset, 2, TRUE); + 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; + guint16 grp_code, usr_code; + + ti = proto_tree_add_item(tree, hf_dec_conn_contents, + tvb, my_offset, -1, TRUE); + 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) { + grp_code = tvb_get_letohs(tvb, my_offset); + proto_tree_add_item(contents_tree, hf_dec_sess_grp_code, + tvb, my_offset, 2, TRUE); + my_offset += 2; + usr_code = tvb_get_letohs(tvb, my_offset); + proto_tree_add_item(contents_tree, hf_dec_sess_usr_code, + tvb, my_offset, 2, TRUE); + 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, TRUE); + 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) { + grp_code = tvb_get_letohs(tvb, my_offset); + proto_tree_add_item(contents_tree, hf_dec_sess_grp_code, + tvb, my_offset, 2, TRUE); + my_offset += 2; + usr_code = tvb_get_letohs(tvb, my_offset); + proto_tree_add_item(contents_tree, hf_dec_sess_usr_code, + tvb, my_offset, 2, TRUE); + 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, TRUE); + 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, TRUE); + 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, TRUE); + 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, TRUE); + 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); +} + + +static const true_false_string yesno = { + "Yes", + "No" +}; + +void +proto_register_dec_rt(void) +{ + + static hf_register_info hf[] = { + /* Mesage header items */ + { &hf_dec_routing_flags, + { "Routing flags", "dec_dna.flags", + FT_UINT8, BASE_HEX, VALS(&routing_flags), 0x0, + "DNA routing flag", HFILL }}, + { &hf_dec_rt_long_msg, + { "Long message", "dec_dna.flags.msglen", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Long message indicator", HFILL }}, + { &hf_dec_rt_short_msg, + { "Short message", "dec_dna.flags.msglen", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Short message indicator", HFILL }}, + { &hf_dec_rt_rqr, + { "Return to Sender Request", "dec_dna.flags.RQR", + FT_BOOLEAN, 8, TFS(&yesno), RT_FLAGS_RQR, + "Return to Sender", HFILL }}, + { &hf_dec_rt_rts, + { "Packet on return trip", "dec_dna.flags.RTS", + FT_BOOLEAN, 8, TFS(&yesno), RT_FLAGS_RTS, + "Packet on return trip", HFILL }}, + { &hf_dec_rt_inter_eth, + { "Intra-ethernet packet", "dec_dna.flags.intra_eth", + FT_BOOLEAN, 8, TFS(&yesno), RT_FLAGS_INTRA_ETHER, + "Intra-ethernet packet", HFILL }}, + { &hf_dec_rt_discard, + { "Discarded packet", "dec_dna.flags.discard", + FT_BOOLEAN, 8, TFS(&yesno), RT_FLAGS_DISCARD, + "Discarded packet", HFILL }}, + { &hf_dec_rt_dst_mac, + { "Destination MAC", "dec_dna.dst.mac", + FT_ETHER, BASE_NONE, NULL, 0x0, + "Destination MAC address", HFILL }}, + { &hf_dec_rt_src_mac, + { "Source MAC", "dec_dna.src.mac", + FT_ETHER, BASE_NONE, NULL, 0x0, + "Source MAC address", 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, + "Visit count", 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, + "Version info", HFILL }}, + { &hf_dec_rt_dst_node, + { "Destination node", "dec_dna.dst_node", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Destination node", 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, + "Source node", HFILL }}, + { &hf_dec_rt_segnum, + { "Message number", "dec_dna.nsp.segnum", + FT_UINT16, BASE_DEC, NULL, 0xfff, + "Segment number", HFILL }}, + { &hf_dec_rt_delay, + { "Delayed ACK allowed", "dec_dna.nsp.delay", + FT_BOOLEAN, 16, TFS(&yesno), 0x1000, + "Delayed ACK allowed?", HFILL }}, + { &hf_dec_rt_visited_nodes, + { "Nodes visited ty this package", "dec_dna.vst_node", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Nodes visited", HFILL }}, + /* Control messsage 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_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, + "Flow control", HFILL }}, + { &hf_dec_rt_tiinfo, + { "Routing information", "dec_dna.ctl.tiinfo", + FT_UINT8, BASE_HEX, VALS(&rt_tiinfo_vals), 0x0, + "Routing information", HFILL }}, + { &hf_dec_rt_blk_size, + { "Block size", "dec_dna.ctl.blk_size", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Block size", 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, + "Reserved", 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_id, + { "Transmitting system ID", "dec_dna.ctl.id", + FT_ETHER, BASE_NONE, NULL, 0x0, + "Transmitting system ID", HFILL }}, + { &hf_dec_rt_iinfo, + { "Routing information", "dec_dna.ctl.tiinfo", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Routing information", 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, + "Node type", HFILL }}, + { &hf_dec_rt_iinfo_vrf, + { "Verification required", "dec_dna.ctl.iinfo.vrf", + FT_BOOLEAN, 8, TFS(&yesno), 0x4, + "Verification required?", HFILL }}, + { &hf_dec_rt_iinfo_rej, + { "Rejected", "dec_dna.ctl.iinfo.rej", + FT_BOOLEAN, 8, TFS(&yesno), 0x8, + "Rejected message", HFILL }}, + { &hf_dec_rt_iinfo_verf, + { "Verification failed", "dec_dna.ctl.iinfo.verf", + FT_BOOLEAN, 8, TFS(&yesno), 0x10, + "Verification failed?", HFILL }}, + { &hf_dec_rt_iinfo_mta, + { "Accepts multicast traffic", "dec_dna.ctl.iinfo.mta", + FT_BOOLEAN, 8, TFS(&yesno), 0x20, + "Accepts multicast traffic?", HFILL }}, + { &hf_dec_rt_iinfo_blkreq, + { "Blocking requested", "dec_dna.ctl.iinfo.blkreq", + FT_BOOLEAN, 8, TFS(&yesno), 0x40, + "Blocking requested?", HFILL }}, + { &hf_dec_rt_iprio, + { "Routing priority", "dec_dna.ctl.prio", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Routing priority", 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_UINT8, BASE_HEX, NULL, 0x0, + "Verification seed", HFILL }}, + { &hf_dec_rt_elist, + { "List of router states", "dec_dna.ctl.elist", + FT_STRING, BASE_NONE, NULL, 0x0, + "Router states", HFILL }}, + { &hf_dec_rt_router_id, + { "Router ID", "dec_dna.ctl.router_id", + FT_ETHER, BASE_NONE, NULL, 0x0, + "Router ID", HFILL }}, + { &hf_dec_rt_router_state, + { "Router state", "dec_dna.ctl.router_state", + FT_STRING, BASE_NONE, NULL, 0x80, + "Router state", HFILL }}, + { &hf_dec_conn_contents, + { "Session connect data", "dec_dna.sess.conn", + FT_NONE, BASE_NONE, NULL, 0x0, + "Session connect data", HFILL }}, + { &hf_dec_rt_router_prio, + { "Router priority", "dec_dna.ctl.router_prio", + FT_UINT8, BASE_HEX, NULL, 0x7f, + "Router priority", HFILL }}, + { &hf_dec_sess_grp_code, + { "Session Group code", "dec_dna.sess.grp_code", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Session group code", HFILL }}, + { &hf_dec_sess_usr_code, + { "Session User code", "dec_dna.sess.usr_code", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Session User code", HFILL }}, + { &hf_dec_sess_dst_name, + { "SessionDestination end user", "dec_dna.sess.dst_name", + FT_STRING, BASE_NONE, NULL, 0x0, + "Session Destination end user", HFILL }}, + { &hf_dec_sess_src_name, + { "Session Source end user", "dec_dna.sess.src_name", + FT_STRING, BASE_NONE, NULL, 0x0, + "Session Source end user", HFILL }}, + { &hf_dec_sess_obj_type, + { "Session Object type", "dec_dna.sess.obj_type", + FT_UINT8, BASE_HEX, NULL, 0x0, + "Session object type", HFILL }}, + { &hf_dec_sess_menu_ver, + { "Session Menu version", "dec_dna.sess.menu_ver", + FT_STRING, BASE_NONE, NULL, 0x0, + "Session menu version", HFILL }}, + { &hf_dec_sess_rqstr_id, + { "Session Requestor ID", "dec_dna.sess.rqstr_id", + FT_STRING, BASE_NONE, NULL, 0x0, + "Session requestor ID", 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_state, + &ett_dec_flow_control, + &ett_dec_sess_contents, + }; + + 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)); +} + +void +proto_reg_handoff_dec_rt(void) +{ + dissector_handle_t dec_rt_handle; + + dec_rt_handle = create_dissector_handle(dissect_dec_rt, + proto_dec_rt); + dissector_add("ethertype", ETHERTYPE_DNA_RT, dec_rt_handle); + dissector_add("chdlctype", ETHERTYPE_DNA_RT, dec_rt_handle); + dissector_add("ppp.protocol", PPP_DEC4, dec_rt_handle); +/* dissector_add("ppp.protocol", PPP_DECNETCP, dec_rt_handle);*/ +} |