/* 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 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include 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 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_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 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(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(wmem_packet_scope(), "%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((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){ const int * 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((const guint8 *)tvb_memdup(wmem_packet_scope(), 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((const guint8 *)tvb_memdup(wmem_packet_scope(), 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 checksum; 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); checksum = tvb_get_letohs(tvb, my_offset); if (checksum != my_checksum) { proto_tree_add_none_format(tree, hf_dec_rt_segment, tvb, my_offset, 2, "Checksum mismatch(computed 0x%x <> received 0x%x)", my_checksum, checksum); } else { proto_tree_add_none_format(tree, hf_dec_rt_segment, tvb, my_offset, 2, "Checksum: match (computed 0x%x = received 0x%x)", my_checksum, checksum); } 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 const int * 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((const guint8 *)tvb_memdup(wmem_packet_scope(), 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((const guint8 *)tvb_memdup(wmem_packet_scope(), 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((const guint8 *)tvb_memdup(wmem_packet_scope(), 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|ENC_NA); 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|ENC_NA); 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|ENC_NA); 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|ENC_NA); 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|ENC_NA); 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[] = { /* Mesage 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, 0xfff, "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 ty 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_UINT8, 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_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, }; 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_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 - http://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: */