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