Trivial warning fixes
[obnox/wireshark/wip.git] / epan / dissectors / packet-tr.c
1 /* packet-tr.c
2  * Routines for Token-Ring packet disassembly
3  * Gilbert Ramirez <gram@alumni.rice.edu>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <string.h>
31 #include <stdio.h>
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include "packet-tr.h"
35 #include "packet-llc.h"
36 #include <epan/prefs.h>
37 #include <epan/tap.h>
38 #include <epan/emem.h>
39
40 static int proto_tr = -1;
41 static int hf_tr_dst = -1;
42 static int hf_tr_src = -1;
43 static int hf_tr_addr = -1;
44 static int hf_tr_sr = -1;
45 static int hf_tr_ac = -1;
46 static int hf_tr_priority = -1;
47 static int hf_tr_frame = -1;
48 static int hf_tr_monitor_cnt = -1;
49 static int hf_tr_priority_reservation = -1;
50 static int hf_tr_fc = -1;
51 static int hf_tr_fc_type = -1;
52 static int hf_tr_fc_pcf = -1;
53 static int hf_tr_rif_bytes = -1;
54 static int hf_tr_broadcast = -1;
55 static int hf_tr_max_frame_size = -1;
56 static int hf_tr_direction = -1;
57 static int hf_tr_rif = -1;
58 static int hf_tr_rif_ring = -1;
59 static int hf_tr_rif_bridge = -1;
60
61 static gint ett_token_ring = -1;
62 static gint ett_token_ring_ac = -1;
63 static gint ett_token_ring_fc = -1;
64
65 static int tr_tap = -1;
66
67 /*
68  * Check for and attempt to fix Linux link-layer header mangling.
69  */
70 static gboolean fix_linux_botches = FALSE;
71
72 #define TR_MIN_HEADER_LEN 14
73 #define TR_MAX_HEADER_LEN 32
74
75 static const true_false_string ac_truth = { "Frame", "Token" };
76
77 static const value_string pcf_vals[] = {
78         { 0,    "Normal buffer" },
79         { 1,    "Express buffer" },
80         { 2,    "Purge" },
81         { 3,    "Claim Token" },
82         { 4,    "Beacon" },
83         { 5,    "Active Monitor Present" },
84         { 6,    "Standby Monitor Present" },
85         { 0,    NULL },
86 };
87
88 static const value_string frame_vals[] = {
89         { 0,    "MAC" },
90         { 1,    "LLC" },
91         { 2,    "Reserved" },
92         { 0,    NULL },
93 };
94
95 static const value_string broadcast_vals[] = {
96         { 0 << 5,       "Non-broadcast" },
97         { 1 << 5,       "Non-broadcast" },
98         { 2 << 5,       "Non-broadcast" },
99         { 3 << 5,       "Non-broadcast" },
100         { 4 << 5,       "All-routes broadcast" },
101         { 5 << 5,       "All-routes broadcast" },
102         { 6 << 5,       "Single-route broadcast" },
103         { 7 << 5,       "Single-route broadcast" },
104         { 0,            NULL }
105 };
106
107 static const value_string max_frame_size_vals[] = {
108         { 0 << 4,       "516" },
109         { 1 << 4,       "1500" },
110         { 2 << 4,       "2052" },
111         { 3 << 4,       "4472" },
112         { 4 << 4,       "8144" },
113         { 5 << 4,       "11407" },
114         { 6 << 4,       "17800" },
115         { 7 << 4,       "65535" },
116         { 0,            NULL }
117 };
118
119 static const value_string direction_vals[] = {
120         { 0,    "From originating station (-->)" },
121         { 128,  "To originating station (<--)" },
122         { 0,    NULL }
123 };
124
125 static dissector_handle_t trmac_handle;
126 static dissector_handle_t llc_handle;
127 static dissector_handle_t data_handle;
128
129 /*
130  * DODGY LINUX HACK DODGY LINUX HACK
131  * Linux 2.0.x always passes frames to the Token Ring driver for transmission with
132  * 18 bytes padding for source routing information.  Some drivers copy the first
133  * (18 - srlen) bytes up the frame (18 - srlen) bytes thus removing the padding.
134  * Other drivers just make a copy of the entire frame and then hack about with it
135  * so the frame the sniffer gets is fine (just has extra sr routing).
136  * In the first instance (driver hacking frame in situ) the sniffer gets a garbled
137  * frame.
138  * This function trys to detect this and returns the offset of where
139  * the frame really starts.
140  * This only detects frames that we have sent ourselves so if we are packet sniffing
141  * on the machine we are watching this is useful.
142  * Compare offset 0 with offset x+1 for a length of x bytes for all value of x = 1 to 18
143  * if match then Linux driver has done in situ source route compression of the crappy
144  * Linux 2.0.x frame so the beginning of the real frame is x bytes in.
145  * (And this real frame x bytes in looks like a proper TR frame that goes on the wire
146  * with none of the Linux idiosyncrasies).
147  *
148  * XXX - there should perhaps be a preference setting to turn this off,
149  * as sometimes it can, and does, get a false hit.
150  */
151 static
152 int check_for_old_linux_tvb(tvbuff_t *tvb)
153 {
154         const guint8    *data;
155         int             x, bytes;
156
157         /* Restrict our looping to the boundaries of the frame */
158         bytes = tvb_length(tvb);
159         if (bytes > 19) {
160                 bytes = 19;
161         }
162
163         data = tvb_get_ptr(tvb, 0, bytes);
164
165         for(x = 1; x <= bytes-1 ;x++)
166         {
167                 if (memcmp(&data[0], &data[x], x) == 0)
168                 {
169                         return x;
170                 }
171         }
172         return 0;
173 }
174
175 static
176 int check_for_old_linux(const guchar * pd)
177 {
178         int x;
179         for(x=1;x<=18;x++)
180         {
181                 if (memcmp(&pd[0],&pd[x],x) == 0)
182                 {
183                         return x;
184                 }
185         }
186         return 0;
187 }
188
189
190 static void
191 add_ring_bridge_pairs(int rcf_len, tvbuff_t*, proto_tree *tree);
192
193 void
194 capture_tr(const guchar *pd, int offset, int len, packet_counts *ld) {
195
196         int                     source_routed = 0;
197         int                     frame_type;
198         int                     x;
199         guint8                  trn_rif_bytes;
200         guint8                  actual_rif_bytes;
201         guint16                 first2_sr;
202
203         /* The trn_hdr struct, as separate variables */
204         guint8                  trn_fc;         /* field control field */
205         const guint8            *trn_shost;     /* source host */
206
207         if (!BYTES_ARE_IN_FRAME(offset, len, TR_MIN_HEADER_LEN)) {
208                 ld->other++;
209                 return;
210         }
211
212         if ((x = check_for_old_linux(pd)))
213         {
214                 /* Actually packet starts x bytes into what we have got but with all
215                    source routing compressed
216                 */
217                  /* pd = &pd[x]; */ offset+=x;
218         }
219
220         /* get the data */
221         trn_fc = pd[offset + 1];
222         trn_shost = &pd[offset + 8];
223
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[offset + 14] & 31;
231
232         if (fix_linux_botches) {
233                 /* the Linux 2.0 TR code strips source-route bits in
234                  * order to test for SR. This can be removed from most
235                  * packets with oltr, but not all. So, I try to figure out
236                  * which packets should have been SR here. I'll check to
237                  * see if there's a SNAP or IPX field right after
238                  * my RIF fields.
239                  *
240                  * The Linux 2.4.18 code, at least appears to do the
241                  * same thing, from a capture I got from somebody running
242                  * 2.4.18 (RH 7.1, so perhaps this is a Red Hat
243                  * "improvement").
244                  */
245                 if (!source_routed && trn_rif_bytes > 0) {
246                         if (pd[offset + 0x0e] != pd[offset + 0x0f]) {
247                                 first2_sr = pntohs(&pd[offset + 0xe0 + trn_rif_bytes]);
248                                 if (
249                                         (first2_sr == 0xaaaa &&
250                                         pd[offset + 0x10 + trn_rif_bytes] == 0x03) ||
251
252                                         first2_sr == 0xe0e0 ||
253                                         first2_sr == 0xe0aa ) {
254
255                                         source_routed = 1;
256                                 }
257                         }
258                 }
259         }
260
261         if (source_routed) {
262                 actual_rif_bytes = trn_rif_bytes;
263         }
264         else {
265                 trn_rif_bytes = 0;
266                 actual_rif_bytes = 0;
267         }
268
269         if (fix_linux_botches) {
270                 /* this is a silly hack for Linux 2.0.x. Read the comment
271                  * below, in front of the other #ifdef linux.
272                  * If we're sniffing our own NIC, we get a full RIF,
273                  * sometimes with garbage
274                  */
275                 if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) ||
276                         (!source_routed && frame_type == 1)) {
277                         /* look for SNAP or IPX only */
278                         if ( (pd[offset + 0x20] == 0xaa && pd[offset + 0x21] == 0xaa && pd[offset + 0x22] == 03) ||
279                                  (pd[offset + 0x20] == 0xe0 && pd[offset + 0x21] == 0xe0) ) {
280                                 actual_rif_bytes = 18;
281                         } else if (
282                                 pd[offset + 0x23] == 0 &&
283                                 pd[offset + 0x24] == 0 &&
284                                 pd[offset + 0x25] == 0 &&
285                                 pd[offset + 0x26] == 0x00 &&
286                                 pd[offset + 0x27] == 0x11) {
287
288                                 actual_rif_bytes = 18;
289
290                                /* Linux 2.0.x also requires drivers pass up
291                                 * a fake SNAP and LLC header before the
292                                 * real LLC hdr for all Token Ring frames
293                                 * that arrive with DSAP and SSAP != 0xAA
294                                 * (i.e. for non SNAP frames e.g. for Netware
295                                 * frames) the fake SNAP header has the
296                                 * ETH_P_TR_802_2 ether type (0x0011) and the protocol id
297                                 * bytes as zero frame looks like :-
298                                 * TR Header | Fake LLC | Fake SNAP | Wire LLC | Rest of data
299                                 */
300                                offset += 8; /* Skip fake LLC and SNAP */
301                         }
302                 }
303         }
304
305         offset += actual_rif_bytes + TR_MIN_HEADER_LEN;
306
307         /* The package is either MAC or LLC */
308         switch (frame_type) {
309                 /* MAC */
310                 case 0:
311                         ld->other++;
312                         break;
313                 case 1:
314                         capture_llc(pd, offset, len, ld);
315                         break;
316                 default:
317                         /* non-MAC, non-LLC, i.e., "Reserved" */
318                         ld->other++;
319                         break;
320         }
321 }
322
323
324 static void
325 dissect_tr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
326 {
327         proto_tree      *tr_tree, *bf_tree;
328         proto_item      *ti, *hidden_item;
329         guint8          rcf1, rcf2;
330         tvbuff_t        *next_tvb;
331
332         volatile int            frame_type;
333         volatile int            fixoffset = 0;
334         volatile int            source_routed = 0;
335         volatile guint8         trn_rif_bytes;
336         volatile guint8         actual_rif_bytes;
337         volatile guint8         c1_nonsr;
338         volatile guint8         c2_nonsr;
339         volatile guint16        first2_sr;
340         tvbuff_t                *volatile tr_tvb;
341
342         static tr_hdr trh_arr[4];
343         static int trh_current=0;
344         tr_hdr *volatile trh;
345
346         /* non-source-routed version of source addr */
347         static guint8           trn_shost_nonsr[6];
348         int                     x;
349
350         /* Token-Ring Strings */
351         const char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" };
352
353
354         trh_current++;
355         if(trh_current==4){
356                 trh_current=0;
357         }
358         trh=&trh_arr[trh_current];
359
360         if (check_col(pinfo->cinfo, COL_PROTOCOL))
361                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TR");
362
363         if (fix_linux_botches)
364                 x = check_for_old_linux_tvb((tvbuff_t*) tvb);
365         else
366                 x = 0;
367         if (x != 0) {
368                 /* Actually packet starts x bytes into what we have got but with all
369                    source routing compressed. See comment above */
370                 tr_tvb = tvb_new_subset((tvbuff_t*) tvb, x, -1, -1);
371         }
372         else {
373                 tr_tvb = tvb;
374         }
375
376         /* Get the data */
377         trh->fc         = tvb_get_guint8(tr_tvb, 1);
378         SET_ADDRESS(&trh->src,  AT_ETHER, 6, tvb_get_ptr(tr_tvb, 8, 6));
379         SET_ADDRESS(&trh->dst,  AT_ETHER, 6, tvb_get_ptr(tr_tvb, 2, 6));
380
381         /* if the high bit on the first byte of src hwaddr is 1, then
382                 this packet is source-routed */
383         memcpy(trn_shost_nonsr, trh->src.data, 6);
384         source_routed = trn_shost_nonsr[0] & 128;
385         trn_shost_nonsr[0] &= 127;
386
387         frame_type = (trh->fc & 192) >> 6;
388
389         if (check_col(pinfo->cinfo, COL_INFO))
390                 col_add_fstr(pinfo->cinfo, COL_INFO, "Token-Ring %s", fc[frame_type]);
391
392         trn_rif_bytes = tvb_get_guint8(tr_tvb, 14) & 31;
393
394         if (fix_linux_botches) {
395                 /* the Linux 2.0 TR code strips source-route bits in
396                  * order to test for SR. This can be removed from most
397                  * packets with oltr, but not all. So, I try to figure out
398                  * which packets should have been SR here. I'll check to
399                  * see if there's a SNAP or IPX field right after
400                  * my RIF fields.
401                  *
402                  * The Linux 2.4.18 code, at least appears to do the
403                  * same thing, from a capture I got from somebody running
404                  * 2.4.18 (RH 7.1, so perhaps this is a Red Hat
405                  * "improvement").
406                  */
407                 if (frame_type == 1 && !source_routed && trn_rif_bytes > 0) {
408                         TRY {
409
410                                 c1_nonsr = tvb_get_guint8(tr_tvb, 14);
411                                 c2_nonsr = tvb_get_guint8(tr_tvb, 15);
412
413                                 if (c1_nonsr != c2_nonsr) {
414
415                                         first2_sr = tvb_get_ntohs(tr_tvb, trn_rif_bytes + 0x0e);
416
417                                         if ( ( first2_sr == 0xaaaa &&
418                                                 tvb_get_guint8(tr_tvb, trn_rif_bytes + 0x10) == 0x03)   ||
419
420                                                 first2_sr == 0xe0e0 ||
421                                                 first2_sr == 0xe0aa ) {
422
423                                                 source_routed = 1;
424                                         }
425                                 }
426                         }
427                         CATCH(BoundsError) {
428                                 /* We had no information beyond the TR header. Just assume
429                                  * this is a normal (non-Linux) TR header. */
430                                 ;
431                         }
432                         ENDTRY;
433                 }
434         }
435
436         if (source_routed) {
437                 actual_rif_bytes = trn_rif_bytes;
438         }
439         else {
440                 trn_rif_bytes = 0;
441                 actual_rif_bytes = 0;
442         }
443
444         if (fix_linux_botches) {
445                 /* this is a silly hack for Linux 2.0.x. Read the comment
446                  * below, in front of the other #ifdef linux. If we're
447                  * sniffing our own NIC, we get a full RIF, sometimes with
448                  * garbage
449                  */
450                 TRY {
451                         if (frame_type == 1 && ( (source_routed && trn_rif_bytes == 2) ||
452                                                  !source_routed) ) {
453                                 /* look for SNAP or IPX only */
454                                 if (
455                                         (tvb_get_ntohs(tr_tvb, 0x20) == 0xaaaa &&
456                                         tvb_get_guint8(tr_tvb, 0x22) == 0x03)
457                                  ||
458                                         tvb_get_ntohs(tr_tvb, 0x20) == 0xe0e0 ) {
459
460                                         actual_rif_bytes = 18;
461                                 }
462                                 else if (
463                                         tvb_get_ntohl(tr_tvb, 0x23) == 0 &&
464                                         tvb_get_guint8(tr_tvb, 0x27) == 0x11) {
465
466                                         actual_rif_bytes = 18;
467
468                                        /* Linux 2.0.x also requires drivers
469                                         * pass up a fake SNAP and LLC header
470                                         * before the real LLC hdr for all
471                                         * Token Ring frames that arrive with
472                                         * DSAP and SSAP != 0xAA
473                                         * (i.e. for non SNAP frames e.g. for
474                                         * Netware frames)
475                                         * the fake SNAP header has the
476                                         * ETH_P_TR_802_2 ether type (0x0011)
477                                         * and the protocol id bytes as zero frame looks like :-
478                                         * TR Header | Fake LLC | Fake SNAP | Wire LLC | Rest of data
479                                         */
480                                         fixoffset += 8; /* Skip fake LLC and SNAP */
481                                 }
482                         }
483                 }
484                 CATCH(BoundsError) {
485                         /* We had no information beyond the TR header. Just assume
486                          * this is a normal (non-Linux) TR header. */
487                         ;
488                 }
489                 ENDTRY;
490         }
491
492         /* XXX - copy it to some buffer associated with "*pinfo", rather than
493            just making "trn_shost_nonsr" static? */
494         SET_ADDRESS(&pinfo->dl_src,     AT_ETHER, 6, trn_shost_nonsr);
495         SET_ADDRESS(&pinfo->src,        AT_ETHER, 6, trn_shost_nonsr);
496         SET_ADDRESS(&pinfo->dl_dst,     AT_ETHER, 6, trh->dst.data);
497         SET_ADDRESS(&pinfo->dst,        AT_ETHER, 6, trh->dst.data);
498
499         /* protocol analysis tree */
500         if (tree) {
501                 /* Create Token-Ring Tree */
502                 ti = proto_tree_add_item(tree, proto_tr, tr_tvb, 0, TR_MIN_HEADER_LEN + actual_rif_bytes, FALSE);
503                 tr_tree = proto_item_add_subtree(ti, ett_token_ring);
504
505                 /* Create the Access Control bitfield tree */
506                 trh->ac = tvb_get_guint8(tr_tvb, 0);
507                 ti = proto_tree_add_uint(tr_tree, hf_tr_ac, tr_tvb, 0, 1, trh->ac);
508                 bf_tree = proto_item_add_subtree(ti, ett_token_ring_ac);
509
510                 proto_tree_add_uint(bf_tree, hf_tr_priority, tr_tvb, 0, 1, trh->ac);
511                 proto_tree_add_boolean(bf_tree, hf_tr_frame, tr_tvb, 0, 1, trh->ac);
512                 proto_tree_add_uint(bf_tree, hf_tr_monitor_cnt, tr_tvb, 0, 1, trh->ac);
513                 proto_tree_add_uint(bf_tree, hf_tr_priority_reservation, tr_tvb, 0, 1, trh->ac);
514
515                 /* Create the Frame Control bitfield tree */
516                 ti = proto_tree_add_uint(tr_tree, hf_tr_fc, tr_tvb, 1, 1, trh->fc);
517                 bf_tree = proto_item_add_subtree(ti, ett_token_ring_fc);
518
519                 proto_tree_add_uint(bf_tree, hf_tr_fc_type, tr_tvb, 1, 1, trh->fc);
520                 proto_tree_add_uint(bf_tree, hf_tr_fc_pcf, tr_tvb,  1, 1, trh->fc);
521                 proto_tree_add_ether(tr_tree, hf_tr_dst, tr_tvb, 2, 6, trh->dst.data);
522                 proto_tree_add_ether(tr_tree, hf_tr_src, tr_tvb, 8, 6, trh->src.data);
523                 hidden_item = proto_tree_add_ether(tr_tree, hf_tr_addr, tr_tvb, 2, 6, trh->dst.data);
524                 PROTO_ITEM_SET_HIDDEN(hidden_item);
525                 hidden_item = proto_tree_add_ether(tr_tree, hf_tr_addr, tr_tvb, 8, 6, trh->src.data);
526                 PROTO_ITEM_SET_HIDDEN(hidden_item);
527
528                 proto_tree_add_boolean(tr_tree, hf_tr_sr, tr_tvb, 8, 1, source_routed);
529
530                 /* non-source-routed version of src addr */
531                 hidden_item = proto_tree_add_ether(tr_tree, hf_tr_src, tr_tvb, 8, 6, trn_shost_nonsr);
532                 PROTO_ITEM_SET_HIDDEN(hidden_item);
533
534                 if (source_routed) {
535                         /* RCF Byte 1 */
536                         rcf1 = tvb_get_guint8(tr_tvb, 14);
537                         proto_tree_add_uint(tr_tree, hf_tr_rif_bytes, tr_tvb, 14, 1, trn_rif_bytes);
538                         proto_tree_add_uint(tr_tree, hf_tr_broadcast, tr_tvb, 14, 1, rcf1 & 224);
539
540                         /* RCF Byte 2 */
541                         rcf2 = tvb_get_guint8(tr_tvb, 15);
542                         proto_tree_add_uint(tr_tree, hf_tr_max_frame_size, tr_tvb, 15, 1, rcf2 & 112);
543                         proto_tree_add_uint(tr_tree, hf_tr_direction, tr_tvb, 15, 1, rcf2 & 128);
544
545                         /* if we have more than 2 bytes of RIF, then we have
546                                 ring/bridge pairs */
547                         if (trn_rif_bytes > 2) {
548                                 add_ring_bridge_pairs(trn_rif_bytes, tr_tvb, tr_tree);
549                         }
550                 }
551
552                 /* Linux 2.0.x has a problem in that the 802.5 code creates
553                 an emtpy full (18-byte) RIF area. It's up to the tr driver to
554                 either fill it in or remove it before sending the bytes out
555                 to the wire. If you run tcpdump on a Linux 2.0.x machine running
556                 token-ring, tcpdump will capture these 18 filler bytes. They
557                 are filled with garbage. The best way to detect this problem is
558                 to know the src hwaddr of the machine from which you were running
559                 tcpdump. W/o that, however, I'm guessing that DSAP == SSAP if the
560                 frame type is LLC.  It's very much a hack. */
561                 if (actual_rif_bytes > trn_rif_bytes) {
562                         proto_tree_add_text(tr_tree, tr_tvb, TR_MIN_HEADER_LEN + trn_rif_bytes, actual_rif_bytes - trn_rif_bytes,
563                                 "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
564                                 "is also running a protocol stack.");
565                 }
566                 if (fixoffset) {
567                         proto_tree_add_text(tr_tree, tr_tvb, TR_MIN_HEADER_LEN + 18,8,"Linux 2.0.x fake LLC and SNAP header");
568                 }
569         }
570
571         next_tvb = tvb_new_subset(tr_tvb, TR_MIN_HEADER_LEN + actual_rif_bytes + fixoffset, -1, -1);
572
573         /* The package is either MAC or LLC */
574         switch (frame_type) {
575                 /* MAC */
576                 case 0:
577                         call_dissector(trmac_handle, next_tvb, pinfo, tree);
578                         break;
579                 case 1:
580                         call_dissector(llc_handle, next_tvb, pinfo, tree);
581                         break;
582                 default:
583                         /* non-MAC, non-LLC, i.e., "Reserved" */
584                         call_dissector(data_handle,next_tvb, pinfo, tree);
585                         break;
586         }
587
588         tap_queue_packet(tr_tap, pinfo, trh);
589 }
590
591 /* this routine is taken from the Linux net/802/tr.c code, which shows
592 ring-bridge pairs in the /proc/net/tr_rif virtual file. */
593 static void
594 add_ring_bridge_pairs(int rcf_len, tvbuff_t *tvb, proto_tree *tree)
595 {
596         proto_item *hidden_item;
597         int     j, size;
598         int     segment, brdgnmb, unprocessed_rif;
599         int     buff_offset=0;
600
601 #define RIF_OFFSET              16
602 #define RIF_BYTES_TO_PROCESS    30
603
604         char    *buffer;
605 #define MAX_BUF_LEN 3 + (RIF_BYTES_TO_PROCESS / 2) * 6 + 1
606
607         buffer=ep_alloc(MAX_BUF_LEN);
608         /* Only process so many  bytes of RIF, as per TR spec, and not overflow
609          * static buffer above */
610         unprocessed_rif = rcf_len - RIF_BYTES_TO_PROCESS;
611         rcf_len = MIN(rcf_len, RIF_BYTES_TO_PROCESS);
612
613         /* Ignore the 2 RCF bytes, since they don't make up the ring/bride pairs */
614         rcf_len -= 2;
615
616         for(j = 1; j < rcf_len - 1; j += 2) {
617                 if (j==1) {
618                         segment = tvb_get_ntohs(tvb, RIF_OFFSET) >> 4;
619                         size = g_snprintf(buffer, MAX_BUF_LEN, "%03X",segment);
620                         size = MIN(size, MAX_BUF_LEN - 1);
621                         hidden_item = proto_tree_add_uint(tree, hf_tr_rif_ring, tvb, TR_MIN_HEADER_LEN + 2, 2, segment);
622                         PROTO_ITEM_SET_HIDDEN(hidden_item);
623                         buff_offset += size;
624                 }
625                 segment = tvb_get_ntohs(tvb, RIF_OFFSET + 1 + j) >> 4;
626                 brdgnmb = tvb_get_guint8(tvb, RIF_OFFSET + j) & 0x0f;
627                 size = g_snprintf(buffer+buff_offset, MAX_BUF_LEN-buff_offset, "-%01X-%03X",brdgnmb,segment);
628                 size = MIN(size, MAX_BUF_LEN-buff_offset-1);
629                 hidden_item = proto_tree_add_uint(tree, hf_tr_rif_ring, tvb, TR_MIN_HEADER_LEN + 3 + j, 2, segment);
630                 PROTO_ITEM_SET_HIDDEN(hidden_item);
631                 hidden_item = proto_tree_add_uint(tree, hf_tr_rif_bridge, tvb, TR_MIN_HEADER_LEN + 2 + j, 1, brdgnmb);
632                 PROTO_ITEM_SET_HIDDEN(hidden_item);
633                 buff_offset += size;
634         }
635         proto_tree_add_string(tree, hf_tr_rif, tvb, TR_MIN_HEADER_LEN + 2, rcf_len, buffer);
636
637         if (unprocessed_rif > 0) {
638                 proto_tree_add_text(tree, tvb, TR_MIN_HEADER_LEN + RIF_BYTES_TO_PROCESS, unprocessed_rif,
639                                 "Extra RIF bytes beyond spec: %d", unprocessed_rif);
640         }
641 }
642
643 void
644 proto_register_tr(void)
645 {
646         static hf_register_info hf[] = {
647                 { &hf_tr_ac,
648                 { "Access Control",     "tr.ac", FT_UINT8, BASE_HEX, NULL, 0x0,
649                         "", HFILL }},
650
651                 { &hf_tr_priority,
652                 { "Priority",           "tr.priority", FT_UINT8, BASE_DEC, NULL, 0xe0,
653                         "", HFILL }},
654
655                 { &hf_tr_frame,
656                 { "Frame",              "tr.frame", FT_BOOLEAN, 8, TFS(&ac_truth), 0x10,
657                         "", HFILL }},
658
659                 { &hf_tr_monitor_cnt,
660                 { "Monitor Count",      "tr.monitor_cnt", FT_UINT8, BASE_DEC, NULL, 0x08,
661                         "", HFILL }},
662
663                 { &hf_tr_priority_reservation,
664                 { "Priority Reservation","tr.priority_reservation", FT_UINT8, BASE_DEC, NULL, 0x07,
665                         "", HFILL }},
666
667                 { &hf_tr_fc,
668                 { "Frame Control",      "tr.fc", FT_UINT8, BASE_HEX, NULL, 0x0,
669                         "", HFILL }},
670
671                 { &hf_tr_fc_type,
672                 { "Frame Type",         "tr.frame_type", FT_UINT8, BASE_DEC, VALS(frame_vals), 0xc0,
673                         "", HFILL }},
674
675                 { &hf_tr_fc_pcf,
676                 { "Frame PCF",          "tr.frame_pcf", FT_UINT8, BASE_DEC, VALS(pcf_vals), 0x0f,
677                         "", HFILL }},
678
679                 { &hf_tr_dst,
680                 { "Destination",        "tr.dst", FT_ETHER, BASE_NONE,  NULL, 0x0,
681                         "Destination Hardware Address", HFILL }},
682
683                 { &hf_tr_src,
684                 { "Source",             "tr.src", FT_ETHER, BASE_NONE, NULL, 0x0,
685                         "Source Hardware Address", HFILL }},
686
687                 { &hf_tr_addr,
688                 { "Source or Destination Address", "tr.addr", FT_ETHER, BASE_NONE, NULL, 0x0,
689                         "Source or Destination Hardware Address", HFILL }},
690
691                 { &hf_tr_sr,
692                 { "Source Routed",      "tr.sr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
693                         "Source Routed", HFILL }},
694
695                 { &hf_tr_rif_bytes,
696                 { "RIF Bytes",          "tr.rif_bytes", FT_UINT8, BASE_DEC, NULL, 0x0,
697                         "Number of bytes in Routing Information Fields, including "
698                         "the two bytes of Routing Control Field", HFILL }},
699
700                 { &hf_tr_broadcast,
701                 { "Broadcast Type",     "tr.broadcast", FT_UINT8, BASE_DEC, VALS(broadcast_vals), 0x0,
702                         "Type of Token-Ring Broadcast", HFILL }},
703
704                 { &hf_tr_max_frame_size,
705                 { "Maximum Frame Size", "tr.max_frame_size", FT_UINT8, BASE_DEC, VALS(max_frame_size_vals),
706                         0x0,
707                         "", HFILL }},
708
709                 { &hf_tr_direction,
710                 { "Direction",          "tr.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
711                         "Direction of RIF", HFILL }},
712
713                 { &hf_tr_rif,
714                 { "Ring-Bridge Pairs",  "tr.rif", FT_STRING, BASE_NONE, NULL, 0x0,
715                         "String representing Ring-Bridge Pairs", HFILL }},
716
717                 { &hf_tr_rif_ring,
718                 { "RIF Ring",           "tr.rif.ring", FT_UINT16, BASE_HEX, NULL, 0x0,
719                         "", HFILL }},
720
721                 { &hf_tr_rif_bridge,
722                 { "RIF Bridge",         "tr.rif.bridge", FT_UINT8, BASE_HEX, NULL, 0x0,
723                         "", HFILL }},
724         };
725         static gint *ett[] = {
726                 &ett_token_ring,
727                 &ett_token_ring_ac,
728                 &ett_token_ring_fc,
729         };
730         module_t *tr_module;
731
732         proto_tr = proto_register_protocol("Token-Ring", "Token-Ring", "tr");
733         proto_register_field_array(proto_tr, hf, array_length(hf));
734         proto_register_subtree_array(ett, array_length(ett));
735
736         /* Register configuration options */
737         tr_module = prefs_register_protocol(proto_tr, NULL);
738         prefs_register_bool_preference(tr_module, "fix_linux_botches",
739             "Attempt to compensate for Linux mangling of the link-layer header",
740             "Whether Linux mangling of the link-layer header should be checked for and worked around",
741             &fix_linux_botches);
742
743         register_dissector("tr", dissect_tr, proto_tr);
744         tr_tap=register_tap("tr");
745 }
746
747 void
748 proto_reg_handoff_tr(void)
749 {
750         dissector_handle_t tr_handle;
751
752         /*
753          * Get handles for the TR MAC and LLC dissectors.
754          */
755         trmac_handle = find_dissector("trmac");
756         llc_handle = find_dissector("llc");
757         data_handle = find_dissector("data");
758
759         tr_handle = find_dissector("tr");
760         dissector_add("wtap_encap", WTAP_ENCAP_TOKEN_RING, tr_handle);
761 }