2 * Routines for FDDI packet disassembly
4 * Laurent Deniel <deniel@worldnet.fr>
6 * $Id: packet-fddi.c,v 1.35 2000/05/28 22:02:16 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@zing.org>
10 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
39 #include "packet-fddi.h"
40 #include "packet-llc.h"
43 static int proto_fddi = -1;
44 static int hf_fddi_fc = -1;
45 static int hf_fddi_dst = -1;
46 static int hf_fddi_src = -1;
47 static int hf_fddi_addr = -1;
49 static gint ett_fddi = -1;
51 /* FDDI Frame Control values */
53 #define FDDI_FC_VOID 0x00 /* Void frame */
54 #define FDDI_FC_NRT 0x80 /* Nonrestricted token */
55 #define FDDI_FC_RT 0xc0 /* Restricted token */
56 #define FDDI_FC_MAC 0xc0 /* MAC frame */
57 #define FDDI_FC_SMT 0x40 /* SMT frame */
58 #define FDDI_FC_SMT_INFO 0x41 /* SMT Info */
59 #define FDDI_FC_SMT_NSA 0x4F /* SMT Next station adrs */
60 #define FDDI_FC_SMT_MIN FDDI_FC_SMT_INFO
61 #define FDDI_FC_SMT_MAX FDDI_FC_SMT_NSA
62 #define FDDI_FC_MAC_MIN 0xc1
63 #define FDDI_FC_MAC_BEACON 0xc2 /* MAC Beacon frame */
64 #define FDDI_FC_MAC_CLAIM 0xc3 /* MAC Claim frame */
65 #define FDDI_FC_MAC_MAX 0xcf
66 #define FDDI_FC_LLC_ASYNC 0x50 /* Async. LLC frame */
67 #define FDDI_FC_LLC_ASYNC_MIN FDDI_FC_LLC_ASYNC
68 #define FDDI_FC_LLC_ASYNC_DEF 0x54
69 #define FDDI_FC_LLC_ASYNC_MAX 0x5f
70 #define FDDI_FC_LLC_SYNC 0xd0 /* Sync. LLC frame */
71 #define FDDI_FC_LLC_SYNC_MIN FDDI_FC_LLC_SYNC
72 #define FDDI_FC_LLC_SYNC_MAX 0xd7
73 #define FDDI_FC_IMP_ASYNC 0x60 /* Implementor Async. */
74 #define FDDI_FC_IMP_ASYNC_MIN FDDI_FC_IMP_ASYNC
75 #define FDDI_FC_IMP_ASYNC_MAX 0x6f
76 #define FDDI_FC_IMP_SYNC 0xe0 /* Implementor Synch. */
78 #define FDDI_FC_CLFF 0xF0 /* Class/Length/Format bits */
79 #define FDDI_FC_ZZZZ 0x0F /* Control bits */
82 * Async frame ZZZZ bits:
84 #define FDDI_FC_ASYNC_R 0x08 /* Reserved */
85 #define FDDI_FC_ASYNC_PRI 0x07 /* Priority */
87 #define FDDI_HEADER_SIZE 13
92 #define FDDI_P_DHOST 1
93 #define FDDI_P_SHOST 7
95 /* "swaptab[i]" is the value of "i" with the bits reversed. */
96 static u_char swaptab[256] = {
97 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
98 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
99 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
100 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
101 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
102 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
103 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
104 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
105 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
106 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
107 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
108 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
109 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
110 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
111 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
112 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
113 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
114 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
115 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
116 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
117 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
118 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
119 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
120 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
121 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
122 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
123 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
124 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
125 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
126 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
127 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
128 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
132 swap_mac_addr(u_char *swapped_addr, const u_char *orig_addr)
136 for (i = 0; i < 6; i++) {
137 swapped_addr[i] = swaptab[orig_addr[i]];
143 capture_fddi(const u_char *pd, packet_counts *ld)
147 if (!BYTES_ARE_IN_FRAME(0, FDDI_HEADER_SIZE)) {
151 offset = FDDI_HEADER_SIZE;
153 fc = (int) pd[FDDI_P_FC];
157 /* From now, only 802.2 SNAP (Async. LCC frame) is supported */
159 case FDDI_FC_LLC_ASYNC + 0 :
160 case FDDI_FC_LLC_ASYNC + 1 :
161 case FDDI_FC_LLC_ASYNC + 2 :
162 case FDDI_FC_LLC_ASYNC + 3 :
163 case FDDI_FC_LLC_ASYNC + 4 :
164 case FDDI_FC_LLC_ASYNC + 5 :
165 case FDDI_FC_LLC_ASYNC + 6 :
166 case FDDI_FC_LLC_ASYNC + 7 :
167 case FDDI_FC_LLC_ASYNC + 8 :
168 case FDDI_FC_LLC_ASYNC + 9 :
169 case FDDI_FC_LLC_ASYNC + 10 :
170 case FDDI_FC_LLC_ASYNC + 11 :
171 case FDDI_FC_LLC_ASYNC + 12 :
172 case FDDI_FC_LLC_ASYNC + 13 :
173 case FDDI_FC_LLC_ASYNC + 14 :
174 case FDDI_FC_LLC_ASYNC + 15 :
175 capture_llc(pd, offset, ld);
186 fddifc_to_str(int fc)
188 static gchar strbuf[128+1];
192 case FDDI_FC_VOID: /* Void frame */
195 case FDDI_FC_NRT: /* Nonrestricted token */
196 return "Nonrestricted token";
198 case FDDI_FC_RT: /* Restricted token */
199 return "Restricted token";
201 case FDDI_FC_SMT_INFO: /* SMT Info */
204 case FDDI_FC_SMT_NSA: /* SMT Next station adrs */
205 return "SMT Next station address";
207 case FDDI_FC_MAC_BEACON: /* MAC Beacon frame */
210 case FDDI_FC_MAC_CLAIM: /* MAC Claim frame */
211 return "MAC claim token";
214 switch (fc & FDDI_FC_CLFF) {
217 sprintf(strbuf, "MAC frame, control %x", fc & FDDI_FC_ZZZZ);
221 sprintf(strbuf, "SMT frame, control %x", fc & FDDI_FC_ZZZZ);
224 case FDDI_FC_LLC_ASYNC:
225 if (fc & FDDI_FC_ASYNC_R)
226 sprintf(strbuf, "Async LLC frame, control %x", fc & FDDI_FC_ZZZZ);
228 sprintf(strbuf, "Async LLC frame, priority %d",
229 fc & FDDI_FC_ASYNC_PRI);
232 case FDDI_FC_LLC_SYNC:
233 if (fc & FDDI_FC_ZZZZ) {
234 sprintf(strbuf, "Sync LLC frame, control %x", fc & FDDI_FC_ZZZZ);
237 return "Sync LLC frame";
239 case FDDI_FC_IMP_ASYNC:
240 sprintf(strbuf, "Implementor async frame, control %x",
244 case FDDI_FC_IMP_SYNC:
245 sprintf(strbuf, "Implementor sync frame, control %x",
251 return "Unknown frame type";
257 dissect_fddi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
261 proto_tree *fh_tree = NULL;
264 static u_char src[6], dst[6];
265 u_char src_swapped[6], dst_swapped[6];
268 pinfo->current_proto = "FDDI";
269 if (check_col(pinfo->fd, COL_PROTOCOL))
270 col_add_str(pinfo->fd, COL_PROTOCOL, "FDDI");
272 fc = (int) tvb_get_guint8(tvb, FDDI_P_FC);
273 fc_str = fddifc_to_str(fc);
275 if (check_col(pinfo->fd, COL_INFO))
276 col_add_str(pinfo->fd, COL_INFO, fc_str);
279 ti = proto_tree_add_protocol_format(tree, proto_fddi, tvb, 0, FDDI_HEADER_SIZE,
280 "Fiber Distributed Data Interface, %s", fc_str);
281 fh_tree = proto_item_add_subtree(ti, ett_fddi);
282 proto_tree_add_item(fh_tree, hf_fddi_fc, tvb, FDDI_P_FC, 1, fc);
285 /* Extract the destination address, possibly bit-swapping it. */
287 swap_mac_addr(dst, (u_char *) tvb_get_ptr(tvb, FDDI_P_DHOST, 6));
289 memcpy(dst, (u_char *) tvb_get_ptr(tvb, FDDI_P_DHOST, 6), sizeof dst);
290 swap_mac_addr(dst_swapped, (u_char*) tvb_get_ptr(tvb, FDDI_P_DHOST, 6));
292 /* XXX - copy them to some buffer associated with "pi", rather than
293 just making "dst" static? */
294 SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, &dst[0]);
295 SET_ADDRESS(&pi.dst, AT_ETHER, 6, &dst[0]);
298 proto_tree_add_item(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST, 6, dst);
299 proto_tree_add_item_hidden(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST, 6, dst);
301 /* hide some bit-swapped mac address fields in the proto_tree, just in case */
302 proto_tree_add_item_hidden(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST, 6, dst_swapped);
303 proto_tree_add_item_hidden(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST, 6, dst_swapped);
306 /* Extract the source address, possibly bit-swapping it. */
308 swap_mac_addr(src, (u_char *) tvb_get_ptr(tvb, FDDI_P_SHOST, 6));
310 memcpy(src, (u_char *) tvb_get_ptr(tvb, FDDI_P_SHOST, 6), sizeof src);
311 swap_mac_addr(src_swapped, (u_char*) tvb_get_ptr(tvb, FDDI_P_SHOST, 6));
313 /* XXX - copy them to some buffer associated with "pi", rather than
314 just making "src" static? */
315 SET_ADDRESS(&pi.dl_src, AT_ETHER, 6, &src[0]);
316 SET_ADDRESS(&pi.src, AT_ETHER, 6, &src[0]);
319 proto_tree_add_item(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST, 6, src);
320 proto_tree_add_item_hidden(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST, 6, src);
322 /* hide some bit-swapped mac address fields in the proto_tree, just in case */
323 proto_tree_add_item_hidden(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST, 6, src_swapped);
324 proto_tree_add_item_hidden(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST, 6, src_swapped);
327 next_tvb = tvb_new_subset(tvb, FDDI_HEADER_SIZE, -1, -1);
331 /* From now, only 802.2 SNAP (Async. LCC frame) is supported */
333 case FDDI_FC_LLC_ASYNC + 0 :
334 case FDDI_FC_LLC_ASYNC + 1 :
335 case FDDI_FC_LLC_ASYNC + 2 :
336 case FDDI_FC_LLC_ASYNC + 3 :
337 case FDDI_FC_LLC_ASYNC + 4 :
338 case FDDI_FC_LLC_ASYNC + 5 :
339 case FDDI_FC_LLC_ASYNC + 6 :
340 case FDDI_FC_LLC_ASYNC + 7 :
341 case FDDI_FC_LLC_ASYNC + 8 :
342 case FDDI_FC_LLC_ASYNC + 9 :
343 case FDDI_FC_LLC_ASYNC + 10 :
344 case FDDI_FC_LLC_ASYNC + 11 :
345 case FDDI_FC_LLC_ASYNC + 12 :
346 case FDDI_FC_LLC_ASYNC + 13 :
347 case FDDI_FC_LLC_ASYNC + 14 :
348 case FDDI_FC_LLC_ASYNC + 15 :
349 dissect_llc(next_tvb, pinfo, tree);
353 dissect_data_tvb(next_tvb, pinfo, tree);
360 proto_register_fddi(void)
362 static hf_register_info hf[] = {
365 * XXX - we want this guy to have his own private formatting
366 * routine, using "fc_to_str()"; if "fc_to_str()" returns
367 * NULL, just show the hex value, else show the string.
370 { "Frame Control", "fddi.fc", FT_UINT8, BASE_HEX, NULL, 0x0,
374 { "Destination", "fddi.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
375 "Destination Hardware Address" }},
378 { "Source", "fddi.src", FT_ETHER, BASE_NONE, NULL, 0x0,
382 { "Source or Destination Address", "fddi.addr", FT_ETHER, BASE_NONE, NULL, 0x0,
383 "Source or Destination Hardware Address" }},
386 static gint *ett[] = {
390 proto_fddi = proto_register_protocol ("Fiber Distributed Data Interface", "fddi" );
391 proto_register_field_array(proto_fddi, hf, array_length(hf));
392 proto_register_subtree_array(ett, array_length(ett));