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