/* packet-dlsw.c * Routines for DLSw packet dissection (Data Link Switching) * Copyright 2001, Paul Ionescu * * $Id: packet-dlsw.c,v 1.7 2002/08/28 21:00:12 jmayer Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* DLSw dissector ( RFC 1434, RFC 1795, RFC 2166) */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include static int proto_dlsw = -1; static gint ett_dlsw = -1; static gint ett_dlsw_header = -1; static gint ett_dlsw_data = -1; static gint ett_dlsw_vector = -1; #define CANUREACH 0x03 #define ICANREACH 0x04 #define REACH_ACK 0x05 #define DGRMFRAME 0x06 #define XIDFRAME 0x07 #define CONTACT 0x08 #define CONTACTED 0x09 #define RESTART_DL 0x10 #define DL_RESTARTED 0x11 #define ENTER_BUSY 0x0C #define EXIT_BUSY 0x0D #define INFOFRAME 0x0A #define HALT_DL 0x0E #define DL_HALTED 0x0F #define NETBIOS_NQ 0x12 #define NETBIOS_NR 0x13 #define DATAFRAME 0x14 #define HALT_DL_NOACK 0x19 #define NETBIOS_ANQ 0x1A #define NETBIOS_ANR 0x1B #define KEEPALIVE 0x1D #define CAP_EXCHANGE 0x20 #define IFCM 0x21 #define TEST_CIRCUIT_REQ 0x7A #define TEST_CIRCUIT_RSP 0x7B static const value_string dlsw_type_vals[] = { { CANUREACH , "Can U Reach Station-circuit start" }, { ICANREACH , "I Can Reach Station-circuit start" }, { REACH_ACK , "Reach Acknowledgment" }, { DGRMFRAME , "Datagram Frame" }, { XIDFRAME , "XID Frame" }, { CONTACT , "Contact Remote Station" }, { CONTACTED , "Remote Station Contacted" }, { RESTART_DL , "Restart Data Link" }, { DL_RESTARTED , "Data Link Restarted" }, { ENTER_BUSY , "Enter Busy" }, { EXIT_BUSY , "Exit Busy" }, { INFOFRAME , "Information (I) Frame" }, { HALT_DL , "Halt Data Link" }, { DL_HALTED , "Data Link Halted" }, { NETBIOS_NQ , "NETBIOS Name Query-circuit setup" }, { NETBIOS_NR , "NETBIOS Name Recog-circuit setup" }, { DATAFRAME , "Data Frame" }, { HALT_DL_NOACK , "Halt Data Link with no Ack" }, { NETBIOS_ANQ , "NETBIOS Add Name Query" }, { NETBIOS_ANR , "NETBIOS Add Name Response" }, { KEEPALIVE , "Transport Keepalive Message" }, { CAP_EXCHANGE , "Capabilities Exchange" }, { IFCM , "Independent Flow Control Message" }, { TEST_CIRCUIT_REQ , "Test Circuit Request" }, { TEST_CIRCUIT_RSP , "Test Circuit Response" }, { 0 , NULL } }; static const value_string dlsw_version_vals[] = { { 0x31 , "Version 1 (RFC 1795)" }, { 0x32 , "Version 2 (RFC 2166)" }, { 0x33 , "Vendor Specific" }, { 0x34 , "Vendor Specific" }, { 0x35 , "Vendor Specific" }, { 0x36 , "Vendor Specific" }, { 0x37 , "Vendor Specific" }, { 0x38 , "Vendor Specific" }, { 0x39 , "Vendor Specific" }, { 0x3A , "Vendor Specific" }, { 0x3B , "Vendor Specific" }, { 0x3C , "Vendor Specific" }, { 0x3D , "Vendor Specific" }, { 0x3E , "Vendor Specific" }, { 0x3F , "Vendor Specific" }, { 0x4B , "Pre 1 (RFC 1434)" }, { 0x00 , NULL } }; static const value_string dlsw_vector_vals[] = { { 0x81 , "Vendor ID Control Vector" }, { 0x82 , "DLSw Version Control Vector" }, { 0x83 , "Initial Pacing Window Control Vector" }, { 0x84 , "Version String Control Vector" }, { 0x85 , "Mac Address Exclusivity Control Vector" }, { 0x86 , "Supported SAP List Control Vector" }, { 0x87 , "TCP Connections Control Vector" }, { 0x88 , "NetBIOS Name Exclusivity Control Vector" }, { 0x89 , "MAC Address List Control Vector" }, { 0x8a , "NetBIOS Name List Control Vector" }, { 0x8b , "Vendor Context Control Vector" }, { 0x8c , "Multicast Capabilities Control Vector" }, { 0x8d , "Reserved for future use" }, { 0x8e , "Reserved for future use" }, { 0x8f , "Reserved for future use" }, { 0x90 , "Reserved for future use" }, { 0x91 , " Control Vector" }, { 0x92 , " Control Vector" }, { 0x93 , " Control Vector" }, { 0x94 , " Control Vector" }, { 0x95 , " Control Vector" }, { 0x96 , " Control Vector" }, { 0x00 , NULL } }; static const value_string dlsw_pri_vals[] = { { 0 , "Unsupported" }, { 1 , "Low Priority" }, { 2 , "Medium Priority" }, { 3 , "High Priority" }, { 4 , "Highest Priority" }, { 5 , "Reserved" }, { 6 , "Reserved" }, { 7 , "Reserved" } }; #define DLSW_GDSID_SEND 0x1520 #define DLSW_GDSID_ACK 0x1521 #define DLSW_GDSID_REF 0x1522 static const value_string dlsw_gds_vals[] = { { DLSW_GDSID_SEND , "Request Capabilities GDS" }, { DLSW_GDSID_ACK , "Response Capabilities GDS" }, { DLSW_GDSID_REF , "Refuse Capabilities GDS" }, { 0 , NULL } }; static const value_string dlsw_refuse_vals[] = { { 0x1 , "invalid GDS length for a DLWs Capabilities Exchange Request"}, { 0x2 , "invalid GDS id for a DLSw Capabilities Exchange Request"}, { 0x3 , "vendor Id control vector is missing"}, { 0x4 , "DLSw Version control vector is missing"}, { 0x5 , "initial Pacing Window control vector is missing"}, { 0x6 , "length of control vectors doewn't correlate to the length of the GDS variable"}, { 0x7 , "invalid control vector id"}, { 0x8 , "length of control vector invalid"}, { 0x9 , "invalid control vector data value"}, { 0xa , "duplicate control vector"}, { 0xb , "out-of-sequence control vector"}, { 0xc , "DLSw Supported SAP List control vector is missing"}, { 0xd , "inconsistent DLSw Version, Multicast Capabilities,\ and TCP Connections CV received on the inbound Capabilities exchange"}, { 0x0 , NULL } }; #define UDP_PORT_DLSW 2067 #define TCP_PORT_DLSW 2065 #define DLSW_INFO_HEADER 16 #define DLSW_CMD_HEADER 72 static void dissect_dlsw_capex(tvbuff_t *tvb, proto_tree *tree, proto_tree *ti); static void dissect_dlsw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint version,hlen = 0,mlen = 0,mtype,dlchlen = 0,direction; proto_tree *dlsw_tree = NULL, *ti,*ti2, *dlsw_header_tree = NULL; proto_tree *dlsw_data_tree; if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "DLSw"); version=tvb_get_guint8(tvb,0); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "DLSw %s",val_to_str(version , dlsw_version_vals, "Unknown Version")); if (tree) { ti = proto_tree_add_item(tree, proto_dlsw, tvb, 0, -1, FALSE); dlsw_tree = proto_item_add_subtree(ti, ett_dlsw); hlen=tvb_get_guint8(tvb,1); ti2 = proto_tree_add_text (dlsw_tree, tvb, 0, hlen,"DLSw header, %s", val_to_str(version , dlsw_version_vals, "Unknown Version")); dlsw_header_tree = proto_item_add_subtree(ti2, ett_dlsw_header); proto_tree_add_text (dlsw_header_tree,tvb,0 ,1,"Version = %s", val_to_str(version , dlsw_version_vals, "Unknown Version, dissection may be innacurate")); proto_tree_add_text (dlsw_header_tree,tvb,1 ,1,"Header Length = %u",hlen) ; mlen=tvb_get_ntohs(tvb,2); proto_tree_add_text (dlsw_header_tree,tvb,2 ,2,"Message Length = %u",mlen); proto_tree_add_text (dlsw_header_tree,tvb,4 ,4,"Remote DLC = %u",tvb_get_ntohl(tvb,4)) ; proto_tree_add_text (dlsw_header_tree,tvb,8 ,4,"Remote DLC PID = %u",tvb_get_ntohl(tvb,8)) ; proto_tree_add_text (dlsw_header_tree,tvb,12,2,"Reserved") ; } ; mtype=tvb_get_guint8(tvb,14); if (check_col(pinfo->cinfo, COL_INFO)) col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",val_to_str(mtype , dlsw_type_vals, "Unknown message Type")); if (tree) { proto_tree_add_text (dlsw_header_tree,tvb,14,1,"Message Type = %s (%d)", val_to_str(mtype , dlsw_type_vals, "Unknown Type"),mtype); proto_tree_add_text (dlsw_header_tree, tvb, 15,1,"Flow ctrl byte = %d",tvb_get_guint8(tvb,15)); if (hlen != DLSW_INFO_HEADER) { proto_tree_add_text (dlsw_header_tree,tvb, 16,1,"Protocol ID = %d",tvb_get_guint8(tvb,16)) ; proto_tree_add_text (dlsw_header_tree,tvb, 17,1,"Header Number = %d",tvb_get_guint8(tvb,17)) ; proto_tree_add_text (dlsw_header_tree,tvb, 18,2,"Reserved") ; proto_tree_add_text (dlsw_header_tree,tvb, 20,1,"Largest Frame size = %d",tvb_get_guint8(tvb,20)) ; proto_tree_add_text (dlsw_header_tree,tvb, 21,1,"SSP Flags = %d",tvb_get_guint8(tvb,21)) ; proto_tree_add_text (dlsw_header_tree,tvb, 22,1,"Circuit priority = %s", match_strval((tvb_get_guint8(tvb,22)&7),dlsw_pri_vals)) ; proto_tree_add_text (dlsw_header_tree,tvb, 23,1,"Old message type = %s (%d)", val_to_str(tvb_get_guint8(tvb,23) , dlsw_type_vals, "Unknown Type"),tvb_get_guint8(tvb,23)); if (mtype==CAP_EXCHANGE) { proto_tree_add_text (dlsw_header_tree,tvb, 24 ,14,"Not used for CapEx") ; proto_tree_add_text (dlsw_header_tree,tvb, 38,1,"Frame direction = %s", tvb_get_guint8(tvb,38)==1?"Capabilities request":"Capabilities response") ; proto_tree_add_text (dlsw_header_tree,tvb, 39,33,"Not used for CapEx") ; } else { proto_tree_add_text (dlsw_header_tree,tvb, 24,6,"Target MAC Address = %s",tvb_bytes_to_str(tvb,24,6)) ; proto_tree_add_text (dlsw_header_tree,tvb, 30,6,"Origin MAC Address = %s",tvb_bytes_to_str(tvb,30,6)) ; proto_tree_add_text (dlsw_header_tree,tvb, 36,1,"Origin Link SAP = %02x",tvb_get_guint8(tvb,36)) ; proto_tree_add_text (dlsw_header_tree,tvb, 37,1,"Target Link SAP = %02x",tvb_get_guint8(tvb,37)) ; proto_tree_add_text (dlsw_header_tree,tvb, 38,1,"Frame direction = %d",tvb_get_guint8(tvb,38)) ; proto_tree_add_text (dlsw_header_tree,tvb, 39,3,"Reserved") ; dlchlen=tvb_get_ntohs(tvb,42); proto_tree_add_text (dlsw_header_tree,tvb, 42,2,"DLC Header Length = %d",dlchlen) ; proto_tree_add_text (dlsw_header_tree,tvb, 44,4,"Origin DLC Port ID = %u",tvb_get_ntohl(tvb,44)) ; proto_tree_add_text (dlsw_header_tree,tvb, 48,4,"Origin DLC = %u",tvb_get_ntohl(tvb,48)) ; proto_tree_add_text (dlsw_header_tree,tvb, 52,4,"Origin Transport ID = %u",tvb_get_ntohl(tvb,52)) ; proto_tree_add_text (dlsw_header_tree,tvb, 56,4,"Target DLC Port ID = %u",tvb_get_ntohl(tvb,56)) ; proto_tree_add_text (dlsw_header_tree,tvb, 60,4,"Target DLC = %u",tvb_get_ntohl(tvb,60)) ; proto_tree_add_text (dlsw_header_tree,tvb, 64,4,"Target Transport ID = %u",tvb_get_ntohl(tvb,64)) ; proto_tree_add_text (dlsw_header_tree,tvb, 68,4,"Reserved") ; } direction=tvb_get_guint8(tvb,38); } /* end of header dissector */ ti2 = proto_tree_add_text (dlsw_tree, tvb, hlen, mlen,"DLSw data"); dlsw_data_tree = proto_item_add_subtree(ti2, ett_dlsw_data); switch (mtype) { case CAP_EXCHANGE: dissect_dlsw_capex(tvb_new_subset(tvb, hlen, mlen, -1), dlsw_data_tree,ti2); break; case IFCM: case INFOFRAME: case KEEPALIVE: proto_tree_add_text (dlsw_data_tree,tvb,hlen,mlen,"Data") ; break; default: if (dlchlen!=0) { proto_tree_add_text (dlsw_data_tree,tvb,hlen,1,"DLC Header - AC byte : 0x%02x",tvb_get_guint8(tvb,hlen)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+1,1,"DLC Header - FC byte : 0x%02x",tvb_get_guint8(tvb,hlen+1)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+2,6,"DLC Header - DA : %s",tvb_bytes_to_str(tvb,hlen+2,6)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+8,6,"DLC Header - SA : %s",tvb_bytes_to_str(tvb,hlen+8,6)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+14,18,"DLC Header - RIF : %s",tvb_bytes_to_str(tvb,hlen+14,18)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+32,1,"DLC Header - DSAP : 0x%02x",tvb_get_guint8(tvb,hlen+32)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+33,1,"DLC Header - SSAP : 0x%02x",tvb_get_guint8(tvb,hlen+33)) ; proto_tree_add_text (dlsw_data_tree,tvb,hlen+34,1,"DLC Header - Ctrl : 0x%02x",tvb_get_guint8(tvb,hlen+34)) ; } proto_tree_add_text (dlsw_data_tree,tvb,hlen+dlchlen,mlen-dlchlen,"Data") ; } } } static void dissect_dlsw_capex(tvbuff_t *tvb, proto_tree *tree, proto_tree *ti2) { int mlen,vlen,vtype,offset=4,gdsid,sap,i=0; proto_tree *ti,*dlsw_vector_tree; mlen=tvb_get_ntohs(tvb,0); gdsid=tvb_get_ntohs(tvb,2); proto_tree_add_text (tree,tvb,0,2,"Capabilities Length = %d",mlen) ; proto_tree_add_text (tree,tvb,2,2,"%s",val_to_str( gdsid, dlsw_gds_vals, "Invalid GDS ID")); proto_item_append_text(ti2," - %s",val_to_str( gdsid, dlsw_gds_vals, "Invalid GDS ID")); switch (gdsid) { case DLSW_GDSID_ACK: break; case DLSW_GDSID_REF: proto_tree_add_text (tree,tvb,4,2,"Erorr pointer = %d",tvb_get_ntohs(tvb,4)); proto_tree_add_text (tree,tvb,6,2,"Erorr cause = %s", val_to_str(tvb_get_ntohs(tvb,6), dlsw_refuse_vals, "Unknown refuse cause")); break; case DLSW_GDSID_SEND: while (offset < mlen){ vlen=tvb_get_guint8(tvb,offset); vtype=tvb_get_guint8(tvb,offset+1); ti=proto_tree_add_text (tree,tvb,offset,vlen,"%s", val_to_str(vtype,dlsw_vector_vals,"Unknown vector type")); dlsw_vector_tree = proto_item_add_subtree(ti, ett_dlsw_vector); proto_tree_add_text (dlsw_vector_tree,tvb,offset,1, "Vector Length = %d",vlen); proto_tree_add_text (dlsw_vector_tree,tvb,offset+1,1,"Vector Type = %s (0x%02x)", val_to_str(vtype,dlsw_vector_vals,"Unknown vector type"),vtype); switch (vtype){ case 0x81: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "OUI = 0x%06x",tvb_get_ntoh24(tvb,offset+2)); break; case 0x82: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "DLSw Version = %d.%d",tvb_get_guint8(tvb,offset+2),tvb_get_guint8(tvb,offset+3)); break; case 0x83: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "Initial Pacing Window = %d",tvb_get_ntohs(tvb,offset+2)); break; case 0x84: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "Version String = %s",tvb_format_text(tvb,offset+2,vlen-2)); break; case 0x85: proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2, "MAC Address Exclusivity = %s",tvb_get_guint8(tvb,offset+2)==1?"On":"Off"); break; case 0x86: while (i