I removed the bit-fields that depended upon gcc's ability to use any type
[obnox/wireshark/wip.git] / packet-tr.c
1 /* packet-tr.c
2  * Routines for Token-Ring packet disassembly
3  * Gilbert Ramirez <gram@verdict.uthscsa.edu>
4  *
5  * $Id: packet-tr.c,v 1.9 1999/01/08 04:42:43 gram Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
9  * Copyright 1998 Gerald Combs
10  *
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <gtk/gtk.h>
32
33 #include <stdio.h>
34
35 #ifdef HAVE_SYS_TYPES_H
36 # include <sys/types.h>
37 #endif
38
39 #ifdef HAVE_NETINET_IN_H
40 # include <netinet/in.h>
41 #endif
42
43
44 #include "ethereal.h"
45 #include "packet.h"
46 #include "etypes.h"
47
48 static void
49 add_ring_bridge_pairs(int rcf_len, const u_char *pd, GtkWidget *tree);
50
51 static char*
52 sr_broadcast(u_char val) {
53
54         if (val < 4) {
55                 return "Non-broadcast";
56         }
57         else if (val < 6) {
58                 return "All-routes broadcast";
59         }
60         else {
61                 return "Single-route broadcast";
62         }
63 }
64
65 static int
66 sr_frame(u_char val) {
67
68         int rc_frame[7] = { 516, 1500, 2052, 4472, 8144, 11407, 17800 };
69
70         if (val > 6) {
71                 return -1;
72         }
73         else return rc_frame[val];
74 }
75
76
77 void
78 dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) {
79
80         GtkWidget       *fh_tree, *ti;
81         int                     offset = 14;
82
83         int                     source_routed = 0;
84         int                     frame_type;
85         guint8                  trn_rif_bytes;
86         guint8                  actual_rif_bytes;
87
88         /* The trn_hdr struct, as separate variables */
89         guint8                  trn_ac;         /* access control field */
90         guint8                  trn_fc;         /* field control field */
91         guint8                  trn_dhost[6];   /* destination host */
92         guint8                  trn_shost[6];   /* source host */
93         guint16                 trn_rcf;        /* routing control field */
94         guint16                 trn_rseg[8];    /* routing registers */
95
96         /* non-source-routed version of source addr */
97         guint8                  trn_shost_nonsr[6];
98
99         static const value_string fc_pcf[] = {
100                 { 0,    "Normal buffer" },
101                 { 1,    "Express buffer" },
102                 { 2,    "Purge" },
103                 { 3,    "Claim Token" },
104                 { 4,    "Beacon" },
105                 { 5,    "Active Monitor Present" },
106                 { 6,    "Standby Monitor Present" },
107                 { 0,    NULL },
108         };
109
110         /* Token-Ring Strings */
111         char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" };
112 /*      char *fc_pcf[] = {
113                 "Normal buffer", "Express buffer", "Purge",
114                 "Claim Token", "Beacon", "Active Monitor Present",
115                 "Standby Monitor Present" };*/
116         char *rc_arrow[] = { "-->", "<--" };
117         char *rc_direction[] = { "From originating station",
118                 "To originating station" };
119
120         /* get the data */
121         memcpy(&trn_ac, &pd[0], sizeof(guint8));
122         memcpy(&trn_fc, &pd[1], sizeof(guint8));
123         memcpy(trn_dhost, &pd[2], 6 * sizeof(guint8));
124         memcpy(trn_shost, &pd[8], 6 * sizeof(guint8));
125         memcpy(&trn_rcf, &pd[14], sizeof(guint16));
126         memcpy(trn_rseg, &pd[16], 8 * sizeof(guint16));
127
128         memcpy(trn_shost_nonsr, &pd[8], 6 * sizeof(guint8));
129         trn_shost_nonsr[0] &= 127;
130         frame_type = (trn_fc & 192) >> 6;
131
132         /* if the high bit on the first byte of src hwaddr is 1, then
133                 this packet is source-routed */
134         source_routed = trn_shost[0] & 128;
135
136         trn_rif_bytes = pd[14] & 31;
137
138         /* sometimes we have a RCF but no RIF... half source-routed? */
139         /* I'll check for 2 bytes of RIF and the 0x70 byte */
140         if (!source_routed) {
141                 if (trn_rif_bytes == 2) {
142                         source_routed = 1;
143                 }
144                 /* the Linux 2.0 TR code strips source-route bits in
145                  * order to test for SR. This can be removed from most
146                  * packets with oltr, but not all. So, I try to figure out
147                  * which packets should have been SR here. I'll check to
148                  * see if there's a SNAP or IPX field right after
149                  * my RIF fields.
150                  */
151                 else if ( (
152                         pd[0x0e + trn_rif_bytes] == 0xaa &&
153                         pd[0x0f + trn_rif_bytes] == 0xaa &&
154                         pd[0x10 + trn_rif_bytes] == 0x03) ||
155                           (
156                         pd[0x0e + trn_rif_bytes] == 0xe0 &&
157                         pd[0x0f + trn_rif_bytes] == 0xe0) ) {
158
159                         source_routed = 1;
160                 }
161 /*              else {
162                         printf("0e+%d = %02X   0f+%d = %02X\n", trn_rif_bytes, pd[0x0e + trn_rif_bytes],
163                                         trn_rif_bytes, pd[0x0f + trn_rif_bytes]);
164                 } */
165
166         }
167
168         if (source_routed) {
169                 actual_rif_bytes = trn_rif_bytes;
170         }
171         else {
172                 trn_rif_bytes = 0;
173                 actual_rif_bytes = 0;
174         }
175
176         /* this is a silly hack for Linux 2.0.x. Read the comment below,
177         in front of the other #ifdef linux. If we're sniffing our own NIC,
178          we get a full RIF, sometimes with garbage */
179         if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) ||
180                 (!source_routed && frame_type == 1)) {
181                 /* look for SNAP or IPX only */
182                 if ( (pd[0x20] == 0xaa && pd[0x21] == 0xaa && pd[0x22] == 03) ||
183                          (pd[0x20] == 0xe0 && pd[0x21] == 0xe0) ) {
184                         actual_rif_bytes = 18;
185                 }
186         }
187         offset += actual_rif_bytes;
188
189
190         /* information window */
191         if (check_col(fd, COL_RES_DL_DST))
192                 col_add_str(fd, COL_RES_DL_DST, ether_to_str((guint8 *)&pd[2]));
193         if (check_col(fd, COL_RES_DL_SRC))
194                 col_add_str(fd, COL_RES_DL_SRC, ether_to_str(trn_shost_nonsr));
195         if (check_col(fd, COL_PROTOCOL))
196                 col_add_str(fd, COL_PROTOCOL, "TR");
197         if (check_col(fd, COL_INFO))
198                 col_add_fstr(fd, COL_INFO, "Token-Ring %s", fc[frame_type]);
199
200         /* protocol analysis tree */
201         if (tree) {
202                 ti = add_item_to_tree(GTK_WIDGET(tree), 0, 14 + actual_rif_bytes,
203                   "Token-Ring");
204                 fh_tree = gtk_tree_new();
205                 add_subtree(ti, fh_tree, ETT_TOKEN_RING);
206                 add_item_to_tree(fh_tree, 0, 1,
207                         "Access Control: %s, Priority=%d, Monitor Count=%d, "
208                         "Priority Reservation=%d",
209                         ((trn_ac & 16) >> 4) ? "Frame" : "Token",       /* frame/token */
210                         ((trn_ac & 224) >> 5),                          /* priority */
211                         ((trn_ac & 8) >> 3),                            /* monitor count */
212                         ((trn_ac & 7)));                                /* priority reserv. */
213
214                 add_item_to_tree(fh_tree, 1, 1,
215                         "Frame Control: %s, Physical Control=%d (%s)",
216                         fc[frame_type], (trn_fc & 15),
217                         val_to_str((trn_fc & 15), fc_pcf, "Unknown"));
218
219                 add_item_to_tree(fh_tree, 2, 6, "Destination: %s",
220                         ether_to_str((guint8 *) trn_dhost));
221                 add_item_to_tree(fh_tree, 8, 6, "Source: %s",
222                         ether_to_str((guint8 *) trn_shost));
223
224                 if (source_routed) {
225                         add_item_to_tree(fh_tree, 14, 1, "RIF length: %d bytes", trn_rif_bytes);
226
227                         add_item_to_tree(fh_tree, 15, 1,
228                                 "%s, up to %d bytes in frame (LF=%d)",
229                                 sr_broadcast((pd[14] & 224) >> 5),
230                                 sr_frame((pd[15] & 112) >> 4),
231                                 (pd[15] & 112) >> 4);
232
233                         add_item_to_tree(fh_tree, 15, 1,
234                                 "Direction: %s (%s)",
235                                 rc_direction[(pd[15] & 128) >> 7],
236                                 rc_arrow[(pd[15] & 128) >> 7]);
237
238                         /* if we have more than 2 bytes of RIF, then we have
239                                 ring/bridge pairs */
240                         if (trn_rif_bytes > 2) {
241                                 add_ring_bridge_pairs(trn_rif_bytes, pd, fh_tree);
242                         }
243                 }
244
245                 /* Linux 2.0.x has a problem in that the 802.5 code creates
246                 an emtpy full (18-byte) RIF area. It's up to the tr driver to
247                 either fill it in or remove it before sending the bytes out
248                 to the wire. If you run tcpdump on a Linux 2.0.x machine running
249                 token-ring, tcpdump will capture these 18 filler bytes. They
250                 are filled with garbage. The best way to detect this problem is
251                 to know the src hwaddr of the machine from which you were running
252                 tcpdump. W/o that, however, I'm guessing that DSAP == SSAP if the
253                 frame type is LLC.  It's very much a hack. -- Gilbert Ramirez */
254                 if (actual_rif_bytes > trn_rif_bytes) {
255                         /*printf("trn_rif %d    actual_rif %d\n", trn_rif_bytes, actual_rif_bytes);*/
256                         add_item_to_tree(fh_tree, 14 + trn_rif_bytes, actual_rif_bytes - trn_rif_bytes,
257                                 "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
258                                 "is also running a protocol stack.");
259                 }
260                 /*
261                 if (source_routed && (trn_rif_bytes == 2) && silly_linux) {
262                         add_item_to_tree(fh_tree, 14 + trn_rif_bytes, 18 - actual_rif_bytes,
263                                 "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
264                                 "is also running a protocol stack.");
265                 }
266                 else if ((!source_routed) && silly_linux ) {
267                         add_item_to_tree(fh_tree, 14, 18,
268                                 "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
269                                 "is also running a protocol stack.");
270                 }*/
271         }
272
273         /* The package is either MAC or LLC */
274         switch (frame_type) {
275                 /* MAC */
276                 case 0:
277                         dissect_trmac(pd, offset, fd, tree);
278                         break;
279                 case 1:
280                         dissect_llc(pd, offset, fd, tree);
281                         break;
282                 default:
283                         /* non-MAC, non-LLC, i.e., "Reserved" */
284                         dissect_data(pd, offset, fd, tree);
285                         break;
286         }
287 }
288
289 /* this routine is taken from the Linux net/802/tr.c code, which shows
290 ring-bridge paires in the /proc/net/tr_rif virtual file. */
291 static void
292 add_ring_bridge_pairs(int rcf_len, const u_char *pd, GtkWidget *tree)
293 {
294         int     j, size;
295         int     segment, brdgnmb;
296         char    buffer[50];
297         int             buff_offset=0;
298
299         rcf_len -= 2;
300
301         if (rcf_len)
302                 rcf_len >>= 1;
303
304         for(j = 1; j < rcf_len; j++) {
305                 if (j==1) {
306                         segment=ntohs(*((unsigned short*)&pd[16])) >> 4;
307                         size = sprintf(buffer,"%03X",segment);
308                         buff_offset += size;
309                 }
310                 segment=ntohs(*((unsigned short*)&pd[17+j])) >> 4;
311                 brdgnmb=pd[16+j] & 0x0f;
312                 size = sprintf(buffer+buff_offset,"-%01X-%03X",brdgnmb,segment);
313                 buff_offset += size;    
314         }
315
316         add_item_to_tree(tree, 16, rcf_len << 1,
317                 "Ring-Bridge Pairs: %s",
318                 buffer);
319
320 }
321