Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-trmac.c
Line
Count
Source
1
/* packet-trmac.c
2
 * Routines for Token-Ring Media Access Control
3
 * Gilbert Ramirez <gram@alumni.rice.edu>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/packet.h>
15
#include <epan/to_str.h>
16
#include <epan/expert.h>
17
#include <epan/unit_strings.h>
18
19
#include <wsutil/array.h>
20
void proto_register_trmac(void);
21
22
static int proto_trmac;
23
static int hf_trmac_mv;
24
static int hf_trmac_length;
25
static int hf_trmac_srcclass;
26
static int hf_trmac_dstclass;
27
static int hf_trmac_sv_len;
28
static int hf_trmac_sv_id;
29
static int hf_trmac_errors_iso;
30
static int hf_trmac_errors_line;
31
static int hf_trmac_errors_internal;
32
static int hf_trmac_errors_burst;
33
static int hf_trmac_errors_ac;
34
static int hf_trmac_errors_abort;
35
static int hf_trmac_errors_noniso;
36
static int hf_trmac_errors_lost;
37
static int hf_trmac_errors_congestion;
38
static int hf_trmac_errors_fc;
39
static int hf_trmac_errors_freq;
40
static int hf_trmac_errors_token;
41
static int hf_trmac_naun;
42
static int hf_trmac_beacon_type;
43
static int hf_trmac_assign_physical_drop_number;
44
static int hf_trmac_error_code;
45
static int hf_trmac_group_address32;
46
static int hf_trmac_transmit_status_code;
47
static int hf_trmac_station_identifier;
48
static int hf_trmac_sa_of_last_amp_or_smp_frame;
49
static int hf_trmac_error_report_timer_value;
50
static int hf_trmac_individual_address_count;
51
static int hf_trmac_correlator;
52
static int hf_trmac_group_address_ether;
53
static int hf_trmac_authorized_access_priority;
54
static int hf_trmac_physical_drop_number;
55
static int hf_trmac_authorized_function_classes;
56
static int hf_trmac_local_ring_number;
57
static int hf_trmac_functional_addresses;
58
/* Generated from convert_proto_tree_add_text.pl */
59
static int hf_trmac_unknown_subvector;
60
static int hf_trmac_response_code48;
61
static int hf_trmac_product_instance_id;
62
static int hf_trmac_ring_station_version_number;
63
static int hf_trmac_wrap_data;
64
static int hf_trmac_ring_station_status;
65
static int hf_trmac_frame_forward;
66
static int hf_trmac_response_code32;
67
68
static int ett_tr_mac;
69
static int ett_tr_sv;
70
static int ett_tr_ierr_cnt;
71
static int ett_tr_nerr_cnt;
72
73
static expert_field ei_trmac_sv_len;
74
75
/* Major Vector */
76
static const value_string major_vector_vs[] = {
77
  { 0x00, "Response" },
78
  { 0x02, "Beacon" },
79
  { 0x03, "Claim Token" },
80
  { 0x04, "Ring Purge" },
81
  { 0x05, "Active Monitor Present" },
82
  { 0x06, "Standby Monitor Present" },
83
  { 0x07, "Duplicate Address Test" },
84
  { 0x09, "Transmit Forward" },
85
  { 0x0B, "Remove Ring Station" },
86
  { 0x0C, "Change Parameters" },
87
  { 0x0D, "Initialize Ring Station" },
88
  { 0x0E, "Request Ring Station Address" },
89
  { 0x0F, "Request Ring Station State" },
90
  { 0x10, "Request Ring Station Attachments" },
91
  { 0x20, "Request Initialization" },
92
  { 0x22, "Report Ring Station Address" },
93
  { 0x23, "Report Ring Station State" },
94
  { 0x24, "Report Ring Station Attachments" },
95
  { 0x25, "Report New Active Monitor" },
96
  { 0x26, "Report NAUN Change" },
97
  { 0x27, "Report Poll Error" },
98
  { 0x28, "Report Monitor Errors" },
99
  { 0x29, "Report Error" },
100
  { 0x2A, "Report Transmit Forward" },
101
  { 0x00, NULL }
102
};
103
static value_string_ext major_vector_vs_ext = VALUE_STRING_EXT_INIT(major_vector_vs);
104
105
/* Src. and Dest. Classes */
106
static const value_string classes_vs[] = {
107
  { 0x00, "Ring Station" },
108
  { 0x01, "LLC Manager" },
109
  { 0x04, "Configuration Report Server" },
110
  { 0x05, "Ring Parameter Server" },
111
  { 0x06, "Ring Error Monitor" },
112
  { 0x00, NULL }
113
};
114
115
static const value_string subvector_vs[] = {
116
  { 0x01, "Beacon Type" },
117
  { 0x02, "Upstream Neighbor's Address" },
118
  { 0x03, "Local Ring Number" },
119
  { 0x04, "Assign Physical Drop Number" },
120
  { 0x05, "Error Report Timer Value" },
121
  { 0x06, "Authorized Function Classes" },
122
  { 0x07, "Authorized Access Priority" },
123
  { 0x09, "Correlator" },
124
  { 0x0A, "SA of Last AMP or SMP Frame" },
125
  { 0x0B, "Physical Drop Number" },
126
  { 0x20, "Response Code" },
127
  { 0x21, "Individual Address Count" },
128
  { 0x22, "Product Instance ID" },
129
  { 0x23, "Ring Station Version Number" },
130
  { 0x26, "Wrap Data" },
131
  { 0x27, "Frame Forward" },
132
  { 0x28, "Station Identifier" },
133
  { 0x29, "Ring Station Status" },
134
  { 0x2A, "Transmit Forward Status Code" },
135
  { 0x2B, "Group Addresses" },
136
  { 0x2C, "Functional Addresses" },
137
  { 0x2D, "Isolating Error Counts" },
138
  { 0x2E, "Non-Isolating Error Counts" },
139
  { 0x2F, "Function Request ID" },
140
  { 0x30, "Error Code" },
141
  { 0x00, NULL }
142
};
143
static value_string_ext subvector_vs_ext = VALUE_STRING_EXT_INIT(subvector_vs);
144
145
static const value_string beacon_vs[] = {
146
  { 0x00, "Recovery mode set" },
147
  { 0x01, "Signal loss error" },
148
  { 0x02, "Streaming signal not Claim Token MAC frame" },
149
  { 0x03, "Streaming signal, Claim Token MAC frame" },
150
  { 0x00, NULL }
151
};
152
153
/* Sub-vectors */
154
static int
155
sv_text(tvbuff_t *tvb, int svoff, packet_info *pinfo, proto_tree *tree)
156
996
{
157
996
  unsigned  sv_length, sv_id;
158
996
  uint16_t  beacon_type, ring;
159
996
  uint32_t  error_report_timer_value;
160
161
996
  proto_tree  *sv_tree, *sv_subtree;
162
996
  proto_item  *sv_item, *len_item, *ti;
163
164
996
  unsigned char   errors[6];  /* isolating or non-isolating */
165
166
996
  sv_tree = proto_tree_add_subtree(tree, tvb, svoff+0, 1, ett_tr_sv, &sv_item, "Subvector");
167
168
996
  sv_length = tvb_get_uint8(tvb, svoff+0);
169
996
  len_item = proto_tree_add_item(sv_tree, hf_trmac_sv_len, tvb, svoff+0, 1, ENC_BIG_ENDIAN);
170
171
  /* Check the SV length; it must be at least 2, to include
172
     the subvector length and indicator. */
173
996
  if (sv_length < 2) {
174
23
    expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
175
23
      "Invalid subvector: length < 2");
176
23
    return 0; /* tells our caller to give up */
177
23
  }
