2 * Routines for SDH/SONET encapsulation dissection
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 - 2012 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include <epan/packet.h>
14 #include <epan/prefs.h>
15 #include <wiretap/wtap.h>
17 #include "packet-erf.h"
21 #define EXT_HDR_TYPE_RAW_LINK 5
23 void proto_register_sdh(void);
24 void proto_reg_handoff_sdh(void);
49 static int hf_sdh_d10
;
50 static int hf_sdh_d11
;
51 static int hf_sdh_d12
;
59 static dissector_handle_t sdh_handle
;
61 static int sdh_data_rate
= 1;
63 static const enum_val_t data_rates
[] = {
64 {"Guess", "Attempt to guess", -1},
66 {"OC-12", "OC-12", 4},
67 {"OC-24", "OC-24", 8},
68 {"OC-48", "OC-48", 16},
72 static const value_string sdh_s1_vals
[] = {
73 { 0, "Quality unknown" },
84 { 11, "SDH Equipment Source" },
88 { 15, "do not use for sync" },
93 get_sdh_level(tvbuff_t
*tvb
, packet_info
*pinfo
)
97 /*data rate has been set in the SDH options*/
98 if(sdh_data_rate
!= -1) return sdh_data_rate
;
100 /*ERF specifies data rate*/
101 hdr
= erf_get_ehdr(pinfo
, EXT_HDR_TYPE_RAW_LINK
, NULL
);
103 switch((*hdr
& 0xff00) >> 8){
110 default: /*drop through and try the next method*/
115 /*returns the multiplier for each data level*/
116 switch(tvb_reported_length(tvb
)){
121 case 19440: /*OC-24*/
123 case 38880: /*OC-48*/
132 dissect_sdh(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
134 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SDH");
135 col_clear(pinfo
->cinfo
,COL_INFO
);
138 proto_tree
*sdh_tree
;
139 proto_item
*sdh_item
;
141 int level
= get_sdh_level(tvb
, pinfo
);
148 sdh_item
= proto_tree_add_protocol_format(tree
, proto_sdh
, tvb
, 0, -1, "SDH");
149 sdh_tree
= proto_item_add_subtree(sdh_item
, ett_sdh
);
151 h1
= tvb_get_uint8(tvb
, 0*level
+(3*level
*COLUMNS
));
152 h2
= tvb_get_uint8(tvb
, 3*level
+(3*level
*COLUMNS
));
153 au
= (h2
| ((0x03 & h1
) << 8));
155 proto_tree_add_item(sdh_tree
, hf_sdh_a1
, tvb
, 0*level
, 3*level
, ENC_NA
);
156 proto_tree_add_item(sdh_tree
, hf_sdh_a2
, tvb
, 3*level
, 3*level
, ENC_NA
);
157 proto_tree_add_item(sdh_tree
, hf_sdh_j0
, tvb
, 6*level
, 1, ENC_BIG_ENDIAN
);
158 proto_tree_add_item(sdh_tree
, hf_sdh_b1
, tvb
, 0*level
+(1*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
159 proto_tree_add_item(sdh_tree
, hf_sdh_e1
, tvb
, 3*level
+(1*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
160 proto_tree_add_item(sdh_tree
, hf_sdh_f1
, tvb
, 6*level
+(1*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
161 proto_tree_add_item(sdh_tree
, hf_sdh_d1
, tvb
, 0*level
+(2*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
162 proto_tree_add_item(sdh_tree
, hf_sdh_d2
, tvb
, 3*level
+(2*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
163 proto_tree_add_item(sdh_tree
, hf_sdh_d3
, tvb
, 6*level
+(2*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
164 proto_tree_add_item(sdh_tree
, hf_sdh_h1
, tvb
, 0*level
+(3*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
165 proto_tree_add_item(sdh_tree
, hf_sdh_h2
, tvb
, 3*level
+(3*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
166 proto_tree_add_uint(sdh_tree
, hf_sdh_au
, tvb
, 0*level
+(3*level
*COLUMNS
), 3*level
+1, au
);
167 proto_tree_add_item(sdh_tree
, hf_sdh_b2
, tvb
, 0*level
+(4*level
*COLUMNS
), 3*level
, ENC_NA
);
168 proto_tree_add_item(sdh_tree
, hf_sdh_k1
, tvb
, 3*level
+(4*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
169 proto_tree_add_item(sdh_tree
, hf_sdh_k2
, tvb
, 6*level
+(4*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
170 proto_tree_add_item(sdh_tree
, hf_sdh_d4
, tvb
, 0*level
+(5*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
171 proto_tree_add_item(sdh_tree
, hf_sdh_d5
, tvb
, 3*level
+(5*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
172 proto_tree_add_item(sdh_tree
, hf_sdh_d6
, tvb
, 6*level
+(5*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
173 proto_tree_add_item(sdh_tree
, hf_sdh_d7
, tvb
, 0*level
+(6*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
174 proto_tree_add_item(sdh_tree
, hf_sdh_d8
, tvb
, 3*level
+(6*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
175 proto_tree_add_item(sdh_tree
, hf_sdh_d9
, tvb
, 6*level
+(6*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
176 proto_tree_add_item(sdh_tree
, hf_sdh_d10
, tvb
, 0*level
+(7*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
177 proto_tree_add_item(sdh_tree
, hf_sdh_d11
, tvb
, 3*level
+(7*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
178 proto_tree_add_item(sdh_tree
, hf_sdh_d12
, tvb
, 6*level
+(7*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
179 proto_tree_add_item(sdh_tree
, hf_sdh_s1
, tvb
, 0*level
+(8*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
180 proto_tree_add_item(sdh_tree
, hf_sdh_m1
, tvb
, 3*level
+2+(8*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
181 proto_tree_add_item(sdh_tree
, hf_sdh_e2
, tvb
, 6*level
+(8*level
*COLUMNS
), 1, ENC_BIG_ENDIAN
);
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 auoffset
= (((9 + 3*COLUMNS
) /*start after H3*/ + au
*3 + 9*(au
/87) /*add extra SOH rows to offset*/) * level
) % (COLUMNS
*9*level
);
186 proto_tree_add_item(sdh_tree
, hf_sdh_j1
, tvb
, auoffset
, 1, ENC_BIG_ENDIAN
);
188 return tvb_captured_length(tvb
);
192 proto_register_sdh(void)
194 static hf_register_info hf
[] = {
196 { "A1", "sdh.a1", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
198 { "A2", "sdh.a2", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
200 { "J0", "sdh.j0", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
202 { "B1", "sdh.b1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
204 { "E1", "sdh.e1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
206 { "F1", "sdh.f1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
208 { "D1", "sdh.d1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
210 { "D2", "sdh.d2", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
212 { "D3", "sdh.d3", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
214 { "AU", "sdh.au", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
216 { "B2", "sdh.b2", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
218 { "K1", "sdh.k1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
220 { "K2", "sdh.k2", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
222 { "D4", "sdh.d4", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
224 { "D5", "sdh.d5", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
226 { "D6", "sdh.d6", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
228 { "D7", "sdh.d7", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
230 { "D8", "sdh.d8", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
232 { "D9", "sdh.d9", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
234 { "D10", "sdh.d10", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
236 { "D11", "sdh.d11", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
238 { "D12", "sdh.d12", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
240 { "S1", "sdh.s1", FT_UINT8
, BASE_HEX
, VALS(sdh_s1_vals
), 0x0, NULL
, HFILL
}},
242 { "M1", "sdh.m1", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
244 { "E2", "sdh.e2", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
246 { "J1", "sdh.j1", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
248 { "H1", "sdh.h1", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
250 { "H2", "sdh.h2", FT_UINT8
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
253 static int *ett
[] = {
257 module_t
*sdh_module
;
260 proto_sdh
= proto_register_protocol("SDH/SONET Protocol", "SDH", "sdh");
261 proto_register_field_array(proto_sdh
, hf
, array_length(hf
));
262 proto_register_subtree_array(ett
, array_length(ett
));
264 sdh_module
= prefs_register_protocol(proto_sdh
, NULL
);
265 prefs_register_enum_preference(sdh_module
, "data.rate",
268 &sdh_data_rate
, data_rates
, ENC_BIG_ENDIAN
);
270 sdh_handle
= register_dissector("sdh", dissect_sdh
, proto_sdh
);
274 proto_reg_handoff_sdh(void)
276 dissector_add_uint("wtap_encap", WTAP_ENCAP_SDH
, sdh_handle
);
280 * Editor modelines - https://www.wireshark.org/tools/modelines.html
285 * indent-tabs-mode: nil
288 * ex: set shiftwidth=2 tabstop=8 expandtab:
289 * :indentSize=2:tabSize=8:noTabs=true: