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