178
179
973
  sv_id = tvb_get_uint8(tvb, svoff+1);
180
973
  proto_tree_add_item(sv_tree, hf_trmac_sv_id, tvb, svoff+1, 1, ENC_BIG_ENDIAN);
181
973
  proto_item_append_text(sv_item, " (%s)", val_to_str_ext(pinfo->pool, sv_id, &subvector_vs_ext, "Unknown subvector ID 0x%02X"));
182
183
973
  switch(sv_id) {
184
21
    case 0x01: /* Beacon Type */
185
21
      if (sv_length != 4) {
186
20
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
187
20
            "Subvector length is != 4");
188
20
        break;
189
20
      }
190
1
      beacon_type = tvb_get_ntohs(tvb, svoff+2);
191
1
      proto_tree_add_item(sv_tree, hf_trmac_beacon_type, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
192
1
      proto_item_append_text(sv_item,
193
1
          ": %s", val_to_str(pinfo->pool, beacon_type, beacon_vs, "Illegal value: %d"));
194
1
      break;
195
196
140
    case 0x02: /* Upstream Neighbor's Address */
197
140
      if (sv_length != 8) {
198
139
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
199
139
            "Subvector length is != 8");
200
139
        break;
201
139
      }
202
1
      proto_tree_add_item(sv_tree, hf_trmac_naun, tvb, svoff+2, sv_length-2, ENC_NA);
