When doing a capture, decode enough of the incoming packets to correctly
[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.10 1999/02/09 00:35:38 guy 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 capture_tr(const u_char *pd, guint32 cap_len, packet_counts *ld) {
79
80         int                     offset = 14;
81
82         int                     source_routed = 0;
83         int                     frame_type;
84         guint8                  trn_rif_bytes;
85         guint8                  actual_rif_bytes;
86
87         /* The trn_hdr struct, as separate variables */
88         guint8                  trn_fc;         /* field control field */
89         guint8                  trn_shost[6];   /* source host */
90
91         /* get the data */
92         memcpy(&trn_fc, &pd[1], sizeof(guint8));
93         memcpy(trn_shost, &pd[8], 6 * sizeof(guint8));
94
95         frame_type = (trn_fc & 192) >> 6;
96
97         /* if the high bit on the first byte of src hwaddr is 1, then
98                 this packet is source-routed */
99         source_routed = trn_shost[0] & 128;
100
101         trn_rif_bytes = pd[14] & 31;
102
103         /* sometimes we have a RCF but no RIF... half source-routed? */
104         /* I'll check for 2 bytes of RIF and the 0x70 byte */
105         if (!source_routed) {
106                 if (trn_rif_bytes == 2) {
107                         source_routed = 1;
108                 }
109                 /* the Linux 2.0 TR code strips source-route bits in
110                  * order to test for SR. This can be removed from most
111                  * packets with oltr, but not all. So, I try to figure out
112                  * which packets should have been SR here. I'll check to
113                  * see if there's a SNAP or IPX field right after
114                  * my RIF fields.
115                  */
116                 else if ( (
117                         pd[0x0e + trn_rif_bytes] == 0xaa &&
118                         pd[0x0f + trn_rif_bytes] == 0xaa &&
119                         pd[0x10 + trn_rif_bytes] == 0x03) ||
120                           (
121                         pd[0x0e + trn_rif_bytes] == 0xe0 &&
122                         pd[0x0f + trn_rif_bytes] == 0xe0) ) {
123
124                         source_routed = 1;
125                 }
126 /*              else {
127                         printf("0e+%d = %02X   0f+%d = %02X\n", trn_rif_bytes, pd[0x0e + trn_rif_bytes],
128                                         trn_rif_bytes, pd[0x0f + trn_rif_bytes]);
129                 } */
130
131         }
132
133         if (source_routed) {
134                 actual_rif_bytes = trn_rif_bytes;
135         }
136         else {
137                 trn_rif_bytes = 0;
138                 actual_rif_bytes = 0;
139         }
140
141         /* this is a silly hack for Linux 2.0.x. Read the comment below,
142         in front of the other #ifdef linux. If we're sniffing our own NIC,
143          we get a full RIF, sometimes with garbage */
144         if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) ||
145                 (!source_routed && frame_type == 1)) {
146                 /* look for SNAP or IPX only */
147                 if ( (pd[0x20] == 0xaa && pd[0x21] == 0xaa && pd[0x22] == 03) ||
148                          (pd[0x20] == 0xe0 && pd[0x21] == 0xe0) ) {
149                         actual_rif_bytes = 18;
150                 }
151         }
152         offset += actual_rif_bytes;
153
154         /* The package is either MAC or LLC */
155         switch (frame_type) {
156                 /* MAC */
157                 case 0:
158                         ld->other++;
159                         break;
160                 case 1:
161                         capture_llc(pd, offset, cap_len, ld);
162                         break;
163                 default:
164                         /* non-MAC, non-LLC, i.e., "Reserved" */
165                         ld->other++;
166                         break;
167         }
168 }
169
170
171 void
172 dissect_tr(const u_char *pd, frame_data *fd, GtkTree *tree) {
173
174         GtkWidget       *fh_tree, *ti;
175         int                     offset = 14;
176
177         int                     source_routed = 0;
178         int                     frame_type;
179         guint8                  trn_rif_bytes;
180         guint8                  actual_rif_bytes;
181
182         /* The trn_hdr struct, as separate variables */
183         guint8                  trn_ac;         /* access control field */
184         guint8                  trn_fc;         /* field control field */
185         guint8                  trn_dhost[6];   /* destination host */
186         guint8                  trn_shost[6];   /* source host */
187         guint16                 trn_rcf;        /* routing control field */
188         guint16                 trn_rseg[8];    /* routing registers */
189
190         /* non-source-routed version of source addr */
191         guint8                  trn_shost_nonsr[6];
192
193         static const value_string fc_pcf[] = {
194                 { 0,    "Normal buffer" },
195                 { 1,    "Express buffer" },
196                 { 2,    "Purge" },
197                 { 3,    "Claim Token" },
198                 { 4,    "Beacon" },
199                 { 5,    "Active Monitor Present" },
200                 { 6,    "Standby Monitor Present" },
201                 { 0,    NULL },
202         };
203
204         /* Token-Ring Strings */
205         char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" };
206 /*      char *fc_pcf[] = {
207                 "Normal buffer", "Express buffer", "Purge",
208                 "Claim Token", "Beacon", "Active Monitor Present",
209                 "Standby Monitor Present" };*/
210         char *rc_arrow[] = { "-->", "<--" };
211         char *rc_direction[] = { "From originating station",
212                 "To originating station" };
213
214         /* get the data */
215         memcpy(&trn_ac, &pd[0], sizeof(guint8));
216         memcpy(&trn_fc, &pd[1], sizeof(guint8));
217         memcpy(trn_dhost, &pd[2], 6 * sizeof(guint8));
218         memcpy(trn_shost, &pd[8], 6 * sizeof(guint8));
219         memcpy(&trn_rcf, &pd[14], sizeof(guint16));
220         memcpy(trn_rseg, &pd[16], 8 * sizeof(guint16));
221
222         memcpy(trn_shost_nonsr, &pd[8], 6 * sizeof(guint8));
223         trn_shost_nonsr[0] &= 127;
224         frame_type = (trn_fc & 192) >> 6;
225
226         /* if the high bit on the first byte of src hwaddr is 1, then
227                 this packet is source-routed */
228         source_routed = trn_shost[0] & 128;
229
230         trn_rif_bytes = pd[14] & 31;
231
232         /* sometimes we have a RCF but no RIF... half source-routed? */
233         /* I'll check for 2 bytes of RIF and the 0x70 byte */
234         if (!source_routed) {
235                 if (trn_rif_bytes == 2) {
236                         source_routed = 1;
237                 }
238                 /* the Linux 2.0 TR code strips source-route bits in
239                  * order to test for SR. This can be removed from most
240                  * packets with oltr, but not all. So, I try to figure out
241                  * which packets should have been SR here. I'll check to
242                  * see if there's a SNAP or IPX field right after
243                  * my RIF fields.
244                  */
245                 else if ( (
246                         pd[0x0e + trn_rif_bytes] == 0xaa &&
247                         pd[0x0f + trn_rif_bytes] == 0xaa &&
248                         pd[0x10 + trn_rif_bytes] == 0x03) ||
249                           (
250                         pd[0x0e + trn_rif_bytes] == 0xe0 &&
251                         pd[0x0f + trn_rif_bytes] == 0xe0) ) {
252
253                         source_routed = 1;
254                 }
255 /*              else {
256                         printf("0e+%d = %02X   0f+%d = %02X\n", trn_rif_bytes, pd[0x0e + trn_rif_bytes],
257                                         trn_rif_bytes, pd[0x0f + trn_rif_bytes]);
258                 } */
259
260         }
261
262         if (source_routed) {
263                 actual_rif_bytes = trn_rif_bytes;
264         }
265         else {
266                 trn_rif_bytes = 0;
267                 actual_rif_bytes = 0;
268         }
269
270         /* this is a silly hack for Linux 2.0.x. Read the comment below,
271         in front of the other #ifdef linux. If we're sniffing our own NIC,
272          we get a full RIF, sometimes with garbage */
273         if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) ||
274                 (!source_routed && frame_type == 1)) {
275                 /* look for SNAP or IPX only */
276                 if ( (pd[0x20] == 0xaa && pd[0x21] == 0xaa && pd[0x22] == 03) ||
277                          (pd[0x20] == 0xe0 && pd[0x21] == 0xe0) ) {
278                         actual_rif_bytes = 18;
279                 }
280         }
281         offset += actual_rif_bytes;
282
283
284         /* information window */
285         if (check_col(fd, COL_RES_DL_DST))
286                 col_add_str(fd, COL_RES_DL_DST, ether_to_str((guint8 *)&pd[2]));
287         if (check_col(fd, COL_RES_DL_SRC))
288                 col_add_str(fd, COL_RES_DL_SRC, ether_to_str(trn_shost_nonsr));
289         if (check_col(fd, COL_PROTOCOL))
290                 col_add_str(fd, COL_PROTOCOL, "TR");
291         if (check_col(fd, COL_INFO))
292                 col_add_fstr(fd, COL_INFO, "Token-Ring %s", fc[frame_type]);
293
294         /* protocol analysis tree */
295         if (tree) {
296                 ti = add_item_to_tree(GTK_WIDGET(tree), 0, 14 + actual_rif_bytes,
297                   "Token-Ring");
298                 fh_tree = gtk_tree_new();
299                 add_subtree(ti, fh_tree, ETT_TOKEN_RING);
300                 add_item_to_tree(fh_tree, 0, 1,
301                         "Access Control: %s, Priority=%d, Monitor Count=%d, "
302                         "Priority Reservation=%d",
303                         ((trn_ac & 16) >> 4) ? "Frame" : "Token",       /* frame/token */
304                         ((trn_ac & 224) >> 5),                          /* priority */
305                         ((trn_ac & 8) >> 3),                            /* monitor count */
306                         ((trn_ac & 7)));                                /* priority reserv. */
307
308                 add_item_to_tree(fh_tree, 1, 1,
309                         "Frame Control: %s, Physical Control=%d (%s)",
310                         fc[frame_type], (trn_fc & 15),
311                         val_to_str((trn_fc & 15), fc_pcf, "Unknown"));
312
313                 add_item_to_tree(fh_tree, 2, 6, "Destination: %s",
314                         ether_to_str((guint8 *) trn_dhost));
315                 add_item_to_tree(fh_tree, 8, 6, "Source: %s",
316                         ether_to_str((guint8 *) trn_shost));
317
318                 if (source_routed) {
319                         add_item_to_tree(fh_tree, 14, 1, "RIF length: %d bytes", trn_rif_bytes);
320
321                         add_item_to_tree(fh_tree, 15, 1,
322                                 "%s, up to %d bytes in frame (LF=%d)",
323                                 sr_broadcast((pd[14] & 224) >> 5),
324                                 sr_frame((pd[15] & 112) >> 4),
325                                 (pd[15] & 112) >> 4);
326
327                         add_item_to_tree(fh_tree, 15, 1,
328                                 "Direction: %s (%s)",
329                                 rc_direction[(pd[15] & 128) >> 7],
330                                 rc_arrow[(pd[15] & 128) >> 7]);
331
332                         /* if we have more than 2 bytes of RIF, then we have
333                                 ring/bridge pairs */
334                         if (trn_rif_bytes > 2) {
335                                 add_ring_bridge_pairs(trn_rif_bytes, pd, fh_tree);
336                         }
337                 }
338
339                 /* Linux 2.0.x has a problem in that the 802.5 code creates
340                 an emtpy full (18-byte) RIF area. It's up to the tr driver to
341                 either fill it in or remove it before sending the bytes out
342                 to the wire. If you run tcpdump on a Linux 2.0.x machine running
343                 token-ring, tcpdump will capture these 18 filler bytes. They
344                 are filled with garbage. The best way to detect this problem is
345                 to know the src hwaddr of the machine from which you were running
346                 tcpdump. W/o that, however, I'm guessing that DSAP == SSAP if the
347                 frame type is LLC.  It's very much a hack. -- Gilbert Ramirez */
348                 if (actual_rif_bytes > trn_rif_bytes) {
349                         /*printf("trn_rif %d    actual_rif %d\n", trn_rif_bytes, actual_rif_bytes);*/
350                         add_item_to_tree(fh_tree, 14 + trn_rif_bytes, actual_rif_bytes - trn_rif_bytes,
351                                 "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
352                                 "is also running a protocol stack.");
353                 }
354                 /*
355                 if (source_routed && (trn_rif_bytes == 2) && silly_linux) {
356                         add_item_to_tree(fh_tree, 14 + trn_rif_bytes, 18 - actual_rif_bytes,
357                                 "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
358                                 "is also running a protocol stack.");
359                 }
360                 else if ((!source_routed) && silly_linux ) {
361                         add_item_to_tree(fh_tree, 14, 18,
362                                 "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
363                                 "is also running a protocol stack.");
364                 }*/
365         }
366
367         /* The package is either MAC or LLC */
368         switch (frame_type) {
369                 /* MAC */
370                 case 0:
371                         dissect_trmac(pd, offset, fd, tree);
372                         break;
373                 case 1:
374                         dissect_llc(pd, offset, fd, tree);
375                         break;
376                 default:
377                         /* non-MAC, non-LLC, i.e., "Reserved" */
378                         dissect_data(pd, offset, fd, tree);
379                         break;
380         }
381 }
382
383 /* this routine is taken from the Linux net/802/tr.c code, which shows
384 ring-bridge paires in the /proc/net/tr_rif virtual file. */
385 static void
386 add_ring_bridge_pairs(int rcf_len, const u_char *pd, GtkWidget *tree)
387 {
388         int     j, size;
389         int     segment, brdgnmb;
390         char    buffer[50];
391         int             buff_offset=0;
392
393         rcf_len -= 2;
394
395         if (rcf_len)
396                 rcf_len >>= 1;
397
398         for(j = 1; j < rcf_len; j++) {
399                 if (j==1) {
400                         segment=ntohs(*((unsigned short*)&pd[16])) >> 4;
401                         size = sprintf(buffer,"%03X",segment);
402                         buff_offset += size;
403                 }
404                 segment=ntohs(*((unsigned short*)&pd[17+j])) >> 4;
405                 brdgnmb=pd[16+j] & 0x0f;
406                 size = sprintf(buffer+buff_offset,"-%01X-%03X",brdgnmb,segment);
407                 buff_offset += size;    
408         }
409
410         add_item_to_tree(tree, 16, rcf_len << 1,
411                 "Ring-Bridge Pairs: %s",
412                 buffer);
413
414 }
415