2 * Routines for Token-Ring packet disassembly
3 * Gilbert Ramirez <gram@alumni.rice.edu>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <epan/capture_dissectors.h>
16 #include <epan/expert.h>
17 #include <epan/exceptions.h>
18 #include <epan/conversation_table.h>
20 #include <wsutil/array.h>
21 #include <wsutil/pint.h>
22 #include "packet-tr.h"
23 #include "packet-sflow.h"
24 #include <epan/prefs.h>
25 void proto_register_tr(void);
26 void proto_reg_handoff_tr(void);
31 static int hf_tr_addr
;
34 static int hf_tr_priority
;
35 static int hf_tr_frame
;
36 static int hf_tr_monitor_cnt
;
37 static int hf_tr_priority_reservation
;
39 static int hf_tr_fc_type
;
40 static int hf_tr_fc_pcf
;
41 static int hf_tr_rif_bytes
;
42 static int hf_tr_broadcast
;
43 static int hf_tr_max_frame_size
;
44 static int hf_tr_direction
;
46 static int hf_tr_rif_ring
;
47 static int hf_tr_rif_bridge
;
48 static int hf_tr_extra_rif
;
50 static int ett_token_ring
;
51 static int ett_token_ring_ac
;
52 static int ett_token_ring_fc
;
54 static expert_field ei_token_empty_rif
;
55 static expert_field ei_token_fake_llc_snap_header
;
60 * Check for and attempt to fix Linux link-layer header mangling.
62 static bool fix_linux_botches
;
64 #define TR_MIN_HEADER_LEN 14
65 #define TR_MAX_HEADER_LEN 32
67 static const true_false_string ac_truth
= { "Frame", "Token" };
69 static const value_string pcf_vals
[] = {
70 { 0, "Normal buffer" },
71 { 1, "Express buffer" },
75 { 5, "Active Monitor Present" },
76 { 6, "Standby Monitor Present" },
80 static const value_string frame_vals
[] = {
87 static const value_string broadcast_vals
[] = {
88 { 0 << 5, "Non-broadcast" },
89 { 1 << 5, "Non-broadcast" },
90 { 2 << 5, "Non-broadcast" },
91 { 3 << 5, "Non-broadcast" },
92 { 4 << 5, "All-routes broadcast" },
93 { 5 << 5, "All-routes broadcast" },
94 { 6 << 5, "Single-route broadcast" },
95 { 7 << 5, "Single-route broadcast" },
99 static const value_string max_frame_size_vals
[] = {
111 static const value_string direction_vals
[] = {
112 { 0, "From originating station (-->)" },
113 { 128, "To originating station (<--)" },
117 static dissector_handle_t tr_handle
;
118 static dissector_handle_t trmac_handle
;
119 static dissector_handle_t llc_handle
;
121 static capture_dissector_handle_t llc_cap_handle
;
123 static const char* tr_conv_get_filter_type(conv_item_t
* conv
, conv_filter_type_e filter
)
125 if ((filter
== CONV_FT_SRC_ADDRESS
) && (conv
->src_address
.type
== AT_ETHER
))
128 if ((filter
== CONV_FT_DST_ADDRESS
) && (conv
->dst_address
.type
== AT_ETHER
))
131 if ((filter
== CONV_FT_ANY_ADDRESS
) && (conv
->src_address
.type
== AT_ETHER
))
134 return CONV_FILTER_INVALID
;
137 static ct_dissector_info_t tr_ct_dissector_info
= {&tr_conv_get_filter_type
};
139 static tap_packet_status
140 tr_conversation_packet(void *pct
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *vip
, tap_flags_t flags
)
142 conv_hash_t
*hash
= (conv_hash_t
*) pct
;
145 const tr_hdr
*trhdr
=(const tr_hdr
*)vip
;
147 add_conversation_table_data(hash
, &trhdr
->src
, &trhdr
->dst
, 0, 0, 1, pinfo
->fd
->pkt_len
, &pinfo
->rel_ts
, &pinfo
->abs_ts
, &tr_ct_dissector_info
, CONVERSATION_NONE
);
149 return TAP_PACKET_REDRAW
;
152 static const char* tr_endpoint_get_filter_type(endpoint_item_t
* endpoint
, conv_filter_type_e filter
)
154 if ((filter
== CONV_FT_ANY_ADDRESS
) && (endpoint
->myaddress
.type
== AT_ETHER
))
157 return CONV_FILTER_INVALID
;
160 static et_dissector_info_t tr_endpoint_dissector_info
= {&tr_endpoint_get_filter_type
};
162 static tap_packet_status
163 tr_endpoint_packet(void *pit
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *vip
, tap_flags_t flags
)
165 conv_hash_t
*hash
= (conv_hash_t
*) pit
;
168 const tr_hdr
*trhdr
=(const tr_hdr
*)vip
;
170 /* Take two "add" passes per packet, adding for each direction, ensures that all
171 packets are counted properly (even if address is sending to itself)
172 XXX - this could probably be done more efficiently inside endpoint_table */
173 add_endpoint_table_data(hash
, &trhdr
->src
, 0, true, 1, pinfo
->fd
->pkt_len
, &tr_endpoint_dissector_info
, ENDPOINT_NONE
);
174 add_endpoint_table_data(hash
, &trhdr
->dst
, 0, false, 1, pinfo
->fd
->pkt_len
, &tr_endpoint_dissector_info
, ENDPOINT_NONE
);
176 return TAP_PACKET_REDRAW
;
180 * DODGY LINUX HACK DODGY LINUX HACK
181 * Linux 2.0.x always passes frames to the Token Ring driver for transmission with
182 * 18 bytes padding for source routing information. Some drivers copy the first
183 * (18 - srlen) bytes up the frame (18 - srlen) bytes thus removing the padding.
184 * Other drivers just make a copy of the entire frame and then hack about with it
185 * so the frame the sniffer gets is fine (just has extra sr routing).
186 * In the first instance (driver hacking frame in situ) the sniffer gets a garbled
188 * This function tries to detect this and returns the offset of where
189 * the frame really starts.
190 * This only detects frames that we have sent ourselves so if we are packet sniffing
191 * on the machine we are watching this is useful.
192 * Compare offset 0 with offset x+1 for a length of x bytes for all value of x = 1 to 18
193 * if match then Linux driver has done in situ source route compression of the crappy
194 * Linux 2.0.x frame so the beginning of the real frame is x bytes in.
195 * (And this real frame x bytes in looks like a proper TR frame that goes on the wire
196 * with none of the Linux idiosyncrasies).
198 * XXX - there should perhaps be a preference setting to turn this off,
199 * as sometimes it can, and does, get a false hit.
202 int check_for_old_linux_tvb(tvbuff_t
*tvb
)
207 /* Restrict our looping to the boundaries of the frame */
208 bytes
= tvb_captured_length(tvb
);
213 data
= tvb_get_ptr(tvb
, 0, bytes
);
215 for(x
= 1; x
<= bytes
-1 ;x
++)
217 if (memcmp(&data
[0], &data
[x
], x
) == 0)
226 int check_for_old_linux(const unsigned char * pd
)
231 if (memcmp(&pd
[0],&pd
[x
],x
) == 0)
241 add_ring_bridge_pairs(int rcf_len
, tvbuff_t
*, proto_tree
*tree
);
244 capture_tr(const unsigned char *pd
, int offset
, int len
, capture_packet_info_t
*cpinfo
, const union wtap_pseudo_header
*pseudo_header _U_
) {
246 int source_routed
= 0;
249 uint8_t trn_rif_bytes
;
250 uint8_t actual_rif_bytes
;
253 /* The trn_hdr struct, as separate variables */
254 uint8_t trn_fc
; /* field control field */
255 const uint8_t *trn_shost
; /* source host */
257 if (!BYTES_ARE_IN_FRAME(offset
, len
, TR_MIN_HEADER_LEN
))
260 if ((x
= check_for_old_linux(pd
)))
262 /* Actually packet starts x bytes into what we have got but with all
263 source routing compressed
265 /* pd = &pd[x]; */ offset
+=x
;
269 trn_fc
= pd
[offset
+ 1];
270 trn_shost
= &pd
[offset
+ 8];
272 frame_type
= (trn_fc
& 192) >> 6;
274 /* if the high bit on the first byte of src hwaddr is 1, then
275 this packet is source-routed */
276 source_routed
= trn_shost
[0] & 128;
278 trn_rif_bytes
= pd
[offset
+ 14] & 31;
280 if (fix_linux_botches
) {
281 /* the Linux 2.0 TR code strips source-route bits in
282 * order to test for SR. This can be removed from most
283 * packets with oltr, but not all. So, I try to figure out
284 * which packets should have been SR here. I'll check to
285 * see if there's a SNAP or IPX field right after
288 * The Linux 2.4.18 code, at least appears to do the
289 * same thing, from a capture I got from somebody running
290 * 2.4.18 (RH 7.1, so perhaps this is a Red Hat
293 if (!source_routed
&& trn_rif_bytes
> 0) {
294 if (pd
[offset
+ 0x0e] != pd
[offset
+ 0x0f]) {
295 first2_sr
= pntoh16(&pd
[offset
+ 0xe0 + trn_rif_bytes
]);
297 (first2_sr
== 0xaaaa &&
298 pd
[offset
+ 0x10 + trn_rif_bytes
] == 0x03) ||
300 first2_sr
== 0xe0e0 ||
301 first2_sr
== 0xe0aa ) {
310 actual_rif_bytes
= trn_rif_bytes
;
314 actual_rif_bytes
= 0;
317 if (fix_linux_botches
) {
318 /* this is a silly hack for Linux 2.0.x. Read the comment
319 * below about LLC headers. If we're sniffing our own NIC,
320 * we get a full RIF, sometimes with garbage
322 if ((source_routed
&& trn_rif_bytes
== 2 && frame_type
== 1) ||
323 (!source_routed
&& frame_type
== 1)) {
324 /* look for SNAP or IPX only */
325 if ( (pd
[offset
+ 0x20] == 0xaa && pd
[offset
+ 0x21] == 0xaa && pd
[offset
+ 0x22] == 03) ||
326 (pd
[offset
+ 0x20] == 0xe0 && pd
[offset
+ 0x21] == 0xe0) ) {
327 actual_rif_bytes
= 18;
329 pd
[offset
+ 0x23] == 0 &&
330 pd
[offset
+ 0x24] == 0 &&
331 pd
[offset
+ 0x25] == 0 &&
332 pd
[offset
+ 0x26] == 0x00 &&
333 pd
[offset
+ 0x27] == 0x11) {
335 actual_rif_bytes
= 18;
337 /* Linux 2.0.x also requires drivers pass up
338 * a fake SNAP and LLC header before the
339 * real LLC hdr for all Token Ring frames
340 * that arrive with DSAP and SSAP != 0xAA
341 * (i.e. for non SNAP frames e.g. for Netware
342 * frames) the fake SNAP header has the
343 * ETH_P_TR_802_2 ether type (0x0011) and the protocol id
344 * bytes as zero frame looks like :-
345 * TR Header | Fake LLC | Fake SNAP | Wire LLC | Rest of data
347 offset
+= 8; /* Skip fake LLC and SNAP */
352 offset
+= actual_rif_bytes
+ TR_MIN_HEADER_LEN
;
354 /* The package is either MAC (0) or LLC (1)*/
355 switch (frame_type
) {
357 return call_capture_dissector(llc_cap_handle
, pd
, offset
, len
, cpinfo
, pseudo_header
);
365 dissect_tr(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
368 proto_item
*ti
, *hidden_item
;
372 volatile int frame_type
;
373 volatile int fixoffset
= 0;
374 volatile int source_routed
= 0;
375 volatile uint8_t trn_rif_bytes
;
376 volatile uint8_t actual_rif_bytes
;
377 volatile uint8_t c1_nonsr
;
378 volatile uint8_t c2_nonsr
;
379 volatile uint16_t first2_sr
;
380 tvbuff_t
*volatile tr_tvb
;
382 static tr_hdr trh_arr
[4];
383 static int trh_current
=0;
384 tr_hdr
*volatile trh
;
386 /* non-source-routed version of source addr */
387 uint8_t *trn_shost_nonsr
= (uint8_t*)wmem_alloc(pinfo
->pool
, 6);
390 /* Token-Ring Strings */
391 static const char *fc
[] = { "MAC", "LLC", "Reserved", "Unknown" };
398 trh
=&trh_arr
[trh_current
];
400 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TR");
402 if (fix_linux_botches
)
403 x
= check_for_old_linux_tvb((tvbuff_t
*) tvb
);
407 /* Actually packet starts x bytes into what we have got but with all
408 source routing compressed. See comment above */
409 tr_tvb
= tvb_new_subset_remaining((tvbuff_t
*) tvb
, x
);
416 trh
->fc
= tvb_get_uint8(tr_tvb
, 1);
417 set_address_tvb(&trh
->src
, AT_ETHER
, 6, tr_tvb
, 8);
418 set_address_tvb(&trh
->dst
, AT_ETHER
, 6, tr_tvb
, 2);
420 /* if the high bit on the first byte of src hwaddr is 1, then
421 this packet is source-routed */
422 memcpy(trn_shost_nonsr
, trh
->src
.data
, 6);
423 source_routed
= trn_shost_nonsr
[0] & 128;
424 trn_shost_nonsr
[0] &= 127;
426 frame_type
= (trh
->fc
& 192) >> 6;
428 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Token-Ring %s", fc
[frame_type
]);
430 trn_rif_bytes
= tvb_get_uint8(tr_tvb
, 14) & 31;
432 if (fix_linux_botches
) {
433 /* the Linux 2.0 TR code strips source-route bits in
434 * order to test for SR. This can be removed from most
435 * packets with oltr, but not all. So, I try to figure out
436 * which packets should have been SR here. I'll check to
437 * see if there's a SNAP or IPX field right after
440 * The Linux 2.4.18 code, at least appears to do the
441 * same thing, from a capture I got from somebody running
442 * 2.4.18 (RH 7.1, so perhaps this is a Red Hat
445 if (frame_type
== 1 && !source_routed
&& trn_rif_bytes
> 0) {
448 c1_nonsr
= tvb_get_uint8(tr_tvb
, 14);
449 c2_nonsr
= tvb_get_uint8(tr_tvb
, 15);
451 if (c1_nonsr
!= c2_nonsr
) {
453 first2_sr
= tvb_get_ntohs(tr_tvb
, trn_rif_bytes
+ 0x0e);
455 if ( ( first2_sr
== 0xaaaa &&
456 tvb_get_uint8(tr_tvb
, trn_rif_bytes
+ 0x10) == 0x03) ||
458 first2_sr
== 0xe0e0 ||
459 first2_sr
== 0xe0aa ) {
466 /* We had no information beyond the TR header. Just assume
467 * this is a normal (non-Linux) TR header. */
475 actual_rif_bytes
= trn_rif_bytes
;
479 actual_rif_bytes
= 0;
482 if (fix_linux_botches
) {
483 /* this is a silly hack for Linux 2.0.x. Read the comment
484 * below about LLC headers. If we're sniffing our own NIC,
485 * we get a full RIF, sometimes with garbage
488 if (frame_type
== 1 && ( (source_routed
&& trn_rif_bytes
== 2) ||
490 /* look for SNAP or IPX only */
492 (tvb_get_ntohs(tr_tvb
, 0x20) == 0xaaaa &&
493 tvb_get_uint8(tr_tvb
, 0x22) == 0x03)
495 tvb_get_ntohs(tr_tvb
, 0x20) == 0xe0e0 ) {
497 actual_rif_bytes
= 18;
500 tvb_get_ntohl(tr_tvb
, 0x23) == 0 &&
501 tvb_get_uint8(tr_tvb
, 0x27) == 0x11) {
503 actual_rif_bytes
= 18;
505 /* Linux 2.0.x also requires drivers
506 * pass up a fake SNAP and LLC header
507 * before the real LLC hdr for all
508 * Token Ring frames that arrive with
509 * DSAP and SSAP != 0xAA
510 * (i.e. for non SNAP frames e.g. for
512 * the fake SNAP header has the
513 * ETH_P_TR_802_2 ether type (0x0011)
514 * and the protocol id bytes as zero frame looks like :-
515 * TR Header | Fake LLC | Fake SNAP | Wire LLC | Rest of data
517 fixoffset
+= 8; /* Skip fake LLC and SNAP */
522 /* We had no information beyond the TR header. Just assume
523 * this is a normal (non-Linux) TR header. */
529 set_address(&pinfo
->dl_src
, AT_ETHER
, 6, trn_shost_nonsr
);
530 copy_address_shallow(&pinfo
->src
, &pinfo
->dl_src
);
531 set_address(&pinfo
->dl_dst
, AT_ETHER
, 6, trh
->dst
.data
);
532 copy_address_shallow(&pinfo
->dst
, &pinfo
->dl_dst
);
534 /* protocol analysis tree */
536 static int * const ac
[] = {
540 &hf_tr_priority_reservation
,
543 static int * const fc_flags
[] = {
549 /* Create Token-Ring Tree */
550 ti
= proto_tree_add_item(tree
, proto_tr
, tr_tvb
, 0, TR_MIN_HEADER_LEN
+ actual_rif_bytes
, ENC_NA
);
551 tr_tree
= proto_item_add_subtree(ti
, ett_token_ring
);
553 /* Create the Access Control bitfield tree */
554 trh
->ac
= tvb_get_uint8(tr_tvb
, 0);
555 proto_tree_add_bitmask(tr_tree
, tr_tvb
, 0, hf_tr_ac
, ett_token_ring_ac
, ac
, ENC_NA
);
557 /* Create the Frame Control bitfield tree */
558 proto_tree_add_bitmask(tr_tree
, tr_tvb
, 1, hf_tr_fc
, ett_token_ring_fc
, fc_flags
, ENC_NA
);
560 proto_tree_add_ether(tr_tree
, hf_tr_dst
, tr_tvb
, 2, 6, (const uint8_t *)trh
->dst
.data
);
561 proto_tree_add_ether(tr_tree
, hf_tr_src
, tr_tvb
, 8, 6, (const uint8_t *)trh
->src
.data
);
562 hidden_item
= proto_tree_add_ether(tr_tree
, hf_tr_addr
, tr_tvb
, 2, 6, (const uint8_t *)trh
->dst
.data
);
563 proto_item_set_hidden(hidden_item
);
564 hidden_item
= proto_tree_add_ether(tr_tree
, hf_tr_addr
, tr_tvb
, 8, 6, (const uint8_t *)trh
->src
.data
);
565 proto_item_set_hidden(hidden_item
);
567 proto_tree_add_boolean(tr_tree
, hf_tr_sr
, tr_tvb
, 8, 1, source_routed
);
569 /* non-source-routed version of src addr */
570 hidden_item
= proto_tree_add_ether(tr_tree
, hf_tr_src
, tr_tvb
, 8, 6, trn_shost_nonsr
);
571 proto_item_set_hidden(hidden_item
);
575 rcf1
= tvb_get_uint8(tr_tvb
, 14);
576 proto_tree_add_uint(tr_tree
, hf_tr_rif_bytes
, tr_tvb
, 14, 1, trn_rif_bytes
);
577 proto_tree_add_uint(tr_tree
, hf_tr_broadcast
, tr_tvb
, 14, 1, rcf1
& 224);
580 rcf2
= tvb_get_uint8(tr_tvb
, 15);
581 proto_tree_add_uint(tr_tree
, hf_tr_max_frame_size
, tr_tvb
, 15, 1, rcf2
& 112);
582 proto_tree_add_uint(tr_tree
, hf_tr_direction
, tr_tvb
, 15, 1, rcf2
& 128);
584 /* if we have more than 2 bytes of RIF, then we have
586 if (trn_rif_bytes
> 2) {
587 add_ring_bridge_pairs(trn_rif_bytes
, tr_tvb
, tr_tree
);
591 /* Linux 2.0.x has a problem in that the 802.5 code creates
592 an emtpy full (18-byte) RIF area. It's up to the tr driver to
593 either fill it in or remove it before sending the bytes out
594 to the wire. If you run tcpdump on a Linux 2.0.x machine running
595 token-ring, tcpdump will capture these 18 filler bytes. They
596 are filled with garbage. The best way to detect this problem is
597 to know the src hwaddr of the machine from which you were running
598 tcpdump. W/o that, however, I'm guessing that DSAP == SSAP if the
599 frame type is LLC. It's very much a hack. */
600 if (actual_rif_bytes
> trn_rif_bytes
) {
601 proto_tree_add_expert(tr_tree
, pinfo
, &ei_token_empty_rif
, tr_tvb
, TR_MIN_HEADER_LEN
+ trn_rif_bytes
, actual_rif_bytes
- trn_rif_bytes
);
604 proto_tree_add_expert(tr_tree
, pinfo
, &ei_token_fake_llc_snap_header
, tr_tvb
, TR_MIN_HEADER_LEN
+ 18, 8);
608 next_tvb
= tvb_new_subset_remaining(tr_tvb
, TR_MIN_HEADER_LEN
+ actual_rif_bytes
+ fixoffset
);
610 /* The package is either MAC or LLC */
611 switch (frame_type
) {
614 call_dissector(trmac_handle
, next_tvb
, pinfo
, tree
);
617 call_dissector(llc_handle
, next_tvb
, pinfo
, tree
);
620 /* non-MAC, non-LLC, i.e., "Reserved" */
621 call_data_dissector(next_tvb
, pinfo
, tree
);
625 tap_queue_packet(tr_tap
, pinfo
, trh
);
626 return tvb_captured_length(tvb
);
629 /* this routine is taken from the Linux net/802/tr.c code, which shows
630 ring-bridge pairs in the /proc/net/tr_rif virtual file. */
632 add_ring_bridge_pairs(int rcf_len
, tvbuff_t
*tvb
, proto_tree
*tree
)
634 proto_item
*hidden_item
;
636 int segment
, brdgnmb
, unprocessed_rif
;
638 #define RIF_OFFSET 16
639 #define RIF_BYTES_TO_PROCESS 30
642 #define MAX_BUF_LEN 3 + (RIF_BYTES_TO_PROCESS / 2) * 6 + 1
644 buf
= wmem_strbuf_new_sized(wmem_packet_scope(), MAX_BUF_LEN
);
645 /* Only process so many bytes of RIF, as per TR spec, and not overflow
646 * static buffer above */
647 unprocessed_rif
= rcf_len
- RIF_BYTES_TO_PROCESS
;
648 rcf_len
= MIN(rcf_len
, RIF_BYTES_TO_PROCESS
);
650 /* Ignore the 2 RCF bytes, since they don't make up the ring/bride pairs */
653 for(j
= 1; j
< rcf_len
- 1; j
+= 2) {
655 segment
= tvb_get_ntohs(tvb
, RIF_OFFSET
) >> 4;
656 wmem_strbuf_append_printf(buf
, "%03X", segment
);
657 hidden_item
= proto_tree_add_uint(tree
, hf_tr_rif_ring
, tvb
, TR_MIN_HEADER_LEN
+ 2, 2, segment
);
658 proto_item_set_hidden(hidden_item
);
660 segment
= tvb_get_ntohs(tvb
, RIF_OFFSET
+ 1 + j
) >> 4;
661 brdgnmb
= tvb_get_uint8(tvb
, RIF_OFFSET
+ j
) & 0x0f;
662 wmem_strbuf_append_printf(buf
, "-%01X-%03X", brdgnmb
, segment
);
663 hidden_item
= proto_tree_add_uint(tree
, hf_tr_rif_ring
, tvb
, TR_MIN_HEADER_LEN
+ 3 + j
, 2, segment
);
664 proto_item_set_hidden(hidden_item
);
665 hidden_item
= proto_tree_add_uint(tree
, hf_tr_rif_bridge
, tvb
, TR_MIN_HEADER_LEN
+ 2 + j
, 1, brdgnmb
);
666 proto_item_set_hidden(hidden_item
);
668 proto_tree_add_string(tree
, hf_tr_rif
, tvb
, TR_MIN_HEADER_LEN
+ 2, rcf_len
, wmem_strbuf_get_str(buf
));
670 if (unprocessed_rif
> 0) {
671 proto_tree_add_item(tree
, hf_tr_extra_rif
, tvb
, TR_MIN_HEADER_LEN
+ RIF_BYTES_TO_PROCESS
, unprocessed_rif
, ENC_NA
);
676 proto_register_tr(void)
678 static hf_register_info hf
[] = {
680 { "Access Control", "tr.ac", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
684 { "Priority", "tr.priority", FT_UINT8
, BASE_DEC
, NULL
, 0xe0,
688 { "Frame", "tr.frame", FT_BOOLEAN
, 8, TFS(&ac_truth
), 0x10,
691 { &hf_tr_monitor_cnt
,
692 { "Monitor Count", "tr.monitor_cnt", FT_UINT8
, BASE_DEC
, NULL
, 0x08,
695 { &hf_tr_priority_reservation
,
696 { "Priority Reservation","tr.priority_reservation", FT_UINT8
, BASE_DEC
, NULL
, 0x07,
700 { "Frame Control", "tr.fc", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
704 { "Frame Type", "tr.frame_type", FT_UINT8
, BASE_DEC
, VALS(frame_vals
), 0xc0,
708 { "Frame PCF", "tr.frame_pcf", FT_UINT8
, BASE_DEC
, VALS(pcf_vals
), 0x0f,
712 { "Destination", "tr.dst", FT_ETHER
, BASE_NONE
, NULL
, 0x0,
713 "Destination Hardware Address", HFILL
}},
716 { "Source", "tr.src", FT_ETHER
, BASE_NONE
, NULL
, 0x0,
717 "Source Hardware Address", HFILL
}},
720 { "Source or Destination Address", "tr.addr", FT_ETHER
, BASE_NONE
, NULL
, 0x0,
721 "Source or Destination Hardware Address", HFILL
}},
724 { "Source Routed", "tr.sr", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
728 { "RIF Bytes", "tr.rif_bytes", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
729 "Number of bytes in Routing Information Fields, including the two bytes of Routing Control Field", HFILL
}},
732 { "Broadcast Type", "tr.broadcast", FT_UINT8
, BASE_DEC
, VALS(broadcast_vals
), 0x0,
733 "Type of Token-Ring Broadcast", HFILL
}},
735 { &hf_tr_max_frame_size
,
736 { "Maximum Frame Size", "tr.max_frame_size", FT_UINT8
, BASE_DEC
, VALS(max_frame_size_vals
),
741 { "Direction", "tr.direction", FT_UINT8
, BASE_DEC
, VALS(direction_vals
), 0x0,
742 "Direction of RIF", HFILL
}},
745 { "Ring-Bridge Pairs", "tr.rif", FT_STRING
, BASE_NONE
, NULL
, 0x0,
746 "String representing Ring-Bridge Pairs", HFILL
}},
749 { "RIF Ring", "tr.rif.ring", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
753 { "RIF Bridge", "tr.rif.bridge", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
757 { "Extra RIF bytes beyond spec", "tr.rif.extra", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
761 static int *ett
[] = {
766 static ei_register_info ei
[] = {
767 { &ei_token_empty_rif
, { "tr.empty_rif", PI_PROTOCOL
, PI_NOTE
, "Empty RIF from Linux 2.0.x driver. The sniffing NIC is also running a protocol stack.", EXPFILL
}},
768 { &ei_token_fake_llc_snap_header
, { "tr.fake_llc_snap_header", PI_PROTOCOL
, PI_NOTE
, "Linux 2.0.x fake LLC and SNAP header", EXPFILL
}},
772 expert_module_t
* expert_tr
;
774 proto_tr
= proto_register_protocol("Token-Ring", "Token-Ring", "tr");
775 proto_register_field_array(proto_tr
, hf
, array_length(hf
));
776 proto_register_subtree_array(ett
, array_length(ett
));
777 expert_tr
= expert_register_protocol(proto_tr
);
778 expert_register_field_array(expert_tr
, ei
, array_length(ei
));
780 /* Register configuration options */
781 tr_module
= prefs_register_protocol(proto_tr
, NULL
);
782 prefs_register_bool_preference(tr_module
, "fix_linux_botches",
783 "Attempt to compensate for Linux mangling of the link-layer header",
784 "Whether Linux mangling of the link-layer header should be checked for and worked around",
787 tr_handle
= register_dissector("tr", dissect_tr
, proto_tr
);
788 tr_tap
=register_tap("tr");
790 register_conversation_table(proto_tr
, true, tr_conversation_packet
, tr_endpoint_packet
);
792 register_capture_dissector("tr", capture_tr
, proto_tr
);
796 proto_reg_handoff_tr(void)
798 capture_dissector_handle_t tr_cap_handle
;
801 * Get handles for the TR MAC and LLC dissectors.
803 trmac_handle
= find_dissector_add_dependency("trmac", proto_tr
);
804 llc_handle
= find_dissector_add_dependency("llc", proto_tr
);
806 dissector_add_uint("wtap_encap", WTAP_ENCAP_TOKEN_RING
, tr_handle
);
807 dissector_add_uint("sflow_245.header_protocol", SFLOW_245_HEADER_TOKENRING
, tr_handle
);
809 tr_cap_handle
= find_capture_dissector("tr");
810 capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_TOKEN_RING
, tr_cap_handle
);
811 capture_dissector_add_uint("atm_lane", TRAF_ST_LANE_802_5
, tr_cap_handle
);
812 capture_dissector_add_uint("atm_lane", TRAF_ST_LANE_802_5_MC
, tr_cap_handle
);
814 llc_cap_handle
= find_capture_dissector("llc");
818 * Editor modelines - https://www.wireshark.org/tools/modelines.html
823 * indent-tabs-mode: t
826 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
827 * :indentSize=8:tabSize=8:noTabs=false: