Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-tr.c
blobe0cd3380e3746c2ab28a17b940b7832c557e6294
1 /* packet-tr.c
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
12 #include "config.h"
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>
19 #include <epan/tfs.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);
28 static int proto_tr;
29 static int hf_tr_dst;
30 static int hf_tr_src;
31 static int hf_tr_addr;
32 static int hf_tr_sr;
33 static int hf_tr_ac;
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;
38 static int hf_tr_fc;
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;
45 static int hf_tr_rif;
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;
57 static int tr_tap;
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" },
72 { 2, "Purge" },
73 { 3, "Claim Token" },
74 { 4, "Beacon" },
75 { 5, "Active Monitor Present" },
76 { 6, "Standby Monitor Present" },
77 { 0, NULL },
80 static const value_string frame_vals[] = {
81 { 0, "MAC" },
82 { 1, "LLC" },
83 { 2, "Reserved" },
84 { 0, NULL },
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" },
96 { 0, NULL }
99 static const value_string max_frame_size_vals[] = {
100 { 0 << 4, "516" },
101 { 1 << 4, "1500" },
102 { 2 << 4, "2052" },
103 { 3 << 4, "4472" },
104 { 4 << 4, "8144" },
105 { 5 << 4, "11407" },
106 { 6 << 4, "17800" },
107 { 7 << 4, "65535" },
108 { 0, NULL }
111 static const value_string direction_vals[] = {
112 { 0, "From originating station (-->)" },
113 { 128, "To originating station (<--)" },
114 { 0, NULL }
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))
126 return "tr.src";
128 if ((filter == CONV_FT_DST_ADDRESS) && (conv->dst_address.type == AT_ETHER))
129 return "tr.dst";
131 if ((filter == CONV_FT_ANY_ADDRESS) && (conv->src_address.type == AT_ETHER))
132 return "tr.addr";
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;
143 hash->flags = flags;
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))
155 return "tr.addr";
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;
166 hash->flags = flags;
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
187 * frame.
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.
201 static
202 int check_for_old_linux_tvb(tvbuff_t *tvb)
204 const uint8_t *data;
205 int x, bytes;
207 /* Restrict our looping to the boundaries of the frame */
208 bytes = tvb_captured_length(tvb);
209 if (bytes > 19) {
210 bytes = 19;
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)
219 return x;
222 return 0;
225 static
226 int check_for_old_linux(const unsigned char * pd)
228 int x;
229 for(x=1;x<=18;x++)
231 if (memcmp(&pd[0],&pd[x],x) == 0)
233 return x;
236 return 0;
240 static void
241 add_ring_bridge_pairs(int rcf_len, tvbuff_t*, proto_tree *tree);
243 static bool
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;
247 int frame_type;
248 int x;
249 uint8_t trn_rif_bytes;
250 uint8_t actual_rif_bytes;
251 uint16_t first2_sr;
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))
258 return false;
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;
268 /* get the data */
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
286 * my RIF fields.
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
291 * "improvement").
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]);
296 if (
297 (first2_sr == 0xaaaa &&
298 pd[offset + 0x10 + trn_rif_bytes] == 0x03) ||
300 first2_sr == 0xe0e0 ||
301 first2_sr == 0xe0aa ) {
303 source_routed = 1;
309 if (source_routed) {
310 actual_rif_bytes = trn_rif_bytes;
312 else {
313 trn_rif_bytes = 0;
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;
328 } else if (
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) {
356 case 1:
357 return call_capture_dissector(llc_cap_handle, pd, offset, len, cpinfo, pseudo_header);
360 return false;
364 static int
365 dissect_tr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
367 proto_tree *tr_tree;
368 proto_item *ti, *hidden_item;
369 uint8_t rcf1, rcf2;
370 tvbuff_t *next_tvb;
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);
388 int x;
390 /* Token-Ring Strings */
391 static const char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" };
394 trh_current++;
395 if(trh_current==4){
396 trh_current=0;
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);
404 else
405 x = 0;
406 if (x != 0) {
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);
411 else {
412 tr_tvb = tvb;
415 /* Get the data */
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
438 * my RIF fields.
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
443 * "improvement").
445 if (frame_type == 1 && !source_routed && trn_rif_bytes > 0) {
446 TRY {
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 ) {
461 source_routed = 1;
465 CATCH(BoundsError) {
466 /* We had no information beyond the TR header. Just assume
467 * this is a normal (non-Linux) TR header. */
470 ENDTRY;
474 if (source_routed) {
475 actual_rif_bytes = trn_rif_bytes;
477 else {
478 trn_rif_bytes = 0;
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
487 TRY {
488 if (frame_type == 1 && ( (source_routed && trn_rif_bytes == 2) ||
489 !source_routed) ) {
490 /* look for SNAP or IPX only */
491 if (
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;
499 else if (
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
511 * Netware frames)
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 */
521 CATCH(BoundsError) {
522 /* We had no information beyond the TR header. Just assume
523 * this is a normal (non-Linux) TR header. */
526 ENDTRY;
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 */
535 if (tree) {
536 static int * const ac[] = {
537 &hf_tr_priority,
538 &hf_tr_frame,
539 &hf_tr_monitor_cnt,
540 &hf_tr_priority_reservation,
541 NULL
543 static int * const fc_flags[] = {
544 &hf_tr_fc_type,
545 &hf_tr_fc_pcf,
546 NULL
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);
573 if (source_routed) {
574 /* RCF Byte 1 */
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);
579 /* RCF Byte 2 */
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
585 ring/bridge pairs */
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);
603 if (fixoffset) {
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) {
612 /* MAC */
613 case 0:
614 call_dissector(trmac_handle, next_tvb, pinfo, tree);
615 break;
616 case 1:
617 call_dissector(llc_handle, next_tvb, pinfo, tree);
618 break;
619 default:
620 /* non-MAC, non-LLC, i.e., "Reserved" */
621 call_data_dissector(next_tvb, pinfo, tree);
622 break;
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. */
631 static void
632 add_ring_bridge_pairs(int rcf_len, tvbuff_t *tvb, proto_tree *tree)
634 proto_item *hidden_item;
635 int j;
636 int segment, brdgnmb, unprocessed_rif;
638 #define RIF_OFFSET 16
639 #define RIF_BYTES_TO_PROCESS 30
641 wmem_strbuf_t *buf;
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 */
651 rcf_len -= 2;
653 for(j = 1; j < rcf_len - 1; j += 2) {
654 if (j==1) {
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);
675 void
676 proto_register_tr(void)
678 static hf_register_info hf[] = {
679 { &hf_tr_ac,
680 { "Access Control", "tr.ac", FT_UINT8, BASE_HEX, NULL, 0x0,
681 NULL, HFILL }},
683 { &hf_tr_priority,
684 { "Priority", "tr.priority", FT_UINT8, BASE_DEC, NULL, 0xe0,
685 NULL, HFILL }},
687 { &hf_tr_frame,
688 { "Frame", "tr.frame", FT_BOOLEAN, 8, TFS(&ac_truth), 0x10,
689 NULL, HFILL }},
691 { &hf_tr_monitor_cnt,
692 { "Monitor Count", "tr.monitor_cnt", FT_UINT8, BASE_DEC, NULL, 0x08,
693 NULL, HFILL }},
695 { &hf_tr_priority_reservation,
696 { "Priority Reservation","tr.priority_reservation", FT_UINT8, BASE_DEC, NULL, 0x07,
697 NULL, HFILL }},
699 { &hf_tr_fc,
700 { "Frame Control", "tr.fc", FT_UINT8, BASE_HEX, NULL, 0x0,
701 NULL, HFILL }},
703 { &hf_tr_fc_type,
704 { "Frame Type", "tr.frame_type", FT_UINT8, BASE_DEC, VALS(frame_vals), 0xc0,
705 NULL, HFILL }},
707 { &hf_tr_fc_pcf,
708 { "Frame PCF", "tr.frame_pcf", FT_UINT8, BASE_DEC, VALS(pcf_vals), 0x0f,
709 NULL, HFILL }},
711 { &hf_tr_dst,
712 { "Destination", "tr.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
713 "Destination Hardware Address", HFILL }},
715 { &hf_tr_src,
716 { "Source", "tr.src", FT_ETHER, BASE_NONE, NULL, 0x0,
717 "Source Hardware Address", HFILL }},
719 { &hf_tr_addr,
720 { "Source or Destination Address", "tr.addr", FT_ETHER, BASE_NONE, NULL, 0x0,
721 "Source or Destination Hardware Address", HFILL }},
723 { &hf_tr_sr,
724 { "Source Routed", "tr.sr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
725 NULL, HFILL }},
727 { &hf_tr_rif_bytes,
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 }},
731 { &hf_tr_broadcast,
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),
737 0x0,
738 NULL, HFILL }},
740 { &hf_tr_direction,
741 { "Direction", "tr.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
742 "Direction of RIF", HFILL }},
744 { &hf_tr_rif,
745 { "Ring-Bridge Pairs", "tr.rif", FT_STRING, BASE_NONE, NULL, 0x0,
746 "String representing Ring-Bridge Pairs", HFILL }},
748 { &hf_tr_rif_ring,
749 { "RIF Ring", "tr.rif.ring", FT_UINT16, BASE_HEX, NULL, 0x0,
750 NULL, HFILL }},
752 { &hf_tr_rif_bridge,
753 { "RIF Bridge", "tr.rif.bridge", FT_UINT8, BASE_HEX, NULL, 0x0,
754 NULL, HFILL }},
756 { &hf_tr_extra_rif,
757 { "Extra RIF bytes beyond spec", "tr.rif.extra", FT_BYTES, BASE_NONE, NULL, 0x0,
758 NULL, HFILL }},
761 static int *ett[] = {
762 &ett_token_ring,
763 &ett_token_ring_ac,
764 &ett_token_ring_fc,
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 }},
771 module_t *tr_module;
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",
785 &fix_linux_botches);
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);
795 void
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
820 * Local variables:
821 * c-basic-offset: 8
822 * tab-width: 8
823 * indent-tabs-mode: t
824 * End:
826 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
827 * :indentSize=8:tabSize=8:noTabs=false: