On most systems, bit-swap the bytes of an FDDI MAC address. (List of
[obnox/wireshark/wip.git] / packet-fddi.c
1 /* packet-fddi.c
2  * Routines for FDDI packet disassembly
3  *
4  * Laurent Deniel <deniel@worldnet.fr>
5  *
6  * $Id: packet-fddi.c,v 1.5 1998/10/13 07:48:03 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * 
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.
17  * 
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.
22  * 
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.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <gtk/gtk.h>
33
34 #include <stdio.h>
35
36 #include <pcap.h>
37
38 #include "ethereal.h"
39 #include "packet.h"
40 #include "resolv.h"
41
42 /* FDDI Frame Control values */
43
44 #define FDDI_FC_VOID            0x00            /* Void frame */
45 #define FDDI_FC_NRT             0x80            /* Nonrestricted token */
46 #define FDDI_FC_RT              0xc0            /* Restricted token */
47 #define FDDI_FC_MAC             0xc0            /* MAC frame */
48 #define FDDI_FC_SMT             0x40            /* SMT frame */
49 #define FDDI_FC_SMT_INFO        0x41            /* SMT Info */
50 #define FDDI_FC_SMT_NSA         0x4F            /* SMT Next station adrs */
51 #define FDDI_FC_SMT_MIN         FDDI_FC_SMT_INFO
52 #define FDDI_FC_SMT_MAX         FDDI_FC_SMT_NSA
53 #define FDDI_FC_MAC_MIN         0xc1
54 #define FDDI_FC_MAC_BEACON      0xc2            /* MAC Beacon frame */
55 #define FDDI_FC_MAC_CLAIM       0xc3            /* MAC Claim frame */
56 #define FDDI_FC_MAC_MAX         0xcf
57 #define FDDI_FC_LLC_ASYNC       0x50            /* Async. LLC frame */
58 #define FDDI_FC_LLC_ASYNC_MIN   FDDI_FC_LLC_ASYNC
59 #define FDDI_FC_LLC_ASYNC_DEF   0x54
60 #define FDDI_FC_LLC_ASYNC_MAX   0x5f
61 #define FDDI_FC_LLC_SYNC        0xd0            /* Sync. LLC frame */
62 #define FDDI_FC_LLC_SYNC_MIN    FDDI_FC_LLC_SYNC
63 #define FDDI_FC_LLC_SYNC_MAX    0xd7
64 #define FDDI_FC_IMP_ASYNC       0x60            /* Implementor Async. */
65 #define FDDI_FC_IMP_ASYNC_MIN   FDDI_FC_IMP_ASYNC
66 #define FDDI_FC_IMP_ASYNC_MAX   0x6f
67 #define FDDI_FC_IMP_SYNC        0xe0            /* Implementor Synch. */
68
69 #define FDDI_HEADER_SIZE        13
70
71 /* field positions */
72
73 #define FDDI_P_FC               0
74 #define FDDI_P_DHOST            1
75 #define FDDI_P_SHOST            7
76
77 /* On some systems, the FDDI MAC addresses are bit-swapped. */
78 #if !defined(ultrix) && !defined(__alpha) && !defined(__bsdi)
79 #define BIT_SWAPPED_MAC_ADDRS
80 #endif
81
82 #ifdef BIT_SWAPPED_MAC_ADDRS
83 /* "swaptab[i]" is the value of "i" with the bits reversed. */
84 static u_char swaptab[256] = {
85   0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
86   0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
87   0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
88   0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
89   0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
90   0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
91   0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
92   0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
93   0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
94   0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
95   0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
96   0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
97   0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
98   0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
99   0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
100   0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
101   0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
102   0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
103   0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
104   0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
105   0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
106   0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
107   0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
108   0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
109   0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
110   0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
111   0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
112   0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
113   0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
114   0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
115   0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
116   0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
117 };
118 #endif
119
120 static void get_mac_addr(u_char *swapped_addr, const u_char *addr)
121 {
122   int i;
123
124   for (i = 0; i < 6; i++) {
125 #ifdef BIT_SWAPPED_MAC_ADDRS
126     swapped_addr[i] = swaptab[addr[i]];
127 #else
128     swapped_addr[i] = addr[i];
129 #endif
130   }
131 }
132
133 void dissect_fddi(const u_char *pd, frame_data *fd, GtkTree *tree) 
134 {
135   int        offset = 0, fc;
136   GtkWidget *fh_tree, *ti;
137   u_char     src[6], dst[6];
138
139   if (fd->cap_len < FDDI_HEADER_SIZE) {
140     dissect_data(pd, offset, fd, tree);
141     return;
142   }
143
144   /* Extract the source and destination addresses, possibly bit-swapping
145      them. */
146   get_mac_addr(dst, (u_char *)&pd[FDDI_P_DHOST]);
147   get_mac_addr(src, (u_char *)&pd[FDDI_P_SHOST]);
148
149   fc = (int) pd[FDDI_P_FC];
150
151   if (fd->win_info[COL_NUM]) {
152     strcpy(fd->win_info[COL_DESTINATION], get_ether_name(dst));
153     strcpy(fd->win_info[COL_SOURCE], get_ether_name(src));
154     strcpy(fd->win_info[COL_INFO], "FDDI");
155   }
156
157   if (tree) {
158     ti = add_item_to_tree(GTK_WIDGET(tree), 0, offset,
159                           "FDDI %s",
160                           (fc >= FDDI_FC_LLC_ASYNC_MIN && fc <= FDDI_FC_LLC_ASYNC_MAX) ?
161                           "Async LLC" : "unsupported FC");
162
163       fh_tree = gtk_tree_new();
164       add_subtree(ti, fh_tree, ETT_FDDI);
165       add_item_to_tree(fh_tree, FDDI_P_FC, 1, "Frame Control: 0x%02x", fc);
166       add_item_to_tree(fh_tree, FDDI_P_DHOST, 6, "Destination: %s (%s)",
167                        ether_to_str(dst), get_ether_name(dst));
168       add_item_to_tree(fh_tree, FDDI_P_SHOST, 6, "Source: %s (%s)",
169                        ether_to_str(src), get_ether_name(src));
170     }
171
172   offset = FDDI_HEADER_SIZE;
173
174   switch (fc) {
175
176     /* From now, only 802.2 SNAP (Async. LCC frame) is supported */
177
178     case FDDI_FC_LLC_ASYNC + 0  :
179     case FDDI_FC_LLC_ASYNC + 1  :
180     case FDDI_FC_LLC_ASYNC + 2  :
181     case FDDI_FC_LLC_ASYNC + 3  :
182     case FDDI_FC_LLC_ASYNC + 4  :
183     case FDDI_FC_LLC_ASYNC + 5  :
184     case FDDI_FC_LLC_ASYNC + 6  :
185     case FDDI_FC_LLC_ASYNC + 7  :
186     case FDDI_FC_LLC_ASYNC + 8  :
187     case FDDI_FC_LLC_ASYNC + 9  :
188     case FDDI_FC_LLC_ASYNC + 10 :
189     case FDDI_FC_LLC_ASYNC + 11 :
190     case FDDI_FC_LLC_ASYNC + 12 :
191     case FDDI_FC_LLC_ASYNC + 13 :
192     case FDDI_FC_LLC_ASYNC + 14 :
193     case FDDI_FC_LLC_ASYNC + 15 :
194       dissect_llc(pd, offset, fd, tree);
195       return;
196       
197     default :
198       dissect_data(pd, offset, fd, tree);
199       return;
200
201   } /* fc */
202
203 } /* dissect_fddi */
204