/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 | | */ |