2 * Routines for Cisco ISL Ethernet header disassembly
4 * $Id: packet-isl.c,v 1.17 2000/11/19 08:53:58 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>
40 #include "packet-eth.h"
41 #include "packet-tr.h"
47 * http://www.cisco.com/warp/public/741/4.html
51 * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
53 * for information on ISL.
55 static int proto_isl = -1;
56 static int hf_isl_dst = -1;
57 static int hf_isl_type = -1;
58 static int hf_isl_user_eth = -1;
59 static int hf_isl_user = -1;
60 static int hf_isl_src = -1;
61 static int hf_isl_addr = -1;
62 static int hf_isl_len = -1;
63 static int hf_isl_hsa = -1;
64 static int hf_isl_vlan_id = -1;
65 static int hf_isl_bpdu = -1;
66 static int hf_isl_index = -1;
67 static int hf_isl_crc = -1;
68 static int hf_isl_src_vlan_id = -1;
69 static int hf_isl_explorer = -1;
70 static int hf_isl_dst_route_descriptor = -1;
71 static int hf_isl_src_route_descriptor = -1;
72 static int hf_isl_fcs_not_incl = -1;
73 static int hf_isl_esize = -1;
75 static gint ett_isl = -1;
77 #define ISL_HEADER_SIZE 26
79 #define TYPE_ETHER 0x0
85 capture_isl(const u_char *pd, int offset, packet_counts *ld)
89 if (!BYTES_ARE_IN_FRAME(offset, ISL_HEADER_SIZE)) {
94 type = (pd[offset+5] >> 4)&0x0F;
99 offset += 14+12; /* skip the header */
100 capture_eth(pd, offset, ld);
104 offset += 14+17; /* skip the header */
105 capture_tr(pd, offset, ld);
114 static const value_string type_vals[] = {
115 {TYPE_ETHER, "Ethernet"},
116 {TYPE_TR, "Token-Ring"},
122 static const value_string ether_user_vals[] = {
123 {0x0, "Normal priority"},
126 {0x3, "Highest priority"},
130 static const true_false_string bpdu_tfs = {
135 static const true_false_string explorer_tfs = {
141 dissect_isl(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
143 proto_tree *fh_tree = NULL;
149 OLD_CHECK_DISPLAY_AS_DATA(proto_isl, pd, offset, fd, tree);
151 if (!BYTES_ARE_IN_FRAME(offset, ISL_HEADER_SIZE)) {
152 old_dissect_data(pd, offset, fd, tree);
156 if (check_col(fd, COL_PROTOCOL))
157 col_set_str(fd, COL_PROTOCOL, "ISL");
158 if (check_col(fd, COL_INFO))
159 col_add_fstr(fd, COL_INFO, "VLAN ID: 0x%04X", pntohs(&pd[offset+20]) >> 1);
161 type = (pd[offset+5] >> 4)&0x0F;
164 ti = proto_tree_add_protocol_format(tree, proto_isl, NullTVB, offset, ISL_HEADER_SIZE,
166 fh_tree = proto_item_add_subtree(ti, ett_isl);
167 proto_tree_add_ether(fh_tree, hf_isl_dst, NullTVB, offset+0, 6, &pd[offset+0]);
168 proto_tree_add_ether_hidden(fh_tree, hf_isl_addr, NullTVB, offset+0, 6, &pd[offset+0]);
169 proto_tree_add_uint(fh_tree, hf_isl_type, NullTVB, offset+5, 1, pd[offset+5]);
173 proto_tree_add_uint(fh_tree, hf_isl_user_eth, NullTVB, offset+5, 1,
178 /* XXX - the spec appears to indicate that the "User" field is
179 used for TYPE_TR to distinguish between types of packets. */
180 proto_tree_add_uint(fh_tree, hf_isl_user, NullTVB, offset+5, 1, pd[offset+5]);
183 proto_tree_add_ether(fh_tree, hf_isl_src, NullTVB, offset+6, 6, &pd[offset+6]);
184 proto_tree_add_ether_hidden(fh_tree, hf_isl_addr, NullTVB, offset+6, 6, &pd[offset+6]);
185 length = pntohs(&pd[offset+12]);
186 proto_tree_add_uint(fh_tree, hf_isl_len, NullTVB, offset+12, 2, length);
188 /* This part looks sort of like a SNAP-encapsulated LLC header... */
189 proto_tree_add_text(fh_tree, NullTVB, offset+14, 1, "DSAP: 0x%X", pd[offset+14]);
190 proto_tree_add_text(fh_tree, NullTVB, offset+15, 1, "SSAP: 0x%X", pd[offset+15]);
191 proto_tree_add_text(fh_tree, NullTVB, offset+16, 1, "Control: 0x%X", pd[offset+16]);
193 /* ...but this is the manufacturer's ID portion of the source address
194 field (which is, admittedly, an OUI). */
195 proto_tree_add_uint(fh_tree, hf_isl_hsa, NullTVB, offset+17, 3,
196 pd[offset+17] << 16 | pd[offset+18] << 8 | pd[offset+19]);
197 proto_tree_add_uint(fh_tree, hf_isl_vlan_id, NullTVB, offset+20, 2,
198 pntohs(&pd[offset+20]));
199 proto_tree_add_boolean(fh_tree, hf_isl_bpdu, NullTVB, offset+20, 2,
200 pntohs(&pd[offset+20]));
201 proto_tree_add_uint(fh_tree, hf_isl_index, NullTVB, offset+22, 2,
202 pntohs(&pd[offset+22]));
204 /* Now for the CRC, which is at the *end* of the packet. */
205 if (BYTES_ARE_IN_FRAME(pi.len - 4, 4)) {
206 proto_tree_add_uint(fh_tree, hf_isl_crc, NullTVB, pi.len - 4, 4,
207 pntohl(&pd[END_OF_FRAME - 4]));
214 next_tvb = tvb_create_from_top(offset+26);
215 dissect_eth(next_tvb, &pi, tree);
219 proto_tree_add_uint(fh_tree, hf_isl_src_vlan_id, NullTVB, offset+24, 2,
220 pntohs(&pd[offset+24]));
221 proto_tree_add_boolean(fh_tree, hf_isl_explorer, NullTVB, offset+24, 2,
222 pntohs(&pd[offset+24]));
223 proto_tree_add_uint(fh_tree, hf_isl_dst_route_descriptor, NullTVB, offset+26, 2,
224 pntohs(&pd[offset+26]));
225 proto_tree_add_uint(fh_tree, hf_isl_src_route_descriptor, NullTVB, offset+28, 2,
226 pntohs(&pd[offset+28]));
227 proto_tree_add_boolean(fh_tree, hf_isl_fcs_not_incl, NullTVB, offset+30, 1,
229 proto_tree_add_uint(fh_tree, hf_isl_esize, NullTVB, offset+16, 1,
231 next_tvb = tvb_create_from_top(offset+31);
232 dissect_tr(next_tvb, &pi, tree);
236 next_tvb = tvb_create_from_top(offset+26);
237 dissect_data(next_tvb, 0, &pi, tree);
243 proto_register_isl(void)
245 static hf_register_info hf[] = {
247 { "Destination", "isl.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
248 "Destination Address" }},
250 { "Type", "isl.type", FT_UINT8, BASE_NONE,
251 VALS(type_vals), 0xF0, "Type" }},
253 { "User", "isl.user_eth", FT_UINT8, BASE_NONE,
254 VALS(ether_user_vals), 0x0F, "Priority (for Ethernet)" }},
256 { "User", "isl.user", FT_UINT8, BASE_HEX, NULL, 0x0F,
257 "User-defined bits" }},
259 { "Source", "isl.src", FT_ETHER, BASE_NONE, NULL, 0x0,
260 "Source Hardware Address" }},
262 { "Source or Destination Address", "isl.addr", FT_ETHER, BASE_NONE, NULL, 0x0,
263 "Source or Destination Hardware Address" }},
265 { "Length", "isl.len", FT_UINT16, BASE_DEC, NULL, 0x0,
268 { "HSA", "isl.hsa", FT_UINT24, BASE_HEX, NULL, 0x0,
269 "High bits of source address" }},
271 { "VLAN ID", "isl.vlan_id", FT_UINT16, BASE_HEX, NULL,
272 0xFFFE, "Virtual LAN ID" }},
274 { "BPDU", "isl.bpdu", FT_BOOLEAN, 16,
275 TFS(&bpdu_tfs), 0x0001, "BPDU indicator" }},
277 { "Index", "isl.index", FT_UINT16, BASE_DEC, NULL, 0x0,
278 "Port index of packet source" }},
280 { "CRC", "isl.crc", FT_UINT32, BASE_HEX, NULL, 0x0,
281 "CRC field of encapsulated frame" }},
282 { &hf_isl_src_vlan_id,
283 { "Source VLAN ID", "isl.src_vlan_id", FT_UINT16, BASE_HEX, NULL,
284 0xFFFE, "Source Virtual LAN ID" }},
286 { "Explorer", "isl.explorer", FT_BOOLEAN, 16,
287 TFS(&explorer_tfs), 0x0001, "Explorer" }},
288 { &hf_isl_dst_route_descriptor,
289 { "Destination route descriptor", "isl.dst_route_desc",
290 FT_UINT16, BASE_HEX, NULL, 0x0,
291 "Route descriptor to be used for forwarding" }},
292 { &hf_isl_src_route_descriptor,
293 { "Source-route descriptor", "isl.src_route_desc",
294 FT_UINT16, BASE_HEX, NULL, 0x0,
295 "Route descriptor to be used for source learning" }},
296 { &hf_isl_fcs_not_incl,
297 { "FCS Not Included", "isl.fcs_not_incl", FT_BOOLEAN, 9,
298 NULL, 0x40, "FCS not included" }},
300 { "Esize", "isl.esize", FT_UINT8, BASE_DEC, NULL,
301 0x3F, "Frame size for frames less than 64 bytes" }},
303 static gint *ett[] = {
307 proto_isl = proto_register_protocol("Cisco ISL", "isl");
308 proto_register_field_array(proto_isl, hf, array_length(hf));
309 proto_register_subtree_array(ett, array_length(ett));