2 * Routines for Cisco ISL Ethernet header disassembly
4 * $Id: packet-isl.c,v 1.4 2000/01/24 21:56:24 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>
45 * http://www.cisco.com/warp/public/741/4.html
49 * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
51 * for information on ISL.
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;
72 static gint ett_isl = -1;
74 #define ISL_HEADER_SIZE 26
76 #define TYPE_ETHER 0x0
82 capture_isl(const u_char *pd, int offset, packet_counts *ld)
86 if (!BYTES_ARE_IN_FRAME(offset, ISL_HEADER_SIZE)) {
91 type = (pd[offset+5] >> 4)&0x0F;
96 offset += 14+12; /* skip the header */
97 capture_eth(pd, offset, ld);
101 offset += 14+17; /* skip the header */
102 capture_tr(pd, offset, ld);
111 static const value_string type_vals[] = {
112 {TYPE_ETHER, "Ethernet"},
113 {TYPE_TR, "Token-Ring"},
119 static const value_string ether_user_vals[] = {
120 {0x0, "Normal priority"},
123 {0x3, "Highest priority"},
127 static const true_false_string bpdu_tfs = {
132 static const true_false_string explorer_tfs = {
138 dissect_isl(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
140 proto_tree *fh_tree = NULL;
145 if (!BYTES_ARE_IN_FRAME(offset, ISL_HEADER_SIZE)) {
146 dissect_data(pd, offset, fd, tree);
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);
155 type = (pd[offset+5] >> 4)&0x0F;
158 ti = proto_tree_add_item_format(tree, proto_isl, offset, ISL_HEADER_SIZE,
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]);
166 proto_tree_add_item(fh_tree, hf_isl_user_eth, offset+5, 1,
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]);
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);
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]);
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]));
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]));
206 dissect_eth(pd, offset+26, fd, tree);
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,
220 proto_tree_add_item(fh_tree, hf_isl_esize, offset+16, 1,
222 dissect_tr(pd, offset+31, fd, tree);
226 dissect_data(pd, offset+26, fd, tree);
232 proto_register_isl(void)
234 static hf_register_info hf[] = {
236 { "Destination", "isl.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
237 "Destination Address" }},
239 { "Type", "isl.type", FT_UINT8, BASE_NONE,
240 VALS(type_vals), 0xF0, "Type" }},
242 { "User", "isl.user_eth", FT_UINT8, BASE_NONE,
243 VALS(ether_user_vals), 0x0F, "Priority (for Ethernet)" }},
245 { "User", "isl.user", FT_UINT8, BASE_HEX, NULL, 0x0F,
246 "User-defined bits" }},
248 { "Source", "isl.src", FT_ETHER, BASE_NONE, NULL, 0x0,
249 "Source Hardware Address" }},
251 { "Length", "isl.len", FT_UINT16, BASE_DEC, NULL, 0x0,
254 { "HSA", "isl.hsa", FT_UINT24, BASE_HEX, NULL, 0x0,
255 "High bits of source address" }},
257 { "VLAN ID", "isl.vlan_id", FT_UINT16, BASE_HEX, NULL,
258 0xFFFE, "Virtual LAN ID" }},
260 { "BPDU", "isl.bpdu", FT_BOOLEAN, 16,
261 TFS(&bpdu_tfs), 0x0001, "BPDU indicator" }},
263 { "Index", "isl.index", FT_UINT16, BASE_DEC, NULL, 0x0,
264 "Port index of packet source" }},
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" }},
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" }},
286 { "Esize", "isl.esize", FT_UINT8, BASE_DEC, NULL,
287 0x3F, "Frame size for frames less than 64 bytes" }},
289 static gint *ett[] = {
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));