203
1
      proto_item_append_text(sv_item, ": %s",
204
1
          tvb_ether_to_str(pinfo->pool, tvb, svoff+2));
205
1
      break;
206
207
108
    case 0x03: /* Local Ring Number */
208
108
      if (sv_length != 4) {
209
107
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
210
107
            "Subvector length is != 4");
211
107
        break;
212
107
      }
213
1
      ring = tvb_get_ntohs(tvb, svoff+2);
214
1
      proto_tree_add_item(sv_tree, hf_trmac_local_ring_number, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
215
1
      proto_item_append_text(sv_item,
216
1
        ": 0x%04X (%d)", ring, ring);
217
1
      break;
218
219
43
    case 0x04: /* Assign Physical Drop Number */
220
43
      if (sv_length != 6) {
221
43
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
222
43
            "Subvector length is != 6");
223
43
        break;
224
43
      }
225
0
      proto_tree_add_item(sv_tree, hf_trmac_assign_physical_drop_number, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
226
0
      proto_item_append_text(sv_item,
227
0
        ": 0x%08X", tvb_get_ntohl(tvb, svoff+2) );
228
0
      break;
229
230
16
    case 0x05: /* Error Report Timer Value */
231
16
      if (sv_length != 4) {
232
16
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
233
16
            "Subvector length is != 4");
234
16
        break;
235
16
      }
236
237
0
      error_report_timer_value = 10 * tvb_get_ntohs(tvb, svoff+2);
238
0
      proto_tree_add_uint(sv_tree, hf_trmac_error_report_timer_value, tvb, svoff+2, sv_length-2, error_report_timer_value);
239
0
      proto_item_append_text(sv_item,
240
0
        ": %u ms", error_report_timer_value );
241
0
      break;
242
243
54
    case 0x06: /* Authorized Function Classes */
244
54
      if (sv_length != 4) {
245
50
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
246
50
            "Subvector length is != 4");
247
50
        break;
248
50
      }
249
4
      proto_tree_add_item(sv_tree, hf_trmac_authorized_function_classes, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
250
4
      proto_item_append_text(sv_item,
251
4
        ": %04X",  tvb_get_ntohs(tvb, svoff+2) );
252
4
      break;
253
254
38
    case 0x07: /* Authorized Access Priority */
255
38
      if (sv_length != 4) {
256
38
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
257
38
            "Subvector length is != 4");
258
38
        break;
259
38
      }
260
0
      proto_tree_add_item(sv_tree, hf_trmac_authorized_access_priority, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
261
0
      proto_item_append_text(sv_item,
262
0
        ": %04X",  tvb_get_ntohs(tvb, svoff+2) );
263
0
      break;
264
265
22
    case 0x09: /* Correlator */
266
22
      if (sv_length != 4) {
267
22
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
268
22
            "Subvector length is != 4");
269
22
        break;
270
22
      }
271
0
      proto_tree_add_item(sv_tree, hf_trmac_correlator, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
272
0
      proto_item_append_text(sv_item,
273
0
        ": %04X",  tvb_get_ntohs(tvb, svoff+2) );
274
0
      break;
275
276
63
    case 0x0A: /* SA of Last AMP or SMP Frame */
277
63
      if (sv_length != 8) {
278
62
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
279
62
            "Subvector length is != 8");
280
62
        break;
281
62
      }
282
1
      proto_tree_add_item(sv_tree, hf_trmac_sa_of_last_amp_or_smp_frame, tvb, svoff+2, sv_length-2, ENC_NA);
283
1
      proto_item_append_text(sv_item,
284
1
        ": %s",
285
1
        tvb_ether_to_str(pinfo->pool, tvb, svoff+2));
286
1
      break;
287
288
25
    case 0x0B: /* Physical Drop Number */
