wireshark/epan/dissectors/packet-dlsw.c
Guy Harris d1f9f0b516 Use tcp_dissect_pdus() for DLSw-over-TCP.
Have the DLSw dissector reject packets with an unknown version field.

Leave out some more fields when dissecting Capability Exchange packets,
as they're not used in those packets.

Show numbers in hex when appropriate.

Show the individual subfields of the flow control and SSP flags fields.

Show the frame direction field with val_to_str(), and show the raw
value.

Clean up indentation.

svn path=/trunk/; revision=13019
2005-01-13 17:26:10 +00:00

556 lines
22 KiB
C

/* packet-dlsw.c
* Routines for DLSw packet dissection (Data Link Switching)
* Copyright 2001, Paul Ionescu <paul@acorp.ro>
*
* $Id$
*
* 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.
*/
/* DLSw dissector ( RFC 1434, RFC 1795, RFC 2166) */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <epan/packet.h>
#include "packet-tcp.h"
static int proto_dlsw = -1;
static gint ett_dlsw = -1;
static gint ett_dlsw_header = -1;
static gint ett_dlsw_fc = -1;
static gint ett_dlsw_sspflags = -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_fc_cmd_vals[] = {
{ 0x00 , "Repeat Window" },
{ 0x01 , "Increment Window" },
{ 0x02 , "Decrement Window" },
{ 0x03 , "Reset Window" },
{ 0x04 , "Halve Window" },
{ 0x00 , NULL }
};
static const value_string dlsw_capex_type_vals[] = {
{ 0x01 , "Capabilities request" },
{ 0x02 , "Capabilities response" },
{ 0x00 , NULL }
};
static const value_string dlsw_frame_direction_vals[] = {
{ 0x01 , "Origin DLSw to target DLSw" },
{ 0x02 , "Target DLSw to origin DLSw" },
{ 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_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
guint version,hlen = 0,mlen = 0,mtype,dlchlen = 0,direction,flags;
proto_tree *dlsw_tree = NULL, *ti,*ti2, *dlsw_header_tree = NULL;
proto_tree *dlsw_flags_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 (0x%02x)",
val_to_str(mtype , dlsw_type_vals, "Unknown Type"),mtype);
if (mtype==CAP_EXCHANGE)
{
proto_tree_add_text (dlsw_header_tree,tvb, 15,1,"Not used for CapEx") ;
}
else
{
flags = tvb_get_guint8(tvb,15);
ti2 = proto_tree_add_text (dlsw_header_tree, tvb, 15,1,"Flow ctrl byte = 0x%02x",flags);
dlsw_flags_tree = proto_item_add_subtree(ti2, ett_dlsw_fc);
proto_tree_add_text (dlsw_flags_tree, tvb, 15, 1, "%s",
decode_boolean_bitfield(flags, 0x80, 8,
"Flow Control Indication: yes",
"Flow Control Indication: no"));
if (flags & 0x80)
{
proto_tree_add_text (dlsw_flags_tree, tvb, 15, 1, "%s",
decode_boolean_bitfield(flags, 0x40, 8,
"Flow Control Acknowledgment: yes",
"Flow Control Acknowledgment: no"));
proto_tree_add_text (dlsw_flags_tree, tvb, 15, 1, "%s",
decode_enumerated_bitfield(flags, 0x07, 8,
dlsw_fc_cmd_vals, "Flow Control Operator: %s"));
}
}
if (hlen != DLSW_INFO_HEADER)
{
if (mtype==CAP_EXCHANGE)
{
proto_tree_add_text (dlsw_header_tree,tvb, 16,1,"Protocol ID = 0x%02x",tvb_get_guint8(tvb,16)) ;
proto_tree_add_text (dlsw_header_tree,tvb, 17,1,"Header Number = 0x%02x",tvb_get_guint8(tvb,17)) ;
proto_tree_add_text (dlsw_header_tree,tvb, 18,5,"Not used for CapEx") ;
proto_tree_add_text (dlsw_header_tree,tvb, 23,1,"Old message type = %s (0x%02x)",
val_to_str(tvb_get_guint8(tvb,23) , dlsw_type_vals, "Unknown Type"),
tvb_get_guint8(tvb,23));
direction=tvb_get_guint8(tvb,38);
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 (0x%02x)",
val_to_str(direction , dlsw_capex_type_vals, "Unknown Direction"),
direction);
proto_tree_add_text (dlsw_header_tree,tvb, 39,33,"Not used for CapEx") ;
}
else
{
proto_tree_add_text (dlsw_header_tree,tvb, 16,1,"Protocol ID = 0x%02x",tvb_get_guint8(tvb,16)) ;
proto_tree_add_text (dlsw_header_tree,tvb, 17,1,"Header Number = 0x%02x",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 = %u",tvb_get_guint8(tvb,20)) ;
flags = tvb_get_guint8(tvb,21);
ti2 = proto_tree_add_text (dlsw_header_tree,tvb, 21,1,"SSP Flags = 0x%02x",flags) ;
dlsw_flags_tree = proto_item_add_subtree(ti2, ett_dlsw_sspflags);
proto_tree_add_text (dlsw_flags_tree, tvb, 21, 1, "%s",
decode_boolean_bitfield(flags, 0x80, 8,
"Explorer message: yes",
"Explorer message: no"));
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 (0x%02x)",
val_to_str(tvb_get_guint8(tvb,23) , dlsw_type_vals, "Unknown Type"),
tvb_get_guint8(tvb,23));
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 = 0x%02x",tvb_get_guint8(tvb,36)) ;
proto_tree_add_text (dlsw_header_tree,tvb, 37,1,"Target Link SAP = 0x%02x",tvb_get_guint8(tvb,37)) ;
direction=tvb_get_guint8(tvb,38);
proto_tree_add_text (dlsw_header_tree,tvb, 38,1,"Frame direction = %s (0x%02x)",
val_to_str(direction , dlsw_frame_direction_vals, "Unknown Direction"),
direction);
proto_tree_add_text (dlsw_header_tree,tvb, 39,3,"Reserved") ;
dlchlen=tvb_get_ntohs(tvb,42);
if ( dlchlen > mlen )
{
proto_tree_add_text (dlsw_header_tree,tvb, 42,2,"DLC Header Length = %u (bogus, must be <= message length %u)",dlchlen, mlen) ;
return;
}
proto_tree_add_text (dlsw_header_tree,tvb, 42,2,"DLC Header Length = %u",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") ;
}
}
/* 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<vlen-2)
{
sap=tvb_get_guint8(tvb,offset+2+i);
proto_tree_add_text (dlsw_vector_tree,tvb,offset+2+i,1,
"SAP List Support = 0x%x0=%s 0x%x2=%s 0x%x4=%s 0x%x6=%s 0x%x8=%s 0x%xa=%s 0x%xc=%s 0x%xe=%s",
i,sap&0x80?"on ":"off",i,sap&0x40?"on ":"off",i,sap&0x20?"on ":"off",i,sap&0x10?"on ":"off",
i,sap&0x08?"on ":"off",i,sap&0x04?"on ":"off",i,sap&0x02?"on ":"off",i,sap&0x01?"on ":"off");
i++;
}
break;
case 0x87:
proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
"TCP connections = %d",tvb_get_guint8(tvb,offset+2));
break;
case 0x88:
proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
"NetBIOS Name Exclusivity = %s",tvb_get_guint8(tvb,offset+2)==1?"On":"Off");
break;
case 0x89:
proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
"MAC Address List = %s / %s",tvb_bytes_to_str(tvb,offset+2,6)
,tvb_bytes_to_str(tvb,offset+8,6));
break;
case 0x8a:
proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
/* %s */ "NetBIOS name = %s",/* tvb_get_guint8(tvb,offset+2)==0?"Individual":"Group",*/
tvb_format_text(tvb,offset+2,vlen-2));
break;
case 0x8b:
proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
"Vendor OUI = 0x%06x",tvb_get_ntoh24(tvb,offset+2));
break;
case 0x8c:
proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
"Multicast Version Number = %d",tvb_get_guint8(tvb,offset+2));
break;
default:
proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,"Vector Data = ???");
}
offset+=vlen;
};
break;
default:
proto_tree_add_text (tree,tvb,4,mlen - 4,"Unknown data");
}
}
static int
dissect_dlsw_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (match_strval(tvb_get_guint8(tvb, 0), dlsw_version_vals) == NULL)
{
/* Probably not a DLSw packet. */
return 0;
}
dissect_dlsw_pdu(tvb, pinfo, tree);
return tvb_length(tvb);
}
static guint
get_dlsw_pdu_len(tvbuff_t *tvb, int offset)
{
guint hlen, mlen;
/*
* Get the length of the DLSw header.
*/
hlen=tvb_get_guint8(tvb,offset+1);
/*
* Get the length of the DLSw message.
*/
mlen = tvb_get_ntohs(tvb,offset+2);
/*
* The total length is the sum of those.
*/
return hlen + mlen;
}
static int
dissect_dlsw_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (match_strval(tvb_get_guint8(tvb, 0), dlsw_version_vals) == NULL)
{
/* Probably not a DLSw packet. */
return 0;
}
tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 4, get_dlsw_pdu_len,
dissect_dlsw_pdu);
return tvb_length(tvb);
}
void
proto_register_dlsw(void)
{
static gint *ett[] = {
&ett_dlsw,
&ett_dlsw_header,
&ett_dlsw_fc,
&ett_dlsw_sspflags,
&ett_dlsw_data,
&ett_dlsw_vector,
};
proto_dlsw = proto_register_protocol("Data Link SWitching", "DLSw", "dlsw");
/* proto_register_field_array(proto_dlsw, hf, array_length(hf)); */
proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_dlsw(void)
{
dissector_handle_t dlsw_udp_handle, dlsw_tcp_handle;
dlsw_udp_handle = new_create_dissector_handle(dissect_dlsw_udp, proto_dlsw);
dissector_add("udp.port", UDP_PORT_DLSW, dlsw_udp_handle);
dlsw_tcp_handle = new_create_dissector_handle(dissect_dlsw_tcp, proto_dlsw);
dissector_add("tcp.port", TCP_PORT_DLSW, dlsw_tcp_handle);
}