baf4bfd816a7c95b8e02e1ef2271ef84531e476d
[obnox/wireshark/wip.git] / packet-dlsw.c
1 /* packet-dlsw.c
2  * Routines for DLSw packet dissection (Data Link Switching)
3  * Copyright 2001, Paul Ionescu <paul@acorp.ro>
4  *
5  * $Id: packet-dlsw.c,v 1.2 2001/12/26 21:21:00 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 /* DLSw dissector ( RFC 1434, RFC 1795, RFC 2166) */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
36 #endif
37
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
40 #endif
41
42 #include <string.h>
43 #include <glib.h>
44 #include "packet.h"
45
46 static int proto_dlsw = -1;
47
48 static gint ett_dlsw = -1;
49 static gint ett_dlsw_header = -1;
50 static gint ett_dlsw_data = -1;
51 static gint ett_dlsw_vector = -1;
52
53 #define  CANUREACH               0x03                     
54 #define  ICANREACH               0x04
55 #define  REACH_ACK               0x05
56 #define  DGRMFRAME               0x06
57 #define  XIDFRAME                0x07
58 #define  CONTACT                 0x08
59 #define  CONTACTED               0x09
60 #define  RESTART_DL              0x10
61 #define  DL_RESTARTED            0x11
62 #define  ENTER_BUSY              0x0C
63 #define  EXIT_BUSY               0x0D
64 #define  INFOFRAME               0x0A
65 #define  HALT_DL                 0x0E
66 #define  DL_HALTED               0x0F
67 #define  NETBIOS_NQ              0x12
68 #define  NETBIOS_NR              0x13
69 #define  DATAFRAME               0x14
70 #define  HALT_DL_NOACK           0x19
71 #define  NETBIOS_ANQ             0x1A
72 #define  NETBIOS_ANR             0x1B
73 #define  KEEPALIVE               0x1D
74 #define  CAP_EXCHANGE            0x20
75 #define  IFCM                    0x21
76 #define  TEST_CIRCUIT_REQ        0x7A
77 #define  TEST_CIRCUIT_RSP        0x7B
78
79 static const value_string dlsw_type_vals[] = {
80         { CANUREACH        , "Can U Reach Station-circuit start" },
81         { ICANREACH        , "I Can Reach Station-circuit start" },
82         { REACH_ACK        , "Reach Acknowledgment" },
83         { DGRMFRAME        , "Datagram Frame" },
84         { XIDFRAME         , "XID Frame" },
85         { CONTACT          , "Contact Remote Station" },
86         { CONTACTED        , "Remote Station Contacted" },
87         { RESTART_DL       , "Restart Data Link" },
88         { DL_RESTARTED     , "Data Link Restarted" },
89         { ENTER_BUSY       , "Enter Busy" },
90         { EXIT_BUSY        , "Exit Busy" },
91         { INFOFRAME        , "Information (I) Frame" },
92         { HALT_DL          , "Halt Data Link" },
93         { DL_HALTED        , "Data Link Halted" },
94         { NETBIOS_NQ       , "NETBIOS Name Query-circuit setup" },
95         { NETBIOS_NR       , "NETBIOS Name Recog-circuit setup" },
96         { DATAFRAME        , "Data Frame" },
97         { HALT_DL_NOACK    , "Halt Data Link with no Ack" },
98         { NETBIOS_ANQ      , "NETBIOS Add Name Query" },
99         { NETBIOS_ANR      , "NETBIOS Add Name Response" },
100         { KEEPALIVE        , "Transport Keepalive Message" },
101         { CAP_EXCHANGE     , "Capabilities Exchange" },
102         { IFCM             , "Independent Flow Control Message" },
103         { TEST_CIRCUIT_REQ , "Test Circuit Request" },
104         { TEST_CIRCUIT_RSP , "Test Circuit Response" },
105         { 0 , NULL }
106 };
107 static const value_string dlsw_version_vals[] = {
108         { 0x31        , "Version 1 (RFC 1795)" },
109         { 0x32        , "Version 2 (RFC 2166)" },
110         { 0x33        , "Vendor Specific" },
111         { 0x34        , "Vendor Specific" },
112         { 0x35        , "Vendor Specific" },
113         { 0x36        , "Vendor Specific" },
114         { 0x37        , "Vendor Specific" },
115         { 0x38        , "Vendor Specific" },
116         { 0x39        , "Vendor Specific" },
117         { 0x3A        , "Vendor Specific" },
118         { 0x3B        , "Vendor Specific" },
119         { 0x3C        , "Vendor Specific" },
120         { 0x3D        , "Vendor Specific" },
121         { 0x3E        , "Vendor Specific" },
122         { 0x3F        , "Vendor Specific" },
123         { 0x4B        , "Pre 1 (RFC 1434)" },
124         { 0x00        , NULL }
125 };
126
127 static const value_string dlsw_vector_vals[] = {
128         { 0x81        , "Vendor ID Control Vector" },
129         { 0x82        , "DLSw Version Control Vector" },
130         { 0x83        , "Initial Pacing Window Control Vector" },
131         { 0x84        , "Version String Control Vector" },
132         { 0x85        , "Mac Address Exclusivity Control Vector" },
133         { 0x86        , "Supported SAP List Control Vector" },
134         { 0x87        , "TCP Connections Control Vector" },
135         { 0x88        , "NetBIOS Name Exclusivity Control Vector" },
136         { 0x89        , "MAC Address List Control Vector" },
137         { 0x8a        , "NetBIOS Name List Control Vector" },
138         { 0x8b        , "Vendor Context Control Vector" },
139         { 0x8c        , "Multicast Capabilities Control Vector" },
140         { 0x8d        , "Reserved for future use" },
141         { 0x8e        , "Reserved for future use" },
142         { 0x8f        , "Reserved for future use" },
143         { 0x90        , "Reserved for future use" },
144         { 0x91        , " Control Vector" },
145         { 0x92        , " Control Vector" },
146         { 0x93        , " Control Vector" },
147         { 0x94        , " Control Vector" },
148         { 0x95        , " Control Vector" },
149         { 0x96        , " Control Vector" },
150         { 0x00        , NULL }
151 };
152
153 static const value_string dlsw_pri_vals[] = {
154         { 0        , "Unsupported" },
155         { 1        , "Low Priority" },
156         { 2        , "Medium Priority" },
157         { 3        , "High Priority" },
158         { 4        , "Highest Priority" },
159         { 5        , "Reserved" },
160         { 6        , "Reserved" },
161         { 7        , "Reserved" }
162 };
163
164
165
166
167 #define DLSW_GDSID_SEND         0x1520
168 #define DLSW_GDSID_ACK          0x1521
169 #define DLSW_GDSID_REF          0x1522
170
171 static const value_string dlsw_gds_vals[] = {
172         { DLSW_GDSID_SEND , "Request Capabilities GDS" },
173         { DLSW_GDSID_ACK  , "Response Capabilities GDS" },
174         { DLSW_GDSID_REF  , "Refuse Capabilities GDS" }, 
175         { 0               , NULL }
176 };
177
178 static const value_string dlsw_refuse_vals[] = {
179         { 0x1   , "invalid GDS length for a DLWs Capabilities Exchange Request"},
180         { 0x2   , "invalid GDS id for a DLSw Capabilities Exchange Request"},
181         { 0x3   , "vendor Id control vector is missing"},
182         { 0x4   , "DLSw Version control vector is missing"},
183         { 0x5   , "initial Pacing Window control vector is missing"},
184         { 0x6   , "length of control vectors doewn't correlate to the length of the GDS variable"},
185         { 0x7   , "invalid control vector id"},
186         { 0x8   , "length of control vector invalid"},
187         { 0x9   , "invalid control vector data value"},
188         { 0xa   , "duplicate control vector"},
189         { 0xb   , "out-of-sequence control vector"},
190         { 0xc   , "DLSw Supported SAP List control vector is missing"},
191         { 0xd   , "inconsistent DLSw Version, Multicast Capabilities,\
192  and TCP Connections CV received on the inbound Capabilities exchange"},
193         { 0x0   , NULL }
194 };
195
196 #define UDP_PORT_DLSW           2067
197 #define TCP_PORT_DLSW           2065  
198 #define DLSW_INFO_HEADER        16
199 #define DLSW_CMD_HEADER         72
200
201 static void
202 dissect_dlsw_capex(tvbuff_t *tvb, proto_tree *tree, proto_tree *ti);
203
204 static void
205 dissect_dlsw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
206 {
207  guint version,hlen = 0,mlen = 0,mtype,offset,dlchlen = 0,direction;
208  proto_tree      *dlsw_tree = NULL, *ti,*ti2, *dlsw_header_tree = NULL;
209  proto_tree      *dlsw_data_tree;
210
211  if (check_col(pinfo->cinfo, COL_PROTOCOL))
212    col_set_str(pinfo->cinfo, COL_PROTOCOL, "DLSw");
213
214  version=tvb_get_guint8(tvb,0);
215
216  if (check_col(pinfo->cinfo, COL_INFO))
217    col_add_fstr(pinfo->cinfo, COL_INFO, "DLSw %s",val_to_str(version , dlsw_version_vals, "Unknown Version"));
218
219  if (tree) 
220  {
221    ti = proto_tree_add_item(tree, proto_dlsw, tvb, 0, tvb_length(tvb), FALSE);
222    dlsw_tree = proto_item_add_subtree(ti, ett_dlsw);
223    
224    hlen=tvb_get_guint8(tvb,1);
225
226    ti2 = proto_tree_add_text (dlsw_tree, tvb, 0, hlen,"DLSw header, %s",
227      val_to_str(version , dlsw_version_vals, "Unknown Version"));
228            
229    dlsw_header_tree = proto_item_add_subtree(ti2, ett_dlsw_header);
230    proto_tree_add_text (dlsw_header_tree,tvb,0 ,1,"Version        = %s",
231     val_to_str(version , dlsw_version_vals, "Unknown Version, dissection may be innacurate"));
232    proto_tree_add_text (dlsw_header_tree,tvb,1 ,1,"Header Length  = %u",hlen) ;
233    mlen=tvb_get_ntohs(tvb,2);
234    proto_tree_add_text (dlsw_header_tree,tvb,2 ,2,"Message Length = %u",mlen);
235    proto_tree_add_text (dlsw_header_tree,tvb,4 ,4,"Remote DLC     = %u",tvb_get_ntohl(tvb,4)) ;
236    proto_tree_add_text (dlsw_header_tree,tvb,8 ,4,"Remote DLC PID = %u",tvb_get_ntohl(tvb,8)) ;
237    proto_tree_add_text (dlsw_header_tree,tvb,12,2,"Reserved") ;
238   } ;
239   
240   mtype=tvb_get_guint8(tvb,14);
241   if (check_col(pinfo->cinfo, COL_INFO))
242      col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",val_to_str(mtype , dlsw_type_vals, "Unknown message Type"));
243   if (tree)
244   {  
245    proto_tree_add_text (dlsw_header_tree,tvb,14,1,"Message Type   = %s (%d)",
246     val_to_str(mtype , dlsw_type_vals, "Unknown Type"),mtype);
247    proto_tree_add_text (dlsw_header_tree, tvb, 15,1,"Flow ctrl byte = %d",tvb_get_guint8(tvb,15));
248
249    if (hlen != DLSW_INFO_HEADER) 
250     {
251     proto_tree_add_text (dlsw_header_tree,tvb, 16,1,"Protocol ID    = %d",tvb_get_guint8(tvb,16)) ;
252     proto_tree_add_text (dlsw_header_tree,tvb, 17,1,"Header Number  = %d",tvb_get_guint8(tvb,17)) ;
253     proto_tree_add_text (dlsw_header_tree,tvb, 18,2,"Reserved") ;
254     proto_tree_add_text (dlsw_header_tree,tvb, 20,1,"Largest Frame size  = %d",tvb_get_guint8(tvb,20)) ;
255     proto_tree_add_text (dlsw_header_tree,tvb, 21,1,"SSP Flags      = %d",tvb_get_guint8(tvb,21)) ;
256     proto_tree_add_text (dlsw_header_tree,tvb, 22,1,"Circuit priority = %s",
257      match_strval((tvb_get_guint8(tvb,22)&7),dlsw_pri_vals)) ;
258     proto_tree_add_text (dlsw_header_tree,tvb, 23,1,"Old message type = %s (%d)",
259      val_to_str(tvb_get_guint8(tvb,23) , dlsw_type_vals, "Unknown Type"),tvb_get_guint8(tvb,23));
260     if (mtype==CAP_EXCHANGE)
261      {
262      proto_tree_add_text (dlsw_header_tree,tvb, 24 ,14,"Not used for CapEx") ;
263      proto_tree_add_text (dlsw_header_tree,tvb, 38,1,"Frame direction   =  %s",
264       tvb_get_guint8(tvb,38)==1?"Capabilities request":"Capabilities response") ;    
265      proto_tree_add_text (dlsw_header_tree,tvb, 39,33,"Not used for CapEx") ;
266      }
267     else
268      {
269      proto_tree_add_text (dlsw_header_tree,tvb, 24,6,"Target MAC Address  = %s",tvb_bytes_to_str(tvb,24,6)) ;
270      proto_tree_add_text (dlsw_header_tree,tvb, 30,6,"Origin MAC Address  = %s",tvb_bytes_to_str(tvb,30,6)) ;
271      proto_tree_add_text (dlsw_header_tree,tvb, 36,1,"Origin Link SAP     = %02x",tvb_get_guint8(tvb,36)) ;
272      proto_tree_add_text (dlsw_header_tree,tvb, 37,1,"Target Link SAP     = %02x",tvb_get_guint8(tvb,37)) ;
273      proto_tree_add_text (dlsw_header_tree,tvb, 38,1,"Frame direction   = %d",tvb_get_guint8(tvb,38)) ;
274      proto_tree_add_text (dlsw_header_tree,tvb, 39,3,"Reserved") ;
275      dlchlen=tvb_get_ntohs(tvb,42);
276      proto_tree_add_text (dlsw_header_tree,tvb, 42,2,"DLC Header Length = %d",dlchlen) ;
277      proto_tree_add_text (dlsw_header_tree,tvb, 44,4,"Origin DLC Port ID     = %u",tvb_get_ntohl(tvb,44)) ;
278      proto_tree_add_text (dlsw_header_tree,tvb, 48,4,"Origin DLC             = %u",tvb_get_ntohl(tvb,48)) ;
279      proto_tree_add_text (dlsw_header_tree,tvb, 52,4,"Origin Transport ID    = %u",tvb_get_ntohl(tvb,52)) ;
280      proto_tree_add_text (dlsw_header_tree,tvb, 56,4,"Target DLC Port ID     = %u",tvb_get_ntohl(tvb,56)) ;
281      proto_tree_add_text (dlsw_header_tree,tvb, 60,4,"Target DLC             = %u",tvb_get_ntohl(tvb,60)) ;
282      proto_tree_add_text (dlsw_header_tree,tvb, 64,4,"Target Transport ID    = %u",tvb_get_ntohl(tvb,64)) ;
283      proto_tree_add_text (dlsw_header_tree,tvb, 68,4,"Reserved") ;
284      }
285     direction=tvb_get_guint8(tvb,38);
286     }
287
288 /* end of header dissector */
289
290     ti2 = proto_tree_add_text (dlsw_tree, tvb, hlen, mlen,"DLSw data");
291     dlsw_data_tree = proto_item_add_subtree(ti2, ett_dlsw_data);
292
293     switch (mtype) 
294       {
295       case CAP_EXCHANGE:
296         dissect_dlsw_capex(tvb_new_subset(tvb, hlen, mlen, -1), dlsw_data_tree,ti2);
297         break;
298       case IFCM:
299       case INFOFRAME:
300       case KEEPALIVE:
301         proto_tree_add_text (dlsw_data_tree,tvb,hlen,mlen,"Data") ;
302         break;
303
304       default:
305         if (dlchlen!=0)
306          {
307          proto_tree_add_text (dlsw_data_tree,tvb,hlen,1,"DLC Header - AC byte : 0x%02x",tvb_get_guint8(tvb,hlen)) ;
308          proto_tree_add_text (dlsw_data_tree,tvb,hlen+1,1,"DLC Header - FC byte : 0x%02x",tvb_get_guint8(tvb,hlen+1)) ;
309          proto_tree_add_text (dlsw_data_tree,tvb,hlen+2,6,"DLC Header - DA : %s",tvb_bytes_to_str(tvb,hlen+2,6)) ;
310          proto_tree_add_text (dlsw_data_tree,tvb,hlen+8,6,"DLC Header - SA : %s",tvb_bytes_to_str(tvb,hlen+8,6)) ;
311          proto_tree_add_text (dlsw_data_tree,tvb,hlen+14,18,"DLC Header - RIF : %s",tvb_bytes_to_str(tvb,hlen+14,18)) ;
312          proto_tree_add_text (dlsw_data_tree,tvb,hlen+32,1,"DLC Header - DSAP : 0x%02x",tvb_get_guint8(tvb,hlen+32)) ;
313          proto_tree_add_text (dlsw_data_tree,tvb,hlen+33,1,"DLC Header - SSAP : 0x%02x",tvb_get_guint8(tvb,hlen+33)) ;
314          proto_tree_add_text (dlsw_data_tree,tvb,hlen+34,1,"DLC Header - Ctrl : 0x%02x",tvb_get_guint8(tvb,hlen+34)) ;
315          }
316         proto_tree_add_text (dlsw_data_tree,tvb,hlen+dlchlen,mlen-dlchlen,"Data") ;
317       }
318
319    }
320 }
321
322 static void
323 dissect_dlsw_capex(tvbuff_t *tvb, proto_tree *tree, proto_tree *ti2)
324 {
325  int mlen,vlen,vtype,offset=4,gdsid,sap,i=0;
326  proto_tree *ti,*dlsw_vector_tree;
327  mlen=tvb_get_ntohs(tvb,0);
328  gdsid=tvb_get_ntohs(tvb,2);
329  proto_tree_add_text (tree,tvb,0,2,"Capabilities Length =  %d",mlen) ;
330  proto_tree_add_text (tree,tvb,2,2,"%s",val_to_str( gdsid, dlsw_gds_vals, "Invalid GDS ID"));
331  proto_item_append_text(ti2," - %s",val_to_str( gdsid, dlsw_gds_vals, "Invalid GDS ID"));
332  switch (gdsid) {
333   case DLSW_GDSID_ACK:
334     break;
335   case DLSW_GDSID_REF:
336     proto_tree_add_text (tree,tvb,4,2,"Erorr pointer =  %d",tvb_get_ntohs(tvb,4));
337     proto_tree_add_text (tree,tvb,6,2,"Erorr cause = %s",
338      val_to_str(tvb_get_ntohs(tvb,6), dlsw_refuse_vals, "Unknown refuse cause"));
339     break;
340   case DLSW_GDSID_SEND:
341     while (offset < mlen){
342       vlen=tvb_get_guint8(tvb,offset);
343       vtype=tvb_get_guint8(tvb,offset+1);
344       ti=proto_tree_add_text (tree,tvb,offset,vlen,"%s",
345          val_to_str(vtype,dlsw_vector_vals,"Unknown vector type"));
346       dlsw_vector_tree = proto_item_add_subtree(ti, ett_dlsw_vector);
347       proto_tree_add_text (dlsw_vector_tree,tvb,offset,1,  "Vector Length = %d",vlen);
348       proto_tree_add_text (dlsw_vector_tree,tvb,offset+1,1,"Vector Type   = %s (0x%02x)",
349        val_to_str(vtype,dlsw_vector_vals,"Unknown vector type"),vtype);
350       switch (vtype){
351         case 0x81:
352           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
353            "OUI = 0x%06x",tvb_get_ntoh24(tvb,offset+2));
354           break;
355         case 0x82:
356           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
357            "DLSw Version = %d.%d",tvb_get_guint8(tvb,offset+2),tvb_get_guint8(tvb,offset+3));
358           break;            
359         case 0x83:
360           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
361            "Initial Pacing Window = %d",tvb_get_ntohs(tvb,offset+2));
362           break;
363         case 0x84:
364            proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
365            "Version String = %s",tvb_format_text(tvb,offset+2,vlen-2));
366           break;
367         case 0x85:
368           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
369            "MAC Address Exclusivity = %s",tvb_get_guint8(tvb,offset+2)==1?"On":"Off");
370           break;
371         case 0x86:
372           while (i<vlen-2)
373            {
374            sap=tvb_get_guint8(tvb,offset+2+i);
375            proto_tree_add_text (dlsw_vector_tree,tvb,offset+2+i,1,
376             "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",
377             i,sap&0x80?"on ":"off",i,sap&0x40?"on ":"off",i,sap&0x20?"on ":"off",i,sap&0x10?"on ":"off",
378             i,sap&0x08?"on ":"off",i,sap&0x04?"on ":"off",i,sap&0x02?"on ":"off",i,sap&0x01?"on ":"off");
379            i++;
380            }
381           break;
382         case 0x87:
383           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
384            "TCP connections  = %d",tvb_get_guint8(tvb,offset+2));
385           break;
386         case 0x88:
387           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
388            "NetBIOS Name Exclusivity = %s",tvb_get_guint8(tvb,offset+2)==1?"On":"Off");
389           break;
390         case 0x89:
391           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
392            "MAC Address List = %s / %s",tvb_bytes_to_str(tvb,offset+2,6)
393            ,tvb_bytes_to_str(tvb,offset+8,6));
394           break;
395         case 0x8a:
396           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
397 /* %s */           "NetBIOS name = %s",/* tvb_get_guint8(tvb,offset+2)==0?"Individual":"Group",*/
398            tvb_format_text(tvb,offset+2,vlen-2));
399           break;
400         case 0x8b:
401           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
402            "Vendor OUI = 0x%06x",tvb_get_ntoh24(tvb,offset+2));
403           break;
404         case 0x8c:
405           proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
406            "Multicast Version Number = %d",tvb_get_guint8(tvb,offset+2));
407           break;
408         default:
409         proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,"Vector Data = ???");
410         }
411       offset+=vlen;
412       };
413     break;
414   default:
415     proto_tree_add_text (tree,tvb,4,mlen - 4,"Unknown data");
416   }
417         
418 }
419
420 void
421 proto_register_dlsw(void)
422 {
423         static gint *ett[] = {
424                 &ett_dlsw,
425                 &ett_dlsw_header,
426                 &ett_dlsw_data,
427                 &ett_dlsw_vector,
428         };
429         proto_dlsw = proto_register_protocol("Data Link SWitching", "DLSw", "dlsw");
430 /*      proto_register_field_array(proto_dlsw, hf, array_length(hf)); */
431         proto_register_subtree_array(ett, array_length(ett));
432 }
433                                                                              
434 void
435 proto_reg_handoff_dlsw(void)
436 {
437         dissector_handle_t dlsw_handle;
438
439         dlsw_handle = create_dissector_handle(dissect_dlsw, proto_dlsw);
440
441         dissector_add("tcp.port", TCP_PORT_DLSW, dlsw_handle);
442         dissector_add("udp.port", UDP_PORT_DLSW, dlsw_handle);
443 }