289
25
      if (sv_length != 6) {
290
25
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
291
25
            "Subvector length is != 6");
292
25
        break;
293
25
      }
294
0
      proto_tree_add_item(sv_tree, hf_trmac_physical_drop_number, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
295
0
      proto_item_append_text(sv_item,
296
0
        ": 0x%08X", tvb_get_ntohl(tvb, svoff+2) );
297
0
      break;
298
299
13
    case 0x20: /* Response Code */
300
13
      if (sv_length != 4 && sv_length != 6) {
301
12
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
302
12
            "Subvector length is != 4 and != 6");
303
12
        break;
304
12
      }
305
1
      if (sv_length == 4) {
306
0
        proto_tree_add_uint_format_value(sv_tree, hf_trmac_response_code32, tvb, svoff+2, sv_length-2,
307
0
          tvb_get_ntohl(tvb, svoff+2), "0x%04X 0x%02X 0x%02x",
308
0
          tvb_get_ntohs(tvb, svoff+2), tvb_get_uint8(tvb, svoff+4), tvb_get_uint8(tvb, svoff+5));
309
0
        proto_item_append_text(sv_item,
310
0
          ": 0x%04X 0x%02X 0x%02x",
311
0
          tvb_get_ntohs(tvb, svoff+2),
312
0
          tvb_get_uint8(tvb, svoff+4),
313
0
          tvb_get_uint8(tvb, svoff+5));
314
1
      } else {
315
1
        proto_tree_add_uint64_format_value(sv_tree, hf_trmac_response_code48, tvb, svoff+2, sv_length-2,
316
1
          tvb_get_ntoh48(tvb, svoff+2), "0x%04X 0x%02X 0x%06X",
317
1
          tvb_get_ntohs(tvb, svoff+2),
318
1
          tvb_get_uint8(tvb, svoff+4),
319
1
          tvb_get_ntoh24(tvb, svoff+5));
320
1
        proto_item_append_text(sv_item,
321
1
          ": 0x%04X 0x%02X 0x%06X",
322
1
          tvb_get_ntohs(tvb, svoff+2),
323
1
          tvb_get_uint8(tvb, svoff+4),
324
1
          tvb_get_ntoh24(tvb, svoff+5));
325
1
      }
326
1
      break;
327
328
15
    case 0x21: /* Individual Address Count */
329
15
      if (sv_length != 4) {
330
15
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
331
15
            "Subvector length is != 4");
332
15
        break;
333
15
      }
334
0
      proto_tree_add_item(sv_tree, hf_trmac_individual_address_count, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
335
0
      proto_item_append_text(sv_item,
336
0
        ": %u", tvb_get_ntohs(tvb, svoff+2) );
337
0
      break;
338
339
2
    case 0x22: /* Product Instance ID */
340
2
      proto_tree_add_item(sv_tree, hf_trmac_product_instance_id, tvb, svoff+2, sv_length-2, ENC_NA);
341
2
      break;
342
343
16
    case 0x23: /* Ring Station Version Number */
344
16
      proto_tree_add_item(sv_tree, hf_trmac_ring_station_version_number, tvb, svoff+2, sv_length-2, ENC_NA);
345
16
      break;
346
347
9
    case 0x26: /* Wrap data */
348
9
      proto_tree_add_item(sv_tree, hf_trmac_wrap_data, tvb, svoff+2, sv_length-2, ENC_NA);
349
9
      break;
350
351
11
    case 0x27: /* Frame Forward */
352
11
      proto_tree_add_item(sv_tree, hf_trmac_frame_forward, tvb, svoff+2, sv_length-2, ENC_NA);
353
11
      break;
354
355
20
    case 0x28: /* Station Identifier */
356
20
      if (sv_length != 8) {
357
19
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
358
19
            "Subvector length is != 8");
359
19
        break;
360
19
      }
361
1
      proto_tree_add_item(sv_tree, hf_trmac_station_identifier, tvb, svoff+2, sv_length-2, ENC_NA);
362
1
      proto_item_append_text(sv_item,
363
1
        ": %s",
364
1
        tvb_ether_to_str(pinfo->pool, tvb, svoff+2));
365
1
      break;
366
367
10
    case 0x29: /* Ring Station Status */
368
10
      proto_tree_add_item(sv_tree, hf_trmac_ring_station_status, tvb, svoff+2, sv_length-2, ENC_NA);
