Coverage Report

Created: 2026-07-12 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-sdh.c
Line
Count
Source
1
/* packet-sdh.c
2
 * Routines for SDH/SONET encapsulation dissection
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 - 2012 Gerald Combs
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 */
10
11
#include "config.h"
12
13
#include <epan/packet.h>
14
#include <epan/prefs.h>
15
#include <wiretap/wtap.h>
16
17
#include "packet-erf.h"
18
19
20
0
#define COLUMNS 270
21
0
#define EXT_HDR_TYPE_RAW_LINK        5
22
23
void proto_register_sdh(void);
24
void proto_reg_handoff_sdh(void);
25
26
static int proto_sdh;
27
28
static int ett_sdh;
29
30
static int hf_sdh_a1;
31
static int hf_sdh_a2;
32
static int hf_sdh_j0;
33
static int hf_sdh_b1;
34
static int hf_sdh_e1;
35
static int hf_sdh_f1;
36
static int hf_sdh_d1;
37
static int hf_sdh_d2;
38
static int hf_sdh_d3;
39
static int hf_sdh_au;
40
static int hf_sdh_b2;
41
static int hf_sdh_k1;
42
static int hf_sdh_k2;
43
static int hf_sdh_d4;
44
static int hf_sdh_d5;
45
static int hf_sdh_d6;
46
static int hf_sdh_d7;
47
static int hf_sdh_d8;
48
static int hf_sdh_d9;
49
static int hf_sdh_d10;
50
static int hf_sdh_d11;
51
static int hf_sdh_d12;
52
static int hf_sdh_s1;
53
static int hf_sdh_m1;
54
static int hf_sdh_e2;
55
static int hf_sdh_h1;
56
static int hf_sdh_h2;
57
static int hf_sdh_j1;
58
59
static dissector_handle_t sdh_handle;
60
61
static int sdh_data_rate = 1;
62
63
static const enum_val_t data_rates[] = {
64
  {"Guess", "Attempt to guess", -1},
65
  {"OC-3",  "OC-3",   1},
66
  {"OC-12", "OC-12",  4},
67
  {"OC-24", "OC-24",  8},
68
  {"OC-48", "OC-48", 16},
69
  {NULL, NULL, -1}
70
};
71
72
static const value_string sdh_s1_vals[] = {
73
  { 0, "Quality unknown" },
74
  { 1, "Reserved" },
75
  { 2, "Rec G.811" },
76
  { 3, "Reserved" },
77
  { 4, "SSU-A" },
78
  { 5, "Reserved" },
79
  { 6, "Reserved" },
80
  { 7, "Reserved" },
81
  { 8, "SSU-B" },
82
  { 9, "Reserved" },
83
  { 10, "Reserved" },
84
  { 11, "SDH Equipment Source" },
85
  { 12, "Reserved" },
86
  { 13, "Reserved" },
87
  { 14, "Reserved" },
88
  { 15, "do not use for sync" },
89
  { 0, NULL }
90
};
91
92
static int
93
get_sdh_level(tvbuff_t *tvb, packet_info *pinfo)
94
0
{
95
0
  uint64_t *hdr = NULL;
96
97
  /*data rate has been set in the SDH options*/
98
0
  if(sdh_data_rate != -1) return sdh_data_rate;
99
100
  /*ERF specifies data rate*/
101
0
  hdr = erf_get_ehdr(pinfo, EXT_HDR_TYPE_RAW_LINK, NULL);
102
0
  if (hdr != NULL){
103
0
    switch((*hdr & 0xff00) >> 8){
104
0
      case 1: /*OC-3*/
105
0
        return 1;
106
0
      case 2: /*OC-12*/
107
0
        return 4;
108
0
      case 3: /*OC-48*/
109
0
        return 16;
110
0
      default:  /*drop through and try the next method*/
111
0
        ;
112
0
    }
113
0
  }
114
115
  /*returns the multiplier for each data level*/
116
0
  switch(tvb_reported_length(tvb)){
117
0
    case 2430:  /*OC-3*/
118
0
      return 1;
119
0
    case 9720:  /*OC-12*/
120
0
      return 4;
121
0
    case 19440: /*OC-24*/
122
0
      return 8;
123
0
    case 38880: /*OC-48*/
124
0
      return 16;
125
0
  }
126
127
0
  return 1;
128
0
}
129
130
131
static int
132
dissect_sdh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
133
0
{
134
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "SDH");
135
0
  col_clear(pinfo->cinfo,COL_INFO);
