Create a header file for every packet-*.c file. Prune the packet.h file.
[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.27 2000/02/15 21:02:08 gram 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 <stdio.h>
37 #include <glib.h>
38 #include "packet.h"
39 #include "packet-llc.h"
40 #include "resolv.h"
41
42 static int proto_fddi = -1;
43 static int hf_fddi_fc = -1;
44 static int hf_fddi_dst = -1;
45 static int hf_fddi_src = -1;
46
47 static gint ett_fddi = -1;
48
49 /* FDDI Frame Control values */
50
51 #define FDDI_FC_VOID            0x00            /* Void frame */
52 #define FDDI_FC_NRT             0x80            /* Nonrestricted token */
53 #define FDDI_FC_RT              0xc0            /* Restricted token */
54 #define FDDI_FC_MAC             0xc0            /* MAC frame */
55 #define FDDI_FC_SMT             0x40            /* SMT frame */
56 #define FDDI_FC_SMT_INFO        0x41            /* SMT Info */
57 #define FDDI_FC_SMT_NSA         0x4F            /* SMT Next station adrs */
58 #define FDDI_FC_SMT_MIN         FDDI_FC_SMT_INFO
59 #define FDDI_FC_SMT_MAX         FDDI_FC_SMT_NSA
60 #define FDDI_FC_MAC_MIN         0xc1
61 #define FDDI_FC_MAC_BEACON      0xc2            /* MAC Beacon frame */
62 #define FDDI_FC_MAC_CLAIM       0xc3            /* MAC Claim frame */
63 #define FDDI_FC_MAC_MAX         0xcf
64 #define FDDI_FC_LLC_ASYNC       0x50            /* Async. LLC frame */
65 #define FDDI_FC_LLC_ASYNC_MIN   FDDI_FC_LLC_ASYNC
66 #define FDDI_FC_LLC_ASYNC_DEF   0x54
67 #define FDDI_FC_LLC_ASYNC_MAX   0x5f
68 #define FDDI_FC_LLC_SYNC        0xd0            /* Sync. LLC frame */
69 #define FDDI_FC_LLC_SYNC_MIN    FDDI_FC_LLC_SYNC
70 #define FDDI_FC_LLC_SYNC_MAX    0xd7
71 #define FDDI_FC_IMP_ASYNC       0x60            /* Implementor Async. */
72 #define FDDI_FC_IMP_ASYNC_MIN   FDDI_FC_IMP_ASYNC
73 #define FDDI_FC_IMP_ASYNC_MAX   0x6f
74 #define FDDI_FC_IMP_SYNC        0xe0            /* Implementor Synch. */
75
76 #define FDDI_FC_CLFF            0xF0            /* Class/Length/Format bits */
77 #define FDDI_FC_ZZZZ            0x0F            /* Control bits */
78
79 /*
80  * Async frame ZZZZ bits:
81  */
82 #define FDDI_FC_ASYNC_R         0x08            /* Reserved */
83 #define FDDI_FC_ASYNC_PRI       0x07            /* Priority */
84
85 #define FDDI_HEADER_SIZE        13
86
87 /* field positions */
88
89 #define FDDI_P_FC               0
90 #define FDDI_P_DHOST            1
91 #define FDDI_P_SHOST            7
92
93 /* "swaptab[i]" is the value of "i" with the bits reversed. */
94 static u_char swaptab[256] = {
95   0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
96   0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
97   0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
98   0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
99   0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
100   0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
101   0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
102   0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
103   0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
104   0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
105   0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
106   0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
107   0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
108   0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
109   0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
110   0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
111   0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
112   0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
113   0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
114   0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
115   0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
116   0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
117   0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
118   0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
119   0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
120   0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
121   0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
122   0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
123   0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
124   0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
125   0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
126   0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
127 };
128
129 static void
130 swap_mac_addr(u_char *swapped_addr, const u_char *orig_addr)
131 {
132         int i;
133
134         for (i = 0; i < 6; i++) {
135                 swapped_addr[i] = swaptab[orig_addr[i]];
136         }
137 }
138
139
140 void
141 capture_fddi(const u_char *pd, packet_counts *ld)
142 {
143   int        offset = 0, fc;
144
145   if (!BYTES_ARE_IN_FRAME(0, FDDI_HEADER_SIZE)) {
146     ld->other++;
147     return;
148   }
149   offset = FDDI_HEADER_SIZE;
150
151   fc = (int) pd[FDDI_P_FC];
152
153   switch (fc) {
154
155     /* From now, only 802.2 SNAP (Async. LCC frame) is supported */
156
157     case FDDI_FC_LLC_ASYNC + 0  :
158     case FDDI_FC_LLC_ASYNC + 1  :
159     case FDDI_FC_LLC_ASYNC + 2  :
160     case FDDI_FC_LLC_ASYNC + 3  :
161     case FDDI_FC_LLC_ASYNC + 4  :
162     case FDDI_FC_LLC_ASYNC + 5  :
163     case FDDI_FC_LLC_ASYNC + 6  :
164     case FDDI_FC_LLC_ASYNC + 7  :
165     case FDDI_FC_LLC_ASYNC + 8  :
166     case FDDI_FC_LLC_ASYNC + 9  :
167     case FDDI_FC_LLC_ASYNC + 10 :
168     case FDDI_FC_LLC_ASYNC + 11 :
169     case FDDI_FC_LLC_ASYNC + 12 :
170     case FDDI_FC_LLC_ASYNC + 13 :
171     case FDDI_FC_LLC_ASYNC + 14 :
172     case FDDI_FC_LLC_ASYNC + 15 :
173       capture_llc(pd, offset, ld);
174       return;
175     default :
176       ld->other++;
177       return;
178
179   } /* fc */
180
181 } /* capture_fddi */
182
183 static gchar *
184 fddifc_to_str(int fc)
185 {
186   static gchar strbuf[128+1];
187
188   switch (fc) {
189
190   case FDDI_FC_VOID:                    /* Void frame */
191     return "Void frame";
192
193   case FDDI_FC_NRT:                     /* Nonrestricted token */
194     return "Nonrestricted token";
195
196   case FDDI_FC_RT:                      /* Restricted token */
197     return "Restricted token";
198
199   case FDDI_FC_SMT_INFO:                /* SMT Info */
200     return "SMT info";
201
202   case FDDI_FC_SMT_NSA:                 /* SMT Next station adrs */
203     return "SMT Next station address";
204
205   case FDDI_FC_MAC_BEACON:              /* MAC Beacon frame */
206     return "MAC beacon";
207
208   case FDDI_FC_MAC_CLAIM:               /* MAC Claim frame */
209     return "MAC claim token";
210
211   default:
212     switch (fc & FDDI_FC_CLFF) {
213
214     case FDDI_FC_MAC:
215       sprintf(strbuf, "MAC frame, control %x", fc & FDDI_FC_ZZZZ);
216       return strbuf;
217
218     case FDDI_FC_SMT:
219       sprintf(strbuf, "SMT frame, control %x", fc & FDDI_FC_ZZZZ);
220       return strbuf;
221
222     case FDDI_FC_LLC_ASYNC:
223       if (fc & FDDI_FC_ASYNC_R)
224         sprintf(strbuf, "Async LLC frame, control %x", fc & FDDI_FC_ZZZZ);
225       else
226         sprintf(strbuf, "Async LLC frame, priority %d",
227                         fc & FDDI_FC_ASYNC_PRI);
228       return strbuf;
229
230     case FDDI_FC_LLC_SYNC:
231       if (fc & FDDI_FC_ZZZZ) {
232         sprintf(strbuf, "Sync LLC frame, control %x", fc & FDDI_FC_ZZZZ);
233         return strbuf;
234       } else
235         return "Sync LLC frame";
236
237     case FDDI_FC_IMP_ASYNC:
238       sprintf(strbuf, "Implementor async frame, control %x",
239                         fc & FDDI_FC_ZZZZ);
240       return strbuf;
241
242     case FDDI_FC_IMP_SYNC:
243       sprintf(strbuf, "Implementor sync frame, control %x",
244                         fc & FDDI_FC_ZZZZ);
245       return strbuf;
246       break;
247
248     default:
249       return "Unknown frame type";
250     }
251   }
252 }
253
254 void dissect_fddi(const u_char *pd, frame_data *fd, proto_tree *tree,
255                 gboolean bitswapped)
256 {
257   int        offset = 0, fc;
258   proto_tree *fh_tree;
259   proto_item *ti;
260   gchar      *fc_str;
261   static u_char src[6], dst[6];
262   u_char     src_swapped[6], dst_swapped[6];
263
264   if (!BYTES_ARE_IN_FRAME(0, FDDI_HEADER_SIZE)) {
265     dissect_data(pd, offset, fd, tree);
266     return;
267   }
268
269   /* Extract the source and destination addresses, possibly bit-swapping
270      them. */
271   if (bitswapped) {
272     swap_mac_addr(dst, (u_char *)&pd[FDDI_P_DHOST]);
273     swap_mac_addr(src, (u_char *)&pd[FDDI_P_SHOST]);
274   } else {
275     memcpy(dst, (u_char *)&pd[FDDI_P_DHOST], sizeof dst);
276     memcpy(src, (u_char *)&pd[FDDI_P_SHOST], sizeof src);
277   }
278
279   fc = (int) pd[FDDI_P_FC];
280   fc_str = fddifc_to_str(fc);
281
282   /* XXX - copy them to some buffer associated with "pi", rather than
283      just making "src" and "dst" static? */
284   SET_ADDRESS(&pi.dl_src, AT_ETHER, 6, &src[0]);
285   SET_ADDRESS(&pi.src, AT_ETHER, 6, &src[0]);
286   SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, &dst[0]);
287   SET_ADDRESS(&pi.dst, AT_ETHER, 6, &dst[0]);
288
289   if (check_col(fd, COL_PROTOCOL))
290     col_add_str(fd, COL_PROTOCOL, "FDDI");
291   if (check_col(fd, COL_INFO))
292     col_add_str(fd, COL_INFO, fc_str);
293
294   offset = FDDI_HEADER_SIZE;
295
296   if (tree) {
297         ti = proto_tree_add_item_format(tree, proto_fddi, 0, offset, NULL,
298                 "Fiber Distributed Data Interface, %s", fc_str);
299
300       swap_mac_addr(dst_swapped, (u_char*)&pd[FDDI_P_DHOST]);
301       swap_mac_addr(src_swapped, (u_char*)&pd[FDDI_P_SHOST]);
302
303       fh_tree = proto_item_add_subtree(ti, ett_fddi);
304       proto_tree_add_item(fh_tree, hf_fddi_fc, FDDI_P_FC, 1, fc);
305       proto_tree_add_item(fh_tree, hf_fddi_dst, FDDI_P_DHOST, 6, dst);
306       proto_tree_add_item(fh_tree, hf_fddi_src, FDDI_P_SHOST, 6, src);
307
308       /* hide some bit-swapped mac address fields in the proto_tree, just in case */
309       proto_tree_add_item_hidden(fh_tree, hf_fddi_dst, FDDI_P_DHOST, 6, dst_swapped);
310       proto_tree_add_item_hidden(fh_tree, hf_fddi_src, FDDI_P_SHOST, 6, src_swapped);
311
312   }
313   switch (fc) {
314
315     /* From now, only 802.2 SNAP (Async. LCC frame) is supported */
316
317     case FDDI_FC_LLC_ASYNC + 0  :
318     case FDDI_FC_LLC_ASYNC + 1  :
319     case FDDI_FC_LLC_ASYNC + 2  :
320     case FDDI_FC_LLC_ASYNC + 3  :
321     case FDDI_FC_LLC_ASYNC + 4  :
322     case FDDI_FC_LLC_ASYNC + 5  :
323     case FDDI_FC_LLC_ASYNC + 6  :
324     case FDDI_FC_LLC_ASYNC + 7  :
325     case FDDI_FC_LLC_ASYNC + 8  :
326     case FDDI_FC_LLC_ASYNC + 9  :
327     case FDDI_FC_LLC_ASYNC + 10 :
328     case FDDI_FC_LLC_ASYNC + 11 :
329     case FDDI_FC_LLC_ASYNC + 12 :
330     case FDDI_FC_LLC_ASYNC + 13 :
331     case FDDI_FC_LLC_ASYNC + 14 :
332     case FDDI_FC_LLC_ASYNC + 15 :
333       dissect_llc(pd, offset, fd, tree);
334       return;
335       
336     default :
337       dissect_data(pd, offset, fd, tree);
338       return;
339
340   } /* fc */
341 } /* dissect_fddi */
342
343 void
344 proto_register_fddi(void)
345 {
346         static hf_register_info hf[] = {
347
348                 /*
349                  * XXX - we want this guy to have his own private formatting
350                  * routine, using "fc_to_str()"; if "fc_to_str()" returns
351                  * NULL, just show the hex value, else show the string.
352                  */
353                 { &hf_fddi_fc,
354                 { "Frame Control",      "fddi.fc", FT_UINT8, BASE_HEX, NULL, 0x0,
355                         "" }},
356
357                 { &hf_fddi_dst,
358                 { "Destination",        "fddi.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
359                         "Destination Hardware Address" }},
360
361                 { &hf_fddi_src,
362                 { "Source",             "fddi.src", FT_ETHER, BASE_NONE, NULL, 0x0,
363                         "" }},
364         };
365         static gint *ett[] = {
366                 &ett_fddi,
367         };
368
369         proto_fddi = proto_register_protocol ("Fiber Distributed Data Interface", "fddi" );
370         proto_register_field_array(proto_fddi, hf, array_length(hf));
371         proto_register_subtree_array(ett, array_length(ett));
372 }