369
10
      break;
370
371
23
    case 0x2A: /* Transmit Status Code */
372
23
      if (sv_length != 4) {
373
23
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
374
23
            "Subvector length is != 4");
375
23
        break;
376
23
      }
377
0
      proto_tree_add_item(sv_tree, hf_trmac_transmit_status_code, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
378
0
      proto_item_append_text(sv_item,
379
0
        ": %04X", tvb_get_ntohs(tvb, svoff+2) );
380
0
      break;
381
382
11
    case 0x2B: /* Group Address */
383
11
      if (sv_length != 6 && sv_length != 8) {
384
11
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
385
11
            "Subvector length is != 6 and != 8");
386
11
        break;
387
11
      }
388
0
      if (sv_length == 6) {
389
0
        proto_tree_add_item(sv_tree, hf_trmac_group_address32, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
390
0
        proto_item_append_text(sv_item,
391
0
          ": %08X", tvb_get_ntohl(tvb, svoff+2) );
392
0
      } else {
393
0
        proto_tree_add_item(sv_tree, hf_trmac_group_address_ether, tvb, svoff+2, sv_length-2, ENC_NA);
394
0
        proto_item_append_text(sv_item,
395
0
          ": %s",
396
0
          tvb_ether_to_str(pinfo->pool, tvb, svoff+2));
397
0
      }
398
0
      break;
399
400
25
    case 0x2C: /* Functional Addresses */
401
25
      if (sv_length != 6) {
402
25
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
403
25
            "Subvector length is != 6");
404
25
        break;
405
25
      }
406
0
      proto_tree_add_item(sv_tree, hf_trmac_functional_addresses, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
407
0
      proto_item_append_text(sv_item,
408
0
        ": %08X", tvb_get_ntohl(tvb, svoff+2) );
409
0
      break;
410
411
17
    case 0x2D: /* Isolating Error Counts */
412
17
      if (sv_length != 8) {
413
17
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
414
17
            "Subvector length is != 8");
415
17
        break;
416
17
      }
417
0
      tvb_memcpy(tvb, errors, svoff+2, 6);
418
0
      ti = proto_tree_add_uint(sv_tree, hf_trmac_errors_iso, tvb, svoff+2, sv_length-2,
419
0
        errors[0] + errors[1] + errors[2] + errors[3] + errors[4]);
420
0
      sv_subtree = proto_item_add_subtree(ti, ett_tr_ierr_cnt);
421
422
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_line, tvb, svoff+2, 1, errors[0]);
423
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_internal, tvb, svoff+3, 1, errors[1]);
424
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_burst, tvb, svoff+4, 1, errors[2]);
425
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_ac, tvb, svoff+5, 1, errors[3]);
426
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_abort, tvb, svoff+6, 1, errors[4]);
427
428
0
      break;
429
430
3
    case 0x2E: /* Non-Isolating Error Counts */
431
3
      if (sv_length != 8) {
432
3
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
433
3
            "Subvector length is != 8");
434
3
        break;
435
3
      }
436
0
      tvb_memcpy(tvb, errors, svoff+2, 6);
437
0
      ti = proto_tree_add_uint(sv_tree, hf_trmac_errors_noniso, tvb, svoff+2, sv_length-2,
438
0
        errors[0] + errors[1] + errors[2] + errors[3] + errors[4]);
439
0
      sv_subtree = proto_item_add_subtree(ti, ett_tr_nerr_cnt);
440
441
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_lost, tvb, svoff+2, 1, errors[0]);
442
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_congestion, tvb, svoff+3, 1, errors[1]);
443
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_fc, tvb, svoff+4, 1, errors[2]);
444
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_freq, tvb, svoff+5, 1, errors[3]);
445
0
      proto_tree_add_uint(sv_subtree, hf_trmac_errors_token, tvb, svoff+6, 1, errors[4]);
446
0
      break;
447
448
14
    case 0x30: /* Error Code */
449
14
      if (sv_length != 4) {
450
14
        expert_add_info_format(pinfo, len_item, &ei_trmac_sv_len,
451
14
            "Subvector length is != 4");
452
14
        break;
453
14
      }
454
0
      proto_tree_add_item(sv_tree, hf_trmac_error_code, tvb, svoff+2, sv_length-2, ENC_BIG_ENDIAN);