136
137
0
  if (tree) {
138
0
    proto_tree *sdh_tree;
139
0
    proto_item *sdh_item;
140
141
0
    int     level = get_sdh_level(tvb, pinfo);
142
143
0
    uint8_t h1;
144
0
    uint8_t h2;
145
0
    uint16_t au;
146
0
    int auoffset;
147
148
0
    sdh_item = proto_tree_add_protocol_format(tree, proto_sdh, tvb, 0, -1, "SDH");
149
0
    sdh_tree = proto_item_add_subtree(sdh_item, ett_sdh);
150
151
0
    h1  = tvb_get_uint8(tvb, 0*level+(3*level*COLUMNS));
152
0
    h2  = tvb_get_uint8(tvb, 3*level+(3*level*COLUMNS));
153
0
    au  = (h2 | ((0x03 & h1) << 8));
154
155
0
    proto_tree_add_item(sdh_tree, hf_sdh_a1, tvb, 0*level, 3*level, ENC_NA);
156
0
    proto_tree_add_item(sdh_tree, hf_sdh_a2, tvb, 3*level, 3*level, ENC_NA);
157
0
    proto_tree_add_item(sdh_tree, hf_sdh_j0, tvb, 6*level, 1, ENC_BIG_ENDIAN);
158
0
    proto_tree_add_item(sdh_tree, hf_sdh_b1, tvb, 0*level+(1*level*COLUMNS), 1, ENC_BIG_ENDIAN);
159
0
    proto_tree_add_item(sdh_tree, hf_sdh_e1, tvb, 3*level+(1*level*COLUMNS), 1, ENC_BIG_ENDIAN);
160
0
    proto_tree_add_item(sdh_tree, hf_sdh_f1, tvb, 6*level+(1*level*COLUMNS), 1, ENC_BIG_ENDIAN);
161
0
    proto_tree_add_item(sdh_tree, hf_sdh_d1, tvb, 0*level+(2*level*COLUMNS), 1, ENC_BIG_ENDIAN);
162
0
    proto_tree_add_item(sdh_tree, hf_sdh_d2, tvb, 3*level+(2*level*COLUMNS), 1, ENC_BIG_ENDIAN);
163
0
    proto_tree_add_item(sdh_tree, hf_sdh_d3, tvb, 6*level+(2*level*COLUMNS), 1, ENC_BIG_ENDIAN);
164
0
    proto_tree_add_item(sdh_tree, hf_sdh_h1, tvb, 0*level+(3*level*COLUMNS), 1, ENC_BIG_ENDIAN);
165
0
    proto_tree_add_item(sdh_tree, hf_sdh_h2, tvb, 3*level+(3*level*COLUMNS), 1, ENC_BIG_ENDIAN);
166
0
    proto_tree_add_uint(sdh_tree, hf_sdh_au, tvb, 0*level+(3*level*COLUMNS), 3*level+1, au);
167
0
    proto_tree_add_item(sdh_tree, hf_sdh_b2, tvb, 0*level+(4*level*COLUMNS), 3*level, ENC_NA);
168
0
    proto_tree_add_item(sdh_tree, hf_sdh_k1, tvb, 3*level+(4*level*COLUMNS), 1, ENC_BIG_ENDIAN);
169
0
    proto_tree_add_item(sdh_tree, hf_sdh_k2, tvb, 6*level+(4*level*COLUMNS), 1, ENC_BIG_ENDIAN);
170
0
    proto_tree_add_item(sdh_tree, hf_sdh_d4, tvb, 0*level+(5*level*COLUMNS), 1, ENC_BIG_ENDIAN);
171
0
    proto_tree_add_item(sdh_tree, hf_sdh_d5, tvb, 3*level+(5*level*COLUMNS), 1, ENC_BIG_ENDIAN);
172
0
    proto_tree_add_item(sdh_tree, hf_sdh_d6, tvb, 6*level+(5*level*COLUMNS), 1, ENC_BIG_ENDIAN);
173
0
    proto_tree_add_item(sdh_tree, hf_sdh_d7, tvb, 0*level+(6*level*COLUMNS), 1, ENC_BIG_ENDIAN);
174
0
    proto_tree_add_item(sdh_tree, hf_sdh_d8, tvb, 3*level+(6*level*COLUMNS), 1, ENC_BIG_ENDIAN);
175
0
    proto_tree_add_item(sdh_tree, hf_sdh_d9, tvb, 6*level+(6*level*COLUMNS), 1, ENC_BIG_ENDIAN);
176
0
    proto_tree_add_item(sdh_tree, hf_sdh_d10, tvb, 0*level+(7*level*COLUMNS), 1, ENC_BIG_ENDIAN);
177
0
    proto_tree_add_item(sdh_tree, hf_sdh_d11, tvb, 3*level+(7*level*COLUMNS), 1, ENC_BIG_ENDIAN);
178
0
    proto_tree_add_item(sdh_tree, hf_sdh_d12, tvb, 6*level+(7*level*COLUMNS), 1, ENC_BIG_ENDIAN);
179
0
    proto_tree_add_item(sdh_tree, hf_sdh_s1, tvb, 0*level+(8*level*COLUMNS), 1, ENC_BIG_ENDIAN);
180
0
    proto_tree_add_item(sdh_tree, hf_sdh_m1, tvb, 3*level+2+(8*level*COLUMNS), 1, ENC_BIG_ENDIAN);
181
0
    proto_tree_add_item(sdh_tree, hf_sdh_e2, tvb, 6*level+(8*level*COLUMNS), 1, ENC_BIG_ENDIAN);
182
183
    /*XXX: POH that au points to may not be in the same frame. Also wrong on pointer justification*/
184
    /*calculate start of SPE by wrapping AU pointer*/
185
0
    auoffset = (((9 + 3*COLUMNS) /*start after H3*/ + au*3 + 9*(au/87) /*add extra SOH rows to offset*/) * level) % (COLUMNS*9*level);
186
0
    proto_tree_add_item(sdh_tree, hf_sdh_j1, tvb, auoffset, 1, ENC_BIG_ENDIAN);
187
0
  }
