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