455
0
      proto_item_append_text(sv_item,
456
0
        ": %04X", tvb_get_ntohs(tvb, svoff+2) );
457
0
      break;
458
459
223
    default: /* Unknown */
460
223
      proto_tree_add_item(sv_tree, hf_trmac_unknown_subvector, tvb, svoff+2, sv_length-2, ENC_NA);
461
223
      break;
462
973
  }
463
882
  return sv_length;
464
973
}
465
466
static int
467
dissect_trmac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
468
120
{
469
120
  proto_tree  *mac_tree;
470
120
  proto_item  *ti;
471
120
  int   sv_additional;
472
120
  uint32_t    mv_val, mv_length, sv_offset;
473
474
120
  if (tvb_captured_length(tvb) < 3)
475
1
    return 0;
476
477
119
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "TR MAC");
478
119
  col_clear(pinfo->cinfo, COL_INFO);
479
480
119
  ti = proto_tree_add_item(tree, proto_trmac, tvb, 0, -1, ENC_NA);
481
119
  mac_tree = proto_item_add_subtree(ti, ett_tr_mac);
482
483
119
  proto_tree_add_item_ret_uint(mac_tree, hf_trmac_mv, tvb, 3, 1, ENC_NA, &mv_val);
484
119
  proto_tree_add_item_ret_uint(mac_tree, hf_trmac_length, tvb, 0, 2, ENC_BIG_ENDIAN, &mv_length);
485
119
  proto_item_set_len(ti, mv_length);
486
119
  proto_tree_add_item(mac_tree, hf_trmac_srcclass, tvb, 2, 1, ENC_NA);
487
119
  proto_tree_add_item(mac_tree, hf_trmac_dstclass, tvb, 2, 1, ENC_NA);
488
489
  /* Interpret the major vector */
490
119
  col_add_str(pinfo->cinfo, COL_INFO,
491
119
        val_to_str_ext(pinfo->pool, mv_val, &major_vector_vs_ext, "Unknown Major Vector: %u"));
492
493
  /* interpret the subvectors */
494
119
  sv_offset = 4;
495
1.00k
  while (sv_offset < mv_length) {
496
996
    sv_additional = sv_text(tvb, sv_offset, pinfo, mac_tree);
497
498
    /* if this is a bad packet, we could get a 0-length added here,
499
      * looping forever */
500
996
    if (sv_additional > 0)
501
882
      sv_offset += sv_additional;
502
114
    else
503
114
      break;
504
996
  }
505
506
119
  return tvb_captured_length(tvb);