188
0
  return tvb_captured_length(tvb);
189
0
}
190
191
void
192
proto_register_sdh(void)
193
15
{
194
15
  static hf_register_info hf[] = {
195
15
    { &hf_sdh_a1,
196
15
    { "A1", "sdh.a1", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
197
15
    { &hf_sdh_a2,
198
15
    { "A2", "sdh.a2", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
199
15
    { &hf_sdh_j0,
200
15
    { "J0", "sdh.j0", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
201
15
    { &hf_sdh_b1,
202
15
    { "B1", "sdh.b1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
203
15
    { &hf_sdh_e1,
204
15
    { "E1", "sdh.e1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
205
15
    { &hf_sdh_f1,
206
15
    { "F1", "sdh.f1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
207
15
    { &hf_sdh_d1,
208
15
    { "D1", "sdh.d1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
209
15
    { &hf_sdh_d2,
210
15
    { "D2", "sdh.d2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
211
15
    { &hf_sdh_d3,
212
15
    { "D3", "sdh.d3", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
213
15
    { &hf_sdh_au,
214
15
    { "AU", "sdh.au", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
215
15
    { &hf_sdh_b2,
216
15
    { "B2", "sdh.b2", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
217
15
    { &hf_sdh_k1,
218
15
    { "K1", "sdh.k1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
219
15
    { &hf_sdh_k2,
220
15
    { "K2", "sdh.k2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
221
15
    { &hf_sdh_d4,
222
15
    { "D4", "sdh.d4", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
223
15
    { &hf_sdh_d5,
224
15
    { "D5", "sdh.d5", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
225
15
    { &hf_sdh_d6,
226
15
    { "D6", "sdh.d6", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
227
15
    { &hf_sdh_d7,
228
15
    { "D7", "sdh.d7", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
229
15
    { &hf_sdh_d8,
230
15
    { "D8", "sdh.d8", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
231
15
    { &hf_sdh_d9,
232
15
    { "D9", "sdh.d9", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
233
15
    { &hf_sdh_d10,
234
15
    { "D10", "sdh.d10", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
235
15
    { &hf_sdh_d11,
236
15
    { "D11", "sdh.d11", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
237
15
    { &hf_sdh_d12,
238
15
    { "D12", "sdh.d12", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
239
15
    { &hf_sdh_s1,
240
15
    { "S1", "sdh.s1", FT_UINT8, BASE_HEX, VALS(sdh_s1_vals), 0x0, NULL, HFILL }},
241
15
    { &hf_sdh_m1,
242
15
    { "M1", "sdh.m1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
243
15
    { &hf_sdh_e2,
244
15
    { "E2", "sdh.e2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
245
15
    { &hf_sdh_j1,
246
15
    { "J1", "sdh.j1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
247
15
    { &hf_sdh_h1,
248
15
    { "H1", "sdh.h1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
249
15
    { &hf_sdh_h2,
250
15
    { "H2", "sdh.h2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
251
252
15
  };
253
15
  static int *ett[] = {
254
15
    &ett_sdh,
255
15
  };
256
257
15
  module_t *sdh_module;
258
259
260
15
  proto_sdh = proto_register_protocol("SDH/SONET Protocol", "SDH", "sdh");
261
15
  proto_register_field_array(proto_sdh, hf, array_length(hf));
262
15
  proto_register_subtree_array(ett, array_length(ett));
263
264
15
  sdh_module = prefs_register_protocol(proto_sdh, NULL);
265
15
  prefs_register_enum_preference(sdh_module, "data.rate",
266
15
    "Data rate",
267
15
    "Data rate",
268
15
    &sdh_data_rate, data_rates, ENC_BIG_ENDIAN);
269
270
15
  sdh_handle = register_dissector("sdh", dissect_sdh, proto_sdh);
271
15
}
272
273
void
274
proto_reg_handoff_sdh(void)
275
15
{
276
15
  dissector_add_uint("wtap_encap", WTAP_ENCAP_SDH, sdh_handle);
277
15
}
278
279
/*
280
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
281
 *
282
 * Local Variables:
283
 * c-basic-offset: 2
284
 * tab-width: 8
285
 * indent-tabs-mode: nil
286
 * End:
287
 *
288
 * ex: set shiftwidth=2 tabstop=8 expandtab:
289
 * :indentSize=2:tabSize=8:noTabs=true:
290
 */