/src/wireshark/epan/dissectors/packet-pw-atm.c
Line | Count | Source |
1 | | /* packet-pw-atm.c |
2 | | * Routines for ATM PW dissection: it should be conform to RFC 4717. |
3 | | * |
4 | | * Copyright 2009 _FF_, _ATA_ |
5 | | * |
6 | | * Francesco Fondelli <francesco dot fondelli, gmail dot com> |
7 | | * Artem Tamazov <artem [dot] tamazov [at] tellabs [dot] com> |
8 | | * |
9 | | * Wireshark - Network traffic analyzer |
10 | | * By Gerald Combs <gerald@wireshark.org> |
11 | | * Copyright 1998 Gerald Combs |
12 | | * |
13 | | * SPDX-License-Identifier: GPL-2.0-or-later |
14 | | */ |
15 | | |
16 | | /* |
17 | | DONE: |
18 | | - ATM N-to-One Cell Mode (with CW) |
19 | | - ATM N-to-One Cell Mode (no CW) |
20 | | - ATM One-to-One Cell Mode |
21 | | - ATM AAL5 SDU Mode |
22 | | - ATM AAL5 PDU Mode |
23 | | */ |
24 | | |
25 | | #include "config.h" |
26 | | |
27 | | #include <epan/packet.h> |
28 | | #include <epan/expert.h> |
29 | | #include <epan/prefs.h> |
30 | | #include <epan/tfs.h> |
31 | | |
32 | | #include <wsutil/array.h> |
33 | | #include <wsutil/str_util.h> |
34 | | |
35 | | #include <wiretap/wtap.h> /*for atm pseudo header*/ |
36 | | #include "packet-mpls.h" |
37 | | #include "packet-atm.h" |
38 | | #include "packet-pw-atm.h" |
39 | | #include "packet-pw-common.h" |
40 | | |
41 | | void proto_register_pw_atm_ata(void); |
42 | | void proto_reg_handoff_pw_atm_ata(void); |
43 | | void proto_register_pw_atm(void); |
44 | | void proto_reg_handoff_pw_atm(void); |
45 | | |
46 | | static int proto_n1_nocw; |
47 | | static int proto_n1_cw; |
48 | | static int proto_11_or_aal5_pdu; |
49 | | static int proto_aal5_sdu; |
50 | | /* subordinate dissectors: */ |
51 | | static int proto_control_word; |
52 | | static int proto_cell_header; |
53 | | static int proto_cell; |
54 | | |
55 | | static int ett_encaps; |
56 | | static int ett_cw; |
57 | | static int ett_cell_header; |
58 | | static int ett_cell; |
59 | | |
60 | | static int hf_pw_type_n1_cw; |
61 | | static int hf_pw_type_n1_nocw; |
62 | | static int hf_pw_type_11_vcc; |
63 | | static int hf_pw_type_11_vpc; |
64 | | static int hf_pw_type_aal5_sdu; |
65 | | static int hf_pw_type_aal5_pdu; |
66 | | |
67 | | static int hf_cell_h_vpi; |
68 | | static int hf_cell_h_vci; |
69 | | static int hf_cell_h_pti; |
70 | | static int hf_cell_h_clp; |
71 | | static int hf_cell_h_m; |
72 | | static int hf_cell_h_v; |
73 | | static int hf_cell_h_rsv; |
74 | | static int hf_aal5_pdu_rsv; |
75 | | static int hf_aal5_pdu_u; |
76 | | static int hf_aal5_pdu_e; |
77 | | |
78 | | static int hf_cw_bits03; |
79 | | static int hf_pref_cw_rsv; |
80 | | static int hf_generic_cw_rsv; |
81 | | static int hf_pref_cw_flags; |
82 | | static int hf_pref_cw_a5s_t; |
83 | | static int hf_pref_cw_a5s_e; |
84 | | static int hf_pref_cw_a5s_c; |
85 | | static int hf_pref_cw_a5s_u; |
86 | | static int hf_pref_cw_len; |
87 | | static int hf_pref_cw_rsvlen; |
88 | | static int hf_cw_seq; |
89 | | static int hf_n1_cw_ncells; |
90 | | static int hf_n1_nocw_ncells; |
91 | | static int hf_11_ncells; |
92 | | static int hf_gen_cw_atmbyte; |
93 | | static int hf_cell_payload_len; |
94 | | |
95 | | static expert_field ei_cell_h_v_not_one; |
96 | | static expert_field ei_cell_h_pti_undecoded; |
97 | | static expert_field ei_pref_cw_flags; |
98 | | static expert_field ei_cell_h_v_not_zero; |
99 | | static expert_field ei_pw_payload_size_invalid_note; |
100 | | static expert_field ei_pw_payload_size_invalid_error; |
101 | | static expert_field ei_cell_h_pti_malformed; |
102 | | static expert_field ei_cell_h_rsv; |
103 | | static expert_field ei_cell_broken; |
104 | | static expert_field ei_cell_h_m; |
105 | | static expert_field ei_cw_bits03; |
106 | | static expert_field ei_pw_packet_size_too_small; |
107 | | static expert_field ei_pref_cw_len; |
108 | | static expert_field ei_gen_cw_atmbyte; |
109 | | |
110 | | |
111 | | static dissector_handle_t dh_cell; |
112 | | static dissector_handle_t dh_cell_header; |
113 | | static dissector_handle_t dh_control_word; |
114 | | static dissector_handle_t dh_atm_truncated; |
115 | | static dissector_handle_t dh_atm_untruncated; |
116 | | static dissector_handle_t dh_atm_oam_cell; |
117 | | static dissector_handle_t dh_padding; |
118 | | |
119 | | typedef enum { |
120 | | PWATM_MODE_UNKNOWN = 0 |
121 | | ,PWATM_MODE_N1_NOCW |
122 | | ,PWATM_MODE_N1_CW |
123 | | ,PWATM_MODE_11_VCC |
124 | | ,PWATM_MODE_11_VPC |
125 | | ,PWATM_MODE_AAL5_SDU |
126 | | ,PWATM_MODE_AAL5_PDU |
127 | | } pwatm_mode_t; |
128 | | |
129 | | typedef enum { |
130 | | PWATM_SUBMODE_DEFAULT = 0 |
131 | | ,PWATM_SUBMODE_ADMIN_CELL /*used in aal5_sdu dissector only*/ |
132 | | } pwatm_submode_t; |
133 | | |
134 | | typedef struct { |
135 | | int pw_cell_number; |
136 | | int props; |
137 | | int packet_size; |
138 | | pwatm_mode_t mode; |
139 | | pwatm_submode_t submode; |
140 | | struct { |
141 | | /* |
142 | | * ATM-specific attributes which remain the same |
143 | | * across all the cells in the pw packet. Values are filled |
144 | | * by sub-dissectors and read by upper-level dissector. |
145 | | * Meanings of values: |
146 | | * (-1) - value is unknown |
147 | | * (-2) - value is different among cells |
148 | | * positive - value is the same in all cells |
149 | | * Machinery is implemented in the UPDATE_CUMULATIVE_VALUE macro. |
150 | | */ |
151 | | int32_t vpi; |
152 | | int32_t vci; |
153 | | int32_t clp; |
154 | | int32_t pti; |
155 | | } cumulative; |
156 | | int32_t vpi; /*-1 if unknown*/ |
157 | | int32_t vci; /*-1 if unknown*/ |
158 | | int32_t pti; /*-1 if unknown*/ |
159 | | struct { |
160 | | /* |
161 | | * Some fields from 3rd byte of CW. Filled by cell_header dissector. |
162 | | * In in AAL5 PDU mode, this allows control_word dissector to print |
163 | | * these values in the CW heading line in the tree. |
164 | | * Meanings of values: |
165 | | * (-1) - value is unknown |
166 | | */ |
167 | | int32_t m; |
168 | | int32_t v; |
169 | | int32_t rsv; |
170 | | int32_t u; |
171 | | int32_t e; |
172 | | int32_t clp; |
173 | | } cwb3; |
174 | | bool aal5_sdu_frame_relay_cr_bit; /*see rfc4717 10.1*/ |
175 | | bool cell_mode_oam; /*atm admin cell*/ |
176 | | } pwatm_private_data_t; |
177 | | |
178 | 0 | #define PWATM_PRIVATE_DATA_T_INITIALIZER { \ |
179 | 0 | 0, PWC_PACKET_PROPERTIES_T_INITIALIZER, 0 \ |
180 | 0 | ,PWATM_MODE_UNKNOWN, PWATM_SUBMODE_DEFAULT \ |
181 | 0 | ,{-1, -1, -1, -1 } \ |
182 | 0 | ,-1, -1, -1 \ |
183 | 0 | ,{-1, -1, -1, -1, -1, -1 } \ |
184 | 0 | ,false, false, \ |
185 | 0 | } |
186 | | |
187 | 0 | #define PTI_IS_ADMIN(pti) ((pti) == 4 || (pti) == 5 || (pti) == 6) /*see atm_pt_vals[]*/ |
188 | | |
189 | 0 | #define MODE_11(mode) (PWATM_MODE_11_VCC == (mode) || PWATM_MODE_11_VPC == (mode)) |
190 | 0 | #define MODE_N1(mode) (PWATM_MODE_N1_NOCW == (mode)|| PWATM_MODE_N1_CW == (mode)) |
191 | 0 | #define MODE_11_OR_AAL5_PDU(mode) (MODE_11(mode) || PWATM_MODE_AAL5_PDU == (mode)) |
192 | | |
193 | | #define VALUE_SELECTOR_VPC_VCC_PDU(mode,val_vpc,val_vcc,val_pdu)\ |
194 | 0 | ((PWATM_MODE_11_VPC == (mode)) \ |
195 | 0 | ? (val_vpc) \ |
196 | 0 | : ((PWATM_MODE_11_VCC == (mode)) \ |
197 | 0 | ? (val_vcc) \ |
198 | 0 | : ((PWATM_MODE_AAL5_PDU == (mode)) \ |
199 | 0 | ? (val_pdu) \ |
200 | 0 | : 0 \ |
201 | 0 | ) \ |
202 | 0 | ) \ |
203 | 0 | ) |
204 | | |
205 | | #define UPDATE_CUMULATIVE_VALUE(cumulative_val,new_val)\ |
206 | 0 | do\ |
207 | 0 | {\ |
208 | 0 | if (-2 >= (cumulative_val))\ |
209 | 0 | {\ |
210 | 0 | }\ |
211 | 0 | else if (-1 == (cumulative_val))\ |
212 | 0 | {\ |
213 | 0 | (cumulative_val) = (new_val);\ |
214 | 0 | }\ |
215 | 0 | else if ((new_val) != (cumulative_val))\ |
216 | 0 | {\ |
217 | 0 | (cumulative_val) = -2;\ |
218 | 0 | }\ |
219 | 0 | }\ |
220 | 0 | while(0) |
221 | | |
222 | 0 | #define SIZEOF_ATM_CELL_PAYLOAD 48 |
223 | 0 | #define SIZEOF_N1_PW_CELL_HEADER 4 |
224 | 0 | #define SIZEOF_11_VCC_PW_CELL_HEADER 1 |
225 | 0 | #define SIZEOF_11_VPC_PW_CELL_HEADER 3 |
226 | 0 | #define SIZEOF_N1_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_N1_PW_CELL_HEADER) |
227 | 0 | #define SIZEOF_11_VCC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VCC_PW_CELL_HEADER) |
228 | 0 | #define SIZEOF_11_VPC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VPC_PW_CELL_HEADER) |
229 | | |
230 | | const char pwc_longname_pw_atm_n1_cw[] = "MPLS PW ATM N-to-One encapsulation, with CW"; |
231 | | const char pwc_longname_pw_atm_n1_nocw[] = "MPLS PW ATM N-to-One encapsulation, no CW"; |
232 | | const char pwc_longname_pw_atm_11_or_aal5_pdu[] = "MPLS PW ATM One-to-One or AAL5 PDU encapsulation"; |
233 | | const char pwc_longname_pw_atm_aal5_sdu[] = "MPLS PW ATM AAL5 CPCS-SDU mode encapsulation"; |
234 | | |
235 | | static const char longname_pw_atm_11_vcc[] = "MPLS PW ATM One-to-One VCC Cell Transport"; |
236 | | static const char longname_pw_atm_11_vpc[] = "MPLS PW ATM One-to-One VPC Cell Transport"; |
237 | | static const char longname_pw_atm_aal5_pdu[] = "MPLS PW ATM AAL5 PDU encapsulation"; |
238 | | |
239 | | static const char shortname_n1_cw[] = "MPLS PW ATM N:1 CW"; |
240 | | static const char shortname_n1_nocw[] = "MPLS PW ATM N:1 no CW"; |
241 | | static const char shortname_11_or_aal5_pdu[] = "MPLS PW ATM 1:1 / AAL5 PDU"; |
242 | | static const char shortname_11_vpc[] = "MPLS PW ATM 1:1 VPC"; |
243 | | static const char shortname_11_vcc[] = "MPLS PW ATM 1:1 VCC"; |
244 | | static const char shortname_aal5_sdu[] = "MPLS PW ATM AAL5 SDU"; |
245 | | static const char shortname_aal5_pdu[] = "MPLS PW ATM AAL5 PDU"; |
246 | | |
247 | | /* |
248 | | * These options are needed to support Nokia AXE and stuff alike. |
249 | | * Note that these options will affect PW type auto-guessing, if such heuristic |
250 | | * implemented in the future. |
251 | | */ |
252 | | static bool pref_n1_cw_allow_cw_length_nonzero; |
253 | | static bool pref_n1_cw_extend_cw_length_with_rsvd; |
254 | | static bool pref_aal5_sdu_allow_cw_length_nonzero; |
255 | | static bool pref_aal5_sdu_extend_cw_length_with_rsvd; |
256 | | |
257 | | |
258 | | static int |
259 | | pw_cell_size(const pwatm_mode_t mode, const pwatm_submode_t submode) |
260 | 0 | { |
261 | 0 | switch (mode) |
262 | 0 | { |
263 | 0 | case PWATM_MODE_N1_NOCW: |
264 | 0 | case PWATM_MODE_N1_CW: |
265 | 0 | return SIZEOF_N1_PW_CELL; |
266 | 0 | case PWATM_MODE_11_VCC: |
267 | 0 | return SIZEOF_11_VCC_PW_CELL; |
268 | 0 | case PWATM_MODE_11_VPC: |
269 | 0 | return SIZEOF_11_VPC_PW_CELL; |
270 | 0 | case PWATM_MODE_AAL5_PDU: |
271 | | /* AAL5 PDU size is n*48 bytes */ |
272 | 0 | return SIZEOF_ATM_CELL_PAYLOAD; |
273 | 0 | case PWATM_MODE_AAL5_SDU: |
274 | 0 | if (PWATM_SUBMODE_ADMIN_CELL == submode) |
275 | 0 | { |
276 | 0 | return SIZEOF_N1_PW_CELL; /*n:1 encapsulation is used for admin cells*/ |
277 | 0 | } |
278 | 0 | else |
279 | 0 | { |
280 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
281 | 0 | return 0; |
282 | 0 | } |
283 | 0 | default: |
284 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
285 | 0 | return 0; |
286 | 0 | } |
287 | 0 | } |
288 | | |
289 | | static int |
290 | | pw_cell_header_size(const pwatm_mode_t mode, const pwatm_submode_t submode) |
291 | 0 | { |
292 | 0 | switch (mode) |
293 | 0 | { |
294 | 0 | case PWATM_MODE_N1_NOCW: |
295 | 0 | case PWATM_MODE_N1_CW: |
296 | 0 | return SIZEOF_N1_PW_CELL_HEADER; |
297 | 0 | case PWATM_MODE_11_VCC: |
298 | 0 | return SIZEOF_11_VCC_PW_CELL_HEADER; |
299 | 0 | case PWATM_MODE_11_VPC: |
300 | 0 | return SIZEOF_11_VPC_PW_CELL_HEADER; |
301 | 0 | case PWATM_MODE_AAL5_SDU: |
302 | 0 | if (PWATM_SUBMODE_ADMIN_CELL == submode) |
303 | 0 | { |
304 | 0 | return SIZEOF_N1_PW_CELL_HEADER; /*n:1 encapsulation is used for admin cells*/ |
305 | 0 | } |
306 | 0 | else |
307 | 0 | { |
308 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
309 | 0 | return 0; |
310 | 0 | } |
311 | 0 | case PWATM_MODE_AAL5_PDU: /*not applicable*/ |
312 | 0 | default: |
313 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
314 | 0 | return 0; |
315 | 0 | } |
316 | 0 | } |
317 | | |
318 | | static int |
319 | | number_of_cells(const pwatm_mode_t mode |
320 | | ,const pwatm_submode_t submode |
321 | | ,const int payload_size |
322 | | ,int* const remainder_size) |
323 | 0 | { |
324 | 0 | int cells; |
325 | |
|
326 | 0 | DISSECTOR_ASSERT(payload_size >= 0); |
327 | |
|
328 | 0 | switch (mode) |
329 | 0 | { |
330 | 0 | case PWATM_MODE_N1_NOCW: |
331 | 0 | case PWATM_MODE_N1_CW: |
332 | 0 | case PWATM_MODE_11_VCC: |
333 | 0 | case PWATM_MODE_11_VPC: |
334 | 0 | case PWATM_MODE_AAL5_PDU: |
335 | 0 | cells = payload_size / pw_cell_size(mode, submode); |
336 | 0 | *remainder_size = payload_size - (cells * pw_cell_size(mode, submode)); |
337 | 0 | return cells; |
338 | 0 | case PWATM_MODE_AAL5_SDU: |
339 | 0 | if (PWATM_SUBMODE_ADMIN_CELL == submode) |
340 | 0 | { |
341 | 0 | cells = payload_size / pw_cell_size(mode, submode); |
342 | 0 | if (cells > 1) cells = 1; /*max. 1 admin cell may be present in aal5 sdu mode */ |
343 | 0 | *remainder_size = payload_size - (cells * pw_cell_size(mode, submode)); |
344 | 0 | return cells; |
345 | 0 | } |
346 | 0 | else |
347 | 0 | { |
348 | | /*not applicable*/ |
349 | 0 | } |
350 | | /*fallthrough*/ |
351 | 0 | default: |
352 | 0 | *remainder_size = payload_size; |
353 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
354 | 0 | return 0; |
355 | 0 | } |
356 | |
|
357 | 0 | } |
358 | | |
359 | | |
360 | | static void |
361 | | col_append_pw_info(packet_info * pinfo |
362 | | ,const int payload_size |
363 | | ,const int cells |
364 | | ,const int padding_size |
365 | | ,pwatm_private_data_t * pd) |
366 | 0 | { |
367 | 0 | if (pd->props & PWC_ANYOF_CW_BAD) |
368 | 0 | { |
369 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "CW:Bad"); |
370 | 0 | } |
371 | |
|
372 | 0 | if (pd->props & PWC_PAY_SIZE_BAD) |
373 | 0 | { |
374 | 0 | if (pd->props & PWC_ANYOF_CW_BAD) |
375 | 0 | { |
376 | 0 | col_append_str(pinfo->cinfo, COL_INFO, ", "); |
377 | 0 | } |
378 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, "); |
379 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%d byte%s" |
380 | 0 | ,(int)payload_size |
381 | 0 | ,plurality(payload_size, "", "s")); |
382 | 0 | } |
383 | |
|
384 | 0 | if (pd->props == 0) /*omit "atm cells" etc if something is wrong*/ |
385 | 0 | { |
386 | | /* number of cells may be not known */ |
387 | 0 | if (cells >=0) |
388 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%d ATM cell%s" |
389 | 0 | ,cells |
390 | 0 | ,plurality(cells, "", "s")); |
391 | | /* |
392 | | * Display ATM-specific attributes which are the same |
393 | | * across all the cells in the pw packet. |
394 | | * Meanings of values: |
395 | | * (-1) unknown - not displayed, |
396 | | * (-2) "not the same in all cells" - not displayed |
397 | | * positive values - ok, displayed |
398 | | */ |
399 | 0 | if (pd->cumulative.vpi >= 0) |
400 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", VPI:%.4d", pd->cumulative.vpi); |
401 | 0 | if (pd->cumulative.vci >= 0) |
402 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", VCI:%.5d", pd->cumulative.vci); |
403 | 0 | if (pd->cumulative.pti >= 0) |
404 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", PTI:%.1d", pd->cumulative.pti); |
405 | 0 | if (pd->cumulative.clp >= 0) |
406 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", CLP:%.1d", pd->cumulative.clp); |
407 | 0 | } |
408 | |
|
409 | 0 | if (padding_size != 0) |
410 | 0 | { |
411 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", %d padding" |
412 | 0 | ,(int)padding_size); |
413 | 0 | } |
414 | 0 | } |
415 | | |
416 | | |
417 | | static void |
418 | | prepare_pseudo_header_atm( |
419 | | struct atm_phdr *ph, |
420 | | const pwatm_private_data_t * const pdata, |
421 | | const unsigned aal) |
422 | 0 | { |
423 | 0 | DISSECTOR_ASSERT(NULL != pdata); |
424 | 0 | DISSECTOR_ASSERT(NULL != ph); |
425 | |
|
426 | 0 | memset(ph, 0 , sizeof(*ph)); /* it is OK to clear unknown values */ |
427 | 0 | ph->flags = 0; /* status flags */ |
428 | 0 | ph->aal = aal; |
429 | 0 | ph->type = TRAF_UNKNOWN; |
430 | 0 | ph->subtype = TRAF_ST_UNKNOWN; |
431 | 0 | ph->vpi = (pdata->vpi >= 0) ? pdata->vpi : 0 /*unknown*/; |
432 | 0 | ph->vci = (pdata->vci >= 0) ? pdata->vci : 0 /*unknown*/; |
433 | 0 | ph->aal2_cid = 0; /*not applicable*//* channel id */ |
434 | 0 | ph->channel = 0; /*unknown*//* link: 0 for DTE->DCE, 1 for DCE->DTE */ |
435 | 0 | ph->cells = 0; /*zero indicates that we do not have trailer info*/ |
436 | | /*user-to-user indicator & CPI*/ |
437 | 0 | ph->aal5t_u2u = 0; /* all bits unknown except lsb of UU */ |
438 | 0 | if (pdata->aal5_sdu_frame_relay_cr_bit) |
439 | 0 | { /* Let's give Frame Relay C/R bit to ATM dissector.*/ |
440 | 0 | ph->aal5t_u2u |= (1<<8); /*UU octet is at << 8 in aal5t_u2u*/ |
441 | 0 | } |
442 | 0 | ph->aal5t_len = 0; /*unknown*//* length of the packet from trailer*/ |
443 | 0 | ph->aal5t_chksum = 0; /*unknown*//* checksum for AAL5 packet from trailer */ |
444 | 0 | return; |
445 | 0 | } |
446 | | |
447 | | |
448 | | static void |
449 | | dissect_payload_and_padding( |
450 | | tvbuff_t * tvb |
451 | | ,packet_info * pinfo |
452 | | ,proto_tree * tree |
453 | | ,const int payload_size |
454 | | ,const int padding_size |
455 | | ,pwatm_private_data_t * pd) |
456 | 0 | { |
457 | 0 | int dissected; |
458 | 0 | tvbuff_t * tvb_2; |
459 | |
|
460 | 0 | tvbuff_t* payload_tvb = tvb_new_subset_length(tvb, 0, payload_size); |
461 | 0 | for(dissected = 0, pd->pw_cell_number = 0; |
462 | 0 | tvb_reported_length_remaining(payload_tvb, dissected); |
463 | 0 | ++(pd->pw_cell_number)) |
464 | 0 | { |
465 | 0 | tvb_2 = tvb_new_subset_remaining(payload_tvb, dissected); |
466 | 0 | dissected += call_dissector_with_data(dh_cell_header, tvb_2, pinfo, tree, pd); |
467 | |
|
468 | 0 | tvb_2 = tvb_new_subset_remaining(payload_tvb, dissected); |
469 | | /*dissect as oam for specific vci/pti, just like atm dissector does*/ |
470 | 0 | if ((pd->vci >= 0) && (pd->pti >=0)) |
471 | 0 | { |
472 | 0 | if (atm_is_oam_cell(pd->vci, pd->pti)) |
473 | 0 | { |
474 | 0 | pd->cell_mode_oam = true; |
475 | 0 | } |
476 | 0 | } |
477 | |
|
478 | 0 | if (pd->cell_mode_oam) |
479 | 0 | { |
480 | 0 | struct pw_atm_phdr ph; |
481 | 0 | int bytes_to_dissect; |
482 | | /* prepare buffer for old-style dissector */ |
483 | | /* oam cell is always 48 bytes, but payload_size may be too small */ |
484 | 0 | bytes_to_dissect = tvb_reported_length_remaining(payload_tvb, dissected); |
485 | 0 | if (bytes_to_dissect >= SIZEOF_ATM_CELL_PAYLOAD) |
486 | 0 | bytes_to_dissect = SIZEOF_ATM_CELL_PAYLOAD; |
487 | 0 | tvb_2 = tvb_new_subset_length(payload_tvb, dissected, bytes_to_dissect); |
488 | | /*aal5_sdu: disable filling columns after 1st (valid) oam cell*/ |
489 | 0 | if (pd->mode == PWATM_MODE_AAL5_SDU && (pd->pw_cell_number > 0)) |
490 | 0 | ph.enable_fill_columns_by_atm_dissector = false; |
491 | 0 | else |
492 | 0 | ph.enable_fill_columns_by_atm_dissector = true; |
493 | | /* prepare atm pseudo header for atm OAM cell decoding */ |
494 | 0 | prepare_pseudo_header_atm(&ph.info, pd, AAL_OAMCELL); |
495 | |
|
496 | 0 | call_dissector_with_data(dh_atm_oam_cell, tvb_2, pinfo, tree, &ph); |
497 | 0 | dissected += bytes_to_dissect; |
498 | 0 | } |
499 | 0 | else |
500 | 0 | { |
501 | 0 | dissected += call_dissector(dh_cell, tvb_2, pinfo, tree); |
502 | 0 | } |
503 | 0 | } |
504 | |
|
505 | 0 | if (padding_size != 0) |
506 | 0 | { |
507 | 0 | tvb_2 = tvb_new_subset_length(tvb, payload_size, padding_size); |
508 | 0 | call_dissector(dh_padding, tvb_2, pinfo, tree); |
509 | 0 | } |
510 | 0 | return; |
511 | 0 | } |
512 | | |
513 | | |
514 | | static bool |
515 | | too_small_packet_or_notpw(tvbuff_t * tvb |
516 | | ,packet_info * pinfo |
517 | | ,proto_tree * tree |
518 | | ,const int proto_handler |
519 | | ,const char * const proto_name_column) |
520 | 0 | { |
521 | 0 | int packet_size; |
522 | 0 | packet_size = tvb_reported_length_remaining(tvb, 0); |
523 | | /* |
524 | | * FIXME |
525 | | * "4" below should be replaced by something like "min_packet_size_this_dissector" |
526 | | * Also call to dissect_try_cw_first_nibble() should be moved before this block |
527 | | */ |
528 | 0 | if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */ |
529 | 0 | { |
530 | 0 | proto_item * item; |
531 | 0 | item = proto_tree_add_item(tree, proto_handler, tvb, 0, -1, ENC_NA); |
532 | 0 | expert_add_info_format(pinfo, item, &ei_pw_packet_size_too_small, |
533 | 0 | "PW packet size (%d) is too small to carry sensible information" |
534 | 0 | ,(int)packet_size); |
535 | | /* represent problems in the Packet List pane */ |
536 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column); |
537 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small"); |
538 | 0 | return true; |
539 | 0 | } |
540 | 0 | if (dissect_try_cw_first_nibble(tvb, pinfo, tree)) |
541 | 0 | { |
542 | 0 | return true; |
543 | 0 | } |
544 | 0 | return false; |
545 | 0 | } |
546 | | |
547 | | |
548 | | /* |
549 | | * NOTE. RFC describes ATM-specific byte in a cumbersome way. |
550 | | * It is a part of CW, but at the same time, it must be repeated |
551 | | * with each cell, _except_ first. |
552 | | * |
553 | | * Alternatively, ATM-specific byte may be considered as part of |
554 | | * PW payload (i.e., as part of pw atm cell header), so we can say that |
555 | | * it is being repeated with each cell. |
556 | | * |
557 | | * This dissector is written according to the latter consideration. |
558 | | */ |
559 | | static int |
560 | | dissect_11_or_aal5_pdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_) |
561 | 0 | { |
562 | 0 | const char * proto_name_column; |
563 | 0 | const char * proto_name_tree = NULL; |
564 | 0 | int payload_size; |
565 | 0 | int cells; |
566 | 0 | pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER; |
567 | |
|
568 | 0 | proto_name_column = &shortname_11_or_aal5_pdu[0]; |
569 | 0 | if (too_small_packet_or_notpw(tvb, pinfo, tree, proto_11_or_aal5_pdu, proto_name_column)) |
570 | 0 | { |
571 | 0 | return 1; |
572 | 0 | } |
573 | 0 | pd.packet_size = tvb_reported_length_remaining(tvb, 0); |
574 | | |
575 | | /* |
576 | | * Guess encapsulation mode according to M & V bits from the 3rd byte of CW. |
577 | | * Also adjust protocol name strings. |
578 | | */ |
579 | 0 | { |
580 | 0 | uint8_t third_byte; |
581 | 0 | third_byte = tvb_get_uint8(tvb, 3); |
582 | 0 | if (0 == (third_byte & 0x80 /*generic_cw.m*/)) |
583 | 0 | { /*1:1 modes*/ |
584 | 0 | if (0 != (third_byte & 0x40 /*generic_cw.v*/)) |
585 | 0 | { |
586 | 0 | pd.mode = PWATM_MODE_11_VPC; |
587 | 0 | proto_name_column = &shortname_11_vpc[0]; |
588 | 0 | proto_name_tree = &longname_pw_atm_11_vpc[0]; |
589 | 0 | } |
590 | 0 | else |
591 | 0 | { |
592 | 0 | pd.mode = PWATM_MODE_11_VCC; |
593 | 0 | proto_name_column = &shortname_11_vcc[0]; |
594 | 0 | proto_name_tree = &longname_pw_atm_11_vcc[0]; |
595 | 0 | } |
596 | 0 | } |
597 | 0 | else |
598 | 0 | { |
599 | 0 | pd.mode = PWATM_MODE_AAL5_PDU; |
600 | 0 | proto_name_column = &shortname_aal5_pdu[0]; |
601 | 0 | proto_name_tree = &longname_pw_atm_aal5_pdu[0]; |
602 | 0 | } |
603 | 0 | } |
604 | | |
605 | | |
606 | | /* check how "good" is this packet */ |
607 | 0 | pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER; |
608 | 0 | if (0 != (tvb_get_uint8(tvb, 0) & 0xf0 /*bits03*/)) |
609 | 0 | { |
610 | 0 | pd.props |= PWC_CW_BAD_BITS03; |
611 | 0 | } |
612 | 0 | if (0 != (tvb_get_uint8(tvb, 0) & 0x0f /*generic_cw.rsvd*/)) |
613 | 0 | { |
614 | 0 | pd.props |= PWC_CW_BAD_RSV; |
615 | 0 | } |
616 | | |
617 | | /* |
618 | | * Do not dissect and validate atm-specific byte (3rd byte of CW). |
619 | | * It will be dissected/validated as pw cell header. |
620 | | */ |
621 | | |
622 | | /* |
623 | | * Decide about payload length and padding. |
624 | | * |
625 | | * Is padding allowed? |
626 | | * eth header length == 14 |
627 | | * mpls label length == 4 |
628 | | * cw length == 4 |
629 | | * min payload length == 48 |
630 | | * => 14 + 4 + 4 + 48 == 70 |
631 | | * => 70 >= 64 |
632 | | * => no padding allowed |
633 | | */ |
634 | 0 | if (MODE_11(pd.mode)) |
635 | 0 | { |
636 | 0 | int bad_padding_size; |
637 | 0 | payload_size = pd.packet_size - (PWC_SIZEOF_CW-1); |
638 | 0 | cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size); |
639 | 0 | if ((0 == cells) || (0 != bad_padding_size)) |
640 | 0 | { |
641 | 0 | pd.props |= PWC_PAY_SIZE_BAD; |
642 | 0 | } |
643 | 0 | } |
644 | 0 | else |
645 | 0 | { /*aal5_pdu mode*/ |
646 | 0 | int bad_padding_size; |
647 | 0 | payload_size = pd.packet_size - PWC_SIZEOF_CW; |
648 | 0 | cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size); |
649 | | /* at least 1 cell must be present in the packet in this mode*/ |
650 | 0 | if ((1 > cells) || (0 != bad_padding_size)) |
651 | 0 | { |
652 | 0 | pd.props |= PWC_PAY_SIZE_BAD; |
653 | 0 | } |
654 | 0 | cells = -1; /*this value not needed anymore, suppress pinting of it*/ |
655 | 0 | } |
656 | |
|
657 | 0 | if (PWATM_MODE_AAL5_PDU == pd.mode) |
658 | 0 | { |
659 | | /* sub-dissectors _may_ overwrite columns in aal5_pdu mode */ |
660 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column); |
661 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
662 | 0 | col_append_pw_info(pinfo, payload_size, cells, 0, &pd); |
663 | 0 | } |
664 | |
|
665 | 0 | { |
666 | 0 | proto_item* item; |
667 | 0 | item = proto_tree_add_item(tree, proto_11_or_aal5_pdu, tvb, 0, -1, ENC_NA); |
668 | | /*overwrite heading line*/ |
669 | 0 | proto_item_set_text(item, proto_name_tree, 0/*-warn gcc 3.4.4*/); |
670 | 0 | pwc_item_append_text_n_items(item, cells, "good ATM cell"); |
671 | 0 | { |
672 | 0 | proto_tree* tree2; |
673 | 0 | tree2 = proto_item_add_subtree(item, ett_encaps); |
674 | 0 | { |
675 | 0 | proto_item* item2; |
676 | 0 | item2 = proto_tree_add_boolean(tree2 |
677 | 0 | ,VALUE_SELECTOR_VPC_VCC_PDU(pd.mode |
678 | 0 | ,hf_pw_type_11_vpc |
679 | 0 | ,hf_pw_type_11_vcc |
680 | 0 | ,hf_pw_type_aal5_pdu) |
681 | 0 | ,tvb, 0, 0, true); |
682 | 0 | proto_item_set_generated(item2); |
683 | 0 | if (MODE_11(pd.mode)) |
684 | 0 | { |
685 | 0 | item2 = proto_tree_add_int(tree2, hf_11_ncells, tvb, 0, 0, cells); |
686 | 0 | proto_item_set_generated(item2); |
687 | 0 | } |
688 | 0 | } |
689 | 0 | } |
690 | 0 | if (pd.props & PWC_PAY_SIZE_BAD) |
691 | 0 | { |
692 | 0 | expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error, |
693 | 0 | "PW payload size (%d) must be <> 0 and multiple of %d", |
694 | 0 | (int)payload_size, pw_cell_size(pd.mode, pd.submode)); |
695 | 0 | if ((payload_size != 0) && MODE_11(pd.mode)) |
696 | 0 | { |
697 | 0 | expert_add_info_format(pinfo, item, &ei_cell_broken, |
698 | 0 | "PW ATM cell [%.3d] is broken", (int)cells); |
699 | 0 | } |
700 | 0 | } |
701 | 0 | } |
702 | |
|
703 | 0 | { |
704 | 0 | tvbuff_t* tvb_2; |
705 | 0 | tvb_2 = tvb_new_subset_length(tvb, 0, PWC_SIZEOF_CW); |
706 | 0 | call_dissector_with_data(dh_control_word, tvb_2, pinfo, tree, &pd); |
707 | |
|
708 | 0 | tvb_2 = tvb_new_subset_remaining(tvb, (PWC_SIZEOF_CW-1)); |
709 | 0 | if (MODE_11(pd.mode)) |
710 | 0 | { |
711 | 0 | dissect_payload_and_padding(tvb_2, pinfo, tree, payload_size, 0, &pd); |
712 | 0 | } |
713 | 0 | else |
714 | 0 | { /*aal5_pdu mode*/ |
715 | 0 | if (payload_size != 0) |
716 | 0 | { |
717 | 0 | tvbuff_t* tvb_3; |
718 | 0 | struct atm_phdr ph; |
719 | |
|
720 | 0 | tvb_3 = tvb_new_subset_remaining(tvb_2, 1); |
721 | | /* prepare atm pseudo header for atm aal5 decoding */ |
722 | 0 | prepare_pseudo_header_atm(&ph, &pd, AAL_5); |
723 | 0 | call_dissector_with_data(dh_atm_untruncated, tvb_3, pinfo, tree, &ph); |
724 | 0 | } |
725 | 0 | } |
726 | 0 | } |
727 | |
|
728 | 0 | if (MODE_11(pd.mode)) |
729 | 0 | { |
730 | | /* overwrite everything written by sub-dissectors in 1:1 modes*/ |
731 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column); |
732 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
733 | 0 | col_append_pw_info(pinfo, payload_size, cells, 0, &pd); |
734 | 0 | } |
735 | |
|
736 | 0 | return tvb_captured_length(tvb); |
737 | 0 | } |
738 | | |
739 | | |
740 | | static int |
741 | | dissect_aal5_sdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_) |
742 | 0 | { |
743 | 0 | const char * proto_name_column; |
744 | 0 | int payload_size; |
745 | 0 | int padding_size; |
746 | 0 | int cells; |
747 | 0 | pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER; |
748 | |
|
749 | 0 | pd.mode = PWATM_MODE_AAL5_SDU; |
750 | |
|
751 | 0 | proto_name_column = &shortname_aal5_sdu[0]; |
752 | 0 | if (too_small_packet_or_notpw(tvb, pinfo, tree, proto_aal5_sdu, proto_name_column)) |
753 | 0 | { |
754 | 0 | return 1; |
755 | 0 | } |
756 | 0 | pd.packet_size = tvb_reported_length_remaining(tvb, 0); |
757 | | |
758 | | /* check how "good" is this packet */ |
759 | | /* also decide payload length from packet size and CW */ |
760 | 0 | if (0 != (tvb_get_uint8(tvb, 0) & 0xf0 /*bits03*/)) |
761 | 0 | { |
762 | 0 | pd.props |= PWC_CW_BAD_BITS03; |
763 | 0 | } |
764 | |
|
765 | 0 | pd.submode = PWATM_SUBMODE_DEFAULT; |
766 | 0 | if (0 != (tvb_get_uint8(tvb, 0) & 0x08 /*preferred_cw.T*/)) |
767 | 0 | { |
768 | 0 | pd.submode = PWATM_SUBMODE_ADMIN_CELL; |
769 | 0 | } |
770 | |
|
771 | 0 | if (! pref_aal5_sdu_extend_cw_length_with_rsvd) |
772 | 0 | { |
773 | 0 | if (0 != (tvb_get_uint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/)) |
774 | 0 | { |
775 | 0 | pd.props |= PWC_CW_BAD_RSV; |
776 | 0 | } |
777 | 0 | } |
778 | 0 | { |
779 | | /* RFC4717: |
780 | | * [ If the packet's length (defined as the length of the layer 2 payload |
781 | | * plus the length of the control word) is less than 64 bytes, the |
782 | | * length field MUST be set to the packet's length. Otherwise, the |
783 | | * length field MUST be set to zero... Note that the length field |
784 | | * is not used in the N-to-one mode and MUST be set to 0. ] |
785 | | * |
786 | | * Also we allow some "extensions"conducted by pref_xxx. |
787 | | */ |
788 | 0 | int payload_size_from_packet; |
789 | 0 | int cw_len; /*length field from cw*/ |
790 | |
|
791 | 0 | payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW; |
792 | 0 | if (pref_aal5_sdu_extend_cw_length_with_rsvd) |
793 | 0 | { |
794 | 0 | cw_len = tvb_get_uint8(tvb, 1) & 0xff; |
795 | 0 | } |
796 | 0 | else |
797 | 0 | { |
798 | 0 | cw_len = tvb_get_uint8(tvb, 1) & 0x3f; |
799 | 0 | } |
800 | | |
801 | | /* |
802 | | * Initial assumptions: no padding, |
803 | | * payload size derived from psn packet size. |
804 | | */ |
805 | 0 | payload_size = payload_size_from_packet; |
806 | 0 | padding_size = 0; |
807 | |
|
808 | 0 | if (0 == cw_len) |
809 | 0 | { |
810 | | /*keep initial assumptions*/ |
811 | 0 | } |
812 | 0 | else if (!pref_aal5_sdu_allow_cw_length_nonzero |
813 | 0 | && (PWATM_SUBMODE_ADMIN_CELL == pd.submode)) |
814 | 0 | { |
815 | | /* |
816 | | * The "allow CW.Length != 0" option affects |
817 | | * ATM admin cell submode only, because this submode |
818 | | * is equal to N:1 encapsulation. |
819 | | * CW.Length !=0 is always OK for normal (AAL5 payload) submode. |
820 | | */ |
821 | 0 | pd.props |= PWC_CW_BAD_LEN_MUST_BE_0; |
822 | 0 | } |
823 | 0 | else |
824 | 0 | { |
825 | 0 | int payload_size_from_cw; |
826 | 0 | payload_size_from_cw = cw_len - PWC_SIZEOF_CW; |
827 | 0 | if (payload_size_from_cw <= 0) |
828 | 0 | { |
829 | 0 | pd.props |= PWC_CW_BAD_PAYLEN_LE_0; |
830 | 0 | } |
831 | 0 | else if (payload_size_from_cw > payload_size_from_packet) |
832 | 0 | { |
833 | 0 | pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET; |
834 | 0 | } |
835 | 0 | else |
836 | 0 | { |
837 | |
|
838 | 0 | payload_size = payload_size_from_cw; |
839 | 0 | padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */ |
840 | 0 | if (padding_size != 0) |
841 | 0 | { |
842 | | /* |
843 | | * Padding is not allowed in ATM admin cell submode only, |
844 | | * because this submode is equal to N:1 encapsulation. |
845 | | * Padding is OK for normal (AAL5 payload) submode. |
846 | | */ |
847 | 0 | if (PWATM_SUBMODE_ADMIN_CELL == pd.submode) |
848 | 0 | { |
849 | 0 | pd.props |= PWC_CW_BAD_PADDING_NE_0; |
850 | | /*restore sizes*/ |
851 | 0 | payload_size = payload_size_from_packet; |
852 | 0 | padding_size = 0; |
853 | 0 | } |
854 | 0 | } |
855 | 0 | } |
856 | 0 | } |
857 | |
|
858 | 0 | if (PWATM_SUBMODE_ADMIN_CELL == pd.submode) |
859 | 0 | { |
860 | 0 | int bad_padding_size; |
861 | 0 | cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size); |
862 | | /* only one atm admin cell is allowed in the packet in this mode*/ |
863 | 0 | if ((1 != cells) || (0 != bad_padding_size)) |
864 | 0 | { |
865 | 0 | pd.props |= PWC_PAY_SIZE_BAD; |
866 | 0 | } |
867 | 0 | } |
868 | 0 | else |
869 | 0 | { |
870 | 0 | cells = -1; /*unknown*/ |
871 | | /* Any size is allowed for AAL5 SDU payload */ |
872 | 0 | } |
873 | 0 | } |
874 | | |
875 | | /* fill columns in Packet List */ |
876 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column); |
877 | 0 | if (PWATM_SUBMODE_ADMIN_CELL == pd.submode) |
878 | 0 | { |
879 | 0 | col_append_str(pinfo->cinfo, COL_PROTOCOL, ", OAM cell"); |
880 | 0 | } |
881 | |
|
882 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
883 | 0 | col_append_pw_info(pinfo, payload_size, cells, padding_size, &pd); |
884 | |
|
885 | 0 | { |
886 | 0 | proto_item* item; |
887 | 0 | item = proto_tree_add_item(tree, proto_aal5_sdu, tvb, 0, -1, ENC_NA); |
888 | 0 | { |
889 | 0 | proto_tree* tree2; |
890 | 0 | tree2 = proto_item_add_subtree(item, ett_encaps); |
891 | 0 | { |
892 | 0 | item = proto_tree_add_boolean(tree2, hf_pw_type_aal5_sdu, tvb, 0, 0, true); |
893 | 0 | proto_item_set_generated(item); |
894 | 0 | } |
895 | 0 | } |
896 | 0 | if (pd.props & PWC_PAY_SIZE_BAD) |
897 | 0 | { |
898 | 0 | DISSECTOR_ASSERT(PWATM_SUBMODE_ADMIN_CELL == pd.submode); |
899 | 0 | expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error, |
900 | 0 | "In ATM admin cell mode," |
901 | 0 | " PW payload size (%d) must be == %d (exactly 1 admin cell)", |
902 | 0 | (int)payload_size, (int)SIZEOF_N1_PW_CELL); |
903 | 0 | } |
904 | 0 | } |
905 | |
|
906 | 0 | { |
907 | 0 | tvbuff_t* tvb_2; |
908 | 0 | tvb_2 = tvb_new_subset_length(tvb, 0, PWC_SIZEOF_CW); |
909 | 0 | call_dissector_with_data(dh_control_word, tvb_2, pinfo, tree, &pd); |
910 | |
|
911 | 0 | tvb_2 = tvb_new_subset_remaining(tvb, PWC_SIZEOF_CW); |
912 | 0 | if (PWATM_SUBMODE_ADMIN_CELL == pd.submode) |
913 | 0 | { |
914 | 0 | dissect_payload_and_padding(tvb_2, pinfo, tree, payload_size, padding_size, &pd); |
915 | 0 | } |
916 | 0 | else /*AAL5 payload*/ |
917 | 0 | { |
918 | 0 | if (payload_size != 0) |
919 | 0 | { |
920 | 0 | tvbuff_t* tvb_3; |
921 | 0 | struct atm_phdr ph; |
922 | |
|
923 | 0 | tvb_3 = tvb_new_subset_length(tvb_2, 0, payload_size); |
924 | | /* prepare atm pseudo header for atm aal5 decoding */ |
925 | 0 | prepare_pseudo_header_atm(&ph, &pd, AAL_5); |
926 | 0 | call_dissector_with_data(dh_atm_truncated, tvb_3, pinfo, tree, &ph); /* no PAD and trailer */ |
927 | 0 | } |
928 | 0 | if (padding_size != 0) |
929 | 0 | { |
930 | 0 | tvbuff_t* tvb_3; |
931 | 0 | tvb_3 = tvb_new_subset_length(tvb_2, payload_size, padding_size); |
932 | 0 | call_dissector(dh_padding, tvb_3, pinfo, tree); |
933 | 0 | } |
934 | 0 | } |
935 | 0 | } |
936 | 0 | return tvb_captured_length(tvb); |
937 | 0 | } |
938 | | |
939 | | |
940 | | static int |
941 | | dissect_n1_cw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_) |
942 | 0 | { |
943 | 0 | const char * proto_name_column; |
944 | 0 | int payload_size; |
945 | 0 | int padding_size; |
946 | 0 | int cells; |
947 | 0 | pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER; |
948 | |
|
949 | 0 | pd.mode = PWATM_MODE_N1_CW; |
950 | |
|
951 | 0 | proto_name_column = &shortname_n1_cw[0]; |
952 | 0 | if (too_small_packet_or_notpw(tvb, pinfo, tree, proto_n1_cw, proto_name_column)) |
953 | 0 | { |
954 | 0 | return 1; |
955 | 0 | } |
956 | 0 | pd.packet_size = tvb_reported_length_remaining(tvb, 0); |
957 | | |
958 | | /* check how "good" is this packet */ |
959 | | /* also decide payload length from packet size and CW */ |
960 | 0 | pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER; |
961 | 0 | if (0 != (tvb_get_uint8(tvb, 0) & 0xf0 /*bits03*/)) |
962 | 0 | { |
963 | 0 | pd.props |= PWC_CW_BAD_BITS03; |
964 | 0 | } |
965 | 0 | if (0 != (tvb_get_uint8(tvb, 0) & 0x0f /*preferred_cw.flags*/)) |
966 | 0 | { |
967 | 0 | pd.props |= PWC_CW_BAD_FLAGS; |
968 | 0 | } |
969 | 0 | if (! pref_n1_cw_extend_cw_length_with_rsvd) |
970 | 0 | { |
971 | 0 | if (0 != (tvb_get_uint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/)) |
972 | 0 | { |
973 | 0 | pd.props |= PWC_CW_BAD_RSV; |
974 | 0 | } |
975 | 0 | } |
976 | 0 | { |
977 | | /* RFC4717: |
978 | | * [ If the packet's length (defined as the length of the layer 2 payload |
979 | | * plus the length of the control word) is less than 64 bytes, the |
980 | | * length field MUST be set to the packet's length. Otherwise, the |
981 | | * length field MUST be set to zero... Note that the length field |
982 | | * is not used in the N-to-one mode and MUST be set to 0. ] |
983 | | * |
984 | | * Also we allow some "extensions"conducted by pref_xxx. |
985 | | */ |
986 | 0 | int payload_size_from_packet; |
987 | 0 | int cw_len; /*length field from cw*/ |
988 | |
|
989 | 0 | payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW; |
990 | 0 | if (pref_n1_cw_extend_cw_length_with_rsvd) |
991 | 0 | { |
992 | 0 | cw_len = tvb_get_uint8(tvb, 1) & 0xff; |
993 | 0 | } |
994 | 0 | else |
995 | 0 | { |
996 | 0 | cw_len = tvb_get_uint8(tvb, 1) & 0x3f; |
997 | 0 | } |
998 | | |
999 | | /* |
1000 | | * Initial assumptions: no padding, |
1001 | | * payload size derived from psn packet size. |
1002 | | */ |
1003 | 0 | payload_size = payload_size_from_packet; |
1004 | 0 | padding_size = 0; |
1005 | |
|
1006 | 0 | if (0 == cw_len) |
1007 | 0 | { |
1008 | | /*keep initial assumptions*/ |
1009 | 0 | } |
1010 | 0 | else if (!pref_n1_cw_allow_cw_length_nonzero) |
1011 | 0 | { |
1012 | 0 | pd.props |= PWC_CW_BAD_LEN_MUST_BE_0; |
1013 | 0 | } |
1014 | 0 | else |
1015 | 0 | { |
1016 | 0 | int payload_size_from_cw; |
1017 | 0 | payload_size_from_cw = cw_len - PWC_SIZEOF_CW; |
1018 | 0 | if (payload_size_from_cw <= 0) |
1019 | 0 | { |
1020 | 0 | pd.props |= PWC_CW_BAD_PAYLEN_LE_0; |
1021 | 0 | } |
1022 | 0 | else if (payload_size_from_cw > payload_size_from_packet) |
1023 | 0 | { |
1024 | 0 | pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET; |
1025 | 0 | } |
1026 | 0 | else |
1027 | 0 | { |
1028 | |
|
1029 | 0 | payload_size = payload_size_from_cw; |
1030 | 0 | padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */ |
1031 | 0 | if (padding_size != 0) |
1032 | 0 | { |
1033 | 0 | pd.props |= PWC_CW_BAD_PADDING_NE_0; |
1034 | | /*restore sizes*/ |
1035 | 0 | payload_size = payload_size_from_packet; |
1036 | 0 | padding_size = 0; |
1037 | 0 | } |
1038 | 0 | } |
1039 | 0 | } |
1040 | 0 | { |
1041 | 0 | int bad_padding_size; |
1042 | 0 | cells = number_of_cells(pd.mode, pd.submode, payload_size, &bad_padding_size); |
1043 | 0 | if ((0 == cells) || (0 != bad_padding_size)) |
1044 | 0 | { |
1045 | 0 | pd.props |= PWC_PAY_SIZE_BAD; |
1046 | 0 | } |
1047 | 0 | } |
1048 | 0 | } |
1049 | |
|
1050 | 0 | { |
1051 | 0 | proto_item* item; |
1052 | 0 | item = proto_tree_add_item(tree, proto_n1_cw, tvb, 0, -1, ENC_NA); |
1053 | 0 | pwc_item_append_text_n_items(item, cells, "good ATM cell"); |
1054 | 0 | { |
1055 | 0 | proto_tree* tree2; |
1056 | 0 | tree2 = proto_item_add_subtree(item, ett_encaps); |
1057 | 0 | { |
1058 | 0 | proto_item* item2; |
1059 | 0 | item2 = proto_tree_add_boolean(tree2, hf_pw_type_n1_cw, tvb, 0, 0, true); |
1060 | 0 | proto_item_set_generated(item2); |
1061 | 0 | item2 = proto_tree_add_int(tree2, hf_n1_cw_ncells, tvb, 0, 0, cells); |
1062 | 0 | proto_item_set_generated(item2); |
1063 | 0 | } |
1064 | 0 | } |
1065 | 0 | if (pd.props & PWC_PAY_SIZE_BAD) |
1066 | 0 | { |
1067 | 0 | if (payload_size != 0) |
1068 | 0 | { |
1069 | 0 | expert_add_info_format(pinfo, item, &ei_cell_broken, |
1070 | 0 | "PW ATM cell [%.3d] is broken", (int)cells); |
1071 | 0 | expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_note, |
1072 | 0 | "PW payload size (%d) must be <>0 and multiple of %d", |
1073 | 0 | (int)payload_size, (int)SIZEOF_N1_PW_CELL); |
1074 | 0 | } |
1075 | 0 | else |
1076 | 0 | { |
1077 | 0 | expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error, |
1078 | 0 | "PW payload size (%d) must be <>0 and multiple of %d", |
1079 | 0 | (int)payload_size, (int)SIZEOF_N1_PW_CELL); |
1080 | 0 | } |
1081 | 0 | } |
1082 | 0 | } |
1083 | |
|
1084 | 0 | { |
1085 | 0 | tvbuff_t* tvb_2; |
1086 | 0 | tvb_2 = tvb_new_subset_length(tvb, 0, PWC_SIZEOF_CW); |
1087 | 0 | call_dissector_with_data(dh_control_word, tvb_2, pinfo, tree, &pd); |
1088 | |
|
1089 | 0 | tvb_2 = tvb_new_subset_remaining(tvb, PWC_SIZEOF_CW); |
1090 | 0 | dissect_payload_and_padding(tvb_2, pinfo, tree, payload_size, padding_size, &pd); |
1091 | 0 | } |
1092 | | |
1093 | | /* fill columns in Packet List */ |
1094 | | /* overwrite everything written by sub-dissectors */ |
1095 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column); |
1096 | |
|
1097 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
1098 | 0 | col_append_pw_info(pinfo, payload_size, cells, padding_size, &pd); |
1099 | 0 | return tvb_captured_length(tvb); |
1100 | 0 | } |
1101 | | |
1102 | | |
1103 | | static int |
1104 | | dissect_n1_nocw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_) |
1105 | 0 | { |
1106 | 0 | const char * proto_name_column = &shortname_n1_nocw[0]; |
1107 | 0 | int payload_size; |
1108 | 0 | int cells; |
1109 | 0 | pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER; |
1110 | |
|
1111 | 0 | pd.mode = PWATM_MODE_N1_NOCW; |
1112 | 0 | pd.packet_size = tvb_reported_length_remaining(tvb, 0); |
1113 | | |
1114 | | /* check how "good" is this packet */ |
1115 | | /* also decide payload length from packet size */ |
1116 | 0 | pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER; |
1117 | 0 | payload_size = pd.packet_size; |
1118 | 0 | { |
1119 | 0 | int bad_padding_size; |
1120 | 0 | cells = number_of_cells(pd.mode, pd.submode, pd.packet_size, &bad_padding_size); |
1121 | 0 | if ((cells == 0) || (bad_padding_size != 0)) |
1122 | 0 | { |
1123 | 0 | pd.props |= PWC_PAY_SIZE_BAD; |
1124 | 0 | } |
1125 | 0 | } |
1126 | |
|
1127 | 0 | { |
1128 | 0 | proto_item* item; |
1129 | 0 | item = proto_tree_add_item(tree, proto_n1_nocw, tvb, 0, -1, ENC_NA); |
1130 | 0 | pwc_item_append_text_n_items(item, cells, "ATM cell"); |
1131 | 0 | { |
1132 | 0 | proto_tree* tree2; |
1133 | 0 | tree2 = proto_item_add_subtree(item, ett_encaps); |
1134 | 0 | { |
1135 | 0 | proto_item* item2; |
1136 | 0 | item2 = proto_tree_add_boolean(tree2, hf_pw_type_n1_nocw, tvb, 0, 0, true); |
1137 | 0 | proto_item_set_generated(item2); |
1138 | 0 | item2 = proto_tree_add_int(tree2, hf_n1_nocw_ncells, tvb, 0, 0, cells); |
1139 | 0 | proto_item_set_generated(item2); |
1140 | 0 | } |
1141 | 0 | } |
1142 | 0 | if (pd.props & PWC_PAY_SIZE_BAD) |
1143 | 0 | { |
1144 | 0 | if (payload_size != 0) |
1145 | 0 | { |
1146 | 0 | expert_add_info_format(pinfo, item, &ei_cell_broken, |
1147 | 0 | "Last PW ATM cell [%.3d] is broken", (int)cells); |
1148 | 0 | expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_note, |
1149 | 0 | "PW payload size (%d) must be <>0 and multiple of %d", |
1150 | 0 | (int)payload_size, (int)SIZEOF_N1_PW_CELL); |
1151 | 0 | } |
1152 | 0 | else |
1153 | 0 | { |
1154 | 0 | expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error, |
1155 | 0 | "PW payload size (%d) must be <>0 and multiple of %d", |
1156 | 0 | (int)payload_size, (int)SIZEOF_N1_PW_CELL); |
1157 | 0 | } |
1158 | 0 | } |
1159 | 0 | } |
1160 | |
|
1161 | 0 | dissect_payload_and_padding(tvb, pinfo, tree, payload_size, 0, &pd); |
1162 | | |
1163 | | /* fill columns in Packet List */ |
1164 | | /* overwrite everything written by sub-dissectors */ |
1165 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column); |
1166 | |
|
1167 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
1168 | 0 | col_append_pw_info(pinfo, payload_size, cells, 0, &pd); |
1169 | 0 | return tvb_captured_length(tvb); |
1170 | 0 | } |
1171 | | |
1172 | | |
1173 | | static void |
1174 | | proto_item_append_text_cwb3_fields(proto_item * item, const pwatm_private_data_t * const pd) |
1175 | 0 | { |
1176 | 0 | if (NULL == item) return; |
1177 | 0 | DISSECTOR_ASSERT(NULL != pd); |
1178 | 0 | if (pd->cwb3.m >= 0) |
1179 | 0 | proto_item_append_text(item, "M:%.1u " , (unsigned)(pd->cwb3.m)); |
1180 | 0 | if (pd->cwb3.v >= 0) |
1181 | 0 | proto_item_append_text(item, "V:%.1u " , (unsigned)(pd->cwb3.v)); |
1182 | 0 | if (pd->cwb3.rsv >= 0) |
1183 | 0 | proto_item_append_text(item, "RSV:%.1u ", (unsigned)(pd->cwb3.rsv)); |
1184 | 0 | if (pd->cwb3.u >= 0) |
1185 | 0 | proto_item_append_text(item, "U:%.1u " , (unsigned)(pd->cwb3.u)); |
1186 | 0 | if (pd->cwb3.e >= 0) |
1187 | 0 | proto_item_append_text(item, "EFCI:%.1u ",(unsigned)(pd->cwb3.e)); |
1188 | 0 | if (pd->cwb3.clp >= 0) |
1189 | 0 | proto_item_append_text(item, "CLP:%.1u ", (unsigned)(pd->cwb3.clp)); |
1190 | 0 | return; |
1191 | 0 | } |
1192 | | |
1193 | | |
1194 | | static int |
1195 | | dissect_control_word(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data) |
1196 | 0 | { |
1197 | 0 | pwatm_private_data_t* pd; |
1198 | | |
1199 | | /* Reject the packet if data is NULL */ |
1200 | 0 | if (data == NULL) |
1201 | 0 | return 0; |
1202 | 0 | pd = (pwatm_private_data_t *)data; |
1203 | | |
1204 | | /* |
1205 | | * NB: do not touch columns -- keep info from previous dissector |
1206 | | */ |
1207 | |
|
1208 | 0 | { |
1209 | 0 | int size; |
1210 | 0 | size = tvb_reported_length_remaining(tvb, 0); |
1211 | 0 | if (size < PWC_SIZEOF_CW) |
1212 | 0 | { |
1213 | 0 | proto_item *item; |
1214 | 0 | item = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, ENC_NA); |
1215 | 0 | expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error, |
1216 | 0 | "Packet (size: %d) is too small to carry MPLS PW Control Word" |
1217 | 0 | ,(int)size); |
1218 | 0 | return tvb_captured_length(tvb); |
1219 | 0 | } |
1220 | 0 | } |
1221 | | |
1222 | 0 | { |
1223 | 0 | proto_item* item_top; |
1224 | 0 | proto_tree* tree2; |
1225 | 0 | proto_item* item; |
1226 | |
|
1227 | 0 | item_top = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, ENC_NA); |
1228 | 0 | pwc_item_append_cw(item_top, tvb_get_ntohl(tvb, 0), false); |
1229 | |
|
1230 | 0 | tree2 = proto_item_add_subtree(item_top, ett_cw); |
1231 | | |
1232 | | /* bits 0..3 */ |
1233 | 0 | item = proto_tree_add_item(tree2, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN); |
1234 | 0 | if (pd->props & PWC_CW_BAD_BITS03) |
1235 | 0 | { |
1236 | | /* add item to tree (and show it) only if its value is wrong*/ |
1237 | 0 | expert_add_info(pinfo, item, &ei_cw_bits03); |
1238 | 0 | } |
1239 | 0 | else |
1240 | 0 | { |
1241 | 0 | proto_item_set_hidden(item); /* show only in error cases */ |
1242 | 0 | } |
1243 | | |
1244 | | /* flags */ |
1245 | 0 | if (MODE_N1(pd->mode)) |
1246 | 0 | { |
1247 | 0 | item = proto_tree_add_item(tree2, hf_pref_cw_flags, tvb, 0, 1, ENC_BIG_ENDIAN); |
1248 | 0 | if (pd->props & PWC_CW_BAD_FLAGS) |
1249 | 0 | { |
1250 | 0 | expert_add_info(pinfo, item, &ei_pref_cw_flags); |
1251 | 0 | } |
1252 | 0 | } |
1253 | 0 | if (pd->mode == PWATM_MODE_AAL5_SDU) |
1254 | 0 | { |
1255 | 0 | proto_tree_add_item(tree2, hf_pref_cw_a5s_t, tvb, 0, 1, ENC_BIG_ENDIAN); |
1256 | 0 | proto_tree_add_item(tree2, hf_pref_cw_a5s_e, tvb, 0, 1, ENC_BIG_ENDIAN); |
1257 | 0 | proto_tree_add_item(tree2, hf_pref_cw_a5s_c, tvb, 0, 1, ENC_BIG_ENDIAN); |
1258 | 0 | proto_tree_add_item(tree2, hf_pref_cw_a5s_u, tvb, 0, 1, ENC_BIG_ENDIAN); |
1259 | | /* |
1260 | | * rfc4717: [When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916] |
1261 | | * traffic is being transported, the CPCS-UU Least Significant Bit |
1262 | | * (LSB) of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit. |
1263 | | * The ingress router, PE1, SHOULD copy this bit to the U bit of the |
1264 | | * control word. The egress router, PE2, SHOULD copy the U bit to |
1265 | | * the CPCS-UU Least Significant Bit (LSB) of the AAL5 CPCS PDU.] |
1266 | | * |
1267 | | * Let's remember this bit (and then transfer it to ATM dissector). |
1268 | | */ |
1269 | 0 | pd->aal5_sdu_frame_relay_cr_bit = |
1270 | 0 | (0 == (tvb_get_uint8(tvb, 0) & 0x01 /*preferred_cw.U*/)) |
1271 | 0 | ? false : true; |
1272 | 0 | } |
1273 | | |
1274 | | /* reserved bits */ |
1275 | 0 | if (MODE_11_OR_AAL5_PDU(pd->mode) |
1276 | 0 | || (MODE_N1(pd->mode) && !pref_n1_cw_extend_cw_length_with_rsvd) |
1277 | | /* for N:1 add RSV only if it is NOT used in length */ |
1278 | 0 | || ((pd->mode == PWATM_MODE_AAL5_SDU) && !pref_aal5_sdu_extend_cw_length_with_rsvd) |
1279 | 0 | /* for AAl5 SDU add RSV only if it is NOT used in length */) |
1280 | 0 | { |
1281 | 0 | if (MODE_11_OR_AAL5_PDU(pd->mode)) |
1282 | 0 | { |
1283 | 0 | item = proto_tree_add_item(tree2 |
1284 | 0 | ,hf_generic_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN); |
1285 | 0 | } |
1286 | 0 | else |
1287 | 0 | { /*preferred cw*/ |
1288 | 0 | item = proto_tree_add_item(tree2 |
1289 | 0 | ,hf_pref_cw_rsv, tvb, 1, 1, ENC_BIG_ENDIAN); |
1290 | 0 | } |
1291 | |
|
1292 | 0 | if (pd->props & PWC_CW_BAD_RSV) |
1293 | 0 | { |
1294 | 0 | expert_add_info(pinfo, item, &ei_cw_bits03); |
1295 | 0 | } |
1296 | 0 | else |
1297 | 0 | { |
1298 | 0 | proto_item_set_hidden(item); /*...and show only in error cases */ |
1299 | 0 | } |
1300 | 0 | } |
1301 | | |
1302 | | /* length */ |
1303 | 0 | if (MODE_N1(pd->mode) |
1304 | 0 | || (PWATM_MODE_AAL5_SDU == pd->mode)) |
1305 | 0 | { |
1306 | 0 | { |
1307 | 0 | int hf_len = hf_pref_cw_len; |
1308 | 0 | if (MODE_N1(pd->mode)) |
1309 | 0 | { |
1310 | 0 | if (pref_n1_cw_extend_cw_length_with_rsvd) |
1311 | 0 | hf_len = hf_pref_cw_rsvlen; |
1312 | 0 | } |
1313 | 0 | else /*PW_MODE_AAL5_SDU*/ |
1314 | 0 | { |
1315 | 0 | if (pref_aal5_sdu_extend_cw_length_with_rsvd) |
1316 | 0 | hf_len = hf_pref_cw_rsvlen; |
1317 | 0 | } |
1318 | 0 | item = proto_tree_add_item(tree2, hf_len, tvb, 1, 1, ENC_BIG_ENDIAN); |
1319 | 0 | } |
1320 | 0 | if (pd->props & PWC_CW_BAD_LEN_MUST_BE_0) |
1321 | 0 | { |
1322 | 0 | expert_add_info_format(pinfo, item, &ei_pref_cw_len, |
1323 | 0 | "Bad Length: must be 0 for this encapsulation"); |
1324 | 0 | } |
1325 | 0 | if (pd->props & PWC_CW_BAD_PAYLEN_LE_0) |
1326 | 0 | { |
1327 | 0 | expert_add_info_format(pinfo, item, &ei_pref_cw_len, |
1328 | 0 | "Bad Length: too small, must be >= %d", |
1329 | 0 | (int)(PWC_SIZEOF_CW+SIZEOF_N1_PW_CELL)); |
1330 | 0 | } |
1331 | 0 | if (pd->props & PWC_CW_BAD_PAYLEN_GT_PACKET) |
1332 | 0 | { |
1333 | 0 | expert_add_info_format(pinfo, item, &ei_pref_cw_len, |
1334 | 0 | "Bad Length: must be <= than PSN packet size (%d)", |
1335 | 0 | (int)pd->packet_size); |
1336 | 0 | } |
1337 | 0 | if (pd->props & PWC_CW_BAD_PADDING_NE_0) |
1338 | 0 | { |
1339 | 0 | expert_add_info_format(pinfo, item, &ei_pref_cw_len, |
1340 | 0 | "Bad Length: must be == PSN packet size (%d), no padding allowed", |
1341 | 0 | (int)pd->packet_size); |
1342 | 0 | } |
1343 | 0 | } |
1344 | | |
1345 | | /* sequence number */ |
1346 | 0 | proto_tree_add_item(tree2, hf_cw_seq, tvb |
1347 | 0 | ,MODE_11_OR_AAL5_PDU(pd->mode) ? 1 : 2, 2, ENC_BIG_ENDIAN); |
1348 | | |
1349 | | /* atm-specific byte */ |
1350 | 0 | if (MODE_11(pd->mode)) |
1351 | 0 | { |
1352 | 0 | item = proto_tree_add_item(tree2, hf_gen_cw_atmbyte, tvb, 3, 1, ENC_BIG_ENDIAN); |
1353 | 0 | expert_add_info_format(pinfo, item, &ei_gen_cw_atmbyte, |
1354 | 0 | "ATM-specific byte of CW is fully dissected below as %s%s" |
1355 | 0 | ,(PWATM_MODE_11_VPC == pd->mode) ? "a part of " : "" |
1356 | 0 | ,"PW ATM Cell Header [000]"); |
1357 | | /* |
1358 | | * Note: if atm-specific byte contains something wrong |
1359 | | * (e.g. non-zero RSV or inadequate V), CW is not |
1360 | | * marked as "bad". |
1361 | | */ |
1362 | 0 | } |
1363 | | |
1364 | | /*3rd byte of CW*/ |
1365 | 0 | if (PWATM_MODE_AAL5_PDU == pd->mode) |
1366 | 0 | { |
1367 | 0 | tvbuff_t* tvb_2; |
1368 | 0 | tvb_2 = tvb_new_subset_remaining(tvb, (PWC_SIZEOF_CW-1)); |
1369 | 0 | call_dissector_with_data(dh_cell_header, tvb_2, pinfo, tree2, pd); |
1370 | 0 | proto_item_append_text(item_top, ", "); |
1371 | 0 | proto_item_append_text_cwb3_fields(item_top, pd); |
1372 | 0 | } |
1373 | 0 | } |
1374 | |
|
1375 | 0 | return tvb_captured_length(tvb); |
1376 | 0 | } |
1377 | | |
1378 | | |
1379 | | /* |
1380 | | * This function is also used to dissect 3rd byte of CW in AAL5 PDU mode. |
1381 | | */ |
1382 | | static int |
1383 | | dissect_cell_header(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data) |
1384 | 0 | { |
1385 | 0 | pwatm_private_data_t * pd; |
1386 | 0 | bool is_enough_data; |
1387 | 0 | int dissect_size; |
1388 | | |
1389 | | /* Reject the packet if data is NULL */ |
1390 | 0 | if (data == NULL) |
1391 | 0 | return 0; |
1392 | 0 | pd = (pwatm_private_data_t *)data; |
1393 | |
|
1394 | 0 | pd->vpi = pd->vci = pd->pti = -1; |
1395 | 0 | pd->cwb3.clp = pd->cwb3.m = pd->cwb3.v = pd->cwb3.rsv = pd->cwb3.u = pd->cwb3.e = -1; |
1396 | |
|
1397 | 0 | if (PWATM_MODE_AAL5_PDU == pd->mode) |
1398 | 0 | { |
1399 | 0 | if (tvb_reported_length_remaining(tvb, 0) < 1) |
1400 | 0 | { |
1401 | 0 | is_enough_data = false; |
1402 | 0 | dissect_size = 0; |
1403 | 0 | } |
1404 | 0 | else |
1405 | 0 | { |
1406 | 0 | is_enough_data = true; |
1407 | 0 | dissect_size = 1; |
1408 | 0 | } |
1409 | 0 | } |
1410 | 0 | else |
1411 | 0 | { |
1412 | 0 | int size; |
1413 | 0 | size = tvb_reported_length_remaining(tvb, 0); |
1414 | |
|
1415 | 0 | if (size < pw_cell_header_size(pd->mode, pd->submode)) |
1416 | 0 | { |
1417 | 0 | is_enough_data = false; |
1418 | 0 | dissect_size = size; |
1419 | 0 | } |
1420 | 0 | else |
1421 | 0 | { |
1422 | 0 | is_enough_data = true; |
1423 | 0 | dissect_size = pw_cell_header_size(pd->mode, pd->submode); |
1424 | 0 | } |
1425 | 0 | } |
1426 | | |
1427 | | /* |
1428 | | * NB: do not touch columns -- keep info from previous dissector |
1429 | | */ |
1430 | | |
1431 | | /* Collect info for upper-level dissectors regardless of |
1432 | | * the presence of the tree |
1433 | | */ |
1434 | 0 | if (is_enough_data) |
1435 | 0 | { |
1436 | 0 | uint8_t tmp8; |
1437 | 0 | switch (pd->mode) |
1438 | 0 | { |
1439 | 0 | case PWATM_MODE_AAL5_SDU: |
1440 | 0 | DISSECTOR_ASSERT(pd->submode == PWATM_SUBMODE_ADMIN_CELL); |
1441 | | /*fallthrough for ATM admin cell submode only*/ |
1442 | | /* FALL THROUGH */ |
1443 | 0 | case PWATM_MODE_N1_CW: |
1444 | 0 | case PWATM_MODE_N1_NOCW: |
1445 | 0 | pd->vpi = (tvb_get_ntohs (tvb, 0) >> 4); |
1446 | 0 | pd->vci = (tvb_get_ntoh24(tvb, 1) >> 4) & 0xffff; |
1447 | 0 | tmp8 = (tvb_get_uint8(tvb, 3)); |
1448 | 0 | pd->pti = (tmp8 >> 1) & 0x07; |
1449 | 0 | pd->cwb3.clp = (tmp8 >> 0) & 0x01; |
1450 | 0 | UPDATE_CUMULATIVE_VALUE(pd->cumulative.vpi, pd->vpi); |
1451 | 0 | UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci, pd->vci); |
1452 | 0 | UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti, pd->pti); |
1453 | 0 | UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp, pd->cwb3.clp); |
1454 | | /* |
1455 | | * OAM cell mode is always used for aal5_sdu/admin_cell mode, |
1456 | | * even if pti indicates user cell. |
1457 | | */ |
1458 | 0 | pd->cell_mode_oam = |
1459 | 0 | ((pd->mode == PWATM_MODE_AAL5_SDU) && (pd->submode == PWATM_SUBMODE_ADMIN_CELL)) |
1460 | 0 | || PTI_IS_ADMIN(pd->pti); |
1461 | 0 | break; |
1462 | 0 | case PWATM_MODE_11_VPC: |
1463 | 0 | pd->vci = tvb_get_ntohs(tvb, 1); |
1464 | 0 | UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci, pd->vci); |
1465 | | /*fallthrough*/ |
1466 | 0 | case PWATM_MODE_11_VCC: |
1467 | 0 | tmp8 = (tvb_get_uint8(tvb, 0)); |
1468 | 0 | pd->cwb3.m = (tmp8 >> 7) & 0x1; |
1469 | 0 | pd->cwb3.v = (tmp8 >> 6) & 0x1; |
1470 | 0 | pd->cwb3.rsv = (tmp8 >> 4) & 0x3; |
1471 | 0 | pd->pti = (tmp8 >> 1) & 0x7; |
1472 | 0 | pd->cwb3.clp = (tmp8 >> 0) & 0x1; |
1473 | 0 | UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti, pd->pti); |
1474 | 0 | UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp, pd->cwb3.clp); |
1475 | | /* |
1476 | | * OAM cell mode is possible if packet contains atm cell (m == 0). |
1477 | | */ |
1478 | 0 | pd->cell_mode_oam = PTI_IS_ADMIN(pd->pti) && (pd->cwb3.m == 0); |
1479 | 0 | break; |
1480 | 0 | case PWATM_MODE_AAL5_PDU: |
1481 | 0 | tmp8 = (tvb_get_uint8(tvb, 0)); |
1482 | 0 | pd->cwb3.m = (tmp8 >> 7) & 0x1; |
1483 | 0 | pd->cwb3.v = (tmp8 >> 6) & 0x1; |
1484 | 0 | pd->cwb3.rsv = (tmp8 >> 3) & 0x7; |
1485 | 0 | pd->cwb3.u = (tmp8 >> 2) & 0x1; |
1486 | 0 | pd->cwb3.e = (tmp8 >> 1) & 0x1; |
1487 | 0 | pd->cwb3.clp = (tmp8 >> 0) & 0x1; |
1488 | 0 | UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp, pd->cwb3.clp); |
1489 | 0 | break; |
1490 | 0 | default: |
1491 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1492 | 0 | break; |
1493 | 0 | } |
1494 | 0 | } |
1495 | | |
1496 | 0 | { |
1497 | 0 | proto_item* item; |
1498 | |
|
1499 | 0 | item = proto_tree_add_item(tree, proto_cell_header, tvb |
1500 | 0 | ,0 |
1501 | 0 | ,dissect_size |
1502 | 0 | ,ENC_NA); |
1503 | 0 | if (PWATM_MODE_AAL5_PDU == pd->mode) |
1504 | 0 | { |
1505 | 0 | proto_item_set_text(item, "Third byte of Control Word"); /*overwrite heading line*/ |
1506 | | /* cwb3 fileds are appended to CW heading line, not here */ |
1507 | 0 | } |
1508 | 0 | else |
1509 | 0 | { |
1510 | 0 | proto_item_append_text(item, " [%.3d]", pd->pw_cell_number); |
1511 | 0 | proto_item_append_text(item, ", "); |
1512 | 0 | if (pd->vpi >= 0) |
1513 | 0 | proto_item_append_text(item, "VPI:%.4u ", (unsigned)(pd->vpi)); |
1514 | 0 | if (pd->vci >= 0) |
1515 | 0 | proto_item_append_text(item, "VCI:%.5u ", (unsigned)(pd->vci)); |
1516 | 0 | if (pd->pti >= 0) |
1517 | 0 | proto_item_append_text(item, "PTI:%.1u ", (unsigned)(pd->pti)); |
1518 | 0 | proto_item_append_text_cwb3_fields(item, pd); |
1519 | 0 | } |
1520 | |
|
1521 | 0 | { |
1522 | 0 | proto_tree* tree2; |
1523 | 0 | tree2 = proto_item_add_subtree(item, ett_cell_header); |
1524 | 0 | if (is_enough_data) |
1525 | 0 | { |
1526 | 0 | proto_item* item2; |
1527 | 0 | if (MODE_N1(pd->mode) |
1528 | 0 | || ((pd->mode == PWATM_MODE_AAL5_SDU) && (pd->submode == PWATM_SUBMODE_ADMIN_CELL))) |
1529 | 0 | { |
1530 | 0 | proto_tree_add_uint(tree2, hf_cell_h_vpi, tvb, 0, 2, (unsigned)pd->vpi); |
1531 | 0 | proto_tree_add_uint(tree2, hf_cell_h_vci, tvb, 1, 3, (unsigned)pd->vci); |
1532 | |
|
1533 | 0 | item2 = proto_tree_add_item(tree2, hf_cell_h_pti, tvb, 3, 1, ENC_BIG_ENDIAN); |
1534 | 0 | if (NULL == try_val_to_str(pd->pti, atm_pt_vals)) |
1535 | 0 | { |
1536 | 0 | expert_add_info_format(pinfo, item2, &ei_cell_h_pti_undecoded, |
1537 | 0 | "Unknown value of PTI field (%d) in the ATM cell header", |
1538 | 0 | pd->pti); |
1539 | 0 | } |
1540 | 0 | else if ((pd->mode == PWATM_MODE_AAL5_SDU) && !PTI_IS_ADMIN(pd->pti)) |
1541 | 0 | { |
1542 | 0 | expert_add_info_format(pinfo, item2, &ei_cell_h_pti_malformed, |
1543 | 0 | "ATM admin cell is transerred;" |
1544 | 0 | " PTI field (%d) should be 4, 5 or 6.", |
1545 | 0 | pd->pti); |
1546 | 0 | } |
1547 | |
|
1548 | 0 | proto_tree_add_item(tree2, hf_cell_h_clp, tvb, 3, 1, ENC_BIG_ENDIAN); |
1549 | 0 | } |
1550 | 0 | else if (MODE_11_OR_AAL5_PDU(pd->mode)) |
1551 | 0 | { |
1552 | 0 | item2 = proto_tree_add_item(tree2, hf_cell_h_m , tvb, 0, 1, ENC_BIG_ENDIAN); |
1553 | 0 | if ((0 != pd->cwb3.m) && MODE_11(pd->mode)) |
1554 | 0 | { |
1555 | 0 | expert_add_info(pinfo, item2, &ei_cell_h_m); |
1556 | 0 | } |
1557 | |
|
1558 | 0 | item2 = proto_tree_add_item(tree2, hf_cell_h_v , tvb, 0, 1, ENC_BIG_ENDIAN); |
1559 | 0 | if ((0 == pd->cwb3.v) && (PWATM_MODE_11_VPC == pd->mode)) |
1560 | 0 | { |
1561 | 0 | expert_add_info(pinfo, item2, &ei_cell_h_v_not_zero); |
1562 | 0 | } |
1563 | 0 | if ((0 != pd->cwb3.v) && (PWATM_MODE_11_VCC == pd->mode)) |
1564 | 0 | { |
1565 | 0 | expert_add_info_format(pinfo, item2, &ei_cell_h_v_not_one, |
1566 | 0 | "1:1 VCC mode:" |
1567 | 0 | " V bit must be 0 to indicate that VCI is absent"); |
1568 | 0 | } |
1569 | 0 | if ((0 != pd->cwb3.v) && (PWATM_MODE_AAL5_PDU == pd->mode)) |
1570 | 0 | { |
1571 | 0 | expert_add_info_format(pinfo, item2, &ei_cell_h_v_not_one, |
1572 | 0 | "AAL5 PDU mode:" |
1573 | 0 | " V bit must be 0 to indicate that VCI is absent"); |
1574 | 0 | } |
1575 | |
|
1576 | 0 | item2 = proto_tree_add_item(tree2 |
1577 | 0 | ,(PWATM_MODE_AAL5_PDU == pd->mode) |
1578 | 0 | ? hf_aal5_pdu_rsv |
1579 | 0 | : hf_cell_h_rsv |
1580 | 0 | ,tvb, 0, 1, ENC_BIG_ENDIAN); |
1581 | 0 | if (0 != pd->cwb3.rsv) |
1582 | 0 | { |
1583 | 0 | expert_add_info(pinfo, item2, &ei_cell_h_rsv); |
1584 | 0 | } |
1585 | 0 | else |
1586 | 0 | { |
1587 | 0 | proto_item_set_hidden(item2); /*...and show only in error cases */ |
1588 | 0 | } |
1589 | |
|
1590 | 0 | if (MODE_11(pd->mode)) |
1591 | 0 | { |
1592 | 0 | item2 = proto_tree_add_item(tree2, hf_cell_h_pti, tvb, 0, 1, ENC_BIG_ENDIAN); |
1593 | 0 | if (NULL == try_val_to_str(pd->pti, atm_pt_vals)) |
1594 | 0 | { |
1595 | 0 | expert_add_info_format(pinfo, item2, &ei_cell_h_pti_undecoded, |
1596 | 0 | "Unknown value of PTI field (%d) in the atm-specific byte" |
1597 | 0 | ,pd->pti); |
1598 | 0 | } |
1599 | 0 | } |
1600 | 0 | else |
1601 | 0 | { |
1602 | 0 | proto_tree_add_item(tree2, hf_aal5_pdu_u, tvb, 0, 1, ENC_BIG_ENDIAN); |
1603 | 0 | proto_tree_add_item(tree2, hf_aal5_pdu_e, tvb, 0, 1, ENC_BIG_ENDIAN); |
1604 | 0 | } |
1605 | |
|
1606 | 0 | proto_tree_add_item(tree2, hf_cell_h_clp, tvb, 0, 1, ENC_BIG_ENDIAN); |
1607 | |
|
1608 | 0 | if (PWATM_MODE_11_VPC == pd->mode) |
1609 | 0 | { |
1610 | 0 | proto_tree_add_uint(tree2, hf_cell_h_vci, tvb, 1, 2 |
1611 | 0 | ,(unsigned)pd->vci); |
1612 | 0 | } |
1613 | 0 | } |
1614 | 0 | else |
1615 | 0 | { |
1616 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1617 | 0 | } |
1618 | 0 | } |
1619 | 0 | else |
1620 | 0 | { |
1621 | 0 | expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error, |
1622 | 0 | "Not enough data (size: %d), impossible to decode", |
1623 | 0 | (int)dissect_size); |
1624 | 0 | } |
1625 | 0 | } |
1626 | 0 | } |
1627 | 0 | return dissect_size; |
1628 | 0 | } |
1629 | | |
1630 | | |
1631 | | |
1632 | | static int |
1633 | | dissect_cell(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data) |
1634 | 0 | { |
1635 | 0 | bool is_enough_data; |
1636 | 0 | int dissect_size; |
1637 | 0 | int size; |
1638 | 0 | proto_item* item; |
1639 | 0 | pwatm_private_data_t * pd = (pwatm_private_data_t *)data; |
1640 | |
|
1641 | 0 | size = tvb_reported_length_remaining(tvb, 0); |
1642 | 0 | if (size < SIZEOF_ATM_CELL_PAYLOAD) |
1643 | 0 | { |
1644 | 0 | is_enough_data = false; |
1645 | 0 | dissect_size = size; |
1646 | 0 | } |
1647 | 0 | else |
1648 | 0 | { |
1649 | 0 | is_enough_data = true; |
1650 | 0 | dissect_size = SIZEOF_ATM_CELL_PAYLOAD; |
1651 | 0 | } |
1652 | | |
1653 | | /* |
1654 | | * NB: do not touch columns -- keep info from previous dissector |
1655 | | */ |
1656 | |
|
1657 | 0 | item = proto_tree_add_item(tree, proto_cell, tvb, 0, dissect_size, ENC_NA); |
1658 | 0 | if (NULL != pd) |
1659 | 0 | proto_item_append_text(item, " [%.3d]", pd->pw_cell_number); |
1660 | |
|
1661 | 0 | pwc_item_append_text_n_items(item, dissect_size, "byte"); |
1662 | 0 | if (!is_enough_data) |
1663 | 0 | { |
1664 | 0 | expert_add_info_format(pinfo, item, &ei_pw_payload_size_invalid_error, |
1665 | 0 | "Bad length of cell payload: must be == %d", |
1666 | 0 | (int)SIZEOF_ATM_CELL_PAYLOAD); |
1667 | 0 | } |
1668 | |
|
1669 | 0 | { |
1670 | 0 | proto_tree* tree2; |
1671 | 0 | tvbuff_t* tvb_d; |
1672 | 0 | tree2 = proto_item_add_subtree(item, ett_cell); |
1673 | 0 | tvb_d = tvb_new_subset_length(tvb, 0, dissect_size); |
1674 | 0 | call_data_dissector(tvb_d, pinfo, tree2); |
1675 | 0 | item = proto_tree_add_int(tree2, hf_cell_payload_len, tvb, 0, 0, dissect_size); |
1676 | 0 | proto_item_set_hidden(item); |
1677 | 0 | } |
1678 | |
|
1679 | 0 | return dissect_size; |
1680 | 0 | } |
1681 | | |
1682 | | |
1683 | | void |
1684 | | proto_register_pw_atm_ata(void) |
1685 | 16 | { |
1686 | 16 | static const value_string clp_vals[] = { |
1687 | 16 | { 0, "High priority" }, |
1688 | 16 | { 1, "Low priority" }, |
1689 | 16 | { 0, NULL } |
1690 | 16 | }; |
1691 | 16 | static const value_string m_vals[] = { |
1692 | 16 | { 0, "ATM cell" }, |
1693 | 16 | { 1, "AAL5 payload" }, |
1694 | 16 | { 0, NULL } |
1695 | 16 | }; |
1696 | 16 | static const value_string u_vals[] = { |
1697 | 16 | { 0, "This frame does not contain the last cell of AAL5 PDU" }, |
1698 | 16 | { 1, "This frame contains the last cell of AAL5 PDU" }, |
1699 | 16 | { 0, NULL } |
1700 | 16 | }; |
1701 | 16 | static const value_string e_vals[] = { |
1702 | 16 | { 0, "Congestion is not experienced" }, |
1703 | 16 | { 1, "Congestion is experienced for one or more ATM AAL5 cells" }, |
1704 | 16 | { 0, NULL } |
1705 | 16 | }; |
1706 | 16 | static hf_register_info hfa_cell_header[] = { |
1707 | 16 | { &hf_cell_h_vpi ,{"VPI" ,"atm.vpi" |
1708 | 16 | ,FT_UINT16 ,BASE_DEC ,NULL ,0 |
1709 | 16 | ,NULL ,HFILL }}, |
1710 | | |
1711 | 16 | { &hf_cell_h_vci ,{"VCI" ,"atm.vci" |
1712 | 16 | ,FT_UINT16 ,BASE_DEC ,NULL ,0 |
1713 | 16 | ,NULL ,HFILL }}, |
1714 | | |
1715 | 16 | { &hf_cell_h_pti ,{"Payload Type" ,"atm.pti" |
1716 | 16 | ,FT_UINT8 ,BASE_DEC ,VALS(atm_pt_vals),0x0e |
1717 | 16 | ,"The 3-bit Payload Type Identifier (PTI) incorporates ATM Layer" |
1718 | 16 | " PTI coding of the cell. These bits are set to the value of the" |
1719 | 16 | " PTI of the encapsulated ATM cell." |
1720 | 16 | ,HFILL }}, |
1721 | | |
1722 | 16 | { &hf_cell_h_clp ,{"Cell Loss Priority" ,"atm.clp" |
1723 | 16 | ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x01 |
1724 | 16 | ,"The Cell Loss Priority (CLP) field indicates CLP value" |
1725 | 16 | " of the encapsulated cell." |
1726 | 16 | ,HFILL }}, |
1727 | | |
1728 | 16 | { &hf_cell_h_m ,{"Transport Mode" ,"atm.pw_control_byte.m" |
1729 | 16 | ,FT_UINT8 ,BASE_DEC ,VALS(m_vals) ,0x80 |
1730 | 16 | ,"Bit (M) of the control byte indicates whether the packet" |
1731 | 16 | " contains an ATM cell or a frame payload. If set to 0," |
1732 | 16 | " the packet contains an ATM cell. If set to 1, the PDU" |
1733 | 16 | " contains an AAL5 payload." |
1734 | 16 | ,HFILL }}, |
1735 | | |
1736 | 16 | { &hf_cell_h_v ,{"VCI Present" ,"atm.pw_control_byte.v" |
1737 | 16 | ,FT_BOOLEAN ,8 ,TFS(&tfs_yes_no),0x40 |
1738 | 16 | ,"Bit (V) of the control byte indicates whether the VCI field" |
1739 | 16 | " is present in the packet. If set to 1, the VCI field is present" |
1740 | 16 | " for the cell. If set to 0, no VCI field is present." |
1741 | 16 | ,HFILL }}, |
1742 | | |
1743 | 16 | { &hf_cell_h_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv" |
1744 | 16 | ,FT_UINT8 ,BASE_DEC ,NULL ,0x30 |
1745 | 16 | ,"The reserved bits should be set to 0 at the transmitter and" |
1746 | 16 | " ignored upon reception." |
1747 | 16 | ,HFILL }}, |
1748 | | |
1749 | 16 | { &hf_aal5_pdu_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv" |
1750 | 16 | ,FT_UINT8 ,BASE_DEC ,NULL ,0x38 |
1751 | 16 | ,"The reserved bits should be set to 0 at the transmitter and" |
1752 | 16 | " ignored upon reception." |
1753 | 16 | ,HFILL }}, |
1754 | | |
1755 | 16 | { &hf_aal5_pdu_u ,{"U bit" ,"atm.pw_control_byte.u" |
1756 | 16 | ,FT_UINT8 ,BASE_DEC ,VALS(u_vals) ,0x04 |
1757 | 16 | ,"Indicates whether this frame contains the last cell of" |
1758 | 16 | " an AAL5 PDU and represents the value of the ATM User-to-User" |
1759 | 16 | " bit for the last ATM cell of the PSN frame. Note: The ATM" |
1760 | 16 | " User-to-User bit is the least significant bit of the PTI" |
1761 | 16 | " in the ATM header." |
1762 | 16 | ,HFILL }}, |
1763 | | |
1764 | 16 | { &hf_aal5_pdu_e ,{"EFCI" ,"atm.pw_control_byte.efci" |
1765 | 16 | ,FT_UINT8 ,BASE_DEC ,VALS(e_vals) ,0x02 |
1766 | 16 | ,"EFCI is set to the EFCI state of the last cell of the" |
1767 | 16 | " AAL5 PDU or AAL5 fragment. Note: The EFCI state is" |
1768 | 16 | " indicated in the middle bit of each ATM cell's PTI." |
1769 | 16 | ,HFILL }} |
1770 | 16 | }; |
1771 | 16 | static hf_register_info hfa_cell[] = { |
1772 | 16 | {&hf_cell_payload_len ,{"Length" ,"atm.cell.len" |
1773 | 16 | ,FT_INT32 ,BASE_DEC ,NULL ,0 |
1774 | 16 | ,NULL ,HFILL }} |
1775 | 16 | }; |
1776 | | |
1777 | 16 | static hf_register_info hfa_n1_nocw[] = { |
1778 | 16 | { &hf_n1_nocw_ncells, |
1779 | 16 | { "Number of good N:1 no CW encapsulated cells", "pw.atm.n1_nocw.cells", FT_INT32, |
1780 | 16 | BASE_DEC, NULL, 0, NULL, HFILL }}, |
1781 | 16 | { &hf_pw_type_n1_nocw, |
1782 | 16 | { "N:1 noCW", "pw.type.atm.n1nocw", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1783 | 16 | NULL, HFILL }} |
1784 | 16 | }; |
1785 | | |
1786 | 16 | static hf_register_info hfa_n1_cw[] = { |
1787 | 16 | { &hf_n1_cw_ncells, |
1788 | 16 | { "Number of good N:1 CW encapsulated cells", "pw.atm.n1_cw.cells", FT_INT32, |
1789 | 16 | BASE_DEC, NULL, 0, NULL, HFILL }}, |
1790 | 16 | { &hf_pw_type_n1_cw, |
1791 | 16 | { "N:1 CW", "pw.type.atm.n1cw", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1792 | 16 | NULL, HFILL }} |
1793 | 16 | }; |
1794 | | |
1795 | 16 | static hf_register_info hfa_11_aal5pdu[] = { |
1796 | 16 | { &hf_11_ncells, |
1797 | 16 | { "Number of good 1:1 encapsulated cells", "pw.atm.11.cells", FT_INT32, |
1798 | 16 | BASE_DEC, NULL, 0, NULL, HFILL }}, |
1799 | 16 | { &hf_pw_type_11_vcc, |
1800 | 16 | { "1:1 VCC", "pw.type.atm.11vcc", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1801 | 16 | NULL, HFILL }}, |
1802 | 16 | { &hf_pw_type_11_vpc, |
1803 | 16 | { "1:1 VPC", "pw.type.atm.11vpc", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1804 | 16 | NULL, HFILL }}, |
1805 | 16 | { &hf_pw_type_aal5_pdu, |
1806 | 16 | { "AAL5 PDU", "pw.type.atm.aal5pdu", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1807 | 16 | NULL, HFILL }} |
1808 | 16 | }; |
1809 | | |
1810 | 16 | static hf_register_info hfa_aal5_sdu[] = { |
1811 | 16 | { &hf_pw_type_aal5_sdu, |
1812 | 16 | { "AAL5 SDU", "pw.type.atm.aal5sdu", FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
1813 | 16 | NULL, HFILL }} |
1814 | 16 | }; |
1815 | | |
1816 | 16 | static const value_string a5s_t_vals[] = { |
1817 | 16 | { 0, "AAL5 payload" }, |
1818 | 16 | { 1, "ATM admin cell" }, |
1819 | 16 | { 0, NULL } |
1820 | 16 | }; |
1821 | | |
1822 | 16 | static const value_string a5s_e_vals[] = { |
1823 | 16 | { 0, "No congestion" }, |
1824 | 16 | { 1, "Congestion experienced" }, |
1825 | 16 | { 0, NULL } |
1826 | 16 | }; |
1827 | | |
1828 | 16 | static hf_register_info hfa_cw[] = { |
1829 | 16 | { &hf_cw_bits03 ,{"Bits 0 to 3" ,"pw.cw.bits03" |
1830 | 16 | ,FT_UINT8 ,BASE_HEX ,NULL ,0xf0 |
1831 | 16 | ,NULL ,HFILL }}, |
1832 | | |
1833 | 16 | { &hf_pref_cw_flags ,{"Flags" ,"pw.cw.flags" |
1834 | 16 | ,FT_UINT8 ,BASE_HEX ,NULL ,0x0f |
1835 | 16 | ,NULL ,HFILL }}, |
1836 | | |
1837 | 16 | { &hf_pref_cw_a5s_t ,{"Payload type" ,"atm.pt" |
1838 | 16 | ,FT_UINT8 ,BASE_DEC ,VALS(a5s_t_vals),0x08 |
1839 | 16 | ,"Bit (T) of the control word indicates whether the packet contains" |
1840 | 16 | " an ATM admin cell or an AAL5 payload. If T = 1, the packet" |
1841 | 16 | " contains an ATM admin cell, encapsulated according to the N:1" |
1842 | 16 | " cell relay encapsulation. If not set, the PDU" |
1843 | 16 | " contains an AAL5 payload." |
1844 | 16 | ,HFILL }}, |
1845 | | |
1846 | 16 | { &hf_pref_cw_a5s_e ,{"EFCI bit" ,"atm.efci" |
1847 | 16 | ,FT_UINT8 ,BASE_DEC ,VALS(a5s_e_vals),0x04 |
1848 | 16 | ,"The ingress router sets this bit to 1 if the EFCI bit" |
1849 | 16 | " of the final cell of those that transported the AAL5 CPCS-SDU is" |
1850 | 16 | " set to 1, or if the EFCI bit of the single ATM cell to be" |
1851 | 16 | " transported in the packet is set to 1. Otherwise, this bit" |
1852 | 16 | " is set to 0." |
1853 | 16 | ,HFILL }}, |
1854 | | |
1855 | 16 | { &hf_pref_cw_a5s_c ,{"CLP bit" ,"atm.clp" |
1856 | 16 | ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x02 |
1857 | 16 | ,"The ingress router sets this bit to 1 if the CLP bit" |
1858 | 16 | " of any of the ATM cells that transported the AAL5 CPCS-SDU is set" |
1859 | 16 | " to 1, or if the CLP bit of the single ATM cell to be transported" |
1860 | 16 | " in the packet is set to 1. Otherwise this bit is set to 0." |
1861 | 16 | ,HFILL }}, |
1862 | | |
1863 | 16 | { &hf_pref_cw_a5s_u ,{"U bit (Command/Response)" ,"pw.cw.aal5sdu.u" |
1864 | 16 | ,FT_UINT8 ,BASE_DEC ,NULL ,0x01 |
1865 | 16 | ,"When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916]" |
1866 | 16 | " traffic is being transported, the Least-Significant Bit of CPCS-UU" |
1867 | 16 | " of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit." |
1868 | 16 | " The ingress router copies this bit here." |
1869 | 16 | ,HFILL }}, |
1870 | | |
1871 | 16 | { &hf_pref_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv" |
1872 | 16 | ,FT_UINT8 ,BASE_DEC ,NULL ,0xc0 |
1873 | 16 | ,NULL ,HFILL }}, |
1874 | | |
1875 | 16 | { &hf_generic_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv" |
1876 | 16 | ,FT_UINT8 ,BASE_DEC ,NULL ,0x0f |
1877 | 16 | ,NULL ,HFILL }}, |
1878 | | |
1879 | 16 | { &hf_pref_cw_len ,{"Length" ,"pw.cw.length" |
1880 | 16 | ,FT_UINT8 ,BASE_DEC ,NULL ,0x3f |
1881 | 16 | ,NULL ,HFILL }}, |
1882 | | |
1883 | 16 | { &hf_pref_cw_rsvlen ,{"Length (extended)" ,"pw.cw.length" |
1884 | 16 | ,FT_UINT8 ,BASE_DEC ,NULL ,0x0 |
1885 | 16 | ,NULL ,HFILL }}, |
1886 | | |
1887 | 16 | { &hf_cw_seq ,{"Sequence number" ,"pw.cw.seqno" |
1888 | 16 | ,FT_UINT16 ,BASE_DEC ,NULL ,0 |
1889 | 16 | ,NULL ,HFILL }}, |
1890 | | |
1891 | 16 | { &hf_gen_cw_atmbyte ,{"ATM-specific byte" ,"pw.cw.3rd_byte" |
1892 | 16 | ,FT_UINT8 ,BASE_HEX ,NULL ,0x0 |
1893 | 16 | ,NULL ,HFILL }} |
1894 | 16 | }; |
1895 | 16 | static int *ett_array[] = { |
1896 | 16 | &ett_encaps |
1897 | 16 | ,&ett_cw |
1898 | 16 | ,&ett_cell_header |
1899 | 16 | ,&ett_cell |
1900 | 16 | }; |
1901 | 16 | static ei_register_info ei[] = { |
1902 | 16 | { &ei_pw_packet_size_too_small, { "pw.packet_size_too_small", PI_MALFORMED, PI_ERROR, "PW packet size too small", EXPFILL }}, |
1903 | 16 | { &ei_pw_payload_size_invalid_error, { "pw.payload.size_invalid_err", PI_MALFORMED, PI_ERROR, "PW payload size invalid", EXPFILL }}, |
1904 | 16 | { &ei_cell_broken, { "atm.cell_broken", PI_MALFORMED, PI_ERROR, "PW ATM cell is broken", EXPFILL }}, |
1905 | 16 | { &ei_pw_payload_size_invalid_note, { "pw.payload.size_invalid", PI_MALFORMED, PI_NOTE, "PW payload size invalid", EXPFILL }}, |
1906 | 16 | { &ei_cw_bits03, { "pw.cw.bits03.not_zero", PI_MALFORMED, PI_ERROR, "Bits 0..3 of Control Word must be 0", EXPFILL }}, |
1907 | 16 | { &ei_pref_cw_flags, { "pw.cw.flags.not_zero", PI_MALFORMED, PI_ERROR, "Flags must be 0 for PW ATM N:1 encapsulation", EXPFILL }}, |
1908 | 16 | { &ei_pref_cw_len, { "pw.cw.length.invalid", PI_MALFORMED, PI_ERROR, "Bad Length: must be 0 for this encapsulation", EXPFILL }}, |
1909 | 16 | { &ei_cell_h_pti_undecoded, { "atm.pti.undecoded", PI_UNDECODED, PI_WARN, "Unknown value of PTI field in the ATM cell header", EXPFILL }}, |
1910 | 16 | { &ei_cell_h_pti_malformed, { "atm.pti.invalid", PI_MALFORMED, PI_ERROR, "ATM admin cell is transerred. PTI field should be 4, 5 or 6.", EXPFILL }}, |
1911 | 16 | { &ei_cell_h_m, { "atm.pw_control_byte.m.not_zero", PI_MALFORMED, PI_ERROR, "1:1 mode: M bit must be 0 to distinguish from AAL5 PDU mode", EXPFILL }}, |
1912 | 16 | { &ei_cell_h_v_not_zero, { "atm.pw_control_byte.v.not_one", PI_MALFORMED, PI_ERROR, "1:1 VPC mode: V bit must be 1 to indicate that VCI is present", EXPFILL }}, |
1913 | 16 | { &ei_cell_h_v_not_one, { "atm.pw_control_byte.v.not_zero", PI_MALFORMED, PI_ERROR, "1:1 VCC mode: V bit must be 0 to indicate that VCI is absent", EXPFILL }}, |
1914 | 16 | { &ei_cell_h_rsv, { "atm.pw_control_byte.rsv.not_zero", PI_MALFORMED, PI_ERROR, "Reserved bits in the 3rd byte of CW must be 0", EXPFILL }}, |
1915 | 16 | { &ei_gen_cw_atmbyte, { "pw.cw.atmbyte", PI_PROTOCOL, PI_NOTE, "ATM-specific byte of CW is fully dissected below", EXPFILL }}, |
1916 | 16 | }; |
1917 | | |
1918 | 16 | expert_module_t* expert_cell; |
1919 | | |
1920 | 16 | proto_n1_cw = |
1921 | 16 | proto_register_protocol(pwc_longname_pw_atm_n1_cw |
1922 | 16 | ,shortname_n1_cw |
1923 | 16 | ,"mplspwatmn1cw"); |
1924 | 16 | proto_11_or_aal5_pdu = |
1925 | 16 | proto_register_protocol(pwc_longname_pw_atm_11_or_aal5_pdu |
1926 | 16 | ,shortname_11_or_aal5_pdu |
1927 | 16 | ,"mplspwatm11_or_aal5pdu"); |
1928 | 16 | proto_aal5_sdu = |
1929 | 16 | proto_register_protocol(pwc_longname_pw_atm_aal5_sdu |
1930 | 16 | ,shortname_aal5_sdu |
1931 | 16 | ,"mplspwatmaal5sdu"); |
1932 | 16 | proto_n1_nocw = |
1933 | 16 | proto_register_protocol(pwc_longname_pw_atm_n1_nocw |
1934 | 16 | ,shortname_n1_nocw |
1935 | 16 | ,"mplspwatmn1nocw"); |
1936 | 16 | proto_control_word = |
1937 | 16 | proto_register_protocol("MPLS PW ATM Control Word" |
1938 | 16 | ,"MPLS PW ATM Control Word" |
1939 | 16 | ,"mplspwatmcontrolword"); |
1940 | 16 | proto_cell_header = |
1941 | 16 | proto_register_protocol("MPLS PW ATM Cell Header" |
1942 | 16 | ,"MPLS PW ATM Cell Header" |
1943 | 16 | ,"mplspwatmcellheader"); |
1944 | 16 | proto_cell = |
1945 | 16 | proto_register_protocol("ATM Cell" |
1946 | 16 | ,"ATM Cell" |
1947 | 16 | ,"mplspwatmcell"); |
1948 | | |
1949 | 16 | proto_register_field_array( proto_cell ,hfa_cell ,array_length(hfa_cell)); |
1950 | 16 | expert_cell = expert_register_protocol(proto_cell); |
1951 | 16 | expert_register_field_array(expert_cell, ei, array_length(ei)); |
1952 | | |
1953 | 16 | proto_register_field_array( proto_cell_header ,hfa_cell_header,array_length(hfa_cell_header)); |
1954 | 16 | proto_register_field_array( proto_control_word ,hfa_cw ,array_length(hfa_cw)); |
1955 | 16 | proto_register_field_array( proto_n1_nocw ,hfa_n1_nocw ,array_length(hfa_n1_nocw)); |
1956 | 16 | proto_register_field_array( proto_n1_cw ,hfa_n1_cw ,array_length(hfa_n1_cw)); |
1957 | 16 | proto_register_field_array( proto_11_or_aal5_pdu ,hfa_11_aal5pdu ,array_length(hfa_11_aal5pdu)); |
1958 | 16 | proto_register_field_array( proto_aal5_sdu ,hfa_aal5_sdu ,array_length(hfa_aal5_sdu)); |
1959 | | |
1960 | 16 | proto_register_subtree_array(ett_array, array_length(ett_array)); |
1961 | | |
1962 | 16 | dh_control_word = register_dissector("mpls_pw_atm_control_word" ,dissect_control_word ,proto_control_word); |
1963 | 16 | dh_cell = register_dissector("mpls_pw_atm_cell" ,dissect_cell ,proto_cell); |
1964 | 16 | dh_cell_header = register_dissector("mpls_pw_atm_cell_header",dissect_cell_header ,proto_cell_header); |
1965 | 16 | register_dissector("mpls_pw_atm_aal5_sdu" ,dissect_aal5_sdu ,proto_aal5_sdu); |
1966 | 16 | register_dissector("mpls_pw_atm_11_or_aal5_pdu" ,dissect_11_or_aal5_pdu ,proto_11_or_aal5_pdu); |
1967 | 16 | register_dissector("mpls_pw_atm_n1_cw" ,dissect_n1_cw ,proto_n1_cw); |
1968 | 16 | register_dissector("mpls_pw_atm_n1_nocw" ,dissect_n1_nocw ,proto_n1_nocw); |
1969 | 16 | { |
1970 | 16 | static const char description_allow_cw_length_nonzero[] = |
1971 | 16 | "Enable to allow non-zero Length in Control Word." |
1972 | 16 | " This may be needed to correctly decode traffic from some legacy devices" |
1973 | 16 | " which generate non-zero Length even if there is no padding in the packet." |
1974 | 16 | " Note that Length should have proper value (dissector checks this anyway)." |
1975 | 16 | "\n\n" |
1976 | 16 | "Disable to blame all packets with CW.Length <> 0. This conforms to RFC4717." |
1977 | 16 | ; |
1978 | 16 | static const char description_extend_cw_length_with_rsvd[] = |
1979 | 16 | "Enable to use reserved bits (8..9) of Control Word as an extension of CW.Length." |
1980 | 16 | " This may be needed to correctly decode traffic from some legacy devices" |
1981 | 16 | " which uses reserved bits as extension of Length" |
1982 | 16 | "\n\n" |
1983 | 16 | "Disable to blame all packets with CW.Reserved <> 0. This conforms to RFC4717." |
1984 | 16 | ; |
1985 | 16 | module_t * module_n1_cw; |
1986 | 16 | module_t * module_aal5_sdu; |
1987 | | |
1988 | 16 | module_n1_cw = prefs_register_protocol(proto_n1_cw,NULL); |
1989 | 16 | prefs_register_bool_preference(module_n1_cw |
1990 | 16 | ,"allow_cw_length_nonzero" |
1991 | 16 | ,"Allow CW.Length <> 0" |
1992 | 16 | ,&description_allow_cw_length_nonzero[0] |
1993 | 16 | ,&pref_n1_cw_allow_cw_length_nonzero); |
1994 | 16 | prefs_register_bool_preference(module_n1_cw |
1995 | 16 | ,"extend_cw_length_with_rsvd" |
1996 | 16 | ,"Use CW.Reserved as extension of CW.Length" |
1997 | 16 | ,&description_extend_cw_length_with_rsvd[0] |
1998 | 16 | ,&pref_n1_cw_extend_cw_length_with_rsvd); |
1999 | | |
2000 | 16 | module_aal5_sdu = prefs_register_protocol(proto_aal5_sdu,NULL); |
2001 | 16 | prefs_register_bool_preference(module_aal5_sdu |
2002 | 16 | ,"allow_cw_length_nonzero_aal5" |
2003 | 16 | ,"Allow CW.Length <> 0" |
2004 | 16 | ,&description_allow_cw_length_nonzero[0] |
2005 | 16 | ,&pref_aal5_sdu_allow_cw_length_nonzero); |
2006 | 16 | prefs_register_bool_preference(module_aal5_sdu |
2007 | 16 | ,"extend_cw_length_with_rsvd_aal5" |
2008 | 16 | ,"Use CW.Reserved as extension of CW.Length" |
2009 | 16 | ,&description_extend_cw_length_with_rsvd[0] |
2010 | 16 | ,&pref_aal5_sdu_extend_cw_length_with_rsvd); |
2011 | 16 | } |
2012 | 16 | } |
2013 | | |
2014 | | |
2015 | | void |
2016 | | proto_reg_handoff_pw_atm_ata(void) |
2017 | 16 | { |
2018 | 16 | dissector_handle_t h; |
2019 | 16 | h = find_dissector("mpls_pw_atm_n1_cw"); |
2020 | 16 | dissector_add_for_decode_as( "mpls.label", h ); |
2021 | 16 | dissector_add_for_decode_as( "mpls.pfn", h); |
2022 | 16 | h = find_dissector("mpls_pw_atm_n1_nocw"); |
2023 | 16 | dissector_add_for_decode_as( "mpls.label", h ); |
2024 | 16 | dissector_add_for_decode_as( "mpls.pfn", h); |
2025 | 16 | h = find_dissector("mpls_pw_atm_11_or_aal5_pdu"); |
2026 | 16 | dissector_add_for_decode_as( "mpls.label", h ); |
2027 | 16 | dissector_add_for_decode_as( "mpls.pfn", h); |
2028 | 16 | h = find_dissector("mpls_pw_atm_aal5_sdu"); |
2029 | 16 | dissector_add_for_decode_as( "mpls.label", h ); |
2030 | 16 | dissector_add_for_decode_as( "mpls.pfn", h); |
2031 | | |
2032 | 16 | dh_atm_truncated = find_dissector("atm_pw_truncated"); |
2033 | 16 | dh_atm_untruncated = find_dissector("atm_pw_untruncated"); |
2034 | 16 | dh_atm_oam_cell = find_dissector("atm_pw_oam_cell"); |
2035 | 16 | dh_padding = find_dissector("pw_padding"); |
2036 | 16 | } |
2037 | | |
2038 | | /* |
2039 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
2040 | | * |
2041 | | * Local variables: |
2042 | | * c-basic-offset: 8 |
2043 | | * tab-width: 8 |
2044 | | * indent-tabs-mode: t |
2045 | | * End: |
2046 | | * |
2047 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
2048 | | * :indentSize=8:tabSize=8:noTabs=false: |
2049 | | */ |