The color stuff is almost completely toolkit-dependent (this isn't just
[obnox/wireshark/wip.git] / packet-isl.c
1 /* packet-isl.c
2  * Routines for Cisco ISL Ethernet header disassembly
3  *
4  * $Id: packet-isl.c,v 1.4 2000/01/24 21:56:24 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
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 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
36 #endif
37
38 #include <glib.h>
39 #include "packet.h"
40 #include "etypes.h"
41
42 /*
43  * See
44  *
45  *      http://www.cisco.com/warp/public/741/4.html
46  *
47  * and
48  *
49  *      http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
50  *
51  * for information on ISL.
52  */
53 static int proto_isl = -1;
54 static int hf_isl_dst = -1;
55 static int hf_isl_type = -1;
56 static int hf_isl_user_eth = -1;
57 static int hf_isl_user = -1;
58 static int hf_isl_src = -1;
59 static int hf_isl_len = -1;
60 static int hf_isl_hsa = -1;
61 static int hf_isl_vlan_id = -1;
62 static int hf_isl_bpdu = -1;
63 static int hf_isl_index = -1;
64 static int hf_isl_crc = -1;
65 static int hf_isl_src_vlan_id = -1;
66 static int hf_isl_explorer = -1;
67 static int hf_isl_dst_route_descriptor = -1;
68 static int hf_isl_src_route_descriptor = -1;
69 static int hf_isl_fcs_not_incl = -1;
70 static int hf_isl_esize = -1;
71
72 static gint ett_isl = -1;
73
74 #define ISL_HEADER_SIZE 26
75
76 #define TYPE_ETHER      0x0
77 #define TYPE_TR         0x1
78 #define TYPE_FDDI       0x2
79 #define TYPE_ATM        0x3
80
81 void
82 capture_isl(const u_char *pd, int offset, packet_counts *ld)
83 {
84   guint8 type;
85
86   if (!BYTES_ARE_IN_FRAME(offset, ISL_HEADER_SIZE)) {
87     ld->other++;
88     return;
89   }
90
91   type = (pd[offset+5] >> 4)&0x0F;
92
93   switch (type) {
94
95   case TYPE_ETHER:
96     offset += 14+12;    /* skip the header */
97     capture_eth(pd, offset, ld);
98     break;
99
100   case TYPE_TR:
101     offset += 14+17;    /* skip the header */
102     capture_tr(pd, offset, ld);
103     break;
104
105   default:
106     ld->other++;
107     break;
108   }
109 }
110
111 static const value_string type_vals[] = {
112         {TYPE_ETHER, "Ethernet"},
113         {TYPE_TR,    "Token-Ring"},
114         {TYPE_FDDI,  "FDDI"},
115         {TYPE_ATM,   "ATM"},
116         {0,          NULL}
117 };
118
119 static const value_string ether_user_vals[] = {
120         {0x0, "Normal priority"},
121         {0x1, "Priority 1"},
122         {0x2, "Priority 2"},
123         {0x3, "Highest priority"},
124         {0,   NULL}
125 };
126
127 static const true_false_string bpdu_tfs = {
128         "Yes",
129         "No"
130 };
131
132 static const true_false_string explorer_tfs = {
133         "Explorer frame",
134         "Data frame"
135 };
136
137 void
138 dissect_isl(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
139 {
140   proto_tree *fh_tree = NULL;
141   proto_item *ti;
142   guint8 type;
143   guint16 length;
144   
145   if (!BYTES_ARE_IN_FRAME(offset, ISL_HEADER_SIZE)) {
146     dissect_data(pd, offset, fd, tree);
147     return;
148   }
149
150   if (check_col(fd, COL_PROTOCOL))
151     col_add_str(fd, COL_PROTOCOL, "ISL");
152   if (check_col(fd, COL_INFO))
153     col_add_fstr(fd, COL_INFO, "VLAN ID: 0x%04X", pntohs(&pd[offset+20]) >> 1);
154
155   type = (pd[offset+5] >> 4)&0x0F;
156
157   if (tree) {
158     ti = proto_tree_add_item_format(tree, proto_isl, offset, ISL_HEADER_SIZE,
159                 NULL, "ISL");
160     fh_tree = proto_item_add_subtree(ti, ett_isl);
161     proto_tree_add_item(fh_tree, hf_isl_dst, offset+0, 6, &pd[offset+0]);
162     proto_tree_add_item(fh_tree, hf_isl_type, offset+5, 1, pd[offset+5]);
163     switch (type) {
164
165     case TYPE_ETHER:
166       proto_tree_add_item(fh_tree, hf_isl_user_eth, offset+5, 1,
167                         pd[offset+5]&0x03);
168       break;
169
170     default:
171       /* XXX - the spec appears to indicate that the "User" field is
172          used for TYPE_TR to distinguish between types of packets. */
173       proto_tree_add_item(fh_tree, hf_isl_user, offset+5, 1, pd[offset+5]);
174       break;
175     }
176     proto_tree_add_item(fh_tree, hf_isl_src, offset+6, 6, &pd[offset+6]);
177     length = pntohs(&pd[offset+12]);
178     proto_tree_add_item(fh_tree, hf_isl_len, offset+12, 2, length);
179
180     /* This part looks sort of like a SNAP-encapsulated LLC header... */
181     proto_tree_add_text(fh_tree, offset+14, 1, "DSAP: 0x%X", pd[offset+14]);
182     proto_tree_add_text(fh_tree, offset+15, 1, "SSAP: 0x%X", pd[offset+15]);
183     proto_tree_add_text(fh_tree, offset+16, 1, "Control: 0x%X", pd[offset+16]);
184
185     /* ...but this is the manufacturer's ID portion of the source address
186        field (which is, admittedly, an OUI). */
187     proto_tree_add_item(fh_tree, hf_isl_hsa, offset+17, 3,
188                 pd[offset+17] << 16 | pd[offset+18] << 8 | pd[offset+19]);
189     proto_tree_add_item(fh_tree, hf_isl_vlan_id, offset+20, 2,
190                         pntohs(&pd[offset+20]));
191     proto_tree_add_item(fh_tree, hf_isl_bpdu, offset+20, 2,
192                         pntohs(&pd[offset+20]));
193     proto_tree_add_item(fh_tree, hf_isl_index, offset+22, 2,
194         pntohs(&pd[offset+22]));
195
196     /* Now for the CRC, which is at the *end* of the packet. */
197     if (BYTES_ARE_IN_FRAME(pi.len - 4, 4)) {
198       proto_tree_add_item(fh_tree, hf_isl_crc, pi.len - 4, 4,
199         pntohl(&pd[END_OF_FRAME - 4]));
200     }
201   }
202
203   switch (type) {
204
205   case TYPE_ETHER:
206     dissect_eth(pd, offset+26, fd, tree);
207     break;
208
209   case TYPE_TR:
210     proto_tree_add_item(fh_tree, hf_isl_src_vlan_id, offset+24, 2,
211                         pntohs(&pd[offset+24]));
212     proto_tree_add_item(fh_tree, hf_isl_explorer, offset+24, 2,
213                         pntohs(&pd[offset+24]));
214     proto_tree_add_item(fh_tree, hf_isl_dst_route_descriptor, offset+26, 2,
215                         pntohs(&pd[offset+26]));
216     proto_tree_add_item(fh_tree, hf_isl_src_route_descriptor, offset+28, 2,
217                         pntohs(&pd[offset+28]));
218     proto_tree_add_item(fh_tree, hf_isl_fcs_not_incl, offset+30, 1,
219                         pd[offset+30]);
220     proto_tree_add_item(fh_tree, hf_isl_esize, offset+16, 1,
221                         pd[offset+30]);
222     dissect_tr(pd, offset+31, fd, tree);
223     break;
224
225   default:
226     dissect_data(pd, offset+26, fd, tree);
227     break;
228   }
229 }
230     
231 void
232 proto_register_isl(void)
233 {
234   static hf_register_info hf[] = {
235         { &hf_isl_dst,
236         { "Destination",        "isl.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
237                 "Destination Address" }},
238         { &hf_isl_type,
239         { "Type",               "isl.type", FT_UINT8, BASE_NONE,
240                 VALS(type_vals), 0xF0, "Type" }},
241         { &hf_isl_user_eth,
242         { "User",               "isl.user_eth", FT_UINT8, BASE_NONE,
243                 VALS(ether_user_vals), 0x0F, "Priority (for Ethernet)" }},
244         { &hf_isl_user,
245         { "User",               "isl.user", FT_UINT8, BASE_HEX, NULL, 0x0F,
246                 "User-defined bits" }},
247         { &hf_isl_src,
248         { "Source",             "isl.src", FT_ETHER, BASE_NONE, NULL, 0x0,
249                 "Source Hardware Address" }},
250         { &hf_isl_len,
251         { "Length",             "isl.len", FT_UINT16, BASE_DEC, NULL, 0x0,
252                 "" }},
253         { &hf_isl_hsa,
254         { "HSA",                "isl.hsa", FT_UINT24, BASE_HEX, NULL, 0x0,
255                 "High bits of source address" }},
256         { &hf_isl_vlan_id,
257         { "VLAN ID",            "isl.vlan_id", FT_UINT16, BASE_HEX, NULL,
258                 0xFFFE, "Virtual LAN ID" }},
259         { &hf_isl_bpdu,
260         { "BPDU",               "isl.bpdu", FT_BOOLEAN, 16,
261                 TFS(&bpdu_tfs), 0x0001, "BPDU indicator" }},
262         { &hf_isl_index,
263         { "Index",              "isl.index", FT_UINT16, BASE_DEC, NULL, 0x0,
264                 "Port index of packet source" }},
265         { &hf_isl_crc,
266         { "CRC",                "isl.crc", FT_UINT32, BASE_HEX, NULL, 0x0,
267                 "CRC field of encapsulated frame" }},
268         { &hf_isl_src_vlan_id,
269         { "Source VLAN ID",     "isl.src_vlan_id", FT_UINT16, BASE_HEX, NULL,
270                 0xFFFE, "Source Virtual LAN ID" }},
271         { &hf_isl_explorer,
272         { "Explorer",           "isl.explorer", FT_BOOLEAN, 16,
273                 TFS(&explorer_tfs), 0x0001, "Explorer" }},
274         { &hf_isl_dst_route_descriptor,
275         { "Destination route descriptor",       "isl.dst_route_desc",
276                 FT_UINT16, BASE_HEX, NULL, 0x0,
277                 "Route descriptor to be used for forwarding" }},
278         { &hf_isl_src_route_descriptor,
279         { "Source-route descriptor",    "isl.src_route_desc",
280                 FT_UINT16, BASE_HEX, NULL, 0x0,
281                 "Route descriptor to be used for source learning" }},
282         { &hf_isl_fcs_not_incl,
283         { "FCS Not Included",   "isl.fcs_not_incl", FT_BOOLEAN, 9,
284                 NULL, 0x40, "FCS not included" }},
285         { &hf_isl_esize,
286         { "Esize",      "isl.esize", FT_UINT8, BASE_DEC, NULL,
287                 0x3F, "Frame size for frames less than 64 bytes" }},
288   };
289   static gint *ett[] = {
290         &ett_isl,
291   };
292
293   proto_isl = proto_register_protocol("Cisco ISL", "isl");
294   proto_register_field_array(proto_isl, hf, array_length(hf));
295   proto_register_subtree_array(ett, array_length(ett));
296 }