507
120
}
508
509
void
510
proto_register_trmac(void)
511
14
{
512
14
  static hf_register_info hf[] = {
513
14
    { &hf_trmac_mv,
514
14
    { "Major Vector",     "trmac.mvec", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &major_vector_vs_ext, 0x0,
515
14
      NULL, HFILL }},
516
517
14
    { &hf_trmac_length,
518
14
    { "Total Length",     "trmac.length", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
519
14
      NULL, HFILL }},
520
521
14
    { &hf_trmac_srcclass,
522
14
    { "Source Class",     "trmac.srcclass", FT_UINT8, BASE_HEX, VALS(classes_vs), 0x0F,
523
14
      NULL, HFILL }},
524
525
14
    { &hf_trmac_dstclass,
526
14
    { "Destination Class",      "trmac.dstclass", FT_UINT8, BASE_HEX, VALS(classes_vs), 0xF0,
527
14
      NULL, HFILL }},
528
529
14
    { &hf_trmac_sv_len,
530
14
    { "Subvector Length",     "trmac.svec.len", FT_UINT8, BASE_DEC, NULL, 0x0,
531
14
      NULL, HFILL }},
532
533
14
    { &hf_trmac_sv_id,
534
14
    { "Subvector Identifier",   "trmac.svec.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &subvector_vs_ext, 0x0,
535
14
      NULL, HFILL }},
536
537
14
    { &hf_trmac_errors_iso,
538
14
    { "Isolating Errors",     "trmac.errors.iso", FT_UINT16, BASE_DEC, NULL, 0x0,
539
14
      NULL, HFILL }},
540
541
14
    { &hf_trmac_errors_line,
542
14
    { "Line Errors",      "trmac.errors.line", FT_UINT8, BASE_DEC, NULL, 0x0,
543
14
      NULL, HFILL }},
544
545
14
    { &hf_trmac_errors_internal,
546
14
    { "Internal Errors",      "trmac.errors.internal", FT_UINT8, BASE_DEC, NULL, 0x0,
547
14
      NULL, HFILL }},
548
549
14
    { &hf_trmac_errors_burst,
550
14
    { "Burst Errors",     "trmac.errors.burst", FT_UINT8, BASE_DEC, NULL, 0x0,
551
14
      NULL, HFILL }},
552
553
14
    { &hf_trmac_errors_ac,
554
14
    { "A/C Errors",       "trmac.errors.ac", FT_UINT8, BASE_DEC, NULL, 0x0,
555
14
      NULL, HFILL }},
556
557
14
    { &hf_trmac_errors_abort,
558
14
    { "Abort Delimiter Transmitted Errors", "trmac.errors.abort", FT_UINT8, BASE_DEC, NULL, 0x0,
559
14
      NULL, HFILL }},
560
561
14
    { &hf_trmac_errors_noniso,
562
14
    { "Non-Isolating Errors",   "trmac.errors.noniso", FT_UINT16, BASE_DEC, NULL, 0x0,
563
14
      NULL, HFILL }},
564
565
14
    { &hf_trmac_errors_lost,
566
14
    { "Lost Frame Errors",      "trmac.errors.lost", FT_UINT8, BASE_DEC, NULL, 0x0,
567
14
      NULL, HFILL }},
568
569
14
    { &hf_trmac_errors_congestion,
570
14
    { "Receiver Congestion Errors",   "trmac.errors.congestion", FT_UINT8, BASE_DEC, NULL, 0x0,
571
14
      NULL, HFILL }},
572
573
14
    { &hf_trmac_errors_fc,
574
14
    { "Frame-Copied Errors",    "trmac.errors.fc", FT_UINT8, BASE_DEC, NULL, 0x0,
575
14
      NULL, HFILL }},
576
577
14
    { &hf_trmac_errors_freq,
578
14
    { "Frequency Errors",     "trmac.errors.freq", FT_UINT8, BASE_DEC, NULL, 0x0,
579
14
      NULL, HFILL }},
580
581
14
    { &hf_trmac_errors_token,
582
14
    { "Token Errors",     "trmac.errors.token", FT_UINT8, BASE_DEC, NULL, 0x0,
583
14
      NULL, HFILL }},
584
585
14
    { &hf_trmac_naun,
586
14
    { "Upstream Neighbor's Address",  "trmac.naun", FT_ETHER, BASE_NONE, NULL, 0x0,
587
14
      NULL, HFILL }},
588
589
14
    { &hf_trmac_beacon_type,
590
14
    { "Beacon Type",      "trmac.beacon_type", FT_UINT16, BASE_DEC, VALS(beacon_vs), 0x0,
591
14
      NULL, HFILL }},
592
593
14
    { &hf_trmac_local_ring_number,
594
14
    { "Local Ring Number",      "trmac.local_ring_number", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
595
14
      NULL, HFILL }},
596
597
14
    { &hf_trmac_assign_physical_drop_number,
598
14
    { "Assign Physical Drop Number",  "trmac.assign_physical_drop_number", FT_UINT32, BASE_HEX, NULL, 0x0,
599
14
      NULL, HFILL }},
600
601
14
    { &hf_trmac_error_report_timer_value,
602
14
    { "Error Report Timer Value",   "trmac.error_report_timer_value", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_milliseconds), 0x0,
603
14
      NULL, HFILL }},
604
605
14
    { &hf_trmac_authorized_function_classes,
606
14
    { "Authorized Function Classes",  "trmac.authorized_function_classes", FT_UINT16, BASE_HEX, NULL, 0x0,
607
14
      NULL, HFILL }},
608
609
14
    { &hf_trmac_authorized_access_priority,
610
14
    { "Authorized Access Priority",   "trmac.authorized_access_priority", FT_UINT16, BASE_HEX, NULL, 0x0,
611
14
      NULL, HFILL }},
612
613
14
    { &hf_trmac_correlator,
614
14
    { "Correlator",       "trmac.correlator", FT_UINT16, BASE_HEX, NULL, 0x0,
615
14
      NULL, HFILL }},
616
617
14
    { &hf_trmac_sa_of_last_amp_or_smp_frame,
618
14
    { "SA of Last AMP or SMP Frame",  "trmac.sa_of_last_amp_or_smp_frame", FT_ETHER, BASE_NONE, NULL, 0x0,
619
14
      NULL, HFILL }},
620
621
14
    { &hf_trmac_physical_drop_number,
622
14
    { "Physical Drop Number",   "trmac.physical_drop_number", FT_UINT32, BASE_HEX, NULL, 0x0,
623
14
      NULL, HFILL }},
624
625
14
    { &hf_trmac_individual_address_count,
626
14
    { "Individual Address Count",   "trmac.individual_address_count", FT_UINT16, BASE_DEC, NULL, 0x0,
627
14
      NULL, HFILL }},
628
629
14
    { &hf_trmac_station_identifier,
630
14
    { "Station Identifier",     "trmac.station_identifier", FT_ETHER, BASE_NONE, NULL, 0x0,
631
14
      NULL, HFILL }},
632
633
14
    { &hf_trmac_transmit_status_code,
634
14
    { "Transmit Status Code",   "trmac.transmit_status_code", FT_UINT16, BASE_HEX, NULL, 0x0,
635
14
      NULL, HFILL }},
636
637
14
    { &hf_trmac_group_address32,
638
14
    { "Group Address",      "trmac.group_address32s", FT_UINT32, BASE_HEX, NULL, 0x0,
639
14
      NULL, HFILL }},
640
641
14
    { &hf_trmac_group_address_ether,
642
14
    { "Group Address",      "trmac.group_address_ether", FT_ETHER, BASE_NONE, NULL, 0x0,
643
14
      NULL, HFILL }},
644
645
14
    { &hf_trmac_functional_addresses,
646
14
    { "Functional Addresses",   "trmac.functional_addresses", FT_UINT32, BASE_HEX, NULL, 0x0,
647
14
      NULL, HFILL }},
648
649
14
    { &hf_trmac_error_code,
650
14
    { "Error Code",       "trmac.error_code", FT_UINT16, BASE_HEX, NULL, 0x0,
651
14
      NULL, HFILL }},
652
653
    /* Generated from convert_proto_tree_add_text.pl */
654
14
    { &hf_trmac_response_code32, { "Response Code", "trmac.response_code", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
655
14
    { &hf_trmac_response_code48, { "Response Code", "trmac.response_code48", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
656
14
    { &hf_trmac_product_instance_id, { "Product Instance ID", "trmac.product_instance_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
657
14
    { &hf_trmac_ring_station_version_number, { "Ring Station Version Number", "trmac.ring_station_version_number", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
658
14
    { &hf_trmac_wrap_data, { "Wrap Data", "trmac.wrap_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
659
14
    { &hf_trmac_frame_forward, { "Frame Forward", "trmac.frame_forward", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
660
14
    { &hf_trmac_ring_station_status, { "Ring Station Status", "trmac.ring_station_status", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
661
14
    { &hf_trmac_unknown_subvector, { "Unknown Subvector", "trmac.unknown_subvector", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
662
663
14
  };
664
14
  static int *ett[] = {
665
14
    &ett_tr_mac,
666
14
    &ett_tr_sv,
667
14
    &ett_tr_ierr_cnt,
668
14
    &ett_tr_nerr_cnt,
669
14
  };
670
671
14
  static ei_register_info ei[] = {
672
14
    { &ei_trmac_sv_len, { "trmac.svec.len.invalid", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
673
14
  };
674
675
14
  expert_module_t* expert_trmac;
676
677
14
  proto_trmac = proto_register_protocol("Token-Ring Media Access Control", "TR MAC", "trmac");
678
14
  proto_register_field_array(proto_trmac, hf, array_length(hf));
679
14
  proto_register_subtree_array(ett, array_length(ett));
680
14
  expert_trmac = expert_register_protocol(proto_trmac);
681
14
  expert_register_field_array(expert_trmac, ei, array_length(ei));
682
683
14
  register_dissector("trmac", dissect_trmac, proto_trmac);
684
14
}
685
686
/*
687
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
688
 *
689
 * Local variables:
690
 * c-basic-offset: 8
691
 * tab-width: 8
692
 * indent-tabs-mode: t
693
 * End:
694
 *
695
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
696
 * :indentSize=8:tabSize=8:noTabs=false:
697
 */